PHOENIX-4658 IllegalStateException: requestSeek cannot be called on 
ReversedKeyValueHeap (Toshihiro Suzuki)


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/0987d09f
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/0987d09f
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/0987d09f

Branch: refs/heads/4.x-cdh5.11
Commit: 0987d09fafda519bff73e50f7dcd4fbd303678ec
Parents: 08564a9
Author: James Taylor <jtay...@salesforce.com>
Authored: Wed Apr 11 21:31:38 2018 +0100
Committer: Pedro Boado <pbo...@apache.org>
Committed: Fri Apr 13 23:27:22 2018 +0100

----------------------------------------------------------------------
 .../phoenix/end2end/MultiCfQueryExecIT.java     | 47 ++++++++++++++++++++
 .../apache/phoenix/compile/OrderByCompiler.java | 11 +++--
 .../apache/phoenix/compile/QueryCompiler.java   | 12 +----
 .../java/org/apache/phoenix/parse/HintNode.java |  4 ++
 .../java/org/apache/phoenix/util/ScanUtil.java  |  2 +
 5 files changed, 62 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/0987d09f/phoenix-core/src/it/java/org/apache/phoenix/end2end/MultiCfQueryExecIT.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/MultiCfQueryExecIT.java 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/MultiCfQueryExecIT.java
index d94df6c..01da2d8 100644
--- 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/MultiCfQueryExecIT.java
+++ 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/MultiCfQueryExecIT.java
@@ -31,11 +31,13 @@ import java.sql.DriverManager;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Statement;
 import java.util.List;
 import java.util.Properties;
 
 import org.apache.phoenix.query.KeyRange;
 import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.QueryUtil;
 import org.apache.phoenix.util.SchemaUtil;
 import org.apache.phoenix.util.TestUtil;
 import org.junit.Before;
@@ -406,4 +408,49 @@ public class MultiCfQueryExecIT extends 
ParallelStatsEnabledIT {
             assertFalse(rs.next());
         }
     }
