Overhaul query API, removing the need for the _named variants of all functions, and rusqlite::NO_PARAMS

This commit is contained in:
Thom Chiovoloni
2020-11-02 23:34:08 -08:00
parent c45446ba73
commit 032aea73b8
10 changed files with 680 additions and 328 deletions

View File

@@ -77,6 +77,7 @@ pub use crate::ffi::ErrorCode;
pub use crate::hooks::Action;
#[cfg(feature = "load_extension")]
pub use crate::load_extension_guard::LoadExtensionGuard;
pub use crate::params::{params_from_iter, Params, ParamsFromIter};
pub use crate::row::{AndThenRows, Map, MappedRows, Row, RowIndex, Rows};
pub use crate::statement::{Statement, StatementStatus};
pub use crate::transaction::{DropBehavior, Savepoint, Transaction, TransactionBehavior};
@@ -107,6 +108,7 @@ mod inner_connection;
pub mod limits;
#[cfg(feature = "load_extension")]
mod load_extension_guard;
mod params;
mod pragma;
mod raw_statement;
mod row;
@@ -127,11 +129,20 @@ pub(crate) use util::SmallCString;
// Number of cached prepared statements we'll hold on to.
const STATEMENT_CACHE_DEFAULT_CAPACITY: usize = 16;
/// To be used when your statement has no [parameter](https://sqlite.org/lang_expr.html#varparam).
/// To be used when your statement has no [parameter][sqlite-varparam].
///
/// [sqlite-varparam]: https://sqlite.org/lang_expr.html#varparam
///
/// Note that for most uses this is no longer necessary, and an empty array
/// should be used instead.
///
/// That is, in previous rusqlite releases you would need to do
/// `conn.execute(rusqlite::NO_PARAMS)`, however you can now do
/// `conn.execute([])` which is equivalent.
pub const NO_PARAMS: &[&dyn ToSql] = &[];
/// A macro making it more convenient to pass heterogeneous lists
/// of parameters as a `&[&dyn ToSql]`.
/// A macro making it more convenient to pass heterogeneous or long lists of
/// parameters as a `&[&dyn ToSql]`.
///
/// # Example
///
@@ -191,12 +202,12 @@ macro_rules! params {
#[macro_export]
macro_rules! named_params {
() => {
&[]
(&[] as &[(&str, &dyn $crate::ToSql)])
};
// Note: It's a lot more work to support this as part of the same macro as
// `params!`, unfortunately.
($($param_name:literal: $param_val:expr),+ $(,)?) => {
&[$(($param_name, &$param_val as &dyn $crate::ToSql)),+]
(&[$(($param_name, &$param_val as &dyn $crate::ToSql)),+] as &[(&str, &dyn $crate::ToSql)])
};
}
@@ -471,25 +482,47 @@ impl Connection {
///
/// ## Example
///
/// ### With positional params
///
/// ```rust,no_run
/// # use rusqlite::{Connection};
/// fn update_rows(conn: &Connection) {
/// match conn.execute("UPDATE foo SET bar = 'baz' WHERE qux = ?", &[1i32]) {
/// match conn.execute("UPDATE foo SET bar = 'baz' WHERE qux = ?", [1i32]) {
/// Ok(updated) => println!("{} rows were updated", updated),
/// Err(err) => println!("update failed: {}", err),
/// }
/// }
/// ```
///
/// ### With positional params of varying types
///
/// ```rust,no_run
/// # use rusqlite::{Connection};
/// fn update_rows(conn: &Connection) {
/// match conn.execute("UPDATE foo SET bar = 'baz' WHERE qux = ?", [1i32]) {
/// Ok(updated) => println!("{} rows were updated", updated),
/// Err(err) => println!("update failed: {}", err),
/// }
/// }
/// ```
///
/// ### With named params
///
/// ```rust,no_run
/// # use rusqlite::{Connection, Result};
/// fn insert(conn: &Connection) -> Result<usize> {
/// conn.execute_named(
/// "INSERT INTO test (name) VALUES (:name)",
/// rusqlite::named_params!{ ":name": "one" },
/// )
/// }
/// ```
///
/// # Failure
///
/// Will return `Err` if `sql` cannot be converted to a C-compatible string
/// or if the underlying SQLite call fails.
pub fn execute<P>(&self, sql: &str, params: P) -> Result<usize>
where
P: IntoIterator,
P::Item: ToSql,
{
pub fn execute<P: Params>(&self, sql: &str, params: P) -> Result<usize> {
self.prepare(sql)
.and_then(|mut stmt| stmt.check_no_tail().and_then(|_| stmt.execute(params)))
}
@@ -500,23 +533,14 @@ impl Connection {
/// On success, returns the number of rows that were changed or inserted or
/// deleted (via `sqlite3_changes`).
///
/// ## Example
///
/// ```rust,no_run
/// # use rusqlite::{Connection, Result};
/// fn insert(conn: &Connection) -> Result<usize> {
/// conn.execute_named(
/// "INSERT INTO test (name) VALUES (:name)",
/// &[(":name", &"one")],
/// )
/// }
/// ```
///
/// # Failure
///
/// Will return `Err` if `sql` cannot be converted to a C-compatible string
/// or if the underlying SQLite call fails.
#[deprecated = "You can use `execute` with named params now."]
pub fn execute_named(&self, sql: &str, params: &[(&str, &dyn ToSql)]) -> Result<usize> {
// This function itself is deprecated, so it's fine
#![allow(deprecated)]
self.prepare(sql).and_then(|mut stmt| {
stmt.check_no_tail()
.and_then(|_| stmt.execute_named(params))
@@ -537,11 +561,11 @@ impl Connection {
/// ## Example
///
/// ```rust,no_run
/// # use rusqlite::{Result,Connection, NO_PARAMS};
/// # use rusqlite::{Result, Connection};
/// fn preferred_locale(conn: &Connection) -> Result<String> {
/// conn.query_row(
/// "SELECT value FROM preferences WHERE name='locale'",
/// NO_PARAMS,
/// [],
/// |row| row.get(0),
/// )
/// }
@@ -560,8 +584,7 @@ impl Connection {
/// or if the underlying SQLite call fails.
pub fn query_row<T, P, F>(&self, sql: &str, params: P, f: F) -> Result<T>
where
P: IntoIterator,
P::Item: ToSql,
P: Params,
F: FnOnce(&Row<'_>) -> Result<T>,
{
let mut stmt = self.prepare(sql)?;
@@ -583,13 +606,12 @@ impl Connection {
///
/// Will return `Err` if `sql` cannot be converted to a C-compatible string
/// or if the underlying SQLite call fails.
#[deprecated = "You can use `query_row` with named params now."]
pub fn query_row_named<T, F>(&self, sql: &str, params: &[(&str, &dyn ToSql)], f: F) -> Result<T>
where
F: FnOnce(&Row<'_>) -> Result<T>,
{
let mut stmt = self.prepare(sql)?;
stmt.check_no_tail()?;
stmt.query_row_named(params, f)
self.query_row(sql, params, f)
}
/// Convenience method to execute a query that is expected to return a
@@ -600,11 +622,11 @@ impl Connection {
/// ## Example
///
/// ```rust,no_run
/// # use rusqlite::{Result,Connection, NO_PARAMS};
/// # use rusqlite::{Result, Connection};
/// fn preferred_locale(conn: &Connection) -> Result<String> {
/// conn.query_row_and_then(
/// "SELECT value FROM preferences WHERE name='locale'",
/// NO_PARAMS,
/// [],
/// |row| row.get(0),
/// )
/// }
@@ -619,8 +641,7 @@ impl Connection {
/// or if the underlying SQLite call fails.
pub fn query_row_and_then<T, E, P, F>(&self, sql: &str, params: P, f: F) -> Result<T, E>
where
P: IntoIterator,
P::Item: ToSql,
P: Params,
F: FnOnce(&Row<'_>) -> Result<T, E>,
E: convert::From<Error>,
{
@@ -1039,13 +1060,13 @@ mod test {
let tx2 = db2.transaction().unwrap();
// SELECT first makes sqlite lock with a shared lock
tx1.query_row("SELECT x FROM foo LIMIT 1", NO_PARAMS, |_| Ok(()))
tx1.query_row("SELECT x FROM foo LIMIT 1", [], |_| Ok(()))
.unwrap();
tx2.query_row("SELECT x FROM foo LIMIT 1", NO_PARAMS, |_| Ok(()))
tx2.query_row("SELECT x FROM foo LIMIT 1", [], |_| Ok(()))
.unwrap();
tx1.execute("INSERT INTO foo VALUES(?1)", &[1]).unwrap();
let _ = tx2.execute("INSERT INTO foo VALUES(?1)", &[2]);
tx1.execute("INSERT INTO foo VALUES(?1)", &[&1]).unwrap();
let _ = tx2.execute("INSERT INTO foo VALUES(?1)", [2]);
let _ = tx1.commit();
let _ = tx2.commit();
@@ -1075,7 +1096,7 @@ mod test {
let path_string = path.to_str().unwrap();
let db = Connection::open(&path_string).unwrap();
let the_answer: Result<i64> = db.query_row("SELECT x FROM foo", NO_PARAMS, |r| r.get(0));
let the_answer: Result<i64> = db.query_row("SELECT x FROM foo", [], |r| r.get(0));
assert_eq!(42i64, the_answer.unwrap());
}
@@ -1132,7 +1153,7 @@ mod test {
}
let db = Connection::open(&db_path).unwrap();
let the_answer: Result<i64> = db.query_row("SELECT x FROM foo", NO_PARAMS, |r| r.get(0));
let the_answer: Result<i64> = db.query_row("SELECT x FROM foo", [], |r| r.get(0));
assert_eq!(42i64, the_answer.unwrap());
}
@@ -1214,18 +1235,16 @@ mod test {
assert_eq!(
1,
db.execute("INSERT INTO foo(x) VALUES (?)", &[1i32])
.unwrap()
db.execute("INSERT INTO foo(x) VALUES (?)", [1i32]).unwrap()
);
assert_eq!(
1,
db.execute("INSERT INTO foo(x) VALUES (?)", &[2i32])
.unwrap()
db.execute("INSERT INTO foo(x) VALUES (?)", [2i32]).unwrap()
);
assert_eq!(
3i32,
db.query_row::<i32, _, _>("SELECT SUM(x) FROM foo", NO_PARAMS, |r| r.get(0))
db.query_row::<i32, _, _>("SELECT SUM(x) FROM foo", [], |r| r.get(0))
.unwrap()
);
}
@@ -1234,7 +1253,7 @@ mod test {
#[cfg(feature = "extra_check")]
fn test_execute_select() {
let db = checked_memory_handle();
let err = db.execute("SELECT 1 WHERE 1 < ?", &[1i32]).unwrap_err();
let err = db.execute("SELECT 1 WHERE 1 < ?", [1i32]).unwrap_err();
if err != Error::ExecuteReturnedResults {
panic!("Unexpected error: {}", err);
}
@@ -1247,7 +1266,7 @@ mod test {
let err = db
.execute(
"CREATE TABLE foo(x INTEGER); CREATE TABLE foo(x INTEGER)",
NO_PARAMS,
[],
)
.unwrap_err();
match err {
@@ -1276,18 +1295,18 @@ mod test {
db.execute_batch("CREATE TABLE foo(x INTEGER);").unwrap();
let mut insert_stmt = db.prepare("INSERT INTO foo(x) VALUES(?)").unwrap();
assert_eq!(insert_stmt.execute(&[1i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute(&[2i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute(&[3i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute([1i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute([2i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute([3i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute(&["hello".to_string()]).unwrap(), 1);
assert_eq!(insert_stmt.execute(&["goodbye".to_string()]).unwrap(), 1);
assert_eq!(insert_stmt.execute(&[types::Null]).unwrap(), 1);
assert_eq!(insert_stmt.execute(["hello".to_string()]).unwrap(), 1);
assert_eq!(insert_stmt.execute(["goodbye".to_string()]).unwrap(), 1);
assert_eq!(insert_stmt.execute([types::Null]).unwrap(), 1);
let mut update_stmt = db.prepare("UPDATE foo SET x=? WHERE x<?").unwrap();
assert_eq!(update_stmt.execute(&[3i32, 3i32]).unwrap(), 2);
assert_eq!(update_stmt.execute(&[3i32, 3i32]).unwrap(), 0);
assert_eq!(update_stmt.execute(&[8i32, 8i32]).unwrap(), 3);
assert_eq!(update_stmt.execute([3i32, 3i32]).unwrap(), 2);
assert_eq!(update_stmt.execute([3i32, 3i32]).unwrap(), 0);
assert_eq!(update_stmt.execute([8i32, 8i32]).unwrap(), 3);
}
#[test]
@@ -1296,15 +1315,15 @@ mod test {
db.execute_batch("CREATE TABLE foo(x INTEGER);").unwrap();
let mut insert_stmt = db.prepare("INSERT INTO foo(x) VALUES(?)").unwrap();
assert_eq!(insert_stmt.execute(&[1i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute(&[2i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute(&[3i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute([1i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute([2i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute([3i32]).unwrap(), 1);
let mut query = db
.prepare("SELECT x FROM foo WHERE x < ? ORDER BY x DESC")
.unwrap();
{
let mut rows = query.query(&[4i32]).unwrap();
let mut rows = query.query([4i32]).unwrap();
let mut v = Vec::<i32>::new();
while let Some(row) = rows.next().unwrap() {
@@ -1315,7 +1334,7 @@ mod test {
}
{
let mut rows = query.query(&[3i32]).unwrap();
let mut rows = query.query([3i32]).unwrap();
let mut v = Vec::<i32>::new();
while let Some(row) = rows.next().unwrap() {
@@ -1339,11 +1358,7 @@ mod test {
db.execute_batch(sql).unwrap();
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
let results: Result<Vec<String>> = query
.query(NO_PARAMS)
.unwrap()
.map(|row| row.get(1))
.collect();
let results: Result<Vec<String>> = query.query([]).unwrap().map(|row| row.get(1)).collect();
assert_eq!(results.unwrap().concat(), "hello, world!");
}
@@ -1362,18 +1377,17 @@ mod test {
assert_eq!(
10i64,
db.query_row::<i64, _, _>("SELECT SUM(x) FROM foo", NO_PARAMS, |r| r.get(0))
db.query_row::<i64, _, _>("SELECT SUM(x) FROM foo", [], |r| r.get(0))
.unwrap()
);
let result: Result<i64> =
db.query_row("SELECT x FROM foo WHERE x > 5", NO_PARAMS, |r| r.get(0));
let result: Result<i64> = db.query_row("SELECT x FROM foo WHERE x > 5", [], |r| r.get(0));
match result.unwrap_err() {
Error::QueryReturnedNoRows => (),
err => panic!("Unexpected error {}", err),
}
let bad_query_result = db.query_row("NOT A PROPER QUERY; test123", NO_PARAMS, |_| Ok(()));
let bad_query_result = db.query_row("NOT A PROPER QUERY; test123", [], |_| Ok(()));
assert!(bad_query_result.is_err());
}
@@ -1382,22 +1396,21 @@ mod test {
fn test_optional() {
let db = checked_memory_handle();
let result: Result<i64> = db.query_row("SELECT 1 WHERE 0 <> 0", NO_PARAMS, |r| r.get(0));
let result: Result<i64> = db.query_row("SELECT 1 WHERE 0 <> 0", [], |r| r.get(0));
let result = result.optional();
match result.unwrap() {
None => (),
_ => panic!("Unexpected result"),
}
let result: Result<i64> = db.query_row("SELECT 1 WHERE 0 == 0", NO_PARAMS, |r| r.get(0));
let result: Result<i64> = db.query_row("SELECT 1 WHERE 0 == 0", [], |r| r.get(0));
let result = result.optional();
match result.unwrap() {
Some(1) => (),
_ => panic!("Unexpected result"),
}
let bad_query_result: Result<i64> =
db.query_row("NOT A PROPER QUERY", NO_PARAMS, |r| r.get(0));
let bad_query_result: Result<i64> = db.query_row("NOT A PROPER QUERY", [], |r| r.get(0));
let bad_query_result = bad_query_result.optional();
assert!(bad_query_result.is_err());
}
@@ -1408,12 +1421,12 @@ mod test {
assert_eq!(
"memory",
db.query_row::<String, _, _>("PRAGMA journal_mode", NO_PARAMS, |r| r.get(0))
db.query_row::<String, _, _>("PRAGMA journal_mode", [], |r| r.get(0))
.unwrap()
);
assert_eq!(
"off",
db.query_row::<String, _, _>("PRAGMA journal_mode=off", NO_PARAMS, |r| r.get(0))
db.query_row::<String, _, _>("PRAGMA journal_mode=off", [], |r| r.get(0))
.unwrap()
);
}
@@ -1438,7 +1451,7 @@ mod test {
let mut stmt = db.prepare("INSERT INTO foo DEFAULT VALUES").unwrap();
for _ in 0i32..9 {
stmt.execute(NO_PARAMS).unwrap();
stmt.execute([]).unwrap();
}
assert_eq!(db.last_insert_rowid(), 10);
}
@@ -1460,7 +1473,7 @@ mod test {
let mut stmt = db.prepare("PRAGMA schema_version").unwrap();
assert!(!db.is_busy());
{
let mut rows = stmt.query(NO_PARAMS).unwrap();
let mut rows = stmt.query([]).unwrap();
assert!(!db.is_busy());
let row = rows.next().unwrap();
assert!(db.is_busy());
@@ -1492,7 +1505,7 @@ mod test {
let db = checked_memory_handle();
db.execute_batch("CREATE TABLE foo(x NOT NULL)").unwrap();
let result = db.execute("INSERT INTO foo (x) VALUES (NULL)", NO_PARAMS);
let result = db.execute("INSERT INTO foo (x) VALUES (NULL)", []);
assert!(result.is_err());
match result.unwrap_err() {
@@ -1536,7 +1549,7 @@ mod test {
.prepare("SELECT interrupt() FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)")
.unwrap();
let result: Result<Vec<i32>> = stmt.query(NO_PARAMS).unwrap().map(|r| r.get(0)).collect();
let result: Result<Vec<i32>> = stmt.query([]).unwrap().map(|r| r.get(0)).collect();
match result.unwrap_err() {
Error::SqliteFailure(err, _) => {
@@ -1576,7 +1589,7 @@ mod test {
}
let mut query = db.prepare("SELECT i, x FROM foo").unwrap();
let mut rows = query.query(NO_PARAMS).unwrap();
let mut rows = query.query([]).unwrap();
while let Some(row) = rows.next().unwrap() {
let i = row.get_raw(0).as_i64().unwrap();
@@ -1651,7 +1664,7 @@ mod test {
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
let results: Result<Vec<String>> = query
.query_and_then(NO_PARAMS, |row| row.get(1))
.query_and_then([], |row| row.get(1))
.unwrap()
.collect();
@@ -1672,7 +1685,7 @@ mod test {
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
let bad_type: Result<Vec<f64>> = query
.query_and_then(NO_PARAMS, |row| row.get(1))
.query_and_then([], |row| row.get(1))
.unwrap()
.collect();
@@ -1682,7 +1695,7 @@ mod test {
}
let bad_idx: Result<Vec<String>> = query
.query_and_then(NO_PARAMS, |row| row.get(3))
.query_and_then([], |row| row.get(3))
.unwrap()
.collect();
@@ -1706,7 +1719,7 @@ mod test {
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
let results: CustomResult<Vec<String>> = query
.query_and_then(NO_PARAMS, |row| row.get(1).map_err(CustomError::Sqlite))
.query_and_then([], |row| row.get(1).map_err(CustomError::Sqlite))
.unwrap()
.collect();
@@ -1727,7 +1740,7 @@ mod test {
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
let bad_type: CustomResult<Vec<f64>> = query
.query_and_then(NO_PARAMS, |row| row.get(1).map_err(CustomError::Sqlite))
.query_and_then([], |row| row.get(1).map_err(CustomError::Sqlite))
.unwrap()
.collect();
@@ -1737,7 +1750,7 @@ mod test {
}
let bad_idx: CustomResult<Vec<String>> = query
.query_and_then(NO_PARAMS, |row| row.get(3).map_err(CustomError::Sqlite))
.query_and_then([], |row| row.get(3).map_err(CustomError::Sqlite))
.unwrap()
.collect();
@@ -1747,7 +1760,7 @@ mod test {
}
let non_sqlite_err: CustomResult<Vec<String>> = query
.query_and_then(NO_PARAMS, |_| Err(CustomError::SomeError))
.query_and_then([], |_| Err(CustomError::SomeError))
.unwrap()
.collect();
@@ -1767,9 +1780,8 @@ mod test {
db.execute_batch(sql).unwrap();
let query = "SELECT x, y FROM foo ORDER BY x DESC";
let results: CustomResult<String> = db.query_row_and_then(query, NO_PARAMS, |row| {
row.get(1).map_err(CustomError::Sqlite)
});
let results: CustomResult<String> =
db.query_row_and_then(query, [], |row| row.get(1).map_err(CustomError::Sqlite));
assert_eq!(results.unwrap(), "hello");
}
@@ -1784,18 +1796,16 @@ mod test {
db.execute_batch(sql).unwrap();
let query = "SELECT x, y FROM foo ORDER BY x DESC";
let bad_type: CustomResult<f64> = db.query_row_and_then(query, NO_PARAMS, |row| {
row.get(1).map_err(CustomError::Sqlite)
});
let bad_type: CustomResult<f64> =
db.query_row_and_then(query, [], |row| row.get(1).map_err(CustomError::Sqlite));
match bad_type.unwrap_err() {
CustomError::Sqlite(Error::InvalidColumnType(..)) => (),
err => panic!("Unexpected error {}", err),
}
let bad_idx: CustomResult<String> = db.query_row_and_then(query, NO_PARAMS, |row| {
row.get(3).map_err(CustomError::Sqlite)
});
let bad_idx: CustomResult<String> =
db.query_row_and_then(query, [], |row| row.get(3).map_err(CustomError::Sqlite));
match bad_idx.unwrap_err() {
CustomError::Sqlite(Error::InvalidColumnIndex(_)) => (),
@@ -1803,7 +1813,7 @@ mod test {
}
let non_sqlite_err: CustomResult<String> =
db.query_row_and_then(query, NO_PARAMS, |_| Err(CustomError::SomeError));
db.query_row_and_then(query, [], |_| Err(CustomError::SomeError));
match non_sqlite_err.unwrap_err() {
CustomError::SomeError => (),
@@ -1821,7 +1831,7 @@ mod test {
END;";
db.execute_batch(sql).unwrap();
db.query_row("SELECT * FROM foo", NO_PARAMS, |r| {
db.query_row("SELECT * FROM foo", [], |r| {
assert_eq!(2, r.column_count());
Ok(())
})
@@ -1832,8 +1842,8 @@ mod test {
let db = checked_memory_handle();
db.execute_batch("CREATE TABLE foo(x INTEGER);").unwrap();
let b: Box<dyn ToSql> = Box::new(5);
db.execute("INSERT INTO foo VALUES(?)", &[b]).unwrap();
db.query_row("SELECT x FROM foo", NO_PARAMS, |r| {
db.execute("INSERT INTO foo VALUES(?)", [b]).unwrap();
db.query_row("SELECT x FROM foo", [], |r| {
assert_eq!(5, r.get_unwrap::<_, i32>(0));
Ok(())
})
@@ -1867,7 +1877,7 @@ mod test {
let db = checked_memory_handle();
db.execute_batch("CREATE TABLE x(t);").unwrap();
// `execute_batch` should be used but `execute` should also work
db.execute("ALTER TABLE x RENAME TO y;", NO_PARAMS).unwrap();
db.execute("ALTER TABLE x RENAME TO y;", []).unwrap();
}
#[test]
@@ -1880,7 +1890,7 @@ mod test {
let batch = Batch::new(&db, sql);
for stmt in batch {
let mut stmt = stmt.unwrap();
stmt.execute(NO_PARAMS).unwrap();
stmt.execute([]).unwrap();
}
}
}