Unverified 提交 6d3600e2 authored 作者: Noel Grandin's avatar Noel Grandin 提交者: GitHub

Merge pull request #757 from katzyn/UUID

Fix handling of UUID in Datatype.readValue()
...@@ -136,6 +136,10 @@ public class TableFunction extends Function { ...@@ -136,6 +136,10 @@ public class TableFunction extends Function {
simple.setAutoClose(false); simple.setAutoClose(false);
for (int i = 0; i < columnCount; i++) { for (int i = 0; i < columnCount; i++) {
String name = rs.getColumnName(i); String name = rs.getColumnName(i);
/*
* TODO Some types, such as Value.BYTES and Value.UUID are mapped to the same
* SQL type and we can lose real type here.
*/
int sqlType = DataType.convertTypeToSQLType(rs.getColumnType(i)); int sqlType = DataType.convertTypeToSQLType(rs.getColumnType(i));
int precision = MathUtils.convertLongToInt(rs.getColumnPrecision(i)); int precision = MathUtils.convertLongToInt(rs.getColumnPrecision(i));
int scale = rs.getColumnScale(i); int scale = rs.getColumnScale(i);
......
...@@ -36,8 +36,8 @@ import org.h2.message.DbException; ...@@ -36,8 +36,8 @@ import org.h2.message.DbException;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.Utils;
import org.h2.value.DataType; import org.h2.value.DataType;
import org.h2.value.ValueUuid;
/** /**
* This class is a simple result set and meta data implementation. * This class is a simple result set and meta data implementation.
...@@ -534,8 +534,7 @@ public class SimpleResultSet implements ResultSet, ResultSetMetaData, ...@@ -534,8 +534,7 @@ public class SimpleResultSet implements ResultSet, ResultSetMetaData,
return (byte[]) o; return (byte[]) o;
} }
if (o instanceof UUID) { if (o instanceof UUID) {
final UUID u = (UUID) o; return Utils.uuidToBytes((UUID) o);
return ValueUuid.get(u.getMostSignificantBits(), u.getLeastSignificantBits()).getBytes();
} }
return JdbcUtils.serialize(o, null); return JdbcUtils.serialize(o, null);
} }
......
...@@ -18,6 +18,7 @@ import java.util.Arrays; ...@@ -18,6 +18,7 @@ import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
...@@ -92,6 +93,28 @@ public class Utils { ...@@ -92,6 +93,28 @@ public class Utils {
(readInt(buff, pos + 4) & 0xffffffffL); (readInt(buff, pos + 4) & 0xffffffffL);
} }
/**
* @param uuid UUID value
* @return byte array representation
*/
public static byte[] uuidToBytes(UUID uuid) {
return uuidToBytes(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits());
}
/**
* @param msb most significant part of UUID
* @param lsb least significant part of UUID
* @return byte array representation
*/
public static byte[] uuidToBytes(long msb, long lsb) {
byte[] buff = new byte[16];
for (int i = 0; i < 8; i++) {
buff[i] = (byte) ((msb >> (8 * (7 - i))) & 255);
buff[8 + i] = (byte) ((lsb >> (8 * (7 - i))) & 255);
}
return buff;
}
/** /**
* Calculate the index of the first occurrence of the pattern in the byte * Calculate the index of the first occurrence of the pattern in the byte
* array, starting with the given index. This methods returns -1 if the * array, starting with the given index. This methods returns -1 if the
......
...@@ -514,15 +514,27 @@ public class DataType { ...@@ -514,15 +514,27 @@ public class DataType {
return ValueNull.INSTANCE; return ValueNull.INSTANCE;
} }
case Value.BYTES: { case Value.BYTES: {
byte[] buff = rs.getBytes(columnIndex); /*
v = buff == null ? (Value) ValueNull.INSTANCE : * Both BINARY and UUID may be mapped to Value.BYTES. getObject() returns byte[]
ValueBytes.getNoCopy(buff); * for SQL BINARY, UUID for SQL UUID and null for SQL NULL.
*/
Object o = rs.getObject(columnIndex);
if (o instanceof byte[]) {
v = ValueBytes.getNoCopy((byte[]) o);
} else if (o != null) {
v = ValueUuid.get((UUID) o);
} else
v = ValueNull.INSTANCE;
break; break;
} }
case Value.UUID: { case Value.UUID: {
byte[] buff = rs.getBytes(columnIndex); Object o = rs.getObject(columnIndex);
v = buff == null ? (Value) ValueNull.INSTANCE : if (o instanceof UUID) {
ValueUuid.get(buff); v = ValueUuid.get((UUID) o);
} else if (o != null)
v = ValueUuid.get((byte[]) o);
else
v = ValueNull.INSTANCE;
break; break;
} }
case Value.BOOLEAN: { case Value.BOOLEAN: {
...@@ -1100,8 +1112,7 @@ public class DataType { ...@@ -1100,8 +1112,7 @@ public class DataType {
} }
return ValueResultSet.getCopy((ResultSet) x, Integer.MAX_VALUE); return ValueResultSet.getCopy((ResultSet) x, Integer.MAX_VALUE);
} else if (x instanceof UUID) { } else if (x instanceof UUID) {
UUID u = (UUID) x; return ValueUuid.get((UUID) x);
return ValueUuid.get(u.getMostSignificantBits(), u.getLeastSignificantBits());
} else if (x instanceof Object[]) { } else if (x instanceof Object[]) {
// (a.getClass().isArray()); // (a.getClass().isArray());
// (a.getClass().getComponentType().isPrimitive()); // (a.getClass().getComponentType().isPrimitive());
......
...@@ -944,9 +944,7 @@ public abstract class Value { ...@@ -944,9 +944,7 @@ public abstract class Value {
Object object = JdbcUtils.deserialize(getBytesNoCopy(), Object object = JdbcUtils.deserialize(getBytesNoCopy(),
getDataHandler()); getDataHandler());
if (object instanceof java.util.UUID) { if (object instanceof java.util.UUID) {
java.util.UUID uuid = (java.util.UUID) object; return ValueUuid.get((java.util.UUID) object);
return ValueUuid.get(uuid.getMostSignificantBits(),
uuid.getLeastSignificantBits());
} }
throw DbException.get(ErrorCode.DATA_CONVERSION_ERROR_1, getString()); throw DbException.get(ErrorCode.DATA_CONVERSION_ERROR_1, getString());
case TIMESTAMP_TZ: case TIMESTAMP_TZ:
......
...@@ -84,6 +84,16 @@ public class ValueUuid extends Value { ...@@ -84,6 +84,16 @@ public class ValueUuid extends Value {
return (ValueUuid) Value.cache(new ValueUuid(high, low)); return (ValueUuid) Value.cache(new ValueUuid(high, low));
} }
/**
* Get or create a UUID for the given Java UUID.
*
* @param uuid Java UUID
* @return the UUID
*/
public static ValueUuid get(UUID uuid) {
return get(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits());
}
/** /**
* Get or create a UUID for the given text representation. * Get or create a UUID for the given text representation.
* *
...@@ -176,12 +186,7 @@ public class ValueUuid extends Value { ...@@ -176,12 +186,7 @@ public class ValueUuid extends Value {
@Override @Override
public byte[] getBytes() { public byte[] getBytes() {
byte[] buff = new byte[16]; return Utils.uuidToBytes(high, low);
for (int i = 0; i < 8; i++) {
buff[i] = (byte) ((high >> (8 * (7 - i))) & 255);
buff[8 + i] = (byte) ((low >> (8 * (7 - i))) & 255);
}
return buff;
} }
@Override @Override
......
...@@ -8,17 +8,21 @@ package org.h2.test.unit; ...@@ -8,17 +8,21 @@ package org.h2.test.unit;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.Connection; import java.sql.Connection;
import java.sql.Date; import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Time; import java.sql.Time;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.sql.Types; import java.sql.Types;
import java.util.Arrays;
import java.util.UUID; import java.util.UUID;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.test.utils.AssertThrows; import org.h2.test.utils.AssertThrows;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.Utils;
import org.h2.value.DataType; import org.h2.value.DataType;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueArray; import org.h2.value.ValueArray;
...@@ -50,6 +54,7 @@ public class TestValue extends TestBase { ...@@ -50,6 +54,7 @@ public class TestValue extends TestBase {
@Override @Override
public void test() throws SQLException { public void test() throws SQLException {
testResultSetOperations(); testResultSetOperations();
testBinaryAndUuid();
testCastTrim(); testCastTrim();
testValueResultSet(); testValueResultSet();
testDataType(); testDataType();
...@@ -87,6 +92,7 @@ public class TestValue extends TestBase { ...@@ -87,6 +92,7 @@ public class TestValue extends TestBase {
testResultSetOperation(new Time(7)); testResultSetOperation(new Time(7));
testResultSetOperation(new Timestamp(8)); testResultSetOperation(new Timestamp(8));
testResultSetOperation(new BigDecimal("9")); testResultSetOperation(new BigDecimal("9"));
testResultSetOperation(UUID.randomUUID());
SimpleResultSet rs2 = new SimpleResultSet(); SimpleResultSet rs2 = new SimpleResultSet();
rs2.setAutoClose(false); rs2.setAutoClose(false);
...@@ -114,6 +120,30 @@ public class TestValue extends TestBase { ...@@ -114,6 +120,30 @@ public class TestValue extends TestBase {
} }
} }
private void testBinaryAndUuid() throws SQLException {
Connection conn = getConnection("binaryAndUuid");
try {
UUID uuid = UUID.randomUUID();
PreparedStatement prep;
ResultSet rs;
// Check conversion to byte[]
prep = conn.prepareStatement("SELECT * FROM TABLE(X BINARY=?)");
prep.setObject(1, new Object[] { uuid });
rs = prep.executeQuery();
rs.next();
assertTrue(Arrays.equals(Utils.uuidToBytes(uuid), (byte[]) rs.getObject(1)));
// Check that type is not changed
prep = conn.prepareStatement("SELECT * FROM TABLE(X UUID=?)");
prep.setObject(1, new Object[] { uuid });
rs = prep.executeQuery();
rs.next();
assertEquals(uuid, rs.getObject(1));
} finally {
conn.close();
deleteDb("binaryAndUuid");
}
}
private void testCastTrim() { private void testCastTrim() {
Value v; Value v;
String spaces = new String(new char[100]).replace((char) 0, ' '); String spaces = new String(new char[100]).replace((char) 0, ' ');
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论