iface) throws SQLException {
return t;
}
+
// Returns unique id for each DataSource instance.
private static int nextDataSourceID() {
return baseDataSourceID.incrementAndGet();
diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSourceObjectFactory.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSourceObjectFactory.java
index 761eb26ae..6518d7057 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSourceObjectFactory.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSourceObjectFactory.java
@@ -8,6 +8,7 @@
package com.microsoft.sqlserver.jdbc;
+import java.lang.reflect.InvocationTargetException;
import java.util.Hashtable;
import javax.naming.Context;
@@ -59,7 +60,7 @@ public Object getObjectInstance(Object ref,
// Create class instance and initialize using reference.
Class> dataSourceClass = Class.forName(className);
- Object dataSourceClassInstance = dataSourceClass.newInstance();
+ Object dataSourceClassInstance = dataSourceClass.getDeclaredConstructor().newInstance();
// If this class we created does not cast to SQLServerDataSource, then caller
// passed in the wrong reference to our factory.
@@ -79,6 +80,18 @@ public Object getObjectInstance(Object ref,
catch (IllegalAccessException e) {
SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_invalidDataSourceReference"), null, true);
}
+ catch (IllegalArgumentException e) {
+ SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_invalidDataSourceReference"), null, true);
+ }
+ catch (InvocationTargetException e) {
+ SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_invalidDataSourceReference"), null, true);
+ }
+ catch (NoSuchMethodException e) {
+ SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_invalidDataSourceReference"), null, true);
+ }
+ catch (SecurityException e) {
+ SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_invalidDataSourceReference"), null, true);
+ }
// no chance of getting here but to keep the compiler happy
return null;
diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java
index d0ac93479..92ab65877 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java
@@ -144,90 +144,90 @@ private void checkClosed() throws SQLServerException {
}
}
- private final static String ASC_OR_DESC = "ASC_OR_DESC";
- private final static String ATTR_NAME = "ATTR_NAME";
- private final static String ATTR_TYPE_NAME = "ATTR_TYPE_NAME";
- private final static String ATTR_SIZE = "ATTR_SIZE";
- private final static String ATTR_DEF = "ATTR_DEF";
- private final static String BASE_TYPE = "BASE_TYPE";
- private final static String BUFFER_LENGTH = "BUFFER_LENGTH";
- private final static String CARDINALITY = "CARDINALITY";
- private final static String CHAR_OCTET_LENGTH = "CHAR_OCTET_LENGTH";
- private final static String CLASS_NAME = "CLASS_NAME";
- private final static String COLUMN_DEF = "COLUMN_DEF";
- private final static String COLUMN_NAME = "COLUMN_NAME";
- private final static String COLUMN_SIZE = "COLUMN_SIZE";
- private final static String COLUMN_TYPE = "COLUMN_TYPE";
- private final static String DATA_TYPE = "DATA_TYPE";
- private final static String DECIMAL_DIGITS = "DECIMAL_DIGITS";
- private final static String DEFERRABILITY = "DEFERRABILITY";
- private final static String DELETE_RULE = "DELETE_RULE";
- private final static String FILTER_CONDITION = "FILTER_CONDITION";
- private final static String FK_NAME = "FK_NAME";
- private final static String FKCOLUMN_NAME = "FKCOLUMN_NAME";
- private final static String FKTABLE_CAT = "FKTABLE_CAT";
- private final static String FKTABLE_NAME = "FKTABLE_NAME";
- private final static String FKTABLE_SCHEM = "FKTABLE_SCHEM";
- private final static String GRANTEE = "GRANTEE";
- private final static String GRANTOR = "GRANTOR";
- private final static String INDEX_NAME = "INDEX_NAME";
- private final static String INDEX_QUALIFIER = "INDEX_QUALIFIER";
- private final static String IS_GRANTABLE = "IS_GRANTABLE";
- private final static String IS_NULLABLE = "IS_NULLABLE";
- private final static String KEY_SEQ = "KEY_SEQ";
- private final static String LENGTH = "LENGTH";
- private final static String NON_UNIQUE = "NON_UNIQUE";
- private final static String NULLABLE = "NULLABLE";
- private final static String NUM_INPUT_PARAMS = "NUM_INPUT_PARAMS";
- private final static String NUM_OUTPUT_PARAMS = "NUM_OUTPUT_PARAMS";
- private final static String NUM_PREC_RADIX = "NUM_PREC_RADIX";
- private final static String NUM_RESULT_SETS = "NUM_RESULT_SETS";
- private final static String ORDINAL_POSITION = "ORDINAL_POSITION";
- private final static String PAGES = "PAGES";
- private final static String PK_NAME = "PK_NAME";
- private final static String PKCOLUMN_NAME = "PKCOLUMN_NAME";
- private final static String PKTABLE_CAT = "PKTABLE_CAT";
- private final static String PKTABLE_NAME = "PKTABLE_NAME";
- private final static String PKTABLE_SCHEM = "PKTABLE_SCHEM";
- private final static String PRECISION = "PRECISION";
- private final static String PRIVILEGE = "PRIVILEGE";
- private final static String PROCEDURE_CAT = "PROCEDURE_CAT";
- private final static String PROCEDURE_NAME = "PROCEDURE_NAME";
- private final static String PROCEDURE_SCHEM = "PROCEDURE_SCHEM";
- private final static String PROCEDURE_TYPE = "PROCEDURE_TYPE";
- private final static String PSEUDO_COLUMN = "PSEUDO_COLUMN";
- private final static String RADIX = "RADIX";
- private final static String REMARKS = "REMARKS";
- private final static String SCALE = "SCALE";
- private final static String SCOPE = "SCOPE";
- private final static String SCOPE_CATALOG = "SCOPE_CATALOG";
- private final static String SCOPE_SCHEMA = "SCOPE_SCHEMA";
- private final static String SCOPE_TABLE = "SCOPE_TABLE";
- private final static String SOURCE_DATA_TYPE = "SOURCE_DATA_TYPE";
- private final static String SQL_DATA_TYPE = "SQL_DATA_TYPE";
- private final static String SQL_DATETIME_SUB = "SQL_DATETIME_SUB";
- private final static String SS_DATA_TYPE = "SS_DATA_TYPE";
- private final static String SUPERTABLE_NAME = "SUPERTABLE_NAME";
- private final static String SUPERTYPE_CAT = "SUPERTYPE_CAT";
- private final static String SUPERTYPE_NAME = "SUPERTYPE_NAME";
- private final static String SUPERTYPE_SCHEM = "SUPERTYPE_SCHEM";
- private final static String TABLE_CAT = "TABLE_CAT";
- private final static String TABLE_NAME = "TABLE_NAME";
- private final static String TABLE_SCHEM = "TABLE_SCHEM";
- private final static String TABLE_TYPE = "TABLE_TYPE";
- private final static String TYPE = "TYPE";
- private final static String TYPE_CAT = "TYPE_CAT";
- private final static String TYPE_NAME = "TYPE_NAME";
- private final static String TYPE_SCHEM = "TYPE_SCHEM";
- private final static String UPDATE_RULE = "UPDATE_RULE";
- private final static String FUNCTION_CAT = "FUNCTION_CAT";
- private final static String FUNCTION_NAME = "FUNCTION_NAME";
- private final static String FUNCTION_SCHEM = "FUNCTION_SCHEM";
- private final static String FUNCTION_TYPE = "FUNCTION_TYPE";
- private final static String SS_IS_SPARSE = "SS_IS_SPARSE";
- private final static String SS_IS_COLUMN_SET = "SS_IS_COLUMN_SET";
- private final static String SS_IS_COMPUTED = "SS_IS_COMPUTED";
- private final static String IS_AUTOINCREMENT = "IS_AUTOINCREMENT";
+ private static final String ASC_OR_DESC = "ASC_OR_DESC";
+ private static final String ATTR_NAME = "ATTR_NAME";
+ private static final String ATTR_TYPE_NAME = "ATTR_TYPE_NAME";
+ private static final String ATTR_SIZE = "ATTR_SIZE";
+ private static final String ATTR_DEF = "ATTR_DEF";
+ private static final String BASE_TYPE = "BASE_TYPE";
+ private static final String BUFFER_LENGTH = "BUFFER_LENGTH";
+ private static final String CARDINALITY = "CARDINALITY";
+ private static final String CHAR_OCTET_LENGTH = "CHAR_OCTET_LENGTH";
+ private static final String CLASS_NAME = "CLASS_NAME";
+ private static final String COLUMN_DEF = "COLUMN_DEF";
+ private static final String COLUMN_NAME = "COLUMN_NAME";
+ private static final String COLUMN_SIZE = "COLUMN_SIZE";
+ private static final String COLUMN_TYPE = "COLUMN_TYPE";
+ private static final String DATA_TYPE = "DATA_TYPE";
+ private static final String DECIMAL_DIGITS = "DECIMAL_DIGITS";
+ private static final String DEFERRABILITY = "DEFERRABILITY";
+ private static final String DELETE_RULE = "DELETE_RULE";
+ private static final String FILTER_CONDITION = "FILTER_CONDITION";
+ private static final String FK_NAME = "FK_NAME";
+ private static final String FKCOLUMN_NAME = "FKCOLUMN_NAME";
+ private static final String FKTABLE_CAT = "FKTABLE_CAT";
+ private static final String FKTABLE_NAME = "FKTABLE_NAME";
+ private static final String FKTABLE_SCHEM = "FKTABLE_SCHEM";
+ private static final String GRANTEE = "GRANTEE";
+ private static final String GRANTOR = "GRANTOR";
+ private static final String INDEX_NAME = "INDEX_NAME";
+ private static final String INDEX_QUALIFIER = "INDEX_QUALIFIER";
+ private static final String IS_GRANTABLE = "IS_GRANTABLE";
+ private static final String IS_NULLABLE = "IS_NULLABLE";
+ private static final String KEY_SEQ = "KEY_SEQ";
+ private static final String LENGTH = "LENGTH";
+ private static final String NON_UNIQUE = "NON_UNIQUE";
+ private static final String NULLABLE = "NULLABLE";
+ private static final String NUM_INPUT_PARAMS = "NUM_INPUT_PARAMS";
+ private static final String NUM_OUTPUT_PARAMS = "NUM_OUTPUT_PARAMS";
+ private static final String NUM_PREC_RADIX = "NUM_PREC_RADIX";
+ private static final String NUM_RESULT_SETS = "NUM_RESULT_SETS";
+ private static final String ORDINAL_POSITION = "ORDINAL_POSITION";
+ private static final String PAGES = "PAGES";
+ private static final String PK_NAME = "PK_NAME";
+ private static final String PKCOLUMN_NAME = "PKCOLUMN_NAME";
+ private static final String PKTABLE_CAT = "PKTABLE_CAT";
+ private static final String PKTABLE_NAME = "PKTABLE_NAME";
+ private static final String PKTABLE_SCHEM = "PKTABLE_SCHEM";
+ private static final String PRECISION = "PRECISION";
+ private static final String PRIVILEGE = "PRIVILEGE";
+ private static final String PROCEDURE_CAT = "PROCEDURE_CAT";
+ private static final String PROCEDURE_NAME = "PROCEDURE_NAME";
+ private static final String PROCEDURE_SCHEM = "PROCEDURE_SCHEM";
+ private static final String PROCEDURE_TYPE = "PROCEDURE_TYPE";
+ private static final String PSEUDO_COLUMN = "PSEUDO_COLUMN";
+ private static final String RADIX = "RADIX";
+ private static final String REMARKS = "REMARKS";
+ private static final String SCALE = "SCALE";
+ private static final String SCOPE = "SCOPE";
+ private static final String SCOPE_CATALOG = "SCOPE_CATALOG";
+ private static final String SCOPE_SCHEMA = "SCOPE_SCHEMA";
+ private static final String SCOPE_TABLE = "SCOPE_TABLE";
+ private static final String SOURCE_DATA_TYPE = "SOURCE_DATA_TYPE";
+ private static final String SQL_DATA_TYPE = "SQL_DATA_TYPE";
+ private static final String SQL_DATETIME_SUB = "SQL_DATETIME_SUB";
+ private static final String SS_DATA_TYPE = "SS_DATA_TYPE";
+ private static final String SUPERTABLE_NAME = "SUPERTABLE_NAME";
+ private static final String SUPERTYPE_CAT = "SUPERTYPE_CAT";
+ private static final String SUPERTYPE_NAME = "SUPERTYPE_NAME";
+ private static final String SUPERTYPE_SCHEM = "SUPERTYPE_SCHEM";
+ private static final String TABLE_CAT = "TABLE_CAT";
+ private static final String TABLE_NAME = "TABLE_NAME";
+ private static final String TABLE_SCHEM = "TABLE_SCHEM";
+ private static final String TABLE_TYPE = "TABLE_TYPE";
+ private static final String TYPE = "TYPE";
+ private static final String TYPE_CAT = "TYPE_CAT";
+ private static final String TYPE_NAME = "TYPE_NAME";
+ private static final String TYPE_SCHEM = "TYPE_SCHEM";
+ private static final String UPDATE_RULE = "UPDATE_RULE";
+ private static final String FUNCTION_CAT = "FUNCTION_CAT";
+ private static final String FUNCTION_NAME = "FUNCTION_NAME";
+ private static final String FUNCTION_SCHEM = "FUNCTION_SCHEM";
+ private static final String FUNCTION_TYPE = "FUNCTION_TYPE";
+ private static final String SS_IS_SPARSE = "SS_IS_SPARSE";
+ private static final String SS_IS_COLUMN_SET = "SS_IS_COLUMN_SET";
+ private static final String SS_IS_COMPUTED = "SS_IS_COMPUTED";
+ private static final String IS_AUTOINCREMENT = "IS_AUTOINCREMENT";
/**
* Make a simple query execute and return the result from it. This is to be used only for internal queries without any user input.
@@ -401,6 +401,13 @@ public boolean supportsRefCursors() throws SQLException {
return false;
}
+ public boolean supportsSharding() throws SQLException {
+ DriverJDBCVersion.checkSupportsJDBC43();
+ checkClosed();
+
+ return false;
+ }
+
/* L0 */ public java.sql.ResultSet getCatalogs() throws SQLServerException {
if (loggerExternal.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) {
loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString());
@@ -421,7 +428,7 @@ public boolean supportsRefCursors() throws SQLException {
return "database";
}
- private final static String[] getColumnPrivilegesColumnNames = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ COLUMN_NAME,
+ private static final String[] getColumnPrivilegesColumnNames = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ COLUMN_NAME,
/* 5 */ GRANTOR, /* 6 */ GRANTEE, /* 7 */ PRIVILEGE, /* 8 */ IS_GRANTABLE};
/* L0 */ public java.sql.ResultSet getColumnPrivileges(String catalog,
@@ -447,7 +454,7 @@ public boolean supportsRefCursors() throws SQLException {
return getResultSetWithProvidedColumnNames(catalog, CallableHandles.SP_COLUMN_PRIVILEGES, arguments, getColumnPrivilegesColumnNames);
}
- private final static String[] getTablesColumnNames = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ TABLE_TYPE,
+ private static final String[] getTablesColumnNames = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ TABLE_TYPE,
/* 5 */ REMARKS};
/* L0 */ public java.sql.ResultSet getTables(String catalog,
@@ -547,14 +554,14 @@ private static String EscapeIDName(String inID) throws SQLServerException {
return outID.toString();
}
- private final static String[] getColumnsColumnNames = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ COLUMN_NAME,
+ private static final String[] getColumnsColumnNames = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ COLUMN_NAME,
/* 5 */ DATA_TYPE, /* 6 */ TYPE_NAME, /* 7 */ COLUMN_SIZE, /* 8 */ BUFFER_LENGTH, /* 9 */ DECIMAL_DIGITS, /* 10 */ NUM_PREC_RADIX,
/* 11 */ NULLABLE, /* 12 */ REMARKS, /* 13 */ COLUMN_DEF, /* 14 */ SQL_DATA_TYPE, /* 15 */ SQL_DATETIME_SUB, /* 16 */ CHAR_OCTET_LENGTH,
/* 17 */ ORDINAL_POSITION, /* 18 */ IS_NULLABLE};
// SQL10 columns not exahustive we only need to set until the one we want to change
// in this case we want to change SS_IS_IDENTITY 22nd column to IS_AUTOINCREMENT
// to be inline with JDBC spec
- private final static String[] getColumnsColumnNamesKatmai = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ COLUMN_NAME,
+ private static final String[] getColumnsColumnNamesKatmai = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ COLUMN_NAME,
/* 5 */ DATA_TYPE, /* 6 */ TYPE_NAME, /* 7 */ COLUMN_SIZE, /* 8 */ BUFFER_LENGTH, /* 9 */ DECIMAL_DIGITS, /* 10 */ NUM_PREC_RADIX,
/* 11 */ NULLABLE, /* 12 */ REMARKS, /* 13 */ COLUMN_DEF, /* 14 */ SQL_DATA_TYPE, /* 15 */ SQL_DATETIME_SUB, /* 16 */ CHAR_OCTET_LENGTH,
/* 17 */ ORDINAL_POSITION, /* 18 */ IS_NULLABLE, /* 20 */ SS_IS_SPARSE, /* 20 */ SS_IS_COLUMN_SET, /* 21 */ SS_IS_COMPUTED,
@@ -612,7 +619,7 @@ private static String EscapeIDName(String inID) throws SQLServerException {
return rs;
}
- private final static String[] getFunctionsColumnNames = {/* 1 */ FUNCTION_CAT, /* 2 */ FUNCTION_SCHEM, /* 3 */ FUNCTION_NAME,
+ private static final String[] getFunctionsColumnNames = {/* 1 */ FUNCTION_CAT, /* 2 */ FUNCTION_SCHEM, /* 3 */ FUNCTION_NAME,
/* 4 */ NUM_INPUT_PARAMS, /* 5 */ NUM_OUTPUT_PARAMS, /* 6 */ NUM_RESULT_SETS, /* 7 */ REMARKS, /* 8 */ FUNCTION_TYPE};
public java.sql.ResultSet getFunctions(String catalog,
@@ -638,7 +645,7 @@ public java.sql.ResultSet getFunctions(String catalog,
return getResultSetWithProvidedColumnNames(catalog, CallableHandles.SP_STORED_PROCEDURES, arguments, getFunctionsColumnNames);
}
- private final static String[] getFunctionsColumnsColumnNames = {/* 1 */ FUNCTION_CAT, /* 2 */ FUNCTION_SCHEM, /* 3 */ FUNCTION_NAME,
+ private static final String[] getFunctionsColumnsColumnNames = {/* 1 */ FUNCTION_CAT, /* 2 */ FUNCTION_SCHEM, /* 3 */ FUNCTION_NAME,
/* 4 */ COLUMN_NAME, /* 5 */ COLUMN_TYPE, /* 6 */ DATA_TYPE, /* 7 */ TYPE_NAME, /* 8 */ PRECISION, /* 9 */ LENGTH, /* 10 */ SCALE,
/* 11 */ RADIX, /* 12 */ NULLABLE, /* 13 */ REMARKS, /* 14 */ COLUMN_DEF, /* 15 */ SQL_DATA_TYPE, /* 16 */ SQL_DATETIME_SUB,
/* 17 */ CHAR_OCTET_LENGTH, /* 18 */ ORDINAL_POSITION, /* 19 */ IS_NULLABLE};
@@ -695,7 +702,7 @@ public java.sql.ResultSet getClientInfoProperties() throws SQLException {
/* 4 */ " cast(NULL as char(1)) as DESCRIPTION " + " where 0 = 1");
}
- private final static String[] getBestRowIdentifierColumnNames = {/* 1 */ SCOPE, /* 2 */ COLUMN_NAME, /* 3 */ DATA_TYPE, /* 4 */ TYPE_NAME,
+ private static final String[] getBestRowIdentifierColumnNames = {/* 1 */ SCOPE, /* 2 */ COLUMN_NAME, /* 3 */ DATA_TYPE, /* 4 */ TYPE_NAME,
/* 5 */ COLUMN_SIZE, /* 6 */ BUFFER_LENGTH, /* 7 */ DECIMAL_DIGITS, /* 8 */ PSEUDO_COLUMN};
/* L0 */ public java.sql.ResultSet getBestRowIdentifier(String catalog,
@@ -735,7 +742,7 @@ public java.sql.ResultSet getClientInfoProperties() throws SQLException {
return rs;
}
- private final static String[] pkfkColumnNames = {/* 1 */ PKTABLE_CAT, /* 2 */ PKTABLE_SCHEM, /* 3 */ PKTABLE_NAME, /* 4 */ PKCOLUMN_NAME,
+ private static final String[] pkfkColumnNames = {/* 1 */ PKTABLE_CAT, /* 2 */ PKTABLE_SCHEM, /* 3 */ PKTABLE_NAME, /* 4 */ PKCOLUMN_NAME,
/* 5 */ FKTABLE_CAT, /* 6 */ FKTABLE_SCHEM, /* 7 */ FKTABLE_NAME, /* 8 */ FKCOLUMN_NAME, /* 9 */ KEY_SEQ, /* 10 */ UPDATE_RULE,
/* 11 */ DELETE_RULE, /* 12 */ FK_NAME, /* 13 */ PK_NAME, /* 14 */ DEFERRABILITY};
@@ -1005,7 +1012,7 @@ private ResultSet getResultSetForForeignKeyInformation(SQLServerResultSet fkeysR
+ foreign_keys_combined_tableName + " order by FKTABLE_QUALIFIER, FKTABLE_OWNER, FKTABLE_NAME, KEY_SEQ");
}
- private final static String[] getIndexInfoColumnNames = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ NON_UNIQUE,
+ private static final String[] getIndexInfoColumnNames = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ NON_UNIQUE,
/* 5 */ INDEX_QUALIFIER, /* 6 */ INDEX_NAME, /* 7 */ TYPE, /* 8 */ ORDINAL_POSITION, /* 9 */ COLUMN_NAME, /* 10 */ ASC_OR_DESC,
/* 11 */ CARDINALITY, /* 12 */ PAGES, /* 13 */ FILTER_CONDITION};
@@ -1159,7 +1166,7 @@ private ResultSet getResultSetForForeignKeyInformation(SQLServerResultSet fkeysR
return "ABS,ACOS,ASIN,ATAN,ATAN2,CEILING,COS,COT,DEGREES,EXP, FLOOR,LOG,LOG10,MOD,PI,POWER,RADIANS,RAND,ROUND,SIGN,SIN,SQRT,TAN,TRUNCATE";
}
- private final static String[] getPrimaryKeysColumnNames = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ COLUMN_NAME,
+ private static final String[] getPrimaryKeysColumnNames = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ COLUMN_NAME,
/* 5 */ KEY_SEQ, /* 6 */ PK_NAME};
/* L0 */ public java.sql.ResultSet getPrimaryKeys(String cat,
@@ -1179,7 +1186,7 @@ private ResultSet getResultSetForForeignKeyInformation(SQLServerResultSet fkeysR
return getResultSetWithProvidedColumnNames(cat, CallableHandles.SP_PKEYS, arguments, getPrimaryKeysColumnNames);
}
- private final static String[] getProcedureColumnsColumnNames = {/* 1 */ PROCEDURE_CAT, /* 2 */ PROCEDURE_SCHEM, /* 3 */ PROCEDURE_NAME,
+ private static final String[] getProcedureColumnsColumnNames = {/* 1 */ PROCEDURE_CAT, /* 2 */ PROCEDURE_SCHEM, /* 3 */ PROCEDURE_NAME,
/* 4 */ COLUMN_NAME, /* 5 */ COLUMN_TYPE, /* 6 */ DATA_TYPE, /* 7 */ TYPE_NAME, /* 8 */ PRECISION, /* 9 */ LENGTH, /* 10 */ SCALE,
/* 11 */ RADIX, /* 12 */ NULLABLE, /* 13 */ REMARKS, /* 14 */ COLUMN_DEF, /* 15 */ SQL_DATA_TYPE, /* 16 */ SQL_DATETIME_SUB,
/* 17 */ CHAR_OCTET_LENGTH, /* 18 */ ORDINAL_POSITION, /* 19 */ IS_NULLABLE};
@@ -1224,7 +1231,7 @@ private ResultSet getResultSetForForeignKeyInformation(SQLServerResultSet fkeysR
return rs;
}
- private final static String[] getProceduresColumnNames = {/* 1 */ PROCEDURE_CAT, /* 2 */ PROCEDURE_SCHEM, /* 3 */ PROCEDURE_NAME,
+ private static final String[] getProceduresColumnNames = {/* 1 */ PROCEDURE_CAT, /* 2 */ PROCEDURE_SCHEM, /* 3 */ PROCEDURE_NAME,
/* 4 */ NUM_INPUT_PARAMS, /* 5 */ NUM_OUTPUT_PARAMS, /* 6 */ NUM_RESULT_SETS, /* 7 */ REMARKS, /* 8 */ PROCEDURE_TYPE};
/* L0 */ public java.sql.ResultSet getProcedures(String catalog,
@@ -1389,7 +1396,7 @@ public java.sql.ResultSet getSchemas(String catalog,
return "DATABASE,IFNULL,USER"; // The functions no reinstated after the CTS certification.
}
- private final static String[] getTablePrivilegesColumnNames = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ GRANTOR,
+ private static final String[] getTablePrivilegesColumnNames = {/* 1 */ TABLE_CAT, /* 2 */ TABLE_SCHEM, /* 3 */ TABLE_NAME, /* 4 */ GRANTOR,
/* 5 */ GRANTEE, /* 6 */ PRIVILEGE, /* 7 */ IS_GRANTABLE};
/* L0 */ public java.sql.ResultSet getTablePrivileges(String catalog,
@@ -1539,7 +1546,7 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) {
return result;
}
- private final static String[] getVersionColumnsColumnNames = {/* 1 */ SCOPE, /* 2 */ COLUMN_NAME, /* 3 */ DATA_TYPE, /* 4 */ TYPE_NAME,
+ private static final String[] getVersionColumnsColumnNames = {/* 1 */ SCOPE, /* 2 */ COLUMN_NAME, /* 3 */ DATA_TYPE, /* 4 */ TYPE_NAME,
/* 5 */ COLUMN_SIZE, /* 6 */ BUFFER_LENGTH, /* 7 */ DECIMAL_DIGITS, /* 8 */ PSEUDO_COLUMN};
/* L0 */ public java.sql.ResultSet getVersionColumns(String catalog,
@@ -1972,10 +1979,7 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) {
case ResultSet.TYPE_SCROLL_INSENSITIVE:
// case SQLServerResultSet.TYPE_SS_SCROLL_STATIC: sensitive synonym
case SQLServerResultSet.TYPE_SS_DIRECT_FORWARD_ONLY:
- if (ResultSet.CONCUR_READ_ONLY == concurrency)
- return true;
- else
- return false;
+ return (ResultSet.CONCUR_READ_ONLY == concurrency);
}
// per spec if we do not know we do not support.
return false;
@@ -1984,60 +1988,48 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) {
/* L0 */ public boolean ownUpdatesAreVisible(int type) throws SQLServerException {
checkClosed();
checkResultType(type);
- if (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type
+ return (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type
|| SQLServerResultSet.TYPE_SCROLL_SENSITIVE == type || SQLServerResultSet.TYPE_SS_SCROLL_KEYSET == type
- || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type)
- return true;
- return false;
+ || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type);
}
/* L0 */ public boolean ownDeletesAreVisible(int type) throws SQLServerException {
checkClosed();
checkResultType(type);
- if (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type
+ return (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type
|| SQLServerResultSet.TYPE_SCROLL_SENSITIVE == type || SQLServerResultSet.TYPE_SS_SCROLL_KEYSET == type
- || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type)
- return true;
- return false;
+ || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type);
}
/* L0 */ public boolean ownInsertsAreVisible(int type) throws SQLServerException {
checkClosed();
checkResultType(type);
- if (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type
+ return (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type
|| SQLServerResultSet.TYPE_SCROLL_SENSITIVE == type || SQLServerResultSet.TYPE_SS_SCROLL_KEYSET == type
- || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type)
- return true;
- return false;
+ || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type);
}
/* L0 */ public boolean othersUpdatesAreVisible(int type) throws SQLServerException {
checkClosed();
checkResultType(type);
- if (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type
+ return (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type
|| SQLServerResultSet.TYPE_SCROLL_SENSITIVE == type || SQLServerResultSet.TYPE_SS_SCROLL_KEYSET == type
- || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type)
- return true;
- return false;
+ || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type);
}
/* L0 */ public boolean othersDeletesAreVisible(int type) throws SQLServerException {
checkClosed();
checkResultType(type);
- if (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type
+ return (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type
|| SQLServerResultSet.TYPE_SCROLL_SENSITIVE == type || SQLServerResultSet.TYPE_SS_SCROLL_KEYSET == type
- || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type)
- return true;
- return false;
+ || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type);
}
/* L0 */ public boolean othersInsertsAreVisible(int type) throws SQLServerException {
checkClosed();
checkResultType(type);
- if (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type
- || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type)
- return true;
- return false;
+ return (type == SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC || SQLServerResultSet.TYPE_FORWARD_ONLY == type
+ || SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY == type);
}
/* L0 */ public boolean updatesAreDetected(int type) throws SQLServerException {
@@ -2049,10 +2041,7 @@ else if (name.equals(SQLServerDriverIntProperty.PORT_NUMBER.toString())) {
/* L0 */ public boolean deletesAreDetected(int type) throws SQLServerException {
checkClosed();
checkResultType(type);
- if (SQLServerResultSet.TYPE_SS_SCROLL_KEYSET == type)
- return true;
- else
- return false;
+ return (SQLServerResultSet.TYPE_SS_SCROLL_KEYSET == type);
}
// Check the result types to make sure the user does not pass a bad value.
@@ -2296,14 +2285,14 @@ public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {
// Filter to convert DATA_TYPE column values from the ODBC types
// returned by SQL Server to their equivalent JDBC types.
final class DataTypeFilter extends IntColumnFilter {
- private final static int ODBC_SQL_GUID = -11;
- private final static int ODBC_SQL_WCHAR = -8;
- private final static int ODBC_SQL_WVARCHAR = -9;
- private final static int ODBC_SQL_WLONGVARCHAR = -10;
- private final static int ODBC_SQL_FLOAT = 6;
- private final static int ODBC_SQL_TIME = -154;
- private final static int ODBC_SQL_XML = -152;
- private final static int ODBC_SQL_UDT = -151;
+ private static final int ODBC_SQL_GUID = -11;
+ private static final int ODBC_SQL_WCHAR = -8;
+ private static final int ODBC_SQL_WVARCHAR = -9;
+ private static final int ODBC_SQL_WLONGVARCHAR = -10;
+ private static final int ODBC_SQL_FLOAT = 6;
+ private static final int ODBC_SQL_TIME = -154;
+ private static final int ODBC_SQL_XML = -152;
+ private static final int ODBC_SQL_UDT = -151;
int oneValueToAnother(int odbcType) {
switch (odbcType) {
diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java
index 1dfeae276..ae4e1fd09 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java
@@ -347,7 +347,7 @@ enum SQLServerDriverBooleanProperty
MULTI_SUBNET_FAILOVER ("multiSubnetFailover", false),
SERVER_NAME_AS_ACE ("serverNameAsACE", false),
SEND_STRING_PARAMETERS_AS_UNICODE ("sendStringParametersAsUnicode", true),
- SEND_TIME_AS_DATETIME ("sendTimeAsDatetime", true),
+ SEND_TIME_AS_DATETIME ("sendTimeAsDatetime", false),
TRANSPARENT_NETWORK_IP_RESOLUTION ("TransparentNetworkIPResolution", true),
TRUST_SERVER_CERTIFICATE ("trustServerCertificate", false),
XOPEN_STATES ("xopenStates", false),
@@ -474,7 +474,9 @@ String getClassNameLogging() {
java.sql.DriverManager.registerDriver(new SQLServerDriver());
}
catch (SQLException e) {
- e.printStackTrace();
+ if (drLogger.isLoggable(Level.FINER) && Util.IsActivityTraceOn()) {
+ drLogger.finer("Error registering driver: " + e);
+ }
}
}
@@ -612,7 +614,12 @@ static String getPropertyOnlyName(String name,
// Merge connectProperties (from URL) and supplied properties from user.
Properties connectProperties = parseAndMergeProperties(Url, suppliedProperties);
if (connectProperties != null) {
- result = new SQLServerConnection(toString());
+ if (Util.use43Wrapper()) {
+ result = new SQLServerConnection43(toString());
+ }
+ else {
+ result = new SQLServerConnection(toString());
+ }
result.connect(connectProperties, null);
}
loggerExternal.exiting(getClassNameLogging(), "connect", result);
@@ -632,7 +639,7 @@ private Properties parseAndMergeProperties(String Url,
// put the user properties into the connect properties
int nTimeout = DriverManager.getLoginTimeout();
if (nTimeout > 0) {
- connectProperties.put(SQLServerDriverIntProperty.LOGIN_TIMEOUT.toString(), new Integer(nTimeout).toString());
+ connectProperties.put(SQLServerDriverIntProperty.LOGIN_TIMEOUT.toString(), Integer.valueOf(nTimeout).toString());
}
// Merge connectProperties (from URL) and supplied properties from user.
diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc42.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc42.java
index 0d078cc1a..1950daf62 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc42.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc42.java
@@ -24,6 +24,10 @@ final class DriverJDBCVersion {
static final void checkSupportsJDBC42() {
}
+
+ static final void checkSupportsJDBC43() {
+ throw new UnsupportedOperationException(SQLServerException.getErrString("R_notSupported"));
+ }
static final void throwBatchUpdateException(SQLServerException lastError,
long[] updateCounts) throws BatchUpdateException {
diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc41.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc43.java
similarity index 55%
rename from src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc41.java
rename to src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc43.java
index 09bb912bf..1f60cd53a 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc41.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerJdbc43.java
@@ -8,24 +8,29 @@
package com.microsoft.sqlserver.jdbc;
+import java.sql.BatchUpdateException;
+
/**
- * Shims for JDBC 4.1 JAR.
+ * Shims for JDBC 4.3 JAR.
*
- * JDBC 4.1 public methods should always check the SQLServerJdbcVersion first to make sure that they are not operable in any earlier driver version.
+ * JDBC 4.3 public methods should always check the SQLServerJdbcVersion first to make sure that they are not operable in any earlier driver version.
* That is, they should throw an exception, be a no-op, or whatever.
*/
final class DriverJDBCVersion {
+ // The 4.3 driver is compliant to JDBC 4.3.
static final int major = 4;
- static final int minor = 1;
+ static final int minor = 3;
+ static final void checkSupportsJDBC43() {
+ }
+
static final void checkSupportsJDBC42() {
- throw new UnsupportedOperationException(SQLServerException.getErrString("R_notSupported"));
}
- // Stub for the new overloaded method in BatchUpdateException in JDBC 4.2
static final void throwBatchUpdateException(SQLServerException lastError,
- long[] updateCounts) {
- throw new UnsupportedOperationException(SQLServerException.getErrString("R_notSupported"));
+ long[] updateCounts) throws BatchUpdateException {
+ throw new BatchUpdateException(lastError.getMessage(), lastError.getSQLState(), lastError.getErrorCode(), updateCounts,
+ new Throwable(lastError.getMessage()));
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java
index 63e701505..dc21fbbdb 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java
@@ -339,7 +339,6 @@ protected Object[][] getContents() {
{"R_TVPEmptyMetadata", "There are not enough fields in the Structured type. Structured types must have at least one field."},
{"R_TVPInvalidValue", "The value provided for Table-Valued Parameter {0} is not valid. Only SQLServerDataTable, ResultSet and ISQLServerDataRecord objects are supported."},
{"R_TVPInvalidColumnValue", "Input data is not in correct format."},
- {"R_AADIntegratedOnNonWindows","ActiveDirectoryIntegrated is only supported on Windows operating systems."},
{"R_TVPSortOrdinalGreaterThanFieldCount", "The sort ordinal {0} on field {1} exceeds the total number of fields."},
{"R_TVPMissingSortOrderOrOrdinal", "The sort order and ordinal must either both be specified, or neither should be specified (SortOrder.Unspecified and -1). The values given were: order = {0}, ordinal = {1}."},
{"R_TVPDuplicateSortOrdinal", "The sort ordinal {0} was specified twice."},
@@ -390,7 +389,7 @@ protected Object[][] getContents() {
{"R_invalidStringValue", "SQL_VARIANT does not support string values of length greater than 8000."},
{"R_invalidValueForTVPWithSQLVariant", "Use of TVPs containing null sql_variant columns is not supported."},
{"R_invalidDataTypeSupportForSQLVariant", "Unexpected TDS type ' '{0}' ' in SQL_VARIANT."},
- {"R_sslProtocolPropertyDescription", "SSL protocol label from TLS, TLSv1, TLSv1.1 & TLSv1.2. The default is TLS."},
- {"R_invalidSSLProtocol", "SSL Protocol {0} label is not valid. Only TLS, TLSv1, TLSv1.1 & TLSv1.2 are supported."},
+ {"R_sslProtocolPropertyDescription", "SSL protocol label from TLS, TLSv1, TLSv1.1, and TLSv1.2. The default is TLS."},
+ {"R_invalidSSLProtocol", "SSL Protocol {0} label is not valid. Only TLS, TLSv1, TLSv1.1, and TLSv1.2 are supported."},
};
}
\ No newline at end of file
diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java
index 9b7933705..37e1ac033 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java
@@ -939,7 +939,6 @@ private void updateCurrentRow(int rowsToMove) {
* and so on.
*
* @return false when there are no more rows to read
- * @return true otherwise
*/
public boolean next() throws SQLServerException {
loggerExternal.entering(getClassNameLogging(), "next");
@@ -1041,8 +1040,7 @@ public boolean wasNull() throws SQLServerException {
}
/**
- * @return true if the cursor is before the first row in this result set
- * @return false otherwise or if thie result set contains no rows.
+ * @return true if the cursor is before the first row in this result set, returns false otherwise or if the result set contains no rows.
*/
public boolean isBeforeFirst() throws SQLServerException {
loggerExternal.entering(getClassNameLogging(), "isBeforeFirst");
@@ -1144,7 +1142,6 @@ public boolean isAfterLast() throws SQLServerException {
* TYPE_SS_SCROLL_STATIC, TYPE_SS_SCROLL_KEYSET, TYPE_SS_SCROLL_DYNAMIC.
*
* @return true if the cursor is on the first row in this result set
- * @return false otherwise
*/
public boolean isFirst() throws SQLServerException {
loggerExternal.entering(getClassNameLogging(), "isFirst");
@@ -1182,7 +1179,6 @@ public boolean isFirst() throws SQLServerException {
* TYPE_SS_SCROLL_STATIC, TYPE_SS_SCROLL_KEYSET, TYPE_SS_SCROLL_DYNAMIC.
*
* @return true if the cursor is on the last row in this result set
- * @return false otherwise
*/
public boolean isLast() throws SQLServerException {
loggerExternal.entering(getClassNameLogging(), "isLast");
@@ -1302,8 +1298,7 @@ private void moveAfterLast() throws SQLServerException {
* This method should be called only on ResultSet objects that are scrollable: TYPE_SCROLL_SENSITIVE, TYPE_SCROLL_INSENSITIVE,
* TYPE_SS_SCROLL_STATIC, TYPE_SS_SCROLL_KEYSET, TYPE_SS_SCROLL_DYNAMIC.
*
- * @return true if the cursor is on a valid row
- * @return false if there are no rows in this ResultSet object
+ * @return true if the cursor is on a valid row, otherwise returns false if there are no rows in this ResultSet object
*/
public boolean first() throws SQLServerException {
loggerExternal.entering(getClassNameLogging(), "first");
@@ -1353,8 +1348,7 @@ private void moveFirst() throws SQLServerException {
* This method should be called only on ResultSet objects that are scrollable: TYPE_SCROLL_SENSITIVE, TYPE_SCROLL_INSENSITIVE,
* TYPE_SS_SCROLL_STATIC, TYPE_SS_SCROLL_KEYSET, TYPE_SS_SCROLL_DYNAMIC.
*
- * @return true if the cursor is on a valid row
- * @return false if there are no rows in this ResultSet object
+ * @return true if the cursor is on a valid row, otherwise returns false if there are no rows in this ResultSet object
*/
public boolean last() throws SQLServerException {
loggerExternal.entering(getClassNameLogging(), "last");
@@ -1442,8 +1436,8 @@ public int getRow() throws SQLServerException {
* This method should be called only on ResultSet objects that are scrollable: TYPE_SCROLL_SENSITIVE, TYPE_SCROLL_INSENSITIVE,
* TYPE_SS_SCROLL_STATIC, TYPE_SS_SCROLL_KEYSET, TYPE_SS_SCROLL_DYNAMIC.
*
- * @return true if the cursor is on a valid row in this result set
- * @return false if the cursor is before the first row or after the last row
+ * @return true if the cursor is on a valid row in this result set, otherwise returns false if the cursor is before the first row or after the
+ * last row
*/
public boolean absolute(int row) throws SQLServerException {
loggerExternal.entering(getClassNameLogging(), "absolute");
@@ -1759,7 +1753,6 @@ private int clientMoveAbsolute(int row) throws SQLServerException {
* TYPE_SS_SCROLL_STATIC, TYPE_SS_SCROLL_KEYSET, TYPE_SS_SCROLL_DYNAMIC.
*
* @return true if the cursor is on a valid row in this result set
- * @return false otherwise
*/
public boolean previous() throws SQLServerException {
loggerExternal.entering(getClassNameLogging(), "previous");
diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSetMetaData.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSetMetaData.java
index 693f3fe0c..93de065ee 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSetMetaData.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSetMetaData.java
@@ -21,7 +21,6 @@
public final class SQLServerResultSetMetaData implements java.sql.ResultSetMetaData {
private SQLServerConnection con;
private final SQLServerResultSet rs;
- public int nBeforeExecuteCols;
static final private java.util.logging.Logger logger = java.util.logging.Logger
.getLogger("com.microsoft.sqlserver.jdbc.internals.SQLServerResultSetMetaData");
diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSQLXML.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSQLXML.java
index 7e8881d8b..3e99ab41f 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSQLXML.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSQLXML.java
@@ -23,6 +23,8 @@
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
@@ -48,8 +50,6 @@
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.XMLReaderFactory;
-
/**
* SQLServerSQLXML represents an XML object and implements a java.sql.SQLXML.
*/
@@ -405,12 +405,14 @@ private DOMSource getDOMSource() throws SQLException {
private SAXSource getSAXSource() throws SQLException {
try {
InputSource src = new InputSource(contents);
- XMLReader reader = XMLReaderFactory.createXMLReader();
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ SAXParser parser = factory.newSAXParser();
+ XMLReader reader = parser.getXMLReader();
SAXSource saxSource = new SAXSource(reader, src);
return saxSource;
}
- catch (SAXException e) {
+ catch (SAXException | ParserConfigurationException e) {
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_failedToParseXML"));
Object[] msgArgs = {e.toString()};
SQLServerException.makeFromDriverError(con, null, form.format(msgArgs), null, true);
diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java
index 9385fd165..696cfa6c5 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java
@@ -1569,7 +1569,8 @@ boolean onInfo(TDSReader tdsReader) throws SQLServerException {
// Not an error. Is it a result set?
else if (nextResult.isResultSet()) {
- if (Util.use42Wrapper()) {
+ // Make sure SQLServerResultSet42 is used for 4.2 and above
+ if (Util.use42Wrapper() || Util.use43Wrapper()) {
resultSet = new SQLServerResultSet42(this);
}
else {
diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSymmetricKeyCache.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSymmetricKeyCache.java
index 76b886786..04f9335ff 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSymmetricKeyCache.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSymmetricKeyCache.java
@@ -18,7 +18,7 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
-import javax.xml.bind.DatatypeConverter;
+import java.util.Base64;;
class CacheClear implements Runnable {
@@ -98,7 +98,7 @@ SQLServerSymmetricKey getKey(EncryptionKeyInfo keyInfo,
String keyLookupValue;
keyLookupValuebuffer.append(":");
- keyLookupValuebuffer.append(DatatypeConverter.printBase64Binary((new String(keyInfo.encryptedKey, UTF_8)).getBytes()));
+ keyLookupValuebuffer.append(Base64.getEncoder().encodeToString((new String(keyInfo.encryptedKey, UTF_8)).getBytes()));
keyLookupValuebuffer.append(":");
keyLookupValuebuffer.append(keyInfo.keyStoreName);
diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAConnection.java
index c1f8d69fd..424fe52ce 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAConnection.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAConnection.java
@@ -44,7 +44,13 @@ public final class SQLServerXAConnection extends SQLServerPooledConnection imple
if (xaLogger.isLoggable(Level.FINER))
xaLogger.finer("Creating an internal control connection for" + toString());
- physicalControlConnection = new SQLServerConnection(toString());
+ physicalControlConnection = null;
+ if (Util.use43Wrapper()) {
+ physicalControlConnection = new SQLServerConnection43(toString());
+ }
+ else {
+ physicalControlConnection = new SQLServerConnection(toString());
+ }
physicalControlConnection.connect(controlConnectionProperties, null);
if (xaLogger.isLoggable(Level.FINER))
xaLogger.finer("Created an internal control connection" + physicalControlConnection.toString() + " for " + toString()
diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAResource.java
index 8e72d0f35..53ff357d4 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAResource.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAResource.java
@@ -16,11 +16,9 @@
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Properties;
-import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
-
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
@@ -165,7 +163,10 @@ public final class SQLServerXAResource implements javax.transaction.xa.XAResourc
public static final int SSTRANSTIGHTLYCPLD = 0x8000;
private SQLServerCallableStatement[] xaStatements = {null, null, null, null, null, null, null, null, null, null};
private final String traceID;
-
+ /**
+ * Variable that shows how many times we attempt the recovery, e.g in case of MSDTC restart
+ */
+ private int recoveryAttempt = 0;
static {
xaInitLock = new Object();
}
@@ -381,7 +382,7 @@ private String typeDisplay(int type) {
SQLServerCallableStatement cs = null;
try {
synchronized (this) {
- if (!xaInitDone) {
+ if (!xaInitDone) {
try {
synchronized (xaInitLock) {
SQLServerCallableStatement initCS = null;
@@ -634,6 +635,14 @@ else if (-1 != version.indexOf('.')) {
}
}
}
+ if (XA_RECOVER == nType && XA_OK != nStatus && recoveryAttempt < 1) {
+ // if recover failed, attempt to start again - adding the variable to check to attempt only once otherwise throw exception that recovery fails
+ // this is added since before this change, if we restart the MSDTC and attempt to do recovery, driver will throw exception
+ //"The function RECOVER: failed. The status is: -3"
+ recoveryAttempt++;
+ DTC_XA_Interface(XA_START, xid, TMNOFLAGS);
+ return DTC_XA_Interface(XA_RECOVER, xid, xaFlags);
+ }
// prepare and end can return XA_RDONLY
// Think should we just check for nStatus to be greater than or equal to zero instead of this check
if (((XA_RDONLY == nStatus) && (XA_END != nType && XA_PREPARE != nType)) || (XA_OK != nStatus && XA_RDONLY != nStatus)) {
@@ -658,7 +667,6 @@ else if (-1 != version.indexOf('.')) {
xaLogger.finer(toString() + " Ignoring exception:" + e1);
}
}
-
throw e;
}
else {
diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SqlVariant.java b/src/main/java/com/microsoft/sqlserver/jdbc/SqlVariant.java
index 2d4c13436..868db7102 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/SqlVariant.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/SqlVariant.java
@@ -62,7 +62,7 @@ static sqlVariantProbBytes valueOf(int intValue) {
if (!(0 <= intValue && intValue < valuesTypes.length) || null == (tdsType = valuesTypes[intValue])) {
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_unknownSSType"));
- Object[] msgArgs = {new Integer(intValue)};
+ Object[] msgArgs = {Integer.valueOf(intValue)};
throw new IllegalArgumentException(form.format(msgArgs));
}
diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/Util.java b/src/main/java/com/microsoft/sqlserver/jdbc/Util.java
index c1d6d81dc..c8842ae09 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/Util.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/Util.java
@@ -391,7 +391,8 @@ else if (ch == ':')
if (null != name) {
if (logger.isLoggable(Level.FINE)) {
if (false == name.equals(SQLServerDriverStringProperty.USER.toString())) {
- if (!name.toLowerCase(Locale.ENGLISH).contains("password")) {
+ if (!name.toLowerCase(Locale.ENGLISH).contains("password") &&
+ !name.toLowerCase(Locale.ENGLISH).contains("keystoresecret")) {
logger.fine("Property:" + name + " Value:" + value);
}
else {
@@ -785,10 +786,7 @@ static final String readGUID(byte[] inputGUID) throws SQLServerException {
static boolean IsActivityTraceOn() {
LogManager lm = LogManager.getLogManager();
String activityTrace = lm.getProperty(ActivityIdTraceProperty);
- if ("on".equalsIgnoreCase(activityTrace))
- return true;
- else
- return false;
+ return ("on".equalsIgnoreCase(activityTrace));
}
/**
@@ -1008,6 +1006,28 @@ static synchronized boolean checkIfNeedNewAccessToken(SQLServerConnection connec
static boolean use42Wrapper() {
return use42Wrapper;
}
+
+ static final boolean use43Wrapper;
+
+ static {
+ boolean supportJDBC43 = true;
+ try {
+ DriverJDBCVersion.checkSupportsJDBC43();
+ }
+ catch (UnsupportedOperationException e) {
+ supportJDBC43 = false;
+ }
+
+ double jvmVersion = Double.parseDouble(Util.SYSTEM_SPEC_VERSION);
+
+ use43Wrapper = supportJDBC43 && (9 <= jvmVersion);
+ }
+
+ // if driver is for JDBC 43 and jvm version is 9 or higher, then always return as SQLServerConnection43,
+ // otherwise return SQLServerConnection
+ static boolean use43Wrapper() {
+ return use43Wrapper;
+ }
}
final class SQLIdentifier {
diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/dtv.java b/src/main/java/com/microsoft/sqlserver/jdbc/dtv.java
index e0ea30378..584cfd681 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/dtv.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/dtv.java
@@ -2208,7 +2208,7 @@ void execute(DTV dtv,
if (null != bigDecimalValue) {
Integer inScale = dtv.getScale();
if (null != inScale && inScale != bigDecimalValue.scale())
- bigDecimalValue = bigDecimalValue.setScale(inScale, BigDecimal.ROUND_DOWN);
+ bigDecimalValue = bigDecimalValue.setScale(inScale, RoundingMode.DOWN);
}
dtv.setValue(bigDecimalValue, JavaType.BIGDECIMAL);
diff --git a/src/main/java/mssql/googlecode/concurrentlinkedhashmap/ConcurrentLinkedHashMap.java b/src/main/java/mssql/googlecode/concurrentlinkedhashmap/ConcurrentLinkedHashMap.java
index a52c70e7b..10f892497 100644
--- a/src/main/java/mssql/googlecode/concurrentlinkedhashmap/ConcurrentLinkedHashMap.java
+++ b/src/main/java/mssql/googlecode/concurrentlinkedhashmap/ConcurrentLinkedHashMap.java
@@ -1446,9 +1446,9 @@ Object readResolve() {
* provides a flexible approach for constructing customized instances with
* a named parameter syntax. It can be used in the following manner:
* {@code
- * ConcurrentMap> graph = new Builder>()
+ * ConcurrentMap> graph = new Builder>()
* .maximumWeightedCapacity(5000)
- * .weigher(Weighers.set())
+ * .weigher(Weighers.set())
* .build();
* }
*/
diff --git a/src/samples/alwaysencrypted/src/main/java/AlwaysEncrypted.java b/src/samples/alwaysencrypted/src/main/java/AlwaysEncrypted.java
index a337f0d74..bf91979c1 100644
--- a/src/samples/alwaysencrypted/src/main/java/AlwaysEncrypted.java
+++ b/src/samples/alwaysencrypted/src/main/java/AlwaysEncrypted.java
@@ -14,7 +14,6 @@
import java.sql.SQLException;
import java.sql.Statement;
-import javax.xml.bind.DatatypeConverter;
import com.microsoft.sqlserver.jdbc.SQLServerColumnEncryptionJavaKeyStoreProvider;
import com.microsoft.sqlserver.jdbc.SQLServerColumnEncryptionKeyStoreProvider;
@@ -116,7 +115,7 @@ public static void main(String[] args) {
*/
String createCEKSQL = "CREATE COLUMN ENCRYPTION KEY " + columnEncryptionKey + " WITH VALUES ( " + " COLUMN_MASTER_KEY = "
+ columnMasterKeyName + " , ALGORITHM = '" + algorithm + "' , ENCRYPTED_VALUE = 0x"
- + DatatypeConverter.printHexBinary(encryptedCEK) + " ) ";
+ + bytesToHexString(encryptedCEK, encryptedCEK.length) + " ) ";
try (Statement cekStatement = sourceConnection.createStatement()) {
cekStatement.executeUpdate(createCEKSQL);
@@ -129,6 +128,27 @@ public static void main(String[] args) {
e.printStackTrace();
}
}
+
+ /**
+ *
+ * @param b
+ * byte value
+ * @param length
+ * length of the array
+ * @return
+ */
+ final static char[] hexChars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+ private static String bytesToHexString(byte[] b,
+ int length) {
+ StringBuilder sb = new StringBuilder(length * 2);
+ for (int i = 0; i < length; i++) {
+ int hexVal = b[i] & 0xFF;
+ sb.append(hexChars[(hexVal & 0xF0) >> 4]);
+ sb.append(hexChars[(hexVal & 0x0F)]);
+ }
+ return sb.toString();
+ }
// To avoid storing the sourceConnection String in your code,
// you can retrieve it from a configuration file.
diff --git a/src/samples/resultsets/src/main/java/retrieveRS.java b/src/samples/resultsets/src/main/java/retrieveRS.java
index 0a4bcc5f4..2422d099f 100644
--- a/src/samples/resultsets/src/main/java/retrieveRS.java
+++ b/src/samples/resultsets/src/main/java/retrieveRS.java
@@ -104,7 +104,7 @@ private static void createTable(Connection con) throws SQLException {
stmt.execute(sql);
- sql = "INSERT Product_JDBC_Sample VALUES ('Adjustable Race','AR-5381','0','0',NULL,'1000','750','0.00','0.00',NULL,NULL,NULL,NULL,'0',NULL,NULL,NULL,NULL,NULL,'2008-04-30 00:00:00.000',NULL,NULL,'694215B7-08F7-4C0D-ACB1-D734BA44C0C8','2014-02-08 10:01:36.827') ";
+ sql = "INSERT Product_JDBC_Sample VALUES ('Adjustable Time','AR-5381','0','0',NULL,'1000','750','0.00','0.00',NULL,NULL,NULL,NULL,'0',NULL,NULL,NULL,NULL,NULL,'2008-04-30 00:00:00.000',NULL,NULL,'694215B7-08F7-4C0D-ACB1-D734BA44C0C8','2014-02-08 10:01:36.827') ";
stmt.execute(sql);
sql = "INSERT Product_JDBC_Sample VALUES ('ML Bottom Bracket','BB-8107','0','0',NULL,'1000','750','0.00','0.00',NULL,NULL,NULL,NULL,'0',NULL,NULL,NULL,NULL,NULL,'2008-04-30 00:00:00.000',NULL,NULL,'694215B7-08F7-4C0D-ACB1-D734BA44C0C8','2014-02-08 10:01:36.827') ";
diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java
index 9ae2445c1..dd4d588df 100644
--- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java
+++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java
@@ -21,7 +21,6 @@
import java.util.LinkedList;
import java.util.Properties;
-import javax.xml.bind.DatatypeConverter;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
@@ -712,7 +711,7 @@ private static void createCEK(SQLServerColumnEncryptionKeyStoreProvider storePro
String cekSql = null;
byte[] key = storeProvider.encryptColumnEncryptionKey(javaKeyAliases, "RSA_OAEP", valuesDefault);
cekSql = "CREATE COLUMN ENCRYPTION KEY " + cekName + " WITH VALUES " + "(COLUMN_MASTER_KEY = " + cmkName
- + ", ALGORITHM = 'RSA_OAEP', ENCRYPTED_VALUE = 0x" + DatatypeConverter.printHexBinary(key) + ")" + ";";
+ + ", ALGORITHM = 'RSA_OAEP', ENCRYPTED_VALUE = 0x" + Util.bytesToHexString(key, key.length) + ")" + ";";
stmt.execute(cekSql);
}
diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/JDBC43Test.java b/src/test/java/com/microsoft/sqlserver/jdbc/JDBC43Test.java
new file mode 100644
index 000000000..6873bbffe
--- /dev/null
+++ b/src/test/java/com/microsoft/sqlserver/jdbc/JDBC43Test.java
@@ -0,0 +1,228 @@
+/*
+ * 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 java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.JDBCType;
+import java.sql.SQLException;
+import java.sql.ShardingKey;
+import java.util.Enumeration;
+import java.util.stream.Stream;
+
+import javax.sql.ConnectionPoolDataSource;
+import javax.sql.PooledConnection;
+import javax.sql.XAConnection;
+
+import org.junit.jupiter.api.Test;
+import org.junit.platform.runner.JUnitPlatform;
+import org.junit.runner.RunWith;
+import org.opentest4j.TestAbortedException;
+
+import com.microsoft.sqlserver.testframework.AbstractTest;
+import com.microsoft.sqlserver.testframework.util.Util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
+
+/**
+ * Tests JDBC 4.3 APIs
+ *
+ */
+@RunWith(JUnitPlatform.class)
+public class JDBC43Test extends AbstractTest {
+ ShardingKey superShardingKey = null;
+ ShardingKey shardingKey = null;
+
+ /**
+ * Tests that we are throwing the unsupported exception for connectionBuilder()
+ * @throws SQLException
+ * @throws TestAbortedException
+ *
+ * @since 1.9
+ */
+ @Test
+ public void connectionBuilderTest() throws TestAbortedException, SQLException {
+ assumeTrue(Util.supportJDBC43(connection));
+ SQLServerDataSource ds = new SQLServerDataSource();
+ try {
+ superShardingKey = ds.createShardingKeyBuilder().subkey("EASTERN_REGION", JDBCType.VARCHAR).build();
+ }
+ catch (SQLException e) {
+ assert (e.getMessage().contains("not implemented"));
+ }
+
+ try {
+ shardingKey = ds.createShardingKeyBuilder().subkey("PITTSBURGH_BRANCH", JDBCType.VARCHAR).build();
+ }
+ catch (SQLException e) {
+ assert (e.getMessage().contains("not implemented"));
+ }
+
+ try {
+ Connection con = ds.createConnectionBuilder().user("rafa").password("tennis").shardingKey(shardingKey).superShardingKey(superShardingKey)
+ .build();
+ }
+ catch (SQLException e) {
+ assert (e.getMessage().contains("not implemented"));
+ }
+ }
+
+ /**
+ * Tests that we are throwing the unsupported exception for connectionBuilder()
+ * @throws SQLException
+ * @throws TestAbortedException
+ *
+ * @since 1.9
+ */
+ @Test
+ public void xaConnectionBuilderTest() throws TestAbortedException, SQLException {
+ assumeTrue(Util.supportJDBC43(connection));
+ SQLServerXADataSource ds = new SQLServerXADataSource();
+ try {
+ superShardingKey = ds.createShardingKeyBuilder().subkey("EASTERN_REGION", JDBCType.VARCHAR).build();
+ }
+ catch (SQLException e) {
+ assert (e.getMessage().contains("not implemented"));
+ }
+
+ try {
+ shardingKey = ds.createShardingKeyBuilder().subkey("PITTSBURGH_BRANCH", JDBCType.VARCHAR).build();
+ }
+ catch (SQLException e) {
+ assert (e.getMessage().contains("not implemented"));
+ }
+
+ try {
+ XAConnection con = ds.createXAConnectionBuilder().user("rafa").password("tennis").shardingKey(shardingKey)
+ .superShardingKey(superShardingKey).build();
+ }
+ catch (SQLException e) {
+ assert (e.getMessage().contains("not implemented"));
+ }
+ }
+
+ /**
+ * Tests that we are throwing the unsupported exception for createPooledConnectionBuilder()
+ * @throws SQLException
+ * @throws TestAbortedException
+ * @since 1.9
+ */
+ @Test
+ public void connectionPoolDataSourceTest() throws TestAbortedException, SQLException {
+ assumeTrue(Util.supportJDBC43(connection));
+ ConnectionPoolDataSource ds = new SQLServerConnectionPoolDataSource();
+ try {
+ superShardingKey = ds.createShardingKeyBuilder().subkey("EASTERN_REGION", JDBCType.VARCHAR).build();
+ }
+ catch (SQLException e) {
+ assert (e.getMessage().contains("not implemented"));
+ }
+
+ try {
+ shardingKey = ds.createShardingKeyBuilder().subkey("PITTSBURGH_BRANCH", JDBCType.VARCHAR).build();
+ }
+ catch (SQLException e) {
+ assert (e.getMessage().contains("not implemented"));
+ }
+ try {
+ PooledConnection con = ds.createPooledConnectionBuilder().user("rafa").password("tennis").shardingKey(shardingKey)
+ .superShardingKey(superShardingKey).build();
+ }
+ catch (SQLException e) {
+ assert (e.getMessage().contains("not implemented"));
+ }
+ }
+
+ /**
+ * Tests that we are throwing the unsupported exception for setShardingKeyIfValid()
+ * @throws SQLException
+ * @throws TestAbortedException
+ * @since 1.9
+ */
+ @Test
+ public void setShardingKeyIfValidTest() throws TestAbortedException, SQLException {
+ assumeTrue(Util.supportJDBC43(connection));
+ SQLServerConnection connection43 = (SQLServerConnection43) DriverManager.getConnection(connectionString);
+ try {
+ connection43.setShardingKeyIfValid(shardingKey, 10);
+ }
+ catch (SQLException e) {
+ assert (e.getMessage().contains("not implemented"));
+ }
+ try {
+ connection43.setShardingKeyIfValid(shardingKey, superShardingKey, 10);
+ }
+ catch (SQLException e) {
+ assert (e.getMessage().contains("not implemented"));
+ }
+
+ }
+
+ /**
+ * Tests that we are throwing the unsupported exception for setShardingKey()
+ * @throws SQLException
+ * @throws TestAbortedException
+ * @since 1.9
+ */
+ @Test
+ public void setShardingKeyTest() throws TestAbortedException, SQLException {
+ assumeTrue(Util.supportJDBC43(connection));
+ SQLServerConnection connection43 = (SQLServerConnection43) DriverManager.getConnection(connectionString);
+ try {
+ connection43.setShardingKey(shardingKey);
+ }
+ catch (SQLException e) {
+ assert (e.getMessage().contains("not implemented"));
+ }
+ try {
+ connection43.setShardingKey(shardingKey, superShardingKey);
+ }
+ catch (SQLException e) {
+ assert (e.getMessage().contains("not implemented"));
+ }
+
+ }
+
+ /**
+ * Tests the stream drivers() methods in java.sql.DriverManager
+ *
+ * @since 1.9
+ * @throws ClassNotFoundException
+ */
+ @Test
+ public void driversTest() throws ClassNotFoundException {
+ Stream drivers = DriverManager.drivers();
+ Object[] driversArray = drivers.toArray();
+ assertEquals(driversArray[0].getClass(), Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"));
+ }
+
+ /**
+ * Tests deregister Driver
+ *
+ * @throws SQLException
+ * @throws ClassNotFoundException
+ */
+ @Test
+ public void deregisterDriverTest() throws SQLException, ClassNotFoundException {
+ Enumeration drivers = DriverManager.getDrivers();
+ Driver current = null;
+ while (drivers.hasMoreElements()) {
+ current = drivers.nextElement();
+ DriverManager.deregisterDriver(current);
+ }
+ Stream currentDrivers = DriverManager.drivers();
+ Object[] driversArray = currentDrivers.toArray();
+ assertEquals(0, driversArray.length);
+
+ DriverManager.registerDriver(current);
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableStatementTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableStatementTest.java
index dad9c195f..2c4c191f2 100644
--- a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableStatementTest.java
+++ b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableStatementTest.java
@@ -133,11 +133,11 @@ public void inputParamsTest() throws SQLException {
// the historical way: no leading '@', parameter names respected (not positional)
CallableStatement cs1 = connection.prepareCall(call);
- cs1.setString("p2", "bar");
- cs1.setString("p1", "foo");
+ cs1.setString("p2", "world");
+ cs1.setString("p1", "hello");
rs = cs1.executeQuery();
rs.next();
- assertEquals("foobar", rs.getString(1));
+ assertEquals("helloworld", rs.getString(1));
// the "new" way: leading '@', parameter names still respected (not positional)
CallableStatement cs2 = connection.prepareCall(call);
@@ -150,7 +150,7 @@ public void inputParamsTest() throws SQLException {
// sanity check: unrecognized parameter name
CallableStatement cs3 = connection.prepareCall(call);
try {
- cs3.setString("@whatever", "junk");
+ cs3.setString("@whatever", "test");
fail("SQLServerException should have been thrown");
} catch (SQLServerException sse) {
if (!sse.getMessage().startsWith("Parameter @whatever was not defined")) {
diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/connection/DriverVersionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/connection/DriverVersionTest.java
index 911120ebb..bbd0ca5d6 100644
--- a/src/test/java/com/microsoft/sqlserver/jdbc/connection/DriverVersionTest.java
+++ b/src/test/java/com/microsoft/sqlserver/jdbc/connection/DriverVersionTest.java
@@ -12,13 +12,14 @@
import java.util.Arrays;
import java.util.Random;
-import javax.xml.bind.DatatypeConverter;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;
+import com.microsoft.sqlserver.jdbc.SQLServerException;
import com.microsoft.sqlserver.testframework.AbstractTest;
+import com.microsoft.sqlserver.testframework.util.Util;
/**
* This test validates PR #342. In this PR, DatatypeConverter#parseHexBinary is replaced with type casting. This tests validates if the behavior
@@ -38,12 +39,13 @@ public class DriverVersionTest extends AbstractTest {
/**
* validates version byte array generated by the original method and type casting reminds the same.
+ * @throws SQLServerException
*/
@Test
- public void testConnectionDriver() {
+ public void testConnectionDriver() throws SQLServerException {
// the original way to create version byte array
String interfaceLibVersion = generateInterfaceLibVersion();
- byte originalVersionBytes[] = DatatypeConverter.parseHexBinary(interfaceLibVersion);
+ byte originalVersionBytes[] = Util.hexStringToByte(interfaceLibVersion);
String originalBytes = Arrays.toString(originalVersionBytes);
diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/connection/SSLProtocolTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/connection/SSLProtocolTest.java
index 5d06220b8..c1e7e3351 100644
--- a/src/test/java/com/microsoft/sqlserver/jdbc/connection/SSLProtocolTest.java
+++ b/src/test/java/com/microsoft/sqlserver/jdbc/connection/SSLProtocolTest.java
@@ -66,11 +66,11 @@ public void testWithUnSupportedProtocols(String sslProtocol) throws Exception {
try {
String url = connectionString + ";sslProtocol=" + sslProtocol;
con = DriverManager.getConnection(url);
- assertFalse(true, "Any protocol other than TLSv1, TLSv1.1 & TLSv1.2 should throw Exception");
+ assertFalse(true, "Any protocol other than TLSv1, TLSv1.1, and TLSv1.2 should throw Exception");
}
catch (SQLServerException e) {
assertTrue(true, "Should throw exception");
- String errMsg = "SSL Protocol " + sslProtocol + " label is not valid. Only TLS, TLSv1, TLSv1.1 & TLSv1.2 are supported.";
+ String errMsg = "SSL Protocol " + sslProtocol + " label is not valid. Only TLS, TLSv1, TLSv1.1, and TLSv1.2 are supported.";
assertTrue(errMsg.equals(e.getMessage()), "Message should be from SQL Server resources : " + e.getMessage());
}
}
diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/connection/WarningTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/connection/WarningTest.java
index 66ee1111b..8b99699b1 100644
--- a/src/test/java/com/microsoft/sqlserver/jdbc/connection/WarningTest.java
+++ b/src/test/java/com/microsoft/sqlserver/jdbc/connection/WarningTest.java
@@ -13,6 +13,8 @@
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLWarning;
+import java.util.Arrays;
+import java.util.List;
import java.util.Properties;
import org.junit.jupiter.api.Test;
@@ -40,9 +42,18 @@ public void testWarnings() throws SQLException {
}
conn.setClientInfo(info2);
warn = conn.getWarnings();
- for (int i = 4; i >= 0; i--) {
- assertTrue(warn.toString().contains(infoArray[i]), "Warnings not found!");
+ for (int i = 0; i < 5; i++) {
+ boolean found = false;
+ List list = Arrays.asList(infoArray);
+ for (String word : list) {
+ if (warn.toString().contains(word)) {
+ found = true;
+ break;
+ }
+ }
+ assertTrue(found, "warning : '" + warn.toString() + "' not found!");
warn = warn.getNextWarning();
+ found = false;
}
conn.clearWarnings();
diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/preparedStatement/BatchExecutionWithNullTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/preparedStatement/BatchExecutionWithNullTest.java
index 667e3fc94..c1c12a8d9 100644
--- a/src/test/java/com/microsoft/sqlserver/jdbc/preparedStatement/BatchExecutionWithNullTest.java
+++ b/src/test/java/com/microsoft/sqlserver/jdbc/preparedStatement/BatchExecutionWithNullTest.java
@@ -40,8 +40,9 @@ public class BatchExecutionWithNullTest extends AbstractTest {
static ResultSet rs = null;
/**
- * Test with combination of setString and setNull which cause the "Violation of PRIMARY KEY constraint and internally
- * "Could not find prepared statement with handle X" error.
+ * Test with combination of setString and setNull which cause the "Violation of PRIMARY KEY constraint and internally "Could not find prepared
+ * statement with handle X" error.
+ *
* @throws SQLException
*/
@Test
@@ -118,7 +119,7 @@ public void testSetup() throws TestAbortedException, Exception {
@AfterAll
public static void terminateVariation() throws SQLException {
connection = DriverManager.getConnection(connectionString);
-
+
SQLServerStatement stmt = (SQLServerStatement) connection.createStatement();
Utils.dropTableIfExists("esimple", stmt);
diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/MergeTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/MergeTest.java
index 54ebcdde2..41674e562 100644
--- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/MergeTest.java
+++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/MergeTest.java
@@ -38,7 +38,7 @@ public class MergeTest extends AbstractTest {
+ " SELECT * FROM CricketTeams IF OBJECT_ID (N'dbo.CricketTeams_UpdatedList', N'U') IS NOT NULL DROP TABLE dbo.CricketTeams_UpdatedList;"
+ " CREATE TABLE dbo.CricketTeams_UpdatedList ( CricketTeamID tinyint NOT NULL PRIMARY KEY, CricketTeamCountry nvarchar(30), CricketTeamContinent nvarchar(50))"
+ "INSERT INTO dbo.CricketTeams_UpdatedList VALUES (1, 'Australia', 'Australia'), (2, 'India', 'Asia'), (3, 'Pakistan', 'Asia'), (4, 'Srilanka', 'Asia'), (5, 'Bangaladesh', 'Asia'),"
- + " (6, 'Hong Kong', 'Asia'), (8, 'England', 'Europe'), (9, 'South Africa', 'Africa'), (10, 'West Indies', 'North America'), (11, 'Zimbabwe', 'Africa');";
+ + " (6, 'Thailand', 'Asia'), (8, 'England', 'Europe'), (9, 'South Africa', 'Africa'), (10, 'West Indies', 'North America'), (11, 'Zimbabwe', 'Africa');";
private static final String mergeCmd2 = "MERGE dbo.CricketTeams AS TARGET " + "USING dbo.CricketTeams_UpdatedList AS SOURCE "
+ "ON (TARGET.CricketTeamID = SOURCE.CricketTeamID) " + "WHEN MATCHED AND TARGET.CricketTeamContinent <> SOURCE.CricketTeamContinent OR "
diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/StatementTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/StatementTest.java
index afb311ae9..eb105a353 100644
--- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/StatementTest.java
+++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/StatementTest.java
@@ -319,7 +319,7 @@ public void testCancelBlockedResponse() throws Exception {
try {
// Start a transaction on a second connection that locks the last part of the table
- // and leave it hanging for now...
+ // and leave it non-responsive for now...
conLock = DriverManager.getConnection(connectionString);
conLock.setAutoCommit(false);
stmtLock = conLock.createStatement();
@@ -434,7 +434,7 @@ public void testCancelBlockedResponsePS() throws Exception {
try {
// Start a transaction on a second connection that locks the last part of the table
- // and leave it hanging for now...
+ // and leave it non-responsive for now...
conLock = DriverManager.getConnection(connectionString);
conLock.setAutoCommit(false);
stmtLock = conLock.createStatement();
@@ -551,7 +551,7 @@ public void testCancelBlockedCursoredResponse() throws Exception {
try {
// Start a transaction on a second connection that locks the last part of the table
- // and leave it hanging for now...
+ // and leave it non-responsive for now...
conLock = DriverManager.getConnection(connectionString);
conLock.setAutoCommit(false);
stmtLock = conLock.createStatement();
@@ -726,11 +726,11 @@ public void testCancelGetOutParams() throws Exception {
/**
* Test that tries to flush out cancellation synchronization issues by repeatedly executing and cancelling statements on multiple threads.
*
- * Typical expected failures would be liveness issues (which would manifest as a test hang), incorrect results, or TDS corruption problems.
+ * Typical expected failures would be liveness issues (which would manifest as a test being non-responsive), incorrect results, or TDS corruption problems.
*
* A set of thread pairs runs for 10 seconds. Each pair has one thread repeatedly executing a SELECT statement and one thread repeatedly
* cancelling execution of that statement. Nothing is done to validate whether any particular call to cancel had any affect on the statement.
- * Liveness issues typically would manifest as a hang in this test.
+ * Liveness issues typically would manifest as a no response in this test.
*
* In order to maximize the likelihood of this test finding bugs, it should run on a multi-proc machine with the -server flag specified to the
* JVM. Also, the debugging println statements are commented out deliberately to minimize the impact to the test from the diagnostics, which
diff --git a/src/test/java/com/microsoft/sqlserver/testframework/util/Util.java b/src/test/java/com/microsoft/sqlserver/testframework/util/Util.java
index f1e5167c4..336c2d304 100644
--- a/src/test/java/com/microsoft/sqlserver/testframework/util/Util.java
+++ b/src/test/java/com/microsoft/sqlserver/testframework/util/Util.java
@@ -11,6 +11,7 @@
import com.microsoft.sqlserver.jdbc.SQLServerConnection;
import com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData;
+import com.microsoft.sqlserver.jdbc.SQLServerException;
import com.microsoft.sqlserver.jdbc.SQLServerStatementColumnEncryptionSetting;
/**
@@ -289,4 +290,82 @@ public static boolean supportJDBC42(Connection con) throws SQLException {
SQLServerDatabaseMetaData meta = (SQLServerDatabaseMetaData) con.getMetaData();
return (meta.getJDBCMajorVersion() >= 4 && meta.getJDBCMinorVersion() >= 2);
}
+
+ /**
+ * Utility function for checking if the system supports JDBC 4.3
+ *
+ * @param con
+ * @return
+ */
+ public static boolean supportJDBC43(Connection con) throws SQLException {
+ SQLServerDatabaseMetaData meta = (SQLServerDatabaseMetaData) con.getMetaData();
+ return (meta.getJDBCMajorVersion() >= 4 && meta.getJDBCMinorVersion() >= 3);
+ }
+
+ /**
+ *
+ * @param b
+ * byte value
+ * @param length
+ * length of the array
+ * @return
+ */
+ final static char[] hexChars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+ public static String bytesToHexString(byte[] b,
+ int length) {
+ StringBuilder sb = new StringBuilder(length * 2);
+ for (int i = 0; i < length; i++) {
+ int hexVal = b[i] & 0xFF;
+ sb.append(hexChars[(hexVal & 0xF0) >> 4]);
+ sb.append(hexChars[(hexVal & 0x0F)]);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * conversion routine valid values 0-9 a-f A-F throws exception when failed to convert
+ *
+ * @param value
+ * charArray
+ * @return
+ * @throws SQLServerException
+ */
+ static byte CharToHex(char value) throws SQLServerException {
+ byte ret = 0;
+ if (value >= 'A' && value <= 'F') {
+ ret = (byte) (value - 'A' + 10);
+ }
+ else if (value >= 'a' && value <= 'f') {
+ ret = (byte) (value - 'a' + 10);
+ }
+ else if (value >= '0' && value <= '9') {
+ ret = (byte) (value - '0');
+ }
+ else {
+ throw new IllegalArgumentException("The string is not in a valid hex format. ");
+ }
+ return ret;
+ }
+
+ /**
+ * Converts a string to an array of bytes
+ *
+ * @param hexV
+ * a hexized string representation of bytes
+ * @return
+ * @throws SQLServerException
+ */
+ public static byte[] hexStringToByte(String hexV) throws SQLServerException {
+ int len = hexV.length();
+ char orig[] = hexV.toCharArray();
+ if ((len % 2) != 0) {
+ throw new IllegalArgumentException("The string is not in a valid hex format: " + hexV);
+ }
+ byte[] bin = new byte[len / 2];
+ for (int i = 0; i < len / 2; i++) {
+ bin[i] = (byte) ((CharToHex(orig[2 * i]) << 4) + CharToHex(orig[2 * i + 1]));
+ }
+ return bin;
+ }
}