Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .changepacks/changepack_log_QfIyEI--ezqnzhvAC7E3G.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"changes":{"crates/vespertide-loader/Cargo.toml":"Patch","crates/vespertide-planner/Cargo.toml":"Patch","crates/vespertide-core/Cargo.toml":"Patch","crates/vespertide-config/Cargo.toml":"Patch","crates/vespertide-macro/Cargo.toml":"Patch","crates/vespertide-naming/Cargo.toml":"Patch","crates/vespertide-query/Cargo.toml":"Patch","crates/vespertide-exporter/Cargo.toml":"Patch","crates/vespertide/Cargo.toml":"Patch","crates/vespertide-cli/Cargo.toml":"Patch"},"note":"Fix auto increament","date":"2025-12-26T09:47:05.639827500Z"}
20 changes: 10 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

144 changes: 144 additions & 0 deletions crates/vespertide-query/src/sql/create_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,23 @@ pub(crate) fn build_create_table_for_backend(
.iter()
.any(|c| matches!(c, TableConstraint::PrimaryKey { .. }));

// Extract auto_increment columns from constraints
let auto_increment_columns: std::collections::HashSet<&str> = constraints
.iter()
.filter_map(|c| {
if let TableConstraint::PrimaryKey {
columns: pk_cols,
auto_increment: true,
} = c
{
Some(pk_cols.iter().map(|s| s.as_str()).collect::<Vec<_>>())
} else {
None
}
})
.flatten()
.collect();

// Add columns
for column in columns {
let mut col = build_sea_column_def_with_table(backend, table, column);
Expand All @@ -30,6 +47,11 @@ pub(crate) fn build_create_table_for_backend(
col.primary_key();
}

// Apply auto_increment if this column is in the auto_increment primary key
if auto_increment_columns.contains(column.name.as_str()) {
col.auto_increment();
}

// NOTE: We do NOT add inline unique constraints here.
// All unique constraints are handled as separate CREATE UNIQUE INDEX statements
// so they have proper names and can be dropped later.
Expand Down Expand Up @@ -502,4 +524,126 @@ mod tests {
assert_snapshot!(sql);
});
}

#[rstest]
#[case::auto_increment_postgres(DatabaseBackend::Postgres)]
#[case::auto_increment_mysql(DatabaseBackend::MySql)]
#[case::auto_increment_sqlite(DatabaseBackend::Sqlite)]
fn test_create_table_with_auto_increment_primary_key(#[case] backend: DatabaseBackend) {
// Test that auto_increment on primary key generates SERIAL/AUTO_INCREMENT/AUTOINCREMENT
let columns = vec![ColumnDef {
name: "id".into(),
r#type: ColumnType::Simple(SimpleColumnType::Integer),
nullable: false,
default: None,
comment: None,
primary_key: None,
unique: None,
index: None,
foreign_key: None,
}];
let constraints = vec![TableConstraint::PrimaryKey {
auto_increment: true,
columns: vec!["id".into()],
}];

let result = build_create_table(&backend, "users", &columns, &constraints);
assert!(result.is_ok());
let queries = result.unwrap();
let sql = queries
.iter()
.map(|q| q.build(backend))
.collect::<Vec<String>>()
.join(";\n");

// Verify auto_increment is applied correctly for each backend
match backend {
DatabaseBackend::Postgres => {
assert!(
sql.contains("SERIAL") || sql.contains("serial"),
"PostgreSQL should use SERIAL for auto_increment, got: {}",
sql
);
}
DatabaseBackend::MySql => {
assert!(
sql.contains("AUTO_INCREMENT") || sql.contains("auto_increment"),
"MySQL should use AUTO_INCREMENT for auto_increment, got: {}",
sql
);
}
DatabaseBackend::Sqlite => {
assert!(
sql.contains("AUTOINCREMENT") || sql.contains("autoincrement"),
"SQLite should use AUTOINCREMENT for auto_increment, got: {}",
sql
);
}
}

with_settings!({ snapshot_suffix => format!("create_table_with_auto_increment_{:?}", backend) }, {
assert_snapshot!(sql);
});
}

#[rstest]
#[case::inline_auto_increment_postgres(DatabaseBackend::Postgres)]
#[case::inline_auto_increment_mysql(DatabaseBackend::MySql)]
#[case::inline_auto_increment_sqlite(DatabaseBackend::Sqlite)]
fn test_create_table_with_inline_auto_increment_primary_key(#[case] backend: DatabaseBackend) {
// Test that inline primary_key with auto_increment generates correct SQL
use vespertide_core::schema::primary_key::{PrimaryKeyDef, PrimaryKeySyntax};

let columns = vec![ColumnDef {
name: "id".into(),
r#type: ColumnType::Simple(SimpleColumnType::Integer),
nullable: false,
default: None,
comment: None,
primary_key: Some(PrimaryKeySyntax::Object(PrimaryKeyDef {
auto_increment: true,
})),
unique: None,
index: None,
foreign_key: None,
}];

let result = build_create_table(&backend, "users", &columns, &[]);
assert!(result.is_ok());
let queries = result.unwrap();
let sql = queries
.iter()
.map(|q| q.build(backend))
.collect::<Vec<String>>()
.join(";\n");

// Verify auto_increment is applied correctly for each backend
match backend {
DatabaseBackend::Postgres => {
assert!(
sql.contains("SERIAL") || sql.contains("serial"),
"PostgreSQL should use SERIAL for auto_increment, got: {}",
sql
);
}
DatabaseBackend::MySql => {
assert!(
sql.contains("AUTO_INCREMENT") || sql.contains("auto_increment"),
"MySQL should use AUTO_INCREMENT for auto_increment, got: {}",
sql
);
}
DatabaseBackend::Sqlite => {
assert!(
sql.contains("AUTOINCREMENT") || sql.contains("autoincrement"),
"SQLite should use AUTOINCREMENT for auto_increment, got: {}",
sql
);
}
}

with_settings!({ snapshot_suffix => format!("create_table_with_inline_auto_increment_{:?}", backend) }, {
assert_snapshot!(sql);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
source: crates/vespertide-query/src/sql/create_table.rs
expression: sql
---
CREATE TABLE `users` ( `id` int NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`) )
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
source: crates/vespertide-query/src/sql/create_table.rs
expression: sql
---
CREATE TABLE "users" ( "id" serial NOT NULL, PRIMARY KEY ("id") )
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
source: crates/vespertide-query/src/sql/create_table.rs
expression: sql
---
CREATE TABLE "users" ( "id" integer NOT NULL AUTOINCREMENT, PRIMARY KEY ("id") )
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
source: crates/vespertide-query/src/sql/create_table.rs
expression: sql
---
CREATE TABLE `users` ( `id` int NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`) )
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
source: crates/vespertide-query/src/sql/create_table.rs
expression: sql
---
CREATE TABLE "users" ( "id" serial NOT NULL, PRIMARY KEY ("id") )
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
source: crates/vespertide-query/src/sql/create_table.rs
expression: sql
---
CREATE TABLE "users" ( "id" integer NOT NULL AUTOINCREMENT, PRIMARY KEY ("id") )