Shape / inspect · All operations
Check a table's structure
A variant of Check data quality
Check that a table has the expected columns, names and types, failing or conforming it when it does not.
Status
- In arcform
Runs as a SQL step
arcform carries it as a
sql:step today.
The DuckDB step
Check a table has the expected columns, names and types, and conform it when it does not
-- what arrived: ids and amounts as text, no order_date, and a column nobody asked for
CREATE TEMP TABLE arrived AS SELECT * FROM (VALUES
('1', 'Alice Ng', '120.5', 'first'), ('2', 'Bob Okafor', 'n/a', 'second')) t(order_id, customer, amount, note);
CREATE TEMP TABLE expected_structure AS SELECT * FROM (VALUES
('order_id', 'BIGINT'), ('customer', 'VARCHAR'), ('amount', 'DOUBLE'), ('order_date', 'DATE')) t(column_name, column_type);
-- read the structure from DESCRIBE, then compare it with the expectation in both directions
CREATE TEMP TABLE problems AS
SELECT coalesce(e.column_name, a.column_name) AS column_name,
CASE WHEN a.column_name IS NULL THEN 'missing'
WHEN e.column_name IS NULL THEN 'unexpected'
ELSE 'wrong type: ' || a.column_type END AS problem
FROM expected_structure e FULL OUTER JOIN (SELECT column_name, column_type FROM (DESCRIBE arrived)) a USING (column_name)
WHERE a.column_name IS NULL OR e.column_name IS NULL OR a.column_type <> e.column_type;
-- conform: cast to the expected types (a value that does not fit becomes NULL), add the missing column, drop the extra one
CREATE TEMP TABLE conformed AS
SELECT TRY_CAST(order_id AS BIGINT) AS order_id, customer, TRY_CAST(amount AS DOUBLE) AS amount, CAST(NULL AS DATE) AS order_date FROM arrived;
CREATE TEMP TABLE problems_after AS
SELECT coalesce(e.column_name, a.column_name) AS column_name FROM expected_structure e
FULL OUTER JOIN (SELECT column_name, column_type FROM (DESCRIBE conformed)) a USING (column_name)
WHERE a.column_name IS NULL OR e.column_name IS NULL OR a.column_type <> e.column_type;
SELECT * FROM problems ORDER BY column_name;
SELECT * FROM conformed ORDER BY order_id;
SELECT CASE WHEN ((SELECT list((column_name, problem) ORDER BY column_name) FROM problems) = [('amount', 'wrong type: VARCHAR'), ('note', 'unexpected'), ('order_date', 'missing'), ('order_id', 'wrong type: VARCHAR')] AND (SELECT count(*) FROM problems_after) = 0 AND (SELECT list(column_name) FROM (DESCRIBE conformed)) = ['order_id', 'customer', 'amount', 'order_date'] AND (SELECT list((order_id, amount) ORDER BY order_id) FROM conformed) IS NOT DISTINCT FROM [(1, 120.5), (2, NULL)]) THEN 'as expected' ELSE error('the arrived table should have four structure problems, and the conformed table none, with the amount n/a turned to NULL') END AS verdict;- The statement builds its own data.
- It needs nothing installed beyond DuckDB itself.
- The statement checks its own result and raises an error when it is wrong: “the arrived table should have four structure problems, and the conformed table none, with the amount n/a turned to NULL”.
- It passed on DuckDB
v2.0.0 (Cyanoptera) d54cbbe3df.
What other tools call it
Meridian's classification; an independent blind rating agreed on 95.7% of 324 rows (variant, version 3).
AWS Glue (4)
ColumnCountread 2026-09-27Check the number of columns, to catch dropped columns
ColumnExistsread 2026-09-27Check that a column exists in the dataset
ColumnNamesMatchPatternread 2026-09-27Check that column names match a pattern
SchemaMatchread 2026-09-27Check that the schemas of two datasets match
KNIME Analytics Platform (3)
Reference Table Validatorread 2026-09-27Check a table's columns, types and domains against a second reference table and conform it
Table Structure Validatorread 2026-09-27Check that a table matches a reference column structure set in the dialog, fixing or failing
Table Validatorread 2026-09-27Check table structure and content against a specification set in the dialog
Polars (1)
DataFrame.match_to_schemaread 2026-09-27Check a frame against a target schema, erroring or coercing on missing, extra or mistyped columns
Power Query M (1)
Table.HasColumnsread 2026-09-27Report whether the table has the named column or columns
RapidMiner Studio (1)
Check Model Conformanceread 2026-09-27Check whether a table's columns and values are compatible with a model's training data
Background
In Polars, match_to_schema matches or evolves a frame's schema into a target schema, and by default returns an error if the two do not exactly match.[1] In DuckDB, DESCRIBE followed by a table name shows the schema of the table, and DESCRIBE put before a query shows the schema of the query's result.[2] DuckDB's information_schema views are Structured Query Language (SQL) standard views that describe the catalogue entries of the database.[3]
When to use it
In Amazon Web Services (AWS) Glue Data Quality, the ColumnCount rule checks whether any columns are dropped and the ColumnExists rule checks that columns exist.[4] Check structure first on any table that arrives from outside, since a renamed or dropped column breaks every rule that names it. (Meridian's view)
DuckDB's comma-separated values (CSV) reader detects column types from a sample of the file, 20,480 rows by default.[5] In DuckDB's CSV type detection, VARCHAR is the fallback, so columns that cannot be cast to any other candidate type are read as VARCHAR.[5] Check detected types against the expected structure on every load, not only the first, because a new file can bring a value that changes what is detected. (Meridian's view)
Polars' match_to_schema can be told to insert missing columns, to ignore extra columns, and to upcast integer or float columns.[1] Decide for each column whether a missing column, an extra column or a changed type should stop the load or be conformed, and write that decision down beside the expected structure. (Meridian's view)
The method
DuckDB's information_schema.columns view gives each column's ordinal position, whether it is nullable, and its data type, such as DECIMAL(18, 2).[3] In DuckDB, DESCRIBE can be used as a subquery, which allows creating a table from the description.[2] Hold the expected structure as a small table of column names and types and compare it with DESCRIBE's output by a full outer join, which names the missing, unexpected and retyped columns at once. (Meridian's view) Compare full type names, precision and scale included, since a DECIMAL(18, 2) that arrives as DECIMAL(18, 3) is a change worth seeing. (Meridian's view)
Sources
- [1]polars.DataFrame.match_to_schema — Polars documentationdocumentation
- [2]Describe – DuckDBdocumentation
- [3]Information Schema – DuckDBdocumentation
- [4]DQDL rule type reference - AWS Gluedocumentation
- [5]CSV Auto Detection – DuckDBdocumentation