Skip to content

[Phase 2] CRUD composite primary keys (trait default methods) #145

@debba

Description

@debba

[Phase 2] CRUD composite primary keys (trait default methods)

Part of the SQL Server Phase 2 epic #150.

The driver isn't on main. Code lives on feat/sql-server and isn't in any release. Check that branch out, branch off it, target your PR at it — not at main. The whole thing squashes into main when Phase 2 closes (#149).

Phase 1 CRUD commands in src-tauri/src/commands.rs (update_record, delete_record around lines 1788–1855) assume a single PK column. SQL Server tables routinely have composite PKs — the driver needs a way to target rows by (col1, col2, ...) without breaking MySQL / Postgres / SQLite.

Task

1. Trait evolution (backward-compatible). In src-tauri/src/drivers/driver_trait.rs, add two default methods to DatabaseDriver:

async fn delete_record_composite(
    &self,
    params: &ConnectionParams,
    table: &str,
    pk_cols: &[String],
    pk_vals: Vec<serde_json::Value>,
    schema: Option<&str>,
) -> Result<u64, String> {
    if pk_cols.len() == 1 {
        let v = pk_vals.into_iter().next().unwrap_or(serde_json::Value::Null);
        return self.delete_record(params, table, &pk_cols[0], v, schema).await;
    }
    Err("Composite primary keys not supported by this driver".into())
}

// Same pattern for update_record_composite (adds col_name / new_val / max_blob_size).

The default forwards to the legacy single-key method when pk_cols.len() == 1, which keeps MySQL / Postgres / SQLite drivers working without any change.

2. SQL Server override. In src-tauri/src/drivers/sqlserver/mod.rs, override both methods to build WHERE [c1]=@P1 AND [c2]=@P2 AND ... using tiberius parameter binding (ordinal markers).

3. Tauri command extension. In src-tauri/src/commands.rs, extend update_record / delete_record with optional parallel parameters:

pk_cols: Option<Vec<String>>,
pk_vals: Option<Vec<serde_json::Value>>,

If present → call the *_composite method. Otherwise → legacy path. Tauri deserializes missing JSON keys as None, so existing frontend callers are unaffected.

Rules

  • Existing frontend CRUD flows (MySQL / Postgres / SQLite) keep working byte-identically — verify with regression test
  • Unit tests for the *_composite methods: one covering the single-key fallback, one covering a real composite WHERE clause (can use mock params for the sql_statement_for_... builders)
  • No breaking changes to existing trait signatures — only new default methods

Reference

  • Plan: docs/sql-server-implementation-plan.md § Phase 2 — 2.3 + 2.4
  • Existing assumption in MySQL: src-tauri/src/drivers/mysql/mod.rs::update_record uses a single pk_col: &str

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is neededsql-serverSQL Server driver

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions