Inspects database schema for DB Sync module.
Discovers available tables, their columns, and metadata. Uses PostgreSQL information_schema for introspection.
Security Considerations
- Only returns tables in the public schema by default
- System tables (pg_*, information_schema) are excluded
- Admin can configure allowed/blocked tables (future feature)
Example
iex> SchemaInspector.list_tables()
{:ok, [
%{name: "users", estimated_count: 150},
%{name: "posts", estimated_count: 1200},
...
]}
iex> SchemaInspector.get_schema("users")
{:ok, %{
table: "users",
columns: [
%{name: "id", type: "bigint", nullable: false, primary_key: true},
%{name: "email", type: "character varying", nullable: false},
...
],
primary_key: ["id"]
}}
Summary
Functions
Creates a table based on a schema definition from another database.
Returns a map of table_name => list of referenced table names (FK dependencies). Only includes tables in the public schema.
Returns FK column details for a table: list of %{column, referenced_table, referenced_column}.
Gets the exact count of records in a local table.
Gets the primary key columns for a table.
Gets the schema (columns, types, constraints) for a specific table.
Returns a content checksum for a table (MD5 hash of all rows cast to text). Used to detect actual data differences beyond row count.
Returns unique constraint columns for a table (excluding primary key). Used to match records by unique fields (e.g., match users by email). Returns list of lists (each inner list is a set of columns forming a unique constraint).
Lists all available tables with row counts.
Checks if a table exists.
Validates a PostgreSQL identifier (table or column name).
Functions
Creates a table based on a schema definition from another database.
Used by DB Sync to create tables that exist on sender but not on receiver.
Parameters
table_name- Name of the table to createschema_def- Schema definition map with columns and primary_key
Example
schema_def = %{
"columns" => [
%{"name" => "id", "type" => "bigint", "nullable" => false, "primary_key" => true},
%{"name" => "name", "type" => "character varying", "nullable" => true}
],
"primary_key" => ["id"]
}
SchemaInspector.create_table("users", schema_def)
Returns a map of table_name => list of referenced table names (FK dependencies). Only includes tables in the public schema.
Returns FK column details for a table: list of %{column, referenced_table, referenced_column}.
@spec get_local_count( String.t(), keyword() ) :: {:ok, non_neg_integer()} | {:error, any()}
Gets the exact count of records in a local table.
This is used by the receiver to compare local vs sender record counts.
Gets the primary key columns for a table.
Gets the schema (columns, types, constraints) for a specific table.
Returns
{:ok, schema}- Map with table info and columns{:error, :not_found}- Table doesn't exist{:error, reason}- Database error
Returns a content checksum for a table (MD5 hash of all rows cast to text). Used to detect actual data differences beyond row count.
Skips checksumming for tables with more than max_rows rows (default: 10_000)
to avoid expensive full-table scans. Returns {:ok, :too_large} in that case.
Returns unique constraint columns for a table (excluding primary key). Used to match records by unique fields (e.g., match users by email). Returns list of lists (each inner list is a set of columns forming a unique constraint).
Lists all available tables with row counts.
Returns tables from the public schema, excluding system tables and security-sensitive tables.
Options
:include_phoenix_kit- Include phoenixkit* tables (default: true):schema- Database schema to inspect (default: "public"):exact_counts- Use exact COUNT(*) instead of pg_stat estimates (default: true)
Checks if a table exists.
Validates a PostgreSQL identifier (table or column name).
Only accepts names that start with a letter or underscore and contain only alphanumerics and underscores. Anything else — including SQL metacharacters, whitespace, or quotes — is rejected.
Use this to guard any dynamic identifier that will be interpolated into raw SQL, before quoting it with double quotes.