Merge branch 'master' into ss/test_suite
This commit is contained in:
commit
f5838f8cbd
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2020 Tsang Hao Fung
|
Copyright (c) 2021 Tsang Hao Fung
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any
|
Permission is hereby granted, free of charge, to any
|
||||||
person obtaining a copy of this software and associated
|
person obtaining a copy of this software and associated
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
Inspired by ActiveRecord, Eloquent and TypeORM, SeaORM aims to provide you an intuitive and ergonomic
|
Inspired by ActiveRecord, Eloquent and TypeORM, SeaORM aims to provide you an intuitive and ergonomic
|
||||||
API to make working with databases in Rust a first-class experience.
|
API to make working with databases in Rust a first-class experience.
|
||||||
|
|
||||||
```rust
|
```markdown
|
||||||
This is a preview of SeaORM, and is not yet released.
|
This is a preview of SeaORM, and is not yet released.
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -145,9 +145,9 @@ fruit::Entity::delete_many()
|
|||||||
Licensed under either of
|
Licensed under either of
|
||||||
|
|
||||||
- Apache License, Version 2.0
|
- Apache License, Version 2.0
|
||||||
([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
|
||||||
- MIT license
|
- MIT license
|
||||||
([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
|
||||||
|
|
||||||
at your option.
|
at your option.
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
|
mod base_entity;
|
||||||
mod column;
|
mod column;
|
||||||
mod entity;
|
|
||||||
mod generator;
|
mod generator;
|
||||||
mod primary_key;
|
mod primary_key;
|
||||||
mod relation;
|
mod relation;
|
||||||
mod transformer;
|
mod transformer;
|
||||||
mod writer;
|
mod writer;
|
||||||
|
|
||||||
|
pub use base_entity::*;
|
||||||
pub use column::*;
|
pub use column::*;
|
||||||
pub use entity::*;
|
|
||||||
pub use generator::*;
|
pub use generator::*;
|
||||||
pub use primary_key::*;
|
pub use primary_key::*;
|
||||||
pub use relation::*;
|
pub use relation::*;
|
||||||
|
@ -2,7 +2,7 @@ mod entity;
|
|||||||
|
|
||||||
use entity::*;
|
use entity::*;
|
||||||
|
|
||||||
use sea_orm::{entity::*, error::*, MockDatabase, MockExecResult, Syntax, Transaction};
|
use sea_orm::{entity::*, error::*, DbBackend, MockDatabase, MockExecResult, Transaction};
|
||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
async fn test_insert() -> Result<(), DbErr> {
|
async fn test_insert() -> Result<(), DbErr> {
|
||||||
@ -11,7 +11,7 @@ async fn test_insert() -> Result<(), DbErr> {
|
|||||||
rows_affected: 1,
|
rows_affected: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
let db = MockDatabase::new(Syntax::Postgres)
|
let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
.append_exec_results(vec![exec_result.clone()])
|
.append_exec_results(vec![exec_result.clone()])
|
||||||
.into_connection();
|
.into_connection();
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ async fn test_insert() -> Result<(), DbErr> {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
db.into_transaction_log(),
|
db.into_transaction_log(),
|
||||||
vec![Transaction::from_sql_and_values(
|
vec![Transaction::from_sql_and_values(
|
||||||
Syntax::Postgres,
|
DbBackend::Postgres,
|
||||||
r#"INSERT INTO "cake" ("name") VALUES ($1)"#,
|
r#"INSERT INTO "cake" ("name") VALUES ($1)"#,
|
||||||
vec!["Apple Pie".into()]
|
vec!["Apple Pie".into()]
|
||||||
)]
|
)]
|
||||||
@ -43,7 +43,7 @@ async fn test_select() -> Result<(), DbErr> {
|
|||||||
filling_id: 3,
|
filling_id: 3,
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let db = MockDatabase::new(Syntax::Postgres)
|
let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
.append_query_results(vec![query_results.clone()])
|
.append_query_results(vec![query_results.clone()])
|
||||||
.into_connection();
|
.into_connection();
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ async fn test_select() -> Result<(), DbErr> {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
db.into_transaction_log(),
|
db.into_transaction_log(),
|
||||||
vec![Transaction::from_sql_and_values(
|
vec![Transaction::from_sql_and_values(
|
||||||
Syntax::Postgres,
|
DbBackend::Postgres,
|
||||||
[
|
[
|
||||||
r#"SELECT "cake_filling"."cake_id", "cake_filling"."filling_id" FROM "cake_filling""#,
|
r#"SELECT "cake_filling"."cake_id", "cake_filling"."filling_id" FROM "cake_filling""#,
|
||||||
r#"WHERE "cake_filling"."cake_id" = $1 AND "cake_filling"."filling_id" = $2"#,
|
r#"WHERE "cake_filling"."cake_id" = $1 AND "cake_filling"."filling_id" = $2"#,
|
||||||
@ -73,7 +73,7 @@ async fn test_update() -> Result<(), DbErr> {
|
|||||||
rows_affected: 1,
|
rows_affected: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
let db = MockDatabase::new(Syntax::Postgres)
|
let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
.append_exec_results(vec![exec_result.clone()])
|
.append_exec_results(vec![exec_result.clone()])
|
||||||
.into_connection();
|
.into_connection();
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ async fn test_update() -> Result<(), DbErr> {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
db.into_transaction_log(),
|
db.into_transaction_log(),
|
||||||
vec![Transaction::from_sql_and_values(
|
vec![Transaction::from_sql_and_values(
|
||||||
Syntax::Postgres,
|
DbBackend::Postgres,
|
||||||
r#"UPDATE "fruit" SET "name" = $1 WHERE "fruit"."id" = $2"#,
|
r#"UPDATE "fruit" SET "name" = $1 WHERE "fruit"."id" = $2"#,
|
||||||
vec!["Orange".into(), 1i32.into()]
|
vec!["Orange".into(), 1i32.into()]
|
||||||
)]
|
)]
|
||||||
@ -106,7 +106,7 @@ async fn test_delete() -> Result<(), DbErr> {
|
|||||||
rows_affected: 1,
|
rows_affected: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
let db = MockDatabase::new(Syntax::Postgres)
|
let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
.append_exec_results(vec![exec_result.clone()])
|
.append_exec_results(vec![exec_result.clone()])
|
||||||
.into_connection();
|
.into_connection();
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ async fn test_delete() -> Result<(), DbErr> {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
db.into_transaction_log(),
|
db.into_transaction_log(),
|
||||||
vec![Transaction::from_sql_and_values(
|
vec![Transaction::from_sql_and_values(
|
||||||
Syntax::Postgres,
|
DbBackend::Postgres,
|
||||||
r#"DELETE FROM "fruit" WHERE "fruit"."id" = $1"#,
|
r#"DELETE FROM "fruit" WHERE "fruit"."id" = $1"#,
|
||||||
vec![3i32.into()]
|
vec![3i32.into()]
|
||||||
)]
|
)]
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
use crate::{error::*, ExecResult, QueryResult, Statement, Syntax};
|
use crate::{error::*, ExecResult, QueryResult, Statement, StatementBuilder};
|
||||||
use sea_query::{
|
use sea_query::{MysqlQueryBuilder, PostgresQueryBuilder, QueryBuilder, SqliteQueryBuilder};
|
||||||
MysqlQueryBuilder, PostgresQueryBuilder, QueryStatementBuilder, SchemaStatementBuilder,
|
|
||||||
SqliteQueryBuilder,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub enum DatabaseConnection {
|
pub enum DatabaseConnection {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
@ -16,17 +13,14 @@ pub enum DatabaseConnection {
|
|||||||
|
|
||||||
pub type DbConn = DatabaseConnection;
|
pub type DbConn = DatabaseConnection;
|
||||||
|
|
||||||
pub enum QueryBuilderBackend {
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
|
pub enum DatabaseBackend {
|
||||||
MySql,
|
MySql,
|
||||||
Postgres,
|
Postgres,
|
||||||
Sqlite,
|
Sqlite,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum SchemaBuilderBackend {
|
pub type DbBackend = DatabaseBackend;
|
||||||
MySql,
|
|
||||||
Postgres,
|
|
||||||
Sqlite,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for DatabaseConnection {
|
impl Default for DatabaseConnection {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
@ -53,26 +47,14 @@ impl std::fmt::Debug for DatabaseConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DatabaseConnection {
|
impl DatabaseConnection {
|
||||||
pub fn get_query_builder_backend(&self) -> QueryBuilderBackend {
|
pub fn get_database_backend(&self) -> DbBackend {
|
||||||
match self {
|
match self {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
DatabaseConnection::SqlxMySqlPoolConnection(_) => QueryBuilderBackend::MySql,
|
DatabaseConnection::SqlxMySqlPoolConnection(_) => DbBackend::MySql,
|
||||||
#[cfg(feature = "sqlx-sqlite")]
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
DatabaseConnection::SqlxSqlitePoolConnection(_) => QueryBuilderBackend::Sqlite,
|
DatabaseConnection::SqlxSqlitePoolConnection(_) => DbBackend::Sqlite,
|
||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
DatabaseConnection::MockDatabaseConnection(conn) => conn.get_query_builder_backend(),
|
DatabaseConnection::MockDatabaseConnection(conn) => conn.get_database_backend(),
|
||||||
DatabaseConnection::Disconnected => panic!("Disconnected"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_schema_builder_backend(&self) -> SchemaBuilderBackend {
|
|
||||||
match self {
|
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
|
||||||
DatabaseConnection::SqlxMySqlPoolConnection(_) => SchemaBuilderBackend::MySql,
|
|
||||||
#[cfg(feature = "sqlx-sqlite")]
|
|
||||||
DatabaseConnection::SqlxSqlitePoolConnection(_) => SchemaBuilderBackend::Sqlite,
|
|
||||||
#[cfg(feature = "mock")]
|
|
||||||
DatabaseConnection::MockDatabaseConnection(conn) => conn.get_schema_builder_backend(),
|
|
||||||
DatabaseConnection::Disconnected => panic!("Disconnected"),
|
DatabaseConnection::Disconnected => panic!("Disconnected"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,50 +115,19 @@ impl DatabaseConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QueryBuilderBackend {
|
impl DbBackend {
|
||||||
pub fn syntax(&self) -> Syntax {
|
|
||||||
match self {
|
|
||||||
Self::MySql => Syntax::MySql,
|
|
||||||
Self::Postgres => Syntax::Postgres,
|
|
||||||
Self::Sqlite => Syntax::Sqlite,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build<S>(&self, statement: &S) -> Statement
|
pub fn build<S>(&self, statement: &S) -> Statement
|
||||||
where
|
where
|
||||||
S: QueryStatementBuilder,
|
S: StatementBuilder,
|
||||||
{
|
{
|
||||||
Statement::from_string_values_tuple(
|
statement.build(self)
|
||||||
self.syntax(),
|
|
||||||
match self {
|
|
||||||
Self::MySql => statement.build(MysqlQueryBuilder),
|
|
||||||
Self::Postgres => statement.build(PostgresQueryBuilder),
|
|
||||||
Self::Sqlite => statement.build(SqliteQueryBuilder),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl SchemaBuilderBackend {
|
pub fn get_query_builder(&self) -> Box<dyn QueryBuilder> {
|
||||||
pub fn syntax(&self) -> Syntax {
|
|
||||||
match self {
|
match self {
|
||||||
Self::MySql => Syntax::MySql,
|
Self::MySql => Box::new(MysqlQueryBuilder),
|
||||||
Self::Postgres => Syntax::Postgres,
|
Self::Postgres => Box::new(PostgresQueryBuilder),
|
||||||
Self::Sqlite => Syntax::Sqlite,
|
Self::Sqlite => Box::new(SqliteQueryBuilder),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build<S>(&self, statement: &S) -> Statement
|
|
||||||
where
|
|
||||||
S: SchemaStatementBuilder,
|
|
||||||
{
|
|
||||||
Statement::from_string(
|
|
||||||
self.syntax(),
|
|
||||||
match self {
|
|
||||||
Self::MySql => statement.build(MysqlQueryBuilder),
|
|
||||||
Self::Postgres => statement.build(PostgresQueryBuilder),
|
|
||||||
Self::Sqlite => statement.build(SqliteQueryBuilder),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error::*, DatabaseConnection, EntityTrait, ExecResult, ExecResultHolder, Iden, Iterable,
|
error::*, DbBackend, DatabaseConnection, EntityTrait, ExecResult, ExecResultHolder, Iden,
|
||||||
MockDatabaseConnection, MockDatabaseTrait, ModelTrait, QueryResult, QueryResultRow, Statement,
|
Iterable, MockDatabaseConnection, MockDatabaseTrait, ModelTrait, QueryResult, QueryResultRow,
|
||||||
Syntax, Transaction,
|
Statement, Transaction,
|
||||||
};
|
};
|
||||||
use sea_query::{Value, ValueType};
|
use sea_query::{Value, ValueType};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MockDatabase {
|
pub struct MockDatabase {
|
||||||
syntax: Syntax,
|
db_backend: DbBackend,
|
||||||
transaction_log: Vec<Transaction>,
|
transaction_log: Vec<Transaction>,
|
||||||
exec_results: Vec<MockExecResult>,
|
exec_results: Vec<MockExecResult>,
|
||||||
query_results: Vec<Vec<MockRow>>,
|
query_results: Vec<Vec<MockRow>>,
|
||||||
@ -43,9 +43,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MockDatabase {
|
impl MockDatabase {
|
||||||
pub fn new(syntax: Syntax) -> Self {
|
pub fn new(db_backend: DbBackend) -> Self {
|
||||||
Self {
|
Self {
|
||||||
syntax,
|
db_backend,
|
||||||
transaction_log: Vec::new(),
|
transaction_log: Vec::new(),
|
||||||
exec_results: Vec::new(),
|
exec_results: Vec::new(),
|
||||||
query_results: Vec::new(),
|
query_results: Vec::new(),
|
||||||
@ -103,8 +103,8 @@ impl MockDatabaseTrait for MockDatabase {
|
|||||||
std::mem::take(&mut self.transaction_log)
|
std::mem::take(&mut self.transaction_log)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_syntax(&self) -> Syntax {
|
fn get_database_backend(&self) -> DbBackend {
|
||||||
self.syntax
|
self.db_backend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,38 +1,47 @@
|
|||||||
use crate::{QueryBuilderBackend, QueryBuilderWithSyntax, SchemaBuilderBackend};
|
use crate::DbBackend;
|
||||||
use sea_query::{
|
use sea_query::{
|
||||||
inject_parameters, MysqlQueryBuilder, PostgresQueryBuilder, QueryBuilder, SqliteQueryBuilder,
|
inject_parameters, MysqlQueryBuilder, PostgresQueryBuilder, SqliteQueryBuilder, Value, Values
|
||||||
Values,
|
|
||||||
};
|
};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
|
||||||
pub enum Syntax {
|
|
||||||
MySql,
|
|
||||||
Postgres,
|
|
||||||
Sqlite,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Statement {
|
pub struct Statement {
|
||||||
pub sql: String,
|
pub sql: String,
|
||||||
pub values: Option<Values>,
|
pub values: Option<Values>,
|
||||||
pub syntax: Syntax,
|
pub db_backend: DbBackend,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait StatementBuilder {
|
||||||
|
fn build(&self, db_backend: &DbBackend) -> Statement;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Statement {
|
impl Statement {
|
||||||
pub fn from_string(syntax: Syntax, stmt: String) -> Statement {
|
pub fn from_string(db_backend: DbBackend, stmt: String) -> Statement {
|
||||||
Statement {
|
Statement {
|
||||||
sql: stmt,
|
sql: stmt,
|
||||||
values: None,
|
values: None,
|
||||||
syntax,
|
db_backend,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_string_values_tuple(syntax: Syntax, stmt: (String, Values)) -> Statement {
|
pub fn from_sql_and_values<I>(db_backend: DbBackend, sql: &str, values: I) -> Self
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = Value>,
|
||||||
|
{
|
||||||
|
Self::from_string_values_tuple(
|
||||||
|
db_backend,
|
||||||
|
(sql.to_owned(), Values(values.into_iter().collect())),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn from_string_values_tuple(
|
||||||
|
db_backend: DbBackend,
|
||||||
|
stmt: (String, Values),
|
||||||
|
) -> Statement {
|
||||||
Statement {
|
Statement {
|
||||||
sql: stmt.0,
|
sql: stmt.0,
|
||||||
values: Some(stmt.1),
|
values: Some(stmt.1),
|
||||||
syntax,
|
db_backend,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,7 +53,7 @@ impl fmt::Display for Statement {
|
|||||||
let string = inject_parameters(
|
let string = inject_parameters(
|
||||||
&self.sql,
|
&self.sql,
|
||||||
values.0.clone(),
|
values.0.clone(),
|
||||||
self.syntax.get_query_builder().as_ref(),
|
self.db_backend.get_query_builder().as_ref(),
|
||||||
);
|
);
|
||||||
write!(f, "{}", &string)
|
write!(f, "{}", &string)
|
||||||
}
|
}
|
||||||
@ -55,46 +64,45 @@ impl fmt::Display for Statement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Syntax {
|
macro_rules! build_any_stmt {
|
||||||
pub fn get_query_builder(&self) -> Box<dyn QueryBuilder> {
|
($stmt: expr, $db_backend: expr) => {
|
||||||
match self {
|
match $db_backend {
|
||||||
Self::MySql => Box::new(MysqlQueryBuilder),
|
DbBackend::MySql => $stmt.build(MysqlQueryBuilder),
|
||||||
Self::Postgres => Box::new(PostgresQueryBuilder),
|
DbBackend::Postgres => $stmt.build(PostgresQueryBuilder),
|
||||||
Self::Sqlite => Box::new(SqliteQueryBuilder),
|
DbBackend::Sqlite => $stmt.build(SqliteQueryBuilder),
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_query_builder_backend(&self) -> QueryBuilderBackend {
|
macro_rules! build_query_stmt {
|
||||||
match self {
|
($stmt: ty) => {
|
||||||
Self::MySql => QueryBuilderBackend::MySql,
|
impl StatementBuilder for $stmt {
|
||||||
Self::Postgres => QueryBuilderBackend::Postgres,
|
fn build(&self, db_backend: &DbBackend) -> Statement {
|
||||||
Self::Sqlite => QueryBuilderBackend::Sqlite,
|
let stmt = build_any_stmt!(self, db_backend);
|
||||||
|
Statement::from_string_values_tuple(*db_backend, stmt)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_schema_builder_backend(&self) -> SchemaBuilderBackend {
|
build_query_stmt!(sea_query::InsertStatement);
|
||||||
match self {
|
build_query_stmt!(sea_query::SelectStatement);
|
||||||
Self::MySql => SchemaBuilderBackend::MySql,
|
build_query_stmt!(sea_query::UpdateStatement);
|
||||||
Self::Postgres => SchemaBuilderBackend::Postgres,
|
build_query_stmt!(sea_query::DeleteStatement);
|
||||||
Self::Sqlite => SchemaBuilderBackend::Sqlite,
|
|
||||||
|
macro_rules! build_schema_stmt {
|
||||||
|
($stmt: ty) => {
|
||||||
|
impl StatementBuilder for $stmt {
|
||||||
|
fn build(&self, db_backend: &DbBackend) -> Statement {
|
||||||
|
let stmt = build_any_stmt!(self, db_backend);
|
||||||
|
Statement::from_string(*db_backend, stmt)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QueryBuilderWithSyntax for MysqlQueryBuilder {
|
build_schema_stmt!(sea_query::TableCreateStatement);
|
||||||
fn syntax(&self) -> Syntax {
|
build_schema_stmt!(sea_query::TableDropStatement);
|
||||||
Syntax::MySql
|
build_schema_stmt!(sea_query::TableAlterStatement);
|
||||||
}
|
build_schema_stmt!(sea_query::TableRenameStatement);
|
||||||
}
|
build_schema_stmt!(sea_query::TableTruncateStatement);
|
||||||
|
|
||||||
impl QueryBuilderWithSyntax for PostgresQueryBuilder {
|
|
||||||
fn syntax(&self) -> Syntax {
|
|
||||||
Syntax::Postgres
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl QueryBuilderWithSyntax for SqliteQueryBuilder {
|
|
||||||
fn syntax(&self) -> Syntax {
|
|
||||||
Syntax::Sqlite
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{Statement, Syntax};
|
use crate::{DbBackend, Statement};
|
||||||
use sea_query::{Value, Values};
|
use sea_query::{Value, Values};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
@ -7,12 +7,12 @@ pub struct Transaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Transaction {
|
impl Transaction {
|
||||||
pub fn from_sql_and_values<I>(syntax: Syntax, sql: &str, values: I) -> Self
|
pub fn from_sql_and_values<I>(db_backend: DbBackend, sql: &str, values: I) -> Self
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = Value>,
|
I: IntoIterator<Item = Value>,
|
||||||
{
|
{
|
||||||
Self::one(Statement::from_string_values_tuple(
|
Self::one(Statement::from_string_values_tuple(
|
||||||
syntax,
|
db_backend,
|
||||||
(sql.to_string(), Values(values.into_iter().collect())),
|
(sql.to_string(), Values(values.into_iter().collect())),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
debug_print, error::*, DatabaseConnection, ExecResult, MockDatabase, QueryBuilderBackend,
|
debug_print, error::*, DbBackend, DatabaseConnection, ExecResult, MockDatabase,
|
||||||
QueryResult, SchemaBuilderBackend, Statement, Syntax, Transaction,
|
QueryResult, Statement, Transaction,
|
||||||
};
|
};
|
||||||
use std::sync::{
|
use std::sync::{
|
||||||
atomic::{AtomicUsize, Ordering},
|
atomic::{AtomicUsize, Ordering},
|
||||||
@ -21,7 +21,7 @@ pub trait MockDatabaseTrait: Send {
|
|||||||
|
|
||||||
fn drain_transaction_log(&mut self) -> Vec<Transaction>;
|
fn drain_transaction_log(&mut self) -> Vec<Transaction>;
|
||||||
|
|
||||||
fn get_syntax(&self) -> Syntax;
|
fn get_database_backend(&self) -> DbBackend;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MockDatabaseConnector {
|
impl MockDatabaseConnector {
|
||||||
@ -48,13 +48,13 @@ impl MockDatabaseConnector {
|
|||||||
|
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
if crate::SqlxMySqlConnector::accepts(string) {
|
if crate::SqlxMySqlConnector::accepts(string) {
|
||||||
return connect_mock_db!(Syntax::MySql);
|
return connect_mock_db!(DbBackend::MySql);
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sqlx-sqlite")]
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
if crate::SqlxSqliteConnector::accepts(string) {
|
if crate::SqlxSqliteConnector::accepts(string) {
|
||||||
return connect_mock_db!(Syntax::Sqlite);
|
return connect_mock_db!(DbBackend::Sqlite);
|
||||||
}
|
}
|
||||||
connect_mock_db!(Syntax::Postgres)
|
connect_mock_db!(DbBackend::Postgres)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,19 +92,7 @@ impl MockDatabaseConnection {
|
|||||||
self.mocker.lock().unwrap().query(counter, statement)
|
self.mocker.lock().unwrap().query(counter, statement)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_query_builder_backend(&self) -> QueryBuilderBackend {
|
pub fn get_database_backend(&self) -> DbBackend {
|
||||||
self.mocker
|
self.mocker.lock().unwrap().get_database_backend()
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.get_syntax()
|
|
||||||
.get_query_builder_backend()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_schema_builder_backend(&self) -> SchemaBuilderBackend {
|
|
||||||
self.mocker
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.get_syntax()
|
|
||||||
.get_schema_builder_backend()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,8 @@ pub trait EntityName: IdenStatic + Default {
|
|||||||
Self::table_name(self)
|
Self::table_name(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Each table in database correspond to a Entity implemented [`EntityTrait`].
|
|
||||||
|
/// An Entity implementing `EntityTrait` represents a table in a database.
|
||||||
///
|
///
|
||||||
/// This trait provides an API for you to inspect it's properties
|
/// This trait provides an API for you to inspect it's properties
|
||||||
/// - Column (implemented [`ColumnTrait`])
|
/// - Column (implemented [`ColumnTrait`])
|
||||||
@ -70,9 +71,9 @@ pub trait EntityTrait: EntityName {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(feature = "mock")]
|
/// # #[cfg(feature = "mock")]
|
||||||
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, Transaction, Syntax};
|
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, Transaction, DbBackend};
|
||||||
/// #
|
/// #
|
||||||
/// # let db = MockDatabase::new(Syntax::Postgres)
|
/// # let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
/// # .append_query_results(vec![
|
/// # .append_query_results(vec![
|
||||||
/// # vec![
|
/// # vec![
|
||||||
/// # cake::Model {
|
/// # cake::Model {
|
||||||
@ -126,10 +127,10 @@ pub trait EntityTrait: EntityName {
|
|||||||
/// db.into_transaction_log(),
|
/// db.into_transaction_log(),
|
||||||
/// vec![
|
/// vec![
|
||||||
/// Transaction::from_sql_and_values(
|
/// Transaction::from_sql_and_values(
|
||||||
/// Syntax::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake" LIMIT $1"#, vec![1u64.into()]
|
/// DbBackend::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake" LIMIT $1"#, vec![1u64.into()]
|
||||||
/// ),
|
/// ),
|
||||||
/// Transaction::from_sql_and_values(
|
/// Transaction::from_sql_and_values(
|
||||||
/// Syntax::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake""#, vec![]
|
/// DbBackend::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake""#, vec![]
|
||||||
/// ),
|
/// ),
|
||||||
/// ]);
|
/// ]);
|
||||||
/// ```
|
/// ```
|
||||||
@ -143,9 +144,9 @@ pub trait EntityTrait: EntityName {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(feature = "mock")]
|
/// # #[cfg(feature = "mock")]
|
||||||
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, Transaction, Syntax};
|
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, Transaction, DbBackend};
|
||||||
/// #
|
/// #
|
||||||
/// # let db = MockDatabase::new(Syntax::Postgres)
|
/// # let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
/// # .append_query_results(vec![
|
/// # .append_query_results(vec![
|
||||||
/// # vec![
|
/// # vec![
|
||||||
/// # cake::Model {
|
/// # cake::Model {
|
||||||
@ -174,15 +175,15 @@ pub trait EntityTrait: EntityName {
|
|||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// db.into_transaction_log(),
|
/// db.into_transaction_log(),
|
||||||
/// vec![Transaction::from_sql_and_values(
|
/// vec![Transaction::from_sql_and_values(
|
||||||
/// Syntax::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake" WHERE "cake"."id" = $1"#, vec![11i32.into()]
|
/// DbBackend::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake" WHERE "cake"."id" = $1"#, vec![11i32.into()]
|
||||||
/// )]);
|
/// )]);
|
||||||
/// ```
|
/// ```
|
||||||
/// Find by composite key
|
/// Find by composite key
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(feature = "mock")]
|
/// # #[cfg(feature = "mock")]
|
||||||
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, Transaction, Syntax};
|
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, Transaction, DbBackend};
|
||||||
/// #
|
/// #
|
||||||
/// # let db = MockDatabase::new(Syntax::Postgres)
|
/// # let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
/// # .append_query_results(vec![
|
/// # .append_query_results(vec![
|
||||||
/// # vec![
|
/// # vec![
|
||||||
/// # cake_filling::Model {
|
/// # cake_filling::Model {
|
||||||
@ -211,7 +212,7 @@ pub trait EntityTrait: EntityName {
|
|||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// db.into_transaction_log(),
|
/// db.into_transaction_log(),
|
||||||
/// vec![Transaction::from_sql_and_values(
|
/// vec![Transaction::from_sql_and_values(
|
||||||
/// Syntax::Postgres,
|
/// DbBackend::Postgres,
|
||||||
/// [
|
/// [
|
||||||
/// r#"SELECT "cake_filling"."cake_id", "cake_filling"."filling_id" FROM "cake_filling""#,
|
/// r#"SELECT "cake_filling"."cake_id", "cake_filling"."filling_id" FROM "cake_filling""#,
|
||||||
/// r#"WHERE "cake_filling"."cake_id" = $1 AND "cake_filling"."filling_id" = $2"#,
|
/// r#"WHERE "cake_filling"."cake_id" = $1 AND "cake_filling"."filling_id" = $2"#,
|
||||||
@ -245,9 +246,9 @@ pub trait EntityTrait: EntityName {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(feature = "mock")]
|
/// # #[cfg(feature = "mock")]
|
||||||
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, Syntax};
|
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, DbBackend};
|
||||||
/// #
|
/// #
|
||||||
/// # let db = MockDatabase::new(Syntax::Postgres)
|
/// # let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
/// # .append_exec_results(vec![
|
/// # .append_exec_results(vec![
|
||||||
/// # MockExecResult {
|
/// # MockExecResult {
|
||||||
/// # last_insert_id: 15,
|
/// # last_insert_id: 15,
|
||||||
@ -276,7 +277,7 @@ pub trait EntityTrait: EntityName {
|
|||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// db.into_transaction_log(),
|
/// db.into_transaction_log(),
|
||||||
/// vec![Transaction::from_sql_and_values(
|
/// vec![Transaction::from_sql_and_values(
|
||||||
/// Syntax::Postgres, r#"INSERT INTO "cake" ("name") VALUES ($1)"#, vec!["Apple Pie".into()]
|
/// DbBackend::Postgres, r#"INSERT INTO "cake" ("name") VALUES ($1)"#, vec!["Apple Pie".into()]
|
||||||
/// )]);
|
/// )]);
|
||||||
/// ```
|
/// ```
|
||||||
fn insert<A>(model: A) -> Insert<A>
|
fn insert<A>(model: A) -> Insert<A>
|
||||||
@ -292,9 +293,9 @@ pub trait EntityTrait: EntityName {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(feature = "mock")]
|
/// # #[cfg(feature = "mock")]
|
||||||
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, Syntax};
|
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, DbBackend};
|
||||||
/// #
|
/// #
|
||||||
/// # let db = MockDatabase::new(Syntax::Postgres)
|
/// # let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
/// # .append_exec_results(vec![
|
/// # .append_exec_results(vec![
|
||||||
/// # MockExecResult {
|
/// # MockExecResult {
|
||||||
/// # last_insert_id: 28,
|
/// # last_insert_id: 28,
|
||||||
@ -327,7 +328,7 @@ pub trait EntityTrait: EntityName {
|
|||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// db.into_transaction_log(),
|
/// db.into_transaction_log(),
|
||||||
/// vec![Transaction::from_sql_and_values(
|
/// vec![Transaction::from_sql_and_values(
|
||||||
/// Syntax::Postgres, r#"INSERT INTO "cake" ("name") VALUES ($1), ($2)"#,
|
/// DbBackend::Postgres, r#"INSERT INTO "cake" ("name") VALUES ($1), ($2)"#,
|
||||||
/// vec!["Apple Pie".into(), "Orange Scone".into()]
|
/// vec!["Apple Pie".into(), "Orange Scone".into()]
|
||||||
/// )]);
|
/// )]);
|
||||||
/// ```
|
/// ```
|
||||||
@ -347,9 +348,9 @@ pub trait EntityTrait: EntityName {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(feature = "mock")]
|
/// # #[cfg(feature = "mock")]
|
||||||
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, Syntax};
|
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, DbBackend};
|
||||||
/// #
|
/// #
|
||||||
/// # let db = MockDatabase::new(Syntax::Postgres)
|
/// # let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
/// # .append_exec_results(vec![
|
/// # .append_exec_results(vec![
|
||||||
/// # MockExecResult {
|
/// # MockExecResult {
|
||||||
/// # last_insert_id: 0,
|
/// # last_insert_id: 0,
|
||||||
@ -379,7 +380,7 @@ pub trait EntityTrait: EntityName {
|
|||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// db.into_transaction_log(),
|
/// db.into_transaction_log(),
|
||||||
/// vec![Transaction::from_sql_and_values(
|
/// vec![Transaction::from_sql_and_values(
|
||||||
/// Syntax::Postgres, r#"UPDATE "fruit" SET "name" = $1 WHERE "fruit"."id" = $2"#, vec!["Orange".into(), 1i32.into()]
|
/// DbBackend::Postgres, r#"UPDATE "fruit" SET "name" = $1 WHERE "fruit"."id" = $2"#, vec!["Orange".into(), 1i32.into()]
|
||||||
/// )]);
|
/// )]);
|
||||||
/// ```
|
/// ```
|
||||||
fn update<A>(model: A) -> UpdateOne<A>
|
fn update<A>(model: A) -> UpdateOne<A>
|
||||||
@ -397,9 +398,9 @@ pub trait EntityTrait: EntityName {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(feature = "mock")]
|
/// # #[cfg(feature = "mock")]
|
||||||
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, Syntax};
|
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, DbBackend};
|
||||||
/// #
|
/// #
|
||||||
/// # let db = MockDatabase::new(Syntax::Postgres)
|
/// # let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
/// # .append_exec_results(vec![
|
/// # .append_exec_results(vec![
|
||||||
/// # MockExecResult {
|
/// # MockExecResult {
|
||||||
/// # last_insert_id: 0,
|
/// # last_insert_id: 0,
|
||||||
@ -426,7 +427,7 @@ pub trait EntityTrait: EntityName {
|
|||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// db.into_transaction_log(),
|
/// db.into_transaction_log(),
|
||||||
/// vec![Transaction::from_sql_and_values(
|
/// vec![Transaction::from_sql_and_values(
|
||||||
/// Syntax::Postgres, r#"UPDATE "fruit" SET "cake_id" = $1 WHERE "fruit"."name" LIKE $2"#, vec![Value::Null, "%Apple%".into()]
|
/// DbBackend::Postgres, r#"UPDATE "fruit" SET "cake_id" = $1 WHERE "fruit"."name" LIKE $2"#, vec![Value::Null, "%Apple%".into()]
|
||||||
/// )]);
|
/// )]);
|
||||||
/// ```
|
/// ```
|
||||||
fn update_many() -> UpdateMany<Self> {
|
fn update_many() -> UpdateMany<Self> {
|
||||||
@ -441,9 +442,9 @@ pub trait EntityTrait: EntityName {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(feature = "mock")]
|
/// # #[cfg(feature = "mock")]
|
||||||
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, Syntax};
|
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, DbBackend};
|
||||||
/// #
|
/// #
|
||||||
/// # let db = MockDatabase::new(Syntax::Postgres)
|
/// # let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
/// # .append_exec_results(vec![
|
/// # .append_exec_results(vec![
|
||||||
/// # MockExecResult {
|
/// # MockExecResult {
|
||||||
/// # last_insert_id: 0,
|
/// # last_insert_id: 0,
|
||||||
@ -471,7 +472,7 @@ pub trait EntityTrait: EntityName {
|
|||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// db.into_transaction_log(),
|
/// db.into_transaction_log(),
|
||||||
/// vec![Transaction::from_sql_and_values(
|
/// vec![Transaction::from_sql_and_values(
|
||||||
/// Syntax::Postgres, r#"DELETE FROM "fruit" WHERE "fruit"."id" = $1"#, vec![3i32.into()]
|
/// DbBackend::Postgres, r#"DELETE FROM "fruit" WHERE "fruit"."id" = $1"#, vec![3i32.into()]
|
||||||
/// )]);
|
/// )]);
|
||||||
/// ```
|
/// ```
|
||||||
fn delete<A>(model: A) -> DeleteOne<A>
|
fn delete<A>(model: A) -> DeleteOne<A>
|
||||||
@ -489,9 +490,9 @@ pub trait EntityTrait: EntityName {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[cfg(feature = "mock")]
|
/// # #[cfg(feature = "mock")]
|
||||||
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, Syntax};
|
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, DbBackend};
|
||||||
/// #
|
/// #
|
||||||
/// # let db = MockDatabase::new(Syntax::Postgres)
|
/// # let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
/// # .append_exec_results(vec![
|
/// # .append_exec_results(vec![
|
||||||
/// # MockExecResult {
|
/// # MockExecResult {
|
||||||
/// # last_insert_id: 0,
|
/// # last_insert_id: 0,
|
||||||
@ -517,7 +518,7 @@ pub trait EntityTrait: EntityName {
|
|||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// db.into_transaction_log(),
|
/// db.into_transaction_log(),
|
||||||
/// vec![Transaction::from_sql_and_values(
|
/// vec![Transaction::from_sql_and_values(
|
||||||
/// Syntax::Postgres, r#"DELETE FROM "fruit" WHERE "fruit"."name" LIKE $1"#, vec!["%Apple%".into()]
|
/// DbBackend::Postgres, r#"DELETE FROM "fruit" WHERE "fruit"."name" LIKE $1"#, vec!["%Apple%".into()]
|
||||||
/// )]);
|
/// )]);
|
||||||
/// ```
|
/// ```
|
||||||
fn delete_many() -> DeleteMany<Self> {
|
fn delete_many() -> DeleteMany<Self> {
|
||||||
|
@ -88,12 +88,12 @@ pub trait ColumnTrait: IdenStatic + Iterable {
|
|||||||
bind_oper!(lte);
|
bind_oper!(lte);
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::MysqlQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// cake::Entity::find()
|
/// cake::Entity::find()
|
||||||
/// .filter(cake::Column::Id.between(2,3))
|
/// .filter(cake::Column::Id.between(2,3))
|
||||||
/// .build(MysqlQueryBuilder)
|
/// .build(DbBackend::MySql)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` BETWEEN 2 AND 3"
|
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` BETWEEN 2 AND 3"
|
||||||
/// );
|
/// );
|
||||||
@ -106,12 +106,12 @@ pub trait ColumnTrait: IdenStatic + Iterable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::MysqlQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// cake::Entity::find()
|
/// cake::Entity::find()
|
||||||
/// .filter(cake::Column::Id.not_between(2,3))
|
/// .filter(cake::Column::Id.not_between(2,3))
|
||||||
/// .build(MysqlQueryBuilder)
|
/// .build(DbBackend::MySql)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` NOT BETWEEN 2 AND 3"
|
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` NOT BETWEEN 2 AND 3"
|
||||||
/// );
|
/// );
|
||||||
@ -124,12 +124,12 @@ pub trait ColumnTrait: IdenStatic + Iterable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::MysqlQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// cake::Entity::find()
|
/// cake::Entity::find()
|
||||||
/// .filter(cake::Column::Name.like("cheese"))
|
/// .filter(cake::Column::Name.like("cheese"))
|
||||||
/// .build(MysqlQueryBuilder)
|
/// .build(DbBackend::MySql)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`name` LIKE 'cheese'"
|
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`name` LIKE 'cheese'"
|
||||||
/// );
|
/// );
|
||||||
@ -139,12 +139,12 @@ pub trait ColumnTrait: IdenStatic + Iterable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::MysqlQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// cake::Entity::find()
|
/// cake::Entity::find()
|
||||||
/// .filter(cake::Column::Name.not_like("cheese"))
|
/// .filter(cake::Column::Name.not_like("cheese"))
|
||||||
/// .build(MysqlQueryBuilder)
|
/// .build(DbBackend::MySql)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`name` NOT LIKE 'cheese'"
|
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`name` NOT LIKE 'cheese'"
|
||||||
/// );
|
/// );
|
||||||
@ -154,12 +154,12 @@ pub trait ColumnTrait: IdenStatic + Iterable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::MysqlQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// cake::Entity::find()
|
/// cake::Entity::find()
|
||||||
/// .filter(cake::Column::Name.starts_with("cheese"))
|
/// .filter(cake::Column::Name.starts_with("cheese"))
|
||||||
/// .build(MysqlQueryBuilder)
|
/// .build(DbBackend::MySql)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`name` LIKE 'cheese%'"
|
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`name` LIKE 'cheese%'"
|
||||||
/// );
|
/// );
|
||||||
@ -170,12 +170,12 @@ pub trait ColumnTrait: IdenStatic + Iterable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::MysqlQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// cake::Entity::find()
|
/// cake::Entity::find()
|
||||||
/// .filter(cake::Column::Name.ends_with("cheese"))
|
/// .filter(cake::Column::Name.ends_with("cheese"))
|
||||||
/// .build(MysqlQueryBuilder)
|
/// .build(DbBackend::MySql)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`name` LIKE '%cheese'"
|
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`name` LIKE '%cheese'"
|
||||||
/// );
|
/// );
|
||||||
@ -186,12 +186,12 @@ pub trait ColumnTrait: IdenStatic + Iterable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::MysqlQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// cake::Entity::find()
|
/// cake::Entity::find()
|
||||||
/// .filter(cake::Column::Name.contains("cheese"))
|
/// .filter(cake::Column::Name.contains("cheese"))
|
||||||
/// .build(MysqlQueryBuilder)
|
/// .build(DbBackend::MySql)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`name` LIKE '%cheese%'"
|
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`name` LIKE '%cheese%'"
|
||||||
/// );
|
/// );
|
||||||
@ -245,29 +245,29 @@ impl ColumnDef {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<sea_query::ColumnType> for ColumnType {
|
impl From<ColumnType> for sea_query::ColumnType {
|
||||||
fn into(self) -> sea_query::ColumnType {
|
fn from(col: ColumnType) -> Self {
|
||||||
match self {
|
match col {
|
||||||
Self::Char(s) => sea_query::ColumnType::Char(s),
|
ColumnType::Char(s) => sea_query::ColumnType::Char(s),
|
||||||
Self::String(s) => sea_query::ColumnType::String(s),
|
ColumnType::String(s) => sea_query::ColumnType::String(s),
|
||||||
Self::Text => sea_query::ColumnType::Text,
|
ColumnType::Text => sea_query::ColumnType::Text,
|
||||||
Self::TinyInteger => sea_query::ColumnType::TinyInteger(None),
|
ColumnType::TinyInteger => sea_query::ColumnType::TinyInteger(None),
|
||||||
Self::SmallInteger => sea_query::ColumnType::SmallInteger(None),
|
ColumnType::SmallInteger => sea_query::ColumnType::SmallInteger(None),
|
||||||
Self::Integer => sea_query::ColumnType::Integer(None),
|
ColumnType::Integer => sea_query::ColumnType::Integer(None),
|
||||||
Self::BigInteger => sea_query::ColumnType::BigInteger(None),
|
ColumnType::BigInteger => sea_query::ColumnType::BigInteger(None),
|
||||||
Self::Float => sea_query::ColumnType::Float(None),
|
ColumnType::Float => sea_query::ColumnType::Float(None),
|
||||||
Self::Double => sea_query::ColumnType::Double(None),
|
ColumnType::Double => sea_query::ColumnType::Double(None),
|
||||||
Self::Decimal(s) => sea_query::ColumnType::Decimal(s),
|
ColumnType::Decimal(s) => sea_query::ColumnType::Decimal(s),
|
||||||
Self::DateTime => sea_query::ColumnType::DateTime(None),
|
ColumnType::DateTime => sea_query::ColumnType::DateTime(None),
|
||||||
Self::Timestamp => sea_query::ColumnType::Timestamp(None),
|
ColumnType::Timestamp => sea_query::ColumnType::Timestamp(None),
|
||||||
Self::Time => sea_query::ColumnType::Time(None),
|
ColumnType::Time => sea_query::ColumnType::Time(None),
|
||||||
Self::Date => sea_query::ColumnType::Date,
|
ColumnType::Date => sea_query::ColumnType::Date,
|
||||||
Self::Binary => sea_query::ColumnType::Binary(None),
|
ColumnType::Binary => sea_query::ColumnType::Binary(None),
|
||||||
Self::Boolean => sea_query::ColumnType::Boolean,
|
ColumnType::Boolean => sea_query::ColumnType::Boolean,
|
||||||
Self::Money(s) => sea_query::ColumnType::Money(s),
|
ColumnType::Money(s) => sea_query::ColumnType::Money(s),
|
||||||
Self::Json => sea_query::ColumnType::Json,
|
ColumnType::Json => sea_query::ColumnType::Json,
|
||||||
Self::JsonBinary => sea_query::ColumnType::JsonBinary,
|
ColumnType::JsonBinary => sea_query::ColumnType::JsonBinary,
|
||||||
Self::Custom(s) => {
|
ColumnType::Custom(s) => {
|
||||||
sea_query::ColumnType::Custom(sea_query::SeaRc::new(sea_query::Alias::new(&s)))
|
sea_query::ColumnType::Custom(sea_query::SeaRc::new(sea_query::Alias::new(&s)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ impl Deleter {
|
|||||||
self,
|
self,
|
||||||
db: &DatabaseConnection,
|
db: &DatabaseConnection,
|
||||||
) -> impl Future<Output = Result<DeleteResult, DbErr>> + '_ {
|
) -> impl Future<Output = Result<DeleteResult, DbErr>> + '_ {
|
||||||
let builder = db.get_query_builder_backend();
|
let builder = db.get_database_backend();
|
||||||
exec_delete(builder.build(&self.query), db)
|
exec_delete(builder.build(&self.query), db)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ impl Inserter {
|
|||||||
self,
|
self,
|
||||||
db: &DatabaseConnection,
|
db: &DatabaseConnection,
|
||||||
) -> impl Future<Output = Result<InsertResult, DbErr>> + '_ {
|
) -> impl Future<Output = Result<InsertResult, DbErr>> + '_ {
|
||||||
let builder = db.get_query_builder_backend();
|
let builder = db.get_database_backend();
|
||||||
exec_insert(builder.build(&self.query), db)
|
exec_insert(builder.build(&self.query), db)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,8 @@ where
|
|||||||
pub(crate) selector: PhantomData<S>,
|
pub(crate) selector: PhantomData<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LINT: warn if paginator is used without an order by clause
|
||||||
|
|
||||||
impl<'db, S> Paginator<'db, S>
|
impl<'db, S> Paginator<'db, S>
|
||||||
where
|
where
|
||||||
S: SelectorTrait + 'db,
|
S: SelectorTrait + 'db,
|
||||||
@ -30,7 +32,7 @@ where
|
|||||||
.limit(self.page_size as u64)
|
.limit(self.page_size as u64)
|
||||||
.offset((self.page_size * page) as u64)
|
.offset((self.page_size * page) as u64)
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let builder = self.db.get_query_builder_backend();
|
let builder = self.db.get_database_backend();
|
||||||
let stmt = builder.build(&query);
|
let stmt = builder.build(&query);
|
||||||
let rows = self.db.query_all(stmt).await?;
|
let rows = self.db.query_all(stmt).await?;
|
||||||
let mut buffer = Vec::with_capacity(rows.len());
|
let mut buffer = Vec::with_capacity(rows.len());
|
||||||
@ -46,12 +48,12 @@ where
|
|||||||
self.fetch_page(self.page).await
|
self.fetch_page(self.page).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the total number of pages
|
/// Get the total number of items
|
||||||
pub async fn num_pages(&self) -> Result<usize, DbErr> {
|
pub async fn num_items(&self) -> Result<usize, DbErr> {
|
||||||
let builder = self.db.get_query_builder_backend();
|
let builder = self.db.get_database_backend();
|
||||||
let stmt = builder.build(
|
let stmt = builder.build(
|
||||||
SelectStatement::new()
|
SelectStatement::new()
|
||||||
.expr(Expr::cust("COUNT(*) AS num_rows"))
|
.expr(Expr::cust("COUNT(*) AS num_items"))
|
||||||
.from_subquery(
|
.from_subquery(
|
||||||
self.query.clone().reset_limit().reset_offset().to_owned(),
|
self.query.clone().reset_limit().reset_offset().to_owned(),
|
||||||
Alias::new("sub_query"),
|
Alias::new("sub_query"),
|
||||||
@ -61,8 +63,14 @@ where
|
|||||||
Some(res) => res,
|
Some(res) => res,
|
||||||
None => return Ok(0),
|
None => return Ok(0),
|
||||||
};
|
};
|
||||||
let num_rows = result.try_get::<i32>("", "num_rows")? as usize;
|
let num_items = result.try_get::<i32>("", "num_items")? as usize;
|
||||||
let num_pages = (num_rows / self.page_size) + (num_rows % self.page_size > 0) as usize;
|
Ok(num_items)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the total number of pages
|
||||||
|
pub async fn num_pages(&self) -> Result<usize, DbErr> {
|
||||||
|
let num_items = self.num_items().await?;
|
||||||
|
let num_pages = (num_items / self.page_size) + (num_items % self.page_size > 0) as usize;
|
||||||
Ok(num_pages)
|
Ok(num_pages)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +85,26 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Fetch one page and increment the page counter
|
/// Fetch one page and increment the page counter
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #[cfg(feature = "mock")]
|
||||||
|
/// # use sea_orm::{error::*, MockDatabase, DbBackend};
|
||||||
|
/// # let owned_db = MockDatabase::new(DbBackend::Postgres).into_connection();
|
||||||
|
/// # let db = &owned_db;
|
||||||
|
/// # let _: Result<(), DbErr> = async_std::task::block_on(async {
|
||||||
|
/// #
|
||||||
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake};
|
||||||
|
/// let mut cake_pages = cake::Entity::find()
|
||||||
|
/// .order_by_asc(cake::Column::Id)
|
||||||
|
/// .paginate(db, 50);
|
||||||
|
///
|
||||||
|
/// while let Some(cakes) = cake_pages.fetch_and_next().await? {
|
||||||
|
/// // Do something on cakes: Vec<cake::Model>
|
||||||
|
/// }
|
||||||
|
/// #
|
||||||
|
/// # Ok(())
|
||||||
|
/// # });
|
||||||
|
/// ```
|
||||||
pub async fn fetch_and_next(&mut self) -> Result<Option<Vec<S::Item>>, DbErr> {
|
pub async fn fetch_and_next(&mut self) -> Result<Option<Vec<S::Item>>, DbErr> {
|
||||||
let vec = self.fetch().await?;
|
let vec = self.fetch().await?;
|
||||||
self.next();
|
self.next();
|
||||||
@ -85,6 +113,28 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert self into an async stream
|
/// Convert self into an async stream
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #[cfg(feature = "mock")]
|
||||||
|
/// # use sea_orm::{error::*, MockDatabase, DbBackend};
|
||||||
|
/// # let owned_db = MockDatabase::new(DbBackend::Postgres).into_connection();
|
||||||
|
/// # let db = &owned_db;
|
||||||
|
/// # let _: Result<(), DbErr> = async_std::task::block_on(async {
|
||||||
|
/// #
|
||||||
|
/// use futures::TryStreamExt;
|
||||||
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake};
|
||||||
|
/// let mut cake_stream = cake::Entity::find()
|
||||||
|
/// .order_by_asc(cake::Column::Id)
|
||||||
|
/// .paginate(db, 50)
|
||||||
|
/// .into_stream();
|
||||||
|
///
|
||||||
|
/// while let Some(cakes) = cake_stream.try_next().await? {
|
||||||
|
/// // Do something on cakes: Vec<cake::Model>
|
||||||
|
/// }
|
||||||
|
/// #
|
||||||
|
/// # Ok(())
|
||||||
|
/// # });
|
||||||
|
/// ```
|
||||||
pub fn into_stream(mut self) -> PinBoxStream<'db, Result<Vec<S::Item>, DbErr>> {
|
pub fn into_stream(mut self) -> PinBoxStream<'db, Result<Vec<S::Item>, DbErr>> {
|
||||||
Box::pin(stream! {
|
Box::pin(stream! {
|
||||||
loop {
|
loop {
|
||||||
@ -103,7 +153,7 @@ where
|
|||||||
mod tests {
|
mod tests {
|
||||||
use crate::entity::prelude::*;
|
use crate::entity::prelude::*;
|
||||||
use crate::tests_cfg::*;
|
use crate::tests_cfg::*;
|
||||||
use crate::{DatabaseConnection, MockDatabase, Syntax, Transaction};
|
use crate::{DbBackend, DatabaseConnection, MockDatabase, Transaction};
|
||||||
use futures::TryStreamExt;
|
use futures::TryStreamExt;
|
||||||
use sea_query::{Alias, Expr, SelectStatement, Value};
|
use sea_query::{Alias, Expr, SelectStatement, Value};
|
||||||
|
|
||||||
@ -129,22 +179,22 @@ mod tests {
|
|||||||
|
|
||||||
let page3 = Vec::<fruit::Model>::new();
|
let page3 = Vec::<fruit::Model>::new();
|
||||||
|
|
||||||
let db = MockDatabase::new(Syntax::Postgres)
|
let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
.append_query_results(vec![page1.clone(), page2.clone(), page3.clone()])
|
.append_query_results(vec![page1.clone(), page2.clone(), page3.clone()])
|
||||||
.into_connection();
|
.into_connection();
|
||||||
|
|
||||||
(db, vec![page1, page2, page3])
|
(db, vec![page1, page2, page3])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_num_rows() -> (DatabaseConnection, i32) {
|
fn setup_num_items() -> (DatabaseConnection, i32) {
|
||||||
let num_rows = 3;
|
let num_items = 3;
|
||||||
let db = MockDatabase::new(Syntax::Postgres)
|
let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
.append_query_results(vec![vec![maplit::btreemap! {
|
.append_query_results(vec![vec![maplit::btreemap! {
|
||||||
"num_rows" => Into::<Value>::into(num_rows),
|
"num_items" => Into::<Value>::into(num_items),
|
||||||
}]])
|
}]])
|
||||||
.into_connection();
|
.into_connection();
|
||||||
|
|
||||||
(db, num_rows)
|
(db, num_items)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
@ -166,7 +216,7 @@ mod tests {
|
|||||||
.from(fruit::Entity)
|
.from(fruit::Entity)
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
let query_builder = db.get_query_builder_backend();
|
let query_builder = db.get_database_backend();
|
||||||
let stmts = vec![
|
let stmts = vec![
|
||||||
query_builder.build(select.clone().offset(0).limit(2)),
|
query_builder.build(select.clone().offset(0).limit(2)),
|
||||||
query_builder.build(select.clone().offset(2).limit(2)),
|
query_builder.build(select.clone().offset(2).limit(2)),
|
||||||
@ -200,7 +250,7 @@ mod tests {
|
|||||||
.from(fruit::Entity)
|
.from(fruit::Entity)
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
let query_builder = db.get_query_builder_backend();
|
let query_builder = db.get_database_backend();
|
||||||
let stmts = vec![
|
let stmts = vec![
|
||||||
query_builder.build(select.clone().offset(0).limit(2)),
|
query_builder.build(select.clone().offset(0).limit(2)),
|
||||||
query_builder.build(select.clone().offset(2).limit(2)),
|
query_builder.build(select.clone().offset(2).limit(2)),
|
||||||
@ -213,11 +263,11 @@ mod tests {
|
|||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
async fn num_pages() -> Result<(), DbErr> {
|
async fn num_pages() -> Result<(), DbErr> {
|
||||||
let (db, num_rows) = setup_num_rows();
|
let (db, num_items) = setup_num_items();
|
||||||
|
|
||||||
let num_rows = num_rows as usize;
|
let num_items = num_items as usize;
|
||||||
let page_size = 2_usize;
|
let page_size = 2_usize;
|
||||||
let num_pages = (num_rows / page_size) + (num_rows % page_size > 0) as usize;
|
let num_pages = (num_items / page_size) + (num_items % page_size > 0) as usize;
|
||||||
let paginator = fruit::Entity::find().paginate(&db, page_size);
|
let paginator = fruit::Entity::find().paginate(&db, page_size);
|
||||||
|
|
||||||
assert_eq!(paginator.num_pages().await?, num_pages);
|
assert_eq!(paginator.num_pages().await?, num_pages);
|
||||||
@ -232,11 +282,11 @@ mod tests {
|
|||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
let select = SelectStatement::new()
|
let select = SelectStatement::new()
|
||||||
.expr(Expr::cust("COUNT(*) AS num_rows"))
|
.expr(Expr::cust("COUNT(*) AS num_items"))
|
||||||
.from_subquery(sub_query, Alias::new("sub_query"))
|
.from_subquery(sub_query, Alias::new("sub_query"))
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
let query_builder = db.get_query_builder_backend();
|
let query_builder = db.get_database_backend();
|
||||||
let stmts = vec![query_builder.build(&select)];
|
let stmts = vec![query_builder.build(&select)];
|
||||||
|
|
||||||
assert_eq!(db.into_transaction_log(), Transaction::wrap(stmts));
|
assert_eq!(db.into_transaction_log(), Transaction::wrap(stmts));
|
||||||
@ -283,7 +333,7 @@ mod tests {
|
|||||||
.from(fruit::Entity)
|
.from(fruit::Entity)
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
let query_builder = db.get_query_builder_backend();
|
let query_builder = db.get_database_backend();
|
||||||
let stmts = vec![
|
let stmts = vec![
|
||||||
query_builder.build(select.clone().offset(0).limit(2)),
|
query_builder.build(select.clone().offset(0).limit(2)),
|
||||||
query_builder.build(select.clone().offset(2).limit(2)),
|
query_builder.build(select.clone().offset(2).limit(2)),
|
||||||
@ -315,7 +365,7 @@ mod tests {
|
|||||||
.from(fruit::Entity)
|
.from(fruit::Entity)
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
let query_builder = db.get_query_builder_backend();
|
let query_builder = db.get_database_backend();
|
||||||
let stmts = vec![
|
let stmts = vec![
|
||||||
query_builder.build(select.clone().offset(0).limit(2)),
|
query_builder.build(select.clone().offset(0).limit(2)),
|
||||||
query_builder.build(select.clone().offset(2).limit(2)),
|
query_builder.build(select.clone().offset(2).limit(2)),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error::*, query::combine, DatabaseConnection, EntityTrait, FromQueryResult, Iterable,
|
error::*, query::combine, DatabaseConnection, EntityTrait, FromQueryResult, Iterable,
|
||||||
JsonValue, ModelTrait, Paginator, PrimaryKeyToColumn, QueryResult, Select, SelectTwo,
|
JsonValue, ModelTrait, Paginator, PrimaryKeyToColumn, QueryResult, Select, SelectTwo,
|
||||||
SelectTwoMany,
|
SelectTwoMany, Statement,
|
||||||
};
|
};
|
||||||
use sea_query::SelectStatement;
|
use sea_query::SelectStatement;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
@ -15,6 +15,15 @@ where
|
|||||||
selector: S,
|
selector: S,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct SelectorRaw<S>
|
||||||
|
where
|
||||||
|
S: SelectorTrait,
|
||||||
|
{
|
||||||
|
stmt: Statement,
|
||||||
|
selector: S,
|
||||||
|
}
|
||||||
|
|
||||||
pub trait SelectorTrait {
|
pub trait SelectorTrait {
|
||||||
type Item: Sized;
|
type Item: Sized;
|
||||||
|
|
||||||
@ -67,6 +76,56 @@ impl<E> Select<E>
|
|||||||
where
|
where
|
||||||
E: EntityTrait,
|
E: EntityTrait,
|
||||||
{
|
{
|
||||||
|
/// ```
|
||||||
|
/// # #[cfg(feature = "mock")]
|
||||||
|
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, Transaction, DbBackend};
|
||||||
|
/// #
|
||||||
|
/// # let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
|
/// # .append_query_results(vec![
|
||||||
|
/// # vec![
|
||||||
|
/// # cake::Model {
|
||||||
|
/// # id: 1,
|
||||||
|
/// # name: "New York Cheese".to_owned(),
|
||||||
|
/// # },
|
||||||
|
/// # ],
|
||||||
|
/// # ])
|
||||||
|
/// # .into_connection();
|
||||||
|
/// #
|
||||||
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake};
|
||||||
|
///
|
||||||
|
/// # let _: Result<(), DbErr> = async_std::task::block_on(async {
|
||||||
|
/// #
|
||||||
|
/// assert_eq!(
|
||||||
|
/// cake::Entity::find().from_raw_sql(
|
||||||
|
/// Statement::from_sql_and_values(
|
||||||
|
/// DbBackend::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake""#, vec![]
|
||||||
|
/// )
|
||||||
|
/// ).one(&db).await?,
|
||||||
|
/// Some(cake::Model {
|
||||||
|
/// id: 1,
|
||||||
|
/// name: "New York Cheese".to_owned(),
|
||||||
|
/// })
|
||||||
|
/// );
|
||||||
|
/// #
|
||||||
|
/// # Ok(())
|
||||||
|
/// # });
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// db.into_transaction_log(),
|
||||||
|
/// vec![
|
||||||
|
/// Transaction::from_sql_and_values(
|
||||||
|
/// DbBackend::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake""#, vec![]
|
||||||
|
/// ),
|
||||||
|
/// ]);
|
||||||
|
/// ```
|
||||||
|
#[allow(clippy::wrong_self_convention)]
|
||||||
|
pub fn from_raw_sql(self, stmt: Statement) -> SelectorRaw<SelectModel<E::Model>> {
|
||||||
|
SelectorRaw {
|
||||||
|
stmt,
|
||||||
|
selector: SelectModel { model: PhantomData },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn into_model<M>(self) -> Selector<SelectModel<M>>
|
pub fn into_model<M>(self) -> Selector<SelectModel<M>>
|
||||||
where
|
where
|
||||||
M: FromQueryResult,
|
M: FromQueryResult,
|
||||||
@ -86,11 +145,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn one(self, db: &DatabaseConnection) -> Result<Option<E::Model>, DbErr> {
|
pub async fn one(self, db: &DatabaseConnection) -> Result<Option<E::Model>, DbErr> {
|
||||||
self.into_model::<E::Model>().one(db).await
|
self.into_model().one(db).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn all(self, db: &DatabaseConnection) -> Result<Vec<E::Model>, DbErr> {
|
pub async fn all(self, db: &DatabaseConnection) -> Result<Vec<E::Model>, DbErr> {
|
||||||
self.into_model::<E::Model>().all(db).await
|
self.into_model().all(db).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn paginate(
|
pub fn paginate(
|
||||||
@ -98,7 +157,11 @@ where
|
|||||||
db: &DatabaseConnection,
|
db: &DatabaseConnection,
|
||||||
page_size: usize,
|
page_size: usize,
|
||||||
) -> Paginator<'_, SelectModel<E::Model>> {
|
) -> Paginator<'_, SelectModel<E::Model>> {
|
||||||
self.into_model::<E::Model>().paginate(db, page_size)
|
self.into_model().paginate(db, page_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn count(self, db: &DatabaseConnection) -> Result<usize, DbErr> {
|
||||||
|
self.paginate(db, 1).num_items().await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,14 +193,26 @@ where
|
|||||||
self,
|
self,
|
||||||
db: &DatabaseConnection,
|
db: &DatabaseConnection,
|
||||||
) -> Result<Option<(E::Model, Option<F::Model>)>, DbErr> {
|
) -> Result<Option<(E::Model, Option<F::Model>)>, DbErr> {
|
||||||
self.into_model::<E::Model, F::Model>().one(db).await
|
self.into_model().one(db).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn all(
|
pub async fn all(
|
||||||
self,
|
self,
|
||||||
db: &DatabaseConnection,
|
db: &DatabaseConnection,
|
||||||
) -> Result<Vec<(E::Model, Option<F::Model>)>, DbErr> {
|
) -> Result<Vec<(E::Model, Option<F::Model>)>, DbErr> {
|
||||||
self.into_model::<E::Model, F::Model>().all(db).await
|
self.into_model().all(db).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn paginate(
|
||||||
|
self,
|
||||||
|
db: &DatabaseConnection,
|
||||||
|
page_size: usize,
|
||||||
|
) -> Paginator<'_, SelectTwoModel<E::Model, F::Model>> {
|
||||||
|
self.into_model().paginate(db, page_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn count(self, db: &DatabaseConnection) -> Result<usize, DbErr> {
|
||||||
|
self.paginate(db, 1).num_items().await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,16 +244,25 @@ where
|
|||||||
self,
|
self,
|
||||||
db: &DatabaseConnection,
|
db: &DatabaseConnection,
|
||||||
) -> Result<Option<(E::Model, Option<F::Model>)>, DbErr> {
|
) -> Result<Option<(E::Model, Option<F::Model>)>, DbErr> {
|
||||||
self.into_model::<E::Model, F::Model>().one(db).await
|
self.into_model().one(db).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn all(
|
pub async fn all(
|
||||||
self,
|
self,
|
||||||
db: &DatabaseConnection,
|
db: &DatabaseConnection,
|
||||||
) -> Result<Vec<(E::Model, Vec<F::Model>)>, DbErr> {
|
) -> Result<Vec<(E::Model, Vec<F::Model>)>, DbErr> {
|
||||||
let rows = self.into_model::<E::Model, F::Model>().all(db).await?;
|
let rows = self.into_model().all(db).await?;
|
||||||
Ok(consolidate_query_result::<E, F>(rows))
|
Ok(consolidate_query_result::<E, F>(rows))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pub fn paginate()
|
||||||
|
// we could not implement paginate easily, if the number of children for a
|
||||||
|
// parent is larger than one page, then we will end up splitting it in two pages
|
||||||
|
// so the correct way is actually perform query in two stages
|
||||||
|
// paginate the parent model and then populate the children
|
||||||
|
|
||||||
|
// pub fn count()
|
||||||
|
// we should only count the number of items of the parent model
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Selector<S>
|
impl<S> Selector<S>
|
||||||
@ -186,7 +270,7 @@ where
|
|||||||
S: SelectorTrait,
|
S: SelectorTrait,
|
||||||
{
|
{
|
||||||
pub async fn one(mut self, db: &DatabaseConnection) -> Result<Option<S::Item>, DbErr> {
|
pub async fn one(mut self, db: &DatabaseConnection) -> Result<Option<S::Item>, DbErr> {
|
||||||
let builder = db.get_query_builder_backend();
|
let builder = db.get_database_backend();
|
||||||
self.query.limit(1);
|
self.query.limit(1);
|
||||||
let row = db.query_one(builder.build(&self.query)).await?;
|
let row = db.query_one(builder.build(&self.query)).await?;
|
||||||
match row {
|
match row {
|
||||||
@ -196,7 +280,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn all(self, db: &DatabaseConnection) -> Result<Vec<S::Item>, DbErr> {
|
pub async fn all(self, db: &DatabaseConnection) -> Result<Vec<S::Item>, DbErr> {
|
||||||
let builder = db.get_query_builder_backend();
|
let builder = db.get_database_backend();
|
||||||
let rows = db.query_all(builder.build(&self.query)).await?;
|
let rows = db.query_all(builder.build(&self.query)).await?;
|
||||||
let mut models = Vec::new();
|
let mut models = Vec::new();
|
||||||
for row in rows.into_iter() {
|
for row in rows.into_iter() {
|
||||||
@ -216,6 +300,28 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<S> SelectorRaw<S>
|
||||||
|
where
|
||||||
|
S: SelectorTrait,
|
||||||
|
{
|
||||||
|
pub async fn one(self, db: &DatabaseConnection) -> Result<Option<S::Item>, DbErr> {
|
||||||
|
let row = db.query_one(self.stmt).await?;
|
||||||
|
match row {
|
||||||
|
Some(row) => Ok(Some(S::from_raw_query_result(row)?)),
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn all(self, db: &DatabaseConnection) -> Result<Vec<S::Item>, DbErr> {
|
||||||
|
let rows = db.query_all(self.stmt).await?;
|
||||||
|
let mut models = Vec::new();
|
||||||
|
for row in rows.into_iter() {
|
||||||
|
models.push(S::from_raw_query_result(row)?);
|
||||||
|
}
|
||||||
|
Ok(models)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn consolidate_query_result<L, R>(
|
fn consolidate_query_result<L, R>(
|
||||||
rows: Vec<(L::Model, Option<R::Model>)>,
|
rows: Vec<(L::Model, Option<R::Model>)>,
|
||||||
) -> Vec<(L::Model, Vec<R::Model>)>
|
) -> Vec<(L::Model, Vec<R::Model>)>
|
||||||
|
@ -46,7 +46,7 @@ impl Updater {
|
|||||||
self,
|
self,
|
||||||
db: &DatabaseConnection,
|
db: &DatabaseConnection,
|
||||||
) -> impl Future<Output = Result<UpdateResult, DbErr>> + '_ {
|
) -> impl Future<Output = Result<UpdateResult, DbErr>> + '_ {
|
||||||
let builder = db.get_query_builder_backend();
|
let builder = db.get_database_backend();
|
||||||
exec_update(builder.build(&self.query), db)
|
exec_update(builder.build(&self.query), db)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
//! Inspired by ActiveRecord, Eloquent and TypeORM, SeaORM aims to provide you an intuitive and ergonomic
|
//! Inspired by ActiveRecord, Eloquent and TypeORM, SeaORM aims to provide you an intuitive and ergonomic
|
||||||
//! API to make working with databases in Rust a first-class experience.
|
//! API to make working with databases in Rust a first-class experience.
|
||||||
//!
|
//!
|
||||||
//! ```ignore
|
//! ```markdown
|
||||||
//! This is a preview of SeaORM, and is not yet released.
|
//! This is a preview of SeaORM, and is not yet released.
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
@ -113,8 +113,7 @@ where
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::tests_cfg::{cake, fruit};
|
use crate::tests_cfg::{cake, fruit};
|
||||||
use crate::{ColumnTrait, EntityTrait, QueryFilter, QuerySelect, QueryTrait};
|
use crate::{ColumnTrait, DbBackend, EntityTrait, QueryFilter, QuerySelect, QueryTrait};
|
||||||
use sea_query::MysqlQueryBuilder;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn alias_1() {
|
fn alias_1() {
|
||||||
@ -122,7 +121,7 @@ mod tests {
|
|||||||
cake::Entity::find()
|
cake::Entity::find()
|
||||||
.column_as(cake::Column::Id, "B")
|
.column_as(cake::Column::Id, "B")
|
||||||
.apply_alias("A_")
|
.apply_alias("A_")
|
||||||
.build(MysqlQueryBuilder)
|
.build(DbBackend::MySql)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`, `cake`.`id` AS `A_B` FROM `cake`",
|
"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`, `cake`.`id` AS `A_B` FROM `cake`",
|
||||||
);
|
);
|
||||||
@ -134,7 +133,7 @@ mod tests {
|
|||||||
cake::Entity::find()
|
cake::Entity::find()
|
||||||
.left_join(fruit::Entity)
|
.left_join(fruit::Entity)
|
||||||
.select_also(fruit::Entity)
|
.select_also(fruit::Entity)
|
||||||
.build(MysqlQueryBuilder)
|
.build(DbBackend::MySql)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
[
|
[
|
||||||
"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,",
|
"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,",
|
||||||
@ -150,7 +149,7 @@ mod tests {
|
|||||||
cake::Entity::find()
|
cake::Entity::find()
|
||||||
.left_join(fruit::Entity)
|
.left_join(fruit::Entity)
|
||||||
.select_with(fruit::Entity)
|
.select_with(fruit::Entity)
|
||||||
.build(MysqlQueryBuilder)
|
.build(DbBackend::MySql)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
[
|
[
|
||||||
"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,",
|
"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,",
|
||||||
@ -169,7 +168,7 @@ mod tests {
|
|||||||
.select_also(fruit::Entity)
|
.select_also(fruit::Entity)
|
||||||
.filter(cake::Column::Id.eq(1))
|
.filter(cake::Column::Id.eq(1))
|
||||||
.filter(fruit::Column::Id.eq(2))
|
.filter(fruit::Column::Id.eq(2))
|
||||||
.build(MysqlQueryBuilder)
|
.build(DbBackend::MySql)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
[
|
[
|
||||||
"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,",
|
"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,",
|
||||||
@ -188,7 +187,7 @@ mod tests {
|
|||||||
.select_with(fruit::Entity)
|
.select_with(fruit::Entity)
|
||||||
.filter(cake::Column::Id.eq(1))
|
.filter(cake::Column::Id.eq(1))
|
||||||
.filter(fruit::Column::Id.eq(2))
|
.filter(fruit::Column::Id.eq(2))
|
||||||
.build(MysqlQueryBuilder)
|
.build(DbBackend::MySql)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
[
|
[
|
||||||
"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,",
|
"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,",
|
||||||
|
@ -31,28 +31,28 @@ impl Delete {
|
|||||||
///
|
///
|
||||||
/// Model
|
/// Model
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::PostgresQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// Delete::one(cake::Model {
|
/// Delete::one(cake::Model {
|
||||||
/// id: 1,
|
/// id: 1,
|
||||||
/// name: "Apple Pie".to_owned(),
|
/// name: "Apple Pie".to_owned(),
|
||||||
/// })
|
/// })
|
||||||
/// .build(PostgresQueryBuilder)
|
/// .build(DbBackend::Postgres)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#,
|
/// r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#,
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
/// ActiveModel
|
/// ActiveModel
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::PostgresQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// Delete::one(cake::ActiveModel {
|
/// Delete::one(cake::ActiveModel {
|
||||||
/// id: ActiveValue::set(1),
|
/// id: ActiveValue::set(1),
|
||||||
/// name: ActiveValue::set("Apple Pie".to_owned()),
|
/// name: ActiveValue::set("Apple Pie".to_owned()),
|
||||||
/// })
|
/// })
|
||||||
/// .build(PostgresQueryBuilder)
|
/// .build(DbBackend::Postgres)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#,
|
/// r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#,
|
||||||
/// );
|
/// );
|
||||||
@ -75,12 +75,12 @@ impl Delete {
|
|||||||
/// Delete many ActiveModel
|
/// Delete many ActiveModel
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::fruit, sea_query::{Expr, PostgresQueryBuilder}};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::fruit, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// Delete::many(fruit::Entity)
|
/// Delete::many(fruit::Entity)
|
||||||
/// .filter(fruit::Column::Name.contains("Apple"))
|
/// .filter(fruit::Column::Name.contains("Apple"))
|
||||||
/// .build(PostgresQueryBuilder)
|
/// .build(DbBackend::Postgres)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// r#"DELETE FROM "fruit" WHERE "fruit"."name" LIKE '%Apple%'"#,
|
/// r#"DELETE FROM "fruit" WHERE "fruit"."name" LIKE '%Apple%'"#,
|
||||||
/// );
|
/// );
|
||||||
@ -179,8 +179,7 @@ where
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::tests_cfg::{cake, fruit};
|
use crate::tests_cfg::{cake, fruit};
|
||||||
use crate::{entity::*, query::*};
|
use crate::{entity::*, query::*, DbBackend};
|
||||||
use sea_query::PostgresQueryBuilder;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn delete_1() {
|
fn delete_1() {
|
||||||
@ -189,7 +188,7 @@ mod tests {
|
|||||||
id: 1,
|
id: 1,
|
||||||
name: "Apple Pie".to_owned(),
|
name: "Apple Pie".to_owned(),
|
||||||
})
|
})
|
||||||
.build(PostgresQueryBuilder)
|
.build(DbBackend::Postgres)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#,
|
r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#,
|
||||||
);
|
);
|
||||||
@ -198,7 +197,7 @@ mod tests {
|
|||||||
id: ActiveValue::set(1),
|
id: ActiveValue::set(1),
|
||||||
name: ActiveValue::set("Apple Pie".to_owned()),
|
name: ActiveValue::set("Apple Pie".to_owned()),
|
||||||
})
|
})
|
||||||
.build(PostgresQueryBuilder)
|
.build(DbBackend::Postgres)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#,
|
r#"DELETE FROM "cake" WHERE "cake"."id" = 1"#,
|
||||||
);
|
);
|
||||||
@ -209,7 +208,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Delete::many(fruit::Entity)
|
Delete::many(fruit::Entity)
|
||||||
.filter(fruit::Column::Name.contains("Cheese"))
|
.filter(fruit::Column::Name.contains("Cheese"))
|
||||||
.build(PostgresQueryBuilder)
|
.build(DbBackend::Postgres)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
r#"DELETE FROM "fruit" WHERE "fruit"."name" LIKE '%Cheese%'"#,
|
r#"DELETE FROM "fruit" WHERE "fruit"."name" LIKE '%Cheese%'"#,
|
||||||
);
|
);
|
||||||
|
@ -23,13 +23,13 @@ pub trait QuerySelect: Sized {
|
|||||||
|
|
||||||
/// Add a select column
|
/// Add a select column
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::PostgresQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// cake::Entity::find()
|
/// cake::Entity::find()
|
||||||
/// .select_only()
|
/// .select_only()
|
||||||
/// .column(cake::Column::Name)
|
/// .column(cake::Column::Name)
|
||||||
/// .build(PostgresQueryBuilder)
|
/// .build(DbBackend::Postgres)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// r#"SELECT "cake"."name" FROM "cake""#
|
/// r#"SELECT "cake"."name" FROM "cake""#
|
||||||
/// );
|
/// );
|
||||||
@ -44,13 +44,13 @@ pub trait QuerySelect: Sized {
|
|||||||
|
|
||||||
/// Add a select column with alias
|
/// Add a select column with alias
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::PostgresQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// cake::Entity::find()
|
/// cake::Entity::find()
|
||||||
/// .select_only()
|
/// .select_only()
|
||||||
/// .column_as(cake::Column::Id.count(), "count")
|
/// .column_as(cake::Column::Id.count(), "count")
|
||||||
/// .build(PostgresQueryBuilder)
|
/// .build(DbBackend::Postgres)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// r#"SELECT COUNT("cake"."id") AS "count" FROM "cake""#
|
/// r#"SELECT COUNT("cake"."id") AS "count" FROM "cake""#
|
||||||
/// );
|
/// );
|
||||||
@ -68,14 +68,14 @@ pub trait QuerySelect: Sized {
|
|||||||
|
|
||||||
/// Add a group by column
|
/// Add a group by column
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::PostgresQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// cake::Entity::find()
|
/// cake::Entity::find()
|
||||||
/// .select_only()
|
/// .select_only()
|
||||||
/// .column(cake::Column::Name)
|
/// .column(cake::Column::Name)
|
||||||
/// .group_by(cake::Column::Name)
|
/// .group_by(cake::Column::Name)
|
||||||
/// .build(PostgresQueryBuilder)
|
/// .build(DbBackend::Postgres)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// r#"SELECT "cake"."name" FROM "cake" GROUP BY "cake"."name""#
|
/// r#"SELECT "cake"."name" FROM "cake" GROUP BY "cake"."name""#
|
||||||
/// );
|
/// );
|
||||||
@ -90,13 +90,13 @@ pub trait QuerySelect: Sized {
|
|||||||
|
|
||||||
/// Add an AND HAVING expression
|
/// Add an AND HAVING expression
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::MysqlQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// cake::Entity::find()
|
/// cake::Entity::find()
|
||||||
/// .having(cake::Column::Id.eq(4))
|
/// .having(cake::Column::Id.eq(4))
|
||||||
/// .having(cake::Column::Id.eq(5))
|
/// .having(cake::Column::Id.eq(5))
|
||||||
/// .build(MysqlQueryBuilder)
|
/// .build(DbBackend::MySql)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` HAVING `cake`.`id` = 4 AND `cake`.`id` = 5"
|
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` HAVING `cake`.`id` = 4 AND `cake`.`id` = 5"
|
||||||
/// );
|
/// );
|
||||||
@ -151,13 +151,13 @@ pub trait QueryOrder: Sized {
|
|||||||
|
|
||||||
/// Add an order_by expression
|
/// Add an order_by expression
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::MysqlQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// cake::Entity::find()
|
/// cake::Entity::find()
|
||||||
/// .order_by(cake::Column::Id, Order::Asc)
|
/// .order_by(cake::Column::Id, Order::Asc)
|
||||||
/// .order_by(cake::Column::Name, Order::Desc)
|
/// .order_by(cake::Column::Name, Order::Desc)
|
||||||
/// .build(MysqlQueryBuilder)
|
/// .build(DbBackend::MySql)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` ORDER BY `cake`.`id` ASC, `cake`.`name` DESC"
|
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` ORDER BY `cake`.`id` ASC, `cake`.`name` DESC"
|
||||||
/// );
|
/// );
|
||||||
@ -172,12 +172,12 @@ pub trait QueryOrder: Sized {
|
|||||||
|
|
||||||
/// Add an order_by expression (ascending)
|
/// Add an order_by expression (ascending)
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::MysqlQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// cake::Entity::find()
|
/// cake::Entity::find()
|
||||||
/// .order_by_asc(cake::Column::Id)
|
/// .order_by_asc(cake::Column::Id)
|
||||||
/// .build(MysqlQueryBuilder)
|
/// .build(DbBackend::MySql)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` ORDER BY `cake`.`id` ASC"
|
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` ORDER BY `cake`.`id` ASC"
|
||||||
/// );
|
/// );
|
||||||
@ -193,12 +193,12 @@ pub trait QueryOrder: Sized {
|
|||||||
|
|
||||||
/// Add an order_by expression (descending)
|
/// Add an order_by expression (descending)
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::MysqlQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// cake::Entity::find()
|
/// cake::Entity::find()
|
||||||
/// .order_by_desc(cake::Column::Id)
|
/// .order_by_desc(cake::Column::Id)
|
||||||
/// .build(MysqlQueryBuilder)
|
/// .build(DbBackend::MySql)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` ORDER BY `cake`.`id` DESC"
|
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` ORDER BY `cake`.`id` DESC"
|
||||||
/// );
|
/// );
|
||||||
@ -221,13 +221,13 @@ pub trait QueryFilter: Sized {
|
|||||||
|
|
||||||
/// Add an AND WHERE expression
|
/// Add an AND WHERE expression
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::MysqlQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// cake::Entity::find()
|
/// cake::Entity::find()
|
||||||
/// .filter(cake::Column::Id.eq(4))
|
/// .filter(cake::Column::Id.eq(4))
|
||||||
/// .filter(cake::Column::Id.eq(5))
|
/// .filter(cake::Column::Id.eq(5))
|
||||||
/// .build(MysqlQueryBuilder)
|
/// .build(DbBackend::MySql)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` = 4 AND `cake`.`id` = 5"
|
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` = 4 AND `cake`.`id` = 5"
|
||||||
/// );
|
/// );
|
||||||
@ -235,7 +235,7 @@ pub trait QueryFilter: Sized {
|
|||||||
///
|
///
|
||||||
/// Add a condition tree.
|
/// Add a condition tree.
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::MysqlQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// cake::Entity::find()
|
/// cake::Entity::find()
|
||||||
@ -244,7 +244,7 @@ pub trait QueryFilter: Sized {
|
|||||||
/// .add(cake::Column::Id.eq(4))
|
/// .add(cake::Column::Id.eq(4))
|
||||||
/// .add(cake::Column::Id.eq(5))
|
/// .add(cake::Column::Id.eq(5))
|
||||||
/// )
|
/// )
|
||||||
/// .build(MysqlQueryBuilder)
|
/// .build(DbBackend::MySql)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` = 4 OR `cake`.`id` = 5"
|
/// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` = 4 OR `cake`.`id` = 5"
|
||||||
/// );
|
/// );
|
||||||
|
@ -25,7 +25,7 @@ impl<A> Insert<A>
|
|||||||
where
|
where
|
||||||
A: ActiveModelTrait,
|
A: ActiveModelTrait,
|
||||||
{
|
{
|
||||||
pub fn new() -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
query: InsertStatement::new()
|
query: InsertStatement::new()
|
||||||
.into_table(A::Entity::default().into_iden())
|
.into_table(A::Entity::default().into_iden())
|
||||||
@ -39,28 +39,28 @@ where
|
|||||||
///
|
///
|
||||||
/// Model
|
/// Model
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::PostgresQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// Insert::one(cake::Model {
|
/// Insert::one(cake::Model {
|
||||||
/// id: 1,
|
/// id: 1,
|
||||||
/// name: "Apple Pie".to_owned(),
|
/// name: "Apple Pie".to_owned(),
|
||||||
/// })
|
/// })
|
||||||
/// .build(PostgresQueryBuilder)
|
/// .build(DbBackend::Postgres)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// r#"INSERT INTO "cake" ("id", "name") VALUES (1, 'Apple Pie')"#,
|
/// r#"INSERT INTO "cake" ("id", "name") VALUES (1, 'Apple Pie')"#,
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
/// ActiveModel
|
/// ActiveModel
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::PostgresQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// Insert::one(cake::ActiveModel {
|
/// Insert::one(cake::ActiveModel {
|
||||||
/// id: Unset(None),
|
/// id: Unset(None),
|
||||||
/// name: Set("Apple Pie".to_owned()),
|
/// name: Set("Apple Pie".to_owned()),
|
||||||
/// })
|
/// })
|
||||||
/// .build(PostgresQueryBuilder)
|
/// .build(DbBackend::Postgres)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// r#"INSERT INTO "cake" ("name") VALUES ('Apple Pie')"#,
|
/// r#"INSERT INTO "cake" ("name") VALUES ('Apple Pie')"#,
|
||||||
/// );
|
/// );
|
||||||
@ -75,7 +75,7 @@ where
|
|||||||
/// Insert many Model or ActiveModel
|
/// Insert many Model or ActiveModel
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::PostgresQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// Insert::many(vec![
|
/// Insert::many(vec![
|
||||||
@ -88,7 +88,7 @@ where
|
|||||||
/// name: "Orange Scone".to_owned(),
|
/// name: "Orange Scone".to_owned(),
|
||||||
/// }
|
/// }
|
||||||
/// ])
|
/// ])
|
||||||
/// .build(PostgresQueryBuilder)
|
/// .build(DbBackend::Postgres)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// r#"INSERT INTO "cake" ("id", "name") VALUES (1, 'Apple Pie'), (2, 'Orange Scone')"#,
|
/// r#"INSERT INTO "cake" ("id", "name") VALUES (1, 'Apple Pie'), (2, 'Orange Scone')"#,
|
||||||
/// );
|
/// );
|
||||||
@ -162,8 +162,7 @@ where
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::tests_cfg::cake;
|
use crate::tests_cfg::cake;
|
||||||
use crate::{ActiveValue, Insert, QueryTrait};
|
use crate::{ActiveValue, DbBackend, Insert, QueryTrait};
|
||||||
use sea_query::PostgresQueryBuilder;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_1() {
|
fn insert_1() {
|
||||||
@ -173,7 +172,7 @@ mod tests {
|
|||||||
id: ActiveValue::unset(),
|
id: ActiveValue::unset(),
|
||||||
name: ActiveValue::set("Apple Pie".to_owned()),
|
name: ActiveValue::set("Apple Pie".to_owned()),
|
||||||
})
|
})
|
||||||
.build(PostgresQueryBuilder)
|
.build(DbBackend::Postgres)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
r#"INSERT INTO "cake" ("name") VALUES ('Apple Pie')"#,
|
r#"INSERT INTO "cake" ("name") VALUES ('Apple Pie')"#,
|
||||||
);
|
);
|
||||||
@ -187,7 +186,7 @@ mod tests {
|
|||||||
id: ActiveValue::set(1),
|
id: ActiveValue::set(1),
|
||||||
name: ActiveValue::set("Apple Pie".to_owned()),
|
name: ActiveValue::set("Apple Pie".to_owned()),
|
||||||
})
|
})
|
||||||
.build(PostgresQueryBuilder)
|
.build(DbBackend::Postgres)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
r#"INSERT INTO "cake" ("id", "name") VALUES (1, 'Apple Pie')"#,
|
r#"INSERT INTO "cake" ("id", "name") VALUES (1, 'Apple Pie')"#,
|
||||||
);
|
);
|
||||||
@ -201,7 +200,7 @@ mod tests {
|
|||||||
id: 1,
|
id: 1,
|
||||||
name: "Apple Pie".to_owned(),
|
name: "Apple Pie".to_owned(),
|
||||||
})
|
})
|
||||||
.build(PostgresQueryBuilder)
|
.build(DbBackend::Postgres)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
r#"INSERT INTO "cake" ("id", "name") VALUES (1, 'Apple Pie')"#,
|
r#"INSERT INTO "cake" ("id", "name") VALUES (1, 'Apple Pie')"#,
|
||||||
);
|
);
|
||||||
@ -221,7 +220,7 @@ mod tests {
|
|||||||
name: "Orange Scone".to_owned(),
|
name: "Orange Scone".to_owned(),
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
.build(PostgresQueryBuilder)
|
.build(DbBackend::Postgres)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
r#"INSERT INTO "cake" ("id", "name") VALUES (1, 'Apple Pie'), (2, 'Orange Scone')"#,
|
r#"INSERT INTO "cake" ("id", "name") VALUES (1, 'Apple Pie'), (2, 'Orange Scone')"#,
|
||||||
);
|
);
|
||||||
@ -241,7 +240,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Insert::<cake::ActiveModel>::new()
|
Insert::<cake::ActiveModel>::new()
|
||||||
.add_many(vec![apple, orange])
|
.add_many(vec![apple, orange])
|
||||||
.build(PostgresQueryBuilder)
|
.build(DbBackend::Postgres)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
r#"INSERT INTO "cake" ("id", "name") VALUES (NULL, 'Apple'), (2, 'Orange')"#,
|
r#"INSERT INTO "cake" ("id", "name") VALUES (NULL, 'Apple'), (2, 'Orange')"#,
|
||||||
);
|
);
|
||||||
|
@ -62,15 +62,14 @@ where
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::tests_cfg::{cake, filling, fruit};
|
use crate::tests_cfg::{cake, filling, fruit};
|
||||||
use crate::{ColumnTrait, EntityTrait, ModelTrait, QueryFilter, QueryTrait};
|
use crate::{ColumnTrait, DbBackend, EntityTrait, ModelTrait, QueryFilter, QueryTrait};
|
||||||
use sea_query::MysqlQueryBuilder;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn join_1() {
|
fn join_1() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cake::Entity::find()
|
cake::Entity::find()
|
||||||
.left_join(fruit::Entity)
|
.left_join(fruit::Entity)
|
||||||
.build(MysqlQueryBuilder)
|
.build(DbBackend::MySql)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
[
|
[
|
||||||
"SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
|
"SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
|
||||||
@ -86,7 +85,7 @@ mod tests {
|
|||||||
cake::Entity::find()
|
cake::Entity::find()
|
||||||
.inner_join(fruit::Entity)
|
.inner_join(fruit::Entity)
|
||||||
.filter(fruit::Column::Name.contains("cherry"))
|
.filter(fruit::Column::Name.contains("cherry"))
|
||||||
.build(MysqlQueryBuilder)
|
.build(DbBackend::MySql)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
[
|
[
|
||||||
"SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
|
"SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
|
||||||
@ -102,7 +101,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
fruit::Entity::find()
|
fruit::Entity::find()
|
||||||
.reverse_join(cake::Entity)
|
.reverse_join(cake::Entity)
|
||||||
.build(MysqlQueryBuilder)
|
.build(DbBackend::MySql)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
[
|
[
|
||||||
"SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`",
|
"SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`",
|
||||||
@ -120,7 +119,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
find_fruit
|
find_fruit
|
||||||
.filter(cake::Column::Id.eq(11))
|
.filter(cake::Column::Id.eq(11))
|
||||||
.build(MysqlQueryBuilder)
|
.build(DbBackend::MySql)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
[
|
[
|
||||||
"SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`",
|
"SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`",
|
||||||
@ -141,7 +140,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
cake_model
|
cake_model
|
||||||
.find_related(fruit::Entity)
|
.find_related(fruit::Entity)
|
||||||
.build(MysqlQueryBuilder)
|
.build(DbBackend::MySql)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
[
|
[
|
||||||
"SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`",
|
"SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`",
|
||||||
@ -157,7 +156,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
cake::Entity::find()
|
cake::Entity::find()
|
||||||
.left_join(filling::Entity)
|
.left_join(filling::Entity)
|
||||||
.build(MysqlQueryBuilder)
|
.build(DbBackend::MySql)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
[
|
[
|
||||||
"SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
|
"SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
|
||||||
@ -174,7 +173,7 @@ mod tests {
|
|||||||
|
|
||||||
let find_filling: Select<filling::Entity> = cake::Entity::find_related();
|
let find_filling: Select<filling::Entity> = cake::Entity::find_related();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
find_filling.build(MysqlQueryBuilder).to_string(),
|
find_filling.build(DbBackend::MySql).to_string(),
|
||||||
[
|
[
|
||||||
"SELECT `filling`.`id`, `filling`.`name` FROM `filling`",
|
"SELECT `filling`.`id`, `filling`.`name` FROM `filling`",
|
||||||
"INNER JOIN `cake_filling` ON `cake_filling`.`filling_id` = `filling`.`id`",
|
"INNER JOIN `cake_filling` ON `cake_filling`.`filling_id` = `filling`.`id`",
|
||||||
|
@ -102,12 +102,12 @@ impl FromQueryResult for JsonValue {
|
|||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::tests_cfg::cake;
|
use crate::tests_cfg::cake;
|
||||||
use crate::{entity::*, MockDatabase, Syntax};
|
use crate::{entity::*, DbBackend, MockDatabase};
|
||||||
use sea_query::Value;
|
use sea_query::Value;
|
||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
async fn to_json_1() {
|
async fn to_json_1() {
|
||||||
let db = MockDatabase::new(Syntax::Postgres)
|
let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
.append_query_results(vec![vec![maplit::btreemap! {
|
.append_query_results(vec![vec![maplit::btreemap! {
|
||||||
"id" => Into::<Value>::into(128), "name" => Into::<Value>::into("apple")
|
"id" => Into::<Value>::into(128), "name" => Into::<Value>::into("apple")
|
||||||
}]])
|
}]])
|
||||||
|
@ -20,4 +20,4 @@ pub use select::*;
|
|||||||
pub use traits::*;
|
pub use traits::*;
|
||||||
pub use update::*;
|
pub use update::*;
|
||||||
|
|
||||||
pub use crate::executor::{InsertResult, UpdateResult};
|
pub use crate::{Statement, InsertResult, UpdateResult};
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{Statement, Syntax};
|
use crate::{DbBackend, Statement};
|
||||||
use sea_query::{QueryBuilder, QueryStatementBuilder};
|
use sea_query::QueryStatementBuilder;
|
||||||
|
|
||||||
pub trait QueryTrait {
|
pub trait QueryTrait {
|
||||||
type QueryStatement: QueryStatementBuilder;
|
type QueryStatement: QueryStatementBuilder;
|
||||||
@ -14,14 +14,11 @@ pub trait QueryTrait {
|
|||||||
fn into_query(self) -> Self::QueryStatement;
|
fn into_query(self) -> Self::QueryStatement;
|
||||||
|
|
||||||
/// Build the query as [`Statement`]
|
/// Build the query as [`Statement`]
|
||||||
fn build<B>(&self, builder: B) -> Statement
|
fn build(&self, db_backend: DbBackend) -> Statement {
|
||||||
where
|
let query_builder = db_backend.get_query_builder();
|
||||||
B: QueryBuilderWithSyntax,
|
Statement::from_string_values_tuple(
|
||||||
{
|
db_backend,
|
||||||
Statement::from_string_values_tuple(builder.syntax(), self.as_query().build(builder))
|
self.as_query().build_any(query_builder.as_ref()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait QueryBuilderWithSyntax: QueryBuilder {
|
|
||||||
fn syntax(&self) -> Syntax;
|
|
||||||
}
|
|
||||||
|
@ -30,14 +30,14 @@ impl Update {
|
|||||||
/// Update one ActiveModel
|
/// Update one ActiveModel
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, sea_query::PostgresQueryBuilder};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// Update::one(cake::ActiveModel {
|
/// Update::one(cake::ActiveModel {
|
||||||
/// id: ActiveValue::set(1),
|
/// id: ActiveValue::set(1),
|
||||||
/// name: ActiveValue::set("Apple Pie".to_owned()),
|
/// name: ActiveValue::set("Apple Pie".to_owned()),
|
||||||
/// })
|
/// })
|
||||||
/// .build(PostgresQueryBuilder)
|
/// .build(DbBackend::Postgres)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// r#"UPDATE "cake" SET "name" = 'Apple Pie' WHERE "cake"."id" = 1"#,
|
/// r#"UPDATE "cake" SET "name" = 'Apple Pie' WHERE "cake"."id" = 1"#,
|
||||||
/// );
|
/// );
|
||||||
@ -59,13 +59,13 @@ impl Update {
|
|||||||
/// Update many ActiveModel
|
/// Update many ActiveModel
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use sea_orm::{entity::*, query::*, tests_cfg::fruit, sea_query::{Expr, PostgresQueryBuilder}};
|
/// use sea_orm::{entity::*, query::*, tests_cfg::fruit, sea_query::Expr, DbBackend};
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// Update::many(fruit::Entity)
|
/// Update::many(fruit::Entity)
|
||||||
/// .col_expr(fruit::Column::Name, Expr::value("Golden Apple"))
|
/// .col_expr(fruit::Column::Name, Expr::value("Golden Apple"))
|
||||||
/// .filter(fruit::Column::Name.contains("Apple"))
|
/// .filter(fruit::Column::Name.contains("Apple"))
|
||||||
/// .build(PostgresQueryBuilder)
|
/// .build(DbBackend::Postgres)
|
||||||
/// .to_string(),
|
/// .to_string(),
|
||||||
/// r#"UPDATE "fruit" SET "name" = 'Golden Apple' WHERE "fruit"."name" LIKE '%Apple%'"#,
|
/// r#"UPDATE "fruit" SET "name" = 'Golden Apple' WHERE "fruit"."name" LIKE '%Apple%'"#,
|
||||||
/// );
|
/// );
|
||||||
@ -184,8 +184,8 @@ where
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::tests_cfg::{cake, fruit};
|
use crate::tests_cfg::{cake, fruit};
|
||||||
use crate::{entity::*, query::*};
|
use crate::{entity::*, query::*, DbBackend};
|
||||||
use sea_query::{Expr, PostgresQueryBuilder, Value};
|
use sea_query::{Expr, Value};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn update_1() {
|
fn update_1() {
|
||||||
@ -194,7 +194,7 @@ mod tests {
|
|||||||
id: ActiveValue::set(1),
|
id: ActiveValue::set(1),
|
||||||
name: ActiveValue::set("Apple Pie".to_owned()),
|
name: ActiveValue::set("Apple Pie".to_owned()),
|
||||||
})
|
})
|
||||||
.build(PostgresQueryBuilder)
|
.build(DbBackend::Postgres)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
r#"UPDATE "cake" SET "name" = 'Apple Pie' WHERE "cake"."id" = 1"#,
|
r#"UPDATE "cake" SET "name" = 'Apple Pie' WHERE "cake"."id" = 1"#,
|
||||||
);
|
);
|
||||||
@ -208,7 +208,7 @@ mod tests {
|
|||||||
name: ActiveValue::set("Orange".to_owned()),
|
name: ActiveValue::set("Orange".to_owned()),
|
||||||
cake_id: ActiveValue::unset(),
|
cake_id: ActiveValue::unset(),
|
||||||
})
|
})
|
||||||
.build(PostgresQueryBuilder)
|
.build(DbBackend::Postgres)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
r#"UPDATE "fruit" SET "name" = 'Orange' WHERE "fruit"."id" = 1"#,
|
r#"UPDATE "fruit" SET "name" = 'Orange' WHERE "fruit"."id" = 1"#,
|
||||||
);
|
);
|
||||||
@ -222,7 +222,7 @@ mod tests {
|
|||||||
name: ActiveValue::unchanged("Apple".to_owned()),
|
name: ActiveValue::unchanged("Apple".to_owned()),
|
||||||
cake_id: ActiveValue::set(Some(3)),
|
cake_id: ActiveValue::set(Some(3)),
|
||||||
})
|
})
|
||||||
.build(PostgresQueryBuilder)
|
.build(DbBackend::Postgres)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
r#"UPDATE "fruit" SET "cake_id" = 3 WHERE "fruit"."id" = 2"#,
|
r#"UPDATE "fruit" SET "cake_id" = 3 WHERE "fruit"."id" = 2"#,
|
||||||
);
|
);
|
||||||
@ -234,7 +234,7 @@ mod tests {
|
|||||||
Update::many(fruit::Entity)
|
Update::many(fruit::Entity)
|
||||||
.col_expr(fruit::Column::CakeId, Expr::value(Value::Null))
|
.col_expr(fruit::Column::CakeId, Expr::value(Value::Null))
|
||||||
.filter(fruit::Column::Id.eq(2))
|
.filter(fruit::Column::Id.eq(2))
|
||||||
.build(PostgresQueryBuilder)
|
.build(DbBackend::Postgres)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
r#"UPDATE "fruit" SET "cake_id" = NULL WHERE "fruit"."id" = 2"#,
|
r#"UPDATE "fruit" SET "cake_id" = NULL WHERE "fruit"."id" = 2"#,
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use sea_orm::{entity::*, error::*, sea_query, tests_cfg::*, DbConn, Statement, Syntax};
|
use sea_orm::{entity::*, error::*, sea_query, tests_cfg::*, DbBackend, DbConn, Statement};
|
||||||
|
|
||||||
mod setup;
|
mod setup;
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ async fn setup_schema(db: &DbConn) {
|
|||||||
.build(SqliteQueryBuilder);
|
.build(SqliteQueryBuilder);
|
||||||
|
|
||||||
let result = db
|
let result = db
|
||||||
.execute(Statement::from_string(Syntax::Sqlite, stmt))
|
.execute(Statement::from_string(DbBackend::Sqlite, stmt))
|
||||||
.await;
|
.await;
|
||||||
println!("Create table cake: {:?}", result);
|
println!("Create table cake: {:?}", result);
|
||||||
}
|
}
|
||||||
@ -59,6 +59,12 @@ async fn crud_cake(db: &DbConn) -> Result<(), DbErr> {
|
|||||||
println!();
|
println!();
|
||||||
println!("Updated: {:?}", apple);
|
println!("Updated: {:?}", apple);
|
||||||
|
|
||||||
|
let count = cake::Entity::find().count(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("Count: {:?}", count);
|
||||||
|
assert_eq!(count, 1);
|
||||||
|
|
||||||
let apple = cake::Entity::find_by_id(1).one(db).await?;
|
let apple = cake::Entity::find_by_id(1).one(db).await?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -80,5 +86,11 @@ async fn crud_cake(db: &DbConn) -> Result<(), DbErr> {
|
|||||||
|
|
||||||
assert_eq!(None, apple);
|
assert_eq!(None, apple);
|
||||||
|
|
||||||
|
let count = cake::Entity::find().count(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("Count: {:?}", count);
|
||||||
|
assert_eq!(count, 0);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use sea_query::{ColumnDef, ForeignKey, ForeignKeyAction, Index, TableCreateState
|
|||||||
pub use super::super::bakery_chain::*;
|
pub use super::super::bakery_chain::*;
|
||||||
|
|
||||||
async fn create_table(db: &DbConn, stmt: &TableCreateStatement) -> Result<ExecResult, DbErr> {
|
async fn create_table(db: &DbConn, stmt: &TableCreateStatement) -> Result<ExecResult, DbErr> {
|
||||||
let builder = db.get_schema_builder_backend();
|
let builder = db.get_database_backend();
|
||||||
db.execute(builder.build(stmt)).await
|
db.execute(builder.build(stmt)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user