Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.UUID;

/**
* CallableStatement implements JDBC callable statements. CallableStatement allows the caller to specify the procedure name to call along with input
Expand Down Expand Up @@ -674,8 +675,84 @@ public Object getObject(int index) throws SQLServerException {

public <T> T getObject(int index,
Class<T> type) throws SQLException {
// The driver currently does not implement the optional JDBC APIs
throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported"));
loggerExternal.entering(getClassNameLogging(), "getObject", index);
checkClosed();
Object returnValue;
if (type == String.class) {
returnValue = getString(index);
}
else if (type == Byte.class) {
byte byteValue = getByte(index);
returnValue = wasNull() ? null : byteValue;
}
else if (type == Short.class) {
short shortValue = getShort(index);
returnValue = wasNull() ? null : shortValue;
}
else if (type == Integer.class) {
int intValue = getInt(index);
returnValue = wasNull() ? null : intValue;
}
else if (type == Long.class) {
long longValue = getLong(index);
returnValue = wasNull() ? null : longValue;
}
else if (type == BigDecimal.class) {
returnValue = getBigDecimal(index);
}
else if (type == Boolean.class) {
boolean booleanValue = getBoolean(index);
returnValue = wasNull() ? null : booleanValue;
}
else if (type == java.sql.Date.class) {
returnValue = getDate(index);
}
else if (type == java.sql.Time.class) {
returnValue = getTime(index);
}
else if (type == java.sql.Timestamp.class) {
returnValue = getTimestamp(index);
}
else if (type == microsoft.sql.DateTimeOffset.class) {
returnValue = getDateTimeOffset(index);
}
else if (type == UUID.class) {
// read binary, avoid string allocation and parsing
byte[] guid = getBytes(index);
returnValue = guid != null ? Util.readGUIDtoUUID(guid) : null;
}
else if (type == SQLXML.class) {
returnValue = getSQLXML(index);
}
else if (type == Blob.class) {
returnValue = getBlob(index);
}
else if (type == Clob.class) {
returnValue = getClob(index);
}
else if (type == NClob.class) {
returnValue = getNClob(index);
}
else if (type == byte[].class) {
returnValue = getBytes(index);
}
else if (type == Float.class) {
float floatValue = getFloat(index);
returnValue = wasNull() ? null : floatValue;
}
else if (type == Double.class) {
double doubleValue = getDouble(index);
returnValue = wasNull() ? null : doubleValue;
}
else {
// if the type is not supported the specification says the should
// a SQLException instead of SQLFeatureNotSupportedException
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_unsupportedConversionTo"));
Object[] msgArgs = {type};
throw new SQLServerException(form.format(msgArgs), SQLState.DATA_EXCEPTION_NOT_SPECIFIC, DriverError.NOT_SET, null);
}
loggerExternal.exiting(getClassNameLogging(), "getObject", index);
return type.cast(returnValue);
}

public Object getObject(String sCol) throws SQLServerException {
Expand All @@ -690,8 +767,12 @@ public Object getObject(String sCol) throws SQLServerException {

public <T> T getObject(String sCol,
Class<T> type) throws SQLException {
// The driver currently does not implement the optional JDBC APIs
throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported"));
loggerExternal.entering(getClassNameLogging(), "getObject", sCol);
checkClosed();
int parameterIndex = findColumn(sCol);
T value = getObject(parameterIndex, type);
loggerExternal.exiting(getClassNameLogging(), "getObject", value);
return value;
}

public short getShort(int index) throws SQLServerException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ protected Object[][] getContents() {
{"R_invalidConnection", "The connection URL is invalid."},
{"R_cannotTakeArgumentsPreparedOrCallable", "The method {0} cannot take arguments on a PreparedStatement or CallableStatement."},
{"R_unsupportedConversionFromTo", "The conversion from {0} to {1} is unsupported."}, // Invalid conversion (e.g. MONEY to Timestamp)
{"R_unsupportedConversionTo", "The conversion to {0} is unsupported."}, // Invalid conversion to an unknown type
{"R_errorConvertingValue","An error occurred while converting the {0} value to JDBC data type {1}."}, // Data-dependent conversion failure (e.g. "foo" vs. "123", to Integer)
{"R_streamIsClosed", "The stream is closed."},
{"R_invalidTDS", "The TDS protocol stream is not valid."},
Expand Down
88 changes: 84 additions & 4 deletions src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.sql.SQLXML;
import java.text.MessageFormat;
import java.util.Calendar;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;

Expand Down Expand Up @@ -2170,8 +2171,84 @@ public Object getObject(int columnIndex) throws SQLServerException {

public <T> T getObject(int columnIndex,
Class<T> type) throws SQLException {
// The driver currently does not implement the optional JDBC APIs
throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported"));
loggerExternal.entering(getClassNameLogging(), "getObject", columnIndex);
checkClosed();
Object returnValue;
if (type == String.class) {
returnValue = getString(columnIndex);
}
else if (type == Byte.class) {
byte byteValue = getByte(columnIndex);
returnValue = wasNull() ? null : byteValue;
}
else if (type == Short.class) {
short shortValue = getShort(columnIndex);
returnValue = wasNull() ? null : shortValue;
}
else if (type == Integer.class) {
int intValue = getInt(columnIndex);
returnValue = wasNull() ? null : intValue;
}
else if (type == Long.class) {
long longValue = getLong(columnIndex);
returnValue = wasNull() ? null : longValue;
}
else if (type == BigDecimal.class) {
returnValue = getBigDecimal(columnIndex);
}
else if (type == Boolean.class) {
boolean booleanValue = getBoolean(columnIndex);
returnValue = wasNull() ? null : booleanValue;
}
else if (type == java.sql.Date.class) {
returnValue = getDate(columnIndex);
}
else if (type == java.sql.Time.class) {
returnValue = getTime(columnIndex);
}
else if (type == java.sql.Timestamp.class) {
returnValue = getTimestamp(columnIndex);
}
else if (type == microsoft.sql.DateTimeOffset.class) {
returnValue = getDateTimeOffset(columnIndex);
}
else if (type == UUID.class) {
// read binary, avoid string allocation and parsing
byte[] guid = getBytes(columnIndex);
returnValue = guid != null ? Util.readGUIDtoUUID(guid) : null;
}
else if (type == SQLXML.class) {
returnValue = getSQLXML(columnIndex);
}
else if (type == Blob.class) {
returnValue = getBlob(columnIndex);
}
else if (type == Clob.class) {
returnValue = getClob(columnIndex);
}
else if (type == NClob.class) {
returnValue = getNClob(columnIndex);
}
else if (type == byte[].class) {
returnValue = getBytes(columnIndex);
}
else if (type == Float.class) {
float floatValue = getFloat(columnIndex);
returnValue = wasNull() ? null : floatValue;
}
else if (type == Double.class) {
double doubleValue = getDouble(columnIndex);
returnValue = wasNull() ? null : doubleValue;
}
else {
// if the type is not supported the specification says the should
// a SQLException instead of SQLFeatureNotSupportedException
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_unsupportedConversionTo"));
Object[] msgArgs = {type};
throw new SQLServerException(form.format(msgArgs), SQLState.DATA_EXCEPTION_NOT_SPECIFIC, DriverError.NOT_SET, null);
}
loggerExternal.exiting(getClassNameLogging(), "getObject", columnIndex);
return type.cast(returnValue);
}

public Object getObject(String columnName) throws SQLServerException {
Expand All @@ -2184,8 +2261,11 @@ public Object getObject(String columnName) throws SQLServerException {

public <T> T getObject(String columnName,
Class<T> type) throws SQLException {
// The driver currently does not implement the optional JDBC APIs
throw new SQLFeatureNotSupportedException(SQLServerException.getErrString("R_notSupported"));
loggerExternal.entering(getClassNameLogging(), "getObject", columnName);
checkClosed();
T value = getObject(findColumn(columnName), type);
loggerExternal.exiting(getClassNameLogging(), "getObject", value);
return value;
}

public short getShort(int columnIndex) throws SQLServerException {
Expand Down
40 changes: 40 additions & 0 deletions src/main/java/com/microsoft/sqlserver/jdbc/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,46 @@ static final byte[] asGuidByteArray(UUID aId) {
return buffer;
}

static final UUID readGUIDtoUUID(byte[] inputGUID) throws SQLServerException {
if (inputGUID.length != 16) {
throw new SQLServerException("guid length must be 16", null);
}

// For the first three fields, UUID uses network byte order,
// Guid uses native byte order. So we need to reverse
// the first three fields before creating a UUID.

byte tmpByte;

// Reverse the first 4 bytes
tmpByte = inputGUID[0];
inputGUID[0] = inputGUID[3];
inputGUID[3] = tmpByte;
tmpByte = inputGUID[1];
inputGUID[1] = inputGUID[2];
inputGUID[2] = tmpByte;

// Reverse the 5th and the 6th
tmpByte = inputGUID[4];
inputGUID[4] = inputGUID[5];
inputGUID[5] = tmpByte;

// Reverse the 7th and the 8th
tmpByte = inputGUID[6];
inputGUID[6] = inputGUID[7];
inputGUID[7] = tmpByte;

long msb = 0L;
for (int i = 0; i < 8; i++) {
msb = msb << 8 | ((long) inputGUID[i] & 0xFFL);
}
long lsb = 0L;
for (int i = 8; i < 16; i++) {
lsb = lsb << 8 | ((long) inputGUID[i] & 0xFFL);
}
return new UUID(msb, lsb);
}

static final String readGUID(byte[] inputGUID) throws SQLServerException {
String guidTemplate = "NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN";
byte guid[] = inputGUID;
Expand Down
32 changes: 32 additions & 0 deletions src/test/java/com/microsoft/sqlserver/jdbc/UtilTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Microsoft JDBC Driver for SQL Server
*
* Copyright(c) Microsoft Corporation All rights reserved.
*
* This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information.
*/
package com.microsoft.sqlserver.jdbc;

import static org.junit.Assert.assertEquals;

import java.util.UUID;

import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

/**
* Tests the Util class
*
*/
@RunWith(JUnitPlatform.class)
public class UtilTest {

@Test
public void readGUIDtoUUID() throws SQLServerException {
UUID expected = UUID.fromString("6F9619FF-8B86-D011-B42D-00C04FC964FF");
byte[] guid = new byte[] {-1, 25, -106, 111, -122, -117, 17, -48, -76, 45, 0, -64, 79, -55, 100, -1};
assertEquals(expected, Util.readGUIDtoUUID(guid));
}

}
Loading