agentsclimarketplace

Schema verify via information schema

Skill Ed3Design/ed3design-skill-bundles/schema-discipline/skills/schema-verify-via-information-schema

Claude Code skill bundles for software engineering: 56 skills + 5 Python tools + 6 hooks + 4 sub-agents across 6 thematic plugins (token-savers, code-quality, planning-disciplines, async-forensik, schema-discipline, skill-system-meta). Empirically TDD-validated patterns, MIT licensed.

Install
npx -y skills add Ed3Design/ed3design-skill-bundles --skill schema-verify-via-information-schema

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use when about to write or execute SQL against a PostgreSQL/TimescaleDB table whose exact schema (column names, types, deprecated-vs-active-variant) is not 100% certain from current context — especially in forensic debugging where multiple tables have similar names (`ohlcv_1d` vs `ohlcv_1d_hist`, `users` vs `users_v2`) or column names have shifted over time. Iron-Law: `SELECT column_name, data_type FROM information_schema.columns WHERE table_name=$1 ORDER BY ordinal_position` is the cheapest 30-second insurance against UndefinedColumn, false-positive-empty-result, and wrong-table-queried. Trigger on phrases like "writing a query against table X", "UndefinedColumn", "column X does not exist", "verify DB schema", "I think the column is called Y", "before any forensic query". Do NOT load for ORM-mediated queries (SQLAlchemy/Django catch drift at model-load), first-time-schema-design, catalog-queries on information_schema itself, or connection issues.

SKILL.md

7.6 KB, ~1.7k tokens by cl100k_base, as published. Nobody here has run it

Schema-Verify via information_schema

The Iron Law

Before any forensic SELECT/UPDATE/DELETE against a table whose schema is not certain from current context: run one information_schema.columns query first. Cost: <100 ms + ~5 lines of code. Saved: typically 10-60 min of dead-end debugging or false-positive empty-result interpretations.

Why this matters

The naive flow:

  1. "I need the win rate. Query against virtual_trades with open_price."
  2. asyncpg.exceptions.UndefinedColumnError: column "open_price" does not exist
  3. "Ah, maybe it's called entry_price?" — retry, errors continue
  4. 2-3 iterations, 10-15 min gone

Or worse:

  1. Query against ohlcv_1d for last 30 days.
  2. 0 Rows returned.
  3. "The data pipeline is dead, build a new hypothesis!"
  4. 30 min debugging pipeline code.
  5. Turns out: ohlcv_1d is deprecated, the active table is ohlcv_1d_hist — it has 21 bars/symbol/30 days perfectly populated.

The real path:

  1. First query always: SELECT column_name, data_type FROM information_schema.columns WHERE table_name=$1 ORDER BY ordinal_position
  2. Look at the schema output (read 10-30 columns, 15 seconds)
  3. Write the real query with verified column names
  4. On false-empty-result: additionally SELECT table_name FROM information_schema.tables WHERE table_schema='public' AND table_name LIKE '%<base>%' to see suffix variants

The 3-Step Procedure

Step 1 — Schema lookup as first DB operation

SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'my_table'
ORDER BY ordinal_position;

In Python/asyncpg:

cols = await conn.fetch(
    "SELECT column_name, data_type FROM information_schema.columns "
    "WHERE table_name=$1 ORDER BY ordinal_position",
    table_name,
)
for c in cols:
    print(f"  {c['column_name']:30s} {c['data_type']}")

Look at the output. THEN build the production query.

Step 2 — On "empty" result: search for sibling tables

If an expected table is empty, before concluding pipeline death:

SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
  AND table_name ILIKE '%my_table%'
ORDER BY table_name;

Discovered today: ohlcv_1d (deprecated, empty) vs ohlcv_1d_hist (active, full). Naming suffix _hist suggests "historical" → first intuition "backtest only". Wrong — it is the active daily yfinance source.

Step 3 — On "weird values" / type-error: check data_type

SELECT column_name, data_type, udt_name
FROM information_schema.columns
WHERE table_name=$1 AND column_name=$2;

Common pitfalls this catches:

  • timestamp vs timestamptz
  • numeric vs double precision (Decimal-vs-float trap from asyncpg-live-vs-mock-shape)
  • text vs varchar(N) with length limit
  • jsonb vs json vs text with JSON content
  • Custom-Enum-Type vs varchar

Concrete examples (your-app forensic day)

SymptomNaive hypothesisTrue findingIf skill had run first
UndefinedColumn open_price in v3_trades"wrong table name?"column is called ko_price_at_signal15s schema read → right column immediately
UndefinedColumn bar_time in ohlcv_1d"schema bug?"column is called time15s schema read
ohlcv_1d 0 rows in 30d"data pipeline dead!"table is deprecated, active is ohlcv_1d_histtables-suffix-search → right table

Anti-patterns

  • "I remember the columns" — schema drifts over weeks, migrations are invisible
  • "Empty result → pipeline dead" — before pipeline hypothesis: check sibling tables
  • Schema lookup only on error — the bias is reversed: lookup is PREVENTION, not REACTION
  • \d in psql without programmatic use — in live debug loop you lose the output on the next statement; keep it programmatically in the fetch result
  • Read schema once and keep it for hours — in long sessions a parallel migration may run; for forensics always fresh

Quick template

# Standard header for EVERY new forensic session against unknown table:
async def forensic_query(conn, table, **filters):
    # Step 1: Schema verify
    cols = await conn.fetch(
        "SELECT column_name, data_type FROM information_schema.columns "
        "WHERE table_name=$1 ORDER BY ordinal_position", table,
    )
    if not cols:
        # Step 2: Table does not exist — find siblings
        siblings = await conn.fetch(
            "SELECT table_name FROM information_schema.tables "
            "WHERE table_schema='public' AND table_name ILIKE $1",
            f"%{table}%",
        )
        raise ValueError(
            f"Table '{table}' not found. Siblings: "
            f"{[s['table_name'] for s in siblings]}"
        )
    schema = {c['column_name']: c['data_type'] for c in cols}
    print(f"[{table}] Schema: {list(schema.keys())}")
    # ... real query with verified columns

Skill composition

  • superpowers:systematic-debugging — runs BEFORE this skill for the wider "what is the bug" framing
  • asyncpg-live-vs-mock-shape — runs AFTER this skill for the Mock-vs-Live-Type-Layer (separate concern: asyncpg-type-coercion)
  • schema-use-case-mismatch-detection — runs IF schema is correct but NULL-pattern persists (different problem: semantic mismatch, not schema drift)
  • decision-plan-hypothesis-matrix — runs AROUND this skill: schema-verify is one of the "distinguishing metrics" before hypothesis formulation

Anti-skill — when this is NOT the right tool

SymptomRight tool instead
Field is consistently NULL despite active writerschema-use-case-mismatch-detection
asyncpg Decimal vs float TypeErrorsasyncpg-live-vs-mock-shape
First-time-schema-design (table doesn't exist)migration design skills (n/a in current catalog)
ORM-mediated query (SQLAlchemy / Django)ORM model introspection (different mechanism)

When-Built / Why-Built

Built after 3 separate schema-drifts caught in a single forensic day on a production domain:

  1. Win-rate analysis (morning): open_price not in v3_trades — schema drift since schema migration, correct column is ko_price_at_signal
  2. OHLCV-coverage query (afternoon): bar_time not in ohlcv_1d/_1h — correct column is time
  3. ohlcv_1d lookup (afternoon): table is deprecated, active table is ohlcv_1d_hist (suffix _hist misleading)

Each instance would have cost 10-30 min of dead-end if discovered through trial-and-error. With information_schema-First: ~15 seconds total overhead, zero dead-ends.

Promotion trigger: ≥3 further live applications in non-work sessions or in other projects (e.g. TimescaleDB-based monitoring).

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 327,069. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.