Accepted SQL
Thunderduck runs DuckDB's dialect. Every statement is classified before the engine sees it, and a refusal is structured — read it rather than retrying variations.
Always allowed
SELECT, plus DESCRIBE, SHOW TABLES and read-only pragmas, which the parser
treats as selects.
Allowed when the caller can write
INSERT, UPDATE, DELETE, CREATE, DROP, ALTER — subject to the catalog
being writable and, for API and AI callers, the token carrying a write scope.
Never allowed
ATTACH, COPY, non-read PRAGMA, SET, INSTALL/LOAD, CALL, EXPORT,
VACUUM, CREATE SECRET, explicit transactions, and the query() and
getenv() functions. These reconfigure the engine rather than
touching data; permission to change data is not permission to reconfigure the
engine that runs it.
EXPLAIN
EXPLAIN <stmt> is unwrapped and the inner statement judged by these same rules,
because EXPLAIN ANALYZE <stmt> genuinely executes the statement. For a plan
without execution, use the cost estimate instead.
Reading files
read_csv, read_parquet, read_json, read_xlsx and friends accept a
catalog/path first argument, which is rewritten to the catalog's bucket with its
own credentials.
Local filesystem paths and arbitrary URLs are rejected — in a subquery or a
CREATE TABLE … AS SELECT just as in a bare SELECT. A path must start with
one of your catalog names; anything else is refused, as are computed paths
('raw/' || name). Reference a catalog rather
than a path, and if the data lives in object storage, register it as a catalog
once instead of pasting a URL into every query.
Path and function rules
- A read path must start with a catalog name.
- No
?or#in paths, so DuckDB's?single-character glob is not available; use*or[...]. No..segments either. - No line may start with
.; write0.5, not.5. - Table functions are an allowlist:
read_csv,read_csv_auto,read_parquet,parquet_scan,read_json,read_json_auto,read_ndjson,read_ndjson_auto,read_text,read_xlsx,glob,clickhouse_query,range,generate_series,unnest,repeat,histogram, and the metadata functionsduckdb_tables,duckdb_columns,duckdb_views,duckdb_schemas,duckdb_databases,duckdb_types,duckdb_constraints,duckdb_indexes,duckdb_functionsandduckdb_keywords.duckdb_secrets,duckdb_settingsandduckdb_extensionsare not available. - Passthrough functions such as
postgres_queryandbigquery_querycannot be called directly; pushdown to those engines is automatic. - S3, GCS and Azure catalogs without their own credentials cannot be read.
- ClickHouse catalogs must use a public DNS hostname, not an IP address or an internal name.
Syntax vs binding
A syntax error fails immediately, in the response. A binding error — unknown table, unknown column — arrives a moment later as a failed query, because resolving names requires your catalog credentials, and those are only opened where the query actually runs.