Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Consult PostgreSQL's pg_dump implementation for guidance on system catalog queries and schema extraction when implementing pgschema features
.claude/skills/microck-pg-dump-reference/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-10 | ✗→✓ | ▲ Improved | 106% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 45% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 30% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 38% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 34% | 0% |
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:
sql-- 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:
sqlSELECT 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):
goquery := ` 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:
sqlSELECT 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):
gotype Index struct { Name string Columns []string Predicate string // WHERE clause for partial indexes // ... }
git log -p or GitHub blame to see when features were added and understand the evolutionAfter consulting pg_dump and implementing in pgschema:
testdata/diff/go test -v ./internal/diff -run TestDiffFromFilesgo test -v ./cmd -run TestPlanAndApply| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-02 | fail→fail | 13,797 | 7,711 | -44% | 1 | 1 | 0% | 2,644 | 3,686 | +39% | 0 | 0 | — |
case-11 | pass→pass | 11,767 | 6,432 | -45% | 1 | 1 | 0% | 1,976 | 3,011 | +52% | 0 | 0 | — |
case-03 | pass→pass | 14,992 | 8,768 | -42% | 1 | 1 | 0% | 2,652 | 3,666 | +38% | 0 | 0 | — |
case-04 | fail→fail | 13,925 | 9,810 | -30% | 1 | 1 | 0% | 2,839 | 4,426 | +56% | 0 | 0 | — |
case-10 | fail→pass | 10,633 | 7,266 | -32% | 1 | 1 | 0% | 1,770 | 3,641 | +106% | 0 | 0 | — |
case-01 | fail→pass | 18,493 | 12,481 | -33% | 1 | 1 | 0% | 3,134 | 4,537 | +45% | 0 | 0 | — |
case-05 | fail→fail | 4,899 | 4,783 | -2% | 1 | 1 | 0% | 843 | 3,012 | +257% | 0 | 0 | — |
case-06 | pass→pass | 8,120 | 4,584 | -44% | 1 | 1 | 0% | 1,642 | 3,035 | +85% | 0 | 0 | — |
case-07 | fail→pass | 18,123 | 12,545 | -31% | 1 | 1 | 0% | 3,769 | 4,897 | +30% | 0 | 0 | — |
case-08 | fail→pass | 11,804 | 4,320 | -63% | 1 | 1 | 0% | 2,142 | 2,960 | +38% | 0 | 0 | — |
case-09 | pass→pass | 14,005 | 6,737 | -52% | 1 | 1 | 0% | 2,536 | 3,513 | +39% | 0 | 0 | — |
case-12 | pass→pass | 3,660 | 3,109 | -15% | 1 | 1 | 0% | 595 | 2,706 | +355% | 0 | 0 | — |
case-13 | fail→pass | 18,586 | 15,917 | -14% | 1 | 1 | 0% | 3,100 | 4,152 | +34% | 0 | 0 | — |
case-14 | fail→pass | 17,147 | 3,668 | -79% | 1 | 1 | 0% | 3,069 | 2,817 | -8% | 0 | 0 | — |
case-15 | fail→pass | 17,950 | 2,836 | -84% | 1 | 1 | 0% | 3,032 | 2,785 | -8% | 0 | 0 | — |
case-16 | pass→pass | 15,477 | 6,351 | -59% | 1 | 1 | 0% | 2,626 | 3,201 | +22% | 0 | 0 | — |
case-17 | pass→pass | 4,962 | 2,396 | -52% | 1 | 1 | 0% | 752 | 2,575 | +242% | 0 | 0 | — |
case-18 | pass→pass | 6,995 | 2,095 | -70% | 1 | 1 | 0% | 1,261 | 2,651 | +110% | 0 | 0 | — |
case-19 | pass→fail | 9,069 | 5,769 | -36% | 1 | 1 | 0% | 1,718 | 3,294 | +92% | 0 | 0 | — |
case-20 | fail→pass | 18,417 | 9,042 | -51% | 1 | 1 | 0% | 2,921 | 3,694 | +26% | 0 | 0 | — |
case-21 | pass→pass | 15,591 | 6,334 | -59% | 1 | 1 | 0% | 2,533 | 3,320 | +31% | 0 | 0 | — |
case-22 | fail→fail | 17,504 | 14,230 | -19% | 1 | 1 | 0% | 3,584 | 4,994 | +39% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +32 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.