BUG #3693: PSQLException when using ResultSet.getLong(String) in turkish locale - Mailing list pgsql-bugs

From Dirk Moebius
Subject BUG #3693: PSQLException when using ResultSet.getLong(String) in turkish locale
Date
Msg-id 200710241623.l9OGNblf022002@wwwmaster.postgresql.org
Whole thread Raw
List pgsql-bugs
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.

pgsql-bugs by date:

Previous
From: Tom Lane
Date:
Subject: Re: Possible planner bug/regression introduced in 8.2.5
Next
From: Jakub Ouhrabka
Date:
Subject: Re: Possible planner bug/regression introduced in 8.2.5