BUG #3693: PSQLException when using ResultSet.getLong(String) in turkish locale

From: "Dirk Moebius" <dirk(dot)moebius(at)dorma(dot)com>
To: pgsql-bugs(at)postgresql(dot)org
Subject: BUG #3693: PSQLException when using ResultSet.getLong(String) in turkish locale
Date: 2007-10-24 16:23:37
Message-ID: 200710241623.l9OGNblf022002@wwwmaster.postgresql.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs


The following bug has been logged online:

Bug reference: 3693
Logged by: Dirk Moebius
Email address: dirk(dot)moebius(at)dorma(dot)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.

Browse pgsql-bugs by date

  From Date Subject
Next Message Jakub Ouhrabka 2007-10-24 16:51:22 Re: Possible planner bug/regression introduced in 8.2.5
Previous Message Tom Lane 2007-10-24 14:01:22 Re: Possible planner bug/regression introduced in 8.2.5