Skip to content

Commit 6ca52fe

Browse files
authored
Added missing special casing for encoding embedded arrays of custom types (#3603)
* Added missing special casing for encoding arrays of custom types * Added the matching test * Formatting
1 parent 6c2a29f commit 6ca52fe

File tree

2 files changed

+70
-4
lines changed

2 files changed

+70
-4
lines changed

sqlx-postgres/src/types/record.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ impl<'a> PgRecordEncoder<'a> {
4141
{
4242
let ty = value.produces().unwrap_or_else(T::type_info);
4343

44-
if let PgType::DeclareWithName(name) = ty.0 {
44+
match ty.0 {
4545
// push a hole for this type ID
4646
// to be filled in on query execution
47-
self.buf.patch_type_by_name(&name);
48-
} else {
47+
PgType::DeclareWithName(name) => self.buf.patch_type_by_name(&name),
48+
PgType::DeclareArrayOf(array) => self.buf.patch_array_type(array),
4949
// write type id
50-
self.buf.extend(&ty.0.oid().0.to_be_bytes());
50+
pg_type => self.buf.extend(&pg_type.oid().0.to_be_bytes()),
5151
}
5252

5353
self.buf.encode(value)?;

tests/postgres/derives.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,3 +810,69 @@ async fn test_custom_pg_array() -> anyhow::Result<()> {
810810
}
811811
Ok(())
812812
}
813+
814+
#[sqlx_macros::test]
815+
async fn test_record_array_type() -> anyhow::Result<()> {
816+
let mut conn = new::<Postgres>().await?;
817+
818+
conn.execute(
819+
r#"
820+
DROP TABLE IF EXISTS responses;
821+
822+
DROP TYPE IF EXISTS http_response CASCADE;
823+
DROP TYPE IF EXISTS header_pair CASCADE;
824+
825+
CREATE TYPE header_pair AS (
826+
name TEXT,
827+
value TEXT
828+
);
829+
830+
CREATE TYPE http_response AS (
831+
headers header_pair[]
832+
);
833+
834+
CREATE TABLE responses (
835+
response http_response NOT NULL
836+
);
837+
"#,
838+
)
839+
.await?;
840+
841+
#[derive(Debug, sqlx::Type)]
842+
#[sqlx(type_name = "http_response")]
843+
struct HttpResponseRecord {
844+
headers: Vec<HeaderPairRecord>,
845+
}
846+
847+
#[derive(Debug, sqlx::Type)]
848+
#[sqlx(type_name = "header_pair")]
849+
struct HeaderPairRecord {
850+
name: String,
851+
value: String,
852+
}
853+
854+
let value = HttpResponseRecord {
855+
headers: vec![
856+
HeaderPairRecord {
857+
name: "Content-Type".to_owned(),
858+
value: "text/html; charset=utf-8".to_owned(),
859+
},
860+
HeaderPairRecord {
861+
name: "Cache-Control".to_owned(),
862+
value: "max-age=0".to_owned(),
863+
},
864+
],
865+
};
866+
867+
sqlx::query(
868+
"
869+
INSERT INTO responses (response)
870+
VALUES ($1)
871+
",
872+
)
873+
.bind(&value)
874+
.execute(&mut conn)
875+
.await?;
876+
877+
Ok(())
878+
}

0 commit comments

Comments
 (0)