This is an automated email from the ASF dual-hosted git repository.

vjasani pushed a commit to branch 5.2
in repository https://gitbox.apache.org/repos/asf/phoenix.git


The following commit(s) were added to refs/heads/5.2 by this push:
     new ee0f4051fb PHOENIX-7299 :- ScanningResultIterator should not time out 
a query after receiving a valid result (#1872)
ee0f4051fb is described below

commit ee0f4051fbefdecf8226ff7f3a42e0cad83d1405
Author: Lokesh Khurana <khuranalokes...@gmail.com>
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

Reply via email to