diff --git a/CHANGELOG.md b/CHANGELOG.md index c35a1760e5..287ca0c2a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,25 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) +## [6.3.2] Preview Release +### Added +- Added new connection property: sslProtocol [#422](https://github.com/Microsoft/mssql-jdbc/pull/422) +- Added "slow" tag to long running tests [#461](https://github.com/Microsoft/mssql-jdbc/pull/461) + +### Fixed Issues +- Fixed some error messages [#452](https://github.com/Microsoft/mssql-jdbc/pull/452) & [#459](https://github.com/Microsoft/mssql-jdbc/pull/459) +- Fixed statement leaks [#455](https://github.com/Microsoft/mssql-jdbc/pull/455) +- Fixed an issue regarding to loginTimeout with TLS [#456](https://github.com/Microsoft/mssql-jdbc/pull/456) +- Fixed sql_variant issue with String type [#442](https://github.com/Microsoft/mssql-jdbc/pull/442) +- Fixed issue with throwing error message for unsupported datatype [#450](https://github.com/Microsoft/mssql-jdbc/pull/450) +- Fixed issue that initial batchException was not thrown [#458](https://github.com/Microsoft/mssql-jdbc/pull/458) + +### Changed +- Changed sendStringParameterAsUnicode to impact set/update null [#445](https://github.com/Microsoft/mssql-jdbc/pull/445) +- Removed connection property: fipsProvider [#460](https://github.com/Microsoft/mssql-jdbc/pull/460) +- Replaced for and while loops with foeach loops [#421](https://github.com/Microsoft/mssql-jdbc/pull/421) +- Replaced explicit types with the diamond operator [#468](https://github.com/Microsoft/mssql-jdbc/pull/468) & [#420](https://github.com/Microsoft/mssql-jdbc/pull/420) + ## [6.3.1] Preview Release ### Added - Added support for datetime/smallDatetime in TVP [#435](https://github.com/Microsoft/mssql-jdbc/pull/435) diff --git a/README.md b/README.md index 54810ab678..5fd1154ac9 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ To get the latest preview version of the driver, add the following to your POM f com.microsoft.sqlserver mssql-jdbc - 6.3.1.jre8-preview-v2 + 6.3.2.jre8-preview ``` @@ -120,7 +120,7 @@ Projects that require either of the two features need to explicitly declare the com.microsoft.sqlserver mssql-jdbc - 6.3.1.jre8-preview-v2 + 6.3.2.jre8-preview compile diff --git a/pom.xml b/pom.xml index f5498d940c..9324600566 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.microsoft.sqlserver mssql-jdbc - 6.3.2-SNAPSHOT + 6.3.2 jar diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/AE.java b/src/main/java/com/microsoft/sqlserver/jdbc/AE.java index c6345d25b5..1b5b2543fa 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/AE.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/AE.java @@ -88,7 +88,7 @@ byte[] getCekMdVersion() { cekId = 0; cekVersion = 0; cekMdVersion = null; - columnEncryptionKeyValues = new ArrayList(); + columnEncryptionKeyValues = new ArrayList<>(); } int getSize() { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/Column.java b/src/main/java/com/microsoft/sqlserver/jdbc/Column.java index a9c09e3305..d6d8017bfc 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/Column.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/Column.java @@ -337,7 +337,7 @@ else if (jdbcType.isBinary()) { // to the server as Unicode rather than MBCS. This is accomplished here by re-tagging // the value with the appropriate corresponding Unicode type. if ((null != cryptoMetadata) && (con.sendStringParametersAsUnicode()) - && (JavaType.STRING == javaType || JavaType.READER == javaType || JavaType.CLOB == javaType)) { + && (JavaType.STRING == javaType || JavaType.READER == javaType || JavaType.CLOB == javaType || JavaType.OBJECT == javaType)) { jdbcType = getSSPAUJDBCType(jdbcType); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/DDC.java b/src/main/java/com/microsoft/sqlserver/jdbc/DDC.java index 562b958c8d..c42dae2869 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/DDC.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/DDC.java @@ -922,7 +922,8 @@ static final Object convertTemporalToObject(JDBCType jdbcType, } // Convert the calendar value (in local time) to the desired Java object type. switch (jdbcType.category) { - case BINARY: { + case BINARY: + case SQL_VARIANT: { switch (ssType) { case DATE: { // Per JDBC spec, the time part of java.sql.Date values is initialized to midnight diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/DataTypes.java b/src/main/java/com/microsoft/sqlserver/jdbc/DataTypes.java index 914e382a29..3f6ebdbea5 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/DataTypes.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/DataTypes.java @@ -382,7 +382,7 @@ private GetterConversion(SSType.Category from, this.to = to; } - private static final EnumMap> conversionMap = new EnumMap>( + private static final EnumMap> conversionMap = new EnumMap<>( SSType.Category.class); static { @@ -776,7 +776,7 @@ private SetterConversionAE(JavaType from, this.to = to; } - private static final EnumMap> setterConversionAEMap = new EnumMap>(JavaType.class); + private static final EnumMap> setterConversionAEMap = new EnumMap<>(JavaType.class); static { for (JavaType javaType : JavaType.values()) @@ -1086,7 +1086,7 @@ private SetterConversion(JDBCType.Category from, this.to = to; } - private static final EnumMap> conversionMap = new EnumMap>( + private static final EnumMap> conversionMap = new EnumMap<>( JDBCType.Category.class); static { @@ -1305,7 +1305,7 @@ private UpdaterConversion(JDBCType.Category from, this.to = to; } - private static final EnumMap> conversionMap = new EnumMap>( + private static final EnumMap> conversionMap = new EnumMap<>( JDBCType.Category.class); static { @@ -1616,7 +1616,7 @@ private NormalizationAE(JDBCType from, this.to = to; } - private static final EnumMap> normalizationMapAE = new EnumMap>(JDBCType.class); + private static final EnumMap> normalizationMapAE = new EnumMap<>(JDBCType.class); static { for (JDBCType jdbcType : JDBCType.values()) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/FailOverMapSingleton.java b/src/main/java/com/microsoft/sqlserver/jdbc/FailOverMapSingleton.java index f3146d926e..8bebf1f0e9 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/FailOverMapSingleton.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/FailOverMapSingleton.java @@ -13,7 +13,7 @@ final class FailoverMapSingleton { private static int INITIALHASHMAPSIZE = 5; - private static HashMap failoverMap = new HashMap(INITIALHASHMAPSIZE); + private static HashMap failoverMap = new HashMap<>(INITIALHASHMAPSIZE); private FailoverMapSingleton() { /* hide the constructor to stop the instantiation of this class. */} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java index e70f04bbff..a9af8068bf 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java @@ -1579,7 +1579,7 @@ void enableSSL(String host, boolean isFips = false; String trustStoreType = null; - String fipsProvider = null; + String sslProtocol = null; // If anything in here fails, terminate the connection and throw an exception try { @@ -1597,11 +1597,11 @@ void enableSSL(String host, trustStoreType = SQLServerDriverStringProperty.TRUST_STORE_TYPE.getDefaultValue(); } - fipsProvider = con.activeConnectionProperties.getProperty(SQLServerDriverStringProperty.FIPS_PROVIDER.toString()); isFips = Boolean.valueOf(con.activeConnectionProperties.getProperty(SQLServerDriverBooleanProperty.FIPS.toString())); + sslProtocol = con.activeConnectionProperties.getProperty(SQLServerDriverStringProperty.SSL_PROTOCOL.toString()); if (isFips) { - validateFips(fipsProvider, trustStoreType, trustStoreFileName); + validateFips(trustStoreType, trustStoreFileName); } assert TDS.ENCRYPT_OFF == con.getRequestedEncryptionLevel() || // Login only SSL @@ -1647,12 +1647,8 @@ void enableSSL(String host, if (logger.isLoggable(Level.FINEST)) logger.finest(toString() + " Finding key store interface"); - if (isFips) { - ks = KeyStore.getInstance(trustStoreType, fipsProvider); - } - else { - ks = KeyStore.getInstance(trustStoreType); - } + + ks = KeyStore.getInstance(trustStoreType); ksProvider = ks.getProvider(); // Next, load up the trust store file from the specified location. @@ -1728,7 +1724,7 @@ void enableSSL(String host, if (logger.isLoggable(Level.FINEST)) logger.finest(toString() + " Getting TLS or better SSL context"); - sslContext = SSLContext.getInstance("TLS"); + sslContext = SSLContext.getInstance(sslProtocol); sslContextProvider = sslContext.getProvider(); if (logger.isLoggable(Level.FINEST)) @@ -1745,8 +1741,7 @@ void enableSSL(String host, logger.finest(toString() + " Creating SSL socket"); sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket(proxySocket, host, port, false); // don't close proxy when SSL socket - // is closed - + // is closed // At long last, start the SSL handshake ... if (logger.isLoggable(Level.FINER)) logger.finer(toString() + " Starting SSL handshake"); @@ -1827,57 +1822,40 @@ void enableSSL(String host, * Valid FIPS settings: *
  • Encrypt should be true *
  • trustServerCertificate should be false - *
  • if certificate is not installed FIPSProvider & TrustStoreType should be present. + *
  • if certificate is not installed TrustStoreType should be present. * - * @param fipsProvider - * FIPS Provider * @param trustStoreType * @param trustStoreFileName * @throws SQLServerException * @since 6.1.4 */ - private void validateFips(final String fipsProvider, - final String trustStoreType, + private void validateFips(final String trustStoreType, final String trustStoreFileName) throws SQLServerException { boolean isValid = false; boolean isEncryptOn; boolean isValidTrustStoreType; boolean isValidTrustStore; boolean isTrustServerCertificate; - boolean isValidFipsProvider; String strError = SQLServerException.getErrString("R_invalidFipsConfig"); isEncryptOn = (TDS.ENCRYPT_ON == con.getRequestedEncryptionLevel()); - // Here different FIPS provider supports different KeyStore type along with different JVM Implementation. - isValidFipsProvider = !StringUtils.isEmpty(fipsProvider); isValidTrustStoreType = !StringUtils.isEmpty(trustStoreType); isValidTrustStore = !StringUtils.isEmpty(trustStoreFileName); isTrustServerCertificate = con.trustServerCertificate(); - if (isEncryptOn && !isTrustServerCertificate) { - if (logger.isLoggable(Level.FINER)) - logger.finer(toString() + " Found parameters are encrypt is true & trustServerCertificate false"); - + if (isEncryptOn && !isTrustServerCertificate) { isValid = true; - if (isValidTrustStore) { - // In case of valid trust store we need to check fipsProvider and TrustStoreType. - if (!isValidFipsProvider || !isValidTrustStoreType) { - isValid = false; - strError = SQLServerException.getErrString("R_invalidFipsProviderConfig"); - + // In case of valid trust store we need to check TrustStoreType. + if (!isValidTrustStoreType) { + isValid = false; if (logger.isLoggable(Level.FINER)) - logger.finer(toString() + " FIPS provider & TrustStoreType should pass with TrustStore."); + logger.finer(toString() + "TrustStoreType is required alongside with TrustStore."); } - if (logger.isLoggable(Level.FINER)) - logger.finer(toString() + " Found FIPS parameters seems to be valid."); } } - else { - strError = SQLServerException.getErrString("R_invalidFipsEncryptConfig"); - } if (!isValid) { throw new SQLServerException(strError, null, 0, null); @@ -2338,8 +2316,8 @@ else if (!useTnir) { findSocketUsingJavaNIO(inetAddrs, portNumber, timeoutInMilliSeconds); } else { - LinkedList inet4Addrs = new LinkedList(); - LinkedList inet6Addrs = new LinkedList(); + LinkedList inet4Addrs = new LinkedList<>(); + LinkedList inet6Addrs = new LinkedList<>(); for (InetAddress inetAddr : inetAddrs) { if (inetAddr instanceof Inet4Address) { @@ -2467,13 +2445,13 @@ private void findSocketUsingJavaNIO(InetAddress[] inetAddrs, assert inetAddrs.length != 0 : "Number of inetAddresses should not be zero in this function"; Selector selector = null; - LinkedList socketChannels = new LinkedList(); + LinkedList socketChannels = new LinkedList<>(); SocketChannel selectedChannel = null; try { selector = Selector.open(); - for (int i = 0; i < inetAddrs.length; i++) { + for (InetAddress inetAddr : inetAddrs) { SocketChannel sChannel = SocketChannel.open(); socketChannels.add(sChannel); @@ -2484,10 +2462,10 @@ private void findSocketUsingJavaNIO(InetAddress[] inetAddrs, int ops = SelectionKey.OP_CONNECT; SelectionKey key = sChannel.register(selector, ops); - sChannel.connect(new InetSocketAddress(inetAddrs[i], portNumber)); + sChannel.connect(new InetSocketAddress(inetAddr, portNumber)); if (logger.isLoggable(Level.FINER)) - logger.finer(this.toString() + " initiated connection to address: " + inetAddrs[i] + ", portNumber: " + portNumber); + logger.finer(this.toString() + " initiated connection to address: " + inetAddr + ", portNumber: " + portNumber); } long timerNow = System.currentTimeMillis(); @@ -2646,8 +2624,8 @@ private void findSocketUsingThreading(LinkedList inetAddrs, assert inetAddrs.isEmpty() == false : "Number of inetAddresses should not be zero in this function"; - LinkedList sockets = new LinkedList(); - LinkedList socketConnectors = new LinkedList(); + LinkedList sockets = new LinkedList<>(); + LinkedList socketConnectors = new LinkedList<>(); try { @@ -5037,13 +5015,11 @@ void writeTVPColumnMetaData(TVP value) throws SQLServerException { writeShort((short) value.getTVPColumnCount()); Map columnMetadata = value.getColumnMetadata(); - Iterator> columnsIterator = columnMetadata.entrySet().iterator(); /* * TypeColumnMetaData = UserType Flags TYPE_INFO ColName ; */ - while (columnsIterator.hasNext()) { - Map.Entry pair = columnsIterator.next(); + for (Entry pair : columnMetadata.entrySet()) { JDBCType jdbcType = JDBCType.of(pair.getValue().javaSqlType); boolean useServerDefault = pair.getValue().useServerDefault; // ULONG ; UserType of column @@ -5118,13 +5094,12 @@ void writeTVPColumnMetaData(TVP value) throws SQLServerException { writeByte(TDSType.NVARCHAR.byteValue()); isShortValue = (2L * pair.getValue().precision) <= DataTypes.SHORT_VARTYPE_MAX_BYTES; // Use PLP encoding on Yukon and later with long values - if (!isShortValue) // PLP + if (!isShortValue) // PLP { // Handle Yukon v*max type header here. writeShort((short) 0xFFFF); con.getDatabaseCollation().writeCollation(this); - } - else // non PLP + } else // non PLP { writeShort((short) DataTypes.SHORT_VARTYPE_MAX_BYTES); con.getDatabaseCollation().writeCollation(this); @@ -5138,16 +5113,16 @@ void writeTVPColumnMetaData(TVP value) throws SQLServerException { writeByte(TDSType.BIGVARBINARY.byteValue()); isShortValue = pair.getValue().precision <= DataTypes.SHORT_VARTYPE_MAX_BYTES; // Use PLP encoding on Yukon and later with long values - if (!isShortValue) // PLP + if (!isShortValue) // PLP // Handle Yukon v*max type header here. writeShort((short) 0xFFFF); - else // non PLP + else // non PLP writeShort((short) DataTypes.SHORT_VARTYPE_MAX_BYTES); break; case SQL_VARIANT: writeByte(TDSType.SQL_VARIANT.byteValue()); writeInt(TDS.SQL_VARIANT_LENGTH);// write length of sql variant 8009 - + break; default: @@ -5168,7 +5143,7 @@ void writeTvpOrderUnique(TVP value) throws SQLServerException { Map columnMetadata = value.getColumnMetadata(); Iterator> columnsIterator = columnMetadata.entrySet().iterator(); - LinkedList columnList = new LinkedList(); + LinkedList columnList = new LinkedList<>(); while (columnsIterator.hasNext()) { byte flags = 0; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/JaasConfiguration.java b/src/main/java/com/microsoft/sqlserver/jdbc/JaasConfiguration.java index f080ae14e5..6443724fd4 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/JaasConfiguration.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/JaasConfiguration.java @@ -23,9 +23,9 @@ public class JaasConfiguration extends Configuration { private static AppConfigurationEntry[] generateDefaultConfiguration() { if (Util.isIBM()) { - Map confDetailsWithoutPassword = new HashMap(); + Map confDetailsWithoutPassword = new HashMap<>(); confDetailsWithoutPassword.put("useDefaultCcache", "true"); - Map confDetailsWithPassword = new HashMap(); + Map confDetailsWithPassword = new HashMap<>(); // We generated a two configurations fallback that is suitable for password and password-less authentication // See https://www.ibm.com/support/knowledgecenter/SSYKE2_8.0.0/com.ibm.java.security.component.80.doc/security-component/jgssDocs/jaas_login_user.html final String ibmLoginModule = "com.ibm.security.auth.module.Krb5LoginModule"; @@ -34,7 +34,7 @@ private static AppConfigurationEntry[] generateDefaultConfiguration() { new AppConfigurationEntry(ibmLoginModule, AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT, confDetailsWithPassword)}; } else { - Map confDetails = new HashMap(); + Map confDetails = new HashMap<>(); confDetails.put("useTicketCache", "true"); return new AppConfigurationEntry[] {new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule", AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, confDetails)}; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/KerbCallback.java b/src/main/java/com/microsoft/sqlserver/jdbc/KerbCallback.java index 8cdc4cca96..6f861c4bbd 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/KerbCallback.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/KerbCallback.java @@ -42,18 +42,15 @@ public String getUsernameRequested() { @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { - for (int i = 0; i < callbacks.length; i++) { - Callback callback = callbacks[i]; + for (Callback callback : callbacks) { if (callback instanceof NameCallback) { usernameRequested = getAnyOf(callback, con.activeConnectionProperties, "user", SQLServerDriverStringProperty.USER.name()); ((NameCallback) callback).setName(usernameRequested); - } - else if (callback instanceof PasswordCallback) { + } else if (callback instanceof PasswordCallback) { String password = getAnyOf(callback, con.activeConnectionProperties, "password", SQLServerDriverStringProperty.PASSWORD.name()); - ((PasswordCallback) callbacks[i]).setPassword(password.toCharArray()); + ((PasswordCallback) callback).setPassword(password.toCharArray()); - } - else { + } else { throw new UnsupportedCallbackException(callback, "Unrecognized Callback type: " + callback.getClass()); } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java b/src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java index afb71cd7fa..d08264c421 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java @@ -375,7 +375,9 @@ else if (value instanceof ISQLServerDataRecord) { // If set to true, this connection property tells the driver to send textual parameters // to the server as Unicode rather than MBCS. This is accomplished here by re-tagging // the value with the appropriate corresponding Unicode type. - if (con.sendStringParametersAsUnicode() && (JavaType.STRING == javaType || JavaType.READER == javaType || JavaType.CLOB == javaType)) { + // JavaType.OBJECT == javaType when calling setNull() + if (con.sendStringParametersAsUnicode() + && (JavaType.STRING == javaType || JavaType.READER == javaType || JavaType.CLOB == javaType || JavaType.OBJECT == javaType)) { jdbcType = getSSPAUJDBCType(jdbcType); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLCollation.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLCollation.java index 7a47b6fecd..d89a95e111 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLCollation.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLCollation.java @@ -530,11 +530,11 @@ private Encoding encodingFromSortId() throws UnsupportedEncodingException { static { // Populate the windows locale and sort order indices - localeIndex = new HashMap(); + localeIndex = new HashMap<>(); for (WindowsLocale locale : EnumSet.allOf(WindowsLocale.class)) localeIndex.put(locale.langID, locale); - sortOrderIndex = new HashMap(); + sortOrderIndex = new HashMap<>(); for (SortOrder sortOrder : EnumSet.allOf(SortOrder.class)) sortOrderIndex.put(sortOrder.sortId, sortOrder); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLJdbcVersion.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLJdbcVersion.java index 26b631b2d0..e7f5bccf71 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLJdbcVersion.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLJdbcVersion.java @@ -11,6 +11,6 @@ final class SQLJdbcVersion { static final int major = 6; static final int minor = 3; - static final int patch = 1; + static final int patch = 2; static final int build = 0; } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerAeadAes256CbcHmac256Factory.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerAeadAes256CbcHmac256Factory.java index 13c8dc3fb3..8f71ec6b61 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerAeadAes256CbcHmac256Factory.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerAeadAes256CbcHmac256Factory.java @@ -21,7 +21,7 @@ class SQLServerAeadAes256CbcHmac256Factory extends SQLServerEncryptionAlgorithmFactory { // In future we can have more private byte algorithmVersion = 0x1; - private ConcurrentHashMap encryptionAlgorithms = new ConcurrentHashMap(); + private ConcurrentHashMap encryptionAlgorithms = new ConcurrentHashMap<>(); @Override SQLServerEncryptionAlgorithm create(SQLServerSymmetricKey columnEncryptionKey, diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBlob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBlob.java index ef74f5c488..47927d6a68 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBlob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBlob.java @@ -40,7 +40,7 @@ public final class SQLServerBlob implements java.sql.Blob, java.io.Serializable // Initial size of the array is based on an assumption that a Blob object is // typically used either for input or output, and then only once. The array size // grows automatically if multiple streams are used. - ArrayList activeStreams = new ArrayList(1); + ArrayList activeStreams = new ArrayList<>(1); static private final Logger logger = Logger.getLogger("com.microsoft.sqlserver.jdbc.internals.SQLServerBlob"); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java index f208f7656a..4ff063dab2 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java @@ -16,6 +16,7 @@ import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.math.RoundingMode; +import java.sql.Types; import java.text.DecimalFormat; import java.text.MessageFormat; import java.time.OffsetDateTime; @@ -158,7 +159,7 @@ else if (null == delimiter) { catch (Exception e) { throw new SQLServerException(null, e.getMessage(), null, 0, false); } - columnMetadata = new HashMap(); + columnMetadata = new HashMap<>(); loggerExternal.exiting(loggerClassName, "SQLServerBulkCSVFileRecord"); } @@ -215,7 +216,7 @@ else if (null == delimiter) { catch (Exception e) { throw new SQLServerException(null, e.getMessage(), null, 0, false); } - columnMetadata = new HashMap(); + columnMetadata = new HashMap<>(); loggerExternal.exiting(loggerClassName, "SQLServerBulkCSVFileRecord"); } @@ -525,9 +526,7 @@ public Object[] getRowData() throws SQLServerException { // Cannot go directly from String[] to Object[] and expect it to act as an array. Object[] dataRow = new Object[data.length]; - Iterator> it = columnMetadata.entrySet().iterator(); - while (it.hasNext()) { - Entry pair = it.next(); + for (Entry pair : columnMetadata.entrySet()) { ColumnMetadata cm = pair.getValue(); // Reading a column not available in csv @@ -556,7 +555,7 @@ public Object[] getRowData() throws SQLServerException { * Both BCP and BULK INSERT considers double quotes as part of the data and throws error if any data (say "10") is to be * inserted into an numeric column. Our implementation does the same. */ - case java.sql.Types.INTEGER: { + case Types.INTEGER: { // Formatter to remove the decimal part as SQL Server floors the decimal in integer types DecimalFormat decimalFormatter = new DecimalFormat("#"); String formatedfInput = decimalFormatter.format(Double.parseDouble(data[pair.getKey() - 1])); @@ -564,8 +563,8 @@ public Object[] getRowData() throws SQLServerException { break; } - case java.sql.Types.TINYINT: - case java.sql.Types.SMALLINT: { + case Types.TINYINT: + case Types.SMALLINT: { // Formatter to remove the decimal part as SQL Server floors the decimal in integer types DecimalFormat decimalFormatter = new DecimalFormat("#"); String formatedfInput = decimalFormatter.format(Double.parseDouble(data[pair.getKey() - 1])); @@ -573,52 +572,50 @@ public Object[] getRowData() throws SQLServerException { break; } - case java.sql.Types.BIGINT: { + case Types.BIGINT: { BigDecimal bd = new BigDecimal(data[pair.getKey() - 1].trim()); try { dataRow[pair.getKey() - 1] = bd.setScale(0, BigDecimal.ROUND_DOWN).longValueExact(); - } - catch (ArithmeticException ex) { + } catch (ArithmeticException ex) { String value = "'" + data[pair.getKey() - 1] + "'"; MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_errorConvertingValue")); - throw new SQLServerException(form.format(new Object[] {value, JDBCType.of(cm.columnType)}), null, 0, ex); + throw new SQLServerException(form.format(new Object[]{value, JDBCType.of(cm.columnType)}), null, 0, ex); } break; } - case java.sql.Types.DECIMAL: - case java.sql.Types.NUMERIC: { + case Types.DECIMAL: + case Types.NUMERIC: { BigDecimal bd = new BigDecimal(data[pair.getKey() - 1].trim()); dataRow[pair.getKey() - 1] = bd.setScale(cm.scale, RoundingMode.HALF_UP); break; } - case java.sql.Types.BIT: { + case Types.BIT: { // "true" => 1, "false" => 0 // Any non-zero value (integer/double) => 1, 0/0.0 => 0 try { dataRow[pair.getKey() - 1] = (0 == Double.parseDouble(data[pair.getKey() - 1])) ? Boolean.FALSE : Boolean.TRUE; - } - catch (NumberFormatException e) { + } catch (NumberFormatException e) { dataRow[pair.getKey() - 1] = Boolean.parseBoolean(data[pair.getKey() - 1]); } break; } - case java.sql.Types.REAL: { + case Types.REAL: { dataRow[pair.getKey() - 1] = Float.parseFloat(data[pair.getKey() - 1]); break; } - case java.sql.Types.DOUBLE: { + case Types.DOUBLE: { dataRow[pair.getKey() - 1] = Double.parseDouble(data[pair.getKey() - 1]); break; } - case java.sql.Types.BINARY: - case java.sql.Types.VARBINARY: - case java.sql.Types.LONGVARBINARY: - case java.sql.Types.BLOB: { + case Types.BINARY: + case Types.VARBINARY: + case Types.LONGVARBINARY: + case Types.BLOB: { /* * For binary data, the value in file may or may not have the '0x' prefix. We will try to match our implementation with * 'BULK INSERT' except that we will allow 0x prefix whereas 'BULK INSERT' command does not allow 0x prefix. A BULK INSERT @@ -630,14 +627,13 @@ public Object[] getRowData() throws SQLServerException { String binData = data[pair.getKey() - 1].trim(); if (binData.startsWith("0x") || binData.startsWith("0X")) { dataRow[pair.getKey() - 1] = binData.substring(2); - } - else { + } else { dataRow[pair.getKey() - 1] = binData; } break; } - case 2013: // java.sql.Types.TIME_WITH_TIMEZONE + case 2013: // java.sql.Types.TIME_WITH_TIMEZONE { DriverJDBCVersion.checkSupportsJDBC42(); OffsetTime offsetTimeValue; @@ -671,19 +667,19 @@ else if (dateTimeFormatter != null) break; } - case java.sql.Types.NULL: { + case Types.NULL: { dataRow[pair.getKey() - 1] = null; break; } - case java.sql.Types.DATE: - case java.sql.Types.CHAR: - case java.sql.Types.NCHAR: - case java.sql.Types.VARCHAR: - case java.sql.Types.NVARCHAR: - case java.sql.Types.LONGVARCHAR: - case java.sql.Types.LONGNVARCHAR: - case java.sql.Types.CLOB: + case Types.DATE: + case Types.CHAR: + case Types.NCHAR: + case Types.VARCHAR: + case Types.NVARCHAR: + case Types.LONGVARCHAR: + case Types.LONGNVARCHAR: + case Types.CLOB: default: { // The string is copied as is. /* @@ -702,13 +698,11 @@ else if (dateTimeFormatter != null) break; } } - } - catch (IllegalArgumentException e) { + } catch (IllegalArgumentException e) { String value = "'" + data[pair.getKey() - 1] + "'"; MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_errorConvertingValue")); - throw new SQLServerException(form.format(new Object[] {value, JDBCType.of(cm.columnType)}), null, 0, e); - } - catch (ArrayIndexOutOfBoundsException e) { + throw new SQLServerException(form.format(new Object[]{value, JDBCType.of(cm.columnType)}), null, 0, e); + } catch (ArrayIndexOutOfBoundsException e) { throw new SQLServerException(SQLServerException.getErrString("R_CSVDataSchemaMismatch"), e); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java index 3076c90177..6e13ad187d 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java @@ -675,7 +675,7 @@ public void writeToServer(ISQLServerBulkRecord sourceData) throws SQLServerExcep * Initializes the defaults for member variables that require it. */ private void initializeDefaults() { - columnMappings = new LinkedList(); + columnMappings = new LinkedList<>(); destinationTableName = null; sourceBulkRecord = null; sourceResultSet = null; @@ -1471,7 +1471,7 @@ private String getDestTypeFromSrcType(int srcColIndx, private String createInsertBulkCommand(TDSWriter tdsWriter) throws SQLServerException { StringBuilder bulkCmd = new StringBuilder(); - List bulkOptions = new ArrayList(); + List bulkOptions = new ArrayList<>(); String endColumn = " , "; bulkCmd.append("INSERT BULK " + destinationTableName + " ("); @@ -1747,7 +1747,7 @@ private void getDestinationMetadata() throws SQLServerException { .executeQueryInternal("SET FMTONLY ON SELECT * FROM " + destinationTableName + " SET FMTONLY OFF "); destColumnCount = rs.getMetaData().getColumnCount(); - destColumnMetadata = new HashMap(); + destColumnMetadata = new HashMap<>(); destCekTable = rs.getCekTable(); if (!connection.getServerSupportsColumnEncryption()) { @@ -1793,7 +1793,7 @@ private void getDestinationMetadata() throws SQLServerException { * source metadata from the same place for both ResultSet and File. */ private void getSourceMetadata() throws SQLServerException { - srcColumnMetadata = new HashMap(); + srcColumnMetadata = new HashMap<>(); int currentColumn; if (null != sourceResultSet) { try { @@ -1818,9 +1818,8 @@ else if (null != sourceBulkRecord) { } else { srcColumnCount = columnOrdinals.size(); - Iterator columnsIterator = columnOrdinals.iterator(); - while (columnsIterator.hasNext()) { - currentColumn = columnsIterator.next(); + for (Integer columnOrdinal : columnOrdinals) { + currentColumn = columnOrdinal; srcColumnMetadata.put(currentColumn, new BulkColumnMetaData(sourceBulkRecord.getColumnName(currentColumn), true, sourceBulkRecord.getPrecision(currentColumn), sourceBulkRecord.getScale(currentColumn), sourceBulkRecord.getColumnType(currentColumn), @@ -1944,9 +1943,7 @@ else if (0 > cm.destinationColumnOrdinal || destColumnCount < cm.destinationColu } else { Set columnOrdinals = sourceBulkRecord.getColumnOrdinals(); - Iterator columnsIterator = columnOrdinals.iterator(); - while (columnsIterator.hasNext()) { - int currentColumn = columnsIterator.next(); + for (Integer currentColumn : columnOrdinals) { if (sourceBulkRecord.getColumnName(currentColumn).equals(cm.sourceColumnName)) { foundColumn = true; cm.sourceColumnOrdinal = currentColumn; @@ -3535,13 +3532,13 @@ private boolean writeBatchData(TDSWriter tdsWriter, if (null != sourceResultSet) { // Loop for each destination column. The mappings is a many to one mapping // where multiple source columns can be mapped to one destination column. - for (int i = 0; i < mappingColumnCount; ++i) { - writeColumn(tdsWriter, columnMappings.get(i).sourceColumnOrdinal, columnMappings.get(i).destinationColumnOrdinal, null // cell - // value is - // retrieved - // inside - // writeRowData() - // method. + for (ColumnMapping columnMapping : columnMappings) { + writeColumn(tdsWriter, columnMapping.sourceColumnOrdinal, columnMapping.destinationColumnOrdinal, null // cell + // value is + // retrieved + // inside + // writeRowData() + // method. ); } } @@ -3558,11 +3555,11 @@ private boolean writeBatchData(TDSWriter tdsWriter, throw new SQLServerException(SQLServerException.getErrString("R_unableRetrieveSourceData"), ex); } - for (int i = 0; i < mappingColumnCount; ++i) { + for (ColumnMapping columnMapping : columnMappings) { // If the SQLServerBulkCSVRecord does not have metadata for columns, it returns strings in the object array. // COnvert the strings using destination table types. - writeColumn(tdsWriter, columnMappings.get(i).sourceColumnOrdinal, columnMappings.get(i).destinationColumnOrdinal, - rowObjects[columnMappings.get(i).sourceColumnOrdinal - 1]); + writeColumn(tdsWriter, columnMapping.sourceColumnOrdinal, columnMapping.destinationColumnOrdinal, + rowObjects[columnMapping.sourceColumnOrdinal - 1]); } } row++; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopyOptions.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopyOptions.java index 774cd39cbf..c247b1c285 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopyOptions.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopyOptions.java @@ -139,7 +139,7 @@ public int getBulkCopyTimeout() { * @param timeout * Number of seconds before operation times out. * @throws SQLServerException - * If the batchSize being set is invalid. + * If the timeout being set is invalid. */ public void setBulkCopyTimeout(int timeout) throws SQLServerException { if (timeout >= 0) { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCallableStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCallableStatement.java index e5eaa7ccf5..40a77be153 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCallableStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCallableStatement.java @@ -1399,11 +1399,12 @@ public NClob getNClob(String parameterName) throws SQLException { */ /* L3 */ private int findColumn(String columnName) throws SQLServerException { if (paramNames == null) { + SQLServerStatement s = null; try { // Note we are concatenating the information from the passed in sql, not any arguments provided by the user // if the user can execute the sql, any fragments of it is potentially executed via the meta data call through injection // is not a security issue. - SQLServerStatement s = (SQLServerStatement) connection.createStatement(); + s = (SQLServerStatement) connection.createStatement(); ThreePartName threePartName = ThreePartName.parse(procedureName); StringBuilder metaQuery = new StringBuilder("exec sp_sproc_columns "); if (null != threePartName.getDatabasePart()) { @@ -1431,7 +1432,7 @@ public NClob getNClob(String parameterName) throws SQLException { } ResultSet rs = s.executeQueryInternal(metaQuery.toString()); - paramNames = new ArrayList(); + paramNames = new ArrayList<>(); while (rs.next()) { String sCol = rs.getString(4); paramNames.add(sCol.trim()); @@ -1440,6 +1441,10 @@ public NClob getNClob(String parameterName) throws SQLException { catch (SQLException e) { SQLServerException.makeFromDriverError(connection, this, e.toString(), null, false); } + finally { + if (null != s) + s.close(); + } } int l = 0; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java index f933727cfe..a9556baf31 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java @@ -88,7 +88,7 @@ abstract class SQLServerClobBase implements Serializable { // Initial size of the array is based on an assumption that a Clob/NClob object is // typically used either for input or output, and then only once. The array size // grows automatically if multiple streams are used. - private ArrayList activeStreams = new ArrayList(1); + private ArrayList activeStreams = new ArrayList<>(1); transient SQLServerConnection con; private static Logger logger; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index 487c99c389..42c050ab62 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -100,7 +100,7 @@ public class SQLServerConnection implements ISQLServerConnection { private Boolean enablePrepareOnFirstPreparedStatementCall = null; // Current limit for this particular connection. // Handle the actual queue of discarded prepared statements. - private ConcurrentLinkedQueue discardedPreparedStatementHandles = new ConcurrentLinkedQueue(); + private ConcurrentLinkedQueue discardedPreparedStatementHandles = new ConcurrentLinkedQueue<>(); private AtomicInteger discardedPreparedStatementHandleCount = new AtomicInteger(0); private boolean fedAuthRequiredByUser = false; @@ -525,7 +525,7 @@ boolean getServerSupportsColumnEncryption() { } static boolean isWindows; - static Map globalSystemColumnEncryptionKeyStoreProviders = new HashMap(); + static Map globalSystemColumnEncryptionKeyStoreProviders = new HashMap<>(); static { if (System.getProperty("os.name").toLowerCase(Locale.ENGLISH).startsWith("windows")) { isWindows = true; @@ -538,7 +538,7 @@ boolean getServerSupportsColumnEncryption() { } static Map globalCustomColumnEncryptionKeyStoreProviders = null; // This is a per-connection store provider. It can be JKS or AKV. - Map systemColumnEncryptionKeyStoreProvider = new HashMap(); + Map systemColumnEncryptionKeyStoreProvider = new HashMap<>(); /** * Registers key store providers in the globalCustomColumnEncryptionKeyStoreProviders. @@ -561,7 +561,7 @@ public static synchronized void registerColumnEncryptionKeyStoreProviders( throw new SQLServerException(null, SQLServerException.getErrString("R_CustomKeyStoreProviderSetOnce"), null, 0, false); } - globalCustomColumnEncryptionKeyStoreProviders = new HashMap(); + globalCustomColumnEncryptionKeyStoreProviders = new HashMap<>(); for (Map.Entry entry : clientKeyStoreProviders.entrySet()) { String providerName = entry.getKey(); @@ -625,7 +625,7 @@ synchronized SQLServerColumnEncryptionKeyStoreProvider getSystemColumnEncryption } private String trustedServerNameAE = null; - private static Map> columnEncryptionTrustedMasterKeyPaths = new HashMap>(); + private static Map> columnEncryptionTrustedMasterKeyPaths = new HashMap<>(); /** * Sets Trusted Master Key Paths in the columnEncryptionTrustedMasterKeyPaths. @@ -691,7 +691,7 @@ public static synchronized void removeColumnEncryptionTrustedMasterKeyPaths(Stri public static synchronized Map> getColumnEncryptionTrustedMasterKeyPaths() { loggerExternal.entering(SQLServerConnection.class.getName(), "getColumnEncryptionTrustedMasterKeyPaths", "Getting Trusted Master Key Paths"); - Map> masterKeyPathCopy = new HashMap>(); + Map> masterKeyPathCopy = new HashMap<>(); for (Map.Entry> entry : columnEncryptionTrustedMasterKeyPaths.entrySet()) { masterKeyPathCopy.put(entry.getKey(), entry.getValue()); @@ -1079,7 +1079,10 @@ Connection connect(Properties propsIn, // timeout, default is 15 per spec String sPropValue = propsIn.getProperty(SQLServerDriverIntProperty.LOGIN_TIMEOUT.toString()); if (null != sPropValue && sPropValue.length() > 0) { - loginTimeoutSeconds = Integer.parseInt(sPropValue); + int sPropValueInt = Integer.parseInt(sPropValue); + if (0 != sPropValueInt) { // Use the default timeout in case of a zero value + loginTimeoutSeconds = sPropValueInt; + } } } @@ -1694,6 +1697,16 @@ else if (0 == requestedPacketSize) setEnablePrepareOnFirstPreparedStatementCall(booleanPropertyOn(sPropKey, sPropValue)); } + sPropKey = SQLServerDriverStringProperty.SSL_PROTOCOL.toString(); + sPropValue = activeConnectionProperties.getProperty(sPropKey); + if (null == sPropValue) { + sPropValue = SQLServerDriverStringProperty.SSL_PROTOCOL.getDefaultValue().toString(); + activeConnectionProperties.setProperty(sPropKey, sPropValue); + } + else { + activeConnectionProperties.setProperty(sPropKey, SSLProtocol.valueOfString(sPropValue).toString()); + } + FailoverInfo fo = null; String databaseNameProperty = SQLServerDriverStringProperty.DATABASE_NAME.toString(); String serverNameProperty = SQLServerDriverStringProperty.SERVER_NAME.toString(); @@ -3217,7 +3230,7 @@ public CallableStatement prepareCall(String sql, public java.util.Map> getTypeMap() throws SQLServerException { loggerExternal.entering(getClassNameLogging(), "getTypeMap"); checkClosed(); - java.util.Map> mp = new java.util.HashMap>(); + java.util.Map> mp = new java.util.HashMap<>(); loggerExternal.exiting(getClassNameLogging(), "getTypeMap", mp); return mp; } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java index 25c269f83c..16891f3f0b 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java @@ -585,13 +585,14 @@ public boolean getFIPS() { return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.FIPS.toString(), SQLServerDriverBooleanProperty.FIPS.getDefaultValue()); } - - public void setFIPSProvider(String fipsProvider) { - setStringProperty(connectionProps, SQLServerDriverStringProperty.FIPS_PROVIDER.toString(), fipsProvider); + + public void setSSLProtocol(String sslProtocol) { + setStringProperty(connectionProps, SQLServerDriverStringProperty.SSL_PROTOCOL.toString(), sslProtocol); } - public String getFIPSProvider() { - return getStringProperty(connectionProps, SQLServerDriverStringProperty.FIPS_PROVIDER.toString(), null); + public String getSSLProtocol() { + return getStringProperty(connectionProps, SQLServerDriverStringProperty.SSL_PROTOCOL.toString(), + SQLServerDriverStringProperty.SSL_PROTOCOL.getDefaultValue()); } // The URL property is exposed for backwards compatibility reasons. Also, several diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataTable.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataTable.java index 53284f3722..d69d3e2744 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataTable.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataTable.java @@ -36,8 +36,8 @@ public final class SQLServerDataTable { */ // Name used in CREATE TYPE public SQLServerDataTable() throws SQLServerException { - columnMetadata = new LinkedHashMap(); - rows = new HashMap(); + columnMetadata = new LinkedHashMap<>(); + rows = new HashMap<>(); } /** diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java index 25e7a7c146..06fbab5277 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDatabaseMetaData.java @@ -89,7 +89,7 @@ final void close() throws SQLServerException { } } - EnumMap handleMap = new EnumMap(CallableHandles.class); + EnumMap handleMap = new EnumMap<>(CallableHandles.class); // Returns unique id for each instance. private static int nextInstanceID() { @@ -244,7 +244,6 @@ private SQLServerResultSet getResultSetFromInternalQueries(String catalog, SQLServerResultSet rs = null; try { rs = ((SQLServerStatement) connection.createStatement()).executeQueryInternal(query); - } finally { if (null != orgCat) { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java index bfe9612202..307e0fb12c 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java @@ -117,6 +117,46 @@ else if (value.toLowerCase(Locale.US).equalsIgnoreCase(ColumnEncryptionSetting.D } } +enum SSLProtocol { + TLS("TLS"), + TLS_V10("TLSv1"), + TLS_V11("TLSv1.1"), + TLS_V12("TLSv1.2"),; + + private final String name; + + private SSLProtocol(String name) { + this.name = name; + } + + public String toString() { + return name; + } + + static SSLProtocol valueOfString(String value) throws SQLServerException { + SSLProtocol protocol = null; + + if (value.toLowerCase(Locale.ENGLISH).equalsIgnoreCase(SSLProtocol.TLS.toString())) { + protocol = SSLProtocol.TLS; + } + else if (value.toLowerCase(Locale.ENGLISH).equalsIgnoreCase(SSLProtocol.TLS_V10.toString())) { + protocol = SSLProtocol.TLS_V10; + } + else if (value.toLowerCase(Locale.ENGLISH).equalsIgnoreCase(SSLProtocol.TLS_V11.toString())) { + protocol = SSLProtocol.TLS_V11; + } + else if (value.toLowerCase(Locale.ENGLISH).equalsIgnoreCase(SSLProtocol.TLS_V12.toString())) { + protocol = SSLProtocol.TLS_V12; + } + else { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidSSLProtocol")); + Object[] msgArgs = {value}; + throw new SQLServerException(null, form.format(msgArgs), null, 0, false); + } + return protocol; + } +} + enum KeyStoreAuthentication { JavaKeyStorePassword; @@ -246,7 +286,7 @@ enum SQLServerDriverStringProperty KEY_STORE_AUTHENTICATION ("keyStoreAuthentication", ""), KEY_STORE_SECRET ("keyStoreSecret", ""), KEY_STORE_LOCATION ("keyStoreLocation", ""), - FIPS_PROVIDER ("fipsProvider", ""), + SSL_PROTOCOL ("sslProtocol", SSLProtocol.TLS.toString()), ; private final String name; @@ -377,13 +417,13 @@ public final class SQLServerDriver implements java.sql.Driver { new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.XOPEN_STATES.toString(), Boolean.toString(SQLServerDriverBooleanProperty.XOPEN_STATES.getDefaultValue()), false, TRUE_FALSE), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.AUTHENTICATION_SCHEME.toString(), SQLServerDriverStringProperty.AUTHENTICATION_SCHEME.getDefaultValue(), false, new String[] {AuthenticationScheme.javaKerberos.toString(),AuthenticationScheme.nativeAuthentication.toString()}), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.AUTHENTICATION.toString(), SQLServerDriverStringProperty.AUTHENTICATION.getDefaultValue(), false, new String[] {SqlAuthentication.NotSpecified.toString(),SqlAuthentication.SqlPassword.toString(),SqlAuthentication.ActiveDirectoryPassword.toString(),SqlAuthentication.ActiveDirectoryIntegrated.toString()}), - new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.FIPS_PROVIDER.toString(), SQLServerDriverStringProperty.FIPS_PROVIDER.getDefaultValue(), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverIntProperty.SOCKET_TIMEOUT.toString(), Integer.toString(SQLServerDriverIntProperty.SOCKET_TIMEOUT.getDefaultValue()), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.FIPS.toString(), Boolean.toString(SQLServerDriverBooleanProperty.FIPS.getDefaultValue()), false, TRUE_FALSE), new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.ENABLE_PREPARE_ON_FIRST_PREPARED_STATEMENT.toString(), Boolean.toString(SQLServerDriverBooleanProperty.ENABLE_PREPARE_ON_FIRST_PREPARED_STATEMENT.getDefaultValue()), false,TRUE_FALSE), new SQLServerDriverPropertyInfo(SQLServerDriverIntProperty.SERVER_PREPARED_STATEMENT_DISCARD_THRESHOLD.toString(), Integer.toString(SQLServerDriverIntProperty.SERVER_PREPARED_STATEMENT_DISCARD_THRESHOLD.getDefaultValue()), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverIntProperty.STATEMENT_POOLING_CACHE_SIZE.toString(), Integer.toString(SQLServerDriverIntProperty.STATEMENT_POOLING_CACHE_SIZE.getDefaultValue()), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.JAAS_CONFIG_NAME.toString(), SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue(), false, null), + new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.SSL_PROTOCOL.toString(), SQLServerDriverStringProperty.SSL_PROTOCOL.getDefaultValue(), false, new String[] {SSLProtocol.TLS.toString(), SSLProtocol.TLS_V10.toString(), SSLProtocol.TLS_V11.toString(), SSLProtocol.TLS_V12.toString()}), }; // Properties that can only be set by using Properties. @@ -485,8 +525,8 @@ static Properties mergeURLAndSuppliedProperties(Properties urlProps, return urlProps; Properties suppliedPropertiesFixed = fixupProperties(suppliedProperties); // Merge URL properties and supplied properties. - for (int i = 0; i < DRIVER_PROPERTIES.length; i++) { - String sProp = DRIVER_PROPERTIES[i].getName(); + for (SQLServerDriverPropertyInfo DRIVER_PROPERTY : DRIVER_PROPERTIES) { + String sProp = DRIVER_PROPERTY.getName(); String sPropVal = suppliedPropertiesFixed.getProperty(sProp); // supplied properties have precedence if (null != sPropVal) { // overwrite the property in urlprops if already exists. supp prop has more precedence @@ -495,8 +535,8 @@ static Properties mergeURLAndSuppliedProperties(Properties urlProps, } // Merge URL properties with property-only properties - for (int i = 0; i < DRIVER_PROPERTIES_PROPERTY_ONLY.length; i++) { - String sProp = DRIVER_PROPERTIES_PROPERTY_ONLY[i].getName(); + for (SQLServerDriverPropertyInfo aDRIVER_PROPERTIES_PROPERTY_ONLY : DRIVER_PROPERTIES_PROPERTY_ONLY) { + String sProp = aDRIVER_PROPERTIES_PROPERTY_ONLY.getName(); Object oPropVal = suppliedPropertiesFixed.get(sProp); // supplied properties have precedence if (null != oPropVal) { // overwrite the property in urlprops if already exists. supp prop has more precedence @@ -520,14 +560,14 @@ static String getNormalizedPropertyName(String name, if (null == name) return name; - for (int i = 0; i < driverPropertiesSynonyms.length; i++) { - if (driverPropertiesSynonyms[i][0].equalsIgnoreCase(name)) { - return driverPropertiesSynonyms[i][1]; + for (String[] driverPropertiesSynonym : driverPropertiesSynonyms) { + if (driverPropertiesSynonym[0].equalsIgnoreCase(name)) { + return driverPropertiesSynonym[1]; } } - for (int i = 0; i < DRIVER_PROPERTIES.length; i++) { - if (DRIVER_PROPERTIES[i].getName().equalsIgnoreCase(name)) { - return DRIVER_PROPERTIES[i].getName(); + for (SQLServerDriverPropertyInfo DRIVER_PROPERTY : DRIVER_PROPERTIES) { + if (DRIVER_PROPERTY.getName().equalsIgnoreCase(name)) { + return DRIVER_PROPERTY.getName(); } } @@ -549,9 +589,9 @@ static String getPropertyOnlyName(String name, if (null == name) return name; - for (int i = 0; i < DRIVER_PROPERTIES_PROPERTY_ONLY.length; i++) { - if (DRIVER_PROPERTIES_PROPERTY_ONLY[i].getName().equalsIgnoreCase(name)) { - return DRIVER_PROPERTIES_PROPERTY_ONLY[i].getName(); + for (SQLServerDriverPropertyInfo aDRIVER_PROPERTIES_PROPERTY_ONLY : DRIVER_PROPERTIES_PROPERTY_ONLY) { + if (aDRIVER_PROPERTIES_PROPERTY_ONLY.getName().equalsIgnoreCase(name)) { + return aDRIVER_PROPERTIES_PROPERTY_ONLY.getName(); } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerEncryptionAlgorithmFactoryList.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerEncryptionAlgorithmFactoryList.java index 91c9a3973d..a7eb1c0ded 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerEncryptionAlgorithmFactoryList.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerEncryptionAlgorithmFactoryList.java @@ -21,7 +21,7 @@ final class SQLServerEncryptionAlgorithmFactoryList { private static final SQLServerEncryptionAlgorithmFactoryList instance = new SQLServerEncryptionAlgorithmFactoryList(); private SQLServerEncryptionAlgorithmFactoryList() { - encryptionAlgoFactoryMap = new ConcurrentHashMap(); + encryptionAlgoFactoryMap = new ConcurrentHashMap<>(); encryptionAlgoFactoryMap.putIfAbsent(SQLServerAeadAes256CbcHmac256Algorithm.algorithmName, new SQLServerAeadAes256CbcHmac256Factory()); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerException.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerException.java index 2f4dfd06ca..e8ed55d5ab 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerException.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerException.java @@ -103,14 +103,12 @@ final void setDriverErrorCode(int value) { if (exLogger.isLoggable(Level.FINE)) { StringBuilder sb = new StringBuilder(100); StackTraceElement st[] = this.getStackTrace(); - for (int i = 0; i < st.length; i++) - sb.append(st[i].toString()); + for (StackTraceElement aSt : st) sb.append(aSt.toString()); Throwable t = this.getCause(); if (t != null) { sb.append("\n caused by " + t + "\n"); StackTraceElement tst[] = t.getStackTrace(); - for (int i = 0; i < tst.length; i++) - sb.append(tst[i].toString()); + for (StackTraceElement aTst : tst) sb.append(aTst.toString()); } exLogger.fine(sb.toString()); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerParameterMetaData.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerParameterMetaData.java index 04df112ea8..1d11e61afd 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerParameterMetaData.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerParameterMetaData.java @@ -563,6 +563,8 @@ private void checkClosed() throws SQLServerException { assert null != st; stmtParent = st; con = st.connection; + SQLServerStatement s = null; + SQLServerStatement stmt = null; if (logger.isLoggable(java.util.logging.Level.FINE)) { logger.fine(toString() + " created by (" + st.toString() + ")"); } @@ -571,7 +573,7 @@ private void checkClosed() throws SQLServerException { // If the CallableStatement/PreparedStatement is a stored procedure call // then we can extract metadata using sp_sproc_columns if (null != st.procedureName) { - SQLServerStatement s = (SQLServerStatement) con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + s = (SQLServerStatement) con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); String sProc = parseProcIdentifier(st.procedureName); if (con.isKatmaiOrLater()) rsProcedureMeta = s.executeQueryInternal("exec sp_sproc_columns_100 " + sProc + ", @ODBCVer=3"); @@ -601,7 +603,7 @@ private void checkClosed() throws SQLServerException { // procedure "sp_describe_undeclared_parameters" to retrieve parameter meta data // if SQL server version is 2008, then use FMTONLY else { - queryMetaMap = new HashMap(); + queryMetaMap = new HashMap<>(); if (con.getServerMajorVersion() >= SQL_SERVER_2012_VERSION) { // new implementation for SQL verser 2012 and above @@ -616,7 +618,7 @@ private void checkClosed() throws SQLServerException { else { // old implementation for SQL server 2008 stringToParse = sProcString; - ArrayList metaInfoList = new ArrayList(); + ArrayList metaInfoList = new ArrayList<>(); while (stringToParse.length() > 0) { MetaInfo metaInfo = parseStatement(stringToParse); @@ -659,13 +661,11 @@ private void checkClosed() throws SQLServerException { String tablesAndJoins = sbTablesAndJoins.toString(); - Statement stmt = con.createStatement(); + stmt = (SQLServerStatement) con.createStatement(); String sCom = "sp_executesql N'SET FMTONLY ON SELECT " + columns + " FROM " + tablesAndJoins + " '"; ResultSet rs = stmt.executeQuery(sCom); parseQueryMetaFor2008(rs); - stmt.close(); - rs.close(); } } } @@ -679,6 +679,10 @@ private void checkClosed() throws SQLServerException { catch(StringIndexOutOfBoundsException e){ SQLServerException.makeFromDriverError(con, stmtParent, e.toString(), null, false); } + finally { + if (null != stmt) + stmt.close(); + } } public boolean isWrapperFor(Class iface) throws SQLException { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPooledConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPooledConnection.java index f407dff112..cc059434d8 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPooledConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPooledConnection.java @@ -38,7 +38,7 @@ public class SQLServerPooledConnection implements PooledConnection { SQLServerPooledConnection(SQLServerDataSource ds, String user, String password) throws SQLException { - listeners = new Vector(); + listeners = new Vector<>(); // Piggyback SQLServerDataSource logger for now. pcLogger = SQLServerDataSource.dsLogger; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java index 2b9350e490..1ba3c62e8d 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java @@ -98,6 +98,9 @@ public class SQLServerPreparedStatement extends SQLServerStatement implements IS /** The prepared statement handle returned by the server */ private int prepStmtHandle = 0; + + /** Statement used for getMetadata(). Declared as a field to facilitate closing the statement. */ + private SQLServerStatement internalStmt = null; private void setPreparedStatementHandle(int handle) { this.prepStmtHandle = handle; @@ -271,6 +274,18 @@ final void closeInternal() { // If we have a prepared statement handle, close it. closePreparedHandle(); + + // Close the statement that was used to generate empty statement from getMetadata(). + try { + if (null != internalStmt) + internalStmt.close(); + } catch (SQLServerException e) { + if (loggerExternal.isLoggable(java.util.logging.Level.FINER)) + loggerExternal.finer("Ignored error closing internal statement: " + e.getErrorCode() + " " + e.getMessage()); + } + finally { + internalStmt = null; + } // Clean up client-side state batchParamValues = null; @@ -338,7 +353,7 @@ private String buildParamTypeDefinitions(Parameter[] params, StringBuilder sb = new StringBuilder(); int nCols = params.length; char cParamName[] = new char[10]; - parameterNames = new ArrayList(); + parameterNames = new ArrayList<>(); for (int i = 0; i < nCols; i++) { if (i > 0) @@ -795,7 +810,7 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer return; } - Map cekList = new HashMap(); + Map cekList = new HashMap<>(); CekTableEntry cekEntry = null; try { while (rs.next()) { @@ -1023,8 +1038,8 @@ else if (resultSet != null) { ResultSet emptyResultSet = null; try { fmtSQL = replaceMarkerWithNull(fmtSQL); - SQLServerStatement stmt = (SQLServerStatement) connection.createStatement(); - emptyResultSet = stmt.executeQueryInternal("set fmtonly on " + fmtSQL + "\nset fmtonly off"); + internalStmt = (SQLServerStatement) connection.createStatement(); + emptyResultSet = internalStmt.executeQueryInternal("set fmtonly on " + fmtSQL + "\nset fmtonly off"); } catch (SQLException sqle) { if (false == sqle.getMessage().equals(SQLServerException.getErrString("R_noResultset"))) { @@ -2376,7 +2391,7 @@ public final void addBatch() throws SQLServerException { // Create the list of batch parameter values first time through if (batchParamValues == null) - batchParamValues = new ArrayList(); + batchParamValues = new ArrayList<>(); final int numParams = inOutParam.length; Parameter paramValues[] = new Parameter[numParams]; @@ -2417,10 +2432,9 @@ public int[] executeBatch() throws SQLServerException, BatchUpdateException { // // OUT and INOUT parameter checking is done here, before executing the batch. If any // OUT or INOUT are present, the entire batch fails. - for (int batch = 0; batch < batchParamValues.size(); ++batch) { - Parameter paramValues[] = batchParamValues.get(batch); - for (int param = 0; param < paramValues.length; ++param) { - if (paramValues[param].isOutput()) { + for (Parameter[] paramValues : batchParamValues) { + for (Parameter paramValue : paramValues) { + if (paramValue.isOutput()) { throw new BatchUpdateException(SQLServerException.getErrString("R_outParamsNotPermittedinBatch"), null, 0, null); } } @@ -2475,10 +2489,9 @@ public long[] executeLargeBatch() throws SQLServerException, BatchUpdateExceptio // // OUT and INOUT parameter checking is done here, before executing the batch. If any // OUT or INOUT are present, the entire batch fails. - for (int batch = 0; batch < batchParamValues.size(); ++batch) { - Parameter paramValues[] = batchParamValues.get(batch); - for (int param = 0; param < paramValues.length; ++param) { - if (paramValues[param].isOutput()) { + for (Parameter[] paramValues : batchParamValues) { + for (Parameter paramValue : paramValues) { + if (paramValue.isOutput()) { throw new BatchUpdateException(SQLServerException.getErrString("R_outParamsNotPermittedinBatch"), null, 0, null); } } @@ -2538,7 +2551,7 @@ final void doExecutePreparedStatementBatch(PrepStmtBatchExecCmd batchCommand) th int numBatchesPrepared = 0; int numBatchesExecuted = 0; - Vector cryptoMetaBatch = new Vector(); + Vector cryptoMetaBatch = new Vector<>(); if (isSelect(userSQL)) { SQLServerException.makeFromDriverError(connection, this, SQLServerException.getErrString("R_selectNotPermittedinBatch"), null, true); @@ -2573,8 +2586,8 @@ final void doExecutePreparedStatementBatch(PrepStmtBatchExecCmd batchCommand) th buildPreparedStrings(batchParam, true); // Save the crypto metadata retrieved for the first batch. We will re-use these for the rest of the batches. - for (int i = 0; i < batchParam.length; i++) { - cryptoMetaBatch.add(batchParam[i].cryptoMeta); + for (Parameter aBatchParam : batchParam) { + cryptoMetaBatch.add(aBatchParam.cryptoMeta); } } @@ -2683,10 +2696,17 @@ final void doExecutePreparedStatementBatch(PrepStmtBatchExecCmd batchCommand) th numBatchesPrepared = numBatchesExecuted; continue; } - else + else if (null != batchCommand.batchException) { + // if batch exception occurred, loop out to throw the initial batchException + numBatchesExecuted = numBatchesPrepared; + attempt++; + continue; + } + else { throw e; + } } - break; + break; } } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index 3945a2096c..0276af73b8 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -38,7 +38,7 @@ protected Object[][] getContents() { {"R_invalidLength", "The length {0} is not valid."}, {"R_unknownSSType", "Invalid SQL Server data type {0}."}, {"R_unknownJDBCType", "Invalid JDBC data type {0}."}, - {"R_notSQLServer", "The driver received an unexpected pre-login response. Verify the connection properties and check that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. This driver can be used only with SQL Server 2000 or later."}, + {"R_notSQLServer", "The driver received an unexpected pre-login response. Verify the connection properties and check that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. This driver can be used only with SQL Server 2005 or later."}, {"R_tcpOpenFailed", "{0}. Verify the connection properties. Make sure that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. Make sure that TCP connections to the port are not blocked by a firewall."}, {"R_unsupportedJREVersion", "Java Runtime Environment (JRE) version {0} is not supported by this driver. Use the sqljdbc4.jar class library, which provides support for JDBC 4.0."}, {"R_unsupportedServerVersion", "SQL Server version {0} is not supported by this driver."}, @@ -180,8 +180,8 @@ protected Object[][] getContents() { {"R_packetSizePropertyDescription", "The network packet size used to communicate with SQL Server."}, {"R_encryptPropertyDescription", "Determines if Secure Sockets Layer (SSL) encryption should be used between the client and the server."}, {"R_trustServerCertificatePropertyDescription", "Determines if the driver should validate the SQL Server Secure Sockets Layer (SSL) certificate."}, - {"R_trustStoreTypePropertyDescription", "Type of trust store type like JKS / PKCS12 or any FIPS Provider KeyStore implementation Type."}, - {"R_trustStorePropertyDescription", "The path to the certificate trust store file."}, + {"R_trustStoreTypePropertyDescription", "KeyStore type."}, + {"R_trustStorePropertyDescription", "The path to the certificate TrustStore file."}, {"R_trustStorePasswordPropertyDescription", "The password used to check the integrity of the trust store data."}, {"R_hostNameInCertificatePropertyDescription", "The host name to be used when validating the SQL Server Secure Sockets Layer (SSL) certificate."}, {"R_sendTimeAsDatetimePropertyDescription", "Determines whether to use the SQL Server datetime data type to send java.sql.Time values to the database."}, @@ -190,7 +190,7 @@ protected Object[][] getContents() { {"R_socketTimeoutPropertyDescription", "The number of milliseconds to wait before the java.net.SocketTimeoutException is raised."}, {"R_serverPreparedStatementDiscardThresholdPropertyDescription", "The threshold for when to close discarded prepare statements on the server (calling a batch of sp_unprepares). A value of 1 or less will cause sp_unprepare to be called immediately on PreparedStatment close."}, {"R_enablePrepareOnFirstPreparedStatementCallPropertyDescription", "This setting specifies whether a prepared statement is prepared (sp_prepexec) on first use (property=true) or on second after first calling sp_executesql (property=false)."}, - {"R_statementPoolingCacheSizePropertyDescription", "This setting specifies the size of the prepared statement cache for a conection. A value less than 1 means no cache."}, + {"R_statementPoolingCacheSizePropertyDescription", "This setting specifies the size of the prepared statement cache for a connection. A value less than 1 means no cache."}, {"R_gsscredentialPropertyDescription", "Impersonated GSS Credential to access SQL Server."}, {"R_noParserSupport", "An error occurred while instantiating the required parser. Error: \"{0}\""}, {"R_writeOnlyXML", "Cannot read from this SQLXML instance. This instance is for writing data only."}, @@ -222,7 +222,7 @@ protected Object[][] getContents() { {"R_unableRetrieveSourceData", "Unable to retrieve data from the source."}, {"R_ParsingError", "Failed to parse data for the {0} type."}, {"R_BulkTypeNotSupported", "Data type {0} is not supported in bulk copy."}, - {"R_invalidTransactionOption", "UseInternalTransaction option can not be set to TRUE when used with a Connection object."}, + {"R_invalidTransactionOption", "UseInternalTransaction option cannot be set to TRUE when used with a Connection object."}, {"R_invalidNegativeArg", "The {0} argument cannot be negative."}, {"R_BulkColumnMappingsIsEmpty", "Cannot perform bulk copy operation if the only mapping is an identity column and KeepIdentity is set to false."}, {"R_CSVDataSchemaMismatch", "Source data does not match source schema."}, @@ -260,7 +260,7 @@ protected Object[][] getContents() { {"R_CertificateError", "Error occurred while retrieving certificate \"{0}\" from keystore \"{1}\"."}, {"R_ByteToShortConversion", "Error occurred while decrypting column encryption key."}, {"R_InvalidCertificateSignature", "The specified encrypted column encryption key signature does not match the signature computed with the column master key (certificate) in \"{0}\". The encrypted column encryption key may be corrupt, or the specified path may be incorrect."}, - {"R_CEKDecryptionFailed", "Exception while decryption of encrypted column encryption key : {0} "}, + {"R_CEKDecryptionFailed", "Exception while decryption of encrypted column encryption key: {0} "}, {"R_NullKeyEncryptionAlgorithm", "Key encryption algorithm cannot be null."}, {"R_NullKeyEncryptionAlgorithmInternal", "Internal error. Key encryption algorithm cannot be null."}, {"R_InvalidKeyEncryptionAlgorithm", "Invalid key encryption algorithm specified: {0}. Expected value: {1}."}, @@ -268,7 +268,7 @@ protected Object[][] getContents() { {"R_NullColumnEncryptionKey", "Column encryption key cannot be null."}, {"R_EmptyColumnEncryptionKey", "Empty column encryption key specified."}, {"R_CertificateNotFoundForAlias", "Certificate with alias {0} not found in the store provided by {1}. Verify the certificate has been imported correctly into the certificate location/store."}, - {"R_UnrecoverableKeyAE", "Cannot recover private key from keystore with certificate details {0}. Verify that imported AE certificate contains private key and password provided for certificate is correct."}, + {"R_UnrecoverableKeyAE", "Cannot recover private key from keystore with certificate details {0}. Verify that imported certificate for Always Encrypted contains private key and password provided for certificate is correct."}, {"R_KeyStoreNotFound", "System cannot find the key store file at the specified path. Verify that the path is correct and you have proper permissions to access it."}, {"R_CustomKeyStoreProviderMapNull", "Column encryption key store provider map cannot be null. Expecting a non-null value."}, {"R_EmptyCustomKeyStoreProviderName", "Invalid key store provider name specified. Key store provider names cannot be null or empty."}, @@ -306,7 +306,7 @@ protected Object[][] getContents() { {"R_ForceEncryptionTrue_HonorAETrue_UnencryptedColumnRS", "Cannot execute update because Force Encryption was set as true for parameter {0} and the database expects this parameter to be sent as plaintext. This may be due to a configuration error."}, {"R_NullValue","{0} cannot be null."}, {"R_AKVPathNull", "Azure Key Vault key path cannot be null." }, - {"R_AKVURLInvalid", "Invalid url specified: {0}." }, + {"R_AKVURLInvalid", "Invalid URL specified: {0}." }, {"R_AKVMasterKeyPathInvalid", "Invalid Azure Key Vault key path specified: {0}."}, {"R_EmptyCEK","Empty column encryption key specified."}, {"R_EncryptedCEKNull","Encrypted column encryption key cannot be null."}, @@ -320,8 +320,8 @@ protected Object[][] getContents() { {"R_NoSHA256Algorithm","SHA-256 Algorithm is not supported."}, {"R_VerifySignature","Unable to verify signature of the column encryption key."}, {"R_CEKSignatureNotMatchCMK","The specified encrypted column encryption key signature does not match the signature computed with the column master key (Asymmetric key in Azure Key Vault) in {0}. The encrypted column encryption key may be corrupt, or the specified path may be incorrect."}, - {"R_DecryptCEKError","Unable to decrypt CEK using specified Azure Key Vault key."}, - {"R_EncryptCEKError","Unable to encrypt CEK using specified Azure Key Vault key."}, + {"R_DecryptCEKError","Unable to decrypt column encryption key using specified Azure Key Vault key."}, + {"R_EncryptCEKError","Unable to encrypt column encryption key using specified Azure Key Vault key."}, {"R_CipherTextLengthNotMatchRSASize","CipherText length does not match the RSA key size."}, {"R_GenerateSignature","Unable to generate signature using a specified Azure Key Vault Key URL."}, {"R_SignedHashLengthError","Signed hash length does not match the RSA key size."}, @@ -363,8 +363,7 @@ protected Object[][] getContents() { {"R_keyStoreAuthenticationPropertyDescription", "The name that identifies a key store."}, {"R_keyStoreSecretPropertyDescription", "The authentication secret or information needed to locate the secret."}, {"R_keyStoreLocationPropertyDescription", "The key store location."}, - {"R_fipsProviderPropertyDescription", "FIPS Provider."}, - {"R_keyStoreAuthenticationNotSet", "\"keyStoreAuthentication\" connection string keyword must be specified, if \"{0}\" is specified."}, + {"R_keyStoreAuthenticationNotSet", "\"keyStoreAuthentication\" connection string keyword must be specified, if \"{0}\" is specified."}, {"R_keyStoreSecretOrLocationNotSet", "Both \"keyStoreSecret\" and \"keyStoreLocation\" must be set, if \"keyStoreAuthentication=JavaKeyStorePassword\" has been specified in the connection string."}, {"R_certificateStoreInvalidKeyword", "Cannot set \"keyStoreSecret\", if \"keyStoreAuthentication=CertificateStore\" has been specified in the connection string."}, {"R_certificateStoreLocationNotSet", "\"keyStoreLocation\" must be specified, if \"keyStoreAuthentication=CertificateStore\" has been specified in the connection string."}, @@ -372,13 +371,11 @@ protected Object[][] getContents() { {"R_invalidKeyStoreFile", "Cannot parse \"{0}\". Either the file format is not valid or the password is not correct."}, // for JKS/PKCS {"R_invalidCEKCacheTtl", "Invalid column encryption key cache time-to-live specified. The columnEncryptionKeyCacheTtl value cannot be negative and timeUnit can only be DAYS, HOURS, MINUTES or SECONDS."}, {"R_sendTimeAsDateTimeForAE", "Use sendTimeAsDateTime=false with Always Encrypted."}, - {"R_TVPnotWorkWithSetObjectResultSet" , "setObject() with ResultSet is not supported for Table-Valued Parameter. Please use setStructured()."}, + {"R_TVPnotWorkWithSetObjectResultSet", "setObject() with ResultSet is not supported for Table-Valued Parameter. Please use setStructured()."}, {"R_invalidQueryTimeout", "The queryTimeout {0} is not valid."}, {"R_invalidSocketTimeout", "The socketTimeout {0} is not valid."}, - {"R_fipsPropertyDescription", "Determines if enable FIPS compilant SSL connection between the client and the server."}, - {"R_invalidFipsConfig", "Could not enable FIPS."}, - {"R_invalidFipsEncryptConfig", "Could not enable FIPS due to either encrypt is not true or using trusted certificate settings."}, - {"R_invalidFipsProviderConfig", "Could not enable FIPS due to invalid FIPSProvider or TrustStoreType."}, + {"R_fipsPropertyDescription", "Determines if FIPS mode is enabled."}, + {"R_invalidFipsConfig", "Unable to verify FIPS mode settings."}, {"R_serverPreparedStatementDiscardThreshold", "The serverPreparedStatementDiscardThreshold {0} is not valid."}, {"R_statementPoolingCacheSize", "The statementPoolingCacheSize {0} is not valid."}, {"R_kerberosLoginFailedForUsername", "Cannot login with Kerberos principal {0}, check your credentials. {1}"}, @@ -386,9 +383,12 @@ protected Object[][] getContents() { {"R_StoredProcedureNotFound", "Could not find stored procedure ''{0}''."}, {"R_jaasConfigurationNamePropertyDescription", "Login configuration file for Kerberos authentication."}, {"R_AKVKeyNotFound", "Key not found: {0}"}, - {"R_SQLVariantSupport", "SQL_VARIANT datatype is not supported in pre-SQL 2008 version."}, - {"R_invalidProbbytes", "SQL_VARIANT: invalid probBytes for {0} type."}, - {"R_invalidStringValue", "SQL_VARIANT does not support string values more than 8000 length."}, - {"R_invalidValueForTVPWithSQLVariant", "Inserting null value with column type sql_variant in TVP is not supported."}, + {"R_SQLVariantSupport", "SQL_VARIANT is not supported in versions of SQL Server before 2008."}, + {"R_invalidProbbytes", "SQL_VARIANT: invalid probBytes for {0} type."}, + {"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."}, }; -} +} \ 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 936e4727e4..e937b27c36 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java @@ -1796,8 +1796,7 @@ private void cancelInsert() { /** Clear any updated column values for the current row in the result set. */ final void clearColumnsValues() { int l = columns.length; - for (int i = 0; i < l; i++) - columns[i].cancelUpdates(); + for (Column column : columns) column.cancelUpdates(); } /* L0 */ public SQLWarning getWarnings() throws SQLServerException { @@ -5684,14 +5683,14 @@ final boolean doExecute() throws SQLServerException { // If no values were set for any columns and no columns are updatable, // then the table name cannot be determined, so error. Column tableColumn = null; - for (int i = 0; i < columns.length; i++) { - if (columns[i].hasUpdates()) { - tableColumn = columns[i]; + for (Column column : columns) { + if (column.hasUpdates()) { + tableColumn = column; break; } - if (null == tableColumn && columns[i].isUpdatable()) - tableColumn = columns[i]; + if (null == tableColumn && column.isUpdatable()) + tableColumn = column; } if (null == tableColumn) { @@ -5726,8 +5725,7 @@ private void doInsertRowRPC(TDSCommand command, if (hasUpdatedColumns()) { tdsWriter.writeRPCStringUnicode(tableName); - for (int i = 0; i < columns.length; i++) - columns[i].sendByRPC(tdsWriter, stmt.connection); + for (Column column : columns) column.sendByRPC(tdsWriter, stmt.connection); } else { tdsWriter.writeRPCStringUnicode(""); @@ -5801,16 +5799,15 @@ private void doUpdateRowRPC(TDSCommand command) throws SQLServerException { assert hasUpdatedColumns(); - for (int i = 0; i < columns.length; i++) - columns[i].sendByRPC(tdsWriter, stmt.connection); + for (Column column : columns) column.sendByRPC(tdsWriter, stmt.connection); TDSParser.parse(command.startResponse(), command.getLogContext()); } /** Determines whether there are updated columns in this result set. */ final boolean hasUpdatedColumns() { - for (int i = 0; i < columns.length; i++) - if (columns[i].hasUpdates()) + for (Column column : columns) + if (column.hasUpdates()) return true; return false; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java index 632edf9e64..7f6d8e1d26 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java @@ -429,7 +429,7 @@ boolean onDone(TDSReader tdsReader) throws SQLServerException { * The array of objects in a batched call. Applicable to statements and prepared statements When the iterativeBatching property is turned on. */ /** The buffer that accumulates batchable statements */ - private final ArrayList batchStatementBuffer = new ArrayList(); + private final ArrayList batchStatementBuffer = new ArrayList<>(); /** logging init at the construction */ static final private java.util.logging.Logger stmtlogger = java.util.logging.Logger @@ -1512,7 +1512,7 @@ boolean onInfo(TDSReader tdsReader) throws SQLServerException { infoToken.msg.getErrorNumber()); if (sqlWarnings == null) { - sqlWarnings = new Vector(); + sqlWarnings = new Vector<>(); } else { int n = sqlWarnings.size(); @@ -2384,7 +2384,7 @@ int translateLimit(StringBuffer sql, Matcher offsetMatcher = limitSyntaxWithOffset.matcher(sql); int startIndx = indx; - Stack topPosition = new Stack(); + Stack topPosition = new Stack<>(); State nextState = State.START; while (indx < sql.length()) { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSymmetricKeyCache.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSymmetricKeyCache.java index 5799251d85..76b886786d 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSymmetricKeyCache.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSymmetricKeyCache.java @@ -68,7 +68,7 @@ public Thread newThread(Runnable r) { .getLogger("com.microsoft.sqlserver.jdbc.SQLServerSymmetricKeyCache"); private SQLServerSymmetricKeyCache() { - cache = new ConcurrentHashMap(); + cache = new ConcurrentHashMap<>(); } static SQLServerSymmetricKeyCache getInstance() { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAResource.java index 60c710bcc1..8e72d0f35a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAResource.java @@ -445,6 +445,7 @@ private String typeDisplay(int type) { case XA_START: if (!serverInfoRetrieved) { + Statement stmt = null; try { serverInfoRetrieved = true; // data are converted to varchar as type variant returned by SERVERPROPERTY is not supported by driver @@ -453,7 +454,7 @@ private String typeDisplay(int type) { + " convert(varchar(100), SERVERPROPERTY('ProductVersion')) as version," + " SUBSTRING(@@VERSION, CHARINDEX('<', @@VERSION)+2, 2)"; - Statement stmt = controlConnection.createStatement(); + stmt = controlConnection.createStatement(); ResultSet rs = stmt.executeQuery(query); rs.next(); @@ -475,7 +476,6 @@ else if (-1 != version.indexOf('.')) { ArchitectureOS = Integer.parseInt(rs.getString(4)); rs.close(); - stmt.close(); } // Got caught in static analysis. Catch only the thrown exceptions, do not catch // run time exceptions. @@ -483,6 +483,16 @@ else if (-1 != version.indexOf('.')) { if (xaLogger.isLoggable(Level.WARNING)) xaLogger.warning(toString() + " Cannot retrieve server information: :" + e.getMessage()); } + finally { + if (null != stmt) + try { + stmt.close(); + } + catch (SQLException e) { + if (xaLogger.isLoggable(Level.FINER)) + xaLogger.finer(toString()); + } + } } sContext = "START:"; @@ -792,7 +802,7 @@ else if (-1 != version.indexOf('.')) { /* L0 */ public Xid[] recover(int flags) throws XAException { XAReturnValue r = DTC_XA_Interface(XA_RECOVER, null, flags | tightlyCoupled); int offset = 0; - ArrayList al = new ArrayList(); + ArrayList al = new ArrayList<>(); // If no XID's found, return zero length XID array (don't return null). // diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/StreamColInfo.java b/src/main/java/com/microsoft/sqlserver/jdbc/StreamColInfo.java index a5fcc1b2ff..e0d7eaeb5c 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/StreamColInfo.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/StreamColInfo.java @@ -36,9 +36,7 @@ int applyTo(Column[] columns) throws SQLServerException { // Read and apply the column info for each column TDSReaderMark currentMark = tdsReader.mark(); tdsReader.reset(colInfoMark); - for (int i = 0; i < columns.length; i++) { - Column col = columns[i]; - + for (Column col : columns) { // Ignore the column number, per TDS spec. // Column info is returned for each column, ascending by column index, // so iterating through the column info is sufficient. diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/StreamTabName.java b/src/main/java/com/microsoft/sqlserver/jdbc/StreamTabName.java index 1dc2a50851..6690990b1d 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/StreamTabName.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/StreamTabName.java @@ -44,9 +44,7 @@ void applyTo(Column[] columns, tableNames[i] = tdsReader.readSQLIdentifier(); // Apply the table names to their appropriate columns - for (int i = 0; i < columns.length; i++) { - Column col = columns[i]; - + for (Column col : columns) { if (col.getTableNum() > 0) col.setTableName(tableNames[col.getTableNum() - 1]); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/TVP.java b/src/main/java/com/microsoft/sqlserver/jdbc/TVP.java index 5113f1fc05..6f68d685a9 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/TVP.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/TVP.java @@ -62,7 +62,7 @@ enum MPIState { void initTVP(TVPType type, String tvpPartName) throws SQLServerException { tvpType = type; - columnMetadata = new LinkedHashMap(); + columnMetadata = new LinkedHashMap<>(); parseTypeName(tvpPartName); } @@ -157,9 +157,7 @@ void populateMetadataFromDataTable() throws SQLServerException { if (null == dataTableMetaData || dataTableMetaData.isEmpty()) { throw new SQLServerException(SQLServerException.getErrString("R_TVPEmptyMetadata"), null); } - Iterator> columnsIterator = dataTableMetaData.entrySet().iterator(); - while (columnsIterator.hasNext()) { - Map.Entry pair = columnsIterator.next(); + for (Entry pair : dataTableMetaData.entrySet()) { // duplicate column names for the dataTable will be checked in the SQLServerDataTable. columnMetadata.put(pair.getKey(), new SQLServerMetaData(pair.getValue().columnName, pair.getValue().javaSqlType, pair.getValue().precision, pair.getValue().scale)); @@ -200,9 +198,7 @@ void validateOrderProperty() throws SQLServerException { int maxSortOrdinal = -1; int sortCount = 0; - Iterator> columnsIterator = columnMetadata.entrySet().iterator(); - while (columnsIterator.hasNext()) { - Map.Entry columnPair = columnsIterator.next(); + for (Entry columnPair : columnMetadata.entrySet()) { SQLServerSortOrder columnSortOrder = columnPair.getValue().sortOrder; int columnSortOrdinal = columnPair.getValue().sortOrdinal; @@ -210,13 +206,13 @@ void validateOrderProperty() throws SQLServerException { // check if there's no way sort order could be monotonically increasing if (columnCount <= columnSortOrdinal) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_TVPSortOrdinalGreaterThanFieldCount")); - throw new SQLServerException(form.format(new Object[] {columnSortOrdinal, columnPair.getKey()}), null, 0, null); + throw new SQLServerException(form.format(new Object[]{columnSortOrdinal, columnPair.getKey()}), null, 0, null); } // Check to make sure we haven't seen this ordinal before if (sortOrdinalSpecified[columnSortOrdinal]) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_TVPDuplicateSortOrdinal")); - throw new SQLServerException(form.format(new Object[] {columnSortOrdinal}), null, 0, null); + throw new SQLServerException(form.format(new Object[]{columnSortOrdinal}), null, 0, null); } sortOrdinalSpecified[columnSortOrdinal] = true; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/Util.java b/src/main/java/com/microsoft/sqlserver/jdbc/Util.java index d630d6e48a..db10ebce1e 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/Util.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/Util.java @@ -626,8 +626,8 @@ static String byteToHexDisplayString(byte[] b) { int hexVal; StringBuilder sb = new StringBuilder(b.length * 2 + 2); sb.append("0x"); - for (int i = 0; i < b.length; i++) { - hexVal = b[i] & 0xFF; + for (byte aB : b) { + hexVal = aB & 0xFF; sb.append(hexChars[(hexVal & 0xF0) >> 4]); sb.append(hexChars[(hexVal & 0x0F)]); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/dns/DNSUtilities.java b/src/main/java/com/microsoft/sqlserver/jdbc/dns/DNSUtilities.java index 3a91a3071e..483ad3635f 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/dns/DNSUtilities.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/dns/DNSUtilities.java @@ -36,13 +36,13 @@ public class DNSUtilities { * if DNS is not available */ public static Set findSrvRecords(final String dnsSrvRecordToFind) throws NamingException { - Hashtable env = new Hashtable(); + Hashtable env = new Hashtable<>(); env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory"); env.put("java.naming.provider.url", "dns:"); DirContext ctx = new InitialDirContext(env); Attributes attrs = ctx.getAttributes(dnsSrvRecordToFind, new String[] {"SRV"}); NamingEnumeration allServers = attrs.getAll(); - TreeSet records = new TreeSet(); + TreeSet records = new TreeSet<>(); while (allServers.hasMoreElements()) { Attribute a = allServers.nextElement(); NamingEnumeration srvRecord = a.getAll(); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/dtv.java b/src/main/java/com/microsoft/sqlserver/jdbc/dtv.java index 5030c22c94..0ac8eb1083 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/dtv.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/dtv.java @@ -3104,7 +3104,7 @@ public void apply(TypeInfo typeInfo, */ public void apply(TypeInfo typeInfo, TDSReader tdsReader) throws SQLServerException { - typeInfo.ssLenType = SSLenType.LONGLENTYPE; //Variant type should be LONGLENTYPE length. + typeInfo.ssLenType = SSLenType.LONGLENTYPE; //sql_variant type should be LONGLENTYPE length. typeInfo.maxLength = tdsReader.readInt(); typeInfo.ssType = SSType.SQL_VARIANT; } @@ -3334,7 +3334,7 @@ boolean supportsFastAsciiConversion() { } } - private static final Map builderMap = new EnumMap(TDSType.class); + private static final Map builderMap = new EnumMap<>(TDSType.class); static { for (Builder builder : Builder.values()) @@ -4115,7 +4115,6 @@ else if (TDSType.NUMERICN == baseType) case MONEY4: jdbcType = JDBCType.SMALLMONEY; - typeInfo.setMaxLength(4); precision = Long.toString(Long.MAX_VALUE).length(); typeInfo.setPrecision(precision); scale = 4; @@ -4128,7 +4127,6 @@ else if (TDSType.NUMERICN == baseType) case MONEY8: jdbcType = JDBCType.MONEY; - typeInfo.setMaxLength(8); precision = Long.toString(Long.MAX_VALUE).length(); scale = 4; typeInfo.setPrecision(precision); @@ -4179,9 +4177,7 @@ else if (TDSType.BIGCHAR == baseType) jdbcType = JDBCType.CHAR; collation = tdsReader.readCollation(); typeInfo.setSQLCollation(collation); - typeInfo.setSSLenType(SSLenType.USHORTLENTYPE); maxLength = tdsReader.readUnsignedShort(); - typeInfo.setMaxLength(maxLength); if (maxLength > DataTypes.SHORT_VARTYPE_MAX_BYTES) tdsReader.throwInvalidTDS(); typeInfo.setDisplaySize(maxLength); @@ -4205,7 +4201,6 @@ else if (TDSType.NVARCHAR == baseType) jdbcType = JDBCType.NVARCHAR; collation = tdsReader.readCollation(); typeInfo.setSQLCollation(collation); - typeInfo.setSSLenType(SSLenType.USHORTLENTYPE); maxLength = tdsReader.readUnsignedShort(); if (maxLength > DataTypes.SHORT_VARTYPE_MAX_BYTES || 0 != maxLength % 2) tdsReader.throwInvalidTDS(); @@ -4238,7 +4233,6 @@ else if (TDSType.NVARCHAR == baseType) MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidProbbytes")); throw new SQLServerException(form.format(new Object[] {baseType}), null, 0, null); } - jdbcType = JDBCType.CHAR; // The reason we use char is to return nanoseconds if (internalVariant.isBaseTypeTimeValue()) { jdbcType = JDBCType.TIMESTAMP; } @@ -4272,7 +4266,6 @@ else if (TDSType.BIGVARBINARY == baseType) jdbcType = JDBCType.VARBINARY; maxLength = tdsReader.readUnsignedShort(); internalVariant.setMaxLength(maxLength); - typeInfo.setMaxLength(maxLength); if (maxLength > DataTypes.SHORT_VARTYPE_MAX_BYTES) tdsReader.throwInvalidTDS(); typeInfo.setDisplaySize(2 * maxLength); @@ -4290,10 +4283,12 @@ else if (TDSType.BIGVARBINARY == baseType) convertedValue = tdsReader.readGUID(expectedValueLength, jdbcType, streamGetterArgs.streamType); break; - // Unknown SSType should have already been rejected by TypeInfo.setFromTDS() - default: - assert false : "Unexpected TDSType in Sql-Variant " + baseType; - break; + // Unsupported TdsType should throw error message + default: { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidDataTypeSupportForSQLVariant")); + throw new SQLServerException(form.format(new Object[] {baseType}), null, 0, null); + } + } return convertedValue; } diff --git a/src/main/java/mssql/googlecode/concurrentlinkedhashmap/Weighers.java b/src/main/java/mssql/googlecode/concurrentlinkedhashmap/Weighers.java index 29194547df..2dd4531d0c 100644 --- a/src/main/java/mssql/googlecode/concurrentlinkedhashmap/Weighers.java +++ b/src/main/java/mssql/googlecode/concurrentlinkedhashmap/Weighers.java @@ -247,10 +247,9 @@ public int weightOf(Iterable values) { return ((Collection) values).size(); } int size = 0; - for (Iterator i = values.iterator(); i.hasNext();) { - i.next(); - size++; - } + for (Object value : values) { + size++; + } return size; } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyConnectionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyConnectionTest.java index b75584ede8..340dbb3eb1 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyConnectionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyConnectionTest.java @@ -161,7 +161,7 @@ void testEmptyBulkCopyOptions() { */ List createTestDatatestBulkCopyConstructor() { String testCaseName = "BulkCopyConstructor "; - List testData = new ArrayList(); + List testData = new ArrayList<>(); BulkCopyTestWrapper bulkWrapper1 = new BulkCopyTestWrapper(connectionString); bulkWrapper1.testName = testCaseName; bulkWrapper1.setUsingConnection(true); @@ -182,14 +182,14 @@ List createTestDatatestBulkCopyConstructor() { */ private List createTestDatatestBulkCopyOption() { String testCaseName = "BulkCopyOption "; - List testData = new ArrayList(); + List testData = new ArrayList<>(); Class bulkOptions = SQLServerBulkCopyOptions.class; Method[] methods = bulkOptions.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { + for (Method method : methods) { // set bulkCopy Option if return is void and input is boolean - if (0 != methods[i].getParameterTypes().length && boolean.class == methods[i].getParameterTypes()[0]) { + if (0 != method.getParameterTypes().length && boolean.class == method.getParameterTypes()[0]) { try { BulkCopyTestWrapper bulkWrapper = new BulkCopyTestWrapper(connectionString); @@ -197,16 +197,15 @@ private List createTestDatatestBulkCopyOption() { bulkWrapper.setUsingConnection((0 == ThreadLocalRandom.current().nextInt(2)) ? true : false); SQLServerBulkCopyOptions option = new SQLServerBulkCopyOptions(); - if (!(methods[i].getName()).equalsIgnoreCase("setUseInternalTransaction") - && !(methods[i].getName()).equalsIgnoreCase("setAllowEncryptedValueModifications")) { - methods[i].invoke(option, true); + if (!(method.getName()).equalsIgnoreCase("setUseInternalTransaction") + && !(method.getName()).equalsIgnoreCase("setAllowEncryptedValueModifications")) { + method.invoke(option, true); bulkWrapper.useBulkCopyOptions(true); bulkWrapper.setBulkOptions(option); - bulkWrapper.testName += methods[i].getName() + ";"; + bulkWrapper.testName += method.getName() + ";"; testData.add(bulkWrapper); } - } - catch (Exception ex) { + } catch (Exception ex) { fail(ex.getMessage()); } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyISQLServerBulkRecordTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyISQLServerBulkRecordTest.java index f33a3bb601..60e7e3da45 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyISQLServerBulkRecordTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyISQLServerBulkRecordTest.java @@ -99,7 +99,7 @@ private class ColumnMetadata { List data; BulkData() { - columnMetadata = new HashMap(); + columnMetadata = new HashMap<>(); totalColumn = dstTable.totalColumns(); // add metadata @@ -116,7 +116,7 @@ private class ColumnMetadata { // add data rowCount = dstTable.getTotalRows(); - data = new ArrayList(rowCount); + data = new ArrayList<>(rowCount); for (int i = 0; i < rowCount; i++) { Object[] CurrentRow = new Object[totalColumn]; for (int j = 0; j < totalColumn; j++) { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyTestWrapper.java b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyTestWrapper.java index 2eaa7f6ab2..c6be7261cf 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyTestWrapper.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyTestWrapper.java @@ -35,7 +35,7 @@ class BulkCopyTestWrapper { */ private boolean isUsingColumnMapping = false; - public LinkedList cm = new LinkedList(); + public LinkedList cm = new LinkedList<>(); private SQLServerBulkCopyOptions bulkOptions; diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/ImpISQLServerBulkRecord_IssuesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/ISQLServerBulkRecordIssuesTest.java similarity index 94% rename from src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/ImpISQLServerBulkRecord_IssuesTest.java rename to src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/ISQLServerBulkRecordIssuesTest.java index 19106b0029..1b45d54a54 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/ImpISQLServerBulkRecord_IssuesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/ISQLServerBulkRecordIssuesTest.java @@ -38,7 +38,7 @@ import com.microsoft.sqlserver.testframework.Utils; @RunWith(JUnitPlatform.class) -public class ImpISQLServerBulkRecord_IssuesTest extends AbstractTest { +public class ISQLServerBulkRecordIssuesTest extends AbstractTest { static Statement stmt = null; static PreparedStatement pStmt = null; @@ -289,53 +289,53 @@ private class ColumnMetadata { BulkDat(String variation) { if (variation.equalsIgnoreCase("testVarchar")) { isStringData = true; - columnMetadata = new HashMap(); + columnMetadata = new HashMap<>(); columnMetadata.put(1, new ColumnMetadata("varchar(2)", java.sql.Types.VARCHAR, 0, 0)); - stringData = new ArrayList(); + stringData = new ArrayList<>(); stringData.add(new String("aaa")); rowCount = stringData.size(); } else if (variation.equalsIgnoreCase("testSmalldatetime")) { isStringData = false; - columnMetadata = new HashMap(); + columnMetadata = new HashMap<>(); columnMetadata.put(1, new ColumnMetadata("smallDatetime", java.sql.Types.TIMESTAMP, 0, 0)); - dateData = new ArrayList(); + dateData = new ArrayList<>(); dateData.add(Timestamp.valueOf("1954-05-22 02:43:37.123")); rowCount = dateData.size(); } else if (variation.equalsIgnoreCase("testSmalldatetimeOutofRange")) { isStringData = false; - columnMetadata = new HashMap(); + columnMetadata = new HashMap<>(); columnMetadata.put(1, new ColumnMetadata("smallDatetime", java.sql.Types.TIMESTAMP, 0, 0)); - dateData = new ArrayList(); + dateData = new ArrayList<>(); dateData.add(Timestamp.valueOf("1954-05-22 02:43:37.1234")); rowCount = dateData.size(); } else if (variation.equalsIgnoreCase("testBinaryColumnAsByte")) { isStringData = false; - columnMetadata = new HashMap(); + columnMetadata = new HashMap<>(); columnMetadata.put(1, new ColumnMetadata("binary(5)", java.sql.Types.BINARY, 5, 0)); - byteData = new ArrayList(); + byteData = new ArrayList<>(); byteData.add("helloo".getBytes()); rowCount = byteData.size(); } else if (variation.equalsIgnoreCase("testBinaryColumnAsString")) { isStringData = true; - columnMetadata = new HashMap(); + columnMetadata = new HashMap<>(); columnMetadata.put(1, new ColumnMetadata("binary(5)", java.sql.Types.BINARY, 5, 0)); - stringData = new ArrayList(); + stringData = new ArrayList<>(); stringData.add("616368697412"); rowCount = stringData.size(); @@ -343,11 +343,11 @@ else if (variation.equalsIgnoreCase("testBinaryColumnAsString")) { else if (variation.equalsIgnoreCase("testSendValidValueforBinaryColumnAsString")) { isStringData = true; - columnMetadata = new HashMap(); + columnMetadata = new HashMap<>(); columnMetadata.put(1, new ColumnMetadata("binary(5)", java.sql.Types.BINARY, 5, 0)); - stringData = new ArrayList(); + stringData = new ArrayList<>(); stringData.add("010101"); rowCount = stringData.size(); 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 da24e42d02..d0271714d3 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableStatementTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableStatementTest.java @@ -6,6 +6,7 @@ import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; +import java.sql.Types; import java.util.UUID; import org.junit.jupiter.api.AfterAll; @@ -15,6 +16,7 @@ import org.junit.runner.RunWith; import com.microsoft.sqlserver.jdbc.SQLServerCallableStatement; +import com.microsoft.sqlserver.jdbc.SQLServerDataSource; import com.microsoft.sqlserver.testframework.AbstractTest; import com.microsoft.sqlserver.testframework.Utils; @@ -25,6 +27,7 @@ public class CallableStatementTest extends AbstractTest { private static String tableNameGUID = "uniqueidentifier_Table"; private static String outputProcedureNameGUID = "uniqueidentifier_SP"; + private static String setNullProcedureName = "CallableStatementTest_setNull_SP"; private static Connection connection = null; private static Statement stmt = null; @@ -41,9 +44,11 @@ public static void setupTest() throws SQLException { Utils.dropTableIfExists(tableNameGUID, stmt); Utils.dropProcedureIfExists(outputProcedureNameGUID, stmt); + Utils.dropProcedureIfExists(setNullProcedureName, stmt); createGUIDTable(); createGUIDStoredProcedure(); + createSetNullPreocedure(); } /** @@ -79,6 +84,55 @@ public void getStringGUIDTest() throws SQLException { } } + /** + * test for setNull(index, varchar) to behave as setNull(index, nvarchar) when SendStringParametersAsUnicode is true + * + * @throws SQLException + */ + @Test + public void getSetNullWithTypeVarchar() throws SQLException { + String polishchar = "\u0143"; + + SQLServerCallableStatement cs = null; + SQLServerCallableStatement cs2 = null; + try { + SQLServerDataSource ds = new SQLServerDataSource(); + ds.setURL(connectionString); + ds.setSendStringParametersAsUnicode(true); + connection = ds.getConnection(); + + String sql = "{? = call " + setNullProcedureName + " (?,?)}"; + + cs = (SQLServerCallableStatement) connection.prepareCall(sql); + cs.registerOutParameter(1, Types.INTEGER); + cs.setString(2, polishchar); + cs.setString(3, null); + cs.registerOutParameter(3, Types.VARCHAR); + cs.execute(); + + String expected = cs.getString(3); + + cs2 = (SQLServerCallableStatement) connection.prepareCall(sql); + cs2.registerOutParameter(1, Types.INTEGER); + cs2.setString(2, polishchar); + cs2.setNull(3, Types.VARCHAR); + cs2.registerOutParameter(3, Types.NVARCHAR); + cs2.execute(); + + String actual = cs2.getString(3); + + assertEquals(expected, actual); + } + finally { + if (null != cs) { + cs.close(); + } + if (null != cs2) { + cs2.close(); + } + } + } + /** * Cleanup after test * @@ -88,6 +142,8 @@ public void getStringGUIDTest() throws SQLException { public static void cleanup() throws SQLException { Utils.dropTableIfExists(tableNameGUID, stmt); Utils.dropProcedureIfExists(outputProcedureNameGUID, stmt); + Utils.dropProcedureIfExists(setNullProcedureName, stmt); + if (null != stmt) { stmt.close(); } @@ -105,4 +161,8 @@ private static void createGUIDTable() throws SQLException { String sql = "CREATE TABLE " + tableNameGUID + " (c1 uniqueidentifier null)"; stmt.execute(sql); } + + private static void createSetNullPreocedure() throws SQLException { + stmt.execute("create procedure " + setNullProcedureName + " (@p1 nvarchar(255), @p2 nvarchar(255) output) as select @p2=@p1 return 0"); + } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/connection/ConnectionDriverTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/connection/ConnectionDriverTest.java index d6d2c5cb41..c8a4155400 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/connection/ConnectionDriverTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/connection/ConnectionDriverTest.java @@ -29,6 +29,7 @@ import javax.sql.ConnectionEvent; import javax.sql.PooledConnection; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; @@ -65,28 +66,28 @@ public void testConnectionDriver() throws SQLServerException { url.append("jdbc:sqlserver://" + randomServer + ";packetSize=512;"); // test defaults DriverPropertyInfo[] infoArray = d.getPropertyInfo(url.toString(), info); - for (int i = 0; i < infoArray.length; i++) { - logger.fine(infoArray[i].name); - logger.fine(infoArray[i].description); - logger.fine(new Boolean(infoArray[i].required).toString()); - logger.fine(infoArray[i].value); + for (DriverPropertyInfo anInfoArray1 : infoArray) { + logger.fine(anInfoArray1.name); + logger.fine(anInfoArray1.description); + logger.fine(new Boolean(anInfoArray1.required).toString()); + logger.fine(anInfoArray1.value); } url.append("encrypt=true; trustStore=someStore; trustStorePassword=somepassword;"); url.append("hostNameInCertificate=someHost; trustServerCertificate=true"); infoArray = d.getPropertyInfo(url.toString(), info); - for (int i = 0; i < infoArray.length; i++) { - if (infoArray[i].name.equals("encrypt")) { - assertTrue(infoArray[i].value.equals("true"), "Values are different"); + for (DriverPropertyInfo anInfoArray : infoArray) { + if (anInfoArray.name.equals("encrypt")) { + assertTrue(anInfoArray.value.equals("true"), "Values are different"); } - if (infoArray[i].name.equals("trustStore")) { - assertTrue(infoArray[i].value.equals("someStore"), "Values are different"); + if (anInfoArray.name.equals("trustStore")) { + assertTrue(anInfoArray.value.equals("someStore"), "Values are different"); } - if (infoArray[i].name.equals("trustStorePassword")) { - assertTrue(infoArray[i].value.equals("somepassword"), "Values are different"); + if (anInfoArray.name.equals("trustStorePassword")) { + assertTrue(anInfoArray.value.equals("somepassword"), "Values are different"); } - if (infoArray[i].name.equals("hostNameInCertificate")) { - assertTrue(infoArray[i].value.equals("someHost"), "Values are different"); + if (anInfoArray.name.equals("hostNameInCertificate")) { + assertTrue(anInfoArray.value.equals("someHost"), "Values are different"); } } } @@ -462,6 +463,7 @@ public void testInvalidCombination() throws SQLServerException { } @Test + @Tag("slow") public void testIncorrectDatabaseWithFailoverPartner() throws SQLServerException { long timerStart = 0; long timerEnd = 0; @@ -522,6 +524,7 @@ public void testGetSchema() throws SQLException { * @throws InterruptedException */ @Test + @Tag("slow") public void testThreadInterruptedStatus() throws InterruptedException { Runnable runnable = new Runnable() { public void run() { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/connection/SSLProtocolTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/connection/SSLProtocolTest.java new file mode 100644 index 0000000000..5d06220b84 --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/jdbc/connection/SSLProtocolTest.java @@ -0,0 +1,104 @@ +/* + * 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.connection; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.DriverManager; +import java.sql.Statement; + +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.jdbc.StringUtils; +import com.microsoft.sqlserver.testframework.AbstractTest; + +/** + * Tests new connection property sslProtocol + */ +@RunWith(JUnitPlatform.class) +public class SSLProtocolTest extends AbstractTest { + + Connection con = null; + Statement stmt = null; + + /** + * Connect with supported protocol + * + * @param sslProtocol + * @throws Exception + */ + public void testWithSupportedProtocols(String sslProtocol) throws Exception { + String url = connectionString + ";sslProtocol=" + sslProtocol; + try { + con = DriverManager.getConnection(url); + DatabaseMetaData dbmd = con.getMetaData(); + assertNotNull(dbmd); + assertTrue(!StringUtils.isEmpty(dbmd.getDatabaseProductName())); + } + catch (SQLServerException e) { + // Some older versions of SQLServer might not have all the TLS protocol versions enabled. + // Example, if the highest TLS version enabled in the server is TLSv1.1, + // the connection will fail if we enable only TLSv1.2 + assertTrue(e.getMessage().contains("protocol version is not enabled or not supported by the client.")); + } + } + + + /** + * Connect with unsupported protocol + * + * @param sslProtocol + * @throws Exception + */ + 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"); + } + 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."; + assertTrue(errMsg.equals(e.getMessage()), "Message should be from SQL Server resources : " + e.getMessage()); + } + } + + /** + * Test with unsupported protocols. + * + * @throws Exception + */ + @Test + public void testConnectWithWrongProtocols() throws Exception { + String[] wrongProtocols = {"SSLv1111", "SSLv2222", "SSLv3111", "SSLv2Hello1111", "TLSv1.11", "TLSv2.4", "random"}; + for (String wrongProtocol : wrongProtocols) { + testWithUnSupportedProtocols(wrongProtocol); + } + } + + /** + * Test with supported protocols. + * + * @throws Exception + */ + @Test + public void testConnectWithSupportedProtocols() throws Exception { + String[] supportedProtocols = {"TLS", "TLSv1", "TLSv1.1", "TLSv1.2"}; + for (String supportedProtocol : supportedProtocols) { + testWithSupportedProtocols(supportedProtocol); + } + } +} + diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/connection/TimeoutTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/connection/TimeoutTest.java index a4b8393422..2141cac429 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/connection/TimeoutTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/connection/TimeoutTest.java @@ -14,6 +14,7 @@ import java.sql.DriverManager; import java.sql.SQLException; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; @@ -31,6 +32,7 @@ public class TimeoutTest extends AbstractTest { final int waitForDelaySeconds = 10; @Test + @Tag("slow") public void testDefaultLoginTimeout() { long timerStart = 0; long timerEnd = 0; diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BulkCopyWithSqlVariantTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BulkCopyWithSqlVariantTest.java index 2f2c4b9b7d..2c4a419807 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BulkCopyWithSqlVariantTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BulkCopyWithSqlVariantTest.java @@ -617,7 +617,7 @@ public void bulkCopyTestTime() throws SQLException { rs = (SQLServerResultSet) stmt.executeQuery("SELECT * FROM " + destTableName); rs.next(); - assertEquals("" + rs.getObject(1).toString(), "12:26:27.15"); // TODO + assertEquals("" + rs.getObject(1).toString(), "12:26:27"); } /** diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SQLVariantResultSetTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SQLVariantResultSetTest.java index bf14063a24..5d47403054 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SQLVariantResultSetTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SQLVariantResultSetTest.java @@ -9,6 +9,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.math.BigDecimal; @@ -131,7 +132,7 @@ public void readTime() throws SQLException { createAndPopulateTable("time(3)", value); rs = (SQLServerResultSet) stmt.executeQuery("SELECT * FROM " + tableName); rs.next(); - assertEquals("" + rs.getObject(1).toString(), "12:26:27.123"); // TODO + assertEquals("" + rs.getObject(1).toString(), "12:26:27"); } /** @@ -640,7 +641,7 @@ public void callableStatementOutputDateTest() throws SQLException { @Test public void callableStatementOutputTimeTest() throws SQLException { String value = "12:26:27.123345"; - String returnValue = "12:26:27.123"; + String returnValue = "12:26:27"; Utils.dropTableIfExists(tableName, stmt); stmt.executeUpdate("create table " + tableName + " (col1 sql_variant)"); stmt.executeUpdate("INSERT into " + tableName + " values (CAST ('" + value + "' AS " + "time(3)" + "))"); @@ -652,7 +653,7 @@ public void callableStatementOutputTimeTest() throws SQLException { CallableStatement cs = con.prepareCall(" {call " + inputProc + " (?) }"); cs.registerOutParameter(1, microsoft.sql.Types.SQL_VARIANT, 3); cs.execute(); - assertEquals(cs.getString(1), String.valueOf(returnValue)); + assertEquals(String.valueOf(returnValue), "" + cs.getObject(1)); if (null != cs) { cs.close(); } @@ -803,6 +804,56 @@ public void readSeveralRows() throws SQLException { } } + + /** + * Test retrieving values with varchar and integer as basetype + * @throws SQLException + */ + @Test + public void readVarcharInteger() throws SQLException { + Object expected[] = {"abc", 42}; + int index = 0; + rs = (SQLServerResultSet) stmt.executeQuery("SELECT cast('abc' as sql_variant) UNION ALL SELECT cast(42 as sql_variant)"); + while (rs.next()) { + assertEquals(rs.getObject(1), expected[index++]); + } + } + + /** + * Tests unsupported type + * + * @throws SQLException + */ + @Test + public void testUnsupportedDatatype() throws SQLException { + rs = (SQLServerResultSet) stmt.executeQuery("select cast(cast('2017-08-16 17:31:09.995 +07:00' as datetimeoffset) as sql_variant)"); + rs.next(); + try { + rs.getObject(1); + fail("Should have thrown unssuported tds type exception"); + } + catch (Exception e) { + assertTrue(e.getMessage().equalsIgnoreCase("Unexpected TDS type DATETIMEOFFSETN in SQL_VARIANT.")); + } + if (null != rs) { + rs.close(); + } + } + + /** + * Tests that the returning class of base type time in sql_variant is correct. + * + * @throws SQLException + * + */ + @Test + public void testTimeClassAsSqlVariant() throws SQLException { + rs = (SQLServerResultSet) stmt.executeQuery("select cast(cast('17:31:09.995' as time(3)) as sql_variant)"); + rs.next(); + Object object = rs.getObject(1); + assertEquals(object.getClass(), java.sql.Time.class); + ; + } private boolean parseByte(byte[] expectedData, byte[] retrieved) { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/TVPWithSqlVariantTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/TVPWithSqlVariantTest.java index cd318ac67b..da20156c73 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/TVPWithSqlVariantTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/TVPWithSqlVariantTest.java @@ -290,7 +290,7 @@ public void testLongVarChar() throws SQLServerException { pstmt.execute(); } catch (SQLServerException e) { - assertTrue(e.getMessage().contains("SQL_VARIANT does not support string values more than 8000 length.")); + assertTrue(e.getMessage().contains("SQL_VARIANT does not support string values of length greater than 8000.")); } catch (Exception e) { fail("Test should have failed! mistakenly inserted string value of more than 8000 in sql-variant"); @@ -340,7 +340,7 @@ public void testNull() throws SQLServerException { tvp.addRow((Date) null); } catch (Exception e) { - assertTrue(e.getMessage().startsWith("Inserting null value with column")); + assertTrue(e.getMessage().startsWith("Use of TVPs containing null sql_variant columns is not supported.")); } pstmt = (SQLServerPreparedStatement) connection.prepareStatement("INSERT INTO " + destTable + " select * from ? ;"); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/fips/FipsTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/fips/FipsTest.java index 83f8a9f716..3a257328aa 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/fips/FipsTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/fips/FipsTest.java @@ -52,7 +52,7 @@ public void fipsTrustServerCertificateTest() throws Exception { } catch (SQLServerException e) { Assertions.assertTrue( - e.getMessage().contains("Could not enable FIPS due to either encrypt is not true or using trusted certificate settings."), + e.getMessage().contains("Unable to verify FIPS mode settings."), "Should create exception for invalid TrustServerCertificate value"); } } @@ -72,31 +72,11 @@ public void fipsEncryptTest() throws Exception { } catch (SQLServerException e) { Assertions.assertTrue( - e.getMessage().contains("Could not enable FIPS due to either encrypt is not true or using trusted certificate settings."), + e.getMessage().contains("Unable to verify FIPS mode settings."), "Should create exception for invalid encrypt value"); } } - /** - * Test after removing FIPS PROVIDER - * - * @throws Exception - */ - @Test - public void fipsProviderTest() throws Exception { - try { - Properties props = buildConnectionProperties(); - props.remove("fipsProvider"); - props.setProperty("trustStore", "/SOME_PATH"); - Connection con = PrepUtil.getConnection(connectionString, props); - Assertions.fail("It should fail as we are not passing appropriate params"); - } - catch (SQLServerException e) { - Assertions.assertTrue(e.getMessage().contains("Could not enable FIPS due to invalid FIPSProvider or TrustStoreType"), - "Should create exception for invalid FIPSProvider"); - } - } - /** * Test after removing fips, encrypt & trustStore it should work appropriately. * @@ -124,7 +104,6 @@ public void fipsDataSourcePropertyTest() throws Exception { SQLServerDataSource ds = new SQLServerDataSource(); setDataSourceProperties(ds); ds.setFIPS(false); - ds.setFIPSProvider(""); ds.setEncrypt(false); ds.setTrustStoreType("JKS"); Connection con = ds.getConnection(); @@ -148,32 +127,11 @@ public void fipsDatSourceEncrypt() { } catch (SQLServerException e) { Assertions.assertTrue( - e.getMessage().contains("Could not enable FIPS due to either encrypt is not true or using trusted certificate settings."), + e.getMessage().contains("Unable to verify FIPS mode settings."), "Should create exception for invalid encrypt value"); } } - /** - * Test after removing FIPS PROVIDER - * - * @throws Exception - */ - @Test - public void fipsDataSourceProviderTest() throws Exception { - try { - SQLServerDataSource ds = new SQLServerDataSource(); - setDataSourceProperties(ds); - ds.setFIPSProvider(""); - ds.setTrustStore("/SOME_PATH"); - Connection con = ds.getConnection(); - Assertions.fail("It should fail as we are not passing appropriate params"); - } - catch (SQLServerException e) { - Assertions.assertTrue(e.getMessage().contains("Could not enable FIPS due to invalid FIPSProvider or TrustStoreType"), - "Should create exception for invalid FIPSProvider"); - } - } - /** * Test after setting TrustServerCertificate as true. * @@ -190,7 +148,7 @@ public void fipsDataSourceTrustServerCertificateTest() throws Exception { } catch (SQLServerException e) { Assertions.assertTrue( - e.getMessage().contains("Could not enable FIPS due to either encrypt is not true or using trusted certificate settings."), + e.getMessage().contains("Unable to verify FIPS mode settings."), "Should create exception for invalid TrustServerCertificate value"); } } @@ -216,7 +174,6 @@ private void setDataSourceProperties(SQLServerDataSource ds) { ds.setTrustServerCertificate(false); ds.setIntegratedSecurity(false); ds.setTrustStoreType("PKCS12"); - ds.setFIPSProvider("BCFIPS"); } /** @@ -235,7 +192,6 @@ private Properties buildConnectionProperties() { // For New Code connectionProps.setProperty("trustStoreType", "PKCS12"); - connectionProps.setProperty("fipsProvider", "BCFIPS"); connectionProps.setProperty("fips", "true"); return connectionProps; diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java index f433c0bf7c..af9499fa97 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java @@ -101,10 +101,10 @@ public Collection executeDynamicTests() { List isResultSetTypes = new ArrayList<>(Arrays.asList(true, false)); Collection dynamicTests = new ArrayList<>(); - for (int i = 0; i < classes.size(); i++) { - for (int j = 0; j < isResultSetTypes.size(); j++) { - final Class lobClass = classes.get(i); - final boolean isResultSet = isResultSetTypes.get(j); + for (Class aClass : classes) { + for (Boolean isResultSetType : isResultSetTypes) { + final Class lobClass = aClass; + final boolean isResultSet = isResultSetType; Executable exec = new Executable() { @Override public void execute() throws Throwable { @@ -572,8 +572,8 @@ private static DBTable createTable(DBTable table, DBStatement stmt = new DBConnection(connectionString).createStatement(); table = new DBTable(false); - for (int i = 0; i < types.length; i++) { - SqlType type = Utils.find(types[i]); + for (String type1 : types) { + SqlType type = Utils.find(type1); table.addColumn(type); } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/BatchTriggerTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/BatchTriggerTest.java new file mode 100644 index 0000000000..1abcf471c1 --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/BatchTriggerTest.java @@ -0,0 +1,161 @@ +/* + * 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.unit.statement; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; +import org.opentest4j.TestAbortedException; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import com.microsoft.sqlserver.jdbc.SQLServerStatement; +import com.microsoft.sqlserver.testframework.AbstractTest; +import com.microsoft.sqlserver.testframework.Utils; + +/** + * Tests batch execution with trigger exception + * + */ +@RunWith(JUnitPlatform.class) +public class BatchTriggerTest extends AbstractTest { + + static Statement stmt = null; + static Connection connection = null; + static String tableName = "triggerTable"; + static String triggerName = "triggerTest"; + static String customErrorMessage = "Custom error message, you should see me. col1 should be higher than 10"; + static String insertQuery = "insert into " + tableName + " (col1, col2, col3, col4) values (1, '22-08-2017 17:30:00.000', 'R4760', 31)"; + + /** + * Tests that the proper trigger exception is thrown using statement + * + * @throws SQLException + */ + @Test + public void statementTest() throws SQLException { + Statement stmt = null; + try { + stmt = connection.createStatement(); + stmt.addBatch(insertQuery); + stmt.executeBatch(); + fail("Trigger Exception not thrown"); + } + catch (Exception e) { + assertTrue(e.getMessage().equalsIgnoreCase(customErrorMessage)); + } + + finally { + if (stmt != null) { + stmt.close(); + } + } + } + + /** + * Tests that the proper trigger exception is thrown using preparedSatement + * + * @throws SQLException + */ + @Test + public void preparedStatementTest() throws SQLException { + PreparedStatement pstmt = null; + try { + pstmt = connection.prepareStatement(insertQuery); + pstmt.addBatch(); + pstmt.executeBatch(); + fail("Trigger Exception not thrown"); + } + catch (Exception e) { + + assertTrue(e.getMessage().equalsIgnoreCase(customErrorMessage)); + } + finally { + if (pstmt != null) { + pstmt.close(); + } + } + } + + /** + * Create the trigger + * + * @param triggerName + * @throws SQLException + */ + private static void createTrigger(String triggerName) throws SQLException { + String sql = "create trigger " + triggerName + " on " + tableName + " for insert " + "as " + "begin " + "if (select col1 from " + tableName + + ") > 10 " + "begin " + "return " + "end " + + "RAISERROR ('Custom error message, you should see me. col1 should be higher than 10', 16, 0) " + "rollback transaction " + "end"; + stmt.execute(sql); + } + + /** + * Creating tables + * + * @throws SQLException + */ + private static void createTable() throws SQLException { + String sql = "create table " + tableName + " ( col1 int, col2 varchar(50), col3 varchar(10), col4 int)"; + stmt.execute(sql); + } + + /** + * Setup test + * + * @throws TestAbortedException + * @throws Exception + */ + @BeforeAll + public static void testSetup() throws TestAbortedException, Exception { + connection = DriverManager.getConnection(connectionString); + stmt = (SQLServerStatement) connection.createStatement(); + stmt.execute("IF EXISTS (\r\n" + " SELECT *\r\n" + " FROM sys.objects\r\n" + " WHERE [type] = 'TR' AND [name] = '" + triggerName + + "'\r\n" + " )\r\n" + " DROP TRIGGER " + triggerName + ";"); + dropTable(); + createTable(); + createTrigger(triggerName); + } + + /** + * Drop the table + * + * @throws SQLException + */ + private static void dropTable() throws SQLException { + Utils.dropTableIfExists(tableName, stmt); + } + + /** + * Cleaning up + * + * @throws SQLException + */ + @AfterAll + public static void terminateVariation() throws SQLException { + dropTable(); + stmt.execute("IF EXISTS (\r\n" + " SELECT *\r\n" + " FROM sys.objects\r\n" + " WHERE [type] = 'TR' AND [name] = '" + triggerName + + "'\r\n" + " )\r\n" + " DROP TRIGGER " + triggerName + ";"); + + if (null != connection) { + connection.close(); + } + if (null != stmt) { + stmt.close(); + } + + } +} \ No newline at end of file diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/LimitEscapeTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/LimitEscapeTest.java index bd6bccd2cc..cc9e0e69fb 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/LimitEscapeTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/LimitEscapeTest.java @@ -40,7 +40,7 @@ @RunWith(JUnitPlatform.class) public class LimitEscapeTest extends AbstractTest { public static final Logger log = Logger.getLogger("LimitEscape"); - private static Vector offsetQuery = new Vector(); + private static Vector offsetQuery = new Vector<>(); private static Connection conn = null; static class Query { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/PreparedStatementTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/PreparedStatementTest.java index c274e36116..944c796727 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/PreparedStatementTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/PreparedStatementTest.java @@ -24,6 +24,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicReference; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; @@ -130,6 +131,7 @@ public void testBatchedUnprepare() throws SQLException { * @throws SQLException */ @Test + @Tag("slow") public void testStatementPooling() throws SQLException { // Test % handle re-use try (SQLServerConnection con = (SQLServerConnection)DriverManager.getConnection(connectionString)) { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/RegressionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/RegressionTest.java index 7748e998b2..2eec0cd70a 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/RegressionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/RegressionTest.java @@ -168,8 +168,8 @@ public void testUpdateQuery() throws SQLException { sql = "update " + tableName + " SET c1= ? where PK =1"; for (int i = 1; i <= rows; i++) { pstmt = (SQLServerPreparedStatement)con.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - for (int t = 0; t < targets.length; t++) { - pstmt.setObject(1, 5 + i, targets[t]); + for (JDBCType target : targets) { + pstmt.setObject(1, 5 + i, target); pstmt.executeUpdate(); } } 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 88b6c54277..715f1c4578 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 @@ -2097,7 +2097,7 @@ public void testNBCROWWithRandomAccess() throws Exception { Random r = new Random(); // randomly generate columns whose values would be set to a non null value - ArrayList nonNullColumns = new ArrayList(); + ArrayList nonNullColumns = new ArrayList<>(); nonNullColumns.add(1);// this is always non-null // Add approximately 10 non-null columns. The number should be low diff --git a/src/test/java/com/microsoft/sqlserver/testframework/DBCoercion.java b/src/test/java/com/microsoft/sqlserver/testframework/DBCoercion.java index e4cea5a53b..e367a94b87 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/DBCoercion.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/DBCoercion.java @@ -46,8 +46,7 @@ public DBCoercion(Class type, int[] tempflags) { name = type.toString(); this.type = type; - for (int i = 0; i < tempflags.length; i++) - flags.set(tempflags[i]); + for (int tempflag : tempflags) flags.set(tempflag); } /** diff --git a/src/test/java/com/microsoft/sqlserver/testframework/DBCoercions.java b/src/test/java/com/microsoft/sqlserver/testframework/DBCoercions.java index c333d71df5..ff8e03f8f1 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/DBCoercions.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/DBCoercions.java @@ -19,7 +19,7 @@ public class DBCoercions extends DBItems { * constructor */ public DBCoercions() { - coercionsList = new ArrayList(); + coercionsList = new ArrayList<>(); } public DBCoercions(DBCoercion coercion) { diff --git a/src/test/java/com/microsoft/sqlserver/testframework/DBColumn.java b/src/test/java/com/microsoft/sqlserver/testframework/DBColumn.java index 7528e9e5d2..f447449834 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/DBColumn.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/DBColumn.java @@ -78,7 +78,7 @@ void setSqlType(SqlType sqlType) { * number of rows */ void populateValues(int rows) { - columnValues = new ArrayList(); + columnValues = new ArrayList<>(); for (int i = 0; i < rows; i++) columnValues.add(sqlType.createdata()); } diff --git a/src/test/java/com/microsoft/sqlserver/testframework/DBItems.java b/src/test/java/com/microsoft/sqlserver/testframework/DBItems.java index a64386ac45..be2999a1b5 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/DBItems.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/DBItems.java @@ -22,8 +22,7 @@ public DBItems() { } public DBCoercion find(Class type) { - for (int i = 0; i < coercionsList.size(); i++) { - DBCoercion item = coercionsList.get(i); + for (DBCoercion item : coercionsList) { if (item.type() == type) return item; } diff --git a/src/test/java/com/microsoft/sqlserver/testframework/DBSchema.java b/src/test/java/com/microsoft/sqlserver/testframework/DBSchema.java index 8260989130..e089953463 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/DBSchema.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/DBSchema.java @@ -52,7 +52,7 @@ public class DBSchema { * @param autoGenerateSchema */ DBSchema(boolean autoGenerateSchema) { - sqlTypes = new ArrayList(); + sqlTypes = new ArrayList<>(); if (autoGenerateSchema) { // Exact Numeric sqlTypes.add(new SqlBigInt()); diff --git a/src/test/java/com/microsoft/sqlserver/testframework/DBTable.java b/src/test/java/com/microsoft/sqlserver/testframework/DBTable.java index 90d6ae3bc8..e3c9b174f7 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/DBTable.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/DBTable.java @@ -85,7 +85,7 @@ public DBTable(boolean autoGenerateSchema, addColumns(); } else { - this.columns = new ArrayList(); + this.columns = new ArrayList<>(); } this.totalColumns = columns.size(); } @@ -108,7 +108,7 @@ private DBTable(DBTable sourceTable) { */ private void addColumns() { totalColumns = schema.getNumberOfSqlTypes(); - columns = new ArrayList(totalColumns); + columns = new ArrayList<>(totalColumns); for (int i = 0; i < totalColumns; i++) { SqlType sqlType = schema.getSqlType(i); @@ -122,7 +122,7 @@ private void addColumns() { */ private void addColumns(boolean unicode) { totalColumns = schema.getNumberOfSqlTypes(); - columns = new ArrayList(totalColumns); + columns = new ArrayList<>(totalColumns); for (int i = 0; i < totalColumns; i++) { SqlType sqlType = schema.getSqlType(i); diff --git a/src/test/java/com/microsoft/sqlserver/testframework/Utils.java b/src/test/java/com/microsoft/sqlserver/testframework/Utils.java index 8db5e96e53..229f7f4c6b 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/Utils.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/Utils.java @@ -131,8 +131,7 @@ public static String getConfiguredProperty(String key, public static SqlType find(Class javatype) { if (null != types) { types(); - for (int i = 0; i < types.size(); i++) { - SqlType type = types.get(i); + for (SqlType type : types) { if (type.getType() == javatype) return type; } @@ -149,8 +148,7 @@ public static SqlType find(String name) { if (null == types) types(); if (null != types) { - for (int i = 0; i < types.size(); i++) { - SqlType type = types.get(i); + for (SqlType type : types) { if (type.getName().equalsIgnoreCase(name)) return type; } @@ -164,7 +162,7 @@ public static SqlType find(String name) { */ public static ArrayList types() { if (null == types) { - types = new ArrayList(); + types = new ArrayList<>(); types.add(new SqlInt()); types.add(new SqlSmallInt());