From 1cab2f8d8c4c456437e5a93c5ee3c202ebb65eda Mon Sep 17 00:00:00 2001 From: Dave Cramer Date: Fri, 30 Jul 2021 07:27:38 -0400 Subject: [PATCH] fix: backpatch type alias handling in TypeInfoCache PR #1986 --- .../org/postgresql/jdbc/TypeInfoCache.java | 50 ++++++++++++------- .../test/jdbc2/DatabaseMetaDataCacheTest.java | 11 ++++ 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/pgjdbc/src/main/java/org/postgresql/jdbc/TypeInfoCache.java b/pgjdbc/src/main/java/org/postgresql/jdbc/TypeInfoCache.java index a0504b1052..7f24e3db5e 100644 --- a/pgjdbc/src/main/java/org/postgresql/jdbc/TypeInfoCache.java +++ b/pgjdbc/src/main/java/org/postgresql/jdbc/TypeInfoCache.java @@ -28,6 +28,8 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.logging.Level; import java.util.logging.Logger; @@ -108,18 +110,29 @@ public class TypeInfoCache implements TypeInfo { /** * PG maps several alias to real type names. When we do queries against pg_catalog, we must use * the real type, not an alias, so use this mapping. + *

+ * Additional values used at runtime (including case variants) will be added to the map. + *

*/ - private static final HashMap typeAliases; + private static final ConcurrentMap TYPE_ALIASES = new ConcurrentHashMap<>(20); static { - typeAliases = new HashMap(); - typeAliases.put("smallint", "int2"); - typeAliases.put("integer", "int4"); - typeAliases.put("int", "int4"); - typeAliases.put("bigint", "int8"); - typeAliases.put("float", "float8"); - typeAliases.put("boolean", "bool"); - typeAliases.put("decimal", "numeric"); + TYPE_ALIASES.put("bool", "bool"); + TYPE_ALIASES.put("boolean", "bool"); + TYPE_ALIASES.put("smallint", "int2"); + TYPE_ALIASES.put("int2", "int2"); + TYPE_ALIASES.put("int", "int4"); + TYPE_ALIASES.put("integer", "int4"); + TYPE_ALIASES.put("int4", "int4"); + TYPE_ALIASES.put("long", "int8"); + TYPE_ALIASES.put("int8", "int8"); + TYPE_ALIASES.put("bigint", "int8"); + TYPE_ALIASES.put("float", "float4"); + TYPE_ALIASES.put("float4", "float4"); + TYPE_ALIASES.put("double", "float8"); + TYPE_ALIASES.put("float8", "float8"); + TYPE_ALIASES.put("decimal", "numeric"); + TYPE_ALIASES.put("numeric", "numeric"); } @SuppressWarnings("method.invocation.invalid") @@ -667,18 +680,21 @@ public synchronized String getJavaClass(int oid) throws SQLException { return result == null ? "java.lang.String" : result; } - public String getTypeForAlias(String alias) { - String type = typeAliases.get(alias); + public String getTypeForAlias(@Nullable String alias) { + if (alias == null) { + return null; + } + String type = TYPE_ALIASES.get(alias); if (type != null) { return type; } - if (alias.indexOf('"') == -1) { - type = typeAliases.get(alias.toLowerCase()); - if (type != null) { - return type; - } + type = TYPE_ALIASES.get(alias.toLowerCase()); + if (type == null) { + type = alias; } - return alias; + //populate for future use + TYPE_ALIASES.put(alias, type); + return type; } public int getPrecision(int oid, int typmod) { diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataCacheTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataCacheTest.java index 2382b6e717..d24f067a2b 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataCacheTest.java +++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/DatabaseMetaDataCacheTest.java @@ -6,6 +6,7 @@ package org.postgresql.test.jdbc2; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import org.postgresql.core.TypeInfo; import org.postgresql.jdbc.PgConnection; @@ -81,4 +82,14 @@ public void testGetTypeInfoUsesCache() throws SQLException { List typeQueries = log.getRecordsMatching(SQL_TYPE_QUERY_LOG_FILTER); assertEquals("PgDatabaseMetadata.getTypeInfo() resulted in individual queries for SQL typecodes", 0, typeQueries.size()); } + + @Test + public void testTypeForAlias() { + TypeInfo ti = con.getTypeInfo(); + assertEquals("bool", ti.getTypeForAlias("boolean")); + assertEquals("bool", ti.getTypeForAlias("Boolean")); + assertEquals("bool", ti.getTypeForAlias("Bool")); + assertEquals("bogus", ti.getTypeForAlias("bogus")); + assertNull(ti.getTypeForAlias(null)); + } }