database-changes

majiayu000's avatarfrom majiayu000

Make database schema changes in IdeaForge. Triggers: create migration, add table/column, modify column type, add index, use JSONB, use pgvector. File-based migrations with raw SQL, no ORM.

⭐5stars🔀1forks📁View on GitHub🕐Updated Jan 11, 2026

When & Why to Use This Skill

This Claude skill automates the end-to-end workflow for database schema migrations within the IdeaForge environment. It streamlines the process of generating idempotent SQL migration scripts, executing database updates, and synchronizing backend Rust API code with frontend TypeScript types to ensure full-stack data consistency and type safety.

Use Cases

  • Case 1: Adding new columns or tables to the CMS database using raw SQL migrations without the need for an ORM.
  • Case 2: Synchronizing backend Rust server code and JSON responses automatically after a database schema change to prevent API mismatches.
  • Case 3: Updating frontend TypeScript interfaces and type definitions to reflect new database fields, ensuring end-to-end development consistency.
  • Case 4: Implementing idempotent database patterns like Upserts and conditional updates to ensure safe deployment replays and system stability.
namedatabase-changes
descriptionMaking database schema changes to the CMS database. Use when adding columns, tables, running migrations, or updating the backend API and TypeScript types for new database fields.

Database Schema Changes

Overview

End-to-end process for adding new columns or tables to the CMS database.

Adding a New Column

1. Create Migration

-- migrations/cms/0004_add_my_column.sql
SET search_path TO toygres_cms, public;

DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.columns
        WHERE table_schema = 'toygres_cms'
          AND table_name = 'instances'
          AND column_name = 'my_column'
    ) THEN
        ALTER TABLE instances ADD COLUMN my_column VARCHAR(255);
    END IF;
END;
$$;

2. Run Migration

./scripts/db-migrate.sh

3. Update Backend API

In toygres-server/src/api.rs, add to SELECT query:

let row = sqlx::query(
    "SELECT ..., my_column FROM toygres_cms.instances WHERE ..."
)

Add to JSON response:

Ok(Json(serde_json::json!({
    // existing fields...
    "my_column": row.get::<Option<String>, _>("my_column")
})))

4. Update TypeScript Types

In toygres-ui/src/lib/types.ts:

export interface InstanceDetail extends Instance {
  // existing fields...
  my_column: string | null;
}

5. Update Activities (if needed)

If an activity should set this column:

sqlx::query("UPDATE toygres_cms.instances SET my_column = $2 WHERE k8s_name = $1")
    .bind(&input.k8s_name)
    .bind(&input.my_column)
    .execute(&pool)
    .await?;

Idempotency Patterns

All CMS activities must be idempotent for Duroxide replay safety:

-- Upsert pattern
INSERT INTO table (id, value) VALUES ($1, $2)
ON CONFLICT (id) DO UPDATE SET value = $2;

-- Conditional update
UPDATE table SET state = 'new_state'
WHERE id = $1 AND state = 'expected_state';