Schema Exploration
Timescale (TigerData)OfficialCreated by tigerdataDistributed by Timescale (TigerData)
- Skill
- Tool integration
- Data and AI
- Apache-2.0
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a systematic approach for AI agents to investigate unfamiliar PostgreSQL databases. It emphasizes read-only catalog exploration to understand schema structure, business concepts, and object relationships. By prioritizing metadata analysis over direct data inspection, it ensures safe, authorized, and context-aware interactions with database environments, requiring explicit user approval before accessing data-derived statistics or row samples.
What it does
- Inventory database schemas, tables, views, and routines using read-only catalog queries.
- Corroborate business meaning through comments, keys, and dependency analysis.
- Request and manage user approval for accessing data-derived statistics or row samples.
- Validate query plans using EXPLAIN without executing data-modifying operations.
- Identify objects owned by installed PostgreSQL extensions.
- Report findings while clearly distinguishing between observed facts and inferences.
When to use it
- When you need to write SQL for an unfamiliar database schema.
- When a user asks for data-backed answers like counts or recent changes.
- When you need to locate where specific business concepts reside in the database.
- When you need to understand how specific tables, views, triggers, or RLS policies function.
Advantages
- Minimizes risk by defaulting to read-only metadata exploration.
- Prevents unauthorized data exposure by requiring explicit approval for statistics and row samples.
- Provides a clear, repeatable process for mapping database structure to business logic.
- Reduces errors in query generation by validating join keys and grains first.
- Ensures transparency by reporting limitations and distinguishing observations from assumptions.
Usage examples
- “How many active users are in the database?”
- The agent will first identify the relevant user table, check its schema and constraints, and then request approval to query statistics or sample rows to provide an accurate count.
- “Where is the order history stored?”
- The agent will search the catalog for tables or views related to 'orders' or 'history', inspect their columns and foreign keys, and report the likely location with supporting evidence.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/timescale/schema-exploration/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip schema-exploration.zip -d .agents/skills
Documentation by tigerdata
Explore a PostgreSQL database
Start with the user's question, not a full-database audit unless that is the explicit ask. Use the database connection already available to you; if none is available, ask for access or work from provided schema files. Stay within the database and schemas the user has authorized. Catalog metadata can reveal sensitive names or source code: do not export it unnecessarily.
Workflow
Establish the current database, server version, role, and scope. Use overview for a small inventory. Choose relevant schemas; do not assume
publiccontains the application.Pick the most promising object(s) and read only the matching drill-down reference: tables, partitioning/inheritance, foreign tables, views, routines, triggers, security/RLS, or extensions. Follow cross-references only when the question requires them.
Corroborate meaning with comments, definitions, keys, and known dependencies. Names are clues, not proof of business meaning. If data-derived values would help, use data-derived values only after obtaining approval for the specific columns and access method. Ask the user when semantics remain ambiguous.
If the user wants SQL, follow query authoring: establish join keys and grain, then validate a vetted read-only query with plain
EXPLAINwhere authorized. Do not mistake a valid plan for proof of business semantics.Stop once you can answer. Report the specific schema-qualified objects and evidence, distinguish observations from inferences, and state limitations (permissions, stale statistics, missing dependencies, unknown application logic).
Example finding
Illustrative only; report facts verified in the target database:
Observed:
sales.ordershas a primary key onorder_idand a foreign key fromaccount_idtosales.accounts.account_id.Inferred:
sales.orderslikely records one row per order; the keys support this, but do not establish what the business calls an “order.”Unresolved: The catalog does not show whether canceled orders remain in this table. Confirm with the application owner before assuming they do.
Safety and execution
Prefer structural catalog queries;
pg_statsis data-derived and requires approval too. Do not change schema, data, roles, or session-wide settings without authorization. Never call discovered functions or procedures, refresh materialized views, or runEXPLAIN ANALYZEon unknown queries. A function markedSTABLEorIMMUTABLEis not a safety guarantee.If your client supports transactions, use a read-only transaction and a reasonable statement timeout for exploration. Metadata queries are not a license to run full-table counts or unrestricted scans. Ask before sampling data; sample only when necessary, with explicit limits and a clear understanding of table size and access controls.
All reference queries are plain PostgreSQL SQL. Bind
$1,$2, etc. as values using your client's API.psqlusers can follow the optional psql adapter. Never interpolate an untrusted object name as raw SQL; placeholders cannot replace SQL identifiers in data queries.Queries target PostgreSQL 18. Each version-sensitive section notes alternatives for older majors where applicable. Check
server_version_numfirst. If a query fails due to permissions or version differences, report the limitation instead of guessing.
Files
- ATTRIBUTION.mdAdded by AutoGineer969 B
- LICENSELicence file added by AutoGineer9.4 KiB
- NOTICELicence file added by AutoGineer573 B
- SKILL.md4.3 KiB
- references/data-values.md5.7 KiB
- references/extensions.md1.8 KiB
- references/foreign-tables.md3.9 KiB
- references/overview.md5.9 KiB
- references/partitioning-and-inheritance.md6.7 KiB
- references/psql.md2.1 KiB
- references/query-authoring.md2.1 KiB
- references/routines.md2.9 KiB
- references/security.md2.5 KiB
- references/tables.md7.7 KiB
- references/triggers.md1.6 KiB
- references/views.md2.4 KiB
references/tables.md
Tables: grain, constraints, and relationships
Contents
Size and object signals
Columns
Constraints
Foreign keys touching the table
Views directly depending on this table
Indexes
Partitioning and inheritance
Interpret and stop
Use the schema and relation name from overview. In every query $1 = schema name, $2 = table name. Names are filtered as values, not interpolated as identifiers. These queries target PostgreSQL 18; see the constraint note for earlier majors.
Size and object signals
These are approximate planning statistics, not a count of visible rows. A partitioned parent's own size excludes children; foreign-table size is not meaningful (see foreign tables). Do not use this as a reason to scan data. The four structural flags are independent: a partition can also be a partitioned parent. Declarative partitions and traditional inheritance both use pg_inherits; relispartition distinguishes their edges. has_user_triggers excludes PostgreSQL's internal triggers, notably the ones created for foreign keys; those relationships are already covered under constraints. The flag includes disabled user-defined triggers. If relevant, drill down with triggers to inspect enabled state and behavior.
select
c.reltuples::bigint as estimated_rows
, c.relpages as estimated_pages
, pg_catalog.pg_total_relation_size(c.oid) as total_bytes
, c.relkind = 'p' as is_partitioned_parent
, c.relispartition as is_partition
, exists (
select 1
from pg_catalog.pg_inherits i
join pg_catalog.pg_class child on child.oid = i.inhrelid
where i.inhparent = c.oid
and not child.relispartition
) as has_inheritance_children
, not c.relispartition and exists (
select 1
from pg_catalog.pg_inherits i
where i.inhrelid = c.oid
) as has_inheritance_parent
, exists (
select 1
from pg_catalog.pg_trigger t
where t.tgrelid = c.oid
and not t.tgisinternal
) as has_user_triggers
from pg_catalog.pg_class c
join pg_catalog.pg_namespace n on n.oid = c.relnamespace
where n.nspname = $1
and c.relname = $2
and c.relkind in ('r', 'p', 'f')
;Columns
select
a.attnum as position
, a.attname as column_name
, pg_catalog.format_type(a.atttypid, a.atttypmod) as data_type
, a.attnotnull as not_null
, pg_catalog.pg_get_expr(d.adbin, d.adrelid) as default_or_generation_expression
, a.attidentity as identity_kind
, a.attgenerated as generated_kind
, pg_catalog.col_description(a.attrelid, a.attnum) as comment
from pg_catalog.pg_class c
join pg_catalog.pg_namespace n on n.oid = c.relnamespace
join pg_catalog.pg_attribute a on a.attrelid = c.oid
left join pg_catalog.pg_attrdef d on d.adrelid = c.oid and d.adnum = a.attnum
where n.nspname = $1
and c.relname = $2
and c.relkind in ('r', 'p', 'f')
and a.attnum > 0
and not a.attisdropped
order by a.attnum
;attidentity: a = always, d = by default, blank = neither. attgenerated: s = stored; PostgreSQL 18 adds v = virtual. On PostgreSQL 14–17 only stored generated columns exist; the same query runs there.
Constraints
Use definitions, not constraint names, to interpret keys and checks. PostgreSQL 18 can represent NOT NULL in pg_constraint (contype = 'n'); on earlier versions rely on pg_attribute.attnotnull above. Domain constraints and constraints on partition parents may also matter.
select
con.conname as constraint_name
, con.contype as kind
, con.convalidated as validated
, pg_catalog.pg_get_constraintdef(con.oid, true) as definition
, pg_catalog.obj_description(con.oid, 'pg_constraint') as comment
from pg_catalog.pg_class c
join pg_catalog.pg_namespace n on n.oid = c.relnamespace
join pg_catalog.pg_constraint con on con.conrelid = c.oid
where n.nspname = $1
and c.relname = $2
and c.relkind in ('r', 'p', 'f')
order by con.contype, con.conname
;contype: p primary key, u unique, f foreign key, c check, x exclusion, n NOT NULL (PG18). A unique index is not necessarily a unique constraint. A valid FK shows an enforced relationship, not necessarily the only relationship used by the application.
Foreign keys touching the table
Includes outgoing and incoming keys, with ordered column pairs (including composite keys). $1 and $2 still identify the chosen table. Use schema-qualified names in findings.
select
sn.nspname as from_schema
, src.relname as from_table
, con.conname as constraint_name
, pg_catalog.pg_get_constraintdef(con.oid, true) as definition
, tn.nspname as to_schema
, dst.relname as to_table
, con.convalidated as validated
from pg_catalog.pg_constraint con
join pg_catalog.pg_class src on src.oid = con.conrelid
join pg_catalog.pg_namespace sn on sn.oid = src.relnamespace
join pg_catalog.pg_class dst on dst.oid = con.confrelid
join pg_catalog.pg_namespace tn on tn.oid = dst.relnamespace
where con.contype = 'f'
and ((sn.nspname = $1 and src.relname = $2)
or (tn.nspname = $1 and dst.relname = $2))
order by sn.nspname, src.relname, con.conname
;Views directly depending on this table
Run this only if you need to know how the table is exposed or transformed. $1 and $2 identify the table. PostgreSQL records a view's relation dependencies on its _RETURN rewrite rule; distinct collapses multiple column-level dependencies to the same table. The result includes ordinary and materialized views across schemas, but only direct dependencies. To follow a view-on-view chain, inspect each result using views. Application queries, procedural bodies, and dynamic SQL are not covered; a partition's parent may be the object referenced by a view rather than that individual partition.
select distinct
vn.nspname as view_schema
, v.relname as view_name
, case v.relkind when 'm' then 'materialized view' else 'view' end as view_kind
from pg_catalog.pg_class c
join pg_catalog.pg_namespace n on n.oid = c.relnamespace
join pg_catalog.pg_depend d on d.refclassid = 'pg_catalog.pg_class'::pg_catalog.regclass
and d.refobjid = c.oid
and d.classid = 'pg_catalog.pg_rewrite'::pg_catalog.regclass
join pg_catalog.pg_rewrite r on r.oid = d.objid and r.rulename = '_RETURN'
join pg_catalog.pg_class v on v.oid = r.ev_class and v.relkind in ('v', 'm')
join pg_catalog.pg_namespace vn on vn.oid = v.relnamespace
where n.nspname = $1
and c.relname = $2
and c.relkind in ('r', 'p', 'f')
and v.oid <> c.oid
order by vn.nspname, v.relname
;Indexes
select
i.relname as index_name
, pg_catalog.pg_get_indexdef(i.oid) as definition
, ix.indisunique as unique_index
, ix.indisvalid as valid
, ix.indisready as ready
, pg_catalog.pg_relation_size(i.oid) as bytes
from pg_catalog.pg_class c
join pg_catalog.pg_namespace n on n.oid = c.relnamespace
join pg_catalog.pg_index ix on ix.indrelid = c.oid
join pg_catalog.pg_class i on i.oid = ix.indexrelid
where n.nspname = $1
and c.relname = $2
order by i.relname
;Partitioning and inheritance
If any of the four structural flags above is true, use partitioning and inheritance to traverse the relevant tree. Do not enumerate every partition just to understand an unrelated table.
Interpret and stop
Infer grain from keys, uniqueness, and columns; confirm it with the user when unclear. A matching *_id name does not prove a join. Indexes suggest access paths, not usage; row estimates can be stale. If you need typical values or distributions, follow data-derived values and obtain approval before querying statistics or rows. Never run an unbounded select * or a full count(*) just to orient yourself.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- tigerdata
- Publisher
- Timescale (TigerData) (Official)
- Distributed by
- Timescale (TigerData)
- Source
- timescale/pg-aiguide · skills/schema-exploration · commit c39008a
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- NOTICE (added by AutoGineer from NOTICE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by tigerdata or Timescale (TigerData).
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download schema-exploration.zip