Skip to content

Commit 4309117

Browse files
committed
wip
1 parent 47d2c2f commit 4309117

22 files changed

Lines changed: 348 additions & 273 deletions

File tree

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

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,30 @@ pub fn cmd_log(backend: DatabaseBackend) -> Result<()> {
5252
" {}. {}",
5353
(i + 1).to_string().bright_magenta().bold(),
5454
match backend {
55-
DatabaseBackend::Postgres => pq.postgres.iter().map(|q| q.build(DatabaseBackend::Postgres)).collect::<Vec<_>>().join(";\n").trim().bright_white(),
56-
DatabaseBackend::MySql => pq.mysql.iter().map(|q| q.build(DatabaseBackend::MySql)).collect::<Vec<_>>().join(";\n").trim().bright_white(),
57-
DatabaseBackend::Sqlite => pq.sqlite.iter().map(|q| q.build(DatabaseBackend::Sqlite)).collect::<Vec<_>>().join(";\n").trim().bright_white(),
55+
DatabaseBackend::Postgres => pq
56+
.postgres
57+
.iter()
58+
.map(|q| q.build(DatabaseBackend::Postgres))
59+
.collect::<Vec<_>>()
60+
.join(";\n")
61+
.trim()
62+
.bright_white(),
63+
DatabaseBackend::MySql => pq
64+
.mysql
65+
.iter()
66+
.map(|q| q.build(DatabaseBackend::MySql))
67+
.collect::<Vec<_>>()
68+
.join(";\n")
69+
.trim()
70+
.bright_white(),
71+
DatabaseBackend::Sqlite => pq
72+
.sqlite
73+
.iter()
74+
.map(|q| q.build(DatabaseBackend::Sqlite))
75+
.collect::<Vec<_>>()
76+
.join(";\n")
77+
.trim()
78+
.bright_white(),
5879
}
5980
);
6081
}

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,11 @@ fn emit_sql(
7676
DatabaseBackend::MySql => &pq.mysql,
7777
DatabaseBackend::Sqlite => &pq.sqlite,
7878
};
79-
println!("{} {}", "Action:".bright_cyan(), pq.action.to_string().bright_white());
79+
println!(
80+
"{} {}",
81+
"Action:".bright_cyan(),
82+
pq.action.to_string().bright_white()
83+
);
8084
for (j, q) in queries.iter().enumerate() {
8185
println!(
8286
"{}{}. {}",
@@ -85,7 +89,9 @@ fn emit_sql(
8589
format!("-{}", j + 1)
8690
} else {
8791
"".to_string()
88-
}.bright_magenta().bold(),
92+
}
93+
.bright_magenta()
94+
.bold(),
8995
q.build(backend).trim().bright_white()
9096
);
9197
}

crates/vespertide-loader/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
pub mod config;
12
pub mod migrations;
23
pub mod models;
3-
pub mod config;
44

55
pub use config::{load_config, load_config_from_path, load_config_or_default};
66
pub use migrations::{load_migrations, load_migrations_at_compile_time, load_migrations_from_dir};

