Skip to content

feat: Automatic column/table rename detection without explicit annotations #35

@Lazialize

Description

@Lazialize

Problem

Currently, correctly detecting column or table renames requires explicitly writing a renamed_from annotation in the schema YAML. Without the annotation, a rename is detected as "old column dropped + new column added", generating a destructive migration that causes data loss.

Proposed Solution

Automatically detect rename candidates using heuristics during schema diff detection, and prompt the user for confirmation.

Rename Detection Heuristics

  1. Type match: Removed column and added column have identical types
  2. 1:1 pairing within a table: Exactly one removal + one addition in the same table
  3. Name similarity: Levenshtein distance or suffix/prefix matching
  4. Constraint match: Columns sharing the same constraints (FK, UNIQUE, etc.)

Workflow

$ strata generate

🔍 Potential renames detected:
  1. users.email → users.email_address  (type: VARCHAR(255), confidence: high)
  2. posts.title → posts.headline       (type: VARCHAR(100), confidence: medium)

Treat as renames? [Y/n/select]: 
  → Selecting 'y' generates ALTER TABLE ... RENAME COLUMN
  → Selecting 'n' generates DROP + ADD (destructive)
  → Selecting 'select' allows per-item choice

Implementation Plan

  1. Rename detector (src/db/src/services/schema_diff_detector/rename_detector.rs — new)

    pub struct RenameCandidate {
        pub table: String,
        pub old_name: String,
        pub new_name: String,
        pub column_type: ColumnType,
        pub confidence: RenameConfidence,  // High, Medium, Low
    }
    
    pub struct RenameDetector;
    
    impl RenameDetector {
        /// Extract rename candidates from removed and added columns
        pub fn detect_column_renames(
            removed: &[Column],
            added: &[Column],
        ) -> Vec<RenameCandidate>;
        
        /// Extract table rename candidates
        pub fn detect_table_renames(
            removed: &[String],
            added: &[String],
            schemas: &[Schema],
        ) -> Vec<TableRenameCandidate>;
    }
  2. Extend SchemaDiffDetectorService (src/db/src/services/schema_diff_detector/mod.rs)

    • Include rename candidates in detect_diff() results
    • Auto-generate renamed_from annotations after user confirmation
  3. Changes to generate command (src/cli/src/cli/commands/generate.rs)

    • Display interactive prompt when rename candidates are detected
    • Auto-append renamed_from to schema YAML based on user selection
  4. MigrationPipeline integration (src/db/src/services/migration_pipeline/mod.rs)

    • Generate ALTER TABLE ... RENAME COLUMN SQL for rename operations

Files Affected

  • src/db/src/services/schema_diff_detector/rename_detector.rs (new)
  • src/db/src/services/schema_diff_detector/column_comparator.rs — Integrate rename detection
  • src/cli/src/cli/commands/generate.rs — Interactive flow
  • src/db/src/services/migration_pipeline/table_stages.rs — RENAME SQL generation

Alternatives Considered

  • Always require renamed_from: The current approach. Safe but poor DX
  • AI-based detection: High accuracy but adds dependencies. Heuristics suffice for most cases
  • strata rename subcommand: Managing renames via a dedicated command. Integration within the generate flow is more natural

Additional Context

  • Corresponds to "Detect rename candidates for columns and tables" in ROADMAP.md
  • The existing rename_validator.rs validates renamed_from annotations, enabling integration with auto-detection
  • Interactive prompts can share the common infrastructure from feat: Interactive confirmation prompts for destructive operations #33 (Interactive confirmation prompts)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions