Add server/client conventions for PhoenixRel and use ConvertRules to apply 
Phoenix server/client operators


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

Branch: refs/heads/calcite
Commit: c1396ecfff867d059cb0eb424188ffbfdbfd54f0
Parents: cedc1c5
Author: maryannxue <wei....@intel.com>
Authored: Wed Jun 10 16:29:15 2015 -0400
Committer: maryannxue <wei....@intel.com>
Committed: Wed Jun 10 16:29:15 2015 -0400

----------------------------------------------------------------------
 .../org/apache/phoenix/calcite/CalciteTest.java | 268 ++++++++-----
 .../calcite/jdbc/PhoenixPrepareImpl.java        |  18 +-
 .../calcite/metadata/PhoenixRelMdCollation.java |   4 -
 .../calcite/rel/PhoenixAbstractAggregate.java   |   1 -
 .../calcite/rel/PhoenixAbstractJoin.java        |   3 +-
 .../calcite/rel/PhoenixAbstractProject.java     |   1 -
 .../calcite/rel/PhoenixAbstractSort.java        |   1 -
 .../calcite/rel/PhoenixClientAggregate.java     |   2 +-
 .../phoenix/calcite/rel/PhoenixClientJoin.java  |  42 +-
 .../calcite/rel/PhoenixClientProject.java       |   2 +-
 .../phoenix/calcite/rel/PhoenixClientSort.java  |   2 +-
 .../calcite/rel/PhoenixCompactClientSort.java   |   2 +-
 .../phoenix/calcite/rel/PhoenixFilter.java      |   3 +-
 .../apache/phoenix/calcite/rel/PhoenixJoin.java |  49 ---
 .../phoenix/calcite/rel/PhoenixLimit.java       |   3 +-
 .../calcite/rel/PhoenixPostJoinProject.java     |  70 ++++
 .../apache/phoenix/calcite/rel/PhoenixRel.java  |   6 +-
 .../calcite/rel/PhoenixServerAggregate.java     |   2 +-
 .../phoenix/calcite/rel/PhoenixServerJoin.java  |  10 +-
 .../calcite/rel/PhoenixServerProject.java       |   9 +-
 .../phoenix/calcite/rel/PhoenixServerSort.java  |   2 +-
 .../phoenix/calcite/rel/PhoenixTableScan.java   |   2 +-
 .../calcite/rel/PhoenixToClientConverter.java   |  45 +++
 .../phoenix/calcite/rel/PhoenixUnion.java       |   3 +-
 .../phoenix/calcite/rel/PhoenixValues.java      |   3 +-
 .../calcite/rules/PhoenixClientJoinRule.java    |  40 --
 .../calcite/rules/PhoenixConverterRules.java    | 388 ++++++++++++++++---
 .../rules/PhoenixFilterScanMergeRule.java       |   6 +-
 .../rules/PhoenixServerAggregateRule.java       |  39 --
 .../calcite/rules/PhoenixServerJoinRule.java    |  54 ---
 .../calcite/rules/PhoenixServerProjectRule.java |  34 --
 .../calcite/rules/PhoenixServerSortRule.java    |  38 --
 32 files changed, 653 insertions(+), 499 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteTest.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteTest.java 
