Skip to content

Commit f3ef9b2

Browse files
committed
Add case
1 parent cc778eb commit f3ef9b2

11 files changed

Lines changed: 672 additions & 51 deletions

File tree

crates/vespertide-cli/src/commands/diff.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ mod tests {
184184
use std::path::PathBuf;
185185
use tempfile::tempdir;
186186
use vespertide_config::VespertideConfig;
187-
use vespertide_core::{ColumnDef, ColumnType, SimpleColumnType, TableDef};
187+
use vespertide_core::{ColumnDef, ColumnType, SimpleColumnType, TableConstraint, TableDef};
188188

189189
struct CwdGuard {
190190
original: PathBuf,
@@ -226,7 +226,10 @@ mod tests {
226226
index: None,
227227
foreign_key: None,
228228
}],
229-
constraints: vec![],
229+
constraints: vec![TableConstraint::PrimaryKey {
230+
auto_increment: false,
231+
columns: vec!["id".into()],
232+
}],
230233
indexes: vec![],
231234
};
232235
let path = models_dir.join(format!("{name}.json"));

crates/vespertide-cli/src/commands/revision.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ mod tests {
124124
use std::{env, fs, path::PathBuf};
125125
use tempfile::tempdir;
126126
use vespertide_config::{FileFormat, VespertideConfig};
127-
use vespertide_core::{ColumnDef, ColumnType, SimpleColumnType, TableDef};
127+
use vespertide_core::{ColumnDef, ColumnType, SimpleColumnType, TableConstraint, TableDef};
128128

129129
struct CwdGuard {
130130
original: PathBuf,
@@ -174,7 +174,10 @@ mod tests {
174174
index: None,
175175
foreign_key: None,
176176
}],
177-
constraints: vec![],
177+
constraints: vec![TableConstraint::PrimaryKey {
178+
auto_increment: false,
179+
columns: vec!["id".into()],
180+
}],
178181
indexes: vec![],
179182
};
180183
let path = models_dir.join(format!("{name}.json"));

crates/vespertide-cli/src/commands/sql.rs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,10 @@ mod tests {
154154
index: None,
155155
foreign_key: None,
156156
}],
157-
constraints: vec![],
157+
constraints: vec![TableConstraint::PrimaryKey {
158+
auto_increment: false,
159+
columns: vec!["id".into()],
160+
}],
158161
indexes: vec![],
159162
};
160163
let path = models_dir.join(format!("{name}.json"));
@@ -405,4 +408,60 @@ mod tests {
405408
let result = emit_sql(&plan, DatabaseBackend::Postgres, &[]);
406409
assert!(result.is_ok());
407410
}
411+
412+
#[test]
413+
#[serial]
414+
fn emit_sql_multiple_queries_per_action() {
415+
// Test case where a single action generates multiple queries (e.g., SQLite constraint addition)
416+
// This should trigger the queries.len() > 1 branch (line 89)
417+
let tmp = tempdir().unwrap();
418+
let _guard = CwdGuard::new(&tmp.path().to_path_buf());
419+
let _cfg = write_config();
420+
write_model("users");
421+
422+
// Create a migration that adds a NOT NULL column in SQLite, which generates multiple queries
423+
let plan = MigrationPlan {
424+
comment: None,
425+
created_at: None,
426+
version: 1,
427+
actions: vec![MigrationAction::AddColumn {
428+
table: "users".into(),
429+
column: ColumnDef {
430+
name: "nickname".into(),
431+
r#type: ColumnType::Simple(SimpleColumnType::Text),
432+
nullable: false,
433+
default: None,
434+
comment: None,
435+
primary_key: None,
436+
unique: None,
437+
index: None,
438+
foreign_key: None,
439+
},
440+
fill_with: Some("default".into()),
441+
}],
442+
};
443+
444+
let current_schema = vec![TableDef {
445+
name: "users".into(),
446+
columns: vec![ColumnDef {
447+
name: "id".into(),
448+
r#type: ColumnType::Simple(SimpleColumnType::Integer),
449+
nullable: false,
450+
default: None,
451+
comment: None,
452+
primary_key: None,
453+
unique: None,
454+
index: None,
455+
foreign_key: None,
456+
}],
457+
constraints: vec![TableConstraint::PrimaryKey {
458+
auto_increment: false,
459+
columns: vec!["id".into()],
460+
}],
461+
indexes: vec![],
462+
}];
463+
464+
let result = emit_sql(&plan, DatabaseBackend::Sqlite, &current_schema);
465+
assert!(result.is_ok());
466+
}
408467
}

