Warehouses¶
A deployment writes to one warehouse, named in the Warehouse section of craft-connector.yml.
What the engine creates there depends on the warehouse and the table format:
Warehouse.Table_format (native by default), which a task may override with its own
TABLE_FORMAT parameter where the warehouse allows it.
Warehouse.Name |
native |
iceberg |
Extra to install |
|---|---|---|---|
| Postgres | ordinary tables | not available | none |
| DuckDB | tables in one local file | tables in an Iceberg REST catalog | none |
| Trino | Iceberg, whatever is asked: the catalog decides | Iceberg | etl-craft[trino] |
| Databricks | Delta tables | Delta tables with UniForm, readable as Iceberg | etl-craft[databricks] |
| Snowflake | ordinary tables | Iceberg tables | etl-craft[snowflake] |
PostgreSQL and DuckDB need no extra. DuckDB is the default local warehouse of the quick start and the demo, so its SQLAlchemy dialect is installed with etl-craft itself.
etl-craft[databricks] keeps SQLAlchemy below 2.1: the Databricks connector returns rows
that SQLAlchemy 2.1 does not accept. Every other warehouse runs on SQLAlchemy 2.0 and 2.1.
A DuckDB file admits one writing process at a time, so tasks writing to it queue behind each other; every other warehouse runs tasks in parallel. On DuckDB, the table format is fixed by the connection and a task cannot override it.
The warehouse schema¶
Every Warehouse profile names a schema. It is where cloning copies the Engine DB's tables, and
the session's default schema on Databricks, Snowflake and DuckDB over Iceberg; DuckDB over Iceberg
cannot connect at all while it is missing. It must already exist: etl-craft never
creates warehouse schemas. A run with cloning on checks it before starting, and stops naming it
when it is missing. On Trino, whose jdbc_url ends in /<catalog>/<schema>, the two must name the
same schema.
Tasks write wherever their own TARGET_OBJECT (schema.table) says, whatever this setting is.
Every profile names its database (or catalog): in the jdbc_url, or in database/catalog
where the warehouse takes separate fields. The engine connects in it, so SQL and TARGET_OBJECT
can name tables as schema.table and move between environments unchanged; a
database.schema.table name is used as written. A profile whose database cannot be told fails
when the file is loaded.
Connecting and authenticating¶
Each warehouse accepts the auth modes below. secret and token always name a variable, never a
value. Modes not verified here follow the vendor's documentation and can be used, but success is
not guaranteed.
| Warehouse | auth_mode (verified here in bold) |
|---|---|
| Postgres | password, token, key_file, oauth, sso, sts (as for a PostgreSQL Engine DB) |
| DuckDB file | none |
| DuckDB over Iceberg | none, token, oauth: how DuckDB logs in to the REST catalog |
| Trino | none, password, token, oauth, sso, key_file |
| Databricks | token, oauth (a service principal), sso (browser login) |
| Snowflake | password, token, key_file (key pair), oauth, sso (browser), sts (workload identity) |
Databricks and Snowflake can also be given as separate fields instead of one JDBC URL; see the examples.
Storage outside the warehouse's own¶
Where the data files live can be chosen per task, with task parameters:
- Databricks, native or Iceberg:
EXTERNAL_LOCATIONis the table's own path in cloud storage (s3://…,abfss://…,gs://…), which makes it an external table; Unity Catalog must cover the path with an external location. Without it, the table is managed and stored where its catalog or schema says, so a catalog backed by external storage needs nothing extra. Cloning mirrors go under the Cloning section'sBase_locationwhen it is set. - Snowflake, Iceberg:
EXTERNAL_VOLUMEandBASE_LOCATIONput the table on a customer volume (both are required together); without them it uses Snowflake-managed storage.CATALOGnames a catalog integration for an externally managed Iceberg catalog, which needs a customer volume; whether Snowflake accepts writes there depends on the integration. Cloning mirrors need the Cloning section'sExternal_volumeandBase_location. - Trino, Iceberg:
EXTERNAL_LOCATIONis the Iceberg table'slocation, which must be empty; without it, the catalog places the table under its schema's location. - Snowflake, native, PostgreSQL, DuckDB and DuckDB over Iceberg take no storage parameters: ordinary tables live in the database's own storage, and the Iceberg REST catalog places DuckDB's Iceberg tables itself.
A storage parameter the warehouse does not use fails the task, naming it and the ones that apply,
instead of being ignored. A table given an EXTERNAL_LOCATION cannot be rebuilt by
SCHEMA_EVOLUTION; add its new columns yourself.
The Databricks and Snowflake options have not been run against a live account in this project; Trino's is tested against the local services.