From b2185af55973315edc853246ee36fcdb9c974159 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Fri, 16 Dec 2022 15:52:00 +0800 Subject: [PATCH 01/18] Cleaning up dependency (#1300) * Dependency version cleanup * Update build tool * Disable default features * [cli] disable default features --- Cargo.toml | 58 +++++++++---------- build-tools/bump-version.sh | 12 ++-- examples/actix3_example/api/Cargo.toml | 4 +- examples/actix3_example/core/Cargo.toml | 2 +- examples/actix3_example/entity/Cargo.toml | 2 +- examples/actix3_example/migration/Cargo.toml | 4 +- examples/actix_example/core/Cargo.toml | 2 +- examples/actix_example/entity/Cargo.toml | 2 +- examples/actix_example/migration/Cargo.toml | 4 +- examples/axum_example/core/Cargo.toml | 2 +- examples/axum_example/entity/Cargo.toml | 2 +- examples/axum_example/migration/Cargo.toml | 4 +- examples/basic/Cargo.toml | 10 ++-- examples/graphql_example/api/Cargo.toml | 4 +- examples/graphql_example/core/Cargo.toml | 2 +- examples/graphql_example/entity/Cargo.toml | 4 +- examples/graphql_example/migration/Cargo.toml | 4 +- examples/jsonrpsee_example/api/Cargo.toml | 2 +- examples/jsonrpsee_example/core/Cargo.toml | 2 +- examples/jsonrpsee_example/entity/Cargo.toml | 2 +- .../jsonrpsee_example/migration/Cargo.toml | 4 +- examples/poem_example/core/Cargo.toml | 2 +- examples/poem_example/entity/Cargo.toml | 2 +- examples/poem_example/migration/Cargo.toml | 4 +- examples/rocket_example/api/Cargo.toml | 8 +-- examples/rocket_example/core/Cargo.toml | 2 +- examples/rocket_example/entity/Cargo.toml | 2 +- examples/rocket_example/migration/Cargo.toml | 4 +- examples/rocket_okapi_example/api/Cargo.toml | 8 +-- examples/rocket_okapi_example/core/Cargo.toml | 2 +- .../rocket_okapi_example/entity/Cargo.toml | 2 +- .../rocket_okapi_example/migration/Cargo.toml | 4 +- examples/salvo_example/core/Cargo.toml | 2 +- examples/salvo_example/entity/Cargo.toml | 2 +- examples/salvo_example/migration/Cargo.toml | 4 +- examples/tonic_example/core/Cargo.toml | 2 +- examples/tonic_example/entity/Cargo.toml | 2 +- examples/tonic_example/migration/Cargo.toml | 4 +- issues/1143/Cargo.toml | 4 +- issues/1278/Cargo.toml | 4 +- issues/262/Cargo.toml | 2 +- issues/319/Cargo.toml | 4 +- issues/630/Cargo.toml | 4 +- sea-orm-cli/Cargo.toml | 22 +++---- sea-orm-cli/src/commands/migrate.rs | 2 +- sea-orm-cli/template/migration/_Cargo.toml | 2 +- sea-orm-codegen/Cargo.toml | 19 +++--- sea-orm-macros/Cargo.toml | 12 ++-- sea-orm-migration/Cargo.toml | 18 +++--- 49 files changed, 138 insertions(+), 143 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1690ef5f..c42e36de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,41 +24,41 @@ name = "sea_orm" path = "src/lib.rs" [dependencies] -async-stream = { version = "^0.3", default-features = false } -async-trait = { version = "^0.1", default-features = false } -chrono = { version = "^0.4.20", default-features = false, optional = true } -time = { version = "^0.3", default-features = false, optional = true } -futures = { version = "^0.3", default-features = false, features = ["std"] } -log = { version = "^0.4", default-features = false } -tracing = { version = "^0.1", default-features = false, features = ["attributes", "log"] } -rust_decimal = { version = "^1", default-features = false, optional = true } -bigdecimal = { version = "^0.3", default-features = false, optional = true } -sea-orm-macros = { version = "^0.10.3", path = "sea-orm-macros", default-features = false, optional = true } -sea-query = { version = "^0.27.2", features = ["thread-safe"] } -sea-query-binder = { version = "^0.2.2", default-features = false, optional = true } -sea-strum = { version = "^0.23", default-features = false, features = ["derive", "sea-orm"] } -serde = { version = "^1.0", default-features = false } -serde_json = { version = "^1.0", default-features = false, optional = true } -sqlx = { version = "^0.6", default-features = false, optional = true } -uuid = { version = "^1", default-features = false, optional = true } +async-stream = { version = "0.3", default-features = false } +async-trait = { version = "0.1", default-features = false } +chrono = { version = "0.4.20", default-features = false, optional = true } +time = { version = "0.3", default-features = false, optional = true } +futures = { version = "0.3", default-features = false, features = ["std"] } +log = { version = "0.4", default-features = false } +tracing = { version = "0.1", default-features = false, features = ["attributes", "log"] } +rust_decimal = { version = "1", default-features = false, optional = true } +bigdecimal = { version = "0.3", default-features = false, optional = true } +sea-orm-macros = { version = "0.10.3", path = "sea-orm-macros", default-features = false, optional = true } +sea-query = { version = "0.27.2", features = ["thread-safe"] } +sea-query-binder = { version = "0.2.2", default-features = false, optional = true } +sea-strum = { version = "0.23", default-features = false, features = ["derive", "sea-orm"] } +serde = { version = "1.0", default-features = false } +serde_json = { version = "1.0", default-features = false, optional = true } +sqlx = { version = "0.6", default-features = false, optional = true } +uuid = { version = "1", default-features = false, optional = true } ouroboros = { version = "0.15", default-features = false } -url = { version = "^2.2", default-features = false } -thiserror = { version = "^1", default-features = false } +url = { version = "2.2", default-features = false } +thiserror = { version = "1", default-features = false } [dev-dependencies] -smol = { version = "^1.2" } -smol-potat = { version = "^1.1" } -async-std = { version = "^1", features = ["attributes", "tokio1"] } -futures = { version = "^0.3" } -tokio = { version = "^1.6", features = ["full"] } +smol = { version = "1.2" } +smol-potat = { version = "1.1" } +async-std = { version = "1", features = ["attributes", "tokio1"] } +futures = { version = "0.3" } +tokio = { version = "1.6", features = ["full"] } actix-rt = { version = "2.2.0" } -maplit = { version = "^1" } -rust_decimal_macros = { version = "^1" } +maplit = { version = "1" } +rust_decimal_macros = { version = "1" } tracing-subscriber = { version = "0.3", features = ["env-filter"] } sea-orm = { path = ".", features = ["mock", "debug-print", "tests-cfg", "postgres-array"] } -pretty_assertions = { version = "^0.7" } -time = { version = "^0.3", features = ["macros"] } -uuid = { version = "^1", features = ["v4"] } +pretty_assertions = { version = "0.7" } +time = { version = "0.3", features = ["macros"] } +uuid = { version = "1", features = ["v4"] } once_cell = "1.8" [features] diff --git a/build-tools/bump-version.sh b/build-tools/bump-version.sh index 5e1296fe..9436e90d 100644 --- a/build-tools/bump-version.sh +++ b/build-tools/bump-version.sh @@ -11,7 +11,7 @@ sleep 1 # Bump `sea-orm-cli` version cd sea-orm-cli sed -i 's/^version.*$/version = "'$1'"/' Cargo.toml -sed -i 's/^sea-orm-codegen [^,]*,/sea-orm-codegen = { version = "\^'$1'",/' Cargo.toml +sed -i 's/^sea-orm-codegen [^,]*,/sea-orm-codegen = { version = "'$1'",/' Cargo.toml git commit -am "sea-orm-cli $1" cd .. sleep 1 @@ -23,21 +23,21 @@ git commit -am "sea-orm-macros $1" cd .. sleep 1 sed -i 's/^version.*$/version = "'$1'"/' Cargo.toml -sed -i 's/^sea-orm-macros [^,]*,/sea-orm-macros = { version = "\^'$1'",/' Cargo.toml +sed -i 's/^sea-orm-macros [^,]*,/sea-orm-macros = { version = "'$1'",/' Cargo.toml git commit -am "$1" # publish sea-orm sleep 1 # Bump `sea-orm-migration` version cd sea-orm-migration sed -i 's/^version.*$/version = "'$1'"/' Cargo.toml -sed -i 's/^sea-orm-cli [^,]*,/sea-orm-cli = { version = "\^'$1'",/' Cargo.toml -sed -i 's/^sea-orm [^,]*,/sea-orm = { version = "\^'$1'",/' Cargo.toml +sed -i 's/^sea-orm-cli [^,]*,/sea-orm-cli = { version = "'$1'",/' Cargo.toml +sed -i 's/^sea-orm [^,]*,/sea-orm = { version = "'$1'",/' Cargo.toml git commit -am "sea-orm-migration $1" cd .. sleep 1 # Bump examples' dependency version cd examples -find . -depth -type f -name '*.toml' -exec sed -i 's/^version = "\^.*" # sea-orm version$/version = "\^'$1'" # sea-orm version/' {} \; -find . -depth -type f -name '*.toml' -exec sed -i 's/^version = "\^.*" # sea-orm-migration version$/version = "\^'$1'" # sea-orm-migration version/' {} \; +find . -depth -type f -name '*.toml' -exec sed -i 's/^version = ".*" # sea-orm version$/version = "'$1'" # sea-orm version/' {} \; +find . -depth -type f -name '*.toml' -exec sed -i 's/^version = ".*" # sea-orm-migration version$/version = "'$1'" # sea-orm-migration version/' {} \; git commit -am "update examples" \ No newline at end of file diff --git a/examples/actix3_example/api/Cargo.toml b/examples/actix3_example/api/Cargo.toml index 16160b49..fa61d230 100644 --- a/examples/actix3_example/api/Cargo.toml +++ b/examples/actix3_example/api/Cargo.toml @@ -11,8 +11,8 @@ actix-http = "2" actix-web = "3" actix-flash = "0.2" actix-files = "0.5" -futures = { version = "^0.3" } -futures-util = { version = "^0.3" } +futures = { version = "0.3" } +futures-util = { version = "0.3" } tera = "1.8.0" dotenvy = "0.15" listenfd = "0.3.3" diff --git a/examples/actix3_example/core/Cargo.toml b/examples/actix3_example/core/Cargo.toml index a64156f4..a23c5735 100644 --- a/examples/actix3_example/core/Cargo.toml +++ b/examples/actix3_example/core/Cargo.toml @@ -10,7 +10,7 @@ entity = { path = "../entity" } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version features = [ "debug-print", "runtime-async-std-native-tls", diff --git a/examples/actix3_example/entity/Cargo.toml b/examples/actix3_example/entity/Cargo.toml index 95913392..d7f3caec 100644 --- a/examples/actix3_example/entity/Cargo.toml +++ b/examples/actix3_example/entity/Cargo.toml @@ -13,4 +13,4 @@ serde = { version = "1", features = ["derive"] } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version diff --git a/examples/actix3_example/migration/Cargo.toml b/examples/actix3_example/migration/Cargo.toml index 5225de98..f8154785 100644 --- a/examples/actix3_example/migration/Cargo.toml +++ b/examples/actix3_example/migration/Cargo.toml @@ -9,11 +9,11 @@ name = "migration" path = "src/lib.rs" [dependencies] -async-std = { version = "^1", features = ["attributes", "tokio1"] } +async-std = { version = "1", features = ["attributes", "tokio1"] } [dependencies.sea-orm-migration] path = "../../../sea-orm-migration" # remove this line in your own project -version = "^0.10.3" # sea-orm-migration version +version = "0.10.3" # sea-orm-migration version features = [ # Enable following runtime and db backend features if you want to run migration via CLI # "runtime-async-std-native-tls", diff --git a/examples/actix_example/core/Cargo.toml b/examples/actix_example/core/Cargo.toml index abf5f22f..abee7f61 100644 --- a/examples/actix_example/core/Cargo.toml +++ b/examples/actix_example/core/Cargo.toml @@ -10,7 +10,7 @@ entity = { path = "../entity" } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version features = [ "debug-print", "runtime-async-std-native-tls", diff --git a/examples/actix_example/entity/Cargo.toml b/examples/actix_example/entity/Cargo.toml index 95913392..d7f3caec 100644 --- a/examples/actix_example/entity/Cargo.toml +++ b/examples/actix_example/entity/Cargo.toml @@ -13,4 +13,4 @@ serde = { version = "1", features = ["derive"] } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version diff --git a/examples/actix_example/migration/Cargo.toml b/examples/actix_example/migration/Cargo.toml index cff51ed5..84c70ff9 100644 --- a/examples/actix_example/migration/Cargo.toml +++ b/examples/actix_example/migration/Cargo.toml @@ -9,11 +9,11 @@ name = "migration" path = "src/lib.rs" [dependencies] -async-std = { version = "^1", features = ["attributes", "tokio1"] } +async-std = { version = "1", features = ["attributes", "tokio1"] } [dependencies.sea-orm-migration] path = "../../../sea-orm-migration" # remove this line in your own project -version = "^0.10.3" # sea-orm-migration version +version = "0.10.3" # sea-orm-migration version features = [ # Enable following runtime and db backend features if you want to run migration via CLI # "runtime-actix-native-tls", diff --git a/examples/axum_example/core/Cargo.toml b/examples/axum_example/core/Cargo.toml index ce086d64..b36b312f 100644 --- a/examples/axum_example/core/Cargo.toml +++ b/examples/axum_example/core/Cargo.toml @@ -10,7 +10,7 @@ entity = { path = "../entity" } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version features = [ "debug-print", "runtime-async-std-native-tls", diff --git a/examples/axum_example/entity/Cargo.toml b/examples/axum_example/entity/Cargo.toml index 95913392..d7f3caec 100644 --- a/examples/axum_example/entity/Cargo.toml +++ b/examples/axum_example/entity/Cargo.toml @@ -13,4 +13,4 @@ serde = { version = "1", features = ["derive"] } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version diff --git a/examples/axum_example/migration/Cargo.toml b/examples/axum_example/migration/Cargo.toml index fba8ba56..e5cc3d92 100644 --- a/examples/axum_example/migration/Cargo.toml +++ b/examples/axum_example/migration/Cargo.toml @@ -9,11 +9,11 @@ name = "migration" path = "src/lib.rs" [dependencies] -async-std = { version = "^1", features = ["attributes", "tokio1"] } +async-std = { version = "1", features = ["attributes", "tokio1"] } [dependencies.sea-orm-migration] path = "../../../sea-orm-migration" # remove this line in your own project -version = "^0.10.3" # sea-orm-migration version +version = "0.10.3" # sea-orm-migration version features = [ # Enable following runtime and db backend features if you want to run migration via CLI # "runtime-tokio-native-tls", diff --git a/examples/basic/Cargo.toml b/examples/basic/Cargo.toml index 9c53df39..4c36d6cc 100644 --- a/examples/basic/Cargo.toml +++ b/examples/basic/Cargo.toml @@ -8,9 +8,9 @@ edition = "2021" publish = false [dependencies] -async-std = { version = "^1.9", features = [ "attributes", "tokio1" ] } +async-std = { version = "1.9", features = [ "attributes", "tokio1" ] } sea-orm = { path = "../../", features = [ "sqlx-all", "runtime-async-std-native-tls" ] } -serde_json = { version = "^1" } -futures = { version = "^0.3" } -async-stream = { version = "^0.3" } -futures-util = { version = "^0.3" } +serde_json = { version = "1" } +futures = { version = "0.3" } +async-stream = { version = "0.3" } +futures-util = { version = "0.3" } diff --git a/examples/graphql_example/api/Cargo.toml b/examples/graphql_example/api/Cargo.toml index a4fd78f4..aecf0466 100644 --- a/examples/graphql_example/api/Cargo.toml +++ b/examples/graphql_example/api/Cargo.toml @@ -8,8 +8,8 @@ publish = false [dependencies] graphql-example-core = { path = "../core" } tokio = { version = "1.0", features = ["full"] } -axum = "^0.5.1" +axum = "0.5.1" dotenvy = "0.15.0" -async-graphql-axum = "^4.0.6" +async-graphql-axum = "4.0.6" entity = { path = "../entity" } migration = { path = "../migration" } diff --git a/examples/graphql_example/core/Cargo.toml b/examples/graphql_example/core/Cargo.toml index 33293225..dad73749 100644 --- a/examples/graphql_example/core/Cargo.toml +++ b/examples/graphql_example/core/Cargo.toml @@ -10,7 +10,7 @@ entity = { path = "../entity" } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version features = [ "debug-print", "runtime-async-std-native-tls", diff --git a/examples/graphql_example/entity/Cargo.toml b/examples/graphql_example/entity/Cargo.toml index f041d507..58cf7b86 100644 --- a/examples/graphql_example/entity/Cargo.toml +++ b/examples/graphql_example/entity/Cargo.toml @@ -12,8 +12,8 @@ path = "src/lib.rs" serde = { version = "1", features = ["derive"] } [dependencies.async-graphql] -version = "^4.0.6" +version = "4.0.6" [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version diff --git a/examples/graphql_example/migration/Cargo.toml b/examples/graphql_example/migration/Cargo.toml index 2b12363a..b5214319 100644 --- a/examples/graphql_example/migration/Cargo.toml +++ b/examples/graphql_example/migration/Cargo.toml @@ -10,11 +10,11 @@ path = "src/lib.rs" [dependencies] dotenvy = "0.15.0" -async-std = { version = "^1", features = ["attributes", "tokio1"] } +async-std = { version = "1", features = ["attributes", "tokio1"] } [dependencies.sea-orm-migration] path = "../../../sea-orm-migration" # remove this line in your own project -version = "^0.10.3" # sea-orm-migration version +version = "0.10.3" # sea-orm-migration version features = [ # Enable following runtime and db backend features if you want to run migration via CLI # "runtime-tokio-native-tls", diff --git a/examples/jsonrpsee_example/api/Cargo.toml b/examples/jsonrpsee_example/api/Cargo.toml index 7f84ecd3..9e98a03c 100644 --- a/examples/jsonrpsee_example/api/Cargo.toml +++ b/examples/jsonrpsee_example/api/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] jsonrpsee-example-core = { path = "../core" } -jsonrpsee = { version = "^0.8.0", features = ["full"] } +jsonrpsee = { version = "0.8.0", features = ["full"] } jsonrpsee-core = "0.9.0" tokio = { version = "1.8.0", features = ["full"] } serde = { version = "1", features = ["derive"] } diff --git a/examples/jsonrpsee_example/core/Cargo.toml b/examples/jsonrpsee_example/core/Cargo.toml index 23aeec82..023152c1 100644 --- a/examples/jsonrpsee_example/core/Cargo.toml +++ b/examples/jsonrpsee_example/core/Cargo.toml @@ -10,7 +10,7 @@ entity = { path = "../entity" } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version features = [ "debug-print", "runtime-tokio-native-tls", diff --git a/examples/jsonrpsee_example/entity/Cargo.toml b/examples/jsonrpsee_example/entity/Cargo.toml index 95913392..d7f3caec 100644 --- a/examples/jsonrpsee_example/entity/Cargo.toml +++ b/examples/jsonrpsee_example/entity/Cargo.toml @@ -13,4 +13,4 @@ serde = { version = "1", features = ["derive"] } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version diff --git a/examples/jsonrpsee_example/migration/Cargo.toml b/examples/jsonrpsee_example/migration/Cargo.toml index 6c0d82a0..246cf688 100644 --- a/examples/jsonrpsee_example/migration/Cargo.toml +++ b/examples/jsonrpsee_example/migration/Cargo.toml @@ -9,11 +9,11 @@ name = "migration" path = "src/lib.rs" [dependencies] -async-std = { version = "^1", features = ["attributes", "tokio1"] } +async-std = { version = "1", features = ["attributes", "tokio1"] } [dependencies.sea-orm-migration] path = "../../../sea-orm-migration" # remove this line in your own project -version = "^0.10.3" # sea-orm-migration version +version = "0.10.3" # sea-orm-migration version features = [ # Enable following runtime and db backend features if you want to run migration via CLI # "runtime-tokio-native-tls", diff --git a/examples/poem_example/core/Cargo.toml b/examples/poem_example/core/Cargo.toml index cacdfcb6..85691245 100644 --- a/examples/poem_example/core/Cargo.toml +++ b/examples/poem_example/core/Cargo.toml @@ -10,7 +10,7 @@ entity = { path = "../entity" } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version features = [ "debug-print", "runtime-async-std-native-tls", diff --git a/examples/poem_example/entity/Cargo.toml b/examples/poem_example/entity/Cargo.toml index 95913392..d7f3caec 100644 --- a/examples/poem_example/entity/Cargo.toml +++ b/examples/poem_example/entity/Cargo.toml @@ -13,4 +13,4 @@ serde = { version = "1", features = ["derive"] } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version diff --git a/examples/poem_example/migration/Cargo.toml b/examples/poem_example/migration/Cargo.toml index 6c0d82a0..246cf688 100644 --- a/examples/poem_example/migration/Cargo.toml +++ b/examples/poem_example/migration/Cargo.toml @@ -9,11 +9,11 @@ name = "migration" path = "src/lib.rs" [dependencies] -async-std = { version = "^1", features = ["attributes", "tokio1"] } +async-std = { version = "1", features = ["attributes", "tokio1"] } [dependencies.sea-orm-migration] path = "../../../sea-orm-migration" # remove this line in your own project -version = "^0.10.3" # sea-orm-migration version +version = "0.10.3" # sea-orm-migration version features = [ # Enable following runtime and db backend features if you want to run migration via CLI # "runtime-tokio-native-tls", diff --git a/examples/rocket_example/api/Cargo.toml b/examples/rocket_example/api/Cargo.toml index 2ce9ab89..4361c460 100644 --- a/examples/rocket_example/api/Cargo.toml +++ b/examples/rocket_example/api/Cargo.toml @@ -6,18 +6,18 @@ edition = "2021" publish = false [dependencies] -async-stream = { version = "^0.3" } +async-stream = { version = "0.3" } async-trait = { version = "0.1" } rocket-example-core = { path = "../core" } -futures = { version = "^0.3" } -futures-util = { version = "^0.3" } +futures = { version = "0.3" } +futures-util = { version = "0.3" } rocket = { version = "0.5.0-rc.1", features = [ "json", ] } rocket_dyn_templates = { version = "0.1.0-rc.1", features = [ "tera", ] } -serde_json = { version = "^1" } +serde_json = { version = "1" } entity = { path = "../entity" } migration = { path = "../migration" } tokio = "1.20.0" diff --git a/examples/rocket_example/core/Cargo.toml b/examples/rocket_example/core/Cargo.toml index ac255632..18740ac3 100644 --- a/examples/rocket_example/core/Cargo.toml +++ b/examples/rocket_example/core/Cargo.toml @@ -10,7 +10,7 @@ entity = { path = "../entity" } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version features = [ "runtime-tokio-native-tls", "sqlx-postgres", diff --git a/examples/rocket_example/entity/Cargo.toml b/examples/rocket_example/entity/Cargo.toml index aefe0beb..3cdacb0d 100644 --- a/examples/rocket_example/entity/Cargo.toml +++ b/examples/rocket_example/entity/Cargo.toml @@ -15,4 +15,4 @@ rocket = { version = "0.5.0-rc.1", features = [ [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version diff --git a/examples/rocket_example/migration/Cargo.toml b/examples/rocket_example/migration/Cargo.toml index 2485d3c8..e195d535 100644 --- a/examples/rocket_example/migration/Cargo.toml +++ b/examples/rocket_example/migration/Cargo.toml @@ -10,11 +10,11 @@ path = "src/lib.rs" [dependencies] rocket = { version = "0.5.0-rc.1" } -async-std = { version = "^1", features = ["attributes", "tokio1"] } +async-std = { version = "1", features = ["attributes", "tokio1"] } [dependencies.sea-orm-migration] path = "../../../sea-orm-migration" # remove this line in your own project -version = "^0.10.3" # sea-orm-migration version +version = "0.10.3" # sea-orm-migration version features = [ # Enable following runtime and db backend features if you want to run migration via CLI # "runtime-tokio-native-tls", diff --git a/examples/rocket_okapi_example/api/Cargo.toml b/examples/rocket_okapi_example/api/Cargo.toml index 00ecdbaf..f2e78e17 100644 --- a/examples/rocket_okapi_example/api/Cargo.toml +++ b/examples/rocket_okapi_example/api/Cargo.toml @@ -6,18 +6,18 @@ edition = "2021" publish = false [dependencies] -async-stream = { version = "^0.3" } +async-stream = { version = "0.3" } async-trait = { version = "0.1" } rocket-example-core = { path = "../core" } -futures = { version = "^0.3" } -futures-util = { version = "^0.3" } +futures = { version = "0.3" } +futures-util = { version = "0.3" } rocket = { version = "0.5.0-rc.1", features = [ "json", ] } rocket_dyn_templates = { version = "0.1.0-rc.1", features = [ "tera", ] } -serde_json = { version = "^1" } +serde_json = { version = "1" } entity = { path = "../entity" } migration = { path = "../migration" } tokio = "1.20.0" diff --git a/examples/rocket_okapi_example/core/Cargo.toml b/examples/rocket_okapi_example/core/Cargo.toml index ac255632..18740ac3 100644 --- a/examples/rocket_okapi_example/core/Cargo.toml +++ b/examples/rocket_okapi_example/core/Cargo.toml @@ -10,7 +10,7 @@ entity = { path = "../entity" } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version features = [ "runtime-tokio-native-tls", "sqlx-postgres", diff --git a/examples/rocket_okapi_example/entity/Cargo.toml b/examples/rocket_okapi_example/entity/Cargo.toml index 42e3ed77..cea785eb 100644 --- a/examples/rocket_okapi_example/entity/Cargo.toml +++ b/examples/rocket_okapi_example/entity/Cargo.toml @@ -15,7 +15,7 @@ rocket = { version = "0.5.0-rc.1", features = [ [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version [dependencies.rocket_okapi] version = "0.8.0-rc.2" diff --git a/examples/rocket_okapi_example/migration/Cargo.toml b/examples/rocket_okapi_example/migration/Cargo.toml index 2485d3c8..e195d535 100644 --- a/examples/rocket_okapi_example/migration/Cargo.toml +++ b/examples/rocket_okapi_example/migration/Cargo.toml @@ -10,11 +10,11 @@ path = "src/lib.rs" [dependencies] rocket = { version = "0.5.0-rc.1" } -async-std = { version = "^1", features = ["attributes", "tokio1"] } +async-std = { version = "1", features = ["attributes", "tokio1"] } [dependencies.sea-orm-migration] path = "../../../sea-orm-migration" # remove this line in your own project -version = "^0.10.3" # sea-orm-migration version +version = "0.10.3" # sea-orm-migration version features = [ # Enable following runtime and db backend features if you want to run migration via CLI # "runtime-tokio-native-tls", diff --git a/examples/salvo_example/core/Cargo.toml b/examples/salvo_example/core/Cargo.toml index 6b70b51a..19ed3fa1 100644 --- a/examples/salvo_example/core/Cargo.toml +++ b/examples/salvo_example/core/Cargo.toml @@ -10,7 +10,7 @@ entity = { path = "../entity" } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version features = [ "debug-print", "runtime-tokio-native-tls", diff --git a/examples/salvo_example/entity/Cargo.toml b/examples/salvo_example/entity/Cargo.toml index 95913392..d7f3caec 100644 --- a/examples/salvo_example/entity/Cargo.toml +++ b/examples/salvo_example/entity/Cargo.toml @@ -13,4 +13,4 @@ serde = { version = "1", features = ["derive"] } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version diff --git a/examples/salvo_example/migration/Cargo.toml b/examples/salvo_example/migration/Cargo.toml index 6c0d82a0..246cf688 100644 --- a/examples/salvo_example/migration/Cargo.toml +++ b/examples/salvo_example/migration/Cargo.toml @@ -9,11 +9,11 @@ name = "migration" path = "src/lib.rs" [dependencies] -async-std = { version = "^1", features = ["attributes", "tokio1"] } +async-std = { version = "1", features = ["attributes", "tokio1"] } [dependencies.sea-orm-migration] path = "../../../sea-orm-migration" # remove this line in your own project -version = "^0.10.3" # sea-orm-migration version +version = "0.10.3" # sea-orm-migration version features = [ # Enable following runtime and db backend features if you want to run migration via CLI # "runtime-tokio-native-tls", diff --git a/examples/tonic_example/core/Cargo.toml b/examples/tonic_example/core/Cargo.toml index a502e2a5..553921f9 100644 --- a/examples/tonic_example/core/Cargo.toml +++ b/examples/tonic_example/core/Cargo.toml @@ -10,7 +10,7 @@ entity = { path = "../entity" } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version features = [ "debug-print", "runtime-tokio-rustls", diff --git a/examples/tonic_example/entity/Cargo.toml b/examples/tonic_example/entity/Cargo.toml index 95913392..d7f3caec 100644 --- a/examples/tonic_example/entity/Cargo.toml +++ b/examples/tonic_example/entity/Cargo.toml @@ -13,4 +13,4 @@ serde = { version = "1", features = ["derive"] } [dependencies.sea-orm] path = "../../../" # remove this line in your own project -version = "^0.10.3" # sea-orm version +version = "0.10.3" # sea-orm version diff --git a/examples/tonic_example/migration/Cargo.toml b/examples/tonic_example/migration/Cargo.toml index e2f7eb90..50658028 100644 --- a/examples/tonic_example/migration/Cargo.toml +++ b/examples/tonic_example/migration/Cargo.toml @@ -9,11 +9,11 @@ name = "migration" path = "src/lib.rs" [dependencies] -async-std = { version = "^1", features = ["attributes", "tokio1"] } +async-std = { version = "1", features = ["attributes", "tokio1"] } [dependencies.sea-orm-migration] path = "../../../sea-orm-migration" # remove this line in your own project -version = "^0.10.3" # sea-orm-migration version +version = "0.10.3" # sea-orm-migration version features = [ # Enable following runtime and db backend features if you want to run migration via CLI # "runtime-tokio-rustls", diff --git a/issues/1143/Cargo.toml b/issues/1143/Cargo.toml index 6dae314c..a2583faa 100644 --- a/issues/1143/Cargo.toml +++ b/issues/1143/Cargo.toml @@ -8,8 +8,8 @@ edition = "2021" publish = false [dependencies] -serde = "^1" -tokio = { version = "^1", features = ["rt", "rt-multi-thread", "macros"] } +serde = "1" +tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] } [dependencies.sea-orm] path = "../../" diff --git a/issues/1278/Cargo.toml b/issues/1278/Cargo.toml index 7be6742e..f9be346b 100644 --- a/issues/1278/Cargo.toml +++ b/issues/1278/Cargo.toml @@ -8,8 +8,8 @@ edition = "2021" publish = false [dependencies] -serde = "^1" -tokio = { version = "^1", features = ["rt", "rt-multi-thread", "macros"] } +serde = "1" +tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] } [dependencies.sea-orm] path = "../../" diff --git a/issues/262/Cargo.toml b/issues/262/Cargo.toml index b397fb8a..6c9ce4e5 100644 --- a/issues/262/Cargo.toml +++ b/issues/262/Cargo.toml @@ -9,4 +9,4 @@ publish = false [dependencies] sea-orm = { path = "../../", features = [ "sqlx-all", "runtime-async-std-native-tls", "debug-print" ] } -async-std = { version = "^1", features = ["attributes", "tokio1"] } +async-std = { version = "1", features = ["attributes", "tokio1"] } diff --git a/issues/319/Cargo.toml b/issues/319/Cargo.toml index a60859a4..2269214d 100644 --- a/issues/319/Cargo.toml +++ b/issues/319/Cargo.toml @@ -8,8 +8,8 @@ edition = "2021" publish = false [dependencies] -async-std = { version = "^1", features = ["attributes", "tokio1"] } -serde = { version = "^1", features = ["derive"] } +async-std = { version = "1", features = ["attributes", "tokio1"] } +serde = { version = "1", features = ["derive"] } sea-orm = { path = "../../", features = [ "sqlx-mysql", "runtime-async-std-native-tls", diff --git a/issues/630/Cargo.toml b/issues/630/Cargo.toml index 00409cb5..5d9dc1da 100644 --- a/issues/630/Cargo.toml +++ b/issues/630/Cargo.toml @@ -9,8 +9,8 @@ edition = "2021" publish = false [dependencies] -serde = "^1" -tokio = { version = "^1", features = ["rt", "rt-multi-thread", "macros"] } +serde = "1" +tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] } [dependencies.sea-orm] path = "../../" diff --git a/sea-orm-cli/Cargo.toml b/sea-orm-cli/Cargo.toml index bac45ef8..b734eee2 100644 --- a/sea-orm-cli/Cargo.toml +++ b/sea-orm-cli/Cargo.toml @@ -31,17 +31,17 @@ path = "src/bin/sea.rs" required-features = ["cli", "codegen"] [dependencies] -clap = { version = "^3.2", features = ["env", "derive"], optional = true } -dotenvy = { version = "^0.15", optional = true } -async-std = { version = "^1.9", features = ["attributes", "tokio1"], optional = true } -sea-orm-codegen = { version = "^0.10.3", path = "../sea-orm-codegen", optional = true } -sea-schema = { version = "^0.10.2" } -sqlx = { version = "^0.6", default-features = false, features = ["mysql", "postgres"], optional = true } -tracing-subscriber = { version = "0.3", features = ["env-filter"] } -tracing = { version = "0.1" } -url = "^2.2" -chrono = { version = "^0.4.20", default-features = false, features = ["clock"] } -regex = "1" +clap = { version = "3.2", default-features = false, features = ["std", "env", "derive"], optional = true } +dotenvy = { version = "0.15", default-features = false, optional = true } +async-std = { version = "1.9", default-features = false, features = ["attributes", "tokio1"], optional = true } +sea-orm-codegen = { version = "0.10.3", path = "../sea-orm-codegen", default-features = false, optional = true } +sea-schema = { version = "0.10.2" } +sqlx = { version = "0.6", default-features = false, features = ["mysql", "postgres"], optional = true } +tracing-subscriber = { version = "0.3", default-features = false, features = ["env-filter", "fmt"] } +tracing = { version = "0.1", default-features = false } +url = { version = "2.2", default-features = false } +chrono = { version = "0.4.20", default-features = false, features = ["clock"] } +regex = { version = "1", default-features = false } [dev-dependencies] smol = "1.2.5" diff --git a/sea-orm-cli/src/commands/migrate.rs b/sea-orm-cli/src/commands/migrate.rs index 8931ea5b..c7fbaea5 100644 --- a/sea-orm-cli/src/commands/migrate.rs +++ b/sea-orm-cli/src/commands/migrate.rs @@ -101,7 +101,7 @@ pub fn run_migrate_init(migration_dir: &str) -> Result<(), Box> { write_file!("src/main.rs"); write_file!("Cargo.toml", "_Cargo.toml", |content: String| { let ver = format!( - "^{}.{}.0", + "{}.{}.0", env!("CARGO_PKG_VERSION_MAJOR"), env!("CARGO_PKG_VERSION_MINOR") ); diff --git a/sea-orm-cli/template/migration/_Cargo.toml b/sea-orm-cli/template/migration/_Cargo.toml index 03cb031e..2c674f23 100644 --- a/sea-orm-cli/template/migration/_Cargo.toml +++ b/sea-orm-cli/template/migration/_Cargo.toml @@ -9,7 +9,7 @@ name = "migration" path = "src/lib.rs" [dependencies] -async-std = { version = "^1", features = ["attributes", "tokio1"] } +async-std = { version = "1", features = ["attributes", "tokio1"] } [dependencies.sea-orm-migration] version = "" diff --git a/sea-orm-codegen/Cargo.toml b/sea-orm-codegen/Cargo.toml index 3bba86e0..0601dfbc 100644 --- a/sea-orm-codegen/Cargo.toml +++ b/sea-orm-codegen/Cargo.toml @@ -17,17 +17,12 @@ name = "sea_orm_codegen" path = "src/lib.rs" [dependencies] -sea-query = { version = "^0.27.1", features = ["thread-safe"] } -syn = { version = "^1", default-features = false, features = [ - "derive", - "parsing", - "proc-macro", - "printing", -] } -quote = "^1" -heck = "^0.3" -proc-macro2 = "^1" -tracing = { version = "0.1", features = ["log"] } +sea-query = { version = "0.27.1", default-features = false, features = ["thread-safe"] } +syn = { version = "1", default-features = false } +quote = { version = "1", default-features = false } +heck = { version = "0.3", default-features = false } +proc-macro2 = { version = "1", default-features = false } +tracing = { version = "0.1", default-features = false, features = ["log"] } [dev-dependencies] -pretty_assertions = { version = "^0.7" } +pretty_assertions = { version = "0.7" } diff --git a/sea-orm-macros/Cargo.toml b/sea-orm-macros/Cargo.toml index 05ccc7e8..adaefe21 100644 --- a/sea-orm-macros/Cargo.toml +++ b/sea-orm-macros/Cargo.toml @@ -18,15 +18,15 @@ path = "src/lib.rs" proc-macro = true [dependencies] -bae = "^0.1" -syn = { version = "^1", default-features = false, features = [ "full", "derive", "clone-impls", "parsing", "proc-macro", "printing", "extra-traits" ] } -quote = "^1" -heck = "^0.3" -proc-macro2 = "^1" +bae = { version = "0.1", default-features = false } +syn = { version = "1", default-features = false } +quote = { version = "1", default-features = false } +heck = { version = "0.3", default-features = false } +proc-macro2 = { version = "1", default-features = false } [dev-dependencies] sea-orm = { path = "../", features = ["macros"] } -serde = { version = "^1.0", features = ["derive"] } +serde = { version = "1.0", features = ["derive"] } [features] postgres-array = [] diff --git a/sea-orm-migration/Cargo.toml b/sea-orm-migration/Cargo.toml index 72bd37cf..d1d96082 100644 --- a/sea-orm-migration/Cargo.toml +++ b/sea-orm-migration/Cargo.toml @@ -20,17 +20,17 @@ name = "sea_orm_migration" path = "src/lib.rs" [dependencies] -async-trait = { version = "^0.1" } -clap = { version = "^3.2", features = ["env", "derive"], optional = true } -dotenvy = { version = "^0.15", optional = true } -sea-orm = { version = "^0.10.3", path = "../", default-features = false, features = ["macros"] } -sea-orm-cli = { version = "^0.10.3", path = "../sea-orm-cli", default-features = false, optional = true } -sea-schema = { version = "^0.10.2" } -tracing = { version = "0.1", features = ["log"] } -tracing-subscriber = { version = "0.3", features = ["env-filter"] } +async-trait = { version = "0.1", default-features = false } +clap = { version = "3.2", default-features = false, features = ["std", "env", "derive"], optional = true } +dotenvy = { version = "0.15", default-features = false, optional = true } +sea-orm = { version = "0.10.3", path = "../", default-features = false, features = ["macros"] } +sea-orm-cli = { version = "0.10.3", path = "../sea-orm-cli", default-features = false, optional = true } +sea-schema = { version = "0.10.2" } +tracing = { version = "0.1", default-features = false, features = ["log"] } +tracing-subscriber = { version = "0.3", default-features = false, features = ["env-filter", "fmt"] } [dev-dependencies] -async-std = { version = "^1", features = ["attributes", "tokio1"] } +async-std = { version = "1", features = ["attributes", "tokio1"] } [features] default = ["cli"] From 596afd208132c1b48149e8b67fdf7229d58b82b3 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Fri, 16 Dec 2022 15:53:58 +0800 Subject: [PATCH 02/18] CHANGELOG --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eed3f853..e7675575 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### House Keeping -* Remove dependency when not needed https://github.com/SeaQL/sea-orm/pull/1213 +* Removed dependency when not needed https://github.com/SeaQL/sea-orm/pull/1213 +* Changed all version = "^x.y.z" into version = "x.y.z" and disabled default features and enable only the needed ones https://github.com/SeaQL/sea-orm/pull/1300 ### Bug Fixes From ccca35ab1a53d08697b4c7dc891c98df58d54f9e Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Fri, 16 Dec 2022 16:48:16 +0800 Subject: [PATCH 03/18] clippy --- sea-orm-codegen/src/entity/transformer.rs | 4 ++-- sea-orm-codegen/src/entity/writer.rs | 4 ++-- src/executor/paginator.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sea-orm-codegen/src/entity/transformer.rs b/sea-orm-codegen/src/entity/transformer.rs index 282d0393..31a4c2a1 100644 --- a/sea-orm-codegen/src/entity/transformer.rs +++ b/sea-orm-codegen/src/entity/transformer.rs @@ -202,8 +202,8 @@ impl EntityTransformer { } Ok(EntityWriter { entities: entities - .into_iter() - .map(|(_, mut v)| { + .into_values() + .map(|mut v| { v.relations.sort_by(|a, b| a.ref_table.cmp(&b.ref_table)); v }) diff --git a/sea-orm-codegen/src/entity/writer.rs b/sea-orm-codegen/src/entity/writer.rs index 6b62cac1..388e2e4a 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -225,8 +225,8 @@ impl EntityWriter { lines.push("".to_owned()); let code_blocks = self .enums - .iter() - .map(|(_, active_enum)| active_enum.impl_active_enum(with_serde, with_copy_enums)) + .values() + .map(|active_enum| active_enum.impl_active_enum(with_serde, with_copy_enums)) .collect(); Self::write(&mut lines, code_blocks); OutputFile { diff --git a/src/executor/paginator.rs b/src/executor/paginator.rs index 60811323..f56d8a32 100644 --- a/src/executor/paginator.rs +++ b/src/executor/paginator.rs @@ -45,8 +45,8 @@ where let query = self .query .clone() - .limit(self.page_size as u64) - .offset((self.page_size * page) as u64) + .limit(self.page_size) + .offset(self.page_size * page) .to_owned(); let builder = self.db.get_database_backend(); let stmt = builder.build(&query); From 69eb4b8ea8c6d7499b6fb7c9907d7f2a720f21ba Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Fri, 16 Dec 2022 18:14:25 +0800 Subject: [PATCH 04/18] Refactor the use of deprecated chrono methods (#1312) --- tests/parallel_tests.rs | 8 ++++---- tests/self_join_tests.rs | 6 +++--- tests/uuid_tests.rs | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/parallel_tests.rs b/tests/parallel_tests.rs index 8eb18dbd..73dae78e 100644 --- a/tests/parallel_tests.rs +++ b/tests/parallel_tests.rs @@ -27,8 +27,8 @@ pub async fn crud_in_parallel(db: &DatabaseConnection) -> Result<(), DbErr> { key: "markup".to_owned(), value: "1.18".to_owned(), bytes: vec![1, 2, 3], - date: Some(Date::from_ymd(2021, 9, 27)), - time: Some(Time::from_hms(11, 32, 55)), + date: Some(Date::from_ymd_opt(2021, 9, 27).unwrap()), + time: Some(Time::from_hms_opt(11, 32, 55).unwrap()), }, metadata::Model { uuid: Uuid::new_v4(), @@ -36,8 +36,8 @@ pub async fn crud_in_parallel(db: &DatabaseConnection) -> Result<(), DbErr> { key: "exchange_rate".to_owned(), value: "0.78".to_owned(), bytes: vec![1, 2, 3], - date: Some(Date::from_ymd(2021, 9, 27)), - time: Some(Time::from_hms(11, 32, 55)), + date: Some(Date::from_ymd_opt(2021, 9, 27).unwrap()), + time: Some(Time::from_hms_opt(11, 32, 55).unwrap()), }, metadata::Model { uuid: Uuid::new_v4(), diff --git a/tests/self_join_tests.rs b/tests/self_join_tests.rs index 0c85a070..d4e86034 100644 --- a/tests/self_join_tests.rs +++ b/tests/self_join_tests.rs @@ -23,7 +23,7 @@ pub async fn create_metadata(db: &DatabaseConnection) -> Result<(), DbErr> { let model = self_join::Model { uuid: Uuid::new_v4(), uuid_ref: None, - time: Some(Time::from_hms(1, 00, 00)), + time: Some(Time::from_hms_opt(1, 00, 00).unwrap()), }; model.clone().into_active_model().insert(db).await?; @@ -31,7 +31,7 @@ pub async fn create_metadata(db: &DatabaseConnection) -> Result<(), DbErr> { let linked_model = self_join::Model { uuid: Uuid::new_v4(), uuid_ref: Some(model.clone().uuid), - time: Some(Time::from_hms(2, 00, 00)), + time: Some(Time::from_hms_opt(2, 00, 00).unwrap()), }; linked_model.clone().into_active_model().insert(db).await?; @@ -39,7 +39,7 @@ pub async fn create_metadata(db: &DatabaseConnection) -> Result<(), DbErr> { let not_linked_model = self_join::Model { uuid: Uuid::new_v4(), uuid_ref: None, - time: Some(Time::from_hms(3, 00, 00)), + time: Some(Time::from_hms_opt(3, 00, 00).unwrap()), }; not_linked_model diff --git a/tests/uuid_tests.rs b/tests/uuid_tests.rs index 20df5085..b0d07772 100644 --- a/tests/uuid_tests.rs +++ b/tests/uuid_tests.rs @@ -28,8 +28,8 @@ pub async fn insert_metadata(db: &DatabaseConnection) -> Result<(), DbErr> { key: "markup".to_owned(), value: "1.18".to_owned(), bytes: vec![1, 2, 3], - date: Some(Date::from_ymd(2021, 9, 27)), - time: Some(Time::from_hms(11, 32, 55)), + date: Some(Date::from_ymd_opt(2021, 9, 27).unwrap()), + time: Some(Time::from_hms_opt(11, 32, 55).unwrap()), }; let result = metadata.clone().into_active_model().insert(db).await?; @@ -65,8 +65,8 @@ pub async fn create_and_update_metadata(db: &DatabaseConnection) -> Result<(), D key: "markup".to_owned(), value: "1.18".to_owned(), bytes: vec![1, 2, 3], - date: Some(Date::from_ymd(2021, 9, 27)), - time: Some(Time::from_hms(11, 32, 55)), + date: Some(Date::from_ymd_opt(2021, 9, 27).unwrap()), + time: Some(Time::from_hms_opt(11, 32, 55).unwrap()), }; let res = Metadata::insert(metadata.clone().into_active_model()) From df2dcdabac154f10121accc399a740b9f4dc3125 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 16 Dec 2022 14:11:51 +0100 Subject: [PATCH 05/18] Prevent returning connections to pool with a positive transaction depth (#1283) Mark transaction as closed *only* after commit/rollback succeeds. Previously, `open` on the transaction would be set to `false` prior to attempting to commit or rollback the transaction. When the operation failed, for example, due to a serialization failure with a serializable isolation level, this would leave the transaction in an inconsistent state, where it thought it was closed but really it was still open. The connection would then be returned to the connection pool with a transaction depth of 1, causing a savepoint to be erroneously created the next time a transaction was created for the connection. By waiting to set `open` to `false` until the commit/rollback succeeds, a failure to do either will result in us correctly rolling back the transaction when dropping it, ensuring that the connection is returned to the pool with a transaction depth of 0. Note that this is consistent with how `sqlx` handles transactions. We attempted to write a test, but had a very difficult time forcing postgres to fail to commit a transaction. We found that it would block our requests instead when creating conflicting updates, and we couldn't find any information about when it blocks vs when transaction commits fail. Co-Authored-By: Nathan Sobo Co-authored-by: Nathan Sobo --- src/database/transaction.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/database/transaction.rs b/src/database/transaction.rs index bfb6f2bb..224f6f92 100644 --- a/src/database/transaction.rs +++ b/src/database/transaction.rs @@ -176,7 +176,6 @@ impl DatabaseTransaction { #[instrument(level = "trace")] #[allow(unreachable_code)] pub async fn commit(mut self) -> Result<(), DbErr> { - self.open = false; match *self.conn.lock().await { #[cfg(feature = "sqlx-mysql")] InnerConnection::MySql(ref mut c) => { @@ -201,6 +200,7 @@ impl DatabaseTransaction { c.commit(); } } + self.open = false; Ok(()) } @@ -208,7 +208,6 @@ impl DatabaseTransaction { #[instrument(level = "trace")] #[allow(unreachable_code)] pub async fn rollback(mut self) -> Result<(), DbErr> { - self.open = false; match *self.conn.lock().await { #[cfg(feature = "sqlx-mysql")] InnerConnection::MySql(ref mut c) => { @@ -233,6 +232,7 @@ impl DatabaseTransaction { c.rollback(); } } + self.open = false; Ok(()) } From d6dc3f8a1912fde019d6bfb8e2b5575be17c0815 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Fri, 16 Dec 2022 21:34:58 +0800 Subject: [PATCH 06/18] CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7675575..310edc0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Bug Fixes * Fixes `DeriveColumn` (by qualifying `IdenStatic::as_str`) https://github.com/SeaQL/sea-orm/pull/1280 +* Prevent returning connections to pool with a positive transaction depth https://github.com/SeaQL/sea-orm/pull/1283 ## 0.10.5 - 2022-12-02 From 7757a46c46e2bfdf4a266b0c2a49327156470ba9 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Fri, 16 Dec 2022 21:36:00 +0800 Subject: [PATCH 07/18] clippy --- src/database/transaction.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/database/transaction.rs b/src/database/transaction.rs index 224f6f92..fa8d5775 100644 --- a/src/database/transaction.rs +++ b/src/database/transaction.rs @@ -174,7 +174,7 @@ impl DatabaseTransaction { /// Commit a transaction atomically #[instrument(level = "trace")] - #[allow(unreachable_code)] + #[allow(unreachable_code, unused_mut)] pub async fn commit(mut self) -> Result<(), DbErr> { match *self.conn.lock().await { #[cfg(feature = "sqlx-mysql")] @@ -206,7 +206,7 @@ impl DatabaseTransaction { /// rolls back a transaction in case error are encountered during the operation #[instrument(level = "trace")] - #[allow(unreachable_code)] + #[allow(unreachable_code, unused_mut)] pub async fn rollback(mut self) -> Result<(), DbErr> { match *self.conn.lock().await { #[cfg(feature = "sqlx-mysql")] From 8982d887747a103c4425bb8c541dc22f850dcf77 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Sat, 17 Dec 2022 12:52:04 +0800 Subject: [PATCH 08/18] Skip implementing `Related` if the same related entity is being referenced by a conjunct relation (#1298) --- sea-orm-codegen/src/entity/base_entity.rs | 2 ++ sea-orm-codegen/src/entity/relation.rs | 5 +++++ sea-orm-codegen/src/entity/transformer.rs | 10 ++++++++++ sea-orm-codegen/src/entity/writer.rs | 15 ++++++++++++++- 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/sea-orm-codegen/src/entity/base_entity.rs b/sea-orm-codegen/src/entity/base_entity.rs index 85d19aa5..628ef638 100644 --- a/sea-orm-codegen/src/entity/base_entity.rs +++ b/sea-orm-codegen/src/entity/base_entity.rs @@ -204,6 +204,7 @@ mod tests { on_update: Some(ForeignKeyAction::Cascade), self_referencing: false, num_suffix: 0, + impl_related: true, }, Relation { ref_table: "filling".to_owned(), @@ -214,6 +215,7 @@ mod tests { on_update: Some(ForeignKeyAction::Cascade), self_referencing: false, num_suffix: 0, + impl_related: true, }, ], conjunct_relations: vec![], diff --git a/sea-orm-codegen/src/entity/relation.rs b/sea-orm-codegen/src/entity/relation.rs index 2c29eef9..ce7b9d82 100644 --- a/sea-orm-codegen/src/entity/relation.rs +++ b/sea-orm-codegen/src/entity/relation.rs @@ -23,6 +23,7 @@ pub struct Relation { pub(crate) on_delete: Option, pub(crate) self_referencing: bool, pub(crate) num_suffix: usize, + pub(crate) impl_related: bool, } impl Relation { @@ -178,6 +179,7 @@ impl From<&TableForeignKey> for Relation { on_update, self_referencing: false, num_suffix: 0, + impl_related: true, } } } @@ -199,6 +201,7 @@ mod tests { on_update: None, self_referencing: false, num_suffix: 0, + impl_related: true, }, Relation { ref_table: "filling".to_owned(), @@ -209,6 +212,7 @@ mod tests { on_update: Some(ForeignKeyAction::Cascade), self_referencing: false, num_suffix: 0, + impl_related: true, }, Relation { ref_table: "filling".to_owned(), @@ -219,6 +223,7 @@ mod tests { on_update: None, self_referencing: false, num_suffix: 0, + impl_related: true, }, ] } diff --git a/sea-orm-codegen/src/entity/transformer.rs b/sea-orm-codegen/src/entity/transformer.rs index 31a4c2a1..53006cbe 100644 --- a/sea-orm-codegen/src/entity/transformer.rs +++ b/sea-orm-codegen/src/entity/transformer.rs @@ -197,6 +197,16 @@ impl EntityTransformer { } for (tbl_name, mut conjunct_relations) in conjunct_relations.into_iter() { if let Some(entity) = entities.get_mut(&tbl_name) { + for relation in entity.relations.iter_mut() { + // Skip `impl Related ... { fn to() ... }` implementation block, + // if the same related entity is being referenced by a conjunct relation + if conjunct_relations + .iter() + .any(|conjunct_relation| conjunct_relation.to == relation.ref_table) + { + relation.impl_related = false; + } + } entity.conjunct_relations.append(&mut conjunct_relations); } } diff --git a/sea-orm-codegen/src/entity/writer.rs b/sea-orm-codegen/src/entity/writer.rs index 388e2e4a..6f293fc7 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -490,7 +490,7 @@ impl EntityWriter { entity .relations .iter() - .filter(|rel| !rel.self_referencing && rel.num_suffix == 0) + .filter(|rel| !rel.self_referencing && rel.num_suffix == 0 && rel.impl_related) .map(|rel| { let enum_name = rel.get_enum_name(); let module_name = rel.get_module_name(); @@ -707,6 +707,7 @@ mod tests { on_update: None, self_referencing: false, num_suffix: 0, + impl_related: true, }], conjunct_relations: vec![ConjunctRelation { via: "cake_filling".to_owned(), @@ -744,6 +745,7 @@ mod tests { on_update: Some(ForeignKeyAction::Cascade), self_referencing: false, num_suffix: 0, + impl_related: true, }, Relation { ref_table: "filling".to_owned(), @@ -754,6 +756,7 @@ mod tests { on_update: Some(ForeignKeyAction::Cascade), self_referencing: false, num_suffix: 0, + impl_related: true, }, ], conjunct_relations: vec![], @@ -828,6 +831,7 @@ mod tests { on_update: None, self_referencing: false, num_suffix: 0, + impl_related: true, }, Relation { ref_table: "vendor".to_owned(), @@ -838,6 +842,7 @@ mod tests { on_update: None, self_referencing: false, num_suffix: 0, + impl_related: true, }, ], conjunct_relations: vec![], @@ -879,6 +884,7 @@ mod tests { on_update: None, self_referencing: false, num_suffix: 0, + impl_related: true, }], conjunct_relations: vec![], primary_keys: vec![PrimaryKey { @@ -990,6 +996,7 @@ mod tests { on_update: None, self_referencing: true, num_suffix: 1, + impl_related: true, }, Relation { ref_table: "rust_keyword".to_owned(), @@ -1000,6 +1007,7 @@ mod tests { on_update: None, self_referencing: true, num_suffix: 2, + impl_related: true, }, Relation { ref_table: "fruit".to_owned(), @@ -1010,6 +1018,7 @@ mod tests { on_update: None, self_referencing: false, num_suffix: 1, + impl_related: true, }, Relation { ref_table: "fruit".to_owned(), @@ -1020,6 +1029,7 @@ mod tests { on_update: None, self_referencing: false, num_suffix: 2, + impl_related: true, }, Relation { ref_table: "cake".to_owned(), @@ -1030,6 +1040,7 @@ mod tests { on_update: None, self_referencing: false, num_suffix: 0, + impl_related: true, }, ], conjunct_relations: vec![], @@ -1071,6 +1082,7 @@ mod tests { on_update: None, self_referencing: false, num_suffix: 0, + impl_related: true, }], conjunct_relations: vec![ConjunctRelation { via: "cake_filling".to_owned(), @@ -1114,6 +1126,7 @@ mod tests { on_update: None, self_referencing: false, num_suffix: 0, + impl_related: true, }], conjunct_relations: vec![ConjunctRelation { via: "cake_filling".to_owned(), From 33a665c6833f8978c47a01f6057518792253521b Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Sat, 17 Dec 2022 12:59:16 +0800 Subject: [PATCH 09/18] [CLI] sea-orm-cli depends on codegen of the same version (#1299) --- build-tools/bump-version.sh | 2 +- sea-orm-cli/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build-tools/bump-version.sh b/build-tools/bump-version.sh index 9436e90d..68062fbc 100644 --- a/build-tools/bump-version.sh +++ b/build-tools/bump-version.sh @@ -11,7 +11,7 @@ sleep 1 # Bump `sea-orm-cli` version cd sea-orm-cli sed -i 's/^version.*$/version = "'$1'"/' Cargo.toml -sed -i 's/^sea-orm-codegen [^,]*,/sea-orm-codegen = { version = "'$1'",/' Cargo.toml +sed -i 's/^sea-orm-codegen [^,]*,/sea-orm-codegen = { version = "\='$1'",/' Cargo.toml git commit -am "sea-orm-cli $1" cd .. sleep 1 diff --git a/sea-orm-cli/Cargo.toml b/sea-orm-cli/Cargo.toml index b734eee2..547f23c0 100644 --- a/sea-orm-cli/Cargo.toml +++ b/sea-orm-cli/Cargo.toml @@ -34,7 +34,7 @@ required-features = ["cli", "codegen"] clap = { version = "3.2", default-features = false, features = ["std", "env", "derive"], optional = true } dotenvy = { version = "0.15", default-features = false, optional = true } async-std = { version = "1.9", default-features = false, features = ["attributes", "tokio1"], optional = true } -sea-orm-codegen = { version = "0.10.3", path = "../sea-orm-codegen", default-features = false, optional = true } +sea-orm-codegen = { version = "=0.10.3", path = "../sea-orm-codegen", default-features = false, optional = true } sea-schema = { version = "0.10.2" } sqlx = { version = "0.6", default-features = false, features = ["mysql", "postgres"], optional = true } tracing-subscriber = { version = "0.3", default-features = false, features = ["env-filter", "fmt"] } From 5809535fb0285a1a45697154386e1ea9697eef6d Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Sat, 17 Dec 2022 13:02:05 +0800 Subject: [PATCH 10/18] CHANGELOG --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 310edc0a..ae992338 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/). * Fixes `DeriveColumn` (by qualifying `IdenStatic::as_str`) https://github.com/SeaQL/sea-orm/pull/1280 * Prevent returning connections to pool with a positive transaction depth https://github.com/SeaQL/sea-orm/pull/1283 +## 0.10.6 - 2022-12-02 + +### Bug Fixes + +* [sea-orm-codegen] Skip implementing Related if the same related entity is being referenced by a conjunct relation https://github.com/SeaQL/sea-orm/pull/1298 +* [sea-orm-cli] CLI depends on codegen of the same version https://github.com/SeaQL/sea-orm/pull/1299/ + ## 0.10.5 - 2022-12-02 ### New Features From 0e3a7c84aef5bb1c1c28f2d8391c587c49a11379 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Sat, 17 Dec 2022 13:08:27 +0800 Subject: [PATCH 11/18] CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae992338..92783f11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,7 +30,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). * Fixes `DeriveColumn` (by qualifying `IdenStatic::as_str`) https://github.com/SeaQL/sea-orm/pull/1280 * Prevent returning connections to pool with a positive transaction depth https://github.com/SeaQL/sea-orm/pull/1283 -## 0.10.6 - 2022-12-02 +## 0.10.6 - Pending ### Bug Fixes From d205338f3f1c8922b0327a30884ed18ed00da06d Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 19 Dec 2022 17:08:32 +0800 Subject: [PATCH 12/18] Try custom vector field (#1273) --- tests/common/features/event_trigger.rs | 70 ++++++++++++++++++++++++++ tests/common/features/mod.rs | 2 + tests/common/features/schema.rs | 21 ++++++++ tests/event_trigger_tests.rs | 48 ++++++++++++++++++ 4 files changed, 141 insertions(+) create mode 100644 tests/common/features/event_trigger.rs create mode 100644 tests/event_trigger_tests.rs diff --git a/tests/common/features/event_trigger.rs b/tests/common/features/event_trigger.rs new file mode 100644 index 00000000..cea0a806 --- /dev/null +++ b/tests/common/features/event_trigger.rs @@ -0,0 +1,70 @@ +use sea_orm::entity::prelude::*; +use sea_orm::{ + sea_query::{ArrayType, ColumnType, SeaRc, ValueType}, + TryGetError, TryGetable, +}; + +#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] +#[sea_orm(table_name = "event_trigger")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub events: Events, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Event(pub String); + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Events(pub Vec); + +impl From for Value { + fn from(events: Events) -> Self { + let Events(events) = events; + Value::Array( + ArrayType::String, + Some(Box::new( + events + .into_iter() + .map(|Event(s)| Value::String(Some(Box::new(s)))) + .collect(), + )), + ) + } +} + +impl TryGetable for Events { + fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result { + let vec: Vec = res.try_get(pre, col).map_err(TryGetError::DbErr)?; + Ok(Events(vec.into_iter().map(Event).collect())) + } +} + +impl ValueType for Events { + fn try_from(v: Value) -> Result { + let value: Option> = + v.expect("This Value::Array should consist of Value::String"); + let vec = match value { + Some(v) => v.into_iter().map(Event).collect(), + None => vec![], + }; + Ok(Events(vec)) + } + + fn type_name() -> String { + stringify!(Events).to_owned() + } + + fn array_type() -> ArrayType { + ArrayType::String + } + + fn column_type() -> ColumnType { + ColumnType::Array(SeaRc::new(Box::new(ColumnType::String(None)))) + } +} diff --git a/tests/common/features/mod.rs b/tests/common/features/mod.rs index ea6a39bc..420c162c 100644 --- a/tests/common/features/mod.rs +++ b/tests/common/features/mod.rs @@ -4,6 +4,7 @@ pub mod applog; pub mod byte_primary_key; pub mod collection; pub mod custom_active_model; +pub mod event_trigger; pub mod insert_default; pub mod json_struct; pub mod json_vec; @@ -21,6 +22,7 @@ pub use active_enum_child::Entity as ActiveEnumChild; pub use applog::Entity as Applog; pub use byte_primary_key::Entity as BytePrimaryKey; pub use collection::Entity as Collection; +pub use event_trigger::Entity as EventTrigger; pub use insert_default::Entity as InsertDefault; pub use json_struct::Entity as JsonStruct; pub use json_vec::Entity as JsonVec; diff --git a/tests/common/features/schema.rs b/tests/common/features/schema.rs index 13ca8c23..c50683be 100644 --- a/tests/common/features/schema.rs +++ b/tests/common/features/schema.rs @@ -45,6 +45,7 @@ pub async fn create_tables(db: &DatabaseConnection) -> Result<(), DbErr> { if DbBackend::Postgres == db_backend { create_collection_table(db).await?; + create_event_trigger_table(db).await?; } Ok(()) @@ -411,3 +412,23 @@ pub async fn create_pi_table(db: &DbConn) -> Result { create_table(db, &stmt, Pi).await } + +pub async fn create_event_trigger_table(db: &DbConn) -> Result { + let stmt = sea_query::Table::create() + .table(event_trigger::Entity) + .col( + ColumnDef::new(event_trigger::Column::Id) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col( + ColumnDef::new(event_trigger::Column::Events) + .array(sea_query::ColumnType::String(None)) + .not_null(), + ) + .to_owned(); + + create_table(db, &stmt, EventTrigger).await +} diff --git a/tests/event_trigger_tests.rs b/tests/event_trigger_tests.rs new file mode 100644 index 00000000..2d8712c5 --- /dev/null +++ b/tests/event_trigger_tests.rs @@ -0,0 +1,48 @@ +pub mod common; + +pub use common::{ + features::{ + event_trigger::{Event, Events}, + *, + }, + setup::*, + TestContext, +}; +use pretty_assertions::assert_eq; +use sea_orm::{entity::prelude::*, entity::*, DatabaseConnection}; + +#[sea_orm_macros::test] +#[cfg(all(feature = "sqlx-postgres", feature = "postgres-array"))] +async fn main() -> Result<(), DbErr> { + let ctx = TestContext::new("event_trigger_tests").await; + create_tables(&ctx.db).await?; + insert_event_trigger(&ctx.db).await?; + ctx.delete().await; + + Ok(()) +} + +pub async fn insert_event_trigger(db: &DatabaseConnection) -> Result<(), DbErr> { + let event_trigger = event_trigger::Model { + id: 1, + events: Events( + ["A", "B", "C"] + .into_iter() + .map(|s| Event(s.to_owned())) + .collect(), + ), + }; + + let result = event_trigger.clone().into_active_model().insert(db).await?; + + assert_eq!(result, event_trigger); + + let model = event_trigger::Entity::find() + .filter(event_trigger::Column::Id.eq(event_trigger.id)) + .one(db) + .await?; + + assert_eq!(model, Some(event_trigger)); + + Ok(()) +} From 17ed7156c486ef0df85a68a0e78312b37b4d2c76 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 19 Dec 2022 17:09:18 +0800 Subject: [PATCH 13/18] Fix: update many cast enum values (#1178) --- src/query/update.rs | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/query/update.rs b/src/query/update.rs index b5d404a0..8d5de747 100644 --- a/src/query/update.rs +++ b/src/query/update.rs @@ -189,7 +189,8 @@ where for col in E::Column::iter() { let av = model.get(col); if av.is_set() { - self.query.value(col, av.unwrap()); + let expr = cast_text_as_enum(Expr::val(av.into_value().unwrap()), &col); + self.query.value(col, expr); } } self @@ -207,7 +208,7 @@ where #[cfg(test)] mod tests { - use crate::tests_cfg::{cake, fruit}; + use crate::tests_cfg::{cake, fruit, lunch_set, sea_orm_active_enums::Tea}; use crate::{entity::*, query::*, DbBackend}; use sea_query::{Expr, Value}; @@ -294,4 +295,33 @@ mod tests { r#"UPDATE "fruit" SET "id" = 3 WHERE "fruit"."id" = 2"#, ); } + + #[test] + fn update_7() { + assert_eq!( + Update::many(lunch_set::Entity) + .set(lunch_set::ActiveModel { + tea: Set(Tea::EverydayTea), + ..Default::default() + }) + .filter(lunch_set::Column::Tea.eq(Tea::BreakfastTea)) + .build(DbBackend::Postgres) + .to_string(), + r#"UPDATE "lunch_set" SET "tea" = CAST('EverydayTea' AS tea) WHERE "lunch_set"."tea" = CAST('BreakfastTea' AS tea)"#, + ); + } + + #[test] + fn update_8() { + assert_eq!( + Update::one(lunch_set::ActiveModel { + id: Unchanged(1), + tea: Set(Tea::EverydayTea), + ..Default::default() + }) + .build(DbBackend::Postgres) + .to_string(), + r#"UPDATE "lunch_set" SET "tea" = CAST('EverydayTea' AS tea) WHERE "lunch_set"."id" = 1"#, + ); + } } From 1f27837f49fcc1752ade988cf35d5d9d4aa09ea7 Mon Sep 17 00:00:00 2001 From: mohs8421 Date: Mon, 19 Dec 2022 10:24:11 +0100 Subject: [PATCH 14/18] refactoring Schema to expose functions for database updates (#1256) * extracting get_column_def from create_table_from_entity to make it available for database upgrade processes. * Align code example formatting * Converting the foreign key related code from create_table_from_entity into From implementations to make its usage easier in different context, like updating a database. * Refactor * Fixup Co-authored-by: Billy Chan --- src/entity/relation.rs | 99 +++++++++++++++++++++++- src/schema/entity.rs | 172 +++++++++++++++++++++-------------------- 2 files changed, 187 insertions(+), 84 deletions(-) diff --git a/src/entity/relation.rs b/src/entity/relation.rs index 06e22a29..9e3c565e 100644 --- a/src/entity/relation.rs +++ b/src/entity/relation.rs @@ -1,6 +1,9 @@ -use crate::{EntityTrait, Identity, IdentityOf, Iterable, QuerySelect, Select}; +use crate::{unpack_table_ref, EntityTrait, Identity, IdentityOf, Iterable, QuerySelect, Select}; use core::marker::PhantomData; -use sea_query::{Alias, Condition, DynIden, JoinType, SeaRc, TableRef}; +use sea_query::{ + Alias, Condition, DynIden, ForeignKeyCreateStatement, JoinType, SeaRc, TableForeignKey, + TableRef, +}; use std::fmt::Debug; /// Defines the type of relationship @@ -309,6 +312,98 @@ where } } +macro_rules! set_foreign_key_stmt { + ( $relation: ident, $foreign_key: ident ) => { + let from_cols: Vec = match $relation.from_col { + Identity::Unary(o1) => vec![o1], + Identity::Binary(o1, o2) => vec![o1, o2], + Identity::Ternary(o1, o2, o3) => vec![o1, o2, o3], + } + .into_iter() + .map(|col| { + let col_name = col.to_string(); + $foreign_key.from_col(col); + col_name + }) + .collect(); + match $relation.to_col { + Identity::Unary(o1) => { + $foreign_key.to_col(o1); + } + Identity::Binary(o1, o2) => { + $foreign_key.to_col(o1); + $foreign_key.to_col(o2); + } + Identity::Ternary(o1, o2, o3) => { + $foreign_key.to_col(o1); + $foreign_key.to_col(o2); + $foreign_key.to_col(o3); + } + } + if let Some(action) = $relation.on_delete { + $foreign_key.on_delete(action); + } + if let Some(action) = $relation.on_update { + $foreign_key.on_update(action); + } + let name = if let Some(name) = $relation.fk_name { + name + } else { + let from_tbl = unpack_table_ref(&$relation.from_tbl); + format!("fk-{}-{}", from_tbl.to_string(), from_cols.join("-")) + }; + $foreign_key.name(&name); + }; +} + +impl From for ForeignKeyCreateStatement { + fn from(relation: RelationDef) -> Self { + let mut foreign_key_stmt = Self::new(); + set_foreign_key_stmt!(relation, foreign_key_stmt); + foreign_key_stmt + .from_tbl(unpack_table_ref(&relation.from_tbl)) + .to_tbl(unpack_table_ref(&relation.to_tbl)) + .take() + } +} + +/// Creates a column definition for example to update a table. +/// ``` +/// use sea_query::{Alias, IntoIden, MysqlQueryBuilder, TableAlterStatement, TableRef}; +/// use sea_orm::{EnumIter, Iden, Identity, PrimaryKeyTrait, RelationDef, RelationTrait, RelationType}; +/// +/// let relation = RelationDef { +/// rel_type: RelationType::HasOne, +/// from_tbl: TableRef::Table(Alias::new("foo").into_iden()), +/// to_tbl: TableRef::Table(Alias::new("bar").into_iden()), +/// from_col: Identity::Unary(Alias::new("bar_id").into_iden()), +/// to_col: Identity::Unary(Alias::new("bar_id").into_iden()), +/// is_owner: false, +/// on_delete: None, +/// on_update: None, +/// on_condition: None, +/// fk_name: Some("foo-bar".to_string()), +/// }; +/// +/// let mut alter_table = TableAlterStatement::new() +/// .table(TableRef::Table(Alias::new("foo").into_iden())) +/// .add_foreign_key(&mut relation.into()).take(); +/// assert_eq!( +/// alter_table.to_string(MysqlQueryBuilder::default()), +/// "ALTER TABLE `foo` ADD CONSTRAINT `foo-bar` FOREIGN KEY (`bar_id`) REFERENCES `bar` (`bar_id`)" +/// ); +/// ``` +impl From for TableForeignKey { + fn from(relation: RelationDef) -> Self { + let mut foreign_key = Self::new(); + set_foreign_key_stmt!(relation, foreign_key); + foreign_key + .from_tbl(unpack_table_ref(&relation.from_tbl)) + .to_tbl(unpack_table_ref(&relation.to_tbl)) + .take() + } +} + #[cfg(test)] mod tests { use crate::{ diff --git a/src/schema/entity.rs b/src/schema/entity.rs index 28bca9d5..c1d23d83 100644 --- a/src/schema/entity.rs +++ b/src/schema/entity.rs @@ -1,10 +1,10 @@ use crate::{ - unpack_table_ref, ActiveEnum, ColumnTrait, ColumnType, DbBackend, EntityTrait, Identity, - Iterable, PrimaryKeyToColumn, PrimaryKeyTrait, RelationTrait, Schema, + ActiveEnum, ColumnTrait, ColumnType, DbBackend, EntityTrait, Iterable, PrimaryKeyToColumn, + PrimaryKeyTrait, RelationTrait, Schema, }; use sea_query::{ extension::postgres::{Type, TypeCreateStatement}, - ColumnDef, ForeignKeyCreateStatement, Iden, Index, IndexCreateStatement, TableCreateStatement, + ColumnDef, Iden, Index, IndexCreateStatement, TableCreateStatement, }; impl Schema { @@ -40,6 +40,51 @@ impl Schema { { create_index_from_entity(entity, self.backend) } + + /// Creates a column definition for example to update a table. + /// ``` + /// use crate::sea_orm::IdenStatic; + /// use sea_orm::{ + /// ActiveModelBehavior, ColumnDef, ColumnTrait, ColumnType, DbBackend, EntityName, + /// EntityTrait, EnumIter, PrimaryKeyTrait, RelationDef, RelationTrait, Schema, + /// }; + /// use sea_orm_macros::{DeriveEntityModel, DerivePrimaryKey}; + /// use sea_query::{MysqlQueryBuilder, TableAlterStatement}; + /// + /// #[derive(Clone, Debug, PartialEq, DeriveEntityModel)] + /// #[sea_orm(table_name = "posts")] + /// pub struct Model { + /// #[sea_orm(primary_key)] + /// pub id: u32, + /// pub title: String, + /// } + /// + /// #[derive(Copy, Clone, Debug, EnumIter)] + /// pub enum Relation {} + /// impl RelationTrait for Relation { + /// fn def(&self) -> RelationDef { + /// panic!("No RelationDef") + /// } + /// } + /// impl ActiveModelBehavior for ActiveModel {} + /// + /// let schema = Schema::new(DbBackend::MySql); + /// + /// let mut alter_table = TableAlterStatement::new() + /// .table(Entity) + /// .add_column(&mut schema.get_column_def::(Column::Title)) + /// .take(); + /// assert_eq!( + /// alter_table.to_string(MysqlQueryBuilder::default()), + /// "ALTER TABLE `posts` ADD COLUMN `title` varchar(255) NOT NULL" + /// ); + /// ``` + pub fn get_column_def(&self, column: E::Column) -> ColumnDef + where + E: EntityTrait, + { + column_def_from_entity_column::(column, self.backend) + } } pub(crate) fn create_enum_from_active_enum(backend: DbBackend) -> TypeCreateStatement @@ -117,39 +162,7 @@ where let mut stmt = TableCreateStatement::new(); for column in E::Column::iter() { - let orm_column_def = column.def(); - let types = match orm_column_def.col_type { - ColumnType::Enum { name, variants } => match backend { - DbBackend::MySql => { - let variants: Vec = variants.iter().map(|v| v.to_string()).collect(); - ColumnType::Custom(format!("ENUM('{}')", variants.join("', '"))) - } - DbBackend::Postgres => ColumnType::Custom(name.to_string()), - DbBackend::Sqlite => ColumnType::Text, - } - .into(), - _ => orm_column_def.col_type.into(), - }; - let mut column_def = ColumnDef::new_with_type(column, types); - if !orm_column_def.null { - column_def.not_null(); - } - if orm_column_def.unique { - column_def.unique_key(); - } - if let Some(value) = orm_column_def.default_value { - column_def.default(value); - } - for primary_key in E::PrimaryKey::iter() { - if column.to_string() == primary_key.into_column().to_string() { - if E::PrimaryKey::auto_increment() { - column_def.auto_increment(); - } - if E::PrimaryKey::iter().count() == 1 { - column_def.primary_key(); - } - } - } + let mut column_def = column_def_from_entity_column::(column, backend); stmt.col(&mut column_def); } @@ -166,57 +179,52 @@ where if relation.is_owner { continue; } - let mut foreign_key_stmt = ForeignKeyCreateStatement::new(); - let from_tbl = unpack_table_ref(&relation.from_tbl); - let to_tbl = unpack_table_ref(&relation.to_tbl); - let from_cols: Vec = match relation.from_col { - Identity::Unary(o1) => vec![o1], - Identity::Binary(o1, o2) => vec![o1, o2], - Identity::Ternary(o1, o2, o3) => vec![o1, o2, o3], - } - .into_iter() - .map(|col| { - let col_name = col.to_string(); - foreign_key_stmt.from_col(col); - col_name - }) - .collect(); - match relation.to_col { - Identity::Unary(o1) => { - foreign_key_stmt.to_col(o1); - } - Identity::Binary(o1, o2) => { - foreign_key_stmt.to_col(o1); - foreign_key_stmt.to_col(o2); - } - Identity::Ternary(o1, o2, o3) => { - foreign_key_stmt.to_col(o1); - foreign_key_stmt.to_col(o2); - foreign_key_stmt.to_col(o3); - } - } - if let Some(action) = relation.on_delete { - foreign_key_stmt.on_delete(action); - } - if let Some(action) = relation.on_update { - foreign_key_stmt.on_update(action); - } - let name = if let Some(name) = relation.fk_name { - name - } else { - format!("fk-{}-{}", from_tbl.to_string(), from_cols.join("-")) - }; - stmt.foreign_key( - foreign_key_stmt - .name(&name) - .from_tbl(from_tbl) - .to_tbl(to_tbl), - ); + stmt.foreign_key(&mut relation.into()); } stmt.table(entity.table_ref()).take() } +fn column_def_from_entity_column(column: E::Column, backend: DbBackend) -> ColumnDef +where + E: EntityTrait, +{ + let orm_column_def = column.def(); + let types = match orm_column_def.col_type { + ColumnType::Enum { name, variants } => match backend { + DbBackend::MySql => { + let variants: Vec = variants.iter().map(|v| v.to_string()).collect(); + ColumnType::Custom(format!("ENUM('{}')", variants.join("', '"))) + } + DbBackend::Postgres => ColumnType::Custom(name.to_string()), + DbBackend::Sqlite => ColumnType::Text, + } + .into(), + _ => orm_column_def.col_type.into(), + }; + let mut column_def = ColumnDef::new_with_type(column, types); + if !orm_column_def.null { + column_def.not_null(); + } + if orm_column_def.unique { + column_def.unique_key(); + } + if let Some(value) = orm_column_def.default_value { + column_def.default(value); + } + for primary_key in E::PrimaryKey::iter() { + if column.to_string() == primary_key.into_column().to_string() { + if E::PrimaryKey::auto_increment() { + column_def.auto_increment(); + } + if E::PrimaryKey::iter().count() == 1 { + column_def.primary_key(); + } + } + } + column_def +} + #[cfg(test)] mod tests { use crate::{sea_query::*, tests_cfg::*, DbBackend, EntityName, Schema}; From 3f00725ee278b515ae767cf03f4cee59df1ed9a2 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 19 Dec 2022 22:11:45 +0800 Subject: [PATCH 15/18] Cli serde skip deserialize for primary key option (#1186) (#1318) * Cli serde skip deserialize for primary key option (#1186) * Add CLI option to skip primary keys with serde Implements: https://github.com/SeaQL/sea-orm/issues/841 * Codegen: fix tests * complete skip_deserialize cli feature * run fmt * fix tests Co-authored-by: witcher * [cli] should be `#[serde(skip_deserializing)]` * [CLI] code refactor * [cli] rename Co-authored-by: Isaiah Gamble <77396670+tsar-boomba@users.noreply.github.com> Co-authored-by: witcher --- sea-orm-cli/src/cli.rs | 7 ++ sea-orm-cli/src/commands/generate.rs | 2 + sea-orm-codegen/src/entity/base_entity.rs | 16 ++++ sea-orm-codegen/src/entity/column.rs | 12 +++ sea-orm-codegen/src/entity/writer.rs | 80 +++++++++++++++---- .../tests/compact_with_serde/cake_both.rs | 1 + .../compact_with_serde/cake_deserialize.rs | 1 + .../tests/expanded_with_serde/cake_both.rs | 1 + .../expanded_with_serde/cake_deserialize.rs | 1 + 9 files changed, 104 insertions(+), 17 deletions(-) diff --git a/sea-orm-cli/src/cli.rs b/sea-orm-cli/src/cli.rs index 1d797aa0..f7983f9f 100644 --- a/sea-orm-cli/src/cli.rs +++ b/sea-orm-cli/src/cli.rs @@ -228,6 +228,13 @@ pub enum GenerateSubcommands { help = "Generate index file as `lib.rs` instead of `mod.rs`." )] lib: bool, + + #[clap( + action, + long, + help = "Generate a serde field attribute, '#[serde(skip_deserializing)]', for the primary key fields to skip them during deserialization, this flag will be affective only when '--with-serde' is 'both' or 'deserialize'" + )] + serde_skip_deserializing_primary_key: bool, }, } diff --git a/sea-orm-cli/src/commands/generate.rs b/sea-orm-cli/src/commands/generate.rs index 8117c852..43756a77 100644 --- a/sea-orm-cli/src/commands/generate.rs +++ b/sea-orm-cli/src/commands/generate.rs @@ -27,6 +27,7 @@ pub async fn run_generate_command( with_copy_enums, date_time_crate, lib, + serde_skip_deserializing_primary_key, } => { if verbose { let _ = tracing_subscriber::fmt() @@ -164,6 +165,7 @@ pub async fn run_generate_command( date_time_crate.into(), schema_name, lib, + serde_skip_deserializing_primary_key, ); let output = EntityTransformer::transform(table_stmts)?.generate(&writer_context); diff --git a/sea-orm-codegen/src/entity/base_entity.rs b/sea-orm-codegen/src/entity/base_entity.rs index 628ef638..403657ba 100644 --- a/sea-orm-codegen/src/entity/base_entity.rs +++ b/sea-orm-codegen/src/entity/base_entity.rs @@ -166,6 +166,22 @@ impl Entity { // if exist, return nothing .map_or(quote! {, Eq}, |_| quote! {}) } + + pub fn get_serde_skip_deserializing( + &self, + serde_skip_deserializing_primary_key: bool, + ) -> Vec { + self.columns + .iter() + .map(|col| { + let is_primary_key = self.primary_keys.iter().any(|pk| pk.name == col.name); + col.get_serde_skip_deserializing( + is_primary_key, + serde_skip_deserializing_primary_key, + ) + }) + .collect() + } } #[cfg(test)] diff --git a/sea-orm-codegen/src/entity/column.rs b/sea-orm-codegen/src/entity/column.rs index 298176f4..73d57283 100644 --- a/sea-orm-codegen/src/entity/column.rs +++ b/sea-orm-codegen/src/entity/column.rs @@ -211,6 +211,18 @@ impl Column { } info } + + pub fn get_serde_skip_deserializing( + &self, + is_primary_key: bool, + serde_skip_deserializing_primary_key: bool, + ) -> TokenStream { + if serde_skip_deserializing_primary_key && is_primary_key { + quote! { #[serde(skip_deserializing)] } + } else { + quote! {} + } + } } impl From for Column { diff --git a/sea-orm-codegen/src/entity/writer.rs b/sea-orm-codegen/src/entity/writer.rs index 6f293fc7..c5de8245 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -43,6 +43,7 @@ pub struct EntityWriterContext { pub(crate) date_time_crate: DateTimeCrate, pub(crate) schema_name: Option, pub(crate) lib: bool, + pub(crate) serde_skip_deserializing_primary_key: bool, } impl WithSerde { @@ -103,6 +104,7 @@ impl EntityWriterContext { date_time_crate: DateTimeCrate, schema_name: Option, lib: bool, + serde_skip_deserializing_primary_key: bool, ) -> Self { Self { expanded_format, @@ -111,6 +113,7 @@ impl EntityWriterContext { date_time_crate, schema_name, lib, + serde_skip_deserializing_primary_key, } } } @@ -139,6 +142,11 @@ impl EntityWriter { .iter() .map(|column| column.get_info(&context.date_time_crate)) .collect::>(); + // use must have serde enabled to use this + let serde_skip_deserializing_primary_key = context + .serde_skip_deserializing_primary_key + && (context.with_serde == WithSerde::Both + || context.with_serde == WithSerde::Deserialize); info!("Generating {}", entity_file); for info in column_info.iter() { @@ -153,6 +161,7 @@ impl EntityWriter { &context.with_serde, &context.date_time_crate, &context.schema_name, + serde_skip_deserializing_primary_key, ) } else { Self::gen_compact_code_blocks( @@ -160,6 +169,7 @@ impl EntityWriter { &context.with_serde, &context.date_time_crate, &context.schema_name, + serde_skip_deserializing_primary_key, ) }; Self::write(&mut lines, code_blocks); @@ -259,6 +269,7 @@ impl EntityWriter { with_serde: &WithSerde, date_time_crate: &DateTimeCrate, schema_name: &Option, + serde_skip_deserializing_primary_key: bool, ) -> Vec { let mut imports = Self::gen_import(with_serde); imports.extend(Self::gen_import_active_enum(entity)); @@ -266,7 +277,12 @@ impl EntityWriter { imports, Self::gen_entity_struct(), Self::gen_impl_entity_name(entity, schema_name), - Self::gen_model_struct(entity, with_serde, date_time_crate), + Self::gen_model_struct( + entity, + with_serde, + date_time_crate, + serde_skip_deserializing_primary_key, + ), Self::gen_column_enum(entity), Self::gen_primary_key_enum(entity), Self::gen_impl_primary_key(entity, date_time_crate), @@ -285,12 +301,19 @@ impl EntityWriter { with_serde: &WithSerde, date_time_crate: &DateTimeCrate, schema_name: &Option, + serde_skip_deserializing_primary_key: bool, ) -> Vec { let mut imports = Self::gen_import(with_serde); imports.extend(Self::gen_import_active_enum(entity)); let mut code_blocks = vec![ imports, - Self::gen_compact_model_struct(entity, with_serde, date_time_crate, schema_name), + Self::gen_compact_model_struct( + entity, + with_serde, + date_time_crate, + schema_name, + serde_skip_deserializing_primary_key, + ), Self::gen_compact_relation_enum(entity), ]; code_blocks.extend(Self::gen_impl_related(entity)); @@ -378,16 +401,22 @@ impl EntityWriter { entity: &Entity, with_serde: &WithSerde, date_time_crate: &DateTimeCrate, + serde_skip_deserializing_primary_key: bool, ) -> TokenStream { let column_names_snake_case = entity.get_column_names_snake_case(); let column_rs_types = entity.get_column_rs_types(date_time_crate); let if_eq_needed = entity.get_eq_needed(); + let serde_skip_deserializing = + entity.get_serde_skip_deserializing(serde_skip_deserializing_primary_key); let extra_derive = with_serde.extra_derive(); quote! { #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel #if_eq_needed #extra_derive)] pub struct Model { - #(pub #column_names_snake_case: #column_rs_types,)* + #( + #serde_skip_deserializing + pub #column_names_snake_case: #column_rs_types, + )* } } } @@ -566,6 +595,7 @@ impl EntityWriter { with_serde: &WithSerde, date_time_crate: &DateTimeCrate, schema_name: &Option, + serde_skip_deserializing_primary_key: bool, ) -> TokenStream { let table_name = entity.table_name.as_str(); let column_names_snake_case = entity.get_column_names_snake_case(); @@ -581,11 +611,12 @@ impl EntityWriter { .iter() .map(|col| { let mut attrs: Punctuated<_, Comma> = Punctuated::new(); + let is_primary_key = primary_keys.contains(&col.name); if !col.is_snake_case_name() { let column_name = &col.name; attrs.push(quote! { column_name = #column_name }); } - if primary_keys.contains(&col.name) { + if is_primary_key { attrs.push(quote! { primary_key }); if !col.auto_increment { attrs.push(quote! { auto_increment = false }); @@ -600,20 +631,25 @@ impl EntityWriter { if col.unique { attrs.push(quote! { unique }); } + let mut ts = quote! {}; if !attrs.is_empty() { - let mut ts = TokenStream::new(); for (i, attr) in attrs.into_iter().enumerate() { if i > 0 { ts = quote! { #ts, }; } ts = quote! { #ts #attr }; } - quote! { - #[sea_orm(#ts)] - } - } else { - TokenStream::new() + ts = quote! { #[sea_orm(#ts)] }; } + let serde_skip_deserializing = col.get_serde_skip_deserializing( + is_primary_key, + serde_skip_deserializing_primary_key, + ); + ts = quote! { + #ts + #serde_skip_deserializing + }; + ts }) .collect(); let schema_name = match Self::gen_schema_name(schema_name) { @@ -1260,7 +1296,8 @@ mod tests { entity, &crate::WithSerde::None, &crate::DateTimeCrate::Chrono, - &None + &None, + false, ) .into_iter() .skip(1) @@ -1276,7 +1313,8 @@ mod tests { entity, &crate::WithSerde::None, &crate::DateTimeCrate::Chrono, - &Some("public".to_owned()) + &Some("public".to_owned()), + false, ) .into_iter() .skip(1) @@ -1292,7 +1330,8 @@ mod tests { entity, &crate::WithSerde::None, &crate::DateTimeCrate::Chrono, - &Some("schema_name".to_owned()) + &Some("schema_name".to_owned()), + false, ) .into_iter() .skip(1) @@ -1344,7 +1383,8 @@ mod tests { entity, &crate::WithSerde::None, &crate::DateTimeCrate::Chrono, - &None + &None, + false, ) .into_iter() .skip(1) @@ -1360,7 +1400,8 @@ mod tests { entity, &crate::WithSerde::None, &crate::DateTimeCrate::Chrono, - &Some("public".to_owned()) + &Some("public".to_owned()), + false, ) .into_iter() .skip(1) @@ -1376,7 +1417,8 @@ mod tests { entity, &crate::WithSerde::None, &crate::DateTimeCrate::Chrono, - &Some("schema_name".to_owned()) + &Some("schema_name".to_owned()), + false, ) .into_iter() .skip(1) @@ -1481,11 +1523,13 @@ mod tests { cake_entity: &Entity, entity_serde_variant: &(String, WithSerde, Option), generator: Box< - dyn Fn(&Entity, &WithSerde, &DateTimeCrate, &Option) -> Vec, + dyn Fn(&Entity, &WithSerde, &DateTimeCrate, &Option, bool) -> Vec, >, ) -> io::Result<()> { let mut reader = BufReader::new(entity_serde_variant.0.as_bytes()); let mut lines: Vec = Vec::new(); + let serde_skip_deserializing_primary_key = entity_serde_variant.1 == WithSerde::Both + || entity_serde_variant.1 == WithSerde::Deserialize; reader.read_until(b'\n', &mut Vec::new())?; @@ -1496,11 +1540,13 @@ mod tests { } let content = lines.join(""); let expected: TokenStream = content.parse().unwrap(); + println!("{:?}", entity_serde_variant.1); let generated = generator( cake_entity, &entity_serde_variant.1, &DateTimeCrate::Chrono, &entity_serde_variant.2, + serde_skip_deserializing_primary_key, ) .into_iter() .fold(TokenStream::new(), |mut acc, tok| { diff --git a/sea-orm-codegen/tests/compact_with_serde/cake_both.rs b/sea-orm-codegen/tests/compact_with_serde/cake_both.rs index 54d3cd16..fa893a5c 100644 --- a/sea-orm-codegen/tests/compact_with_serde/cake_both.rs +++ b/sea-orm-codegen/tests/compact_with_serde/cake_both.rs @@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize}; #[sea_orm(table_name = "cake")] pub struct Model { #[sea_orm(primary_key)] + #[serde(skip_deserializing)] pub id: i32, #[sea_orm(column_type = "Text", nullable)] pub name: Option , diff --git a/sea-orm-codegen/tests/compact_with_serde/cake_deserialize.rs b/sea-orm-codegen/tests/compact_with_serde/cake_deserialize.rs index f11569e4..620bdf67 100644 --- a/sea-orm-codegen/tests/compact_with_serde/cake_deserialize.rs +++ b/sea-orm-codegen/tests/compact_with_serde/cake_deserialize.rs @@ -7,6 +7,7 @@ use serde::Deserialize; #[sea_orm(table_name = "cake")] pub struct Model { #[sea_orm(primary_key)] + #[serde(skip_deserializing)] pub id: i32, #[sea_orm(column_type = "Text", nullable)] pub name: Option , diff --git a/sea-orm-codegen/tests/expanded_with_serde/cake_both.rs b/sea-orm-codegen/tests/expanded_with_serde/cake_both.rs index 924887b4..40c9e998 100644 --- a/sea-orm-codegen/tests/expanded_with_serde/cake_both.rs +++ b/sea-orm-codegen/tests/expanded_with_serde/cake_both.rs @@ -14,6 +14,7 @@ impl EntityName for Entity { #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Eq, Serialize, Deserialize)] pub struct Model { + #[serde(skip_deserializing)] pub id: i32, pub name: Option , } diff --git a/sea-orm-codegen/tests/expanded_with_serde/cake_deserialize.rs b/sea-orm-codegen/tests/expanded_with_serde/cake_deserialize.rs index 88a7c3a9..ec201073 100644 --- a/sea-orm-codegen/tests/expanded_with_serde/cake_deserialize.rs +++ b/sea-orm-codegen/tests/expanded_with_serde/cake_deserialize.rs @@ -14,6 +14,7 @@ impl EntityName for Entity { #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Eq, Deserialize)] pub struct Model { + #[serde(skip_deserializing)] pub id: i32, pub name: Option , } From 9282ce2ded4957d3207ea614c200c0030592bc76 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 20 Dec 2022 00:43:21 +0800 Subject: [PATCH 16/18] Cont. Add serde skip options for hidden columns to the CLI (#1320) * Add serde skip options for hidden columns to the CLI (#1171) * Add serde skip options for hidden columns to the CLI * Resolve rustfmt and clippy issues * Use SerdeDeriveOptions instead of WithSerde in tests * Resolve upstream conflict Co-authored-by: Billy Chan * [CLI] serde_skip_hidden_column * clippy * clippy Co-authored-by: Jacob Trueb --- sea-orm-cli/src/cli.rs | 22 +++-- sea-orm-cli/src/commands/generate.rs | 6 +- sea-orm-codegen/src/entity/base_entity.rs | 6 +- sea-orm-codegen/src/entity/column.rs | 13 ++- sea-orm-codegen/src/entity/writer.rs | 90 +++++++++++++++---- .../cake_serialize_with_hidden_column.rs | 37 ++++++++ .../cake_serialize_with_hidden_column.rs | 80 +++++++++++++++++ 7 files changed, 224 insertions(+), 30 deletions(-) create mode 100644 sea-orm-codegen/tests/compact_with_serde/cake_serialize_with_hidden_column.rs create mode 100644 sea-orm-codegen/tests/expanded_with_serde/cake_serialize_with_hidden_column.rs diff --git a/sea-orm-cli/src/cli.rs b/sea-orm-cli/src/cli.rs index f7983f9f..9538d402 100644 --- a/sea-orm-cli/src/cli.rs +++ b/sea-orm-cli/src/cli.rs @@ -200,6 +200,21 @@ pub enum GenerateSubcommands { )] with_serde: String, + #[clap( + action, + long, + help = "Generate a serde field attribute, '#[serde(skip_deserializing)]', for the primary key fields to skip them during deserialization, this flag will be affective only when '--with-serde' is 'both' or 'deserialize'" + )] + serde_skip_deserializing_primary_key: bool, + + #[clap( + action, + long, + default_value = "false", + help = "Opt-in to add skip attributes to hidden columns (i.e. when 'with-serde' enabled and column name starts with an underscore)" + )] + serde_skip_hidden_column: bool, + #[clap( action, long, @@ -228,13 +243,6 @@ pub enum GenerateSubcommands { help = "Generate index file as `lib.rs` instead of `mod.rs`." )] lib: bool, - - #[clap( - action, - long, - help = "Generate a serde field attribute, '#[serde(skip_deserializing)]', for the primary key fields to skip them during deserialization, this flag will be affective only when '--with-serde' is 'both' or 'deserialize'" - )] - serde_skip_deserializing_primary_key: bool, }, } diff --git a/sea-orm-cli/src/commands/generate.rs b/sea-orm-cli/src/commands/generate.rs index 43756a77..587504c6 100644 --- a/sea-orm-cli/src/commands/generate.rs +++ b/sea-orm-cli/src/commands/generate.rs @@ -24,10 +24,11 @@ pub async fn run_generate_command( database_schema, database_url, with_serde, + serde_skip_deserializing_primary_key, + serde_skip_hidden_column, with_copy_enums, date_time_crate, lib, - serde_skip_deserializing_primary_key, } => { if verbose { let _ = tracing_subscriber::fmt() @@ -160,12 +161,13 @@ pub async fn run_generate_command( let writer_context = EntityWriterContext::new( expanded_format, - WithSerde::from_str(&with_serde).unwrap(), + WithSerde::from_str(&with_serde).expect("Invalid serde derive option"), with_copy_enums, date_time_crate.into(), schema_name, lib, serde_skip_deserializing_primary_key, + serde_skip_hidden_column, ); let output = EntityTransformer::transform(table_stmts)?.generate(&writer_context); diff --git a/sea-orm-codegen/src/entity/base_entity.rs b/sea-orm-codegen/src/entity/base_entity.rs index 403657ba..7a79f600 100644 --- a/sea-orm-codegen/src/entity/base_entity.rs +++ b/sea-orm-codegen/src/entity/base_entity.rs @@ -167,17 +167,19 @@ impl Entity { .map_or(quote! {, Eq}, |_| quote! {}) } - pub fn get_serde_skip_deserializing( + pub fn get_column_serde_attributes( &self, serde_skip_deserializing_primary_key: bool, + serde_skip_hidden_column: bool, ) -> Vec { self.columns .iter() .map(|col| { let is_primary_key = self.primary_keys.iter().any(|pk| pk.name == col.name); - col.get_serde_skip_deserializing( + col.get_serde_attribute( is_primary_key, serde_skip_deserializing_primary_key, + serde_skip_hidden_column, ) }) .collect() diff --git a/sea-orm-codegen/src/entity/column.rs b/sea-orm-codegen/src/entity/column.rs index 73d57283..5e2a6f57 100644 --- a/sea-orm-codegen/src/entity/column.rs +++ b/sea-orm-codegen/src/entity/column.rs @@ -212,13 +212,20 @@ impl Column { info } - pub fn get_serde_skip_deserializing( + pub fn get_serde_attribute( &self, is_primary_key: bool, serde_skip_deserializing_primary_key: bool, + serde_skip_hidden_column: bool, ) -> TokenStream { - if serde_skip_deserializing_primary_key && is_primary_key { - quote! { #[serde(skip_deserializing)] } + if self.name.starts_with('_') && serde_skip_hidden_column { + quote! { + #[serde(skip)] + } + } else if serde_skip_deserializing_primary_key && is_primary_key { + quote! { + #[serde(skip_deserializing)] + } } else { quote! {} } diff --git a/sea-orm-codegen/src/entity/writer.rs b/sea-orm-codegen/src/entity/writer.rs index c5de8245..8c2ab7f3 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -43,6 +43,7 @@ pub struct EntityWriterContext { pub(crate) date_time_crate: DateTimeCrate, pub(crate) schema_name: Option, pub(crate) lib: bool, + pub(crate) serde_skip_hidden_column: bool, pub(crate) serde_skip_deserializing_primary_key: bool, } @@ -68,11 +69,9 @@ impl WithSerde { } } }; - if !extra_derive.is_empty() { extra_derive = quote! { , #extra_derive } } - extra_derive } } @@ -97,6 +96,7 @@ impl FromStr for WithSerde { } impl EntityWriterContext { + #[allow(clippy::too_many_arguments)] pub fn new( expanded_format: bool, with_serde: WithSerde, @@ -105,6 +105,7 @@ impl EntityWriterContext { schema_name: Option, lib: bool, serde_skip_deserializing_primary_key: bool, + serde_skip_hidden_column: bool, ) -> Self { Self { expanded_format, @@ -114,6 +115,7 @@ impl EntityWriterContext { schema_name, lib, serde_skip_deserializing_primary_key, + serde_skip_hidden_column, } } } @@ -142,11 +144,15 @@ impl EntityWriter { .iter() .map(|column| column.get_info(&context.date_time_crate)) .collect::>(); - // use must have serde enabled to use this + // Serde must be enabled to use this let serde_skip_deserializing_primary_key = context .serde_skip_deserializing_primary_key - && (context.with_serde == WithSerde::Both - || context.with_serde == WithSerde::Deserialize); + && matches!(context.with_serde, WithSerde::Both | WithSerde::Deserialize); + let serde_skip_hidden_column = context.serde_skip_hidden_column + && matches!( + context.with_serde, + WithSerde::Both | WithSerde::Serialize | WithSerde::Deserialize + ); info!("Generating {}", entity_file); for info in column_info.iter() { @@ -162,6 +168,7 @@ impl EntityWriter { &context.date_time_crate, &context.schema_name, serde_skip_deserializing_primary_key, + serde_skip_hidden_column, ) } else { Self::gen_compact_code_blocks( @@ -170,6 +177,7 @@ impl EntityWriter { &context.date_time_crate, &context.schema_name, serde_skip_deserializing_primary_key, + serde_skip_hidden_column, ) }; Self::write(&mut lines, code_blocks); @@ -270,6 +278,7 @@ impl EntityWriter { date_time_crate: &DateTimeCrate, schema_name: &Option, serde_skip_deserializing_primary_key: bool, + serde_skip_hidden_column: bool, ) -> Vec { let mut imports = Self::gen_import(with_serde); imports.extend(Self::gen_import_active_enum(entity)); @@ -282,6 +291,7 @@ impl EntityWriter { with_serde, date_time_crate, serde_skip_deserializing_primary_key, + serde_skip_hidden_column, ), Self::gen_column_enum(entity), Self::gen_primary_key_enum(entity), @@ -302,6 +312,7 @@ impl EntityWriter { date_time_crate: &DateTimeCrate, schema_name: &Option, serde_skip_deserializing_primary_key: bool, + serde_skip_hidden_column: bool, ) -> Vec { let mut imports = Self::gen_import(with_serde); imports.extend(Self::gen_import_active_enum(entity)); @@ -313,6 +324,7 @@ impl EntityWriter { date_time_crate, schema_name, serde_skip_deserializing_primary_key, + serde_skip_hidden_column, ), Self::gen_compact_relation_enum(entity), ]; @@ -335,14 +347,12 @@ impl EntityWriter { use serde::Serialize; } } - WithSerde::Deserialize => { quote! { #prelude_import use serde::Deserialize; } } - WithSerde::Both => { quote! { #prelude_import @@ -402,19 +412,22 @@ impl EntityWriter { with_serde: &WithSerde, date_time_crate: &DateTimeCrate, serde_skip_deserializing_primary_key: bool, + serde_skip_hidden_column: bool, ) -> TokenStream { let column_names_snake_case = entity.get_column_names_snake_case(); let column_rs_types = entity.get_column_rs_types(date_time_crate); let if_eq_needed = entity.get_eq_needed(); - let serde_skip_deserializing = - entity.get_serde_skip_deserializing(serde_skip_deserializing_primary_key); + let serde_attributes = entity.get_column_serde_attributes( + serde_skip_deserializing_primary_key, + serde_skip_hidden_column, + ); let extra_derive = with_serde.extra_derive(); quote! { #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel #if_eq_needed #extra_derive)] pub struct Model { #( - #serde_skip_deserializing + #serde_attributes pub #column_names_snake_case: #column_rs_types, )* } @@ -596,6 +609,7 @@ impl EntityWriter { date_time_crate: &DateTimeCrate, schema_name: &Option, serde_skip_deserializing_primary_key: bool, + serde_skip_hidden_column: bool, ) -> TokenStream { let table_name = entity.table_name.as_str(); let column_names_snake_case = entity.get_column_names_snake_case(); @@ -641,13 +655,14 @@ impl EntityWriter { } ts = quote! { #[sea_orm(#ts)] }; } - let serde_skip_deserializing = col.get_serde_skip_deserializing( + let serde_attribute = col.get_serde_attribute( is_primary_key, serde_skip_deserializing_primary_key, + serde_skip_hidden_column, ); ts = quote! { #ts - #serde_skip_deserializing + #serde_attribute }; ts }) @@ -1298,6 +1313,7 @@ mod tests { &crate::DateTimeCrate::Chrono, &None, false, + false, ) .into_iter() .skip(1) @@ -1315,6 +1331,7 @@ mod tests { &crate::DateTimeCrate::Chrono, &Some("public".to_owned()), false, + false, ) .into_iter() .skip(1) @@ -1332,6 +1349,7 @@ mod tests { &crate::DateTimeCrate::Chrono, &Some("schema_name".to_owned()), false, + false, ) .into_iter() .skip(1) @@ -1385,6 +1403,7 @@ mod tests { &crate::DateTimeCrate::Chrono, &None, false, + false, ) .into_iter() .skip(1) @@ -1402,6 +1421,7 @@ mod tests { &crate::DateTimeCrate::Chrono, &Some("public".to_owned()), false, + false, ) .into_iter() .skip(1) @@ -1419,6 +1439,7 @@ mod tests { &crate::DateTimeCrate::Chrono, &Some("schema_name".to_owned()), false, + false, ) .into_iter() .skip(1) @@ -1435,7 +1456,7 @@ mod tests { #[test] fn test_gen_with_serde() -> io::Result<()> { - let cake_entity = setup().get(0).unwrap().clone(); + let mut cake_entity = setup().get_mut(0).unwrap().clone(); assert_eq!(cake_entity.get_table_name_snake_case(), "cake"); @@ -1515,6 +1536,32 @@ mod tests { Box::new(EntityWriter::gen_expanded_code_blocks), )?; + // Make the `name` column of `cake` entity as hidden column + cake_entity.columns[1].name = "_name".into(); + + assert_serde_variant_results( + &cake_entity, + &( + include_str!("../../tests/compact_with_serde/cake_serialize_with_hidden_column.rs") + .into(), + WithSerde::Serialize, + None, + ), + Box::new(EntityWriter::gen_compact_code_blocks), + )?; + assert_serde_variant_results( + &cake_entity, + &( + include_str!( + "../../tests/expanded_with_serde/cake_serialize_with_hidden_column.rs" + ) + .into(), + WithSerde::Serialize, + None, + ), + Box::new(EntityWriter::gen_expanded_code_blocks), + )?; + Ok(()) } @@ -1523,13 +1570,23 @@ mod tests { cake_entity: &Entity, entity_serde_variant: &(String, WithSerde, Option), generator: Box< - dyn Fn(&Entity, &WithSerde, &DateTimeCrate, &Option, bool) -> Vec, + dyn Fn( + &Entity, + &WithSerde, + &DateTimeCrate, + &Option, + bool, + bool, + ) -> Vec, >, ) -> io::Result<()> { let mut reader = BufReader::new(entity_serde_variant.0.as_bytes()); let mut lines: Vec = Vec::new(); - let serde_skip_deserializing_primary_key = entity_serde_variant.1 == WithSerde::Both - || entity_serde_variant.1 == WithSerde::Deserialize; + let serde_skip_deserializing_primary_key = matches!( + entity_serde_variant.1, + WithSerde::Both | WithSerde::Deserialize + ); + let serde_skip_hidden_column = matches!(entity_serde_variant.1, WithSerde::Serialize); reader.read_until(b'\n', &mut Vec::new())?; @@ -1547,6 +1604,7 @@ mod tests { &DateTimeCrate::Chrono, &entity_serde_variant.2, serde_skip_deserializing_primary_key, + serde_skip_hidden_column, ) .into_iter() .fold(TokenStream::new(), |mut acc, tok| { diff --git a/sea-orm-codegen/tests/compact_with_serde/cake_serialize_with_hidden_column.rs b/sea-orm-codegen/tests/compact_with_serde/cake_serialize_with_hidden_column.rs new file mode 100644 index 00000000..50aa9dcb --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_serde/cake_serialize_with_hidden_column.rs @@ -0,0 +1,37 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; +use serde::Serialize; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize)] +#[sea_orm(table_name = "cake")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + #[sea_orm(column_name = "_name", column_type = "Text", nullable)] + #[serde(skip)] + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::fruit::Entity")] + Fruit, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_serde/cake_serialize_with_hidden_column.rs b/sea-orm-codegen/tests/expanded_with_serde/cake_serialize_with_hidden_column.rs new file mode 100644 index 00000000..74db3085 --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_serde/cake_serialize_with_hidden_column.rs @@ -0,0 +1,80 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; +use serde::Serialize; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "cake" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Eq, Serialize)] +pub struct Model { + pub id: i32, + #[serde(skip)] + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + #[sea_orm(column_name = "_name")] + Name, +} + +#[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 { + Fruit, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Name => ColumnType::Text.def().null(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Fruit => Entity::has_many(super::fruit::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} From 384ac1bea6e82fe76d8f56ba874443d8b7bde1a6 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 20 Dec 2022 12:59:42 +0800 Subject: [PATCH 17/18] Cont. sea-orm-cli Implement derives & attributes parameters for entity generation (#1321) * sea-orm-cli Implement derives & attributes parameters for entity generation (#1124) * implement derives & attributes for cli * fmt and clippy fix * use comma delimiter for attributes arg * Update help message use `'` instead of `"` to quote * Refactoring * remove unnecessary cloning Co-authored-by: Billy Chan * [CLI] generate model with extra derives and attributes * clippy Co-authored-by: Isaiah Gamble <77396670+tsar-boomba@users.noreply.github.com> --- sea-orm-cli/src/cli.rs | 18 + sea-orm-cli/src/commands/generate.rs | 4 + sea-orm-codegen/src/entity/writer.rs | 502 +++++++++++++++--- .../compact_with_attributes/cake_multiple.rs | 37 ++ .../compact_with_attributes/cake_none.rs | 35 ++ .../tests/compact_with_attributes/cake_one.rs | 36 ++ .../compact_with_derives/cake_multiple.rs | 35 ++ .../tests/compact_with_derives/cake_none.rs | 35 ++ .../tests/compact_with_derives/cake_one.rs | 35 ++ .../expanded_with_attributes/cake_multiple.rs | 79 +++ .../expanded_with_attributes/cake_none.rs | 77 +++ .../expanded_with_attributes/cake_one.rs | 78 +++ .../expanded_with_derives/cake_multiple.rs | 77 +++ .../tests/expanded_with_derives/cake_none.rs | 77 +++ .../tests/expanded_with_derives/cake_one.rs | 77 +++ 15 files changed, 1123 insertions(+), 79 deletions(-) create mode 100644 sea-orm-codegen/tests/compact_with_attributes/cake_multiple.rs create mode 100644 sea-orm-codegen/tests/compact_with_attributes/cake_none.rs create mode 100644 sea-orm-codegen/tests/compact_with_attributes/cake_one.rs create mode 100644 sea-orm-codegen/tests/compact_with_derives/cake_multiple.rs create mode 100644 sea-orm-codegen/tests/compact_with_derives/cake_none.rs create mode 100644 sea-orm-codegen/tests/compact_with_derives/cake_one.rs create mode 100644 sea-orm-codegen/tests/expanded_with_attributes/cake_multiple.rs create mode 100644 sea-orm-codegen/tests/expanded_with_attributes/cake_none.rs create mode 100644 sea-orm-codegen/tests/expanded_with_attributes/cake_one.rs create mode 100644 sea-orm-codegen/tests/expanded_with_derives/cake_multiple.rs create mode 100644 sea-orm-codegen/tests/expanded_with_derives/cake_none.rs create mode 100644 sea-orm-codegen/tests/expanded_with_derives/cake_one.rs diff --git a/sea-orm-cli/src/cli.rs b/sea-orm-cli/src/cli.rs index 9538d402..eafb433a 100644 --- a/sea-orm-cli/src/cli.rs +++ b/sea-orm-cli/src/cli.rs @@ -243,6 +243,24 @@ pub enum GenerateSubcommands { help = "Generate index file as `lib.rs` instead of `mod.rs`." )] lib: bool, + + #[clap( + value_parser, + long, + use_value_delimiter = true, + takes_value = true, + help = "Add extra derive macros to generated model structs (comma separated), ex. `--derives 'ts_rs::Ts'`" + )] + model_extra_derives: Vec, + + #[clap( + value_parser, + long, + use_value_delimiter = true, + takes_value = true, + help = r#"Add extra attributes to generated model struct, no need for `#[]` (comma separated), ex. `--attributes 'serde(rename_all = "camelCase")','ts(export)'`"# + )] + model_extra_attributes: Vec, }, } diff --git a/sea-orm-cli/src/commands/generate.rs b/sea-orm-cli/src/commands/generate.rs index 587504c6..1203e4f2 100644 --- a/sea-orm-cli/src/commands/generate.rs +++ b/sea-orm-cli/src/commands/generate.rs @@ -29,6 +29,8 @@ pub async fn run_generate_command( with_copy_enums, date_time_crate, lib, + model_extra_derives, + model_extra_attributes, } => { if verbose { let _ = tracing_subscriber::fmt() @@ -168,6 +170,8 @@ pub async fn run_generate_command( lib, serde_skip_deserializing_primary_key, serde_skip_hidden_column, + model_extra_derives, + model_extra_attributes, ); let output = EntityTransformer::transform(table_stmts)?.generate(&writer_context); diff --git a/sea-orm-codegen/src/entity/writer.rs b/sea-orm-codegen/src/entity/writer.rs index 8c2ab7f3..5da97365 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -45,6 +45,8 @@ pub struct EntityWriterContext { pub(crate) lib: bool, pub(crate) serde_skip_hidden_column: bool, pub(crate) serde_skip_deserializing_primary_key: bool, + pub(crate) model_extra_derives: TokenStream, + pub(crate) model_extra_attributes: TokenStream, } impl WithSerde { @@ -76,6 +78,37 @@ impl WithSerde { } } +/// Converts model_extra_derives argument to token stream +fn bonus_derive(model_extra_derives: Vec) -> TokenStream +where + T: Into, +{ + model_extra_derives + .into_iter() + .map(Into::::into) + .fold(TokenStream::default(), |acc, derive| { + let tokens: TokenStream = derive.parse().unwrap(); + quote! { #acc, #tokens } + }) +} + +/// convert attributes argument to token stream +fn bonus_attributes(attributes: Vec) -> TokenStream +where + T: Into, +{ + attributes.into_iter().map(Into::::into).fold( + TokenStream::default(), + |acc, attribute| { + let tokens: TokenStream = attribute.parse().unwrap(); + quote! { + #acc + #[#tokens] + } + }, + ) +} + impl FromStr for WithSerde { type Err = crate::Error; @@ -106,6 +139,8 @@ impl EntityWriterContext { lib: bool, serde_skip_deserializing_primary_key: bool, serde_skip_hidden_column: bool, + model_extra_derives: Vec, + model_extra_attributes: Vec, ) -> Self { Self { expanded_format, @@ -116,6 +151,8 @@ impl EntityWriterContext { lib, serde_skip_deserializing_primary_key, serde_skip_hidden_column, + model_extra_derives: bonus_derive(model_extra_derives), + model_extra_attributes: bonus_attributes(model_extra_attributes), } } } @@ -169,6 +206,8 @@ impl EntityWriter { &context.schema_name, serde_skip_deserializing_primary_key, serde_skip_hidden_column, + &context.model_extra_derives, + &context.model_extra_attributes, ) } else { Self::gen_compact_code_blocks( @@ -178,6 +217,8 @@ impl EntityWriter { &context.schema_name, serde_skip_deserializing_primary_key, serde_skip_hidden_column, + &context.model_extra_derives, + &context.model_extra_attributes, ) }; Self::write(&mut lines, code_blocks); @@ -272,6 +313,7 @@ impl EntityWriter { lines.push("".to_owned()); } + #[allow(clippy::too_many_arguments)] pub fn gen_expanded_code_blocks( entity: &Entity, with_serde: &WithSerde, @@ -279,6 +321,8 @@ impl EntityWriter { schema_name: &Option, serde_skip_deserializing_primary_key: bool, serde_skip_hidden_column: bool, + model_extra_derives: &TokenStream, + model_extra_attributes: &TokenStream, ) -> Vec { let mut imports = Self::gen_import(with_serde); imports.extend(Self::gen_import_active_enum(entity)); @@ -292,6 +336,8 @@ impl EntityWriter { date_time_crate, serde_skip_deserializing_primary_key, serde_skip_hidden_column, + model_extra_derives, + model_extra_attributes, ), Self::gen_column_enum(entity), Self::gen_primary_key_enum(entity), @@ -306,6 +352,7 @@ impl EntityWriter { code_blocks } + #[allow(clippy::too_many_arguments)] pub fn gen_compact_code_blocks( entity: &Entity, with_serde: &WithSerde, @@ -313,6 +360,8 @@ impl EntityWriter { schema_name: &Option, serde_skip_deserializing_primary_key: bool, serde_skip_hidden_column: bool, + model_extra_derives: &TokenStream, + model_extra_attributes: &TokenStream, ) -> Vec { let mut imports = Self::gen_import(with_serde); imports.extend(Self::gen_import_active_enum(entity)); @@ -325,6 +374,8 @@ impl EntityWriter { schema_name, serde_skip_deserializing_primary_key, serde_skip_hidden_column, + model_extra_derives, + model_extra_attributes, ), Self::gen_compact_relation_enum(entity), ]; @@ -413,6 +464,8 @@ impl EntityWriter { date_time_crate: &DateTimeCrate, serde_skip_deserializing_primary_key: bool, serde_skip_hidden_column: bool, + model_extra_derives: &TokenStream, + model_extra_attributes: &TokenStream, ) -> TokenStream { let column_names_snake_case = entity.get_column_names_snake_case(); let column_rs_types = entity.get_column_rs_types(date_time_crate); @@ -424,7 +477,8 @@ impl EntityWriter { let extra_derive = with_serde.extra_derive(); quote! { - #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel #if_eq_needed #extra_derive)] + #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel #if_eq_needed #extra_derive #model_extra_derives)] + #model_extra_attributes pub struct Model { #( #serde_attributes @@ -603,6 +657,7 @@ impl EntityWriter { } } + #[allow(clippy::too_many_arguments)] pub fn gen_compact_model_struct( entity: &Entity, with_serde: &WithSerde, @@ -610,6 +665,8 @@ impl EntityWriter { schema_name: &Option, serde_skip_deserializing_primary_key: bool, serde_skip_hidden_column: bool, + model_extra_derives: &TokenStream, + model_extra_attributes: &TokenStream, ) -> TokenStream { let table_name = entity.table_name.as_str(); let column_names_snake_case = entity.get_column_names_snake_case(); @@ -676,11 +733,12 @@ impl EntityWriter { let extra_derive = with_serde.extra_derive(); quote! { - #[derive(Clone, Debug, PartialEq, DeriveEntityModel #if_eq_needed #extra_derive)] + #[derive(Clone, Debug, PartialEq, DeriveEntityModel #if_eq_needed #extra_derive #model_extra_derives)] #[sea_orm( #schema_name table_name = #table_name )] + #model_extra_attributes pub struct Model { #( #attrs @@ -721,6 +779,7 @@ impl EntityWriter { #[cfg(test)] mod tests { use crate::{ + entity::writer::{bonus_attributes, bonus_derive}, Column, ConjunctRelation, DateTimeCrate, Entity, EntityWriter, PrimaryKey, Relation, RelationType, WithSerde, }; @@ -1314,6 +1373,8 @@ mod tests { &None, false, false, + &TokenStream::new(), + &TokenStream::new(), ) .into_iter() .skip(1) @@ -1332,6 +1393,8 @@ mod tests { &Some("public".to_owned()), false, false, + &TokenStream::new(), + &TokenStream::new(), ) .into_iter() .skip(1) @@ -1350,6 +1413,8 @@ mod tests { &Some("schema_name".to_owned()), false, false, + &TokenStream::new(), + &TokenStream::new(), ) .into_iter() .skip(1) @@ -1404,6 +1469,8 @@ mod tests { &None, false, false, + &TokenStream::new(), + &TokenStream::new(), ) .into_iter() .skip(1) @@ -1422,6 +1489,8 @@ mod tests { &Some("public".to_owned()), false, false, + &TokenStream::new(), + &TokenStream::new(), ) .into_iter() .skip(1) @@ -1440,6 +1509,8 @@ mod tests { &Some("schema_name".to_owned()), false, false, + &TokenStream::new(), + &TokenStream::new(), ) .into_iter() .skip(1) @@ -1456,85 +1527,226 @@ mod tests { #[test] fn test_gen_with_serde() -> io::Result<()> { + let cake_entity = setup().get(0).unwrap().clone(); + + assert_eq!(cake_entity.get_table_name_snake_case(), "cake"); + + // Compact code blocks + assert_eq!( + comparable_file_string(include_str!("../../tests/compact_with_serde/cake_none.rs"))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::None, + &DateTimeCrate::Chrono, + &None, + false, + false, + &TokenStream::new(), + &TokenStream::new(), + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/compact_with_serde/cake_serialize.rs" + ))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::Serialize, + &DateTimeCrate::Chrono, + &None, + false, + false, + &TokenStream::new(), + &TokenStream::new(), + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/compact_with_serde/cake_deserialize.rs" + ))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::Deserialize, + &DateTimeCrate::Chrono, + &None, + true, + false, + &TokenStream::new(), + &TokenStream::new(), + )) + ); + assert_eq!( + comparable_file_string(include_str!("../../tests/compact_with_serde/cake_both.rs"))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::Both, + &DateTimeCrate::Chrono, + &None, + true, + false, + &TokenStream::new(), + &TokenStream::new(), + )) + ); + + // Expanded code blocks + assert_eq!( + comparable_file_string(include_str!("../../tests/expanded_with_serde/cake_none.rs"))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::None, + &DateTimeCrate::Chrono, + &None, + false, + false, + &TokenStream::new(), + &TokenStream::new(), + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/expanded_with_serde/cake_serialize.rs" + ))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::Serialize, + &DateTimeCrate::Chrono, + &None, + false, + false, + &TokenStream::new(), + &TokenStream::new(), + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/expanded_with_serde/cake_deserialize.rs" + ))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::Deserialize, + &DateTimeCrate::Chrono, + &None, + true, + false, + &TokenStream::new(), + &TokenStream::new(), + )) + ); + assert_eq!( + comparable_file_string(include_str!("../../tests/expanded_with_serde/cake_both.rs"))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::Both, + &DateTimeCrate::Chrono, + &None, + true, + false, + &TokenStream::new(), + &TokenStream::new(), + )) + ); + + Ok(()) + } + + #[test] + fn test_gen_with_derives() -> io::Result<()> { let mut cake_entity = setup().get_mut(0).unwrap().clone(); assert_eq!(cake_entity.get_table_name_snake_case(), "cake"); // Compact code blocks - assert_serde_variant_results( - &cake_entity, - &( - include_str!("../../tests/compact_with_serde/cake_none.rs").into(), - WithSerde::None, - None, - ), - Box::new(EntityWriter::gen_compact_code_blocks), - )?; - assert_serde_variant_results( - &cake_entity, - &( - include_str!("../../tests/compact_with_serde/cake_serialize.rs").into(), - WithSerde::Serialize, - None, - ), - Box::new(EntityWriter::gen_compact_code_blocks), - )?; - assert_serde_variant_results( - &cake_entity, - &( - include_str!("../../tests/compact_with_serde/cake_deserialize.rs").into(), - WithSerde::Deserialize, - None, - ), - Box::new(EntityWriter::gen_compact_code_blocks), - )?; - assert_serde_variant_results( - &cake_entity, - &( - include_str!("../../tests/compact_with_serde/cake_both.rs").into(), - WithSerde::Both, - None, - ), - Box::new(EntityWriter::gen_compact_code_blocks), - )?; + assert_eq!( + comparable_file_string(include_str!( + "../../tests/compact_with_derives/cake_none.rs" + ))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::None, + &DateTimeCrate::Chrono, + &None, + false, + false, + &TokenStream::new(), + &TokenStream::new(), + )) + ); + assert_eq!( + comparable_file_string(include_str!("../../tests/compact_with_derives/cake_one.rs"))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::None, + &DateTimeCrate::Chrono, + &None, + false, + false, + &bonus_derive(vec!["ts_rs::TS"]), + &TokenStream::new(), + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/compact_with_derives/cake_multiple.rs" + ))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::None, + &DateTimeCrate::Chrono, + &None, + false, + false, + &bonus_derive(vec!["ts_rs::TS", "utoipa::ToSchema"]), + &TokenStream::new(), + )) + ); // Expanded code blocks - assert_serde_variant_results( - &cake_entity, - &( - include_str!("../../tests/expanded_with_serde/cake_none.rs").into(), - WithSerde::None, - None, - ), - Box::new(EntityWriter::gen_expanded_code_blocks), - )?; - assert_serde_variant_results( - &cake_entity, - &( - include_str!("../../tests/expanded_with_serde/cake_serialize.rs").into(), - WithSerde::Serialize, - None, - ), - Box::new(EntityWriter::gen_expanded_code_blocks), - )?; - assert_serde_variant_results( - &cake_entity, - &( - include_str!("../../tests/expanded_with_serde/cake_deserialize.rs").into(), - WithSerde::Deserialize, - None, - ), - Box::new(EntityWriter::gen_expanded_code_blocks), - )?; - assert_serde_variant_results( - &cake_entity, - &( - include_str!("../../tests/expanded_with_serde/cake_both.rs").into(), - WithSerde::Both, - None, - ), - Box::new(EntityWriter::gen_expanded_code_blocks), - )?; + assert_eq!( + comparable_file_string(include_str!( + "../../tests/expanded_with_derives/cake_none.rs" + ))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::None, + &DateTimeCrate::Chrono, + &None, + false, + false, + &TokenStream::new(), + &TokenStream::new(), + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/expanded_with_derives/cake_one.rs" + ))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::None, + &DateTimeCrate::Chrono, + &None, + false, + false, + &bonus_derive(vec!["ts_rs::TS"]), + &TokenStream::new(), + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/expanded_with_derives/cake_multiple.rs" + ))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::None, + &DateTimeCrate::Chrono, + &None, + false, + false, + &bonus_derive(vec!["ts_rs::TS", "utoipa::ToSchema"]), + &TokenStream::new(), + )) + ); // Make the `name` column of `cake` entity as hidden column cake_entity.columns[1].name = "_name".into(); @@ -1542,8 +1754,7 @@ mod tests { assert_serde_variant_results( &cake_entity, &( - include_str!("../../tests/compact_with_serde/cake_serialize_with_hidden_column.rs") - .into(), + include_str!("../../tests/compact_with_serde/cake_serialize_with_hidden_column.rs"), WithSerde::Serialize, None, ), @@ -1554,8 +1765,7 @@ mod tests { &( include_str!( "../../tests/expanded_with_serde/cake_serialize_with_hidden_column.rs" - ) - .into(), + ), WithSerde::Serialize, None, ), @@ -1568,7 +1778,7 @@ mod tests { #[allow(clippy::type_complexity)] fn assert_serde_variant_results( cake_entity: &Entity, - entity_serde_variant: &(String, WithSerde, Option), + entity_serde_variant: &(&str, WithSerde, Option), generator: Box< dyn Fn( &Entity, @@ -1577,6 +1787,8 @@ mod tests { &Option, bool, bool, + &TokenStream, + &TokenStream, ) -> Vec, >, ) -> io::Result<()> { @@ -1605,6 +1817,8 @@ mod tests { &entity_serde_variant.2, serde_skip_deserializing_primary_key, serde_skip_hidden_column, + &TokenStream::new(), + &TokenStream::new(), ) .into_iter() .fold(TokenStream::new(), |mut acc, tok| { @@ -1615,4 +1829,134 @@ mod tests { assert_eq!(expected.to_string(), generated.to_string()); Ok(()) } + + #[test] + fn test_gen_with_attributes() -> io::Result<()> { + let cake_entity = setup().get(0).unwrap().clone(); + + assert_eq!(cake_entity.get_table_name_snake_case(), "cake"); + + // Compact code blocks + assert_eq!( + comparable_file_string(include_str!( + "../../tests/compact_with_attributes/cake_none.rs" + ))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::None, + &DateTimeCrate::Chrono, + &None, + false, + false, + &TokenStream::new(), + &TokenStream::new(), + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/compact_with_attributes/cake_one.rs" + ))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::None, + &DateTimeCrate::Chrono, + &None, + false, + false, + &TokenStream::new(), + &bonus_attributes(vec![r#"serde(rename_all = "camelCase")"#]), + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/compact_with_attributes/cake_multiple.rs" + ))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::None, + &DateTimeCrate::Chrono, + &None, + false, + false, + &TokenStream::new(), + &bonus_attributes(vec![r#"serde(rename_all = "camelCase")"#, "ts(export)"]), + )) + ); + + // Expanded code blocks + assert_eq!( + comparable_file_string(include_str!( + "../../tests/expanded_with_attributes/cake_none.rs" + ))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::None, + &DateTimeCrate::Chrono, + &None, + false, + false, + &TokenStream::new(), + &TokenStream::new(), + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/expanded_with_attributes/cake_one.rs" + ))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::None, + &DateTimeCrate::Chrono, + &None, + false, + false, + &TokenStream::new(), + &bonus_attributes(vec![r#"serde(rename_all = "camelCase")"#]), + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/expanded_with_attributes/cake_multiple.rs" + ))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::None, + &DateTimeCrate::Chrono, + &None, + false, + false, + &TokenStream::new(), + &bonus_attributes(vec![r#"serde(rename_all = "camelCase")"#, "ts(export)"]), + )) + ); + + Ok(()) + } + + fn generated_to_string(generated: Vec) -> String { + generated + .into_iter() + .fold(TokenStream::new(), |mut acc, tok| { + acc.extend(tok); + acc + }) + .to_string() + } + + fn comparable_file_string(file: &str) -> io::Result { + let mut reader = BufReader::new(file.as_bytes()); + let mut lines: Vec = Vec::new(); + + reader.read_until(b'\n', &mut Vec::new())?; + + let mut line = String::new(); + while reader.read_line(&mut line)? > 0 { + lines.push(line.to_owned()); + line.clear(); + } + let content = lines.join(""); + let expected: TokenStream = content.parse().unwrap(); + + Ok(expected.to_string()) + } } diff --git a/sea-orm-codegen/tests/compact_with_attributes/cake_multiple.rs b/sea-orm-codegen/tests/compact_with_attributes/cake_multiple.rs new file mode 100644 index 00000000..795a3b9b --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_attributes/cake_multiple.rs @@ -0,0 +1,37 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "cake")] +#[serde(rename_all = "camelCase")] +#[ts(export)] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + #[sea_orm(column_type = "Text", nullable)] + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::fruit::Entity")] + Fruit, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/compact_with_attributes/cake_none.rs b/sea-orm-codegen/tests/compact_with_attributes/cake_none.rs new file mode 100644 index 00000000..d72ea6b2 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_attributes/cake_none.rs @@ -0,0 +1,35 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "cake")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + #[sea_orm(column_type = "Text", nullable)] + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::fruit::Entity")] + Fruit, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/compact_with_attributes/cake_one.rs b/sea-orm-codegen/tests/compact_with_attributes/cake_one.rs new file mode 100644 index 00000000..11162ca1 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_attributes/cake_one.rs @@ -0,0 +1,36 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "cake")] +#[serde(rename_all = "camelCase")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + #[sea_orm(column_type = "Text", nullable)] + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::fruit::Entity")] + Fruit, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/compact_with_derives/cake_multiple.rs b/sea-orm-codegen/tests/compact_with_derives/cake_multiple.rs new file mode 100644 index 00000000..dd69de77 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_derives/cake_multiple.rs @@ -0,0 +1,35 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, ts_rs::TS, utoipa::ToSchema)] +#[sea_orm(table_name = "cake")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + #[sea_orm(column_type = "Text", nullable)] + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::fruit::Entity")] + Fruit, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/compact_with_derives/cake_none.rs b/sea-orm-codegen/tests/compact_with_derives/cake_none.rs new file mode 100644 index 00000000..d72ea6b2 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_derives/cake_none.rs @@ -0,0 +1,35 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "cake")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + #[sea_orm(column_type = "Text", nullable)] + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::fruit::Entity")] + Fruit, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/compact_with_derives/cake_one.rs b/sea-orm-codegen/tests/compact_with_derives/cake_one.rs new file mode 100644 index 00000000..9a4aeaba --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_derives/cake_one.rs @@ -0,0 +1,35 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, ts_rs::TS)] +#[sea_orm(table_name = "cake")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + #[sea_orm(column_type = "Text", nullable)] + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::fruit::Entity")] + Fruit, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_attributes/cake_multiple.rs b/sea-orm-codegen/tests/expanded_with_attributes/cake_multiple.rs new file mode 100644 index 00000000..5c498d83 --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_attributes/cake_multiple.rs @@ -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 { + "cake" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Eq)] +#[serde(rename_all = "camelCase")] +#[ts(export)] +pub struct Model { + pub id: i32, + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Name, +} + +#[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 { + Fruit, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Name => ColumnType::Text.def().null(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Fruit => Entity::has_many(super::fruit::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_attributes/cake_none.rs b/sea-orm-codegen/tests/expanded_with_attributes/cake_none.rs new file mode 100644 index 00000000..a540fad1 --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_attributes/cake_none.rs @@ -0,0 +1,77 @@ +//! 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 { + "cake" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Eq)] +pub struct Model { + pub id: i32, + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Name, +} + +#[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 { + Fruit, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Name => ColumnType::Text.def().null(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Fruit => Entity::has_many(super::fruit::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_attributes/cake_one.rs b/sea-orm-codegen/tests/expanded_with_attributes/cake_one.rs new file mode 100644 index 00000000..77da3181 --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_attributes/cake_one.rs @@ -0,0 +1,78 @@ +//! 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 { + "cake" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Eq)] +#[serde(rename_all = "camelCase")] +pub struct Model { + pub id: i32, + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Name, +} + +#[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 { + Fruit, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Name => ColumnType::Text.def().null(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Fruit => Entity::has_many(super::fruit::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_derives/cake_multiple.rs b/sea-orm-codegen/tests/expanded_with_derives/cake_multiple.rs new file mode 100644 index 00000000..c04dfdd4 --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_derives/cake_multiple.rs @@ -0,0 +1,77 @@ +//! 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 { + "cake" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Eq, ts_rs::TS, utoipa::ToSchema)] +pub struct Model { + pub id: i32, + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Name, +} + +#[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 { + Fruit, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Name => ColumnType::Text.def().null(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Fruit => Entity::has_many(super::fruit::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_derives/cake_none.rs b/sea-orm-codegen/tests/expanded_with_derives/cake_none.rs new file mode 100644 index 00000000..a540fad1 --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_derives/cake_none.rs @@ -0,0 +1,77 @@ +//! 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 { + "cake" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Eq)] +pub struct Model { + pub id: i32, + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Name, +} + +#[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 { + Fruit, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Name => ColumnType::Text.def().null(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Fruit => Entity::has_many(super::fruit::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_derives/cake_one.rs b/sea-orm-codegen/tests/expanded_with_derives/cake_one.rs new file mode 100644 index 00000000..a4ebdf82 --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_derives/cake_one.rs @@ -0,0 +1,77 @@ +//! 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 { + "cake" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Eq, ts_rs::TS)] +pub struct Model { + pub id: i32, + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Name, +} + +#[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 { + Fruit, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Name => ColumnType::Text.def().null(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Fruit => Entity::has_many(super::fruit::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} From 83d46d9786293b798da32478b5d3f27f75e674d8 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Tue, 20 Dec 2022 15:00:09 +0800 Subject: [PATCH 18/18] CHANGELOG --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92783f11..e561dec0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,11 +10,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### New Features * Transactions Isolation level and Access mode https://github.com/SeaQL/sea-orm/pull/1230 +* [sea-orm-cli] Generate `#[serde(skip_deserializing)]` for primary key columns https://github.com/SeaQL/sea-orm/pull/846, https://github.com/SeaQL/sea-orm/pull/1186, https://github.com/SeaQL/sea-orm/pull/1318 +* [sea-orm-cli] Generate `#[serde(skip)]` for hidden columns https://github.com/SeaQL/sea-orm/pull/1171, https://github.com/SeaQL/sea-orm/pull/1320 +* [sea-orm-cli] Generate entity with extra derives and attributes for model struct https://github.com/SeaQL/sea-orm/pull/1124, https://github.com/SeaQL/sea-orm/pull/1321 ### Enhancements * Support Vector of enum for Postgres https://github.com/SeaQL/sea-orm/pull/1210 * Added `DatabaseConnection::close` https://github.com/SeaQL/sea-orm/pull/1236 +* Refactor schema module to expose functions for database alteration https://github.com/SeaQL/sea-orm/pull/1256 ### Upgrades @@ -32,6 +36,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## 0.10.6 - Pending +### Enhancements + +* Cast enum values when constructing update many query https://github.com/SeaQL/sea-orm/pull/1178 + ### Bug Fixes * [sea-orm-codegen] Skip implementing Related if the same related entity is being referenced by a conjunct relation https://github.com/SeaQL/sea-orm/pull/1298