crates/vespertide-cli/src/commands/status.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ mod tests {
144144
use tempfile::tempdir;
145145
use vespertide_config::VespertideConfig;
146146
use vespertide_core::{
147-
ColumnDef, ColumnType, MigrationAction, MigrationPlan, SimpleColumnType, TableDef,
147+
ColumnDef, ColumnType, MigrationAction, MigrationPlan, SimpleColumnType, TableConstraint,
148+
TableDef,
148149
};
149150

150151
struct CwdGuard {
@@ -188,7 +189,10 @@ mod tests {
188189
index: None,
189190
foreign_key: None,
190191
}],
191-
constraints: vec![],
192+
constraints: vec![TableConstraint::PrimaryKey {
193+
auto_increment: false,
194+
columns: vec!["id".into()],
195+
}],
192196
indexes: vec![],
193197
};
194198
let path = models_dir.join(format!("{name}.json"));

crates/vespertide-cli/src/utils.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ mod tests {
109109
use tempfile::tempdir;
110110
use vespertide_config::VespertideConfig;
111111
use vespertide_core::{
112-
ColumnDef, ColumnType, MigrationPlan, SimpleColumnType, TableDef,
112+
ColumnDef, ColumnType, MigrationPlan, SimpleColumnType, TableConstraint, TableDef,
113113
schema::foreign_key::ForeignKeySyntax,
114114
};
115115

@@ -167,7 +167,10 @@ mod tests {
167167
index: None,
168168
foreign_key: None,
169169
}],
170-
constraints: vec![],
170+
constraints: vec![TableConstraint::PrimaryKey {
171+
auto_increment: false,
172+
columns: vec!["id".into()],
173+
}],
171174
indexes: vec![],
172175
};
173176
fs::write("models/users.yaml", serde_yaml::to_string(&table).unwrap()).unwrap();
@@ -200,7 +203,10 @@ mod tests {
200203
index: None,
201204
foreign_key: None,
202205
}],
203-
constraints: vec![],
206+
constraints: vec![TableConstraint::PrimaryKey {
207+
auto_increment: false,
208+
columns: vec!["id".into()],
209+
}],
204210
indexes: vec![],
205211
};
206212
let content = serde_json::to_string_pretty(&table).unwrap();

crates/vespertide-core/src/schema/table.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,26 @@ mod tests {
745745
assert_eq!(normalized.indexes.len(), 0);
746746
}
747747

748+
#[test]
749+
fn normalize_table_without_primary_key() {
750+
// Test normalize with a table that has no primary key columns
751+
// This should cover lines 67-69, 72-73, and 93 (pk_columns.is_empty() branch)
752+
let table = TableDef {
753+
name: "users".into(),
754+
columns: vec![
755+
col("name", ColumnType::Simple(SimpleColumnType::Text)),
756+
col("email", ColumnType::Simple(SimpleColumnType::Text)),
757+
],
758+
constraints: vec![],
759+
indexes: vec![],
760+
};
761+
762+
let normalized = table.normalize().unwrap();
763+
// Should not add any primary key constraint
764+
assert_eq!(normalized.constraints.len(), 0);
765+
assert_eq!(normalized.indexes.len(), 0);
766+
}
767+
748768
#[test]
749769
fn normalize_multiple_indexes_from_same_array() {
750770
// Multiple columns with same array of index names should create multiple composite indexes

crates/vespertide-loader/src/models.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ mod tests {
171171
use std::fs;
172172
use tempfile::tempdir;
173173
use vespertide_core::{
174-
ColumnDef, ColumnType, SimpleColumnType, schema::foreign_key::ForeignKeySyntax,
174+
ColumnDef, ColumnType, SimpleColumnType, TableConstraint,
175+
schema::foreign_key::ForeignKeySyntax,
175176
};
176177

177178
struct CwdGuard {
@@ -231,7 +232,10 @@ mod tests {
231232
index: None,
232233
foreign_key: None,
233234
}],
234-
constraints: vec![],
235+
constraints: vec![TableConstraint::PrimaryKey {
236+
auto_increment: false,
237+
columns: vec!["id".into()],
238+
}],
235239
indexes: vec![],
236240
};
237241
fs::write("models/users.yaml", serde_yaml::to_string(&table).unwrap()).unwrap();
@@ -264,7 +268,10 @@ mod tests {
264268
index: None,
265269
foreign_key: None,
266270
}],
267-
constraints: vec![],
271+
constraints: vec![TableConstraint::PrimaryKey {
272+
auto_increment: false,
273+
columns: vec!["id".into()],
274+
}],
268275
indexes: vec![],
269276
};
270277
let content = serde_json::to_string_pretty(&table).unwrap();

crates/vespertide-planner/src/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,6 @@ pub enum PlannerError {
2828
MissingFillWith(String, String),
2929
#[error("table validation error: {0}")]
3030
TableValidation(String),
31+
#[error("table '{0}' must have a primary key")]
32+
MissingPrimaryKey(String),
3133
}

0 commit comments

Comments
 (0)