Skip to content

Add SqlStr #3723

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Jul 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
3eeb165
refactor: introduce `SqlSafeStr` API
abonander Apr 23, 2024
35e368c
rebase main
joeydewaal Feb 17, 2025
cb9b7d0
Add SqlStr + remove Statement lifetime
joeydewaal Feb 1, 2025
6dd8fd6
Update the definition of Executor and AnyConnectionBackend + update P…
joeydewaal Feb 1, 2025
d836f65
Update MySql driver
joeydewaal Feb 1, 2025
88d9f8f
Update Sqlite driver
joeydewaal Feb 1, 2025
db51756
remove debug clone count
joeydewaal Feb 1, 2025
694682d
Reduce the amount of SqlStr clones
joeydewaal Feb 1, 2025
a6aa63d
improve QueryBuilder error message
joeydewaal Feb 1, 2025
28bc322
cargo fmt
joeydewaal Feb 17, 2025
a0f122b
fix clippy warnings
joeydewaal Feb 17, 2025
a0b6739
fix doc test
joeydewaal Feb 17, 2025
3a90efc
Merge branch 'main' into sqlstr
joeydewaal Jul 5, 2025
09018d0
Avoid panic in `QueryBuilder::reset`
joeydewaal Jul 5, 2025
99fc942
Use `QueryBuilder` when removing all test db's
joeydewaal Jul 5, 2025
211aa78
Add comment to `SqlStr`
joeydewaal Jul 6, 2025
afb3cc5
Update sqlx-core/src/query_builder.rs
joeydewaal Jul 6, 2025
e89de06
Add `Clone` as supertrait to `Statement`
joeydewaal Jul 6, 2025
d962d70
Move `Connection`, `AnyConnectionBackend` and `TransactionManager` to…
joeydewaal Jul 6, 2025
4e09194
Replace `sql_cloned` with `sql` in `Statement`
joeydewaal Jul 6, 2025
af52820
Update `Executor` trait
joeydewaal Jul 6, 2025
d13a184
Update unit tests + QueryBuilder changes
joeydewaal Jul 6, 2025
abe2b2f
Remove code in comments
joeydewaal Jul 6, 2025
d098847
Update comment in `QueryBuilder`
joeydewaal Jul 6, 2025
627c2fa
Merge branch 'main' into sqlstr
joeydewaal Jul 6, 2025
ad522e5
Fix clippy warnings
joeydewaal Jul 6, 2025
61f4f43
Update `Migrate` comment
joeydewaal Jul 6, 2025
fa2910f
Small changes
joeydewaal Jul 6, 2025
1607a11
Move `Migration` to `SqlStr`
joeydewaal Jul 6, 2025
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
14 changes: 7 additions & 7 deletions sqlx-core/src/any/connection/backend.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::any::{Any, AnyArguments, AnyQueryResult, AnyRow, AnyStatement, AnyTypeInfo};
use crate::describe::Describe;
use crate::sql_str::SqlStr;
use either::Either;
use futures_core::future::BoxFuture;
use futures_core::stream::BoxStream;
use std::borrow::Cow;
use std::fmt::Debug;

pub trait AnyConnectionBackend: std::any::Any + Debug + Send + 'static {
Expand Down Expand Up @@ -33,7 +33,7 @@ pub trait AnyConnectionBackend: std::any::Any + Debug + Send + 'static {
///
/// If we are already inside a transaction and `statement.is_some()`, then
/// `Error::InvalidSavePoint` is returned without running any statements.
fn begin(&mut self, statement: Option<Cow<'static, str>>) -> BoxFuture<'_, crate::Result<()>>;
fn begin(&mut self, statement: Option<SqlStr>) -> BoxFuture<'_, crate::Result<()>>;

fn commit(&mut self) -> BoxFuture<'_, crate::Result<()>>;

Expand Down Expand Up @@ -96,23 +96,23 @@ pub trait AnyConnectionBackend: std::any::Any + Debug + Send + 'static {

fn fetch_many<'q>(
&'q mut self,
query: &'q str,
query: SqlStr,
persistent: bool,
arguments: Option<AnyArguments<'q>>,
) -> BoxStream<'q, crate::Result<Either<AnyQueryResult, AnyRow>>>;

fn fetch_optional<'q>(
&'q mut self,
query: &'q str,
query: SqlStr,
persistent: bool,
arguments: Option<AnyArguments<'q>>,
) -> BoxFuture<'q, crate::Result<Option<AnyRow>>>;

fn prepare_with<'c, 'q: 'c>(
&'c mut self,
sql: &'q str,
sql: SqlStr,
parameters: &[AnyTypeInfo],
) -> BoxFuture<'c, crate::Result<AnyStatement<'q>>>;
) -> BoxFuture<'c, crate::Result<AnyStatement>>;

