Skip to main content
Run SQL queries, browse your catalogs and tables, register S3 Tables catalogs, and open a DuckDB terminal connected to your lake from the command line. For a full overview of the lake, see the Lake documentation.

Query

oleander query sends SQL through the query router: oleander parses it, estimates how much data the referenced tables hold, and picks the engine and machine size to match. There is nothing to size by hand.
Example:
Results are printed as a formatted table with row counts and execution time, under a block naming the engine that ran the query, the sandbox or cluster shape, the estimated input, and the router’s reasons. oleander query is read-only. Anything that changes data - a SELECT you want written to a table, or an INSERT, UPDATE, DELETE, MERGE, or DDL statement - goes to oleander query submit. Mutating SQL is refused before the request leaves your machine.

Explain before you run

--explain prints the engine, estimated input size, and reason trail without executing anything or spending compute. Worth doing before a query you expect to be large.
The same block prints under every result, so the engine choice is visible where the query ran.

Pick an engine yourself

Leave the engine on auto unless you have a reason. --engine accepts auto, duckdb, polars, or bloom; Spark is not an option here because it never returns rows.
An engine that cannot serve the query returns a capability error rather than rerouting.

Polars scripts

Pass --script instead of SQL to run a Python Polars script that assigns result, declaring the tables it reads with --table. This forces the Polars engine.

Write results with query submit

oleander query submit takes everything that changes data: a SELECT plus --destination, or a statement that names its own target.
--write-mode defaults to overwrite, which replaces the destination table’s contents.
Whether a write finishes on the call is the router’s choice, not yours, so read the state it reports: Add --wait to block on a submitted run until it reaches a terminal state; --poll-interval (default 10s) and --timeout (default 600s) control the polling. A run that fails or is aborted exits non-zero.

Options

A 402 or 403 on a query is a billing decision, not a transient failure. The CLI prints what it asks for - settle billing, upgrade the plan, add a card, or run a read on --engine duckdb. Retrying the same query fails identically.
oleander query --save and --table-name are gone: a read no longer writes a table. Use oleander query submit --destination instead.

Catalogs

List catalogs

List all available catalogs in your organization:

Register an S3 Tables catalog

Register a catalog backed by S3 Tables:
--type is optional and defaults to s3tables.

Get catalog credentials

Retrieve short-lived credentials for a registered catalog:
Pass --json to get raw JSON output (useful for scripting):

List namespaces

Omit --catalog to use the oleander default catalog. Pass --json for JSON output.

Create a namespace

--catalog defaults to oleander.

List tables

List tables in a catalog namespace:
If you omit --catalog or --namespace, the CLI prompts you interactively.

Describe a table

View the schema of a table:
If you omit any of --catalog, --namespace, or --table, the CLI prompts you interactively.

Create a table

Create a new Iceberg table from a JSON schema definition:
Pass a file path prefixed with @ or just a path to load the schema from a file:
Optionally include a partition spec:
--catalog defaults to oleander. --namespace defaults to default.

Delete a table

--catalog defaults to oleander. --namespace defaults to default.

Load data into a table

Create a new table and populate it from a local file or a remote URI. The source can be a local Parquet, CSV, or JSON file, or an S3/HTTPS URI.
Local file example:
Remote URI example:

Schema evolution

Add, rename, or drop columns on an existing table. Pass the operation as a JSON body - either inline or from a file. Add columns:
Rename a column:
Drop columns:
All three schema commands accept --input as either an inline JSON string or a path to a JSON file.

DuckDB terminal

Launch a DuckDB terminal pre-configured with your registered catalogs:
The CLI loads registered lakekeeper and s3tables catalogs into DuckDB before opening the interactive shell.
The duckdb command requires DuckDB to be installed on your machine.