Execute unprepared statement (#1327)
This commit is contained in:
parent
d332afa99c
commit
e927a0e5f5
@ -15,6 +15,9 @@ pub trait ConnectionTrait: Sync {
|
|||||||
/// Execute a [Statement]
|
/// Execute a [Statement]
|
||||||
async fn execute(&self, stmt: Statement) -> Result<ExecResult, DbErr>;
|
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
|
/// Execute a [Statement] and return a query
|
||||||
async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr>;
|
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")]
|
#[instrument(level = "trace")]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr> {
|
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")]
|
#[instrument(level = "trace")]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr> {
|
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
|
/// Get one result from a SQL query. Returns [Option::None] if no match was found
|
||||||
#[instrument(level = "trace")]
|
#[instrument(level = "trace")]
|
||||||
pub async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr> {
|
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
|
/// Get one result from a SQL query. Returns [Option::None] if no match was found
|
||||||
#[instrument(level = "trace")]
|
#[instrument(level = "trace")]
|
||||||
pub async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr> {
|
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::{
|
use sqlx::{
|
||||||
pool::PoolConnection,
|
pool::PoolConnection,
|
||||||
sqlite::{SqliteConnectOptions, SqliteQueryResult, SqliteRow},
|
sqlite::{SqliteConnectOptions, SqliteQueryResult, SqliteRow},
|
||||||
Sqlite, SqlitePool,
|
Executor, Sqlite, SqlitePool,
|
||||||
};
|
};
|
||||||
|
|
||||||
use sea_query_binder::SqlxValues;
|
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
|
/// Get one result from a SQL query. Returns [Option::None] if no match was found
|
||||||
#[instrument(level = "trace")]
|
#[instrument(level = "trace")]
|
||||||
pub async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr> {
|
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