PostgreSQL schema management toolkit with YAML-based definitions
Project description
pg-schema-toolkit
A self-contained PostgreSQL schema management toolkit with YAML-based definitions, automatic audit tables, and intelligent schema change tracking.
Philosophy: Schema-first design. Define your database structure in YAML, generate clean DDL, track changes, and maintain complete audit trails.
๐ Quick Start
# Install
pip install -e .
# Optional: Install with tab completion support
pip install -e ".[completion]"
activate-global-python-argcomplete --user
# Then restart your shell or source ~/.bashrc
# Validate a schema
pg-schema validate examples/schemas/users.yaml
# Generate DDL
pg-schema ddl-init examples/schemas/users.yaml -o create_users.sql
# Compare YAML with database
pg-schema diff examples/schemas/users.yaml
# Generate schema change SQL
pg-schema ddl-migrate examples/schemas/users.yaml \
-m "Add status column" \
-o schema_changes/002_add_status.sql
# Apply change to database
psql < schema_changes/002_add_status.sql
๐ฆ Core Features
- โ YAML Schema Definitions - Define tables declaratively
- โ Schema Inheritance - Reusable templates and field types
- โ
DDL Generation - Generate clean
CREATE TABLEstatements - โ Automatic Audit Tables - Track all changes with triggers
- โ Database Introspection - Read current database schema
- โ Schema Diffing - Compare YAML vs. database state
- โ
Change Generation - Generate
ALTER TABLEstatements - โ Safety Classification - SAFE/WARNING/DESTRUCTIVE labels
- โ CLI Interface - Complete command-line tooling
๐ Schema Change Workflow
Philosophy: Generate-First with Optional Execution
Core Principle: All schema changes are SQL files. Never execute DDL without a reviewed file.
Complete Workflow
1. Modify YAML Schema
# examples/schemas/users.yaml
tables:
- name: users
columns:
- name: status
type: TEXT
default: "'active'"
2. Generate Change File
pg-schema ddl-migrate examples/schemas/users.yaml \
-m "Add status column" \
-o schema_changes/005_add_status.sql
Note: A SQL file is always generated, even if no changes are detected. This ensures every YAML change has a corresponding SQL file for audit/review purposes.
3. Review Generated SQL
cat schema_changes/005_add_status.sql
4. Apply Change
# Manual (recommended for production)
psql < schema_changes/005_add_status.sql
Safety Classification
SAFE โ
- Add nullable column
- Add index
- Add column with default
WARNING โ
- Add NOT NULL column
- Change column type
- Type conversions
DESTRUCTIVE โ
- Drop column
- Drop table
- Data loss possible
๐๏ธ Example Schema
# examples/schemas/users.yaml
schema: public
extends: base_definitions.yaml
description: "User accounts with full audit history"
tables:
- name: users
extends: audited_table # Gets audit fields + audit table + trigger
description: "Application users"
columns:
- name: email
field_type: email
description: "User email address"
- name: username
field_type: slug
description: "Unique username"
- name: full_name
field_type: name
description: "User's full name"
- name: is_active
field_type: is_active
description: "Account active status"
indexes:
- columns: [email]
- columns: [username]
- columns: [is_active]
where: "deleted_at IS NULL"
Generates:
public.userstable with audit fieldspublic.users_audraudit tableaudit_users()trigger functionaudit_users_triggertrigger- All indexes and constraints
๐ง Configuration
Uses standard PostgreSQL environment variables:
export PGHOST=localhost
export PGPORT=5432
export PGDATABASE=mydb
export PGUSER=myuser
# Password from ~/.pgpass (secure)
Optional:
export DB_SCHEMA=public # Default schema
export DB_CONNECT_TIMEOUT=10 # Connection timeout (seconds)
export ENVIRONMENT=development # Environment name
๐ฏ Usage Patterns
1. As Command-Line Tool
# Validate schema
pg-schema validate examples/schemas/users.yaml
# Generate DDL
pg-schema ddl-init examples/schemas/users.yaml -o /tmp/create_users.sql
# Apply to database
psql -f /tmp/create_users.sql
2. As Python Library
from pg_schema_toolkit import SchemaLoader, DDLGenerator, load_config_from_env
import psycopg2
# Load schema
loader = SchemaLoader()
schema = loader.load_schema('examples/schemas/users.yaml')
# Generate DDL
generator = DDLGenerator(schema)
ddl = generator.generate_all()
# Connect to database
config = load_config_from_env()
conn = psycopg2.connect(**config.psycopg2_params)
๐ Project Structure
pg-schema-toolkit/
โโโ pg_schema_toolkit/ # Main package
โ โโโ __init__.py
โ โโโ cli.py # Command-line interface
โ โโโ scripts/ # Core functionality
โ โโโ schema_loader.py # Load and parse YAML
โ โโโ ddl_generator.py # Generate CREATE TABLE
โ โโโ audit_generator.py # Generate audit infrastructure
โ โโโ introspector.py # Read database schema
โ โโโ differ.py # Compare YAML vs database
โ โโโ change_generator.py # Generate ALTER TABLE
โ โโโ db_config.py # Database connection
โโโ examples/
โ โโโ schemas/ # Example schemas
โ โโโ base_definitions.yaml
โ โโโ users.yaml
โ โโโ products.yaml
โโโ pyproject.toml # Package configuration
โโโ setup.py # Setup script
โโโ requirements.txt # Dependencies
โโโ README.md # This file
๐ Audit Table System
Every table marked with generate_audit_table: true automatically gets:
{table_name}_audraudit table- Trigger function to capture INSERT/UPDATE/DELETE
- Complete change history with timestamps, users, and operation types
- Indexes on
audit_row_id,audit_timestamp,audit_operation,audit_user
Example
-- Main table
INSERT INTO users (email, username) VALUES ('user@example.com', 'john');
-- Audit table automatically populated
SELECT * FROM users_audr;
-- audit_id | audit_timestamp | audit_user | audit_operation | audit_row_id | email | username
-- 1 | 2026-01-17... | myuser | INSERT | 1 | user@... | john
-- Update tracked
UPDATE users SET username = 'john_doe' WHERE id = 1;
SELECT * FROM users_audr ORDER BY audit_id;
-- Shows both INSERT and UPDATE operations with full snapshots
๐ Best Practices
Schema Changes
-
Small, Incremental Changes
- Prefer many small changes over one large change
-
Always Use Transactions
- Wrap related changes in
BEGIN/COMMIT
- Wrap related changes in
-
Test in Staging First
- Never apply untested changes to production
-
Backwards Compatibility
- Add nullable column first
- Backfill data
- Then make NOT NULL
-
Version Control
git add schema_changes/005_add_field.sql git commit -m "Schema change: add status field"
- Always commit SQL files, even when no DDL changes (file documents review)
- Files with no DDL show that YAML changes required no DB migration
Development Workflow
- Edit YAML schema - Make changes declaratively
- Generate change - Tool creates SQL file (always, even if no changes)
- Review SQL - Always review before applying
- Test locally - Apply to dev database
- Commit SQL file - Track in git
- Apply to staging - Test in staging environment
- Apply to production - Manual execution recommended
๐ฆ Status
Production Ready โ
- Comprehensive feature set
- Clean, maintainable code
- Schema-first design philosophy
- Safe for production use
๐ CLI Reference
# Validate schema
pg-schema validate <schema_file>
# Generate initial DDL
pg-schema ddl-init <schema_file> [-o output.sql]
# Show database info
pg-schema info
# Compare with database
pg-schema diff <schema_file>
# Generate migration DDL
pg-schema ddl-migrate <schema_file> -m "message" [-o output.sql]
๐ Why Schema-First?
Data Integrity = Business Rules
- Constraints enforced at DB level, not app level
- Single source of truth
- Multi-client safety
- Audit from day one
For ERP Systems:
- Financial/regulatory data needs complete history
- Can't retrofit audit tables later
- Database enforces rules even with multiple apps
- Future integrations are safe
๐ License
MIT License
Questions? Check the examples! The examples/schemas/ directory contains working examples of every feature.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pg_schema_toolkit-0.1.1.tar.gz.
File metadata
- Download URL: pg_schema_toolkit-0.1.1.tar.gz
- Upload date:
- Size: 31.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e3af6795a601a0017d2e5b06c387e6348f01b10ec5206738e176118e52841f9a
|
|
| MD5 |
a98f06fe8145c04631a5fb205e78f791
|
|
| BLAKE2b-256 |
57b4460b8511616e335b24c6202effe61b9bb9e2141487e36937a02cfab1ecb1
|
File details
Details for the file pg_schema_toolkit-0.1.1-py3-none-any.whl.
File metadata
- Download URL: pg_schema_toolkit-0.1.1-py3-none-any.whl
- Upload date:
- Size: 30.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
351784e66bd7caa9fcee4a53aa5774ce08b24d71230ae6b3697fcc72075681ed
|
|
| MD5 |
89bca1d732191b3ebded04cc064d7d1e
|
|
| BLAKE2b-256 |
765ed445f5e752ba33e81c53e38210c72d129687d9ab1e46e35f8e8bf3c93574
|