+
+    @Test
+    public void testBug4658() throws Exception {
+        try (Connection conn = DriverManager.getConnection(getUrl());
+          Statement stmt = conn.createStatement()) {
+            String tableName = generateUniqueName();
+
+            stmt.execute("CREATE TABLE " + tableName + " ("
+                + "COL1 VARCHAR NOT NULL,"
+                + "COL2 VARCHAR NOT NULL,"
+                + "COL3 VARCHAR,"
+                + "FAM.COL4 VARCHAR,"
+                + "CONSTRAINT TRADE_EVENT_PK PRIMARY KEY (COL1, COL2))");
+            stmt.execute("UPSERT INTO " + tableName + " (COL1, COL2) values 
('111', 'AAA')");
+            stmt.execute("UPSERT INTO " + tableName + " (COL1, COL2) values 
('222', 'AAA')");
+            conn.commit();
+
+            try (ResultSet rs = stmt.executeQuery(
+              "SELECT * FROM " + tableName + " WHERE COL2 = 'AAA' ORDER BY 
COL1 DESC")) {
+                assertTrue(rs.next());
+                assertEquals(rs.getString("COL1"), "222");
+                assertEquals(rs.getString("COL2"), "AAA");
+                assertTrue(rs.next());
+                assertEquals(rs.getString("COL1"), "111");
+                assertEquals(rs.getString("COL2"), "AAA");
+                assertFalse(rs.next());
+            }
+
+            // Tests for FORWARD_SCAN hint
+            String query = "SELECT /*+ FORWARD_SCAN */ * FROM " + tableName + 
" WHERE COL2 = 'AAA' ORDER BY COL1 DESC";
+            try (ResultSet rs = stmt.executeQuery("EXPLAIN " + query)) {
+                String explainPlan = QueryUtil.getExplainPlan(rs);
+                assertFalse(explainPlan.contains("REVERSE"));
+            }
+            try (ResultSet rs = stmt.executeQuery(query)) {
+                assertTrue(rs.next());
+                assertEquals(rs.getString("COL1"), "222");
+                assertEquals(rs.getString("COL2"), "AAA");
+                assertTrue(rs.next());
+                assertEquals(rs.getString("COL1"), "111");
+                assertEquals(rs.getString("COL2"), "AAA");
+                assertFalse(rs.next());
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/0987d09f/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java 
b/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java
index 1097f70..b83c7a8 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderByCompiler.java
@@ -30,6 +30,7 @@ import org.apache.phoenix.exception.SQLExceptionInfo;
 import org.apache.phoenix.execute.TupleProjector;
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.expression.OrderByExpression;
+import org.apache.phoenix.parse.HintNode.Hint;
 import org.apache.phoenix.parse.LiteralParseNode;
 import org.apache.phoenix.parse.OrderByNode;
 import org.apache.phoenix.parse.ParseNode;
@@ -154,12 +155,16 @@ public class OrderByCompiler {
         // If we're ordering by the order returned by the scan, we don't need 
an order by
         if (isInRowKeyOrder && tracker.isOrderPreserving()) {
             if (tracker.isReverse()) {
-                // Don't use reverse scan if we're using a skip scan, as our 
skip scan doesn't support this yet.
+                // Don't use reverse scan if:
+                // 1) we're using a skip scan, as our skip scan doesn't 
support this yet.
+                // 2) we have the FORWARD_SCAN hint set to choose to keep 
loading of column
+                //    families on demand versus doing a reverse scan
                 // REV_ROW_KEY_ORDER_BY scan would not take effect for a 
projected table, so don't return it for such table types.
                 if 
(context.getConnection().getQueryServices().getProps().getBoolean(QueryServices.USE_REVERSE_SCAN_ATTRIB,
 QueryServicesOptions.DEFAULT_USE_REVERSE_SCAN)
                         && !context.getScanRanges().useSkipScanFilter()
                         && context.getCurrentTable().getTable().getType() != 
PTableType.PROJECTED
-                        && context.getCurrentTable().getTable().getType() != 
PTableType.SUBQUERY) {
+                        && context.getCurrentTable().getTable().getType() != 
PTableType.SUBQUERY
+                        && !statement.getHint().hasHint(Hint.FORWARD_SCAN)) {
                     return OrderBy.REV_ROW_KEY_ORDER_BY;
                 }
             } else {
@@ -172,4 +177,4 @@ public class OrderByCompiler {
 
     private OrderByCompiler() {
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/0987d09f/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java 
b/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
index 9568ad8..3e5f5ee 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
@@ -66,7 +66,6 @@ import org.apache.phoenix.parse.SelectStatement;
 import org.apache.phoenix.parse.SubqueryParseNode;
 import org.apache.phoenix.parse.TableNode;
 import org.apache.phoenix.query.ConnectionQueryServices;
-import org.apache.phoenix.query.QueryConstants;
 import org.apache.phoenix.query.QueryServices;
 import org.apache.phoenix.query.QueryServicesOptions;
 import org.apache.phoenix.schema.AmbiguousColumnException;
@@ -91,13 +90,6 @@ import com.google.common.collect.Sets;
  */
 public class QueryCompiler {
     private static final ParseNodeFactory NODE_FACTORY = new 
ParseNodeFactory();
-    /*
-     * Not using Scan.setLoadColumnFamiliesOnDemand(true) because we don't
-     * want to introduce a dependency on 0.94.5 (where this feature was
-     * introduced). This will do the same thing. Once we do have a
-     * dependency on 0.94.5 or above, switch this around.
-     */
-    private static final String LOAD_COLUMN_FAMILIES_ON_DEMAND_ATTR = 
"_ondemand_";
     private final PhoenixStatement statement;
     private final Scan scan;
     private final Scan originalScan;
@@ -128,9 +120,7 @@ public class QueryCompiler {
         this.noChildParentJoinOptimization = 
select.getHint().hasHint(Hint.NO_CHILD_PARENT_JOIN_OPTIMIZATION);
         ConnectionQueryServices services = 
statement.getConnection().getQueryServices();
         this.costBased = 
services.getProps().getBoolean(QueryServices.COST_BASED_OPTIMIZER_ENABLED, 
QueryServicesOptions.DEFAULT_COST_BASED_OPTIMIZER_ENABLED);
-        if (services.getLowestClusterHBaseVersion() >= 
PhoenixDatabaseMetaData.ESSENTIAL_FAMILY_VERSION_THRESHOLD) {
-            this.scan.setAttribute(LOAD_COLUMN_FAMILIES_ON_DEMAND_ATTR, 
QueryConstants.TRUE);
-        }
+        scan.setLoadColumnFamiliesOnDemand(true);
         if (select.getHint().hasHint(Hint.NO_CACHE)) {
             scan.setCacheBlocks(false);
         }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/0987d09f/phoenix-core/src/main/java/org/apache/phoenix/parse/HintNode.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/HintNode.java 
b/phoenix-core/src/main/java/org/apache/phoenix/parse/HintNode.java
index 6d8451b..39e9b05 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/HintNode.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/HintNode.java
@@ -104,6 +104,10 @@ public class HintNode {
       * Enforces a serial scan.
       */
      SERIAL,
+        /**
+         * Enforces a forward scan.
+         */
+        FORWARD_SCAN,
     };
 
     private final Map<Hint,String> hints;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/0987d09f/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java 
b/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
index 9c710c1..dd885fd 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/ScanUtil.java
@@ -612,10 +612,12 @@ public class ScanUtil {
     
     public static void setReversed(Scan scan) {
         scan.setAttribute(BaseScannerRegionObserver.REVERSE_SCAN, 
PDataType.TRUE_BYTES);
+        scan.setLoadColumnFamiliesOnDemand(false);
     }
 
     public static void unsetReversed(Scan scan) {
         scan.setAttribute(BaseScannerRegionObserver.REVERSE_SCAN, 
PDataType.FALSE_BYTES);
+        scan.setLoadColumnFamiliesOnDemand(true);
     }
 
     private static byte[] getReversedRow(byte[] startRow) {

Reply via email to