crates/vespertide-loader/src/migrations.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,15 +81,18 @@ pub fn load_migrations_from_dir(
8181
if path.is_file() {
8282
let ext = path.extension().and_then(|s| s.to_str());
8383
if ext == Some("json") || ext == Some("yaml") || ext == Some("yml") {
84-
let content = fs::read_to_string(&path)
85-
.map_err(|e| format!("Failed to read migration file {}: {}", path.display(), e))?;
84+
let content = fs::read_to_string(&path).map_err(|e| {
85+
format!("Failed to read migration file {}: {}", path.display(), e)
86+
})?;
8687

8788
let plan: MigrationPlan = if ext == Some("json") {
88-
serde_json::from_str(&content)
89-
.map_err(|e| format!("Failed to parse JSON migration {}: {}", path.display(), e))?
89+
serde_json::from_str(&content).map_err(|e| {
90+
format!("Failed to parse JSON migration {}: {}", path.display(), e)
91+
})?
9092
} else {
91-
serde_yaml::from_str(&content)
92-
.map_err(|e| format!("Failed to parse YAML migration {}: {}", path.display(), e))?
93+
serde_yaml::from_str(&content).map_err(|e| {
94+
format!("Failed to parse YAML migration {}: {}", path.display(), e)
95+
})?
9396
};
9497

9598
plans.push(plan);

crates/vespertide-loader/src/models.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,10 @@ pub fn load_models_from_dir(
115115
}
116116

117117
/// Internal recursive function for loading models (used by both runtime and compile-time).
118-
fn load_models_recursive_internal(dir: &Path, tables: &mut Vec<TableDef>) -> Result<(), Box<dyn std::error::Error>> {
118+
fn load_models_recursive_internal(
119+
dir: &Path,
120+
tables: &mut Vec<TableDef>,
121+
) -> Result<(), Box<dyn std::error::Error>> {
119122
use std::fs;
120123

121124
let entries = fs::read_dir(dir)
@@ -138,11 +141,13 @@ fn load_models_recursive_internal(dir: &Path, tables: &mut Vec<TableDef>) -> Res
138141
.map_err(|e| format!("Failed to read model file {}: {}", path.display(), e))?;
139142

140143
let table: TableDef = if ext == Some("json") {
141-
serde_json::from_str(&content)
142-
.map_err(|e| format!("Failed to parse JSON model {}: {}", path.display(), e))?
144+
serde_json::from_str(&content).map_err(|e| {
145+
format!("Failed to parse JSON model {}: {}", path.display(), e)
146+
})?
143147
} else {
144-
serde_yaml::from_str(&content)
145-
.map_err(|e| format!("Failed to parse YAML model {}: {}", path.display(), e))?
148+
serde_yaml::from_str(&content).map_err(|e| {
149+
format!("Failed to parse YAML model {}: {}", path.display(), e)
150+
})?
146151
};
147152

148153
tables.push(table);

crates/vespertide-macro/src/lib.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,24 @@ pub fn vespertide_migration(input: TokenStream) -> TokenStream {
9999
let sql_statements: Vec<_> = queries
100100
.iter()
101101
.map(|q| {
102-
let pg_sql = q.postgres.iter().map(|q| q.build(DatabaseBackend::Postgres)).collect::<Vec<_>>().join(";\n");
103-
let mysql_sql = q.mysql.iter().map(|q| q.build(DatabaseBackend::MySql)).collect::<Vec<_>>().join(";\n");
104-
let sqlite_sql = q.sqlite.iter().map(|q| q.build(DatabaseBackend::Sqlite)).collect::<Vec<_>>().join(";\n");
102+
let pg_sql = q
103+
.postgres
104+
.iter()
105+
.map(|q| q.build(DatabaseBackend::Postgres))
106+
.collect::<Vec<_>>()
107+
.join(";\n");
108+
let mysql_sql = q
109+
.mysql
110+
.iter()
111+
.map(|q| q.build(DatabaseBackend::MySql))
112+
.collect::<Vec<_>>()
113+
.join(";\n");
114+
let sqlite_sql = q
115+
.sqlite
116+
.iter()
117+
.map(|q| q.build(DatabaseBackend::Sqlite))
118+
.collect::<Vec<_>>()
119+
.join(";\n");
105120

106121
quote! {
107122
match backend {

crates/vespertide-query/src/builder.rs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ pub fn build_plan_queries(
1717
) -> Result<Vec<PlanQueries>, QueryError> {
1818
let mut queries: Vec<PlanQueries> = Vec::new();
1919
for action in &plan.actions {
20-
let postgres_queries = build_action_queries(&DatabaseBackend::Postgres, action, current_schema)?;
20+
let postgres_queries =
21+
build_action_queries(&DatabaseBackend::Postgres, action, current_schema)?;
2122
let mysql_queries = build_action_queries(&DatabaseBackend::MySql, action, current_schema)?;
22-
let sqlite_queries = build_action_queries(&DatabaseBackend::Sqlite, action, current_schema)?;
23+
let sqlite_queries =
24+
build_action_queries(&DatabaseBackend::Sqlite, action, current_schema)?;
2325
queries.push(PlanQueries {
2426
action: action.clone(),
2527
postgres: postgres_queries,
@@ -125,20 +127,40 @@ mod tests {
125127
assert_eq!(result.len(), 2);
126128

127129
// Test PostgreSQL output
128-
let sql1 = result[0].postgres.iter().map(|q| q.build(DatabaseBackend::Postgres)).collect::<Vec<_>>().join(";\n");
130+
let sql1 = result[0]
131+
.postgres
132+
.iter()
133+
.map(|q| q.build(DatabaseBackend::Postgres))
134+
.collect::<Vec<_>>()
135+
.join(";\n");
129136
assert!(sql1.contains("CREATE TABLE"));
130137
assert!(sql1.contains("\"users\""));
131138
assert!(sql1.contains("\"id\""));
132139

133-
let sql2 = result[1].postgres.iter().map(|q| q.build(DatabaseBackend::Postgres)).collect::<Vec<_>>().join(";\n");
140+
let sql2 = result[1]
141+
.postgres
142+
.iter()
143+
.map(|q| q.build(DatabaseBackend::Postgres))
144+
.collect::<Vec<_>>()
145+
.join(";\n");
134146
assert!(sql2.contains("DROP TABLE"));
135147
assert!(sql2.contains("\"posts\""));
136148

137149
// Test MySQL output
138-
let sql1_mysql = result[0].mysql.iter().map(|q| q.build(DatabaseBackend::MySql)).collect::<Vec<_>>().join(";\n");
150+
let sql1_mysql = result[0]
151+
.mysql
152+
.iter()
153+
.map(|q| q.build(DatabaseBackend::MySql))
154+
.collect::<Vec<_>>()
155+
.join(";\n");
139156
assert!(sql1_mysql.contains("`users`"));
140157

141-
let sql2_mysql = result[1].mysql.iter().map(|q| q.build(DatabaseBackend::MySql)).collect::<Vec<_>>().join(";\n");
158+
let sql2_mysql = result[1]
159+
.mysql
160+
.iter()
161+
.map(|q| q.build(DatabaseBackend::MySql))
162+
.collect::<Vec<_>>()
163+
.join(";\n");
142164
assert!(sql2_mysql.contains("`posts`"));
143165
}
144166
}

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

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use sea_query::{Alias, Table, TableAlterStatement};
1+
use sea_query::{Alias, Expr, Query, Table, TableAlterStatement};
22

33
use vespertide_core::ColumnDef;
44

5-
use crate::error::QueryError;
6-
use super::types::{BuiltQuery, DatabaseBackend, RawSql};
75
use super::helpers::build_sea_column_def;
6+
use super::types::{BuiltQuery, DatabaseBackend};
7+
use crate::error::QueryError;
88

99
fn build_add_column_alter_for_backend(
1010
backend: &DatabaseBackend,
@@ -34,43 +34,32 @@ pub fn build_add_column(
3434
let mut temp_col = column.clone();
3535
temp_col.nullable = true;
3636

37-
stmts.push(BuiltQuery::AlterTable(
38-
Box::new(build_add_column_alter_for_backend(backend, table, &temp_col)),
39-
));
37+
stmts.push(BuiltQuery::AlterTable(Box::new(
38+
build_add_column_alter_for_backend(backend, table, &temp_col),
39+
)));
4040

4141
// Backfill with provided value
4242
if let Some(fill) = fill_with {
43-
// PostgreSQL and SQLite use double quotes, MySQL uses backticks
44-
let pg_sql = format!("UPDATE \"{}\" SET \"{}\" = {}", table, column.name, fill);
45-
let mysql_sql = format!("UPDATE `{}` SET `{}` = {}", table, column.name, fill);
46-
stmts.push(BuiltQuery::Raw(RawSql::per_backend(
47-
pg_sql.clone(),
48-
mysql_sql,
49-
pg_sql,
50-
)));
43+
// Build UPDATE query using sea_query
44+
let update_stmt = Query::update()
45+
.table(Alias::new(table))
46+
.value(Alias::new(&column.name), Expr::cust(fill))
47+
.to_owned();
48+
stmts.push(BuiltQuery::Update(Box::new(update_stmt)));
5149
}
5250

53-
// Set NOT NULL - different syntax per backend
54-
let pg_sql = format!(
55-
"ALTER TABLE \"{}\" ALTER COLUMN \"{}\" SET NOT NULL",
56-
table, column.name
57-
);
58-
let mysql_sql = format!(
59-
"ALTER TABLE `{}` MODIFY COLUMN `{}` NOT NULL",
60-
table, column.name
61-
);
62-
// SQLite doesn't support ALTER COLUMN, would need table recreation
63-
let sqlite_sql = format!(
64-
"-- SQLite: ALTER TABLE \"{}\" requires table recreation to set NOT NULL on \"{}\"",
65-
table, column.name
66-
);
67-
stmts.push(BuiltQuery::Raw(RawSql::per_backend(
68-
pg_sql, mysql_sql, sqlite_sql,
69-
)));
51+
// Set NOT NULL using ALTER TABLE with modify_column
52+
// For SQLite, this will need table recreation, but we generate the SQL anyway
53+
let not_null_col = build_sea_column_def(backend, column);
54+
let alter_not_null = Table::alter()
55+
.table(Alias::new(table))
56+
.modify_column(not_null_col)
57+
.to_owned();
58+
stmts.push(BuiltQuery::AlterTable(Box::new(alter_not_null)));
7059
} else {
71-
stmts.push(BuiltQuery::AlterTable(
72-
Box::new(build_add_column_alter_for_backend(backend, table, column)),
73-
));
60+
stmts.push(BuiltQuery::AlterTable(Box::new(
61+
build_add_column_alter_for_backend(backend, table, column),
62+
)));
7463
}
7564

7665
Ok(stmts)
@@ -120,7 +109,12 @@ mod tests {
120109
#[case] expected: &[&str],
121110
) {
122111
let column = ColumnDef {
123-
name: if title.contains("age") { "age" } else { "nickname" }.into(),
112+
name: if title.contains("age") {
113+
"age"
114+
} else {
115+
"nickname"
116+
}
117+
.into(),
124118
r#type: if title.contains("age") {
125119
ColumnType::Simple(SimpleColumnType::Integer)
126120
} else {
@@ -134,7 +128,11 @@ mod tests {
134128
index: None,
135129
foreign_key: None,
136130
};
137-
let fill_with = if title.contains("backfill") { Some("0") } else { None };
131+
let fill_with = if title.contains("backfill") {
132+
Some("0")
133+
} else {
134+
None
135+
};
138136
let result = build_add_column(&backend, "users", &column, fill_with).unwrap();
139137
let sql = result[0].build(backend);
140138
for exp in expected {

0 commit comments

Comments
 (0)