b/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteTest.java
index 89006ed..dca783d 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteTest.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteTest.java
@@ -238,7 +238,8 @@ public class CalciteTest extends BaseClientManagedTimeIT {
     @Test public void testTableScan() throws Exception {
         start().sql("select * from aTable where a_string = 'a'")
                 .explainIs("PhoenixToEnumerableConverter\n" +
-                           "  PhoenixTableScan(table=[[phoenix, ATABLE]], 
filter=[=($2, 'a')])\n")
+                           "  PhoenixToClientConverter\n" +
+                           "    PhoenixTableScan(table=[[phoenix, ATABLE]], 
filter=[=($2, 'a')])\n")
                 .resultIs(new Object[][] {
                           {"00D300000000XHP", "00A123122312312", "a"}, 
                           {"00D300000000XHP", "00A223122312312", "a"}, 
@@ -250,8 +251,9 @@ public class CalciteTest extends BaseClientManagedTimeIT {
     @Test public void testProject() throws Exception {
         start().sql("select entity_id, a_string, organization_id from aTable 
where a_string = 'a'")
                 .explainIs("PhoenixToEnumerableConverter\n" +
-                           "  PhoenixServerProject(ENTITY_ID=[$1], 
A_STRING=[$2], ORGANIZATION_ID=[$0])\n" +
-                           "    PhoenixTableScan(table=[[phoenix, ATABLE]], 
filter=[=($2, 'a')])\n")
+                           "  PhoenixToClientConverter\n" +
+                           "    PhoenixServerProject(ENTITY_ID=[$1], 
A_STRING=[$2], ORGANIZATION_ID=[$0])\n" +
+                           "      PhoenixTableScan(table=[[phoenix, ATABLE]], 
filter=[=($2, 'a')])\n")
                 .resultIs(new Object[][] {
                           {"00A123122312312", "a", "00D300000000XHP"}, 
                           {"00A223122312312", "a", "00D300000000XHP"}, 
@@ -263,12 +265,14 @@ public class CalciteTest extends BaseClientManagedTimeIT {
     @Test public void testJoin() throws Exception {
         start().sql("select t1.entity_id, t2.a_string, t1.organization_id from 
aTable t1 join aTable t2 on t1.entity_id = t2.entity_id and t1.organization_id 
= t2.organization_id where t1.a_string = 'a'") 
                 .explainIs("PhoenixToEnumerableConverter\n" +
-                           "  PhoenixServerProject(ENTITY_ID=[$4], 
A_STRING=[$2], ORGANIZATION_ID=[$3])\n" +
-                           "    PhoenixServerJoin(condition=[AND(=($1, $4), 
=($0, $3))], joinType=[inner])\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]], filter=[=($2, 'a')])\n")
+                           "  PhoenixToClientConverter\n" +
+                           "    PhoenixPostJoinProject(ENTITY_ID=[$4], 
A_STRING=[$2], ORGANIZATION_ID=[$3])\n" +
+                           "      PhoenixServerJoin(condition=[AND(=($4, $1), 
=($3, $0))], joinType=[inner])\n" +
+                           "        PhoenixServerProject(ORGANIZATION_ID=[$0], 
ENTITY_ID=[$1], A_STRING=[$2])\n" +
+                           "          PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n" +
+                           "        PhoenixToClientConverter\n" +
+                           "          
PhoenixServerProject(ORGANIZATION_ID=[$0], ENTITY_ID=[$1], A_STRING=[$2])\n" +
+                           "            PhoenixTableScan(table=[[phoenix, 
ATABLE]], filter=[=($2, 'a')])\n")
                 .resultIs(new Object[][] {
                           {"00A123122312312", "a", "00D300000000XHP"}, 
                           {"00A223122312312", "a", "00D300000000XHP"}, 
@@ -278,12 +282,14 @@ public class CalciteTest extends BaseClientManagedTimeIT {
         
         start().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\"")
                 .explainIs("PhoenixToEnumerableConverter\n" +
-                           "  PhoenixServerProject(item_id=[$0], NAME=[$1], 
supplier_id=[$3], NAME0=[$4])\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")
+                           "  PhoenixToClientConverter\n" +
+                           "    PhoenixPostJoinProject(item_id=[$0], 
NAME=[$1], supplier_id=[$3], NAME0=[$4])\n" +
+                           "      PhoenixServerJoin(condition=[=($2, $3)], 
joinType=[inner])\n" +
+                           "        PhoenixServerProject(item_id=[$0], 
NAME=[$1], supplier_id=[$5])\n" +
+                           "          PhoenixTableScan(table=[[phoenix, Join, 
ItemTable]])\n" +
+                           "        PhoenixToClientConverter\n" +
+                           "          PhoenixServerProject(supplier_id=[$0], 
NAME=[$1])\n" +
+                           "            PhoenixTableScan(table=[[phoenix, 
Join, SupplierTable]])\n")
                 .resultIs(new Object[][] {
                           {"0000000001", "T1", "0000000001", "S1"}, 
                           {"0000000002", "T2", "0000000001", "S1"}, 
@@ -295,11 +301,13 @@ public class CalciteTest extends BaseClientManagedTimeIT {
         
         start().sql("SELECT * FROM " + JOIN_ITEM_TABLE_FULL_NAME + " item JOIN 
" + JOIN_SUPPLIER_TABLE_FULL_NAME + " supp ON item.\"supplier_id\" = 
supp.\"supplier_id\" AND supp.name = 'S5'")
                 .explainIs("PhoenixToEnumerableConverter\n" +
-                           "  PhoenixServerProject(item_id=[$0], NAME=[$1], 
PRICE=[$2], DISCOUNT1=[$3], DISCOUNT2=[$4], supplier_id=[$5], DESCRIPTION=[$6], 
supplier_id0=[$7], NAME0=[$8], PHONE=[$9], ADDRESS=[$10], LOC_ID=[$11])\n" +
-                           "    PhoenixServerJoin(condition=[=($5, $7)], 
joinType=[inner])\n" +
-                           "      PhoenixTableScan(table=[[phoenix, Join, 
ItemTable]])\n" +
-                           "      PhoenixServerProject(supplier_id=[$0], 
NAME=[$1], PHONE=[$2], ADDRESS=[$3], LOC_ID=[$4], $f5=[CAST($1):VARCHAR(2) 
CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\" NOT NULL])\n" 
+
-                           "        PhoenixTableScan(table=[[phoenix, Join, 
SupplierTable]], filter=[=(CAST($1):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" 
COLLATE \"ISO-8859-1$en_US$primary\" NOT NULL, 'S5')])\n")
+                           "  PhoenixToClientConverter\n" +
+                           "    PhoenixPostJoinProject(item_id=[$0], 
NAME=[$1], PRICE=[$2], DISCOUNT1=[$3], DISCOUNT2=[$4], supplier_id=[$5], 
DESCRIPTION=[$6], supplier_id0=[$7], NAME0=[$8], PHONE=[$9], ADDRESS=[$10], 
LOC_ID=[$11])\n" +
+                           "      PhoenixServerJoin(condition=[=($5, $7)], 
joinType=[inner])\n" +
+                           "        PhoenixTableScan(table=[[phoenix, Join, 
ItemTable]])\n" +
+                           "        PhoenixToClientConverter\n" +
+                           "          PhoenixServerProject(supplier_id=[$0], 
NAME=[$1], PHONE=[$2], ADDRESS=[$3], LOC_ID=[$4], $f5=[CAST($1):VARCHAR(2) 
CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\" NOT NULL])\n" 
+
+                           "            PhoenixTableScan(table=[[phoenix, 
Join, SupplierTable]], filter=[=(CAST($1):VARCHAR(2) CHARACTER SET 
\"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\" NOT NULL, 'S5')])\n")
                 .resultIs(new Object[][] {
                           {"0000000005", "T5", 500, 8, 15, "0000000005", "Item 
T5", "0000000005", "S5", "888-888-5555", "505 YYY Street", "10005"}})
                 .close();
@@ -314,8 +322,9 @@ public class CalciteTest extends BaseClientManagedTimeIT {
                            "        PhoenixServerSort(sort0=[$2], 
dir0=[ASC])\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")
+                           "        PhoenixToClientConverter\n" +
+                           "          PhoenixServerProject(supplier_id=[$0], 
NAME=[$1])\n" +
+                           "            PhoenixTableScan(table=[[phoenix, 
Join, SupplierTable]])\n")
                 .resultIs(new Object[][] {
                         {null, null, "0000000003", "S3"},
                         {null, null, "0000000004", "S4"},
@@ -326,19 +335,44 @@ public class CalciteTest extends BaseClientManagedTimeIT {
                         {"0000000005", "T5", "0000000005", "S5"},
                         {"0000000006", "T6", "0000000006", "S6"},
                         {"invalid001", "INVALID-1", null, null}})
-                .close();        
+                .close();
+        
+        start().sql("select t1.entity_id, t2.a_string, t1.organization_id from 
aTable t1 join aTable t2 on t1.organization_id = t2.organization_id and 
t1.entity_id = t2.entity_id") 
+                .explainIs("PhoenixToEnumerableConverter\n" +
+                           "  PhoenixClientProject(ENTITY_ID=[$1], 
A_STRING=[$4], ORGANIZATION_ID=[$0])\n" +
+                           "    PhoenixClientJoin(condition=[AND(=($0, $2), 
=($1, $3))], joinType=[inner])\n" +
+                           "      PhoenixToClientConverter\n" +
+                           "        PhoenixServerProject(ORGANIZATION_ID=[$0], 
ENTITY_ID=[$1])\n" +
+                           "          PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n" +
+                           "      PhoenixToClientConverter\n" +
+                           "        PhoenixServerProject(ORGANIZATION_ID=[$0], 
ENTITY_ID=[$1], A_STRING=[$2])\n" +
+                           "          PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n")
+                .resultIs(new Object[][] {
+                          {"00A123122312312", "a", "00D300000000XHP"}, 
+                          {"00A223122312312", "a", "00D300000000XHP"}, 
+                          {"00A323122312312", "a", "00D300000000XHP"}, 
+                          {"00A423122312312", "a", "00D300000000XHP"}, 
+                          {"00B523122312312", "b", "00D300000000XHP"}, 
+                          {"00B623122312312", "b", "00D300000000XHP"}, 
+                          {"00B723122312312", "b", "00D300000000XHP"}, 
+                          {"00B823122312312", "b", "00D300000000XHP"}, 
+                          {"00C923122312312", "c", "00D300000000XHP"}})
+                .close();
     }
     
     @Test public void testMultiJoin() throws Exception {
         start().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 where t1.a_string = 'a'") 
                 .explainIs("PhoenixToEnumerableConverter\n" +
-                           "  PhoenixServerProject(ENTITY_ID=[$19], 
A_STRING=[$2], ORGANIZATION_ID=[$36])\n" +
-                           "    PhoenixServerJoin(condition=[AND(=($1, $19), 
=($0, $18))], joinType=[inner])\n" +
-                           "      PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n" +
-                           "      PhoenixServerProject(ORGANIZATION_ID=[$18], 
ENTITY_ID=[$19], A_STRING=[$20], B_STRING=[$21], A_INTEGER=[$22], A_DATE=[$23], 
A_TIME=[$24], A_TIMESTAMP=[$25], X_DECIMAL=[$26], X_LONG=[$27], 
X_INTEGER=[$28], Y_INTEGER=[$29], A_BYTE=[$30], A_SHORT=[$31], A_FLOAT=[$32], 
A_DOUBLE=[$33], A_UNSIGNED_FLOAT=[$34], A_UNSIGNED_DOUBLE=[$35], 
ORGANIZATION_ID0=[$0], ENTITY_ID0=[$1], A_STRING0=[$2], B_STRING0=[$3], 
A_INTEGER0=[$4], A_DATE0=[$5], A_TIME0=[$6], A_TIMESTAMP0=[$7], 
X_DECIMAL0=[$8], X_LONG0=[$9], X_INTEGER0=[$10], Y_INTEGER0=[$11], 
A_BYTE0=[$12], A_SHORT0=[$13], A_FLOAT0=[$14], A_DOUBLE0=[$15], 
A_UNSIGNED_FLOAT0=[$16], A_UNSIGNED_DOUBLE0=[$17])\n" +
-                           "        PhoenixServerJoin(condition=[AND(=($1, 
$19), =($0, $18))], joinType=[inner])\n" +
-                           "          PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n" +
-                           "          PhoenixTableScan(table=[[phoenix, 
ATABLE]], filter=[=($2, 'a')])\n")
+                           "  PhoenixToClientConverter\n" +
+                           "    PhoenixPostJoinProject(ENTITY_ID=[$19], 
A_STRING=[$38], ORGANIZATION_ID=[$0])\n" +
+                           "      PhoenixServerJoin(condition=[AND(=($19, $1), 
=($18, $0))], joinType=[inner])\n" +
+                           "        PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n" +
+                           "        PhoenixToClientConverter\n" +
+                           "          
PhoenixPostJoinProject(ORGANIZATION_ID=[$18], ENTITY_ID=[$19], A_STRING=[$20], 
B_STRING=[$21], A_INTEGER=[$22], A_DATE=[$23], A_TIME=[$24], A_TIMESTAMP=[$25], 
X_DECIMAL=[$26], X_LONG=[$27], X_INTEGER=[$28], Y_INTEGER=[$29], A_BYTE=[$30], 
A_SHORT=[$31], A_FLOAT=[$32], A_DOUBLE=[$33], A_UNSIGNED_FLOAT=[$34], 
A_UNSIGNED_DOUBLE=[$35], ORGANIZATION_ID0=[$0], ENTITY_ID0=[$1], 
A_STRING0=[$2], B_STRING0=[$3], A_INTEGER0=[$4], A_DATE0=[$5], A_TIME0=[$6], 
A_TIMESTAMP0=[$7], X_DECIMAL0=[$8], X_LONG0=[$9], X_INTEGER0=[$10], 
Y_INTEGER0=[$11], A_BYTE0=[$12], A_SHORT0=[$13], A_FLOAT0=[$14], 
A_DOUBLE0=[$15], A_UNSIGNED_FLOAT0=[$16], A_UNSIGNED_DOUBLE0=[$17])\n" +
+                           "            
PhoenixServerJoin(condition=[AND(=($19, $1), =($18, $0))], joinType=[inner])\n" 
+
+                           "              PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n" +
+                           "              PhoenixToClientConverter\n" +
+                           "                PhoenixTableScan(table=[[phoenix, 
ATABLE]], filter=[=($2, 'a')])\n")
                 .resultIs(new Object[][] {
                           {"00A123122312312", "a", "00D300000000XHP"}, 
                           {"00A223122312312", "a", "00D300000000XHP"}, 
@@ -348,12 +382,15 @@ public class CalciteTest extends BaseClientManagedTimeIT {
         
         start().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") 
                 .explainIs("PhoenixToEnumerableConverter\n" +
-                           "  PhoenixServerProject(ENTITY_ID=[$19], 
A_STRING=[$38], ORGANIZATION_ID=[$0])\n" +
-                           "    PhoenixServerJoin(condition=[AND(=($19, $1), 
=($18, $0))], joinType=[inner])\n" +
-                           "      PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n" +
-                           "      PhoenixServerJoin(condition=[AND(=($1, $19), 
=($0, $18))], joinType=[inner])\n" +
+                           "  PhoenixToClientConverter\n" +
+                           "    PhoenixPostJoinProject(ENTITY_ID=[$19], 
A_STRING=[$2], ORGANIZATION_ID=[$36])\n" +
+                           "      PhoenixServerJoin(condition=[AND(=($19, $1), 
=($18, $0))], joinType=[inner])\n" +
                            "        PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n" +
