diff --git a/src/behavior.rs b/src/behavior.rs index b9d4105..32f300b 100644 --- a/src/behavior.rs +++ b/src/behavior.rs @@ -44,27 +44,6 @@ pub(crate) trait ConcatSqlStandard { format!("{query}{raw_sql}{space}{lb}") } - fn concat_values( - &self, - items_raw_before: &Vec<(Clause, String)>, - items_raw_after: &Vec<(Clause, String)>, - query: String, - fmts: &fmt::Formatter, - clause: Clause, - items: &Vec, - ) -> String { - let fmt::Formatter { comma, lb, space, .. } = fmts; - let sql = if items.is_empty() == false { - let sep = format!("{comma}{lb}"); - let values = items.join(&sep); - format!("VALUES{space}{lb}{values}{space}{lb}") - } else { - "".to_string() - }; - - concat_raw_before_after(items_raw_before, items_raw_after, query, fmts, clause, sql) - } - fn concat_where( &self, items_raw_before: &Vec<(Clause, String)>, @@ -227,30 +206,6 @@ pub(crate) trait ConcatSqlite { concat_raw_before_after(items_raw_before, items_raw_after, query, fmts, clause, sql) } - - fn concat_values( - &self, - items_raw_before: &Vec<(InsertClause, String)>, - items_raw_after: &Vec<(InsertClause, String)>, - query: String, - fmts: &fmt::Formatter, - values: &Vec, - default_values: &bool, - ) -> String { - let fmt::Formatter { comma, lb, space, .. } = fmts; - - let (clause, sql) = if *default_values { - (InsertClause::DefaultValues, format!("DEFAULT VALUES{space}{lb}")) - } else if values.is_empty() == false { - let sep = format!("{comma}{lb}"); - let values = values.join(&sep); - (InsertClause::Values, format!("VALUES{space}{lb}{values}{space}{lb}")) - } else { - (InsertClause::Values, "".to_string()) - }; - - concat_raw_before_after(items_raw_before, items_raw_after, query, fmts, clause, sql) - } } impl std::fmt::Display for LogicalOperator { diff --git a/src/insert/insert.rs b/src/insert/insert.rs index 46769ec..d1f792c 100644 --- a/src/insert/insert.rs +++ b/src/insert/insert.rs @@ -65,6 +65,31 @@ impl Insert { self } + /// The `default values` clause + /// + /// # Example + /// + /// ``` + /// # use sql_query_builder as sql; + /// let insert_query = sql::Insert::new() + /// .insert_into("users") + /// .default_values() + /// .to_string(); + /// + /// # let expected = "INSERT INTO users DEFAULT VALUES"; + /// # assert_eq!(insert_query, expected); + /// ``` + /// + /// Output + /// + /// ```sql + /// INSERT INTO users DEFAULT VALUES + /// ``` + pub fn default_values(mut self) -> Self { + self._default_values = true; + self + } + /// The `insert into` clause. This method overrides the previous value /// /// # Example @@ -381,34 +406,6 @@ impl Insert { #[cfg(any(doc, feature = "sqlite"))] impl Insert { - /// The `default values` clause, this method can be used enabling the feature flag `sqlite` - /// - /// # Example - /// - /// ``` - /// # #[cfg(feature = "sqlite")] - /// # { - /// # use sql_query_builder as sql; - /// let insert_query = sql::Insert::new() - /// .insert_into("users") - /// .default_values() - /// .to_string(); - /// - /// # let expected = "INSERT INTO users DEFAULT VALUES"; - /// # assert_eq!(insert_query, expected); - /// # } - /// ``` - /// - /// Output - /// - /// ```sql - /// INSERT INTO users DEFAULT VALUES - /// ``` - pub fn default_values(mut self) -> Self { - self._default_values = true; - self - } - /// The `insert into` clause, this method overrides the previous value and can be used enabling the feature flag `sqlite` #[cfg(not(doc))] pub fn insert_into(mut self, expression: &str) -> Self { diff --git a/src/insert/insert_internal.rs b/src/insert/insert_internal.rs index b2e994d..69781ad 100644 --- a/src/insert/insert_internal.rs +++ b/src/insert/insert_internal.rs @@ -1,6 +1,6 @@ #[cfg(any(feature = "postgresql", feature = "sqlite"))] use crate::behavior::ConcatCommon; -#[cfg(any(feature = "sqlite"))] +#[cfg(feature = "sqlite")] use crate::behavior::ConcatSqlite; use crate::{ behavior::{concat_raw_before_after, Concat, ConcatSqlStandard}, @@ -87,6 +87,22 @@ impl Insert { sql, ) } + + fn concat_values(&self, query: String, fmts: &fmt::Formatter) -> String { + let fmt::Formatter { comma, lb, space, .. } = fmts; + + let (clause, sql) = if self._default_values { + (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); + (InsertClause::Values, format!("VALUES{space}{lb}{values}{space}{lb}")) + } else { + (InsertClause::Values, "".to_string()) + }; + + concat_raw_before_after(&self._raw_before, &self._raw_after, query, fmts, clause, sql) + } } impl Concat for Insert { @@ -118,32 +134,10 @@ impl Concat for Insert { query = self.concat_overriding(query, &fmts); - #[cfg(not(feature = "sqlite"))] - { - query = ConcatSqlStandard::concat_values( - self, - &self._raw_before, - &self._raw_after, - query, - &fmts, - InsertClause::Values, - &self._values, - ); - } - #[cfg(feature = "sqlite")] - { - query = ConcatSqlite::concat_values( - self, - &self._raw_before, - &self._raw_after, - query, - &fmts, - &self._values, - &self._default_values, - ); - } + query = self.concat_values(query, &fmts); query = self.concat_select(query, &fmts); + query = self.concat_on_conflict(query, &fmts); #[cfg(any(feature = "postgresql", feature = "sqlite"))] diff --git a/src/structure.rs b/src/structure.rs index ea558c6..187c0f4 100644 --- a/src/structure.rs +++ b/src/structure.rs @@ -52,6 +52,7 @@ pub enum DeleteClause { /// Builder to contruct a [Insert] command #[derive(Default, Clone)] pub struct Insert { + pub(crate) _default_values: bool, pub(crate) _on_conflict: String, pub(crate) _overriding: String, pub(crate) _raw_after: Vec<(InsertClause, String)>, @@ -69,9 +70,6 @@ pub struct Insert { pub(crate) _insert_into: String, #[cfg(feature = "sqlite")] pub(crate) _insert: (InsertVars, String), - - #[cfg(feature = "sqlite")] - pub(crate) _default_values: bool, } #[cfg(feature = "sqlite")] @@ -97,6 +95,7 @@ pub(crate) enum InsertVars { /// ``` #[derive(PartialEq, Clone)] pub enum InsertClause { + DefaultValues, InsertInto, OnConflict, Overriding, @@ -107,12 +106,11 @@ pub enum InsertClause { Returning, #[cfg(any(feature = "postgresql", feature = "sqlite"))] With, - #[cfg(any(feature = "sqlite"))] + + #[cfg(feature = "sqlite")] InsertOr, - #[cfg(any(feature = "sqlite"))] + #[cfg(feature = "sqlite")] ReplaceInto, - #[cfg(any(feature = "sqlite"))] - DefaultValues, } #[derive(Clone, PartialEq)] diff --git a/src/values/values_internal.rs b/src/values/values_internal.rs index ed4c076..147b7dd 100644 --- a/src/values/values_internal.rs +++ b/src/values/values_internal.rs @@ -1,24 +1,40 @@ use crate::{ - behavior::{Concat, ConcatSqlStandard}, + behavior::{concat_raw_before_after, Concat, ConcatSqlStandard}, fmt, structure::{Values, ValuesClause}, }; impl ConcatSqlStandard for Values {} -impl Concat for Values { - fn concat(&self, fmts: &fmt::Formatter) -> String { - let mut query = "".to_string(); +impl Values { + fn concat_values(&self, query: String, fmts: &fmt::Formatter) -> String { + 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); + format!("VALUES{space}{lb}{values}{space}{lb}") + } else { + "".to_string() + }; - query = self.concat_raw(query, &fmts, &self._raw); - query = self.concat_values( + concat_raw_before_after( &self._raw_before, &self._raw_after, query, - &fmts, + fmts, ValuesClause::Values, - &self._values, - ); + sql, + ) + } +} + +impl Concat for Values { + fn concat(&self, fmts: &fmt::Formatter) -> String { + let mut query = "".to_string(); + + query = self.concat_raw(query, &fmts, &self._raw); + + query = self.concat_values(query, &fmts); query.trim_end().to_string() } diff --git a/tests/clause_default_values_spec.rs b/tests/clause_default_values_spec.rs index 422554f..bd28f80 100644 --- a/tests/clause_default_values_spec.rs +++ b/tests/clause_default_values_spec.rs @@ -1,4 +1,3 @@ -#[cfg(feature = "sqlite")] mod insert_command { use pretty_assertions::assert_eq; use sql_query_builder as sql; diff --git a/tests/clause_insert_or_spec.rs b/tests/clause_insert_or_spec.rs index 7f47a78..8bab176 100644 --- a/tests/clause_insert_or_spec.rs +++ b/tests/clause_insert_or_spec.rs @@ -24,6 +24,14 @@ mod insert_command { assert_eq!(query, expected_query); } + #[test] + fn method_insert_or_should_not_add_clause_when_argument_is_empty() { + let query = sql::Insert::new().insert_or("").as_string(); + let expected_query = ""; + + assert_eq!(query, expected_query); + } + #[test] fn method_insert_or_should_trim_space_of_the_argument() { let query = sql::Insert::new().insert_or(" IGNORE INTO users (name) ").as_string(); diff --git a/tests/clause_replace_into_spec.rs b/tests/clause_replace_into_spec.rs index dea57c6..f1d7257 100644 --- a/tests/clause_replace_into_spec.rs +++ b/tests/clause_replace_into_spec.rs @@ -22,6 +22,14 @@ mod insert_command { assert_eq!(query, expected_query); } + #[test] + fn method_replace_into_should_not_add_clause_when_argument_is_empty() { + let query = sql::Insert::new().replace_into("").as_string(); + let expected_query = ""; + + assert_eq!(query, expected_query); + } + #[test] fn method_replace_into_should_trim_space_of_the_argument() { let query = sql::Insert::new().replace_into(" users (name) ").as_string(); diff --git a/tests/clause_update_or_spec.rs b/tests/clause_update_or_spec.rs index f5a47f3..29db255 100644 --- a/tests/clause_update_or_spec.rs +++ b/tests/clause_update_or_spec.rs @@ -41,6 +41,14 @@ mod update_command { assert_eq!(query, expected_query); } + #[test] + fn method_update_or_should_not_add_clause_when_argument_is_empty() { + let query = sql::Update::new().update_or("").as_string(); + let expected_query = ""; + + assert_eq!(query, expected_query); + } + #[test] fn method_update_or_should_trim_space_of_the_argument() { let query = sql::Update::new().update_or(" REPLACE orders ").as_string();