This is an automated email from the ASF dual-hosted git repository.
lokiore pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/phoenix.git
The following commit(s) were added to refs/heads/master by this push:
new d8f6e6ea53 PHOENIX-7299 :- ScanningResultIterator should not time out
a query after receiving a valid result (#1872)
d8f6e6ea53 is described below
commit d8f6e6ea53e0f4a96e492f925f15571df34f7d87
Author: Lokesh Khurana <[email protected]>
AuthorDate: Wed Apr 3 22:04:07 2024 -0700
PHOENIX-7299 :- ScanningResultIterator should not time out a query after
receiving a valid result (#1872)
---
.../phoenix/iterate/ScanningResultIterator.java | 5 +-
.../phoenix/iterate/PhoenixQueryTimeoutIT.java | 55 ++++++++++++++++++++++
2 files changed, 59 insertions(+), 1 deletion(-)
diff --git
a/phoenix-core-client/src/main/java/org/apache/phoenix/iterate/ScanningResultIterator.java
b/phoenix-core-client/src/main/java/org/apache/phoenix/iterate/ScanningResultIterator.java
index 82081267bf..979bd1f41a 100644
---
a/phoenix-core-client/src/main/java/org/apache/phoenix/iterate/ScanningResultIterator.java
+++
b/phoenix-core-client/src/main/java/org/apache/phoenix/iterate/ScanningResultIterator.java
@@ -85,6 +85,8 @@ public class ScanningResultIterator implements ResultIterator
{
private long dummyRowCounter = 0;
+ private boolean hasFirstValidResult = false;
+
private final ScanningResultPostDummyResultCaller
scanningResultPostDummyResultCaller;
private final ScanningResultPostValidResultCaller
scanningResultPostValidResultCaller;
@@ -205,7 +207,7 @@ public class ScanningResultIterator implements
ResultIterator {
while (result != null && (result.isEmpty() || isDummy(result))) {
dummyRowCounter += 1;
long timeOutForScan = maxQueryEndTime -
EnvironmentEdgeManager.currentTimeMillis();
- if (timeOutForScan < 0) {
+ if (!hasFirstValidResult && timeOutForScan < 0) {
throw new
SQLExceptionInfo.Builder(OPERATION_TIMED_OUT).setMessage(
". Query couldn't be completed in the allotted
time : "
+
context.getStatement().getQueryTimeoutInMillis() + "
ms").build().buildException();
@@ -225,6 +227,7 @@ public class ScanningResultIterator implements
ResultIterator {
close(); // Free up resources early
return null;
}
+ hasFirstValidResult = true;
// TODO: use ResultTuple.setResult(result)?
// Need to create a new one if holding on to it (i.e.
OrderedResultIterator)
processAfterRetrievingValidResult();
diff --git
a/phoenix-core/src/it/java/org/apache/phoenix/iterate/PhoenixQueryTimeoutIT.java
b/phoenix-core/src/it/java/org/apache/phoenix/iterate/PhoenixQueryTimeoutIT.java
index 43dd06a645..8157135e40 100644
---
a/phoenix-core/src/it/java/org/apache/phoenix/iterate/PhoenixQueryTimeoutIT.java
+++
b/phoenix-core/src/it/java/org/apache/phoenix/iterate/PhoenixQueryTimeoutIT.java
@@ -48,6 +48,8 @@ import org.apache.phoenix.end2end.ParallelStatsDisabledIT;
import org.apache.phoenix.jdbc.PhoenixConnection;
import org.apache.phoenix.jdbc.PhoenixStatement;
import org.apache.phoenix.query.QueryServices;
+import org.apache.phoenix.util.EnvironmentEdgeManager;
+import org.apache.phoenix.util.ManualEnvironmentEdge;
import org.apache.phoenix.util.ReadOnlyProps;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -202,6 +204,59 @@ public class PhoenixQueryTimeoutIT extends
ParallelStatsDisabledIT {
}
}
+ @Test
+ public void
testScanningResultIteratorShouldNotQueryTimeoutForPagingAfterReceivingAValidRow()
throws Exception {
+ //Arrange
+ PreparedStatement ps = loadDataAndPreparePagedQuery(10,1);
+
+ ManualEnvironmentEdge injectEdge;
+ injectEdge = new ManualEnvironmentEdge();
+ injectEdge.setValue(EnvironmentEdgeManager.currentTimeMillis());
+ EnvironmentEdgeManager.injectEdge(injectEdge);
+ // First query we are executing with timeout of 10ms, so it should not
timeout as first row will be retrieved
+ // before 10 ms.
+
+ //Act + Assert
+ try {
+ //Do not let BaseResultIterators throw Timeout Exception Let
ScanningResultIterator handle it.
+
BaseResultIterators.setForTestingSetTimeoutToMaxToLetQueryPassHere(true);
+ ResultSet rs = ps.executeQuery();
+ while(rs.next()) {
+ injectEdge.incrementValue(10);
+ }
+ } catch (SQLException e) {
+ fail("Query should have run smoothly");
+ } finally {
+
BaseResultIterators.setForTestingSetTimeoutToMaxToLetQueryPassHere(false);
+ }
+
+ PreparedStatement failingPs = loadDataAndPreparePagedQuery(0,0);
+ //Second query should timeout as queryTimeout is set to 0ms
+ try {
+ //Do not let BaseResultIterators throw Timeout Exception Let
ScanningResultIterator handle it.
+
BaseResultIterators.setForTestingSetTimeoutToMaxToLetQueryPassHere(true);
+ ResultSet rs = failingPs.executeQuery();
+ EnvironmentEdgeManager.reset();
+ while(rs.next()) {}
+ fail("Expected query to timeout with a 0 ms timeout");
+ } catch (SQLException e) {
+ //OPERATION_TIMED_OUT Exception expected
+ Throwable t = e;
+ // SQLTimeoutException can be wrapped inside outer exceptions like
PhoenixIOException
+ while (t != null && !(t instanceof SQLTimeoutException)) {
+ t = t.getCause();
+ }
+ if (t == null) {
+ fail("Expected query to fail with SQLTimeoutException");
+ }
+ assertEquals(OPERATION_TIMED_OUT.getErrorCode(),
+ ((SQLTimeoutException)t).getErrorCode());
+ } finally {
+
BaseResultIterators.setForTestingSetTimeoutToMaxToLetQueryPassHere(false);
+ }
+
+ }
+
@Test
public void
testScanningResultIteratorQueryTimeoutForPagingWithNormalLowTimeout() throws
Exception {
//Arrange