From ba215c8ba91cfd776112e5f25220249fdb6d3159 Mon Sep 17 00:00:00 2001 From: pedrocarlo Date: Tue, 27 May 2025 22:01:20 -0300 Subject: [PATCH] test for create table + fixes --- .../src/to_sql_string/stmt/alter_table.rs | 4 +- .../src/to_sql_string/stmt/create_table.rs | 138 +++++++++++++++++- .../src/to_sql_string/stmt/mod.rs | 5 +- 3 files changed, 137 insertions(+), 10 deletions(-) diff --git a/vendored/sqlite3-parser/src/to_sql_string/stmt/alter_table.rs b/vendored/sqlite3-parser/src/to_sql_string/stmt/alter_table.rs index af5169800..98a464fa4 100644 --- a/vendored/sqlite3-parser/src/to_sql_string/stmt/alter_table.rs +++ b/vendored/sqlite3-parser/src/to_sql_string/stmt/alter_table.rs @@ -41,7 +41,7 @@ impl ToSqlString for ast::NamedColumnConstraint { fn to_sql_string(&self, context: &C) -> String { let mut ret = Vec::new(); if let Some(name) = &self.name { - ret.push(format!("CONSTRAINT {} ", name.0)); + ret.push(format!("CONSTRAINT {}", name.0)); } ret.push(self.constraint.to_sql_string(context)); ret.join(" ") @@ -104,7 +104,7 @@ impl ToSqlString for ast::ColumnConstraint { auto_increment, } => { format!( - "PRIMARY KEY {}{}{}", + "PRIMARY KEY{}{}{}", order.map_or("".to_string(), |order| format!( " {}", order.to_sql_string(context) diff --git a/vendored/sqlite3-parser/src/to_sql_string/stmt/create_table.rs b/vendored/sqlite3-parser/src/to_sql_string/stmt/create_table.rs index 8ef7d9570..75b0dd618 100644 --- a/vendored/sqlite3-parser/src/to_sql_string/stmt/create_table.rs +++ b/vendored/sqlite3-parser/src/to_sql_string/stmt/create_table.rs @@ -10,7 +10,7 @@ impl ToSqlString for ast::CreateTableBody { options, } => { format!( - "({}) {}{}", + "({}{}){}", columns .iter() .map(|(_, col)| col.to_sql_string(context)) @@ -19,7 +19,7 @@ impl ToSqlString for ast::CreateTableBody { constraints .as_ref() .map_or("".to_string(), |constraints| format!( - " {}", + ", {}", constraints .iter() .map(|constraint| constraint.to_sql_string(context)) @@ -36,7 +36,11 @@ impl ToSqlString for ast::CreateTableBody { impl ToSqlString for ast::NamedTableConstraint { fn to_sql_string(&self, context: &C) -> String { if let Some(name) = &self.name { - format!("{} {}", name.0, self.constraint.to_sql_string(context)) + format!( + "CONSTRAINT {} {}", + name.0, + self.constraint.to_sql_string(context) + ) } else { format!("{}", self.constraint.to_sql_string(context)) } @@ -52,7 +56,7 @@ impl ToSqlString for ast::TableConstraint { clause, deref_clause, } => format!( - "FOREIGN KEY ({}){}{}", + "FOREIGN KEY ({}) {}{}", columns .iter() .map(|col| col.to_sql_string(context)) @@ -106,10 +110,132 @@ impl ToSqlString for ast::TableOptions { if *self == Self::NONE { "" } else if *self == Self::STRICT { - "STRICT" + " STRICT" } else { - "WITHOUT ROWID" + " WITHOUT ROWID" } .to_string() } } + +#[cfg(test)] +mod tests { + use crate::to_sql_string_test; + + to_sql_string_test!( + test_create_table_simple, + "CREATE TABLE t (a INTEGER, b TEXT)" + ); + + to_sql_string_test!( + test_create_table_primary_key, + "CREATE TABLE t (id INTEGER PRIMARY KEY, name TEXT)" + ); + + to_sql_string_test!( + test_create_table_multi_primary_key, + "CREATE TABLE t (a INTEGER, b TEXT, PRIMARY KEY (a, b))" + ); + + to_sql_string_test!( + test_create_table_data_types, + "CREATE TABLE t (a INTEGER, b TEXT, c REAL, d BLOB, e NUMERIC)" + ); + + to_sql_string_test!( + test_create_table_foreign_key, + "CREATE TABLE t2 (id INTEGER PRIMARY KEY, t_id INTEGER, FOREIGN KEY (t_id) REFERENCES t(id))" + ); + + to_sql_string_test!( + test_create_table_foreign_key_cascade, + "CREATE TABLE t2 (id INTEGER PRIMARY KEY, t_id INTEGER, FOREIGN KEY (t_id) REFERENCES t(id) ON DELETE CASCADE)" + ); + + to_sql_string_test!( + test_create_table_unique, + "CREATE TABLE t (a INTEGER UNIQUE, b TEXT)" + ); + + to_sql_string_test!( + test_create_table_not_null, + "CREATE TABLE t (a INTEGER NOT NULL, b TEXT)" + ); + + to_sql_string_test!( + test_create_table_check, + "CREATE TABLE t (a INTEGER CHECK (a > 0), b TEXT)" + ); + + to_sql_string_test!( + test_create_table_default, + "CREATE TABLE t (a INTEGER DEFAULT 0, b TEXT)" + ); + + to_sql_string_test!( + test_create_table_multiple_constraints, + "CREATE TABLE t (a INTEGER NOT NULL UNIQUE, b TEXT DEFAULT 'default')" + ); + + to_sql_string_test!( + test_create_table_generated_column, + "CREATE TABLE t (a INTEGER, b INTEGER, c INTEGER AS (a + b))" + ); + + to_sql_string_test!( + test_create_table_generated_stored, + "CREATE TABLE t (a INTEGER, b INTEGER, c INTEGER AS (a + b) STORED)" + ); + + to_sql_string_test!( + test_create_table_generated_virtual, + "CREATE TABLE t (a INTEGER, b INTEGER, c INTEGER AS (a + b) VIRTUAL)" + ); + + to_sql_string_test!( + test_create_table_quoted_columns, + "CREATE TABLE t (\"select\" INTEGER, \"from\" TEXT)" + ); + + to_sql_string_test!( + test_create_table_quoted_table, + "CREATE TABLE \"my table\" (a INTEGER)" + ); + + to_sql_string_test!( + test_create_table_if_not_exists, + "CREATE TABLE IF NOT EXISTS t (a INTEGER)" + ); + + to_sql_string_test!(test_create_temp_table, "CREATE TEMP TABLE t (a INTEGER)"); + + to_sql_string_test!( + test_create_table_without_rowid, + "CREATE TABLE t (a INTEGER PRIMARY KEY, b TEXT) WITHOUT ROWID" + ); + + to_sql_string_test!( + test_create_table_named_primary_key, + "CREATE TABLE t (a INTEGER CONSTRAINT pk_a PRIMARY KEY)" + ); + + to_sql_string_test!( + test_create_table_named_unique, + "CREATE TABLE t (a INTEGER, CONSTRAINT unique_a UNIQUE (a))" + ); + + to_sql_string_test!( + test_create_table_named_foreign_key, + "CREATE TABLE t2 (id INTEGER, t_id INTEGER, CONSTRAINT fk_t FOREIGN KEY (t_id) REFERENCES t(id))" + ); + + to_sql_string_test!( + test_create_table_complex, + "CREATE TABLE t (id INTEGER PRIMARY KEY, a INTEGER NOT NULL, b TEXT DEFAULT 'default', c INTEGER AS (a * 2), CONSTRAINT unique_a UNIQUE (a))" + ); + + to_sql_string_test!( + test_create_table_multiple_foreign_keys, + "CREATE TABLE t3 (id INTEGER PRIMARY KEY, t1_id INTEGER, t2_id INTEGER, FOREIGN KEY (t1_id) REFERENCES t1(id), FOREIGN KEY (t2_id) REFERENCES t2(id))" + ); +} diff --git a/vendored/sqlite3-parser/src/to_sql_string/stmt/mod.rs b/vendored/sqlite3-parser/src/to_sql_string/stmt/mod.rs index 8efa00722..8f720d423 100644 --- a/vendored/sqlite3-parser/src/to_sql_string/stmt/mod.rs +++ b/vendored/sqlite3-parser/src/to_sql_string/stmt/mod.rs @@ -8,6 +8,7 @@ mod select; impl ToSqlString for ast::Stmt { fn to_sql_string(&self, context: &C) -> String { + dbg!(self); match self { Self::AlterTable(alter_table) => { let (name, body) = alter_table.as_ref(); @@ -103,7 +104,7 @@ mod tests { #[macro_export] /// Create a test that first parses then input, the converts the parsed ast back to a string and compares with original input macro_rules! to_sql_string_test { - ($test_name:ident, $input:literal) => { + ($test_name:ident, $input:expr) => { #[test] fn $test_name() { let context = crate::to_sql_string::stmt::tests::TestContext; @@ -118,7 +119,7 @@ mod tests { ); } }; - ($test_name:ident, $input:literal, $($attribute:meta),*) => { + ($test_name:ident, $input:expr, $($attribute:meta),*) => { #[test] $(#[$attribute])* fn $test_name() {