-                           "        PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n")
+                           "        PhoenixToClientConverter\n" +
+                           "          PhoenixServerJoin(condition=[AND(=($1, 
$19), =($0, $18))], joinType=[inner])\n" +
+                           "            PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n" +
+                           "            PhoenixToClientConverter\n" +
+                           "              PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n")
                 .resultIs(new Object[][] {
                           {"00A123122312312", "a", "00D300000000XHP"}, 
                           {"00A223122312312", "a", "00D300000000XHP"}, 
@@ -394,12 +431,13 @@ public class CalciteTest extends BaseClientManagedTimeIT {
         start().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")
                 .explainIs("PhoenixToEnumerableConverter\n" +
                            "  PhoenixServerAggregate(group=[{0}], 
EXPR$1=[COUNT()])\n" +
-                           "    PhoenixServerProject(NAME=[$2])\n" +
+                           "    PhoenixPostJoinProject(NAME=[$2])\n" +
                            "      PhoenixServerJoin(condition=[=($1, $0)], 
joinType=[inner])\n" +
                            "        PhoenixServerProject(supplier_id=[$5])\n" +
                            "          PhoenixTableScan(table=[[phoenix, Join, 
ItemTable]])\n" +
-                           "        PhoenixServerProject(supplier_id=[$0], 
NAME=[$1])\n" +
-                           "          PhoenixTableScan(table=[[phoenix, Join, 
SupplierTable]])\n")
+                           "        PhoenixToClientConverter\n" +
+                           "          PhoenixServerProject(supplier_id=[$0], 
NAME=[$1])\n" +
+                           "            PhoenixTableScan(table=[[phoenix, 
Join, SupplierTable]])\n")
                 .resultIs(new Object[][] {
                           {"S1", 2L},
                           {"S2", 2L},
@@ -441,8 +479,9 @@ public class CalciteTest extends BaseClientManagedTimeIT {
         
         start().sql("select organization_id, entity_id, a_string from aTable 
order by organization_id, entity_id")
                 .explainIs("PhoenixToEnumerableConverter\n" +
-                           "  PhoenixServerProject(ORGANIZATION_ID=[$0], 
ENTITY_ID=[$1], A_STRING=[$2])\n" +
-                           "    PhoenixTableScan(table=[[phoenix, ATABLE]])\n")
+                           "  PhoenixToClientConverter\n" +
+                           "    PhoenixServerProject(ORGANIZATION_ID=[$0], 
ENTITY_ID=[$1], A_STRING=[$2])\n" +
+                           "      PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n")
                 .resultIs(new Object[][] {
                           {"00D300000000XHP", "00A123122312312", "a"}, 
                           {"00D300000000XHP", "00A223122312312", "a"}, 
@@ -472,12 +511,13 @@ public class CalciteTest extends BaseClientManagedTimeIT {
                 .explainIs("PhoenixToEnumerableConverter\n" +
                            "  PhoenixCompactClientSort(sort0=[$1], sort1=[$0], 
dir0=[ASC], dir1=[DESC])\n" +
                            "    PhoenixServerAggregate(group=[{0}], 
EXPR$1=[COUNT()])\n" +
-                           "      PhoenixServerProject(NAME=[$2])\n" +
+                           "      PhoenixPostJoinProject(NAME=[$2])\n" +
                            "        PhoenixServerJoin(condition=[=($1, $0)], 
joinType=[inner])\n" +
                            "          
PhoenixServerProject(supplier_id=[$5])\n" +
                            "            PhoenixTableScan(table=[[phoenix, 
Join, ItemTable]])\n" +
-                           "          PhoenixServerProject(supplier_id=[$0], 
NAME=[$1])\n" +
-                           "            PhoenixTableScan(table=[[phoenix, 
Join, SupplierTable]])\n")
+                           "          PhoenixToClientConverter\n" +
+                           "            PhoenixServerProject(supplier_id=[$0], 
NAME=[$1])\n" +
+                           "              PhoenixTableScan(table=[[phoenix, 
Join, SupplierTable]])\n")
                 .resultIs(new Object[][] {
                           {"S6", 1L},
                           {"S5", 1L},
@@ -488,12 +528,13 @@ public class CalciteTest extends BaseClientManagedTimeIT {
         start().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")
                 .explainIs("PhoenixToEnumerableConverter\n" +
                            "  PhoenixServerSort(sort0=[$1], dir0=[DESC])\n" +
-                           "    PhoenixServerProject(item_id=[$0], NAME=[$1], 
supplier_id=[$3], NAME0=[$4])\n" +
+                           "    PhoenixPostJoinProject(item_id=[$0], 
NAME=[$1], supplier_id=[$3], NAME0=[$4])\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")
+                           "        PhoenixToClientConverter\n" +
+                           "          PhoenixServerProject(supplier_id=[$0], 
NAME=[$1])\n" +
+                           "            PhoenixTableScan(table=[[phoenix, 
Join, SupplierTable]])\n")
                 .resultIs(new Object[][] {
                           {"0000000006", "T6", "0000000006", "S6"}, 
                           {"0000000005", "T5", "0000000005", "S5"}, 
@@ -522,8 +563,9 @@ public class CalciteTest extends BaseClientManagedTimeIT {
         start().sql("select organization_id, entity_id, a_string from aTable 
order by organization_id, entity_id limit 5")
                 .explainIs("PhoenixToEnumerableConverter\n" +
                            "  PhoenixLimit(fetch=[5])\n" +
-                           "    PhoenixServerProject(ORGANIZATION_ID=[$0], 
ENTITY_ID=[$1], A_STRING=[$2])\n" +
-                           "      PhoenixTableScan(table=[[phoenix, ATABLE]], 
statelessFetch=[5])\n")
+                           "    PhoenixToClientConverter\n" +
+                           "      PhoenixServerProject(ORGANIZATION_ID=[$0], 
ENTITY_ID=[$1], A_STRING=[$2])\n" +
+                           "        PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n")
                 .resultIs(new Object[][] {
                           {"00D300000000XHP", "00A123122312312", "a"}, 
                           {"00D300000000XHP", "00A223122312312", "a"}, 
@@ -550,12 +592,13 @@ public class CalciteTest extends BaseClientManagedTimeIT {
                            "  PhoenixLimit(fetch=[3])\n" +
                            "    PhoenixCompactClientSort(sort0=[$1], 
sort1=[$0], dir0=[ASC], dir1=[DESC])\n" +
                            "      PhoenixServerAggregate(group=[{0}], 
EXPR$1=[COUNT()])\n" +
-                           "        PhoenixServerProject(NAME=[$2])\n" +
+                           "        PhoenixPostJoinProject(NAME=[$2])\n" +
                            "          PhoenixServerJoin(condition=[=($1, $0)], 
joinType=[inner])\n" +
                            "            
PhoenixServerProject(supplier_id=[$5])\n" +
                            "              PhoenixTableScan(table=[[phoenix, 
Join, ItemTable]])\n" +
-                           "            PhoenixServerProject(supplier_id=[$0], 
NAME=[$1])\n" +
-                           "              PhoenixTableScan(table=[[phoenix, 
Join, SupplierTable]])\n")
+                           "            PhoenixToClientConverter\n" +
+                           "              
PhoenixServerProject(supplier_id=[$0], NAME=[$1])\n" +
+                           "                PhoenixTableScan(table=[[phoenix, 
Join, SupplierTable]])\n")
                 .resultIs(new Object[][] {
                           {"S6", 1L},
                           {"S5", 1L},
@@ -566,12 +609,13 @@ public class CalciteTest extends BaseClientManagedTimeIT {
                 .explainIs("PhoenixToEnumerableConverter\n" +
                            "  PhoenixLimit(fetch=[3])\n" +
                            "    PhoenixServerSort(sort0=[$1], dir0=[DESC])\n" +
-                           "      PhoenixServerProject(item_id=[$0], 
NAME=[$1], supplier_id=[$3], NAME0=[$4])\n" +
+                           "      PhoenixPostJoinProject(item_id=[$0], 
NAME=[$1], supplier_id=[$3], NAME0=[$4])\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")
+                           "          PhoenixToClientConverter\n" +
+                           "            PhoenixServerProject(supplier_id=[$0], 
NAME=[$1])\n" +
+                           "              PhoenixTableScan(table=[[phoenix, 
Join, SupplierTable]])\n")
                 .resultIs(new Object[][] {
                           {"0000000006", "T6", "0000000006", "S6"}, 
                           {"0000000005", "T5", "0000000005", "S5"}, 
@@ -583,8 +627,9 @@ public class CalciteTest extends BaseClientManagedTimeIT {
         start().sql("select organization_id, entity_id, a_string from aTable 
limit 5")
                 .explainIs("PhoenixToEnumerableConverter\n" +
                            "  PhoenixLimit(fetch=[5])\n" +
-                           "    PhoenixServerProject(ORGANIZATION_ID=[$0], 
ENTITY_ID=[$1], A_STRING=[$2])\n" +
-                           "      PhoenixTableScan(table=[[phoenix, ATABLE]], 
statelessFetch=[5])\n")
+                           "    PhoenixToClientConverter\n" +
+                           "      PhoenixServerProject(ORGANIZATION_ID=[$0], 
ENTITY_ID=[$1], A_STRING=[$2])\n" +
+                           "        PhoenixTableScan(table=[[phoenix, 
ATABLE]])\n")
                 .resultIs(new Object[][] {
                           {"00D300000000XHP", "00A123122312312", "a"}, 
                           {"00D300000000XHP", "00A223122312312", "a"}, 
@@ -609,12 +654,13 @@ public class CalciteTest extends BaseClientManagedTimeIT {
                 .explainIs("PhoenixToEnumerableConverter\n" +
                            "  PhoenixLimit(fetch=[3])\n" +
                            "    PhoenixServerAggregate(group=[{0}], 
EXPR$1=[COUNT()])\n" +
-                           "      PhoenixServerProject(NAME=[$2])\n" +
+                           "      PhoenixPostJoinProject(NAME=[$2])\n" +
                            "        PhoenixServerJoin(condition=[=($1, $0)], 
joinType=[inner])\n" +
                            "          
PhoenixServerProject(supplier_id=[$5])\n" +
                            "            PhoenixTableScan(table=[[phoenix, 
Join, ItemTable]])\n" +
-                           "          PhoenixServerProject(supplier_id=[$0], 
NAME=[$1])\n" +
-                           "            PhoenixTableScan(table=[[phoenix, 
Join, SupplierTable]])\n")
+                           "          PhoenixToClientConverter\n" +
+                           "            PhoenixServerProject(supplier_id=[$0], 
NAME=[$1])\n" +
+                           "              PhoenixTableScan(table=[[phoenix, 
Join, SupplierTable]])\n")
                 .resultIs(new Object[][] {
                           {"S1", 2L},
                           {"S2", 2L},
@@ -624,12 +670,14 @@ public class CalciteTest extends BaseClientManagedTimeIT {
         start().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")
                 .explainIs("PhoenixToEnumerableConverter\n" +
                            "  PhoenixLimit(fetch=[3])\n" +
-                           "    PhoenixServerProject(item_id=[$0], NAME=[$1], 
supplier_id=[$3], NAME0=[$4])\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")
+                           "    PhoenixToClientConverter\n" +
+                           "      PhoenixPostJoinProject(item_id=[$0], 
NAME=[$1], supplier_id=[$3], NAME0=[$4])\n" +
+                           "        PhoenixServerJoin(condition=[=($2, $3)], 
joinType=[inner])\n" +
+                           "          PhoenixServerProject(item_id=[$0], 
NAME=[$1], supplier_id=[$5])\n" +
+                           "            PhoenixTableScan(table=[[phoenix, 
Join, ItemTable]])\n" +
+                           "          PhoenixToClientConverter\n" +
+                           "            PhoenixServerProject(supplier_id=[$0], 
NAME=[$1])\n" +
+                           "              PhoenixTableScan(table=[[phoenix, 
Join, SupplierTable]])\n")
                 .resultIs(new Object[][] {
                           {"0000000001", "T1", "0000000001", "S1"}, 
                           {"0000000002", "T2", "0000000001", "S1"}, 
@@ -640,16 +688,17 @@ public class CalciteTest extends BaseClientManagedTimeIT {
     @Test public void testSubquery() {
         start().sql("SELECT \"order_id\", quantity FROM " + 
JOIN_ORDER_TABLE_FULL_NAME + " o WHERE quantity = (SELECT max(quantity) FROM " 
+ JOIN_ORDER_TABLE_FULL_NAME + " q WHERE o.\"item_id\" = q.\"item_id\")")
                .explainIs("PhoenixToEnumerableConverter\n" +
-                          "  PhoenixServerProject(order_id=[$0], 
QUANTITY=[$4])\n" +
-                          "    PhoenixServerJoin(condition=[AND(=($2, $7), 
=($4, $8))], joinType=[inner])\n" +
-                          "      PhoenixTableScan(table=[[phoenix, Join, 
OrderTable]])\n" +
-                          "      PhoenixServerAggregate(group=[{0}], 
EXPR$0=[MAX($1)])\n" +
-                          "        PhoenixServerProject(item_id0=[$7], 
QUANTITY=[$4])\n" +
-                          "          PhoenixServerJoin(condition=[=($7, $2)], 
joinType=[inner])\n" +
-                          "            PhoenixTableScan(table=[[phoenix, Join, 
OrderTable]])\n" +
-                          "            PhoenixServerAggregate(group=[{0}])\n" +
-                          "              PhoenixServerProject(item_id=[$2])\n" 
+
-                          "                PhoenixTableScan(table=[[phoenix, 
Join, OrderTable]])\n")
+                          "  PhoenixToClientConverter\n" +
+                          "    PhoenixPostJoinProject(order_id=[$0], 
QUANTITY=[$4])\n" +
+                          "      PhoenixServerJoin(condition=[AND(=($2, $7), 
=($4, $8))], joinType=[inner])\n" +
+                          "        PhoenixTableScan(table=[[phoenix, Join, 
OrderTable]])\n" +
+                          "        PhoenixServerAggregate(group=[{0}], 
EXPR$0=[MAX($1)])\n" +
+                          "          PhoenixPostJoinProject(item_id0=[$7], 
QUANTITY=[$4])\n" +
+                          "            PhoenixServerJoin(condition=[=($7, 
$2)], joinType=[inner])\n" +
+                          "              PhoenixTableScan(table=[[phoenix, 
Join, OrderTable]])\n" +
+                          "              
PhoenixServerAggregate(group=[{0}])\n" +
+                          "                
PhoenixServerProject(item_id=[$2])\n" +
+                          "                  PhoenixTableScan(table=[[phoenix, 
Join, OrderTable]])\n")
                .resultIs(new Object[][]{
                          {"000000000000001", 1000},
                          {"000000000000003", 3000},
@@ -663,16 +712,17 @@ public class CalciteTest extends BaseClientManagedTimeIT {
             + "from " + JOIN_ORDER_TABLE_FULL_NAME + " o where o.\"item_id\" = 
i.\"item_id\")\n"
             + "from " + JOIN_ITEM_TABLE_FULL_NAME + " i")
             .explainIs("PhoenixToEnumerableConverter\n" +
-                       "  PhoenixServerProject(item_id=[$0], NAME=[$1], 
EXPR$2=[$8])\n" +
-                       "    PhoenixServerJoin(condition=[=($0, $7)], 
joinType=[left], isSingleValueRhs=[true])\n" +
-                       "      PhoenixTableScan(table=[[phoenix, Join, 
ItemTable]])\n" +
-                       "      PhoenixServerAggregate(group=[{0}], 
SQ=[MAX($1)])\n" +
-                       "        PhoenixServerProject(item_id0=[$7], 
QUANTITY=[$4])\n" +
-                       "          PhoenixServerJoin(condition=[=($2, $7)], 
joinType=[inner])\n" +
-                       "            PhoenixTableScan(table=[[phoenix, Join, 
OrderTable]])\n" +
-                       "            PhoenixServerAggregate(group=[{0}])\n" +
-                       "              PhoenixServerProject(item_id=[$0])\n" +
-                       "                PhoenixTableScan(table=[[phoenix, 
Join, ItemTable]])\n")
+                       "  PhoenixToClientConverter\n" +
+                       "    PhoenixPostJoinProject(item_id=[$0], NAME=[$1], 
EXPR$2=[$8])\n" +
+                       "      PhoenixServerJoin(condition=[=($0, $7)], 
joinType=[left], isSingleValueRhs=[true])\n" +
+                       "        PhoenixTableScan(table=[[phoenix, Join, 
ItemTable]])\n" +
+                       "        PhoenixServerAggregate(group=[{0}], 
SQ=[MAX($1)])\n" +
+                       "          PhoenixPostJoinProject(item_id0=[$7], 
QUANTITY=[$4])\n" +
+                       "            PhoenixServerJoin(condition=[=($2, $7)], 
joinType=[inner])\n" +
+                       "              PhoenixTableScan(table=[[phoenix, Join, 
OrderTable]])\n" +
+                       "              PhoenixServerAggregate(group=[{0}])\n" +
+                       "                PhoenixServerProject(item_id=[$0])\n" +
+                       "                  PhoenixTableScan(table=[[phoenix, 
Join, ItemTable]])\n")
             .resultIs(new Object[][] {
                     new Object[] {"0000000001", "T1", 1000}, 
                     new Object[] {"0000000002", "T2", 3000}, 
@@ -681,27 +731,29 @@ public class CalciteTest extends BaseClientManagedTimeIT {
                     new Object[] {"0000000005", "T5", null}, 
                     new Object[] {"0000000006", "T6", 4000}, 
                     new Object[] {"invalid001", "INVALID-1", null}})
-            .close();;
-            start().sql("select \"item_id\", name, (select quantity sq \n"
+            .close();
+        
+        start().sql("select \"item_id\", name, (select quantity sq \n"
                     + "from " + JOIN_ORDER_TABLE_FULL_NAME + " o where 
o.\"item_id\" = i.\"item_id\")\n"
                     + "from " + JOIN_ITEM_TABLE_FULL_NAME + " i where 
\"item_id\" < '0000000006'")
-                    .explainIs("PhoenixToEnumerableConverter\n" +
-                               "  PhoenixServerProject(item_id=[$0], 
NAME=[$1], EXPR$2=[$8])\n" +
-                               "    PhoenixServerJoin(condition=[=($0, $7)], 
joinType=[left], isSingleValueRhs=[true])\n" +
-                               "      PhoenixTableScan(table=[[phoenix, Join, 
ItemTable]], filter=[<($0, '0000000006')])\n" +
-                               "      PhoenixServerProject(item_id0=[$7], 
SQ=[$4])\n" +
-                               "        PhoenixServerJoin(condition=[=($2, 
$7)], joinType=[inner])\n" +
-                               "          PhoenixTableScan(table=[[phoenix, 
Join, OrderTable]])\n" +
-                               "          
PhoenixServerAggregate(group=[{0}])\n" +
-                               "            
PhoenixServerProject(item_id=[$0])\n" +
-                               "              
PhoenixTableScan(table=[[phoenix, Join, ItemTable]], filter=[<($0, 
'0000000006')])\n")
-                    .resultIs(new Object[][] {
-                            new Object[] {"0000000001", "T1", 1000}, 
-                            new Object[] {"0000000002", "T2", 3000}, 
-                            new Object[] {"0000000003", "T3", 5000}, 
-                            new Object[] {"0000000004", "T4", null}, 
-                            new Object[] {"0000000005", "T5", null}})
-                    .close();;
+               .explainIs("PhoenixToEnumerableConverter\n" +
+                          "  PhoenixToClientConverter\n" +
+                          "    PhoenixPostJoinProject(item_id=[$0], NAME=[$1], 
EXPR$2=[$8])\n" +
+                          "      PhoenixServerJoin(condition=[=($0, $7)], 
joinType=[left], isSingleValueRhs=[true])\n" +
+                          "        PhoenixTableScan(table=[[phoenix, Join, 
ItemTable]], filter=[<($0, '0000000006')])\n" +
+                          "        PhoenixPostJoinProject(item_id0=[$7], 
SQ=[$4])\n" +
+                          "          PhoenixServerJoin(condition=[=($2, $7)], 
joinType=[inner])\n" +
+                          "            PhoenixTableScan(table=[[phoenix, Join, 
OrderTable]])\n" +
+                          "            PhoenixServerAggregate(group=[{0}])\n" +
+                          "              PhoenixServerProject(item_id=[$0])\n" 
+
+                          "                PhoenixTableScan(table=[[phoenix, 
Join, ItemTable]], filter=[<($0, '0000000006')])\n")
+               .resultIs(new Object[][] {
+                         new Object[] {"0000000001", "T1", 1000}, 
+                         new Object[] {"0000000002", "T2", 3000}, 
+                         new Object[] {"0000000003", "T3", 5000}, 
+                         new Object[] {"0000000004", "T4", null}, 
+                         new Object[] {"0000000005", "T5", null}})
+               .close();;
     }
     
     @Test public void testConnectJoinHsqldb() {
@@ -717,7 +769,8 @@ public class CalciteTest extends BaseClientManagedTimeIT {
             .explainIs("EnumerableCalc(expr#0..8=[{inputs}], THE_YEAR=[$t6], 
Q=[$t4], EXPR$2=[$t8])\n" +
                        "  EnumerableJoin(condition=[=($6, $7)], 
joinType=[left])\n" +
                        "    PhoenixToEnumerableConverter\n" +
-                       "      PhoenixTableScan(table=[[phoenix, Join, 
OrderTable]])\n" +
+                       "      PhoenixToClientConverter\n" +
+                       "        PhoenixTableScan(table=[[phoenix, Join, 
OrderTable]])\n" +
                        "    EnumerableAggregate(group=[{0}], 
