Execute unprepared statement (#1327)
This commit is contained in:
parent
d332afa99c
commit
e927a0e5f5
@ -15,6 +15,9 @@ pub trait ConnectionTrait: Sync {
|
||||
/// Execute a [Statement]
|
||||
async fn execute(&self, stmt: Statement) -> Result<ExecResult, DbErr>;
|
||||
|
||||
/// Execute a unprepared [Statement]
|
||||
async fn execute_unprepared(&self, sql: &str) -> Result<ExecResult, DbErr>;
|
||||
|
||||
/// Execute a [Statement] and return a query
|
||||
async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr>;
|
||||
|
||||
|
@ -122,6 +122,32 @@ impl ConnectionTrait for DatabaseConnection {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "trace")]
|
||||
#[allow(unused_variables)]
|
||||
async fn execute_unprepared(&self, sql: &str) -> Result<ExecResult, DbErr> {
|
||||
match self {
|
||||
#[cfg(feature = "sqlx-mysql")]
|
||||
DatabaseConnection::SqlxMySqlPoolConnection(conn) => conn.execute_unprepared(sql).await,
|
||||
#[cfg(feature = "sqlx-postgres")]
|
||||
DatabaseConnection::SqlxPostgresPoolConnection(conn) => {
|
||||
conn.execute_unprepared(sql).await
|
||||
}
|
||||
#[cfg(feature = "sqlx-sqlite")]
|
||||
DatabaseConnection::SqlxSqlitePoolConnection(conn) => {
|
||||
conn.execute_unprepared(sql).await
|
||||
}
|
||||
#[cfg(feature = "mock")]
|
||||
DatabaseConnection::MockDatabaseConnection(conn) => {
|
||||
let db_backend = conn.get_database_backend();
|
||||
let stmt = Statement::from_string(db_backend, sql.into());
|
||||
conn.execute(stmt)
|
||||
}
|
||||
DatabaseConnection::Disconnected => {
|
||||
Err(DbErr::Conn(RuntimeErr::Internal("Disconnected".to_owned())))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "trace")]
|
||||
#[allow(unused_variables)]
|
||||
async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr> {
|
||||
|
@ -330,6 +330,38 @@ impl ConnectionTrait for DatabaseTransaction {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "trace")]
|
||||
#[allow(unused_variables)]
|
||||
async fn execute_unprepared(&self, sql: &str) -> Result<ExecResult, DbErr> {
|
||||
debug_print!("{}", sql);
|
||||
|
||||
match &mut *self.conn.lock().await {
|
||||
#[cfg(feature = "sqlx-mysql")]
|
||||
InnerConnection::MySql(conn) => sqlx::Executor::execute(conn, sql)
|
||||
.await
|
||||
.map(Into::into)
|
||||
.map_err(sqlx_error_to_exec_err),
|
||||
#[cfg(feature = "sqlx-postgres")]
|
||||
InnerConnection::Postgres(conn) => sqlx::Executor::execute(conn, sql)
|
||||
.await
|
||||
.map(Into::into)
|
||||
.map_err(sqlx_error_to_exec_err),
|
||||
#[cfg(feature = "sqlx-sqlite")]
|
||||
InnerConnection::Sqlite(conn) => sqlx::Executor::execute(conn, sql)
|
||||
.await
|
||||
.map(Into::into)
|
||||
.map_err(sqlx_error_to_exec_err),
|
||||
#[cfg(feature = "mock")]
|
||||
InnerConnection::Mock(conn) => {
|
||||
let db_backend = conn.get_database_backend();
|
||||
let stmt = Statement::from_string(db_backend, sql.into());
|
||||
conn.execute(stmt)
|
||||
}
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "trace")]
|
||||
#[allow(unused_variables)]
|
||||
async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr> {
|
||||
|
@ -94,6 +94,21 @@ impl SqlxMySqlPoolConnection {
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute an unprepared SQL statement on a MySQL backend
|
||||
#[instrument(level = "trace")]
|
||||
pub async fn execute_unprepared(&self, sql: &str) -> Result<ExecResult, DbErr> {
|
||||
debug_print!("{}", sql);
|
||||
|
||||
if let Ok(conn) = &mut self.pool.acquire().await {
|
||||
match conn.execute(sql).await {
|
||||
Ok(res) => Ok(res.into()),
|
||||
Err(err) => Err(sqlx_error_to_exec_err(err)),
|
||||
}
|
||||
} else {
|
||||
Err(DbErr::ConnectionAcquire)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get one result from a SQL query. Returns [Option::None] if no match was found
|
||||
#[instrument(level = "trace")]
|
||||
pub async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr> {
|
||||
|
@ -109,6 +109,21 @@ impl SqlxPostgresPoolConnection {
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute an unprepared SQL statement on a PostgreSQL backend
|
||||
#[instrument(level = "trace")]
|
||||
pub async fn execute_unprepared(&self, sql: &str) -> Result<ExecResult, DbErr> {
|
||||
debug_print!("{}", sql);
|
||||
|
||||
if let Ok(conn) = &mut self.pool.acquire().await {
|
||||
match conn.execute(sql).await {
|
||||
Ok(res) => Ok(res.into()),
|
||||
Err(err) => Err(sqlx_error_to_exec_err(err)),
|
||||
}
|
||||
} else {
|
||||
Err(DbErr::ConnectionAcquire)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get one result from a SQL query. Returns [Option::None] if no match was found
|
||||
#[instrument(level = "trace")]
|
||||
pub async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr> {
|
||||
|
@ -4,7 +4,7 @@ use std::{future::Future, pin::Pin, sync::Arc};
|
||||
use sqlx::{
|
||||
pool::PoolConnection,
|
||||
sqlite::{SqliteConnectOptions, SqliteQueryResult, SqliteRow},
|
||||
Sqlite, SqlitePool,
|
||||
Executor, Sqlite, SqlitePool,
|
||||
};
|
||||
|
||||
use sea_query_binder::SqlxValues;
|
||||
@ -101,6 +101,21 @@ impl SqlxSqlitePoolConnection {
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute an unprepared SQL statement on a SQLite backend
|
||||
#[instrument(level = "trace")]
|
||||
pub async fn execute_unprepared(&self, sql: &str) -> Result<ExecResult, DbErr> {
|
||||
debug_print!("{}", sql);
|
||||
|
||||
if let Ok(conn) = &mut self.pool.acquire().await {
|
||||
match conn.execute(sql).await {
|
||||
Ok(res) => Ok(res.into()),
|
||||
Err(err) => Err(sqlx_error_to_exec_err(err)),
|
||||
}
|
||||
} else {
|
||||
Err(DbErr::ConnectionAcquire)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get one result from a SQL query. Returns [Option::None] if no match was found
|
||||
#[instrument(level = "trace")]
|
||||
pub async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr> {
|
||||
|
41
tests/execute_unprepared_tests.rs
Normal file
41
tests/execute_unprepared_tests.rs
Normal file
@ -0,0 +1,41 @@
|
||||
pub mod common;
|
||||
|
||||
pub use common::{features::*, setup::*, TestContext};
|
||||
use pretty_assertions::assert_eq;
|
||||
use sea_orm::{entity::prelude::*, ConnectionTrait, DatabaseConnection};
|
||||
|
||||
#[sea_orm_macros::test]
|
||||
#[cfg(any(
|
||||
feature = "sqlx-mysql",
|
||||
feature = "sqlx-sqlite",
|
||||
feature = "sqlx-postgres"
|
||||
))]
|
||||
async fn main() -> Result<(), DbErr> {
|
||||
let ctx = TestContext::new("execute_unprepared_tests").await;
|
||||
create_tables(&ctx.db).await?;
|
||||
execute_unprepared(&ctx.db).await?;
|
||||
ctx.delete().await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn execute_unprepared(db: &DatabaseConnection) -> Result<(), DbErr> {
|
||||
use insert_default::*;
|
||||
|
||||
db.execute_unprepared(
|
||||
[
|
||||
"INSERT INTO insert_default VALUES (1), (2), (3), (4), (5)",
|
||||
"DELETE FROM insert_default WHERE id % 2 = 0",
|
||||
]
|
||||
.join(";")
|
||||
.as_str(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert_eq!(
|
||||
Entity::find().all(db).await?,
|
||||
vec![Model { id: 1 }, Model { id: 3 }, Model { id: 5 },]
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user