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.
| RPC | HTTP |
|---|---|
Query | POST /:bucket/tables/_query |
gRPC setup —
grpcurl, endpoints, reflection, and field-name casing — is covered once in Conventions → Using gRPC.
Query
Request
HTTP
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
HTTP
{
"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
- Execute → SELECT — full read-strategy reference (
UNARY_WAREHOUSE,UNARY_MERGED_STRONG,FEDERATED_*) - Insert · Merge · Update · DeleteRows — sibling write RPCs
- Core Concepts → QueryStrategy / Freshness / ServedBy — full enum reference
- SQL Compatibility — DuckDB dialect, statement shapes
- CLI Guide —
dodil k3 table query grpcurlreference — full flag set + reflection-disabled fallbacks