agg#0=[SINGLE_VALUE($1)])\n" +
                        "      EnumerableAggregate(group=[{0}], 
CNT=[COUNT()])\n" +
                        "        EnumerableCalc(expr#0..10=[{inputs}], 
expr#11=[0], expr#12=[CAST($t5):INTEGER], expr#13=[=($t12, $t0)], 
THE_YEAR=[$t0], $f0=[$t11], $condition=[$t13])\n" +
@@ -745,8 +798,9 @@ public class CalciteTest extends BaseClientManagedTimeIT {
             }
         };
         start.sql("select * from aTable")
-            .explainIs("PhoenixToEnumerableConverter\n"
-                + "  PhoenixTableScan(table=[[HR, ATABLE]])\n")
+            .explainIs("PhoenixToEnumerableConverter\n" +
+                       "  PhoenixToClientConverter\n" +
+                       "    PhoenixTableScan(table=[[HR, ATABLE]])\n")
             // .resultIs("Xx")
             .close();
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/jdbc/PhoenixPrepareImpl.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/jdbc/PhoenixPrepareImpl.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/jdbc/PhoenixPrepareImpl.java
index e4c0821..20e1943 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/jdbc/PhoenixPrepareImpl.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/jdbc/PhoenixPrepareImpl.java
@@ -6,15 +6,11 @@ import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelOptRule;
 import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.phoenix.calcite.rules.PhoenixAddScanLimitRule;
