From: mmatthews Date: December 20 2005 7:39pm Subject: Connector/J commit: r4717 - in branches/branch_3_1/connector-j: . src/com/mysql/jdbc List-Archive: http://lists.mysql.com/commits/297 X-Bug: 11874 Message-Id: <200512201939.jBKJdF5E008864@bk-internal.mysql.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modified: branches/branch_3_1/connector-j/CHANGES branches/branch_3_1/connector-j/src/com/mysql/jdbc/ConnectionProperties.java branches/branch_3_1/connector-j/src/com/mysql/jdbc/ResultSet.java Log: Fixed BUG#11874 - ResultSet.getShort() for UNSIGNED TINYINT returned wrong values. Added diagnostics for column not found when calling ResultSet.findColumn(). Modified: branches/branch_3_1/connector-j/CHANGES =================================================================== --- branches/branch_3_1/connector-j/CHANGES 2005-12-20 18:54:40 UTC (rev 4716) +++ branches/branch_3_1/connector-j/CHANGES 2005-12-20 19:39:12 UTC (rev 4717) @@ -14,6 +14,9 @@ BigInteger as object, rather than sending as numeric value (and is thus not complementary to .getObject() on an UNSIGNED LONG type). + + - Fixed BUG#11874 - ResultSet.getShort() for UNSIGNED TINYINT + returned wrong values. 11-30-05 - Version 3.1.12 Modified: branches/branch_3_1/connector-j/src/com/mysql/jdbc/ConnectionProperties.java =================================================================== --- branches/branch_3_1/connector-j/src/com/mysql/jdbc/ConnectionProperties.java 2005-12-20 18:54:40 UTC (rev 4716) +++ branches/branch_3_1/connector-j/src/com/mysql/jdbc/ConnectionProperties.java 2005-12-20 19:39:12 UTC (rev 4717) @@ -786,6 +786,13 @@ + "some applications.", "3.1.7", PERFORMANCE_CATEGORY, Integer.MIN_VALUE); + private BooleanConnectionProperty dumpMetadataOnColumnNotFound = new BooleanConnectionProperty( + "dumpMetadataOnColumnNotFound", + false, + "Should the driver dump the field-level metadata of a result set into " + + "the exception message when ResultSet.findColumn() fails?", + "3.1.13", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); + private BooleanConnectionProperty dumpQueriesOnException = new BooleanConnectionProperty( "dumpQueriesOnException", false, @@ -3491,4 +3498,12 @@ protected void setProcessEscapeCodesForPrepStmts(boolean flag) { this.processEscapeCodesForPrepStmts.setValue(flag); } + + protected boolean getDumpMetadataOnColumnNotFound() { + return this.dumpMetadataOnColumnNotFound.getValueAsBoolean(); + } + + protected void setDumpMetadataOnColumnNotFound(boolean flag) { + this.dumpMetadataOnColumnNotFound.setValue(flag); + } } Modified: branches/branch_3_1/connector-j/src/com/mysql/jdbc/ResultSet.java =================================================================== --- branches/branch_3_1/connector-j/src/com/mysql/jdbc/ResultSet.java 2005-12-20 18:54:40 UTC (rev 4716) +++ branches/branch_3_1/connector-j/src/com/mysql/jdbc/ResultSet.java 2005-12-20 19:39:12 UTC (rev 4717) @@ -947,9 +947,26 @@ } } + StringBuffer debugBuf = null; + + if (this.connection.getDumpMetadataOnColumnNotFound()) { + debugBuf = new StringBuffer(); + + for (int i = 0; i < this.fields.length; i++) { + debugBuf.append("Column "); + debugBuf.append(i); + debugBuf.append(": "); + debugBuf.append(this.fields[i].toString()); + debugBuf.append("\n\n"); + } + + debugBuf.append("\n\nStatement was: " + this.owningStatement.toString()); + } + throw new SQLException(Messages.getString("ResultSet.Column____112") + columnName - + Messages.getString("ResultSet.___not_found._113"), //$NON-NLS-1$ //$NON-NLS-2$ + + Messages.getString("ResultSet.___not_found._113") + "\n\n" + + ((debugBuf == null) ? "" : debugBuf.toString()), SQLError.SQL_STATE_COLUMN_NOT_FOUND); } @@ -2997,8 +3014,8 @@ case MysqlDefs.FIELD_TYPE_TINY: byte valueAsByte = ((byte[]) this.thisRow[columnIndex])[0]; - - if (!field.isUnsigned() || valueAsByte >= 0) { + + if (field.isUnsigned()) { short valueAsShort = (short)(valueAsByte + (short)256); if (this.connection.getJdbcCompliantTruncation()) { @@ -3936,71 +3953,7 @@ throw new NotImplemented(); } - /** - * Get the value of a column in the current row as a Java short. - * - * @param columnIndex - * the first column is 1, the second is 2,... - * - * @return the column value; 0 if SQL NULL - * - * @exception SQLException - * if a database access error occurs - */ - protected short getNativeShort(int columnIndex) throws SQLException { - checkRowPos(); - checkColumnBounds(columnIndex); - columnIndex--; // / JDBC is 1-based - - if (this.thisRow[columnIndex] == null) { - this.wasNullFlag = true; - - return 0; - } - - this.wasNullFlag = false; - - // TODO: Truncation warning? - switch (this.fields[columnIndex].getMysqlType()) { - case MysqlDefs.FIELD_TYPE_DOUBLE: - return (short) getNativeDouble(columnIndex + 1); - case MysqlDefs.FIELD_TYPE_TINY: - return getNativeByte(columnIndex + 1); - case MysqlDefs.FIELD_TYPE_SHORT: - case MysqlDefs.FIELD_TYPE_YEAR: - byte[] bits = (byte[]) this.thisRow[columnIndex]; - - short shortVal = (short) ((bits[0] & 0xff) | ((bits[1] & 0xff) << 8)); - - return shortVal; - case MysqlDefs.FIELD_TYPE_INT24: - case MysqlDefs.FIELD_TYPE_LONG: - return (short) getNativeInt(columnIndex + 1); - case MysqlDefs.FIELD_TYPE_LONGLONG: - return (short) getNativeLong(columnIndex + 1); - case MysqlDefs.FIELD_TYPE_FLOAT: - return (short) getNativeFloat(columnIndex + 1); - - default: - - if (this.useUsageAdvisor) { - issueConversionViaParsingWarning("getShort()", columnIndex, - this.thisRow[columnIndex], this.fields[columnIndex], - new int[] { MysqlDefs.FIELD_TYPE_DOUBLE, - MysqlDefs.FIELD_TYPE_TINY, - MysqlDefs.FIELD_TYPE_SHORT, - MysqlDefs.FIELD_TYPE_LONG, - MysqlDefs.FIELD_TYPE_LONGLONG, - MysqlDefs.FIELD_TYPE_FLOAT }); - } - - String stringVal = getNativeString(columnIndex + 1); - - return getShortFromString(stringVal, columnIndex + 1); - } - } - /** * Get the value of a column in the current row as a Java String * @@ -7691,4 +7644,121 @@ return this.gmtCalendar; } + + /** + * Get the value of a column in the current row as a Java short. + * + * @param columnIndex + * the first column is 1, the second is 2,... + * + * @return the column value; 0 if SQL NULL + * + * @exception SQLException + * if a database access error occurs + */ + protected short getNativeShort(int columnIndex) throws SQLException { + checkRowPos(); + checkColumnBounds(columnIndex); + + columnIndex--; // / JDBC is 1-based + + if (this.thisRow[columnIndex] == null) { + this.wasNullFlag = true; + + return 0; + } + + this.wasNullFlag = false; + + Field f = this.fields[columnIndex]; + + switch (f.getMysqlType()) { + + case MysqlDefs.FIELD_TYPE_TINY: + byte tinyintVal = getNativeByte(columnIndex + 1); + + if (!f.isUnsigned()) { + return tinyintVal; + } + + return (short)(tinyintVal + (short)256); + case MysqlDefs.FIELD_TYPE_SHORT: + case MysqlDefs.FIELD_TYPE_YEAR: + short asShort = getNativeShort(columnIndex + 1); + + if (!f.isUnsigned()) { + return asShort; + } + + int valueAsInt = asShort + 65536; + + if (this.connection.getJdbcCompliantTruncation() && + valueAsInt > Short.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsInt), + columnIndex + 1, Types.SMALLINT); + } + + return (short)valueAsInt; + case MysqlDefs.FIELD_TYPE_INT24: + case MysqlDefs.FIELD_TYPE_LONG: + byte[] bits = (byte[]) this.thisRow[columnIndex]; + + valueAsInt = (bits[0] & 0xff) | ((bits[1] & 0xff) << 8) + | ((bits[2] & 0xff) << 16) | ((bits[3] & 0xff) << 24); + + return (short)valueAsInt; + case MysqlDefs.FIELD_TYPE_LONGLONG: + long valueAsLong = getNativeLong(columnIndex + 1); + + if (this.connection.getJdbcCompliantTruncation()) { + if (valueAsLong < Integer.MIN_VALUE + || valueAsLong > Integer.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsLong), + columnIndex + 1, Types.INTEGER); + } + } + + return (short) valueAsLong; + case MysqlDefs.FIELD_TYPE_DOUBLE: + double valueAsDouble = getNativeDouble(columnIndex + 1); + + if (this.connection.getJdbcCompliantTruncation()) { + if (valueAsDouble < Short.MIN_VALUE + || valueAsDouble > Short.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsDouble), + columnIndex + 1, Types.SMALLINT); + } + } + + return (short) valueAsDouble; + case MysqlDefs.FIELD_TYPE_FLOAT: + float valueAsFloat = getNativeFloat(columnIndex + 1); + + if (this.connection.getJdbcCompliantTruncation()) { + if (valueAsFloat < Short.MIN_VALUE + || valueAsFloat > Short.MAX_VALUE) { + throwRangeException(String.valueOf(valueAsFloat), + columnIndex + 1, Types.SMALLINT); + } + } + + return (short) valueAsFloat; + default: + + if (this.useUsageAdvisor) { + issueConversionViaParsingWarning("getShort()", columnIndex, + this.thisRow[columnIndex], this.fields[columnIndex], + new int[] { MysqlDefs.FIELD_TYPE_DOUBLE, + MysqlDefs.FIELD_TYPE_TINY, + MysqlDefs.FIELD_TYPE_SHORT, + MysqlDefs.FIELD_TYPE_LONG, + MysqlDefs.FIELD_TYPE_LONGLONG, + MysqlDefs.FIELD_TYPE_FLOAT }); + } + + String stringVal = getNativeString(columnIndex + 1); + + return getShortFromString(stringVal, columnIndex + 1); + } + } }