Support Vector of enum for Postgres (#1210)
* Support Vector of enum for Postgres * Fix clippy * Add tests for integer array * Fix dependency * Bump sea-query to 0.27.2 Co-authored-by: Chris Tsang <chris.2y3@outlook.com>
This commit is contained in:
parent
588ec92fdb
commit
4d8645ae8b
@ -34,8 +34,8 @@ log = { version = "^0.4" }
|
|||||||
tracing = { version = "^0.1", features = ["log"] }
|
tracing = { version = "^0.1", features = ["log"] }
|
||||||
rust_decimal = { version = "^1", optional = true }
|
rust_decimal = { version = "^1", optional = true }
|
||||||
sea-orm-macros = { version = "^0.10.3", path = "sea-orm-macros", optional = true }
|
sea-orm-macros = { version = "^0.10.3", path = "sea-orm-macros", optional = true }
|
||||||
sea-query = { version = "^0.27.1", features = ["thread-safe"] }
|
sea-query = { version = "^0.27.2", features = ["thread-safe"] }
|
||||||
sea-query-binder = { version = "^0.2.1", optional = true }
|
sea-query-binder = { version = "^0.2.2", optional = true }
|
||||||
sea-strum = { version = "^0.23", features = ["derive", "sea-orm"] }
|
sea-strum = { version = "^0.23", features = ["derive", "sea-orm"] }
|
||||||
serde = { version = "^1.0", features = ["derive"] }
|
serde = { version = "^1.0", features = ["derive"] }
|
||||||
serde_json = { version = "^1.0", optional = true }
|
serde_json = { version = "^1.0", optional = true }
|
||||||
@ -76,7 +76,7 @@ with-chrono = ["chrono", "sea-query/with-chrono", "sea-query-binder?/with-chrono
|
|||||||
with-rust_decimal = ["rust_decimal", "sea-query/with-rust_decimal", "sea-query-binder?/with-rust_decimal", "sqlx?/decimal"]
|
with-rust_decimal = ["rust_decimal", "sea-query/with-rust_decimal", "sea-query-binder?/with-rust_decimal", "sqlx?/decimal"]
|
||||||
with-uuid = ["uuid", "sea-query/with-uuid", "sea-query-binder?/with-uuid", "sqlx?/uuid"]
|
with-uuid = ["uuid", "sea-query/with-uuid", "sea-query-binder?/with-uuid", "sqlx?/uuid"]
|
||||||
with-time = ["time", "sea-query/with-time", "sea-query-binder?/with-time", "sqlx?/time"]
|
with-time = ["time", "sea-query/with-time", "sea-query-binder?/with-time", "sqlx?/time"]
|
||||||
postgres-array = ["sea-query/postgres-array", "sea-query-binder?/postgres-array"]
|
postgres-array = ["sea-query/postgres-array", "sea-query-binder?/postgres-array", "sea-orm-macros?/postgres-array"]
|
||||||
sqlx-dep = []
|
sqlx-dep = []
|
||||||
sqlx-all = ["sqlx-mysql", "sqlx-postgres", "sqlx-sqlite"]
|
sqlx-all = ["sqlx-mysql", "sqlx-postgres", "sqlx-sqlite"]
|
||||||
sqlx-mysql = ["sqlx-dep", "sea-query-binder/sqlx-mysql", "sqlx/mysql"]
|
sqlx-mysql = ["sqlx-dep", "sea-query-binder/sqlx-mysql", "sqlx/mysql"]
|
||||||
|
@ -27,3 +27,6 @@ proc-macro2 = "^1"
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
sea-orm = { path = "../", features = ["macros"] }
|
sea-orm = { path = "../", features = ["macros"] }
|
||||||
serde = { version = "^1.0", features = ["derive"] }
|
serde = { version = "^1.0", features = ["derive"] }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
postgres-array = []
|
||||||
|
@ -287,6 +287,15 @@ impl ActiveEnum {
|
|||||||
quote!()
|
quote!()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let impl_not_u8 = if cfg!(feature = "postgres-array") {
|
||||||
|
quote!(
|
||||||
|
#[automatically_derived]
|
||||||
|
impl sea_orm::sea_query::value::with_array::NotU8 for #ident {}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
quote!()
|
||||||
|
};
|
||||||
|
|
||||||
quote!(
|
quote!(
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct #enum_name_iden;
|
pub struct #enum_name_iden;
|
||||||
@ -304,6 +313,8 @@ impl ActiveEnum {
|
|||||||
impl sea_orm::ActiveEnum for #ident {
|
impl sea_orm::ActiveEnum for #ident {
|
||||||
type Value = #rs_type;
|
type Value = #rs_type;
|
||||||
|
|
||||||
|
type ValueVec = Vec<#rs_type>;
|
||||||
|
|
||||||
fn name() -> sea_orm::sea_query::DynIden {
|
fn name() -> sea_orm::sea_query::DynIden {
|
||||||
sea_orm::sea_query::SeaRc::new(#enum_name_iden) as sea_orm::sea_query::DynIden
|
sea_orm::sea_query::SeaRc::new(#enum_name_iden) as sea_orm::sea_query::DynIden
|
||||||
}
|
}
|
||||||
@ -359,7 +370,7 @@ impl ActiveEnum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn array_type() -> sea_orm::sea_query::ArrayType {
|
fn array_type() -> sea_orm::sea_query::ArrayType {
|
||||||
unimplemented!("Array of Enum is not supported")
|
<<Self as sea_orm::ActiveEnum>::Value as sea_orm::sea_query::ValueType>::array_type()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn column_type() -> sea_orm::sea_query::ColumnType {
|
fn column_type() -> sea_orm::sea_query::ColumnType {
|
||||||
@ -384,6 +395,8 @@ impl ActiveEnum {
|
|||||||
write!(f, "{}", v)
|
write!(f, "{}", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#impl_not_u8
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{ColumnDef, DbErr, Iterable, TryGetable};
|
use crate::{ColumnDef, DbErr, Iterable, QueryResult, TryGetError, TryGetable};
|
||||||
use sea_query::{DynIden, Expr, Nullable, SimpleExpr, Value, ValueType};
|
use sea_query::{DynIden, Expr, Nullable, SimpleExpr, Value, ValueType};
|
||||||
|
|
||||||
/// A Rust representation of enum defined in database.
|
/// A Rust representation of enum defined in database.
|
||||||
@ -47,6 +47,8 @@ use sea_query::{DynIden, Expr, Nullable, SimpleExpr, Value, ValueType};
|
|||||||
/// // The macro attribute `rs_type` is being pasted here
|
/// // The macro attribute `rs_type` is being pasted here
|
||||||
/// type Value = String;
|
/// type Value = String;
|
||||||
///
|
///
|
||||||
|
/// type ValueVec = Vec<String>;
|
||||||
|
///
|
||||||
/// // Will be atomically generated by `DeriveActiveEnum`
|
/// // Will be atomically generated by `DeriveActiveEnum`
|
||||||
/// fn name() -> DynIden {
|
/// fn name() -> DynIden {
|
||||||
/// SeaRc::new(CategoryEnum)
|
/// SeaRc::new(CategoryEnum)
|
||||||
@ -114,6 +116,9 @@ pub trait ActiveEnum: Sized + Iterable {
|
|||||||
/// Define the Rust type that each enum variant represents.
|
/// Define the Rust type that each enum variant represents.
|
||||||
type Value: Into<Value> + ValueType + Nullable + TryGetable;
|
type Value: Into<Value> + ValueType + Nullable + TryGetable;
|
||||||
|
|
||||||
|
/// Define the enum value in Vector type.
|
||||||
|
type ValueVec: IntoIterator<Item = Self::Value>;
|
||||||
|
|
||||||
/// Get the name of enum
|
/// Get the name of enum
|
||||||
fn name() -> DynIden;
|
fn name() -> DynIden;
|
||||||
|
|
||||||
@ -142,6 +147,19 @@ pub trait ActiveEnum: Sized + Iterable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> TryGetable for Vec<T>
|
||||||
|
where
|
||||||
|
T: ActiveEnum,
|
||||||
|
T::ValueVec: TryGetable,
|
||||||
|
{
|
||||||
|
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
||||||
|
<T::ValueVec as TryGetable>::try_get(res, pre, col)?
|
||||||
|
.into_iter()
|
||||||
|
.map(|value| T::try_from_value(&value).map_err(TryGetError::DbErr))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate as sea_orm;
|
use crate as sea_orm;
|
||||||
@ -163,6 +181,8 @@ mod tests {
|
|||||||
impl ActiveEnum for Category {
|
impl ActiveEnum for Category {
|
||||||
type Value = String;
|
type Value = String;
|
||||||
|
|
||||||
|
type ValueVec = Vec<String>;
|
||||||
|
|
||||||
fn name() -> DynIden {
|
fn name() -> DynIden {
|
||||||
SeaRc::new(CategoryEnum)
|
SeaRc::new(CategoryEnum)
|
||||||
}
|
}
|
||||||
|
@ -353,10 +353,14 @@ impl ColumnType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_enum_name(&self) -> Option<&DynIden> {
|
pub(crate) fn get_enum_name(&self) -> Option<&DynIden> {
|
||||||
match self {
|
fn enum_name(col_type: &ColumnType) -> Option<&DynIden> {
|
||||||
ColumnType::Enum { name, .. } => Some(name),
|
match col_type {
|
||||||
_ => None,
|
ColumnType::Enum { name, .. } => Some(name),
|
||||||
|
ColumnType::Array(col_type) => enum_name(col_type),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
enum_name(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ColumnTrait, EntityTrait, Identity, IntoIdentity, IntoSimpleExpr, Iterable, ModelTrait,
|
ColumnTrait, ColumnType, EntityTrait, Identity, IntoIdentity, IntoSimpleExpr, Iterable,
|
||||||
PrimaryKeyToColumn, RelationDef,
|
ModelTrait, PrimaryKeyToColumn, RelationDef,
|
||||||
};
|
};
|
||||||
use sea_query::{
|
use sea_query::{
|
||||||
Alias, Expr, Iden, IntoCondition, IntoIden, LockType, SeaRc, SelectExpr, SelectStatement,
|
Alias, Expr, Iden, IntoCondition, IntoIden, LockType, SeaRc, SelectExpr, SelectStatement,
|
||||||
@ -616,29 +616,45 @@ pub(crate) fn unpack_table_alias(table_ref: &TableRef) -> Option<DynIden> {
|
|||||||
#[derive(Iden)]
|
#[derive(Iden)]
|
||||||
struct Text;
|
struct Text;
|
||||||
|
|
||||||
|
#[derive(Iden)]
|
||||||
|
#[iden = "text[]"]
|
||||||
|
struct TextArray;
|
||||||
|
|
||||||
pub(crate) fn cast_enum_as_text<C>(expr: Expr, col: &C) -> SimpleExpr
|
pub(crate) fn cast_enum_as_text<C>(expr: Expr, col: &C) -> SimpleExpr
|
||||||
where
|
where
|
||||||
C: ColumnTrait,
|
C: ColumnTrait,
|
||||||
{
|
{
|
||||||
cast_enum_text_inner(expr, col, |col, _| col.as_enum(Text))
|
cast_enum_text_inner(expr, col, |col, _, col_type| {
|
||||||
|
let type_name = match col_type {
|
||||||
|
ColumnType::Array(_) => TextArray.into_iden(),
|
||||||
|
_ => Text.into_iden(),
|
||||||
|
};
|
||||||
|
col.as_enum(type_name)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cast_text_as_enum<C>(expr: Expr, col: &C) -> SimpleExpr
|
pub(crate) fn cast_text_as_enum<C>(expr: Expr, col: &C) -> SimpleExpr
|
||||||
where
|
where
|
||||||
C: ColumnTrait,
|
C: ColumnTrait,
|
||||||
{
|
{
|
||||||
cast_enum_text_inner(expr, col, |col, enum_name| col.as_enum(enum_name))
|
cast_enum_text_inner(expr, col, |col, enum_name, col_type| {
|
||||||
|
let type_name = match col_type {
|
||||||
|
ColumnType::Array(_) => Alias::new(&format!("{}[]", enum_name.to_string())).into_iden(),
|
||||||
|
_ => enum_name,
|
||||||
|
};
|
||||||
|
col.as_enum(type_name)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cast_enum_text_inner<C, F>(expr: Expr, col: &C, f: F) -> SimpleExpr
|
fn cast_enum_text_inner<C, F>(expr: Expr, col: &C, f: F) -> SimpleExpr
|
||||||
where
|
where
|
||||||
C: ColumnTrait,
|
C: ColumnTrait,
|
||||||
F: Fn(Expr, DynIden) -> SimpleExpr,
|
F: Fn(Expr, DynIden, &ColumnType) -> SimpleExpr,
|
||||||
{
|
{
|
||||||
let col_def = col.def();
|
let col_def = col.def();
|
||||||
let col_type = col_def.get_column_type();
|
let col_type = col_def.get_column_type();
|
||||||
match col_type.get_enum_name() {
|
match col_type.get_enum_name() {
|
||||||
Some(enum_name) => f(expr, SeaRc::clone(enum_name)),
|
Some(enum_name) => f(expr, SeaRc::clone(enum_name), col_type),
|
||||||
None => expr.into(),
|
None => expr.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,10 @@ pub async fn insert_collection(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|||||||
id: 1,
|
id: 1,
|
||||||
integers: vec![1, 2, 3],
|
integers: vec![1, 2, 3],
|
||||||
integers_opt: Some(vec![1, 2, 3]),
|
integers_opt: Some(vec![1, 2, 3]),
|
||||||
|
teas: vec![Tea::BreakfastTea],
|
||||||
|
teas_opt: Some(vec![Tea::BreakfastTea]),
|
||||||
|
colors: vec![Color::Black],
|
||||||
|
colors_opt: Some(vec![Color::Black]),
|
||||||
}
|
}
|
||||||
.into_active_model()
|
.into_active_model()
|
||||||
.insert(db)
|
.insert(db)
|
||||||
@ -32,6 +36,10 @@ pub async fn insert_collection(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|||||||
id: 1,
|
id: 1,
|
||||||
integers: vec![1, 2, 3],
|
integers: vec![1, 2, 3],
|
||||||
integers_opt: Some(vec![1, 2, 3]),
|
integers_opt: Some(vec![1, 2, 3]),
|
||||||
|
teas: vec![Tea::BreakfastTea],
|
||||||
|
teas_opt: Some(vec![Tea::BreakfastTea]),
|
||||||
|
colors: vec![Color::Black],
|
||||||
|
colors_opt: Some(vec![Color::Black]),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -40,6 +48,10 @@ pub async fn insert_collection(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|||||||
id: 2,
|
id: 2,
|
||||||
integers: vec![10, 9],
|
integers: vec![10, 9],
|
||||||
integers_opt: None,
|
integers_opt: None,
|
||||||
|
teas: vec![Tea::BreakfastTea],
|
||||||
|
teas_opt: None,
|
||||||
|
colors: vec![Color::Black],
|
||||||
|
colors_opt: None,
|
||||||
}
|
}
|
||||||
.into_active_model()
|
.into_active_model()
|
||||||
.insert(db)
|
.insert(db)
|
||||||
@ -48,6 +60,10 @@ pub async fn insert_collection(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|||||||
id: 2,
|
id: 2,
|
||||||
integers: vec![10, 9],
|
integers: vec![10, 9],
|
||||||
integers_opt: None,
|
integers_opt: None,
|
||||||
|
teas: vec![Tea::BreakfastTea],
|
||||||
|
teas_opt: None,
|
||||||
|
colors: vec![Color::Black],
|
||||||
|
colors_opt: None,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -56,6 +72,10 @@ pub async fn insert_collection(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|||||||
id: 3,
|
id: 3,
|
||||||
integers: vec![],
|
integers: vec![],
|
||||||
integers_opt: Some(vec![]),
|
integers_opt: Some(vec![]),
|
||||||
|
teas: vec![],
|
||||||
|
teas_opt: Some(vec![]),
|
||||||
|
colors: vec![],
|
||||||
|
colors_opt: Some(vec![]),
|
||||||
}
|
}
|
||||||
.into_active_model()
|
.into_active_model()
|
||||||
.insert(db)
|
.insert(db)
|
||||||
@ -64,6 +84,10 @@ pub async fn insert_collection(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|||||||
id: 3,
|
id: 3,
|
||||||
integers: vec![],
|
integers: vec![],
|
||||||
integers_opt: Some(vec![]),
|
integers_opt: Some(vec![]),
|
||||||
|
teas: vec![],
|
||||||
|
teas_opt: Some(vec![]),
|
||||||
|
colors: vec![],
|
||||||
|
colors_opt: Some(vec![]),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -78,6 +102,10 @@ pub async fn update_collection(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|||||||
ActiveModel {
|
ActiveModel {
|
||||||
integers: Set(vec![4, 5, 6]),
|
integers: Set(vec![4, 5, 6]),
|
||||||
integers_opt: Set(Some(vec![4, 5, 6])),
|
integers_opt: Set(Some(vec![4, 5, 6])),
|
||||||
|
teas: Set(vec![Tea::EverydayTea]),
|
||||||
|
teas_opt: Set(Some(vec![Tea::EverydayTea])),
|
||||||
|
colors: Set(vec![Color::White]),
|
||||||
|
colors_opt: Set(Some(vec![Color::White])),
|
||||||
..model.into_active_model()
|
..model.into_active_model()
|
||||||
}
|
}
|
||||||
.update(db)
|
.update(db)
|
||||||
@ -87,6 +115,10 @@ pub async fn update_collection(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|||||||
id: Unchanged(3),
|
id: Unchanged(3),
|
||||||
integers: Set(vec![3, 1, 4]),
|
integers: Set(vec![3, 1, 4]),
|
||||||
integers_opt: Set(None),
|
integers_opt: Set(None),
|
||||||
|
teas: Set(vec![Tea::EverydayTea]),
|
||||||
|
teas_opt: Set(None),
|
||||||
|
colors: Set(vec![Color::White]),
|
||||||
|
colors_opt: Set(None),
|
||||||
}
|
}
|
||||||
.update(db)
|
.update(db)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use super::sea_orm_active_enums::*;
|
||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
||||||
@ -7,6 +8,10 @@ pub struct Model {
|
|||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub integers: Vec<i32>,
|
pub integers: Vec<i32>,
|
||||||
pub integers_opt: Option<Vec<i32>>,
|
pub integers_opt: Option<Vec<i32>>,
|
||||||
|
pub teas: Vec<Tea>,
|
||||||
|
pub teas_opt: Option<Vec<Tea>>,
|
||||||
|
pub colors: Vec<Color>,
|
||||||
|
pub colors_opt: Option<Vec<Color>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
@ -6,7 +6,7 @@ use sea_orm::{
|
|||||||
error::*, sea_query, ConnectionTrait, DatabaseConnection, DbBackend, DbConn, EntityName,
|
error::*, sea_query, ConnectionTrait, DatabaseConnection, DbBackend, DbConn, EntityName,
|
||||||
ExecResult, Schema,
|
ExecResult, Schema,
|
||||||
};
|
};
|
||||||
use sea_query::{extension::postgres::Type, Alias, ColumnDef, ForeignKeyCreateStatement};
|
use sea_query::{extension::postgres::Type, Alias, ColumnDef, ForeignKeyCreateStatement, IntoIden};
|
||||||
|
|
||||||
pub async fn create_tables(db: &DatabaseConnection) -> Result<(), DbErr> {
|
pub async fn create_tables(db: &DatabaseConnection) -> Result<(), DbErr> {
|
||||||
let db_backend = db.get_database_backend();
|
let db_backend = db.get_database_backend();
|
||||||
@ -350,6 +350,35 @@ pub async fn create_collection_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
|||||||
ColumnDef::new(collection::Column::IntegersOpt)
|
ColumnDef::new(collection::Column::IntegersOpt)
|
||||||
.array(sea_query::ColumnType::Integer(None)),
|
.array(sea_query::ColumnType::Integer(None)),
|
||||||
)
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(collection::Column::Teas)
|
||||||
|
.array(sea_query::ColumnType::Enum {
|
||||||
|
name: TeaEnum.into_iden(),
|
||||||
|
variants: vec![
|
||||||
|
TeaVariant::EverydayTea.into_iden(),
|
||||||
|
TeaVariant::BreakfastTea.into_iden(),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.not_null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(collection::Column::TeasOpt).array(sea_query::ColumnType::Enum {
|
||||||
|
name: TeaEnum.into_iden(),
|
||||||
|
variants: vec![
|
||||||
|
TeaVariant::EverydayTea.into_iden(),
|
||||||
|
TeaVariant::BreakfastTea.into_iden(),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(collection::Column::Colors)
|
||||||
|
.array(sea_query::ColumnType::Integer(None))
|
||||||
|
.not_null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(collection::Column::ColorsOpt)
|
||||||
|
.array(sea_query::ColumnType::Integer(None)),
|
||||||
|
)
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
create_table(db, &stmt, Collection).await
|
create_table(db, &stmt, Collection).await
|
||||||
|
Loading…
x
Reference in New Issue
Block a user