Type Introspection
Purpose: How codegen discovers PostgreSQL types and functions
Last Updated: 2024-11-28
Overview
The introspection layer queries PostgreSQL system catalogs (pg_catalog) to discover types, functions, and their relationships. This information drives code generation.
Architecture
pg_catalog (PostgreSQL system tables)
↓ queries
IntrospectionBootstrap
↓ creates
TypeCatalog + FunctionCatalog
↓ provides
Type and Function metadata
↓ used by
Schema Generation + Function Generation
Key Classes
IntrospectionBootstrap
Purpose: Entry point for introspection process
Key Methods:
connect()- Establish database connectionloadSchema(name)- Load schema informationgetTypeCatalog()- Get type cataloggetFunctionCatalog()- Get function catalog
TypeCatalog
Purpose: Manage PostgreSQL types and dependencies
Key Methods:
loadSchema(name)- Load types from schemagetType(oid)- Get type by OIDgetTypeByName(schema, name)- Get type by qualified namegetDependencies(type)- Get type dependenciestopologicalSort()- Sort types by dependenciesgetStats()- Get catalog statistics
FunctionCatalog
Purpose: Manage PostgreSQL functions
Key Methods:
loadSchema(name)- Load functions from schemagetFunctions()- Get all functionsgetFunction(name)- Get function by namegetFunctionsByReturnType(oid)- Find functions by return type
Type Discovery
Base Types
Query pg_type for built-in types (int4, int8, text, bool, etc.)
Enum Types
Query for enum types and their values using pg_enum join
Composite Types
Query for composite types and attributes using pg_attribute join
Domain Types
Query for domain types with constraints using pg_constraint join
Array Types
Query for array types and their element types
Function Discovery
Function Metadata
Query pg_proc for:
- Function name and schema
- Parameter count and types
- Parameter names and modes
- Return type
- Documentation comments
Parameter Information
Extract parameter details including:
- Parameter names
- Parameter types (OIDs)
- Parameter modes (IN, OUT, INOUT)
Return Type Information
Determine return type semantics:
- Single value vs SETOF
- Base type vs composite
- Table-returning functions
Dependency Resolution
Type Dependencies
Build dependency graph:
- Composites depend on field types
- Arrays depend on element types
- Domains depend on base types
- Ranges depend on subtypes
Topological Sort
Order types for generation so dependencies are generated first
Circular Dependencies
Handle circular references using forward declarations and z.lazy()
Type Categories
Enumeration
enum TypeCategory {
BASE = 'b', // Base type
COMPOSITE = 'c', // Composite (record)
DOMAIN = 'd', // Domain (constrained type)
ENUM = 'e', // Enum
PSEUDO = 'p', // Pseudo-type
RANGE = 'r' // Range type
}
Type Metadata
interface Type {
oid: number;
name: string;
schema: string;
category: TypeCategory;
length: number;
byValue: boolean;
// Category-specific fields
fields?: CompositeField[]; // for composite
values?: string[]; // for enum
baseTypeOid?: number; // for domain
elementOid?: number; // for array
constraint?: string; // for domain
}
Performance Optimization
Batch Queries
Load multiple types in one query using ANY($1::oid[])
Caching
Cache introspection results to avoid redundant queries
Filtering
Only load types from specified schemas
Examples
For detailed code examples, see:
- Introspection Examples - Complete code examples
- Bootstrap usage
- SQL queries
- Dependency resolution
- Performance optimization
- Error handling
Related Documentation
- Overview - System architecture
- Schema Generation - Using type catalog
- Type System - Type mappings
- Troubleshooting - Debugging introspection
Key Takeaway: Introspection discovers the database schema structure, enabling type-safe code generation.