Skip to content

bug: native engine's init_schema() never mirrors migration v20 (edges.dynamic_kind), but do_insert_edges always references it #2066

Description

@carlos-alm

Summary

src/db/migrations.ts migration v20 (added in #1629, commit 5907d58) adds edges.dynamic_kind:

ALTER TABLE edges ADD COLUMN dynamic_kind TEXT;
CREATE INDEX IF NOT EXISTS idx_edges_dynamic_kind ON edges(dynamic_kind) WHERE dynamic_kind IS NOT NULL;

crates/codegraph-core/src/db/connection.rs's MIGRATIONS array — the Rust mirror of migrations.ts, per the file's own doc comment ("IMPORTANT: Migration DDL is mirrored from src/db/migrations.ts. Any changes there MUST be reflected here (and vice-versa)") — only goes up to version: 19. The v20 migration was never mirrored; that commit touched only src/db/migrations.ts (confirmed via git show 5907d588 --stat).

Why this matters

crates/codegraph-core/src/db/repository/edges.rs's do_insert_edges — used for every single edge insert on the native path — unconditionally includes dynamic_kind in its INSERT column list:

let sql = format!(
    "INSERT OR IGNORE INTO edges (source_id, target_id, kind, confidence, dynamic, dynamic_kind) VALUES {}",
    placeholders.join(",")
);

NativeDatabase::init_schema() (connection.rs) is the actual native schema-migration runner (mirrors initSchema() from migrations.ts) — it runs its own MIGRATIONS array directly against the native rusqlite::Connection, independent of the TS migration runner. Since its MIGRATIONS array stops at v19, any database whose schema was initialized purely through the native path (schema_version <= 19, never previously touched by the TS initSchema()) will be missing the dynamic_kind column entirely — and every native edge insert will fail with no such column: dynamic_kind.

This is likely masked in most real-world usage because db/index.ts's openDb() calls the TS initSchema() (which does include v20) before native code ever touches most databases — but any code path that creates/migrates a fresh DB purely through the native NativeDatabase.init_schema() (e.g. a native-first proxy path) would hit this immediately.

Fix

Add the missing migration to crates/codegraph-core/src/db/connection.rs's MIGRATIONS array:

Migration {
    version: 20,
    up: r#"
      ALTER TABLE edges ADD COLUMN dynamic_kind TEXT;
      CREATE INDEX IF NOT EXISTS idx_edges_dynamic_kind ON edges(dynamic_kind) WHERE dynamic_kind IS NOT NULL;
    "#,
},

Also worth auditing whether any other TS migrations added after v19 were similarly missed, and whether ensure_legacy_columns-equivalent handling is needed for dynamic_kind (mirroring ensureEdgeColumns in migrations.ts, which does NOT currently handle dynamic_kind either — only confidence/dynamic).

Found while working on #1938; not fixed there to keep that PR scoped to a single concern.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions