Skip to content

Commit

Permalink
allow using hstore and hstore[] in macros
Browse files Browse the repository at this point in the history
  • Loading branch information
ibotty committed Sep 20, 2024
1 parent a496413 commit ec8c030
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 0 deletions.
3 changes: 3 additions & 0 deletions sqlx-postgres/src/type_checking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@ impl_type_checking!(
#[cfg(feature = "time")]
Vec<sqlx::postgres::types::PgRange<sqlx::types::time::OffsetDateTime>> |
&[sqlx::postgres::types::PgRange<sqlx::types::time::OffsetDateTime>],

sqlx::postgres::types::PgHstore,
Vec<sqlx::postgres::types::PgHstore> | &[sqlx::postgres::types::PgHstore],
},
ParamChecking::Strong,
feature-types: info => info.__type_feature_gate(),
Expand Down
8 changes: 8 additions & 0 deletions sqlx-postgres/src/types/hstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ use crate::{
use serde::{Deserialize, Serialize};
use sqlx_core::bytes::Buf;

use super::PgHasArrayType;

/// Key-value support (`hstore`) for Postgres.
///
/// SQLx currently maps `hstore` to a `BTreeMap<String, Option<String>>` but this may be expanded in
Expand Down Expand Up @@ -138,6 +140,12 @@ impl Type<Postgres> for PgHstore {
}
}

impl PgHasArrayType for PgHstore {
fn array_type_info() -> PgTypeInfo {
PgTypeInfo::array_of("hstore")
}
}

impl<'r> Decode<'r, Postgres> for PgHstore {
fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
let mut buf = <&[u8] as Decode<Postgres>>::decode(value)?;
Expand Down
43 changes: 43 additions & 0 deletions tests/postgres/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,49 @@ async fn test_query() -> anyhow::Result<()> {
Ok(())
}

#[sqlx_macros::test]
async fn test_hstores() -> anyhow::Result<()> {
let mut conn = new::<Postgres>().await?;

let _ = sqlx::query!(
"INSERT INTO test_hstores(stores) VALUES ($1);",
&[
sqlx::postgres::types::PgHstore::from_iter([("key1".to_string(), "value".to_string())]),
sqlx::postgres::types::PgHstore::from_iter([("key2".to_string(), "value".to_string())]),
]
)
.execute(&mut conn)
.await?;

let record = sqlx::query!("SELECT stores FROM test_hstores LIMIT 1;")
.fetch_one(&mut conn)
.await?;

assert_eq!(record.stores.unwrap()[1]["key2"], Some("value".to_string()));

Ok(())
}

#[sqlx_macros::test]
async fn test_hstore() -> anyhow::Result<()> {
let mut conn = new::<Postgres>().await?;

let _ = sqlx::query!(
"INSERT INTO test_hstore(store) VALUES ($1);",
sqlx::postgres::types::PgHstore::from_iter([("key".to_string(), "value".to_string())])
)
.execute(&mut conn)
.await?;

let record = sqlx::query!("SELECT store FROM test_hstore LIMIT 1;")
.fetch_one(&mut conn)
.await?;

assert_eq!(record.store.unwrap()["key"], Some("value".to_string()));

Ok(())
}

#[sqlx_macros::test]
async fn test_non_null() -> anyhow::Result<()> {
let mut conn = new::<Postgres>().await?;
Expand Down
6 changes: 6 additions & 0 deletions tests/postgres/setup.sql
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ CREATE EXTENSION IF NOT EXISTS cube;
-- https://www.postgresql.org/docs/current/citext.html
CREATE EXTENSION IF NOT EXISTS citext;

-- https://www.postgresql.org/docs/current/hstore.html
CREATE EXTENSION IF NOT EXISTS hstore;

-- https://www.postgresql.org/docs/current/sql-createtype.html
CREATE TYPE status AS ENUM ('new', 'open', 'closed');

Expand Down Expand Up @@ -58,3 +61,6 @@ CREATE TABLE test_citext (
CREATE SCHEMA IF NOT EXISTS foo;

CREATE TYPE foo."Foo" as ENUM ('Bar', 'Baz');

CREATE TABLE test_hstore(id_test_hstore SERIAL, store HSTORE);
CREATE TABLE test_hstores(id_test_hstores SERIAL, stores HSTORE[]);

0 comments on commit ec8c030

Please sign in to comment.