fn describe<'q>(&'q mut self, sql: &'q str) -> BoxFuture<'q, crate::Result<Describe<Any>>>;
fn describe(&mut self, sql: SqlStr) -> BoxFuture<'_, crate::Result<Describe<Any>>>;
}
19 changes: 9 additions & 10 deletions sqlx-core/src/any/connection/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::any::{Any, AnyConnection, AnyQueryResult, AnyRow, AnyStatement, AnyTy
use crate::describe::Describe;
use crate::error::Error;
use crate::executor::{Execute, Executor};
use crate::sql_str::SqlStr;
use either::Either;
use futures_core::future::BoxFuture;
use futures_core::stream::BoxStream;
Expand All @@ -23,8 +24,8 @@ impl<'c> Executor<'c> for &'c mut AnyConnection {
Ok(arguments) => arguments,
Err(error) => return stream::once(future::ready(Err(error))).boxed(),
};
self.backend
.fetch_many(query.sql(), query.persistent(), arguments)
let persistent = query.persistent();
self.backend.fetch_many(query.sql(), persistent, arguments)
}

fn fetch_optional<'e, 'q: 'e, E>(
Expand All @@ -39,25 +40,23 @@ impl<'c> Executor<'c> for &'c mut AnyConnection {
Ok(arguments) => arguments,
Err(error) => return future::ready(Err(error)).boxed(),
};
let persistent = query.persistent();
self.backend
.fetch_optional(query.sql(), query.persistent(), arguments)
.fetch_optional(query.sql(), persistent, arguments)
}

fn prepare_with<'e, 'q: 'e>(
fn prepare_with<'e>(
self,
sql: &'q str,
sql: SqlStr,
parameters: &[AnyTypeInfo],
) -> BoxFuture<'e, Result<AnyStatement<'q>, Error>>
) -> BoxFuture<'e, Result<AnyStatement, Error>>
where
'c: 'e,
{
self.backend.prepare_with(sql, parameters)
}

