Skip to content

Commit 3e8672a

Browse files
divanglilgreenbirdtkycDivang Sharma
authored
Blackrock: Added QUOTED_IDENTIFIER and CONCAT_NULL_YIELDS_NULL flag in connection (#2618)
* add props * add test * change default * change to use executeQuery * change default * update test * Deadlock and null TDSCommand counter fix * Moved the QUOTED_IDENTIFIER and CONCAT_NULL_YIELDS_NULL flag setting in initResettableValues() method to handle it in pooled connection too * Removed the default Flag setting call to server for QUOTED_IDENTIFIER and CONCAT_NULL_YIELDS_NULL * Added one more state - NOT_SET for QUOTED_IDENTIFIER and CONCAT_NULL_YIELDS_NULL flag * Fixed setCustomFlags to set correct state of a flag * Reverted defaultFlagSet method. It is not required. Server set ANSI_DEFAULTS=ON on LOGIN7 call and CONCAT_NULL_YIELDS_NULL/QUOTED_IDENTIFIER are set ON by default. * Optimized the code for QUOTED_IDENTIFIER/CONCAT_NULL_YIELDS_NULL flags are not supplied (server default case) * Added test cases for QUOTED_IDENTIFIER/CONCAT_NULL_YIELDS_NULL flags' value for new and pooled connection * Added test case for CONCAT_NULL_YIELDS_NULL and QUOTED_IDENTIFIER flag with ON value and helper method * resetPooledConnection() method keep the flags CONCAT_NULL_YIELDS_NULL and QUOTED_IDENTIFIER values, suppilied in connection properties * Added proper error message in testSessionPropertyValueHelper and fixed catch block in new test cases * Removed catch block in testConcatNullYieldsNull() --------- Co-authored-by: lilgreenbird <[email protected]> Co-authored-by: Terry Chow <[email protected]> Co-authored-by: Divang Sharma <[email protected]>
1 parent 1e9cebd commit 3e8672a

File tree

8 files changed

+291
-20
lines changed

8 files changed

+291
-20
lines changed

src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,8 +1451,8 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource {
14511451
* @return cacheBulkCopyMetadata boolean value
14521452
*/
14531453
boolean getcacheBulkCopyMetadata();
1454-
1455-
/**
1454+
1455+
/**
14561456
* Returns value of 'retryExec' from Connection String.
14571457
*
14581458
* @param retryExec
@@ -1506,4 +1506,38 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource {
15061506
* @return useFlexibleCallableStatements
15071507
*/
15081508
boolean getUseFlexibleCallableStatements();
1509+
1510+
/**
1511+
* Returns value of 'quotedIdentifier' from Connection String.
1512+
*
1513+
* @return true
1514+
* if quotedIdentifier is set to true, false otherwise
1515+
*/
1516+
String getQuotedIdentifier();
1517+
1518+
/**
1519+
* Sets the value for 'quotedIdentifier' property
1520+
*
1521+
* @param quotedIdentifier
1522+
* boolean value
1523+
*
1524+
*/
1525+
void setQuotedIdentifier(String quotedIdentifier);
1526+
1527+
/**
1528+
* Returns value of 'concatNullYieldsNull' from Connection String.
1529+
*
1530+
* @return true
1531+
* if concatNullYieldsNull is set to true, false otherwise
1532+
*/
1533+
String getConcatNullYieldsNull();
1534+
1535+
/**
1536+
* Sets the value for 'concatNullYieldsNull' property
1537+
*
1538+
* @param concatNullYieldsNull
1539+
* boolean value
1540+
*
1541+
*/
1542+
void setConcatNullYieldsNull(String concatNullYieldsNull);
15091543
}

src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2038,7 +2038,7 @@ final Connection getConnection() {
20382038
return this;
20392039
}
20402040

2041-
final void resetPooledConnection() {
2041+
final void resetPooledConnection() throws SQLServerException {
20422042
tdsChannel.resetPooledConnection();
20432043
initResettableValues();
20442044

@@ -2051,6 +2051,8 @@ final void resetPooledConnection() {
20512051
if (null != bulkCopyOperationCache) {
20522052
bulkCopyOperationCache.clear();
20532053
}
2054+
2055+
setSessionProperties();
20542056
}
20552057

20562058
/**
@@ -3530,7 +3532,8 @@ else if (0 == requestedPacketSize)
35303532
}
35313533

35323534
state = State.OPENED;
3533-
3535+
setSessionProperties();
3536+
35343537
// Socket timeout is bounded by loginTimeout during the login phase.
35353538
// Reset socket timeout back to the original value.
35363539
tdsChannel.resetTcpSocketTimeout();
@@ -3552,6 +3555,40 @@ else if (0 == requestedPacketSize)
35523555
return this;
35533556
}
35543557

3558+
private void setSessionProperties() throws SQLServerException {
3559+
// check QUOTED_IDENTIFIER property
3560+
String quotedIdentifierProperty = SQLServerDriverStringProperty.QUOTED_IDENTIFIER.toString();
3561+
String quotedIdentifierValue = activeConnectionProperties.getProperty(quotedIdentifierProperty);
3562+
if (null != quotedIdentifierValue) {
3563+
OnOffOption quotedIdentifierOption = OnOffOption.valueOfString(quotedIdentifierValue);
3564+
activeConnectionProperties.setProperty(quotedIdentifierProperty, quotedIdentifierValue);
3565+
switch (quotedIdentifierOption) {
3566+
case ON:
3567+
connectionCommand("SET QUOTED_IDENTIFIER ON", "quotedIdentifier");
3568+
break;
3569+
case OFF:
3570+
connectionCommand("SET QUOTED_IDENTIFIER OFF", "quotedIdentifier");
3571+
break;
3572+
}
3573+
}
3574+
3575+
// check CONCAT_NULL_YIELDS_NULL property
3576+
String concatNullYieldsNullProperty = SQLServerDriverStringProperty.CONCAT_NULL_YIELDS_NULL.toString();
3577+
String concatNullYieldsNullValue = activeConnectionProperties.getProperty(concatNullYieldsNullProperty);
3578+
if (null != concatNullYieldsNullValue) {
3579+
OnOffOption concatNullYieldsOption = OnOffOption.valueOfString(concatNullYieldsNullValue);
3580+
activeConnectionProperties.setProperty(concatNullYieldsNullProperty, concatNullYieldsNullValue);
3581+
switch (concatNullYieldsOption) {
3582+
case ON:
3583+
connectionCommand("SET CONCAT_NULL_YIELDS_NULL ON", "concatNullYields");
3584+
break;
3585+
case OFF:
3586+
connectionCommand("SET CONCAT_NULL_YIELDS_NULL OFF", "concatNullYields");
3587+
break;
3588+
}
3589+
}
3590+
}
3591+
35553592
// log open connection failures
35563593
private void logConnectFailure(int attemptNumber, SQLServerException e, SQLServerError sqlServerError) {
35573594
loggerResiliency.finer(toString() + " Connection open - connection failed on attempt: " + attemptNumber + ".");
@@ -4786,6 +4823,7 @@ boolean executeReconnectCommand(TDSCommand newCommand) throws SQLServerException
47864823
*/
47874824
boolean commandComplete = false;
47884825
try {
4826+
newCommand.createCounter(null, activeConnectionProperties);
47894827
commandComplete = newCommand.execute(tdsChannel.getWriter(), tdsChannel.getReader(newCommand));
47904828
} finally {
47914829
/*

src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -948,17 +948,15 @@ public boolean getEnablePrepareOnFirstPreparedStatementCall() {
948948

949949
@Override
950950
public void setcacheBulkCopyMetadata(boolean cacheBulkCopyMetadata) {
951-
setBooleanProperty(connectionProps,
952-
SQLServerDriverBooleanProperty.ENABLE_BULK_COPY_CACHE.toString(),
951+
setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.ENABLE_BULK_COPY_CACHE.toString(),
953952
cacheBulkCopyMetadata);
954953
}
955954

956955
@Override
957956
public boolean getcacheBulkCopyMetadata() {
958-
boolean defaultValue = SQLServerDriverBooleanProperty.ENABLE_BULK_COPY_CACHE
959-
.getDefaultValue();
960-
return getBooleanProperty(connectionProps,
961-
SQLServerDriverBooleanProperty.ENABLE_BULK_COPY_CACHE.toString(), defaultValue);
957+
boolean defaultValue = SQLServerDriverBooleanProperty.ENABLE_BULK_COPY_CACHE.getDefaultValue();
958+
return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.ENABLE_BULK_COPY_CACHE.toString(),
959+
defaultValue);
962960
}
963961

964962
@Override
@@ -1392,7 +1390,6 @@ public int getMsiTokenCacheTtl() {
13921390
@Override
13931391
public void setUseFlexibleCallableStatements(boolean enable) {}
13941392

1395-
13961393
/**
13971394
* useFlexibleCallableStatements is temporarily removed.
13981395
* This method is a no-op for backwards compatibility only.
@@ -1494,6 +1491,29 @@ public String getRetryExec() {
14941491
return getStringProperty(connectionProps, SQLServerDriverStringProperty.RETRY_EXEC.toString(), null);
14951492
}
14961493

1494+
@Override
1495+
public String getQuotedIdentifier() {
1496+
return getStringProperty(connectionProps, SQLServerDriverStringProperty.QUOTED_IDENTIFIER.toString(),
1497+
SQLServerDriverStringProperty.QUOTED_IDENTIFIER.getDefaultValue());
1498+
}
1499+
1500+
@Override
1501+
public void setQuotedIdentifier(String quotedIdentifier) {
1502+
setStringProperty(connectionProps, SQLServerDriverStringProperty.QUOTED_IDENTIFIER.toString(), quotedIdentifier);
1503+
}
1504+
1505+
@Override
1506+
public String getConcatNullYieldsNull() {
1507+
return getStringProperty(connectionProps, SQLServerDriverStringProperty.CONCAT_NULL_YIELDS_NULL.toString(),
1508+
SQLServerDriverStringProperty.CONCAT_NULL_YIELDS_NULL.getDefaultValue());
1509+
}
1510+
1511+
@Override
1512+
public void setConcatNullYieldsNull(String concatNullYieldNull) {
1513+
setStringProperty(connectionProps, SQLServerDriverStringProperty.CONCAT_NULL_YIELDS_NULL.toString(),
1514+
concatNullYieldNull);
1515+
}
1516+
14971517
/**
14981518
* Sets the 'retryConn' setting.
14991519
*

src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,9 @@ enum SQLServerDriverStringProperty {
612612
DATETIME_DATATYPE("datetimeParameterType", DatetimeType.DATETIME2.toString()),
613613
ACCESS_TOKEN_CALLBACK_CLASS("accessTokenCallbackClass", ""),
614614
RETRY_EXEC("retryExec", ""),
615-
RETRY_CONN("retryConn", "");
615+
RETRY_CONN("retryConn", ""),
616+
QUOTED_IDENTIFIER("quotedIdentifier", OnOffOption.ON.toString()),
617+
CONCAT_NULL_YIELDS_NULL("concatNullYieldsNull", OnOffOption.ON.toString());
616618

617619
private final String name;
618620
private final String defaultValue;
@@ -728,6 +730,47 @@ public String toString() {
728730
}
729731

730732

733+
enum OnOffOption {
734+
ON("ON"),
735+
OFF("OFF");
736+
737+
private final String option;
738+
739+
private OnOffOption(String option) {
740+
this.option = option;
741+
}
742+
743+
@Override
744+
public String toString() {
745+
return option;
746+
}
747+
748+
static OnOffOption valueOfString(String value) throws SQLServerException {
749+
OnOffOption option = null;
750+
751+
if (value.toLowerCase(Locale.US).equalsIgnoreCase(OnOffOption.ON.toString())) {
752+
option = OnOffOption.ON;
753+
} else if (value.toLowerCase(Locale.US).equalsIgnoreCase(OnOffOption.OFF.toString())) {
754+
option = OnOffOption.OFF;
755+
} else {
756+
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_InvalidConnectionSetting"));
757+
Object[] msgArgs = {"OnOffOption", value};
758+
throw new SQLServerException(form.format(msgArgs), null);
759+
}
760+
return option;
761+
}
762+
763+
static boolean isValidOnOffOption(String option) {
764+
for (OnOffOption t : OnOffOption.values()) {
765+
if (option.equalsIgnoreCase(t.toString())) {
766+
return true;
767+
}
768+
}
769+
return false;
770+
}
771+
}
772+
773+
731774
/**
732775
* Provides methods to connect to a SQL Server database and to obtain information about the JDBC driver.
733776
*/
@@ -807,8 +850,8 @@ public final class SQLServerDriver implements java.sql.Driver {
807850
Boolean.toString(SQLServerDriverBooleanProperty.INTEGRATED_SECURITY.getDefaultValue()), false,
808851
TRUE_FALSE),
809852
new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.USE_DEFAULT_GSS_CREDENTIAL.toString(),
810-
Boolean.toString(SQLServerDriverBooleanProperty.USE_DEFAULT_GSS_CREDENTIAL.getDefaultValue()), false,
811-
TRUE_FALSE),
853+
Boolean.toString(SQLServerDriverBooleanProperty.USE_DEFAULT_GSS_CREDENTIAL.getDefaultValue()),
854+
false, TRUE_FALSE),
812855
new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.KEY_STORE_AUTHENTICATION.toString(),
813856
SQLServerDriverStringProperty.KEY_STORE_AUTHENTICATION.getDefaultValue(), false,
814857
new String[] {KeyStoreAuthentication.JAVA_KEYSTORE_PASSWORD.toString()}),
@@ -1002,8 +1045,13 @@ public final class SQLServerDriver implements java.sql.Driver {
10021045
new SQLServerDriverPropertyInfo(SQLServerDriverIntProperty.CONNECT_RETRY_COUNT.toString(),
10031046
Integer.toString(SQLServerDriverIntProperty.CONNECT_RETRY_COUNT.getDefaultValue()), false, null),
10041047
new SQLServerDriverPropertyInfo(SQLServerDriverIntProperty.CONNECT_RETRY_INTERVAL.toString(),
1005-
Integer.toString(SQLServerDriverIntProperty.CONNECT_RETRY_INTERVAL.getDefaultValue()), false,
1006-
null),};
1048+
Integer.toString(SQLServerDriverIntProperty.CONNECT_RETRY_INTERVAL.getDefaultValue()), false, null),
1049+
new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.QUOTED_IDENTIFIER.toString(),
1050+
SQLServerDriverStringProperty.QUOTED_IDENTIFIER.getDefaultValue(), false,
1051+
new String[] {OnOffOption.OFF.toString(), OnOffOption.OFF.toString()}),
1052+
new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.CONCAT_NULL_YIELDS_NULL.toString(),
1053+
SQLServerDriverStringProperty.CONCAT_NULL_YIELDS_NULL.getDefaultValue(), false,
1054+
new String[] {OnOffOption.OFF.toString(), OnOffOption.OFF.toString()}),};
10071055

10081056
/**
10091057
* Properties that can only be set by using Properties. Cannot set in connection string

src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ protected Object[][] getContents() {
244244
{"R_AADSecurePrincipalSecretPropertyDescription", "A Secret defined for a registered application which has been granted permission to the database connected."},
245245
{"R_accessTokenCallbackClassPropertyDescription", "The class to instantiate as the SQLServerAccessTokenCallback for acquiring tokens."},
246246
{"R_accessTokenCallbackPropertyDescription", "A SQLServerAccessTokenCallback object which is used to call a callback method to return an access token."},
247+
{"R_quotedIdentifierPropertyDescription", "Indicates whether quotedIdentifier property is set."},
248+
{"R_concatNullYieldsNullPropertyDescription", "Indicates whether concatNullYieldsNull property is set."},
247249
{"R_noParserSupport", "An error occurred while instantiating the required parser. Error: \"{0}\""},
248250
{"R_writeOnlyXML", "Cannot read from this SQLXML instance. This instance is for writing data only."},
249251
{"R_dataHasBeenReadXML", "Cannot read from this SQLXML instance. The data has already been read."},

0 commit comments

Comments
 (0)