Thread: BUG #3693: PSQLException when using ResultSet.getLong(String) in turkish locale
BUG #3693: PSQLException when using ResultSet.getLong(String) in turkish locale
From
"Dirk Moebius"
Date:
The following bug has been logged online: Bug reference: 3693 Logged by: Dirk Moebius Email address: dirk.moebius@dorma.com PostgreSQL version: 8.2.4 Operating system: Windows 2000 Description: PSQLException when using ResultSet.getLong(String) in turkish locale Details: JDBC driver: postgresql-jdbc-8.2-506.zip OS: Windows 2000, but applies to other any other OS Java: Sun JRE 1.5.11 Using one of the get...(String columnName) methods in ResultSet in a JVM running in a turkish environment results in a PSQLException saying that the named column cannot be found. Here's the shortest testcase I could come up with: import java.sql.*; import java.util.Locale; public class PostgresLocaleProblem { public static void main(String[] args) throws Exception { Locale.setDefault(new Locale("tr", "TR")); Class.forName("org.postgresql.Driver"); String url = "jdbc:postgresql://localhost/?user=postgres&password=postgres"; Connection conn = DriverManager.getConnection(url); try { conn.setAutoCommit(true); conn.createStatement().execute("drop table if exists test"); conn.createStatement().execute("create table test ( id int )"); conn.createStatement().execute("insert into test values (1)"); ResultSet rs = conn.createStatement().executeQuery("select * from test"); rs.next(); System.out.println("id: " + rs.getLong("ID")); rs.close(); } finally { conn.close(); } } } This results in: Exception in thread "main" org.postgresql.util.PSQLException: The column name ID was not found in this ResultSet. at org.postgresql.jdbc2.AbstractJdbc2ResultSet.findColumn(AbstractJdbc2ResultSe t.java:2465) at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getLong(AbstractJdbc2ResultSet.j ava:2332) at PostgresLocaleProblem.main(PostgresLocaleProblem.java:18) (I translated the turkish exception message text for you.) The reason is that AbstractJdbc2ResultSet.findColumn() uses an internal HashMap for quick access to the field indices of the result set (because of performance reasons, I guess). The problem is that the HashMap is keyed by toLowerCase() values of the field names. The lowercase variant of columnName "ID" in the turkish locale is "ıd" (the i doesn't have a dot), so it is not "id", so the column is not found. When using toLowerCase(), the developer must be well aware that Java always applies the standard Unicode collation functions. So lowercasing a char/String may not always result the expected result. Note that in the swedish locale there's exactly the same problem. A correct solution would be to use locale agnostic keys in the HashMap, e.g. by defining something like this: class LocaleAgnosticCaseInsensitiveHashMap extends HashMap { public Object get(String key) { return super.get(transformKey(key)); } public void put(String key, Object value) { super.put(transformKey(key), value); } private String transformKey(String key) { return key.toLowerCase(Locale.US); } } Hope this helps. Dirk.