Consult PostgreSQL's pg_dump implementation for guidance on system catalog queries and schema extraction when implementing pgschema features
Use this skill when implementing or debugging pgschema features that involve extracting schema information from PostgreSQL databases. pg_dump is the canonical PostgreSQL schema dumping tool and serves as a reference implementation for how to query system catalogs correctly.
Invoke this skill when:
ir/inspector.goMain pg_dump repository: https://github.com/postgres/postgres/blob/master/src/bin/pg_dump/
Key files to reference:
pg_dump.c - Main implementation with system catalog queriespg_dump.h - Data structures and function declarationspg_dump_sort.c - Dependency sorting logicpg_backup_archiver.c - Output formattingcommon.c - Shared utility functions for querying system catalogsDetermine which PostgreSQL object type you're working with:
Search pg_dump.c for the function that handles your object type:
| Object Type | pg_dump Function | System Catalogs Used |
|---|---|---|
| Tables & Columns | getTables() | pg_class, pg_attribute, pg_type |
| Indexes | getIndexes() | pg_index, pg_class |
| Triggers | getTriggers() | pg_trigger, pg_proc |
| Functions | getFuncs() | pg_proc |
| Procedures | getProcs() | pg_proc |
| Views | getViews() | pg_class, pg_rewrite |
| Materialized Views | getMatViews() | pg_class |
| Sequences | getSequences() | pg_sequence, pg_class |
| Constraints | getConstraints() | pg_constraint |
| Policies | getPolicies() | pg_policy |
| Aggregates | getAggregates() | pg_aggregate, pg_proc |
| Types | getTypes() | pg_type |
| Comments | getComments() | pg_description |
Examine the SQL query used by pg_dump:
pg_get_expr, pg_get_constraintdef, etc.)Example - Extracting trigger WHEN conditions:
-- pg_dump's approach (from getTriggers):
SELECT t.tgname,
pg_get_expr(t.tgqual, t.tgrelid, false) as when_clause
FROM pg_catalog.pg_trigger t
WHERE t.tgqual IS NOT NULL
Note: information_schema.triggers.action_condition is NOT reliable for WHEN clauses. Always use pg_get_expr(t.tgqual, ...) from pg_catalog.pg_trigger.
Look for how pg_dump handles:
Apply the pattern to pgschema's codebase:
For database introspection (ir/inspector.go):
For SQL parsing (ir/parser.go):
For DDL generation (internal/diff/*.go):
pg_class - Tables, indexes, views, sequencespg_attribute - Table columnspg_type - Data typespg_constraint - Constraints (PK, FK, UNIQUE, CHECK)pg_index - Index definitionspg_proc - Functions, procedures, trigger functionspg_trigger - Trigger definitionspg_aggregate - Aggregate function definitionspg_policy - Row-level security policiespg_description - Comments on database objectspg_depend - Object dependenciespg_get_expr(expr, relation, pretty) - Deparse expressionspg_get_constraintdef(constraint_oid, pretty) - Get constraint definitionpg_get_indexdef(index_oid, column, pretty) - Get index definitionpg_get_triggerdef(trigger_oid, pretty) - Get trigger definitionKey differences:
Don't blindly copy pg_dump for:
Always reference pg_dump for:
pg_get_* functionspg_dump approach:
SELECT a.attname,
a.attgenerated,
pg_get_expr(ad.adbin, ad.adrelid) as generation_expr
FROM pg_attribute a
LEFT JOIN pg_attrdef ad ON (a.attrelid = ad.adrelid AND a.attnum = ad.adnum)
WHERE a.attgenerated != ''
pgschema adaptation (in ir/inspector.go):
query := `
SELECT a.attname,
a.attgenerated,
pg_get_expr(ad.adbin, ad.adrelid) as generation_expr
FROM pg_attribute a
LEFT JOIN pg_attrdef ad ON (a.attrelid = ad.adrelid AND a.attnum = ad.adnum)
WHERE a.attrelid = $1 AND a.attgenerated != ''
`
rows, err := conn.Query(ctx, query, tableOID)
pg_dump extracts WHERE clauses:
SELECT pg_get_expr(i.indpred, i.indrelid, true) as index_predicate
FROM pg_index i
WHERE i.indpred IS NOT NULL
pgschema stores in IR (ir/ir.go):
type Index struct {
Name string
Columns []string
Predicate string // WHERE clause for partial indexes
// ...
}
Search strategically: Clone postgres repo and use grep/ag to search for specific system catalog columns or keywords
Check git history: Use git log -p or GitHub blame to see when features were added and understand the evolution
Read comments carefully: pg_dump.c contains valuable comments explaining PostgreSQL internals and edge cases
Cross-reference documentation: Always combine pg_dump source with official PostgreSQL documentation:
Test incrementally: After adapting from pg_dump, test against real PostgreSQL instances using pgschema's embedded-postgres integration tests
Version awareness: Check how pg_dump handles version differences - pgschema supports PostgreSQL 14-17, so you may need conditional logic
After consulting pg_dump and implementing in pgschema:
testdata/diff/go test -v ./internal/diff -run TestDiffFromFilesgo test -v ./cmd -run TestPlanAndApply