Concepts
Schema files
Declare the relations and functions your SQL reads, so conversion can type it.
Conversion needs to know what each relation and column name refers to and what Snowflake type it
has. A schema file declares them as JSON. Pass it with --schema to convert, function,
census and index.
{ "ORDERS": [ ["ORDER_ID", "NUMBER(38,0)"], ["CUSTOMER_ID", "NUMBER(38,0)"], ["TOTAL", "NUMBER(12,2)"], ["ORDERED_AT", "TIMESTAMP_NTZ"] ]}A name the schema does not declare is refused with SQ0004.
Naming relations and columns
Section titled “Naming relations and columns”Names resolve as Snowflake resolves them. An unquoted name is upper-cased, so FROM orders reads
the relation ORDERS. A quoted name keeps its case, so "orders" is a different relation from
ORDERS. When a name matches a declared one only ignoring case, the diagnostic says so and
suggests the spelling to declare.
Declare a relation as ORDERS, SALES.ORDERS or ANALYTICS.SALES.ORDERS. A qualified name in the
SQL, such as analytics.sales.orders in dbt’s compiled models, reads the declared relation whose
parts agree with it, and the converted SQL names that relation as declared:
| Declared | SQL | Reads |
|---|---|---|
ORDERS |
orders, sales.orders, analytics.sales.orders |
ORDERS |
ANALYTICS.SALES.ORDERS |
orders, sales.orders, Analytics.Sales.Orders |
ANALYTICS.SALES.ORDERS |
ANALYTICS.SALES.ORDERS and ANALYTICS.ARCHIVE.ORDERS |
sales.orders |
ANALYTICS.SALES.ORDERS |
ANALYTICS.SALES.ORDERS and ANALYTICS.ARCHIVE.ORDERS |
orders |
refused: it matches both |
The session’s DATABASE and SCHEMA complete a name written without them, as in Snowflake:
with --session SCHEMA=archive, orders reads ANALYTICS.ARCHIVE.ORDERS. See
Sessions.
These are refused with SQ0004, naming the relations
involved:
- A name matching several declared relations that no session default settles.
- A qualified name whose declared relation a CTE of the same name hides.
- Two differently qualified names in one statement that read the same declared relation. Declare each under its qualified name.
The converted SQL reads a qualified relation from the database you attach to DuckDB under that
name, such as ATTACH 'analytics.duckdb' AS analytics.
Columns
Section titled “Columns”Each column is a [name, type] pair, or an object:
| Field | Meaning |
|---|---|
name |
The column name. |
type |
Its Snowflake type, such as NUMBER(12,2), VARCHAR or VARIANT. |
typed_leaves |
true when a VARIANT column’s leaves hold typed values. Default false. |
offset |
For a TIMESTAMP_TZ column whose every value has one offset: +00:00 or UTC. |
--confirm-declared-offsets lets strict mode rely on the offsets the schema declares.
Relations and functions
Section titled “Relations and functions”The top level is either a map of relations, as above, or an object with two sections:
{ "relations": { "ORDERS": [["ORDER_ID", "NUMBER(38,0)"], ["TOTAL", "NUMBER(12,2)"]] }, "functions": { "NET_TOTAL": { "language": "sql", "arguments": [["GROSS", "NUMBER(12,2)"]], "returns": "NUMBER(12,2)" } }}A function declares its language (sql or python), its arguments as columns, and what it
returns. volatility, null_input and vectorized are optional. Unknown fields are rejected.