Skip to content

Blackrock: Added QUOTED_IDENTIFIER and CONCAT_NULL_YIELDS_NULL flag in connection #2618

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Apr 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
9bc117c
add props
lilgreenbird Nov 13, 2024
a93cfae
add test
lilgreenbird Nov 13, 2024
c3e8fed
change default
lilgreenbird Nov 14, 2024
c24c9e7
change to use executeQuery
lilgreenbird Nov 14, 2024
e530011
change default
lilgreenbird Nov 14, 2024
70d0f96
update test
lilgreenbird Nov 15, 2024
29a12c9
Deadlock and null TDSCommand counter fix
tkyc Nov 15, 2024
90a1d0e
Moved the QUOTED_IDENTIFIER and CONCAT_NULL_YIELDS_NULL flag setting …
Feb 27, 2025
8d7f987
Merged from main branch
Feb 27, 2025
cf9ea3a
Removed the default Flag setting call to server for QUOTED_IDENTIFIER…
Feb 28, 2025
1b333c0
Added one more state - NOT_SET for QUOTED_IDENTIFIER and CONCAT_NULL_…
Feb 28, 2025
bb41fb6
Fixed setCustomFlags to set correct state of a flag
Feb 28, 2025
bfad8d7
Reverted defaultFlagSet method. It is not required. Server set ANSI_D…
Mar 3, 2025
e3d0cf2
Optimized the code for QUOTED_IDENTIFIER/CONCAT_NULL_YIELDS_NULL flag…
Mar 3, 2025
4e7192a
Added test cases for QUOTED_IDENTIFIER/CONCAT_NULL_YIELDS_NULL flags'…
Mar 4, 2025
17279dd
Added test case for CONCAT_NULL_YIELDS_NULL and QUOTED_IDENTIFIER fla…
Apr 17, 2025
c22952c
Merge remote-tracking branch 'origin/main' into blackrock
Apr 18, 2025
a60b8b1
resetPooledConnection() method keep the flags CONCAT_NULL_YIELDS_NULL…
Apr 18, 2025
1891329
Merge branch 'main' into blackrock
Apr 21, 2025
d2a20ae
Added proper error message in testSessionPropertyValueHelper and fixe…
Apr 21, 2025
2d39a0d
Removed catch block in testConcatNullYieldsNull()
Apr 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1451,8 +1451,8 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource {
* @return cacheBulkCopyMetadata boolean value
*/
boolean getcacheBulkCopyMetadata();
/**

/**
* Returns value of 'retryExec' from Connection String.
*
* @param retryExec
Expand Down Expand Up @@ -1506,4 +1506,38 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource {
* @return useFlexibleCallableStatements
*/
boolean getUseFlexibleCallableStatements();

/**
* Returns value of 'quotedIdentifier' from Connection String.
*
* @return true
* if quotedIdentifier is set to true, false otherwise
*/
String getQuotedIdentifier();

/**
* Sets the value for 'quotedIdentifier' property
*
* @param quotedIdentifier
* boolean value
*
*/
void setQuotedIdentifier(String quotedIdentifier);

/**
* Returns value of 'concatNullYieldsNull' from Connection String.
*
* @return true
* if concatNullYieldsNull is set to true, false otherwise
*/
String getConcatNullYieldsNull();

/**
* Sets the value for 'concatNullYieldsNull' property
*
* @param concatNullYieldsNull
* boolean value
*
*/
void setConcatNullYieldsNull(String concatNullYieldsNull);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2038,7 +2038,7 @@
return this;
}

