Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6335589

REGRESSION: JdbcOdbc ResultSet.getString returning text and char(0) padding

    XMLWordPrintable

    Details

    • Subcomponent:
    • Resolved In Build:
      b86
    • CPU:
      x86
    • OS:
      windows_2000, windows_xp
    • Verification:
      Verified

      Description

      FULL PRODUCT VERSION :
      java version "1.6.0-ea"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-ea-b53)
      Java HotSpot(TM) Client VM (build 1.6.0-ea-b53, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows 2000 [Version 5.00.2195]

      A DESCRIPTION OF THE PROBLEM :
      Attempting to get a String value from a ResultSet or DatabaseMetaData or ResultSetMetaData (with a Microsoft Access database at least), or calling getObject() on the ResultSet for String-type columns, returns the value of the string AND lots of extra characters, with the value char(0). It looks like padding on VARCHAR columns might be the problem (being returned when it shouldn't), BUT this also affects ANY string column, including those from "MetaData" JDBC objects.

      JDBC-ODBC regression has occurred in early-access versions of "Mustang" (Java 6). The same code running against the same Access database on the same machine, under 1.5.0_04 works fine, but under 1.6.0_ea_b53 (and more than one previous early-access build of Mustang).

      I can reproduce this on ANY MS-Access database here. I am unable to test this using other databases accessible through ODBC, and have not yet had the opportunity to test other JDBC drivers.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Create a simple Access database (one table with some fields of different types, some indexed, some not) should be ample. I can provide one if necessary, but the bug-reporting form doesn't seem to provide any field for uploads.

      Then run my source code below. Try it with Java 5 AND Java 6. For simplicity, I hard-coded the path to the Access database into the source code, so you may wish to adapt it to get the code running.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The code uses database metadata to get the names of all user tables in the database, and prints out their name and type. Then, it selects all records from each table in turn, printing out the values of each field. The procedure runs TWICE, with the difference being that the first attempt just dumps exactly what the driver is outputting, and the second attempt uses a cumbersome workaround to strip the junk -- if any -- from returned strings.

      It is expected that each time the procedure runs, the exact same output is generated.
      ACTUAL -
      Under Java 6 (ea/b49), extra "things" appears on the JDBC-ODBC strings. Under Java 5, it doesn't. The result of running the code under Java 6 with my test database is show below (NOTE: I can't paste in char(0), so I was forced to replace that with the asterisk ("*") symbol):

      Seeking MS-Access database:
      C:\sandbox\db.mdb

      Running test (skip trimming)...
      Name: Table1***************************************************************************************************************************
      Type: TABLE****************************************************************************************************************************

      Querying Table1...
      1:Table1.id = 1
      1:Table1.uniqueText = apple***********************************************************************************************************************************************************************************************************************************************************
      1:Table1.arbitraryText = braeburn********************************************************************************************************************************************************************************************************************************************************

      2:Table1.id = 2
      2:Table1.uniqueText = banana**********************************************************************************************************************************************************************************************************************************************************
      2:Table1.arbitraryText = null

      3:Table1.id = 3
      3:Table1.uniqueText = melon***********************************************************************************************************************************************************************************************************************************************************
      3:Table1.arbitraryText = watermelon******************************************************************************************************************************************************************************************************************************************************

      4:Table1.id = 4
      4:Table1.uniqueText = orange**********************************************************************************************************************************************************************************************************************************************************
      4:Table1.arbitraryText = null

      Running test (with trimming)...
      Name: Table1
      Type: TABLE

      Querying Table1...
      1:Table1.id = 1
      1:Table1.uniqueText = apple
      1:Table1.arbitraryText = braeburn

      2:Table1.id = 2
      2:Table1.uniqueText = banana
      2:Table1.arbitraryText = null

      3:Table1.id = 3
      3:Table1.uniqueText = melon
      3:Table1.arbitraryText = watermelon

      4:Table1.id = 4
      4:Table1.uniqueText = orange
      4:Table1.arbitraryText = null

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package test;

      import java.sql.Connection;
      import java.sql.DatabaseMetaData;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      import java.sql.DriverManager;
      import java.sql.ResultSetMetaData;
      import java.io.File;
      import java.util.Properties;
      import java.util.List;
      import java.util.ArrayList;



      public class AccessTest implements Runnable
      {
      public static void main(String[] args)
      {
      new Thread(new AccessTest()).start();
      }


      private boolean skipTrim;



      private AccessTest()
      {
      skipTrim = false;
      }


      public void run()
      {
      try
      {
      Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
      }
      catch (Exception e)
      {
      e.printStackTrace();
      return;
      }

      File mdbFile = new File("db.mdb");
      System.out.printf("Seeking MS-Access database:\n%s\n\n",mdbFile.getAbsolutePath());
      Properties jdbcProperties = new Properties();

      String url = "jdbc:odbc:driver={Microsoft Access Driver (*.mdb)};DBQ="+mdbFile.getPath();
      Connection conn = null;
      try
      {
      conn = DriverManager.getConnection(url,jdbcProperties);
      skipTrim = true;
      test(conn);
      skipTrim = false;
      test(conn);
      }
      catch (SQLException e)
      {
      e.printStackTrace();
      }
      finally
      {
      if (conn != null) try { conn.close(); } catch (Exception e) {}
      }
      }


      private void test(Connection conn) throws SQLException
      {
      System.out.printf("Running test (%s trimming)...\n",(skipTrim?"skip":"with"));

      List<String> tableNames = new ArrayList<String>();

      DatabaseMetaData dbmd = conn.getMetaData();
      ResultSet tables = dbmd.getTables(null, null, "%", new String[]{"TABLE","VIEW"});
      while (tables.next())
      {
      String tableName = trim(tables.getString("TABLE_NAME"));
      String tableType = trim(tables.getString("TABLE_TYPE"));
      System.out.printf("Name: %s\n",tableName);
      System.out.printf("Type: %s\n",tableType);
      System.out.println();

      if (skipTrim) tableName = trim(tableName,false);
      tableNames.add(tableName);
      }
      tables.close();

      for (String tableName : tableNames)
      {
      System.out.printf("Querying %s...\n",tableName);
      ResultSet records = conn.createStatement().executeQuery(
      "SELECT * FROM "+tableName
      );
      ResultSetMetaData rsmd = records.getMetaData();
      final int colCount = rsmd.getColumnCount();
      int r = 0;
      while (records.next())
      {
      r++;
      for (int i = 1; i <= colCount; i++)
      {
      Object field = records.getObject(i);
      if (field instanceof String)
      {
      field = trim((String)field);
      }
      System.out.printf("%d:%s.%s = %s\n",r,tableName,rsmd.getColumnName(i),field);
      }
      System.out.println();
      }
      records.close();
      }
      }


      private String trim(String text)
      {
      return trim(text,skipTrim);
      }


      private String trim(String text,boolean skip)
      {
      if (skip) return text;

      StringBuilder sb = new StringBuilder(text.length());
      char c;
      for (int i = 0; i < text.length(); i++)
      {
      c = text.charAt(i);
      if (c == (char)0) break;
      sb.append(c);
      }
      return sb.toString();
      }


      // private String trim(String text,boolean skip)
      // {
      // if (skip) return text;
      //
      // StringBuilder sb = new StringBuilder(text.length());
      // char c;
      // for (int i = 0; i < text.length(); i++)
      // {
      // c = text.charAt(i);
      // if (c == (char)0 || (!skip && c == '*'))
      // {
      // if (!skip) break;
      // sb.append('*');
      // continue;
      // }
      // if (skip &&c == (char)0) break;
      // sb.append(c);
      // }
      // return sb.toString();
      // }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Using the cumbersome "trim" method above. That's not a practical option in many cases.

      Release Regression From : mustang
      The above release value was the last known release where this
      bug was known to work. Since then there has been a regression.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              ahandasunw Amit Handa (Inactive)
              Reporter:
              rmandalasunw Ranjith Mandala (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: