Skip to content

Commit 75effc3

Browse files
committed
Add case
1 parent f3ef9b2 commit 75effc3

3 files changed

Lines changed: 206 additions & 0 deletions

File tree

crates/vespertide-query/src/sql/add_constraint.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,94 @@ mod tests {
999999
assert!(sql.contains("CONSTRAINT \"chk_age\" CHECK"));
10001000
}
10011001

1002+
#[test]
1003+
fn test_add_constraint_primary_key_sqlite_without_existing_check() {
1004+
// Test PrimaryKey addition when there are no existing CHECK constraints (line 84)
1005+
// This should hit the else branch: BuiltQuery::CreateTable(Box::new(create_temp_table))
1006+
let constraint = TableConstraint::PrimaryKey {
1007+
columns: vec!["id".into()],
1008+
auto_increment: false,
1009+
};
1010+
let current_schema = vec![TableDef {
1011+
name: "users".into(),
1012+
columns: vec![ColumnDef {
1013+
name: "id".into(),
1014+
r#type: ColumnType::Simple(SimpleColumnType::Integer),
1015+
nullable: true,
1016+
default: None,
1017+
comment: None,
1018+
primary_key: None,
1019+
unique: None,
1020+
index: None,
1021+
foreign_key: None,
1022+
}],
1023+
constraints: vec![], // No existing CHECK constraints
1024+
indexes: vec![],
1025+
}];
1026+
let result = build_add_constraint(
1027+
&DatabaseBackend::Sqlite,
1028+
"users",
1029+
&constraint,
1030+
&current_schema,
1031+
);
1032+
assert!(result.is_ok());
1033+
let queries = result.unwrap();
1034+
let sql = queries
1035+
.iter()
1036+
.map(|q| q.build(DatabaseBackend::Sqlite))
1037+
.collect::<Vec<String>>()
1038+
.join("\n");
1039+
// Should create table without CHECK constraints (using BuiltQuery::CreateTable)
1040+
assert!(sql.contains("CREATE TABLE"));
1041+
assert!(sql.contains("PRIMARY KEY"));
1042+
}
1043+
1044+
#[test]
1045+
fn test_add_constraint_foreign_key_sqlite_without_existing_check() {
1046+
// Test ForeignKey addition when there are no existing CHECK constraints (line 238)
1047+
// This should hit the else branch: BuiltQuery::CreateTable(Box::new(create_temp_table))
1048+
let constraint = TableConstraint::ForeignKey {
1049+
name: Some("fk_user".into()),
1050+
columns: vec!["user_id".into()],
1051+
ref_table: "users".into(),
1052+
ref_columns: vec!["id".into()],
1053+
on_delete: None,
1054+
on_update: None,
1055+
};
1056+
let current_schema = vec![TableDef {
1057+
name: "posts".into(),
1058+
columns: vec![ColumnDef {
1059+
name: "user_id".into(),
1060+
r#type: ColumnType::Simple(SimpleColumnType::Integer),
1061+
nullable: true,
1062+
default: None,
1063+
comment: None,
1064+
primary_key: None,
1065+
unique: None,
1066+
index: None,
1067+
foreign_key: None,
1068+
}],
1069+
constraints: vec![], // No existing CHECK constraints
1070+
indexes: vec![],
1071+
}];
1072+
let result = build_add_constraint(
1073+
&DatabaseBackend::Sqlite,
1074+
"posts",
1075+
&constraint,
1076+
&current_schema,
1077+
);
1078+
assert!(result.is_ok());
1079+
let queries = result.unwrap();
1080+
let sql = queries
1081+
.iter()
1082+
.map(|q| q.build(DatabaseBackend::Sqlite))
1083+
.collect::<Vec<String>>()
1084+
.join("\n");
1085+
// Should create table without CHECK constraints (using BuiltQuery::CreateTable)
1086+
assert!(sql.contains("CREATE TABLE"));
1087+
assert!(sql.contains("FOREIGN KEY"));
1088+
}
1089+
10021090
#[test]
10031091
fn test_add_constraint_check_sqlite_with_indexes() {
10041092
use vespertide_core::IndexDef;

crates/vespertide-query/src/sql/create_table.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,4 +176,68 @@ mod tests {
176176
assert_snapshot!(sql);
177177
});
178178
}
179+
180+
#[test]
181+
fn test_create_table_with_inline_unique() {
182+
// Test inline unique constraint (line 32)
183+
use vespertide_core::schema::str_or_bool::StrOrBoolOrArray;
184+
185+
let mut email_col = col("email", ColumnType::Simple(SimpleColumnType::Text));
186+
email_col.unique = Some(StrOrBoolOrArray::Bool(true));
187+
188+
let result = build_create_table(
189+
&DatabaseBackend::Postgres,
190+
"users",
191+
&[
192+
col("id", ColumnType::Simple(SimpleColumnType::Integer)),
193+
email_col,
194+
],
195+
&[],
196+
)
197+
.unwrap();
198+
let sql = result.build(DatabaseBackend::Postgres);
199+
assert!(sql.contains("UNIQUE"));
200+
}
201+
202+
#[test]
203+
fn test_create_table_with_table_level_unique() {
204+
// Test table-level unique constraint (lines 53-54, 56-58, 60-61)
205+
let result = build_create_table(
206+
&DatabaseBackend::Postgres,
207+
"users",
208+
&[
209+
col("id", ColumnType::Simple(SimpleColumnType::Integer)),
210+
col("email", ColumnType::Simple(SimpleColumnType::Text)),
211+
],
212+
&[TableConstraint::Unique {
213+
name: Some("uq_email".into()),
214+
columns: vec!["email".into()],
215+
}],
216+
)
217+
.unwrap();
218+
let sql = result.build(DatabaseBackend::Postgres);
219+
// sea-query doesn't directly support named unique constraints in CREATE TABLE
220+
// but the code path should be covered
221+
assert!(sql.contains("CREATE TABLE"));
222+
}
223+
224+
#[test]
225+
fn test_create_table_with_table_level_unique_no_name() {
226+
// Test table-level unique constraint without name (lines 53-54, 56-58, 60-61)
227+
let result = build_create_table(
228+
&DatabaseBackend::Postgres,
229+
"users",
230+
&[
231+
col("id", ColumnType::Simple(SimpleColumnType::Integer)),
232+
col("email", ColumnType::Simple(SimpleColumnType::Text)),
233+
],
234+
&[TableConstraint::Unique {
235+
name: None,
236+
columns: vec!["email".into()],
237+
}],
238+
)
239+
.unwrap();
240+
let sql = result.build(DatabaseBackend::Postgres);
241+
assert!(sql.contains("CREATE TABLE"));
242+
}
179243
}

