SQL catalogue, policy, and pagination
Query granted DuckLake datasets with bounded, parameterized, read-only DuckDB SQL.
Logical relations
Each relation has three parts:
"source_alias"."logical_schema"."logical_table"Use the exact names returned by GET /v1/catalog. Direct S3 URLs, file paths, DuckLake metadata
schemas, and provider credentials are intentionally absent. Double-quote identifiers copied from the
catalogue. Parameters bind values only; SQL identifiers cannot be placeholders.
Parameters and values
Use ? placeholders and provide values through parameters. The number of placeholders must
exactly match the number of values. Parameters may be strings, numbers, booleans, or null.
{
"accountId": "00000000-0000-4000-8000-000000000000",
"sql": "select * from slack_a1b2c3d4.public.messages where emitted_at >= ? order by emitted_at, id limit 100",
"parameters": ["2026-08-01T00:00:00Z"],
"maxRows": 100
}Send timestamps as ISO 8601 strings with an explicit offset. Cast only when required by the returned
DuckDB type. NULL follows SQL three-valued logic; use IS NULL rather than = NULL.
Accepted statements
The broker accepts one read-only SELECT or a sequence of common table expressions ending in
SELECT. Joins, aggregates, filtering, ordering, window functions, scalar functions, and bounded
subqueries are available when they remain inside resolved granted relations.
The policy rejects DDL, DML, multiple statements, COPY, ATTACH, DETACH, PRAGMA, extension
installation/loading, filesystem or URL reads, system catalogues, secrets, unsafe table functions,
and references outside the granted catalogue. SQL is parsed and resolved before an isolated worker
is invoked.
Provenance columns
| Column | Meaning |
|---|---|
_combined_record_id | Stable provider key or deterministic selected-field hash |
_combined_op | Current delivery operation |
_combined_emitted_at | Provider emission time, when available |
_combined_observed_at | Time the Source observed the record |
_combined_ingested_at | Lake commit ingestion time |
_combined_run_id | Source Run that produced the row |
_combined_delivery_id | Deterministic Delivery that committed the row |
_combined_payload_hash | Canonical payload integrity hash |
_combined_provenance | Structured Source/dataset/producer provenance |
These fields trace a row to the exact Source, dataset, Run, and Delivery. They are queryable but are not duplicated into query receipts.
Launch limits
- 16 KiB SQL and 100 parameters;
- eight Sources per query;
- 1,000 rows by default and 10,000 absolute maximum when the grant permits it;
- 1 MiB synchronous serialized result;
- 256 MiB estimated input scan;
- 10-second soft and 20-second hard execution deadlines;
- two concurrent queries per Account and 60 requests per minute per Principal.
MCP query_sql applies a stricter 1,000-row maximum and defaults to 100 rows. A grant or Account
policy can lower any applicable bound. The effective limit is always the strictest one. If the
broker cannot prove that the referenced dataset projection fits the input limit, it rejects the query
before invoking the worker.
Truncation and pagination
SQL results are not cursor-paginated by the API. When truncated is true, add a stable ORDER BY
and a keyset predicate such as WHERE (created_at, id) > (?, ?) for the next request. Avoid OFFSET
for changing datasets because concurrent commits can move rows between pages. The 1 MiB serialized
limit can truncate before maxRows when rows are wide.
Stop, revocation, receipts, and cache
The Query workspace forwards cancellation through the broker. A canceled, timed-out, or revoked execution can never return a result. Successful bounded results may remain in the isolated result cache for five minutes under the principal, Account, grants, query, parameters, and data snapshot. Grant changes invalidate access to prior entries. Receipts persist operational metadata and the canonical SQL hash, never result rows.