From 611016175cd46259bc0b3b6c47e16b8baea259a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juha=20Syrj=C3=A4l=C3=A4?= Date: Mon, 13 Sep 2021 12:20:28 +0300 Subject: [PATCH] PgDatabaseMetaData.getIndexInfo() cast operands to smallint (#2242) It is possible to break method PgDatabaseMetaData.getIndexInfo() by adding certain custom operators. This PR casts operands in a query so that PgDatabaseMetaData.getIndexInfo() works in presence of such operator config. Creating this operator triggers this issue: CREATE OR REPLACE FUNCTION f6(numeric, integer) returns integer as 'BEGIN return $1::integer & $2;END;' language plpgsql immutable; CREATE OPERATOR & (LEFTARG = numeric, RIGHTARG = integer, PROCEDURE = f6); Fixes #2241 --- .../main/java/org/postgresql/jdbc/PgDatabaseMetaData.java | 4 ++-- .../org/postgresql/test/jdbc2/DatabaseMetaDataTest.java | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java b/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java index a060504fff..42a54c49a1 100644 --- a/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java +++ b/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java @@ -2535,14 +2535,14 @@ public ResultSet getIndexInfo( + " trim(both '\"' from pg_catalog.pg_get_indexdef(tmp.CI_OID, tmp.ORDINAL_POSITION, false)) AS COLUMN_NAME, " + (connection.haveMinimumServerVersion(ServerVersion.v9_6) ? " CASE tmp.AM_NAME " - + " WHEN 'btree' THEN CASE tmp.I_INDOPTION[tmp.ORDINAL_POSITION - 1] & 1 " + + " WHEN 'btree' THEN CASE tmp.I_INDOPTION[tmp.ORDINAL_POSITION - 1] & 1::smallint " + " WHEN 1 THEN 'D' " + " ELSE 'A' " + " END " + " ELSE NULL " + " END AS ASC_OR_DESC, " : " CASE tmp.AM_CANORDER " - + " WHEN true THEN CASE tmp.I_INDOPTION[tmp.ORDINAL_POSITION - 1] & 1 " + + " WHEN true THEN CASE tmp.I_INDOPTION[tmp.ORDINAL_POSITION - 1] & 1::smallint " + " WHEN 1 THEN 'D' " + " ELSE 'A' " + " END " diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java index f088916cb5..bbe45131f0 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java +++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java @@ -120,6 +120,12 @@ public void setUp() throws Exception { "CREATE OR REPLACE FUNCTION f5() RETURNS TABLE (i int) LANGUAGE sql AS 'SELECT 1'"); } + // create a custom `&` operator, which caused failure with `&` usage in getIndexInfo() + stmt.execute( + "CREATE OR REPLACE FUNCTION f6(numeric, integer) returns integer as 'BEGIN return $1::integer & $2;END;' language plpgsql immutable;"); + stmt.execute("DROP OPERATOR IF EXISTS & (numeric, integer)"); + stmt.execute("CREATE OPERATOR & (LEFTARG = numeric, RIGHTARG = integer, PROCEDURE = f6)"); + TestUtil.createDomain(con, "nndom", "int not null"); TestUtil.createDomain(con, "varbit2", "varbit(3)"); TestUtil.createDomain(con, "float83", "numeric(8,3)"); @@ -154,6 +160,8 @@ public void tearDown() throws Exception { stmt.execute("DROP FUNCTION f1(int, varchar)"); stmt.execute("DROP FUNCTION f2(int, varchar)"); stmt.execute("DROP FUNCTION f3(int, varchar)"); + stmt.execute("DROP OPERATOR IF EXISTS & (numeric, integer)"); + stmt.execute("DROP FUNCTION f6(numeric, integer)"); TestUtil.dropTable(con, "domaintable"); TestUtil.dropDomain(con, "nndom"); TestUtil.dropDomain(con, "varbit2");