-import org.apache.phoenix.calcite.rules.PhoenixClientJoinRule;
 import org.apache.phoenix.calcite.rules.PhoenixCompactClientSortRule;
 import org.apache.phoenix.calcite.rules.PhoenixConverterRules;
 import org.apache.phoenix.calcite.rules.PhoenixFilterScanMergeRule;
+import org.apache.phoenix.calcite.rules.PhoenixInnerSortRemoveRule;
 import 
org.apache.phoenix.calcite.rules.PhoenixJoinSingleValueAggregateMergeRule;
-import org.apache.phoenix.calcite.rules.PhoenixServerAggregateRule;
-import org.apache.phoenix.calcite.rules.PhoenixServerJoinRule;
-import org.apache.phoenix.calcite.rules.PhoenixServerProjectRule;
-import org.apache.phoenix.calcite.rules.PhoenixServerSortRule;
 
 public class PhoenixPrepareImpl extends CalcitePrepareImpl {
 
@@ -35,19 +31,9 @@ public class PhoenixPrepareImpl extends CalcitePrepareImpl {
         planner.addRule(PhoenixFilterScanMergeRule.INSTANCE);
         planner.addRule(PhoenixAddScanLimitRule.LIMIT_SCAN);
         planner.addRule(PhoenixAddScanLimitRule.LIMIT_SERVERPROJECT_SCAN);
-        planner.addRule(PhoenixServerProjectRule.PROJECT_SCAN);
-        planner.addRule(PhoenixServerProjectRule.PROJECT_SERVERJOIN);
-        planner.addRule(PhoenixServerJoinRule.JOIN_SCAN);
-        planner.addRule(PhoenixServerJoinRule.JOIN_SERVERPROJECT_SCAN);
-        planner.addRule(PhoenixServerAggregateRule.AGGREGATE_SCAN);
-        planner.addRule(PhoenixServerAggregateRule.AGGREGATE_SERVERJOIN);
-        planner.addRule(PhoenixServerAggregateRule.AGGREGATE_SERVERPROJECT);
-        planner.addRule(PhoenixServerSortRule.SORT_SCAN);
-        planner.addRule(PhoenixServerSortRule.SORT_SERVERJOIN);
-        planner.addRule(PhoenixServerSortRule.SORT_SERVERPROJECT);
         planner.addRule(PhoenixCompactClientSortRule.SORT_SERVERAGGREGATE);
-        planner.addRule(PhoenixClientJoinRule.INSTANCE);
         planner.addRule(PhoenixJoinSingleValueAggregateMergeRule.INSTANCE);
+        planner.addRule(PhoenixInnerSortRemoveRule.INSTANCE);
 
         return planner;
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/metadata/PhoenixRelMdCollation.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/metadata/PhoenixRelMdCollation.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/metadata/PhoenixRelMdCollation.java
index e3d46b7..53c273b 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/metadata/PhoenixRelMdCollation.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/metadata/PhoenixRelMdCollation.java
@@ -50,8 +50,6 @@ public class PhoenixRelMdCollation {
 
         final ImmutableList<RelCollation> leftCollations =
                 RelMetadataQuery.collations(left);
-        assert RelCollations.contains(leftCollations, leftKeys)
-        : "cannot merge join: left input is not sorted on left keys";
         for (RelCollation collation : leftCollations) {
             if (!collation.getFieldCollations().isEmpty()) {
                 builder.add(collation);
@@ -60,8 +58,6 @@ public class PhoenixRelMdCollation {
         
         final ImmutableList<RelCollation> rightCollations =
                 RelMetadataQuery.collations(right);
-        assert RelCollations.contains(rightCollations, rightKeys)
-        : "cannot merge join: right input is not sorted on right keys";
         final int leftFieldCount = left.getRowType().getFieldCount();
         for (RelCollation collation : rightCollations) {
             if (!collation.getFieldCollations().isEmpty()) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractAggregate.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractAggregate.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractAggregate.java
index 7d36494..b807011 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractAggregate.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractAggregate.java
@@ -55,7 +55,6 @@ abstract public class PhoenixAbstractAggregate extends 
Aggregate implements Phoe
     
     protected PhoenixAbstractAggregate(RelOptCluster cluster, RelTraitSet 
traits, RelNode child, boolean indicator, ImmutableBitSet groupSet, 
List<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) {
         super(cluster, traits, child, indicator, groupSet, groupSets, 
aggCalls);
-        assert getConvention() == PhoenixRel.CONVENTION;
 
         for (AggregateCall aggCall : aggCalls) {
             if (aggCall.isDistinct()) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractJoin.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractJoin.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractJoin.java
index 01f3536..829c401 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractJoin.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractJoin.java
@@ -27,10 +27,9 @@ abstract public class PhoenixAbstractJoin extends Join 
implements PhoenixRel {
     public final boolean isSingleValueRhs;
 
     protected PhoenixAbstractJoin(RelOptCluster cluster, RelTraitSet traits, 
RelNode left, RelNode right, RexNode condition, JoinRelType joinType, 
Set<String> variablesStopped, boolean isSingleValueRhs) {
-        super( cluster, traits, left, right, condition, joinType, 
variablesStopped);
+        super(cluster, traits, left, right, condition, joinType, 
variablesStopped);
         this.joinInfo = JoinInfo.of(left, right, condition);
         this.isSingleValueRhs = isSingleValueRhs;
-        assert getConvention() == PhoenixRel.CONVENTION;
     }
     
     abstract public PhoenixAbstractJoin copy(RelTraitSet traits, RexNode 
condition, RelNode left,

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractProject.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractProject.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractProject.java
index 893dcd1..3c16563 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractProject.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractProject.java
@@ -26,7 +26,6 @@ import com.google.common.collect.Lists;
 abstract public class PhoenixAbstractProject extends Project implements 
PhoenixRel {
     protected PhoenixAbstractProject(RelOptCluster cluster, RelTraitSet 
traits, RelNode input, List<? extends RexNode> projects, RelDataType rowType) {
         super(cluster, traits, input, projects, rowType);
-        assert getConvention() == PhoenixRel.CONVENTION;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractSort.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractSort.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractSort.java
index 5a43269..c2ac235 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractSort.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixAbstractSort.java
@@ -29,7 +29,6 @@ abstract public class PhoenixAbstractSort extends Sort 
implements PhoenixRel {
     
     protected PhoenixAbstractSort(RelOptCluster cluster, RelTraitSet traits, 
RelNode child, RelCollation collation) {
         super(cluster, traits, child, collation, null, null);
-        assert getConvention() == PhoenixRel.CONVENTION;
         assert !getCollation().getFieldCollations().isEmpty();
     }
     

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientAggregate.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientAggregate.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientAggregate.java
index 360c9b8..db3de2c 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientAggregate.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientAggregate.java
@@ -29,7 +29,7 @@ public class PhoenixClientAggregate extends 
PhoenixAbstractAggregate {
             ImmutableBitSet groupSet, List<ImmutableBitSet> groupSets, 
             List<AggregateCall> aggCalls) {
         RelOptCluster cluster = input.getCluster();
-        RelTraitSet traits = cluster.traitSetOf(PhoenixRel.CONVENTION);
+        RelTraitSet traits = cluster.traitSetOf(PhoenixRel.CLIENT_CONVENTION);
         return new PhoenixClientAggregate(cluster, traits, input, indicator, 
                 groupSet, groupSets, aggCalls);
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientJoin.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientJoin.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientJoin.java
index 7bc0b5e..d664843 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientJoin.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientJoin.java
@@ -1,7 +1,6 @@
 package org.apache.phoenix.calcite.rel;
 
 import java.sql.SQLException;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
@@ -12,14 +11,11 @@ import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelCollation;
 import org.apache.calcite.rel.RelCollationTraitDef;
 import org.apache.calcite.rel.RelCollations;
-import org.apache.calcite.rel.RelFieldCollation;
-import org.apache.calcite.rel.RelFieldCollation.Direction;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.JoinInfo;
 import org.apache.calcite.rel.core.JoinRelType;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.util.ImmutableIntList;
 import org.apache.hadoop.hbase.client.Scan;
 import org.apache.phoenix.calcite.CalciteUtils;
 import org.apache.phoenix.calcite.metadata.PhoenixRelMdCollation;
@@ -44,40 +40,20 @@ import com.google.common.collect.Lists;
 
 public class PhoenixClientJoin extends PhoenixAbstractJoin {
     
-    public static PhoenixClientJoin create(RelNode left, RelNode right, 
+    public static PhoenixClientJoin create(final RelNode left, final RelNode 
right, 
             RexNode condition, JoinRelType joinType, Set<String> 
variablesStopped,
             boolean isSingleValueRhs) {
         RelOptCluster cluster = left.getCluster();
         final JoinInfo joinInfo = JoinInfo.of(left, right, condition);
-        final RelNode sortedLeft = sortInput(left, joinInfo.leftKeys);
-        final RelNode sortedRight = sortInput(right, joinInfo.rightKeys);
         final RelTraitSet traits =
-                cluster.traitSet().replace(PhoenixRel.CONVENTION)
+                cluster.traitSet().replace(PhoenixRel.CLIENT_CONVENTION)
                 .replaceIfs(RelCollationTraitDef.INSTANCE,
                         new Supplier<List<RelCollation>>() {
                     public List<RelCollation> get() {
-                        return PhoenixRelMdCollation.mergeJoin(sortedLeft, 
sortedRight, joinInfo.leftKeys, joinInfo.rightKeys);
+                        return PhoenixRelMdCollation.mergeJoin(left, right, 
joinInfo.leftKeys, joinInfo.rightKeys);
                     }
                 });
-        return new PhoenixClientJoin(cluster, traits, sortedLeft, sortedRight, 
condition, joinType, variablesStopped, isSingleValueRhs);
-    }
-    
-    private static RelNode sortInput(RelNode input, ImmutableIntList sortKeys) 
{
-        if (sortKeys.isEmpty()) {
-            return input;
-        }
-        
-        List<RelFieldCollation> fieldCollations = Lists.newArrayList();
-        for (Iterator<Integer> iter = sortKeys.iterator(); iter.hasNext();) {
-            fieldCollations.add(new RelFieldCollation(iter.next(), 
Direction.ASCENDING));
-        }
-        RelCollation collation = RelCollations.of(fieldCollations);
-        List<RelCollation> collations = 
input.getTraitSet().getTraits(RelCollationTraitDef.INSTANCE);
-        if (collations.contains(collation)) {
-            return input;
-        }
-        
-        return PhoenixClientSort.create(input, collation);
+        return new PhoenixClientJoin(cluster, traits, left, right, condition, 
joinType, variablesStopped, isSingleValueRhs);
     }
 
     private PhoenixClientJoin(RelOptCluster cluster, RelTraitSet traits,
@@ -102,6 +78,11 @@ public class PhoenixClientJoin extends PhoenixAbstractJoin {
 
     @Override
     public RelOptCost computeSelfCost(RelOptPlanner planner) {
+        if (joinType == JoinRelType.RIGHT
+                || (!joinInfo.leftKeys.isEmpty() && 
!RelCollations.contains(RelMetadataQuery.collations(getLeft()), 
joinInfo.leftKeys))
+                || (!joinInfo.rightKeys.isEmpty() && 
!RelCollations.contains(RelMetadataQuery.collations(getRight()), 
joinInfo.rightKeys)))
+            return planner.getCostFactory().makeInfiniteCost();
+        
         double rowCount = RelMetadataQuery.getRowCount(this);        
 
         double leftRowCount = RelMetadataQuery.getRowCount(getLeft());
@@ -118,14 +99,11 @@ public class PhoenixClientJoin extends PhoenixAbstractJoin 
{
         }            
         RelOptCost cost = planner.getCostFactory().makeCost(rowCount, 0, 0);
 
-        return cost.multiplyBy(PHOENIX_FACTOR);
+        return cost.multiplyBy(SERVER_FACTOR).multiplyBy(PHOENIX_FACTOR);
     }
 
     @Override
     public QueryPlan implement(Implementor implementor) {
-        assert getLeft().getConvention() == PhoenixRel.CONVENTION;
-        assert getRight().getConvention() == PhoenixRel.CONVENTION;
-        
         List<Expression> leftExprs = Lists.<Expression> newArrayList();
         List<Expression> rightExprs = Lists.<Expression> newArrayList();
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientProject.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientProject.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientProject.java
index 593fba7..ecdbc3b 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientProject.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientProject.java
@@ -24,7 +24,7 @@ public class PhoenixClientProject extends 
PhoenixAbstractProject {
             final List<? extends RexNode> projects, RelDataType rowType) {
         RelOptCluster cluster = input.getCluster();
         final RelTraitSet traits =
-                cluster.traitSet().replace(PhoenixRel.CONVENTION)
+                cluster.traitSet().replace(PhoenixRel.CLIENT_CONVENTION)
                 .replaceIfs(RelCollationTraitDef.INSTANCE,
                         new Supplier<List<RelCollation>>() {
                     public List<RelCollation> get() {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientSort.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientSort.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientSort.java
index bee20e4..052f078 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientSort.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixClientSort.java
@@ -27,7 +27,7 @@ public class PhoenixClientSort extends PhoenixAbstractSort {
         RelOptCluster cluster = input.getCluster();
         collation = RelCollationTraitDef.INSTANCE.canonize(collation);
         RelTraitSet traits =
-            
input.getTraitSet().replace(PhoenixRel.CONVENTION).replace(collation);
+            
input.getTraitSet().replace(PhoenixRel.CLIENT_CONVENTION).replace(collation);
         return new PhoenixClientSort(cluster, traits, input, collation);
     }
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixCompactClientSort.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixCompactClientSort.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixCompactClientSort.java
index 863cd22..39d7d08 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixCompactClientSort.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixCompactClientSort.java
@@ -21,7 +21,7 @@ public class PhoenixCompactClientSort extends 
PhoenixAbstractSort {
         RelOptCluster cluster = input.getCluster();
         collation = RelCollationTraitDef.INSTANCE.canonize(collation);
         RelTraitSet traits =
-            
input.getTraitSet().replace(PhoenixRel.CONVENTION).replace(collation);
+            
input.getTraitSet().replace(PhoenixRel.CLIENT_CONVENTION).replace(collation);
         return new PhoenixCompactClientSort(cluster, traits, input, collation);
     }
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixFilter.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixFilter.java 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixFilter.java
index f54744d..d958fe7 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixFilter.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixFilter.java
@@ -29,7 +29,7 @@ public class PhoenixFilter extends Filter implements 
PhoenixRel {
     public static PhoenixFilter create(final RelNode input, final RexNode 
condition) {
         RelOptCluster cluster = input.getCluster();
         final RelTraitSet traits =
-                cluster.traitSet().replace(PhoenixRel.CONVENTION)
+                cluster.traitSet().replace(PhoenixRel.CLIENT_CONVENTION)
                 .replaceIfs(RelCollationTraitDef.INSTANCE,
                         new Supplier<List<RelCollation>>() {
                     public List<RelCollation> get() {
@@ -41,7 +41,6 @@ public class PhoenixFilter extends Filter implements 
PhoenixRel {
     
     private PhoenixFilter(RelOptCluster cluster, RelTraitSet traits, RelNode 
input, RexNode condition) {
         super(cluster, traits, input, condition);
-        assert getConvention() == PhoenixRel.CONVENTION;
     }
 
     public PhoenixFilter copy(RelTraitSet traitSet, RelNode input, RexNode 
condition) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixJoin.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixJoin.java 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixJoin.java
deleted file mode 100644
index ff8ef29..0000000
--- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixJoin.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.apache.phoenix.calcite.rel;
-
-import java.util.Set;
-
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.plan.RelOptCost;
-import org.apache.calcite.plan.RelOptPlanner;
-import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.Join;
-import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.rex.RexNode;
-import org.apache.phoenix.compile.QueryPlan;
-
-import com.google.common.collect.ImmutableSet;
-
-public class PhoenixJoin extends Join implements PhoenixRel {
-    
-    public static PhoenixJoin create(RelNode left, RelNode right, 
-            RexNode condition, JoinRelType joinType, Set<String> 
variablesStopped) {
-        RelOptCluster cluster = left.getCluster();
-        RelTraitSet traits = cluster.traitSetOf(PhoenixRel.CONVENTION);
-        return new PhoenixJoin(cluster, traits, left, right, condition, 
joinType, variablesStopped);
-    }
-
-    private PhoenixJoin(RelOptCluster cluster, RelTraitSet traits, RelNode 
left,
-            RelNode right, RexNode condition, JoinRelType joinType,
-            Set<String> variablesStopped) {
-        super(cluster, traits, left, right, condition, joinType,
-                variablesStopped);
-    }
-
-    @Override
-    public Join copy(RelTraitSet traits, RexNode condition, RelNode left,
-            RelNode right, JoinRelType joinRelType, boolean semiJoinDone) {
-        return create(left, right, condition, joinRelType, 
ImmutableSet.<String>of());
-    }
-
-    @Override
-    public RelOptCost computeSelfCost(RelOptPlanner planner) {
-        return planner.getCostFactory().makeCost(Double.POSITIVE_INFINITY, 0, 
0);
-    }
-
-    @Override
-    public QueryPlan implement(Implementor implementor) {
-        throw new UnsupportedOperationException();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/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 d09c3c6..52482c1 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
@@ -30,7 +30,7 @@ public class PhoenixLimit extends SingleRel implements 
PhoenixRel {
     public static PhoenixLimit create(final RelNode input, RexNode offset, 
RexNode fetch) {
         RelOptCluster cluster = input.getCluster();
         final RelTraitSet traits =
-                cluster.traitSet().replace(PhoenixRel.CONVENTION)
+                cluster.traitSet().replace(PhoenixRel.CLIENT_CONVENTION)
                 .replaceIfs(RelCollationTraitDef.INSTANCE,
                         new Supplier<List<RelCollation>>() {
                     public List<RelCollation> get() {
@@ -46,7 +46,6 @@ public class PhoenixLimit extends SingleRel implements 
PhoenixRel {
         this.fetch = fetch;
         Object value = fetch == null ? null : 
CalciteUtils.evaluateStatelessExpression(fetch);
         this.statelessFetch = value == null ? null : ((Number) 
value).intValue();        
-        assert getConvention() == PhoenixRel.CONVENTION;
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixPostJoinProject.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixPostJoinProject.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixPostJoinProject.java
new file mode 100644
index 0000000..daa2978
--- /dev/null
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixPostJoinProject.java
@@ -0,0 +1,70 @@
+package org.apache.phoenix.calcite.rel;
+
+import java.util.List;
+
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptCost;
+import org.apache.calcite.plan.RelOptPlanner;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelCollation;
+import org.apache.calcite.rel.RelCollationTraitDef;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.metadata.RelMdCollation;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rex.RexNode;
+import org.apache.phoenix.compile.QueryPlan;
+import org.apache.phoenix.execute.HashJoinPlan;
+import org.apache.phoenix.execute.TupleProjector;
+
+import com.google.common.base.Supplier;
+
+public class PhoenixPostJoinProject extends PhoenixAbstractProject {
+    
+    public static PhoenixPostJoinProject create(final RelNode input, 
+            final List<? extends RexNode> projects, RelDataType rowType) {
+        RelOptCluster cluster = input.getCluster();
+        final RelTraitSet traits =
+                cluster.traitSet().replace(PhoenixRel.PROJECTABLE_CONVENTION)
+                .replaceIfs(RelCollationTraitDef.INSTANCE,
+                        new Supplier<List<RelCollation>>() {
+                    public List<RelCollation> get() {
+                        return RelMdCollation.project(input, projects);
+                    }
+                });
+        return new PhoenixPostJoinProject(cluster, traits, input, projects, 
rowType);
+    }
+
+    private PhoenixPostJoinProject(RelOptCluster cluster, RelTraitSet traits,
+            RelNode input, List<? extends RexNode> projects, RelDataType 
rowType) {
+        super(cluster, traits, input, projects, rowType);
+    }
+
+    @Override
+    public PhoenixPostJoinProject copy(RelTraitSet traits, RelNode input,
+            List<RexNode> projects, RelDataType rowType) {
+        return create(input, projects, rowType);
+    }
+
+    @Override
+    public RelOptCost computeSelfCost(RelOptPlanner planner) {
+        return super.computeSelfCost(planner)
+                .multiplyBy(SERVER_FACTOR)
+                .multiplyBy(PHOENIX_FACTOR);
+    }
+
+    @Override
+    public QueryPlan implement(Implementor implementor) {
+        assert getConvention() == getInput().getConvention();
+        
+        implementor.pushContext(new 
ImplementorContext(implementor.getCurrentContext().isRetainPKColumns(), false));
+        QueryPlan plan = implementor.visitInput(0, (PhoenixRel) getInput());
+        implementor.popContext();
+        assert (plan instanceof HashJoinPlan
+                && !TupleProjector.hasProjector(plan.getContext().getScan(), 
false));
+        
+        TupleProjector tupleProjector = super.project(implementor);
+        TupleProjector.serializeProjectorIntoScan(plan.getContext().getScan(), 
tupleProjector, false);
+        return plan;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixRel.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixRel.java 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixRel.java
index d19f0b4..82afedc 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixRel.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixRel.java
@@ -21,8 +21,10 @@ import org.apache.phoenix.schema.TableRef;
  * over streams of {@link org.apache.phoenix.schema.tuple.Tuple}s.</p>
  */
 public interface PhoenixRel extends RelNode {
-  /** Calling convention for relational operations that occur in Phoenix. */
-  Convention CONVENTION = new Convention.Impl("PHOENIX", PhoenixRel.class);
+  /** Calling conventions for relational operations that occur in Phoenix. */
+  Convention SERVER_CONVENTION = new Convention.Impl("PHOENIX_SERVER", 
PhoenixRel.class);
+  Convention PROJECTABLE_CONVENTION = new 
Convention.Impl("PHOENIX_PROJECTABLE", PhoenixRel.class);
+  Convention CLIENT_CONVENTION = new Convention.Impl("PHOENIX_CLIENT", 
PhoenixRel.class);
   
   /** Metadata Provider for PhoenixRel */
   RelMetadataProvider METADATA_PROVIDER = new PhoenixRelMetadataProvider();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerAggregate.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerAggregate.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerAggregate.java
index 0eb2808..776ec0d 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerAggregate.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerAggregate.java
@@ -25,7 +25,7 @@ public class PhoenixServerAggregate extends 
PhoenixAbstractAggregate {
             ImmutableBitSet groupSet, List<ImmutableBitSet> groupSets, 
             List<AggregateCall> aggCalls) {
         RelOptCluster cluster = input.getCluster();
-        RelTraitSet traits = cluster.traitSetOf(PhoenixRel.CONVENTION);
+        RelTraitSet traits = cluster.traitSetOf(PhoenixRel.CLIENT_CONVENTION);
         return new PhoenixServerAggregate(cluster, traits, input, indicator, 
                 groupSet, groupSets, aggCalls);
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerJoin.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerJoin.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerJoin.java
index 32ec08b..ef0abd3 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerJoin.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerJoin.java
@@ -38,7 +38,7 @@ public class PhoenixServerJoin extends PhoenixAbstractJoin {
             Set<String> variablesStopped, boolean isSingleValueRhs) {
         RelOptCluster cluster = left.getCluster();
         final RelTraitSet traits =
-                cluster.traitSet().replace(PhoenixRel.CONVENTION)
+                cluster.traitSet().replace(PhoenixRel.PROJECTABLE_CONVENTION)
                 .replaceIfs(RelCollationTraitDef.INSTANCE,
                         new Supplier<List<RelCollation>>() {
                     public List<RelCollation> get() {
@@ -54,7 +54,6 @@ public class PhoenixServerJoin extends PhoenixAbstractJoin {
             boolean isSingleValueRhs) {
         super(cluster, traits, left, right, condition, joinType,
                 variablesStopped, isSingleValueRhs);
-        assert joinType != JoinRelType.FULL && joinType != JoinRelType.RIGHT;
     }
 
     @Override
@@ -73,6 +72,10 @@ public class PhoenixServerJoin extends PhoenixAbstractJoin {
     public RelOptCost computeSelfCost(RelOptPlanner planner) {
         //TODO return infinite cost if RHS size exceeds memory limit.
         
+        if (joinType == JoinRelType.FULL || joinType == JoinRelType.RIGHT
+                || getLeft().getConvention() != PhoenixRel.SERVER_CONVENTION)
+            return planner.getCostFactory().makeInfiniteCost();
+        
         double rowCount = RelMetadataQuery.getRowCount(this);
 
         double leftRowCount = RelMetadataQuery.getRowCount(getLeft());
@@ -95,9 +98,6 @@ public class PhoenixServerJoin extends PhoenixAbstractJoin {
     
     @Override
     public QueryPlan implement(Implementor implementor) {
-        assert getLeft().getConvention() == PhoenixRel.CONVENTION;
-        assert getRight().getConvention() == PhoenixRel.CONVENTION;
-        
         List<Expression> leftExprs = Lists.<Expression> newArrayList();
         List<Expression> rightExprs = Lists.<Expression> newArrayList();
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerProject.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerProject.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerProject.java
index 2f201fc..a5d9039 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerProject.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerProject.java
@@ -13,7 +13,6 @@ import org.apache.calcite.rel.metadata.RelMdCollation;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rex.RexNode;
 import org.apache.phoenix.compile.QueryPlan;
-import org.apache.phoenix.execute.HashJoinPlan;
 import org.apache.phoenix.execute.ScanPlan;
 import org.apache.phoenix.execute.TupleProjector;
 
@@ -25,7 +24,7 @@ public class PhoenixServerProject extends 
PhoenixAbstractProject {
             final List<? extends RexNode> projects, RelDataType rowType) {
         RelOptCluster cluster = input.getCluster();
         final RelTraitSet traits =
-                cluster.traitSet().replace(PhoenixRel.CONVENTION)
+                cluster.traitSet().replace(PhoenixRel.SERVER_CONVENTION)
                 .replaceIfs(RelCollationTraitDef.INSTANCE,
                         new Supplier<List<RelCollation>>() {
                     public List<RelCollation> get() {
@@ -60,11 +59,11 @@ public class PhoenixServerProject extends 
PhoenixAbstractProject {
         implementor.pushContext(new 
ImplementorContext(implementor.getCurrentContext().isRetainPKColumns(), false));
         QueryPlan plan = implementor.visitInput(0, (PhoenixRel) getInput());
         implementor.popContext();
-        assert (plan instanceof ScanPlan || plan instanceof HashJoinPlan) 
-                && !TupleProjector.hasProjector(plan.getContext().getScan(), 
plan instanceof ScanPlan);
+        assert (plan instanceof ScanPlan
+                && !TupleProjector.hasProjector(plan.getContext().getScan(), 
true));
         
         TupleProjector tupleProjector = super.project(implementor);
-        TupleProjector.serializeProjectorIntoScan(plan.getContext().getScan(), 
tupleProjector, plan instanceof ScanPlan);
+        TupleProjector.serializeProjectorIntoScan(plan.getContext().getScan(), 
tupleProjector, true);
         return plan;
     }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerSort.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerSort.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerSort.java
index 4f40182..a57dd8d 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerSort.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixServerSort.java
@@ -21,7 +21,7 @@ public class PhoenixServerSort extends PhoenixAbstractSort {
         RelOptCluster cluster = input.getCluster();
         collation = RelCollationTraitDef.INSTANCE.canonize(collation);
         RelTraitSet traits =
-            
input.getTraitSet().replace(PhoenixRel.CONVENTION).replace(collation);
+            
input.getTraitSet().replace(PhoenixRel.CLIENT_CONVENTION).replace(collation);
         return new PhoenixServerSort(cluster, traits, input, collation);
     }
 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixTableScan.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixTableScan.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixTableScan.java
index 51cca21..d646a99 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixTableScan.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixTableScan.java
@@ -60,7 +60,7 @@ public class PhoenixTableScan extends TableScan implements 
PhoenixRel {
     public static PhoenixTableScan create(RelOptCluster cluster, final 
RelOptTable table, 
             RexNode filter, Integer statelessFetch) {
         final RelTraitSet traits =
-                cluster.traitSetOf(PhoenixRel.CONVENTION)
+                cluster.traitSetOf(PhoenixRel.SERVER_CONVENTION)
                 .replaceIfs(RelCollationTraitDef.INSTANCE,
                         new Supplier<List<RelCollation>>() {
                     public List<RelCollation> get() {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixToClientConverter.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixToClientConverter.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixToClientConverter.java
new file mode 100644
index 0000000..f395787
--- /dev/null
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixToClientConverter.java
@@ -0,0 +1,45 @@
+package org.apache.phoenix.calcite.rel;
+
+import java.util.List;
+
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptCost;
+import org.apache.calcite.plan.RelOptPlanner;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.SingleRel;
+import org.apache.phoenix.compile.QueryPlan;
+
+public class PhoenixToClientConverter extends SingleRel implements
+        PhoenixRel {
+    
+    public static PhoenixToClientConverter create(RelNode input) {
+        return new PhoenixToClientConverter(
+                input.getCluster(), 
+                input.getTraitSet().replace(PhoenixRel.CLIENT_CONVENTION), 
+                input);
+    }
+
+    private PhoenixToClientConverter(RelOptCluster cluster,
+            RelTraitSet traits, RelNode input) {
+        super(cluster, traits, input);
+    }
+    
+    @Override
+    public PhoenixToClientConverter copy(
+            RelTraitSet traitSet,
+            List<RelNode> newInputs) {
+        return create(sole(newInputs));
+    }
+
+    @Override 
+    public RelOptCost computeSelfCost(RelOptPlanner planner) {
+        return planner.getCostFactory().makeCost(0, 0, 0);
+    }
+    
+    @Override
+    public QueryPlan implement(Implementor implementor) {
+        return implementor.visitInput(0, (PhoenixRel) getInput());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixUnion.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixUnion.java 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixUnion.java
index b961679..9a19a95 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixUnion.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixUnion.java
@@ -17,13 +17,12 @@ public class PhoenixUnion extends Union implements 
PhoenixRel {
     
     public static PhoenixUnion create(List<RelNode> inputs, boolean all) {
         RelOptCluster cluster = inputs.get(0).getCluster();
-        RelTraitSet traits = cluster.traitSetOf(PhoenixRel.CONVENTION);
+        RelTraitSet traits = cluster.traitSetOf(PhoenixRel.CLIENT_CONVENTION);
         return new PhoenixUnion(cluster, traits, inputs, all);
     }
     
     private PhoenixUnion(RelOptCluster cluster, RelTraitSet traits, 
List<RelNode> inputs, boolean all) {
         super(cluster, traits, inputs, all);
-        assert getConvention() == PhoenixRel.CONVENTION;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixValues.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixValues.java 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixValues.java
index 52cd5a4..c982a28 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixValues.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixValues.java
@@ -19,13 +19,12 @@ import com.google.common.collect.ImmutableList;
 public class PhoenixValues extends Values implements PhoenixRel {
     
     public static PhoenixValues create(RelOptCluster cluster, RelDataType 
rowType, ImmutableList<ImmutableList<RexLiteral>> tuples) {
-        RelTraitSet traits = cluster.traitSetOf(PhoenixRel.CONVENTION);
+        RelTraitSet traits = cluster.traitSetOf(PhoenixRel.CLIENT_CONVENTION);
         return new PhoenixValues(cluster, rowType, tuples, traits);
     }
     
     private PhoenixValues(RelOptCluster cluster, RelDataType rowType, 
ImmutableList<ImmutableList<RexLiteral>> tuples, RelTraitSet traits) {
         super(cluster, rowType, tuples, traits);
-        assert getConvention() == PhoenixRel.CONVENTION;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/phoenix/blob/c1396ecf/phoenix-core/src/main/java/org/apache/phoenix/calcite/rules/PhoenixClientJoinRule.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rules/PhoenixClientJoinRule.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rules/PhoenixClientJoinRule.java
deleted file mode 100644
index 86f0f08..0000000
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rules/PhoenixClientJoinRule.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.apache.phoenix.calcite.rules;
-
-import org.apache.calcite.plan.RelOptRule;
-import org.apache.calcite.plan.RelOptRuleCall;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.phoenix.calcite.rel.PhoenixClientJoin;
-import org.apache.phoenix.calcite.rel.PhoenixJoin;
-
-import com.google.common.base.Predicate;
-
-public class PhoenixClientJoinRule extends RelOptRule {
-    
-    /** Predicate that returns true if a join type is not right. */
-    private static final Predicate<PhoenixJoin> NO_RIGHT_JOIN =
-        new Predicate<PhoenixJoin>() {
-            @Override
-            public boolean apply(PhoenixJoin phoenixJoin) {
-                return phoenixJoin.getJoinType() != JoinRelType.RIGHT;
-            }
-        };
-    
-    public static PhoenixClientJoinRule INSTANCE = new PhoenixClientJoinRule();
-
-    public PhoenixClientJoinRule() {
-        super(operand(PhoenixJoin.class, null, NO_RIGHT_JOIN, any()), 
"PhoenixClientJoinRule");
-    }
-
-    @Override
-    public void onMatch(RelOptRuleCall call) {
-        PhoenixJoin join = call.rel(0);
-        RelNode left = join.getLeft();
-        RelNode right = join.getRight();
-
-        call.transformTo(PhoenixClientJoin.create(
-                left, right, join.getCondition(), 
-                join.getJoinType(), join.getVariablesStopped(), false));
-    }
-
-}

Reply via email to