final void resetPooledConnection() {
final void resetPooledConnection() throws SQLServerException {
tdsChannel.resetPooledConnection();
initResettableValues();

Expand All @@ -2051,6 +2051,8 @@
if (null != bulkCopyOperationCache) {
bulkCopyOperationCache.clear();
}

setSessionProperties();
}

/**
Expand Down Expand Up @@ -3530,7 +3532,8 @@
}

state = State.OPENED;

setSessionProperties();

// Socket timeout is bounded by loginTimeout during the login phase.
// Reset socket timeout back to the original value.
tdsChannel.resetTcpSocketTimeout();
Expand All @@ -3552,6 +3555,40 @@
return this;
}

private void setSessionProperties() throws SQLServerException {
// check QUOTED_IDENTIFIER property
String quotedIdentifierProperty = SQLServerDriverStringProperty.QUOTED_IDENTIFIER.toString();
String quotedIdentifierValue = activeConnectionProperties.getProperty(quotedIdentifierProperty);
if (null != quotedIdentifierValue) {
OnOffOption quotedIdentifierOption = OnOffOption.valueOfString(quotedIdentifierValue);
activeConnectionProperties.setProperty(quotedIdentifierProperty, quotedIdentifierValue);
switch (quotedIdentifierOption) {
case ON:
connectionCommand("SET QUOTED_IDENTIFIER ON", "quotedIdentifier");
break;
case OFF:
connectionCommand("SET QUOTED_IDENTIFIER OFF", "quotedIdentifier");
break;
}
}

// check CONCAT_NULL_YIELDS_NULL property
String concatNullYieldsNullProperty = SQLServerDriverStringProperty.CONCAT_NULL_YIELDS_NULL.toString();
String concatNullYieldsNullValue = activeConnectionProperties.getProperty(concatNullYieldsNullProperty);
if (null != concatNullYieldsNullValue) {
OnOffOption concatNullYieldsOption = OnOffOption.valueOfString(concatNullYieldsNullValue);
activeConnectionProperties.setProperty(concatNullYieldsNullProperty, concatNullYieldsNullValue);
switch (concatNullYieldsOption) {
case ON:
connectionCommand("SET CONCAT_NULL_YIELDS_NULL ON", "concatNullYields");
break;
case OFF:
connectionCommand("SET CONCAT_NULL_YIELDS_NULL OFF", "concatNullYields");
break;
}
}
}

// log open connection failures
private void logConnectFailure(int attemptNumber, SQLServerException e, SQLServerError sqlServerError) {
loggerResiliency.finer(toString() + " Connection open - connection failed on attempt: " + attemptNumber + ".");
Expand Down Expand Up @@ -4786,6 +4823,7 @@
*/
boolean commandComplete = false;
try {
newCommand.createCounter(null, activeConnectionProperties);

Check warning on line 4826 in src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java

View check run for this annotation

Codecov / codecov/patch

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

Added line #L4826 was not covered by tests
commandComplete = newCommand.execute(tdsChannel.getWriter(), tdsChannel.getReader(newCommand));
} finally {
/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -948,17 +948,15 @@

@Override
public void setcacheBulkCopyMetadata(boolean cacheBulkCopyMetadata) {
setBooleanProperty(connectionProps,
SQLServerDriverBooleanProperty.ENABLE_BULK_COPY_CACHE.toString(),
setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.ENABLE_BULK_COPY_CACHE.toString(),

Check warning on line 951 in src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java

View check run for this annotation

Codecov / codecov/patch

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

Added line #L951 was not covered by tests
cacheBulkCopyMetadata);
}

@Override
public boolean getcacheBulkCopyMetadata() {
boolean defaultValue = SQLServerDriverBooleanProperty.ENABLE_BULK_COPY_CACHE
.getDefaultValue();
return getBooleanProperty(connectionProps,
SQLServerDriverBooleanProperty.ENABLE_BULK_COPY_CACHE.toString(), defaultValue);
boolean defaultValue = SQLServerDriverBooleanProperty.ENABLE_BULK_COPY_CACHE.getDefaultValue();
return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.ENABLE_BULK_COPY_CACHE.toString(),

Check warning on line 958 in src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java#L957-L958

Added lines #L957 - L958 were not covered by tests
defaultValue);
}

@Override
Expand Down Expand Up @@ -1392,7 +1390,6 @@
@Override
public void setUseFlexibleCallableStatements(boolean enable) {}


/**
* useFlexibleCallableStatements is temporarily removed.
* This method is a no-op for backwards compatibility only.
Expand Down Expand Up @@ -1494,6 +1491,29 @@
return getStringProperty(connectionProps, SQLServerDriverStringProperty.RETRY_EXEC.toString(), null);
}

@Override
public String getQuotedIdentifier() {
return getStringProperty(connectionProps, SQLServerDriverStringProperty.QUOTED_IDENTIFIER.toString(),
SQLServerDriverStringProperty.QUOTED_IDENTIFIER.getDefaultValue());
}

@Override
public void setQuotedIdentifier(String quotedIdentifier) {
setStringProperty(connectionProps, SQLServerDriverStringProperty.QUOTED_IDENTIFIER.toString(), quotedIdentifier);
}

@Override
public String getConcatNullYieldsNull() {
return getStringProperty(connectionProps, SQLServerDriverStringProperty.CONCAT_NULL_YIELDS_NULL.toString(),
SQLServerDriverStringProperty.CONCAT_NULL_YIELDS_NULL.getDefaultValue());
}

@Override
public void setConcatNullYieldsNull(String concatNullYieldNull) {
setStringProperty(connectionProps, SQLServerDriverStringProperty.CONCAT_NULL_YIELDS_NULL.toString(),
concatNullYieldNull);
}

/**
* Sets the 'retryConn' setting.
*
Expand Down
58 changes: 53 additions & 5 deletions src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,9 @@
DATETIME_DATATYPE("datetimeParameterType", DatetimeType.DATETIME2.toString()),
ACCESS_TOKEN_CALLBACK_CLASS("accessTokenCallbackClass", ""),
RETRY_EXEC("retryExec", ""),
RETRY_CONN("retryConn", "");
RETRY_CONN("retryConn", ""),
QUOTED_IDENTIFIER("quotedIdentifier", OnOffOption.ON.toString()),
CONCAT_NULL_YIELDS_NULL("concatNullYieldsNull", OnOffOption.ON.toString());

private final String name;
private final String defaultValue;
Expand Down Expand Up @@ -728,6 +730,47 @@
}


enum OnOffOption {
ON("ON"),
OFF("OFF");

private final String option;

private OnOffOption(String option) {
this.option = option;
}

@Override
public String toString() {
return option;
}

static OnOffOption valueOfString(String value) throws SQLServerException {
OnOffOption option = null;

if (value.toLowerCase(Locale.US).equalsIgnoreCase(OnOffOption.ON.toString())) {
option = OnOffOption.ON;
} else if (value.toLowerCase(Locale.US).equalsIgnoreCase(OnOffOption.OFF.toString())) {
option = OnOffOption.OFF;
} else {
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_InvalidConnectionSetting"));
Object[] msgArgs = {"OnOffOption", value};
throw new SQLServerException(form.format(msgArgs), null);

Check warning on line 758 in src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java#L756-L758

Added lines #L756 - L758 were not covered by tests
}
return option;
}

static boolean isValidOnOffOption(String option) {
for (OnOffOption t : OnOffOption.values()) {
if (option.equalsIgnoreCase(t.toString())) {
return true;

Check warning on line 766 in src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java

View check run for this annotation

Codecov / codecov/patch

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

Added line #L766 was not covered by tests
}
}
return false;

Check warning on line 769 in src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java

View check run for this annotation

Codecov / codecov/patch

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

Added line #L769 was not covered by tests
}
}


/**
* Provides methods to connect to a SQL Server database and to obtain information about the JDBC driver.
*/
Expand Down Expand Up @@ -807,8 +850,8 @@
Boolean.toString(SQLServerDriverBooleanProperty.INTEGRATED_SECURITY.getDefaultValue()), false,
TRUE_FALSE),
new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.USE_DEFAULT_GSS_CREDENTIAL.toString(),
Boolean.toString(SQLServerDriverBooleanProperty.USE_DEFAULT_GSS_CREDENTIAL.getDefaultValue()), false,
TRUE_FALSE),
Boolean.toString(SQLServerDriverBooleanProperty.USE_DEFAULT_GSS_CREDENTIAL.getDefaultValue()),
false, TRUE_FALSE),
new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.KEY_STORE_AUTHENTICATION.toString(),
SQLServerDriverStringProperty.KEY_STORE_AUTHENTICATION.getDefaultValue(), false,
new String[] {KeyStoreAuthentication.JAVA_KEYSTORE_PASSWORD.toString()}),
Expand Down Expand Up @@ -1002,8 +1045,13 @@
new SQLServerDriverPropertyInfo(SQLServerDriverIntProperty.CONNECT_RETRY_COUNT.toString(),
Integer.toString(SQLServerDriverIntProperty.CONNECT_RETRY_COUNT.getDefaultValue()), false, null),
new SQLServerDriverPropertyInfo(SQLServerDriverIntProperty.CONNECT_RETRY_INTERVAL.toString(),
Integer.toString(SQLServerDriverIntProperty.CONNECT_RETRY_INTERVAL.getDefaultValue()), false,
null),};
Integer.toString(SQLServerDriverIntProperty.CONNECT_RETRY_INTERVAL.getDefaultValue()), false, null),
new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.QUOTED_IDENTIFIER.toString(),
SQLServerDriverStringProperty.QUOTED_IDENTIFIER.getDefaultValue(), false,
new String[] {OnOffOption.OFF.toString(), OnOffOption.OFF.toString()}),
new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.CONCAT_NULL_YIELDS_NULL.toString(),
SQLServerDriverStringProperty.CONCAT_NULL_YIELDS_NULL.getDefaultValue(), false,
new String[] {OnOffOption.OFF.toString(), OnOffOption.OFF.toString()}),};

/**
* Properties that can only be set by using Properties. Cannot set in connection string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ protected Object[][] getContents() {
{"R_AADSecurePrincipalSecretPropertyDescription", "A Secret defined for a registered application which has been granted permission to the database connected."},
{"R_accessTokenCallbackClassPropertyDescription", "The class to instantiate as the SQLServerAccessTokenCallback for acquiring tokens."},
{"R_accessTokenCallbackPropertyDescription", "A SQLServerAccessTokenCallback object which is used to call a callback method to return an access token."},
{"R_quotedIdentifierPropertyDescription", "Indicates whether quotedIdentifier property is set."},
{"R_concatNullYieldsNullPropertyDescription", "Indicates whether concatNullYieldsNull property is set."},
{"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."},
{"R_dataHasBeenReadXML", "Cannot read from this SQLXML instance. The data has already been read."},
Expand Down
Loading
Loading