refactor: ColumnSpec / AddColumn carry constraint fields (ADR-0029 scaffolding)
Expand ColumnSpec and Command::AddColumn with the four ADR-0029 constraint slots (not_null, unique, default, check), all defaulting off; `Database::add_column` now takes a ColumnSpec. No behaviour change — the grammar to set the fields and the DDL to enforce them land in the following commits. Isolated here so those commits stay readable. Adds ColumnSpec::new for the unconstrained case; 110 call sites updated. 1172 tests pass; clippy clean.
This commit is contained in:
+6
-8
@@ -2209,10 +2209,7 @@ mod tests {
|
|||||||
command,
|
command,
|
||||||
&Command::CreateTable {
|
&Command::CreateTable {
|
||||||
name: "Customers".to_string(),
|
name: "Customers".to_string(),
|
||||||
columns: vec![crate::dsl::ColumnSpec {
|
columns: vec![crate::dsl::ColumnSpec::new("id", Type::Serial)],
|
||||||
name: "id".to_string(),
|
|
||||||
ty: Type::Serial,
|
|
||||||
}],
|
|
||||||
primary_key: vec!["id".to_string()],
|
primary_key: vec!["id".to_string()],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -2419,10 +2416,7 @@ mod tests {
|
|||||||
let mut app = App::new();
|
let mut app = App::new();
|
||||||
let cmd = Command::CreateTable {
|
let cmd = Command::CreateTable {
|
||||||
name: "Customers".to_string(),
|
name: "Customers".to_string(),
|
||||||
columns: vec![crate::dsl::ColumnSpec {
|
columns: vec![crate::dsl::ColumnSpec::new("id", Type::Serial)],
|
||||||
name: "id".to_string(),
|
|
||||||
ty: Type::Serial,
|
|
||||||
}],
|
|
||||||
primary_key: vec!["id".to_string()],
|
primary_key: vec!["id".to_string()],
|
||||||
};
|
};
|
||||||
let desc = sample_description("Customers");
|
let desc = sample_description("Customers");
|
||||||
@@ -3174,6 +3168,10 @@ mod tests {
|
|||||||
table: "T".to_string(),
|
table: "T".to_string(),
|
||||||
column: "Name".to_string(),
|
column: "Name".to_string(),
|
||||||
ty: Type::Text,
|
ty: Type::Text,
|
||||||
|
not_null: false,
|
||||||
|
unique: false,
|
||||||
|
default: None,
|
||||||
|
check: None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -446,8 +446,7 @@ enum Request {
|
|||||||
},
|
},
|
||||||
AddColumn {
|
AddColumn {
|
||||||
table: String,
|
table: String,
|
||||||
column: String,
|
column: ColumnSpec,
|
||||||
ty: Type,
|
|
||||||
source: Option<String>,
|
source: Option<String>,
|
||||||
reply: oneshot::Sender<Result<AddColumnResult, DbError>>,
|
reply: oneshot::Sender<Result<AddColumnResult, DbError>>,
|
||||||
},
|
},
|
||||||
@@ -670,15 +669,13 @@ impl Database {
|
|||||||
pub async fn add_column(
|
pub async fn add_column(
|
||||||
&self,
|
&self,
|
||||||
table: String,
|
table: String,
|
||||||
column: String,
|
column: ColumnSpec,
|
||||||
ty: Type,
|
|
||||||
source: Option<String>,
|
source: Option<String>,
|
||||||
) -> Result<AddColumnResult, DbError> {
|
) -> Result<AddColumnResult, DbError> {
|
||||||
let (reply, recv) = oneshot::channel();
|
let (reply, recv) = oneshot::channel();
|
||||||
self.send(Request::AddColumn {
|
self.send(Request::AddColumn {
|
||||||
table,
|
table,
|
||||||
column,
|
column,
|
||||||
ty,
|
|
||||||
source,
|
source,
|
||||||
reply,
|
reply,
|
||||||
})
|
})
|
||||||
@@ -1142,7 +1139,6 @@ fn handle_request(conn: &Connection, persistence: Option<&Persistence>, req: Req
|
|||||||
Request::AddColumn {
|
Request::AddColumn {
|
||||||
table,
|
table,
|
||||||
column,
|
column,
|
||||||
ty,
|
|
||||||
source,
|
source,
|
||||||
reply,
|
reply,
|
||||||
} => {
|
} => {
|
||||||
@@ -1152,7 +1148,6 @@ fn handle_request(conn: &Connection, persistence: Option<&Persistence>, req: Req
|
|||||||
source.as_deref(),
|
source.as_deref(),
|
||||||
&table,
|
&table,
|
||||||
&column,
|
&column,
|
||||||
ty,
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Request::DropColumn {
|
Request::DropColumn {
|
||||||
@@ -1932,14 +1927,13 @@ fn do_add_column(
|
|||||||
persistence: Option<&Persistence>,
|
persistence: Option<&Persistence>,
|
||||||
source: Option<&str>,
|
source: Option<&str>,
|
||||||
table: &str,
|
table: &str,
|
||||||
column: &str,
|
column: &ColumnSpec,
|
||||||
ty: Type,
|
|
||||||
) -> Result<AddColumnResult, DbError> {
|
) -> Result<AddColumnResult, DbError> {
|
||||||
let auto_generated = matches!(ty, Type::Serial | Type::ShortId);
|
let auto_generated = matches!(column.ty, Type::Serial | Type::ShortId);
|
||||||
if !auto_generated {
|
if !auto_generated {
|
||||||
return do_add_plain_column(conn, persistence, source, table, column, ty);
|
return do_add_plain_column(conn, persistence, source, table, column);
|
||||||
}
|
}
|
||||||
do_add_auto_generated_column(conn, persistence, source, table, column, ty)
|
do_add_auto_generated_column(conn, persistence, source, table, column)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Plain ALTER-TABLE path for non-auto-generated types.
|
/// Plain ALTER-TABLE path for non-auto-generated types.
|
||||||
@@ -1948,9 +1942,12 @@ fn do_add_plain_column(
|
|||||||
persistence: Option<&Persistence>,
|
persistence: Option<&Persistence>,
|
||||||
source: Option<&str>,
|
source: Option<&str>,
|
||||||
table: &str,
|
table: &str,
|
||||||
column: &str,
|
spec: &ColumnSpec,
|
||||||
ty: Type,
|
|
||||||
) -> Result<AddColumnResult, DbError> {
|
) -> Result<AddColumnResult, DbError> {
|
||||||
|
// ADR-0029: the constraint DDL suffix is emitted here once
|
||||||
|
// the constraint grammar lands; for now name + type only.
|
||||||
|
let ty = spec.ty;
|
||||||
|
let column = spec.name.as_str();
|
||||||
let ddl = format!(
|
let ddl = format!(
|
||||||
"ALTER TABLE {tbl} ADD COLUMN {col} {sqlite_type};",
|
"ALTER TABLE {tbl} ADD COLUMN {col} {sqlite_type};",
|
||||||
tbl = quote_ident(table),
|
tbl = quote_ident(table),
|
||||||
@@ -1994,11 +1991,12 @@ fn do_add_auto_generated_column(
|
|||||||
persistence: Option<&Persistence>,
|
persistence: Option<&Persistence>,
|
||||||
source: Option<&str>,
|
source: Option<&str>,
|
||||||
table: &str,
|
table: &str,
|
||||||
column: &str,
|
spec: &ColumnSpec,
|
||||||
ty: Type,
|
|
||||||
) -> Result<AddColumnResult, DbError> {
|
) -> Result<AddColumnResult, DbError> {
|
||||||
use rusqlite::types::Value as RV;
|
use rusqlite::types::Value as RV;
|
||||||
|
|
||||||
|
let ty = spec.ty;
|
||||||
|
let column = spec.name.as_str();
|
||||||
let old_schema = read_schema(conn, table)?;
|
let old_schema = read_schema(conn, table)?;
|
||||||
if old_schema.columns.iter().any(|c| c.name == column) {
|
if old_schema.columns.iter().any(|c| c.name == column) {
|
||||||
return Err(DbError::Unsupported(format!(
|
return Err(DbError::Unsupported(format!(
|
||||||
@@ -5473,10 +5471,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn col(name: &str, ty: Type) -> ColumnSpec {
|
fn col(name: &str, ty: Type) -> ColumnSpec {
|
||||||
ColumnSpec {
|
ColumnSpec::new(name, ty)
|
||||||
name: name.to_string(),
|
|
||||||
ty,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience: a `serial`-PK table with a single `id` column.
|
/// Convenience: a `serial`-PK table with a single `id` column.
|
||||||
@@ -5589,7 +5584,7 @@ mod tests {
|
|||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "Customers").await;
|
make_id_table(&db, "Customers").await;
|
||||||
let result = db
|
let result = db
|
||||||
.add_column("Customers".to_string(), "Name".to_string(), Type::Text, None)
|
.add_column("Customers".to_string(), ColumnSpec::new("Name".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let desc = &result.description;
|
let desc = &result.description;
|
||||||
@@ -5609,7 +5604,7 @@ mod tests {
|
|||||||
// datetime, decimal — all backed by TEXT).
|
// datetime, decimal — all backed by TEXT).
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
for ty in [Type::Date, Type::DateTime, Type::Decimal, Type::ShortId] {
|
for ty in [Type::Date, Type::DateTime, Type::Decimal, Type::ShortId] {
|
||||||
db.add_column("T".to_string(), format!("c_{ty}"), ty, None)
|
db.add_column("T".to_string(), ColumnSpec::new(format!("c_{ty}"), ty), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
@@ -5671,7 +5666,7 @@ mod tests {
|
|||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
for ty in [Type::Text, Type::Int, Type::Real, Type::Bool, Type::ShortId] {
|
for ty in [Type::Text, Type::Int, Type::Real, Type::Bool, Type::ShortId] {
|
||||||
let col_name = format!("c_{ty}");
|
let col_name = format!("c_{ty}");
|
||||||
db.add_column("T".to_string(), col_name.clone(), ty, None)
|
db.add_column("T".to_string(), ColumnSpec::new(col_name.clone(), ty), None)
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|e| panic!("type {ty} failed: {e}"));
|
.unwrap_or_else(|e| panic!("type {ty} failed: {e}"));
|
||||||
}
|
}
|
||||||
@@ -5688,7 +5683,7 @@ mod tests {
|
|||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
let result = db
|
let result = db
|
||||||
.add_column("T".to_string(), "code".to_string(), Type::Serial, None)
|
.add_column("T".to_string(), ColumnSpec::new("code".to_string(), Type::Serial), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let code = result
|
let code = result
|
||||||
@@ -5712,7 +5707,7 @@ mod tests {
|
|||||||
/// (text) and insert N rows, populating just `Name`.
|
/// (text) and insert N rows, populating just `Name`.
|
||||||
async fn make_table_with_n_rows(db: &Database, table: &str, count: usize) {
|
async fn make_table_with_n_rows(db: &Database, table: &str, count: usize) {
|
||||||
make_id_table(db, table).await;
|
make_id_table(db, table).await;
|
||||||
db.add_column(table.to_string(), "Name".to_string(), Type::Text, None)
|
db.add_column(table.to_string(), ColumnSpec::new("Name".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
for i in 0..count {
|
for i in 0..count {
|
||||||
@@ -5732,7 +5727,7 @@ mod tests {
|
|||||||
let db = db();
|
let db = db();
|
||||||
make_table_with_n_rows(&db, "T", 3).await;
|
make_table_with_n_rows(&db, "T", 3).await;
|
||||||
let result = db
|
let result = db
|
||||||
.add_column("T".to_string(), "seq".to_string(), Type::Serial, None)
|
.add_column("T".to_string(), ColumnSpec::new("seq".to_string(), Type::Serial), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let seq = result
|
let seq = result
|
||||||
@@ -5765,7 +5760,7 @@ mod tests {
|
|||||||
let db = db();
|
let db = db();
|
||||||
make_table_with_n_rows(&db, "T", 3).await;
|
make_table_with_n_rows(&db, "T", 3).await;
|
||||||
let result = db
|
let result = db
|
||||||
.add_column("T".to_string(), "tag".to_string(), Type::ShortId, None)
|
.add_column("T".to_string(), ColumnSpec::new("tag".to_string(), Type::ShortId), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let tag = result
|
let tag = result
|
||||||
@@ -5800,7 +5795,7 @@ mod tests {
|
|||||||
// columns continue to use SQLite's rowid alias.
|
// columns continue to use SQLite's rowid alias.
|
||||||
let db = db();
|
let db = db();
|
||||||
make_table_with_n_rows(&db, "T", 0).await;
|
make_table_with_n_rows(&db, "T", 0).await;
|
||||||
db.add_column("T".to_string(), "seq".to_string(), Type::Serial, None)
|
db.add_column("T".to_string(), ColumnSpec::new("seq".to_string(), Type::Serial), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// Insert three rows providing only `Name`. The seq
|
// Insert three rows providing only `Name`. The seq
|
||||||
@@ -5833,7 +5828,7 @@ mod tests {
|
|||||||
// accepted (ADR-0018 Resolution 2).
|
// accepted (ADR-0018 Resolution 2).
|
||||||
let db = db();
|
let db = db();
|
||||||
make_table_with_n_rows(&db, "T", 0).await;
|
make_table_with_n_rows(&db, "T", 0).await;
|
||||||
db.add_column("T".to_string(), "seq".to_string(), Type::Serial, None)
|
db.add_column("T".to_string(), ColumnSpec::new("seq".to_string(), Type::Serial), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// Insert with explicit seq=100.
|
// Insert with explicit seq=100.
|
||||||
@@ -5872,7 +5867,7 @@ mod tests {
|
|||||||
// confirming the engine refuses.
|
// confirming the engine refuses.
|
||||||
let db = db();
|
let db = db();
|
||||||
make_table_with_n_rows(&db, "T", 2).await;
|
make_table_with_n_rows(&db, "T", 2).await;
|
||||||
db.add_column("T".to_string(), "seq".to_string(), Type::Serial, None)
|
db.add_column("T".to_string(), ColumnSpec::new("seq".to_string(), Type::Serial), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// Attempt to UPDATE one row to have the same `seq` value
|
// Attempt to UPDATE one row to have the same `seq` value
|
||||||
@@ -5928,7 +5923,7 @@ mod tests {
|
|||||||
async fn add_column_to_missing_table_returns_no_such_table() {
|
async fn add_column_to_missing_table_returns_no_such_table() {
|
||||||
let db = db();
|
let db = db();
|
||||||
let err = db
|
let err = db
|
||||||
.add_column("Ghost".to_string(), "x".to_string(), Type::Text, None)
|
.add_column("Ghost".to_string(), ColumnSpec::new("x".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
match err {
|
match err {
|
||||||
@@ -5943,7 +5938,7 @@ mod tests {
|
|||||||
async fn drop_column_removes_column_and_data() {
|
async fn drop_column_removes_column_and_data() {
|
||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
db.add_column("T".to_string(), "Score".to_string(), Type::Int, None)
|
db.add_column("T".to_string(), ColumnSpec::new("Score".to_string(), Type::Int), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
db.insert(
|
db.insert(
|
||||||
@@ -5993,12 +5988,7 @@ mod tests {
|
|||||||
// Customers(id PK) ← Orders(cust_id FK)
|
// Customers(id PK) ← Orders(cust_id FK)
|
||||||
make_id_table(&db, "Customers").await;
|
make_id_table(&db, "Customers").await;
|
||||||
make_id_table(&db, "Orders").await;
|
make_id_table(&db, "Orders").await;
|
||||||
db.add_column(
|
db.add_column("Orders".to_string(), ColumnSpec::new("cust_id".to_string(), Type::Int), None)
|
||||||
"Orders".to_string(),
|
|
||||||
"cust_id".to_string(),
|
|
||||||
Type::Int,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
db.add_relationship(
|
db.add_relationship(
|
||||||
@@ -6043,7 +6033,7 @@ mod tests {
|
|||||||
/// something indexable.
|
/// something indexable.
|
||||||
async fn make_indexable_table(db: &Database, name: &str) {
|
async fn make_indexable_table(db: &Database, name: &str) {
|
||||||
make_id_table(db, name).await;
|
make_id_table(db, name).await;
|
||||||
db.add_column(name.to_string(), "Email".to_string(), Type::Text, None)
|
db.add_column(name.to_string(), ColumnSpec::new("Email".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.expect("add Email column");
|
.expect("add Email column");
|
||||||
}
|
}
|
||||||
@@ -6081,10 +6071,10 @@ mod tests {
|
|||||||
async fn add_index_composite_auto_name_joins_columns() {
|
async fn add_index_composite_auto_name_joins_columns() {
|
||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "Orders").await;
|
make_id_table(&db, "Orders").await;
|
||||||
db.add_column("Orders".to_string(), "CustId".to_string(), Type::Int, None)
|
db.add_column("Orders".to_string(), ColumnSpec::new("CustId".to_string(), Type::Int), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
db.add_column("Orders".to_string(), "Day".to_string(), Type::Date, None)
|
db.add_column("Orders".to_string(), ColumnSpec::new("Day".to_string(), Type::Date), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let desc = db
|
let desc = db
|
||||||
@@ -6107,7 +6097,7 @@ mod tests {
|
|||||||
async fn add_index_rejects_duplicate_name() {
|
async fn add_index_rejects_duplicate_name() {
|
||||||
let db = db();
|
let db = db();
|
||||||
make_indexable_table(&db, "Customers").await;
|
make_indexable_table(&db, "Customers").await;
|
||||||
db.add_column("Customers".to_string(), "Nick".to_string(), Type::Text, None)
|
db.add_column("Customers".to_string(), ColumnSpec::new("Nick".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
db.add_index(
|
db.add_index(
|
||||||
@@ -6306,7 +6296,7 @@ mod tests {
|
|||||||
// unrelated column must survive the rebuild (ADR-0025).
|
// unrelated column must survive the rebuild (ADR-0025).
|
||||||
let db = db();
|
let db = db();
|
||||||
make_indexable_table(&db, "T").await;
|
make_indexable_table(&db, "T").await;
|
||||||
db.add_column("T".to_string(), "Score".to_string(), Type::Int, None)
|
db.add_column("T".to_string(), ColumnSpec::new("Score".to_string(), Type::Int), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
db.add_index(
|
db.add_index(
|
||||||
@@ -6339,7 +6329,7 @@ mod tests {
|
|||||||
async fn rename_column_updates_schema_and_metadata() {
|
async fn rename_column_updates_schema_and_metadata() {
|
||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
db.add_column("T".to_string(), "Old".to_string(), Type::Text, None)
|
db.add_column("T".to_string(), ColumnSpec::new("Old".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let desc = db
|
let desc = db
|
||||||
@@ -6358,12 +6348,7 @@ mod tests {
|
|||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "Customers").await;
|
make_id_table(&db, "Customers").await;
|
||||||
make_id_table(&db, "Orders").await;
|
make_id_table(&db, "Orders").await;
|
||||||
db.add_column(
|
db.add_column("Orders".to_string(), ColumnSpec::new("cust_id".to_string(), Type::Int), None)
|
||||||
"Orders".to_string(),
|
|
||||||
"cust_id".to_string(),
|
|
||||||
Type::Int,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
db.add_relationship(
|
db.add_relationship(
|
||||||
@@ -6423,10 +6408,10 @@ mod tests {
|
|||||||
async fn rename_column_refuses_collision() {
|
async fn rename_column_refuses_collision() {
|
||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
db.add_column("T".to_string(), "A".to_string(), Type::Text, None)
|
db.add_column("T".to_string(), ColumnSpec::new("A".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
db.add_column("T".to_string(), "B".to_string(), Type::Text, None)
|
db.add_column("T".to_string(), ColumnSpec::new("B".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let err = db
|
let err = db
|
||||||
@@ -6440,7 +6425,7 @@ mod tests {
|
|||||||
async fn rename_column_refuses_identity_rename() {
|
async fn rename_column_refuses_identity_rename() {
|
||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
db.add_column("T".to_string(), "A".to_string(), Type::Text, None)
|
db.add_column("T".to_string(), ColumnSpec::new("A".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let err = db
|
let err = db
|
||||||
@@ -6454,7 +6439,7 @@ mod tests {
|
|||||||
async fn change_column_type_works_for_compatible_data() {
|
async fn change_column_type_works_for_compatible_data() {
|
||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
db.add_column("T".to_string(), "Score".to_string(), Type::Text, None)
|
db.add_column("T".to_string(), ColumnSpec::new("Score".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// Insert numeric-looking strings.
|
// Insert numeric-looking strings.
|
||||||
@@ -6523,12 +6508,7 @@ mod tests {
|
|||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "Customers").await;
|
make_id_table(&db, "Customers").await;
|
||||||
make_id_table(&db, "Orders").await;
|
make_id_table(&db, "Orders").await;
|
||||||
db.add_column(
|
db.add_column("Orders".to_string(), ColumnSpec::new("cust_id".to_string(), Type::Int), None)
|
||||||
"Orders".to_string(),
|
|
||||||
"cust_id".to_string(),
|
|
||||||
Type::Int,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
db.add_relationship(
|
db.add_relationship(
|
||||||
@@ -6572,12 +6552,7 @@ mod tests {
|
|||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "Customers").await;
|
make_id_table(&db, "Customers").await;
|
||||||
make_id_table(&db, "Orders").await;
|
make_id_table(&db, "Orders").await;
|
||||||
db.add_column(
|
db.add_column("Orders".to_string(), ColumnSpec::new("cust_id".to_string(), Type::Int), None)
|
||||||
"Orders".to_string(),
|
|
||||||
"cust_id".to_string(),
|
|
||||||
Type::Int,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
db.add_relationship(
|
db.add_relationship(
|
||||||
@@ -6613,7 +6588,7 @@ mod tests {
|
|||||||
// table.
|
// table.
|
||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
db.add_column("T".to_string(), "Score".to_string(), Type::Real, None)
|
db.add_column("T".to_string(), ColumnSpec::new("Score".to_string(), Type::Real), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
for v in ["3.14", "2.71"] {
|
for v in ["3.14", "2.71"] {
|
||||||
@@ -6664,7 +6639,7 @@ mod tests {
|
|||||||
// the lossy count.
|
// the lossy count.
|
||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
db.add_column("T".to_string(), "Score".to_string(), Type::Real, None)
|
db.add_column("T".to_string(), ColumnSpec::new("Score".to_string(), Type::Real), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
for v in ["3.14", "2.71", "5.0"] {
|
for v in ["3.14", "2.71", "5.0"] {
|
||||||
@@ -6699,7 +6674,7 @@ mod tests {
|
|||||||
// does NOT help (per ADR-0017 §5 / §2 step 3).
|
// does NOT help (per ADR-0017 §5 / §2 step 3).
|
||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
db.add_column("T".to_string(), "Note".to_string(), Type::Text, None)
|
db.add_column("T".to_string(), ColumnSpec::new("Note".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
for v in ["abc", "123", "xyz"] {
|
for v in ["abc", "123", "xyz"] {
|
||||||
@@ -6748,7 +6723,7 @@ mod tests {
|
|||||||
// [client-side] note is expected.
|
// [client-side] note is expected.
|
||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
db.add_column("T".to_string(), "Flag".to_string(), Type::Int, None)
|
db.add_column("T".to_string(), ColumnSpec::new("Flag".to_string(), Type::Int), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
for v in ["0", "1", "0"] {
|
for v in ["0", "1", "0"] {
|
||||||
@@ -6796,7 +6771,7 @@ mod tests {
|
|||||||
// help (incompatible is not lossy).
|
// help (incompatible is not lossy).
|
||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
db.add_column("T".to_string(), "Flag".to_string(), Type::Int, None)
|
db.add_column("T".to_string(), ColumnSpec::new("Flag".to_string(), Type::Int), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
for v in ["0", "1", "2"] {
|
for v in ["0", "1", "2"] {
|
||||||
@@ -6848,7 +6823,7 @@ mod tests {
|
|||||||
// engine coercion; the note is suppressed.
|
// engine coercion; the note is suppressed.
|
||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
db.add_column("T".to_string(), "Score".to_string(), Type::Text, None)
|
db.add_column("T".to_string(), ColumnSpec::new("Score".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
for v in ["1", "2", "3"] {
|
for v in ["1", "2", "3"] {
|
||||||
@@ -6933,7 +6908,7 @@ mod tests {
|
|||||||
async fn change_column_type_blob_target_refused_statically() {
|
async fn change_column_type_blob_target_refused_statically() {
|
||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
db.add_column("T".to_string(), "Note".to_string(), Type::Text, None)
|
db.add_column("T".to_string(), ColumnSpec::new("Note".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let err = db
|
let err = db
|
||||||
@@ -6956,12 +6931,7 @@ mod tests {
|
|||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "Customers").await;
|
make_id_table(&db, "Customers").await;
|
||||||
make_id_table(&db, "Orders").await;
|
make_id_table(&db, "Orders").await;
|
||||||
db.add_column(
|
db.add_column("Orders".to_string(), ColumnSpec::new("cust_id".to_string(), Type::Int), None)
|
||||||
"Orders".to_string(),
|
|
||||||
"cust_id".to_string(),
|
|
||||||
Type::Int,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
db.add_relationship(
|
db.add_relationship(
|
||||||
@@ -7004,7 +6974,7 @@ mod tests {
|
|||||||
// note, and the structural change goes through.
|
// note, and the structural change goes through.
|
||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
db.add_column("T".to_string(), "Note".to_string(), Type::Text, None)
|
db.add_column("T".to_string(), ColumnSpec::new("Note".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let result = db
|
let result = db
|
||||||
@@ -7037,7 +7007,7 @@ mod tests {
|
|||||||
// existing values are preserved.
|
// existing values are preserved.
|
||||||
let db = db();
|
let db = db();
|
||||||
make_table_with_n_rows(&db, "T", 0).await;
|
make_table_with_n_rows(&db, "T", 0).await;
|
||||||
db.add_column("T".to_string(), "code".to_string(), Type::Int, None)
|
db.add_column("T".to_string(), ColumnSpec::new("code".to_string(), Type::Int), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// Insert a few rows with explicit code values.
|
// Insert a few rows with explicit code values.
|
||||||
@@ -7087,7 +7057,7 @@ mod tests {
|
|||||||
// uniqueness-collision diagnostic.
|
// uniqueness-collision diagnostic.
|
||||||
let db = db();
|
let db = db();
|
||||||
make_table_with_n_rows(&db, "T", 0).await;
|
make_table_with_n_rows(&db, "T", 0).await;
|
||||||
db.add_column("T".to_string(), "code".to_string(), Type::Int, None)
|
db.add_column("T".to_string(), ColumnSpec::new("code".to_string(), Type::Int), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// Two rows with the same code.
|
// Two rows with the same code.
|
||||||
@@ -7129,7 +7099,7 @@ mod tests {
|
|||||||
// to route through int.
|
// to route through int.
|
||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
db.add_column("T".to_string(), "A".to_string(), Type::Text, None)
|
db.add_column("T".to_string(), ColumnSpec::new("A".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let err = db
|
let err = db
|
||||||
@@ -7160,7 +7130,7 @@ mod tests {
|
|||||||
// [client-side] note reports the auto-fill count.
|
// [client-side] note reports the auto-fill count.
|
||||||
let db = db();
|
let db = db();
|
||||||
make_table_with_n_rows(&db, "T", 0).await;
|
make_table_with_n_rows(&db, "T", 0).await;
|
||||||
db.add_column("T".to_string(), "code".to_string(), Type::Int, None)
|
db.add_column("T".to_string(), ColumnSpec::new("code".to_string(), Type::Int), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// Three rows: one with code=5, two with NULL.
|
// Three rows: one with code=5, two with NULL.
|
||||||
@@ -7216,7 +7186,7 @@ mod tests {
|
|||||||
// text column get fresh shortids (ADR-0018 §3).
|
// text column get fresh shortids (ADR-0018 §3).
|
||||||
let db = db();
|
let db = db();
|
||||||
make_table_with_n_rows(&db, "T", 0).await;
|
make_table_with_n_rows(&db, "T", 0).await;
|
||||||
db.add_column("T".to_string(), "tag".to_string(), Type::Text, None)
|
db.add_column("T".to_string(), ColumnSpec::new("tag".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// One row with a valid shortid value, two with NULL.
|
// One row with a valid shortid value, two with NULL.
|
||||||
@@ -7270,12 +7240,7 @@ mod tests {
|
|||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "Customers").await;
|
make_id_table(&db, "Customers").await;
|
||||||
make_id_table(&db, "Orders").await;
|
make_id_table(&db, "Orders").await;
|
||||||
db.add_column(
|
db.add_column("Orders".to_string(), ColumnSpec::new("cust_id".to_string(), Type::Int), None)
|
||||||
"Orders".to_string(),
|
|
||||||
"cust_id".to_string(),
|
|
||||||
Type::Int,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
db.add_relationship(
|
db.add_relationship(
|
||||||
@@ -7308,7 +7273,7 @@ mod tests {
|
|||||||
async fn change_column_type_no_op_to_same_type_errors() {
|
async fn change_column_type_no_op_to_same_type_errors() {
|
||||||
let db = db();
|
let db = db();
|
||||||
make_id_table(&db, "T").await;
|
make_id_table(&db, "T").await;
|
||||||
db.add_column("T".to_string(), "A".to_string(), Type::Int, None)
|
db.add_column("T".to_string(), ColumnSpec::new("A".to_string(), Type::Int), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let err = db
|
let err = db
|
||||||
@@ -7345,7 +7310,7 @@ mod tests {
|
|||||||
None)
|
None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
db.add_column("Orders".to_string(), "CustId".to_string(), Type::Int, None)
|
db.add_column("Orders".to_string(), ColumnSpec::new("CustId".to_string(), Type::Int), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
@@ -7517,7 +7482,7 @@ mod tests {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// Wrong type — text instead of int.
|
// Wrong type — text instead of int.
|
||||||
db.add_column("Orders".to_string(), "CustId".to_string(), Type::Text, None)
|
db.add_column("Orders".to_string(), ColumnSpec::new("CustId".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -7561,7 +7526,7 @@ mod tests {
|
|||||||
None)
|
None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
db.add_column("Orders".to_string(), "CustName".to_string(), Type::Text, None)
|
db.add_column("Orders".to_string(), ColumnSpec::new("CustName".to_string(), Type::Text), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let err = db
|
let err = db
|
||||||
@@ -7690,7 +7655,7 @@ mod tests {
|
|||||||
async fn add_relationship_with_duplicate_name_errors() {
|
async fn add_relationship_with_duplicate_name_errors() {
|
||||||
let db = db();
|
let db = db();
|
||||||
customers_orders_setup(&db).await;
|
customers_orders_setup(&db).await;
|
||||||
db.add_column("Orders".to_string(), "OtherCust".to_string(), Type::Int, None)
|
db.add_column("Orders".to_string(), ColumnSpec::new("OtherCust".to_string(), Type::Int), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
db.add_relationship(
|
db.add_relationship(
|
||||||
@@ -8604,7 +8569,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
db.add_column("T".to_string(), "seq".to_string(), Type::Serial, None)
|
db.add_column("T".to_string(), ColumnSpec::new("seq".to_string(), Type::Serial), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// Read the persisted YAML straight from disk.
|
// Read the persisted YAML straight from disk.
|
||||||
@@ -8647,7 +8612,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
db.add_column("T".to_string(), "seq".to_string(), Type::Serial, None)
|
db.add_column("T".to_string(), ColumnSpec::new("seq".to_string(), Type::Serial), None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// Tear down the .db file and rebuild from yaml + csvs.
|
// Tear down the .db file and rebuild from yaml + csvs.
|
||||||
|
|||||||
+40
-3
@@ -15,13 +15,42 @@ use crate::dsl::action::ReferentialAction;
|
|||||||
use crate::dsl::types::Type;
|
use crate::dsl::types::Type;
|
||||||
use crate::dsl::value::Value;
|
use crate::dsl::value::Value;
|
||||||
|
|
||||||
/// A column at table-creation time: a name and a user-facing
|
/// A column at table-creation time: a name, a user-facing
|
||||||
/// type. Constraints beyond `PRIMARY KEY` (NOT NULL, UNIQUE,
|
/// type, and its column-level constraints (ADR-0029).
|
||||||
/// CHECK, DEFAULT) come in later iterations.
|
///
|
||||||
|
/// `PRIMARY KEY` is not represented here — it is a table-level
|
||||||
|
/// property carried separately in `Command::CreateTable`'s
|
||||||
|
/// `primary_key` list, since it may span columns.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct ColumnSpec {
|
pub struct ColumnSpec {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub ty: Type,
|
pub ty: Type,
|
||||||
|
/// `NOT NULL` — the column rejects `NULL` (ADR-0029).
|
||||||
|
pub not_null: bool,
|
||||||
|
/// `UNIQUE` — non-`NULL` values must be distinct (ADR-0029).
|
||||||
|
pub unique: bool,
|
||||||
|
/// `DEFAULT <literal>` — the value used when an `insert`
|
||||||
|
/// omits this column (ADR-0029).
|
||||||
|
pub default: Option<Value>,
|
||||||
|
/// `CHECK (<expr>)` — every row must satisfy this boolean
|
||||||
|
/// expression (ADR-0029).
|
||||||
|
pub check: Option<Expr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ColumnSpec {
|
||||||
|
/// A column spec carrying no constraints — the common case
|
||||||
|
/// for callers and tests that do not exercise ADR-0029.
|
||||||
|
#[must_use]
|
||||||
|
pub fn new(name: impl Into<String>, ty: Type) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.into(),
|
||||||
|
ty,
|
||||||
|
not_null: false,
|
||||||
|
unique: false,
|
||||||
|
default: None,
|
||||||
|
check: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
@@ -39,10 +68,18 @@ pub enum Command {
|
|||||||
DropTable {
|
DropTable {
|
||||||
name: String,
|
name: String,
|
||||||
},
|
},
|
||||||
|
/// Add a column to an existing table. The column carries
|
||||||
|
/// its constraints from the same suffix grammar as
|
||||||
|
/// `create table` (ADR-0029); `check` is `None` until the
|
||||||
|
/// CHECK grammar lands.
|
||||||
AddColumn {
|
AddColumn {
|
||||||
table: String,
|
table: String,
|
||||||
column: String,
|
column: String,
|
||||||
ty: Type,
|
ty: Type,
|
||||||
|
not_null: bool,
|
||||||
|
unique: bool,
|
||||||
|
default: Option<Value>,
|
||||||
|
check: Option<Expr>,
|
||||||
},
|
},
|
||||||
/// Remove a column from a table. Refused if the column is
|
/// Remove a column from a table. Refused if the column is
|
||||||
/// part of the primary key or is involved in a declared
|
/// part of the primary key or is involved in a declared
|
||||||
|
|||||||
@@ -616,6 +616,12 @@ fn build_add(path: &MatchedPath) -> Result<Command, ValidationError> {
|
|||||||
table: require_ident(path, "table_name")?,
|
table: require_ident(path, "table_name")?,
|
||||||
column: require_ident(path, "column_name")?,
|
column: require_ident(path, "column_name")?,
|
||||||
ty,
|
ty,
|
||||||
|
// Constraint suffix is wired in once the
|
||||||
|
// constraint grammar lands (ADR-0029).
|
||||||
|
not_null: false,
|
||||||
|
unique: false,
|
||||||
|
default: None,
|
||||||
|
check: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Some("1") => build_add_relationship(path),
|
Some("1") => build_add_relationship(path),
|
||||||
@@ -907,10 +913,7 @@ fn build_create_table(path: &MatchedPath) -> Result<Command, ValidationError> {
|
|||||||
|
|
||||||
let columns = pk_specs
|
let columns = pk_specs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(n, t)| ColumnSpec {
|
.map(|(n, t)| ColumnSpec::new(n.clone(), *t))
|
||||||
name: n.clone(),
|
|
||||||
ty: *t,
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
let primary_key = pk_specs.into_iter().map(|(n, _)| n).collect();
|
let primary_key = pk_specs.into_iter().map(|(n, _)| n).collect();
|
||||||
|
|
||||||
|
|||||||
+25
-4
@@ -358,10 +358,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn col(name: &str, ty: Type) -> ColumnSpec {
|
fn col(name: &str, ty: Type) -> ColumnSpec {
|
||||||
ColumnSpec {
|
ColumnSpec::new(name, ty)
|
||||||
name: name.to_string(),
|
|
||||||
ty,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -657,6 +654,10 @@ mod tests {
|
|||||||
table: "Customers".to_string(),
|
table: "Customers".to_string(),
|
||||||
column: "Name".to_string(),
|
column: "Name".to_string(),
|
||||||
ty: Type::Text,
|
ty: Type::Text,
|
||||||
|
not_null: false,
|
||||||
|
unique: false,
|
||||||
|
default: None,
|
||||||
|
check: None,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -671,6 +672,10 @@ mod tests {
|
|||||||
table: "T".to_string(),
|
table: "T".to_string(),
|
||||||
column: "C".to_string(),
|
column: "C".to_string(),
|
||||||
ty: *ty,
|
ty: *ty,
|
||||||
|
not_null: false,
|
||||||
|
unique: false,
|
||||||
|
default: None,
|
||||||
|
check: None,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -684,6 +689,10 @@ mod tests {
|
|||||||
table: "Customers".to_string(),
|
table: "Customers".to_string(),
|
||||||
column: "Name".to_string(),
|
column: "Name".to_string(),
|
||||||
ty: Type::Text,
|
ty: Type::Text,
|
||||||
|
not_null: false,
|
||||||
|
unique: false,
|
||||||
|
default: None,
|
||||||
|
check: None,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -696,6 +705,10 @@ mod tests {
|
|||||||
table: "Customers".to_string(),
|
table: "Customers".to_string(),
|
||||||
column: "Name".to_string(),
|
column: "Name".to_string(),
|
||||||
ty: Type::Text,
|
ty: Type::Text,
|
||||||
|
not_null: false,
|
||||||
|
unique: false,
|
||||||
|
default: None,
|
||||||
|
check: None,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -708,6 +721,10 @@ mod tests {
|
|||||||
table: "Customers".to_string(),
|
table: "Customers".to_string(),
|
||||||
column: "Name".to_string(),
|
column: "Name".to_string(),
|
||||||
ty: Type::Text,
|
ty: Type::Text,
|
||||||
|
not_null: false,
|
||||||
|
unique: false,
|
||||||
|
default: None,
|
||||||
|
check: None,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -720,6 +737,10 @@ mod tests {
|
|||||||
table: "T".to_string(),
|
table: "T".to_string(),
|
||||||
column: "Name".to_string(),
|
column: "Name".to_string(),
|
||||||
ty: Type::Text,
|
ty: Type::Text,
|
||||||
|
not_null: false,
|
||||||
|
unique: false,
|
||||||
|
default: None,
|
||||||
|
check: None,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1346,6 +1346,10 @@ mod tests {
|
|||||||
table: "Customers".to_string(),
|
table: "Customers".to_string(),
|
||||||
column: "Email".to_string(),
|
column: "Email".to_string(),
|
||||||
ty: Type::Text,
|
ty: Type::Text,
|
||||||
|
not_null: false,
|
||||||
|
unique: false,
|
||||||
|
default: None,
|
||||||
|
check: None,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1474,10 +1478,7 @@ mod tests {
|
|||||||
use crate::dsl::command::ColumnSpec;
|
use crate::dsl::command::ColumnSpec;
|
||||||
|
|
||||||
fn col(name: &str, ty: Type) -> ColumnSpec {
|
fn col(name: &str, ty: Type) -> ColumnSpec {
|
||||||
ColumnSpec {
|
ColumnSpec::new(name, ty)
|
||||||
name: name.to_string(),
|
|
||||||
ty,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
+22
-3
@@ -32,7 +32,7 @@ use crate::db::{
|
|||||||
AddColumnResult, ChangeColumnTypeResult, DataResult, Database, DbError, DeleteResult,
|
AddColumnResult, ChangeColumnTypeResult, DataResult, Database, DbError, DeleteResult,
|
||||||
DropColumnResult, InsertResult, QueryPlan, TableDescription, UpdateResult,
|
DropColumnResult, InsertResult, QueryPlan, TableDescription, UpdateResult,
|
||||||
};
|
};
|
||||||
use crate::dsl::Command;
|
use crate::dsl::{Command, ColumnSpec};
|
||||||
use crate::dsl::walker::Severity;
|
use crate::dsl::walker::Severity;
|
||||||
use crate::event::AppEvent;
|
use crate::event::AppEvent;
|
||||||
use crate::project::{
|
use crate::project::{
|
||||||
@@ -1706,8 +1706,27 @@ async fn execute_command_typed(
|
|||||||
.drop_table(name, src)
|
.drop_table(name, src)
|
||||||
.await
|
.await
|
||||||
.map(|()| CommandOutcome::Schema(None)),
|
.map(|()| CommandOutcome::Schema(None)),
|
||||||
Command::AddColumn { table, column, ty } => database
|
Command::AddColumn {
|
||||||
.add_column(table, column, ty, src)
|
table,
|
||||||
|
column,
|
||||||
|
ty,
|
||||||
|
not_null,
|
||||||
|
unique,
|
||||||
|
default,
|
||||||
|
check,
|
||||||
|
} => database
|
||||||
|
.add_column(
|
||||||
|
table,
|
||||||
|
ColumnSpec {
|
||||||
|
name: column,
|
||||||
|
ty,
|
||||||
|
not_null,
|
||||||
|
unique,
|
||||||
|
default,
|
||||||
|
check,
|
||||||
|
},
|
||||||
|
src,
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
.map(CommandOutcome::AddColumn),
|
.map(CommandOutcome::AddColumn),
|
||||||
Command::DropColumn {
|
Command::DropColumn {
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ fn enrich_unique_insert_resolves_table_column_value_and_pinpoint() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Int },
|
ColumnSpec::new("id".to_string(), Type::Int),
|
||||||
ColumnSpec { name: "name".to_string(), ty: Type::Text },
|
ColumnSpec::new("name".to_string(), Type::Text),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
None,
|
None,
|
||||||
@@ -109,7 +109,7 @@ fn enrich_unique_insert_natural_order_short_form_resolves_value_via_schema() {
|
|||||||
rt().block_on(async {
|
rt().block_on(async {
|
||||||
db.create_table(
|
db.create_table(
|
||||||
"thing".to_string(),
|
"thing".to_string(),
|
||||||
vec![ColumnSpec { name: "id".to_string(), ty: Type::Int }],
|
vec![ColumnSpec::new("id".to_string(), Type::Int)],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@@ -152,8 +152,8 @@ fn enrich_unique_update_resolves_value_from_assignments() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Int },
|
ColumnSpec::new("id".to_string(), Type::Int),
|
||||||
ColumnSpec { name: "name".to_string(), ty: Type::Text },
|
ColumnSpec::new("name".to_string(), Type::Text),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
None,
|
None,
|
||||||
@@ -215,8 +215,8 @@ fn enrich_not_null_resolves_table_and_column() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"T".to_string(),
|
"T".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "a".to_string(), ty: Type::Int },
|
ColumnSpec::new("a".to_string(), Type::Int),
|
||||||
ColumnSpec { name: "b".to_string(), ty: Type::Text },
|
ColumnSpec::new("b".to_string(), Type::Text),
|
||||||
],
|
],
|
||||||
vec!["a".to_string(), "b".to_string()],
|
vec!["a".to_string(), "b".to_string()],
|
||||||
None,
|
None,
|
||||||
@@ -258,7 +258,7 @@ fn enrich_fk_insert_resolves_parent_table_column_and_value() {
|
|||||||
rt().block_on(async {
|
rt().block_on(async {
|
||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![ColumnSpec { name: "id".to_string(), ty: Type::Int }],
|
vec![ColumnSpec::new("id".to_string(), Type::Int)],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@@ -267,8 +267,8 @@ fn enrich_fk_insert_resolves_parent_table_column_and_value() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Orders".to_string(),
|
"Orders".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Int },
|
ColumnSpec::new("id".to_string(), Type::Int),
|
||||||
ColumnSpec { name: "CustId".to_string(), ty: Type::Int },
|
ColumnSpec::new("CustId".to_string(), Type::Int),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
None,
|
None,
|
||||||
@@ -333,7 +333,7 @@ fn enrich_fk_insert_natural_order_multi_value_resolves_via_schema() {
|
|||||||
rt().block_on(async {
|
rt().block_on(async {
|
||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![ColumnSpec { name: "id".to_string(), ty: Type::Int }],
|
vec![ColumnSpec::new("id".to_string(), Type::Int)],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@@ -342,9 +342,9 @@ fn enrich_fk_insert_natural_order_multi_value_resolves_via_schema() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Orders".to_string(),
|
"Orders".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Serial },
|
ColumnSpec::new("id".to_string(), Type::Serial),
|
||||||
ColumnSpec { name: "CustId".to_string(), ty: Type::Int },
|
ColumnSpec::new("CustId".to_string(), Type::Int),
|
||||||
ColumnSpec { name: "Total".to_string(), ty: Type::Real },
|
ColumnSpec::new("Total".to_string(), Type::Real),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
None,
|
None,
|
||||||
@@ -408,7 +408,7 @@ fn enrich_fk_delete_resolves_child_table() {
|
|||||||
rt().block_on(async {
|
rt().block_on(async {
|
||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![ColumnSpec { name: "id".to_string(), ty: Type::Int }],
|
vec![ColumnSpec::new("id".to_string(), Type::Int)],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@@ -417,8 +417,8 @@ fn enrich_fk_delete_resolves_child_table() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Orders".to_string(),
|
"Orders".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Int },
|
ColumnSpec::new("id".to_string(), Type::Int),
|
||||||
ColumnSpec { name: "CustId".to_string(), ty: Type::Int },
|
ColumnSpec::new("CustId".to_string(), Type::Int),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
None,
|
None,
|
||||||
|
|||||||
@@ -66,8 +66,8 @@ fn create_table_writes_yaml_and_history() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Serial },
|
ColumnSpec::new("id".to_string(), Type::Serial),
|
||||||
ColumnSpec { name: "Name".to_string(), ty: Type::Text },
|
ColumnSpec::new("Name".to_string(), Type::Text),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create table Customers with pk id(serial)".to_string()),
|
Some("create table Customers with pk id(serial)".to_string()),
|
||||||
@@ -96,8 +96,8 @@ fn insert_writes_csv_and_history() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Serial },
|
ColumnSpec::new("id".to_string(), Type::Serial),
|
||||||
ColumnSpec { name: "Name".to_string(), ty: Type::Text },
|
ColumnSpec::new("Name".to_string(), Type::Text),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create table Customers with pk id(serial)".to_string()),
|
Some("create table Customers with pk id(serial)".to_string()),
|
||||||
@@ -134,7 +134,7 @@ fn drop_table_removes_its_csv() {
|
|||||||
rt().block_on(async {
|
rt().block_on(async {
|
||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![ColumnSpec { name: "id".to_string(), ty: Type::Serial }],
|
vec![ColumnSpec::new("id".to_string(), Type::Serial)],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create table Customers with pk id(serial)".to_string()),
|
Some("create table Customers with pk id(serial)".to_string()),
|
||||||
)
|
)
|
||||||
@@ -172,7 +172,7 @@ fn delete_with_cascade_rewrites_both_csvs() {
|
|||||||
rt().block_on(async {
|
rt().block_on(async {
|
||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![ColumnSpec { name: "id".to_string(), ty: Type::Serial }],
|
vec![ColumnSpec::new("id".to_string(), Type::Serial)],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create table Customers with pk id(serial)".to_string()),
|
Some("create table Customers with pk id(serial)".to_string()),
|
||||||
)
|
)
|
||||||
@@ -181,8 +181,8 @@ fn delete_with_cascade_rewrites_both_csvs() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Orders".to_string(),
|
"Orders".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Serial },
|
ColumnSpec::new("id".to_string(), Type::Serial),
|
||||||
ColumnSpec { name: "CustId".to_string(), ty: Type::Int },
|
ColumnSpec::new("CustId".to_string(), Type::Int),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create table Orders with pk id(serial), CustId(int)".to_string()),
|
Some("create table Orders with pk id(serial), CustId(int)".to_string()),
|
||||||
@@ -259,8 +259,8 @@ fn create_table_does_not_write_csv_for_empty_table() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Serial },
|
ColumnSpec::new("id".to_string(), Type::Serial),
|
||||||
ColumnSpec { name: "Name".to_string(), ty: Type::Text },
|
ColumnSpec::new("Name".to_string(), Type::Text),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create table Customers with pk id(serial)".to_string()),
|
Some("create table Customers with pk id(serial)".to_string()),
|
||||||
@@ -288,8 +288,8 @@ fn delete_all_rows_removes_csv() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Serial },
|
ColumnSpec::new("id".to_string(), Type::Serial),
|
||||||
ColumnSpec { name: "Name".to_string(), ty: Type::Text },
|
ColumnSpec::new("Name".to_string(), Type::Text),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create table Customers with pk id(serial)".to_string()),
|
Some("create table Customers with pk id(serial)".to_string()),
|
||||||
@@ -330,7 +330,7 @@ fn show_table_appends_history_only() {
|
|||||||
rt().block_on(async {
|
rt().block_on(async {
|
||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![ColumnSpec { name: "id".to_string(), ty: Type::Serial }],
|
vec![ColumnSpec::new("id".to_string(), Type::Serial)],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create table Customers with pk id(serial)".to_string()),
|
Some("create table Customers with pk id(serial)".to_string()),
|
||||||
)
|
)
|
||||||
@@ -363,7 +363,7 @@ fn failed_command_does_not_append_history_or_change_yaml() {
|
|||||||
rt().block_on(async {
|
rt().block_on(async {
|
||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![ColumnSpec { name: "id".to_string(), ty: Type::Serial }],
|
vec![ColumnSpec::new("id".to_string(), Type::Serial)],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create table Customers with pk id(serial)".to_string()),
|
Some("create table Customers with pk id(serial)".to_string()),
|
||||||
)
|
)
|
||||||
@@ -375,7 +375,7 @@ fn failed_command_does_not_append_history_or_change_yaml() {
|
|||||||
let err = db
|
let err = db
|
||||||
.create_table(
|
.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![ColumnSpec { name: "id".to_string(), ty: Type::Serial }],
|
vec![ColumnSpec::new("id".to_string(), Type::Serial)],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create table Customers with pk id(serial)".to_string()),
|
Some("create table Customers with pk id(serial)".to_string()),
|
||||||
)
|
)
|
||||||
@@ -404,7 +404,7 @@ fn project_yaml_carries_relationship_after_add() {
|
|||||||
rt().block_on(async {
|
rt().block_on(async {
|
||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![ColumnSpec { name: "id".to_string(), ty: Type::Serial }],
|
vec![ColumnSpec::new("id".to_string(), Type::Serial)],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@@ -413,8 +413,8 @@ fn project_yaml_carries_relationship_after_add() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Orders".to_string(),
|
"Orders".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Serial },
|
ColumnSpec::new("id".to_string(), Type::Serial),
|
||||||
ColumnSpec { name: "CustId".to_string(), ty: Type::Int },
|
ColumnSpec::new("CustId".to_string(), Type::Int),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
None,
|
None,
|
||||||
|
|||||||
+13
-14
@@ -44,8 +44,8 @@ fn rebuild_restores_schema_only_project() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Serial },
|
ColumnSpec::new("id".to_string(), Type::Serial),
|
||||||
ColumnSpec { name: "Name".to_string(), ty: Type::Text },
|
ColumnSpec::new("Name".to_string(), Type::Text),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create table Customers with pk id(serial)".to_string()),
|
Some("create table Customers with pk id(serial)".to_string()),
|
||||||
@@ -98,8 +98,8 @@ fn rebuild_restores_rows_from_csv() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Serial },
|
ColumnSpec::new("id".to_string(), Type::Serial),
|
||||||
ColumnSpec { name: "Name".to_string(), ty: Type::Text },
|
ColumnSpec::new("Name".to_string(), Type::Text),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create".to_string()),
|
Some("create".to_string()),
|
||||||
@@ -165,7 +165,7 @@ fn rebuild_restores_relationships_and_cascade_behaviour() {
|
|||||||
rt().block_on(async {
|
rt().block_on(async {
|
||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![ColumnSpec { name: "id".to_string(), ty: Type::Serial }],
|
vec![ColumnSpec::new("id".to_string(), Type::Serial)],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create".to_string()),
|
Some("create".to_string()),
|
||||||
)
|
)
|
||||||
@@ -174,8 +174,8 @@ fn rebuild_restores_relationships_and_cascade_behaviour() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Orders".to_string(),
|
"Orders".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Serial },
|
ColumnSpec::new("id".to_string(), Type::Serial),
|
||||||
ColumnSpec { name: "CustId".to_string(), ty: Type::Int },
|
ColumnSpec::new("CustId".to_string(), Type::Int),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create".to_string()),
|
Some("create".to_string()),
|
||||||
@@ -265,8 +265,8 @@ fn rebuild_reports_fatal_error_on_bad_csv_row() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Numbers".to_string(),
|
"Numbers".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Serial },
|
ColumnSpec::new("id".to_string(), Type::Serial),
|
||||||
ColumnSpec { name: "n".to_string(), ty: Type::Int },
|
ColumnSpec::new("n".to_string(), Type::Int),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create".to_string()),
|
Some("create".to_string()),
|
||||||
@@ -326,7 +326,7 @@ fn rebuild_preserves_created_at_from_yaml() {
|
|||||||
rt().block_on(async {
|
rt().block_on(async {
|
||||||
db.create_table(
|
db.create_table(
|
||||||
"T".to_string(),
|
"T".to_string(),
|
||||||
vec![ColumnSpec { name: "id".to_string(), ty: Type::Serial }],
|
vec![ColumnSpec::new("id".to_string(), Type::Serial)],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create".to_string()),
|
Some("create".to_string()),
|
||||||
)
|
)
|
||||||
@@ -377,8 +377,7 @@ fn rebuild_preserves_created_at_from_yaml() {
|
|||||||
// describe is read-only; force a rewrite by adding a column.
|
// describe is read-only; force a rewrite by adding a column.
|
||||||
db.add_column(
|
db.add_column(
|
||||||
"T".to_string(),
|
"T".to_string(),
|
||||||
"Note".to_string(),
|
ColumnSpec::new("Note", Type::Text),
|
||||||
Type::Text,
|
|
||||||
Some("add column".to_string()),
|
Some("add column".to_string()),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@@ -410,8 +409,8 @@ fn rebuild_restores_indexes() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Serial },
|
ColumnSpec::new("id".to_string(), Type::Serial),
|
||||||
ColumnSpec { name: "Email".to_string(), ty: Type::Text },
|
ColumnSpec::new("Email".to_string(), Type::Text),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create table Customers with pk id(serial)".to_string()),
|
Some("create table Customers with pk id(serial)".to_string()),
|
||||||
|
|||||||
@@ -131,8 +131,8 @@ fn rebuild_against_populated_db_wipes_and_reloads() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Serial },
|
ColumnSpec::new("id".to_string(), Type::Serial),
|
||||||
ColumnSpec { name: "Name".to_string(), ty: Type::Text },
|
ColumnSpec::new("Name".to_string(), Type::Text),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create".to_string()),
|
Some("create".to_string()),
|
||||||
|
|||||||
@@ -388,7 +388,7 @@ fn temp_with_a_table_is_no_longer_unmodified() {
|
|||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
db.create_table(
|
db.create_table(
|
||||||
"T".to_string(),
|
"T".to_string(),
|
||||||
vec![ColumnSpec { name: "id".to_string(), ty: Type::Serial }],
|
vec![ColumnSpec::new("id".to_string(), Type::Serial)],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create".to_string()),
|
Some("create".to_string()),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -299,8 +299,8 @@ fn end_to_end_export_then_import_real_project() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![
|
vec![
|
||||||
ColumnSpec { name: "id".to_string(), ty: Type::Serial },
|
ColumnSpec::new("id".to_string(), Type::Serial),
|
||||||
ColumnSpec { name: "Name".to_string(), ty: Type::Text },
|
ColumnSpec::new("Name".to_string(), Type::Text),
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
Some("create table Customers with pk id(serial)".to_string()),
|
Some("create table Customers with pk id(serial)".to_string()),
|
||||||
|
|||||||
@@ -165,14 +165,8 @@ fn db_persists_across_open_close_cycles() {
|
|||||||
db.create_table(
|
db.create_table(
|
||||||
"Customers".to_string(),
|
"Customers".to_string(),
|
||||||
vec![
|
vec![
|
||||||
rdbms_playground::dsl::ColumnSpec {
|
rdbms_playground::dsl::ColumnSpec::new("id".to_string(), rdbms_playground::dsl::Type::Serial),
|
||||||
name: "id".to_string(),
|
rdbms_playground::dsl::ColumnSpec::new("Name".to_string(), rdbms_playground::dsl::Type::Text),
|
||||||
ty: rdbms_playground::dsl::Type::Serial,
|
|
||||||
},
|
|
||||||
rdbms_playground::dsl::ColumnSpec {
|
|
||||||
name: "Name".to_string(),
|
|
||||||
ty: rdbms_playground::dsl::Type::Text,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
vec!["id".to_string()],
|
vec!["id".to_string()],
|
||||||
None)
|
None)
|
||||||
|
|||||||
@@ -90,10 +90,7 @@ fn typing_then_submitting_a_dsl_command_emits_execute_action() {
|
|||||||
&actions,
|
&actions,
|
||||||
&Command::CreateTable {
|
&Command::CreateTable {
|
||||||
name: "Customers".to_string(),
|
name: "Customers".to_string(),
|
||||||
columns: vec![ColumnSpec {
|
columns: vec![ColumnSpec::new("id".to_string(), Type::Serial)],
|
||||||
name: "id".to_string(),
|
|
||||||
ty: Type::Serial,
|
|
||||||
}],
|
|
||||||
primary_key: vec!["id".to_string()],
|
primary_key: vec!["id".to_string()],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -271,10 +268,7 @@ fn create_table_flow_updates_tables_list_and_structure_view() {
|
|||||||
let actions = submit(&mut app);
|
let actions = submit(&mut app);
|
||||||
let expected_cmd = Command::CreateTable {
|
let expected_cmd = Command::CreateTable {
|
||||||
name: "Customers".to_string(),
|
name: "Customers".to_string(),
|
||||||
columns: vec![ColumnSpec {
|
columns: vec![ColumnSpec::new("id".to_string(), Type::Serial)],
|
||||||
name: "id".to_string(),
|
|
||||||
ty: Type::Serial,
|
|
||||||
}],
|
|
||||||
primary_key: vec!["id".to_string()],
|
primary_key: vec!["id".to_string()],
|
||||||
};
|
};
|
||||||
assert_one_execute_dsl(&actions, &expected_cmd);
|
assert_one_execute_dsl(&actions, &expected_cmd);
|
||||||
@@ -326,6 +320,10 @@ fn add_column_flow_updates_structure_view() {
|
|||||||
table: "Customers".to_string(),
|
table: "Customers".to_string(),
|
||||||
column: "Name".to_string(),
|
column: "Name".to_string(),
|
||||||
ty: Type::Text,
|
ty: Type::Text,
|
||||||
|
not_null: false,
|
||||||
|
unique: false,
|
||||||
|
default: None,
|
||||||
|
check: None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -338,6 +336,10 @@ fn add_column_flow_updates_structure_view() {
|
|||||||
table: "Customers".to_string(),
|
table: "Customers".to_string(),
|
||||||
column: "Name".to_string(),
|
column: "Name".to_string(),
|
||||||
ty: Type::Text,
|
ty: Type::Text,
|
||||||
|
not_null: false,
|
||||||
|
unique: false,
|
||||||
|
default: None,
|
||||||
|
check: None,
|
||||||
},
|
},
|
||||||
description: Some(updated.clone()),
|
description: Some(updated.clone()),
|
||||||
});
|
});
|
||||||
@@ -479,6 +481,10 @@ fn add_relationship_flow_shows_inbound_section_on_parent() {
|
|||||||
table: "Customers".to_string(),
|
table: "Customers".to_string(),
|
||||||
column: "extra".to_string(),
|
column: "extra".to_string(),
|
||||||
ty: Type::Text,
|
ty: Type::Text,
|
||||||
|
not_null: false,
|
||||||
|
unique: false,
|
||||||
|
default: None,
|
||||||
|
check: None,
|
||||||
},
|
},
|
||||||
description: Some(customers),
|
description: Some(customers),
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user