diff --git a/vendored/sqlite3-parser/src/to_sql_string/expr.rs b/vendored/sqlite3-parser/src/to_sql_string/expr.rs index 50bc6da69..2bf2b7749 100644 --- a/vendored/sqlite3-parser/src/to_sql_string/expr.rs +++ b/vendored/sqlite3-parser/src/to_sql_string/expr.rs @@ -246,7 +246,7 @@ impl ToSqlString for Expr { ret.push_str(&name1.0); } Expr::Raise(resolve_type, expr) => { - ret.push_str("RAISE ("); + ret.push_str("RAISE("); ret.push_str(&resolve_type.to_sql_string(context)); if let Some(expr) = expr { ret.push_str(", "); 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 98a464fa4..294a1a2a0 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 @@ -65,7 +65,7 @@ impl ToSqlString for ast::ColumnConstraint { clause, deref_clause, } => format!( - "FOREIGN KEY {}{}", + "{}{}", clause.to_sql_string(context), if let Some(deref) = deref_clause { deref.to_sql_string(context) @@ -214,71 +214,71 @@ mod tests { to_sql_string_test!( test_alter_table_rename, - "ALTER TABLE t RENAME TO new_table_name" + "ALTER TABLE t RENAME TO new_table_name;" ); to_sql_string_test!( test_alter_table_add_column, - "ALTER TABLE t ADD COLUMN c INTEGER" + "ALTER TABLE t ADD COLUMN c INTEGER;" ); to_sql_string_test!( test_alter_table_add_column_with_default, - "ALTER TABLE t ADD COLUMN c TEXT DEFAULT 'value'" + "ALTER TABLE t ADD COLUMN c TEXT DEFAULT 'value';" ); to_sql_string_test!( test_alter_table_add_column_not_null_default, - "ALTER TABLE t ADD COLUMN c REAL NOT NULL DEFAULT 0.0" + "ALTER TABLE t ADD COLUMN c REAL NOT NULL DEFAULT 0.0;" ); to_sql_string_test!( test_alter_table_add_column_unique, "ALTER TABLE t ADD COLUMN c TEXT UNIQUE", - ignore = "ParserError = Cannot add a UNIQUE column" + ignore = "ParserError = Cannot add a UNIQUE column;" ); to_sql_string_test!( test_alter_table_rename_column, - "ALTER TABLE t RENAME COLUMN old_name TO new_name" + "ALTER TABLE t RENAME COLUMN old_name TO new_name;" ); - to_sql_string_test!(test_alter_table_drop_column, "ALTER TABLE t DROP COLUMN c"); + to_sql_string_test!(test_alter_table_drop_column, "ALTER TABLE t DROP COLUMN c;"); to_sql_string_test!( test_alter_table_add_column_check, - "ALTER TABLE t ADD COLUMN c INTEGER CHECK (c > 0)" + "ALTER TABLE t ADD COLUMN c INTEGER CHECK (c > 0);" ); to_sql_string_test!( test_alter_table_add_column_foreign_key, - "ALTER TABLE t ADD COLUMN c INTEGER REFERENCES t2(id) ON DELETE CASCADE" + "ALTER TABLE t ADD COLUMN c INTEGER REFERENCES t2(id) ON DELETE CASCADE;" ); to_sql_string_test!( test_alter_table_add_column_collate, - "ALTER TABLE t ADD COLUMN c TEXT COLLATE NOCASE" + "ALTER TABLE t ADD COLUMN c TEXT COLLATE NOCASE;" ); to_sql_string_test!( test_alter_table_add_column_primary_key, - "ALTER TABLE t ADD COLUMN c INTEGER PRIMARY KEY", + "ALTER TABLE t ADD COLUMN c INTEGER PRIMARY KEY;", ignore = "ParserError = Cannot add a PRIMARY KEY column" ); to_sql_string_test!( test_alter_table_add_column_primary_key_autoincrement, - "ALTER TABLE t ADD COLUMN c INTEGER PRIMARY KEY AUTOINCREMENT", + "ALTER TABLE t ADD COLUMN c INTEGER PRIMARY KEY AUTOINCREMENT;", ignore = "ParserError = Cannot add a PRIMARY KEY column" ); to_sql_string_test!( test_alter_table_add_generated_column, - "ALTER TABLE t ADD COLUMN c_generated AS (a + b) STORED" + "ALTER TABLE t ADD COLUMN c_generated AS (a + b) STORED;" ); to_sql_string_test!( test_alter_table_add_column_schema, - "ALTER TABLE schema_name.t ADD COLUMN c INTEGER" + "ALTER TABLE schema_name.t ADD COLUMN c INTEGER;" ); } 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 75b0dd618..b0853a3f9 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 @@ -124,118 +124,118 @@ mod tests { to_sql_string_test!( test_create_table_simple, - "CREATE TABLE t (a INTEGER, b TEXT)" + "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)" + "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))" + "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)" + "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))" + "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)" + "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)" + "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)" + "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)" + "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)" + "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')" + "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))" + "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)" + "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)" + "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)" + "CREATE TABLE t (\"select\" INTEGER, \"from\" TEXT);" ); to_sql_string_test!( test_create_table_quoted_table, - "CREATE TABLE \"my table\" (a INTEGER)" + "CREATE TABLE \"my table\" (a INTEGER);" ); to_sql_string_test!( test_create_table_if_not_exists, - "CREATE TABLE IF NOT EXISTS t (a INTEGER)" + "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_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" + "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)" + "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))" + "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))" + "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))" + "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))" + "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/create_trigger.rs b/vendored/sqlite3-parser/src/to_sql_string/stmt/create_trigger.rs index e524678da..88c244976 100644 --- a/vendored/sqlite3-parser/src/to_sql_string/stmt/create_trigger.rs +++ b/vendored/sqlite3-parser/src/to_sql_string/stmt/create_trigger.rs @@ -3,7 +3,7 @@ use crate::{ast, to_sql_string::ToSqlString}; impl ToSqlString for ast::CreateTrigger { fn to_sql_string(&self, context: &C) -> String { format!( - "CREATE{} TRIGGER {}{} {}{} ON {} {}{} BEGIN {} END", + "CREATE{} TRIGGER {}{}{} {} ON {}{}{} BEGIN {} END;", self.temporary.then_some(" TEMP").unwrap_or(""), self.if_not_exists.then_some("IF NOT EXISTS ").unwrap_or(""), self.trigger_name.to_sql_string(context), @@ -13,15 +13,15 @@ impl ToSqlString for ast::CreateTrigger { )), self.event.to_sql_string(context), self.tbl_name.to_sql_string(context), - self.for_each_row.then_some("FOR EACH ROW ").unwrap_or(""), + self.for_each_row.then_some(" FOR EACH ROW").unwrap_or(""), self.when_clause .as_ref() - .map_or("".to_string(), |expr| expr.to_string()), + .map_or("".to_string(), |expr| format!(" WHEN {}", expr.to_string())), self.commands .iter() - .map(|command| command.to_sql_string(context)) + .map(|command| format!("{};", command.to_sql_string(context))) .collect::>() - .join("; ") + .join(" ") ) } } @@ -234,3 +234,63 @@ impl ToSqlString for ast::TriggerCmdUpdate { ) } } + +#[cfg(test)] +mod tests { + use crate::to_sql_string_test; + + to_sql_string_test!( + test_log_employee_insert, + "CREATE TRIGGER log_employee_insert + AFTER INSERT ON employees + FOR EACH ROW + BEGIN + INSERT INTO employee_log (action, employee_id, timestamp) + VALUES ('INSERT', NEW.id, CURRENT_TIMESTAMP); + END;" + ); + + to_sql_string_test!( + test_log_salary_update, + "CREATE TRIGGER log_salary_update + AFTER UPDATE OF salary ON employees + FOR EACH ROW + BEGIN + INSERT INTO employee_log (action, employee_id, old_value, new_value, timestamp) + VALUES ('UPDATE', OLD.id, OLD.salary, NEW.salary, CURRENT_TIMESTAMP); + END;" + ); + + to_sql_string_test!( + test_log_employee_delete, + "CREATE TRIGGER log_employee_delete + AFTER DELETE ON employees + FOR EACH ROW + BEGIN + INSERT INTO employee_log (action, employee_id, timestamp) + VALUES ('DELETE', OLD.id, CURRENT_TIMESTAMP); + END;" + ); + + to_sql_string_test!( + test_check_salary_insert, + "CREATE TRIGGER check_salary_insert + BEFORE INSERT ON employees + FOR EACH ROW + WHEN NEW.salary < 0 + BEGIN + SELECT RAISE(FAIL, 'Salary cannot be negative'); + END;" + ); + + to_sql_string_test!( + test_insert_employee_dept, + "CREATE TRIGGER insert_employee_dept + INSTEAD OF INSERT ON employee_dept + FOR EACH ROW + BEGIN + INSERT INTO departments (name) SELECT NEW.department WHERE NOT EXISTS (SELECT 1 FROM departments WHERE name = NEW.department); + INSERT INTO employees (name, department_id) VALUES (NEW.name, (SELECT id FROM departments WHERE name = NEW.department)); + END;" + ); +} 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 f09e45116..9006129c6 100644 --- a/vendored/sqlite3-parser/src/to_sql_string/stmt/mod.rs +++ b/vendored/sqlite3-parser/src/to_sql_string/stmt/mod.rs @@ -9,21 +9,20 @@ 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(); format!( - "ALTER TABLE {} {}", + "ALTER TABLE {} {};", name.to_sql_string(context), body.to_sql_string(context) ) } Self::Analyze(name) => { if let Some(name) = name { - format!("ANALYZE {}", name.to_sql_string(context)) + format!("ANALYZE {};", name.to_sql_string(context)) } else { - format!("ANALYZE") + format!("ANALYZE;") } } Self::Attach { @@ -33,7 +32,7 @@ impl ToSqlString for ast::Stmt { } => { // TODO: what is `key` in the attach syntax? format!( - "ATTACH {} AS {}", + "ATTACH {} AS {};", expr.to_sql_string(context), db_name.to_sql_string(context) ) @@ -46,11 +45,11 @@ impl ToSqlString for ast::Stmt { ast::TransactionType::Exclusive => " EXCLUSIVE", ast::TransactionType::Immediate => " IMMEDIATE", }); - format!("BEGIN{}", t_type) + format!("BEGIN{};", t_type) } // END or COMMIT are equivalent here, so just defaulting to COMMIT // TODO: again there are no names in the docs - Self::Commit(_name) => "COMMIT".to_string(), + Self::Commit(_name) => "COMMIT;".to_string(), Self::CreateIndex { unique, if_not_exists, @@ -60,7 +59,7 @@ impl ToSqlString for ast::Stmt { where_clause, } => { format!( - "CREATE {}INDEX {}{} ON {} ({}){}", + "CREATE {}INDEX {}{} ON {} ({}){};", unique.then_some("UNIQUE ").unwrap_or(""), if_not_exists.then_some("IF NOT EXISTS ").unwrap_or(""), idx_name.to_sql_string(context), @@ -85,7 +84,7 @@ impl ToSqlString for ast::Stmt { body, } => { format!( - "CREATE{} TABLE {}{} {}", + "CREATE{} TABLE {}{} {};", temporary.then_some(" TEMP").unwrap_or(""), if_not_exists.then_some("IF NOT EXISTS ").unwrap_or(""), tbl_name.to_sql_string(context), @@ -93,7 +92,7 @@ impl ToSqlString for ast::Stmt { ) } Self::CreateTrigger(trigger) => trigger.to_sql_string(context), - Self::Select(select) => select.to_sql_string(context), + Self::Select(select) => format!("{};", select.to_sql_string(context)), _ => todo!(), } } @@ -110,7 +109,7 @@ mod tests { #[test] fn $test_name() { let context = crate::to_sql_string::stmt::tests::TestContext; - let input: &str = $input; + let input = $input.split_whitespace().collect::>().join(" "); let mut parser = crate::lexer::sql::Parser::new(input.as_bytes()); let cmd = fallible_iterator::FallibleIterator::next(&mut parser) .unwrap() @@ -126,7 +125,7 @@ mod tests { $(#[$attribute])* fn $test_name() { let context = crate::to_sql_string::stmt::tests::TestContext; - let input: &str = $input; + let input = $input.split_whitespace().collect::>().join(" "); let mut parser = crate::lexer::sql::Parser::new(input.as_bytes()); let cmd = fallible_iterator::FallibleIterator::next(&mut parser) .unwrap() @@ -153,71 +152,71 @@ mod tests { } } - to_sql_string_test!(test_analyze, "ANALYZE"); + to_sql_string_test!(test_analyze, "ANALYZE;"); to_sql_string_test!( test_analyze_table, - "ANALYZE table", + "ANALYZE table;", ignore = "parser can't parse table name" ); to_sql_string_test!( test_analyze_schema_table, - "ANALYZE schema.table", + "ANALYZE schema.table;", ignore = "parser can't parse schema.table name" ); - to_sql_string_test!(test_attach, "ATTACH './test.db' AS test_db"); + to_sql_string_test!(test_attach, "ATTACH './test.db' AS test_db;"); - to_sql_string_test!(test_transaction, "BEGIN"); + to_sql_string_test!(test_transaction, "BEGIN;"); - to_sql_string_test!(test_transaction_deferred, "BEGIN DEFERRED"); + to_sql_string_test!(test_transaction_deferred, "BEGIN DEFERRED;"); - to_sql_string_test!(test_transaction_immediate, "BEGIN IMMEDIATE"); + to_sql_string_test!(test_transaction_immediate, "BEGIN IMMEDIATE;"); - to_sql_string_test!(test_transaction_exclusive, "BEGIN EXCLUSIVE"); + to_sql_string_test!(test_transaction_exclusive, "BEGIN EXCLUSIVE;"); - to_sql_string_test!(test_commit, "COMMIT"); + to_sql_string_test!(test_commit, "COMMIT;"); // Test a simple index on a single column to_sql_string_test!( test_create_index_simple, - "CREATE INDEX idx_name ON employees (last_name)" + "CREATE INDEX idx_name ON employees (last_name);" ); // Test a unique index to enforce uniqueness on a column to_sql_string_test!( test_create_unique_index, - "CREATE UNIQUE INDEX idx_unique_email ON users (email)" + "CREATE UNIQUE INDEX idx_unique_email ON users (email);" ); // Test a multi-column index to_sql_string_test!( test_create_index_multi_column, - "CREATE INDEX idx_name_salary ON employees (last_name, salary)" + "CREATE INDEX idx_name_salary ON employees (last_name, salary);" ); // Test a partial index with a WHERE clause to_sql_string_test!( test_create_partial_index, - "CREATE INDEX idx_active_users ON users (username) WHERE active = true" + "CREATE INDEX idx_active_users ON users (username) WHERE active = true;" ); // Test an index on an expression to_sql_string_test!( test_create_index_on_expression, - "CREATE INDEX idx_upper_name ON employees (UPPER(last_name))" + "CREATE INDEX idx_upper_name ON employees (UPPER(last_name));" ); // Test an index with descending order to_sql_string_test!( test_create_index_descending, - "CREATE INDEX idx_salary_desc ON employees (salary DESC)" + "CREATE INDEX idx_salary_desc ON employees (salary DESC);" ); // Test an index with mixed ascending and descending orders on multiple columns to_sql_string_test!( test_create_index_mixed_order, - "CREATE INDEX idx_name_asc_salary_desc ON employees (last_name ASC, salary DESC)" + "CREATE INDEX idx_name_asc_salary_desc ON employees (last_name ASC, salary DESC);" ); } diff --git a/vendored/sqlite3-parser/src/to_sql_string/stmt/select.rs b/vendored/sqlite3-parser/src/to_sql_string/stmt/select.rs index 0d162b66d..c31012e2d 100644 --- a/vendored/sqlite3-parser/src/to_sql_string/stmt/select.rs +++ b/vendored/sqlite3-parser/src/to_sql_string/stmt/select.rs @@ -5,7 +5,6 @@ use crate::{ impl ToSqlString for ast::Select { fn to_sql_string(&self, context: &C) -> String { - dbg!(&self); let mut ret = Vec::new(); if let Some(with) = &self.with { let joined_expr = with @@ -78,12 +77,12 @@ impl ToSqlString for ast::OneSelect { .iter() .map(|e| e.to_sql_string(context)) .collect::>() - .join(","); + .join(", "); format!("({})", joined_value) }) .collect::>() .join(", "); - joined_values + format!("VALUES {}", joined_values) } } } @@ -523,119 +522,125 @@ impl ToSqlString for ast::FrameExclude { mod tests { use crate::to_sql_string_test; - to_sql_string_test!(test_select_basic, "SELECT 1"); + to_sql_string_test!(test_select_basic, "SELECT 1;"); - to_sql_string_test!(test_select_table, "SELECT * FROM t"); + to_sql_string_test!(test_select_table, "SELECT * FROM t;"); - to_sql_string_test!(test_select_table_2, "SELECT a FROM t"); + to_sql_string_test!(test_select_table_2, "SELECT a FROM t;"); - to_sql_string_test!(test_select_multiple_columns, "SELECT a, b, c FROM t"); + to_sql_string_test!(test_select_multiple_columns, "SELECT a, b, c FROM t;"); - to_sql_string_test!(test_select_with_alias, "SELECT a AS col1 FROM t"); + to_sql_string_test!(test_select_with_alias, "SELECT a AS col1 FROM t;"); - to_sql_string_test!(test_select_with_table_alias, "SELECT t1.a FROM t AS t1"); + to_sql_string_test!(test_select_with_table_alias, "SELECT t1.a FROM t AS t1;"); - to_sql_string_test!(test_select_with_where, "SELECT a FROM t WHERE b = 1"); + to_sql_string_test!(test_select_with_where, "SELECT a FROM t WHERE b = 1;"); to_sql_string_test!( test_select_with_multiple_conditions, - "SELECT a FROM t WHERE b = 1 AND c > 2" + "SELECT a FROM t WHERE b = 1 AND c > 2;" ); - to_sql_string_test!(test_select_with_order_by, "SELECT a FROM t ORDER BY a DESC"); + to_sql_string_test!( + test_select_with_order_by, + "SELECT a FROM t ORDER BY a DESC;" + ); - to_sql_string_test!(test_select_with_limit, "SELECT a FROM t LIMIT 10"); + to_sql_string_test!(test_select_with_limit, "SELECT a FROM t LIMIT 10;"); - to_sql_string_test!(test_select_with_offset, "SELECT a FROM t LIMIT 10 OFFSET 5"); + to_sql_string_test!( + test_select_with_offset, + "SELECT a FROM t LIMIT 10 OFFSET 5;" + ); to_sql_string_test!( test_select_with_join, - "SELECT a FROM t JOIN t2 ON t.b = t2.b" + "SELECT a FROM t JOIN t2 ON t.b = t2.b;" ); to_sql_string_test!( test_select_with_group_by, - "SELECT a, COUNT(*) FROM t GROUP BY a" + "SELECT a, COUNT(*) FROM t GROUP BY a;" ); to_sql_string_test!( test_select_with_having, - "SELECT a, COUNT(*) FROM t GROUP BY a HAVING COUNT(*) > 1" + "SELECT a, COUNT(*) FROM t GROUP BY a HAVING COUNT(*) > 1;" ); - to_sql_string_test!(test_select_with_distinct, "SELECT DISTINCT a FROM t"); + to_sql_string_test!(test_select_with_distinct, "SELECT DISTINCT a FROM t;"); - to_sql_string_test!(test_select_with_function, "SELECT COUNT(a) FROM t"); + to_sql_string_test!(test_select_with_function, "SELECT COUNT(a) FROM t;"); to_sql_string_test!( test_select_with_subquery, - "SELECT a FROM (SELECT b FROM t) AS sub" + "SELECT a FROM (SELECT b FROM t) AS sub;" ); to_sql_string_test!( test_select_nested_subquery, - "SELECT a FROM (SELECT b FROM (SELECT c FROM t WHERE c > 10) AS sub1 WHERE b < 20) AS sub2" + "SELECT a FROM (SELECT b FROM (SELECT c FROM t WHERE c > 10) AS sub1 WHERE b < 20) AS sub2;" ); to_sql_string_test!( test_select_multiple_joins, - "SELECT t1.a, t2.b, t3.c FROM t1 JOIN t2 ON t1.id = t2.id LEFT JOIN t3 ON t2.id = t3.id" + "SELECT t1.a, t2.b, t3.c FROM t1 JOIN t2 ON t1.id = t2.id LEFT JOIN t3 ON t2.id = t3.id;" ); to_sql_string_test!( test_select_with_cte, - "WITH cte AS (SELECT a FROM t WHERE b = 1) SELECT a FROM cte WHERE a > 10" + "WITH cte AS (SELECT a FROM t WHERE b = 1) SELECT a FROM cte WHERE a > 10;" ); to_sql_string_test!( test_select_with_window_function, - "SELECT a, ROW_NUMBER() OVER (PARTITION BY b ORDER BY c DESC) AS rn FROM t" + "SELECT a, ROW_NUMBER() OVER (PARTITION BY b ORDER BY c DESC) AS rn FROM t;" ); to_sql_string_test!( test_select_with_complex_where, - "SELECT a FROM t WHERE b IN (1, 2, 3) AND c BETWEEN 10 AND 20 OR d IS NULL" + "SELECT a FROM t WHERE b IN (1, 2, 3) AND c BETWEEN 10 AND 20 OR d IS NULL;" ); to_sql_string_test!( test_select_with_case, - "SELECT CASE WHEN a > 0 THEN 'positive' ELSE 'non-positive' END AS result FROM t" + "SELECT CASE WHEN a > 0 THEN 'positive' ELSE 'non-positive' END AS result FROM t;" ); - to_sql_string_test!(test_select_with_aggregate_and_join, "SELECT t1.a, COUNT(t2.b) FROM t1 LEFT JOIN t2 ON t1.id = t2.id GROUP BY t1.a HAVING COUNT(t2.b) > 5"); + to_sql_string_test!(test_select_with_aggregate_and_join, "SELECT t1.a, COUNT(t2.b) FROM t1 LEFT JOIN t2 ON t1.id = t2.id GROUP BY t1.a HAVING COUNT(t2.b) > 5;"); - to_sql_string_test!(test_select_with_multiple_ctes, "WITH cte1 AS (SELECT a FROM t WHERE b = 1), cte2 AS (SELECT c FROM t2 WHERE d = 2) SELECT cte1.a, cte2.c FROM cte1 JOIN cte2 ON cte1.a = cte2.c"); + to_sql_string_test!(test_select_with_multiple_ctes, "WITH cte1 AS (SELECT a FROM t WHERE b = 1), cte2 AS (SELECT c FROM t2 WHERE d = 2) SELECT cte1.a, cte2.c FROM cte1 JOIN cte2 ON cte1.a = cte2.c;"); to_sql_string_test!( test_select_with_union, - "SELECT a FROM t1 UNION SELECT b FROM t2" + "SELECT a FROM t1 UNION SELECT b FROM t2;" ); to_sql_string_test!( test_select_with_union_all, - "SELECT a FROM t1 UNION ALL SELECT b FROM t2" + "SELECT a FROM t1 UNION ALL SELECT b FROM t2;" ); to_sql_string_test!( test_select_with_exists, - "SELECT a FROM t WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.b = t.a)" + "SELECT a FROM t WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.b = t.a);" ); to_sql_string_test!( test_select_with_correlated_subquery, - "SELECT a, (SELECT COUNT(*) FROM t2 WHERE t2.b = t.a) AS count_b FROM t" + "SELECT a, (SELECT COUNT(*) FROM t2 WHERE t2.b = t.a) AS count_b FROM t;" ); to_sql_string_test!( test_select_with_complex_order_by, - "SELECT a, b FROM t ORDER BY CASE WHEN a IS NULL THEN 1 ELSE 0 END, b ASC, c DESC" + "SELECT a, b FROM t ORDER BY CASE WHEN a IS NULL THEN 1 ELSE 0 END, b ASC, c DESC;" ); to_sql_string_test!( test_select_with_full_outer_join, - "SELECT t1.a, t2.b FROM t1 FULL OUTER JOIN t2 ON t1.id = t2.id", + "SELECT t1.a, t2.b FROM t1 FULL OUTER JOIN t2 ON t1.id = t2.id;", ignore = "OUTER JOIN is incorrectly parsed in parser" ); - to_sql_string_test!(test_select_with_aggregate_window, "SELECT a, SUM(b) OVER (PARTITION BY c ORDER BY d ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS running_sum FROM t"); + to_sql_string_test!(test_select_with_aggregate_window, "SELECT a, SUM(b) OVER (PARTITION BY c ORDER BY d ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS running_sum FROM t;"); }