Repository: phoenix
Updated Branches:
  refs/heads/calcite 1193e5afe -> 4f01c91ec


PHOENIX-2827 Support OFFSET in Calcite-Phoenix (Eric Lomore)


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

Branch: refs/heads/calcite
Commit: 4f01c91ec78988058fbed1f31a51e2bf06db04a8
Parents: 1193e5a
Author: maryannxue <maryann....@gmail.com>
Authored: Mon Oct 3 13:09:26 2016 -0700
Committer: maryannxue <maryann....@gmail.com>
Committed: Mon Oct 3 13:10:18 2016 -0700

----------------------------------------------------------------------
 .../org/apache/phoenix/calcite/CalciteIT.java   | 259 ++++++++++++++-----
 .../phoenix/calcite/rel/PhoenixLimit.java       |  17 +-
 .../rel/PhoenixToEnumerableConverter.java       |   4 +-
 .../calcite/rules/PhoenixConverterRules.java    |   3 +-
 .../phoenix/compile/ListJarsQueryPlan.java      |   2 +-
 .../org/apache/phoenix/compile/QueryPlan.java   |  11 +-
 .../apache/phoenix/compile/TraceQueryPlan.java  |   2 +-
 .../apache/phoenix/execute/AggregatePlan.java   |  17 +-
 .../phoenix/execute/ClientAggregatePlan.java    |  15 +-
 .../apache/phoenix/execute/ClientScanPlan.java  |  15 +-
 .../apache/phoenix/execute/CorrelatePlan.java   |  12 +-
 .../phoenix/execute/DegenerateQueryPlan.java    |   2 +-
 .../phoenix/execute/DelegateQueryPlan.java      |  12 +-
 .../apache/phoenix/execute/HashJoinPlan.java    |   4 +-
 .../execute/LiteralResultIterationPlan.java     |  16 +-
 .../org/apache/phoenix/execute/ScanPlan.java    |  16 +-
 .../phoenix/execute/SortMergeJoinPlan.java      |  10 +-
 .../phoenix/execute/TupleProjectionPlan.java    |   4 +-
 .../org/apache/phoenix/execute/UnionPlan.java   |  11 +-
 .../apache/phoenix/execute/UnnestArrayPlan.java |  10 +-
 .../apache/phoenix/jdbc/PhoenixStatement.java   |   2 +-
 .../query/ParallelIteratorsSplitTest.java       |   2 +-
 22 files changed, 300 insertions(+), 146 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteIT.java 
b/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteIT.java
index da6303b..abea491 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteIT.java
@@ -280,19 +280,19 @@ public class CalciteIT extends BaseCalciteIT {
                            "      PhoenixServerProject(supplier_id=[$0], 
NAME=[$1])\n" +
                            "        PhoenixTableScan(table=[[phoenix, Join, 
SupplierTable]], scanOrder=[FORWARD])\n")
                 .close();
-        
-        start(false, 1000f).sql("SELECT \"order_id\", i.name, i.price, 
discount2, quantity FROM " + JOIN_ORDER_TABLE_FULL_NAME + " o LEFT JOIN " 
-                + JOIN_ITEM_TABLE_FULL_NAME + " i ON o.\"item_id\" = 
i.\"item_id\" limit 2")
-                .explainIs("PhoenixToEnumerableConverter\n" +
-                                  "  PhoenixClientProject(order_id=[$0], 
NAME=[$4], PRICE=[$5], DISCOUNT2=[$6], QUANTITY=[$2])\n" +
-                                  "    PhoenixLimit(fetch=[2])\n" +
-                                  "      PhoenixClientJoin(condition=[=($1, 
$3)], joinType=[left])\n" +
-                                  "        PhoenixClientSort(sort0=[$1], 
dir0=[ASC])\n" +
-                                  "          PhoenixLimit(fetch=[2])\n" +
-                                  "            
PhoenixServerProject(order_id=[$0], item_id=[$2], QUANTITY=[$4])\n" +
-                                  "              
PhoenixTableScan(table=[[phoenix, Join, OrderTable]])\n" +
-                                  "        PhoenixServerProject(item_id=[$0], 
NAME=[$1], PRICE=[$2], DISCOUNT2=[$4])\n" +
-                                  "          PhoenixTableScan(table=[[phoenix, 
Join, ItemTable]], scanOrder=[FORWARD])\n")
+
+        start(false, 1000f).sql("SELECT \"order_id\", i.name, i.price, 
discount2, quantity FROM " + JOIN_ORDER_TABLE_FULL_NAME + " o LEFT JOIN "
+                + JOIN_ITEM_TABLE_FULL_NAME + " i ON o.\"item_id\" = 
i.\"item_id\" limit 2 offset 1")
+                .explainIs("PhoenixToEnumerableConverter\n" +
+                           "  PhoenixClientProject(order_id=[$0], NAME=[$4], 
PRICE=[$5], DISCOUNT2=[$6], QUANTITY=[$2])\n" +
+                           "    PhoenixLimit(offset=[1], fetch=[2])\n" +
+                           "      PhoenixClientJoin(condition=[=($1, $3)], 
joinType=[left])\n" +
+                           "        PhoenixClientSort(sort0=[$1], 
dir0=[ASC])\n" +
+                           "          PhoenixLimit(offset=[1], fetch=[2])\n" +
+                           "            PhoenixServerProject(order_id=[$0], 
item_id=[$2], QUANTITY=[$4])\n" +
+                           "              PhoenixTableScan(table=[[phoenix, 
Join, OrderTable]])\n" +
+                           "        PhoenixServerProject(item_id=[$0], 
NAME=[$1], PRICE=[$2], DISCOUNT2=[$4])\n" +
+                           "          PhoenixTableScan(table=[[phoenix, Join, 
ItemTable]], scanOrder=[FORWARD])\n")
                 .close();
     }
     
@@ -316,22 +316,22 @@ public class CalciteIT extends BaseCalciteIT {
                           {"00A423122312312", "a", "00D300000000XHP"}})
                 .close();
         
-        start(false, 1000f).sql("select t1.entity_id, t2.a_string, 
t3.organization_id from aTable t1 join aTable t2 on t1.entity_id = t2.entity_id 
and t1.organization_id = t2.organization_id join atable t3 on t1.entity_id = 
t3.entity_id and t1.organization_id = t3.organization_id")
+        start(false, 1000f).sql("select t1.entity_id, t2.a_string, 
t3.organization_id from aTable t1 join aTable t2 on t1.entity_id = t2.entity_id 
and t1.organization_id = t2.organization_id join atable t3 on t1.entity_id = 
t3.entity_id and t1.organization_id = t3.organization_id limit 8 offset 1")
                 .explainIs("PhoenixToEnumerableConverter\n" +
                            "  PhoenixClientProject(ENTITY_ID=[$1], 
A_STRING=[$6], ORGANIZATION_ID=[$2])\n" +
-                           "    PhoenixClientJoin(condition=[AND(=($1, $5), 
=($0, $4))], joinType=[inner])\n" +
-                           "      PhoenixClientJoin(condition=[AND(=($1, $3), 
=($0, $2))], joinType=[inner])\n" +
+                           "    PhoenixLimit(offset=[1], fetch=[8])\n" +
+                           "      PhoenixClientJoin(condition=[AND(=($1, $5), 
=($0, $4))], joinType=[inner])\n" +
+                           "        PhoenixClientJoin(condition=[AND(=($1, 
$3), =($0, $2))], joinType=[inner])\n" +
+                           "          PhoenixServerSort(sort0=[$1], 
sort1=[$0], dir0=[ASC], dir1=[ASC])\n" +
+                           "            
PhoenixServerProject(ORGANIZATION_ID=[$0], ENTITY_ID=[$1])\n" +
+                           "              PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n" +
+                           "          PhoenixServerSort(sort0=[$1], 
sort1=[$0], dir0=[ASC], dir1=[ASC])\n" +
+                           "            
PhoenixServerProject(ORGANIZATION_ID=[$0], ENTITY_ID=[$1])\n" +
+                           "              PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n" +
                            "        PhoenixServerSort(sort0=[$1], sort1=[$0], 
dir0=[ASC], dir1=[ASC])\n" +
-                           "          
PhoenixServerProject(ORGANIZATION_ID=[$0], ENTITY_ID=[$1])\n" +
-                           "            PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n" +
-                           "        PhoenixServerSort(sort0=[$1], sort1=[$0], 
dir0=[ASC], dir1=[ASC])\n" +
-                           "          
PhoenixServerProject(ORGANIZATION_ID=[$0], ENTITY_ID=[$1])\n" +
-                           "            PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n" +
-                           "      PhoenixServerSort(sort0=[$1], sort1=[$0], 
dir0=[ASC], dir1=[ASC])\n" +
-                           "        PhoenixServerProject(ORGANIZATION_ID=[$0], 
ENTITY_ID=[$1], A_STRING=[$2])\n" +
-                           "          PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n")
+                           "          
PhoenixServerProject(ORGANIZATION_ID=[$0], ENTITY_ID=[$1], A_STRING=[$2])\n" +
+                           "            PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n")
                 .resultIs(0, new Object[][] {
-                          {"00A123122312312", "a", "00D300000000XHP"},
                           {"00A223122312312", "a", "00D300000000XHP"},
                           {"00A323122312312", "a", "00D300000000XHP"},
                           {"00A423122312312", "a", "00D300000000XHP"},
@@ -385,7 +385,7 @@ public class CalciteIT extends BaseCalciteIT {
                         {"00A223122312312", 1L}, 
                         {"00A323122312312", 1L}, 
                         {"00A423122312312", 1L}, 
-                        {"00B523122312312", 1L}, 
+                        {"00B523122312312", 1L},
                         {"00B623122312312", 1L}, 
                         {"00B723122312312", 1L}, 
                         {"00B823122312312", 1L}, 
@@ -610,8 +610,8 @@ public class CalciteIT extends BaseCalciteIT {
                 .close();
     }
     
-    @Test public void testSortWithLimit() throws Exception {
-        start(false, 1000f).sql("select organization_id, entity_id, a_string 
from aTable order by a_string, entity_id limit 5")
+    @Test public void testSortWithLimitOffset() throws Exception {
+        start(false, 1000f).sql("select organization_id, entity_id, a_string 
from aTable order by a_string, entity_id limit 5 offset 0")
                 .explainIs("PhoenixToEnumerableConverter\n" +
                            "  PhoenixLimit(fetch=[5])\n" +
                            "    PhoenixServerSort(sort0=[$2], sort1=[$1], 
dir0=[ASC], dir1=[ASC])\n" +
@@ -625,46 +625,45 @@ public class CalciteIT extends BaseCalciteIT {
                           {"00D300000000XHP", "00B523122312312", "b"}})
                 .close();
         
-        start(false, 1000f).sql("select organization_id, entity_id, a_string 
from aTable order by organization_id, entity_id limit 5")
+        start(false, 1000f).sql("select organization_id, entity_id, a_string 
from aTable order by organization_id, entity_id limit 5 offset 3")
                 .explainIs("PhoenixToEnumerableConverter\n" +
-                           "  PhoenixLimit(fetch=[5])\n" +
+                           "  PhoenixLimit(offset=[3], fetch=[5])\n" +
                            "    PhoenixServerProject(ORGANIZATION_ID=[$0], 
ENTITY_ID=[$1], A_STRING=[$2])\n" +
                            "      PhoenixTableScan(table=[[phoenix, ATABLE]], 
scanOrder=[FORWARD])\n")
                 .resultIs(new Object[][] {
-                          {"00D300000000XHP", "00A123122312312", "a"}, 
-                          {"00D300000000XHP", "00A223122312312", "a"}, 
-                          {"00D300000000XHP", "00A323122312312", "a"}, 
                           {"00D300000000XHP", "00A423122312312", "a"}, 
-                          {"00D300000000XHP", "00B523122312312", "b"}})
+                          {"00D300000000XHP", "00B523122312312", "b"},
+                          {"00D300000000XHP", "00B623122312312", "b"},
+                          {"00D300000000XHP", "00B723122312312", "b"},
+                          {"00D300000000XHP", "00B823122312312", "b"}})
                 .close();
         
-        start(false, 1000f).sql("select organization_id, entity_id, a_string 
from aTable order by organization_id DESC limit 5")
+        start(false, 1000f).sql("select organization_id, entity_id, a_string 
from aTable order by organization_id DESC limit 5 offset 5")
                 .explainIs("PhoenixToEnumerableConverter\n" +
-                           "  PhoenixLimit(fetch=[5])\n" +
+                           "  PhoenixLimit(offset=[5], fetch=[5])\n" +
                            "    PhoenixServerProject(ORGANIZATION_ID=[$0], 
ENTITY_ID=[$1], A_STRING=[$2])\n" +
                            "      PhoenixTableScan(table=[[phoenix, ATABLE]], 
scanOrder=[REVERSE])\n")
                 .resultIs(new Object[][] {
-                          {"00D300000000XHP", "00C923122312312", "c"},
-                          {"00D300000000XHP", "00B823122312312", "b"}, 
-                          {"00D300000000XHP", "00B723122312312", "b"}, 
-                          {"00D300000000XHP", "00B623122312312", "b"}, 
-                          {"00D300000000XHP", "00B523122312312", "b"}})
+                          {"00D300000000XHP", "00A423122312312", "a"},
+                          {"00D300000000XHP", "00A323122312312", "a"},
+                          {"00D300000000XHP", "00A223122312312", "a"},
+                          {"00D300000000XHP", "00A123122312312", "a"}})
                 .close();
         
-        start(false, 1000f).sql("select organization_id, entity_id, a_string 
from aTable order by organization_id DESC, entity_id DESC limit 5")
+        start(false, 1000f).sql("select organization_id, entity_id, a_string 
from aTable order by organization_id DESC, entity_id DESC limit 5 offset 2")
                 .explainIs("PhoenixToEnumerableConverter\n" +
-                           "  PhoenixLimit(fetch=[5])\n" +
+                           "  PhoenixLimit(offset=[2], fetch=[5])\n" +
                            "    PhoenixServerProject(ORGANIZATION_ID=[$0], 
ENTITY_ID=[$1], A_STRING=[$2])\n" +
                            "      PhoenixTableScan(table=[[phoenix, ATABLE]], 
scanOrder=[REVERSE])\n")
                 .resultIs(new Object[][] {
-                          {"00D300000000XHP", "00C923122312312", "c"},
-                          {"00D300000000XHP", "00B823122312312", "b"}, 
                           {"00D300000000XHP", "00B723122312312", "b"}, 
                           {"00D300000000XHP", "00B623122312312", "b"}, 
-                          {"00D300000000XHP", "00B523122312312", "b"}})
+                          {"00D300000000XHP", "00B523122312312", "b"},
+                          {"00D300000000XHP", "00A423122312312", "a"},
+                          {"00D300000000XHP", "00A323122312312", "a"}})
                 .close();
 
-        start(false, 1000f).sql("select organization_id, entity_id, a_string 
from aTable order by organization_id ASC, entity_id DESC limit 5")
+        start(false, 1000f).sql("select organization_id, entity_id, a_string 
from aTable order by organization_id ASC, entity_id DESC limit 5 offset 0")
                 .explainIs("PhoenixToEnumerableConverter\n" +
                            "  PhoenixLimit(fetch=[5])\n" +
                            "    PhoenixServerSort(sort0=[$0], sort1=[$1], 
dir0=[ASC], dir1=[DESC])\n" +
@@ -678,21 +677,21 @@ public class CalciteIT extends BaseCalciteIT {
                           {"00D300000000XHP", "00B523122312312", "b"}})
                 .close();
         
-        start(false, 1000f).sql("select count(entity_id), a_string from atable 
group by a_string order by count(entity_id), a_string desc limit 2")
+        start(false, 1000f).sql("select count(entity_id), a_string from atable 
group by a_string order by count(entity_id), a_string desc limit 2 offset 1")
                 .explainIs("PhoenixToEnumerableConverter\n" +
                            "  PhoenixClientProject(EXPR$0=[$1], 
A_STRING=[$0])\n" +
-                           "    PhoenixLimit(fetch=[2])\n" +
+                           "    PhoenixLimit(offset=[1], fetch=[2])\n" +
                            "      PhoenixServerSort(sort0=[$1], sort1=[$0], 
dir0=[ASC], dir1=[DESC])\n" +
                            "        PhoenixServerAggregate(group=[{2}], 
EXPR$0=[COUNT()], isOrdered=[false])\n" +
                            "          PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n")
                 .resultIs(new Object[][] {
-                          {1L, "c"},
-                          {4L, "b"}})
+                          {4L, "b"},
+                          {4L, "a"}})
                 .close();
         
-        start(false, 1000f).sql("select s.name, count(\"item_id\") from " + 
JOIN_SUPPLIER_TABLE_FULL_NAME + " s join " + JOIN_ITEM_TABLE_FULL_NAME + " i on 
s.\"supplier_id\" = i.\"supplier_id\" group by s.name order by 
count(\"item_id\"), s.name desc limit 3")
+        start(false, 1000f).sql("select s.name, count(\"item_id\") from " + 
JOIN_SUPPLIER_TABLE_FULL_NAME + " s join " + JOIN_ITEM_TABLE_FULL_NAME + " i on 
s.\"supplier_id\" = i.\"supplier_id\" group by s.name order by 
count(\"item_id\"), s.name desc limit 3 offset 1")
                 .explainIs("PhoenixToEnumerableConverter\n" +
-                           "  PhoenixLimit(fetch=[3])\n" +
+                           "  PhoenixLimit(offset=[1], fetch=[3])\n" +
                            "    PhoenixServerSort(sort0=[$1], sort1=[$0], 
dir0=[ASC], dir1=[DESC])\n" +
                            "      PhoenixServerAggregate(group=[{1}], 
EXPR$1=[COUNT()], isOrdered=[false])\n" +
                            "        PhoenixServerJoin(condition=[=($0, $2)], 
joinType=[inner])\n" +
@@ -701,9 +700,9 @@ public class CalciteIT extends BaseCalciteIT {
                            "          
PhoenixServerProject(supplier_id=[$5])\n" +
                            "            PhoenixTableScan(table=[[phoenix, 
Join, ItemTable]])\n")
                 .resultIs(new Object[][] {
-                          {"S6", 1L},
                           {"S5", 1L},
-                          {"S2", 2L}})
+                          {"S2", 2L},
+                          {"S1", 2L}})
                 .close();
         
         start(false, 1000f).sql("SELECT item.\"item_id\", item.name, 
supp.\"supplier_id\", supp.name FROM " + JOIN_ITEM_TABLE_FULL_NAME + " item 
JOIN " + JOIN_SUPPLIER_TABLE_FULL_NAME + " supp ON item.\"supplier_id\" = 
supp.\"supplier_id\" order by item.name desc limit 3")
@@ -796,6 +795,134 @@ public class CalciteIT extends BaseCalciteIT {
                 .close();
     }
 
+    // PHOENIX CALCITE INTEGRATION : PHOENIX-2827
+    @Test public void testLimitOffset() throws Exception {
+        start(false, 1000f).sql(
+                "select organization_id, entity_id, a_string from aTable limit 
5 offset 3")
+                .explainIs("PhoenixToEnumerableConverter\n" +
+                        "  PhoenixLimit(offset=[3], fetch=[5])\n" +
+                        "    PhoenixServerProject(ORGANIZATION_ID=[$0], 
ENTITY_ID=[$1], A_STRING=[$2])\n" +
+                        "      PhoenixTableScan(table=[[phoenix, ATABLE]])\n")
+                .resultIs(new Object[][] {
+                        { "00D300000000XHP", "00A423122312312", "a" },
+                        { "00D300000000XHP", "00B523122312312", "b" },
+                        { "00D300000000XHP", "00B623122312312", "b" },
+                        { "00D300000000XHP", "00B723122312312", "b" },
+                        { "00D300000000XHP", "00B823122312312", "b" }, })
+                .close();
+
+        start(false, 1000f).sql(
+                "select organization_id, entity_id, a_string from aTable limit 
13 offset 12")
+                .explainIs("PhoenixToEnumerableConverter\n" +
+                        "  PhoenixLimit(offset=[12], fetch=[13])\n" +
+                        "    PhoenixServerProject(ORGANIZATION_ID=[$0], 
ENTITY_ID=[$1], A_STRING=[$2])\n" +
+                        "      PhoenixTableScan(table=[[phoenix, ATABLE]])\n")
+                .resultIs(new Object[][] {})
+                .close();
+
+        start(false, 1000f).sql("select count(entity_id), a_string from atable 
group by a_string limit 2 offset 0")
+                .explainIs("PhoenixToEnumerableConverter\n" +
+                        "  PhoenixClientProject(EXPR$0=[$1], A_STRING=[$0])\n" 
+
+                        "    PhoenixLimit(fetch=[2])\n" +
+                        "      PhoenixServerAggregate(group=[{2}], 
EXPR$0=[COUNT()], isOrdered=[false])\n" +
+                        "        PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n")
+                .resultIsSomeOf(2, new Object[][] {
+                        {4L, "a"},
+                        {4L, "b"},
+                        {1L, "c"}})
+                .close();
+
+        start(false, 1000f).sql("SELECT item.\"item_id\", item.name, 
supp.\"supplier_id\", supp.name FROM " + JOIN_ITEM_TABLE_FULL_NAME + " item 
JOIN " + JOIN_SUPPLIER_TABLE_FULL_NAME + " supp ON item.\"supplier_id\" = 
supp.\"supplier_id\" limit 3 offset 3")
+                .explainIs("PhoenixToEnumerableConverter\n" +
+                        "  PhoenixClientProject(item_id=[$0], NAME=[$1], 
supplier_id=[$3], NAME0=[$4])\n" +
+                        "    PhoenixLimit(offset=[3], fetch=[3])\n" +
+                        "      PhoenixServerJoin(condition=[=($2, $3)], 
joinType=[inner])\n" +
+                        "        PhoenixServerProject(item_id=[$0], NAME=[$1], 
supplier_id=[$5])\n" +
+                        "          PhoenixTableScan(table=[[phoenix, Join, 
ItemTable]])\n" +
+                        "        PhoenixServerProject(supplier_id=[$0], 
NAME=[$1])\n" +
+                        "          PhoenixTableScan(table=[[phoenix, Join, 
SupplierTable]])\n")
+                .resultIsSomeOf(3, new Object[][] {
+                        { "0000000001", "T1", "0000000001", "S1" },
+                        { "0000000002", "T2", "0000000001", "S1" },
+                        { "0000000003", "T3", "0000000002", "S2" },
+                        { "0000000004", "T4", "0000000002", "S2" },
+                        { "0000000005", "T5", "0000000005", "S5" },
+                        { "0000000006", "T6", "0000000006", "S6" } })
+                .close();
+
+        start(false, 1000f).sql("SELECT x from (values (1, 2), (2, 4), (3, 6)) 
as t(x, y) limit 2 offset 2")
+                .explainIs("PhoenixToEnumerableConverter\n" +
+                        "  PhoenixClientProject(X=[$0])\n" +
+                        "    PhoenixLimit(offset=[2], fetch=[2])\n" +
+                        "      PhoenixValues(tuples=[[{ 1, 2 }, { 2, 4 }, { 3, 
6 }]])\n")
+                .resultIs(new Object[][] {{3}})
+                .close();
+
+        start(false, 1000f).sql("SELECT x from (values (1, 2), (2, 4), (3, 6)) 
as t(x, y) limit 3 offset 4")
+                .explainIs("PhoenixToEnumerableConverter\n" +
+                        "  PhoenixClientProject(X=[$0])\n" +
+                        "    PhoenixLimit(offset=[4], fetch=[3])\n" +
+                        "      PhoenixValues(tuples=[[{ 1, 2 }, { 2, 4 }, { 3, 
6 }]])\n")
+                .resultIs(new Object[][] {})
+                .close();
+    }
+
+    @Test public void testOffset() throws Exception {
+        start(false, 1000f).sql(
+                "select organization_id, entity_id, a_string from aTable 
offset 3")
+                .explainIs("PhoenixToEnumerableConverter\n" +
+                        "  PhoenixLimit(offset=[3])\n" +
+                        "    PhoenixServerProject(ORGANIZATION_ID=[$0], 
ENTITY_ID=[$1], A_STRING=[$2])\n" +
+                        "      PhoenixTableScan(table=[[phoenix, ATABLE]])\n")
+                .resultIs(new Object[][] {
+                        { "00D300000000XHP", "00A423122312312", "a" },
+                        { "00D300000000XHP", "00B523122312312", "b" },
+                        { "00D300000000XHP", "00B623122312312", "b" },
+                        { "00D300000000XHP", "00B723122312312", "b" },
+                        { "00D300000000XHP", "00B823122312312", "b" },
+                        { "00D300000000XHP", "00C923122312312", "c" }})
+                .close();
+
+        start(false, 1000f).sql("select count(entity_id), a_string from atable 
group by a_string offset 1")
+                .explainIs("PhoenixToEnumerableConverter\n" +
+                        "  PhoenixClientProject(EXPR$0=[$1], A_STRING=[$0])\n" 
+
+                        "    PhoenixLimit(offset=[1])\n" +
+                        "      PhoenixServerAggregate(group=[{2}], 
EXPR$0=[COUNT()], isOrdered=[false])\n" +
+                        "        PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n")
+                .resultIsSomeOf(2, new Object[][] {
+                        {4L, "a"},
+                        {4L, "b"},
+                        {1L, "c"}})
+                .close();
+
+        start(false, 1000f).sql("SELECT item.\"item_id\", item.name, 
supp.\"supplier_id\", supp.name FROM " + JOIN_ITEM_TABLE_FULL_NAME + " item 
JOIN " + JOIN_SUPPLIER_TABLE_FULL_NAME + " supp ON item.\"supplier_id\" = 
supp.\"supplier_id\" offset 7")
+                .explainIs("PhoenixToEnumerableConverter\n" +
+                        "  PhoenixClientProject(item_id=[$0], NAME=[$1], 
supplier_id=[$3], NAME0=[$4])\n" +
+                        "    PhoenixLimit(offset=[7])\n" +
+                        "      PhoenixServerJoin(condition=[=($2, $3)], 
joinType=[inner])\n" +
+                        "        PhoenixServerProject(item_id=[$0], NAME=[$1], 
supplier_id=[$5])\n" +
+                        "          PhoenixTableScan(table=[[phoenix, Join, 
ItemTable]])\n" +
+                        "        PhoenixServerProject(supplier_id=[$0], 
NAME=[$1])\n" +
+                        "          PhoenixTableScan(table=[[phoenix, Join, 
SupplierTable]])\n")
+                .resultIs(new Object [][] {})
+                .close();
+
+        start(false, 1000f).sql("SELECT x from (values (1, 2), (2, 4), (3, 6)) 
as t(x, y) offset 0")
+                .explainIs("PhoenixToEnumerableConverter\n" +
+                        "  PhoenixClientProject(X=[$0])\n" +
+                        "    PhoenixValues(tuples=[[{ 1, 2 }, { 2, 4 }, { 3, 6 
}]])\n")
+                .resultIs(new Object[][] {{1},{2},{3}})
+                .close();
+
+        start(false, 1000f).sql("SELECT x from (values (1, 2), (2, 4), (3, 6)) 
as t(x, y) offset 3")
+                .explainIs("PhoenixToEnumerableConverter\n" +
+                        "  PhoenixClientProject(X=[$0])\n" +
+                        "    PhoenixLimit(offset=[3])\n" +
+                        "      PhoenixValues(tuples=[[{ 1, 2 }, { 2, 4 }, { 3, 
6 }]])\n")
+                .resultIs(new Object[][] {})
+                .close();
+    }
+
     @Ignore // CALCITE-1045
     @Test public void testScalarSubquery() throws Exception {
         start(false, 1000f).sql("select \"item_id\", name, (select 
max(quantity) sq \n"
@@ -874,22 +1001,20 @@ public class CalciteIT extends BaseCalciteIT {
                         {"00B823122312312"}})
                 .close();
         
-        start(false, 1000f).sql("select entity_id, a_string from atable where 
a_string = 'a' union all select entity_id, a_string from atable where a_string 
= 'c' order by entity_id desc limit 3")
+        start(false, 1000f).sql("select entity_id, a_string from atable where 
a_string = 'a' union all select entity_id, a_string from atable where a_string 
= 'c' order by entity_id desc limit 3 offset 1")
                 .explainIs("PhoenixToEnumerableConverter\n" +
-                           "  PhoenixLimit(fetch=[3])\n" +
+                           "  PhoenixLimit(offset=[1], fetch=[3])\n" +
                            "    PhoenixMergeSortUnion(all=[true])\n" +
-                           "      PhoenixLimit(fetch=[3])\n" +
-                           "        PhoenixServerSort(sort0=[$0], 
dir0=[DESC])\n" +
-                           "          PhoenixServerProject(ENTITY_ID=[$1], 
A_STRING=[$2])\n" +
-                           "            PhoenixTableScan(table=[[phoenix, 
ATABLE]], filter=[=($2, 'a')])\n" +
-                           "      PhoenixLimit(fetch=[3])\n" +
-                           "        PhoenixServerSort(sort0=[$0], 
dir0=[DESC])\n" +
-                           "          PhoenixServerProject(ENTITY_ID=[$1], 
A_STRING=[$2])\n" +
-                           "            PhoenixTableScan(table=[[phoenix, 
ATABLE]], filter=[=($2, 'c')])\n")
+                           "      PhoenixServerSort(sort0=[$0], 
dir0=[DESC])\n" +
+                           "        PhoenixServerProject(ENTITY_ID=[$1], 
A_STRING=[$2])\n" +
+                           "          PhoenixTableScan(table=[[phoenix, 
ATABLE]], filter=[=($2, 'a')])\n" +
+                           "      PhoenixServerSort(sort0=[$0], 
dir0=[DESC])\n" +
+                           "        PhoenixServerProject(ENTITY_ID=[$1], 
A_STRING=[$2])\n" +
+                           "          PhoenixTableScan(table=[[phoenix, 
ATABLE]], filter=[=($2, 'c')])\n")
                 .resultIs(new Object[][] {
-                        {"00C923122312312", "c"},
                         {"00A423122312312", "a"},
-                        {"00A323122312312", "a"}})
+                        {"00A323122312312", "a"},
+                        {"00A223122312312", "a"}})
                 .close();
         
         start(false, 1000f).sql("select entity_id, a_string from atable where 
a_string = 'a' union all select entity_id, a_string from atable where a_string 
= 'c' order by entity_id desc")

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixLimit.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixLimit.java 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixLimit.java
index 50b6f2b..8406929 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixLimit.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixLimit.java
@@ -67,7 +67,6 @@ public class PhoenixLimit extends SingleRel implements 
PhoenixQueryRel {
     public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery 
mq) {
         if (!getInput().getConvention().satisfies(PhoenixConvention.GENERIC))
             return planner.getCostFactory().makeInfiniteCost();
-        
         double rowCount = mq.getRowCount(this);
         return planner.getCostFactory()
                 .makeCost(rowCount, 0, 0)
@@ -76,20 +75,24 @@ public class PhoenixLimit extends SingleRel implements 
PhoenixQueryRel {
     
     @Override 
     public double estimateRowCount(RelMetadataQuery mq) {
-        double rows = super.estimateRowCount(mq);        
-        return Math.min(RexLiteral.intValue(fetch), rows);
+        double rows = super.estimateRowCount(mq);
+        int offset = this.offset == null ? 0 : 
RexLiteral.intValue(this.offset);
+        int fetch = this.fetch == null ? Integer.MAX_VALUE : 
RexLiteral.intValue(this.fetch);
+        return Math.max(0, Math.min(fetch, rows - offset));
     }
 
     @Override
     public QueryPlan implement(PhoenixRelImplementor implementor) {
         QueryPlan plan = implementor.visitInput(0, (PhoenixQueryRel) 
getInput());
-        int fetchValue = RexLiteral.intValue(fetch);
-        if (plan.getLimit() == null) {
-            return plan.limit(fetchValue);
+        Integer fetch = this.fetch == null ? null : 
RexLiteral.intValue(this.fetch);
+        Integer offset = this.offset == null ? null : 
RexLiteral.intValue(this.offset);
+
+        if (plan.getLimit() == null && plan.getOffset() == null) {
+            return plan.limit(fetch, offset);
         }
         
         return new ClientScanPlan(plan.getContext(), plan.getStatement(), 
                 implementor.getTableMapping().getTableRef(), 
RowProjector.EMPTY_PROJECTOR, 
-                fetchValue, null, null, OrderBy.EMPTY_ORDER_BY, plan);
+                fetch, offset, null, OrderBy.EMPTY_ORDER_BY, plan);
     }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixToEnumerableConverter.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixToEnumerableConverter.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixToEnumerableConverter.java
index 5bc2c0d..5aef483 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixToEnumerableConverter.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixToEnumerableConverter.java
@@ -121,8 +121,8 @@ public class PhoenixToEnumerableConverter extends 
ConverterImpl implements Enume
                 return delegate.iterator(scanGrouper);
             }
             @Override
-            public QueryPlan limit(Integer limit) {
-                return delegate.limit(limit);
+            public QueryPlan limit(Integer limit, Integer offset) {
+                return delegate.limit(limit, offset);
             }
             @Override
             public ResultIterator iterator(ParallelScanGrouper scanGrouper, 
Scan scan) throws SQLException {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/calcite/rules/PhoenixConverterRules.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rules/PhoenixConverterRules.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rules/PhoenixConverterRules.java
index 4347aa5..ca71ab1 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rules/PhoenixConverterRules.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rules/PhoenixConverterRules.java
@@ -232,8 +232,7 @@ public class PhoenixConverterRules {
         private static Predicate<LogicalSort> HAS_FETCH = new 
Predicate<LogicalSort>() {
             @Override
             public boolean apply(LogicalSort input) {
-                return input.offset == null 
-                        && input.fetch != null;
+                return input.fetch != null || input.offset != null;
             }
         };
         

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java 
b/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java
index a8c725a..bd23a36 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/compile/ListJarsQueryPlan.java
@@ -243,7 +243,7 @@ public class ListJarsQueryPlan implements QueryPlan {
     }
 
     @Override
-    public QueryPlan limit(Integer limit) {
+    public QueryPlan limit(Integer limit, Integer offset) {
         return this;
     }
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryPlan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryPlan.java 
b/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryPlan.java
index 60cd1a7..aaf79d9 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/QueryPlan.java
@@ -88,12 +88,13 @@ public interface QueryPlan extends StatementPlan {
     public boolean useRoundRobinIterator() throws SQLException;
     
     /**
-     * Create a copy of the current QueryPlan with a new limit value.
+     * Create a copy of the current QueryPlan with a new limit and offset 
value.
      * 
-     * @param  limit the new limit value.
-     * @return the new QueryPlan or the current QueryPlan if the limit 
-     *         value is unchanged or if the limit value does not make a
+     * @param  limit the new limit value
+     * @param  offset is the new offset value
+     * @return the new QueryPlan or the current QueryPlan if the limit & offset
+     *         value is unchanged or if the limit & offset values do not make a
      *         difference in the QueryPlan's behavior.
      */
-    public QueryPlan limit(Integer limit);
+    public QueryPlan limit(Integer limit, Integer offset);
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/compile/TraceQueryPlan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/compile/TraceQueryPlan.java 
b/phoenix-core/src/main/java/org/apache/phoenix/compile/TraceQueryPlan.java
index 833df2c..e79f634 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/TraceQueryPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/TraceQueryPlan.java
@@ -261,7 +261,7 @@ public class TraceQueryPlan implements QueryPlan {
     }
 
     @Override
-    public QueryPlan limit(Integer limit) {
+    public QueryPlan limit(Integer limit, Integer offset) {
         return this;
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/execute/AggregatePlan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/AggregatePlan.java 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/AggregatePlan.java
index cd83c4d..dc86376 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/AggregatePlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/AggregatePlan.java
@@ -21,6 +21,7 @@ package org.apache.phoenix.execute;
 import java.sql.SQLException;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 
 import org.apache.hadoop.hbase.client.Scan;
 import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
@@ -268,11 +269,15 @@ public class AggregatePlan extends BaseQueryPlan {
     }
 
     @Override
-    public QueryPlan limit(Integer limit) {
-        if (limit == this.limit || (limit != null && limit.equals(this.limit)))
+    public QueryPlan limit(Integer limit, Integer offset) {
+        if (Objects.equals(limit, this.limit) &&
+                Objects.equals(offset, this.offset)) {
             return this;
-        
-        return new AggregatePlan(this.context, this.statement, this.tableRef, 
this.tableRefs.iterator().next(), this.projection,
-            limit, this.offset, this.orderBy, this.parallelIteratorFactory, 
this.groupBy, this.having, this.dynamicFilter);
+        }
+
+        return new AggregatePlan(this.context, this.statement, this.tableRef,
+                this.tableRefs.iterator().next(), this.projection,
+                limit, offset, this.orderBy, this.parallelIteratorFactory, 
this.groupBy,
+                        this.having, this.dynamicFilter);
     }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientAggregatePlan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientAggregatePlan.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientAggregatePlan.java
index af93d92..f4afc19 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientAggregatePlan.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientAggregatePlan.java
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.sql.SQLException;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 
 import org.apache.hadoop.hbase.Cell;
 import org.apache.hadoop.hbase.KeyValue;
@@ -247,12 +248,14 @@ public class ClientAggregatePlan extends 
ClientProcessingPlan {
     }
 
     @Override
-    public QueryPlan limit(Integer limit) {
-        if (limit == this.limit || (limit != null && limit.equals(this.limit)))
+    public QueryPlan limit(Integer limit, Integer offset) {
+        if (Objects.equals(limit, this.limit) &&
+                Objects.equals(offset, this.offset)) {
             return this;
-        
-        return new ClientAggregatePlan(this.context, this.statement, 
this.table, 
-                this.projector, limit, this.offset, this.where, this.orderBy, 
this.groupBy, this.having, 
+        }
+
+        return new ClientAggregatePlan(this.context, this.statement, 
this.table,
+                this.projector, limit, offset, this.where, this.orderBy, 
this.groupBy, this.having,
                 this.delegate, this.serverAggregators, this.clientAggregators);
     }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientScanPlan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientScanPlan.java 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientScanPlan.java
index 26a0f28..8aec425 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientScanPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/ClientScanPlan.java
@@ -19,6 +19,7 @@ package org.apache.phoenix.execute;
 
 import java.sql.SQLException;
 import java.util.List;
+import java.util.Objects;
 
 import org.apache.hadoop.hbase.client.Scan;
 import org.apache.phoenix.compile.ExplainPlan;
@@ -106,12 +107,14 @@ public class ClientScanPlan extends ClientProcessingPlan {
     }
 
     @Override
-    public QueryPlan limit(Integer limit) {
-        if (limit == this.limit || (limit != null && limit.equals(this.limit)))
+    public QueryPlan limit(Integer limit, Integer offset) {
+        if (Objects.equals(limit, this.limit) &&
+                Objects.equals(offset, this.offset)) {
             return this;
-        
+        }
+
         return new ClientScanPlan(this.context, this.statement, this.table,
-                this.projector, limit, this.offset, this.where, this.orderBy, 
this.delegate);
-    }
+                this.projector, limit, offset, this.where, this.orderBy, 
this.delegate);
 
-}
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/execute/CorrelatePlan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/CorrelatePlan.java 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/CorrelatePlan.java
index be0c7c0..adeb0db 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/CorrelatePlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/CorrelatePlan.java
@@ -204,12 +204,16 @@ public class CorrelatePlan extends DelegateQueryPlan {
     }
 
     @Override
-    public QueryPlan limit(Integer limit) {
-        if (limit == null)
+    public Integer getOffset() {
+        return null;
+    }
+
+    @Override
+    public QueryPlan limit(Integer limit, Integer offset) {
+        if (limit == null && offset == null)
             return this;
         
         return new ClientScanPlan(this.getContext(), this.getStatement(), 
this.getTableRef(),
-                this.getProjector(), limit, this.getOffset(), null, 
OrderBy.EMPTY_ORDER_BY, this);
+                this.getProjector(), limit, offset, null, 
OrderBy.EMPTY_ORDER_BY, this);
     }
-
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/execute/DegenerateQueryPlan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/DegenerateQueryPlan.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/DegenerateQueryPlan.java
index 31ad0e9..3537bd1 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/DegenerateQueryPlan.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/DegenerateQueryPlan.java
@@ -63,7 +63,7 @@ public class DegenerateQueryPlan extends BaseQueryPlan {
     }
 
     @Override
-    public QueryPlan limit(Integer limit) {
+    public QueryPlan limit(Integer limit, Integer offset) {
         return this;
     }
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/execute/DelegateQueryPlan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/DelegateQueryPlan.java 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/DelegateQueryPlan.java
index 3f120fd..4300245 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/DelegateQueryPlan.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/DelegateQueryPlan.java
@@ -122,12 +122,12 @@ public abstract class DelegateQueryPlan implements 
QueryPlan {
         return delegate.useRoundRobinIterator();
     }
 
-       @Override
-       public Operation getOperation() {
-               return delegate.getOperation();
-       }
-       
-       @Override
+    @Override
+    public Operation getOperation() {
+        return delegate.getOperation();
+    }
+
+    @Override
     public Integer getOffset() {
         return delegate.getOffset();
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/execute/HashJoinPlan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/HashJoinPlan.java 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/HashJoinPlan.java
index 191b77c..9d08cef 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/HashJoinPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/HashJoinPlan.java
@@ -449,8 +449,8 @@ public class HashJoinPlan extends DelegateQueryPlan {
     }
 
     @Override
-    public QueryPlan limit(Integer limit) {
-        QueryPlan delegate = this.delegate.limit(limit);
+    public QueryPlan limit(Integer limit, Integer offset) {
+        QueryPlan delegate = this.delegate.limit(limit, offset);
         if (delegate == this.delegate)
             return this;
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java
index e5bf7fa..4955844 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/LiteralResultIterationPlan.java
@@ -21,6 +21,7 @@ import java.sql.SQLException;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 
 import org.apache.hadoop.hbase.KeyValue;
 import org.apache.hadoop.hbase.client.Scan;
@@ -113,12 +114,13 @@ public class LiteralResultIterationPlan extends 
BaseQueryPlan {
     }
 
     @Override
-    public QueryPlan limit(Integer limit) {
-        if (limit == this.limit || (limit != null && limit.equals(this.limit)))
+    public QueryPlan limit(Integer limit, Integer offset) {
+        if (Objects.equals(limit, this.limit) &&
+                Objects.equals(offset, this.offset)) {
             return this;
-        
-        return new LiteralResultIterationPlan(this.tuples, this.context, 
this.statement, this.tableRef, 
-                this.projection, limit, this.offset, this.orderBy, 
this.parallelIteratorFactory);
-    }
+        }
 
-}
+        return new LiteralResultIterationPlan(this.tuples, this.context, 
this.statement, this.tableRef,
+                this.projection, limit, offset, this.orderBy, 
this.parallelIteratorFactory);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/execute/ScanPlan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/ScanPlan.java 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/ScanPlan.java
index d3d000b..6de9287 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/ScanPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/ScanPlan.java
@@ -24,6 +24,7 @@ import static 
org.apache.phoenix.util.ScanUtil.isRoundRobinPossible;
 import java.sql.SQLException;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.client.Scan;
@@ -269,16 +270,19 @@ public class ScanPlan extends BaseQueryPlan {
     }
 
     @Override
-    public QueryPlan limit(Integer limit) {
-        if (limit == this.limit || (limit != null && limit.equals(this.limit)))
+    public QueryPlan limit(Integer limit, Integer offset) {
+        if (Objects.equals(limit, this.limit) &&
+                Objects.equals(offset, this.offset)) {
             return this;
-        
+        }
+
         try {
-            return new ScanPlan(this.context, this.statement, this.tableRef, 
this.tableRefs.iterator().next(), this.projection, 
-                    limit, this.offset, this.orderBy, 
this.parallelIteratorFactory, this.allowPageFilter, this.dynamicFilter);
+            return new ScanPlan(this.context, this.statement, this.tableRef,
+                    this.tableRefs.iterator().next(), this.projection,
+                    limit, offset, this.orderBy, this.parallelIteratorFactory,
+                    this.allowPageFilter, this.dynamicFilter);
         } catch (SQLException e) {
             throw new RuntimeException(e);
         }
     }
-
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/execute/SortMergeJoinPlan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/SortMergeJoinPlan.java 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/SortMergeJoinPlan.java
index 0d09274..bde1ed5 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/SortMergeJoinPlan.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/SortMergeJoinPlan.java
@@ -667,16 +667,18 @@ public class SortMergeJoinPlan implements QueryPlan {
         return false;
     }
 
+
     @Override
-    public QueryPlan limit(Integer limit) {
-        if (limit == null)
+    public QueryPlan limit(Integer limit, Integer offset) {
+        if (limit == null && offset == null)
             return this;
-        
+
         return new ClientScanPlan(this.getContext(), this.getStatement(), 
this.getTableRef(),
-                this.getProjector(), limit, this.getOffset(), null, 
OrderBy.EMPTY_ORDER_BY, this);
+                this.getProjector(), limit, offset, null, 
OrderBy.EMPTY_ORDER_BY, this);
     }
 
     public Set<TableRef> getSourceRefs() {
         return tableRefs;
     }
 }
+

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/execute/TupleProjectionPlan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/TupleProjectionPlan.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/TupleProjectionPlan.java
index 3952502..9f26b46 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/TupleProjectionPlan.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/TupleProjectionPlan.java
@@ -88,8 +88,8 @@ public class TupleProjectionPlan extends DelegateQueryPlan {
     }
 
     @Override
-    public QueryPlan limit(Integer limit) {
-        QueryPlan delegate = this.delegate.limit(limit);
+    public QueryPlan limit(Integer limit, Integer offset) {
+        QueryPlan delegate = this.delegate.limit(limit, offset);
         if (delegate == this.delegate)
             return this;
         

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/execute/UnionPlan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/UnionPlan.java 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/UnionPlan.java
index 1467824..61d0144 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/UnionPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/UnionPlan.java
@@ -21,6 +21,7 @@ import java.sql.ParameterMetaData;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
 import org.apache.hadoop.hbase.client.Scan;
@@ -203,12 +204,14 @@ public class UnionPlan implements QueryPlan {
     }
 
     @Override
-    public QueryPlan limit(Integer limit) {
-        if (limit == this.limit || (limit != null && limit.equals(this.limit)))
+    public QueryPlan limit(Integer limit, Integer offset) {
+        if (Objects.equals(limit, this.limit) &&
+                Objects.equals(offset, this.offset)) {
             return this;
-        
+        }
+
         return new UnionPlan(this.parentContext, this.statement, 
this.tableRef, this.projector,
-            limit, this.offset, this.orderBy, this.groupBy, this.plans, 
this.paramMetaData);
+                limit, offset, this.orderBy, this.groupBy, this.plans, 
this.paramMetaData);
     }
 
        @Override

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/execute/UnnestArrayPlan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/execute/UnnestArrayPlan.java 
b/phoenix-core/src/main/java/org/apache/phoenix/execute/UnnestArrayPlan.java
index 181f168..00cecf1 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/UnnestArrayPlan.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/UnnestArrayPlan.java
@@ -184,11 +184,11 @@ public class UnnestArrayPlan extends DelegateQueryPlan {
     }
 
     @Override
-    public QueryPlan limit(Integer limit) {
-        if (limit == null)
+    public QueryPlan limit(Integer limit, Integer offset) {
+        if (limit == null && offset == null)
             return this;
-        
+
         return new ClientScanPlan(this.getContext(), this.getStatement(), 
this.getTableRef(),
-                this.getProjector(), limit, this.getOffset(), null, 
OrderBy.EMPTY_ORDER_BY, this);
+                this.getProjector(), limit, offset, null, 
OrderBy.EMPTY_ORDER_BY, this);
     }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java 
b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
index a5b5779..2bbe595 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixStatement.java
@@ -591,7 +591,7 @@ public class PhoenixStatement implements Statement, 
SQLCloseable {
                 }
 
                 @Override
-                public QueryPlan limit(Integer limit) {
+                public QueryPlan limit(Integer limit, Integer offset) {
                     return this;
                 }
                 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4f01c91e/phoenix-core/src/test/java/org/apache/phoenix/query/ParallelIteratorsSplitTest.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/test/java/org/apache/phoenix/query/ParallelIteratorsSplitTest.java
 
b/phoenix-core/src/test/java/org/apache/phoenix/query/ParallelIteratorsSplitTest.java
index ecf31ab..0eb054e 100644
--- 
a/phoenix-core/src/test/java/org/apache/phoenix/query/ParallelIteratorsSplitTest.java
+++ 
b/phoenix-core/src/test/java/org/apache/phoenix/query/ParallelIteratorsSplitTest.java
@@ -473,7 +473,7 @@ public class ParallelIteratorsSplitTest extends 
BaseConnectionlessQueryTest {
             }
 
             @Override
-            public QueryPlan limit(Integer limit) {
+            public QueryPlan limit(Integer limit, Integer offset) {
                 return this;
             }
             

Reply via email to