ADR-0018 implementation: auto-fill contracts for serial and shortid
Generalises serial and shortid beyond their previous restricted forms: - `serial` is no longer restricted to single-column PK. Non-PK serial columns get an emitted UNIQUE constraint and use application-side MAX(col)+1 at INSERT time (rowid alias still drives the PK case for free; per ADR-0010 worker-thread serialisation, the read-then-insert sequence is safe). - `shortid` columns auto-fill existing null cells when the column is materialised — `add column T: x (shortid)` on a non-empty table no longer leaves rows in a not-really-valid NULL state. - `int -> serial` joins the type-change matrix as always-clean identity (closes the asymmetry vs `text -> shortid`); other sources are refused with a route-via-int hint. - `change column T: x (serial|shortid)` fills null source cells with sequence / generated values in the same rebuild transaction. Internal infrastructure: - ReadColumn gains `unique: bool`; read_schema detects single- column UNIQUE indexes via pragma_index_list / pragma_index_info; schema_to_ddl emits inline UNIQUE for non-PK columns. - ColumnSchema (persistence) gains `unique: bool` so the flag survives YAML round-trip and rebuild-from-text reconstructs it faithfully — preserves the "serial -> int leaves UNIQUE in place" promise across save/load cycles. - ChangeColumnTypeResult.client_side now carries `auto_filled` + `auto_fill_kind` alongside `transformed` + `lossy`; the app handler renders separate note lines when both apply. - AddColumnResult is a new return type carrying pre-rendered [client-side] note lines for the auto-fill paths. Tests: 519 -> 534 (+15). Clippy clean.
This commit is contained in:
+8
-3
@@ -29,8 +29,8 @@ use crate::action::Action;
|
||||
use crate::app::App;
|
||||
use crate::cli::Args;
|
||||
use crate::db::{
|
||||
ChangeColumnTypeResult, DataResult, Database, DbError, DeleteResult, InsertResult,
|
||||
TableDescription, UpdateResult,
|
||||
AddColumnResult, ChangeColumnTypeResult, DataResult, Database, DbError, DeleteResult,
|
||||
InsertResult, TableDescription, UpdateResult,
|
||||
};
|
||||
use crate::dsl::Command;
|
||||
use crate::event::AppEvent;
|
||||
@@ -951,6 +951,10 @@ fn spawn_dsl_dispatch(
|
||||
command: command.clone(),
|
||||
result,
|
||||
},
|
||||
Ok(CommandOutcome::AddColumn(result)) => AppEvent::DslAddColumnSucceeded {
|
||||
command: command.clone(),
|
||||
result,
|
||||
},
|
||||
Err(DbError::PersistenceFatal {
|
||||
operation,
|
||||
path,
|
||||
@@ -988,6 +992,7 @@ enum CommandOutcome {
|
||||
Update(UpdateResult),
|
||||
Delete(DeleteResult),
|
||||
ChangeColumn(ChangeColumnTypeResult),
|
||||
AddColumn(AddColumnResult),
|
||||
}
|
||||
|
||||
/// Execute a parsed user command and return either a typed
|
||||
@@ -1016,7 +1021,7 @@ async fn execute_command_typed(
|
||||
Command::AddColumn { table, column, ty } => database
|
||||
.add_column(table, column, ty, src)
|
||||
.await
|
||||
.map(|d| CommandOutcome::Schema(Some(d))),
|
||||
.map(CommandOutcome::AddColumn),
|
||||
Command::DropColumn { table, column } => database
|
||||
.drop_column(table, column, src)
|
||||
.await
|
||||
|
||||
Reference in New Issue
Block a user