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

Fix | Connection pool proxy with delayLoadingLobs #1403

Merged
merged 23 commits into from
Aug 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7c9d4e0
check exp
rene-ye Jul 15, 2020
0c88dab
Change "0" to ""
rene-ye Jul 20, 2020
562a5bd
Remove AE cert
rene-ye Jul 27, 2020
f274639
Merge branch 'dev' of https://github.com/microsoft/mssql-jdbc into ch…
rene-ye Jul 27, 2020
8645964
Remove cert check in KeystoreCommon
rene-ye Jul 28, 2020
f534eb2
Fix comment grammar
rene-ye Jul 28, 2020
abffa05
changes for connecitonpoolproxy
rene-ye Aug 5, 2020
bd35d5d
Merge branch 'dev' of https://github.com/microsoft/mssql-jdbc into ch…
rene-ye Aug 5, 2020
992c515
Merge branch 'checkHash' of https://github.com/rene-ye/mssql-jdbc int…
rene-ye Aug 5, 2020
72a3151
Add test
rene-ye Aug 5, 2020
a1e8291
Remove displayname
rene-ye Aug 5, 2020
469d618
Add new public methods to requestBoundaryTest
rene-ye Aug 6, 2020
8499a7c
Merge branch 'connectionPoolProxy' of https://github.com/rene-ye/mssq…
rene-ye Aug 6, 2020
7056c60
change default
rene-ye Aug 12, 2020
ed66b63
add delayLoadingLobs to req boundary methods
rene-ye Aug 12, 2020
67592f2
test fix
rene-ye Aug 12, 2020
56d779a
Merge branch 'connectionPoolProxy' of https://github.com/rene-ye/mssq…
rene-ye Aug 12, 2020
171f564
wrong function name
rene-ye Aug 12, 2020
946cabb
Update src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnection…
rene-ye Aug 13, 2020
fc5f700
comments
rene-ye Aug 14, 2020
20b67d4
Fix for null column
rene-ye Aug 18, 2020
325321a
Address comments
rene-ye Aug 21, 2020
e5b166d
remove comments
rene-ye Aug 24, 2020
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 @@ -358,4 +358,19 @@ CallableStatement prepareCall(String sql, int nType, int nConcur, int nHold,
* boolean value for 'useFmtOnly'.
*/
void setUseFmtOnly(boolean useFmtOnly);

/**
* Returns the current flag value for delayLoadingLobs.
*
* @return 'delayLoadingLobs' property value.
*/
boolean getDelayLoadingLobs();
rene-ye marked this conversation as resolved.
Show resolved Hide resolved

/**
* Specifies the flag to immediately load LOB objects into memory.
*
* @param delayLoadingLobs
* boolean value for 'delayLoadingLobs'.
*/
void setDelayLoadingLobs(boolean delayLoadingLobs);
}
Original file line number Diff line number Diff line change
Expand Up @@ -702,10 +702,16 @@ byte getServerSupportedDataClassificationVersion() {
// Boolean that indicates whether LOB objects created by this connection should be loaded into memory
private boolean delayLoadingLobs = SQLServerDriverBooleanProperty.DELAY_LOADING_LOBS.getDefaultValue();

boolean getDelayLoadingLobs() {
@Override
public boolean getDelayLoadingLobs() {
rene-ye marked this conversation as resolved.
Show resolved Hide resolved
return delayLoadingLobs;
}

@Override
public void setDelayLoadingLobs(boolean b) {
rene-ye marked this conversation as resolved.
Show resolved Hide resolved
delayLoadingLobs = b;
}

static Map<String, SQLServerColumnEncryptionKeyStoreProvider> globalSystemColumnEncryptionKeyStoreProviders = new HashMap<>();
static {
if (System.getProperty("os.name").toLowerCase(Locale.ENGLISH).startsWith("windows")) {
Expand Down Expand Up @@ -5838,6 +5844,7 @@ public <T> T unwrap(Class<T> iface) throws SQLException {
private volatile SQLWarning originalSqlWarnings;
private List<ISQLServerStatement> openStatements;
private boolean originalUseFmtOnly;
private boolean originalDelayLoadingLobs;

int aeVersion = TDS.COLUMNENCRYPTION_NOT_SUPPORTED;

Expand All @@ -5859,6 +5866,7 @@ protected void beginRequestInternal() throws SQLException {
originalSqlWarnings = sqlWarnings;
openStatements = new LinkedList<ISQLServerStatement>();
originalUseFmtOnly = useFmtOnly;
originalDelayLoadingLobs = delayLoadingLobs;
requestStarted = true;
}
}
Expand Down Expand Up @@ -5908,6 +5916,9 @@ protected void endRequestInternal() throws SQLException {
if (getUseBulkCopyForBatchInsert() != originalUseBulkCopyForBatchInsert) {
setUseBulkCopyForBatchInsert(originalUseBulkCopyForBatchInsert);
}
if (delayLoadingLobs != originalDelayLoadingLobs) {
setDelayLoadingLobs(originalDelayLoadingLobs);
}
sqlWarnings = originalSqlWarnings;
if (null != openStatements) {
while (!openStatements.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -593,4 +593,14 @@ public void setUseFmtOnly(boolean useFmtOnly) {
public boolean getUseFmtOnly() {
return wrappedConnection.getUseFmtOnly();
}

@Override
public boolean getDelayLoadingLobs() {
return wrappedConnection.getDelayLoadingLobs();
}

@Override
public void setDelayLoadingLobs(boolean delayLoadingLobs) {
wrappedConnection.setDelayLoadingLobs(delayLoadingLobs);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.NClob;
import java.sql.Ref;
import java.sql.ResultSet;
Expand Down Expand Up @@ -2082,9 +2083,11 @@ private SQLXML getSQLXMLInternal(int columnIndex) throws SQLServerException {

private void configureLobs(SQLServerLob lob) throws SQLServerException {
if (null != stmt) {
SQLServerConnection c = (SQLServerConnection) stmt.getConnection();
if (null != c && !c.getDelayLoadingLobs()) {
lob.setDelayLoadingLob();
Connection c = stmt.getConnection();
if (c instanceof ISQLServerConnection) {
if (null != c && !((ISQLServerConnection) c).getDelayLoadingLobs() && null != lob) {
lob.setDelayLoadingLob();
}
}
}
activeLOB = lob;
Expand Down Expand Up @@ -2638,7 +2641,7 @@ public java.sql.Timestamp getTimestamp(String colName, Calendar cal) throws SQLS
loggerExternal.exiting(getClassNameLogging(), "getTimestamp", value);
return value;
}

LocalDateTime getLocalDateTime(int columnIndex) throws SQLServerException {
loggerExternal.entering(getClassNameLogging(), "getLocalDateTime", columnIndex);
checkClosed();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

import java.io.IOException;
import java.io.Reader;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
Expand Down Expand Up @@ -434,7 +437,7 @@ public void testClosedConnection() throws SQLException {
} catch (SQLServerException e) {
assertEquals(e.getMessage(), TestResource.getResource("R_connectionIsClosed"),
TestResource.getResource("R_wrongExceptionMessage"));
assertEquals("08S01", e.getSQLState(), TestResource.getResource("R_wrongSqlState"));
assertEquals("08S01", e.getSQLState(), TestResource.getResource("R_wrongSqlState"));
rene-ye marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down Expand Up @@ -567,9 +570,10 @@ public void testClientConnectionId() throws Exception {
conn.getClientConnectionId();
fail(TestResource.getResource("R_noExceptionClosedConnection"));
} catch (SQLException e) {
assertEquals(e.getMessage(), TestResource.getResource("R_connectionIsClosed"),
assertEquals(TestResource.getResource("R_connectionIsClosed"), e.getMessage(),

TestResource.getResource("R_wrongExceptionMessage"));
assertEquals("08S01", e.getSQLState(), TestResource.getResource("R_wrongSqlState"));
assertEquals("08S01", e.getSQLState(), TestResource.getResource("R_wrongSqlState"));
}
}

Expand Down Expand Up @@ -803,4 +807,57 @@ public void testRedirectedError() {
fail(TestResource.getResource("R_unexpectedErrorMessage") + e.getMessage());
}
}

/*
* Basic test to make sure lobs work with ConnectionPoolProxy as well
*/
@Test
public void testConnectionPoolProxyWithLobs() throws SQLException, IOException {
String cString = getConnectionString() + ";delayLoadingLobs=false;";
String data = "testConnectionPoolProxyWithLobs";
Clob c = null;
try (Connection conn = PrepUtil.getConnection(cString);
SQLServerConnectionPoolProxy proxy = new SQLServerConnectionPoolProxy((SQLServerConnection) conn)) {
try (Statement stmt = proxy.createStatement()) {
String tableName = RandomUtil.getIdentifier("streamingTest");
stmt.execute(
"CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (lob varchar(max))");
stmt.execute(
"INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " VALUES ('" + data + "')");
try (ResultSet rs = stmt
.executeQuery("SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName))) {
while (rs.next()) {
c = rs.getClob(1);
try (Reader r = c.getCharacterStream()) {
long clobLength = c.length();
// read the Reader contents into a buffer and return the complete string
final StringBuilder stringBuilder = new StringBuilder((int) clobLength);
char[] buffer = new char[(int) clobLength];
int amountRead = -1;
while ((amountRead = r.read(buffer, 0, (int) clobLength)) != -1) {
stringBuilder.append(buffer, 0, amountRead);
}
String received = stringBuilder.toString();
assertTrue(data.equals(received), "Expected String: " + data + "\nReceived String: " + received);
}
}
} finally {
TestUtils.dropTableIfExists(tableName, stmt);
}
}
}
// Read the lob after it's been closed
try (Reader r = c.getCharacterStream()) {
long clobLength = c.length();
// read the Reader contents into a buffer and return the complete string
final StringBuilder stringBuilder = new StringBuilder((int) clobLength);
char[] buffer = new char[(int) clobLength];
int amountRead = -1;
while ((amountRead = r.read(buffer, 0, (int) clobLength)) != -1) {
stringBuilder.append(buffer, 0, amountRead);
}
String received = stringBuilder.toString();
assertTrue(data.equals(received), "Expected String: " + data + "\nReceived String: " + received);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public void testModifiableConnectionProperties() throws SQLException {
String sCatalog1 = "master";
boolean useBulkCopyForBatchInsert1 = true;
boolean useFmtOnly1 = true;
boolean delayLoadingLobs1 = false;

boolean autoCommitMode2 = false;
int transactionIsolationLevel2 = SQLServerConnection.TRANSACTION_SERIALIZABLE;
Expand All @@ -80,6 +81,7 @@ public void testModifiableConnectionProperties() throws SQLException {
String sCatalog2 = RandomUtil.getIdentifier("RequestBoundaryDatabase");
boolean useBulkCopyForBatchInsert2 = false;
boolean useFmtOnly2 = false;
boolean delayLoadingLobs2 = true;

try (SQLServerConnection con = getConnection(); Statement stmt = con.createStatement()) {
if (TestUtils.isJDBC43OrGreater(con)) {
Expand All @@ -90,53 +92,53 @@ public void testModifiableConnectionProperties() throws SQLException {
setConnectionFields(con, autoCommitMode1, transactionIsolationLevel1, networkTimeout1, holdability1,
sendTimeAsDatetime1, statementPoolingCacheSize1, disableStatementPooling1,
serverPreparedStatementDiscardThreshold1, enablePrepareOnFirstPreparedStatementCall1, sCatalog1,
useBulkCopyForBatchInsert1, useFmtOnly1);
useBulkCopyForBatchInsert1, useFmtOnly1, delayLoadingLobs1);
con.beginRequest();
// Call setters with the second set of values inside beginRequest()/endRequest() block.
setConnectionFields(con, autoCommitMode2, transactionIsolationLevel2, networkTimeout2, holdability2,
sendTimeAsDatetime2, statementPoolingCacheSize2, disableStatementPooling2,
serverPreparedStatementDiscardThreshold2, enablePrepareOnFirstPreparedStatementCall2, sCatalog2,
useBulkCopyForBatchInsert2, useFmtOnly2);
useBulkCopyForBatchInsert2, useFmtOnly2, delayLoadingLobs2);
con.endRequest();
// Test if endRequest() resets the SQLServerConnection properties back to the first set of values.
compareValuesAgainstConnection(con, autoCommitMode1, transactionIsolationLevel1, networkTimeout1,
holdability1, sendTimeAsDatetime1, statementPoolingCacheSize1, disableStatementPooling1,
serverPreparedStatementDiscardThreshold1, enablePrepareOnFirstPreparedStatementCall1, sCatalog1,
useBulkCopyForBatchInsert1, useFmtOnly1);
useBulkCopyForBatchInsert1, useFmtOnly1, delayLoadingLobs1);

// Multiple calls to beginRequest() without an intervening call to endRequest() are no-op.
setConnectionFields(con, autoCommitMode2, transactionIsolationLevel2, networkTimeout2, holdability2,
sendTimeAsDatetime2, statementPoolingCacheSize2, disableStatementPooling2,
serverPreparedStatementDiscardThreshold2, enablePrepareOnFirstPreparedStatementCall2, sCatalog2,
useBulkCopyForBatchInsert2, useFmtOnly2);
useBulkCopyForBatchInsert2, useFmtOnly2, delayLoadingLobs2);
con.beginRequest();
setConnectionFields(con, autoCommitMode1, transactionIsolationLevel1, networkTimeout1, holdability1,
sendTimeAsDatetime1, statementPoolingCacheSize1, disableStatementPooling1,
serverPreparedStatementDiscardThreshold1, enablePrepareOnFirstPreparedStatementCall1, sCatalog1,
useBulkCopyForBatchInsert1, useFmtOnly1);
useBulkCopyForBatchInsert1, useFmtOnly1, delayLoadingLobs1);
con.beginRequest();
con.endRequest();
// Same values as before the first beginRequest()
compareValuesAgainstConnection(con, autoCommitMode2, transactionIsolationLevel2, networkTimeout2,
holdability2, sendTimeAsDatetime2, statementPoolingCacheSize2, disableStatementPooling2,
serverPreparedStatementDiscardThreshold2, enablePrepareOnFirstPreparedStatementCall2, sCatalog2,
useBulkCopyForBatchInsert2, useFmtOnly2);
useBulkCopyForBatchInsert2, useFmtOnly2, delayLoadingLobs2);

// A call to endRequest() without an intervening call to beginRequest() is no-op.
setConnectionFields(con, autoCommitMode1, transactionIsolationLevel1, networkTimeout1, holdability1,
sendTimeAsDatetime1, statementPoolingCacheSize1, disableStatementPooling1,
serverPreparedStatementDiscardThreshold1, enablePrepareOnFirstPreparedStatementCall1, sCatalog1,
useBulkCopyForBatchInsert1, useFmtOnly1);
useBulkCopyForBatchInsert1, useFmtOnly1, delayLoadingLobs1);
setConnectionFields(con, autoCommitMode2, transactionIsolationLevel2, networkTimeout2, holdability2,
sendTimeAsDatetime2, statementPoolingCacheSize2, disableStatementPooling2,
serverPreparedStatementDiscardThreshold2, enablePrepareOnFirstPreparedStatementCall2, sCatalog2,
useBulkCopyForBatchInsert2, useFmtOnly2);
useBulkCopyForBatchInsert2, useFmtOnly2, delayLoadingLobs2);
con.endRequest();
// No change.
compareValuesAgainstConnection(con, autoCommitMode2, transactionIsolationLevel2, networkTimeout2,
holdability2, sendTimeAsDatetime2, statementPoolingCacheSize2, disableStatementPooling2,
serverPreparedStatementDiscardThreshold2, enablePrepareOnFirstPreparedStatementCall2, sCatalog2,
useBulkCopyForBatchInsert2, useFmtOnly2);
useBulkCopyForBatchInsert2, useFmtOnly2, delayLoadingLobs2);
}
} finally {
TestUtils.dropDatabaseIfExists(sCatalog2, connectionString);
Expand Down Expand Up @@ -389,7 +391,7 @@ private void setConnectionFields(SQLServerConnection con, boolean autoCommitMode
int networkTimeout, int holdability, boolean sendTimeAsDatetime, int statementPoolingCacheSize,
boolean disableStatementPooling, int serverPreparedStatementDiscardThreshold,
boolean enablePrepareOnFirstPreparedStatementCall, String sCatalog, boolean useBulkCopyForBatchInsert,
boolean useFmtOnly) throws SQLException {
boolean useFmtOnly, boolean delayLoadingLobs) throws SQLException {
con.setAutoCommit(autoCommitMode);
con.setTransactionIsolation(transactionIsolationLevel);
con.setNetworkTimeout(null, networkTimeout);
Expand All @@ -402,13 +404,14 @@ private void setConnectionFields(SQLServerConnection con, boolean autoCommitMode
con.setCatalog(sCatalog);
con.setUseBulkCopyForBatchInsert(useBulkCopyForBatchInsert);
con.setUseFmtOnly(useFmtOnly);
con.setDelayLoadingLobs(delayLoadingLobs);
}

private void compareValuesAgainstConnection(SQLServerConnection con, boolean autoCommitMode,
int transactionIsolationLevel, int networkTimeout, int holdability, boolean sendTimeAsDatetime,
int statementPoolingCacheSize, boolean disableStatementPooling, int serverPreparedStatementDiscardThreshold,
boolean enablePrepareOnFirstPreparedStatementCall, String sCatalog, boolean useBulkCopyForBatchInsert,
boolean useFmtOnly) throws SQLException {
boolean useFmtOnly, boolean delayLoadingLobs) throws SQLException {
final String description = " values do not match.";
assertEquals(autoCommitMode, con.getAutoCommit(), "autoCommitmode" + description);
assertEquals(transactionIsolationLevel, con.getTransactionIsolation(),
Expand All @@ -428,6 +431,7 @@ private void compareValuesAgainstConnection(SQLServerConnection con, boolean aut
assertEquals(useBulkCopyForBatchInsert, con.getUseBulkCopyForBatchInsert(),
"useBulkCopyForBatchInsert" + description);
assertEquals(useFmtOnly, con.getUseFmtOnly(), "useFmtOnly" + description);
assertEquals(delayLoadingLobs, con.getDelayLoadingLobs(), "delayLoadingLobs" + description);
}

private void generateWarning(Connection con) throws SQLException {
Expand Down Expand Up @@ -483,6 +487,7 @@ private List<String> getVerifiedMethodNames() {
verifiedMethodNames.add("setTypeMap");
verifiedMethodNames.add("createArrayOf");
verifiedMethodNames.add("setUseFmtOnly");
verifiedMethodNames.add("setDelayLoadingLobs");

return verifiedMethodNames;
}
Expand Down