Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -30,7 +30,7 @@ path = "src/lib.rs"
[dependencies]
inherent = "1.0"
sea-query-derive = { version = "1.0.0-rc", path = "sea-query-derive", 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"] }
postgres-types = { version = "0", default-features = false, optional = true }
Expand Down
2 changes: 1 addition & 1 deletion sea-query-postgres/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ rust-version = "1.85.0"
[lib]

[dependencies]
sea-query = { version = "1.0.0-rc.1", path = "..", default-features = false }
sea-query = { version = "1.0.0-rc.1", path = "..", default-features = false, features = ["backend-postgres"] }
postgres-types = { version = "0.2", default-features = false }
pgvector = { version = "~0.4", default-features = false, optional = true }
bytes = { version = "1", default-features = false }
Expand Down
165 changes: 144 additions & 21 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,10 @@ 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(_) => Err(PostgresBindError::new(
"Binding Enum is not supported by sea-query-postgres binder",
)
.into()),
#[cfg(feature = "with-json")]
Value::Json(v) => v.to_sql(ty, out),
#[cfg(feature = "with-chrono")]
Expand Down Expand Up @@ -104,38 +110,126 @@ impl ToSql for PostgresValue {
#[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"))
.to_sql(ty, out)
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(|x| i64::try_from(x)).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),
Array::Array(_) => Err(PostgresBindError::new(
"Nested arrays (Array::Array) are not supported by sea-query-postgres binder",
)
.into()),
Array::Enum(_) => Err(PostgresBindError::new(
"Array of Enum is not supported by sea-query-postgres binder; consider casting in SQL",
)
.into()),
_ => 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),
}
}

Expand All @@ -145,3 +239,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")
}
2 changes: 1 addition & 1 deletion sea-query-rusqlite/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ 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")]
Expand Down
2 changes: 1 addition & 1 deletion sea-query-sqlx/src/sqlx_any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,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
4 changes: 2 additions & 2 deletions sea-query-sqlx/src/sqlx_mysql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,14 @@ impl sqlx::IntoArguments<'_, sqlx::mysql::MySql> for SqlxValues {
}
#[cfg(feature = "with-bigdecimal")]
Value::BigDecimal(d) => {
let _ = args.add(d.as_deref());
let _ = args.add(d.as_ref());
}
#[cfg(feature = "with-json")]
Value::Json(j) => {
let _ = args.add(j);
}
#[cfg(feature = "postgres-array")]
Value::Array(_, _) => {
Value::Array(_) => {
panic!("Mysql doesn't support array arguments");
}
#[cfg(feature = "postgres-vector")]
Expand Down
Loading
Loading