introspect_schema
List the tables and columns a cube SQL may read from a connection, with row estimates and semantic roles. Parameters, errors and scope.
Lists the tables and columns a cube SQL may read from a connection, and only
those. It never exposes the full database. This is step one of authoring a
refreshable dashboard: read the columns, pick low-cardinality dimensions and
additive measures, then write and validate the SQL with
validate_cube_sql.
Behaviour hints for clients: read-only, not open-world.
Parameters
| Parameter | Type | Required | Notes |
|---|---|---|---|
connection | string | no | self (the default) or a warehouse connection id from list_connections. |
tables | array | no | Filter terms. Each is matched case-insensitively against any part of the fully-qualified table name. |
Narrow with tables once you know what you are building
On a real warehouse an unfiltered introspect returns every readable table with
every column, which is the single largest result in the authoring flow and mostly
not about your dashboard. Because a term matches any part of the qualified name,
one argument serves as a database, schema or table filter: on Snowflake SALES
narrows to that database and SALES.PUBLIC to that schema; on Postgres and
self the names are bare, so pass the table name. Omit it the first time, when
you genuinely want to see what is there.
Returns
Readable schema for connection "self".
Table: dashies_usage_metrics
- day: date - dimension: the UTC day the metric was recorded
- publishes: bigint - flow: dashboards published that day
- active_dashboards: bigint - stock: dashboards live at the end of that day
BEGIN_JSON
{"connection":"self","tables":[{"name":"dashies_usage_metrics","columns":[{"name":"day","type":"date","role":"dimension","description":"..."}]}]}
END_JSON
With a filter applied the header instead reads
Readable schema for connection "<c>" - 3 of 214 tables matching "orders".
| Field | Meaning |
|---|---|
role | dimension, flow or stock. self only; warehouse columns carry no role yet. |
row_estimate | Rendered as Table: <name> (~<n> rows). Warehouse only. |
size_band | small, big or extreme. |
recommended_mode | inline, parquet or reject. |
Never SUM a stock column
flow accumulates across the grain and is safe to sum. stock is a level
measured at one instant, and summing it across a time grain recounts the same
entities every period. A cohort cube summing ending ARR over 24 tenure months
once reported 596 million dollars against a real 36 million. Only self columns
carry the role, so on a warehouse you have to know this yourself, and declare it
with stock_columns when you validate.
The row estimate is the remote planner's approximation, captured when the
connection was created or last resynced. Treat it as a scale signal, never an
exact count. A table with no estimate may simply be unanalyzed on the remote; the
fast exact check is validate_cube_sql with
select count(*) as n from <table>, which pushes down to the remote and stays
fast at millions of rows.
It returns column names, not column values
Before writing a filter predicate or a conditional count against an enum-like
column, confirm its real values with a quick validate_cube_sql that groups by
that column. Introspection cannot tell you what is in a column.
Errors
The shared connection rules, plus:
| Condition | Text |
|---|---|
| The schema read failed | Could not read the schema for connection "<c>": <err> |
| Nothing readable, warehouse | No readable tables are available for connection "<c>". The connection has no readable tables yet - check the imported schema(s) and that the read-only role can SELECT them. |
Nothing readable, self | No readable tables are available for connection "<c>". The refresh allowlist may be misconfigured. |
| A filter that matches nothing | No readable table on connection "<c>" matches "<f>". Each filter is matched case-insensitively against the fully-qualified table name, so any part of one works. Available: <up to 40 names> (+<n> more). |
| A malformed filter | tables must be an array of table-name filters (or a single string) - each is matched case-insensitively against the fully-qualified table name. |
| An empty filter array | tables must contain at least one filter - omit it entirely to list every readable table. |
A filter that matches nothing lists what is actually there, so the fix is one corrected call rather than an unfiltered re-list of the whole warehouse.
Scope
Connection-scoped, so there is no workspace argument. It accepts a
connection you own personally or one belonging to a workspace you are a current
member of. Using a warehouse connection requires a paid plan; self does not.
Check it worked
Every column you intend to group by or aggregate should appear in the listing
with the type you expect. If a table you know exists is missing, check the
connection's imported schemas in the web app rather than assuming the filter is
wrong, and re-run without tables to see the full set.