mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-12-30 13:20:59 +00:00
* refactor: introduce `SqlSafeStr` API * rebase main * Add SqlStr + remove Statement lifetime * Update the definition of Executor and AnyConnectionBackend + update Postgres driver * Update MySql driver * Update Sqlite driver * remove debug clone count * Reduce the amount of SqlStr clones * improve QueryBuilder error message * cargo fmt * fix clippy warnings * fix doc test * Avoid panic in `QueryBuilder::reset` * Use `QueryBuilder` when removing all test db's * Add comment to `SqlStr` Co-authored-by: Austin Bonander <austin.bonander@gmail.com> * Update sqlx-core/src/query_builder.rs Co-authored-by: Austin Bonander <austin.bonander@gmail.com> * Add `Clone` as supertrait to `Statement` * Move `Connection`, `AnyConnectionBackend` and `TransactionManager` to `SqlStr` * Replace `sql_cloned` with `sql` in `Statement` * Update `Executor` trait * Update unit tests + QueryBuilder changes * Remove code in comments * Update comment in `QueryBuilder` * Fix clippy warnings * Update `Migrate` comment * Small changes * Move `Migration` to `SqlStr` --------- Co-authored-by: Austin Bonander <austin.bonander@gmail.com>
164 lines
4.0 KiB
Rust
164 lines
4.0 KiB
Rust
use sqlx::postgres::Postgres;
|
|
use sqlx::query_builder::QueryBuilder;
|
|
use sqlx::Executor;
|
|
use sqlx::Type;
|
|
use sqlx::{Either, Execute};
|
|
use sqlx_test::new;
|
|
|
|
#[test]
|
|
fn test_new() {
|
|
let qb: QueryBuilder<'_, Postgres> = QueryBuilder::new("SELECT * FROM users");
|
|
assert_eq!(qb.sql(), "SELECT * FROM users");
|
|
}
|
|
|
|
#[test]
|
|
fn test_push() {
|
|
let mut qb: QueryBuilder<'_, Postgres> = QueryBuilder::new("SELECT * FROM users");
|
|
let second_line = " WHERE last_name LIKE '[A-N]%';";
|
|
qb.push(second_line);
|
|
|
|
assert_eq!(
|
|
qb.sql(),
|
|
"SELECT * FROM users WHERE last_name LIKE '[A-N]%';".to_string(),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic]
|
|
fn test_push_panics_after_build_without_reset() {
|
|
let mut qb: QueryBuilder<'_, Postgres> = QueryBuilder::new("SELECT * FROM users;");
|
|
|
|
let _query = qb.build();
|
|
|
|
qb.push("SELECT * FROM users;");
|
|
}
|
|
|
|
#[test]
|
|
fn test_push_bind() {
|
|
let mut qb: QueryBuilder<'_, Postgres> = QueryBuilder::new("SELECT * FROM users WHERE id = ");
|
|
|
|
qb.push_bind(42i32)
|
|
.push(" OR membership_level = ")
|
|
.push_bind(3i32);
|
|
|
|
assert_eq!(
|
|
qb.sql(),
|
|
"SELECT * FROM users WHERE id = $1 OR membership_level = $2"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_build() {
|
|
let mut qb: QueryBuilder<'_, Postgres> = QueryBuilder::new("SELECT * FROM users");
|
|
|
|
qb.push(" WHERE id = ").push_bind(42i32);
|
|
let query = qb.build();
|
|
|
|
assert!(Execute::persistent(&query));
|
|
assert_eq!(query.sql(), "SELECT * FROM users WHERE id = $1");
|
|
}
|
|
|
|
#[test]
|
|
fn test_reset() {
|
|
let mut qb: QueryBuilder<'_, Postgres> = QueryBuilder::new("");
|
|
|
|
{
|
|
let _query = qb
|
|
.push("SELECT * FROM users WHERE id = ")
|
|
.push_bind(42i32)
|
|
.build();
|
|
}
|
|
|
|
qb.reset();
|
|
|
|
assert_eq!(qb.sql(), "");
|
|
}
|
|
|
|
#[test]
|
|
fn test_query_builder_reuse() {
|
|
let mut qb: QueryBuilder<'_, Postgres> = QueryBuilder::new("");
|
|
|
|
let _query = qb
|
|
.push("SELECT * FROM users WHERE id = ")
|
|
.push_bind(42i32)
|
|
.build();
|
|
|
|
qb.reset();
|
|
|
|
let query = qb.push("SELECT * FROM users WHERE id = 99").build();
|
|
|
|
assert_eq!(query.sql(), "SELECT * FROM users WHERE id = 99");
|
|
}
|
|
|
|
#[test]
|
|
fn test_query_builder_with_args() {
|
|
let mut qb: QueryBuilder<'_, Postgres> = QueryBuilder::new("");
|
|
|
|
let mut query = qb
|
|
.push("SELECT * FROM users WHERE id = ")
|
|
.push_bind(42i32)
|
|
.build();
|
|
|
|
let args = query.take_arguments().unwrap().unwrap();
|
|
|
|
let mut qb: QueryBuilder<'_, Postgres> =
|
|
QueryBuilder::with_arguments(query.sql().as_str(), args);
|
|
let query = qb.push(" OR membership_level = ").push_bind(3i32).build();
|
|
|
|
assert_eq!(
|
|
query.sql(),
|
|
"SELECT * FROM users WHERE id = $1 OR membership_level = $2"
|
|
);
|
|
}
|
|
|
|
#[sqlx::test]
|
|
async fn test_max_number_of_binds() -> anyhow::Result<()> {
|
|
// The maximum number of binds is 65535 (u16::MAX), not 32567 (i16::MAX)
|
|
// as the protocol documentation would imply
|
|
//
|
|
// https://github.com/launchbadge/sqlx/issues/3464
|
|
|
|
let mut qb: QueryBuilder<'_, Postgres> = QueryBuilder::new("SELECT ARRAY[");
|
|
|
|
let mut elements = qb.separated(',');
|
|
|
|
let max_bind = u16::MAX as i32;
|
|
|
|
for i in 1..=max_bind {
|
|
elements.push_bind(i);
|
|
}
|
|
|
|
qb.push("]::int4[]");
|
|
|
|
let mut conn = new::<Postgres>().await?;
|
|
|
|
// Indirectly ensures the macros support this many binds since this is what they use.
|
|
let describe = conn.describe(qb.sql()).await?;
|
|
|
|
match describe
|
|
.parameters
|
|
.expect("describe() returned no parameter information")
|
|
{
|
|
Either::Left(params) => {
|
|
assert_eq!(params.len(), 65535);
|
|
|
|
for param in params {
|
|
assert_eq!(param, <i32 as Type<Postgres>>::type_info())
|
|
}
|
|
}
|
|
Either::Right(num_params) => {
|
|
assert_eq!(num_params, 65535);
|
|
}
|
|
}
|
|
|
|
let values: Vec<i32> = qb.build_query_scalar().fetch_one(&mut conn).await?;
|
|
|
|
assert_eq!(values.len(), 65535);
|
|
|
|
for (idx, (i, j)) in (1..=max_bind).zip(values).enumerate() {
|
|
assert_eq!(i, j, "mismatch at index {idx}");
|
|
}
|
|
|
|
Ok(())
|
|
}
|