Modified:
branches/branch_5_0/connector-j/src/com/mysql/jdbc/ResultSet.java
Log:
Fixups for UNSIGNED values with server-side prepared statements.
Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/ResultSet.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/ResultSet.java 2005-12-21 01:02:50 UTC (rev 4727)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/ResultSet.java 2005-12-21 22:51:50 UTC (rev 4728)
@@ -2987,6 +2987,10 @@
* if a database access error occurs
*/
protected byte getNativeByte(int columnIndex) throws SQLException {
+ return getNativeByte(columnIndex, true);
+ }
+
+ protected byte getNativeByte(int columnIndex, boolean overflowCheck) throws SQLException {
checkRowPos();
checkColumnBounds(columnIndex);
@@ -3019,25 +3023,27 @@
case MysqlDefs.FIELD_TYPE_TINY:
byte valueAsByte = ((byte[]) this.thisRow[columnIndex])[0];
- if (!field.isUnsigned() || valueAsByte >= 0) {
- short valueAsShort = (short)(valueAsByte + (short)256);
-
- if (this.connection.getJdbcCompliantTruncation()) {
- if (valueAsShort > Byte.MAX_VALUE) {
- throwRangeException(String.valueOf(valueAsShort),
- columnIndex + 1, Types.TINYINT);
- }
+ if (!field.isUnsigned()) {
+ return valueAsByte;
+ }
+
+ short valueAsShort = (valueAsByte >= 0) ?
+ valueAsByte : (short)(valueAsByte + (short)256);
+
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation()) {
+ if (valueAsShort > Byte.MAX_VALUE) {
+ throwRangeException(String.valueOf(valueAsShort),
+ columnIndex + 1, Types.TINYINT);
}
-
- return (byte)valueAsShort;
}
- return valueAsByte;
+ return (byte)valueAsShort;
+
case MysqlDefs.FIELD_TYPE_SHORT:
case MysqlDefs.FIELD_TYPE_YEAR:
- int valueAsShort = getNativeShort(columnIndex + 1);
+ valueAsShort = getNativeShort(columnIndex + 1);
- if (this.connection.getJdbcCompliantTruncation()) {
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation()) {
if (valueAsShort < Byte.MIN_VALUE
|| valueAsShort > Byte.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsShort),
@@ -3048,9 +3054,9 @@
return (byte) valueAsShort;
case MysqlDefs.FIELD_TYPE_INT24:
case MysqlDefs.FIELD_TYPE_LONG:
- int valueAsInt = getNativeInt(columnIndex + 1);
+ int valueAsInt = getNativeInt(columnIndex + 1, false);
- if (this.connection.getJdbcCompliantTruncation()) {
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation()) {
if (valueAsInt < Byte.MIN_VALUE || valueAsInt > Byte.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsInt),
columnIndex + 1, Types.TINYINT);
@@ -3062,7 +3068,7 @@
case MysqlDefs.FIELD_TYPE_FLOAT:
float valueAsFloat = getNativeFloat(columnIndex + 1);
- if (this.connection.getJdbcCompliantTruncation()) {
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation()) {
if (valueAsFloat < Byte.MIN_VALUE
|| valueAsFloat > Byte.MAX_VALUE) {
@@ -3076,7 +3082,7 @@
case MysqlDefs.FIELD_TYPE_DOUBLE:
double valueAsDouble = getNativeDouble(columnIndex + 1);
- if (this.connection.getJdbcCompliantTruncation()) {
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation()) {
if (valueAsDouble < Byte.MIN_VALUE
|| valueAsDouble > Byte.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsDouble),
@@ -3087,9 +3093,9 @@
return (byte) valueAsDouble;
case MysqlDefs.FIELD_TYPE_LONGLONG:
- long valueAsLong = getNativeLong(columnIndex + 1);
+ long valueAsLong = getNativeLong(columnIndex + 1, false, true);
- if (this.connection.getJdbcCompliantTruncation()) {
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation()) {
if (valueAsLong < Byte.MIN_VALUE
|| valueAsLong > Byte.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsLong),
@@ -3248,7 +3254,7 @@
return String.valueOf(booleanVal);
case Types.TINYINT:
- byte tinyintVal = getNativeByte(columnIndex);
+ byte tinyintVal = getNativeByte(columnIndex, false);
if (this.wasNullFlag) {
return null;
@@ -3264,7 +3270,7 @@
case Types.SMALLINT:
- int intVal = getNativeInt(columnIndex);
+ int intVal = getNativeInt(columnIndex, false);
if (this.wasNullFlag) {
return null;
@@ -3279,7 +3285,7 @@
return String.valueOf(intVal);
case Types.INTEGER:
- intVal = getNativeInt(columnIndex);
+ intVal = getNativeInt(columnIndex, false);
if (this.wasNullFlag) {
return null;
@@ -3298,7 +3304,7 @@
case Types.BIGINT:
if (!field.isUnsigned()) {
- longVal = getNativeLong(columnIndex);
+ longVal = getNativeLong(columnIndex, false, true);
if (this.wasNullFlag) {
return null;
@@ -3307,7 +3313,7 @@
return String.valueOf(longVal);
}
- longVal = getNativeLong(columnIndex);
+ longVal = getNativeLong(columnIndex, false, false);
if (this.wasNullFlag) {
return null;
@@ -3603,7 +3609,9 @@
this.wasNullFlag = false;
- switch (this.fields[columnIndex].getMysqlType()) {
+ Field f= this.fields[columnIndex];
+
+ switch (f.getMysqlType()) {
case MysqlDefs.FIELD_TYPE_DOUBLE:
byte[] bits = (byte[]) this.thisRow[columnIndex];
@@ -3618,15 +3626,37 @@
return Double.longBitsToDouble(valueAsLong);
case MysqlDefs.FIELD_TYPE_TINY:
- return (double) getNativeByte(columnIndex + 1);
+ if (!f.isUnsigned()) {
+ return (double) getNativeByte(columnIndex + 1);
+ }
+
+ return (double) getNativeShort(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_SHORT:
case MysqlDefs.FIELD_TYPE_YEAR:
- return (double) getNativeShort(columnIndex + 1);
+ if (!f.isUnsigned()) {
+ return (double) getNativeShort(columnIndex + 1);
+ }
+
+ return (double) getNativeInt(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_INT24:
case MysqlDefs.FIELD_TYPE_LONG:
- return (double) getNativeInt(columnIndex + 1);
+ if (!f.isUnsigned()) {
+ return (double) getNativeInt(columnIndex + 1);
+ }
+
+ return (double) getNativeLong(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_LONGLONG:
- return (double) getNativeLong(columnIndex + 1);
+ valueAsLong = getNativeLong(columnIndex + 1);
+
+ if (!f.isUnsigned()) {
+ return (double) valueAsLong;
+ }
+
+ BigInteger asBigInt = convertLongToUlong(valueAsLong);
+
+ // TODO: Check for overflow
+
+ return asBigInt.doubleValue();
case MysqlDefs.FIELD_TYPE_FLOAT:
return (double) getNativeFloat(columnIndex + 1);
@@ -3674,20 +3704,52 @@
this.wasNullFlag = false;
- // TODO: Truncation check
- switch (this.fields[columnIndex].getMysqlType()) {
+ Field f = this.fields[columnIndex];
+
+ switch (f.getMysqlType()) {
case MysqlDefs.FIELD_TYPE_DOUBLE:
+ double valueAsDouble = getNativeDouble(columnIndex + 1);
+
+ if (this.connection.getJdbcCompliantTruncation() &&
+ (valueAsDouble < Float.MIN_VALUE ||
+ valueAsDouble > Float.MAX_VALUE)) {
+ throwRangeException(String.valueOf(valueAsDouble),
+ columnIndex + 1, Types.FLOAT);
+ }
+
return (float) getNativeDouble(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_TINY:
- return (float) getNativeByte(columnIndex + 1);
+ if (!f.isUnsigned()) {
+ return (float) getNativeByte(columnIndex + 1);
+ }
+
+ return (float) getNativeShort(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_SHORT:
case MysqlDefs.FIELD_TYPE_YEAR:
- return (float) getNativeShort(columnIndex + 1);
+ if (!f.isUnsigned()) {
+ return (float) getNativeShort(columnIndex + 1);
+ }
+
+ return (float) getNativeInt(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_INT24:
case MysqlDefs.FIELD_TYPE_LONG:
- return (float) getNativeInt(columnIndex + 1);
+ if (!f.isUnsigned()) {
+ return (float) getNativeInt(columnIndex + 1);
+ }
+
+ return (float) getNativeLong(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_LONGLONG:
- return (float) getNativeLong(columnIndex + 1);
+ long valueAsLong = getNativeLong(columnIndex + 1);
+
+ if (!f.isUnsigned()) {
+ return (float) valueAsLong;
+ }
+
+ BigInteger asBigInt = convertLongToUlong(valueAsLong);
+
+ // TODO: Check for overflow
+
+ return asBigInt.floatValue();
case MysqlDefs.FIELD_TYPE_FLOAT:
byte[] bits = (byte[]) this.thisRow[columnIndex];
@@ -3727,6 +3789,10 @@
* if a database access error occurs
*/
protected int getNativeInt(int columnIndex) throws SQLException {
+ return getNativeInt(columnIndex, false);
+ }
+
+ protected int getNativeInt(int columnIndex, boolean overflowCheck) throws SQLException {
checkRowPos();
checkColumnBounds(columnIndex);
@@ -3745,7 +3811,7 @@
switch (f.getMysqlType()) {
case MysqlDefs.FIELD_TYPE_TINY:
- byte tinyintVal = getNativeByte(columnIndex + 1);
+ byte tinyintVal = getNativeByte(columnIndex + 1, false);
if (!f.isUnsigned() || tinyintVal >= 0) {
return tinyintVal;
@@ -3753,15 +3819,14 @@
return tinyintVal + 256;
case MysqlDefs.FIELD_TYPE_SHORT:
- short asShort = getNativeShort(columnIndex + 1);
+ case MysqlDefs.FIELD_TYPE_YEAR:
+ short asShort = getNativeShort(columnIndex + 1, false);
if (!f.isUnsigned() || asShort >= 0) {
return asShort;
}
return asShort + 65536;
- case MysqlDefs.FIELD_TYPE_YEAR:
- return getNativeShort(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_INT24:
case MysqlDefs.FIELD_TYPE_LONG:
byte[] bits = (byte[]) this.thisRow[columnIndex];
@@ -3769,11 +3834,24 @@
int valueAsInt = (bits[0] & 0xff) | ((bits[1] & 0xff) << 8)
| ((bits[2] & 0xff) << 16) | ((bits[3] & 0xff) << 24);
- return valueAsInt;
+ if (!f.isUnsigned()) {
+ return valueAsInt;
+ }
+
+ long valueAsLong = (valueAsInt >= 0) ?
+ valueAsInt : valueAsInt + 4294967296L;
+
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation() &&
+ valueAsLong > Integer.MAX_VALUE) {
+ throwRangeException(String.valueOf(valueAsLong),
+ columnIndex + 1, Types.INTEGER);
+ }
+
+ return (int)valueAsLong;
case MysqlDefs.FIELD_TYPE_LONGLONG:
- long valueAsLong = getNativeLong(columnIndex + 1);
+ valueAsLong = getNativeLong(columnIndex + 1, false, true);
- if (this.connection.getJdbcCompliantTruncation()) {
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation()) {
if (valueAsLong < Integer.MIN_VALUE
|| valueAsLong > Integer.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsLong),
@@ -3785,7 +3863,7 @@
case MysqlDefs.FIELD_TYPE_DOUBLE:
double valueAsDouble = getNativeDouble(columnIndex + 1);
- if (this.connection.getJdbcCompliantTruncation()) {
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation()) {
if (valueAsDouble < Integer.MIN_VALUE
|| valueAsDouble > Integer.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsDouble),
@@ -3797,7 +3875,7 @@
case MysqlDefs.FIELD_TYPE_FLOAT:
valueAsDouble = getNativeFloat(columnIndex + 1);
- if (this.connection.getJdbcCompliantTruncation()) {
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation()) {
if (valueAsDouble < Integer.MIN_VALUE
|| valueAsDouble > Integer.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsDouble),
@@ -3838,6 +3916,11 @@
* if a database access error occurs
*/
protected long getNativeLong(int columnIndex) throws SQLException {
+ return getNativeLong(columnIndex, false, true);
+ }
+
+ protected long getNativeLong(int columnIndex, boolean overflowCheck,
+ boolean expandUnsignedLong) throws SQLException {
checkRowPos();
checkColumnBounds(columnIndex);
@@ -3891,21 +3974,25 @@
| ((long) (bits[6] & 0xff) << 48)
| ((long) (bits[7] & 0xff) << 56);
- //
- // TODO: Actually do this check
- //
- // if (f.isUnsigned()) {
- // if (this.connection.getJdbcCompliantTruncation()) {
- // throwRangeException(String.valueOf(valueAsDouble), columnIndex +
- // 1, Types.BIGINT);
- // }
- // }
+ if (!f.isUnsigned() || !expandUnsignedLong) {
+ return valueAsLong;
+ }
+
+ BigInteger asBigInt = convertLongToUlong(valueAsLong);
+
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation() &&
+ ((asBigInt.compareTo(new BigInteger(String.valueOf(Long.MAX_VALUE))) > 0 ) ||
+ (asBigInt.compareTo(new BigInteger(String.valueOf(Long.MIN_VALUE))) < 0))) {
+ throwRangeException(asBigInt.toString(),
+ columnIndex + 1, Types.BIGINT);
+ }
+
+ return getLongFromString(asBigInt.toString(), columnIndex + 1);
- return valueAsLong;
case MysqlDefs.FIELD_TYPE_DOUBLE:
double valueAsDouble = getNativeDouble(columnIndex + 1);
- if (this.connection.getJdbcCompliantTruncation()) {
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation()) {
if (valueAsDouble < Long.MIN_VALUE
|| valueAsDouble > Long.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsDouble),
@@ -3917,7 +4004,7 @@
case MysqlDefs.FIELD_TYPE_FLOAT:
valueAsDouble = getNativeFloat(columnIndex + 1);
- if (this.connection.getJdbcCompliantTruncation()) {
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation()) {
if (valueAsDouble < Long.MIN_VALUE
|| valueAsDouble > Long.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsDouble),
@@ -3974,6 +4061,10 @@
* if a database access error occurs
*/
protected short getNativeShort(int columnIndex) throws SQLException {
+ return getNativeShort(columnIndex, true);
+ }
+
+ protected short getNativeShort(int columnIndex, boolean overflowCheck) throws SQLException {
checkRowPos();
checkColumnBounds(columnIndex);
@@ -4001,15 +4092,17 @@
return (short)(tinyintVal + (short)256);
case MysqlDefs.FIELD_TYPE_SHORT:
case MysqlDefs.FIELD_TYPE_YEAR:
- short asShort = getNativeShort(columnIndex + 1);
+ byte[] bits = (byte[]) this.thisRow[columnIndex];
+ short asShort = (short) ((bits[0] & 0xff) | ((bits[1] & 0xff) << 8));
+
if (!f.isUnsigned()) {
return asShort;
}
- int valueAsInt = asShort + 65536;
+ int valueAsInt = asShort & 0xffff;
- if (this.connection.getJdbcCompliantTruncation() &&
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation() &&
valueAsInt > Short.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsInt),
columnIndex + 1, Types.SMALLINT);
@@ -4018,28 +4111,59 @@
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;
+ if (!f.isUnsigned()) {
+ valueAsInt = getNativeInt(columnIndex + 1, false);
+
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation() &&
+ valueAsInt > Short.MAX_VALUE ||
+ valueAsInt < Short.MIN_VALUE) {
+ throwRangeException(String.valueOf(valueAsInt),
+ columnIndex + 1, Types.SMALLINT);
+ }
+
+ return (short)valueAsInt;
+ }
+
+ long valueAsLong = getNativeLong(columnIndex + 1, false, true);
+
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation() &&
+ valueAsLong > Short.MAX_VALUE) {
+ throwRangeException(String.valueOf(valueAsLong),
+ columnIndex + 1, Types.SMALLINT);
+ }
+
+ return (short)valueAsLong;
+
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);
+ valueAsLong = getNativeLong(columnIndex + 1, false, false);
+
+ if (!f.isUnsigned()) {
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation()) {
+ if (valueAsLong < Short.MIN_VALUE
+ || valueAsLong > Short.MAX_VALUE) {
+ throwRangeException(String.valueOf(valueAsLong),
+ columnIndex + 1, Types.SMALLINT);
+ }
}
+
+ return (short) valueAsLong;
}
+
+ BigInteger asBigInt = convertLongToUlong(valueAsLong);
+
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation() &&
+ ((asBigInt.compareTo(new BigInteger(String.valueOf(Short.MAX_VALUE))) > 0 ) ||
+ (asBigInt.compareTo(new BigInteger(String.valueOf(Short.MIN_VALUE))) < 0))) {
+ throwRangeException(asBigInt.toString(),
+ columnIndex + 1, Types.SMALLINT);
+ }
+
+ return (short)getIntFromString(asBigInt.toString(), columnIndex + 1);
- return (short) valueAsLong;
case MysqlDefs.FIELD_TYPE_DOUBLE:
double valueAsDouble = getNativeDouble(columnIndex + 1);
- if (this.connection.getJdbcCompliantTruncation()) {
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation()) {
if (valueAsDouble < Short.MIN_VALUE
|| valueAsDouble > Short.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsDouble),
@@ -4051,7 +4175,7 @@
case MysqlDefs.FIELD_TYPE_FLOAT:
float valueAsFloat = getNativeFloat(columnIndex + 1);
- if (this.connection.getJdbcCompliantTruncation()) {
+ if (overflowCheck && this.connection.getJdbcCompliantTruncation()) {
if (valueAsFloat < Short.MIN_VALUE
|| valueAsFloat > Short.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsFloat),
| Thread |
|---|
| • Connector/J commit: r4728 - branches/branch_5_0/connector-j/src/com/mysql/jdbc | mmatthews | 21 Dec |