From ff1f049fa39d11a194edc29d09df7bb6efda17bd Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Thu, 15 Feb 2018 12:42:30 -0800 Subject: [PATCH 1/4] Added needsPrepare Check and removed error code 99586 check --- .../sqlserver/jdbc/SQLServerPreparedStatement.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java index 0ec3d4aab..5da1b8db1 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java @@ -548,7 +548,7 @@ final void doExecutePreparedStatement(PrepStmtExecCmd command) throws SQLServerE getNextResult(); } catch (SQLException e) { - if (retryBasedOnFailedReuseOfCachedHandle(e, attempt)) + if (retryBasedOnFailedReuseOfCachedHandle(e, attempt, needsPrepare)) continue; else throw e; @@ -566,13 +566,13 @@ else if (EXECUTE_UPDATE == executeMethod && null != resultSet) { /** Should the execution be retried because the re-used cached handle could not be re-used due to server side state changes? */ private boolean retryBasedOnFailedReuseOfCachedHandle(SQLException e, - int attempt) { + int attempt, boolean needsPrepare) { // Only retry based on these error codes and if statementPooling is enabled: // 586: The prepared statement handle %d is not valid in this context. Please verify that current database, user default schema, and // ANSI_NULLS and QUOTED_IDENTIFIER set options are not changed since the handle is prepared. // 8179: Could not find prepared statement with handle %d. - // 99586: Error used for testing. - return 1 == attempt && (586 == e.getErrorCode() || 8179 == e.getErrorCode() || 99586 == e.getErrorCode()) && connection.isStatementPoolingEnabled(); + if(needsPrepare) {return false;} + return 1 == attempt && (586 == e.getErrorCode() || 8179 == e.getErrorCode()) && connection.isStatementPoolingEnabled(); } /** @@ -2692,7 +2692,7 @@ final void doExecutePreparedStatementBatch(PrepStmtBatchExecCmd batchCommand) th throw e; // Retry if invalid handle exception. - if (retryBasedOnFailedReuseOfCachedHandle(e, attempt)) { + if (retryBasedOnFailedReuseOfCachedHandle(e, attempt, needsPrepare)) { // reset number of batches prepare numBatchesPrepared = numBatchesExecuted; retry = true; @@ -2723,7 +2723,7 @@ final void doExecutePreparedStatementBatch(PrepStmtBatchExecCmd batchCommand) th } } catch (SQLException e) { - if (retryBasedOnFailedReuseOfCachedHandle(e, attempt) && connection.isStatementPoolingEnabled()) { + if (retryBasedOnFailedReuseOfCachedHandle(e, attempt, needsPrepare) && connection.isStatementPoolingEnabled()) { // Reset number of batches prepared. numBatchesPrepared = numBatchesExecuted; continue; From ba2460c18df023714d31d35c0313f31358f188f4 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Thu, 15 Feb 2018 13:29:10 -0800 Subject: [PATCH 2/4] Added check for needsPrepare and removed 99586 check + Moved NeedsPrepare to class level declaration to avoid multi-threading issues. --- .../sqlserver/jdbc/SQLServerPreparedStatement.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java index 5da1b8db1..cbb4687f9 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java @@ -69,6 +69,7 @@ public class SQLServerPreparedStatement extends SQLServerStatement implements IS /** True if this execute has been called for this statement at least once */ private boolean isExecutedAtLeastOnce = false; + private boolean needsPrepare = false; /** Reference to cache item for statement handle pooling. Only used to decrement ref count on statement close. */ private PreparedStatementHandle cachedPreparedStatementHandle; @@ -528,7 +529,6 @@ final void doExecutePreparedStatement(PrepStmtExecCmd command) throws SQLServerE } String dbName = connection.getSCatalog(); - boolean needsPrepare = false; // Retry execution if existing handle could not be re-used. for (int attempt = 1; attempt <= 2; ++attempt) { try { @@ -571,7 +571,7 @@ private boolean retryBasedOnFailedReuseOfCachedHandle(SQLException e, // 586: The prepared statement handle %d is not valid in this context. Please verify that current database, user default schema, and // ANSI_NULLS and QUOTED_IDENTIFIER set options are not changed since the handle is prepared. // 8179: Could not find prepared statement with handle %d. - if(needsPrepare) {return false;} + if(needsPrepare) return false; return 1 == attempt && (586 == e.getErrorCode() || 8179 == e.getErrorCode()) && connection.isStatementPoolingEnabled(); } @@ -981,7 +981,7 @@ private boolean doPrepExec(TDSWriter tdsWriter, boolean hasNewTypeDefinitions, boolean hasExistingTypeDefinitions) throws SQLServerException { - boolean needsPrepare = (hasNewTypeDefinitions && hasExistingTypeDefinitions) || !hasPreparedStatementHandle(); + needsPrepare = (hasNewTypeDefinitions && hasExistingTypeDefinitions) || !hasPreparedStatementHandle(); // Cursors don't use statement pooling. if (isCursorable(executeMethod)) { @@ -2629,7 +2629,6 @@ final void doExecutePreparedStatementBatch(PrepStmtBatchExecCmd batchCommand) th } String dbName = connection.getSCatalog(); - boolean needsPrepare = false; // Retry execution if existing handle could not be re-used. for (int attempt = 1; attempt <= 2; ++attempt) { try { From 0eb0a6140d66cb0a63e86a4317e8f31b6c2b22a1 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Thu, 15 Feb 2018 14:32:18 -0800 Subject: [PATCH 3/4] Moved 'needsPrepare' to local variable. --- .../microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java index cbb4687f9..67bc5dd68 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java @@ -69,7 +69,6 @@ public class SQLServerPreparedStatement extends SQLServerStatement implements IS /** True if this execute has been called for this statement at least once */ private boolean isExecutedAtLeastOnce = false; - private boolean needsPrepare = false; /** Reference to cache item for statement handle pooling. Only used to decrement ref count on statement close. */ private PreparedStatementHandle cachedPreparedStatementHandle; @@ -529,6 +528,7 @@ final void doExecutePreparedStatement(PrepStmtExecCmd command) throws SQLServerE } String dbName = connection.getSCatalog(); + boolean needsPrepare = false; // Retry execution if existing handle could not be re-used. for (int attempt = 1; attempt <= 2; ++attempt) { try { @@ -981,7 +981,7 @@ private boolean doPrepExec(TDSWriter tdsWriter, boolean hasNewTypeDefinitions, boolean hasExistingTypeDefinitions) throws SQLServerException { - needsPrepare = (hasNewTypeDefinitions && hasExistingTypeDefinitions) || !hasPreparedStatementHandle(); + boolean needsPrepare = (hasNewTypeDefinitions && hasExistingTypeDefinitions) || !hasPreparedStatementHandle(); // Cursors don't use statement pooling. if (isCursorable(executeMethod)) { @@ -2629,6 +2629,7 @@ final void doExecutePreparedStatementBatch(PrepStmtBatchExecCmd batchCommand) th } String dbName = connection.getSCatalog(); + boolean needsPrepare = false; // Retry execution if existing handle could not be re-used. for (int attempt = 1; attempt <= 2; ++attempt) { try { From ea723f6492e6bc81e3a9187ce4455f0ea52dbd95 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Thu, 15 Feb 2018 16:28:36 -0800 Subject: [PATCH 4/4] Defaulting needsPrepare to true. --- .../microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java index 67bc5dd68..262728a94 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java @@ -528,7 +528,7 @@ final void doExecutePreparedStatement(PrepStmtExecCmd command) throws SQLServerE } String dbName = connection.getSCatalog(); - boolean needsPrepare = false; + boolean needsPrepare = true; // Retry execution if existing handle could not be re-used. for (int attempt = 1; attempt <= 2; ++attempt) { try { @@ -2629,7 +2629,7 @@ final void doExecutePreparedStatementBatch(PrepStmtBatchExecCmd batchCommand) th } String dbName = connection.getSCatalog(); - boolean needsPrepare = false; + boolean needsPrepare = true; // Retry execution if existing handle could not be re-used. for (int attempt = 1; attempt <= 2; ++attempt) { try {