diff --git a/.github/workflows/diesel.yml b/.github/workflows/diesel.yml index 99879fa58..192003c98 100644 --- a/.github/workflows/diesel.yml +++ b/.github/workflows/diesel.yml @@ -29,7 +29,7 @@ jobs: name: Rustfmt runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: toolchain: nightly @@ -42,10 +42,9 @@ jobs: name: Build `sea-query-diesel` runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - - run: cargo update --manifest-path sea-query-diesel/Cargo.toml --workspace -p bigdecimal:0.4.5 --precise 0.3.1 - - run: cargo build --manifest-path sea-query-diesel/Cargo.toml --workspace --features postgres,sqlite,mysql --features=with-chrono,with-json,with-rust_decimal,with-bigdecimal,with-uuid,with-time,with-ipnetwork,with-mac_address,postgres-array + - run: cargo build --manifest-path sea-query-diesel/Cargo.toml --workspace --features postgres,sqlite,mysql --features=with-chrono,with-json,with-rust_decimal,with-bigdecimal,with-uuid,with-time,with-ipnetwork,with-mac_address,postgres-array,postgres-vector - run: cargo build --manifest-path sea-query-diesel/Cargo.toml --workspace --features postgres,sqlite,mysql --features=with-chrono - run: cargo build --manifest-path sea-query-diesel/Cargo.toml --workspace --features postgres,sqlite,mysql --features=with-json - run: cargo build --manifest-path sea-query-diesel/Cargo.toml --workspace --features postgres,sqlite,mysql --features=with-rust_decimal @@ -57,6 +56,7 @@ jobs: - run: cargo build --manifest-path sea-query-diesel/Cargo.toml --workspace --features postgres,sqlite,mysql --features=with-ipnetwork - run: cargo build --manifest-path sea-query-diesel/Cargo.toml --workspace --features postgres,sqlite,mysql --features=with-mac_address - run: cargo build --manifest-path sea-query-diesel/Cargo.toml --workspace --features postgres,sqlite,mysql --features=postgres-array + - run: cargo build --manifest-path sea-query-diesel/Cargo.toml --workspace --features postgres,sqlite,mysql --features=postgres-vector sqlite: name: SQLite @@ -66,7 +66,7 @@ jobs: matrix: example: [diesel_sqlite] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: cargo build --manifest-path examples/${{ matrix.example }}/Cargo.toml - run: cargo run --manifest-path examples/${{ matrix.example }}/Cargo.toml @@ -96,7 +96,7 @@ jobs: --health-timeout=5s --health-retries=3 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: cargo build --manifest-path examples/${{ matrix.example }}/Cargo.toml - run: cargo run --manifest-path examples/${{ matrix.example }}/Cargo.toml @@ -126,7 +126,7 @@ jobs: --health-timeout=5s --health-retries=3 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: cargo build --manifest-path examples/${{ matrix.example }}/Cargo.toml - run: cargo run --manifest-path examples/${{ matrix.example }}/Cargo.toml @@ -155,8 +155,7 @@ jobs: --health-timeout 5s --health-retries 5 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - - run: cargo update --manifest-path examples/${{ matrix.example }}/Cargo.toml -p bigdecimal:0.4.5 --precise 0.3.1 - run: cargo build --manifest-path examples/${{ matrix.example }}/Cargo.toml - run: cargo run --manifest-path examples/${{ matrix.example }}/Cargo.toml diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index b2c763357..af5fc7b85 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -29,7 +29,7 @@ jobs: name: Rustfmt runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: toolchain: nightly @@ -51,13 +51,13 @@ jobs: name: Clippy runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: toolchain: stable components: clippy - run: cargo clippy --features=all-features --workspace -- -D warnings - - run: cargo clippy --manifest-path sea-query-binder/Cargo.toml --workspace --features runtime-async-std-rustls --features=with-chrono,with-json,with-rust_decimal,with-bigdecimal,with-uuid,with-time,with-ipnetwork,with-mac_address,postgres-array -- -D warnings + - run: cargo clippy --manifest-path sea-query-binder/Cargo.toml --workspace --features runtime-async-std-rustls --features=with-chrono,with-json,with-rust_decimal,with-bigdecimal,with-uuid,with-time,with-ipnetwork,with-mac_address,postgres-array,postgres-vector -- -D warnings - run: cargo clippy --manifest-path sea-query-rusqlite/Cargo.toml --all-features --workspace -- -D warnings - run: cargo clippy --manifest-path sea-query-postgres/Cargo.toml --all-features --workspace -- -D warnings @@ -65,7 +65,7 @@ jobs: name: Build `sea-query` runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: cargo build --workspace --no-default-features - run: cargo build --workspace --all-features @@ -78,6 +78,7 @@ jobs: - run: cargo build --workspace --features=with-ipnetwork - run: cargo build --workspace --features=with-mac_address - run: cargo build --workspace --features=postgres-array + - run: cargo build --workspace --features=postgres-vector - run: cargo build --workspace --features=thread-safe binder-build: @@ -89,9 +90,9 @@ jobs: runtime: [async-std] tls: [rustls] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - - run: cargo build --manifest-path sea-query-binder/Cargo.toml --workspace --features sqlx-postgres,sqlx-sqlite,sqlx-any,sqlx-mysql --features=runtime-${{ matrix.runtime }}-${{ matrix.tls }} --features=with-chrono,with-json,with-rust_decimal,with-bigdecimal,with-uuid,with-time,with-ipnetwork,with-mac_address,postgres-array + - run: cargo build --manifest-path sea-query-binder/Cargo.toml --workspace --features sqlx-postgres,sqlx-sqlite,sqlx-any,sqlx-mysql --features=runtime-${{ matrix.runtime }}-${{ matrix.tls }} --features=with-chrono,with-json,with-rust_decimal,with-bigdecimal,with-uuid,with-time,with-ipnetwork,with-mac_address,postgres-array,postgres-vector - run: cargo build --manifest-path sea-query-binder/Cargo.toml --workspace --features sqlx-postgres,sqlx-sqlite,sqlx-any,sqlx-mysql --features=runtime-${{ matrix.runtime }}-${{ matrix.tls }} --features=with-chrono - run: cargo build --manifest-path sea-query-binder/Cargo.toml --workspace --features sqlx-postgres,sqlx-sqlite,sqlx-any,sqlx-mysql --features=runtime-${{ matrix.runtime }}-${{ matrix.tls }} --features=with-json - run: cargo build --manifest-path sea-query-binder/Cargo.toml --workspace --features sqlx-postgres,sqlx-sqlite,sqlx-any,sqlx-mysql --features=runtime-${{ matrix.runtime }}-${{ matrix.tls }} --features=with-rust_decimal @@ -101,14 +102,15 @@ jobs: - run: cargo build --manifest-path sea-query-binder/Cargo.toml --workspace --features sqlx-postgres,sqlx-sqlite,sqlx-any,sqlx-mysql --features=runtime-${{ matrix.runtime }}-${{ matrix.tls }} --features=with-ipnetwork - run: cargo build --manifest-path sea-query-binder/Cargo.toml --workspace --features sqlx-postgres,sqlx-sqlite,sqlx-any,sqlx-mysql --features=runtime-${{ matrix.runtime }}-${{ matrix.tls }} --features=with-mac_address - run: cargo build --manifest-path sea-query-binder/Cargo.toml --workspace --features sqlx-postgres,sqlx-sqlite,sqlx-any,sqlx-mysql --features=runtime-${{ matrix.runtime }}-${{ matrix.tls }} --features=postgres-array + - run: cargo build --manifest-path sea-query-binder/Cargo.toml --workspace --features sqlx-postgres,sqlx-sqlite,sqlx-any,sqlx-mysql --features=runtime-${{ matrix.runtime }}-${{ matrix.tls }} --features=postgres-vector rusqlite-build: name: Build `sea-query-rusqlite` runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - - run: cargo build --manifest-path sea-query-rusqlite/Cargo.toml --workspace --features=with-chrono,with-json,with-rust_decimal,with-bigdecimal,with-uuid,with-time,with-ipnetwork,with-mac_address,postgres-array + - run: cargo build --manifest-path sea-query-rusqlite/Cargo.toml --workspace --features=with-chrono,with-json,with-rust_decimal,with-bigdecimal,with-uuid,with-time,with-ipnetwork,with-mac_address,postgres-array,postgres-vector - run: cargo build --manifest-path sea-query-rusqlite/Cargo.toml --workspace --features=with-chrono - run: cargo build --manifest-path sea-query-rusqlite/Cargo.toml --workspace --features=with-json - run: cargo build --manifest-path sea-query-rusqlite/Cargo.toml --workspace --features=with-rust_decimal @@ -118,14 +120,15 @@ jobs: - run: cargo build --manifest-path sea-query-rusqlite/Cargo.toml --workspace --features=with-ipnetwork - run: cargo build --manifest-path sea-query-rusqlite/Cargo.toml --workspace --features=with-mac_address - run: cargo build --manifest-path sea-query-rusqlite/Cargo.toml --workspace --features=postgres-array + - run: cargo build --manifest-path sea-query-rusqlite/Cargo.toml --workspace --features=postgres-vector postgres-build: name: Build `sea-query-postgres` runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - - run: cargo build --manifest-path sea-query-postgres/Cargo.toml --workspace --features=with-chrono,with-json,with-rust_decimal,with-bigdecimal,with-uuid,with-time,with-ipnetwork,with-mac_address,postgres-array + - run: cargo build --manifest-path sea-query-postgres/Cargo.toml --workspace --features=with-chrono,with-json,with-rust_decimal,with-bigdecimal,with-uuid,with-time,with-ipnetwork,with-mac_address,postgres-array,postgres-vector - run: cargo build --manifest-path sea-query-postgres/Cargo.toml --workspace --features=with-chrono - run: cargo build --manifest-path sea-query-postgres/Cargo.toml --workspace --features=with-json - run: cargo build --manifest-path sea-query-postgres/Cargo.toml --workspace --features=with-rust_decimal @@ -135,14 +138,16 @@ jobs: - run: cargo build --manifest-path sea-query-postgres/Cargo.toml --workspace --features=with-ipnetwork - run: cargo build --manifest-path sea-query-postgres/Cargo.toml --workspace --features=with-mac_address - run: cargo build --manifest-path sea-query-postgres/Cargo.toml --workspace --features=postgres-array + - run: cargo build --manifest-path sea-query-postgres/Cargo.toml --workspace --features=postgres-vector test: name: Unit Test runs-on: ubuntu-latest needs: ["build"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable + - run: cargo test - run: cargo test --features=all-features - run: cargo test --test option-more-parentheses --features=tests-cfg,option-more-parentheses @@ -151,7 +156,7 @@ jobs: runs-on: ubuntu-latest needs: ["build"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: cargo build --package sea-query-derive - run: cargo test --package sea-query-derive @@ -164,7 +169,7 @@ jobs: matrix: example: [rusqlite, sqlx_sqlite] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: cargo build --manifest-path examples/${{ matrix.example }}/Cargo.toml - run: cargo run --manifest-path examples/${{ matrix.example }}/Cargo.toml @@ -194,7 +199,7 @@ jobs: --health-timeout=5s --health-retries=3 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: cargo build --manifest-path examples/${{ matrix.example }}/Cargo.toml - run: cargo run --manifest-path examples/${{ matrix.example }}/Cargo.toml @@ -224,7 +229,7 @@ jobs: --health-timeout=5s --health-retries=3 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: cargo build --manifest-path examples/${{ matrix.example }}/Cargo.toml - run: cargo run --manifest-path examples/${{ matrix.example }}/Cargo.toml @@ -253,7 +258,7 @@ jobs: --health-timeout 5s --health-retries 5 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: cargo build --manifest-path examples/${{ matrix.example }}/Cargo.toml - run: cargo run --manifest-path examples/${{ matrix.example }}/Cargo.toml @@ -263,6 +268,6 @@ jobs: runs-on: ubuntu-latest needs: ["test", "derive-test", "binder-build"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: cargo build --manifest-path examples/sqlx_any/Cargo.toml diff --git a/CHANGELOG.md b/CHANGELOG.md index 339581cd7..4040c73f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,50 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## 0.31.0 - Pending +## 0.32.0 - Pending + +### Versions + ++ `sea-query`/`0.32.0-rc.1`: 2024-08-09 ++ `sea-query-binder`/`0.7.0-rc.1`: 2024-08-09 ++ `sea-query-binder`/`0.7.0-rc.2`: 2024-08-09 ++ `sea-query-rusqlite`/`0.7.0-rc.1`: 2024-08-09 ++ `sea-query-postgres`/`0.5.0-rc.1`: 2024-08-09 + +### New Features + +* Construct Postgres query with vector extension https://github.com/SeaQL/sea-query/pull/774 +```rust +assert_eq!( + Query::select() + .columns([Char::Character]) + .from(Char::Table) + .and_where( + Expr::col(Char::Character).eq(Expr::val(pgvector::Vector::from(vec![1.0, 2.0]))) + ) + .to_string(PostgresQueryBuilder), + r#"SELECT "character" FROM "character" WHERE "character" = '[1,2]'"# +); +``` +* Added `postgres-vector` feature https://github.com/SeaQL/sea-query/pull/774 +* Added `Value::Vector` https://github.com/SeaQL/sea-query/pull/774 +* Added `ColumnType::Vector` https://github.com/SeaQL/sea-query/pull/774 +* Added `ColumnDef::vector()` https://github.com/SeaQL/sea-query/pull/774 +* Added `PgBinOper::EuclideanDistance`, `PgBinOper::NegativeInnerProduct` and `PgBinOper::CosineDistance` https://github.com/SeaQL/sea-query/pull/774 + +### Upgrades + +* Upgrade `sqlx` to `0.8` https://github.com/SeaQL/sea-query/pull/798 +* Upgrade `bigdecimal` to `0.4` https://github.com/SeaQL/sea-query/pull/798 + +## 0.31.1 - Pending + +### Enhancements + +* Added Md5 function https://github.com/SeaQL/sea-query/pull/786 +* Added Postgres Json functions: `JSON_BUILD_OBJECT` and `JSON_AGG` https://github.com/SeaQL/sea-query/pull/787 + +## 0.31.0 - 2024-08-02 ### Versions @@ -18,8 +61,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/). + `sea-query-binder`/`0.6.0-rc.1`: 2024-01-31 + `sea-query-binder`/`0.6.0-rc.2`: 2024-04-14 + `sea-query-binder`/`0.6.0-rc.3`: 2024-06-19 ++ `sea-query-binder`/`0.6.0-rc.4`: 2024-06-25 ++ `sea-query-binder`/`0.6.0`: 2024-08-02 + `sea-query-rusqlite`/`0.6.0-rc.1`: 2024-02-19 ++ `sea-query-rusqlite`/`0.6.0`: 2024-08-02 + `sea-query-attr`/`0.1.2`: 2024-04-14 ++ `sea-query-diesel`/`0.2.0`: 2024-08-02 ### New Features @@ -152,6 +199,7 @@ pub enum StringLen { ### Upgrades * Upgrade `rusqlite` to `0.31` https://github.com/SeaQL/sea-query/pull/755 +* Upgrade `time` to `0.3.36` https://github.com/SeaQL/sea-query/pull/788 ## 0.30.8 - Pending diff --git a/Cargo.toml b/Cargo.toml index 37ead8f44..f66694fe9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = [".", "sea-query-derive"] [package] name = "sea-query" -version = "0.31.0-rc.8" +version = "0.32.0-rc.1" authors = [ "Chris Tsang ", "Billy Chan ", @@ -35,10 +35,11 @@ serde_json = { version = "1", default-features = false, optional = true, feature educe = { version = "=0.5.11", default-features = false, optional = true, features = ["Hash", "PartialEq", "Eq"] } chrono = { version = "0.4.27", default-features = false, optional = true, features = ["clock"] } postgres-types = { version = "0", default-features = false, optional = true } +pgvector = { version = "~0.4", default-features = false, optional = true } rust_decimal = { version = "1", default-features = false, optional = true } -bigdecimal = { version = "0.3", default-features = false, optional = true } +bigdecimal = { version = "0.4", default-features = false, optional = true } uuid = { version = "1", default-features = false, optional = true } -time = { version = "0.3", default-features = false, optional = true, features = ["macros", "formatting"] } +time = { version = "0.3.36", default-features = false, optional = true, features = ["macros", "formatting"] } ipnetwork = { version = "0.20", default-features = false, optional = true } mac_address = { version = "1.1", default-features = false, optional = true } ordered-float = { version = "3.4", default-features = false, optional = true } @@ -58,6 +59,7 @@ derive = ["sea-query-derive"] attr = ["sea-query-attr"] hashable-value = ["educe", "ordered-float"] postgres-array = [] +postgres-vector = ["pgvector"] postgres-interval = [] thread-safe = [] with-chrono = ["chrono"] @@ -80,6 +82,7 @@ all-features = [ "all-types", ] # everything except option-* all-types = [ + "postgres-vector", "postgres-array", "postgres-interval", "with-chrono", diff --git a/examples/diesel_mysql/Cargo.toml b/examples/diesel_mysql/Cargo.toml index d7c67ca0d..8b8607aee 100644 --- a/examples/diesel_mysql/Cargo.toml +++ b/examples/diesel_mysql/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [dependencies] chrono = { version = "0.4", default-features = false, features = ["clock"] } -time = { version = "0.3", features = ["parsing", "macros"] } +time = { version = "0.3.36", features = ["parsing", "macros"] } serde_json = { version = "1" } uuid = { version = "1", features = ["serde", "v4"] } diesel = { version = "2.1.1", features = ["mysql"] } diff --git a/examples/diesel_postgres/Cargo.toml b/examples/diesel_postgres/Cargo.toml index 580378ba9..078dc399f 100644 --- a/examples/diesel_postgres/Cargo.toml +++ b/examples/diesel_postgres/Cargo.toml @@ -8,13 +8,13 @@ edition = "2021" [dependencies] chrono = { version = "0.4", default-features = false, features = ["clock"] } -time = { version = "0.3", features = ["parsing", "macros"] } +time = { version = "0.3.36", features = ["parsing", "macros"] } serde_json = { version = "1" } uuid = { version = "1", features = ["serde", "v4"] } ipnetwork = { version = "0.20" } mac_address = { version = "1.1" } rust_decimal = { version = "1" } -bigdecimal = { version = "0.3" } +bigdecimal = { version = "0.4" } diesel = { version = "2.1.1", features = ["postgres"] } sea-query = { path = "../.." } sea-query-diesel = { path = "../../sea-query-diesel", features = [ diff --git a/examples/diesel_sqlite/Cargo.toml b/examples/diesel_sqlite/Cargo.toml index d0f3e7ac8..ec82ea066 100644 --- a/examples/diesel_sqlite/Cargo.toml +++ b/examples/diesel_sqlite/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [dependencies] chrono = { version = "0.4", default-features = false, features = ["clock"] } -time = { version = "0.3", features = ["parsing", "macros"] } +time = { version = "0.3.36", features = ["parsing", "macros"] } serde_json = { version = "1" } uuid = { version = "1", features = ["serde", "v4"] } diesel = { version = "2.1.1", features = ["sqlite"] } diff --git a/examples/postgres/Cargo.toml b/examples/postgres/Cargo.toml index cec0b383f..d702cad92 100644 --- a/examples/postgres/Cargo.toml +++ b/examples/postgres/Cargo.toml @@ -9,7 +9,7 @@ publish = false [dependencies] chrono = { version = "0.4", default-features = false, features = ["clock"] } -time = { version = "0.3", features = ["macros"] } +time = { version = "0.3.36", features = ["macros"] } uuid = { version = "1", features = ["serde", "v4"] } serde_json = "1" rust_decimal = { version = "1" } diff --git a/examples/rusqlite/Cargo.toml b/examples/rusqlite/Cargo.toml index cb7aaa384..4916f053c 100644 --- a/examples/rusqlite/Cargo.toml +++ b/examples/rusqlite/Cargo.toml @@ -9,7 +9,7 @@ publish = false [dependencies] chrono = { version = "0.4", default-features = false, features = ["clock"] } -time = { version = "0.3", features = ["parsing", "macros"] } +time = { version = "0.3.36", features = ["parsing", "macros"] } serde_json = { version = "1" } uuid = { version = "1", features = ["serde", "v4"] } rusqlite = { version = "0.31" } diff --git a/examples/sqlx_any/Cargo.toml b/examples/sqlx_any/Cargo.toml index 1e2ea915e..42e58068f 100644 --- a/examples/sqlx_any/Cargo.toml +++ b/examples/sqlx_any/Cargo.toml @@ -9,13 +9,13 @@ publish = false [dependencies] chrono = { version = "0.4", default-features = false, features = ["clock"] } -time = "0.3" +time = "0.3.36" uuid = { version = "1", features = ["serde", "v4"] } serde_json = "1" rust_decimal = { version = "1" } -bigdecimal = { version = "0.3" } +bigdecimal = { version = "0.4" } async-std = { version = "1.8", features = [ "attributes" ] } -sqlx = "0.7" +sqlx = "0.8" sea-query = { path = "../../" } sea-query-binder = { path = "../../sea-query-binder", features = [ "sqlx-postgres", diff --git a/examples/sqlx_mysql/Cargo.toml b/examples/sqlx_mysql/Cargo.toml index bbf5e335a..965278068 100644 --- a/examples/sqlx_mysql/Cargo.toml +++ b/examples/sqlx_mysql/Cargo.toml @@ -9,13 +9,13 @@ publish = false [dependencies] chrono = { version = "0.4", default-features = false, features = ["clock"] } -time = { version = "0.3", features = ["macros"] } +time = { version = "0.3.36", features = ["macros"] } uuid = { version = "1", features = ["serde", "v4"] } serde_json = "1" rust_decimal = { version = "1" } -bigdecimal = { version = "0.3" } +bigdecimal = { version = "0.4" } async-std = { version = "1.8", features = [ "attributes" ] } -sqlx = "0.7" +sqlx = "0.8" sea-query = { path = "../../" } sea-query-binder = { path = "../../sea-query-binder", features = [ "sqlx-mysql", diff --git a/examples/sqlx_postgres/Cargo.toml b/examples/sqlx_postgres/Cargo.toml index dd08ee279..81553e5b2 100644 --- a/examples/sqlx_postgres/Cargo.toml +++ b/examples/sqlx_postgres/Cargo.toml @@ -9,15 +9,15 @@ publish = false [dependencies] chrono = { version = "0.4", default-features = false, features = ["clock"] } -time = { version = "0.3", features = ["macros"] } +time = { version = "0.3.36", features = ["macros"] } uuid = { version = "1", features = ["serde", "v4"] } serde_json = "1" rust_decimal = { version = "1" } -bigdecimal = { version = "0.3" } +bigdecimal = { version = "0.4" } ipnetwork = { version = "0.20" } mac_address = { version = "1.1" } async-std = { version = "1.8", features = [ "attributes" ] } -sqlx = "0.7" +sqlx = "0.8" sea-query = { path = "../../" } sea-query-binder = { path = "../../sea-query-binder", features = [ "sqlx-postgres", diff --git a/examples/sqlx_sqlite/Cargo.toml b/examples/sqlx_sqlite/Cargo.toml index 22162020a..c445a646d 100644 --- a/examples/sqlx_sqlite/Cargo.toml +++ b/examples/sqlx_sqlite/Cargo.toml @@ -9,11 +9,11 @@ publish = false [dependencies] chrono = { version = "0.4", default-features = false, features = ["clock"] } -time = { version = "0.3", features = ["macros"] } +time = { version = "0.3.36", features = ["macros"] } uuid = { version = "1", features = ["serde", "v4"] } serde_json = "1" async-std = { version = "1.8", features = [ "attributes" ] } -sqlx = "0.7" +sqlx = "0.8" sea-query = { path = "../../" } sea-query-binder = { path = "../../sea-query-binder", features = [ "sqlx-sqlite", diff --git a/sea-query-attr/Cargo.toml b/sea-query-attr/Cargo.toml index aecd5042e..be3d730de 100644 --- a/sea-query-attr/Cargo.toml +++ b/sea-query-attr/Cargo.toml @@ -22,5 +22,5 @@ darling = { version = "0.14", default-features = false } [dev-dependencies] trybuild = "1.0" -sea-query = { version = "0.31.0-rc.8", path = ".." } +sea-query = { version = "0.32.0-rc.1", path = ".." } strum = { version = "0.25", features = ["derive"] } diff --git a/sea-query-binder/Cargo.toml b/sea-query-binder/Cargo.toml index 624af39f5..e5413adf5 100644 --- a/sea-query-binder/Cargo.toml +++ b/sea-query-binder/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "sea-query-binder" -version = "0.6.0-rc.3" +version = "0.7.0-rc.2" authors = [ "Valentin Tolmer ", "Ivan Krivosheev " ] edition = "2021" description = "Driver library for using SeaQuery with SQLx" @@ -17,16 +17,17 @@ rust-version = "1.60" [lib] [dependencies] -sea-query = { version = "0.31.0-rc.8", path = "..", default-features = false, features = ["thread-safe"] } -sqlx = { version = "<0.7.5", default-features = false, optional = true } +sea-query = { version = "0.32.0-rc.1", path = "..", default-features = false, features = ["thread-safe"] } +sqlx = { version = "0.8", default-features = false, optional = true } serde_json = { version = "1", default-features = false, optional = true, features = ["std"] } chrono = { version = "0.4", default-features = false, optional = true, features = ["clock"] } rust_decimal = { version = "1", default-features = false, optional = true } -bigdecimal = { version = "0.3", default-features = false, optional = true } +bigdecimal = { version = "0.4", default-features = false, optional = true } uuid = { version = "1", default-features = false, optional = true } -time = { version = "<0.3.35", default-features = false, optional = true, features = ["macros", "formatting"] } +time = { version = "0.3.36", default-features = false, optional = true, features = ["macros", "formatting"] } ipnetwork = { version = "0.20", default-features = false, optional = true } mac_address = { version = "1.1", default-features = false, optional = true } +pgvector = { version = "~0.4", default-features = false, optional = true } [features] sqlx-mysql = ["sqlx/mysql"] @@ -42,6 +43,7 @@ with-time = ["sqlx?/time", "sea-query/with-time", "time"] with-ipnetwork = ["sqlx?/ipnetwork", "sea-query/with-ipnetwork", "ipnetwork"] with-mac_address = ["sqlx?/mac_address", "sea-query/with-mac_address", "mac_address"] postgres-array = ["sea-query/postgres-array"] +postgres-vector = ["sea-query/postgres-vector", "pgvector/sqlx"] runtime-async-std = ["sqlx?/runtime-async-std"] runtime-async-std-native-tls = ["sqlx?/runtime-async-std-native-tls"] runtime-async-std-rustls = ["sqlx?/runtime-async-std-rustls", ] diff --git a/sea-query-binder/src/sqlx_any.rs b/sea-query-binder/src/sqlx_any.rs index 1f6019241..263ec8b9d 100644 --- a/sea-query-binder/src/sqlx_any.rs +++ b/sea-query-binder/src/sqlx_any.rs @@ -8,86 +8,89 @@ impl<'q> sqlx::IntoArguments<'q, sqlx::any::Any> for SqlxValues { use sqlx::Arguments; match arg { Value::Bool(b) => { - args.add(b); + let _ = args.add(b); } Value::TinyInt(i) => { - args.add(i.map(Into::::into)); + let _ = args.add(i.map(Into::::into)); } Value::SmallInt(i) => { - args.add(i.map(Into::::into)); + let _ = args.add(i.map(Into::::into)); } Value::Int(i) => { - args.add(i); + let _ = args.add(i); } Value::BigInt(i) => { - args.add(i); + let _ = args.add(i); } Value::TinyUnsigned(i) => { - args.add(i.map(Into::::into)); + let _ = args.add(i.map(Into::::into)); } Value::SmallUnsigned(i) => { - args.add(i.map(Into::::into)); + let _ = args.add(i.map(Into::::into)); } Value::Unsigned(i) => { - args.add(i.map(Into::::into)); + let _ = args.add(i.map(Into::::into)); } Value::BigUnsigned(i) => { - args.add(i.map(|i| >::try_from(i).unwrap())); + let _ = args + .add(i.map(|i| >::try_from(i).unwrap())); } Value::Float(f) => { - args.add(f); + let _ = args.add(f); } Value::Double(d) => { - args.add(d); + let _ = args.add(d); } Value::String(s) => { - args.add(s.map(|s| *s)); + let _ = args.add(s.map(|s| *s)); } Value::Char(c) => { - args.add(c.map(|c| c.to_string())); + let _ = args.add(c.map(|c| c.to_string())); } Value::Bytes(b) => { - args.add(b.map(|b| *b)); + let _ = args.add(b.map(|b| *b)); } #[cfg(feature = "with-chrono")] Value::ChronoDate(t) => { - args.add(Value::ChronoDate(t).chrono_as_naive_utc_in_string()); + let _ = args.add(Value::ChronoDate(t).chrono_as_naive_utc_in_string()); } #[cfg(feature = "with-chrono")] Value::ChronoTime(t) => { - args.add(Value::ChronoTime(t).chrono_as_naive_utc_in_string()); + let _ = args.add(Value::ChronoTime(t).chrono_as_naive_utc_in_string()); } #[cfg(feature = "with-chrono")] Value::ChronoDateTime(t) => { - args.add(Value::ChronoDateTime(t).chrono_as_naive_utc_in_string()); + let _ = args.add(Value::ChronoDateTime(t).chrono_as_naive_utc_in_string()); } #[cfg(feature = "with-chrono")] Value::ChronoDateTimeUtc(t) => { - args.add(Value::ChronoDateTimeUtc(t).chrono_as_naive_utc_in_string()); + let _ = args.add(Value::ChronoDateTimeUtc(t).chrono_as_naive_utc_in_string()); } #[cfg(feature = "with-chrono")] Value::ChronoDateTimeLocal(t) => { - args.add(Value::ChronoDateTimeLocal(t).chrono_as_naive_utc_in_string()); + let _ = args.add(Value::ChronoDateTimeLocal(t).chrono_as_naive_utc_in_string()); } #[cfg(feature = "with-chrono")] Value::ChronoDateTimeWithTimeZone(t) => { - args.add(Value::ChronoDateTimeWithTimeZone(t).chrono_as_naive_utc_in_string()); + let _ = args + .add(Value::ChronoDateTimeWithTimeZone(t).chrono_as_naive_utc_in_string()); } #[cfg(feature = "with-time")] Value::TimeDate(t) => { - args.add(Value::TimeDate(t).time_as_naive_utc_in_string()); + let _ = args.add(Value::TimeDate(t).time_as_naive_utc_in_string()); } #[cfg(feature = "with-time")] Value::TimeTime(t) => { - args.add(Value::TimeTime(t).time_as_naive_utc_in_string()); + let _ = args.add(Value::TimeTime(t).time_as_naive_utc_in_string()); } #[cfg(feature = "with-time")] Value::TimeDateTime(t) => { - args.add(Value::TimeDateTime(t).time_as_naive_utc_in_string()); + let _ = args.add(Value::TimeDateTime(t).time_as_naive_utc_in_string()); } #[cfg(feature = "with-time")] Value::TimeDateTimeWithTimeZone(t) => { - args.add(Value::TimeDateTimeWithTimeZone(t).time_as_naive_utc_in_string()); + let _ = + args.add(Value::TimeDateTimeWithTimeZone(t).time_as_naive_utc_in_string()); } #[cfg(feature = "with-uuid")] Value::Uuid(_) => { @@ -117,6 +120,10 @@ impl<'q> sqlx::IntoArguments<'q, sqlx::any::Any> for SqlxValues { Value::Array(_, _) => { panic!("SQLx doesn't support array arguments for Any"); } + #[cfg(feature = "postgres-vector")] + Value::Vector(_) => { + panic!("SQLx doesn't support vector arguments for Any"); + } } } args diff --git a/sea-query-binder/src/sqlx_mysql.rs b/sea-query-binder/src/sqlx_mysql.rs index abeac3862..3261ef293 100644 --- a/sea-query-binder/src/sqlx_mysql.rs +++ b/sea-query-binder/src/sqlx_mysql.rs @@ -8,107 +8,112 @@ impl sqlx::IntoArguments<'_, sqlx::mysql::MySql> for SqlxValues { use sqlx::Arguments; match arg { Value::Bool(b) => { - args.add(b); + let _ = args.add(b); } Value::TinyInt(i) => { - args.add(i); + let _ = args.add(i); } Value::SmallInt(i) => { - args.add(i); + let _ = args.add(i); } Value::Int(i) => { - args.add(i); + let _ = args.add(i); } Value::BigInt(i) => { - args.add(i); + let _ = args.add(i); } Value::TinyUnsigned(i) => { - args.add(i); + let _ = args.add(i); } Value::SmallUnsigned(i) => { - args.add(i); + let _ = args.add(i); } Value::Unsigned(i) => { - args.add(i); + let _ = args.add(i); } Value::BigUnsigned(i) => { - args.add(i); + let _ = args.add(i); } Value::Float(f) => { - args.add(f); + let _ = args.add(f); } Value::Double(d) => { - args.add(d); + let _ = args.add(d); } Value::String(s) => { - args.add(s.as_deref()); + let _ = args.add(s.as_deref()); } Value::Char(c) => { - args.add(c.map(|c| c.to_string())); + let _ = args.add(c.map(|c| c.to_string())); } Value::Bytes(b) => { - args.add(b.as_deref()); + let _ = args.add(b.as_deref()); } #[cfg(feature = "with-chrono")] Value::ChronoDate(d) => { - args.add(d.as_deref()); + let _ = args.add(d.as_deref()); } #[cfg(feature = "with-chrono")] Value::ChronoTime(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-chrono")] Value::ChronoDateTime(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-chrono")] Value::ChronoDateTimeUtc(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-chrono")] Value::ChronoDateTimeLocal(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-chrono")] Value::ChronoDateTimeWithTimeZone(t) => { - args.add(Value::ChronoDateTimeWithTimeZone(t).chrono_as_naive_utc_in_string()); + let _ = args + .add(Value::ChronoDateTimeWithTimeZone(t).chrono_as_naive_utc_in_string()); } #[cfg(feature = "with-time")] Value::TimeDate(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-time")] Value::TimeTime(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-time")] Value::TimeDateTime(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-time")] Value::TimeDateTimeWithTimeZone(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-uuid")] Value::Uuid(uuid) => { - args.add(uuid.as_deref()); + let _ = args.add(uuid.as_deref()); } #[cfg(feature = "with-rust_decimal")] Value::Decimal(d) => { - args.add(d.as_deref()); + let _ = args.add(d.as_deref()); } #[cfg(feature = "with-bigdecimal")] Value::BigDecimal(d) => { - args.add(d.as_deref()); + let _ = args.add(d.as_deref()); } #[cfg(feature = "with-json")] Value::Json(j) => { - args.add(j.as_deref()); + let _ = args.add(j.as_deref()); } #[cfg(feature = "postgres-array")] Value::Array(_, _) => { panic!("Mysql doesn't support array arguments"); } + #[cfg(feature = "postgres-vector")] + Value::Vector(_) => { + panic!("Mysql doesn't support vector arguments"); + } #[cfg(feature = "with-ipnetwork")] Value::IpNetwork(_) => { panic!("Mysql doesn't support IpNetwork arguments"); diff --git a/sea-query-binder/src/sqlx_postgres.rs b/sea-query-binder/src/sqlx_postgres.rs index b0fce77a0..314a7e44c 100644 --- a/sea-query-binder/src/sqlx_postgres.rs +++ b/sea-query-binder/src/sqlx_postgres.rs @@ -24,158 +24,158 @@ impl sqlx::IntoArguments<'_, sqlx::postgres::Postgres> for SqlxValues { use sqlx::Arguments; match arg { Value::Bool(b) => { - args.add(b); + let _ = args.add(b); } Value::TinyInt(i) => { - args.add(i); + let _ = args.add(i); } Value::SmallInt(i) => { - args.add(i); + let _ = args.add(i); } Value::Int(i) => { - args.add(i); + let _ = args.add(i); } Value::BigInt(i) => { - args.add(i); + let _ = args.add(i); } Value::TinyUnsigned(i) => { - args.add(i.map(|i| i as i16)); + let _ = args.add(i.map(|i| i as i16)); } Value::SmallUnsigned(i) => { - args.add(i.map(|i| i as i32)); + let _ = args.add(i.map(|i| i as i32)); } Value::Unsigned(i) => { - args.add(i.map(|i| i as i64)); + let _ = args.add(i.map(|i| i as i64)); } Value::BigUnsigned(i) => { - args.add(i.map(|i| >::try_from(i).unwrap())); + let _ = args.add(i.map(|i| >::try_from(i).unwrap())); } Value::Float(f) => { - args.add(f); + let _ = args.add(f); } Value::Double(d) => { - args.add(d); + let _ = args.add(d); } Value::String(s) => { - args.add(s.as_deref()); + let _ = args.add(s.as_deref()); } Value::Char(c) => { - args.add(c.map(|c| c.to_string())); + let _ = args.add(c.map(|c| c.to_string())); } Value::Bytes(b) => { - args.add(b.as_deref()); + let _ = args.add(b.as_deref()); } #[cfg(feature = "with-chrono")] Value::ChronoDate(d) => { - args.add(d.as_deref()); + let _ = args.add(d.as_deref()); } #[cfg(feature = "with-chrono")] Value::ChronoTime(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-chrono")] Value::ChronoDateTime(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-chrono")] Value::ChronoDateTimeUtc(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-chrono")] Value::ChronoDateTimeLocal(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-chrono")] Value::ChronoDateTimeWithTimeZone(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-time")] Value::TimeDate(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-time")] Value::TimeTime(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-time")] Value::TimeDateTime(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-time")] Value::TimeDateTimeWithTimeZone(t) => { - args.add(t.as_deref()); + let _ = args.add(t.as_deref()); } #[cfg(feature = "with-uuid")] Value::Uuid(uuid) => { - args.add(uuid.as_deref()); + let _ = args.add(uuid.as_deref()); } #[cfg(feature = "with-rust_decimal")] Value::Decimal(d) => { - args.add(d.as_deref()); + let _ = args.add(d.as_deref()); } #[cfg(feature = "with-bigdecimal")] Value::BigDecimal(d) => { - args.add(d.as_deref()); + let _ = args.add(d.as_deref()); } #[cfg(feature = "with-json")] Value::Json(j) => { - args.add(j.as_deref()); + let _ = args.add(j.as_deref()); } #[cfg(feature = "with-ipnetwork")] Value::IpNetwork(ip) => { - args.add(ip.as_deref()); + let _ = args.add(ip.as_deref()); } #[cfg(feature = "with-mac_address")] Value::MacAddress(mac) => { - args.add(mac.as_deref()); + let _ = args.add(mac.as_deref()); } #[cfg(feature = "postgres-array")] Value::Array(ty, v) => match ty { ArrayType::Bool => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::Bool"); - args.add(value) + let _ = args.add(value); } ArrayType::TinyInt => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::TinyInt"); - args.add(value) + let _ = args.add(value); } ArrayType::SmallInt => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::SmallInt"); - args.add(value) + let _ = args.add(value); } ArrayType::Int => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::Int"); - args.add(value) + let _ = args.add(value); } ArrayType::BigInt => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::BigInt"); - args.add(value) + let _ = args.add(value); } ArrayType::TinyUnsigned => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::TinyUnsigned"); let value: Option> = value.map(|vec| vec.into_iter().map(|i| i as i16).collect()); - args.add(value) + let _ = args.add(value); } ArrayType::SmallUnsigned => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::SmallUnsigned"); let value: Option> = value.map(|vec| vec.into_iter().map(|i| i as i32).collect()); - args.add(value) + let _ = args.add(value); } ArrayType::Unsigned => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::Unsigned"); let value: Option> = value.map(|vec| vec.into_iter().map(|i| i as i64).collect()); - args.add(value) + let _ = args.add(value); } ArrayType::BigUnsigned => { let value: Option> = Value::Array(ty, v) @@ -185,135 +185,139 @@ impl sqlx::IntoArguments<'_, sqlx::postgres::Postgres> for SqlxValues { .map(|i| >::try_from(i).unwrap()) .collect() }); - args.add(value) + let _ = args.add(value); } ArrayType::Float => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::Float"); - args.add(value) + let _ = args.add(value); } ArrayType::Double => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::Double"); - args.add(value) + let _ = args.add(value); } ArrayType::String => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::String"); - args.add(value) + let _ = args.add(value); } ArrayType::Char => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::Char"); let value: Option> = value.map(|vec| vec.into_iter().map(|c| c.to_string()).collect()); - args.add(value) + let _ = args.add(value); } ArrayType::Bytes => { let value: Option>> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::Bytes"); - args.add(value) + let _ = args.add(value); } #[cfg(feature = "with-chrono")] ArrayType::ChronoDate => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::ChronoDate"); - args.add(value); + let _ = args.add(value); } #[cfg(feature = "with-chrono")] ArrayType::ChronoTime => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::ChronoTime"); - args.add(value); + let _ = args.add(value); } #[cfg(feature = "with-chrono")] ArrayType::ChronoDateTime => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::ChronoDateTime"); - args.add(value); + let _ = args.add(value); } #[cfg(feature = "with-chrono")] ArrayType::ChronoDateTimeUtc => { let value: Option>> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::ChronoDateTimeUtc"); - args.add(value); + let _ = args.add(value); } #[cfg(feature = "with-chrono")] ArrayType::ChronoDateTimeLocal => { let value: Option>> = Value::Array(ty, v).expect( "This Value::Array should consist of Value::ChronoDateTimeLocal", ); - args.add(value); + let _ = args.add(value); } #[cfg(feature = "with-chrono")] ArrayType::ChronoDateTimeWithTimeZone => { let value: Option>> = Value::Array(ty, v).expect( "This Value::Array should consist of Value::ChronoDateTimeWithTimeZone", ); - args.add(value); + let _ = args.add(value); } #[cfg(feature = "with-time")] ArrayType::TimeDate => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::TimeDate"); - args.add(value); + let _ = args.add(value); } #[cfg(feature = "with-time")] ArrayType::TimeTime => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::TimeTime"); - args.add(value); + let _ = args.add(value); } #[cfg(feature = "with-time")] ArrayType::TimeDateTime => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::TimeDateTime"); - args.add(value); + let _ = args.add(value); } #[cfg(feature = "with-time")] ArrayType::TimeDateTimeWithTimeZone => { let value: Option> = Value::Array(ty, v).expect( "This Value::Array should consist of Value::TimeDateTimeWithTimeZone", ); - args.add(value); + let _ = args.add(value); } #[cfg(feature = "with-uuid")] ArrayType::Uuid => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::Uuid"); - args.add(value); + let _ = args.add(value); } #[cfg(feature = "with-rust_decimal")] ArrayType::Decimal => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::Decimal"); - args.add(value); + let _ = args.add(value); } #[cfg(feature = "with-bigdecimal")] ArrayType::BigDecimal => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::BigDecimal"); - args.add(value); + let _ = args.add(value); } #[cfg(feature = "with-json")] ArrayType::Json => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::Json"); - args.add(value); + let _ = args.add(value); } #[cfg(feature = "with-ipnetwork")] ArrayType::IpNetwork => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::IpNetwork"); - args.add(value); + let _ = args.add(value); } #[cfg(feature = "with-mac_address")] ArrayType::MacAddress => { let value: Option> = Value::Array(ty, v) .expect("This Value::Array should consist of Value::MacAddress"); - args.add(value); + let _ = args.add(value); } }, + #[cfg(feature = "postgres-vector")] + Value::Vector(v) => { + let _ = args.add(v.as_deref()); + } } } args diff --git a/sea-query-binder/src/sqlx_sqlite.rs b/sea-query-binder/src/sqlx_sqlite.rs index 1865ba6f6..e31751a0b 100644 --- a/sea-query-binder/src/sqlx_sqlite.rs +++ b/sea-query-binder/src/sqlx_sqlite.rs @@ -8,104 +8,105 @@ impl<'q> sqlx::IntoArguments<'q, sqlx::sqlite::Sqlite> for SqlxValues { use sqlx::Arguments; match arg { Value::Bool(b) => { - args.add(b); + let _ = args.add(b); } Value::TinyInt(i) => { - args.add(i); + let _ = args.add(i); } Value::SmallInt(i) => { - args.add(i); + let _ = args.add(i); } Value::Int(i) => { - args.add(i); + let _ = args.add(i); } Value::BigInt(i) => { - args.add(i); + let _ = args.add(i); } Value::TinyUnsigned(i) => { - args.add(i); + let _ = args.add(i); } Value::SmallUnsigned(i) => { - args.add(i); + let _ = args.add(i); } Value::Unsigned(i) => { - args.add(i); + let _ = args.add(i); } Value::BigUnsigned(i) => { - args.add(i.map(|i| >::try_from(i).unwrap())); + let _ = args + .add(i.map(|i| >::try_from(i).unwrap())); } Value::Float(f) => { - args.add(f); + let _ = args.add(f); } Value::Double(d) => { - args.add(d); + let _ = args.add(d); } Value::String(s) => { - args.add(s.map(|s| *s)); + let _ = args.add(s.map(|s| *s)); } Value::Char(c) => { - args.add(c.map(|c| c.to_string())); + let _ = args.add(c.map(|c| c.to_string())); } Value::Bytes(b) => { - args.add(b.map(|b| *b)); + let _ = args.add(b.map(|b| *b)); } #[cfg(feature = "with-chrono")] Value::ChronoDate(d) => { - args.add(d.map(|d| *d)); + let _ = args.add(d.map(|d| *d)); } #[cfg(feature = "with-chrono")] Value::ChronoTime(t) => { - args.add(t.map(|t| *t)); + let _ = args.add(t.map(|t| *t)); } #[cfg(feature = "with-chrono")] Value::ChronoDateTime(t) => { - args.add(t.map(|t| *t)); + let _ = args.add(t.map(|t| *t)); } #[cfg(feature = "with-chrono")] Value::ChronoDateTimeUtc(t) => { - args.add(t.map(|t| *t)); + let _ = args.add(t.map(|t| *t)); } #[cfg(feature = "with-chrono")] Value::ChronoDateTimeLocal(t) => { - args.add(t.map(|t| *t)); + let _ = args.add(t.map(|t| *t)); } #[cfg(feature = "with-chrono")] Value::ChronoDateTimeWithTimeZone(t) => { - args.add(t.map(|t| *t)); + let _ = args.add(t.map(|t| *t)); } #[cfg(feature = "with-time")] Value::TimeDate(t) => { - args.add(t.map(|t| *t)); + let _ = args.add(t.map(|t| *t)); } #[cfg(feature = "with-time")] Value::TimeTime(t) => { - args.add(t.map(|t| *t)); + let _ = args.add(t.map(|t| *t)); } #[cfg(feature = "with-time")] Value::TimeDateTime(t) => { - args.add(t.map(|t| *t)); + let _ = args.add(t.map(|t| *t)); } #[cfg(feature = "with-time")] Value::TimeDateTimeWithTimeZone(t) => { - args.add(t.map(|t| *t)); + let _ = args.add(t.map(|t| *t)); } #[cfg(feature = "with-uuid")] Value::Uuid(uuid) => { - args.add(uuid.map(|uuid| *uuid)); + let _ = args.add(uuid.map(|uuid| *uuid)); } #[cfg(feature = "with-rust_decimal")] Value::Decimal(decimal) => { use rust_decimal::prelude::ToPrimitive; - args.add(decimal.map(|d| d.to_string())); + let _ = args.add(decimal.map(|d| d.to_string())); } #[cfg(feature = "with-bigdecimal")] Value::BigDecimal(big_decimal) => { use bigdecimal::ToPrimitive; - args.add(big_decimal.map(|d| d.to_string())); + let _ = args.add(big_decimal.map(|d| d.to_string())); } #[cfg(feature = "with-json")] Value::Json(j) => { - args.add(j.map(|j| *j)); + let _ = args.add(j.map(|j| *j)); } #[cfg(feature = "with-ipnetwork")] Value::IpNetwork(_) => { @@ -119,6 +120,10 @@ impl<'q> sqlx::IntoArguments<'q, sqlx::sqlite::Sqlite> for SqlxValues { Value::Array(_, _) => { panic!("Sqlite doesn't support array arguments"); } + #[cfg(feature = "postgres-vector")] + Value::Vector(_) => { + panic!("Sqlite doesn't support vector arguments"); + } } } args diff --git a/sea-query-derive/Cargo.toml b/sea-query-derive/Cargo.toml index 0af7724ab..4b9b8d505 100644 --- a/sea-query-derive/Cargo.toml +++ b/sea-query-derive/Cargo.toml @@ -23,7 +23,7 @@ thiserror = { version = "1.0", default-features = false } [dev-dependencies] trybuild = "1.0" -sea-query = { version = "0.31.0-rc.8", path = ".." } +sea-query = { version = "0.32.0-rc.1", path = ".." } strum = { version = "0.25", features = ["derive"] } [features] diff --git a/sea-query-diesel/Cargo.toml b/sea-query-diesel/Cargo.toml index 5e9abe265..91f9cf1c5 100644 --- a/sea-query-diesel/Cargo.toml +++ b/sea-query-diesel/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "sea-query-diesel" -version = "0.1.0" +version = "0.2.0" authors = ["Emile Fugulin "] edition = "2021" description = "Binder traits for connecting sea-query with diesel" @@ -17,18 +17,19 @@ rust-version = "1.60" [lib] [dependencies] -sea-query = { version = "0.31.0-rc.8", path = "..", default-features = false } +sea-query = { version = "0.32.0-rc.1", path = "..", default-features = false } diesel = { version = "2.1.1", features = [ "i-implement-a-third-party-backend-and-opt-into-breaking-changes", ] } -bigdecimal = { version = "0.3", default-features = false, optional = true } +bigdecimal = { version = "0.4", default-features = false, optional = true } rust_decimal = { version = "1", default-features = false, optional = true } chrono = { version = "0.4", default-features = false, optional = true } -time = { version = "0.3", default-features = false, optional = true } +time = { version = "0.3.36", default-features = false, optional = true } uuid = { version = "1", default-features = false, optional = true } serde_json = { version = "1", default-features = false, optional = true } ipnetwork = { version = "0.20", default-features = false, optional = true } mac_address = { version = "1.1", default-features = false, optional = true } +pgvector = { version = "~0.4", default-features = false, optional = true } [features] default = [] @@ -64,3 +65,4 @@ with-ipnetwork = [ ] with-mac_address = ["sea-query/with-mac_address", "mac_address"] postgres-array = ["sea-query/postgres-array"] +postgres-vector = ["sea-query/postgres-vector", "pgvector/diesel"] diff --git a/sea-query-diesel/src/backend/mysql.rs b/sea-query-diesel/src/backend/mysql.rs index ee8ccd0bd..631eeaadb 100644 --- a/sea-query-diesel/src/backend/mysql.rs +++ b/sea-query-diesel/src/backend/mysql.rs @@ -73,6 +73,8 @@ impl TransformValue for Mysql { Value::MacAddress(_) => bail!("Mysql doesn't support MacAddress arguments"), #[cfg(feature = "postgres-array")] Value::Array(_, _) => bail!("Mysql doesn't support array arguments"), + #[cfg(feature = "postgres-vector")] + Value::Vector(_) => bail!("Mysql doesn't support vector arguments"), }; Ok(transformed) } diff --git a/sea-query-diesel/src/backend/postgres.rs b/sea-query-diesel/src/backend/postgres.rs index ebf634a9d..a0bbfd425 100644 --- a/sea-query-diesel/src/backend/postgres.rs +++ b/sea-query-diesel/src/backend/postgres.rs @@ -205,6 +205,8 @@ impl TransformValue for Pg { ) } }, + #[cfg(feature = "postgres-vector")] + Value::Vector(v) => build!(pgvector::sql_types::Vector, v.map(|v| *v)), }; Ok(transformed) } diff --git a/sea-query-diesel/src/backend/sqlite.rs b/sea-query-diesel/src/backend/sqlite.rs index 45d1a8462..e101d0228 100644 --- a/sea-query-diesel/src/backend/sqlite.rs +++ b/sea-query-diesel/src/backend/sqlite.rs @@ -98,6 +98,8 @@ impl TransformValue for Sqlite { Value::MacAddress(_) => bail!("Sqlite doesn't support MacAddress arguments"), #[cfg(feature = "postgres-array")] Value::Array(_, _) => bail!("Sqlite doesn't support array arguments"), + #[cfg(feature = "postgres-vector")] + Value::Vector(_) => bail!("Sqlite doesn't support vector arguments"), }; Ok(transformed) } diff --git a/sea-query-postgres/Cargo.toml b/sea-query-postgres/Cargo.toml index 131199e64..6d054116b 100644 --- a/sea-query-postgres/Cargo.toml +++ b/sea-query-postgres/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "sea-query-postgres" -version = "0.4.0" +version = "0.5.0-rc.1" authors = [ "Ivan Krivosheev " ] edition = "2021" description = "Binder traits for connecting sea-query with postgres driver" @@ -17,11 +17,12 @@ rust-version = "1.60" [lib] [dependencies] -sea-query = { version = "0.31.0-rc.8", path = "..", default-features = false } +sea-query = { version = "0.32.0-rc.1", path = "..", default-features = false } postgres-types = { version = "0.2", default-features = false } +pgvector = { version = "~0.4", default-features = false, optional = true } bytes = { version = "1", default-features = false } rust_decimal = { version = "1", default-features = false, optional = true } -bigdecimal = { version = "0.3", default-features = false, optional = true } +bigdecimal = { version = "0.4", default-features = false, optional = true } ipnetwork = { version = "0.20", default-features = false, optional = true } mac_address = { version = "1.1", default-features = false, optional = true } eui48 = { version = "1", default-features = false, optional = true } @@ -35,5 +36,6 @@ with-bigdecimal = ["sea-query/with-bigdecimal", "bigdecimal"] with-uuid = ["postgres-types/with-uuid-1", "sea-query/with-uuid"] with-time = ["postgres-types/with-time-0_3", "sea-query/with-time"] postgres-array = ["postgres-types/array-impls", "sea-query/postgres-array"] +postgres-vector = ["sea-query/postgres-vector", "pgvector/postgres"] with-ipnetwork = ["postgres-types/with-cidr-0_2", "sea-query/with-ipnetwork", "ipnetwork", "cidr"] with-mac_address = ["postgres-types/with-eui48-1", "sea-query/with-mac_address", "mac_address", "eui48"] diff --git a/sea-query-postgres/src/lib.rs b/sea-query-postgres/src/lib.rs index a5cdf6757..130567457 100644 --- a/sea-query-postgres/src/lib.rs +++ b/sea-query-postgres/src/lib.rs @@ -116,6 +116,10 @@ impl ToSql for PostgresValue { .to_sql(ty, out), #[cfg(feature = "postgres-array")] Value::Array(_, None) => Ok(IsNull::Yes), + #[cfg(feature = "postgres-vector")] + Value::Vector(Some(v)) => v.to_sql(ty, out), + #[cfg(feature = "postgres-vector")] + Value::Vector(None) => Ok(IsNull::Yes), #[cfg(feature = "with-ipnetwork")] Value::IpNetwork(v) => { use cidr::IpCidr; diff --git a/sea-query-rbatis/Cargo.toml b/sea-query-rbatis/Cargo.toml index 39cb0ec95..78973a052 100644 --- a/sea-query-rbatis/Cargo.toml +++ b/sea-query-rbatis/Cargo.toml @@ -17,14 +17,14 @@ rust-version = "1.60" [lib] [dependencies] -sea-query = { version = "0.31.0-rc.8", path = "..", default-features = false, features = ["thread-safe"] } +sea-query = { version = "0.32.0-rc.1", path = "..", default-features = false, features = ["thread-safe"] } rbs = { version = "4.3.1" } serde_json = { version = "1", default-features = false, optional = true, features = ["std"] } chrono = { version = "0.4", default-features = false, optional = true, features = [ "clock"] } rust_decimal = { version = "1", default-features = false, optional = true } -bigdecimal = { version = "0.3", default-features = false, optional = true } +bigdecimal = { version = "0.4", default-features = false, optional = true } uuid = { version = "1", default-features = false, optional = true } -time = { version = "0.3", default-features = false, optional = true, features = ["macros", "formatting"] } +time = { version = "0.3.36", default-features = false, optional = true, features = ["macros", "formatting"] } ipnetwork = { version = "0.20", default-features = false, optional = true } mac_address = { version = "1.1", default-features = false, optional = true } diff --git a/sea-query-rusqlite/Cargo.toml b/sea-query-rusqlite/Cargo.toml index 2e1180a43..84b2f51de 100644 --- a/sea-query-rusqlite/Cargo.toml +++ b/sea-query-rusqlite/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "sea-query-rusqlite" -version = "0.6.0-rc.1" +version = "0.7.0-rc.1" authors = [ "Ivan Krivosheev " ] edition = "2021" description = "Binder traits for connecting sea-query with Rusqlite" @@ -17,7 +17,7 @@ rust-version = "1.60" [lib] [dependencies] -sea-query = { version = "0.31.0-rc.8", path = "..", default-features = false } +sea-query = { version = "0.32.0-rc.1", path = "..", default-features = false } rusqlite = { version = "0.31" } [features] @@ -30,3 +30,4 @@ with-time = ["rusqlite/time", "sea-query/with-time"] with-ipnetwork = ["sea-query/with-ipnetwork"] with-mac_address = ["sea-query/with-mac_address"] postgres-array = ["sea-query/postgres-array"] +postgres-vector = ["sea-query/postgres-vector"] diff --git a/sea-query-rusqlite/src/lib.rs b/sea-query-rusqlite/src/lib.rs index 286ac7868..03d9918ad 100644 --- a/sea-query-rusqlite/src/lib.rs +++ b/sea-query-rusqlite/src/lib.rs @@ -130,6 +130,10 @@ impl ToSql for RusqliteValue { Value::Array(_, _) => { panic!("Rusqlite doesn't support Array arguments"); } + #[cfg(feature = "postgres-vector")] + Value::Vector(_) => { + panic!("Rusqlite doesn't support Vector arguments"); + } } } } diff --git a/src/backend/mysql/table.rs b/src/backend/mysql/table.rs index 562ec36b8..0da5ef304 100644 --- a/src/backend/mysql/table.rs +++ b/src/backend/mysql/table.rs @@ -90,6 +90,7 @@ impl TableBuilder for MysqlQueryBuilder { .join("', '") ), ColumnType::Array(_) => unimplemented!("Array is not available in MySQL."), + ColumnType::Vector(_) => unimplemented!("Vector is not available in MySQL."), ColumnType::Cidr => unimplemented!("Cidr is not available in MySQL."), ColumnType::Inet => unimplemented!("Inet is not available in MySQL."), ColumnType::MacAddr => unimplemented!("MacAddr is not available in MySQL."), @@ -153,7 +154,7 @@ impl TableBuilder for MysqlQueryBuilder { } TableAlterOption::DropForeignKey(name) => { let mut foreign_key = TableForeignKey::new(); - foreign_key.name(&name.to_string()); + foreign_key.name(name.to_string()); let drop = ForeignKeyDropStatement { foreign_key, table: None, diff --git a/src/backend/postgres/query.rs b/src/backend/postgres/query.rs index f7cce9d0d..f06501103 100644 --- a/src/backend/postgres/query.rs +++ b/src/backend/postgres/query.rs @@ -90,6 +90,12 @@ impl QueryBuilder for PostgresQueryBuilder { PgBinOper::CastJsonField => "->>", PgBinOper::Regex => "~", PgBinOper::RegexCaseInsensitive => "~*", + #[cfg(feature = "postgres-vector")] + PgBinOper::EuclideanDistance => "<->", + #[cfg(feature = "postgres-vector")] + PgBinOper::NegativeInnerProduct => "<#>", + #[cfg(feature = "postgres-vector")] + PgBinOper::CosineDistance => "<=>", } ) .unwrap(), @@ -116,6 +122,8 @@ impl QueryBuilder for PostgresQueryBuilder { PgFunction::TsRankCd => "TS_RANK_CD", PgFunction::StartsWith => "STARTS_WITH", PgFunction::GenRandomUUID => "GEN_RANDOM_UUID", + PgFunction::JsonBuildObject => "JSON_BUILD_OBJECT", + PgFunction::JsonAgg => "JSON_AGG", #[cfg(feature = "postgres-array")] PgFunction::Any => "ANY", #[cfg(feature = "postgres-array")] diff --git a/src/backend/postgres/table.rs b/src/backend/postgres/table.rs index a022d1d73..a1a3e2f9c 100644 --- a/src/backend/postgres/table.rs +++ b/src/backend/postgres/table.rs @@ -71,6 +71,10 @@ impl TableBuilder for PostgresQueryBuilder { self.prepare_column_type(elem_type, &mut sql); format!("{sql}[]") } + ColumnType::Vector(size) => match size { + Some(size) => format!("vector({size})"), + None => "vector".into(), + }, ColumnType::Custom(iden) => iden.to_string(), ColumnType::Enum { name, .. } => name.to_string(), ColumnType::Cidr => "cidr".into(), @@ -192,7 +196,7 @@ impl TableBuilder for PostgresQueryBuilder { } TableAlterOption::DropForeignKey(name) => { let mut foreign_key = TableForeignKey::new(); - foreign_key.name(&name.to_string()); + foreign_key.name(name.to_string()); let drop = ForeignKeyDropStatement { foreign_key, table: None, diff --git a/src/backend/query_builder.rs b/src/backend/query_builder.rs index e3823eaec..7bf29b552 100644 --- a/src/backend/query_builder.rs +++ b/src/backend/query_builder.rs @@ -676,6 +676,7 @@ pub trait QueryBuilder: Function::Custom(_) => "", Function::Random => self.random_function(), Function::Round => "ROUND", + Function::Md5 => "MD5", #[cfg(feature = "backend-postgres")] Function::PgFunction(_) => unimplemented!(), } @@ -1045,6 +1046,8 @@ pub trait QueryBuilder: Value::MacAddress(None) => write!(s, "NULL").unwrap(), #[cfg(feature = "postgres-array")] Value::Array(_, None) => write!(s, "NULL").unwrap(), + #[cfg(feature = "postgres-vector")] + Value::Vector(None) => write!(s, "NULL").unwrap(), Value::Bool(Some(b)) => write!(s, "{}", if *b { "TRUE" } else { "FALSE" }).unwrap(), Value::TinyInt(Some(v)) => write!(s, "{v}").unwrap(), Value::SmallInt(Some(v)) => write!(s, "{v}").unwrap(), @@ -1118,6 +1121,17 @@ pub trait QueryBuilder: .join(",") ) .unwrap(), + #[cfg(feature = "postgres-vector")] + Value::Vector(Some(v)) => { + write!(s, "'[").unwrap(); + for (i, &element) in v.as_slice().iter().enumerate() { + if i != 0 { + write!(s, ",").unwrap(); + } + write!(s, "{element}").unwrap(); + } + write!(s, "]'").unwrap(); + } #[cfg(feature = "with-ipnetwork")] Value::IpNetwork(Some(v)) => write!(s, "'{v}'").unwrap(), #[cfg(feature = "with-mac_address")] diff --git a/src/backend/sqlite/table.rs b/src/backend/sqlite/table.rs index 834b07278..429a4572e 100644 --- a/src/backend/sqlite/table.rs +++ b/src/backend/sqlite/table.rs @@ -184,6 +184,7 @@ impl SqliteQueryBuilder { ColumnType::Custom(iden) => iden.to_string(), ColumnType::Enum { .. } => "enum_text".into(), ColumnType::Array(_) => unimplemented!("Array is not available in Sqlite."), + ColumnType::Vector(_) => unimplemented!("Vector is not available in Sqlite."), ColumnType::Cidr => unimplemented!("Cidr is not available in Sqlite."), ColumnType::Inet => unimplemented!("Inet is not available in Sqlite."), ColumnType::MacAddr => unimplemented!("MacAddr is not available in Sqlite."), diff --git a/src/expr.rs b/src/expr.rs index 165fb09c9..815a60ee8 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -614,20 +614,20 @@ impl Expr { /// let query = Query::select() /// .columns([Char::Character, Char::SizeW, Char::SizeH]) /// .from(Char::Table) - /// .and_where(Expr::col((Char::Table, Char::FontId)).equals((Font::Table, Font::Id))) + /// .and_where(Expr::col((Char::Table, Char::FontId)).not_equals((Font::Table, Font::Id))) /// .to_owned(); /// /// assert_eq!( /// query.to_string(MysqlQueryBuilder), - /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`font_id` = `font`.`id`"# + /// r#"SELECT `character`, `size_w`, `size_h` FROM `character` WHERE `character`.`font_id` <> `font`.`id`"# /// ); /// assert_eq!( /// query.to_string(PostgresQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."font_id" = "font"."id""# + /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."font_id" <> "font"."id""# /// ); /// assert_eq!( /// query.to_string(SqliteQueryBuilder), - /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."font_id" = "font"."id""# + /// r#"SELECT "character", "size_w", "size_h" FROM "character" WHERE "character"."font_id" <> "font"."id""# /// ); /// ``` pub fn not_equals(self, col: C) -> SimpleExpr @@ -1980,7 +1980,7 @@ impl Expr { SimpleExpr::FunctionCall(func) } - /// Keyword `CURRENT_TIMESTAMP`. + /// Keyword `CURRENT_DATE`. /// /// # Examples /// diff --git a/src/extension/postgres/func.rs b/src/extension/postgres/func.rs index 642d08759..67fc0b2a3 100644 --- a/src/extension/postgres/func.rs +++ b/src/extension/postgres/func.rs @@ -14,6 +14,8 @@ pub enum PgFunction { TsRankCd, StartsWith, GenRandomUUID, + JsonBuildObject, + JsonAgg, #[cfg(feature = "postgres-array")] Any, #[cfg(feature = "postgres-array")] @@ -350,4 +352,59 @@ impl PgFunc { pub fn gen_random_uuid() -> FunctionCall { FunctionCall::new(Function::PgFunction(PgFunction::GenRandomUUID)) } + + /// Call the `JSON_BUILD_OBJECT` function. Postgres only. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .expr(PgFunc::json_build_object(vec![ + /// (Expr::val("a"), Expr::val(1)), + /// (Expr::val("b"), Expr::val("2")), + /// ])) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT JSON_BUILD_OBJECT('a', 1, 'b', '2')"# + /// ); + /// ``` + pub fn json_build_object(pairs: Vec<(T, T)>) -> FunctionCall + where + T: Into, + { + let mut args = vec![]; + for (key, value) in pairs { + args.push(key.into()); + args.push(value.into()); + } + FunctionCall::new(Function::PgFunction(PgFunction::JsonBuildObject)).args(args) + } + + /// Call the `JSON_AGG` function. Postgres only. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .from(Char::Table) + /// .expr(PgFunc::json_agg(Expr::col(Char::SizeW))) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT JSON_AGG("size_w") FROM "character""# + /// ); + /// ``` + pub fn json_agg(expr: T) -> FunctionCall + where + T: Into, + { + FunctionCall::new(Function::PgFunction(PgFunction::JsonAgg)).arg(expr) + } } diff --git a/src/extension/postgres/mod.rs b/src/extension/postgres/mod.rs index 6dd48041f..930b23e7d 100644 --- a/src/extension/postgres/mod.rs +++ b/src/extension/postgres/mod.rs @@ -37,6 +37,12 @@ pub enum PgBinOper { Regex, /// `~*`. Regex operator with case insensitive matching. RegexCaseInsensitive, + #[cfg(feature = "postgres-vector")] + EuclideanDistance, + #[cfg(feature = "postgres-vector")] + NegativeInnerProduct, + #[cfg(feature = "postgres-vector")] + CosineDistance, } impl From for BinOper { diff --git a/src/func.rs b/src/func.rs index 24b17d196..9ee69379a 100644 --- a/src/func.rs +++ b/src/func.rs @@ -25,6 +25,7 @@ pub enum Function { BitOr, Random, Round, + Md5, #[cfg(feature = "backend-postgres")] PgFunction(PgFunction), } @@ -38,8 +39,8 @@ pub struct FunctionCall { } #[derive(Debug, Default, Copy, Clone, PartialEq)] -pub(crate) struct FuncArgMod { - pub(crate) distinct: bool, +pub struct FuncArgMod { + pub distinct: bool, } impl FunctionCall { @@ -85,6 +86,10 @@ impl FunctionCall { pub fn get_args(&self) -> &[SimpleExpr] { &self.args } + + pub fn get_mods(&self) -> &[FuncArgMod] { + &self.mods + } } /// Function call helper. @@ -721,4 +726,33 @@ impl Func { pub fn random() -> FunctionCall { FunctionCall::new(Function::Random) } + + /// Call `MD5` function, this is only available in Postgres and MySQL. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .expr(Func::md5(Expr::col((Char::Table, Char::Character)))) + /// .from(Char::Table) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(MysqlQueryBuilder), + /// r#"SELECT MD5(`character`.`character`) FROM `character`"# + /// ); + /// + /// assert_eq!( + /// query.to_string(PostgresQueryBuilder), + /// r#"SELECT MD5("character"."character") FROM "character""# + /// ); + /// ``` + pub fn md5(expr: T) -> FunctionCall + where + T: Into, + { + FunctionCall::new(Function::Md5).arg(expr) + } } diff --git a/src/query/select.rs b/src/query/select.rs index dd39862a8..debd0807b 100644 --- a/src/query/select.rs +++ b/src/query/select.rs @@ -214,6 +214,37 @@ impl SelectStatement { self } + /// A shorthand to express if ... else ... when constructing the select statement. + /// + /// # Examples + /// + /// ``` + /// use sea_query::{tests_cfg::*, *}; + /// + /// let query = Query::select() + /// .column(Char::Character) + /// .from(Char::Table) + /// .apply_if(Some(5), |q, v| { + /// q.and_where(Expr::col(Char::FontId).eq(v)); + /// }) + /// .to_owned(); + /// + /// assert_eq!( + /// query.to_string(MysqlQueryBuilder), + /// r#"SELECT `character` FROM `character` WHERE `font_id` = 5"# + /// ); + /// ``` + pub fn apply_if(&mut self, val: Option, if_some: F) -> &mut Self + where + Self: Sized, + F: FnOnce(&mut Self, T), + { + if let Some(val) = val { + if_some(self, val); + } + self + } + /// Construct part of the select statement in another function. /// /// # Examples diff --git a/src/table/column.rs b/src/table/column.rs index eac4ee725..4f6d2ba9b 100644 --- a/src/table/column.rs +++ b/src/table/column.rs @@ -50,6 +50,7 @@ pub trait IntoColumnDef { /// | Uuid | binary(16) | uuid | uuid_text | /// | Enum | ENUM(...) | ENUM_NAME | enum_text | /// | Array | N/A | DATA_TYPE[] | N/A | +/// | Vector | N/A | vector | N/A | /// | Cidr | N/A | cidr | N/A | /// | Inet | N/A | inet | N/A | /// | MacAddr | N/A | macaddr | N/A | @@ -94,6 +95,7 @@ pub enum ColumnType { variants: Vec, }, Array(RcOrArc), + Vector(Option), Cidr, Inet, MacAddr, @@ -454,6 +456,12 @@ impl ColumnDef { self } + #[cfg(feature = "postgres-vector")] + pub fn vector(&mut self, size: Option) -> &mut Self { + self.types = Some(ColumnType::Vector(size)); + self + } + /// Set column type as timestamp pub fn timestamp(&mut self) -> &mut Self { self.types = Some(ColumnType::Timestamp); diff --git a/src/value.rs b/src/value.rs index 3c9dbbf28..7ca60fff6 100644 --- a/src/value.rs +++ b/src/value.rs @@ -234,6 +234,19 @@ pub enum Value { #[cfg_attr(docsrs, doc(cfg(feature = "postgres-array")))] Array(ArrayType, Option>>), + #[cfg(feature = "postgres-vector")] + #[cfg_attr(docsrs, doc(cfg(feature = "postgres-vector")))] + Vector( + #[cfg_attr( + feature = "hashable-value", + educe( + Hash(method(hashable_value::hash_vector)), + PartialEq(method(hashable_value::cmp_vector)) + ) + )] + Option>, + ), + #[cfg(feature = "with-ipnetwork")] #[cfg_attr(docsrs, doc(cfg(feature = "with-ipnetwork")))] IpNetwork(Option>), @@ -893,6 +906,45 @@ pub mod with_array { } } +#[cfg(feature = "postgres-vector")] +#[cfg_attr(docsrs, doc(cfg(feature = "postgres-vector")))] +pub mod with_vector { + use super::*; + + impl From for Value { + fn from(x: pgvector::Vector) -> Value { + Value::Vector(Some(Box::new(x))) + } + } + + impl Nullable for pgvector::Vector { + fn null() -> Value { + Value::Vector(None) + } + } + + impl ValueType for pgvector::Vector { + fn try_from(v: Value) -> Result { + match v { + Value::Vector(Some(x)) => Ok(*x), + _ => Err(ValueTypeErr), + } + } + + fn type_name() -> String { + stringify!(Vector).to_owned() + } + + fn array_type() -> ArrayType { + unimplemented!("Vector does not have array type") + } + + fn column_type() -> ColumnType { + ColumnType::Vector(None) + } + } +} + #[allow(unused_macros)] macro_rules! box_to_opt_ref { ( $v: expr ) => { @@ -1392,6 +1444,8 @@ pub fn sea_value_to_json_value(value: &Value) -> Json { Value::Uuid(None) => Json::Null, #[cfg(feature = "postgres-array")] Value::Array(_, None) => Json::Null, + #[cfg(feature = "postgres-vector")] + Value::Vector(None) => Json::Null, #[cfg(feature = "with-ipnetwork")] Value::IpNetwork(None) => Json::Null, #[cfg(feature = "with-mac_address")] @@ -1447,6 +1501,8 @@ pub fn sea_value_to_json_value(value: &Value) -> Json { Value::Array(_, Some(v)) => { Json::Array(v.as_ref().iter().map(sea_value_to_json_value).collect()) } + #[cfg(feature = "postgres-vector")] + Value::Vector(Some(v)) => Json::Array(v.as_slice().iter().map(|&v| v.into()).collect()), #[cfg(feature = "with-ipnetwork")] Value::IpNetwork(Some(_)) => CommonSqlQueryBuilder.value_to_string(value).into(), #[cfg(feature = "with-mac_address")] @@ -1969,6 +2025,41 @@ mod hashable_value { } } + #[cfg(feature = "postgres-vector")] + pub fn hash_vector(v: &Option>, state: &mut H) { + match v { + Some(v) => { + for &value in v.as_slice().iter() { + hash_f32(&Some(value), state); + } + } + None => "null".hash(state), + } + } + + #[cfg(feature = "postgres-vector")] + pub fn cmp_vector( + l: &Option>, + r: &Option>, + ) -> bool { + match (l, r) { + (Some(l), Some(r)) => { + let (l, r) = (l.as_slice(), r.as_slice()); + if l.len() != r.len() { + return false; + } + for (l, r) in l.iter().zip(r.iter()) { + if !cmp_f32(&Some(*l), &Some(*r)) { + return false; + } + } + true + } + (None, None) => true, + _ => false, + } + } + #[test] fn test_hash_value_0() { let hash_set: std::collections::HashSet = [ diff --git a/tests/mysql/query.rs b/tests/mysql/query.rs index a9e46525b..c0bb2e7dc 100644 --- a/tests/mysql/query.rs +++ b/tests/mysql/query.rs @@ -1061,6 +1061,16 @@ fn select_61() { ); } +#[test] +fn md5_fn() { + assert_eq!( + Query::select() + .expr(Func::md5(Expr::val("test"))) + .to_string(MysqlQueryBuilder), + r#"SELECT MD5('test')"# + ); +} + #[test] #[allow(clippy::approx_constant)] fn insert_2() { diff --git a/tests/postgres/query.rs b/tests/postgres/query.rs index a00d57513..804818b1d 100644 --- a/tests/postgres/query.rs +++ b/tests/postgres/query.rs @@ -1925,6 +1925,16 @@ fn sub_query_with_fn() { ); } +#[test] +fn md5_fn() { + assert_eq!( + Query::select() + .expr(Func::md5(Expr::val("test"))) + .to_string(PostgresQueryBuilder), + r#"SELECT MD5('test')"# + ); +} + #[test] fn select_array_contains_bin_oper() { assert_eq!( @@ -2110,3 +2120,18 @@ fn test_issue_674_nested_logical_panic() { r#"SELECT "character" FROM "character" WHERE TRUE AND (TRUE AND TRUE AND TRUE)"# ); } + +#[test] +#[cfg(feature = "postgres-vector")] +fn test_pgvector_select() { + assert_eq!( + Query::select() + .columns([Char::Character]) + .from(Char::Table) + .and_where( + Expr::col(Char::Character).eq(Expr::val(pgvector::Vector::from(vec![1.0, 2.0]))) + ) + .to_string(PostgresQueryBuilder), + r#"SELECT "character" FROM "character" WHERE "character" = '[1,2]'"# + ); +}