Skip to Content
We are live but in Staging 🎉

Query

Typed shortcut for a single-table SELECT. Pass a SQL body, optional broadcast JOIN aliases, and a Freshness mode; K3’s planner routes through a QueryStrategy and returns rows + the strategy it picked. See the Data hub for the full RPC list.

RPCHTTP
QueryPOST /:bucket/tables/_query

gRPC setup — grpcurl, endpoints, reflection, and field-name casing — is covered once in Conventions → Using gRPC.

Query

Request

Simple aggregate, eventual freshness:

curl -sS -X POST "https://k3.dev.dodil.io/kb-prod/tables/_query" \ -H "Authorization: Bearer $DODIL_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "bucket": "kb-prod", "tableName": "events", "sql": "SELECT event_type, COUNT(*) AS n FROM {table} GROUP BY event_type ORDER BY n DESC", "limit": "10000", "freshness": "FRESHNESS_EVENTUAL" }'

Strong-freshness (read-your-writes):

curl -sS -X POST "https://k3.dev.dodil.io/kb-prod/tables/_query" \ -H "Authorization: Bearer $DODIL_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "bucket": "kb-prod", "tableName": "events", "sql": "SELECT * FROM {table} WHERE user_id = '\''u-101'\''", "freshness": "FRESHNESS_STRONG" }'

Broadcast JOIN — pass aliases for other tables in the same bucket:

curl -sS -X POST "https://k3.dev.dodil.io/kb-prod/tables/_query" \ -H "Authorization: Bearer $DODIL_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "bucket": "kb-prod", "tableName": "events", "sql": "SELECT e.user_id, u.email, COUNT(*) AS clicks FROM {table} e JOIN users u ON e.user_id = u.id WHERE e.event_type = '\''click'\'' GROUP BY e.user_id, u.email", "lookupTables": { "users": "users" } }'

Response

{ "columns": ["event_type", "n"], "rows": [ "{\"event_type\":\"click\",\"n\":12483}", "{\"event_type\":\"purchase\",\"n\":42}" ], "rowCount": "2", "executionTimeMs": "47", "strategy": "QUERY_STRATEGY_DUCKDB_DIRECT", "strategyReason": "table is not partitioned", "partitionsQueried": 1, "servedBy": "SERVED_BY_DELTA" }

{table} placeholder — the dispatcher rewrites it to the literal target. The SQL also accepts the literal table name directly; pick whichever reads better.

lookup_tables — alias → table-name map for JOINs against other tables in the same bucket. Empty when not joining.

freshness=STRONG watch-out: oltp_overlay_truncated = true means the write-log scan hit its per-call cap and the result is incomplete. Either page (lower limit) or run Compact to shrink the log, then re-query.

See also