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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion scripts/coverage_test.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#!/bin/sh

# Prerequisites
# cargo install rustfilt cargo-binutils
# rustup override set 1.82.0
# cargo install rustfilt@0.2.1 cargo-binutils@0.3.6
# rustup component add llvm-tools-preview
clear

Expand Down
2 changes: 1 addition & 1 deletion scripts/test.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/sh

test_names=$(git status -s | grep 'A tests/\|M tests/' | sed -e 's/.* //' -e 's/tests\//--test /' -e 's/\.rs//' | tr '\n' ' ')
test_names=$(git status -s | grep 'A[[:space:]]*tests/\|M[[:space:]]*tests/' | sed -e 's/.* //' -e 's/tests\//--test /' -e 's/\.rs//' | tr '\n' ' ')

clear
echo "\n-- ------------------------------------------------------------------------------"
Expand Down
2 changes: 1 addition & 1 deletion scripts/watch_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

all_features='postgresql sqlite mysql'
features=''
test_names=$(git status -s | grep 'A tests/\|M tests/' | sed -e 's/.* //' -e 's/tests\//--test /' -e 's/\.rs//' | tr '\n' ' ')
test_names=$(git status -s | grep 'A[[:space:]]*tests/\|M[[:space:]]*tests/' | sed -e 's/.* //' -e 's/tests\//--test /' -e 's/\.rs//' | tr '\n' ' ')

