Reference
Introspection support
Look up which catalog facts each adapter reads, which versions it accepts, and which database features remain outside Snapshot v1.
The optional qubu/introspection entrypoint reads one selected database
namespace through a user-owned CatalogConnection. It returns normalized
catalog data and can map that data to canonical Snapshot v1 or v2. The
application owns the driver and connection lifecycle. Snapshot diffing,
migration planning, and DDL emission are separate Qubu capabilities; see the
ownership map.
Version and namespace baseline
| Adapter | Baseline | Selected namespace | Product policy |
|---|---|---|---|
| PostgreSQL | 12+ | one PostgreSQL schema | PostgreSQL only |
| SQLite | 3.37+ | one database, normally main |
attached databases are not combined |
| MySQL | 8.0.16+ | one MySQL database | MariaDB requires a separate adapter |
Version and product failures are structured diagnostics. The adapters do not silently downgrade to a different product's catalog rules.
Catalog facts
| Fact | PostgreSQL | SQLite | MySQL |
|---|---|---|---|
| Tables and visible columns | pg_class, pg_attribute |
sqlite_schema, table_xinfo |
TABLES, COLUMNS |
| Native storage | format_type |
declared type | COLUMN_TYPE |
| Defaults | pg_get_expr |
dflt_value |
COLUMN_DEFAULT |
| Generated columns | stored expressions | stored/virtual when CREATE SQL is recoverable | stored/virtual and GENERATION_EXPRESSION |
| Identity behavior | attidentity |
INTEGER PRIMARY KEY, AUTOINCREMENT |
AUTO_INCREMENT |
| Keys and foreign keys | pg_constraint |
table metadata and foreign_key_list |
TABLE_CONSTRAINTS, KEY_COLUMN_USAGE, REFERENTIAL_CONSTRAINTS |
| Checks | pg_constraint and decompiled definition |
CREATE SQL | CHECK_CONSTRAINTS |
| Indexes | pg_index, access method, decompiled terms |
index_list, index_xinfo, schema SQL |
STATISTICS |
| Complete PostgreSQL objects | views/materialized views, sequences, enums/domains, collations, triggers, routines, partitions, row-level policies, comments/owners, and extensions | N/A | N/A |
| Complete SQLite objects | N/A | views and triggers when CREATE SQL is recoverable; table/view columns from table_xinfo |
N/A |
| Complete MySQL objects | N/A | N/A | typed views and view columns, routines and parameters, triggers, partitions, used collations, comments, and opaque scheduled events |
| Unsupported MySQL families | N/A | N/A | sequences, materialized views, row-level security (RLS) policies, extensions, and ownership |
| Deferred or opaque objects | foreign tables and relation kinds without a safe typed mapping | virtual/shadow tables, attached-database boundaries, and unrecoverable definitions | scheduled events are opaque; unknown or other non-base table rows are deferred |
The readers preserve physical names and use database catalog identifiers only as current-run join keys. The normalized catalog keeps opaque SQL and its source, whether it came from a catalog value, a database decompiler, or CREATE SQL.
PostgreSQL complete catalog surface
The PostgreSQL reader also fills the complete normalized catalog used by
Snapshot v2. It keeps PostgreSQL OIDs in current-run physical references and
keeps decompiler output such as pg_get_viewdef, pg_get_triggerdef, and
pg_get_functiondef as tagged SQL data. It does not evaluate that text.
The query and normalization layout follows the catalog-oriented parts of the Drizzle PostgreSQL introspector, while Qubu keeps the result as typed data instead of generating TypeScript declarations.
Use mapCatalogToCompleteSnapshot() for this object set. Use
mapCatalogToSnapshot() when a caller explicitly needs the existing table-only
Snapshot v1.
SQLite complete catalog surface
The SQLite reader uses fixed statements over sqlite_schema and the
table-valued PRAGMAs database_list, table_list, table_xinfo,
index_list, index_xinfo, and foreign_key_list. Each table-valued PRAGMA
receives bound namespace or object parameters through the caller's
CatalogConnection. The reader does not interpolate a database name into SQL.
SQLite views and triggers become typed complete catalog objects when their
CREATE SQL has a recoverable definition and target. Their SQL remains tagged
opaque data with a sqlite dialect and a catalog reference. Generated column
expressions, declared storage types, SQLite affinity, rowid aliases, and
AUTOINCREMENT are kept as column or identity dialect extensions. User indexes
retain ordered column or expression terms and partial predicates. Inline UNIQUE
constraints are recovered from their internal indexes with deterministic Qubu
names, so SQLite's sqlite_autoindex_* names do not become persisted logical
IDs.
SQLite virtual tables and shadow tables remain typed deferred objects with an
unmodeled-object diagnostic. A selected attached database can expose table
PRAGMA rows, but its schema SQL is outside the fixed main and temp
statements. Qubu marks that result as limited and keeps other attached
databases as opaque boundary records. It never combines attached databases into
the selected namespace. SQLite does not provide the PostgreSQL object families
such as routines, materialized views, policies, or ownership, so the reader
does not fabricate them.
mapCatalogToCompleteSnapshot() retains the typed views, triggers, deferred
objects, opaque boundaries, and dialect extensions in Snapshot v2. The existing
mapCatalogToSnapshot() still maps only tables and preserves Snapshot v1
behavior.
The query and normalization seams follow the catalog-reading portions of the Drizzle SQLite introspector. Drizzle's module generates source declarations; Qubu keeps the same SQLite metadata sources as normalized data and never evaluates database-provided SQL. The optional source generator consumes the strict Snapshot v1 result through a separate controlled printer.
MySQL 8 complete catalog surface
The MySQL reader accepts MySQL 8.0.16 and later within the MySQL 8 series. It
rejects MariaDB and older MySQL versions instead of applying MySQL catalog
rules to a different product or server version. It reads INFORMATION_SCHEMA
rows for one selected database and retains database-provided SQL as tagged,
unevaluated MySQL data.
MySQL has typed complete records for views, routines and their parameters,
triggers, partitions, collations used by selected tables or columns, and
comments. View definitions come from INFORMATION_SCHEMA.VIEWS; each view's
columns are joined back to the matching COLUMNS rows by physical table name,
so the complete Snapshot v2 cross-reference points at the view's own column
IDs. Missing view definitions or unresolved trigger, partition, or other
object references become deferred records with diagnostics.
Scheduled events are retained as CatalogOpaqueObject records. Their event
metadata and definition remain opaque, and the reader emits an
unmodeled-object warning. Snapshot v2 keeps these records in
opaqueObjects; they are not treated as typed routines, triggers, or
migration operations.
The MySQL reader does not expose typed sequences or materialized views. A sequence-like or other non-base table row is retained as a deferred object when the catalog reports one. MySQL row-level security (RLS) policies, extension objects, and ownership are unsupported complete families. Definers on views, routines, triggers, and events remain dialect metadata; they do not become ownership records. The corresponding capability flags are false.
The query and normalization layout follows the catalog-reading portions of the Drizzle MySQL introspector, while Qubu keeps the result as typed data instead of generating TypeScript declarations.
Use mapCatalogToCompleteSnapshot() to retain these typed MySQL families and
the opaque or deferred boundaries in Snapshot v2. Use mapCatalogToSnapshot()
when a caller explicitly needs the existing table-only Snapshot v1.
Snapshot v1 surface
The mapper can emit these facts in canonical Snapshot v1:
- one namespace and ordinary tables;
- exact dialect-native column storage;
- nullability and unambiguous literal or opaque SQL defaults;
- generated columns with stored or virtual mode;
- identities kept separate from defaults and generated columns;
- primary, unique, nullable-unique, foreign-key, and check constraints;
- ordered column or expression index terms, predicates, included columns, and representable dialect extensions;
- stable logical IDs with physical names preserved separately.
Strict mode returns no snapshot when a supported table fact cannot be mapped soundly. Lossy mode is explicit and marks warnings in the result. A fingerprint is canonical content, not an identity or rename marker.
Deferred and limited features
The following remain catalog facts or diagnostics rather than fabricated Snapshot v1 objects:
- views and materialized views;
- sequences, enums, domains, routines, triggers, policies, extensions, collations, comments, and partition metadata;
- PostgreSQL identity sequence options that have no typed Snapshot v1 field;
- SQLite virtual/shadow tables, attached namespaces, and unrecoverable generated or expression definitions;
- MySQL/MariaDB differences, prefix indexes, invisible indexes, and advanced functional, full-text, or spatial index semantics.
Use the complete catalog and Snapshot v2 mapper to retain supported PostgreSQL and MySQL families. MySQL scheduled events stay opaque, and MySQL sequences, materialized views, row-level security (RLS) policies, extension objects, and ownership stay unsupported or deferred. When a row cannot be normalized safely, the reader keeps a typed deferred or opaque record and emits a diagnostic instead of dropping it.
Upstream references
The dialect reader structure follows useful patterns from Drizzle Kit while keeping Qubu's output data-only:
Those modules generate TypeScript declarations as part of their workflows. Qubu keeps catalog normalization, Snapshot v1 mapping, and optional source generation as separate pure boundaries, so diffing and planning do not depend on source generation.
See Database introspection for the connection adapter example, identity rules, diagnostics, and the later diff/planning boundary. See the PostgreSQL, SQLite, and MySQL snapshot pages for the pure serialization adapters.