Skip to main content
The SDK has two query methods and one legacy one. query_run reads, query_submit writes, and both go through the query router, which picks the engine and machine size for you. All methods are async.

query_run(sql_or_options)

Runs a query and returns the rows on the call. oleander parses the SQL, estimates how much data the referenced tables hold, and picks the engine (duckdb, polars, bloom) and machine size to match, so leave engine as auto unless you want a specific one. The choice and the reasoning behind it come back in engine_decision.
query_run is read-only. SQL that could change data is rejected before the request goes out - use query_submit for those.

Explain without running

Pass explain=True to see which engine a query would take, its estimated input size, and whether your plan allows it, without running anything or spending compute.
Do this before a query you expect to be large.

Polars scripts

Pass script instead of sql to run a Polars DataFrame script that assigns result, listing the tables it reads in tables. This forces the Polars engine.

Parameters

str
The SQL query to run. Pass a bare string as the only argument for the common case, or a QueryRunOptions instance for anything else. Mutually exclusive with script.
str
A Polars DataFrame script that assigns result. Requires tables.
list[QueryTable]
Tables the script reads, as QueryTable(alias=..., table=...).
"auto" | "duckdb" | "polars" | "bloom"
default:"\"auto\""
Ask for a specific engine. An impossible combination raises an engine capability error rather than rerouting.
bool
default:"False"
Return the routing decision without executing.

query_submit(options)

Covers everything that changes data: a SELECT plus a destination to write it to, and a statement that names its own target (INSERT, UPDATE, DELETE, MERGE, DDL) with no destination. It also takes reads too large to return interactively. Whether the write finishes on the call depends on the engine the router picked, so read state. Result rows are never returned, only row_count when it is known.

query_submit_and_wait(options)

Submits and polls until an asynchronous run finishes. A write that lands inline returns immediately with run unset.

Parameters

str
The statement to run. With a destination, a SELECT; without one, a statement that names its own target.
str
Table to write the result to, as namespace.table.
"overwrite" | "append"
default:"\"overwrite\""
Applies to a destination write. A statement that names its own target carries its own semantics.
"auto" | "duckdb" | "polars" | "bloom" | "spark"
default:"\"auto\""
Ask for a specific engine.
bool
default:"False"
Return the routing decision without submitting anything.

query(sql, options?)

query predates the router. It always runs DuckDB, sized by the org’s default sandbox setting rather than by the query. Prefer query_run; reach for this only when you need save=True.
Executes SQL against the lake on DuckDB, with optional auto-save by query hash. If the API rejects the query, the SDK raises instead of returning a failed result.

Parameters

str
required
The SQL query to execute. Supports DuckDB SQL syntax.
bool
default:"False"
When True, persists query results as a table. The table name is returned in saved_table_name.

Return fields

Iterating over results