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://mp-staging.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/data-values.md
Data-derived values (opt in)
Use this reference only when types, constraints, defaults, enum labels, comments, and view definitions cannot answer the user's question. Ask for approval before reading either statistics or table rows. Name the schema, table, columns, purpose, and whether you propose catalog statistics or row sampling. Approval for that scope can cover a small sequence of bounded queries; do not silently expand to other columns or tables. If approval is declined, explain what cannot be determined from schema alone.
Constraints and enum labels describe permitted values. Statistics and row samples describe values observed at some point; neither establishes the complete set of valid values. Both can disclose sensitive data. Use a role authorized for the investigation, honor RLS and privilege boundaries, and do not log or export raw values unnecessarily.
Queries target PostgreSQL 18; the pg_stats columns and TABLESAMPLE SYSTEM syntax below are also available in PostgreSQL 14–17. $1 = schema name, $2 = table name, $3 = a text[] of approved column names (for example, ARRAY['status']::text[]).
1. Read existing column statistics
After approval, start with pg_catalog.pg_stats, the supported view over planner statistics; do not query raw pg_statistic. Restrict it to the approved columns. This query reads stored statistics rather than scanning the table, but the most-common values and histogram bounds may contain real data values.
select
s.attname as column_name
, s.inherited
, s.null_frac
, s.n_distinct
, s.most_common_vals::text as most_common_vals
, s.most_common_freqs
, s.histogram_bounds::text as histogram_bounds
from pg_catalog.pg_stats s
where s.schemaname = $1
and s.tablename = $2
and s.attname = any($3::text[])
order by s.attname, s.inherited
;inherited = true describes statistics including inheritance children when available; the two rows may differ. null_frac is estimated. Positive n_distinct estimates the count of distinct values; negative values estimate the distinct fraction relative to row count (-1 means roughly all values differ). Most-common values and histogram bounds are samples used by the planner, not an exhaustive vocabulary or exact range. Statistics can be stale, missing (no ANALYZE yet), suppressed by privileges, or unrepresentative of the rows visible under RLS. Do not run ANALYZE yourself to fill gaps.
2. Optionally sample rows
Only if approved statistics are insufficient, ask for row-sampling approval if it was not already granted. Check the table's estimated size in tables first and keep a statement timeout; a sampling percentage and LIMIT are not a fixed work budget. SYSTEM samples physical pages, so it can miss rare values, favor clustered values, or return no rows on small tables. BERNOULLI samples rows but typically reads the whole relation. Do not retry with a larger percentage or run a full-table distribution query without further approval.
SYSTEM (0.01) means 0.01% of pages (one-hundredth of one percent), not 1%. With roughly uniform rows per page, an estimate of rows in the sample before LIMIT is pg_class.reltuples × 0.0001 (or reltuples / 10,000). For the table being considered, $1 = schema name and $2 = table name:
select
c.reltuples::bigint as estimated_table_rows
, case when c.reltuples >= 0 then round(c.reltuples::numeric / 10000)::bigint end as estimated_sample_rows_before_limit
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 = 'r'
;This is an expectation, not a minimum or maximum: reltuples may be stale or -1 (unknown), physical page densities vary, and random sampling can return zero rows. LIMIT 10 caps returned rows, not pages examined or the work required.
Identifiers cannot be bound as $1 in FROM or in a column list. The following parameterized generator verifies the approved column names and produces a complete SQL statement with safely quoted identifiers. It only targets ordinary tables or individual partition children (relkind = 'r'); it does not sample foreign tables, views, or partitioned parents. At most five named columns are allowed. Run the generated statement separately, after reviewing its table and column list. No output means the table or one of the requested columns was not found (or the column list has duplicates); do not fall back to raw interpolation.
select
pg_catalog.format(
'select %s from %I.%I tablesample system (0.01) limit 10;'
, pg_catalog.string_agg(pg_catalog.format('%I', a.attname), ', ' order by wanted.ord)
, n.nspname
, c.relname
) as sample_sql
from pg_catalog.pg_class c
join pg_catalog.pg_namespace n on n.oid = c.relnamespace
cross join lateral unnest($3::text[]) with ordinality wanted(column_name, ord)
join pg_catalog.pg_attribute a on a.attrelid = c.oid
and a.attname = wanted.column_name
and a.attnum > 0
and not a.attisdropped
where n.nspname = $1
and c.relname = $2
and c.relkind = 'r'
and pg_catalog.cardinality($3::text[]) between 1 and 5
group by c.oid, n.nspname, c.relname
having count(*) = pg_catalog.cardinality($3::text[])
and count(distinct a.attnum) = pg_catalog.cardinality($3::text[])
;The generated query selects only the approved columns, samples about 0.01% of pages (one-hundredth of one percent), and returns at most 10 rows. It may still read more than 10 rows' worth of pages, and the sample may be empty. Sampling actual rows can reveal identifiers or personal information even if the columns sound harmless. If only aggregate distributions are needed, agree on an appropriate cost and privacy budget before running any GROUP BY or count(*); those can scan the entire table.
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