Merge branch 'master' into transaction-3
This commit is contained in:
commit
51b30ee837
1
.github/workflows/rust.yml
vendored
1
.github/workflows/rust.yml
vendored
@ -5,6 +5,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
- 0.2.x
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
|
10
CHANGELOG.md
10
CHANGELOG.md
@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## 0.2.5 - 2021-10-06
|
||||||
|
|
||||||
|
- [[#227]] Resolve "Inserting actual none value of Option<Date> results in panic"
|
||||||
|
- [[#219]] [sea-orm-cli] Add `--tables` option
|
||||||
|
- [[#189]] Add `debug_query` and `debug_query_stmt` macro
|
||||||
|
|
||||||
|
[#227]: https://github.com/SeaQL/sea-orm/issues/227
|
||||||
|
[#219]: https://github.com/SeaQL/sea-orm/pull/219
|
||||||
|
[#189]: https://github.com/SeaQL/sea-orm/pull/189
|
||||||
|
|
||||||
## 0.2.4 - 2021-10-01
|
## 0.2.4 - 2021-10-01
|
||||||
|
|
||||||
- [[#186]] [sea-orm-cli] Foreign key handling
|
- [[#186]] [sea-orm-cli] Foreign key handling
|
||||||
|
@ -3,7 +3,7 @@ members = [".", "sea-orm-macros", "sea-orm-codegen"]
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "sea-orm"
|
name = "sea-orm"
|
||||||
version = "0.2.4"
|
version = "0.2.5"
|
||||||
authors = ["Chris Tsang <tyt2y7@gmail.com>"]
|
authors = ["Chris Tsang <tyt2y7@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "🐚 An async & dynamic ORM for Rust"
|
description = "🐚 An async & dynamic ORM for Rust"
|
||||||
@ -29,8 +29,8 @@ futures = { version = "^0.3" }
|
|||||||
futures-util = { version = "^0.3" }
|
futures-util = { version = "^0.3" }
|
||||||
log = { version = "^0.4", optional = true }
|
log = { version = "^0.4", optional = true }
|
||||||
rust_decimal = { version = "^1", optional = true }
|
rust_decimal = { version = "^1", optional = true }
|
||||||
sea-orm-macros = { version = "^0.2.4", path = "sea-orm-macros", optional = true }
|
sea-orm-macros = { version = "^0.2.5", path = "sea-orm-macros", optional = true }
|
||||||
sea-query = { version = "^0.16.5", features = ["thread-safe"] }
|
sea-query = { version = "^0.17.0", features = ["thread-safe"] }
|
||||||
sea-strum = { version = "^0.21", features = ["derive", "sea-orm"] }
|
sea-strum = { version = "^0.21", features = ["derive", "sea-orm"] }
|
||||||
serde = { version = "^1.0", features = ["derive"] }
|
serde = { version = "^1.0", features = ["derive"] }
|
||||||
serde_json = { version = "^1", optional = true }
|
serde_json = { version = "^1", optional = true }
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "sea-orm-cli"
|
name = "sea-orm-cli"
|
||||||
version = "0.2.4"
|
version = "0.2.5"
|
||||||
authors = [ "Billy Chan <ccw.billy.123@gmail.com>" ]
|
authors = [ "Billy Chan <ccw.billy.123@gmail.com>" ]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "Command line utility for SeaORM"
|
description = "Command line utility for SeaORM"
|
||||||
@ -21,7 +21,7 @@ path = "src/main.rs"
|
|||||||
clap = { version = "^2.33.3" }
|
clap = { version = "^2.33.3" }
|
||||||
dotenv = { version = "^0.15" }
|
dotenv = { version = "^0.15" }
|
||||||
async-std = { version = "^1.9", features = [ "attributes" ] }
|
async-std = { version = "^1.9", features = [ "attributes" ] }
|
||||||
sea-orm-codegen = { version = "^0.2.4", path = "../sea-orm-codegen" }
|
sea-orm-codegen = { version = "^0.2.5", path = "../sea-orm-codegen" }
|
||||||
sea-schema = { version = "^0.2.9", default-features = false, features = [
|
sea-schema = { version = "^0.2.9", default-features = false, features = [
|
||||||
"debug-print",
|
"debug-print",
|
||||||
"sqlx-mysql",
|
"sqlx-mysql",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "sea-orm-codegen"
|
name = "sea-orm-codegen"
|
||||||
version = "0.2.4"
|
version = "0.2.5"
|
||||||
authors = ["Billy Chan <ccw.billy.123@gmail.com>"]
|
authors = ["Billy Chan <ccw.billy.123@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "Code Generator for SeaORM"
|
description = "Code Generator for SeaORM"
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::util::escape_rust_keyword;
|
||||||
use heck::{CamelCase, SnakeCase};
|
use heck::{CamelCase, SnakeCase};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
@ -14,11 +15,11 @@ pub struct Column {
|
|||||||
|
|
||||||
impl Column {
|
impl Column {
|
||||||
pub fn get_name_snake_case(&self) -> Ident {
|
pub fn get_name_snake_case(&self) -> Ident {
|
||||||
format_ident!("{}", self.name.to_snake_case())
|
format_ident!("{}", escape_rust_keyword(self.name.to_snake_case()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_name_camel_case(&self) -> Ident {
|
pub fn get_name_camel_case(&self) -> Ident {
|
||||||
format_ident!("{}", self.name.to_camel_case())
|
format_ident!("{}", escape_rust_keyword(self.name.to_camel_case()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_rs_type(&self) -> TokenStream {
|
pub fn get_rs_type(&self) -> TokenStream {
|
||||||
@ -27,8 +28,6 @@ impl Column {
|
|||||||
ColumnType::Char(_)
|
ColumnType::Char(_)
|
||||||
| ColumnType::String(_)
|
| ColumnType::String(_)
|
||||||
| ColumnType::Text
|
| ColumnType::Text
|
||||||
| ColumnType::Time(_)
|
|
||||||
| ColumnType::Date
|
|
||||||
| ColumnType::Custom(_) => "String",
|
| ColumnType::Custom(_) => "String",
|
||||||
ColumnType::TinyInteger(_) => "i8",
|
ColumnType::TinyInteger(_) => "i8",
|
||||||
ColumnType::SmallInteger(_) => "i16",
|
ColumnType::SmallInteger(_) => "i16",
|
||||||
@ -37,6 +36,8 @@ impl Column {
|
|||||||
ColumnType::Float(_) => "f32",
|
ColumnType::Float(_) => "f32",
|
||||||
ColumnType::Double(_) => "f64",
|
ColumnType::Double(_) => "f64",
|
||||||
ColumnType::Json | ColumnType::JsonBinary => "Json",
|
ColumnType::Json | ColumnType::JsonBinary => "Json",
|
||||||
|
ColumnType::Date => "Date",
|
||||||
|
ColumnType::Time(_) => "Time",
|
||||||
ColumnType::DateTime(_) | ColumnType::Timestamp(_) => "DateTime",
|
ColumnType::DateTime(_) | ColumnType::Timestamp(_) => "DateTime",
|
||||||
ColumnType::TimestampWithTimeZone(_) => "DateTimeWithTimeZone",
|
ColumnType::TimestampWithTimeZone(_) => "DateTimeWithTimeZone",
|
||||||
ColumnType::Decimal(_) | ColumnType::Money(_) => "Decimal",
|
ColumnType::Decimal(_) | ColumnType::Money(_) => "Decimal",
|
||||||
@ -194,6 +195,11 @@ mod tests {
|
|||||||
make_col!("CAKE_FILLING_ID", ColumnType::Double(None)),
|
make_col!("CAKE_FILLING_ID", ColumnType::Double(None)),
|
||||||
make_col!("CAKE-FILLING-ID", ColumnType::Binary(None)),
|
make_col!("CAKE-FILLING-ID", ColumnType::Binary(None)),
|
||||||
make_col!("CAKE", ColumnType::Boolean),
|
make_col!("CAKE", ColumnType::Boolean),
|
||||||
|
make_col!("date", ColumnType::Date),
|
||||||
|
make_col!("time", ColumnType::Time(None)),
|
||||||
|
make_col!("date_time", ColumnType::DateTime(None)),
|
||||||
|
make_col!("timestamp", ColumnType::Timestamp(None)),
|
||||||
|
make_col!("timestamp_tz", ColumnType::TimestampWithTimeZone(None)),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,6 +217,11 @@ mod tests {
|
|||||||
"cake_filling_id",
|
"cake_filling_id",
|
||||||
"cake_filling_id",
|
"cake_filling_id",
|
||||||
"cake",
|
"cake",
|
||||||
|
"date",
|
||||||
|
"time",
|
||||||
|
"date_time",
|
||||||
|
"timestamp",
|
||||||
|
"timestamp_tz",
|
||||||
];
|
];
|
||||||
for (col, snack_case) in columns.into_iter().zip(snack_cases) {
|
for (col, snack_case) in columns.into_iter().zip(snack_cases) {
|
||||||
assert_eq!(col.get_name_snake_case().to_string(), snack_case);
|
assert_eq!(col.get_name_snake_case().to_string(), snack_case);
|
||||||
@ -231,6 +242,11 @@ mod tests {
|
|||||||
"CakeFillingId",
|
"CakeFillingId",
|
||||||
"CakeFillingId",
|
"CakeFillingId",
|
||||||
"Cake",
|
"Cake",
|
||||||
|
"Date",
|
||||||
|
"Time",
|
||||||
|
"DateTime",
|
||||||
|
"Timestamp",
|
||||||
|
"TimestampTz",
|
||||||
];
|
];
|
||||||
for (col, camel_case) in columns.into_iter().zip(camel_cases) {
|
for (col, camel_case) in columns.into_iter().zip(camel_cases) {
|
||||||
assert_eq!(col.get_name_camel_case().to_string(), camel_case);
|
assert_eq!(col.get_name_camel_case().to_string(), camel_case);
|
||||||
@ -241,7 +257,21 @@ mod tests {
|
|||||||
fn test_get_rs_type() {
|
fn test_get_rs_type() {
|
||||||
let columns = setup();
|
let columns = setup();
|
||||||
let rs_types = vec![
|
let rs_types = vec![
|
||||||
"String", "String", "i8", "i16", "i32", "i64", "f32", "f64", "Vec<u8>", "bool",
|
"String",
|
||||||
|
"String",
|
||||||
|
"i8",
|
||||||
|
"i16",
|
||||||
|
"i32",
|
||||||
|
"i64",
|
||||||
|
"f32",
|
||||||
|
"f64",
|
||||||
|
"Vec<u8>",
|
||||||
|
"bool",
|
||||||
|
"Date",
|
||||||
|
"Time",
|
||||||
|
"DateTime",
|
||||||
|
"DateTime",
|
||||||
|
"DateTimeWithTimeZone",
|
||||||
];
|
];
|
||||||
for (mut col, rs_type) in columns.into_iter().zip(rs_types) {
|
for (mut col, rs_type) in columns.into_iter().zip(rs_types) {
|
||||||
let rs_type: TokenStream = rs_type.parse().unwrap();
|
let rs_type: TokenStream = rs_type.parse().unwrap();
|
||||||
@ -271,6 +301,11 @@ mod tests {
|
|||||||
"ColumnType::Double.def()",
|
"ColumnType::Double.def()",
|
||||||
"ColumnType::Binary.def()",
|
"ColumnType::Binary.def()",
|
||||||
"ColumnType::Boolean.def()",
|
"ColumnType::Boolean.def()",
|
||||||
|
"ColumnType::Date.def()",
|
||||||
|
"ColumnType::Time.def()",
|
||||||
|
"ColumnType::DateTime.def()",
|
||||||
|
"ColumnType::Timestamp.def()",
|
||||||
|
"ColumnType::TimestampWithTimeZone.def()",
|
||||||
];
|
];
|
||||||
for (mut col, col_def) in columns.into_iter().zip(col_defs) {
|
for (mut col, col_def) in columns.into_iter().zip(col_defs) {
|
||||||
let mut col_def: TokenStream = col_def.parse().unwrap();
|
let mut col_def: TokenStream = col_def.parse().unwrap();
|
||||||
|
@ -597,18 +597,85 @@ mod tests {
|
|||||||
name: "id".to_owned(),
|
name: "id".to_owned(),
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
|
Entity {
|
||||||
|
table_name: "rust_keyword".to_owned(),
|
||||||
|
columns: vec![
|
||||||
|
Column {
|
||||||
|
name: "id".to_owned(),
|
||||||
|
col_type: ColumnType::Integer(Some(11)),
|
||||||
|
auto_increment: true,
|
||||||
|
not_null: true,
|
||||||
|
unique: false,
|
||||||
|
},
|
||||||
|
Column {
|
||||||
|
name: "testing".to_owned(),
|
||||||
|
col_type: ColumnType::Integer(Some(11)),
|
||||||
|
auto_increment: false,
|
||||||
|
not_null: true,
|
||||||
|
unique: false,
|
||||||
|
},
|
||||||
|
Column {
|
||||||
|
name: "rust".to_owned(),
|
||||||
|
col_type: ColumnType::Integer(Some(11)),
|
||||||
|
auto_increment: false,
|
||||||
|
not_null: true,
|
||||||
|
unique: false,
|
||||||
|
},
|
||||||
|
Column {
|
||||||
|
name: "keywords".to_owned(),
|
||||||
|
col_type: ColumnType::Integer(Some(11)),
|
||||||
|
auto_increment: false,
|
||||||
|
not_null: true,
|
||||||
|
unique: false,
|
||||||
|
},
|
||||||
|
Column {
|
||||||
|
name: "type".to_owned(),
|
||||||
|
col_type: ColumnType::Integer(Some(11)),
|
||||||
|
auto_increment: false,
|
||||||
|
not_null: true,
|
||||||
|
unique: false,
|
||||||
|
},
|
||||||
|
Column {
|
||||||
|
name: "typeof".to_owned(),
|
||||||
|
col_type: ColumnType::Integer(Some(11)),
|
||||||
|
auto_increment: false,
|
||||||
|
not_null: true,
|
||||||
|
unique: false,
|
||||||
|
},
|
||||||
|
Column {
|
||||||
|
name: "crate".to_owned(),
|
||||||
|
col_type: ColumnType::Integer(Some(11)),
|
||||||
|
auto_increment: false,
|
||||||
|
not_null: true,
|
||||||
|
unique: false,
|
||||||
|
},
|
||||||
|
Column {
|
||||||
|
name: "self".to_owned(),
|
||||||
|
col_type: ColumnType::Integer(Some(11)),
|
||||||
|
auto_increment: false,
|
||||||
|
not_null: true,
|
||||||
|
unique: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
relations: vec![],
|
||||||
|
conjunct_relations: vec![],
|
||||||
|
primary_keys: vec![PrimaryKey {
|
||||||
|
name: "id".to_owned(),
|
||||||
|
}],
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_gen_expanded_code_blocks() -> io::Result<()> {
|
fn test_gen_expanded_code_blocks() -> io::Result<()> {
|
||||||
let entities = setup();
|
let entities = setup();
|
||||||
const ENTITY_FILES: [&str; 5] = [
|
const ENTITY_FILES: [&str; 6] = [
|
||||||
include_str!("../../tests/expanded/cake.rs"),
|
include_str!("../../tests/expanded/cake.rs"),
|
||||||
include_str!("../../tests/expanded/cake_filling.rs"),
|
include_str!("../../tests/expanded/cake_filling.rs"),
|
||||||
include_str!("../../tests/expanded/filling.rs"),
|
include_str!("../../tests/expanded/filling.rs"),
|
||||||
include_str!("../../tests/expanded/fruit.rs"),
|
include_str!("../../tests/expanded/fruit.rs"),
|
||||||
include_str!("../../tests/expanded/vendor.rs"),
|
include_str!("../../tests/expanded/vendor.rs"),
|
||||||
|
include_str!("../../tests/expanded/rust_keyword.rs"),
|
||||||
];
|
];
|
||||||
|
|
||||||
assert_eq!(entities.len(), ENTITY_FILES.len());
|
assert_eq!(entities.len(), ENTITY_FILES.len());
|
||||||
@ -642,12 +709,13 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_gen_compact_code_blocks() -> io::Result<()> {
|
fn test_gen_compact_code_blocks() -> io::Result<()> {
|
||||||
let entities = setup();
|
let entities = setup();
|
||||||
const ENTITY_FILES: [&str; 5] = [
|
const ENTITY_FILES: [&str; 6] = [
|
||||||
include_str!("../../tests/compact/cake.rs"),
|
include_str!("../../tests/compact/cake.rs"),
|
||||||
include_str!("../../tests/compact/cake_filling.rs"),
|
include_str!("../../tests/compact/cake_filling.rs"),
|
||||||
include_str!("../../tests/compact/filling.rs"),
|
include_str!("../../tests/compact/filling.rs"),
|
||||||
include_str!("../../tests/compact/fruit.rs"),
|
include_str!("../../tests/compact/fruit.rs"),
|
||||||
include_str!("../../tests/compact/vendor.rs"),
|
include_str!("../../tests/compact/vendor.rs"),
|
||||||
|
include_str!("../../tests/compact/rust_keyword.rs"),
|
||||||
];
|
];
|
||||||
|
|
||||||
assert_eq!(entities.len(), ENTITY_FILES.len());
|
assert_eq!(entities.len(), ENTITY_FILES.len());
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
mod entity;
|
mod entity;
|
||||||
mod error;
|
mod error;
|
||||||
|
mod util;
|
||||||
|
|
||||||
pub use entity::*;
|
pub use entity::*;
|
||||||
pub use error::*;
|
pub use error::*;
|
||||||
|
23
sea-orm-codegen/src/util.rs
Normal file
23
sea-orm-codegen/src/util.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
pub(crate) fn escape_rust_keyword<T>(string: T) -> String
|
||||||
|
where
|
||||||
|
T: ToString,
|
||||||
|
{
|
||||||
|
let string = string.to_string();
|
||||||
|
if RUST_KEYWORDS.iter().any(|s| s.eq(&string)) {
|
||||||
|
format!("r#{}", string)
|
||||||
|
} else if RUST_SPECIAL_KEYWORDS.iter().any(|s| s.eq(&string)) {
|
||||||
|
format!("{}_", string)
|
||||||
|
} else {
|
||||||
|
string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) const RUST_KEYWORDS: [&str; 49] = [
|
||||||
|
"as", "async", "await", "break", "const", "continue", "dyn", "else", "enum", "extern", "false",
|
||||||
|
"fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", "ref",
|
||||||
|
"return", "static", "struct", "super", "trait", "true", "type", "union", "unsafe", "use",
|
||||||
|
"where", "while", "abstract", "become", "box", "do", "final", "macro", "override", "priv",
|
||||||
|
"try", "typeof", "unsized", "virtual", "yield",
|
||||||
|
];
|
||||||
|
|
||||||
|
pub(crate) const RUST_SPECIAL_KEYWORDS: [&str; 3] = ["crate", "Self", "self"];
|
30
sea-orm-codegen/tests/compact/rust_keyword.rs
Normal file
30
sea-orm-codegen/tests/compact/rust_keyword.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0
|
||||||
|
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
||||||
|
#[sea_orm(table_name = "rust_keyword")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
pub testing: i32,
|
||||||
|
pub rust: i32,
|
||||||
|
pub keywords: i32,
|
||||||
|
pub r#type: i32,
|
||||||
|
pub r#typeof: i32,
|
||||||
|
pub crate_: i32,
|
||||||
|
pub self_: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||||
|
pub enum Relation {}
|
||||||
|
|
||||||
|
impl RelationTrait for Relation {
|
||||||
|
fn def(&self) -> RelationDef {
|
||||||
|
match self {
|
||||||
|
_ => panic!("No RelationDef"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
79
sea-orm-codegen/tests/expanded/rust_keyword.rs
Normal file
79
sea-orm-codegen/tests/expanded/rust_keyword.rs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0
|
||||||
|
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||||
|
pub struct Entity;
|
||||||
|
|
||||||
|
impl EntityName for Entity {
|
||||||
|
fn table_name(&self) -> &str {
|
||||||
|
"rust_keyword"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||||
|
pub struct Model {
|
||||||
|
pub id: i32,
|
||||||
|
pub testing: i32,
|
||||||
|
pub rust: i32,
|
||||||
|
pub keywords: i32,
|
||||||
|
pub r#type: i32,
|
||||||
|
pub r#typeof: i32,
|
||||||
|
pub crate_: i32,
|
||||||
|
pub self_: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||||
|
pub enum Column {
|
||||||
|
Id,
|
||||||
|
Testing,
|
||||||
|
Rust,
|
||||||
|
Keywords,
|
||||||
|
Type,
|
||||||
|
Typeof,
|
||||||
|
Crate,
|
||||||
|
Self_,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||||
|
pub enum PrimaryKey {
|
||||||
|
Id,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrimaryKeyTrait for PrimaryKey {
|
||||||
|
type ValueType = i32;
|
||||||
|
|
||||||
|
fn auto_increment() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||||
|
pub enum Relation {}
|
||||||
|
|
||||||
|
impl ColumnTrait for Column {
|
||||||
|
type EntityName = Entity;
|
||||||
|
|
||||||
|
fn def(&self) -> ColumnDef {
|
||||||
|
match self {
|
||||||
|
Self::Id => ColumnType::Integer.def(),
|
||||||
|
Self::Testing => ColumnType::Integer.def(),
|
||||||
|
Self::Rust => ColumnType::Integer.def(),
|
||||||
|
Self::Keywords => ColumnType::Integer.def(),
|
||||||
|
Self::Type => ColumnType::Integer.def(),
|
||||||
|
Self::Typeof => ColumnType::Integer.def(),
|
||||||
|
Self::Crate => ColumnType::Integer.def(),
|
||||||
|
Self::Self_ => ColumnType::Integer.def(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelationTrait for Relation {
|
||||||
|
fn def(&self) -> RelationDef {
|
||||||
|
match self {
|
||||||
|
_ => panic!("No RelationDef"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "sea-orm-macros"
|
name = "sea-orm-macros"
|
||||||
version = "0.2.4"
|
version = "0.2.5"
|
||||||
authors = [ "Billy Chan <ccw.billy.123@gmail.com>" ]
|
authors = [ "Billy Chan <ccw.billy.123@gmail.com>" ]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "Derive macros for SeaORM"
|
description = "Derive macros for SeaORM"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::util::field_not_ignored;
|
use crate::util::{escape_rust_keyword, field_not_ignored, trim_starting_raw_identifier};
|
||||||
use heck::CamelCase;
|
use heck::CamelCase;
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote, quote_spanned};
|
use quote::{format_ident, quote, quote_spanned};
|
||||||
@ -29,10 +29,10 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result<Token
|
|||||||
.clone()
|
.clone()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let mut ident = format_ident!(
|
let ident = field.ident.as_ref().unwrap().to_string();
|
||||||
"{}",
|
let ident = trim_starting_raw_identifier(ident).to_camel_case();
|
||||||
field.ident.as_ref().unwrap().to_string().to_camel_case()
|
let ident = escape_rust_keyword(ident);
|
||||||
);
|
let mut ident = format_ident!("{}", &ident);
|
||||||
for attr in field.attrs.iter() {
|
for attr in field.attrs.iter() {
|
||||||
if let Some(ident) = attr.path.get_ident() {
|
if let Some(ident) = attr.path.get_ident() {
|
||||||
if ident != "sea_orm" {
|
if ident != "sea_orm" {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use crate::util::{escape_rust_keyword, trim_starting_raw_identifier};
|
||||||
|
use convert_case::{Case, Casing};
|
||||||
use proc_macro2::{Ident, Span, TokenStream};
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{
|
use syn::{
|
||||||
@ -5,8 +7,6 @@ use syn::{
|
|||||||
Lit, Meta,
|
Lit, Meta,
|
||||||
};
|
};
|
||||||
|
|
||||||
use convert_case::{Case, Casing};
|
|
||||||
|
|
||||||
pub fn expand_derive_entity_model(data: Data, attrs: Vec<Attribute>) -> syn::Result<TokenStream> {
|
pub fn expand_derive_entity_model(data: Data, attrs: Vec<Attribute>) -> syn::Result<TokenStream> {
|
||||||
// if #[sea_orm(table_name = "foo", schema_name = "bar")] specified, create Entity struct
|
// if #[sea_orm(table_name = "foo", schema_name = "bar")] specified, create Entity struct
|
||||||
let mut table_name = None;
|
let mut table_name = None;
|
||||||
@ -60,8 +60,10 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec<Attribute>) -> syn::Res
|
|||||||
if let Fields::Named(fields) = item_struct.fields {
|
if let Fields::Named(fields) = item_struct.fields {
|
||||||
for field in fields.named {
|
for field in fields.named {
|
||||||
if let Some(ident) = &field.ident {
|
if let Some(ident) = &field.ident {
|
||||||
let mut field_name =
|
let mut field_name = Ident::new(
|
||||||
Ident::new(&ident.to_string().to_case(Case::Pascal), Span::call_site());
|
&trim_starting_raw_identifier(&ident).to_case(Case::Pascal),
|
||||||
|
Span::call_site(),
|
||||||
|
);
|
||||||
|
|
||||||
let mut nullable = false;
|
let mut nullable = false;
|
||||||
let mut default_value = None;
|
let mut default_value = None;
|
||||||
@ -168,6 +170,8 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec<Attribute>) -> syn::Res
|
|||||||
field_name = enum_name;
|
field_name = enum_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
field_name = Ident::new(&escape_rust_keyword(field_name), Span::call_site());
|
||||||
|
|
||||||
if ignore {
|
if ignore {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use crate::{attributes::derive_attr, util::field_not_ignored};
|
use crate::{
|
||||||
|
attributes::derive_attr,
|
||||||
|
util::{escape_rust_keyword, field_not_ignored, trim_starting_raw_identifier},
|
||||||
|
};
|
||||||
use heck::CamelCase;
|
use heck::CamelCase;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote, quote_spanned};
|
use quote::{format_ident, quote, quote_spanned};
|
||||||
@ -43,10 +46,10 @@ impl DeriveModel {
|
|||||||
let column_idents = fields
|
let column_idents = fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let mut ident = format_ident!(
|
let ident = field.ident.as_ref().unwrap().to_string();
|
||||||
"{}",
|
let ident = trim_starting_raw_identifier(ident).to_camel_case();
|
||||||
field.ident.as_ref().unwrap().to_string().to_camel_case()
|
let ident = escape_rust_keyword(ident);
|
||||||
);
|
let mut ident = format_ident!("{}", &ident);
|
||||||
for attr in field.attrs.iter() {
|
for attr in field.attrs.iter() {
|
||||||
if let Some(ident) = attr.path.get_ident() {
|
if let Some(ident) = attr.path.get_ident() {
|
||||||
if ident != "sea_orm" {
|
if ident != "sea_orm" {
|
||||||
|
@ -24,3 +24,39 @@ pub(crate) fn field_not_ignored(field: &Field) -> bool {
|
|||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn trim_starting_raw_identifier<T>(string: T) -> String
|
||||||
|
where
|
||||||
|
T: ToString,
|
||||||
|
{
|
||||||
|
string
|
||||||
|
.to_string()
|
||||||
|
.trim_start_matches(RAW_IDENTIFIER)
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn escape_rust_keyword<T>(string: T) -> String
|
||||||
|
where
|
||||||
|
T: ToString,
|
||||||
|
{
|
||||||
|
let string = string.to_string();
|
||||||
|
if RUST_KEYWORDS.iter().any(|s| s.eq(&string)) {
|
||||||
|
format!("r#{}", string)
|
||||||
|
} else if RUST_SPECIAL_KEYWORDS.iter().any(|s| s.eq(&string)) {
|
||||||
|
format!("{}_", string)
|
||||||
|
} else {
|
||||||
|
string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) const RAW_IDENTIFIER: &str = "r#";
|
||||||
|
|
||||||
|
pub(crate) const RUST_KEYWORDS: [&str; 49] = [
|
||||||
|
"as", "async", "await", "break", "const", "continue", "dyn", "else", "enum", "extern", "false",
|
||||||
|
"fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", "ref",
|
||||||
|
"return", "static", "struct", "super", "trait", "true", "type", "union", "unsafe", "use",
|
||||||
|
"where", "while", "abstract", "become", "box", "do", "final", "macro", "override", "priv",
|
||||||
|
"try", "typeof", "unsized", "virtual", "yield",
|
||||||
|
];
|
||||||
|
|
||||||
|
pub(crate) const RUST_SPECIAL_KEYWORDS: [&str; 3] = ["crate", "Self", "self"];
|
||||||
|
@ -69,12 +69,10 @@ pub trait FromQueryResult: Sized {
|
|||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// res,
|
/// res,
|
||||||
/// vec![
|
/// vec![SelectResult {
|
||||||
/// SelectResult {
|
/// name: "Chocolate Forest".to_owned(),
|
||||||
/// name: "Chocolate Forest".to_owned(),
|
/// num_of_cakes: 2,
|
||||||
/// num_of_cakes: 2,
|
/// },]
|
||||||
/// },
|
|
||||||
/// ]
|
|
||||||
/// );
|
/// );
|
||||||
/// #
|
/// #
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
|
@ -126,12 +126,12 @@ macro_rules! try_getable_unsigned {
|
|||||||
( $type: ty ) => {
|
( $type: ty ) => {
|
||||||
impl TryGetable for $type {
|
impl TryGetable for $type {
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
||||||
let column = format!("{}{}", pre, col);
|
let _column = format!("{}{}", pre, col);
|
||||||
match &res.row {
|
match &res.row {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
QueryResultRow::SqlxMySql(row) => {
|
QueryResultRow::SqlxMySql(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<$type>, _>(column.as_str())
|
row.try_get::<Option<$type>, _>(_column.as_str())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null))
|
.and_then(|opt| opt.ok_or(TryGetError::Null))
|
||||||
}
|
}
|
||||||
@ -142,13 +142,13 @@ macro_rules! try_getable_unsigned {
|
|||||||
#[cfg(feature = "sqlx-sqlite")]
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
QueryResultRow::SqlxSqlite(row) => {
|
QueryResultRow::SqlxSqlite(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<$type>, _>(column.as_str())
|
row.try_get::<Option<$type>, _>(_column.as_str())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null))
|
.and_then(|opt| opt.ok_or(TryGetError::Null))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| {
|
QueryResultRow::Mock(row) => row.try_get(_column.as_str()).map_err(|e| {
|
||||||
debug_print!("{:#?}", e.to_string());
|
debug_print!("{:#?}", e.to_string());
|
||||||
TryGetError::Null
|
TryGetError::Null
|
||||||
}),
|
}),
|
||||||
@ -162,12 +162,12 @@ macro_rules! try_getable_mysql {
|
|||||||
( $type: ty ) => {
|
( $type: ty ) => {
|
||||||
impl TryGetable for $type {
|
impl TryGetable for $type {
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
||||||
let column = format!("{}{}", pre, col);
|
let _column = format!("{}{}", pre, col);
|
||||||
match &res.row {
|
match &res.row {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
QueryResultRow::SqlxMySql(row) => {
|
QueryResultRow::SqlxMySql(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<$type>, _>(column.as_str())
|
row.try_get::<Option<$type>, _>(_column.as_str())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null))
|
.and_then(|opt| opt.ok_or(TryGetError::Null))
|
||||||
}
|
}
|
||||||
@ -181,7 +181,7 @@ macro_rules! try_getable_mysql {
|
|||||||
}
|
}
|
||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| {
|
QueryResultRow::Mock(row) => row.try_get(_column.as_str()).map_err(|e| {
|
||||||
debug_print!("{:#?}", e.to_string());
|
debug_print!("{:#?}", e.to_string());
|
||||||
TryGetError::Null
|
TryGetError::Null
|
||||||
}),
|
}),
|
||||||
@ -195,7 +195,7 @@ macro_rules! try_getable_postgres {
|
|||||||
( $type: ty ) => {
|
( $type: ty ) => {
|
||||||
impl TryGetable for $type {
|
impl TryGetable for $type {
|
||||||
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, TryGetError> {
|
||||||
let column = format!("{}{}", pre, col);
|
let _column = format!("{}{}", pre, col);
|
||||||
match &res.row {
|
match &res.row {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
QueryResultRow::SqlxMySql(_) => {
|
QueryResultRow::SqlxMySql(_) => {
|
||||||
@ -204,7 +204,7 @@ macro_rules! try_getable_postgres {
|
|||||||
#[cfg(feature = "sqlx-postgres")]
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
QueryResultRow::SqlxPostgres(row) => {
|
QueryResultRow::SqlxPostgres(row) => {
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
row.try_get::<Option<$type>, _>(column.as_str())
|
row.try_get::<Option<$type>, _>(_column.as_str())
|
||||||
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
.map_err(|e| TryGetError::DbErr(crate::sqlx_error_to_query_err(e)))
|
||||||
.and_then(|opt| opt.ok_or(TryGetError::Null))
|
.and_then(|opt| opt.ok_or(TryGetError::Null))
|
||||||
}
|
}
|
||||||
@ -214,7 +214,7 @@ macro_rules! try_getable_postgres {
|
|||||||
}
|
}
|
||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
QueryResultRow::Mock(row) => row.try_get(column.as_str()).map_err(|e| {
|
QueryResultRow::Mock(row) => row.try_get(_column.as_str()).map_err(|e| {
|
||||||
debug_print!("{:#?}", e.to_string());
|
debug_print!("{:#?}", e.to_string());
|
||||||
TryGetError::Null
|
TryGetError::Null
|
||||||
}),
|
}),
|
||||||
|
@ -211,10 +211,7 @@ where
|
|||||||
/// .all(&db)
|
/// .all(&db)
|
||||||
/// .await?;
|
/// .await?;
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(res, vec![("Chocolate Forest".to_owned(), 2i64)]);
|
||||||
/// res,
|
|
||||||
/// vec![("Chocolate Forest".to_owned(), 2i64)]
|
|
||||||
/// );
|
|
||||||
/// #
|
/// #
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # });
|
/// # });
|
||||||
@ -226,7 +223,9 @@ where
|
|||||||
/// vec![
|
/// vec![
|
||||||
/// r#"SELECT "cake"."name" AS "cake_name", COUNT("cake"."id") AS "num_of_cakes""#,
|
/// r#"SELECT "cake"."name" AS "cake_name", COUNT("cake"."id") AS "num_of_cakes""#,
|
||||||
/// r#"FROM "cake" GROUP BY "cake"."name""#,
|
/// r#"FROM "cake" GROUP BY "cake"."name""#,
|
||||||
/// ].join(" ").as_str(),
|
/// ]
|
||||||
|
/// .join(" ")
|
||||||
|
/// .as_str(),
|
||||||
/// vec![]
|
/// vec![]
|
||||||
/// )]
|
/// )]
|
||||||
/// );
|
/// );
|
||||||
|
@ -8,6 +8,7 @@ mod json;
|
|||||||
mod select;
|
mod select;
|
||||||
mod traits;
|
mod traits;
|
||||||
mod update;
|
mod update;
|
||||||
|
mod util;
|
||||||
|
|
||||||
pub use combine::{SelectA, SelectB};
|
pub use combine::{SelectA, SelectB};
|
||||||
pub use delete::*;
|
pub use delete::*;
|
||||||
@ -19,5 +20,6 @@ pub use json::*;
|
|||||||
pub use select::*;
|
pub use select::*;
|
||||||
pub use traits::*;
|
pub use traits::*;
|
||||||
pub use update::*;
|
pub use update::*;
|
||||||
|
pub use util::*;
|
||||||
|
|
||||||
pub use crate::{ConnectionTrait, InsertResult, Statement, UpdateResult, Value, Values};
|
pub use crate::{ConnectionTrait, InsertResult, Statement, UpdateResult, Value, Values};
|
||||||
|
112
src/query/util.rs
Normal file
112
src/query/util.rs
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
use crate::{database::*, QueryTrait, Statement};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DebugQuery<'a, Q, T> {
|
||||||
|
pub query: &'a Q,
|
||||||
|
pub value: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! debug_query_build {
|
||||||
|
($impl_obj:ty, $db_expr:expr) => {
|
||||||
|
impl<'a, Q> DebugQuery<'a, Q, $impl_obj>
|
||||||
|
where
|
||||||
|
Q: QueryTrait,
|
||||||
|
{
|
||||||
|
pub fn build(&self) -> Statement {
|
||||||
|
let func = $db_expr;
|
||||||
|
let db_backend = func(self);
|
||||||
|
self.query.build(db_backend)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_query_build!(DbBackend, |x: &DebugQuery<_, DbBackend>| x.value);
|
||||||
|
debug_query_build!(&DbBackend, |x: &DebugQuery<_, &DbBackend>| *x.value);
|
||||||
|
debug_query_build!(
|
||||||
|
DatabaseConnection,
|
||||||
|
|x: &DebugQuery<_, DatabaseConnection>| x.value.get_database_backend()
|
||||||
|
);
|
||||||
|
debug_query_build!(
|
||||||
|
&DatabaseConnection,
|
||||||
|
|x: &DebugQuery<_, &DatabaseConnection>| x.value.get_database_backend()
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Helper to get a `Statement` from an object that impl `QueryTrait`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # #[cfg(feature = "mock")]
|
||||||
|
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, DbBackend};
|
||||||
|
/// #
|
||||||
|
/// # let conn = MockDatabase::new(DbBackend::Postgres)
|
||||||
|
/// # .into_connection();
|
||||||
|
/// #
|
||||||
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, debug_query_stmt};
|
||||||
|
///
|
||||||
|
/// let c = cake::Entity::insert(
|
||||||
|
/// cake::ActiveModel {
|
||||||
|
/// id: ActiveValue::set(1),
|
||||||
|
/// name: ActiveValue::set("Apple Pie".to_owned()),
|
||||||
|
/// });
|
||||||
|
///
|
||||||
|
/// let raw_sql = debug_query_stmt!(&c, &conn).to_string();
|
||||||
|
/// assert_eq!(raw_sql, r#"INSERT INTO "cake" ("id", "name") VALUES (1, 'Apple Pie')"#);
|
||||||
|
///
|
||||||
|
/// let raw_sql = debug_query_stmt!(&c, conn).to_string();
|
||||||
|
/// assert_eq!(raw_sql, r#"INSERT INTO "cake" ("id", "name") VALUES (1, 'Apple Pie')"#);
|
||||||
|
///
|
||||||
|
/// let raw_sql = debug_query_stmt!(&c, DbBackend::MySql).to_string();
|
||||||
|
/// assert_eq!(raw_sql, r#"INSERT INTO `cake` (`id`, `name`) VALUES (1, 'Apple Pie')"#);
|
||||||
|
///
|
||||||
|
/// let raw_sql = debug_query_stmt!(&c, &DbBackend::MySql).to_string();
|
||||||
|
/// assert_eq!(raw_sql, r#"INSERT INTO `cake` (`id`, `name`) VALUES (1, 'Apple Pie')"#);
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! debug_query_stmt {
|
||||||
|
($query:expr,$value:expr) => {
|
||||||
|
$crate::DebugQuery {
|
||||||
|
query: $query,
|
||||||
|
value: $value,
|
||||||
|
}
|
||||||
|
.build();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper to get a raw SQL string from an object that impl `QueryTrait`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # #[cfg(feature = "mock")]
|
||||||
|
/// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, DbBackend};
|
||||||
|
/// #
|
||||||
|
/// # let conn = MockDatabase::new(DbBackend::Postgres)
|
||||||
|
/// # .into_connection();
|
||||||
|
/// #
|
||||||
|
/// use sea_orm::{entity::*, query::*, tests_cfg::cake,debug_query};
|
||||||
|
///
|
||||||
|
/// let c = cake::Entity::insert(
|
||||||
|
/// cake::ActiveModel {
|
||||||
|
/// id: ActiveValue::set(1),
|
||||||
|
/// name: ActiveValue::set("Apple Pie".to_owned()),
|
||||||
|
/// });
|
||||||
|
///
|
||||||
|
/// let raw_sql = debug_query!(&c, &conn);
|
||||||
|
/// assert_eq!(raw_sql, r#"INSERT INTO "cake" ("id", "name") VALUES (1, 'Apple Pie')"#);
|
||||||
|
///
|
||||||
|
/// let raw_sql = debug_query!(&c, conn);
|
||||||
|
/// assert_eq!(raw_sql, r#"INSERT INTO "cake" ("id", "name") VALUES (1, 'Apple Pie')"#);
|
||||||
|
///
|
||||||
|
/// let raw_sql = debug_query!(&c, DbBackend::Sqlite);
|
||||||
|
/// assert_eq!(raw_sql, r#"INSERT INTO `cake` (`id`, `name`) VALUES (1, 'Apple Pie')"#);
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! debug_query {
|
||||||
|
($query:expr,$value:expr) => {
|
||||||
|
$crate::debug_query_stmt!($query, $value).to_string();
|
||||||
|
};
|
||||||
|
}
|
@ -7,6 +7,7 @@ pub mod cake_filling_price;
|
|||||||
pub mod entity_linked;
|
pub mod entity_linked;
|
||||||
pub mod filling;
|
pub mod filling;
|
||||||
pub mod fruit;
|
pub mod fruit;
|
||||||
|
pub mod rust_keyword;
|
||||||
pub mod vendor;
|
pub mod vendor;
|
||||||
|
|
||||||
pub use cake::Entity as Cake;
|
pub use cake::Entity as Cake;
|
||||||
@ -15,4 +16,5 @@ pub use cake_filling::Entity as CakeFilling;
|
|||||||
pub use cake_filling_price::Entity as CakeFillingPrice;
|
pub use cake_filling_price::Entity as CakeFillingPrice;
|
||||||
pub use filling::Entity as Filling;
|
pub use filling::Entity as Filling;
|
||||||
pub use fruit::Entity as Fruit;
|
pub use fruit::Entity as Fruit;
|
||||||
|
pub use rust_keyword::Entity as RustKeyword;
|
||||||
pub use vendor::Entity as Vendor;
|
pub use vendor::Entity as Vendor;
|
||||||
|
141
src/tests_cfg/rust_keyword.rs
Normal file
141
src/tests_cfg/rust_keyword.rs
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
use crate as sea_orm;
|
||||||
|
use crate::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
||||||
|
#[sea_orm(table_name = "rust_keyword")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
pub testing: i32,
|
||||||
|
pub rust: i32,
|
||||||
|
pub keywords: i32,
|
||||||
|
pub r#raw_identifier: i32,
|
||||||
|
pub r#as: i32,
|
||||||
|
pub r#async: i32,
|
||||||
|
pub r#await: i32,
|
||||||
|
pub r#break: i32,
|
||||||
|
pub r#const: i32,
|
||||||
|
pub r#continue: i32,
|
||||||
|
pub crate_: i32,
|
||||||
|
pub r#dyn: i32,
|
||||||
|
pub r#else: i32,
|
||||||
|
pub r#enum: i32,
|
||||||
|
pub r#extern: i32,
|
||||||
|
pub r#false: i32,
|
||||||
|
pub r#fn: i32,
|
||||||
|
pub r#for: i32,
|
||||||
|
pub r#if: i32,
|
||||||
|
pub r#impl: i32,
|
||||||
|
pub r#in: i32,
|
||||||
|
pub r#let: i32,
|
||||||
|
pub r#loop: i32,
|
||||||
|
pub r#match: i32,
|
||||||
|
pub r#mod: i32,
|
||||||
|
pub r#move: i32,
|
||||||
|
pub r#mut: i32,
|
||||||
|
pub r#pub: i32,
|
||||||
|
pub r#ref: i32,
|
||||||
|
pub r#return: i32,
|
||||||
|
pub self_: i32,
|
||||||
|
pub r#static: i32,
|
||||||
|
pub r#struct: i32,
|
||||||
|
pub r#trait: i32,
|
||||||
|
pub r#true: i32,
|
||||||
|
pub r#type: i32,
|
||||||
|
pub r#union: i32,
|
||||||
|
pub r#unsafe: i32,
|
||||||
|
pub r#use: i32,
|
||||||
|
pub r#where: i32,
|
||||||
|
pub r#while: i32,
|
||||||
|
pub r#abstract: i32,
|
||||||
|
pub r#become: i32,
|
||||||
|
pub r#box: i32,
|
||||||
|
pub r#do: i32,
|
||||||
|
pub r#final: i32,
|
||||||
|
pub r#macro: i32,
|
||||||
|
pub r#override: i32,
|
||||||
|
pub r#priv: i32,
|
||||||
|
pub r#try: i32,
|
||||||
|
pub r#typeof: i32,
|
||||||
|
pub r#unsized: i32,
|
||||||
|
pub r#virtual: i32,
|
||||||
|
pub r#yield: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||||
|
pub enum Relation {}
|
||||||
|
|
||||||
|
impl RelationTrait for Relation {
|
||||||
|
fn def(&self) -> RelationDef {
|
||||||
|
match self {
|
||||||
|
_ => panic!("No RelationDef"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::tests_cfg::rust_keyword::*;
|
||||||
|
use sea_query::Iden;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_columns() {
|
||||||
|
assert_eq!(Column::Id.to_string().as_str(), "id");
|
||||||
|
assert_eq!(Column::Testing.to_string().as_str(), "testing");
|
||||||
|
assert_eq!(Column::Rust.to_string().as_str(), "rust");
|
||||||
|
assert_eq!(Column::Keywords.to_string().as_str(), "keywords");
|
||||||
|
assert_eq!(Column::RawIdentifier.to_string().as_str(), "raw_identifier");
|
||||||
|
assert_eq!(Column::As.to_string().as_str(), "as");
|
||||||
|
assert_eq!(Column::Async.to_string().as_str(), "async");
|
||||||
|
assert_eq!(Column::Await.to_string().as_str(), "await");
|
||||||
|
assert_eq!(Column::Break.to_string().as_str(), "break");
|
||||||
|
assert_eq!(Column::Const.to_string().as_str(), "const");
|
||||||
|
assert_eq!(Column::Continue.to_string().as_str(), "continue");
|
||||||
|
assert_eq!(Column::Dyn.to_string().as_str(), "dyn");
|
||||||
|
assert_eq!(Column::Crate.to_string().as_str(), "crate");
|
||||||
|
assert_eq!(Column::Else.to_string().as_str(), "else");
|
||||||
|
assert_eq!(Column::Enum.to_string().as_str(), "enum");
|
||||||
|
assert_eq!(Column::Extern.to_string().as_str(), "extern");
|
||||||
|
assert_eq!(Column::False.to_string().as_str(), "false");
|
||||||
|
assert_eq!(Column::Fn.to_string().as_str(), "fn");
|
||||||
|
assert_eq!(Column::For.to_string().as_str(), "for");
|
||||||
|
assert_eq!(Column::If.to_string().as_str(), "if");
|
||||||
|
assert_eq!(Column::Impl.to_string().as_str(), "impl");
|
||||||
|
assert_eq!(Column::In.to_string().as_str(), "in");
|
||||||
|
assert_eq!(Column::Let.to_string().as_str(), "let");
|
||||||
|
assert_eq!(Column::Loop.to_string().as_str(), "loop");
|
||||||
|
assert_eq!(Column::Match.to_string().as_str(), "match");
|
||||||
|
assert_eq!(Column::Mod.to_string().as_str(), "mod");
|
||||||
|
assert_eq!(Column::Move.to_string().as_str(), "move");
|
||||||
|
assert_eq!(Column::Mut.to_string().as_str(), "mut");
|
||||||
|
assert_eq!(Column::Pub.to_string().as_str(), "pub");
|
||||||
|
assert_eq!(Column::Ref.to_string().as_str(), "ref");
|
||||||
|
assert_eq!(Column::Return.to_string().as_str(), "return");
|
||||||
|
assert_eq!(Column::Self_.to_string().as_str(), "self");
|
||||||
|
assert_eq!(Column::Static.to_string().as_str(), "static");
|
||||||
|
assert_eq!(Column::Struct.to_string().as_str(), "struct");
|
||||||
|
assert_eq!(Column::Trait.to_string().as_str(), "trait");
|
||||||
|
assert_eq!(Column::True.to_string().as_str(), "true");
|
||||||
|
assert_eq!(Column::Type.to_string().as_str(), "type");
|
||||||
|
assert_eq!(Column::Union.to_string().as_str(), "union");
|
||||||
|
assert_eq!(Column::Unsafe.to_string().as_str(), "unsafe");
|
||||||
|
assert_eq!(Column::Use.to_string().as_str(), "use");
|
||||||
|
assert_eq!(Column::Where.to_string().as_str(), "where");
|
||||||
|
assert_eq!(Column::While.to_string().as_str(), "while");
|
||||||
|
assert_eq!(Column::Abstract.to_string().as_str(), "abstract");
|
||||||
|
assert_eq!(Column::Become.to_string().as_str(), "become");
|
||||||
|
assert_eq!(Column::Box.to_string().as_str(), "box");
|
||||||
|
assert_eq!(Column::Do.to_string().as_str(), "do");
|
||||||
|
assert_eq!(Column::Final.to_string().as_str(), "final");
|
||||||
|
assert_eq!(Column::Macro.to_string().as_str(), "macro");
|
||||||
|
assert_eq!(Column::Override.to_string().as_str(), "override");
|
||||||
|
assert_eq!(Column::Priv.to_string().as_str(), "priv");
|
||||||
|
assert_eq!(Column::Try.to_string().as_str(), "try");
|
||||||
|
assert_eq!(Column::Typeof.to_string().as_str(), "typeof");
|
||||||
|
assert_eq!(Column::Unsized.to_string().as_str(), "unsized");
|
||||||
|
assert_eq!(Column::Virtual.to_string().as_str(), "virtual");
|
||||||
|
assert_eq!(Column::Yield.to_string().as_str(), "yield");
|
||||||
|
}
|
||||||
|
}
|
@ -10,8 +10,8 @@ pub struct Model {
|
|||||||
pub key: String,
|
pub key: String,
|
||||||
pub value: String,
|
pub value: String,
|
||||||
pub bytes: Vec<u8>,
|
pub bytes: Vec<u8>,
|
||||||
pub date: Date,
|
pub date: Option<Date>,
|
||||||
pub time: Time,
|
pub time: Option<Time>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
@ -289,8 +289,8 @@ pub async fn create_metadata_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
|||||||
.col(ColumnDef::new(metadata::Column::Key).string().not_null())
|
.col(ColumnDef::new(metadata::Column::Key).string().not_null())
|
||||||
.col(ColumnDef::new(metadata::Column::Value).string().not_null())
|
.col(ColumnDef::new(metadata::Column::Value).string().not_null())
|
||||||
.col(ColumnDef::new(metadata::Column::Bytes).binary().not_null())
|
.col(ColumnDef::new(metadata::Column::Bytes).binary().not_null())
|
||||||
.col(ColumnDef::new(metadata::Column::Date).date().not_null())
|
.col(ColumnDef::new(metadata::Column::Date).date())
|
||||||
.col(ColumnDef::new(metadata::Column::Time).time().not_null())
|
.col(ColumnDef::new(metadata::Column::Time).time())
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
create_table(db, &stmt, Metadata).await
|
create_table(db, &stmt, Metadata).await
|
||||||
|
@ -26,8 +26,8 @@ pub async fn crud_in_parallel(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|||||||
key: "markup".to_owned(),
|
key: "markup".to_owned(),
|
||||||
value: "1.18".to_owned(),
|
value: "1.18".to_owned(),
|
||||||
bytes: vec![1, 2, 3],
|
bytes: vec![1, 2, 3],
|
||||||
date: Date::from_ymd(2021, 9, 27),
|
date: Some(Date::from_ymd(2021, 9, 27)),
|
||||||
time: Time::from_hms(11, 32, 55),
|
time: Some(Time::from_hms(11, 32, 55)),
|
||||||
},
|
},
|
||||||
metadata::Model {
|
metadata::Model {
|
||||||
uuid: Uuid::new_v4(),
|
uuid: Uuid::new_v4(),
|
||||||
@ -35,8 +35,8 @@ pub async fn crud_in_parallel(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|||||||
key: "exchange_rate".to_owned(),
|
key: "exchange_rate".to_owned(),
|
||||||
value: "0.78".to_owned(),
|
value: "0.78".to_owned(),
|
||||||
bytes: vec![1, 2, 3],
|
bytes: vec![1, 2, 3],
|
||||||
date: Date::from_ymd(2021, 9, 27),
|
date: Some(Date::from_ymd(2021, 9, 27)),
|
||||||
time: Time::from_hms(11, 32, 55),
|
time: Some(Time::from_hms(11, 32, 55)),
|
||||||
},
|
},
|
||||||
metadata::Model {
|
metadata::Model {
|
||||||
uuid: Uuid::new_v4(),
|
uuid: Uuid::new_v4(),
|
||||||
@ -44,8 +44,8 @@ pub async fn crud_in_parallel(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|||||||
key: "service_charge".to_owned(),
|
key: "service_charge".to_owned(),
|
||||||
value: "1.1".to_owned(),
|
value: "1.1".to_owned(),
|
||||||
bytes: vec![1, 2, 3],
|
bytes: vec![1, 2, 3],
|
||||||
date: Date::from_ymd(2021, 9, 27),
|
date: None,
|
||||||
time: Time::from_hms(11, 32, 55),
|
time: None,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -24,8 +24,8 @@ pub async fn create_metadata(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|||||||
key: "markup".to_owned(),
|
key: "markup".to_owned(),
|
||||||
value: "1.18".to_owned(),
|
value: "1.18".to_owned(),
|
||||||
bytes: vec![1, 2, 3],
|
bytes: vec![1, 2, 3],
|
||||||
date: Date::from_ymd(2021, 9, 27),
|
date: Some(Date::from_ymd(2021, 9, 27)),
|
||||||
time: Time::from_hms(11, 32, 55),
|
time: Some(Time::from_hms(11, 32, 55)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = Metadata::insert(metadata.clone().into_active_model())
|
let res = Metadata::insert(metadata.clone().into_active_model())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user