Postgres: Insert into a composite type containing varchar(256) doesn't work.
Bug Description
I have a table containing composite type that contains varchar(256). The table also contains other top-level fields, among whose there are the varchars are as well.
I used the derive trait for a rust type as instructed but keep receiving error
PgDatabaseError { severity: Error, code: "42804", message: "wrong data type: 25, expected 1043", detail: None, hint: None, position: None, where: None, schema: None, table: None, column: None, data_type: None, constraint: None, file: Some("rowtypes.c"), line: Some(557), routine: Some("record_recv") }
I found that the data type 25 is TEXT, while the expected 1043 is VARCHAR.
Indeed, if I change the type in the database, the insert statement succeeds.
Minimal Reproduction
I have a composite type containing varchar(256) (my_comptype) and a table (my_table) containing varchar(256) and my_comptype.
create schema my_schema;
create type my_schema.mycomp_type as (
inner varchar(256),
some_other varchar(256)
);
create table my_schema.my_table
(
outter varchar(256),
my_composite my_schema.mycomp_type
);
in the rust:
// definition
#[derive(sqlx::Type)]
#[sqlx(type_name = "my_schema.mycomp_type")]
// Macros are incompatible with struct lifetimes <----- THIS IS BTW ALSO PROBLEM
pub(crate) struct MyCompType {
inner: String,
some_other: String,
}
pub(crate) struct DbItem {
top_string: String,
my_comp_type: Option<MyCompType>,
}
/* snip */
// bulk insert:
let mut query_builder: sqlx::QueryBuilder<sqlx::Postgres> =
sqlx::QueryBuilder::new(r#"
INSERT INTO my_schema.my_table (
outter,
my_composite
) "#);
query_builder.push_values(top_string, |mut b, item| {
b.push_bind(item.some_top_string)
.push_bind(item.my_comp_type);
});
query_builder.build().execute(pool).await?;
This query fails if the DbItem.my_comp_type is Some(...) with the error given above. And succeeds if it is None.
Info
- SQLx version:
0.7.1 - SQLx features enabled:
["postgres", "bit-vec", "ipnetwork", "json", "chrono", "uuid", "runtime-tokio"] - Database server and version:
PostgreSQL 13.8 (Debian 13.8-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit - Operating system:
Arch linux: 6.4.2-arch1-1 #1 SMP PREEMPT_DYNAMIC Thu, 06 Jul 2023 18:35:54 +0000 x86_64 GNU/Linux -
rustc --version:rustc 1.69.0 (84c898d65 2023-04-16)
Yay! I am not doing something stupid.
I am having this issue too.
Doing something like this can "bypass" the issue.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VarCharString(pub String);
impl Type<Postgres> for VarCharString {
fn type_info() -> <Postgres as sqlx::Database>::TypeInfo {
PgTypeInfo::with_oid(Oid(1043))
}
}
impl Encode<'_, Postgres> for VarCharString {
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result<IsNull, BoxDynError> {
self.0.encode_by_ref(buf)
}
}
impl Decode<'_, Postgres> for VarCharString {
fn decode(value: PgValueRef<'_>) -> Result<Self, BoxDynError> {
String::decode(value).map(Self)
}
}