case "$@" in
"") features="";;
Expand Down
1 change: 1 addition & 0 deletions src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ pub fn colorize(query: String) -> String {
(blue, "RETURNING", "returning"),
(blue, "RIGHT", "right"),
(blue, "ROLLBACK", "rollback"),
(blue, "ROW", "row"),
(blue, "SAVEPOINT", "savepoint"),
(blue, "SELECT ", "select "),
(blue, "SERIALIZABLE", "serializable"),
Expand Down
34 changes: 32 additions & 2 deletions src/insert/insert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,8 @@ impl Insert {
/// ```sql
/// INSERT INTO users (login, name) VALUES ('foo', 'Foo'), ('bar', 'Bar')
/// ```
pub fn values(mut self, value: &str) -> Self {
push_unique(&mut self._values, value.trim().to_string());
pub fn values(mut self, expression: &str) -> Self {
push_unique(&mut self._values, expression.trim().to_string());
#[cfg(not(feature = "mysql"))]
{
self._default_values = false
Expand Down Expand Up @@ -663,6 +663,36 @@ impl Insert {
self
}

/// The `values` clause with the `row` constructor clause
///
/// # Example
///
/// ```
/// # #[cfg(feature = "mysql")]
/// # {
/// # use sql_query_builder as sql;
/// let query = sql::Insert::new()
/// .insert_into("users (login, name)")
/// .row("('foo', 'Foo')")
/// .row("('bar', 'Bar')")
/// .as_string();
///
/// # let expected = "INSERT INTO users (login, name) VALUES ROW('foo', 'Foo'), ROW('bar', 'Bar')";
/// # assert_eq!(expected, query);
/// # }
/// ```
///
/// Output
///
/// ```sql
/// INSERT INTO users (login, name) VALUES ROW('foo', 'Foo'), ROW('bar', 'Bar')
/// ```
pub fn row(mut self, expression: &str) -> Self {
push_unique(&mut self._values, expression.trim().to_string());
self._use_row = true;
self
}

/// The `set` clause
///
/// # Example
Expand Down
27 changes: 23 additions & 4 deletions src/insert/insert_internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::{
concat::{concat_raw_before_after, Concat},
fmt,
structure::{Insert, InsertClause},
utils,
};

impl Concat for Insert {
Expand Down Expand Up @@ -180,8 +179,25 @@ impl Insert {
let fmt::Formatter { comma, lb, space, .. } = fmts;
let sql = if self._values.is_empty() == false {
let sep = format!("{comma}{lb}");
let values = utils::join(&self._values, &sep);
format!("VALUES{space}{lb}{values}{space}{lb}")
let rows = self
._values
.iter()
.filter(|item| item.is_empty() == false)
.map(|item| {
if self._use_row {
format!("ROW{item}")
} else {
item.clone()
}
})
.collect::<Vec<_>>()
.join(&sep);

if rows.is_empty() == true {
return "".to_string();
}

format!("VALUES{space}{lb}{rows}{space}{lb}")
} else {
"".to_string()
};
Expand Down Expand Up @@ -269,7 +285,10 @@ impl Insert {
}

#[cfg(feature = "mysql")]
use crate::concat::{mysql::ConcatPartition, non_standard::ConcatColumn, sql_standard::ConcatSet};
use crate::{
concat::{mysql::ConcatPartition, non_standard::ConcatColumn, sql_standard::ConcatSet},
utils,
};

#[cfg(feature = "mysql")]
impl ConcatColumn<InsertClause> for Insert {}
Expand Down
4 changes: 4 additions & 0 deletions src/structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ pub struct Insert {
pub(crate) _raw: Vec<String>,
pub(crate) _select: Option<Select>,
pub(crate) _values: Vec<String>,
pub(crate) _use_row: bool,

#[cfg(any(feature = "postgresql", feature = "sqlite"))]
pub(crate) _on_conflict: String,
Expand Down Expand Up @@ -858,6 +859,8 @@ pub enum UpdateClause {
/// Basic API
///
/// ```
/// # #[cfg(not(feature = "mysql"))]
/// # {
/// use sql_query_builder as sql;
///
/// let query = sql::Values::new()
Expand All @@ -867,6 +870,7 @@ pub enum UpdateClause {
///
/// # let expected = "VALUES ('foo', 'Foo'), ('bar', 'Bar')";
/// # assert_eq!(expected, query);
/// # }
/// ```
///
/// Output
Expand Down
60 changes: 54 additions & 6 deletions src/values/values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ impl Values {
/// # Example
///
/// ```
/// # #[cfg(not(feature = "mysql"))]
/// # {
/// # use sql_query_builder as sql;
/// let values_query = sql::Values::new()
/// .values("('foo', 'Foo')")
/// .as_string();
///
/// # let expected = "VALUES ('foo', 'Foo')";
/// # assert_eq!(values_query, expected);
/// # assert_eq!(expected, values_query);
/// # }
/// ```
///
/// Output
Expand All @@ -42,14 +45,17 @@ impl Values {
/// # Example
///
/// ```
/// # #[cfg(not(feature = "mysql"))]
/// # {
/// # use sql_query_builder as sql;
/// let values = sql::Values::new()
/// .values("(1, 'one'), (2, 'two')")
/// .values("(3, 'three')")
/// .debug();
///
/// # let expected = "VALUES (1, 'one'), (2, 'two'), (3, 'three')";
/// # assert_eq!(values.as_string(), expected);
/// # assert_eq!(expected, values.as_string());
/// # }
/// ```
///
/// Prints to the standard output
Expand Down Expand Up @@ -83,6 +89,8 @@ impl Values {
/// # Example
///
/// ```
/// # #[cfg(not(feature = "mysql"))]
/// # {
/// # use sql_query_builder as sql;
/// let raw_query = "insert into my_table(num, txt)";
///
Expand All @@ -92,7 +100,8 @@ impl Values {
/// .as_string();
///
/// # let expected = "insert into my_table(num, txt) VALUES (1, 'one'), (2, 'two')";
/// # assert_eq!(values_query, expected);
/// # assert_eq!(expected, values_query);
/// # }
/// ```
///
/// Output
Expand All @@ -111,6 +120,8 @@ impl Values {
/// # Example
///
/// ```
/// # #[cfg(not(feature = "mysql"))]
/// # {
/// # use sql_query_builder as sql;
/// let raw_query = ", (3, 'three')";
///
Expand All @@ -120,7 +131,8 @@ impl Values {
/// .as_string();
///
/// # let expected = "VALUES (1, 'one'), (2, 'two') , (3, 'three')";
/// # assert_eq!(values_query, expected);
/// # assert_eq!(expected, values_query);
/// # }
/// ```
///
/// Output
Expand All @@ -138,6 +150,8 @@ impl Values {
/// # Example
///
/// ```
/// # #[cfg(not(feature = "mysql"))]
/// # {
/// # use sql_query_builder as sql;
/// let raw_query = "/* the values command */";
///
Expand All @@ -147,7 +161,8 @@ impl Values {
/// .as_string();
///
/// # let expected = "/* the values command */ VALUES (1, 'one'), (2, 'two')";
/// # assert_eq!(values_query, expected);
/// # assert_eq!(expected, values_query);
/// # }
/// ```
///
/// Output
Expand All @@ -166,27 +181,60 @@ impl Values {
/// # Example
///
/// ```
/// # #[cfg(not(feature = "mysql"))]
/// # {
/// # use sql_query_builder as sql;
/// let values_query = sql::Values::new()
/// .values("(1, 'one'), (2, 'two')")
/// .values("(3, 'three')")
/// .as_string();
///
/// # let expected = "VALUES (1, 'one'), (2, 'two'), (3, 'three')";
/// # assert_eq!(values_query, expected);
/// # assert_eq!(expected, values_query);
/// # }
/// ```
///
/// Output
///
/// ```sql
/// VALUES (1, 'one'), (2, 'two'), (3, 'three')
/// ```
#[cfg(not(feature = "mysql"))]
pub fn values(mut self, expression: &str) -> Self {
push_unique(&mut self._values, expression.trim().to_string());
self
}
}

#[cfg(feature = "mysql")]
#[cfg_attr(docsrs, doc(cfg(feature = "mysql")))]
impl Values {
/// The `values` clause with the `row` constructor clause
///
/// # Example
///
/// ```
/// # use sql_query_builder as sql;
/// let values_query = sql::Values::new()
/// .row("(1, 'one'), row(2, 'two')")
/// .row("(3, 'three')")
/// .as_string();
///
/// # let expected = "VALUES ROW(1, 'one'), row(2, 'two'), ROW(3, 'three')";
/// # assert_eq!(expected, values_query);
/// ```
///
/// Output
///
/// ```sql
/// VALUES ROW(1, 'one'), row(2, 'two'), ROW(3, 'three')
/// ```
pub fn row(mut self, expression: &str) -> Self {
push_unique(&mut self._values, expression.trim().to_string());
self
}
}

impl std::fmt::Display for Values {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.as_string())
Expand Down
20 changes: 17 additions & 3 deletions src/values/values_internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,28 @@ 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
let rows = self
._values
.iter()
.filter(|item| item.is_empty() == false)
.map(|item| item.as_str())
.map(|item| {
#[cfg(not(feature = "mysql"))]
{
item.clone()
}
#[cfg(feature = "mysql")]
{
format!("ROW{item}")
}
})
.collect::<Vec<_>>()
.join(&sep);
format!("VALUES{space}{lb}{values}{space}{lb}")

if rows.is_empty() == true {
return "".to_string();
};

format!("VALUES{space}{lb}{rows}{space}{lb}")
} else {
"".to_string()
};
Expand Down
Loading
Loading