Merge remote-tracking branch 'origin/master' into returning

This commit is contained in:
Billy Chan 2021-11-16 14:44:12 +08:00
commit fd50ffd5ea
No known key found for this signature in database
GPG Key ID: A2D690CAC7DF3CC7
29 changed files with 247 additions and 141 deletions

View File

@ -316,7 +316,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest]
path: [86, 249, 262]
path: [86, 249, 262, 319]
steps:
- uses: actions/checkout@v2

View File

@ -63,7 +63,7 @@ default = [
]
macros = ["sea-orm-macros"]
mock = []
with-json = ["serde_json", "sea-query/with-json"]
with-json = ["serde_json", "sea-query/with-json", "chrono/serde"]
with-chrono = ["chrono", "sea-query/with-chrono"]
with-rust_decimal = ["rust_decimal", "sea-query/with-rust_decimal"]
with-uuid = ["uuid", "sea-query/with-uuid"]

View File

@ -1,5 +1,5 @@
use super::*;
use sea_orm::{entity::*, error::*, query::*, DbConn};
use sea_orm::{entity::*, error::*, DbConn};
pub async fn all_about_operation(db: &DbConn) -> Result<(), DbErr> {
insert_and_update(db).await?;

18
issues/319/Cargo.toml Normal file
View File

@ -0,0 +1,18 @@
[workspace]
# A separate workspace
[package]
name = "sea-orm-issues-319"
version = "0.1.0"
edition = "2021"
publish = false
[dependencies]
async-std = { version = "^1", features = ["attributes"] }
serde = { version = "^1", features = ["derive"] }
sea-orm = { path = "../../", features = [
"sqlx-mysql",
"runtime-async-std-native-tls",
"with-json",
"macros",
], default-features = false }

14
issues/319/src/main.rs Normal file
View File

@ -0,0 +1,14 @@
mod material;
use sea_orm::*;
#[async_std::main]
pub async fn main() {
let db = Database::connect("mysql://sea:sea@localhost/bakery")
.await
.unwrap();
async_std::task::spawn(async move {
material::Entity::find().one(&db).await.unwrap();
})
.await;
}

View File

@ -0,0 +1,20 @@
use sea_orm::entity::prelude::*;
use serde::{Serialize, Deserialize};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "materials")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub created_at: DateTimeWithTimeZone,
pub updated_at: DateTimeWithTimeZone,
pub name: String,
#[sea_orm(column_type = "Text", nullable)]
pub description: Option<String>,
pub tag_ids: Vec<u8>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}

View File

