Skip to content

Commit 43f84d6

Browse files
95ulisseabonander
authored andcommitted
Postgres OID resolution query does not take into account current search_path (#2133)
* Fix oid resolution query * Address review comments
1 parent e1b0049 commit 43f84d6

File tree

3 files changed

+72
-11
lines changed

3 files changed

+72
-11
lines changed

sqlx-postgres/src/connection/describe.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -344,17 +344,13 @@ WHERE rngtypid = $1
344344
}
345345

346346
// language=SQL
347-
let (oid,): (Oid,) = query_as(
348-
"
349-
SELECT oid FROM pg_catalog.pg_type WHERE typname ILIKE $1
350-
",
351-
)
352-
.bind(name)
353-
.fetch_optional(&mut *self)
354-
.await?
355-
.ok_or_else(|| Error::TypeNotFound {
356-
type_name: String::from(name),
357-
})?;
347+
let (oid,): (Oid,) = query_as("SELECT $1::regtype::oid")
348+
.bind(name)
349+
.fetch_optional(&mut *self)
350+
.await?
351+
.ok_or_else(|| Error::TypeNotFound {
352+
type_name: String::from(name),
353+
})?;
358354

359355
self.cache_type_oid.insert(name.to_string().into(), oid);
360356
Ok(oid)

sqlx-postgres/src/connection/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ impl Connection for PgConnection {
176176

177177
fn clear_cached_statements(&mut self) -> BoxFuture<'_, Result<(), Error>> {
178178
Box::pin(async move {
179+
self.cache_type_oid.clear();
180+
179181
let mut cleared = 0_usize;
180182

181183
self.wait_until_ready().await?;

tests/postgres/postgres.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,6 +1388,69 @@ VALUES
13881388
Ok(())
13891389
}
13901390

1391+
#[sqlx_macros::test]
1392+
async fn custom_type_resolution_respects_search_path() -> anyhow::Result<()> {
1393+
let mut conn = new::<Postgres>().await?;
1394+
1395+
conn.execute(
1396+
r#"
1397+
DROP TYPE IF EXISTS some_enum_type;
1398+
DROP SCHEMA IF EXISTS another CASCADE;
1399+
1400+
CREATE SCHEMA another;
1401+
CREATE TYPE some_enum_type AS ENUM ('a', 'b', 'c');
1402+
CREATE TYPE another.some_enum_type AS ENUM ('d', 'e', 'f');
1403+
"#,
1404+
)
1405+
.await?;
1406+
1407+
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1408+
struct SomeEnumType(String);
1409+
1410+
impl sqlx::Type<Postgres> for SomeEnumType {
1411+
fn type_info() -> sqlx::postgres::PgTypeInfo {
1412+
sqlx::postgres::PgTypeInfo::with_name("some_enum_type")
1413+
}
1414+
1415+
fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> bool {
1416+
*ty == Self::type_info()
1417+
}
1418+
}
1419+
1420+
impl<'r> sqlx::Decode<'r, Postgres> for SomeEnumType {
1421+
fn decode(
1422+
value: sqlx::postgres::PgValueRef<'r>,
1423+
) -> Result<Self, Box<dyn std::error::Error + 'static + Send + Sync>> {
1424+
Ok(Self(<String as sqlx::Decode<Postgres>>::decode(value)?))
1425+
}
1426+
}
1427+
1428+
impl<'q> sqlx::Encode<'q, Postgres> for SomeEnumType {
1429+
fn encode_by_ref(
1430+
&self,
1431+
buf: &mut sqlx::postgres::PgArgumentBuffer,
1432+
) -> sqlx::encode::IsNull {
1433+
<String as sqlx::Encode<Postgres>>::encode_by_ref(&self.0, buf)
1434+
}
1435+
}
1436+
1437+
let mut conn = new::<Postgres>().await?;
1438+
1439+
sqlx::query("set search_path = 'another'")
1440+
.execute(&mut conn)
1441+
.await?;
1442+
1443+
let result = sqlx::query("SELECT 1 WHERE $1::some_enum_type = 'd'::some_enum_type;")
1444+
.bind(SomeEnumType("d".into()))
1445+
.fetch_all(&mut conn)
1446+
.await;
1447+
1448+
let result = result.unwrap();
1449+
assert_eq!(result.len(), 1);
1450+
1451+
Ok(())
1452+
}
1453+
13911454
#[sqlx_macros::test]
13921455
async fn test_pg_server_num() -> anyhow::Result<()> {
13931456
let conn = new::<Postgres>().await?;

0 commit comments

Comments
 (0)