Skip to content
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

Blackrock: Added QUOTED_IDENTIFIER and CONCAT_NULL_YIELDS_NULL flag in connection #2618

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
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 @@ -1828,6 +1828,40 @@ final void initResettableValues() {
sqlWarnings = null;
sCatalog = originalCatalog;
databaseMetaData = null;

try{
// check QUOTED_IDENTIFIER property
String quotedIdentifierProperty = SQLServerDriverStringProperty.QUOTED_IDENTIFIER.toString();
String quotedIdentifierValue = activeConnectionProperties.getProperty(quotedIdentifierProperty);
if (null == quotedIdentifierValue) {
quotedIdentifierValue = SQLServerDriverStringProperty.QUOTED_IDENTIFIER.getDefaultValue();
activeConnectionProperties.setProperty(quotedIdentifierProperty, quotedIdentifierValue);
}

String quotedIdentifierOption = OnOffOption.valueOfString(quotedIdentifierValue).toString();
if (quotedIdentifierOption.compareToIgnoreCase(OnOffOption.OFF.toString()) == 0) {
connectionCommand("SET QUOTED_IDENTIFIER OFF", "quotedIdentifier");
} else if (quotedIdentifierOption.compareToIgnoreCase(OnOffOption.ON.toString()) == 0) {
connectionCommand("SET QUOTED_IDENTIFIER ON", "quotedIdentifier");
}

// check CONCAT_NULL_YIELDS_NULL property
String concatNullYieldsNullProperty = SQLServerDriverStringProperty.CONCAT_NULL_YIELDS_NULL.toString();
String concatNullYieldsNullValue = activeConnectionProperties.getProperty(concatNullYieldsNullProperty);
if (null == concatNullYieldsNullValue) {
concatNullYieldsNullValue = SQLServerDriverStringProperty.CONCAT_NULL_YIELDS_NULL.getDefaultValue();
activeConnectionProperties.setProperty(concatNullYieldsNullProperty, concatNullYieldsNullValue);
}
String concatNullYieldsNullOption = OnOffOption.valueOfString(concatNullYieldsNullValue).toString();
if (concatNullYieldsNullOption.compareToIgnoreCase(OnOffOption.OFF.toString()) == 0) {
connectionCommand("SET CONCAT_NULL_YIELDS_NULL OFF", "concatNullYieldsNull");

} else if (concatNullYieldsNullOption.compareToIgnoreCase(OnOffOption.ON.toString()) == 0) {
connectionCommand("SET CONCAT_NULL_YIELDS_NULL ON", "concatNullYieldsNull");
}
} catch(SQLServerException e) {
loggerExternal.log(Level.WARNING, "Error setting QUOTED_IDENTIFIER and CONCAT_NULL_YIELDS_NULL properties", e);
}
}

/** Limit for the maximum number of rows returned from queries on this connection */
Expand Down Expand Up @@ -3534,7 +3568,9 @@ else if (0 == requestedPacketSize)
if (connectionlogger.isLoggable(Level.FINER)) {
connectionlogger.finer(toString() + " End of connect");
}
} catch (SocketException e) {
} catch (

SocketException e) {
throw new SQLServerException(e.getMessage(), null);
} finally {
// once we exit the connect function, the connection can be only in one of two
Expand Down Expand Up @@ -4782,6 +4818,7 @@ boolean executeReconnectCommand(TDSCommand newCommand) throws SQLServerException
*/
boolean commandComplete = false;
try {
newCommand.createCounter(null, activeConnectionProperties);
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 @@ public boolean getEnablePrepareOnFirstPreparedStatementCall() {

@Override
public void setcacheBulkCopyMetadata(boolean cacheBulkCopyMetadata) {
setBooleanProperty(connectionProps,
SQLServerDriverBooleanProperty.ENABLE_BULK_COPY_CACHE.toString(),
setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.ENABLE_BULK_COPY_CACHE.toString(),
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(),
defaultValue);
}

@Override
Expand Down Expand Up @@ -1392,7 +1390,6 @@ public int getMsiTokenCacheTtl() {
@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 @@ public String getRetryExec() {
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 @@ enum SQLServerDriverStringProperty {
DATETIME_DATATYPE("datetimeParameterType", DatetimeType.DATETIME2.toString()),
ACCESS_TOKEN_CALLBACK_CLASS("accessTokenCallbackClass", ""),
RETRY_EXEC("retryExec", ""),
RETRY_CONN("retryConn", "");
RETRY_CONN("retryConn", ""),
QUOTED_IDENTIFIER("quotedIdentifier", OnOffOption.OFF.toString()),
CONCAT_NULL_YIELDS_NULL("concatNullYieldsNull", OnOffOption.OFF.toString());

private final String name;
private final String defaultValue;
Expand Down Expand Up @@ -728,6 +730,47 @@ public String toString() {
}


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);
}
return option;
}

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


/**
* 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 @@ public final class SQLServerDriver implements java.sql.Driver {
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 @@ public final class SQLServerDriver implements java.sql.Driver {
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
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,12 @@ public void testDataSource() throws SQLServerException {

ds.setKeyStorePrincipalId(stringPropValue);
assertTrue(ds.getKeyStorePrincipalId().equals(stringPropValue));

ds.setQuotedIdentifier(stringPropValue);
assertTrue(ds.getQuotedIdentifier().equals(stringPropValue));

ds.setConcatNullYieldsNull(stringPropValue);
assertTrue(ds.getConcatNullYieldsNull().equals(stringPropValue));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ public void compareStoredProcTest() throws SQLException {
"SELECT cInt FROM " + tableName + " WHERE (cInt + (3 - 5)) = ?",
"SELECT cInt FROM " + tableName + " WHERE " + tableName + ".[cInt] = ?",
"SELECT cInt FROM " + tableName + " WHERE ? = " + tableName + ".[cInt]",
"WITH t1(cInt) AS (SELECT 1), t2(cInt) AS (SELECT 2) SELECT * FROM t1 JOIN t2 ON [t1].\"cInt\" = \"t2\".[cInt] WHERE \"t1\".[cInt] = [t2].\"cInt\" + ?",
"WITH t1(cInt) AS (SELECT 1), t2(cInt) AS (SELECT 2) SELECT * FROM t1 JOIN t2 ON [t1].[cInt] = [t2].[cInt] WHERE [t1].[cInt] = [t2].[cInt] + ?",
"INSERT INTO " + tableName + "(cInt,cFloat) SELECT 1,1.5 WHERE 1 > ?",
"WITH t1(cInt) AS (SELECT 1), t2(cInt) AS (SELECT 2), t3(cInt) AS (SELECT 3) SELECT * FROM t1,t2,t3 WHERE t1.cInt >= ?",
"SELECT (1),2,[cInt],\"cFloat\" FROM " + tableName + " WHERE cNvarchar LIKE ?",
"WITH t1(cInt) AS (SELECT 1) SELECT * FROM \"t1\"");
"SELECT (1),2,[cInt],[cFloat] FROM " + tableName + " WHERE cNvarchar LIKE ?",
"WITH t1(cInt) AS (SELECT 1) SELECT * FROM [t1]");
l.forEach(this::compareFmtAndSp);
}

Expand Down
Loading