diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/AE.java b/src/main/java/com/microsoft/sqlserver/jdbc/AE.java index 6aa55b865c..cbe7ecaa53 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/AE.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/AE.java @@ -5,6 +5,7 @@ package com.microsoft.sqlserver.jdbc; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -121,7 +122,12 @@ void add(byte[] encryptedKey, int dbId, int keyId, int keyVersion, byte[] mdVers /** * Contains all CEKs, each row represents one unique CEK (represented by CekTableEntry). */ -class CekTable { +class CekTable implements Serializable { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = -4568542970907052239L; + CekTableEntry[] keyList; CekTable(int tableSize) { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/Column.java b/src/main/java/com/microsoft/sqlserver/jdbc/Column.java index fdd71facbf..fd6b0e8f5b 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/Column.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/Column.java @@ -436,7 +436,7 @@ void sendByRPC(TDSWriter tdsWriter, SQLServerConnection conn) throws SQLServerEx try { // this is for updateRow() stuff updaterDTV.sendCryptoMetaData(cryptoMetadata, tdsWriter); - updaterDTV.jdbcTypeSetByUser(getJdbcTypeSetByUser(), getValueLength()); + updaterDTV.setJdbcTypeSetByUser(getJdbcTypeSetByUser(), getValueLength()); // Otherwise, send the updated value via RPC updaterDTV.sendByRPC(baseColumnName, typeInfo, diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/DDC.java b/src/main/java/com/microsoft/sqlserver/jdbc/DDC.java index 7e18aec104..53e0fd9085 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/DDC.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/DDC.java @@ -573,6 +573,22 @@ static final Object convertStreamToObject(BaseInputStream stream, TypeInfo typeI try { switch (jdbcType) { + case CLOB: + return new SQLServerClob(stream, typeInfo); + case NCLOB: + return new SQLServerNClob(stream, typeInfo); + case SQLXML: + return new SQLServerSQLXML(stream, getterArgs, typeInfo); + case BINARY: + case VARBINARY: + case LONGVARBINARY: + case BLOB: + // Where allowed, streams convert directly to binary representation + if (StreamType.BINARY == getterArgs.streamType) + return stream; + if (JDBCType.BLOB == jdbcType) + return new SQLServerBlob(stream); + return stream.getBytes(); case CHAR: case VARCHAR: case LONGVARCHAR: @@ -580,7 +596,6 @@ static final Object convertStreamToObject(BaseInputStream stream, TypeInfo typeI case NVARCHAR: case LONGNVARCHAR: default: - // Binary streams to character types: // - Direct conversion to ASCII stream // - Convert as hexized value to other character types @@ -597,12 +612,14 @@ static final Object convertStreamToObject(BaseInputStream stream, TypeInfo typeI return Util.readGUID(byteValue); } else if (JDBCType.GEOMETRY == jdbcType) { if (!typeInfo.getSSTypeName().equalsIgnoreCase(jdbcType.toString())) { - DataTypes.throwConversionError(typeInfo.getSSTypeName().toUpperCase(), jdbcType.toString()); + DataTypes.throwConversionError(typeInfo.getSSTypeName().toUpperCase(), + jdbcType.toString()); } return Geometry.STGeomFromWKB(byteValue); } else if (JDBCType.GEOGRAPHY == jdbcType) { if (!typeInfo.getSSTypeName().equalsIgnoreCase(jdbcType.toString())) { - DataTypes.throwConversionError(typeInfo.getSSTypeName().toUpperCase(), jdbcType.toString()); + DataTypes.throwConversionError(typeInfo.getSSTypeName().toUpperCase(), + jdbcType.toString()); } return Geography.STGeomFromWKB(byteValue); } else { @@ -643,28 +660,6 @@ static final Object convertStreamToObject(BaseInputStream stream, TypeInfo typeI return convertStringToObject(new String(stream.getBytes(), typeInfo.getCharset()), typeInfo.getCharset(), jdbcType, getterArgs.streamType); - case CLOB: - return new SQLServerClob(stream, typeInfo); - - case NCLOB: - return new SQLServerNClob(stream, typeInfo); - case SQLXML: - return new SQLServerSQLXML(stream, getterArgs, typeInfo); - - case BINARY: - case VARBINARY: - case LONGVARBINARY: - case BLOB: - - // Where allowed, streams convert directly to binary representation - - if (StreamType.BINARY == getterArgs.streamType) - return stream; - - if (JDBCType.BLOB == jdbcType) - return new SQLServerBlob(stream); - - return stream.getBytes(); } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/DataTypes.java b/src/main/java/com/microsoft/sqlserver/jdbc/DataTypes.java index a5970e6dce..21d9f91c49 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/DataTypes.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/DataTypes.java @@ -612,55 +612,56 @@ else if (!sendStringParametersAsUnicode && fromJavaType == JavaType.BYTEARRAY enum JDBCType { - UNKNOWN(Category.UNKNOWN, 999, "java.lang.Object"), - ARRAY(Category.UNKNOWN, java.sql.Types.ARRAY, "java.lang.Object"), - BIGINT(Category.NUMERIC, java.sql.Types.BIGINT, "java.lang.Long"), + UNKNOWN(Category.UNKNOWN, 999, Object.class.getName()), + ARRAY(Category.UNKNOWN, java.sql.Types.ARRAY, Object.class.getName()), + BIGINT(Category.NUMERIC, java.sql.Types.BIGINT, Long.class.getName()), BINARY(Category.BINARY, java.sql.Types.BINARY, "[B"), - BIT(Category.NUMERIC, java.sql.Types.BIT, "java.lang.Boolean"), - BLOB(Category.BLOB, java.sql.Types.BLOB, "java.sql.Blob"), - BOOLEAN(Category.NUMERIC, java.sql.Types.BOOLEAN, "java.lang.Boolean"), - CHAR(Category.CHARACTER, java.sql.Types.CHAR, "java.lang.String"), - CLOB(Category.CLOB, java.sql.Types.CLOB, "java.sql.Clob"), - DATALINK(Category.UNKNOWN, java.sql.Types.DATALINK, "java.lang.Object"), - DATE(Category.DATE, java.sql.Types.DATE, "java.sql.Date"), - DATETIMEOFFSET(Category.DATETIMEOFFSET, microsoft.sql.Types.DATETIMEOFFSET, "microsoft.sql.DateTimeOffset"), - DECIMAL(Category.NUMERIC, java.sql.Types.DECIMAL, "java.math.BigDecimal"), - DISTINCT(Category.UNKNOWN, java.sql.Types.DISTINCT, "java.lang.Object"), - DOUBLE(Category.NUMERIC, java.sql.Types.DOUBLE, "java.lang.Double"), - FLOAT(Category.NUMERIC, java.sql.Types.FLOAT, "java.lang.Double"), - INTEGER(Category.NUMERIC, java.sql.Types.INTEGER, "java.lang.Integer"), - JAVA_OBJECT(Category.UNKNOWN, java.sql.Types.JAVA_OBJECT, "java.lang.Object"), - LONGNVARCHAR(Category.LONG_NCHARACTER, -16, "java.lang.String"), + BIT(Category.NUMERIC, java.sql.Types.BIT, Boolean.class.getName()), + BLOB(Category.BLOB, java.sql.Types.BLOB, java.sql.Blob.class.getName()), + BOOLEAN(Category.NUMERIC, java.sql.Types.BOOLEAN, Boolean.class.getName()), + CHAR(Category.CHARACTER, java.sql.Types.CHAR, String.class.getName()), + CLOB(Category.CLOB, java.sql.Types.CLOB, java.sql.Clob.class.getName()), + DATALINK(Category.UNKNOWN, java.sql.Types.DATALINK, Object.class.getName()), + DATE(Category.DATE, java.sql.Types.DATE, java.sql.Date.class.getName()), + DATETIMEOFFSET(Category.DATETIMEOFFSET, microsoft.sql.Types.DATETIMEOFFSET, microsoft.sql.DateTimeOffset.class + .getName()), + DECIMAL(Category.NUMERIC, java.sql.Types.DECIMAL, BigDecimal.class.getName()), + DISTINCT(Category.UNKNOWN, java.sql.Types.DISTINCT, Object.class.getName()), + DOUBLE(Category.NUMERIC, java.sql.Types.DOUBLE, Double.class.getName()), + FLOAT(Category.NUMERIC, java.sql.Types.FLOAT, Double.class.getName()), + INTEGER(Category.NUMERIC, java.sql.Types.INTEGER, Integer.class.getName()), + JAVA_OBJECT(Category.UNKNOWN, java.sql.Types.JAVA_OBJECT, Object.class.getName()), + LONGNVARCHAR(Category.LONG_NCHARACTER, -16, String.class.getName()), LONGVARBINARY(Category.LONG_BINARY, java.sql.Types.LONGVARBINARY, "[B"), - LONGVARCHAR(Category.LONG_CHARACTER, java.sql.Types.LONGVARCHAR, "java.lang.String"), - NCHAR(Category.NCHARACTER, -15, "java.lang.String"), - NCLOB(Category.NCLOB, 2011, "java.sql.NClob"), - NULL(Category.UNKNOWN, java.sql.Types.NULL, "java.lang.Object"), - NUMERIC(Category.NUMERIC, java.sql.Types.NUMERIC, "java.math.BigDecimal"), - NVARCHAR(Category.NCHARACTER, -9, "java.lang.String"), - OTHER(Category.UNKNOWN, java.sql.Types.OTHER, "java.lang.Object"), - REAL(Category.NUMERIC, java.sql.Types.REAL, "java.lang.Float"), - REF(Category.UNKNOWN, java.sql.Types.REF, "java.lang.Object"), - ROWID(Category.UNKNOWN, -8, "java.lang.Object"), - SMALLINT(Category.NUMERIC, java.sql.Types.SMALLINT, "java.lang.Short"), - SQLXML(Category.SQLXML, 2009, "java.lang.Object"), - STRUCT(Category.UNKNOWN, java.sql.Types.STRUCT, "java.lang.Object"), - TIME(Category.TIME, java.sql.Types.TIME, "java.sql.Time"), - TIME_WITH_TIMEZONE(Category.TIME_WITH_TIMEZONE, 2013, "java.time.OffsetTime"), - TIMESTAMP(Category.TIMESTAMP, java.sql.Types.TIMESTAMP, "java.sql.Timestamp"), - TIMESTAMP_WITH_TIMEZONE(Category.TIMESTAMP_WITH_TIMEZONE, 2014, "java.time.OffsetDateTime"), - TINYINT(Category.NUMERIC, java.sql.Types.TINYINT, "java.lang.Short"), + LONGVARCHAR(Category.LONG_CHARACTER, java.sql.Types.LONGVARCHAR, String.class.getName()), + NCHAR(Category.NCHARACTER, -15, String.class.getName()), + NCLOB(Category.NCLOB, 2011, java.sql.NClob.class.getName()), + NULL(Category.UNKNOWN, java.sql.Types.NULL, Object.class.getName()), + NUMERIC(Category.NUMERIC, java.sql.Types.NUMERIC, BigDecimal.class.getName()), + NVARCHAR(Category.NCHARACTER, -9, String.class.getName()), + OTHER(Category.UNKNOWN, java.sql.Types.OTHER, Object.class.getName()), + REAL(Category.NUMERIC, java.sql.Types.REAL, Float.class.getName()), + REF(Category.UNKNOWN, java.sql.Types.REF, Object.class.getName()), + ROWID(Category.UNKNOWN, -8, Object.class.getName()), + SMALLINT(Category.NUMERIC, java.sql.Types.SMALLINT, Short.class.getName()), + SQLXML(Category.SQLXML, 2009, Object.class.getName()), + STRUCT(Category.UNKNOWN, java.sql.Types.STRUCT, Object.class.getName()), + TIME(Category.TIME, java.sql.Types.TIME, java.sql.Time.class.getName()), + TIME_WITH_TIMEZONE(Category.TIME_WITH_TIMEZONE, 2013, java.time.OffsetTime.class.getName()), + TIMESTAMP(Category.TIMESTAMP, java.sql.Types.TIMESTAMP, java.sql.Timestamp.class.getName()), + TIMESTAMP_WITH_TIMEZONE(Category.TIMESTAMP_WITH_TIMEZONE, 2014, java.time.OffsetDateTime.class.getName()), + TINYINT(Category.NUMERIC, java.sql.Types.TINYINT, Short.class.getName()), VARBINARY(Category.BINARY, java.sql.Types.VARBINARY, "[B"), - VARCHAR(Category.CHARACTER, java.sql.Types.VARCHAR, "java.lang.String"), - MONEY(Category.NUMERIC, microsoft.sql.Types.MONEY, "java.math.BigDecimal"), - SMALLMONEY(Category.NUMERIC, microsoft.sql.Types.SMALLMONEY, "java.math.BigDecimal"), - TVP(Category.TVP, microsoft.sql.Types.STRUCTURED, "java.lang.Object"), - DATETIME(Category.TIMESTAMP, microsoft.sql.Types.DATETIME, "java.sql.Timestamp"), - SMALLDATETIME(Category.TIMESTAMP, microsoft.sql.Types.SMALLDATETIME, "java.sql.Timestamp"), - GUID(Category.CHARACTER, microsoft.sql.Types.GUID, "java.lang.String"), - SQL_VARIANT(Category.SQL_VARIANT, microsoft.sql.Types.SQL_VARIANT, "java.lang.Object"), - GEOMETRY(Category.GEOMETRY, microsoft.sql.Types.GEOMETRY, "java.lang.Object"), - GEOGRAPHY(Category.GEOGRAPHY, microsoft.sql.Types.GEOGRAPHY, "java.lang.Object"); + VARCHAR(Category.CHARACTER, java.sql.Types.VARCHAR, String.class.getName()), + MONEY(Category.NUMERIC, microsoft.sql.Types.MONEY, BigDecimal.class.getName()), + SMALLMONEY(Category.NUMERIC, microsoft.sql.Types.SMALLMONEY, BigDecimal.class.getName()), + TVP(Category.TVP, microsoft.sql.Types.STRUCTURED, Object.class.getName()), + DATETIME(Category.TIMESTAMP, microsoft.sql.Types.DATETIME, java.sql.Timestamp.class.getName()), + SMALLDATETIME(Category.TIMESTAMP, microsoft.sql.Types.SMALLDATETIME, java.sql.Timestamp.class.getName()), + GUID(Category.CHARACTER, microsoft.sql.Types.GUID, String.class.getName()), + SQL_VARIANT(Category.SQL_VARIANT, microsoft.sql.Types.SQL_VARIANT, Object.class.getName()), + GEOMETRY(Category.GEOMETRY, microsoft.sql.Types.GEOMETRY, Object.class.getName()), + GEOGRAPHY(Category.GEOGRAPHY, microsoft.sql.Types.GEOGRAPHY, Object.class.getName()); final Category category; private final int intValue; @@ -1143,8 +1144,6 @@ static final void throwConversionError(String fromType, String toType) throws SQ final static int MAX_VARTYPE_MAX_CHARS = 0x3FFFFFFF; final static int MAX_VARTYPE_MAX_BYTES = 0x7FFFFFFF; - static private java.util.logging.Logger stmtDT; - // Special length indicator for varchar(max), nvarchar(max) and varbinary(max). static final int MAXTYPE_LENGTH = 0xFFFF; @@ -1160,12 +1159,12 @@ static final long getCheckedLength(SQLServerConnection con, JDBCType jdbcType, l case NVARCHAR: case LONGNVARCHAR: case NCLOB: - assert MAX_VARTYPE_MAX_CHARS == NTEXT_MAX_CHARS; + // assert MAX_VARTYPE_MAX_CHARS == NTEXT_MAX_CHARS; maxLength = DataTypes.MAX_VARTYPE_MAX_CHARS; break; default: - assert MAX_VARTYPE_MAX_BYTES == IMAGE_TEXT_MAX_BYTES; + // assert MAX_VARTYPE_MAX_BYTES == IMAGE_TEXT_MAX_BYTES; maxLength = DataTypes.MAX_VARTYPE_MAX_BYTES; break; } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/FailOverInfo.java b/src/main/java/com/microsoft/sqlserver/jdbc/FailOverInfo.java index 14f394ab3d..23f2e72efe 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/FailOverInfo.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/FailOverInfo.java @@ -5,6 +5,7 @@ package com.microsoft.sqlserver.jdbc; +import java.io.Serializable; import java.text.MessageFormat; import java.util.logging.Level; @@ -113,7 +114,12 @@ synchronized void failoverAdd(SQLServerConnection connection, boolean actualUseF // We need this class so during a connection open we can keep a copy of the current failover info stable // This is also used to keep the standalone primary server connection information. // -final class ServerPortPlaceHolder { +final class ServerPortPlaceHolder implements Serializable { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 7393779415545731523L; + private final String serverName; private final int port; private final String instanceName; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java index 30e9ed674b..334c8ab85d 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java @@ -13,6 +13,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; +import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.math.BigInteger; @@ -543,7 +544,12 @@ private UTC() {} } -final class TDSChannel { +final class TDSChannel implements Serializable { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = -866497813437384090L; + private static final Logger logger = Logger.getLogger("com.microsoft.sqlserver.jdbc.internals.TDS.Channel"); final Logger getLogger() { @@ -578,6 +584,7 @@ final TDSReader getReader(TDSCommand command) { * Socket providing the communications interface to the driver. For SSL-encrypted connections, this is the SSLSocket * wrapped around the TCP socket. For unencrypted connections, it is just the TCP socket itself. */ + @SuppressWarnings("unused") private Socket channelSocket; /* @@ -2586,6 +2593,7 @@ private void findSocketUsingJavaNIO(InetAddress[] inetAddrs, int portNumber, sChannel.configureBlocking(false); // register the channel for connect event + @SuppressWarnings("unused") int ops = SelectionKey.OP_CONNECT; sChannel.connect(new InetSocketAddress(inetAddr, portNumber)); @@ -4234,11 +4242,11 @@ private void writePacketHeader(int tdsMessageStatus) { // length is 16 // bits, stagingBuffer.put(TDS.PACKET_HEADER_MESSAGE_LENGTH + 1, (byte) ((tdsMessageLength >> 0) & 0xFF)); // written BIG - // ENDIAN + // ENDIAN stagingBuffer.put(TDS.PACKET_HEADER_SPID, (byte) ((tdsChannel.getSPID() >> 8) & 0xFF)); // Note: SPID is 16 // bits, stagingBuffer.put(TDS.PACKET_HEADER_SPID + 1, (byte) ((tdsChannel.getSPID() >> 0) & 0xFF)); // written BIG - // ENDIAN + // ENDIAN stagingBuffer.put(TDS.PACKET_HEADER_SEQUENCE_NUM, (byte) (packetNum % 256)); stagingBuffer.put(TDS.PACKET_HEADER_WINDOW, (byte) 0); // Window (Reserved/Not used) @@ -4250,11 +4258,11 @@ private void writePacketHeader(int tdsMessageStatus) { // length is 16 // bits, logBuffer.put(TDS.PACKET_HEADER_MESSAGE_LENGTH + 1, (byte) ((tdsMessageLength >> 0) & 0xFF)); // written BIG - // ENDIAN + // ENDIAN logBuffer.put(TDS.PACKET_HEADER_SPID, (byte) ((tdsChannel.getSPID() >> 8) & 0xFF)); // Note: SPID is 16 // bits, logBuffer.put(TDS.PACKET_HEADER_SPID + 1, (byte) ((tdsChannel.getSPID() >> 0) & 0xFF)); // written BIG - // ENDIAN + // ENDIAN logBuffer.put(TDS.PACKET_HEADER_SEQUENCE_NUM, (byte) (packetNum % 256)); logBuffer.put(TDS.PACKET_HEADER_WINDOW, (byte) 0); // Window (Reserved/Not used); } @@ -6418,7 +6426,13 @@ final class TDSReaderMark { * * Bytes are read from SQL Server into a FIFO of packets. Reader methods traverse the packets to access the data. */ -final class TDSReader { +final class TDSReader implements Serializable { + + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = -392905303734809731L; + private static final Logger logger = Logger.getLogger("com.microsoft.sqlserver.jdbc.internals.TDS.Reader"); final private String traceID; private ScheduledFuture timeout; @@ -7214,7 +7228,12 @@ final void trySetSensitivityClassification(SensitivityClassification sensitivity * the interrupt event occurs when the timeout period expires. Currently, only the time to receive the response from the * channel counts against the timeout period. */ -abstract class TDSCommand { +abstract class TDSCommand implements Serializable { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 5485075546328951857L; + abstract boolean doExecute() throws SQLServerException; static final Logger logger = Logger.getLogger("com.microsoft.sqlserver.jdbc.internals.TDS.Command"); @@ -7800,6 +7819,11 @@ final TDSReader startResponse(boolean isAdaptive) throws SQLServerException { * implementation for such commands. */ abstract class UninterruptableTDSCommand extends TDSCommand { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = -6457195977162963793L; + UninterruptableTDSCommand(String logContext) { super(logContext, 0, 0); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerBulkRecord.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerBulkRecord.java index 1f347cac99..04fa829021 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerBulkRecord.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerBulkRecord.java @@ -5,6 +5,7 @@ package com.microsoft.sqlserver.jdbc; +import java.io.Serializable; import java.time.format.DateTimeFormatter; @@ -14,7 +15,7 @@ * * This interface is implemented by {@link SQLServerBulkCommon} Class */ -public interface ISQLServerBulkRecord { +public interface ISQLServerBulkRecord extends Serializable { /** * Returns the ordinals for each of the columns represented in this data record. diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerResultSetMetaData.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerResultSetMetaData.java index 32788d998d..6f6366469c 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerResultSetMetaData.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerResultSetMetaData.java @@ -5,13 +5,14 @@ package com.microsoft.sqlserver.jdbc; +import java.io.Serializable; import java.sql.ResultSetMetaData; /** * Provides an interface to the{@link SQLServerResultSetMetaData} class. */ -public interface ISQLServerResultSetMetaData extends ResultSetMetaData { +public interface ISQLServerResultSetMetaData extends ResultSetMetaData, Serializable { /** * Returns if the column is a SQLServer SparseColumnSet. diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerSavepoint.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerSavepoint.java index 3f97fe79b5..a988a02040 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerSavepoint.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerSavepoint.java @@ -5,13 +5,14 @@ package com.microsoft.sqlserver.jdbc; +import java.io.Serializable; import java.sql.Savepoint; /** * Provides an interface to the {@link SQLServerSavepoint} class. */ -public interface ISQLServerSavepoint extends Savepoint { +public interface ISQLServerSavepoint extends Savepoint, Serializable { /** * Returns the savepoint name diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerStatement.java index 51797677b2..49ddd7a83b 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerStatement.java @@ -5,10 +5,12 @@ package com.microsoft.sqlserver.jdbc; +import java.io.Serializable; + /** * Provides an interface to the {@link SQLServerStatement} class. */ -public interface ISQLServerStatement extends java.sql.Statement { +public interface ISQLServerStatement extends java.sql.Statement, Serializable { /** * Sets the response buffering mode for this SQLServerStatement object to case-insensitive String full or adaptive. *

diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java b/src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java index 7e94fe9e4c..e96be19a9a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java @@ -1152,7 +1152,7 @@ void sendByRPC(TDSWriter tdsWriter, SQLServerConnection conn) throws SQLServerEx try { inputDTV.sendCryptoMetaData(this.cryptoMeta, tdsWriter); - inputDTV.jdbcTypeSetByUser(getJdbcTypeSetByUser(), getValueLength()); + inputDTV.setJdbcTypeSetByUser(getJdbcTypeSetByUser(), getValueLength()); inputDTV.sendByRPC(name, null, conn.getDatabaseCollation(), valueLength, isOutput() ? outScale : scale, isOutput(), tdsWriter, conn); } finally { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ParameterUtils.java b/src/main/java/com/microsoft/sqlserver/jdbc/ParameterUtils.java index b1c141ca2a..bad1aeddb3 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ParameterUtils.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ParameterUtils.java @@ -75,10 +75,8 @@ static int scanSQLForChar(char ch, String sql, int offset) { if (sql.charAt(offset) == '*') { // If '/* ... */' comment while (++offset < len) { // Go thru comment. - if (sql.charAt(offset) == '*' && offset + 1 < len && sql.charAt(offset + 1) == '/') { // If - // end - // of - // comment + if (sql.charAt(offset) == '*' && offset + 1 < len && sql.charAt(offset + 1) == '/') { + // If end of comment offset += 2; break; } @@ -91,7 +89,8 @@ static int scanSQLForChar(char ch, String sql, int offset) { case '-': if (sql.charAt(offset) == '-') { // If '-- ... \n' comment while (++offset < len) { // Go thru comment. - if (sql.charAt(offset) == '\n' || sql.charAt(offset) == '\r') { // If end of comment + if (sql.charAt(offset) == '\n' || sql.charAt(offset) == '\r') { + // If end of comment offset++; break; } @@ -99,11 +98,6 @@ static int scanSQLForChar(char ch, String sql, int offset) { break; } // Fall through to test character - default: - if (ch == chTmp) - return offset - 1; - break; - case '[': chTmp = ']'; case '\'': @@ -118,6 +112,10 @@ static int scanSQLForChar(char ch, String sql, int offset) { } } break; + default: + if (ch == chTmp) + return offset - 1; + break; } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkBatchInsertRecord.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkBatchInsertRecord.java index 3c662b267e..7359eda283 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkBatchInsertRecord.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkBatchInsertRecord.java @@ -26,6 +26,11 @@ */ public class SQLServerBulkBatchInsertRecord extends SQLServerBulkCommon { + /** + * Update serialVersionUID when making changes to this file + */ + private static final long serialVersionUID = -955998113956445541L; + private List batchParam; private int batchParamIndex = -1; private List columnList; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java index ac84bc58d2..f47c4fd2cc 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java @@ -29,6 +29,10 @@ * data types from a delimited file where each line represents a row of data. */ public class SQLServerBulkCSVFileRecord extends SQLServerBulkCommon implements java.lang.AutoCloseable { + /** + * Update serialVersionUID when making changes to this file + */ + private static final long serialVersionUID = 1546487135640225989L; /* * Resources associated with reading in the file */ diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCommon.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCommon.java index 4fdae12499..b48fe8e4d1 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCommon.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCommon.java @@ -13,6 +13,11 @@ abstract class SQLServerBulkCommon implements ISQLServerBulkRecord { + /** + * Update serialVersionUID when making changes to this file + */ + private static final long serialVersionUID = -170992637946357449L; + /* * Class to represent the column metadata */ diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java index 38260da28b..28e7911bcd 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.Reader; +import java.io.Serializable; import java.io.StringReader; import java.math.BigDecimal; import java.nio.ByteBuffer; @@ -70,7 +71,12 @@ public class SQLServerBulkCopy implements java.lang.AutoCloseable, java.io.Seria /** * Represents the column mappings between the source and destination table */ - private class ColumnMapping { + private class ColumnMapping implements Serializable { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 6428337550654423919L; + String sourceColumnName = null; int sourceColumnOrdinal = -1; String destinationColumnName = null; @@ -102,8 +108,6 @@ private class ColumnMapping { */ private static final String loggerClassName = "com.microsoft.sqlserver.jdbc.SQLServerBulkCopy"; - private static final int SQL_SERVER_2016_VERSION = 13; - /** * Logger */ @@ -621,6 +625,11 @@ private void initializeDefaults() { private void sendBulkLoadBCP() throws SQLServerException { final class InsertBulk extends TDSCommand { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 6714118105257791547L; + InsertBulk() { super("InsertBulk", 0, 0); } @@ -747,7 +756,7 @@ private void writeColumnMetaDataColumnData(TDSWriter tdsWriter, int idx) throws CryptoMetadata destCryptoMeta = destColumnMetadata.get(destColumnIndex).cryptoMeta; /* - * if source is encrypted and destination is unenecrypted, use destination's sql type to send since there is no + * if source is encrypted and destination is unencrypted, use destination's sql type to send since there is no * way of finding if source is encrypted without accessing the resultset. Send destination type if source * resultset set is of type SQLServer, encryption is enabled and destination column is not encrypted */ @@ -1170,6 +1179,18 @@ private String getDestTypeFromSrcType(int srcColIndx, int destColIndx, // Encrypted columns are sent as binary data. tdsWriter.setCryptoMetaData(destColumnMetadata.get(destColIndx).cryptoMeta); + /* + * if source is encrypted and destination is unencrypted, use destination's sql type to send since there is + * no way of finding if source is encrypted without accessing the resultset. Send destination type if source + * resultset set is of type SQLServer, encryption is enabled and destination column is not encrypted + */ + if ((sourceResultSet instanceof SQLServerResultSet) && (connection.isColumnEncryptionSettingEnabled()) + && (null != destCryptoMeta)) { + bulkJdbcType = destColumnMetadata.get(destColIndx).jdbcType; + bulkPrecision = destPrecision; + bulkScale = destColumnMetadata.get(destColIndx).scale; + } + // if destination is encrypted send metadata from destination and not from source if (DataTypes.SHORT_VARTYPE_MAX_BYTES < destPrecision) { return "varbinary(max)"; @@ -1185,18 +1206,6 @@ private String getDestTypeFromSrcType(int srcColIndx, int destColIndx, } bulkPrecision = validateSourcePrecision(srcPrecision, bulkJdbcType, destPrecision); - /* - * if source is encrypted and destination is unenecrypted, use destination's sql type to send since there is no - * way of finding if source is encrypted without accessing the resultset. Send destination type if source - * resultset set is of type SQLServer, encryption is enabled and destination column is not encrypted - */ - if ((sourceResultSet instanceof SQLServerResultSet) && (connection.isColumnEncryptionSettingEnabled()) - && (null != destCryptoMeta)) { - bulkJdbcType = destColumnMetadata.get(destColIndx).jdbcType; - bulkPrecision = destPrecision; - bulkScale = destColumnMetadata.get(destColIndx).scale; - } - if ((java.sql.Types.NCHAR == bulkJdbcType) || (java.sql.Types.NVARCHAR == bulkJdbcType) || (java.sql.Types.LONGNVARCHAR == bulkJdbcType)) { isStreaming = (DataTypes.SHORT_VARTYPE_MAX_CHARS < srcPrecision) @@ -1548,14 +1557,6 @@ private void throwInvalidArgument(String argument) throws SQLServerException { SQLServerException.makeFromDriverError(null, null, form.format(msgArgs), null, false); } - /** - * Helper method to throw a SQLServerExeption with the errorConvertingValue message and given arguments. - */ - private void throwInvalidJavaToJDBC(String javaClassName, int jdbcType) throws SQLServerException { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_errorConvertingValue")); - throw new SQLServerException(form.format(new Object[] {javaClassName, jdbcType}), null, 0, null); - } - /** * The bulk copy operation */ @@ -1641,8 +1642,8 @@ private void getDestinationMetadata() throws SQLServerException { ResultSet.CONCUR_READ_ONLY, connection.getHoldability(), stmtColumnEncriptionSetting); // Get destination metadata - rs = stmt.executeQueryInternal("sp_executesql N'SET FMTONLY ON SELECT * FROM " - + escapedDestinationTableName + " '"); + rs = stmt.executeQueryInternal( + "sp_executesql N'SET FMTONLY ON SELECT * FROM " + escapedDestinationTableName + " '"); } destColumnCount = rs.getMetaData().getColumnCount(); @@ -1961,7 +1962,7 @@ private void writeColumnToTdsWriter(TDSWriter tdsWriter, int bulkPrecision, int bulkJdbcType = java.sql.Types.VARBINARY; } /* - * if source is encrypted and destination is unenecrypted, use destination sql type to send since there is no + * if source is encrypted and destination is unencrypted, use destination sql type to send since there is no * way of finding if source is encrypted without accessing the resultset, send destination type if source * resultset set is of type SQLServer and encryption is enabled */ @@ -2621,8 +2622,7 @@ private void writeSqlVariant(TDSWriter tdsWriter, Object colValue, ResultSet sou try { srcBytes = ParameterUtils.HexToBin(colValue.toString()); } catch (SQLServerException e) { - throw new SQLServerException(SQLServerException.getErrString("R_unableRetrieveSourceData"), - e); + throw new SQLServerException(SQLServerException.getErrString("R_unableRetrieveSourceData"), e); } } tdsWriter.writeBytes(srcBytes); @@ -2639,8 +2639,7 @@ private void writeSqlVariant(TDSWriter tdsWriter, Object colValue, ResultSet sou try { srcBytes = ParameterUtils.HexToBin(colValue.toString()); } catch (SQLServerException e) { - throw new SQLServerException(SQLServerException.getErrString("R_unableRetrieveSourceData"), - e); + throw new SQLServerException(SQLServerException.getErrString("R_unableRetrieveSourceData"), e); } } tdsWriter.writeBytes(srcBytes); @@ -2983,13 +2982,14 @@ protected Object getTemporalObjectFromCSVWithFormatter(String valueStrUntrimmed, return new java.sql.Date(ts.getTime()); case microsoft.sql.Types.DATETIMEOFFSET: return DateTimeOffset.valueOf(ts, taOffsetSec / 60); + default: + return valueStrUntrimmed; } } catch (DateTimeException | ArithmeticException e) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_ParsingError")); Object[] msgArgs = {JDBCType.of(srcJdbcType)}; throw new SQLServerException(this, form.format(msgArgs), null, 0, false); } - return valueStrUntrimmed; } private Object getTemporalObjectFromCSV(Object value, int srcJdbcType, @@ -3021,6 +3021,8 @@ private Object getTemporalObjectFromCSV(Object value, int srcJdbcType, case java.sql.Types.DATE: case microsoft.sql.Types.DATETIMEOFFSET: return null; + default: + break; } } @@ -3132,6 +3134,8 @@ else if ('-' == valueStr.charAt(startIndx)) { Timestamp ts = new Timestamp(cal.getTimeInMillis()); ts.setNanos(fractionalSeconds); return microsoft.sql.DateTimeOffset.valueOf(ts, totalOffset); + default: + break; } } catch (IndexOutOfBoundsException e) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_ParsingError")); @@ -3440,7 +3444,6 @@ private boolean writeBatchData(TDSWriter tdsWriter, TDSCommand command, // Write row header for each row. tdsWriter.writeByte((byte) TDS.TDS_ROW); - int mappingColumnCount = columnMappings.size(); // Copying from a resultset. if (null != sourceResultSet) { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopyOptions.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopyOptions.java index 67f76277bd..17bde2b87d 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopyOptions.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopyOptions.java @@ -5,6 +5,7 @@ package com.microsoft.sqlserver.jdbc; +import java.io.Serializable; import java.text.MessageFormat; @@ -12,7 +13,12 @@ * Provides a collection of settings that control how an instance of SQLServerBulkCopy behaves. Used when constructing a * SQLServerBulkCopy instance to change how the writeToServer methods for that instance behave. */ -public class SQLServerBulkCopyOptions { +public class SQLServerBulkCopyOptions implements Serializable { + /** + * Update serialVersionUID when making changes to this file + */ + private static final long serialVersionUID = 711570696894155194L; + /** * Number of rows in each batch. * diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCallableStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCallableStatement.java index 6331df080a..52fa922532 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCallableStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCallableStatement.java @@ -40,6 +40,11 @@ public class SQLServerCallableStatement extends SQLServerPreparedStatement implements ISQLServerCallableStatement { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 5044984771674532350L; + /** the call param names */ private ArrayList parameterNames; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java index 8d4816e8bd..1d5a05e454 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java @@ -13,7 +13,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; -import java.io.Serializable; import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; @@ -72,7 +71,7 @@ final JDBCType getJdbcType() { } -abstract class SQLServerClobBase extends SQLServerLob implements Serializable { +abstract class SQLServerClobBase extends SQLServerLob { /** * Always refresh SerialVersionUID when prompted */ diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionCertificateStoreProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionCertificateStoreProvider.java index 1f87ecbe08..7733e6db22 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionCertificateStoreProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionCertificateStoreProvider.java @@ -5,22 +5,6 @@ package com.microsoft.sqlserver.jdbc; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.file.Path; -import java.security.Key; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.text.MessageFormat; -import java.util.Base64; -import java.util.Enumeration; import java.util.Locale; @@ -48,7 +32,6 @@ public final class SQLServerColumnEncryptionCertificateStoreProvider extends SQL isWindows = false; } } - private Path keyStoreDirectoryPath = null; /** * Constructs a SQLServerColumnEncryptionCertificateStoreProvider. @@ -83,143 +66,6 @@ private byte[] decryptColumnEncryptionKeyWindows(String masterKeyPath, String en } } - private CertificateDetails getCertificateDetails(String masterKeyPath) throws SQLServerException { - String storeLocation = null; - - String[] certParts = masterKeyPath.split("/"); - - // Validate certificate path - // Certificate path should only contain 3 parts (Certificate Location, Certificate Store Name and Thumbprint) - if (certParts.length > 3) { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_AECertpathBad")); - Object[] msgArgs = {masterKeyPath}; - throw new SQLServerException(form.format(msgArgs), null); - } - - // Extract the store location where the cert is stored - if (certParts.length > 2) { - if (certParts[0].equalsIgnoreCase(localMachineDirectory)) { - storeLocation = localMachineDirectory; - } else if (certParts[0].equalsIgnoreCase(currentUserDirectory)) { - storeLocation = currentUserDirectory; - } else { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_AECertLocBad")); - Object[] msgArgs = {certParts[0], masterKeyPath}; - throw new SQLServerException(form.format(msgArgs), null); - } - } - - // Parse the certificate store name. Only store name "My" is supported. - if (certParts.length > 1) { - if (!certParts[certParts.length - 2].equalsIgnoreCase(myCertificateStore)) { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_AECertStoreBad")); - Object[] msgArgs = {certParts[certParts.length - 2], masterKeyPath}; - throw new SQLServerException(form.format(msgArgs), null); - } - } - - // Get thumpbrint - String thumbprint = certParts[certParts.length - 1]; - if ((null == thumbprint) || (0 == thumbprint.length())) { - // An empty thumbprint specified - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_AECertHashEmpty")); - Object[] msgArgs = {masterKeyPath}; - throw new SQLServerException(form.format(msgArgs), null); - } - - // Find the certificate and return - return getCertificateByThumbprint(storeLocation, thumbprint, masterKeyPath); - } - - private String getThumbPrint(X509Certificate cert) throws NoSuchAlgorithmException, CertificateEncodingException { - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] der = cert.getEncoded(); - md.update(der); - byte[] digest = md.digest(); - return Base64.getEncoder().encodeToString(digest); - } - - private CertificateDetails getCertificateByThumbprint(String storeLocation, String thumbprint, - String masterKeyPath) throws SQLServerException { - FileInputStream fis; - - if ((null == keyStoreDirectoryPath)) { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_AEKeyPathEmptyOrReserved")); - Object[] msgArgs = {keyStoreDirectoryPath}; - throw new SQLServerException(form.format(msgArgs), null); - } - - Path keyStoreFullPath = keyStoreDirectoryPath.resolve(storeLocation); - - KeyStore keyStore = null; - try { - keyStore = KeyStore.getInstance("PKCS12"); - } catch (KeyStoreException e) { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_CertificateError")); - Object[] msgArgs = {masterKeyPath, name}; - throw new SQLServerException(this, form.format(msgArgs), null, 0, false); - } - - File keyStoreDirectory = keyStoreFullPath.toFile(); - File[] listOfFiles = keyStoreDirectory.listFiles(); - - if ((null == listOfFiles) || (0 == listOfFiles.length)) { - throw new SQLServerException(SQLServerException.getErrString("R_KeyStoreNotFound"), null); - } - - for (File f : listOfFiles) { - - if (f.isDirectory()) { - continue; - } - - char[] password = "".toCharArray(); - try { - fis = new FileInputStream(f); - keyStore.load(fis, password); - } catch (IOException | CertificateException | NoSuchAlgorithmException e) { - // Cannot parse the current file, continue to the next. - continue; - } - - // If we are here, we were able to load a PKCS12 file. - try { - for (Enumeration enumeration = keyStore.aliases(); enumeration.hasMoreElements();) { - - String alias = enumeration.nextElement(); - - X509Certificate publicCertificate = (X509Certificate) keyStore.getCertificate(alias); - - if (thumbprint.matches(getThumbPrint(publicCertificate))) { - // Found the right certificate - Key keyPrivate = null; - try { - keyPrivate = keyStore.getKey(alias, "".toCharArray()); - if (null == keyPrivate) { - MessageFormat form = new MessageFormat( - SQLServerException.getErrString("R_UnrecoverableKeyAE")); - Object[] msgArgs = {masterKeyPath}; - throw new SQLServerException(this, form.format(msgArgs), null, 0, false); - } - } catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException e) { - MessageFormat form = new MessageFormat( - SQLServerException.getErrString("R_UnrecoverableKeyAE")); - Object[] msgArgs = {masterKeyPath}; - throw new SQLServerException(this, form.format(msgArgs), null, 0, false); - } - return new CertificateDetails(publicCertificate, keyPrivate); - } - } // end of for for alias - } catch (CertificateException | NoSuchAlgorithmException | KeyStoreException e) { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_CertificateError")); - Object[] msgArgs = {masterKeyPath, name}; - throw new SQLServerException(form.format(msgArgs), e); - } - } - // Looped over all files, haven't found the certificate - throw new SQLServerException(SQLServerException.getErrString("R_KeyStoreNotFound"), null); - } - public byte[] decryptColumnEncryptionKey(String masterKeyPath, String encryptionAlgorithm, byte[] encryptedColumnEncryptionKey) throws SQLServerException { windowsCertificateStoreLogger.entering(SQLServerColumnEncryptionCertificateStoreProvider.class.getName(), diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index 0b2d985dde..09d444ae24 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.Serializable; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.HttpURLConnection; @@ -356,7 +357,11 @@ private static int[] locateParams(String sql) { /** * Encapsulates the data to be sent to the server as part of Federated Authentication Feature Extension. */ - class FederatedAuthenticationFeatureExtensionData { + class FederatedAuthenticationFeatureExtensionData implements Serializable { + /** + * Always update serialVersionUID when prompted + */ + private static final long serialVersionUID = -6709861741957202475L; boolean fedAuthRequiredPreLoginResponse; int libraryType = -1; byte[] accessToken = null; @@ -930,7 +935,7 @@ final SQLCollation getDatabaseCollation() { private int transactionIsolationLevel; private SQLServerPooledConnection pooledConnectionParent; - private DatabaseMetaData databaseMetaData; // the meta data for this connection + private SQLServerDatabaseMetaData databaseMetaData; // the meta data for this connection private int nNextSavePointId = 10000; // first save point id static final private java.util.logging.Logger connectionlogger = java.util.logging.Logger @@ -1004,7 +1009,6 @@ final boolean attachConnId() { return state.equals(State.Connected); } - @SuppressWarnings("unused") SQLServerConnection(String parentInfo) throws SQLServerException { int connectionID = nextConnectionID(); // sequential connection id traceID = "ConnectionID:" + connectionID; @@ -2897,7 +2901,7 @@ final void terminate(int driverErrorCode, String message, Throwable throwable) t throw ex; } - private final Object schedulerLock = new Object(); + private final transient Object schedulerLock = new Object(); /** * Executes a command through the scheduler. @@ -2952,6 +2956,10 @@ void resetCurrentCommand() throws SQLServerException { */ private void connectionCommand(String sql, String logContext) throws SQLServerException { final class ConnectionCommand extends UninterruptableTDSCommand { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 1L; final String sql; ConnectionCommand(String sql, String logContext) { @@ -3375,7 +3383,7 @@ public Statement createStatement(int resultSetType, int resultSetConcurrency) th loggerExternal.entering(getClassNameLogging(), "createStatement", new Object[] {resultSetType, resultSetConcurrency}); checkClosed(); - Statement st = new SQLServerStatement(this, resultSetType, resultSetConcurrency, + SQLServerStatement st = new SQLServerStatement(this, resultSetType, resultSetConcurrency, SQLServerStatementColumnEncryptionSetting.UseConnectionSetting); if (requestStarted) { addOpenStatement(st); @@ -3392,7 +3400,7 @@ public PreparedStatement prepareStatement(String sql, int resultSetType, new Object[] {sql, resultSetType, resultSetConcurrency}); checkClosed(); - PreparedStatement st = new SQLServerPreparedStatement(this, sql, resultSetType, resultSetConcurrency, + SQLServerPreparedStatement st = new SQLServerPreparedStatement(this, sql, resultSetType, resultSetConcurrency, SQLServerStatementColumnEncryptionSetting.UseConnectionSetting); if (requestStarted) { @@ -3409,7 +3417,7 @@ private PreparedStatement prepareStatement(String sql, int resultSetType, int re new Object[] {sql, resultSetType, resultSetConcurrency, stmtColEncSetting}); checkClosed(); - PreparedStatement st = new SQLServerPreparedStatement(this, sql, resultSetType, resultSetConcurrency, + SQLServerPreparedStatement st = new SQLServerPreparedStatement(this, sql, resultSetType, resultSetConcurrency, stmtColEncSetting); if (requestStarted) { @@ -3428,7 +3436,7 @@ public CallableStatement prepareCall(String sql, int resultSetType, new Object[] {sql, resultSetType, resultSetConcurrency}); checkClosed(); - CallableStatement st = new SQLServerCallableStatement(this, sql, resultSetType, resultSetConcurrency, + SQLServerCallableStatement st = new SQLServerCallableStatement(this, sql, resultSetType, resultSetConcurrency, SQLServerStatementColumnEncryptionSetting.UseConnectionSetting); if (requestStarted) { @@ -3598,6 +3606,11 @@ int writeUTF8SupportFeatureRequest(boolean write, } private final class LogonCommand extends UninterruptableTDSCommand { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 1L; + LogonCommand() { super("logon"); } @@ -4047,6 +4060,10 @@ final void processFedAuthInfo(TDSReader tdsReader, TDSTokenHandler tdsTokenHandl } final class FedAuthTokenCommand extends UninterruptableTDSCommand { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 1L; TDSTokenHandler tdsTokenHandler = null; SqlFedAuthToken sqlFedAuthToken = null; @@ -4514,6 +4531,7 @@ private void onFeatureExtAck(byte featureId, byte[] data) throws SQLServerExcept byte enabled = data[1]; serverSupportsDataClassification = enabled != 0; + break; } case TDS.TDS_FEATURE_EXT_UTF8SUPPORT: { if (connectionlogger.isLoggable(Level.FINER)) { @@ -4543,6 +4561,10 @@ private void onFeatureExtAck(byte featureId, byte[] data) throws SQLServerExcept */ private void executeDTCCommand(int requestType, byte[] payload, String logContext) throws SQLServerException { final class DTCCommand extends UninterruptableTDSCommand { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 1L; private final int requestType; private final byte[] payload; @@ -5055,7 +5077,7 @@ public Statement createStatement(int nType, int nConcur, int resultSetHoldabilit checkMatchesCurrentHoldability(resultSetHoldability); Statement st = new SQLServerStatement(this, nType, nConcur, stmtColEncSetting); if (requestStarted) { - addOpenStatement(st); + addOpenStatement((ISQLServerStatement) st); } loggerExternal.exiting(getClassNameLogging(), "createStatement", st); return st; @@ -5084,7 +5106,7 @@ public PreparedStatement prepareStatement(java.lang.String sql, int nType, int n PreparedStatement st = new SQLServerPreparedStatement(this, sql, nType, nConcur, stmtColEncSetting); if (requestStarted) { - addOpenStatement(st); + addOpenStatement((ISQLServerStatement) st); } loggerExternal.exiting(getClassNameLogging(), "prepareStatement", st); @@ -5114,7 +5136,7 @@ public CallableStatement prepareCall(String sql, int nType, int nConcur, int res CallableStatement st = new SQLServerCallableStatement(this, sql, nType, nConcur, stmtColEncSetiing); if (requestStarted) { - addOpenStatement(st); + addOpenStatement((ISQLServerStatement) st); } loggerExternal.exiting(getClassNameLogging(), "prepareCall", st); @@ -5608,7 +5630,7 @@ public T unwrap(Class iface) throws SQLException { private String originalSCatalog; private boolean originalUseBulkCopyForBatchInsert; private volatile SQLWarning originalSqlWarnings; - private List openStatements; + private List openStatements; protected void beginRequestInternal() throws SQLException { loggerExternal.entering(getClassNameLogging(), "beginRequest", this); @@ -5626,7 +5648,7 @@ protected void beginRequestInternal() throws SQLException { originalSCatalog = sCatalog; originalUseBulkCopyForBatchInsert = getUseBulkCopyForBatchInsert(); originalSqlWarnings = sqlWarnings; - openStatements = new LinkedList(); + openStatements = new LinkedList(); requestStarted = true; } } @@ -6236,7 +6258,7 @@ boolean isAzureDW() throws SQLServerException, SQLException { * @param st * Statement to add to openStatements */ - final synchronized void addOpenStatement(Statement st) { + final synchronized void addOpenStatement(ISQLServerStatement st) { if (null != openStatements) { openStatements.add(st); } @@ -6248,7 +6270,7 @@ final synchronized void addOpenStatement(Statement st) { * @param st * Statement to remove from openStatements */ - final synchronized void removeOpenStatement(Statement st) { + final synchronized void removeOpenStatement(ISQLServerStatement st) { if (null != openStatements) { openStatements.remove(st); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java index 9c8428f2d7..affb6904e9 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java @@ -5,6 +5,7 @@ package com.microsoft.sqlserver.jdbc; +import java.io.Serializable; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverPropertyInfo; @@ -27,7 +28,12 @@ * The API javadoc for JDBC API methods that this class implements are not repeated here. Please see Sun's JDBC API * interfaces javadoc for those details. */ -public final class SQLServerDatabaseMetaData implements java.sql.DatabaseMetaData { +public final class SQLServerDatabaseMetaData implements java.sql.DatabaseMetaData, Serializable { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = -116977606028371577L; + private SQLServerConnection connection; static final String URL_PREFIX = "jdbc:sqlserver://"; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerException.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerException.java index 2b10a8dbca..fe336ce4e3 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerException.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerException.java @@ -293,21 +293,23 @@ static String mapFromXopen(String state) { // since the SQL99 states cant be located on the web (must pay) and the XOPEN states appear to // be specific. Therefore if the driver is in SQL 99 mode we must map to SQL 99 state codes. // SQL99 values based on previous SQLServerConnect code and some inet values.. - if (state == null) - return null; - if (state.equals("07009")) - return "S1093"; - - // Connection (network) failure after connection made - if (state.equals(SQLServerException.EXCEPTION_XOPEN_CONNECTION_CANT_ESTABLISH)) - return "08S01"; - if (state.equals(SQLServerException.EXCEPTION_XOPEN_CONNECTION_FAILURE)) - return "08S01"; - - // if (state.equals(SQLServerException.EXCEPTION_XOPEN_NETWORK_ERROR)) - // return "S0022"; //Previous SQL99 state code for bad column name - - return ""; + if (null != state) { + switch (state) { + case "07009": + return "S1093"; + + // Connection (network) failure after connection made + case SQLServerException.EXCEPTION_XOPEN_CONNECTION_CANT_ESTABLISH: + return "08S01"; + case SQLServerException.EXCEPTION_XOPEN_CONNECTION_FAILURE: + return "08S01"; + default: + return ""; + } + // if (state.equals(SQLServerException.EXCEPTION_XOPEN_NETWORK_ERROR)) + // return "S0022"; //Previous SQL99 state code for bad column name + } + return null; } /** @@ -336,9 +338,9 @@ static String generateStateCode(SQLServerConnection con, int errNum, int databas return "42S02"; // Table not found case 207: return "42S22"; // Column not found - // case 156: return "42000"; //Invalid syntax + default: + return "42000"; // Use XOPEN 'Syntax error or access violation' } - return "42000"; // Use XOPEN 'Syntax error or access violation' // The error code came from the db but XOPEN does not have a specific case for it. } else { switch (errNum) { @@ -358,8 +360,9 @@ static String generateStateCode(SQLServerConnection con, int errNum, int databas return "40001"; // deadlock detected case 2627: return "23000"; // DPM 4.04. Primary key violation + default: + return "S000" + databaseState; } - return "S000" + databaseState; } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc43.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc43.java index 4c7f2db6f5..9279df2ab2 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc43.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc43.java @@ -20,7 +20,9 @@ final class DriverJDBCVersion { static final int major = 4; static final int minor = 3; - static final void checkSupportsJDBC43() {} + static final void checkSupportsJDBC43() { + return; + } static final void throwBatchUpdateException(SQLServerException lastError, long[] updateCounts) throws BatchUpdateException { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerLob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerLob.java index 0fdee293db..41eb1b5c61 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerLob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerLob.java @@ -4,10 +4,16 @@ */ package com.microsoft.sqlserver.jdbc; +import java.io.Serializable; import java.sql.SQLException; -abstract class SQLServerLob { +abstract class SQLServerLob implements Serializable{ + + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = -6444654924359581662L; /** * Provides functionality for the result set to maintain blobs it has created. diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java index fac688f1b2..89ecc10a36 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java @@ -6,11 +6,6 @@ package com.microsoft.sqlserver.jdbc; import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.io.UnsupportedEncodingException; -import java.io.Writer; -import java.sql.Clob; import java.sql.NClob; import java.sql.SQLException; import java.util.logging.Logger; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerParameterMetaData.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerParameterMetaData.java index 9e1321a122..0f4bf01563 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerParameterMetaData.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerParameterMetaData.java @@ -555,7 +555,6 @@ private void checkClosed() throws SQLServerException { * the procedure name * @throws SQLServerException */ - @SuppressWarnings("serial") SQLServerParameterMetaData(SQLServerPreparedStatement st, String sProcString) throws SQLServerException { assert null != st; @@ -805,8 +804,7 @@ public int getParameterMode(int param) throws SQLServerException { @Override public int getParameterType(int param) throws SQLServerException { checkClosed(); - - int parameterType; + int parameterType = 0; try { if (procMetadata == null) { // PreparedStatement. @@ -814,23 +812,27 @@ public int getParameterType(int param) throws SQLServerException { parameterType = queryMetaMap.get(param).parameterType; } else { Map info = getParameterInfo(param); - parameterType = (null != info) ? (short) info.get(DATA_TYPE) : null; + if (null != info) { + parameterType = (short) info.get(DATA_TYPE); + } } - - switch (parameterType) { - case microsoft.sql.Types.DATETIME: - case microsoft.sql.Types.SMALLDATETIME: - parameterType = SSType.DATETIME2.getJDBCType().asJavaSqlType(); - break; - case microsoft.sql.Types.MONEY: - case microsoft.sql.Types.SMALLMONEY: - parameterType = SSType.DECIMAL.getJDBCType().asJavaSqlType(); - break; - case microsoft.sql.Types.GUID: - parameterType = SSType.CHAR.getJDBCType().asJavaSqlType(); - break; + if (0 != parameterType) { + switch (parameterType) { + case microsoft.sql.Types.DATETIME: + case microsoft.sql.Types.SMALLDATETIME: + parameterType = SSType.DATETIME2.getJDBCType().asJavaSqlType(); + break; + case microsoft.sql.Types.MONEY: + case microsoft.sql.Types.SMALLMONEY: + parameterType = SSType.DECIMAL.getJDBCType().asJavaSqlType(); + break; + case microsoft.sql.Types.GUID: + parameterType = SSType.CHAR.getJDBCType().asJavaSqlType(); + break; + default: + break; + } } - return parameterType; } catch (SQLException e) { SQLServerException.makeFromDriverError(con, stmtParent, e.toString(), null, false); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPooledConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPooledConnection.java index 31ca83aa8e..cf55d0cc77 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPooledConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPooledConnection.java @@ -5,6 +5,7 @@ package com.microsoft.sqlserver.jdbc; +import java.io.Serializable; import java.sql.Connection; import java.sql.SQLException; import java.util.Vector; @@ -22,7 +23,12 @@ * to manage the connection pool. Applications typically do not instantiate these connections directly. */ -public class SQLServerPooledConnection implements PooledConnection { +public class SQLServerPooledConnection implements PooledConnection, Serializable { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 3492921646187451164L; + private final Vector listeners; private SQLServerDataSource factoryDataSource; private SQLServerConnection physicalConnection; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java index 56b7a611ff..adf3be3dae 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java @@ -47,6 +47,11 @@ * interfaces javadoc for those details. */ public class SQLServerPreparedStatement extends SQLServerStatement implements ISQLServerPreparedStatement { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = -6292257029445685221L; + /** Flag to indicate that it is an internal query to retrieve encryption metadata. */ boolean isInternalEncryptionQuery = false; @@ -269,6 +274,11 @@ else if (connection.isPreparedStatementUnprepareBatchingEnabled()) { loggerExternal.finer(this + ": Closing PreparedHandle:" + handleToClose); final class PreparedHandleClose extends UninterruptableTDSCommand { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = -8944096664249990764L; + PreparedHandleClose() { super("closePreparedHandle"); } @@ -496,6 +506,10 @@ public boolean execute() throws SQLServerException, SQLTimeoutException { } private final class PrepStmtExecCmd extends TDSCommand { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 4098801171124750861L; private final SQLServerPreparedStatement stmt; PrepStmtExecCmd(SQLServerPreparedStatement stmt, int executeMethod) { @@ -2642,6 +2656,10 @@ private boolean checkSQLLength(int length) { } private final class PrepStmtBatchExecCmd extends TDSCommand { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 5225705304799552318L; private final SQLServerPreparedStatement stmt; SQLServerException batchException; long updateCounts[]; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java index caa6b4e683..f17289f527 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java @@ -16,7 +16,6 @@ import java.sql.NClob; import java.sql.Ref; import java.sql.ResultSet; -import java.sql.ResultSetMetaData; import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; @@ -88,7 +87,7 @@ String getClassNameLogging() { private final int maxRows; /** the meta data for this result set */ - private ResultSetMetaData metaData; + private SQLServerResultSetMetaData metaData; /** is the result set close */ private boolean isClosed = false; @@ -135,7 +134,7 @@ final void setCurrentRowType(RowType rowType) { * Currently active Stream Note only one stream can be active at a time, JDBC spec calls for the streams to be * closed when a column or row move occurs */ - private Closeable activeStream; + private transient Closeable activeStream; private SQLServerLob activeLOB; /** @@ -737,11 +736,10 @@ private void initializeNullCompressedColumns() throws SQLServerException { continue; } - for (int bitNo = 0; bitNo < 8 && columnNo < this.columns.length; bitNo++) { + for (int bitNo = 0; bitNo < 8 && columnNo < this.columns.length; bitNo++, columnNo++) { if ((byteValue & (1 << bitNo)) != 0) { this.columns[columnNo].initFromCompressedNull(); } - columnNo++; } } areNullCompressedColumnsInitialized = true; @@ -1598,67 +1596,68 @@ private void moveAbsolute(int row) throws SQLServerException { case -1: moveLast(); return; - } - - // Depending on how much we know about the result set, an absolute move - // can be translated into a relative move. The advantage to doing this - // is that we gain the benefit of using the scroll window, which reduces - // calls to the server when absolute moves can translate to small moves - // relative to the current row. - if (hasCurrentRow()) { - assert currentRow >= 1; - // If the absolute move is from the start of the result set (+ve rows) - // then we can easily express it as a relative (to the current row) move: - // the amount to move is just the difference between the current row and - // the target absolute row. - if (row > 0) { - moveRelative(row - currentRow); - return; - } + default: + // Depending on how much we know about the result set, an absolute move + // can be translated into a relative move. The advantage to doing this + // is that we gain the benefit of using the scroll window, which reduces + // calls to the server when absolute moves can translate to small moves + // relative to the current row. + if (hasCurrentRow()) { + assert currentRow >= 1; + + // If the absolute move is from the start of the result set (+ve rows) + // then we can easily express it as a relative (to the current row) move: + // the amount to move is just the difference between the current row and + // the target absolute row. + if (row > 0) { + moveRelative(row - currentRow); + return; + } - // If the absolute move is from the end of the result set (-ve rows) - // then we also need to know how many rows are in the result set. - // If we do then we can convert to an absolute move from the start - // of the result set, and apply the logic above. - if (UNKNOWN_ROW_COUNT != rowCount) { - assert row < 0; - moveRelative((rowCount + row + 1) - currentRow); - return; - } - } + // If the absolute move is from the end of the result set (-ve rows) + // then we also need to know how many rows are in the result set. + // If we do then we can convert to an absolute move from the start + // of the result set, and apply the logic above. + if (UNKNOWN_ROW_COUNT != rowCount) { + assert row < 0; + moveRelative((rowCount + row + 1) - currentRow); + return; + } + } - // Ok, so there's no chance of a relative move. In other words, the current - // position may be before the first row or after the last row. Or perhaps - // it's an absolute move from the end of the result set and we don't know - // how many rows there are yet (can happen with a scrollable client cursor). - // In that case, we need to move absolutely. + // Ok, so there's no chance of a relative move. In other words, the current + // position may be before the first row or after the last row. Or perhaps + // it's an absolute move from the end of the result set and we don't know + // how many rows there are yet (can happen with a scrollable client cursor). + // In that case, we need to move absolutely. - // Try to fetch a block of up to fetchSize rows starting at row row. - if (0 == serverCursorId) { - currentRow = clientMoveAbsolute(row); - return; - } + // Try to fetch a block of up to fetchSize rows starting at row row. + if (0 == serverCursorId) { + currentRow = clientMoveAbsolute(row); + return; + } - doServerFetch(TDS.FETCH_ABSOLUTE, row, fetchSize); + doServerFetch(TDS.FETCH_ABSOLUTE, row, fetchSize); - // If the absolute server fetch didn't land somewhere on the result set - // then it's either before the first row or after the last row. - if (!scrollWindow.next(this)) { - currentRow = (row < 0) ? BEFORE_FIRST_ROW : AFTER_LAST_ROW; - return; - } + // If the absolute server fetch didn't land somewhere on the result set + // then it's either before the first row or after the last row. + if (!scrollWindow.next(this)) { + currentRow = (row < 0) ? BEFORE_FIRST_ROW : AFTER_LAST_ROW; + return; + } - // The absolute server fetch landed somewhere on the result set, - // so update the current row to reflect the new position. - if (row > 0) { - // The current row is just the row to which we moved. - currentRow = row; - } else { - // Absolute fetch with -ve row is relative to the end of the result set. - assert row < 0; - assert rowCount + row + 1 >= 1; - currentRow = rowCount + row + 1; + // The absolute server fetch landed somewhere on the result set, + // so update the current row to reflect the new position. + if (row > 0) { + // The current row is just the row to which we moved. + currentRow = row; + } else { + // Absolute fetch with -ve row is relative to the end of the result set. + assert row < 0; + assert rowCount + row + 1 >= 1; + currentRow = rowCount + row + 1; + } } } @@ -4634,6 +4633,10 @@ public void insertRow() throws SQLException { } final class InsertRowRPC extends TDSCommand { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 1L; final String tableName; InsertRowRPC(String tableName) { @@ -4736,6 +4739,11 @@ public void updateRow() throws SQLException { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); } final class UpdateRowRPC extends TDSCommand { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 1L; + UpdateRowRPC() { super("UpdateRowRPC", 0, 0); } @@ -4816,6 +4824,11 @@ public void deleteRow() throws SQLException { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); } final class DeleteRowRPC extends TDSCommand { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 1L; + DeleteRowRPC() { super("DeleteRowRPC", 0, 0); } @@ -5421,6 +5434,10 @@ final RowType nextRow() throws SQLServerException { } private final class CursorFetchCommand extends TDSCommand { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 1L; private final int serverCursorId; private int fetchType; private int startRow; @@ -5600,6 +5617,11 @@ final void closeServerCursor() { logger.finer(toString() + " Closing cursor:" + serverCursorId); final class CloseServerCursorCommand extends UninterruptableTDSCommand { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 1L; + CloseServerCursorCommand() { super("closeServerCursor"); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSetMetaData.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSetMetaData.java index 5f36d2d75f..d9e4125159 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSetMetaData.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSetMetaData.java @@ -17,6 +17,11 @@ * interfaces javadoc for those details. */ public final class SQLServerResultSetMetaData implements ISQLServerResultSetMetaData { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = -5747558730471411712L; + private SQLServerConnection con; private final SQLServerResultSet rs; static final private java.util.logging.Logger logger = java.util.logging.Logger diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSavepoint.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSavepoint.java index 94679be972..fa6552d867 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSavepoint.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSavepoint.java @@ -17,6 +17,11 @@ */ public final class SQLServerSavepoint implements ISQLServerSavepoint { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 1857415943191289598L; + private final String sName; private final int nId; private final SQLServerConnection con; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSpatialDatatype.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSpatialDatatype.java index 672982ce98..091fd206c0 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSpatialDatatype.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSpatialDatatype.java @@ -1092,7 +1092,7 @@ protected void readSegmentWkt(int segmentType, boolean isFirstIteration) throws if (currentWktPos < wkt.length() && wkt.charAt(currentWktPos) != ')') { if (segmentType == SEGMENT_FIRST_ARC || segmentType == SEGMENT_ARC) { readSegmentWkt(SEGMENT_ARC, false); - } else if (segmentType == SEGMENT_FIRST_LINE | segmentType == SEGMENT_LINE) { + } else if (segmentType == SEGMENT_FIRST_LINE || segmentType == SEGMENT_LINE) { readSegmentWkt(SEGMENT_LINE, false); } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java index 39ab2702f4..3db1126d20 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java @@ -50,6 +50,11 @@ * interfaces javadoc for those details. */ public class SQLServerStatement implements ISQLServerStatement { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = -4421134713913331507L; + final static char LEFT_CURLY_BRACKET = 123; final static char RIGHT_CURLY_BRACKET = 125; @@ -742,6 +747,10 @@ public boolean execute(String sql) throws SQLServerException, SQLTimeoutExceptio } private final class StmtExecCmd extends TDSCommand { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 4534132352812876292L; final SQLServerStatement stmt; final String sql; final int executeMethod; @@ -877,6 +886,10 @@ final void doExecuteStatement(StmtExecCmd execCmd) throws SQLServerException { } private final class StmtBatchExecCmd extends TDSCommand { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = -4621631860790243331L; final SQLServerStatement stmt; StmtBatchExecCmd(SQLServerStatement stmt) { @@ -1399,22 +1412,16 @@ final boolean isResultSet() { } boolean onColMetaData(TDSReader tdsReader) throws SQLServerException { - // If we have an update count from a previous command that we haven't - // acknowledged because we didn't know at the time whether it was - // the undesired result from a trigger, we now know that it wasn't, - // so return it. - if (null != stmtDoneToken) - return false; - - // If we encountered an ERROR token before hitting this COLMETADATA token, - // without any intervening DONE token (indicating an error result), then - // act as if that had been the case and drop out to propagate the error - // up as an SQLException. - if (null != getDatabaseError()) - return false; - - // Otherwise, column metadata indicates the start of a ResultSet - isResultSet = true; + /* + * If we have an update count from a previous command that we haven't acknowledged because we didn't + * know at the time whether it was the undesired result from a trigger, and if we did not encounter an + * ERROR token before hitting this COLMETADATA token, with any intervening DONE token (does not indicate + * an error result), then go ahead. + */ + if (null == stmtDoneToken && null == getDatabaseError()) { + // If both conditions are true, column metadata indicates the start of a ResultSet + isResultSet = true; + } return false; } @@ -1947,9 +1954,9 @@ final int getResultSetScrollOpt() { return scrollOpt | TDS.SCROLLOPT_STATIC; // Other (invalid) values were caught by the constructor. + default: + return 0; } - - return 0; } final int getResultSetCCOpt() { @@ -1968,9 +1975,9 @@ final int getResultSetCCOpt() { return TDS.CCOPT_OPTIMISTIC_CCVAL | TDS.CCOPT_UPDT_IN_PLACE | TDS.CCOPT_ALLOW_DIRECT; // Other (invalid) values were caught by the constructor. + default: + return 0; } - - return 0; } private void doExecuteCursored(StmtExecCmd execCmd, String sql) throws SQLServerException { @@ -2643,15 +2650,12 @@ String translate(String sql) throws SQLServerException { } } - // LIMIT escape is introduced in JDBC 4.1. Make sure versions lower than 4.1 do not have this feature. - if (((4 == DriverJDBCVersion.major) && (1 <= DriverJDBCVersion.minor)) || (4 < DriverJDBCVersion.major)) { - // Search for LIMIT escape syntax. Do further processing if present. - matcher = limitSyntaxGeneric.matcher(sql); - if (matcher.find()) { - StringBuffer sqlbuf = new StringBuffer(sql); - translateLimit(sqlbuf, 0, '\0'); - return sqlbuf.toString(); - } + // Search for LIMIT escape syntax. Do further processing if present. + matcher = limitSyntaxGeneric.matcher(sql); + if (matcher.find()) { + StringBuffer sqlbuf = new StringBuffer(sql); + translateLimit(sqlbuf, 0, '\0'); + return sqlbuf.toString(); } // 'sql' is modified if CALL or LIMIT escape sequence is present, Otherwise pass it straight through. diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAConnection.java index bfb18780ca..c2664412ed 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAConnection.java @@ -19,6 +19,11 @@ */ public final class SQLServerXAConnection extends SQLServerPooledConnection implements XAConnection { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = -8154621218821899459L; + // NB These instances are not used by applications, only by the app server who is // providing the connection pool and transactional processing to the application. // That app server is the one who should restrict commit/rollback on the connections diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ScrollWindow.java b/src/main/java/com/microsoft/sqlserver/jdbc/ScrollWindow.java index 3ae4f6053f..2c55eccbb1 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ScrollWindow.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ScrollWindow.java @@ -5,6 +5,9 @@ package com.microsoft.sqlserver.jdbc; +import java.io.Serializable; + + /** * ScrollWindow provides an efficient way to scroll around within a limited number of rows, typically the ResultSet * fetch size, by saving and restoring row state, such as starting point in the response and updated/deleted status, on @@ -13,7 +16,12 @@ * Without a scroll window, scrolling backward through a result set would be very costly, requiring reindexing the fetch * buffer up to row N-1 for each move to the previous row. */ -final class ScrollWindow { +final class ScrollWindow implements Serializable { + /** + * Always update serialVersionUID when prompted. + */ + private static final long serialVersionUID = 3028807583846251111L; + /** Set of marks for the rows in the window */ private TDSReaderMark[] rowMark; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SharedTimer.java b/src/main/java/com/microsoft/sqlserver/jdbc/SharedTimer.java index 57cc70dfa3..1c593119ce 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SharedTimer.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SharedTimer.java @@ -4,13 +4,19 @@ */ package com.microsoft.sqlserver.jdbc; +import java.io.Serializable; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; -class SharedTimer { +class SharedTimer implements Serializable { + /** + * Always update serialVersionUID when prompted + */ + private static final long serialVersionUID = -4069361613863955760L; + static final String CORE_THREAD_PREFIX = "mssql-jdbc-shared-timer-core-"; private static final AtomicLong CORE_THREAD_COUNTER = new AtomicLong(); private static SharedTimer instance; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SimpleInputStream.java b/src/main/java/com/microsoft/sqlserver/jdbc/SimpleInputStream.java index cce77c4689..48d1431a7a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SimpleInputStream.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SimpleInputStream.java @@ -24,12 +24,10 @@ abstract class BaseInputStream extends InputStream { // Flag indicating whether the stream consumes and discards data as it reads it final boolean isStreaming; - + // Stated length of the payload int payloadLength; - /** Generate the logging ID */ - private String parentLoggingInfo = ""; private static final AtomicInteger lastLoggingID = new AtomicInteger(0); private static int nextLoggingID() { @@ -47,7 +45,6 @@ final public String toString() { } final void setLoggingInfo(String info) { - parentLoggingInfo = info; if (logger.isLoggable(java.util.logging.Level.FINER)) logger.finer(toString()); } @@ -159,7 +156,7 @@ public void close() throws IOException { // Discard the remainder of the stream, positioning the TDSReader // at the next item in the TDS response. Once the stream is closed, // it can no longer access the discarded response data. - skip((long)(payloadLength) - (long)(streamPos)); + skip((long) (payloadLength) - (long) (streamPos)); closeHelper(); if (logger.isLoggable(java.util.logging.Level.FINER)) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SqlFedAuthToken.java b/src/main/java/com/microsoft/sqlserver/jdbc/SqlFedAuthToken.java index 21aedbb8ec..a2e9e08ed8 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SqlFedAuthToken.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SqlFedAuthToken.java @@ -5,10 +5,16 @@ package com.microsoft.sqlserver.jdbc; +import java.io.Serializable; import java.util.Date; -class SqlFedAuthToken { +class SqlFedAuthToken implements Serializable { + /** + * Always update serialVersionUID when prompted + */ + private static final long serialVersionUID = -1343105491285383937L; + final Date expiresOn; final String accessToken; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/StreamRetValue.java b/src/main/java/com/microsoft/sqlserver/jdbc/StreamRetValue.java index 095301d515..20427c1f8b 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/StreamRetValue.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/StreamRetValue.java @@ -9,6 +9,7 @@ * StreamRetValue represents a TDS return value. */ final class StreamRetValue extends StreamPacket { + @SuppressWarnings("unused") private String paramName; /* @@ -25,6 +26,7 @@ final int getOrdinalOrLength() { * Status: 0x01 if the return value is an OUTPUT parameter of a stored procedure 0x02 if the return value is from a * User Defined Function */ + @SuppressWarnings("unused") private int status; StreamRetValue() { @@ -41,7 +43,6 @@ void setFromTDS(TDSReader tdsReader) throws SQLServerException { CryptoMetadata getCryptoMetadata(TDSReader tdsReader) throws SQLServerException { CryptoMetadata cryptoMeta = (new StreamColumns()).readCryptoMetadata(tdsReader); - return cryptoMeta; } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/UDTTDSHeader.java b/src/main/java/com/microsoft/sqlserver/jdbc/UDTTDSHeader.java index 4d848aa0f2..5b6ebd88fa 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/UDTTDSHeader.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/UDTTDSHeader.java @@ -22,9 +22,12 @@ final class UDTTDSHeader { private final int maxLen; // MaxLen read from UDT type (not used when writing). + @SuppressWarnings("unused") private final String databaseName; // Database name where UDT type resides. + @SuppressWarnings("unused") private final String schemaName; // Schema where UDT resides. private final String typeName; // Type name of UDT. + @SuppressWarnings("unused") private final String assemblyQualifiedName; // Assembly qualified name of UDT. UDTTDSHeader(TDSReader tdsReader) throws SQLServerException { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/Util.java b/src/main/java/com/microsoft/sqlserver/jdbc/Util.java index 52d7adff0f..86b818ef32 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/Util.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/Util.java @@ -150,8 +150,8 @@ static void writeShortBigEndian(short value, byte valueBytes[], int offset) { } static int readIntBigEndian(byte data[], int nOffset) { - return ((data[nOffset + 3] & 0xFF) << 0) | ((data[nOffset + 2] & 0xFF) << 8) | ((data[nOffset + 1] & 0xFF) << 16) - | ((data[nOffset + 0] & 0xFF) << 24); + return ((data[nOffset + 3] & 0xFF) << 0) | ((data[nOffset + 2] & 0xFF) << 8) + | ((data[nOffset + 1] & 0xFF) << 16) | ((data[nOffset + 0] & 0xFF) << 24); } static void writeInt(int value, byte valueBytes[], int offset) { @@ -833,6 +833,8 @@ static void validateMoneyRange(BigDecimal bd, JDBCType jdbcType) throws SQLServe return; } break; + default: + break; } MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_valueOutOfRange")); Object[] msgArgs = {jdbcType}; @@ -863,6 +865,8 @@ static int getValueLengthBaseOnJavaType(Object value, JavaType javaType, Integer break; } break; + default: + break; } switch (javaType) { @@ -878,13 +882,10 @@ static int getValueLengthBaseOnJavaType(Object value, JavaType javaType, Integer } else { return ((null == value) ? 0 : ((String) value).length()); } - case BYTEARRAY: return ((null == value) ? 0 : ((byte[]) value).length); - case BIGDECIMAL: int length; - if (null == precision) { if (null == value) { length = 0; @@ -914,22 +915,19 @@ else if (("" + value).contains("E")) { } else { length = precision; } - return length; - case TIMESTAMP: case TIME: case DATETIMEOFFSET: return ((null == scale) ? TDS.MAX_FRACTIONAL_SECONDS_SCALE : scale); - case CLOB: return ((null == value) ? 0 : (DataTypes.NTEXT_MAX_CHARS * 2)); - case NCLOB: case READER: return ((null == value) ? 0 : DataTypes.NTEXT_MAX_CHARS); + default: + return 0; } - return 0; } // If the access token is expiring within next 10 minutes, lets just re-create a token for this connection attempt. diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/XMLTDSHeader.java b/src/main/java/com/microsoft/sqlserver/jdbc/XMLTDSHeader.java index efcb52a48a..f056479ff5 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/XMLTDSHeader.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/XMLTDSHeader.java @@ -23,8 +23,11 @@ */ final class XMLTDSHeader { + @SuppressWarnings("unused") private final String databaseName; // Database name where XML schema resides. + @SuppressWarnings("unused") private final String owningSchema; // Owner of XML schema (like dbo for example). + @SuppressWarnings("unused") private final String xmlSchemaCollection; // Name of XML schema collection. XMLTDSHeader(TDSReader tdsReader) throws SQLServerException { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/dataclassification/ColumnSensitivity.java b/src/main/java/com/microsoft/sqlserver/jdbc/dataclassification/ColumnSensitivity.java index 5bc4cab721..61c0fc4221 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/dataclassification/ColumnSensitivity.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/dataclassification/ColumnSensitivity.java @@ -22,7 +22,7 @@ public class ColumnSensitivity { * List of sensitivity properties as received from SQL Server */ public ColumnSensitivity(List sensitivityProperties) { - this.sensitivityProperties = new ArrayList(sensitivityProperties); + this.sensitivityProperties = new ArrayList<>(sensitivityProperties); } /** diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/dataclassification/SensitivityClassification.java b/src/main/java/com/microsoft/sqlserver/jdbc/dataclassification/SensitivityClassification.java index 7acffa5148..5eb212d457 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/dataclassification/SensitivityClassification.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/dataclassification/SensitivityClassification.java @@ -34,9 +34,9 @@ public class SensitivityClassification { */ public SensitivityClassification(List