@ -4,7 +4,7 @@ use crate::{
use futures::Stream;
use std::{future::Future, pin::Pin};
/// Creates constraints for any structure that wants to create a database connection
/// Creates constraints for any structure that can create a database connection
/// and execute SQL statements
#[async_trait::async_trait]
pub trait ConnectionTrait<'a>: Sync {

View File

@ -8,9 +8,10 @@ use std::fmt;
pub struct Statement {
/// The SQL query
pub sql: String,
/// The values for the SQL statement
/// The values for the SQL statement's parameters
pub values: Option<Values>,
/// The database backend to use
/// The database backend this statement is constructed for.
/// The SQL dialect and values should be valid for the DbBackend.
pub db_backend: DbBackend,
}
@ -31,7 +32,7 @@ impl Statement {
}
/// Create a SQL statement from a [crate::DatabaseBackend], a
/// raw SQL statement and defined values
/// raw SQL statement and param values
pub fn from_sql_and_values<I>(db_backend: DbBackend, sql: &str, values: I) -> Self
where
I: IntoIterator<Item = Value>,

View File

@ -1,3 +1,5 @@
#![allow(missing_docs)]
use std::{pin::Pin, task::Poll};
#[cfg(feature = "mock")]

View File

@ -1,3 +1,5 @@
#![allow(missing_docs)]
use std::{ops::DerefMut, pin::Pin, task::Poll};
use futures::Stream;
@ -11,9 +13,9 @@ use futures::lock::MutexGuard;
use crate::{DbErr, InnerConnection, QueryResult, Statement};
#[ouroboros::self_referencing]
/// `TransactionStream` cannot be used in a `transaction` closure as it does not impl `Send`.
/// It seems to be a Rust limitation right now, and solution to work around this deemed to be extremely hard.
#[ouroboros::self_referencing]
pub struct TransactionStream<'a> {
stmt: Statement,
conn: MutexGuard<'a, InnerConnection>,

View File

@ -23,7 +23,7 @@ pub struct MockDatabaseConnection {
mocker: Mutex<Box<dyn MockDatabaseTrait>>,
}
/// A set of constraints for any type wanting to perform operations on the [MockDatabase]
/// A Trait for any type wanting to perform operations on the [MockDatabase]
pub trait MockDatabaseTrait: Send + Debug {
/// Execute a statement in the [MockDatabase]
fn execute(&mut self, counter: usize, stmt: Statement) -> Result<ExecResult, DbErr>;

View File

@ -9,3 +9,8 @@ pub fn sqlx_error_to_exec_err(err: sqlx::Error) -> DbErr {
pub fn sqlx_error_to_query_err(err: sqlx::Error) -> DbErr {
DbErr::Query(err.to_string())
}
/// Converts an [sqlx::error] connection error to a [DbErr]
pub fn sqlx_error_to_conn_err(err: sqlx::Error) -> DbErr {
DbErr::Conn(err.to_string())
}

View File

@ -41,12 +41,11 @@ impl SqlxMySqlConnector {
use sqlx::ConnectOptions;
opt.disable_statement_logging();
}
if let Ok(pool) = options.pool_options().connect_with(opt).await {
Ok(DatabaseConnection::SqlxMySqlPoolConnection(
match options.pool_options().connect_with(opt).await {
Ok(pool) => Ok(DatabaseConnection::SqlxMySqlPoolConnection(
SqlxMySqlPoolConnection { pool },
))
} else {
Err(DbErr::Conn("Failed to connect.".to_owned()))
)),
Err(e) => Err(sqlx_error_to_conn_err(e)),
}
}
}

View File

@ -41,12 +41,11 @@ impl SqlxPostgresConnector {
use sqlx::ConnectOptions;
opt.disable_statement_logging();
}
if let Ok(pool) = options.pool_options().connect_with(opt).await {
Ok(DatabaseConnection::SqlxPostgresPoolConnection(
match options.pool_options().connect_with(opt).await {
Ok(pool) => Ok(DatabaseConnection::SqlxPostgresPoolConnection(
SqlxPostgresPoolConnection { pool },
))
} else {
Err(DbErr::Conn("Failed to connect.".to_owned()))
)),
Err(e) => Err(sqlx_error_to_conn_err(e)),
}
}
}

View File

@ -45,12 +45,11 @@ impl SqlxSqliteConnector {
if options.get_max_connections().is_none() {
options.max_connections(1);
}
if let Ok(pool) = options.pool_options().connect_with(opt).await {
Ok(DatabaseConnection::SqlxSqlitePoolConnection(
match options.pool_options().connect_with(opt).await {
Ok(pool) => Ok(DatabaseConnection::SqlxSqlitePoolConnection(
SqlxSqlitePoolConnection { pool },
))
} else {
Err(DbErr::Conn("Failed to connect.".to_owned()))
)),
Err(e) => Err(sqlx_error_to_conn_err(e)),
}
}
}

View File

@ -76,12 +76,12 @@ where
ActiveValue::unchanged(value)
}
/// Enforces a set of constraints on any type performing an Create, Update or Delete operation.
/// A Trait for ActiveModel to perform Create, Update or Delete operation.
/// The type must also implement the [EntityTrait].
/// See module level docs [crate::entity] for a full example
#[async_trait]
pub trait ActiveModelTrait: Clone + Debug {
/// Enforce the type to the constraints of the [EntityTrait]
/// The Entity this ActiveModel belongs to
type Entity: EntityTrait;
/// Get a mutable [ActiveValue] from an ActiveModel
@ -204,9 +204,7 @@ pub trait ActiveModelTrait: Clone + Debug {
}
}
/// Enforce a set of constraints to a override the ActiveModel behavior
/// Behaviors for users to override.
/// The type must also implement the [ActiveModelTrait]
/// A Trait for overriding the ActiveModel behavior
///
/// ### Example
/// ```ignore
@ -261,7 +259,7 @@ pub trait ActiveModelBehavior: ActiveModelTrait {
}
}
/// Enforce constraints for conversion to an ActiveModel
/// A Trait for any type that can be converted into an ActiveModel
pub trait IntoActiveModel<A>
where
A: ActiveModelTrait,

View File

