Fixup
This commit is contained in:
parent
80c0d69733
commit
30f43b64c6
6
.github/workflows/rust.yml
vendored
6
.github/workflows/rust.yml
vendored
@ -350,6 +350,7 @@ jobs:
|
||||
env:
|
||||
DATABASE_URL: "sqlite::memory:"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
runtime: [async-std, actix, tokio]
|
||||
tls: [native-tls, rustls]
|
||||
@ -392,6 +393,7 @@ jobs:
|
||||
env:
|
||||
DATABASE_URL: "mysql://root:@localhost"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version: [8.0, 5.7]
|
||||
runtime: [async-std, actix, tokio]
|
||||
@ -452,8 +454,9 @@ jobs:
|
||||
env:
|
||||
DATABASE_URL: "mysql://root:@localhost"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version: [10.6]
|
||||
version: [10.7, 10.6, 10.5, 10.0, 5.5]
|
||||
runtime: [async-std, actix, tokio]
|
||||
tls: [native-tls]
|
||||
services:
|
||||
@ -512,6 +515,7 @@ jobs:
|
||||
env:
|
||||
DATABASE_URL: "postgres://root:root@localhost"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version: [13.3, 12.7, 11.12, 10.17, 9.6.22]
|
||||
runtime: [tokio]
|
||||
|
@ -30,7 +30,7 @@ futures-util = { version = "^0.3" }
|
||||
log = { version = "^0.4", optional = true }
|
||||
rust_decimal = { version = "^1", optional = true }
|
||||
sea-orm-macros = { version = "^0.3.1", path = "sea-orm-macros", optional = true }
|
||||
sea-query = { version = "^0.18.0", git = "https://github.com/marlon-sousa/sea-query.git", branch = "extended-returning-support", features = ["thread-safe"] }
|
||||
sea-query = { version = "^0.18.2", features = ["thread-safe"] }
|
||||
sea-strum = { version = "^0.21", features = ["derive", "sea-orm"] }
|
||||
serde = { version = "^1.0", features = ["derive"] }
|
||||
serde_json = { version = "^1", optional = true }
|
||||
|
@ -19,9 +19,11 @@ pub enum DatabaseConnection {
|
||||
/// Create a MYSQL database connection and pool
|
||||
#[cfg(feature = "sqlx-mysql")]
|
||||
SqlxMySqlPoolConnection {
|
||||
/// A SQLx MySQL pool
|
||||
/// The SQLx MySQL pool
|
||||
conn: crate::SqlxMySqlPoolConnection,
|
||||
/// A flag indicating whether `RETURNING` syntax is supported
|
||||
/// The MySQL version
|
||||
version: String,
|
||||
/// The flag indicating whether `RETURNING` syntax is supported
|
||||
support_returning: bool,
|
||||
},
|
||||
/// Create a PostgreSQL database connection and pool
|
||||
@ -226,7 +228,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseConnection {
|
||||
fn support_returning(&self) -> bool {
|
||||
match self {
|
||||
#[cfg(feature = "sqlx-mysql")]
|
||||
DatabaseConnection::SqlxMySqlPoolConnection { .. } => false,
|
||||
DatabaseConnection::SqlxMySqlPoolConnection { support_returning, .. } => *support_returning,
|
||||
#[cfg(feature = "sqlx-postgres")]
|
||||
DatabaseConnection::SqlxPostgresPoolConnection(_) => true,
|
||||
#[cfg(feature = "sqlx-sqlite")]
|
||||
@ -264,6 +266,40 @@ impl DatabaseConnection {
|
||||
}
|
||||
}
|
||||
|
||||
impl DatabaseConnection {
|
||||
/// Get database version
|
||||
pub fn db_version(&self) -> String {
|
||||
match self {
|
||||
#[cfg(feature = "sqlx-mysql")]
|
||||
DatabaseConnection::SqlxMySqlPoolConnection { version, .. } => version.to_string(),
|
||||
// #[cfg(feature = "sqlx-postgres")]
|
||||
// DatabaseConnection::SqlxPostgresPoolConnection(conn) => ,
|
||||
// #[cfg(feature = "sqlx-sqlite")]
|
||||
// DatabaseConnection::SqlxSqlitePoolConnection(conn) => ,
|
||||
// #[cfg(feature = "mock")]
|
||||
// DatabaseConnection::MockDatabaseConnection(conn) => ,
|
||||
DatabaseConnection::Disconnected => panic!("Disconnected"),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if database supports `RETURNING`
|
||||
pub fn db_support_returning(&self) -> bool {
|
||||
match self {
|
||||
#[cfg(feature = "sqlx-mysql")]
|
||||
DatabaseConnection::SqlxMySqlPoolConnection { support_returning, .. } => *support_returning,
|
||||
#[cfg(feature = "sqlx-postgres")]
|
||||
DatabaseConnection::SqlxPostgresPoolConnection(_) => true,
|
||||
// #[cfg(feature = "sqlx-sqlite")]
|
||||
// DatabaseConnection::SqlxSqlitePoolConnection(conn) => ,
|
||||
// #[cfg(feature = "mock")]
|
||||
// DatabaseConnection::MockDatabaseConnection(conn) => ,
|
||||
DatabaseConnection::Disconnected => panic!("Disconnected"),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DbBackend {
|
||||
/// Check if the URI is the same as the specified database backend.
|
||||
/// Returns true if they match.
|
||||
|
@ -349,11 +349,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseTransaction {
|
||||
}
|
||||
|
||||
fn support_returning(&self) -> bool {
|
||||
match self.backend {
|
||||
DbBackend::MySql => false,
|
||||
DbBackend::Postgres => true,
|
||||
DbBackend::Sqlite => false,
|
||||
}
|
||||
panic!("FIXME: How?")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,9 +191,9 @@ async fn into_db_connection(pool: MySqlPool) -> Result<DatabaseConnection, DbErr
|
||||
r#"SHOW VARIABLES LIKE "version""#.to_owned(),
|
||||
))
|
||||
.await?;
|
||||
let support_returning = if let Some(query_result) = res {
|
||||
let (version, support_returning) = if let Some(query_result) = res {
|
||||
let version: String = query_result.try_get("", "Value")?;
|
||||
if !version.contains("MariaDB") {
|
||||
let support_returning = if !version.contains("MariaDB") {
|
||||
// This is MySQL
|
||||
false
|
||||
} else {
|
||||
@ -213,12 +213,14 @@ async fn into_db_connection(pool: MySqlPool) -> Result<DatabaseConnection, DbErr
|
||||
let ver_major = parse_captures!(1);
|
||||
let ver_minor = parse_captures!(2);
|
||||
ver_major >= 10 && ver_minor >= 5
|
||||
}
|
||||
};
|
||||
(version, support_returning)
|
||||
} else {
|
||||
return Err(DbErr::Conn("Fail to parse MySQL version".to_owned()));
|
||||
};
|
||||
Ok(DatabaseConnection::SqlxMySqlPoolConnection {
|
||||
conn,
|
||||
version,
|
||||
support_returning,
|
||||
})
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
use crate::{
|
||||
error::*, ActiveModelTrait, ConnectionTrait, EntityTrait, Insert, IntoActiveModel, Iterable,
|
||||
PrimaryKeyTrait, SelectModel, SelectorRaw, Statement, TryFromU64,
|
||||
error::*, ActiveModelTrait, ColumnTrait, ConnectionTrait, EntityTrait, Insert, IntoActiveModel,
|
||||
Iterable, PrimaryKeyTrait, SelectModel, SelectorRaw, Statement, TryFromU64,
|
||||
};
|
||||
use sea_query::{
|
||||
Alias, Expr, FromValueTuple, Iden, InsertStatement, IntoColumnRef, Query, ValueTuple,
|
||||
};
|
||||
use sea_query::{FromValueTuple, Iden, InsertStatement, IntoColumnRef, Returning, ValueTuple};
|
||||
use std::{future::Future, marker::PhantomData};
|
||||
|
||||
/// Defines a structure to perform INSERT operations in an ActiveModel
|
||||
@ -40,11 +42,10 @@ where
|
||||
// so that self is dropped before entering await
|
||||
let mut query = self.query;
|
||||
if db.support_returning() && <A::Entity as EntityTrait>::PrimaryKey::iter().count() > 0 {
|
||||
query.returning(Returning::Columns(
|
||||
<A::Entity as EntityTrait>::PrimaryKey::iter()
|
||||
.map(|c| c.into_column_ref())
|
||||
.collect(),
|
||||
));
|
||||
let mut returning = Query::select();
|
||||
returning
|
||||
.columns(<A::Entity as EntityTrait>::PrimaryKey::iter().map(|c| c.into_column_ref()));
|
||||
query.returning(returning);
|
||||
}
|
||||
Inserter::<A>::new(self.primary_key, query).exec(db)
|
||||
}
|
||||
@ -147,11 +148,17 @@ where
|
||||
let db_backend = db.get_database_backend();
|
||||
let found = match db.support_returning() {
|
||||
true => {
|
||||
insert_statement.returning(Returning::Columns(
|
||||
<A::Entity as EntityTrait>::Column::iter()
|
||||
.map(|c| c.into_column_ref())
|
||||
.collect(),
|
||||
));
|
||||
let mut returning = Query::select();
|
||||
returning.exprs(<A::Entity as EntityTrait>::Column::iter().map(|c| {
|
||||
let col = Expr::col(c);
|
||||
let col_def = ColumnTrait::def(&c);
|
||||
let col_type = col_def.get_column_type();
|
||||
match col_type.get_enum_name() {
|
||||
Some(_) => col.as_enum(Alias::new("text")),
|
||||
None => col.into(),
|
||||
}
|
||||
}));
|
||||
insert_statement.returning(returning);
|
||||
SelectorRaw::<SelectModel<<A::Entity as EntityTrait>::Model>>::from_statement(
|
||||
db_backend.build(&insert_statement),
|
||||
)
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::{
|
||||
error::*, ActiveModelTrait, ConnectionTrait, EntityTrait, IntoActiveModel, Iterable,
|
||||
SelectModel, SelectorRaw, Statement, UpdateMany, UpdateOne,
|
||||
error::*, ActiveModelTrait, ColumnTrait, ConnectionTrait, EntityTrait, IntoActiveModel,
|
||||
Iterable, SelectModel, SelectorRaw, Statement, UpdateMany, UpdateOne,
|
||||
};
|
||||
use sea_query::{FromValueTuple, IntoColumnRef, Returning, UpdateStatement};
|
||||
use sea_query::{Alias, Expr, FromValueTuple, Query, UpdateStatement};
|
||||
use std::future::Future;
|
||||
|
||||
/// Defines an update operation
|
||||
@ -92,11 +92,17 @@ where
|
||||
{
|
||||
match db.support_returning() {
|
||||
true => {
|
||||
query.returning(Returning::Columns(
|
||||
<A::Entity as EntityTrait>::Column::iter()
|
||||
.map(|c| c.into_column_ref())
|
||||
.collect(),
|
||||
));
|
||||
let mut returning = Query::select();
|
||||
returning.exprs(<A::Entity as EntityTrait>::Column::iter().map(|c| {
|
||||
let col = Expr::col(c);
|
||||
let col_def = c.def();
|
||||
let col_type = col_def.get_column_type();
|
||||
match col_type.get_enum_name() {
|
||||
Some(_) => col.as_enum(Alias::new("text")),
|
||||
None => col.into(),
|
||||
}
|
||||
}));
|
||||
query.returning(returning);
|
||||
let db_backend = db.get_database_backend();
|
||||
let found: Option<<A::Entity as EntityTrait>::Model> =
|
||||
SelectorRaw::<SelectModel<<A::Entity as EntityTrait>::Model>>::from_statement(
|
||||
|
37
tests/returning_tests.rs
Normal file
37
tests/returning_tests.rs
Normal file
@ -0,0 +1,37 @@
|
||||
pub mod common;
|
||||
|
||||
pub use common::{features::*, setup::*, TestContext};
|
||||
use sea_orm::{entity::prelude::*, entity::*, 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("returning_tests").await;
|
||||
let db = &ctx.db;
|
||||
|
||||
match db {
|
||||
#[cfg(feature = "sqlx-mysql")]
|
||||
DatabaseConnection::SqlxMySqlPoolConnection { .. } => {
|
||||
let version = db.db_version();
|
||||
match version.as_str() {
|
||||
"5.7.26" => assert!(!db.db_support_returning()),
|
||||
_ => unimplemented!("Version {} is not included", version),
|
||||
};
|
||||
},
|
||||
#[cfg(feature = "sqlx-postgres")]
|
||||
DatabaseConnection::SqlxPostgresPoolConnection(_) => {
|
||||
assert!(db.db_support_returning());
|
||||
},
|
||||
#[cfg(feature = "sqlx-sqlite")]
|
||||
DatabaseConnection::SqlxSqlitePoolConnection(_) => {},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
ctx.delete().await;
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user