From 3a92381b6f76b6e42b2869ee61a31ead4bcb939e Mon Sep 17 00:00:00 2001 From: Belchior Oliveira Date: Wed, 16 Oct 2024 11:43:30 -0300 Subject: [PATCH 01/14] fix accumulator methods of alter table --- src/alter_table/alter_table_internal.rs | 1 + src/behavior.rs | 33 ++++++++++--- tests/command_alter_table_spec.rs | 65 +++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 8 deletions(-) diff --git a/src/alter_table/alter_table_internal.rs b/src/alter_table/alter_table_internal.rs index f64675c..4ae335d 100644 --- a/src/alter_table/alter_table_internal.rs +++ b/src/alter_table/alter_table_internal.rs @@ -38,6 +38,7 @@ impl AlterTable { let actions = self ._ordered_actions .iter() + .filter(|item| item.1.is_empty() == false) .map(|item| { let AlterTableActionItem(action, content) = item; match action { diff --git a/src/behavior.rs b/src/behavior.rs index 23b205f..c8a2d53 100644 --- a/src/behavior.rs +++ b/src/behavior.rs @@ -26,7 +26,12 @@ pub(crate) trait ConcatSqlStandard { ) -> String { let fmt::Formatter { comma, lb, space, .. } = fmts; let sql = if items.is_empty() == false { - let tables = items.join(comma); + let tables = items + .iter() + .filter(|item| item.is_empty() == false) + .map(|item| item.as_str()) + .collect::>() + .join(comma); format!("FROM{space}{tables}{space}{lb}") } else { "".to_string() @@ -40,7 +45,7 @@ pub(crate) trait ConcatSqlStandard { return query; } let fmt::Formatter { lb, space, .. } = fmts; - let raw_sql = items.join(space); + let raw_sql = items.join(space).trim_start().to_string(); format!("{query}{raw_sql}{space}{lb}") } @@ -56,14 +61,17 @@ pub(crate) trait ConcatSqlStandard { ) -> String { let fmt::Formatter { lb, space, indent, .. } = fmts; let sql = if items.is_empty() == false { - let ((_, cond), tail) = items.split_first().unwrap(); - - let first_condition = format!("{lb}{indent}{cond}"); + let filtered_items = items + .iter() + .filter(|item| item.1.is_empty() == false) + .collect::>(); + let ((_, cond), tail) = filtered_items.split_first().unwrap(); + let first_condition = format!("{indent}{cond}"); let conditions = tail.iter().fold(first_condition, |acc, (log_op, condition)| { format!("{acc}{space}{lb}{indent}{log_op}{space}{condition}") }); - format!("WHERE{space}{conditions}{space}{lb}") + format!("WHERE{lb}{space}{conditions}{space}{lb}") } else { "".to_string() }; @@ -85,7 +93,12 @@ pub(crate) trait ConcatCommon { ) -> String { let fmt::Formatter { lb, space, comma, .. } = fmts; let sql = if items.is_empty() == false { - let output_names = items.join(comma); + let output_names = items + .iter() + .filter(|item| item.is_empty() == false) + .map(|item| item.as_str()) + .collect::>() + .join(comma); format!("RETURNING{space}{output_names}{space}{lb}") } else { "".to_string() @@ -123,7 +136,11 @@ pub(crate) trait ConcatCommon { }; let query_string = query.concat(&inner_fmts); - format!("{acc}{name}{space}AS{space}({lb}{indent}{query_string}{lb}){comma}{lb}") + if query_string.is_empty() == false { + format!("{acc}{name}{space}AS{space}({lb}{indent}{query_string}{lb}){comma}{lb}") + } else { + acc + } }); let with = &with[..with.len() - comma.len() - lb.len()]; diff --git a/tests/command_alter_table_spec.rs b/tests/command_alter_table_spec.rs index 51303d3..3bffbd2 100644 --- a/tests/command_alter_table_spec.rs +++ b/tests/command_alter_table_spec.rs @@ -209,6 +209,19 @@ mod builder_methods { assert_eq!(expected_query, query); } + #[test] + fn method_raw_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::AlterTable::new() + .raw("") + .raw("add column id serial") + .raw("") + .as_string(); + + let expected_query = "add column id serial"; + + assert_eq!(expected_query, query); + } + #[test] fn method_raw_should_be_the_first_to_be_concatenated() { let query = sql::AlterTable::new() @@ -285,6 +298,19 @@ mod method_add { assert_eq!(expected_query, query); } + #[test] + fn method_add_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::AlterTable::new() + .add("") + .add("COLUMN created_at timestamp not null") + .add("") + .as_string(); + + let expected_query = "ADD COLUMN created_at timestamp not null"; + + assert_eq!(expected_query, query); + } + #[test] fn method_add_should_preserve_the_order_of_the_actions_on_consecutive_calls() { let query = sql::AlterTable::new() @@ -350,6 +376,19 @@ mod method_alter { assert_eq!(expected_query, query); } + #[test] + fn method_alter_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::AlterTable::new() + .alter("") + .alter("COLUMN created_at SET DEFAULT now()") + .alter("") + .as_string(); + + let expected_query = "ALTER COLUMN created_at SET DEFAULT now()"; + + assert_eq!(expected_query, query); + } + #[test] fn method_alter_should_preserve_the_order_of_the_actions_on_consecutive_calls() { let query = sql::AlterTable::new() @@ -447,6 +486,19 @@ mod method_drop { assert_eq!(expected_query, query); } + #[test] + fn method_drop_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::AlterTable::new() + .drop("") + .drop("COLUMN login") + .drop("") + .as_string(); + + let expected_query = "DROP COLUMN login"; + + assert_eq!(expected_query, query); + } + #[test] fn method_drop_should_preserve_the_order_of_the_actions_on_consecutive_calls() { let query = sql::AlterTable::new() @@ -510,6 +562,19 @@ mod method_rename { assert_eq!(expected_query, query); } + #[test] + fn method_rename_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::AlterTable::new() + .rename("") + .rename("COLUMN created TO created_at") + .rename("") + .as_string(); + + let expected_query = "RENAME COLUMN created TO created_at"; + + assert_eq!(expected_query, query); + } + #[test] fn method_rename_should_preserve_the_order_of_the_actions_on_consecutive_calls() { let query = sql::AlterTable::new() From 3ebd5ae0b03479f36b722a91a555a060fd8c800e Mon Sep 17 00:00:00 2001 From: Belchior Oliveira Date: Wed, 16 Oct 2024 14:24:30 -0300 Subject: [PATCH 02/14] fix accumulator methods of create table --- src/create_table/create_table_internal.rs | 3 ++ tests/command_create_table_spec.rs | 53 +++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/src/create_table/create_table_internal.rs b/src/create_table/create_table_internal.rs index d4c3ce1..9710e0b 100644 --- a/src/create_table/create_table_internal.rs +++ b/src/create_table/create_table_internal.rs @@ -32,6 +32,7 @@ impl CreateTable { let columns = self ._column .iter() + .filter(|column| column.is_empty() == false) .map(|column| format!("{lb}{indent}{column}")) .collect::>() .join(comma) @@ -60,6 +61,7 @@ impl CreateTable { let constraints = self ._constraint .iter() + .filter(|constraint| constraint.is_empty() == false) .map(|constraint| format!("{lb}{indent}CONSTRAINT{space}{constraint}")) .collect::>() .join(comma); @@ -80,6 +82,7 @@ impl CreateTable { let foreign_keys = self ._foreign_key .iter() + .filter(|foreign_key| foreign_key.is_empty() == false) .map(|foreign_key| format!("{lb}{indent}FOREIGN KEY{foreign_key}")) .collect::>() .join(comma); diff --git a/tests/command_create_table_spec.rs b/tests/command_create_table_spec.rs index ef47b4e..e959ae6 100644 --- a/tests/command_create_table_spec.rs +++ b/tests/command_create_table_spec.rs @@ -214,6 +214,20 @@ mod builder_methods { assert_eq!(expected_query, query); } + #[test] + fn method_raw_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::CreateTable::new() + .raw("") + .raw("create table local temp users (") + .raw("id serial)") + .raw("") + .as_string(); + + let expected_query = "create table local temp users ( id serial)"; + + assert_eq!(expected_query, query); + } + #[test] fn method_raw_should_be_the_first_to_be_concatenated() { let query = sql::CreateTable::new() @@ -283,6 +297,19 @@ mod method_column { assert_eq!(expected_query, query); } + #[test] + fn method_column_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::CreateTable::new() + .column("") + .column("login varchar(40) not null") + .column("") + .as_string(); + + let expected_query = "(login varchar(40) not null)"; + + assert_eq!(expected_query, query); + } + #[test] fn method_column_should_not_accumulate_parameters_with_the_same_content() { let query = sql::CreateTable::new() @@ -359,6 +386,19 @@ mod method_constraint { assert_eq!(expected_query, query); } + #[test] + fn method_constraint_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::CreateTable::new() + .constraint("") + .constraint("login users_login_key unique(login)") + .constraint("") + .as_string(); + + let expected_query = "(CONSTRAINT login users_login_key unique(login))"; + + assert_eq!(expected_query, query); + } + #[test] fn method_constraint_should_not_accumulate_parameters_with_the_same_content() { let query = sql::CreateTable::new() @@ -503,6 +543,19 @@ mod method_foreign_key { assert_eq!(expected_query, query); } + #[test] + fn method_foreign_key_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::CreateTable::new() + .foreign_key("") + .foreign_key("(users_login) REFERENCES users(login)") + .foreign_key("") + .as_string(); + + let expected_query = "(FOREIGN KEY(users_login) REFERENCES users(login))"; + + assert_eq!(expected_query, query); + } + #[test] fn method_foreign_key_should_not_accumulate_constraints_with_the_same_content() { let query = sql::CreateTable::new() From b5ffa8482218b15fdf8dba57ef52f6b02865a950 Mon Sep 17 00:00:00 2001 From: Belchior Oliveira Date: Wed, 16 Oct 2024 14:28:48 -0300 Subject: [PATCH 03/14] fix accumulator methods of drop index --- src/drop_index/drop_index_internal.rs | 10 +++++-- tests/command_drop_index_spec.rs | 40 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/drop_index/drop_index_internal.rs b/src/drop_index/drop_index_internal.rs index 7a46537..70f22f1 100644 --- a/src/drop_index/drop_index_internal.rs +++ b/src/drop_index/drop_index_internal.rs @@ -10,7 +10,7 @@ impl DropIndex { fn concat_drop_index(&self, query: String, fmts: &fmt::Formatter) -> String { let fmt::Formatter { comma, lb, space, .. } = fmts; - let sql = if self._drop_index.len() != 0 { + let sql = if self._drop_index.is_empty() == false { let if_exists = if self._if_exists { format!("IF EXISTS{space}") } else { @@ -18,7 +18,13 @@ impl DropIndex { }; let index_names = if cfg!(any(feature = "postgresql")) { - self._drop_index.join(comma) + self + ._drop_index + .iter() + .filter(|item| item.is_empty() == false) + .map(|item| item.as_str()) + .collect::>() + .join(comma) } else { self._drop_index.last().unwrap().to_string() }; diff --git a/tests/command_drop_index_spec.rs b/tests/command_drop_index_spec.rs index bb75fed..da37722 100644 --- a/tests/command_drop_index_spec.rs +++ b/tests/command_drop_index_spec.rs @@ -177,6 +177,20 @@ mod builder_methods { assert_eq!(expected_query, query); } + #[test] + fn method_raw_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::DropIndex::new() + .raw("") + .raw("drop index") + .raw("users_name_idx") + .raw("") + .as_string(); + + let expected_query = "drop index users_name_idx"; + + assert_eq!(expected_query, query); + } + #[test] fn method_raw_should_be_the_first_to_be_concatenated() { let query = sql::DropIndex::new() @@ -383,6 +397,19 @@ mod postgres_feature_flag { assert_eq!(expected_query, query); } + #[test] + fn method_drop_index_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::DropIndex::new() + .drop_index("") + .drop_index("series") + .drop_index("") + .as_string(); + + let expected_query = "DROP INDEX series"; + + assert_eq!(expected_query, query); + } + #[test] fn method_drop_index_if_exists_should_accumulate_values_on_consecutive_calls() { let query = sql::DropIndex::new() @@ -394,4 +421,17 @@ mod postgres_feature_flag { assert_eq!(expected_query, query); } + + #[test] + fn method_drop_index_if_exists_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::DropIndex::new() + .drop_index_if_exists("") + .drop_index_if_exists("series") + .drop_index_if_exists("") + .as_string(); + + let expected_query = "DROP INDEX IF EXISTS series"; + + assert_eq!(expected_query, query); + } } From 8425d35ac37d8a514573e1a0c2e1b0c54b5b44bf Mon Sep 17 00:00:00 2001 From: Belchior Oliveira Date: Wed, 16 Oct 2024 14:37:30 -0300 Subject: [PATCH 04/14] fix accumulator methods of drop table --- src/drop_table/drop_table_internal.rs | 10 +++++-- tests/command_drop_table_spec.rs | 40 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/drop_table/drop_table_internal.rs b/src/drop_table/drop_table_internal.rs index 593d074..9713a30 100644 --- a/src/drop_table/drop_table_internal.rs +++ b/src/drop_table/drop_table_internal.rs @@ -10,7 +10,7 @@ impl DropTable { fn concat_drop_table(&self, query: String, fmts: &fmt::Formatter) -> String { let fmt::Formatter { comma, lb, space, .. } = fmts; - let sql = if self._drop_table.len() != 0 { + let sql = if self._drop_table.is_empty() == false { let if_exists = if self._if_exists { format!("IF EXISTS{space}") } else { @@ -18,7 +18,13 @@ impl DropTable { }; let table_names = if cfg!(any(feature = "postgresql")) { - self._drop_table.join(comma) + self + ._drop_table + .iter() + .filter(|item| item.is_empty() == false) + .map(|item| item.as_str()) + .collect::>() + .join(comma) } else { self._drop_table.last().unwrap().to_string() }; diff --git a/tests/command_drop_table_spec.rs b/tests/command_drop_table_spec.rs index c40c085..5c9c385 100644 --- a/tests/command_drop_table_spec.rs +++ b/tests/command_drop_table_spec.rs @@ -164,6 +164,20 @@ mod builder_methods { assert_eq!(expected_query, query); } + #[test] + fn method_raw_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::DropTable::new() + .raw("") + .raw("drop table users") + .raw("cascade") + .raw("") + .as_string(); + + let expected_query = "drop table users cascade"; + + assert_eq!(expected_query, query); + } + #[test] fn method_raw_should_be_the_first_to_be_concatenated() { let query = sql::DropTable::new() @@ -364,6 +378,19 @@ mod postgres_feature_flag { assert_eq!(expected_query, query); } + #[test] + fn method_drop_table_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::DropTable::new() + .drop_table("") + .drop_table("series") + .drop_table("") + .as_string(); + + let expected_query = "DROP TABLE series"; + + assert_eq!(expected_query, query); + } + #[test] fn method_drop_table_if_exists_should_accumulate_values_on_consecutive_calls() { let query = sql::DropTable::new() @@ -375,4 +402,17 @@ mod postgres_feature_flag { assert_eq!(expected_query, query); } + + #[test] + fn method_drop_table_if_exists_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::DropTable::new() + .drop_table_if_exists("") + .drop_table_if_exists("series") + .drop_table_if_exists("") + .as_string(); + + let expected_query = "DROP TABLE IF EXISTS series"; + + assert_eq!(expected_query, query); + } } From 9bb5ac737866d69b7fdde0d64db98e75e33c2d93 Mon Sep 17 00:00:00 2001 From: Belchior Oliveira Date: Wed, 16 Oct 2024 15:05:00 -0300 Subject: [PATCH 05/14] fix accumulator methods of insert --- src/insert/insert_internal.rs | 8 +++++++- tests/clause_values_spec.rs | 12 ++++++++++++ tests/command_insert_spec.rs | 13 +++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/insert/insert_internal.rs b/src/insert/insert_internal.rs index 69781ad..84aa479 100644 --- a/src/insert/insert_internal.rs +++ b/src/insert/insert_internal.rs @@ -95,7 +95,13 @@ impl Insert { (InsertClause::DefaultValues, format!("DEFAULT VALUES{space}{lb}")) } else if self._values.is_empty() == false { let sep = format!("{comma}{lb}"); - let values = self._values.join(&sep); + let values = self + ._values + .iter() + .filter(|item| item.is_empty() == false) + .map(|item| item.as_str()) + .collect::>() + .join(&sep); (InsertClause::Values, format!("VALUES{space}{lb}{values}{space}{lb}")) } else { (InsertClause::Values, "".to_string()) diff --git a/tests/clause_values_spec.rs b/tests/clause_values_spec.rs index 7431adb..b906c30 100644 --- a/tests/clause_values_spec.rs +++ b/tests/clause_values_spec.rs @@ -21,6 +21,18 @@ mod insert_command { assert_eq!(query, expected_query); } + #[test] + fn method_values_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Insert::new() + .values("") + .values("('bar', 'Bar')") + .values("") + .as_string(); + let expected_query = "VALUES ('bar', 'Bar')"; + + assert_eq!(query, expected_query); + } + #[test] fn method_values_should_trim_space_of_the_argument() { let query = sql::Insert::new().values(" ('Bar') ").as_string(); diff --git a/tests/command_insert_spec.rs b/tests/command_insert_spec.rs index c441dd6..7d8875f 100644 --- a/tests/command_insert_spec.rs +++ b/tests/command_insert_spec.rs @@ -183,6 +183,19 @@ mod builder_methods { assert_eq!(query, expected_query); } + #[test] + fn method_raw_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Insert::new() + .raw("") + .raw("/* raw statement */") + .raw("insert into addresses (state, country)") + .raw("") + .as_string(); + let expected_query = "/* raw statement */ insert into addresses (state, country)"; + + assert_eq!(query, expected_query); + } + #[test] fn method_raw_should_be_the_first_to_be_concatenated() { let query = sql::Insert::new() From 39a1b89e214fd1410a9eaab4566a38dd54fe30df Mon Sep 17 00:00:00 2001 From: Belchior Oliveira Date: Wed, 16 Oct 2024 15:10:48 -0300 Subject: [PATCH 06/14] fix accumulator methods of values command --- src/values/values_internal.rs | 8 +++++++- tests/clause_values_spec.rs | 12 ++++++++++++ tests/command_values_spec.rs | 8 ++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/values/values_internal.rs b/src/values/values_internal.rs index 022d190..f82bb9b 100644 --- a/src/values/values_internal.rs +++ b/src/values/values_internal.rs @@ -11,7 +11,13 @@ impl Values { let fmt::Formatter { comma, lb, space, .. } = fmts; let sql = if self._values.is_empty() == false { let sep = format!("{comma}{lb}"); - let values = self._values.join(&sep); + let values = self + ._values + .iter() + .filter(|item| item.is_empty() == false) + .map(|item| item.as_str()) + .collect::>() + .join(&sep); format!("VALUES{space}{lb}{values}{space}{lb}") } else { "".to_string() diff --git a/tests/clause_values_spec.rs b/tests/clause_values_spec.rs index b906c30..a66a63b 100644 --- a/tests/clause_values_spec.rs +++ b/tests/clause_values_spec.rs @@ -109,6 +109,18 @@ mod values_command { assert_eq!(query, expected_query); } + #[test] + fn method_values_should_not_accumulate_values_when_table_name_is_empty() { + let query = sql::Values::new() + .values("") + .values("('foo', 'Foo')") + .values("") + .as_string(); + let expected_query = "VALUES ('foo', 'Foo')"; + + assert_eq!(query, expected_query); + } + #[test] fn method_values_should_trim_space_of_the_argument() { let query = sql::Values::new().values(" ('Bar') ").as_string(); diff --git a/tests/command_values_spec.rs b/tests/command_values_spec.rs index 47335f6..f572266 100644 --- a/tests/command_values_spec.rs +++ b/tests/command_values_spec.rs @@ -161,6 +161,14 @@ mod builder_methods { assert_eq!(query, expected_query); } + #[test] + fn method_raw_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Values::new().raw("").raw("/* raw one */").raw("").as_string(); + let expected_query = "/* raw one */"; + + assert_eq!(query, expected_query); + } + #[test] fn method_raw_should_be_the_first_to_be_concatenated() { let query = sql::Values::new() From 130a62708ad93608ad0c77f8a464a32a72a18318 Mon Sep 17 00:00:00 2001 From: Belchior Oliveira Date: Wed, 16 Oct 2024 15:58:11 -0300 Subject: [PATCH 07/14] fix accumulator methods of transaction command --- src/transaction/transaction_internal.rs | 7 +- tests/command_transaction_spec.rs | 121 ++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 1 deletion(-) diff --git a/src/transaction/transaction_internal.rs b/src/transaction/transaction_internal.rs index ab1ad24..ff9c293 100644 --- a/src/transaction/transaction_internal.rs +++ b/src/transaction/transaction_internal.rs @@ -100,7 +100,12 @@ impl Transaction { fn concat_ordered_commands(&self, query: String, fmts: &fmt::Formatter) -> String { let fmt::Formatter { lb, space, .. } = fmts; let sql = self._ordered_commands.iter().fold("".to_string(), |acc, cmd| { - format!("{acc}{0};{space}{lb}", cmd.concat(fmts)) + let inner_cmd = cmd.concat(fmts); + if inner_cmd.is_empty() == false { + format!("{acc}{inner_cmd};{space}{lb}") + } else { + acc + } }); format!("{query}{sql}") diff --git a/tests/command_transaction_spec.rs b/tests/command_transaction_spec.rs index b2b1377..e230a86 100644 --- a/tests/command_transaction_spec.rs +++ b/tests/command_transaction_spec.rs @@ -262,6 +262,14 @@ mod builder_methods { assert_eq!(query, expected_query); } + #[test] + fn method_raw_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Transaction::new().raw("").raw("/* raw one */").raw("").as_string(); + let expected_query = "/* raw one */"; + + assert_eq!(query, expected_query); + } + #[test] fn method_raw_should_be_the_first_to_be_concatenated() { #[cfg(not(feature = "sqlite"))] @@ -329,6 +337,19 @@ mod alter_table_method { assert_eq!(expected_query, query); } + + #[test] + fn method_alter_table_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Transaction::new() + .alter_table(sql::AlterTable::new()) + .alter_table(sql::AlterTable::new().alter_table("orders")) + .alter_table(sql::AlterTable::new()) + .as_string(); + + let expected_query = "ALTER TABLE orders;"; + + assert_eq!(expected_query, query); + } } mod create_table_method { @@ -357,6 +378,19 @@ mod create_table_method { assert_eq!(expected_query, query); } + + #[test] + fn method_create_table_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Transaction::new() + .create_table(sql::CreateTable::new()) + .create_table(sql::CreateTable::new().create_table("orders")) + .create_table(sql::CreateTable::new()) + .as_string(); + + let expected_query = "CREATE TABLE orders;"; + + assert_eq!(expected_query, query); + } } mod delete_method { @@ -383,6 +417,18 @@ mod delete_method { assert_eq!(query, expected_query); } + + #[test] + fn method_delete_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Transaction::new() + .delete(sql::Delete::new()) + .delete(sql::Delete::new().delete_from("users")) + .delete(sql::Delete::new()) + .as_string(); + let expected_query = "DELETE FROM users;"; + + assert_eq!(query, expected_query); + } } #[cfg(any(feature = "postgresql", feature = "sqlite"))] @@ -412,6 +458,19 @@ mod create_index_method { assert_eq!(expected_query, query); } + + #[test] + fn method_create_index_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Transaction::new() + .create_index(sql::CreateIndex::new()) + .create_index(sql::CreateIndex::new().create_index("orders_product_name_idx")) + .create_index(sql::CreateIndex::new()) + .as_string(); + + let expected_query = "CREATE INDEX orders_product_name_idx;"; + + assert_eq!(expected_query, query); + } } #[cfg(any(feature = "postgresql", feature = "sqlite"))] @@ -441,6 +500,19 @@ mod drop_index_method { assert_eq!(expected_query, query); } + + #[test] + fn method_drop_index_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Transaction::new() + .drop_index(sql::DropIndex::new()) + .drop_index(sql::DropIndex::new().drop_index("orders_product_name_idx")) + .drop_index(sql::DropIndex::new()) + .as_string(); + + let expected_query = "DROP INDEX orders_product_name_idx;"; + + assert_eq!(expected_query, query); + } } mod drop_table_method { @@ -469,6 +541,19 @@ mod drop_table_method { assert_eq!(expected_query, query); } + + #[test] + fn method_drop_table_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Transaction::new() + .drop_table(sql::DropTable::new()) + .drop_table(sql::DropTable::new().drop_table("orders")) + .drop_table(sql::DropTable::new()) + .as_string(); + + let expected_query = "DROP TABLE orders;"; + + assert_eq!(expected_query, query); + } } mod insert_method { @@ -495,6 +580,18 @@ mod insert_method { assert_eq!(query, expected_query); } + + #[test] + fn method_insert_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Transaction::new() + .insert(sql::Insert::new()) + .insert(sql::Insert::new().insert_into("users (login, name)")) + .insert(sql::Insert::new()) + .as_string(); + let expected_query = "INSERT INTO users (login, name);"; + + assert_eq!(query, expected_query); + } } mod multi_commands { @@ -687,6 +784,18 @@ mod select_method { assert_eq!(query, expected_query); } + + #[test] + fn method_select_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Transaction::new() + .select(sql::Select::new()) + .select(sql::Select::new().select("login, name")) + .select(sql::Select::new()) + .as_string(); + let expected_query = "SELECT login, name;"; + + assert_eq!(query, expected_query); + } } mod update_method { @@ -713,4 +822,16 @@ mod update_method { assert_eq!(query, expected_query); } + + #[test] + fn method_update_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Transaction::new() + .update(sql::Update::new()) + .update(sql::Update::new().update("users")) + .update(sql::Update::new()) + .as_string(); + let expected_query = "UPDATE users;"; + + assert_eq!(query, expected_query); + } } From dff142fd20e2e66cbe6dc8e2f664319a343ff2b9 Mon Sep 17 00:00:00 2001 From: Belchior Oliveira Date: Wed, 16 Oct 2024 16:09:30 -0300 Subject: [PATCH 08/14] fix accumulator methods of update command --- src/update/update.rs | 24 ++++++++++++------ src/update/update_internal.rs | 8 +++++- tests/clause_join_spec.rs | 48 +++++++++++++++++++++++++++++++++++ tests/clause_set_spec.rs | 8 ++++++ tests/command_update_spec.rs | 8 ++++++ 5 files changed, 87 insertions(+), 9 deletions(-) diff --git a/src/update/update.rs b/src/update/update.rs index de0644c..530a75e 100644 --- a/src/update/update.rs +++ b/src/update/update.rs @@ -452,8 +452,10 @@ impl Update { /// ``` pub fn cross_join(mut self, table: &str) -> Self { let table = table.trim(); - let table = format!("CROSS JOIN {table}"); - push_unique(&mut self._join, table); + if table.is_empty() == false { + let table = format!("CROSS JOIN {table}"); + push_unique(&mut self._join, table); + } self } @@ -481,8 +483,10 @@ impl Update { /// ``` pub fn inner_join(mut self, table: &str) -> Self { let table = table.trim(); - let table = format!("INNER JOIN {table}"); - push_unique(&mut self._join, table); + if table.is_empty() == false { + let table = format!("INNER JOIN {table}"); + push_unique(&mut self._join, table); + } self } @@ -510,8 +514,10 @@ impl Update { /// ``` pub fn left_join(mut self, table: &str) -> Self { let table = table.trim(); - let table = format!("LEFT JOIN {table}"); - push_unique(&mut self._join, table); + if table.is_empty() == false { + let table = format!("LEFT JOIN {table}"); + push_unique(&mut self._join, table); + } self } @@ -539,8 +545,10 @@ impl Update { /// ``` pub fn right_join(mut self, table: &str) -> Self { let table = table.trim(); - let table = format!("RIGHT JOIN {table}"); - push_unique(&mut self._join, table); + if table.is_empty() == false { + let table = format!("RIGHT JOIN {table}"); + push_unique(&mut self._join, table); + } self } diff --git a/src/update/update_internal.rs b/src/update/update_internal.rs index a269893..f9cd9a1 100644 --- a/src/update/update_internal.rs +++ b/src/update/update_internal.rs @@ -17,7 +17,13 @@ impl Update { fn concat_set(&self, query: String, fmts: &fmt::Formatter) -> String { let fmt::Formatter { comma, lb, space, .. } = fmts; let sql = if self._set.is_empty() == false { - let values = self._set.join(comma); + let values = self + ._set + .iter() + .filter(|item| item.is_empty() == false) + .map(|item| item.as_str()) + .collect::>() + .join(comma); format!("SET{space}{values}{space}{lb}") } else { "".to_string() diff --git a/tests/clause_join_spec.rs b/tests/clause_join_spec.rs index 7622e63..c7bee89 100644 --- a/tests/clause_join_spec.rs +++ b/tests/clause_join_spec.rs @@ -144,6 +144,18 @@ mod cross_join_clause { assert_eq!(query, expected_query); } + #[test] + fn method_cross_join_should_not_accumulate_values_when_table_name_is_empty() { + let query = sql::Update::new() + .cross_join("") + .cross_join("orders") + .cross_join("") + .as_string(); + let expected_query = "CROSS JOIN orders"; + + assert_eq!(query, expected_query); + } + #[test] fn method_cross_join_by_should_trim_space_of_the_argument() { let query = sql::Update::new().cross_join(" orders ").as_string(); @@ -262,6 +274,18 @@ mod inner_join_clause { assert_eq!(query, expected_query); } + #[test] + fn method_inner_join_should_not_accumulate_values_when_table_expression_is_empty() { + let query = sql::Update::new() + .inner_join("") + .inner_join("orders ON users.login = orders.login") + .inner_join("") + .as_string(); + let expected_query = "INNER JOIN orders ON users.login = orders.login"; + + assert_eq!(query, expected_query); + } + #[test] fn method_inner_join_by_should_trim_space_of_the_argument() { let query = sql::Update::new().inner_join(" orders ").as_string(); @@ -383,6 +407,18 @@ mod left_join_clause { assert_eq!(query, expected_query); } + #[test] + fn method_left_join_should_not_accumulate_values_when_table_expression_is_empty() { + let query = sql::Update::new() + .left_join("") + .left_join("orders ON users.login = orders.login") + .left_join("") + .as_string(); + let expected_query = "LEFT JOIN orders ON users.login = orders.login"; + + assert_eq!(query, expected_query); + } + #[test] fn method_left_join_by_should_trim_space_of_the_argument() { let query = sql::Update::new().left_join(" orders ").as_string(); @@ -504,6 +540,18 @@ mod right_join_clause { assert_eq!(query, expected_query); } + #[test] + fn method_right_join_should_not_accumulate_values_when_table_expression_is_empty() { + let query = sql::Update::new() + .right_join("") + .right_join("orders ON users.login = orders.login") + .right_join("") + .as_string(); + let expected_query = "RIGHT JOIN orders ON users.login = orders.login"; + + assert_eq!(query, expected_query); + } + #[test] fn method_right_join_by_should_trim_space_of_the_argument() { let query = sql::Update::new().right_join(" orders ").as_string(); diff --git a/tests/clause_set_spec.rs b/tests/clause_set_spec.rs index 28c2184..26608c2 100644 --- a/tests/clause_set_spec.rs +++ b/tests/clause_set_spec.rs @@ -18,6 +18,14 @@ mod update_command { assert_eq!(query, expected_query); } + #[test] + fn method_set_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Update::new().set("").set("name = 'Foo'").set("").as_string(); + let expected_query = "SET name = 'Foo'"; + + assert_eq!(query, expected_query); + } + #[test] fn method_set_should_trim_space_of_the_argument() { let query = sql::Update::new().set(" name = 'Bar' ").as_string(); diff --git a/tests/command_update_spec.rs b/tests/command_update_spec.rs index cbf56ad..0832d44 100644 --- a/tests/command_update_spec.rs +++ b/tests/command_update_spec.rs @@ -190,6 +190,14 @@ mod builder_methods { assert_eq!(query, expected_query); } + #[test] + fn method_raw_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Update::new().raw("").raw("update addresses").raw("").as_string(); + let expected_query = "update addresses"; + + assert_eq!(query, expected_query); + } + #[test] fn method_raw_should_be_the_first_to_be_concatenated() { let query = sql::Update::new() From 6489b46debf1a49df4770336c7ec9cb7b3732d00 Mon Sep 17 00:00:00 2001 From: Belchior Oliveira Date: Wed, 16 Oct 2024 16:16:24 -0300 Subject: [PATCH 09/14] adds more tests to create index command --- tests/command_create_index_spec.rs | 40 ++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/command_create_index_spec.rs b/tests/command_create_index_spec.rs index 64f328d..85607f7 100644 --- a/tests/command_create_index_spec.rs +++ b/tests/command_create_index_spec.rs @@ -228,6 +228,20 @@ mod builder_methods { assert_eq!(expected_query, query); } + #[test] + fn method_raw_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::CreateIndex::new() + .raw("") + .raw("on users") + .raw("(name)") + .raw("") + .as_string(); + + let expected_query = "on users (name)"; + + assert_eq!(expected_query, query); + } + #[test] fn method_raw_should_be_the_first_to_be_concatenated() { let query = sql::CreateIndex::new() @@ -315,6 +329,19 @@ mod method_column { assert_eq!(expected_query, query); } + #[test] + fn method_column_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::CreateIndex::new() + .column("") + .column("login") + .column("") + .as_string(); + + let expected_query = "(login)"; + + assert_eq!(expected_query, query); + } + #[test] fn method_column_should_not_accumulate_parameters_with_the_same_content() { let query = sql::CreateIndex::new().column("login").column("login").as_string(); @@ -848,6 +875,19 @@ mod method_include { assert_eq!(expected_query, query); } + #[test] + fn method_include_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::CreateIndex::new() + .include("") + .include("login") + .include("") + .as_string(); + + let expected_query = "INCLUDE (login)"; + + assert_eq!(expected_query, query); + } + #[test] fn method_include_should_not_accumulate_columns_with_the_same_content() { let query = sql::CreateIndex::new().include("login").include("login").as_string(); From f4becc52b1a298b4817cd3709c90beb01eeab939 Mon Sep 17 00:00:00 2001 From: Belchior Oliveira Date: Wed, 16 Oct 2024 16:22:55 -0300 Subject: [PATCH 10/14] adds more tests to delete command --- tests/clause_returning_spec.rs | 12 ++++++++++++ tests/command_delete_spec.rs | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/tests/clause_returning_spec.rs b/tests/clause_returning_spec.rs index 6fa3fab..deb3b10 100644 --- a/tests/clause_returning_spec.rs +++ b/tests/clause_returning_spec.rs @@ -19,6 +19,18 @@ mod delete_command { assert_eq!(query, expected_query); } + #[test] + fn method_returning_should_not_accumulate_values_when_column_name_is_empty() { + let query = sql::Delete::new() + .returning("") + .returning("name") + .returning("") + .as_string(); + let expected_query = "RETURNING name"; + + assert_eq!(query, expected_query); + } + #[test] fn method_returning_should_not_accumulate_arguments_with_the_same_content() { let query = sql::Delete::new().returning("id").returning("id").as_string(); diff --git a/tests/command_delete_spec.rs b/tests/command_delete_spec.rs index 93f304d..768817b 100644 --- a/tests/command_delete_spec.rs +++ b/tests/command_delete_spec.rs @@ -181,6 +181,18 @@ mod builder_methods { assert_eq!(query, expected_query); } + #[test] + fn method_raw_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Delete::new() + .raw("") + .raw("delete from addresses") + .raw("") + .as_string(); + let expected_query = "delete from addresses"; + + assert_eq!(query, expected_query); + } + #[test] fn method_raw_should_be_the_first_to_be_concatenated() { let query = sql::Delete::new() From b596c7bdbcb967b26fb71be56685965652052413 Mon Sep 17 00:00:00 2001 From: Belchior Oliveira Date: Wed, 16 Oct 2024 17:08:41 -0300 Subject: [PATCH 11/14] fix accumulator methods of select command --- src/select/select.rs | 24 +++++--- src/select/select_internal.rs | 40 +++++++++++-- tests/clause_from_spec.rs | 16 ++++++ tests/clause_group_by_spec.rs | 12 ++++ tests/clause_having_spec.rs | 12 ++++ tests/clause_join_spec.rs | 48 ++++++++++++++++ tests/clause_order_by_spec.rs | 12 ++++ tests/clause_select_spec.rs | 10 +++- tests/clause_where_spec.rs | 104 ++++++++++++++++++++++++++++++++++ tests/clause_window_spec.rs | 8 +++ tests/clause_with_spec.rs | 48 ++++++++++++++++ tests/command_select_spec.rs | 13 +++++ 12 files changed, 331 insertions(+), 16 deletions(-) diff --git a/src/select/select.rs b/src/select/select.rs index bb2c267..bde8a86 100644 --- a/src/select/select.rs +++ b/src/select/select.rs @@ -168,8 +168,10 @@ impl Select { /// ``` pub fn cross_join(mut self, table: &str) -> Self { let table = table.trim(); - let table = format!("CROSS JOIN {table}"); - push_unique(&mut self._join, table); + if table.is_empty() == false { + let table = format!("CROSS JOIN {table}"); + push_unique(&mut self._join, table); + } self } @@ -195,8 +197,10 @@ impl Select { /// ``` pub fn inner_join(mut self, table: &str) -> Self { let table = table.trim(); - let table = format!("INNER JOIN {table}"); - push_unique(&mut self._join, table); + if table.is_empty() == false { + let table = format!("INNER JOIN {table}"); + push_unique(&mut self._join, table); + } self } @@ -222,8 +226,10 @@ impl Select { /// ``` pub fn left_join(mut self, table: &str) -> Self { let table = table.trim(); - let table = format!("LEFT JOIN {table}"); - push_unique(&mut self._join, table); + if table.is_empty() == false { + let table = format!("LEFT JOIN {table}"); + push_unique(&mut self._join, table); + } self } @@ -249,8 +255,10 @@ impl Select { /// ``` pub fn right_join(mut self, table: &str) -> Self { let table = table.trim(); - let table = format!("RIGHT JOIN {table}"); - push_unique(&mut self._join, table); + if table.is_empty() == false { + let table = format!("RIGHT JOIN {table}"); + push_unique(&mut self._join, table); + } self } diff --git a/src/select/select_internal.rs b/src/select/select_internal.rs index 9735382..59b71aa 100644 --- a/src/select/select_internal.rs +++ b/src/select/select_internal.rs @@ -71,7 +71,13 @@ impl Select { fn concat_group_by(&self, query: String, fmts: &fmt::Formatter) -> String { let fmt::Formatter { comma, lb, space, .. } = fmts; let sql = if self._group_by.is_empty() == false { - let columns = self._group_by.join(comma); + let columns = self + ._group_by + .iter() + .filter(|column| column.is_empty() == false) + .map(|column| column.as_str()) + .collect::>() + .join(comma); format!("GROUP BY{space}{columns}{space}{lb}") } else { "".to_string() @@ -90,7 +96,13 @@ impl Select { fn concat_having(&self, query: String, fmts: &fmt::Formatter) -> String { let fmt::Formatter { lb, space, .. } = fmts; let sql = if self._having.is_empty() == false { - let conditions = self._having.join(" AND "); + let conditions = self + ._having + .iter() + .filter(|item| item.is_empty() == false) + .map(|item| item.as_str()) + .collect::>() + .join(" AND "); format!("HAVING{space}{conditions}{space}{lb}") } else { "".to_string() @@ -128,7 +140,13 @@ impl Select { fn concat_order_by(&self, query: String, fmts: &fmt::Formatter) -> String { let fmt::Formatter { comma, lb, space, .. } = fmts; let sql = if self._order_by.is_empty() == false { - let columns = self._order_by.join(comma); + let columns = self + ._order_by + .iter() + .filter(|item| item.is_empty() == false) + .map(|item| item.as_str()) + .collect::>() + .join(comma); format!("ORDER BY{space}{columns}{space}{lb}") } else { "".to_string() @@ -147,7 +165,13 @@ impl Select { fn concat_select(&self, query: String, fmts: &fmt::Formatter) -> String { let fmt::Formatter { comma, lb, space, .. } = fmts; let sql = if self._select.is_empty() == false { - let columns = self._select.join(comma); + let columns = self + ._select + .iter() + .filter(|column| column.is_empty() == false) + .map(|column| column.as_str()) + .collect::>() + .join(comma); format!("SELECT{space}{columns}{space}{lb}") } else { "".to_string() @@ -166,7 +190,13 @@ impl Select { fn concat_window(&self, query: String, fmts: &fmt::Formatter) -> String { let fmt::Formatter { comma, lb, space, .. } = fmts; let sql = if self._window.is_empty() == false { - let columns = self._window.join(comma); + let columns = self + ._window + .iter() + .filter(|item| item.is_empty() == false) + .map(|item| item.as_str()) + .collect::>() + .join(comma); format!("WINDOW{space}{columns}{space}{lb}") } else { "".to_string() diff --git a/tests/clause_from_spec.rs b/tests/clause_from_spec.rs index 9c1e67e..5d57ce6 100644 --- a/tests/clause_from_spec.rs +++ b/tests/clause_from_spec.rs @@ -18,6 +18,14 @@ mod select_command { assert_eq!(query, expected_query); } + #[test] + fn method_from_should_not_accumulate_values_when_table_name_is_empty() { + let query = sql::Select::new().from("").from("users").from("").as_string(); + let expected_query = "FROM users"; + + assert_eq!(query, expected_query); + } + #[test] fn method_from_should_trim_space_of_the_argument() { let query = sql::Select::new().from(" users ").as_string(); @@ -89,6 +97,14 @@ mod update_command { assert_eq!(query, expected_query); } + #[test] + fn method_from_should_not_accumulate_values_when_table_name_is_empty() { + let query = sql::Update::new().from("").from("users").from("").as_string(); + let expected_query = "FROM users"; + + assert_eq!(query, expected_query); + } + #[test] fn method_from_should_trim_space_of_the_argument() { let query = sql::Update::new().from(" users ").as_string(); diff --git a/tests/clause_group_by_spec.rs b/tests/clause_group_by_spec.rs index 68578ac..f400dd1 100644 --- a/tests/clause_group_by_spec.rs +++ b/tests/clause_group_by_spec.rs @@ -21,6 +21,18 @@ mod select_command { assert_eq!(query, expected_query); } + #[test] + fn method_group_by_should_not_accumulate_values_when_column_name_is_empty() { + let query = sql::Select::new() + .group_by("") + .group_by("created_at") + .group_by("") + .as_string(); + let expected_query = "GROUP BY created_at"; + + assert_eq!(query, expected_query); + } + #[test] fn method_group_by_should_trim_space_of_the_argument() { let query = sql::Select::new().group_by(" id, login ").as_string(); diff --git a/tests/clause_having_spec.rs b/tests/clause_having_spec.rs index 63ac3f9..113eb45 100644 --- a/tests/clause_having_spec.rs +++ b/tests/clause_having_spec.rs @@ -21,6 +21,18 @@ mod select_command { assert_eq!(query, expected_query); } + #[test] + fn method_having_should_not_accumulate_values_when_condition_is_empty() { + let query = sql::Select::new() + .having("") + .having("allow = true") + .having("") + .as_string(); + let expected_query = "HAVING allow = true"; + + assert_eq!(query, expected_query); + } + #[test] fn method_having_should_trim_space_of_the_argument() { let query = sql::Select::new().having(" sum(amount) > 500 ").as_string(); diff --git a/tests/clause_join_spec.rs b/tests/clause_join_spec.rs index c7bee89..f4a1810 100644 --- a/tests/clause_join_spec.rs +++ b/tests/clause_join_spec.rs @@ -89,6 +89,18 @@ mod cross_join_clause { assert_eq!(query, expected_query); } + #[test] + fn method_cross_join_should_not_accumulate_values_when_table_name_is_empty() { + let query = sql::Select::new() + .cross_join("") + .cross_join("orders") + .cross_join("") + .as_string(); + let expected_query = "CROSS JOIN orders"; + + assert_eq!(query, expected_query); + } + #[test] fn method_cross_join_by_should_trim_space_of_the_argument() { let query = sql::Select::new().cross_join(" orders ").as_string(); @@ -214,6 +226,18 @@ mod inner_join_clause { assert_eq!(query, expected_query); } + #[test] + fn method_inner_join_should_not_accumulate_values_when_table_expression_is_empty() { + let query = sql::Select::new() + .inner_join("") + .inner_join("orders ON users.login = orders.login") + .inner_join("") + .as_string(); + let expected_query = "INNER JOIN orders ON users.login = orders.login"; + + assert_eq!(query, expected_query); + } + #[test] fn method_inner_join_by_should_trim_space_of_the_argument() { let query = sql::Select::new().inner_join(" orders ").as_string(); @@ -347,6 +371,18 @@ mod left_join_clause { assert_eq!(query, expected_query); } + #[test] + fn method_left_join_should_not_accumulate_values_when_table_expression_is_empty() { + let query = sql::Select::new() + .left_join("") + .left_join("orders ON users.login = orders.login") + .left_join("") + .as_string(); + let expected_query = "LEFT JOIN orders ON users.login = orders.login"; + + assert_eq!(query, expected_query); + } + #[test] fn method_left_join_by_should_trim_space_of_the_argument() { let query = sql::Select::new().left_join(" orders ").as_string(); @@ -480,6 +516,18 @@ mod right_join_clause { assert_eq!(query, expected_query); } + #[test] + fn method_right_join_should_not_accumulate_values_when_table_expression_is_empty() { + let query = sql::Select::new() + .right_join("") + .right_join("orders ON users.login = orders.login") + .right_join("") + .as_string(); + let expected_query = "RIGHT JOIN orders ON users.login = orders.login"; + + assert_eq!(query, expected_query); + } + #[test] fn method_right_join_by_should_trim_space_of_the_argument() { let query = sql::Select::new().right_join(" orders ").as_string(); diff --git a/tests/clause_order_by_spec.rs b/tests/clause_order_by_spec.rs index aadbb5e..9212f99 100644 --- a/tests/clause_order_by_spec.rs +++ b/tests/clause_order_by_spec.rs @@ -21,6 +21,18 @@ mod select_command { assert_eq!(query, expected_query); } + #[test] + fn method_order_by_should_not_accumulate_values_when_column_name_is_empty() { + let query = sql::Select::new() + .order_by("") + .order_by("created_at desc") + .order_by("") + .as_string(); + let expected_query = "ORDER BY created_at desc"; + + assert_eq!(query, expected_query); + } + #[test] fn method_order_by_should_trim_space_of_the_argument() { let query = sql::Select::new().order_by(" id desc ").as_string(); diff --git a/tests/clause_select_spec.rs b/tests/clause_select_spec.rs index 74adb60..99e1eb4 100644 --- a/tests/clause_select_spec.rs +++ b/tests/clause_select_spec.rs @@ -86,9 +86,13 @@ mod select_command { } #[test] - fn method_select_should_accumulate_values_on_consecutive_calls() { - let query = sql::Select::new().select("id, login").select("created_at").as_string(); - let expected_query = "SELECT id, login, created_at"; + fn method_select_should_not_accumulate_values_when_column_name_is_empty() { + let query = sql::Select::new() + .select("") + .select("created_at") + .select("") + .as_string(); + let expected_query = "SELECT created_at"; assert_eq!(expected_query, query); } diff --git a/tests/clause_where_spec.rs b/tests/clause_where_spec.rs index 1fa65cf..339ca6c 100644 --- a/tests/clause_where_spec.rs +++ b/tests/clause_where_spec.rs @@ -36,6 +36,19 @@ mod where_clause { assert_eq!(query, expected_query); } + #[test] + fn method_where_clause_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::CreateIndex::new() + .where_clause("") + .where_clause("status = 'active'") + .where_clause("") + .as_string(); + + let expected_query = "WHERE status = 'active'"; + + assert_eq!(query, expected_query); + } + #[test] fn method_where_clause_should_not_accumulate_arguments_with_the_same_content() { let query = sql::CreateIndex::new() @@ -116,6 +129,19 @@ mod where_clause { assert_eq!(query, expected_query); } + #[test] + fn method_where_clause_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Delete::new() + .where_clause("") + .where_clause("status = 'pending'") + .where_clause("") + .as_string(); + + let expected_query = "WHERE status = 'pending'"; + + assert_eq!(query, expected_query); + } + #[test] fn method_where_clause_should_not_accumulate_arguments_with_the_same_content() { let query = sql::Delete::new() @@ -207,6 +233,19 @@ mod where_clause { assert_eq!(query, expected_query); } + #[test] + fn method_where_clause_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Select::new() + .where_clause("") + .where_clause("created_at::date <= current_date") + .where_clause("") + .as_string(); + + let expected_query = "WHERE created_at::date <= current_date"; + + assert_eq!(query, expected_query); + } + #[test] fn method_where_clause_should_trim_space_of_the_argument() { let query = sql::Select::new().where_clause(" id = $1 ").as_string(); @@ -288,6 +327,19 @@ mod where_clause { assert_eq!(query, expected_query); } + #[test] + fn method_where_clause_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Update::new() + .where_clause("") + .where_clause("status = 'pending'") + .where_clause("") + .as_string(); + + let expected_query = "WHERE status = 'pending'"; + + assert_eq!(query, expected_query); + } + #[test] fn clause_where_should_be_after_set_clause() { let query = sql::Update::new() @@ -447,6 +499,19 @@ mod where_or { assert_eq!(query, expected_query); } + #[test] + fn method_where_or_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::CreateIndex::new() + .where_or("") + .where_or("status = 'active'") + .where_or("") + .as_string(); + + let expected_query = "WHERE status = 'active'"; + + assert_eq!(query, expected_query); + } + #[test] fn method_where_or_should_trim_space_of_the_argument() { let query = sql::CreateIndex::new().where_or(" status = 'active' ").as_string(); @@ -527,6 +592,19 @@ mod where_or { assert_eq!(query, expected_query); } + #[test] + fn method_where_or_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Delete::new() + .where_or("") + .where_or("login = 'bar'") + .where_or("") + .as_string(); + + let expected_query = "WHERE login = 'bar'"; + + assert_eq!(query, expected_query); + } + #[test] fn method_where_or_should_trim_space_of_the_argument() { let query = sql::Delete::new().where_or(" id = $1 ").as_string(); @@ -618,6 +696,19 @@ mod where_or { assert_eq!(query, expected_query); } + #[test] + fn method_where_or_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Select::new() + .where_or("") + .where_or("login = 'bar'") + .where_or("") + .as_string(); + + let expected_query = "WHERE login = 'bar'"; + + assert_eq!(query, expected_query); + } + #[test] fn method_where_or_should_trim_space_of_the_argument() { let query = sql::Select::new().where_or(" id = $1 ").as_string(); @@ -709,6 +800,19 @@ mod where_or { assert_eq!(query, expected_query); } + #[test] + fn method_where_or_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Update::new() + .where_or("") + .where_or("login = 'bar'") + .where_or("") + .as_string(); + + let expected_query = "WHERE login = 'bar'"; + + assert_eq!(query, expected_query); + } + #[test] fn method_where_or_should_trim_space_of_the_argument() { let query = sql::Update::new().where_or(" id = $1 ").as_string(); diff --git a/tests/clause_window_spec.rs b/tests/clause_window_spec.rs index 5847130..67bc25e 100644 --- a/tests/clause_window_spec.rs +++ b/tests/clause_window_spec.rs @@ -18,6 +18,14 @@ mod select_command { assert_eq!(query, expected_query); } + #[test] + fn method_window_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Select::new().window("").window("bar").window("").as_string(); + let expected_query = "WINDOW bar"; + + assert_eq!(query, expected_query); + } + #[test] fn method_window_should_trim_space_of_the_argument() { let query = sql::Select::new().window(" foo ").as_string(); diff --git a/tests/clause_with_spec.rs b/tests/clause_with_spec.rs index a6bb872..da848c3 100644 --- a/tests/clause_with_spec.rs +++ b/tests/clause_with_spec.rs @@ -61,6 +61,18 @@ mod delete_command { assert_eq!(query, expected_query); } + #[test] + fn method_with_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Delete::new() + .with("deleted_products", sql::Delete::new()) + .with("deleted_users", sql::Delete::new().delete_from("users")) + .with("deleted_orders", sql::Delete::new()) + .as_string(); + let expected_query = "WITH deleted_users AS (DELETE FROM users)"; + + assert_eq!(query, expected_query); + } + #[test] fn method_with_should_trim_space_of_the_argument() { let query = sql::Delete::new() @@ -189,6 +201,18 @@ mod insert_command { assert_eq!(query, expected_query); } + #[test] + fn method_with_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Insert::new() + .with("inserted_users", sql::Insert::new()) + .with("inserted_orders", sql::Insert::new().insert_into("orders")) + .with("inserted_products", sql::Insert::new()) + .as_string(); + let expected_query = "WITH inserted_orders AS (INSERT INTO orders)"; + + assert_eq!(query, expected_query); + } + #[test] fn method_with_should_trim_space_of_the_argument() { let query = sql::Insert::new() @@ -307,6 +331,18 @@ mod select_command { assert_eq!(query, expected_query); } + #[test] + fn method_with_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Select::new() + .with("user_list", sql::Select::new()) + .with("user_ids", sql::Select::new().select("id").from("user_list")) + .with("user_list2", sql::Select::new()) + .as_string(); + let expected_query = "WITH user_ids AS (SELECT id FROM user_list)"; + + assert_eq!(query, expected_query); + } + #[test] fn method_with_should_trim_space_of_the_argument() { let query = sql::Select::new() @@ -430,6 +466,18 @@ mod update_command { assert_eq!(query, expected_query); } + #[test] + fn method_with_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Update::new() + .with("updated_users", sql::Update::new()) + .with("updated_orders", sql::Update::new().update("orders")) + .with("updated_users2", sql::Update::new()) + .as_string(); + let expected_query = "WITH updated_orders AS (UPDATE orders)"; + + assert_eq!(query, expected_query); + } + #[test] fn method_with_should_trim_space_of_the_argument() { let query = sql::Update::new() diff --git a/tests/command_select_spec.rs b/tests/command_select_spec.rs index 18a4a0d..d0e6700 100644 --- a/tests/command_select_spec.rs +++ b/tests/command_select_spec.rs @@ -220,6 +220,19 @@ mod builder_methods { assert_eq!(query, expected_query); } + #[test] + fn method_raw_should_not_accumulate_values_when_expression_is_empty() { + let query = sql::Select::new() + .raw("") + .raw("select id") + .raw("from users") + .raw("") + .as_string(); + let expected_query = "select id from users"; + + assert_eq!(query, expected_query); + } + #[test] fn method_raw_should_be_the_first_to_be_concatenated() { let query = sql::Select::new().raw("select *").from("users").as_string(); From f8cac040202e0fedb5b14746548bf4e92c1c24ea Mon Sep 17 00:00:00 2001 From: Belchior Oliveira Date: Thu, 17 Oct 2024 11:25:42 -0300 Subject: [PATCH 12/14] trim space of raw queries --- src/behavior.rs | 6 +++--- src/select/select_internal.rs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/behavior.rs b/src/behavior.rs index c8a2d53..3c59d60 100644 --- a/src/behavior.rs +++ b/src/behavior.rs @@ -45,7 +45,7 @@ pub(crate) trait ConcatSqlStandard { return query; } let fmt::Formatter { lb, space, .. } = fmts; - let raw_sql = items.join(space).trim_start().to_string(); + let raw_sql = items.join(space).trim().to_string(); format!("{query}{raw_sql}{space}{lb}") } @@ -245,8 +245,8 @@ pub(crate) fn concat_raw_before_after( sql: String, ) -> String { let fmt::Formatter { space, .. } = fmts; - let raw_before = raw_queries(items_before, &clause).join(space); - let raw_after = raw_queries(items_after, &clause).join(space); + let raw_before = raw_queries(items_before, &clause).join(space).trim().to_string(); + let raw_after = raw_queries(items_after, &clause).join(space).trim().to_string(); let space_after = if raw_after.is_empty() == false { space } else { "" }; let space_before = if raw_before.is_empty() == false { space } else { "" }; diff --git a/src/select/select_internal.rs b/src/select/select_internal.rs index 59b71aa..061db36 100644 --- a/src/select/select_internal.rs +++ b/src/select/select_internal.rs @@ -168,8 +168,8 @@ impl Select { let columns = self ._select .iter() - .filter(|column| column.is_empty() == false) - .map(|column| column.as_str()) + .filter(|item| item.is_empty() == false) + .map(|item| item.as_str()) .collect::>() .join(comma); format!("SELECT{space}{columns}{space}{lb}") @@ -234,8 +234,8 @@ impl Select { Combinator::Union => (SelectClause::Union, "UNION", &self._union), }; - let raw_before = raw_queries(&self._raw_before, &clause).join(space); - let raw_after = raw_queries(&self._raw_after, &clause).join(space); + let raw_before = raw_queries(&self._raw_before, &clause).join(space).trim().to_string(); + let raw_after = raw_queries(&self._raw_after, &clause).join(space).trim().to_string(); let space_before = if raw_before.is_empty() { "".to_string() From 6e49c5d3ad745ec1d160ec4facad8cdbc1b783c5 Mon Sep 17 00:00:00 2001 From: Belchior Oliveira Date: Thu, 17 Oct 2024 17:26:11 -0300 Subject: [PATCH 13/14] adds more test --- tests/clause_select_spec.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/clause_select_spec.rs b/tests/clause_select_spec.rs index 99e1eb4..c6987cc 100644 --- a/tests/clause_select_spec.rs +++ b/tests/clause_select_spec.rs @@ -85,6 +85,14 @@ mod select_command { assert_eq!(expected_query, query); } + #[test] + fn method_select_should_accumulate_values_on_consecutive_calls() { + let query = sql::Select::new().select("id, login").select("created_at").as_string(); + let expected_query = "SELECT id, login, created_at"; + + assert_eq!(expected_query, query); + } + #[test] fn method_select_should_not_accumulate_values_when_column_name_is_empty() { let query = sql::Select::new() From 88d17895d4945497a12de21d70d7bf5060792cd5 Mon Sep 17 00:00:00 2001 From: Belchior Oliveira Date: Fri, 18 Oct 2024 15:49:47 -0300 Subject: [PATCH 14/14] 2.4.1 --- Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ed6cb2f..908cba9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,11 +4,11 @@ description = "Write SQL queries in a simple and composable way" documentation = "https://docs.rs/sql_query_builder" repository = "https://github.com/belchior/sql_query_builder" authors = ["Belchior Oliveira "] -version = "2.4.0" +version = "2.4.1" edition = "2021" rust-version = "1.62" license = "MIT" -keywords = ["sql", "query", "postgres", "sqlite"] +keywords = ["sql", "query", "database", "postgres", "sqlite"] [features] postgresql = [] @@ -20,4 +20,4 @@ rustdoc-args = ["--cfg", "docsrs"] features = ["postgresql", "sqlite"] [dev-dependencies] -pretty_assertions = "1.4.0" +pretty_assertions = "=1.4.0"