Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
6ae05ef
Add postgres enum value support
Huliiiiii Oct 21, 2025
52ab44b
Refactor Value::Array
Huliiiiii Oct 28, 2025
fea232c
WIP
Huliiiiii Oct 23, 2025
114a16a
Update
Huliiiiii Oct 27, 2025
6e3869b
Update
Huliiiiii Oct 28, 2025
929dc47
Rename
Huliiiiii Oct 28, 2025
582d676
Pass value instead of reference
Huliiiiii Oct 28, 2025
33a8ef8
Tweak
Huliiiiii Oct 28, 2025
4ec2b45
Refactor
Huliiiiii Oct 28, 2025
b7abc21
Fix
Huliiiiii Oct 28, 2025
087356c
Replace `ARRAY [` with `ARRAY[`
Huliiiiii Oct 28, 2025
6c2a598
Fix rust postgres binder
Huliiiiii Oct 28, 2025
e3449a2
Fix sqlx except pg
Huliiiiii Oct 28, 2025
36e4b10
Fix
Huliiiiii Oct 29, 2025
4e1b37a
Tweak
Huliiiiii Oct 29, 2025
b7505dc
Refactor Postgres binder error handling
Huliiiiii Oct 29, 2025
17e2e60
Refactor Postgres binder error handling
Huliiiiii Oct 29, 2025
533758b
Remove try_from_parts
Huliiiiii Oct 29, 2025
ba70b69
Remove panics
Huliiiiii Oct 29, 2025
dbd10e7
Merge remote-tracking branch 'upstream/master' into value-array
Huliiiiii Dec 2, 2025
2fd6b4a
Update
Huliiiiii Dec 2, 2025
e6f1679
Fmt
Huliiiiii Dec 2, 2025
6390c10
Fix
Huliiiiii Dec 2, 2025
fbb1307
Fix
Huliiiiii Dec 2, 2025
e50012b
Fmt
Huliiiiii Dec 2, 2025
885e401
Fix
Huliiiiii Dec 2, 2025
21b821b
Fix
Huliiiiii Dec 2, 2025
75c37f5
Fix
Huliiiiii Dec 2, 2025
05eecc8
Bump ipnetwork
Huliiiiii Dec 2, 2025
82566a1
Revert
Huliiiiii Dec 2, 2025
d7632e1
Fix
Huliiiiii Dec 2, 2025
ee86f23
Update
Huliiiiii Dec 3, 2025
ea28377
Cleanup features
Huliiiiii Dec 3, 2025
79848f8
Support postgres enums and try fix example
Huliiiiii Dec 3, 2025
fe025f6
Fix
Huliiiiii Dec 3, 2025
e9db159
Revert
Huliiiiii Dec 3, 2025
6f0c317
Remove nested array
Huliiiiii Dec 3, 2025
26f23d5
Tweak
Huliiiiii Dec 3, 2025
d0602fa
Keep range as it is
Huliiiiii Dec 3, 2025
da57a27
Remove unneed impls
Huliiiiii Dec 4, 2025
2cd856c
Fix
Huliiiiii Dec 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ path = "src/lib.rs"
inherent = "1.0"
sea-query-derive = { version = "1.0.0-rc", path = "sea-query-derive", optional = true }
sea-query-postgres-types = { version = "0.1.0", path = "sea-query-postgres-types", optional = true }
serde = { version = "1", default-features = false, optional = true, features = ["std", "derive"] }
serde = { version = "1", default-features = false, optional = true, features = ["std", "derive", "rc"] }
serde_json = { version = "1", default-features = false, optional = true, features = ["std"] }
chrono = { version = "0.4.27", default-features = false, optional = true, features = ["clock"] }
pgvector = { version = "~0.4", default-features = false, optional = true }
Expand Down
5 changes: 3 additions & 2 deletions sea-query-diesel/src/backend/mysql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,18 @@ impl TransformValue for Mysql {
))]
Value::Decimal(_) => bail!("Enable feature with-rust_decimal-mysql"),
#[cfg(feature = "with-bigdecimal")]
Value::BigDecimal(v) => build!(Numeric, v.map(|v| *v)),
Value::BigDecimal(v) => build!(Numeric, v),
#[cfg(feature = "with-json")]
Value::Json(v) => build!(Json, v),
#[cfg(feature = "with-ipnetwork")]
Value::IpNetwork(_) => bail!("Mysql doesn't support IpNetwork arguments"),
#[cfg(feature = "with-mac_address")]
Value::MacAddress(_) => bail!("Mysql doesn't support MacAddress arguments"),
#[cfg(feature = "postgres-array")]
Value::Array(_, _) => bail!("Mysql doesn't support array arguments"),
Value::Array(_) => bail!("Mysql doesn't support array arguments"),
#[cfg(feature = "postgres-vector")]
Value::Vector(_) => bail!("Mysql doesn't support vector arguments"),
Value::Enum(_) => bail!("Mysql doesn't support enum arguments"),
};
Ok(transformed)
}
Expand Down
330 changes: 205 additions & 125 deletions sea-query-diesel/src/backend/postgres.rs

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion sea-query-diesel/src/backend/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,10 @@ impl TransformValue for Sqlite {
#[cfg(feature = "with-mac_address")]
Value::MacAddress(_) => bail!("Sqlite doesn't support MacAddress arguments"),
#[cfg(feature = "postgres-array")]
Value::Array(_, _) => bail!("Sqlite doesn't support array arguments"),
Value::Array(_) => bail!("Sqlite doesn't support array arguments"),
#[cfg(feature = "postgres-vector")]
Value::Vector(_) => bail!("Sqlite doesn't support vector arguments"),
Value::Enum(v) => build!(Text, v.map(|v| v.as_str().to_owned())),
};
Ok(transformed)
}
Expand Down
3 changes: 2 additions & 1 deletion sea-query-postgres-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ default = ["hashable-value"]
postgres-driver = ["postgres-protocol", "postgres-types", "bytes"]
hashable-value = ["ordered-float"]
range = []
serde = ["dep:serde"]
serde = ["dep:serde"]

