You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ma...@apache.org on 2015/06/13 05:29:27 UTC

phoenix git commit: PHOENIX-1829 Extend support for equi-join conditions

Repository: phoenix
Updated Branches:
  refs/heads/calcite 171cc9249 -> f9ddb988c


PHOENIX-1829 Extend support for equi-join conditions


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

Branch: refs/heads/calcite
Commit: f9ddb988cd7dca05a4d4aaa75264b505770f3061
Parents: 171cc92
Author: maryannxue <we...@intel.com>
Authored: Fri Jun 12 23:29:15 2015 -0400
Committer: maryannxue <we...@intel.com>
Committed: Fri Jun 12 23:29:15 2015 -0400

----------------------------------------------------------------------
 .../org/apache/phoenix/calcite/CalciteTest.java |  15 +
 .../apache/phoenix/calcite/BuiltInMethod.java   |   3 +
 .../apache/phoenix/calcite/CalciteUtils.java    | 353 ++++++++++++++++++-
 .../apache/phoenix/calcite/PhoenixTable.java    |   1 +
 .../rel/PhoenixToEnumerableConverter.java       |   1 +
 5 files changed, 369 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/f9ddb988/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 7ce4f49..ebd9dfb 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
@@ -311,6 +311,21 @@ public class CalciteTest extends BaseClientManagedTimeIT {
                 .resultIs(new Object[][] {
                           {"0000000005", "T5", 500, 8, 15, "0000000005", "Item T5", "0000000005", "S5", "888-888-5555", "505 YYY Street", "10005"}})
                 .close();
+        
+        start().sql("SELECT \"order_id\", i.name, i.price, discount2, quantity FROM " + JOIN_ORDER_TABLE_FULL_NAME + " o INNER JOIN " 
+                + JOIN_ITEM_TABLE_FULL_NAME + " i ON o.\"item_id\" = i.\"item_id\" AND o.price = (i.price * (100 - discount2)) / 100.0 WHERE quantity < 5000")
+                .explainIs("PhoenixToEnumerableConverter\n" +
+                           "  PhoenixToClientConverter\n" +
+                           "    PhoenixPostJoinProject(order_id=[$5], NAME=[$1], PRICE=[$2], DISCOUNT2=[$3], QUANTITY=[$7])\n" +
+                           "      PhoenixServerJoin(condition=[AND(=($6, $0), =($8, $4))], joinType=[inner])\n" +
+                           "        PhoenixServerProject(item_id=[$0], NAME=[$1], PRICE=[$2], DISCOUNT2=[$4], $f7=[/(*($2, -(100, $4)), 100.0)])\n" +
+                           "          PhoenixTableScan(table=[[phoenix, Join, ItemTable]])\n" +
+                           "        PhoenixToClientConverter\n" +
+                           "          PhoenixServerProject(order_id=[$0], item_id=[$2], QUANTITY=[$4], $f7=[CAST($3):DECIMAL(17, 6) NOT NULL])\n" +
+                           "            PhoenixTableScan(table=[[phoenix, Join, OrderTable]], filter=[<($4, 5000)])\n")
+                .resultIs(new Object[][] {
+                          {"000000000000004", "T6", 600, 15, 4000}})
+                .close();
     }
     
     @Test public void testRightOuterJoin() throws Exception {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f9ddb988/phoenix-core/src/main/java/org/apache/phoenix/calcite/BuiltInMethod.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/BuiltInMethod.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/BuiltInMethod.java
index 192b421..3c0feeb 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/BuiltInMethod.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/BuiltInMethod.java
@@ -17,6 +17,7 @@ public enum BuiltInMethod {
     TO_ENUMERABLE(CalciteRuntime.class, "toEnumerable", QueryPlan.class);
 
     public final Method method;
+    @SuppressWarnings("rawtypes")
     public final Constructor constructor;
 
     public static final ImmutableMap<Method, BuiltInMethod> MAP;
@@ -32,11 +33,13 @@ public enum BuiltInMethod {
         MAP = builder.build();
     }
 
+    @SuppressWarnings("rawtypes")
     BuiltInMethod(Class clazz, String methodName, Class... argumentTypes) {
         this.method = Types.lookupMethod(clazz, methodName, argumentTypes);
         this.constructor = null;
     }
 
+    @SuppressWarnings("rawtypes")
     BuiltInMethod(Class clazz, Class... argumentTypes) {
         this.method = null;
         this.constructor = Types.lookupConstructor(clazz, argumentTypes);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f9ddb988/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java
index 93be79d..6e1f07d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java
@@ -1,6 +1,7 @@
 package org.apache.phoenix.calcite;
 
 import java.sql.SQLException;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -12,21 +13,51 @@ import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.sql.SqlAggFunction;
 import org.apache.calcite.sql.SqlFunction;
 import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.util.NlsString;
 import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.phoenix.calcite.rel.PhoenixRel.Implementor;
 import org.apache.phoenix.expression.AndExpression;
+import org.apache.phoenix.expression.CoerceExpression;
 import org.apache.phoenix.expression.ComparisonExpression;
+import org.apache.phoenix.expression.DateAddExpression;
+import org.apache.phoenix.expression.DateSubtractExpression;
+import org.apache.phoenix.expression.DecimalAddExpression;
+import org.apache.phoenix.expression.DecimalDivideExpression;
+import org.apache.phoenix.expression.DecimalMultiplyExpression;
+import org.apache.phoenix.expression.DecimalSubtractExpression;
 import org.apache.phoenix.expression.Determinism;
+import org.apache.phoenix.expression.DoubleAddExpression;
+import org.apache.phoenix.expression.DoubleDivideExpression;
+import org.apache.phoenix.expression.DoubleMultiplyExpression;
+import org.apache.phoenix.expression.DoubleSubtractExpression;
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.expression.ExpressionType;
 import org.apache.phoenix.expression.LiteralExpression;
+import org.apache.phoenix.expression.LongAddExpression;
+import org.apache.phoenix.expression.LongDivideExpression;
+import org.apache.phoenix.expression.LongMultiplyExpression;
+import org.apache.phoenix.expression.LongSubtractExpression;
 import org.apache.phoenix.expression.OrExpression;
+import org.apache.phoenix.expression.TimestampAddExpression;
+import org.apache.phoenix.expression.TimestampSubtractExpression;
 import org.apache.phoenix.expression.function.AggregateFunction;
 import org.apache.phoenix.expression.function.CountAggregateFunction;
 import org.apache.phoenix.expression.function.FunctionExpression;
 import org.apache.phoenix.expression.function.MaxAggregateFunction;
 import org.apache.phoenix.expression.function.MinAggregateFunction;
+import org.apache.phoenix.expression.function.RoundDecimalExpression;
+import org.apache.phoenix.expression.function.RoundTimestampExpression;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.TypeMismatchException;
+import org.apache.phoenix.schema.types.PDataType;
+import org.apache.phoenix.schema.types.PDate;
+import org.apache.phoenix.schema.types.PDecimal;
+import org.apache.phoenix.schema.types.PDouble;
+import org.apache.phoenix.schema.types.PLong;
+import org.apache.phoenix.schema.types.PTimestamp;
+import org.apache.phoenix.schema.types.PUnsignedTimestamp;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -42,6 +73,11 @@ public class CalciteUtils {
     public static String createTempAlias() {
         return "$" + tempAliasCounter.incrementAndGet();
     }
+    
+    @SuppressWarnings("rawtypes")
+    public static PDataType sqlTypeNameToPDataType(SqlTypeName sqlTypeName) {
+        return PDataType.fromTypeId(sqlTypeName.getJdbcOrdinal());
+    }
 
 	private static final Map<SqlKind, ExpressionFactory> EXPRESSION_MAP = Maps
 			.newHashMapWithExpectedSize(ExpressionType.values().length);
@@ -152,12 +188,287 @@ public class CalciteUtils {
             }
             
         });
+        EXPRESSION_MAP.put(SqlKind.PLUS, new ExpressionFactory() {
+
+            @SuppressWarnings("rawtypes")
+            @Override
+            public Expression newExpression(RexNode node, Implementor implementor) {
+                try {
+                    List<Expression> children = convertChildren((RexCall) node, implementor);
+                    Expression expr = null;
+                    boolean foundDate = false;
+                    Determinism determinism = Determinism.ALWAYS;
+                    PDataType theType = null;
+                    for(int i = 0; i < children.size(); i++) {
+                        Expression e = children.get(i);
+                        determinism = determinism.combine(e.getDeterminism());
+                        PDataType type = e.getDataType();
+                        if (type == null) {
+                            continue; 
+                        } else if (type.isCoercibleTo(PTimestamp.INSTANCE)) {
+                            if (foundDate) {
+                                throw TypeMismatchException.newException(type, node.toString());
+                            }
+                            if (theType == null || (theType != PTimestamp.INSTANCE && theType != PUnsignedTimestamp.INSTANCE)) {
+                                theType = type;
+                            }
+                            foundDate = true;
+                        }else if (type == PDecimal.INSTANCE) {
+                            if (theType == null || !theType.isCoercibleTo(PTimestamp.INSTANCE)) {
+                                theType = PDecimal.INSTANCE;
+                            }
+                        } else if (type.isCoercibleTo(PLong.INSTANCE)) {
+                            if (theType == null) {
+                                theType = PLong.INSTANCE;
+                            }
+                        } else if (type.isCoercibleTo(PDouble.INSTANCE)) {
+                            if (theType == null) {
+                                theType = PDouble.INSTANCE;
+                            }
+                        } else {
+                            throw TypeMismatchException.newException(type, node.toString());
+                        }
+                    }
+                    if (theType == PDecimal.INSTANCE) {
+                        expr = new DecimalAddExpression(children);
+                    } else if (theType == PLong.INSTANCE) {
+                        expr = new LongAddExpression(children);
+                    } else if (theType == PDouble.INSTANCE) {
+                        expr = new DoubleAddExpression(children);
+                    } else if (theType == null) {
+                        expr = LiteralExpression.newConstant(null, theType, determinism);
+                    } else if (theType == PTimestamp.INSTANCE || theType == PUnsignedTimestamp.INSTANCE) {
+                        expr = new TimestampAddExpression(children);
+                    } else if (theType.isCoercibleTo(PDate.INSTANCE)) {
+                        expr = new DateAddExpression(children);
+                    } else {
+                        throw TypeMismatchException.newException(theType, node.toString());
+                    }
+                    
+                    PDataType targetType = sqlTypeNameToPDataType(node.getType().getSqlTypeName());
+                    return cast(targetType, expr);
+                } catch (SQLException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+            
+        });
+        EXPRESSION_MAP.put(SqlKind.MINUS, new ExpressionFactory() {
+
+            @SuppressWarnings("rawtypes")
+            @Override
+            public Expression newExpression(RexNode node, Implementor implementor) {
+                try {
+                    List<Expression> children = convertChildren((RexCall) node, implementor);
+                    Expression expr = null;
+                    int i = 0;
+                    PDataType theType = null;
+                    Expression e1 = children.get(0);
+                    Expression e2 = children.get(1);
+                    Determinism determinism = e1.getDeterminism().combine(e2.getDeterminism());
+                    PDataType type1 = e1.getDataType();
+                    PDataType type2 = e2.getDataType();
+                    // TODO: simplify this special case for DATE conversion
+                    /**
+                     * For date1-date2, we want to coerce to a LONG because this
+                     * cannot be compared against another date. It has essentially
+                     * become a number. For date1-5, we want to preserve the DATE
+                     * type because this can still be compared against another date
+                     * and cannot be multiplied or divided. Any other time occurs is
+                     * an error. For example, 5-date1 is an error. The nulls occur if
+                     * we have bind variables.
+                     */
+                    boolean isType1Date = 
+                            type1 != null 
+                            && type1 != PTimestamp.INSTANCE
+                            && type1 != PUnsignedTimestamp.INSTANCE
+                            && type1.isCoercibleTo(PDate.INSTANCE);
+                    boolean isType2Date = 
+                            type2 != null
+                            && type2 != PTimestamp.INSTANCE
+                            && type2 != PUnsignedTimestamp.INSTANCE
+                            && type2.isCoercibleTo(PDate.INSTANCE);
+                    if (isType1Date || isType2Date) {
+                        if (isType1Date && isType2Date) {
+                            i = 2;
+                            theType = PDecimal.INSTANCE;
+                        } else if (isType1Date && type2 != null
+                                && type2.isCoercibleTo(PDecimal.INSTANCE)) {
+                            i = 2;
+                            theType = PDate.INSTANCE;
+                        } else if (type1 == null || type2 == null) {
+                            /*
+                             * FIXME: Could be either a Date or BigDecimal, but we
+                             * don't know if we're comparing to a date or a number
+                             * which would be disambiguate it.
+                             */
+                            i = 2;
+                            theType = null;
+                        }
+                    } else if(type1 == PTimestamp.INSTANCE || type2 == PTimestamp.INSTANCE) {
+                        i = 2;
+                        theType = PTimestamp.INSTANCE;
+                    } else if(type1 == PUnsignedTimestamp.INSTANCE || type2 == PUnsignedTimestamp.INSTANCE) {
+                        i = 2;
+                        theType = PUnsignedTimestamp.INSTANCE;
+                    }
+                    
+                    for (; i < children.size(); i++) {
+                        // This logic finds the common type to which all child types are coercible
+                        // without losing precision.
+                        Expression e = children.get(i);
+                        determinism = determinism.combine(e.getDeterminism());
+                        PDataType type = e.getDataType();
+                        if (type == null) {
+                            continue;
+                        } else if (type.isCoercibleTo(PLong.INSTANCE)) {
+                            if (theType == null) {
+                                theType = PLong.INSTANCE;
+                            }
+                        } else if (type == PDecimal.INSTANCE) {
+                            // Coerce return type to DECIMAL from LONG or DOUBLE if DECIMAL child found,
+                            // unless we're doing date arithmetic.
+                            if (theType == null
+                                    || !theType.isCoercibleTo(PDate.INSTANCE)) {
+                                theType = PDecimal.INSTANCE;
+                            }
+                        } else if (type.isCoercibleTo(PDouble.INSTANCE)) {
+                            // Coerce return type to DOUBLE from LONG if DOUBLE child found,
+                            // unless we're doing date arithmetic or we've found another child of type DECIMAL
+                            if (theType == null
+                                    || (theType != PDecimal.INSTANCE && !theType.isCoercibleTo(PDate.INSTANCE) )) {
+                                theType = PDouble.INSTANCE;
+                            }
+                        } else {
+                            throw TypeMismatchException.newException(type, node.toString());
+                        }
+                    }
+                    if (theType == PDecimal.INSTANCE) {
+                        expr = new DecimalSubtractExpression(children);
+                    } else if (theType == PLong.INSTANCE) {
+                        expr = new LongSubtractExpression(children);
+                    } else if (theType == PDouble.INSTANCE) {
+                        expr = new DoubleSubtractExpression(children);
+                    } else if (theType == null) {
+                        expr = LiteralExpression.newConstant(null, theType, determinism);
+                    } else if (theType == PTimestamp.INSTANCE || theType == PUnsignedTimestamp.INSTANCE) {
+                        expr = new TimestampSubtractExpression(children);
+                    } else if (theType.isCoercibleTo(PDate.INSTANCE)) {
+                        expr = new DateSubtractExpression(children);
+                    } else {
+                        throw TypeMismatchException.newException(theType, node.toString());
+                    }
+                    PDataType targetType = sqlTypeNameToPDataType(node.getType().getSqlTypeName());
+                    return cast(targetType, expr);
+                } catch (SQLException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+            
+        });
+        EXPRESSION_MAP.put(SqlKind.TIMES, new ExpressionFactory() {
+
+            @SuppressWarnings("rawtypes")
+            @Override
+            public Expression newExpression(RexNode node, Implementor implementor) {
+                try {
+                    List<Expression> children = convertChildren((RexCall) node, implementor);
+                    Expression expr = null;
+                    PDataType theType = null;
+                    Determinism determinism = Determinism.ALWAYS;
+                    for(int i = 0; i < children.size(); i++) {
+                        Expression e = children.get(i);
+                        determinism = determinism.combine(e.getDeterminism());
+                        PDataType type = e.getDataType();
+                        if (type == null) {
+                            continue;
+                        } else if (type == PDecimal.INSTANCE) {
+                            theType = PDecimal.INSTANCE;
+                        } else if (type.isCoercibleTo(PLong.INSTANCE)) {
+                            if (theType == null) {
+                                theType = PLong.INSTANCE;
+                            }
+                        } else if (type.isCoercibleTo(PDouble.INSTANCE)) {
+                            if (theType == null) {
+                                theType = PDouble.INSTANCE;
+                            }
+                        } else {
+                            throw TypeMismatchException.newException(type, node.toString());
+                        }
+                    }
+                    if (theType == PDecimal.INSTANCE) {
+                        expr = new DecimalMultiplyExpression(children);
+                    } else if (theType == PLong.INSTANCE) {
+                        expr = new LongMultiplyExpression(children);
+                    } else if (theType == PDouble.INSTANCE) {
+                        expr = new DoubleMultiplyExpression(children);
+                    } else {
+                        expr = LiteralExpression.newConstant(null, theType, determinism);
+                    }
+                    PDataType targetType = sqlTypeNameToPDataType(node.getType().getSqlTypeName());
+                    return cast(targetType, expr);
+                } catch (SQLException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+            
+        });
+        EXPRESSION_MAP.put(SqlKind.DIVIDE, new ExpressionFactory() {
+
+            @SuppressWarnings("rawtypes")
+            @Override
+            public Expression newExpression(RexNode node, Implementor implementor) {
+                try {
+                    List<Expression> children = convertChildren((RexCall) node, implementor);
+                    Expression expr = null;
+                    PDataType theType = null;
+                    Determinism determinism = Determinism.ALWAYS;
+                    for(int i = 0; i < children.size(); i++) {
+                        Expression e = children.get(i);
+                        determinism = determinism.combine(e.getDeterminism());
+                        PDataType type = e.getDataType();
+                        if (type == null) {
+                            continue;
+                        } else if (type == PDecimal.INSTANCE) {
+                            theType = PDecimal.INSTANCE;
+                        } else if (type.isCoercibleTo(PLong.INSTANCE)) {
+                            if (theType == null) {
+                                theType = PLong.INSTANCE;
+                            }
+                        } else if (type.isCoercibleTo(PDouble.INSTANCE)) {
+                            if (theType == null) {
+                                theType = PDouble.INSTANCE;
+                            }
+                        } else {
+                            throw TypeMismatchException.newException(type, node.toString());
+                        }
+                    }
+                    if (theType == PDecimal.INSTANCE) {
+                        expr = new DecimalDivideExpression( children);
+                    } else if (theType == PLong.INSTANCE) {
+                        expr = new LongDivideExpression( children);
+                    } else if (theType == PDouble.INSTANCE) {
+                        expr = new DoubleDivideExpression(children);
+                    } else {
+                        expr = LiteralExpression.newConstant(null, theType, determinism);
+                    }
+                    PDataType targetType = sqlTypeNameToPDataType(node.getType().getSqlTypeName());
+                    return cast(targetType, expr);
+                } catch (SQLException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+            
+        });
 		EXPRESSION_MAP.put(SqlKind.LITERAL, new ExpressionFactory() {
 
 			@Override
 			public Expression newExpression(RexNode node, Implementor implementor) {
 				RexLiteral lit = (RexLiteral) node;
-				Object o = lit.getValue2();
+				Object o = lit.getValue();
+				if (o instanceof NlsString) {
+				    o = ((NlsString) o).getValue();
+				}
 				return LiteralExpression.newConstant(o);
 			}
 			
@@ -174,11 +485,17 @@ public class CalciteUtils {
 		});
 		EXPRESSION_MAP.put(SqlKind.CAST, new ExpressionFactory() {
 
+            @SuppressWarnings("rawtypes")
             @Override
             public Expression newExpression(RexNode node,
-                    Implementor implementor) {
-                // TODO replace with real implementation
-                return toExpression(((RexCall) node).getOperands().get(0), implementor);
+                    Implementor implementor) {                
+                List<Expression> children = convertChildren((RexCall) node, implementor);
+                PDataType targetType = sqlTypeNameToPDataType(node.getType().getSqlTypeName());
+                try {
+                    return cast(targetType, children.get(0));
+                } catch (SQLException e) {
+                    throw new RuntimeException(e);
+                }
             }
 		    
 		});
@@ -237,6 +554,34 @@ public class CalciteUtils {
         }
         return children;
     }
+    
+    @SuppressWarnings("rawtypes")
+    private static Expression cast(PDataType targetDataType, Expression childExpr) throws SQLException {
+        PDataType fromDataType = childExpr.getDataType();
+        
+        Expression expr = childExpr;
+        if(fromDataType != null) {
+            expr =  convertToRoundExpressionIfNeeded(fromDataType, targetDataType, childExpr);
+        }
+        return CoerceExpression.create(expr, targetDataType, SortOrder.getDefault(), expr.getMaxLength());
+    }
+    
+    @SuppressWarnings("rawtypes")
+    private static Expression convertToRoundExpressionIfNeeded(PDataType fromDataType, PDataType targetDataType, Expression expr) throws SQLException {
+        if(fromDataType == targetDataType) {
+            return expr;
+        } else if((fromDataType == PDecimal.INSTANCE || fromDataType == PTimestamp.INSTANCE || fromDataType == PUnsignedTimestamp.INSTANCE) && targetDataType.isCoercibleTo(
+          PLong.INSTANCE)) {
+            return RoundDecimalExpression.create(Arrays.asList(expr));
+        } else if((fromDataType == PDecimal.INSTANCE || fromDataType == PTimestamp.INSTANCE || fromDataType == PUnsignedTimestamp.INSTANCE) && targetDataType.isCoercibleTo(
+          PDate.INSTANCE)) {
+            return RoundTimestampExpression.create(Arrays.asList(expr));
+        } else if(fromDataType.isCastableTo(targetDataType)) {
+            return expr;
+        } else {
+            throw TypeMismatchException.newException(fromDataType, targetDataType, expr.toString());
+        }
+    }
 
     public static boolean isExpressionSupported(RexNode node) {
         try {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f9ddb988/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTable.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTable.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTable.java
index 19d05da..99e829d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTable.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTable.java
@@ -62,6 +62,7 @@ public class PhoenixTable extends AbstractTable implements TranslatableTable {
     	return pTable;
     }
 
+    @SuppressWarnings("rawtypes")
     @Override
     public RelDataType getRowType(RelDataTypeFactory typeFactory) {
         final RelDataTypeFactory.FieldInfoBuilder builder = typeFactory.builder();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f9ddb988/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 058922c..771cad9 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
@@ -99,6 +99,7 @@ public class PhoenixToEnumerableConverter extends ConverterImpl implements Enume
         };
     }
 
+    @SuppressWarnings({ "rawtypes", "unchecked" })
     static Expression stash(EnumerableRelImplementor implementor, Object o, Class clazz) {
         ParameterExpression x = (ParameterExpression) implementor.stash(o, clazz);
         MethodCallExpression e =