# RelSpec Scripts Command - Quick Examples ## Basic Workflow ### 1. Create migration directory structure ```bash mkdir -p migrations ``` ### 2. Create migration scripts Both underscore and hyphen formats are supported. Examples below use underscore format, but you can also use: `1-001-create-users-table.sql` ```bash # Priority 1: Core schema cat > migrations/1_001_create_users_table.sql << 'EOF' CREATE TABLE users ( id SERIAL PRIMARY KEY, username VARCHAR(100) NOT NULL UNIQUE, email VARCHAR(255) NOT NULL UNIQUE, password_hash VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_users_username ON users(username); CREATE INDEX idx_users_email ON users(email); EOF cat > migrations/1_002_create_posts_table.sql << 'EOF' CREATE TABLE posts ( id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, title VARCHAR(200) NOT NULL, content TEXT, published BOOLEAN DEFAULT FALSE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); EOF # Priority 2: Additional indexes cat > migrations/2_001_add_post_indexes.sql << 'EOF' CREATE INDEX idx_posts_user_id ON posts(user_id); CREATE INDEX idx_posts_published ON posts(published); CREATE INDEX idx_posts_created_at ON posts(created_at); EOF # Priority 3: Seed data cat > migrations/3_001_seed_admin_user.sql << 'EOF' INSERT INTO users (username, email, password_hash) VALUES ('admin', 'admin@example.com', 'hashed_password_here') ON CONFLICT (username) DO NOTHING; EOF ``` ### 3. List scripts to verify order ```bash relspec scripts list --dir migrations ``` Output: ``` === SQL Scripts List === Directory: migrations Found 4 script(s) in execution order: No. Priority Sequence Name Lines ---- -------- -------- ------------------------------ ----- 1 1 1 create_users_table 13 2 1 2 create_posts_table 11 3 2 1 add_post_indexes 4 4 3 1 seed_admin_user 4 ``` ### 4. Execute against database ```bash relspec scripts execute \ --dir migrations \ --conn "postgres://myuser:mypass@localhost:5432/myapp" ``` ## Real-World Examples ### Example 1: E-commerce Database Setup ```bash # Directory structure migrations/ ├── 1_001_create_users.sql ├── 1_002_create_products.sql ├── 1_003_create_orders.sql ├── 1_004_create_order_items.sql ├── 2_001_add_indexes.sql ├── 2_002_add_constraints.sql ├── 3_001_seed_categories.sql └── 3_002_seed_sample_products.sql # Execute relspec scripts execute \ --dir migrations \ --conn "postgres://ecommerce_user:pass@db.example.com:5432/ecommerce_prod?sslmode=require" ``` ### Example 2: Multi-Schema Database ```bash # Organize by schema using subdirectories migrations/ ├── public/ │ ├── 1_001_create_users.sql │ └── 1_002_create_sessions.sql ├── analytics/ │ ├── 1_001_create_events.sql │ └── 2_001_create_views.sql └── reporting/ └── 1_001_create_reports.sql # Execute (all schemas processed together) relspec scripts execute \ --dir migrations \ --conn "postgres://localhost/multi_schema_db" \ --schema public ``` ### Example 3: Development Environment Setup ```bash # Create local development database createdb myapp_dev # Run migrations relspec scripts execute \ --dir ./db/migrations \ --conn "postgres://localhost/myapp_dev?sslmode=disable" # Verify psql myapp_dev -c "\dt" ``` ### Example 4: CI/CD Pipeline ```yaml # .github/workflows/deploy.yml - name: Run database migrations run: | relspec scripts list --dir migrations relspec scripts execute \ --dir migrations \ --conn "${{ secrets.DATABASE_URL }}" ``` ### Example 5: Docker Compose Integration ```yaml # docker-compose.yml services: postgres: image: postgres:16 environment: POSTGRES_DB: myapp POSTGRES_USER: myuser POSTGRES_PASSWORD: mypass ports: - "5432:5432" migrate: image: relspec:latest depends_on: - postgres volumes: - ./migrations:/migrations command: > scripts execute --dir /migrations --conn "postgres://myuser:mypass@postgres:5432/myapp" ``` ```bash # Run migrations with docker-compose docker-compose up -d postgres sleep 5 # Wait for postgres to be ready docker-compose run --rm migrate ``` ### Example 6: Incremental Feature Rollout ```bash # Feature branch structure migrations/ ├── 1_100_user_profiles_schema.sql # Feature: User profiles ├── 1_101_user_profiles_constraints.sql ├── 1_102_user_profiles_indexes.sql ├── 2_100_notifications_schema.sql # Feature: Notifications ├── 2_101_notifications_constraints.sql └── 2_102_notifications_indexes.sql # Deploy just user profiles (Priority 1) # Then later deploy notifications (Priority 2) ``` ### Example 7: Rollback Strategy (Manual) ```bash # Forward migration cat > migrations/1_001_add_column.sql << 'EOF' ALTER TABLE users ADD COLUMN phone VARCHAR(20); EOF # Create manual rollback script (not auto-executed) cat > rollbacks/1_001_remove_column.sql << 'EOF' ALTER TABLE users DROP COLUMN phone; EOF # If needed, manually execute rollback psql myapp -f rollbacks/1_001_remove_column.sql ``` ### Example 8: Complex Schema Changes ```bash # migrations/1_001_alter_users_table.sql BEGIN; -- Add new column ALTER TABLE users ADD COLUMN full_name VARCHAR(200); -- Populate from existing data UPDATE users SET full_name = username WHERE full_name IS NULL; -- Make it required ALTER TABLE users ALTER COLUMN full_name SET NOT NULL; -- Add index CREATE INDEX idx_users_full_name ON users(full_name); COMMIT; ``` Execute: ```bash relspec scripts execute \ --dir migrations \ --conn "postgres://localhost/myapp" ``` ## File Naming Format Examples ### Underscore Format (Traditional) ``` migrations/ ├── 1_001_create_users.sql ├── 1_002_create_posts.sql ├── 2_001_add_indexes.sql └── 3_001_seed_data.sql ``` ### Hyphen Format (Alternative) ``` migrations/ ├── 1-001-create-users.sql ├── 1-002-create-posts.sql ├── 10-10-create-newid.pgsql └── 2-001-add-indexes.sql ``` ### Mixed Format (Both in Same Directory) ``` migrations/ ├── 1_001_create_users.sql # Underscore format ├── 1-002-create-posts.sql # Hyphen format ├── 2_001_add_indexes.sql # Underscore format └── 10-10-special-migration.pgsql # Hyphen format ``` **Note:** All three approaches work identically - use whichever naming style you prefer! ## Common Patterns ### Pattern 1: Schema → Indexes → Constraints → Data ``` 1_xxx_*.sql # Tables and basic structure 2_xxx_*.sql # Indexes for performance 3_xxx_*.sql # Foreign keys and constraints 4_xxx_*.sql # Seed/reference data ``` ### Pattern 2: Feature-Based Organization ``` 1_001_feature_auth_users.sql 1_002_feature_auth_sessions.sql 1_003_feature_auth_permissions.sql 2_001_feature_blog_posts.sql 2_002_feature_blog_comments.sql 3_001_feature_payments_transactions.sql ``` ### Pattern 3: Date-Based Versioning ``` 1_20250130_create_users.sql 2_20250131_add_user_indexes.sql 3_20250201_create_posts.sql ``` ### Pattern 4: Environment-Specific Scripts ```bash # Base migrations (all environments) migrations/base/ ├── 1_001_create_users.sql ├── 1_002_create_products.sql # Development-specific migrations/dev/ └── 9_001_seed_test_data.sql # Production-specific migrations/prod/ └── 9_001_seed_production_config.sql # Execute different paths based on environment ENV=dev relspec scripts execute \ --dir migrations/base \ --conn "postgres://localhost/myapp_${ENV}" relspec scripts execute \ --dir migrations/${ENV} \ --conn "postgres://localhost/myapp_${ENV}" ``` ## Troubleshooting ### Check script order before execution ```bash relspec scripts list --dir migrations ``` ### Test against local database first ```bash # Create test database createdb myapp_test # Test migrations relspec scripts execute \ --dir migrations \ --conn "postgres://localhost/myapp_test" # Inspect results psql myapp_test # Cleanup dropdb myapp_test ``` ### Validate SQL syntax ```bash # Use PostgreSQL to check syntax without executing for f in migrations/*.sql; do echo "Checking $f..." psql myapp -c "BEGIN; \i $f; ROLLBACK;" --single-transaction done ``` ### Debug connection issues ```bash # Test connection string psql "postgres://user:pass@localhost:5432/myapp" # If that works, use the same string for relspec relspec scripts execute \ --dir migrations \ --conn "postgres://user:pass@localhost:5432/myapp" ``` ## Tips 1. **Always review execution order** with `list` before running `execute` 2. **Test in development** before running against production 3. **Use zero-padded sequences** (001, 002, not 1, 2) for consistent sorting 4. **Keep scripts idempotent** when possible (use IF NOT EXISTS, ON CONFLICT, etc.) 5. **Back up production** before running migrations 6. **Use transactions** for complex multi-statement migrations 7. **Document breaking changes** with SQL comments in the migration files 8. **Version control everything** - commit migrations with code changes