FULL PRODUCT VERSION :
java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
Java HotSpot(TM) Client VM (build 19.1-b02, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Windows 7 Professional, but based on source code, will happen on all OSs
A DESCRIPTION OF THE PROBLEM :
The CachedRowSet implementation com.sun.rowset.CachedRowSetImpl has a problem with the way it implements java.sql.ResultSet.getString(String columnName).
Given the SQL "select x as y from t", if you call ResultSet.getString("y") the expected value (from column x) is returned, even though the label/alias was passed to ResultSet.
Using CachedRowSetImpl.getString("y") throws an exception because the method getX(String column) only considers column names, not aliases or labels, as do most implementations of ResultSet.
Prior API documentation versions of ResultSet showed the parameter to getX(String) as columnLabel. It has since been changed to columnName, but that makes aliased query results inaccessible.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Trying calling the method CachedRowSetImpl.getString(String) on an aliased column. Will throw Exception.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
<value from TBL1.COL1>
<value from TBL1.COL1>
ACTUAL -
<value from TBL1.COL1>
EXCEPTION THROWN
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.sql.SQLException: Invalid column name
at com.sun.rowset.CachedRowSetImpl.getColIdxByName(Unknown Source)
at com.sun.rowset.CachedRowSetImpl.getString(Unknown Source)
at com.cygnus.packages.ticketing.v4_cart.AddCartItem.addItem(AddCartItem.java:200)
at com.cygnus.packages.ticketing.v4_cart.AddCartItem.addItem(AddCartItem.java:95)
at com.cygnus.packages.ticketing.v4_cart.AddCartItem.execute(AddCartItem.java:67)
at com.cygnus.services.ticketing.Processor.service_AddCartItem(Processor.java:1708)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.cygnus.ceService.ceRequestProcessor.processRequest(ceRequestProcessor.java:869)
at com.cygnus.ceService.ceRequestProcessor.run(ceRequestProcessor.java:336)
at java.lang.Thread.run(Unknown Source)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
public static CachedRowSet runPreparedQuery(Connection conn) throws SQLException
{
ResultSet rs = null;
CachedRowSet crs = null;
PreparedStatement prepStmt = null;
try
{
prepStmt = conn.prepareStatement("SELECT COL1 AS A1 FROM TBL1");
rs = prepStmt.executeQuery();
crs = new CachedRowSetImpl2();
crs.populate(rs);
System.out.println(crs.getString("COL1")); // returns value from query
System.out.println(crs.getString("A1")); // throws Exception
}
finally
{
try
{
if (rs != null) rs.close();
if (prepStmt != null) prepStmt.close();
}
catch (Exception se)
{
se.printStackTrace();
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Copying the source for the class into my project and repairing the method getColIdxByName(String).
for (int i=1; i <= cols; ++i) {
String colName = RowSetMD.getColumnName(i);
String colLabel = RowSetMD.getColumnLabel(i);
if (colName != null)
if (name.equalsIgnoreCase(colName))
return (i);
else
continue;
}
SHOULD BE
for (int i=1; i <= cols; ++i) {
String colName = RowSetMD.getColumnName(i);
String colLabel = RowSetMD.getColumnLabel(i);
if (colName != null)
if (name.equalsIgnoreCase(colName) || name.equalsIgnoreCase(colLabel))
return (i);
else
continue;
}
java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
Java HotSpot(TM) Client VM (build 19.1-b02, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Windows 7 Professional, but based on source code, will happen on all OSs
A DESCRIPTION OF THE PROBLEM :
The CachedRowSet implementation com.sun.rowset.CachedRowSetImpl has a problem with the way it implements java.sql.ResultSet.getString(String columnName).
Given the SQL "select x as y from t", if you call ResultSet.getString("y") the expected value (from column x) is returned, even though the label/alias was passed to ResultSet.
Using CachedRowSetImpl.getString("y") throws an exception because the method getX(String column) only considers column names, not aliases or labels, as do most implementations of ResultSet.
Prior API documentation versions of ResultSet showed the parameter to getX(String) as columnLabel. It has since been changed to columnName, but that makes aliased query results inaccessible.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Trying calling the method CachedRowSetImpl.getString(String) on an aliased column. Will throw Exception.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
<value from TBL1.COL1>
<value from TBL1.COL1>
ACTUAL -
<value from TBL1.COL1>
EXCEPTION THROWN
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.sql.SQLException: Invalid column name
at com.sun.rowset.CachedRowSetImpl.getColIdxByName(Unknown Source)
at com.sun.rowset.CachedRowSetImpl.getString(Unknown Source)
at com.cygnus.packages.ticketing.v4_cart.AddCartItem.addItem(AddCartItem.java:200)
at com.cygnus.packages.ticketing.v4_cart.AddCartItem.addItem(AddCartItem.java:95)
at com.cygnus.packages.ticketing.v4_cart.AddCartItem.execute(AddCartItem.java:67)
at com.cygnus.services.ticketing.Processor.service_AddCartItem(Processor.java:1708)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.cygnus.ceService.ceRequestProcessor.processRequest(ceRequestProcessor.java:869)
at com.cygnus.ceService.ceRequestProcessor.run(ceRequestProcessor.java:336)
at java.lang.Thread.run(Unknown Source)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
public static CachedRowSet runPreparedQuery(Connection conn) throws SQLException
{
ResultSet rs = null;
CachedRowSet crs = null;
PreparedStatement prepStmt = null;
try
{
prepStmt = conn.prepareStatement("SELECT COL1 AS A1 FROM TBL1");
rs = prepStmt.executeQuery();
crs = new CachedRowSetImpl2();
crs.populate(rs);
System.out.println(crs.getString("COL1")); // returns value from query
System.out.println(crs.getString("A1")); // throws Exception
}
finally
{
try
{
if (rs != null) rs.close();
if (prepStmt != null) prepStmt.close();
}
catch (Exception se)
{
se.printStackTrace();
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Copying the source for the class into my project and repairing the method getColIdxByName(String).
for (int i=1; i <= cols; ++i) {
String colName = RowSetMD.getColumnName(i);
String colLabel = RowSetMD.getColumnLabel(i);
if (colName != null)
if (name.equalsIgnoreCase(colName))
return (i);
else
continue;
}
SHOULD BE
for (int i=1; i <= cols; ++i) {
String colName = RowSetMD.getColumnName(i);
String colLabel = RowSetMD.getColumnLabel(i);
if (colName != null)
if (name.equalsIgnoreCase(colName) || name.equalsIgnoreCase(colLabel))
return (i);
else
continue;
}