fn describe<'e, 'q: 'e>(
self,
sql: &'q str,
) -> BoxFuture<'e, Result<Describe<Self::Database>, Error>>
fn describe<'e>(self, sql: SqlStr) -> BoxFuture<'e, Result<Describe<Self::Database>, Error>>
where
'c: 'e,
{
Expand Down
6 changes: 3 additions & 3 deletions sqlx-core/src/any/connection/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use futures_core::future::BoxFuture;
use std::borrow::Cow;
use std::future::Future;

use crate::any::{Any, AnyConnectOptions};
use crate::connection::{ConnectOptions, Connection};
use crate::error::Error;

use crate::database::Database;
use crate::sql_str::SqlSafeStr;
pub use backend::AnyConnectionBackend;

use crate::transaction::Transaction;
Expand Down Expand Up @@ -96,12 +96,12 @@ impl Connection for AnyConnection {

fn begin_with(
&mut self,
statement: impl Into<Cow<'static, str>>,
statement: impl SqlSafeStr,
) -> impl Future<Output = Result<Transaction<'_, Self::Database>, Error>> + Send + '_
where
Self: Sized,
{
Transaction::begin(self, Some(statement.into()))
Transaction::begin(self, Some(statement.into_sql_str()))
}

fn cached_statements_size(&self) -> usize {
Expand Down
2 changes: 1 addition & 1 deletion sqlx-core/src/any/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl Database for Any {
type Arguments<'q> = AnyArguments<'q>;
type ArgumentBuffer<'q> = AnyArgumentBuffer<'q>;

type Statement<'q> = AnyStatement<'q>;
type Statement = AnyStatement;

const NAME: &'static str = "Any";

Expand Down
33 changes: 14 additions & 19 deletions sqlx-core/src/any/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ use crate::column::ColumnIndex;
use crate::database::Database;
use crate::error::Error;
use crate::ext::ustr::UStr;
use crate::sql_str::SqlStr;
use crate::statement::Statement;
use crate::HashMap;
use either::Either;
use std::borrow::Cow;
use std::sync::Arc;

pub struct AnyStatement<'q> {
#[derive(Clone)]
pub struct AnyStatement {
#[doc(hidden)]
pub sql: Cow<'q, str>,
pub sql: SqlStr,
#[doc(hidden)]
pub parameters: Option<Either<Vec<AnyTypeInfo>, usize>>,
#[doc(hidden)]
Expand All @@ -20,19 +21,14 @@ pub struct AnyStatement<'q> {
pub columns: Vec<AnyColumn>,
}

impl<'q> Statement<'q> for AnyStatement<'q> {
impl Statement for AnyStatement {
type Database = Any;

fn to_owned(&self) -> AnyStatement<'static> {
AnyStatement::<'static> {
sql: Cow::Owned(self.sql.clone().into_owned()),
column_names: self.column_names.clone(),
parameters: self.parameters.clone(),
columns: self.columns.clone(),
}
fn into_sql(self) -> SqlStr {
self.sql
}

fn sql(&self) -> &str {
fn sql(&self) -> &SqlStr {
&self.sql
}

Expand All @@ -51,8 +47,8 @@ impl<'q> Statement<'q> for AnyStatement<'q> {
impl_statement_query!(AnyArguments<'_>);
}

impl ColumnIndex<AnyStatement<'_>> for &'_ str {
fn index(&self, statement: &AnyStatement<'_>) -> Result<usize, Error> {
impl ColumnIndex<AnyStatement> for &'_ str {
fn index(&self, statement: &AnyStatement) -> Result<usize, Error> {
statement
.column_names
.get(*self)
Expand All @@ -61,15 +57,14 @@ impl ColumnIndex<AnyStatement<'_>> for &'_ str {
}
}

impl<'q> AnyStatement<'q> {
impl AnyStatement {
#[doc(hidden)]
pub fn try_from_statement<S>(
query: &'q str,
statement: &S,
statement: S,
column_names: Arc<HashMap<UStr, usize>>,
) -> crate::Result<Self>
where
S: Statement<'q>,
S: Statement,
AnyTypeInfo: for<'a> TryFrom<&'a <S::Database as Database>::TypeInfo, Error = Error>,
AnyColumn: for<'a> TryFrom<&'a <S::Database as Database>::Column, Error = Error>,
{
Expand All @@ -91,7 +86,7 @@ impl<'q> AnyStatement<'q> {
.collect::<Result<Vec<_>, _>>()?;

Ok(Self {
sql: query.into(),
sql: statement.into_sql(),
columns,
column_names,
parameters,
Expand Down
10 changes: 5 additions & 5 deletions sqlx-core/src/any/transaction.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
use std::borrow::Cow;
use std::future::Future;

use crate::any::{Any, AnyConnection};
use crate::database::Database;
use crate::error::Error;
use crate::sql_str::SqlStr;
use crate::transaction::TransactionManager;

pub struct AnyTransactionManager;

impl TransactionManager for AnyTransactionManager {
type Database = Any;

fn begin<'conn>(
conn: &'conn mut AnyConnection,
statement: Option<Cow<'static, str>>,
) -> impl Future<Output = Result<(), Error>> + Send + 'conn {
fn begin(
conn: &mut AnyConnection,
statement: Option<SqlStr>,
) -> impl Future<Output = Result<(), Error>> + Send + '_ {
conn.backend.begin(statement)
}

Expand Down
4 changes: 2 additions & 2 deletions sqlx-core/src/column.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ macro_rules! impl_column_index_for_row {
#[macro_export]
macro_rules! impl_column_index_for_statement {
($S:ident) => {
impl $crate::column::ColumnIndex<$S<'_>> for usize {
fn index(&self, statement: &$S<'_>) -> Result<usize, $crate::error::Error> {
impl $crate::column::ColumnIndex<$S> for usize {
fn index(&self, statement: &$S) -> Result<usize, $crate::error::Error> {
let len = $crate::statement::Statement::columns(statement).len();

if *self >= len {
Expand Down
6 changes: 3 additions & 3 deletions sqlx-core/src/connection.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::database::{Database, HasStatementCache};
use crate::error::Error;

use crate::sql_str::SqlSafeStr;
use crate::transaction::{Transaction, TransactionManager};
use futures_core::future::BoxFuture;
use log::LevelFilter;
use std::borrow::Cow;
use std::fmt::Debug;
use std::future::Future;
use std::str::FromStr;
Expand Down Expand Up @@ -59,12 +59,12 @@ pub trait Connection: Send {
/// `statement` does not put the connection into a transaction.
fn begin_with(
&mut self,
statement: impl Into<Cow<'static, str>>,
statement: impl SqlSafeStr,
) -> impl Future<Output = Result<Transaction<'_, Self::Database>, Error>> + Send + '_
where
Self: Sized,
{
Transaction::begin(self, Some(statement.into()))
Transaction::begin(self, Some(statement.into_sql_str()))
}

/// Returns `true` if the connection is currently in a transaction.
Expand Down
2 changes: 1 addition & 1 deletion sqlx-core/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub trait Database: 'static + Sized + Send + Debug {
type ArgumentBuffer<'q>;

/// The concrete `Statement` implementation for this database.
type Statement<'q>: Statement<'q, Database = Self>;
type Statement: Statement<Database = Self>;

/// The display name for this database driver.
const NAME: &'static str;
Expand Down
Loading