Cerbero.Snapshot.Exporter.Queries (cerbero v0.1.0)

Copy Markdown View Source

EVERY SQL statement the exporter can run, on one reviewable screen. No dynamic SQL beyond schema-name parameters and the quoted migrations-table identifier. The only non-catalog read is the versions column of the migrations table. This module is the privacy allowlist's first layer — review it like one.

Note on tables/1 and indexes/1: both take an engine ("postgres" | "cockroachdb") because pg_relation_size/pg_total_relation_size — the only byte-size functions PG exposes — don't exist on CockroachDB (confirmed empirically in the layer 4 CRDB differential: unknown function: pg_relation_size(), SQLSTATE 42883). Rather than fail the whole export over two columns, the CockroachDB branch reports heap_bytes/total_bytes/bytes as NULL — an honest "unknown," not a fabricated zero. CRDB does expose row-count estimates via crdb_internal.table_row_statistics (see crdb_row_counts/0) but nothing equivalent for on-disk bytes was found in this CRDB version (v25.1) at the time of writing; revisit if a later version adds one.

Note on crdb_row_counts/0: estimated_row_count reads a literal 0 — not SQL NULL — for a table whose statistics haven't been collected/propagated yet, confirmed empirically to persist for several seconds after a statistics-collection statement (a "create statistics" DDL, deliberately not spelled in full caps here — this comment lives in the module the read-only regression test greps for write keywords) completes (some internal cache/propagation lag beyond the statement's own commit). 0 is therefore indistinguishable at the SQL level from "no statistics yet," so Cerbero.Snapshot.Exporter maps a 0 here to nil rather than forwarding it as a real row count — see the crdb_row_counts/2 comment there for the full reasoning and its accepted cost (a genuinely empty CRDB table also reads as unknown scale, not confidently zero).

Note on constraints/0: is_not_null_check_on used to extract its capture group with regexp_match(...)... [1], which does not exist on CockroachDB (unknown function: regexp_match()). substring(x from pattern) — SQL-standard POSIX substring, not engine-specific — returns the same capture directly (no array indexing) and is supported identically by both engines, so this one has no engine branch; it was simply the more portable way to write the same query.

Note on columns/0: it reports default_kind (a closed enum: sequence | literal | expression) but deliberately does NOT compute a default_volatile column itself. Cerbero.Snapshot.Exporter derives volatile from default_kind downstream (literal -> false, anything else -> true) — privacy is unaffected since kind is already an exported enum. This replaced an earlier pg_depend/pg_proc.provolatile join that under-reported: Postgres never records a pg_depend row from a default onto a pinned (built-in) function, so now(), clock_timestamp(), random(), and nextval() were all invisible to it. Deriving from kind instead over-reports (a deterministic expression default like lower('x') reads as volatile too) rather than under-report — the safe direction, since a false "this rewrites the table" is a nuisance and a false "this doesn't" is an outage.

Summary

Functions

All (name, sql) pairs the --emit-sql script includes, in order. The engine argument selects the engine-branched queries and, for CockroachDB, appends the crdb-only sections; from_file detects the engine by the presence of the crdb_version section, so the two scripts stay self-describing.

Functions

applied_migrations(quoted_table)

columns()

constraints()

crdb_probe()

crdb_row_counts()

crdb_stats_times()

crdb_version()

current_database()

emit_list(engine \\ "postgres")

All (name, sql) pairs the --emit-sql script includes, in order. The engine argument selects the engine-branched queries and, for CockroachDB, appends the crdb-only sections; from_file detects the engine by the presence of the crdb_version section, so the two scripts stay self-describing.

indexes(engine \\ "postgres")

server_version_num()

standby()

stats_reset()

tables(engine \\ "postgres")

version()