crates/vespertide-query/src/sql/helpers.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,4 +260,58 @@ mod tests {
260260
) {
261261
assert_eq!(reference_action_sql(&action), expected);
262262
}
263+
264+
#[rstest]
265+
#[case::gen_random_uuid_postgres(
266+
"gen_random_uuid()",
267+
DatabaseBackend::Postgres,
268+
"gen_random_uuid()"
269+
)]
270+
#[case::gen_random_uuid_mysql("gen_random_uuid()", DatabaseBackend::MySql, "(UUID())")]
271+
#[case::gen_random_uuid_sqlite(
272+
"gen_random_uuid()",
273+
DatabaseBackend::Sqlite,
274+
"(lower(hex(randomblob(16))))"
275+
)]
276+
#[case::current_timestamp_postgres(
277+
"current_timestamp()",
278+
DatabaseBackend::Postgres,
279+
"CURRENT_TIMESTAMP"
280+
)]
281+
#[case::current_timestamp_mysql(
282+
"current_timestamp()",
283+
DatabaseBackend::MySql,
284+
"CURRENT_TIMESTAMP"
285+
)]
286+
#[case::current_timestamp_sqlite(
287+
"current_timestamp()",
288+
DatabaseBackend::Sqlite,
289+
"CURRENT_TIMESTAMP"
290+
)]
291+
#[case::now_postgres("now()", DatabaseBackend::Postgres, "CURRENT_TIMESTAMP")]
292+
#[case::now_mysql("now()", DatabaseBackend::MySql, "CURRENT_TIMESTAMP")]
293+
#[case::now_sqlite("now()", DatabaseBackend::Sqlite, "CURRENT_TIMESTAMP")]
294+
#[case::current_timestamp_upper_postgres(
295+
"CURRENT_TIMESTAMP",
296+
DatabaseBackend::Postgres,
297+
"CURRENT_TIMESTAMP"
298+
)]
299+
#[case::current_timestamp_upper_mysql(
300+
"CURRENT_TIMESTAMP",
301+
DatabaseBackend::MySql,
302+
"CURRENT_TIMESTAMP"
303+
)]
304+
#[case::current_timestamp_upper_sqlite(
305+
"CURRENT_TIMESTAMP",
306+
DatabaseBackend::Sqlite,
307+
"CURRENT_TIMESTAMP"
308+
)]
309+
fn test_convert_default_for_backend(
310+
#[case] default: &str,
311+
#[case] backend: DatabaseBackend,
312+
#[case] expected: &str,
313+
) {
314+
let result = convert_default_for_backend(default, &backend);
315+
assert_eq!(result, expected);
316+
}
263317
}

0 commit comments

Comments
 (0)