@ -13,7 +13,7 @@ pub trait IdenStatic: Iden + Copy + Debug + 'static {
fn as_str(&self) -> &str;
}
/// Enforces the naming of an entity to a set of constraints
/// A Trait for mapping an Entity to a database table
pub trait EntityName: IdenStatic + Default {
/// Method to get the name for the schema, defaults to [Option::None] if not set
fn schema_name(&self) -> Option<&str> {

View File

@ -6,7 +6,7 @@ use sea_query::{Alias, IntoIden, JoinType, SeaRc};
/// Same as [RelationDef]
pub type LinkDef = RelationDef;
/// A set of constraints for links between Entities
/// A Trait for links between Entities
pub trait Linked {
#[allow(missing_docs)]
type FromEntity: EntityTrait;

View File

@ -5,7 +5,7 @@ use crate::{
pub use sea_query::Value;
use std::fmt::Debug;
/// A set of constraints for a Model
/// A Trait for a Model
pub trait ModelTrait: Clone + Send + Debug {
#[allow(missing_docs)]
type Entity: EntityTrait;
@ -35,7 +35,7 @@ pub trait ModelTrait: Clone + Send + Debug {
}
}
/// A set of constraints for implementing a [QueryResult]
/// A Trait for implementing a [QueryResult]
pub trait FromQueryResult: Sized {
/// Instantiate a Model from a [QueryResult]
fn from_query_result(res: &QueryResult, pre: &str) -> Result<Self, DbErr>;

View File

@ -1,8 +1,8 @@
pub use crate::{
error::*, ActiveEnum, ActiveModelBehavior, ActiveModelTrait, ColumnDef, ColumnTrait,
ColumnType, DatabaseConnection, DbConn, EntityName, EntityTrait, EnumIter, ForeignKeyAction,
Iden, IdenStatic, Linked, ModelTrait, PrimaryKeyToColumn, PrimaryKeyTrait, QueryFilter,
QueryResult, Related, RelationDef, RelationTrait, Select, Value,
Iden, IdenStatic, Linked, ModelTrait, PaginatorTrait, PrimaryKeyToColumn, PrimaryKeyTrait,
QueryFilter, QueryResult, Related, RelationDef, RelationTrait, Select, Value,
};
#[cfg(feature = "macros")]

View File

@ -4,7 +4,7 @@ use sea_query::{FromValueTuple, IntoValueTuple};
use std::fmt::Debug;
//LINT: composite primary key cannot auto increment
/// A set of constraints to be used to define a Primary Key.
/// A Trait for to be used to define a Primary Key.
///
/// A primary key can be derived manually
///

View File

@ -1,4 +1,7 @@
use crate::{error::*, ConnectionTrait, DbBackend, SelectorTrait};
use crate::{
error::*, ConnectionTrait, DbBackend, EntityTrait, FromQueryResult, Select, SelectModel,
SelectTwo, SelectTwoModel, Selector, SelectorTrait,
};
use async_stream::stream;
use futures::Stream;
use sea_query::{Alias, Expr, SelectStatement};
@ -155,9 +158,77 @@ where
}
}
#[async_trait::async_trait]
/// A Trait for any type that can paginate results
pub trait PaginatorTrait<'db, C>
where
C: ConnectionTrait<'db>,
{
/// Select operation
type Selector: SelectorTrait + Send + Sync + 'db;
/// Paginate the result of a select operation.
fn paginate(self, db: &'db C, page_size: usize) -> Paginator<'db, C, Self::Selector>;
/// Perform a count on the paginated results
async fn count(self, db: &'db C) -> Result<usize, DbErr>
where
Self: Send + Sized,
{
self.paginate(db, 1).num_items().await
}
}
impl<'db, C, S> PaginatorTrait<'db, C> for Selector<S>
where
C: ConnectionTrait<'db>,
S: SelectorTrait + Send + Sync + 'db,
{
type Selector = S;
fn paginate(self, db: &'db C, page_size: usize) -> Paginator<'db, C, S> {
Paginator {
query: self.query,
page: 0,
page_size,
db,
selector: PhantomData,
}
}
}
impl<'db, C, M, E> PaginatorTrait<'db, C> for Select<E>
where
C: ConnectionTrait<'db>,
E: EntityTrait<Model = M>,
M: FromQueryResult + Sized + Send + Sync + 'db,
{
type Selector = SelectModel<M>;
fn paginate(self, db: &'db C, page_size: usize) -> Paginator<'db, C, Self::Selector> {
self.into_model().paginate(db, page_size)
}
}
impl<'db, C, M, N, E, F> PaginatorTrait<'db, C> for SelectTwo<E, F>
where
C: ConnectionTrait<'db>,
E: EntityTrait<Model = M>,
F: EntityTrait<Model = N>,
M: FromQueryResult + Sized + Send + Sync + 'db,
N: FromQueryResult + Sized + Send + Sync + 'db,
{
type Selector = SelectTwoModel<M, N>;
fn paginate(self, db: &'db C, page_size: usize) -> Paginator<'db, C, Self::Selector> {
self.into_model().paginate(db, page_size)
}
}
#[cfg(test)]
#[cfg(feature = "mock")]
mod tests {
use super::*;
use crate::entity::prelude::*;
use crate::{tests_cfg::*, ConnectionTrait};
use crate::{DatabaseConnection, DbBackend, MockDatabase, Transaction};

View File

@ -1,7 +1,7 @@
use crate::{
error::*, ConnectionTrait, EntityTrait, FromQueryResult, IdenStatic, Iterable, ModelTrait,
Paginator, PrimaryKeyToColumn, QueryResult, Select, SelectA, SelectB, SelectTwo, SelectTwoMany,
Statement, TryGetableMany,
PrimaryKeyToColumn, QueryResult, Select, SelectA, SelectB, SelectTwo, SelectTwoMany, Statement,
TryGetableMany,
};
use futures::{Stream, TryStreamExt};
use sea_query::SelectStatement;
@ -11,13 +11,13 @@ use std::pin::Pin;
#[cfg(feature = "with-json")]
use crate::JsonValue;
/// Defines a type to do `SELECT` operations though a [SelectStatement] on a Model
/// Defines a type to do `SELECT` operations through a [SelectStatement] on a Model
#[derive(Clone, Debug)]
pub struct Selector<S>
where
S: SelectorTrait,
{
query: SelectStatement,
pub(crate) query: SelectStatement,
selector: S,
}
@ -31,7 +31,7 @@ where
selector: S,
}
/// Used to enforce constraints on any type that wants to perform SELECT queries
/// A Trait for any type that can perform SELECT queries
pub trait SelectorTrait {
#[allow(missing_docs)]
type Item: Sized;
@ -250,7 +250,7 @@ where
Selector::<SelectGetableValue<T, C>>::with_columns(self.query)
}
/// Get one Model from a SELECT operation
/// Get one Model from the SELECT query
pub async fn one<'a, C>(self, db: &C) -> Result<Option<E::Model>, DbErr>
where
C: ConnectionTrait<'a>,
@ -258,7 +258,7 @@ where
self.into_model().one(db).await
}
/// Get all the Models from a SELECT operation
/// Get all Models from the SELECT query
pub async fn all<'a, C>(self, db: &C) -> Result<Vec<E::Model>, DbErr>
where
C: ConnectionTrait<'a>,
@ -276,26 +276,6 @@ where
{
self.into_model().stream(db).await
}
/// Paginate the results of a SELECT operation on a Model
pub fn paginate<'a, C>(
self,
db: &'a C,
page_size: usize,
) -> Paginator<'a, C, SelectModel<E::Model>>
where
C: ConnectionTrait<'a>,
{
self.into_model().paginate(db, page_size)
}
/// Perform a `COUNT` operation on a items on a Model using pagination
pub async fn count<'a, C>(self, db: &'a C) -> Result<usize, DbErr>
where
C: ConnectionTrait<'a>,
{
self.paginate(db, 1).num_items().await
}
}
impl<E, F> SelectTwo<E, F>
@ -324,7 +304,7 @@ where
}
}
/// Get one Model from a Select operation
/// Get one Model from the Select query
pub async fn one<'a, C>(self, db: &C) -> Result<Option<(E::Model, Option<F::Model>)>, DbErr>
where
C: ConnectionTrait<'a>,
@ -332,7 +312,7 @@ where
self.into_model().one(db).await
}
/// Get all Models from a Select operation
/// Get all Models from the Select query
pub async fn all<'a, C>(self, db: &C) -> Result<Vec<(E::Model, Option<F::Model>)>, DbErr>
where
C: ConnectionTrait<'a>,
@ -350,26 +330,6 @@ where
{
self.into_model().stream(db).await
}
/// Paginate the results of a select operation on two models
pub fn paginate<'a, C>(
self,
db: &'a C,
page_size: usize,
) -> Paginator<'a, C, SelectTwoModel<E::Model, F::Model>>
where
C: ConnectionTrait<'a>,
{
self.into_model().paginate(db, page_size)
}
/// Perform a count on the paginated results
pub async fn count<'a, C>(self, db: &'a C) -> Result<usize, DbErr>
where
C: ConnectionTrait<'a>,
{
self.paginate(db, 1).num_items().await
}
}
impl<E, F> SelectTwoMany<E, F>
@ -417,7 +377,7 @@ where
self.into_model().stream(db).await
}
/// Get all the Models from the select operation
/// Get all Models from the select operation
pub async fn all<'a, C>(self, db: &C) -> Result<Vec<(E::Model, Vec<F::Model>)>, DbErr>
where
C: ConnectionTrait<'a>,
@ -456,35 +416,36 @@ where
}
}
/// Get a Model from a Select operation
fn into_selector_raw<'a, C>(self, db: &C) -> SelectorRaw<S>
where
C: ConnectionTrait<'a>,
{
let builder = db.get_database_backend();
let stmt = builder.build(&self.query);
SelectorRaw {
stmt,
selector: self.selector,
}
}
/// Get an item from the Select query
pub async fn one<'a, C>(mut self, db: &C) -> Result<Option<S::Item>, DbErr>
where
C: ConnectionTrait<'a>,
{
let builder = db.get_database_backend();
self.query.limit(1);
let row = db.query_one(builder.build(&self.query)).await?;
match row {
Some(row) => Ok(Some(S::from_raw_query_result(row)?)),
None => Ok(None),
}
self.into_selector_raw(db).one(db).await
}
/// Get all results from a Select operation
/// Get all items from the Select query
pub async fn all<'a, C>(self, db: &C) -> Result<Vec<S::Item>, DbErr>
where
C: ConnectionTrait<'a>,
{
let builder = db.get_database_backend();
let rows = db.query_all(builder.build(&self.query)).await?;
let mut models = Vec::new();
for row in rows.into_iter() {
models.push(S::from_raw_query_result(row)?);
}
Ok(models)
self.into_selector_raw(db).all(db).await
}
/// Stream the results of the operation
/// Stream the results of the Select operation
pub async fn stream<'a: 'b, 'b, C>(
self,
db: &'a C,
@ -493,25 +454,7 @@ where
C: ConnectionTrait<'a>,
S: 'b,
{
let builder = db.get_database_backend();
let stream = db.stream(builder.build(&self.query)).await?;
Ok(Box::pin(stream.and_then(|row| {
futures::future::ready(S::from_raw_query_result(row))
})))
}
/// Paginate the result of a select operation on a Model
pub fn paginate<'a, C>(self, db: &'a C, page_size: usize) -> Paginator<'a, C, S>
where
C: ConnectionTrait<'a>,
{
Paginator {
query: self.query,
page: 0,
page_size,
db,
selector: PhantomData,
}
self.into_selector_raw(db).stream(db).await
}
}
@ -519,8 +462,7 @@ impl<S> SelectorRaw<S>
where
S: SelectorTrait,
{
/// Create `SelectorRaw` from Statment. Executing this `SelectorRaw` will
/// return a type `M` which implement `FromQueryResult`.
/// Select a custom Model from a raw SQL [Statement].
pub fn from_statement<M>(stmt: Statement) -> SelectorRaw<SelectModel<M>>
where
M: FromQueryResult,
@ -683,6 +625,7 @@ where
}
}
/// Get an item from the Select query
/// ```
/// # #[cfg(feature = "mock")]
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, Transaction, DbBackend};
@ -725,6 +668,7 @@ where
}
}
/// Get all items from the Select query
/// ```
/// # #[cfg(feature = "mock")]
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, Transaction, DbBackend};
@ -767,6 +711,21 @@ where
}
Ok(models)
}
/// Stream the results of the Select operation
pub async fn stream<'a: 'b, 'b, C>(
self,
db: &'a C,
) -> Result<Pin<Box<dyn Stream<Item = Result<S::Item, DbErr>> + 'b>>, DbErr>
where
C: ConnectionTrait<'a>,
S: 'b,
{
let stream = db.stream(self.stmt).await?;
Ok(Box::pin(stream.and_then(|row| {
futures::future::ready(S::from_raw_query_result(row))
})))
}
}
fn consolidate_query_result<L, R>(

View File

@ -22,4 +22,6 @@ pub use traits::*;
pub use update::*;
pub use util::*;
pub use crate::{ConnectionTrait, InsertResult, Statement, UpdateResult, Value, Values};
pub use crate::{
ConnectionTrait, InsertResult, PaginatorTrait, Statement, UpdateResult, Value, Values,
};

View File

@ -1,7 +1,7 @@
use crate::{DbBackend, Statement};
use sea_query::QueryStatementBuilder;
/// Enforces a set of constraints to any type performing queries on a Model or ActiveModel
/// A Trait for any type performing queries on a Model or ActiveModel
pub trait QueryTrait {
/// Constrain the QueryStatement to [QueryStatementBuilder] trait
type QueryStatement: QueryStatementBuilder;

View File

@ -9,27 +9,27 @@ use sea_query::{
impl Schema {
/// Creates Postgres enums from an Entity. See [TypeCreateStatement] for more details
pub fn create_enum_from_entity<E>(entity: E, db_backend: DbBackend) -> Vec<TypeCreateStatement>
pub fn create_enum_from_entity<E>(&self, entity: E) -> Vec<TypeCreateStatement>
where
E: EntityTrait,
{
create_enum_from_entity(entity, db_backend)
create_enum_from_entity(entity, self.backend)
}
/// Creates a table from an Entity. See [TableCreateStatement] for more details
pub fn create_table_from_entity<E>(entity: E, db_backend: DbBackend) -> TableCreateStatement
pub fn create_table_from_entity<E>(&self, entity: E) -> TableCreateStatement
where
E: EntityTrait,
{
create_table_from_entity(entity, db_backend)
create_table_from_entity(entity, self.backend)
}
}
pub(crate) fn create_enum_from_entity<E>(_: E, db_backend: DbBackend) -> Vec<TypeCreateStatement>
pub(crate) fn create_enum_from_entity<E>(_: E, backend: DbBackend) -> Vec<TypeCreateStatement>
where
E: EntityTrait,
{
if matches!(db_backend, DbBackend::MySql | DbBackend::Sqlite) {
if matches!(backend, DbBackend::MySql | DbBackend::Sqlite) {
return Vec::new();
}
let mut vec = Vec::new();
@ -52,7 +52,7 @@ where
vec
}
pub(crate) fn create_table_from_entity<E>(entity: E, db_backend: DbBackend) -> TableCreateStatement
pub(crate) fn create_table_from_entity<E>(entity: E, backend: DbBackend) -> TableCreateStatement
where
E: EntityTrait,
{
@ -61,7 +61,7 @@ where
for column in E::Column::iter() {
let orm_column_def = column.def();
let types = match orm_column_def.col_type {
ColumnType::Enum(s, variants) => match db_backend {
ColumnType::Enum(s, variants) => match backend {
DbBackend::MySql => {
ColumnType::Custom(format!("ENUM('{}')", variants.join("', '")))
}
@ -175,8 +175,10 @@ mod tests {
#[test]
fn test_create_table_from_entity() {
let schema = Schema::new(DbBackend::MySql);
assert_eq!(
Schema::create_table_from_entity(CakeFillingPrice, DbBackend::MySql)
schema
.create_table_from_entity(CakeFillingPrice)
.to_string(MysqlQueryBuilder),
Table::create()
.table(CakeFillingPrice)

View File

@ -1,5 +1,17 @@
use crate::DbBackend;
mod entity;
/// This structure defines a schema for a table
/// This is a helper struct to convert [`EntityTrait`](crate::EntityTrait)
/// into different [`sea_query`](crate::sea_query) statements.
#[derive(Debug)]
pub struct Schema;
pub struct Schema {
backend: DbBackend,
}
impl Schema {
/// Create a helper for a specific database backend
pub fn new(backend: DbBackend) -> Self {
Self { backend }
}
}

View File

@ -108,7 +108,9 @@ where
}
let expect_stmts: Vec<Statement> = creates.iter().map(|stmt| builder.build(stmt)).collect();
let create_from_entity_stmts: Vec<Statement> = Schema::create_enum_from_entity(entity, builder)
let schema = Schema::new(builder);
let create_from_entity_stmts: Vec<Statement> = schema
.create_enum_from_entity(entity)
.iter()
.map(|stmt| builder.build(stmt))
.collect();
@ -131,8 +133,9 @@ where
E: EntityTrait,
{
let builder = db.get_database_backend();
let schema = Schema::new(builder);
assert_eq!(
builder.build(&Schema::create_table_from_entity(entity, builder)),
builder.build(&schema.create_table_from_entity(entity)),
builder.build(create)
);

View File

@ -1,6 +1,6 @@
pub use super::*;
use rust_decimal_macros::dec;
use sea_orm::DbErr;
use sea_orm::{query::*, DbErr};
use uuid::Uuid;
pub async fn test_update_cake(db: &DbConn) {