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:
|
env:
|
||||||
DATABASE_URL: "sqlite::memory:"
|
DATABASE_URL: "sqlite::memory:"
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
runtime: [async-std, actix, tokio]
|
runtime: [async-std, actix, tokio]
|
||||||
tls: [native-tls, rustls]
|
tls: [native-tls, rustls]
|
||||||
@ -392,6 +393,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
DATABASE_URL: "mysql://root:@localhost"
|
DATABASE_URL: "mysql://root:@localhost"
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
version: [8.0, 5.7]
|
version: [8.0, 5.7]
|
||||||
runtime: [async-std, actix, tokio]
|
runtime: [async-std, actix, tokio]
|
||||||
@ -452,8 +454,9 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
DATABASE_URL: "mysql://root:@localhost"
|
DATABASE_URL: "mysql://root:@localhost"
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
version: [10.6]
|
version: [10.7, 10.6, 10.5, 10.0, 5.5]
|
||||||
runtime: [async-std, actix, tokio]
|
runtime: [async-std, actix, tokio]
|
||||||
tls: [native-tls]
|
tls: [native-tls]
|
||||||
services:
|
services:
|
||||||
@ -512,6 +515,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
DATABASE_URL: "postgres://root:root@localhost"
|
DATABASE_URL: "postgres://root:root@localhost"
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
version: [13.3, 12.7, 11.12, 10.17, 9.6.22]
|
version: [13.3, 12.7, 11.12, 10.17, 9.6.22]
|
||||||
runtime: [tokio]
|
runtime: [tokio]
|
||||||
|
@ -30,7 +30,7 @@ futures-util = { version = "^0.3" }
|
|||||||
log = { version = "^0.4", optional = true }
|
log = { version = "^0.4", optional = true }
|
||||||
rust_decimal = { version = "^1", optional = true }
|
rust_decimal = { version = "^1", optional = true }
|
||||||
sea-orm-macros = { version = "^0.3.1", path = "sea-orm-macros", 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"] }
|
sea-strum = { version = "^0.21", features = ["derive", "sea-orm"] }
|
||||||
serde = { version = "^1.0", features = ["derive"] }
|
serde = { version = "^1.0", features = ["derive"] }
|
||||||
serde_json = { version = "^1", optional = true }
|
serde_json = { version = "^1", optional = true }
|
||||||
|
@ -19,9 +19,11 @@ pub enum DatabaseConnection {
|
|||||||
/// Create a MYSQL database connection and pool
|
/// Create a MYSQL database connection and pool
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
SqlxMySqlPoolConnection {
|
SqlxMySqlPoolConnection {
|
||||||
/// A SQLx MySQL pool
|
/// The SQLx MySQL pool
|
||||||
conn: crate::SqlxMySqlPoolConnection,
|
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,
|
support_returning: bool,
|
||||||
},
|
},
|
||||||
/// Create a PostgreSQL database connection and pool
|
/// Create a PostgreSQL database connection and pool
|
||||||
@ -226,7 +228,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseConnection {
|
|||||||
fn support_returning(&self) -> bool {
|
fn support_returning(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
DatabaseConnection::SqlxMySqlPoolConnection { .. } => false,
|
DatabaseConnection::SqlxMySqlPoolConnection { support_returning, .. } => *support_returning,
|
||||||
#[cfg(feature = "sqlx-postgres")]
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
DatabaseConnection::SqlxPostgresPoolConnection(_) => true,
|
DatabaseConnection::SqlxPostgresPoolConnection(_) => true,
|
||||||
#[cfg(feature = "sqlx-sqlite")]
|
#[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 {
|
impl DbBackend {
|
||||||
/// Check if the URI is the same as the specified database backend.
|
/// Check if the URI is the same as the specified database backend.
|
||||||
/// Returns true if they match.
|
/// Returns true if they match.
|
||||||
|
@ -349,11 +349,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseTransaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn support_returning(&self) -> bool {
|
fn support_returning(&self) -> bool {
|
||||||
match self.backend {
|
panic!("FIXME: How?")
|
||||||
DbBackend::MySql => false,
|
|
||||||
DbBackend::Postgres => true,
|
|
||||||
DbBackend::Sqlite => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,9 +191,9 @@ async fn into_db_connection(pool: MySqlPool) -> Result<DatabaseConnection, DbErr
|
|||||||
r#"SHOW VARIABLES LIKE "version""#.to_owned(),
|
r#"SHOW VARIABLES LIKE "version""#.to_owned(),
|
||||||
))
|
))
|
||||||
.await?;
|
.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")?;
|
let version: String = query_result.try_get("", "Value")?;
|
||||||
if !version.contains("MariaDB") {
|
let support_returning = if !version.contains("MariaDB") {
|
||||||
// This is MySQL
|
// This is MySQL
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@ -213,12 +213,14 @@ async fn into_db_connection(pool: MySqlPool) -> Result<DatabaseConnection, DbErr
|
|||||||
let ver_major = parse_captures!(1);
|
let ver_major = parse_captures!(1);
|
||||||
let ver_minor = parse_captures!(2);
|
let ver_minor = parse_captures!(2);
|
||||||
ver_major >= 10 && ver_minor >= 5
|
ver_major >= 10 && ver_minor >= 5
|
||||||
}
|
};
|
||||||
|
(version, support_returning)
|
||||||
} else {
|
} else {
|
||||||
return Err(DbErr::Conn("Fail to parse MySQL version".to_owned()));
|
return Err(DbErr::Conn("Fail to parse MySQL version".to_owned()));
|
||||||
};
|
};
|
||||||
Ok(DatabaseConnection::SqlxMySqlPoolConnection {
|
Ok(DatabaseConnection::SqlxMySqlPoolConnection {
|
||||||
conn,
|
conn,
|
||||||
|
version,
|
||||||
support_returning,
|
support_returning,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error::*, ActiveModelTrait, ConnectionTrait, EntityTrait, Insert, IntoActiveModel, Iterable,
|
error::*, ActiveModelTrait, ColumnTrait, ConnectionTrait, EntityTrait, Insert, IntoActiveModel,
|
||||||
PrimaryKeyTrait, SelectModel, SelectorRaw, Statement, TryFromU64,
|
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};
|
use std::{future::Future, marker::PhantomData};
|
||||||
|
|
||||||
/// Defines a structure to perform INSERT operations in an ActiveModel
|
/// Defines a structure to perform INSERT operations in an ActiveModel
|
||||||
@ -40,11 +42,10 @@ where
|
|||||||
// so that self is dropped before entering await
|
// so that self is dropped before entering await
|
||||||
let mut query = self.query;
|
let mut query = self.query;
|
||||||
if db.support_returning() && <A::Entity as EntityTrait>::PrimaryKey::iter().count() > 0 {
|
if db.support_returning() && <A::Entity as EntityTrait>::PrimaryKey::iter().count() > 0 {
|
||||||
query.returning(Returning::Columns(
|
let mut returning = Query::select();
|
||||||
<A::Entity as EntityTrait>::PrimaryKey::iter()
|
returning
|
||||||
.map(|c| c.into_column_ref())
|
.columns(<A::Entity as EntityTrait>::PrimaryKey::iter().map(|c| c.into_column_ref()));
|
||||||
.collect(),
|
query.returning(returning);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
Inserter::<A>::new(self.primary_key, query).exec(db)
|
Inserter::<A>::new(self.primary_key, query).exec(db)
|
||||||
}
|
}
|
||||||
@ -147,11 +148,17 @@ where
|
|||||||
let db_backend = db.get_database_backend();
|
let db_backend = db.get_database_backend();
|
||||||
let found = match db.support_returning() {
|
let found = match db.support_returning() {
|
||||||
true => {
|
true => {
|
||||||
insert_statement.returning(Returning::Columns(
|
let mut returning = Query::select();
|
||||||
<A::Entity as EntityTrait>::Column::iter()
|
returning.exprs(<A::Entity as EntityTrait>::Column::iter().map(|c| {
|
||||||
.map(|c| c.into_column_ref())
|
let col = Expr::col(c);
|
||||||
.collect(),
|
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(
|
SelectorRaw::<SelectModel<<A::Entity as EntityTrait>::Model>>::from_statement(
|
||||||
db_backend.build(&insert_statement),
|
db_backend.build(&insert_statement),
|
||||||
)
|
)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error::*, ActiveModelTrait, ConnectionTrait, EntityTrait, IntoActiveModel, Iterable,
|
error::*, ActiveModelTrait, ColumnTrait, ConnectionTrait, EntityTrait, IntoActiveModel,
|
||||||
SelectModel, SelectorRaw, Statement, UpdateMany, UpdateOne,
|
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;
|
use std::future::Future;
|
||||||
|
|
||||||
/// Defines an update operation
|
/// Defines an update operation
|
||||||
@ -92,11 +92,17 @@ where
|
|||||||
{
|
{
|
||||||
match db.support_returning() {
|
match db.support_returning() {
|
||||||
true => {
|
true => {
|
||||||
query.returning(Returning::Columns(
|
let mut returning = Query::select();
|
||||||
<A::Entity as EntityTrait>::Column::iter()
|
returning.exprs(<A::Entity as EntityTrait>::Column::iter().map(|c| {
|
||||||
.map(|c| c.into_column_ref())
|
let col = Expr::col(c);
|
||||||
.collect(),
|
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 db_backend = db.get_database_backend();
|
||||||
let found: Option<<A::Entity as EntityTrait>::Model> =
|
let found: Option<<A::Entity as EntityTrait>::Model> =
|
||||||
SelectorRaw::<SelectModel<<A::Entity as EntityTrait>::Model>>::from_statement(
|
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