1 change: 1 addition & 0 deletions sea-query-postgres/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ with-mac_address = [
"mac_address",
"eui48",
]
with-jiff = ["postgres-types/with-jiff-0_2", "sea-query/with-jiff"]
187 changes: 167 additions & 20 deletions sea-query-postgres/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use std::error::Error;
use bytes::BytesMut;
use postgres_types::{IsNull, ToSql, Type, to_sql_checked};

#[cfg(feature = "postgres-array")]
use sea_query::Array;
use sea_query::{QueryBuilder, Value, query::*};

#[derive(Clone, Debug, PartialEq)]
Expand Down Expand Up @@ -77,6 +79,7 @@ impl ToSql for PostgresValue {
Value::String(v) => v.as_deref().to_sql(ty, out),
Value::Char(v) => v.map(|v| v.to_string()).to_sql(ty, out),
Value::Bytes(v) => v.as_deref().to_sql(ty, out),
Value::Enum(v) => v.as_ref().map(|v| v.as_str()).to_sql(ty, out),
#[cfg(feature = "with-json")]
Value::Json(v) => v.to_sql(ty, out),
#[cfg(feature = "with-chrono")]
Expand All @@ -99,43 +102,158 @@ impl ToSql for PostgresValue {
Value::TimeDateTime(v) => v.to_sql(ty, out),
#[cfg(feature = "with-time")]
Value::TimeDateTimeWithTimeZone(v) => v.to_sql(ty, out),
#[cfg(feature = "with-jiff")]
Value::JiffDate(v) => v.to_sql(ty, out),
#[cfg(feature = "with-jiff")]
Value::JiffTime(v) => v.to_sql(ty, out),
#[cfg(feature = "with-jiff")]
Value::JiffDateTime(v) => v.to_sql(ty, out),
#[cfg(feature = "with-jiff")]
Value::JiffTimestamp(v) => v.to_sql(ty, out),
#[cfg(feature = "with-jiff")]
Value::JiffZoned(v) => v.as_ref().map(|z| z.timestamp()).to_sql(ty, out),
#[cfg(feature = "with-rust_decimal")]
Value::Decimal(v) => v.to_sql(ty, out),
#[cfg(feature = "with-bigdecimal")]
Value::BigDecimal(v) => {
use bigdecimal::ToPrimitive;
v.as_deref()
.map(|v| v.to_f64().expect("Fail to convert bigdecimal as f64"))
v.as_ref()
.map(|x| {
x.to_f64().ok_or(PostgresBindError::new(
"Fail to convert bigdecimal as f64 for sea-query-postgres binder",
))
})
.transpose()?
.to_sql(ty, out)
}
#[cfg(feature = "with-uuid")]
Value::Uuid(v) => v.to_sql(ty, out),
#[cfg(feature = "postgres-array")]
Value::Array(_, Some(v)) => v
.iter()
.map(|v| PostgresValue(v.clone()))
.collect::<Vec<PostgresValue>>()
.to_sql(ty, out),
Value::Array(Some(arr)) => match arr {
Array::Bool(inner) => inner.to_sql(ty, out),
Array::TinyInt(inner) => inner.to_sql(ty, out),
Array::SmallInt(inner) => inner.to_sql(ty, out),
Array::Int(inner) => inner.to_sql(ty, out),
Array::BigInt(inner) => inner.to_sql(ty, out),
Array::TinyUnsigned(inner) => inner
.iter()
.map(|v| v.map(|x| x as u32))
.collect::<Vec<Option<_>>>()
.to_sql(ty, out),
Array::SmallUnsigned(inner) => inner
.iter()
.map(|v| v.map(|x| x as u32))
.collect::<Vec<Option<_>>>()
.to_sql(ty, out),
Array::Unsigned(inner) => inner.to_sql(ty, out),
Array::BigUnsigned(inner) => inner
.into_iter()
.map(|v| v.map(i64::try_from).transpose())
.collect::<Result<Vec<Option<_>>, _>>()?
.to_sql(ty, out),
Array::Float(inner) => inner.to_sql(ty, out),
Array::Double(inner) => inner.to_sql(ty, out),
Array::String(inner) => inner.to_sql(ty, out),
Array::Char(inner) => inner
.into_iter()
.map(|v| v.map(|c| c.to_string()))
.collect::<Vec<Option<String>>>()
.to_sql(ty, out),
Array::Bytes(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-json")]
Array::Json(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-chrono")]
Array::ChronoDate(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-chrono")]
Array::ChronoTime(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-chrono")]
Array::ChronoDateTime(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-chrono")]
Array::ChronoDateTimeUtc(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-chrono")]
Array::ChronoDateTimeLocal(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-chrono")]
Array::ChronoDateTimeWithTimeZone(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-time")]
Array::TimeDate(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-time")]
Array::TimeTime(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-time")]
Array::TimeDateTime(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-time")]
Array::TimeDateTimeWithTimeZone(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-uuid")]
Array::Uuid(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-rust_decimal")]
Array::Decimal(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-bigdecimal")]
Array::BigDecimal(inner) => {
use bigdecimal::ToPrimitive;
inner
.iter()
.map(|v| {
v.as_ref()
.map(|bd| {
bd.to_f64().ok_or(PostgresBindError::new(
"Fail to convert bigdecimal as f64 for sea-query-postgres binder",
))
})
.transpose()
})
.collect::<Result<Vec<Option<f64>>, _>>()?
.to_sql(ty, out)
}
#[cfg(feature = "with-ipnetwork")]
Array::IpNetwork(inner) => inner
.iter()
.cloned()
.map(|v| v.map(conv_ip_network))
.collect::<Vec<_>>()
.to_sql(ty, out),
#[cfg(feature = "with-mac_address")]
Array::MacAddress(inner) => inner
.into_iter()
.map(|v| v.map(conv_mac_address))
.collect::<Vec<_>>()
.to_sql(ty, out),
#[cfg(feature = "with-jiff")]
Array::JiffDate(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-jiff")]
Array::JiffTime(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-jiff")]
Array::JiffDateTime(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-jiff")]
Array::JiffTimestamp(inner) => inner.to_sql(ty, out),
#[cfg(feature = "with-jiff")]
Array::JiffZoned(inner) => inner
.iter()
.map(|v| v.as_ref().map(|z| z.timestamp()))
.collect::<Vec<_>>()
.to_sql(ty, out),
Array::Enum(v) => {
// Convert array of enum to array of text
v.as_ref()
.1
.iter()
.map(|opt| opt.as_ref().map(|r#enum| r#enum.as_str()))
.collect::<Vec<_>>()
.to_sql(ty, out)
}
_ => Err(PostgresBindError::new(
"Unsupported array variant for sea-query-postgres binder",
)
.into()),
},
#[cfg(feature = "postgres-array")]
Value::Array(_, None) => Ok(IsNull::Yes),
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;
v.map(|v| {
IpCidr::new(v.network(), v.prefix())
.expect("Fail to convert IpNetwork to IpCidr")
})
.to_sql(ty, out)
}
Value::IpNetwork(v) => v.map(conv_ip_network).to_sql(ty, out),
#[cfg(feature = "with-mac_address")]
Value::MacAddress(v) => {
use eui48::MacAddress;
v.map(|v| MacAddress::new(v.bytes())).to_sql(ty, out)
}
Value::MacAddress(v) => v.map(conv_mac_address).to_sql(ty, out),
#[cfg(feature = "postgres-range")]
Value::Range(None) => Ok(IsNull::Yes),
#[cfg(feature = "postgres-range")]
Expand All @@ -149,3 +267,32 @@ impl ToSql for PostgresValue {

to_sql_checked!();
}

#[derive(Debug, Clone)]
struct PostgresBindError(&'static str);

impl PostgresBindError {
fn new(msg: &'static str) -> Self {
Self(msg)
}
}

impl std::fmt::Display for PostgresBindError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.0)
}
}

impl Error for PostgresBindError {}

#[cfg(feature = "with-mac_address")]
fn conv_mac_address(input: mac_address::MacAddress) -> eui48::MacAddress {
use eui48::MacAddress;
MacAddress::new(input.bytes())
}

#[cfg(feature = "with-ipnetwork")]
fn conv_ip_network(input: ipnetwork::IpNetwork) -> cidr::IpCidr {
use cidr::IpCidr;
IpCidr::new(input.network(), input.prefix()).expect("Fail to convert IpNetwork to IpCidr")
}
6 changes: 5 additions & 1 deletion sea-query-rusqlite/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,17 @@ impl ToSql for RusqliteValue {
panic!("Rusqlite doesn't support MacAddress arguments");
}
#[cfg(feature = "postgres-array")]
Value::Array(_, _) => {
Value::Array(_) => {
panic!("Rusqlite doesn't support Array arguments");
}
#[cfg(feature = "postgres-vector")]
Value::Vector(_) => {
panic!("Rusqlite doesn't support Vector arguments");
}
Value::Enum(v) => match v {
Some(v) => v.as_str().to_sql(),
None => Null.to_sql(),
},
}
}
}
8 changes: 6 additions & 2 deletions sea-query-sqlx/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@ time = { version = "0.3.36", default-features = false, optional = true, features
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 }
jiff-sqlx = { version = "0.1", default-features = false, optional = true }
sea-query-postgres-types = { version = "0.1.0", path = "../sea-query-postgres-types", default-features = false, optional = true }

[features]
sqlx-mysql = ["sqlx/mysql"]
sqlx-postgres = ["sqlx/postgres"]
sqlx-sqlite = ["sqlx/sqlite"]
sqlx-postgres = ["sqlx/postgres", "jiff-sqlx?/postgres"]
sqlx-sqlite = ["sqlx/sqlite", "jiff-sqlx?/sqlite"]
sqlx-any = ["sqlx/any"]
with-chrono = ["sqlx?/chrono", "sea-query/with-chrono", "chrono"]
with-json = ["sqlx?/json", "sea-query/with-json", "serde_json"]
Expand All @@ -42,8 +44,10 @@ with-uuid = ["sqlx?/uuid", "sea-query/with-uuid", "uuid"]
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"]
with-jiff = ["sea-query/with-jiff", "jiff-sqlx"]
postgres-array = ["sea-query/postgres-array"]
postgres-vector = ["sea-query/postgres-vector", "pgvector/sqlx"]
postgres-range = ["sea-query/postgres-range", "sea-query-postgres-types/range"]
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", ]
Expand Down
25 changes: 24 additions & 1 deletion sea-query-sqlx/src/sqlx_any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,29 @@ impl<'q> sqlx::IntoArguments<'q, sqlx::any::Any> for SqlxValues {
let _ =
args.add(Value::TimeDateTimeWithTimeZone(t).time_as_naive_utc_in_string());
}
#[cfg(feature = "with-jiff")]
Value::JiffDate(_) => {
panic!("SQLx doesn't support Jiff arguments for Any");
}
#[cfg(feature = "with-jiff")]
Value::JiffTime(_) => {
panic!("SQLx doesn't support Jiff arguments for Any");
}
#[cfg(feature = "with-jiff")]
Value::JiffDateTime(_) => {
panic!("SQLx doesn't support Jiff arguments for Any");
}
#[cfg(feature = "with-jiff")]
Value::JiffTimestamp(_) => {
panic!("SQLx doesn't support Jiff arguments for Any");
}
#[cfg(feature = "with-jiff")]
Value::JiffZoned(_) => {
panic!("SQLx doesn't support Jiff arguments for Any");
}
Value::Enum(_) => {
panic!("SQLx doesn't support Postgres Enum arguments for Any");
}
#[cfg(feature = "with-uuid")]
Value::Uuid(_) => {
panic!("UUID support not implemented for Any");
Expand All @@ -117,7 +140,7 @@ impl<'q> sqlx::IntoArguments<'q, sqlx::any::Any> for SqlxValues {
panic!("SQLx doesn't support MacAddress arguments for Any");
}
#[cfg(feature = "postgres-array")]
Value::Array(_, _) => {
Value::Array(_) => {
panic!("SQLx doesn't support array arguments for Any");
}
#[cfg(feature = "postgres-vector")]
Expand Down
Loading
Loading