postgres/postgres
Catalog
Everything PostgreSQL knows about the database — tables, columns, types, functions, indexes, roles, statistics — lives in system catalog tables. The catalog is bootstrapped at initdb time and is itself queried using the same access methods that user tables use. Source: src/backend/catalog/, src/include/catalog/.
Directory layout
src/backend/catalog/
├── Catalog.pm # Perl module: parses pg_*.dat files
├── genbki.pl # generates postgres.bki + per-table headers
├── postgres.bki.in # input template for the bootstrap data
├── system_views.sql # SQL run after bootstrap to create the views
├── information_schema.sql
├── sql_features.txt # tracking of which SQL standards features are supported
├── pg_aggregate.c, pg_collation.c, pg_proc.c, ...
├── catalog.c, dependency.c, indexing.c, namespace.c, objectaccess.c
└── partition.c, storage.c, ...
src/include/catalog/
├── pg_aggregate.h, pg_attribute.h, pg_class.h, pg_proc.h, ... # row formats
├── pg_*.dat # initial contents
├── catalog.h, indexing.h, namespace.h, dependency.h
├── pg_attribute.dat, pg_proc.dat, pg_type.dat, ... # data
└── unused_oids # script for assigning new OIDsAnatomy of a system catalog
Each catalog is just a regular table with a fixed name (pg_class, pg_attribute, pg_proc, ...) and a fixed OID. Its row format is described in a pg_*.h header that contains a Form_pg_* C struct, plus annotations that genbki.pl reads to produce the bootstrap .bki file:
/* src/include/catalog/pg_class.h */
CATALOG(pg_class,1259,RelationRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83,RelationRelation_Rowtype_Id) BKI_SCHEMA_MACRO
{
Oid oid;
NameData relname;
Oid relnamespace;
Oid reltype;
/* ... */
};
typedef FormData_pg_class *Form_pg_class;The CATALOG(name, oid, ...) macro is interpreted both by the C compiler (becoming a regular struct) and by genbki.pl (becoming a catalog-table definition). The pg_class.dat file alongside the header contains the bootstrap rows.
genbki.pl
src/backend/catalog/genbki.pl is the hub. It reads pg_*.h and pg_*.dat, validates them, assigns OIDs to entries that don't pin one, and emits:
postgres.bki— the bootstrap data file.schemapg.h— C definitions of the catalog schemas, used by the relcache.pg_*_d.h— derived headers with macros for column attributes.
The .bki file is a tiny declarative script that initdb feeds to a stripped-down "bootstrap" backend, which physically lays out the on-disk representation of each catalog and inserts its rows. After bootstrap, initdb runs system_views.sql and information_schema.sql to create the SQL-level views and informational schema.
Catalogs you'll meet
| Table | Purpose |
|---|---|
pg_class |
All "relations": tables, views, indexes, sequences, etc. One row each. |
pg_attribute |
Columns. One row per (relation, attno). |
pg_type |
Data types: built-in, user-defined, composite, domain, enum. |
pg_proc |
Functions and procedures. |
pg_operator |
Operators, with their function references. |
pg_namespace |
Schemas. |
pg_database |
Databases (cluster-wide; shared across DBs). |
pg_authid / pg_auth_members |
Roles and group membership (cluster-wide). |
pg_index |
Index metadata. |
pg_constraint |
Check, unique, foreign-key, primary-key, exclusion constraints. |
pg_depend, pg_shdepend |
Dependency graph between catalog objects. |
pg_amproc, pg_amop |
Index AM support functions and operator strategies. |
pg_extension |
Installed extensions. |
pg_statistic |
Per-column statistics (planner input). |
pg_stat_* |
Cumulative statistics (live in shared memory, exposed as views). |
pg_subscription, pg_publication, pg_publication_rel |
Logical replication. |
pg_replication_slots |
Replication slot state. |
There are dozens more; \dS pg_* in psql shows the full list.
OID assignment
Every catalog row has a 32-bit OID. OIDs below FirstUnpinnedObjectId (currently 12000) are pinned — they are assigned by hand in pg_*.dat and baked into the source. The src/include/catalog/unused_oids script lists currently-free OIDs for new pinned objects; running src/include/catalog/duplicate_oids checks for accidental collisions.
OIDs ≥ 12000 are auto-assigned at bootstrap. After bootstrap, new objects get OIDs from a per-cluster counter (varsup.c::GetNewObjectId).
Sys cache and rel cache
Direct heap scans of catalog tables would be slow, so the backend has two caches in front of them:
Sys cache
Source: src/backend/utils/cache/syscache.c. A set of per-catalog hash tables keyed by common lookup keys (PROCOID, RELNAMENSP, TYPEOID, etc.). Entries are loaded lazily on first lookup. The list of registered caches is in cacheinfo[] in syscache.c.
Usage:
HeapTuple tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
if (HeapTupleIsValid(tup))
{
Form_pg_class pgcform = (Form_pg_class) GETSTRUCT(tup);
/* use pgcform->relname etc. */
ReleaseSysCache(tup);
}Sys cache reference counts are owned by the resource manager; abort cleans them up.
Rel cache
src/backend/utils/cache/relcache.c. A cache of RelationData structs — fully assembled descriptors of each relation, including the TupleDesc, index info, partition descriptor, etc. Building a Relation is expensive; the rel cache amortizes it. Eviction happens when the relation is dropped or schema-altered, signaled via cache invalidation.
Cache invalidation
When a backend modifies a catalog row (e.g., ALTER TABLE adds a column), it queues invalidation messages describing the affected entries. At commit, those messages are broadcast to all other backends through shared memory, which evict the relevant sys-cache and rel-cache entries. Source: src/backend/utils/cache/inval.c.
Without this, a peer backend could keep using an out-of-date relcache entry and miss the new column.
Dependency tracking
pg_depend and pg_shdepend record dependencies between catalog objects. When you DROP TABLE, the engine walks the dependency graph and prevents the drop (or cascades) based on the edge types. Source: src/backend/catalog/dependency.c. Everything that creates a catalog object is expected to record its dependencies via recordDependencyOn*.
This is also how pg_dump figures out which order to emit CREATE statements in.
Namespace and search_path
pg_namespace is the schema catalog. The search_path setting tells the backend which schemas to look in, in order, for an unqualified name. Source: src/backend/catalog/namespace.c. Functions like RangeVarGetRelid resolve a RangeVar (potentially schema-qualified) to an OID.
Special schemas: pg_catalog (always implicit at the front of search*path; holds the system catalogs), pg_temp*\*(per-session temporary),information_schema (SQL-standard read-only views).
Object addresses
Many DDL operations work in terms of an ObjectAddress — the (catalog OID, object OID, sub-id) triple identifying any catalog object. Source: src/backend/catalog/objectaddress.c. The dispatcher translates between SQL syntax (schema.table.column) and ObjectAddress.
DDL execution path
A typical DDL command like CREATE TABLE:
- Parser: produces
CreateStmt(gram.y→parsenodes.h). - Parse analysis:
transformCreateStmtinsrc/backend/parser/parse_utilcmd.c. - Utility command:
ProcessUtility(insrc/backend/tcop/utility.c) dispatches toExecCreateStmtinsrc/backend/commands/tablecmds.c. - The command code uses catalog helpers —
heap_create_with_catalog,index_create,recordDependencyOn, etc. — to insert the necessary catalog rows. - WAL records describe the catalog inserts (just like any other heap modification) so recovery can reproduce them.
- Cache invalidation messages are queued.
- Commit flushes WAL, broadcasts invalidations.
For other DDLs (ALTER, DROP, CREATE INDEX, etc.) the code is in src/backend/commands/ — one file per command family.
Bootstrap process
The first phase of initdb runs the backend in --boot mode. It reads postgres.bki and:
- Lays down
pg_class,pg_attribute,pg_type,pg_procfiles manually (no catalog yet to consult). - Inserts the bootstrap rows.
- Builds the indexes on those tables.
Once that's done, the backend is "live" enough to read SQL scripts. initdb then runs system_views.sql and information_schema.sql over a normal connection to create the rest.
src/backend/bootstrap/ contains the bootstrap-mode entry points. They are minimal — most of the work is just running INSERT statements with reduced safety nets.
Entry points for modification
- Add a column to a catalog: edit the
pg_*.hto extendFormData, update thepg_*.datif it pins rows, regenerate (just rebuild). Update any code that reads the catalog to handle the new column. BumpingCATALOG_VERSION_NOincatversion.hforces existing clusters to fail to start, signaling that a newinitdbis needed. - Add a new catalog table: a sizable patch. New
.h/.dat, new C file, register ingenbki.pl's expected list, add cache-info entries, etc. - Add a system view: append to
system_views.sql.
For the access-method layer underneath, see Access methods. For how DDL is parsed and dispatched, see Parser.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.