You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ja...@apache.org on 2014/01/27 20:23:34 UTC

[33/51] [partial] Initial commit

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java b/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java
new file mode 100644
index 0000000..f3e7b94
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.hadoop.io.WritableUtils;
+
+import org.apache.phoenix.expression.visitor.ExpressionVisitor;
+import org.apache.phoenix.schema.ColumnModifier;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.util.ByteUtil;
+import org.apache.phoenix.util.StringUtil;
+
+
+/**
+ * 
+ * Implementation for <,<=,>,>=,=,!= comparison expressions
+ * @author jtaylor
+ * @since 0.1
+ */
+public class ComparisonExpression extends BaseCompoundExpression {
+    private CompareOp op;
+    private static final String[] CompareOpString = new String[CompareOp.values().length];
+    static {
+        CompareOpString[CompareOp.EQUAL.ordinal()] = " = ";
+        CompareOpString[CompareOp.NOT_EQUAL.ordinal()] = " != ";
+        CompareOpString[CompareOp.GREATER.ordinal()] = " > ";
+        CompareOpString[CompareOp.LESS.ordinal()] = " < ";
+        CompareOpString[CompareOp.GREATER_OR_EQUAL.ordinal()] = " >= ";
+        CompareOpString[CompareOp.LESS_OR_EQUAL.ordinal()] = " <= ";
+    }
+    
+    public ComparisonExpression() {
+    }
+
+    public ComparisonExpression(CompareOp op, List<Expression> children) {
+        super(children);
+        if (op == null) {
+            throw new NullPointerException();
+        }
+        this.op = op;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + op.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (!super.equals(obj)) return false;
+        if (getClass() != obj.getClass()) return false;
+        ComparisonExpression other = (ComparisonExpression)obj;
+        if (op != other.op) return false;
+        return true;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PDataType.BOOLEAN;
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        if (!children.get(0).evaluate(tuple, ptr)) {
+            return false;
+        }
+        byte[] lhsBytes = ptr.get();
+        int lhsOffset = ptr.getOffset();
+        int lhsLength = ptr.getLength();
+        PDataType lhsDataType = children.get(0).getDataType();
+        ColumnModifier lhsColumnModifier = children.get(0).getColumnModifier();
+        
+        if (!children.get(1).evaluate(tuple, ptr)) {
+            return false;
+        }
+        
+        byte[] rhsBytes = ptr.get();
+        int rhsOffset = ptr.getOffset();
+        int rhsLength = ptr.getLength();
+        PDataType rhsDataType = children.get(1).getDataType();
+        ColumnModifier rhsColumnModifier = children.get(1).getColumnModifier();   
+        if (rhsDataType == PDataType.CHAR) {
+            rhsLength = StringUtil.getUnpaddedCharLength(rhsBytes, rhsOffset, rhsLength, rhsColumnModifier);
+        }
+        if (lhsDataType == PDataType.CHAR) {
+            lhsLength = StringUtil.getUnpaddedCharLength(lhsBytes, lhsOffset, lhsLength, lhsColumnModifier);
+        }
+        
+        
+        int comparisonResult = lhsDataType.compareTo(lhsBytes, lhsOffset, lhsLength, lhsColumnModifier, 
+                rhsBytes, rhsOffset, rhsLength, rhsColumnModifier, rhsDataType);
+        ptr.set(ByteUtil.compare(op, comparisonResult) ? PDataType.TRUE_BYTES : PDataType.FALSE_BYTES);
+        return true;
+    }
+    
+    @Override
+    public void readFields(DataInput input) throws IOException {
+        op = CompareOp.values()[WritableUtils.readVInt(input)];
+        super.readFields(input);
+    }
+
+    @Override
+    public void write(DataOutput output) throws IOException {
+        WritableUtils.writeVInt(output, op.ordinal());
+        super.write(output);
+    }
+
+    @Override
+    public final <T> T accept(ExpressionVisitor<T> visitor) {
+        List<T> l = acceptChildren(visitor, visitor.visitEnter(this));
+        T t = visitor.visitLeave(this, l);
+        if (t == null) {
+            t = visitor.defaultReturn(this, l);
+        }
+        return t;
+    }
+
+    public CompareOp getFilterOp() {
+        return op;
+    }
+    
+    @Override
+    public String toString() {
+        return (children.get(0) + CompareOpString[getFilterOp().ordinal()] + children.get(1));
+    }    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/DateAddExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/DateAddExpression.java b/src/main/java/org/apache/phoenix/expression/DateAddExpression.java
new file mode 100644
index 0000000..a36bb48
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/DateAddExpression.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.schema.ColumnModifier;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+
+public class DateAddExpression extends AddExpression {
+    static private final BigDecimal BD_MILLIS_IN_DAY = BigDecimal.valueOf(QueryConstants.MILLIS_IN_DAY);
+    
+    public DateAddExpression() {
+    }
+
+    public DateAddExpression(List<Expression> children) {
+        super(children);
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        long finalResult=0;
+        
+        for(int i=0;i<children.size();i++) {
+            if (!children.get(i).evaluate(tuple, ptr)) {
+                return false;
+            }
+            if (ptr.getLength() == 0) {
+                return true;
+            }
+            long value;
+            PDataType type = children.get(i).getDataType();
+            ColumnModifier columnModifier = children.get(i).getColumnModifier();
+            if (type == PDataType.DECIMAL) {
+                BigDecimal bd = (BigDecimal)PDataType.DECIMAL.toObject(ptr, columnModifier);
+                value = bd.multiply(BD_MILLIS_IN_DAY).longValue();
+            } else if (type.isCoercibleTo(PDataType.LONG)) {
+                value = type.getCodec().decodeLong(ptr, columnModifier) * QueryConstants.MILLIS_IN_DAY;
+            } else if (type.isCoercibleTo(PDataType.DOUBLE)) {
+                value = (long)(type.getCodec().decodeDouble(ptr, columnModifier) * QueryConstants.MILLIS_IN_DAY);
+            } else {
+                value = type.getCodec().decodeLong(ptr, columnModifier);
+            }
+            finalResult += value;
+        }
+        byte[] resultPtr = new byte[getDataType().getByteSize()];
+        ptr.set(resultPtr);
+        getDataType().getCodec().encodeLong(finalResult, ptr);
+        return true;
+    }
+
+    @Override
+    public final PDataType getDataType() {
+        return PDataType.DATE;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/DateSubtractExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/DateSubtractExpression.java b/src/main/java/org/apache/phoenix/expression/DateSubtractExpression.java
new file mode 100644
index 0000000..7329aff
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/DateSubtractExpression.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.schema.ColumnModifier;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+
+public class DateSubtractExpression extends SubtractExpression {
+    
+    public DateSubtractExpression() {
+    }
+
+    public DateSubtractExpression(List<Expression> children) {
+        super(children);
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        long finalResult=0;
+        
+        for(int i=0;i<children.size();i++) {
+            if (!children.get(i).evaluate(tuple, ptr) || ptr.getLength() == 0) {
+                return false;
+            }
+            long value;
+            PDataType type = children.get(i).getDataType();
+            ColumnModifier columnModifier = children.get(i).getColumnModifier();
+            if (type == PDataType.DECIMAL) {
+                BigDecimal bd = (BigDecimal)PDataType.DECIMAL.toObject(ptr, columnModifier);
+                value = bd.multiply(BD_MILLIS_IN_DAY).longValue();
+            } else if (type.isCoercibleTo(PDataType.LONG)) {
+                value = type.getCodec().decodeLong(ptr, columnModifier) * QueryConstants.MILLIS_IN_DAY;
+            } else if (type.isCoercibleTo(PDataType.DOUBLE)) {
+                value = (long)(type.getCodec().decodeDouble(ptr, columnModifier) * QueryConstants.MILLIS_IN_DAY);
+            } else {
+                value = type.getCodec().decodeLong(ptr, columnModifier);
+            }
+            if (i == 0) {
+                finalResult = value;
+            } else {
+                finalResult -= value;
+            }
+        }
+        byte[] resultPtr=new byte[getDataType().getByteSize()];
+        ptr.set(resultPtr);
+        getDataType().getCodec().encodeLong(finalResult, ptr);
+        return true;
+    }
+
+    @Override
+    public final PDataType getDataType() {
+        return PDataType.DATE;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/DecimalAddExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/DecimalAddExpression.java b/src/main/java/org/apache/phoenix/expression/DecimalAddExpression.java
new file mode 100644
index 0000000..24444a6
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/DecimalAddExpression.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.exception.ValueTypeIncompatibleException;
+import org.apache.phoenix.schema.ColumnModifier;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.util.NumberUtil;
+
+
+public class DecimalAddExpression extends AddExpression {
+    private Integer maxLength;
+    private Integer scale;
+
+    public DecimalAddExpression() {
+    }
+
+    public DecimalAddExpression(List<Expression> children) {
+        super(children);
+        for (int i=0; i<children.size(); i++) {
+            Expression childExpr = children.get(i);
+            if (i == 0) {
+                maxLength = childExpr.getMaxLength();
+                scale = childExpr.getScale();
+            } else {
+                maxLength = getPrecision(maxLength, childExpr.getMaxLength(), scale, childExpr.getScale());
+                scale = getScale(maxLength, childExpr.getMaxLength(), scale, childExpr.getScale());
+            }
+        }
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        BigDecimal result = null;
+        for (int i=0; i<children.size(); i++) {
+            Expression childExpr = children.get(i);
+            if (!childExpr.evaluate(tuple, ptr)) {
+                return false;
+            }
+            if (ptr.getLength() == 0) {
+                return true;
+            }
+            
+            PDataType childType = childExpr.getDataType();
+            ColumnModifier childColumnModifier = childExpr.getColumnModifier();
+            BigDecimal bd = (BigDecimal)PDataType.DECIMAL.toObject(ptr, childType, childColumnModifier);
+            
+            if (result == null) {
+                result = bd;
+            } else {
+                result = result.add(bd);
+            }
+        }
+        if (maxLength != null && scale != null) {
+            result = NumberUtil.setDecimalWidthAndScale(result, maxLength, scale);
+        }
+        if (result == null) {
+            throw new ValueTypeIncompatibleException(PDataType.DECIMAL, maxLength, scale);
+        }
+        ptr.set(PDataType.DECIMAL.toBytes(result));
+        return true;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PDataType.DECIMAL;
+    }
+
+    @Override
+    public Integer getScale() {
+        return scale;
+    }
+
+    @Override
+    public Integer getMaxLength() {
+        return maxLength;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/DecimalDivideExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/DecimalDivideExpression.java b/src/main/java/org/apache/phoenix/expression/DecimalDivideExpression.java
new file mode 100644
index 0000000..a1e3b34
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/DecimalDivideExpression.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.exception.ValueTypeIncompatibleException;
+import org.apache.phoenix.schema.ColumnModifier;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.util.NumberUtil;
+
+
+public class DecimalDivideExpression extends DivideExpression {
+
+    public DecimalDivideExpression() {
+    }
+
+    public DecimalDivideExpression(List<Expression> children) {
+        super(children);
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        BigDecimal result = null;
+        for (int i=0; i<children.size(); i++) {
+            Expression childExpr = children.get(i);
+            if (!childExpr.evaluate(tuple, ptr)) {
+                return false;
+            }
+            if (ptr.getLength() == 0) {
+                return true;
+            }
+            
+            PDataType childType = childExpr.getDataType();
+            ColumnModifier childColumnModifier = childExpr.getColumnModifier();
+            BigDecimal bd= (BigDecimal)PDataType.DECIMAL.toObject(ptr, childType, childColumnModifier);
+            
+            if (result == null) {
+                result = bd;
+            } else {
+                result = result.divide(bd, PDataType.DEFAULT_MATH_CONTEXT);
+            }
+        }
+        if (getMaxLength() != null && getScale() != null) {
+            result = NumberUtil.setDecimalWidthAndScale(result, getMaxLength(), getScale());
+        }
+        if (result == null) {
+            throw new ValueTypeIncompatibleException(PDataType.DECIMAL, getMaxLength(), getScale());
+        }
+        ptr.set(PDataType.DECIMAL.toBytes(result));
+        return true;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PDataType.DECIMAL;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/DecimalMultiplyExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/DecimalMultiplyExpression.java b/src/main/java/org/apache/phoenix/expression/DecimalMultiplyExpression.java
new file mode 100644
index 0000000..8b5ffae
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/DecimalMultiplyExpression.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.exception.ValueTypeIncompatibleException;
+import org.apache.phoenix.schema.ColumnModifier;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.util.NumberUtil;
+
+
+public class DecimalMultiplyExpression extends MultiplyExpression {
+
+    public DecimalMultiplyExpression() {
+    }
+
+    public DecimalMultiplyExpression(List<Expression> children) {
+        super(children);
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        BigDecimal result = null;
+        for (int i=0; i<children.size(); i++) {
+            Expression childExpr = children.get(i);
+            if (!childExpr.evaluate(tuple, ptr)) {
+                return false;
+            }
+            if (ptr.getLength() == 0) {
+                return true;
+            }
+            
+            PDataType childType = children.get(i).getDataType();
+            ColumnModifier childColumnModifier = children.get(i).getColumnModifier();
+            BigDecimal bd = (BigDecimal)PDataType.DECIMAL.toObject(ptr, childType, childColumnModifier);
+            
+            if (result == null) {
+                result = bd;
+            } else {
+                result = result.multiply(bd);
+            }
+        }
+        if (getMaxLength() != null && getScale() != null) {
+            result = NumberUtil.setDecimalWidthAndScale(result, getMaxLength(), getScale());
+        }
+        if (result == null) {
+            throw new ValueTypeIncompatibleException(PDataType.DECIMAL, getMaxLength(), getScale());
+        }
+        ptr.set(PDataType.DECIMAL.toBytes(result));
+        return true;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PDataType.DECIMAL;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/DecimalSubtractExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/DecimalSubtractExpression.java b/src/main/java/org/apache/phoenix/expression/DecimalSubtractExpression.java
new file mode 100644
index 0000000..a572cf2
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/DecimalSubtractExpression.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.exception.ValueTypeIncompatibleException;
+import org.apache.phoenix.schema.ColumnModifier;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.util.NumberUtil;
+
+
+/**
+ * 
+ * Subtract expression implementation
+ *
+ * @author kmahadik
+ * @since 0.1
+ */
+public class DecimalSubtractExpression extends SubtractExpression {
+    private Integer maxLength;
+    private Integer scale;
+
+    public DecimalSubtractExpression() {
+    }
+
+    public DecimalSubtractExpression(List<Expression> children) {
+        super(children);
+        for (int i=0; i<children.size(); i++) {
+            Expression childExpr = children.get(i);
+            if (i == 0) {
+                maxLength = childExpr.getMaxLength();
+                scale = childExpr.getScale();
+            } else {
+                maxLength = getPrecision(maxLength, childExpr.getMaxLength(), scale, childExpr.getScale());
+                scale = getScale(maxLength, childExpr.getMaxLength(), scale, childExpr.getScale());
+            }
+        }
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        BigDecimal result = null;
+        for (int i=0; i<children.size(); i++) {
+            Expression childExpr = children.get(i);
+            if (!childExpr.evaluate(tuple, ptr)) { 
+                return false;
+            }
+            if (ptr.getLength() == 0) {
+                return true;
+            }
+            
+            PDataType childType = childExpr.getDataType();
+            boolean isDate = childType.isCoercibleTo(PDataType.DATE);
+            ColumnModifier childColumnModifier = childExpr.getColumnModifier();
+            BigDecimal bd = isDate ?
+                    BigDecimal.valueOf(childType.getCodec().decodeLong(ptr, childColumnModifier)) :
+                    (BigDecimal)PDataType.DECIMAL.toObject(ptr, childType, childColumnModifier);
+            
+            if (result == null) {
+                result = bd;
+            } else {
+                result = result.subtract(bd);
+                /*
+                 * Special case for date subtraction - note that only first two expression may be dates.
+                 * We need to convert the date to a unit of "days" because that's what sql expects.
+                 */
+                if (isDate) {
+                    result = result.divide(BD_MILLIS_IN_DAY, PDataType.DEFAULT_MATH_CONTEXT);
+                }
+            }
+        }
+        if (maxLength != null && scale != null) {
+            result = NumberUtil.setDecimalWidthAndScale(result, maxLength, scale);
+        }
+        if (result == null) {
+            throw new ValueTypeIncompatibleException(PDataType.DECIMAL, maxLength, scale);
+        }
+        ptr.set(PDataType.DECIMAL.toBytes(result));
+        return true;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PDataType.DECIMAL;
+    }
+
+    @Override
+    public Integer getScale() {
+        return scale;
+    }
+
+    @Override
+    public Integer getMaxLength() {
+        return maxLength;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/DivideExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/DivideExpression.java b/src/main/java/org/apache/phoenix/expression/DivideExpression.java
new file mode 100644
index 0000000..ab9d0d7
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/DivideExpression.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.util.List;
+
+import org.apache.phoenix.expression.visitor.ExpressionVisitor;
+import org.apache.phoenix.schema.PDataType;
+
+
+/**
+ * 
+ * Divide expression implementation
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public abstract class DivideExpression extends ArithmeticExpression {
+    private Integer maxLength;
+    private Integer scale;
+
+    public DivideExpression() {
+    }
+
+    public DivideExpression(List<Expression> children) {
+        super(children);
+        for (int i=0; i<children.size(); i++) {
+            Expression childExpr = children.get(i);
+            if (i == 0) {
+                maxLength = childExpr.getMaxLength();
+                scale = childExpr.getScale();
+            } else {
+                maxLength = getPrecision(maxLength, childExpr.getMaxLength(), scale, childExpr.getScale());
+                scale = getScale(maxLength, childExpr.getMaxLength(), scale, childExpr.getScale());
+            }
+        }
+    }
+
+    @Override
+    public final <T> T accept(ExpressionVisitor<T> visitor) {
+        List<T> l = acceptChildren(visitor, visitor.visitEnter(this));
+        T t = visitor.visitLeave(this, l);
+        if (t == null) {
+            t = visitor.defaultReturn(this, l);
+        }
+        return t;
+    }
+
+    @Override
+    public String getOperatorString() {
+        return " / ";
+    }
+    
+    private static Integer getPrecision(Integer lp, Integer rp, Integer ls, Integer rs) {
+    	if (ls == null || rs == null) {
+    		return PDataType.MAX_PRECISION;
+    	}
+        int val = getScale(lp, rp, ls, rs) + lp - ls + rp;
+        return Math.min(PDataType.MAX_PRECISION, val);
+    }
+
+    private static Integer getScale(Integer lp, Integer rp, Integer ls, Integer rs) {
+    	// If we are adding a decimal with scale and precision to a decimal
+    	// with no precision nor scale, the scale system does not apply.
+    	if (ls == null || rs == null) {
+    		return null;
+    	}
+        int val = Math.max(PDataType.MAX_PRECISION - lp + ls - rs, 0);
+        return Math.min(PDataType.MAX_PRECISION, val);
+    }
+
+    @Override
+    public Integer getScale() {
+        return scale;
+    }
+
+    @Override
+    public Integer getMaxLength() {
+        return maxLength;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/DoubleAddExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/DoubleAddExpression.java b/src/main/java/org/apache/phoenix/expression/DoubleAddExpression.java
new file mode 100644
index 0000000..96fc9fa
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/DoubleAddExpression.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+public class DoubleAddExpression extends AddExpression {
+
+    public DoubleAddExpression() {
+    }
+
+    public DoubleAddExpression(List<Expression> children) {
+        super(children);
+    }
+    
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        double result = 0.0;
+        for (int i = 0; i < children.size(); i++) {
+            Expression child = children.get(i);
+            if (!child.evaluate(tuple, ptr)) {
+                return false;
+            }
+            if (ptr.getLength() == 0) {
+                return true;
+            }
+            double childvalue = child.getDataType().getCodec()
+                    .decodeDouble(ptr, child.getColumnModifier());
+            if (!Double.isNaN(childvalue)
+                    && childvalue != Double.NEGATIVE_INFINITY
+                    && childvalue != Double.POSITIVE_INFINITY) {
+                result += childvalue;
+            } else {
+                return false;
+            }
+        }
+        byte[] resultPtr = new byte[getDataType().getByteSize()];
+        ptr.set(resultPtr);
+        getDataType().getCodec().encodeDouble(result, ptr);
+        return true;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PDataType.DOUBLE;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/DoubleDivideExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/DoubleDivideExpression.java b/src/main/java/org/apache/phoenix/expression/DoubleDivideExpression.java
new file mode 100644
index 0000000..561cf90
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/DoubleDivideExpression.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+public class DoubleDivideExpression extends DivideExpression {
+
+    public DoubleDivideExpression() {
+    }
+
+    public DoubleDivideExpression(List<Expression> children) {
+        super(children);
+    }
+    
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        double result = 0.0;
+        for (int i = 0; i < children.size(); i++) {
+            Expression child = children.get(i);
+            if (!child.evaluate(tuple, ptr)) {
+                return false;
+            }
+            if (ptr.getLength() == 0) {
+                return true;
+            }
+            double childvalue = child.getDataType().getCodec()
+                    .decodeDouble(ptr, child.getColumnModifier());
+            if (!Double.isNaN(childvalue)
+                    && childvalue != Double.NEGATIVE_INFINITY
+                    && childvalue != Double.POSITIVE_INFINITY) {
+                if (i == 0) {
+                    result = childvalue;
+                } else {
+                    result /= childvalue;
+                }
+            } else {
+                return false;
+            }
+        }
+        byte[] resultPtr = new byte[getDataType().getByteSize()];
+        ptr.set(resultPtr);
+        getDataType().getCodec().encodeDouble(result, ptr);
+        return true;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PDataType.DOUBLE;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/DoubleMultiplyExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/DoubleMultiplyExpression.java b/src/main/java/org/apache/phoenix/expression/DoubleMultiplyExpression.java
new file mode 100644
index 0000000..b9e8165
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/DoubleMultiplyExpression.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+public class DoubleMultiplyExpression extends MultiplyExpression {
+
+    public DoubleMultiplyExpression() {
+    }
+
+    public DoubleMultiplyExpression(List<Expression> children) {
+        super(children);
+    }
+    
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        double result = 1.0;
+        for (int i = 0; i < children.size(); i++) {
+            Expression child = children.get(i);
+            if (!child.evaluate(tuple, ptr)) {
+                return false;
+            }
+            if (ptr.getLength() == 0) {
+                return true;
+            }
+            double childvalue = child.getDataType().getCodec()
+                    .decodeDouble(ptr, child.getColumnModifier());
+            if (!Double.isNaN(childvalue)
+                    && childvalue != Double.NEGATIVE_INFINITY
+                    && childvalue != Double.POSITIVE_INFINITY) {
+                result *= childvalue;
+            } else {
+                return false;
+            }
+        }
+        byte[] resultPtr = new byte[getDataType().getByteSize()];
+        ptr.set(resultPtr);
+        getDataType().getCodec().encodeDouble(result, ptr);
+        return true;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PDataType.DOUBLE;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/DoubleSubtractExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/DoubleSubtractExpression.java b/src/main/java/org/apache/phoenix/expression/DoubleSubtractExpression.java
new file mode 100644
index 0000000..8752c15
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/DoubleSubtractExpression.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+public class DoubleSubtractExpression extends SubtractExpression {
+
+    public DoubleSubtractExpression() {
+    }
+
+    public DoubleSubtractExpression(List<Expression> children) {
+        super(children);
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        double result = 0.0;
+        for (int i = 0; i < children.size(); i++) {
+            Expression child = children.get(i);
+            if (!child.evaluate(tuple, ptr)) {
+                return false;
+            }
+            if (ptr.getLength() == 0) {
+                return true;
+            }
+            double childvalue = child.getDataType().getCodec()
+                    .decodeDouble(ptr, child.getColumnModifier());
+            if (!Double.isNaN(childvalue)
+                    && childvalue != Double.NEGATIVE_INFINITY
+                    && childvalue != Double.POSITIVE_INFINITY) {
+                if (i == 0) {
+                    result = childvalue;
+                } else {
+                    result -= childvalue;
+                }
+            } else {
+                return false;
+            }
+        }
+        byte[] resultPtr = new byte[getDataType().getByteSize()];
+        ptr.set(resultPtr);
+        getDataType().getCodec().encodeDouble(result, ptr);
+        return true;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PDataType.DOUBLE;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/Expression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/Expression.java b/src/main/java/org/apache/phoenix/expression/Expression.java
new file mode 100644
index 0000000..a17c23a
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/Expression.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.hadoop.io.Writable;
+
+import org.apache.phoenix.expression.visitor.ExpressionVisitor;
+import org.apache.phoenix.schema.PDatum;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+
+/**
+ * 
+ * Interface for general expression evaluation
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public interface Expression extends PDatum, Writable {
+    /**
+     * Access the value by setting a pointer to it (as opposed to making
+     * a copy of it which can be expensive)
+     * @param tuple Single row result during scan iteration
+     * @param ptr Pointer to byte value being accessed
+     * @return true if the expression could be evaluated (i.e. ptr was set)
+     * and false otherwise
+     */
+    boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr);
+    
+    /**
+     * Means of traversing expression tree through visitor.
+     * @param visitor
+     */
+    <T> T accept(ExpressionVisitor<T> visitor);
+    
+    /**
+     * @return the child expressions
+     */
+    List<Expression> getChildren();
+    
+    /**
+     * Resets the state of a expression back to its initial state and
+     * enables the expession to be evaluated incrementally (which
+     * occurs during filter evaluation where we see one key value at
+     * a time; it's possible to evaluate immediately rather than
+     * wait until all key values have been seen). Note that when
+     * evaluating incrementally, you must call this method before
+     * processing a new row.
+     */
+    void reset();
+    
+    /**
+     * @return true if the expression represents a constant value and
+     * false otherwise.
+     */
+    boolean isConstant();
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/ExpressionType.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/ExpressionType.java b/src/main/java/org/apache/phoenix/expression/ExpressionType.java
new file mode 100644
index 0000000..c865842
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/ExpressionType.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.util.Map;
+
+import org.apache.phoenix.expression.function.CoalesceFunction;
+import org.apache.phoenix.expression.function.CountAggregateFunction;
+import org.apache.phoenix.expression.function.DistinctCountAggregateFunction;
+import org.apache.phoenix.expression.function.IndexStateNameFunction;
+import org.apache.phoenix.expression.function.InvertFunction;
+import org.apache.phoenix.expression.function.LTrimFunction;
+import org.apache.phoenix.expression.function.LengthFunction;
+import org.apache.phoenix.expression.function.MaxAggregateFunction;
+import org.apache.phoenix.expression.function.MinAggregateFunction;
+import org.apache.phoenix.expression.function.PercentRankAggregateFunction;
+import org.apache.phoenix.expression.function.PercentileContAggregateFunction;
+import org.apache.phoenix.expression.function.PercentileDiscAggregateFunction;
+import org.apache.phoenix.expression.function.RTrimFunction;
+import org.apache.phoenix.expression.function.RegexpReplaceFunction;
+import org.apache.phoenix.expression.function.RegexpSubstrFunction;
+import org.apache.phoenix.expression.function.ReverseFunction;
+import org.apache.phoenix.expression.function.RoundFunction;
+import org.apache.phoenix.expression.function.SqlTableType;
+import org.apache.phoenix.expression.function.SqlTypeNameFunction;
+import org.apache.phoenix.expression.function.StddevPopFunction;
+import org.apache.phoenix.expression.function.StddevSampFunction;
+import org.apache.phoenix.expression.function.SubstrFunction;
+import org.apache.phoenix.expression.function.SumAggregateFunction;
+import org.apache.phoenix.expression.function.ToCharFunction;
+import org.apache.phoenix.expression.function.ToDateFunction;
+import org.apache.phoenix.expression.function.ToNumberFunction;
+import org.apache.phoenix.expression.function.TrimFunction;
+import org.apache.phoenix.expression.function.TruncFunction;
+
+import com.google.common.collect.Maps;
+
+/**
+ * 
+ * Enumeration of all Expression types that may be evaluated on the server-side.
+ * Used during serialization and deserialization to pass Expression between client
+ * and server.
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public enum ExpressionType {
+    ReverseFunction(ReverseFunction.class),
+    RowKey(RowKeyColumnExpression.class),
+    KeyValue(KeyValueColumnExpression.class),
+    LiteralValue(LiteralExpression.class),
+    RoundFunction(RoundFunction.class),
+    TruncFunction(TruncFunction.class),
+    ToDateFunction(ToDateFunction.class),
+    ToCharFunction(ToCharFunction.class),
+    ToNumberFunction(ToNumberFunction.class),
+    CoerceFunction(CoerceExpression.class),
+    SubstrFunction(SubstrFunction.class),
+    AndExpression(AndExpression.class),
+    OrExpression(OrExpression.class),
+    ComparisonExpression(ComparisonExpression.class),
+    CountAggregateFunction(CountAggregateFunction.class),
+    SumAggregateFunction(SumAggregateFunction.class),
+    MinAggregateFunction(MinAggregateFunction.class),
+    MaxAggregateFunction(MaxAggregateFunction.class),
+    LikeExpression(LikeExpression.class),
+    NotExpression(NotExpression.class),
+    CaseExpression(CaseExpression.class),
+    InListExpression(InListExpression.class),
+    IsNullExpression(IsNullExpression.class),
+    LongSubtractExpression(LongSubtractExpression.class),
+    DateSubtractExpression(DateSubtractExpression.class),
+    DecimalSubtractExpression(DecimalSubtractExpression.class),
+    LongAddExpression(LongAddExpression.class),
+    DecimalAddExpression(DecimalAddExpression.class),
+    DateAddExpression(DateAddExpression.class),
+    LongMultiplyExpression(LongMultiplyExpression.class),
+    DecimalMultiplyExpression(DecimalMultiplyExpression.class),
+    LongDivideExpression(LongDivideExpression.class),
+    DecimalDivideExpression(DecimalDivideExpression.class),
+    CoalesceFunction(CoalesceFunction.class),
+    RegexpReplaceFunction(RegexpReplaceFunction.class),
+    SQLTypeNameFunction(SqlTypeNameFunction.class),
+    RegexpSubstrFunction(RegexpSubstrFunction.class),
+    StringConcatExpression(StringConcatExpression.class),
+    LengthFunction(LengthFunction.class),
+    LTrimFunction(LTrimFunction.class),
+    RTrimFunction(RTrimFunction.class),
+    TrimFunction(TrimFunction.class),
+    DistinctCountAggregateFunction(DistinctCountAggregateFunction.class),
+    PercentileContAggregateFunction(PercentileContAggregateFunction.class),
+    PercentRankAggregateFunction(PercentRankAggregateFunction.class),
+    StddevPopFunction(StddevPopFunction.class),
+    StddevSampFunction(StddevSampFunction.class),
+    PercentileDiscAggregateFunction(PercentileDiscAggregateFunction.class),
+    DoubleAddExpression(DoubleAddExpression.class),
+    DoubleSubtractExpression(DoubleSubtractExpression.class),
+    DoubleMultiplyExpression(DoubleMultiplyExpression.class),
+    DoubleDivideExpression(DoubleDivideExpression.class),
+    RowValueConstructorExpression(RowValueConstructorExpression.class),
+    SqlTableType(SqlTableType.class),
+    CeilingDecimalExpression(CeilingDecimalExpression.class),
+    CeilingTimestampExpression(CeilingTimestampExpression.class),
+    FloorDecimalExpression(FloorDecimalExpression.class),
+    FloorTimestampExpression(FloorTimestampExpression.class),
+    IndexKeyValue(IndexKeyValueColumnExpression.class),
+    IndexStateName(IndexStateNameFunction.class),
+    InvertFunction(InvertFunction.class),
+    TimestampAddExpression(TimestampAddExpression.class),
+    TimestampSubtractExpression(TimestampSubtractExpression.class),
+    ;
+    
+    ExpressionType(Class<? extends Expression> clazz) {
+        this.clazz = clazz;
+    }
+
+    public Class<? extends Expression> getExpressionClass() {
+        return clazz;
+    }
+
+    private final Class<? extends Expression> clazz;
+
+    private static final Map<Class<? extends Expression>,ExpressionType> classToEnumMap = Maps.newHashMapWithExpectedSize(3);
+    static {
+        for (ExpressionType type : ExpressionType.values()) {
+            classToEnumMap.put(type.clazz, type);
+        }
+    }
+
+    /**
+     * Return the ExpressionType for a given Expression instance
+     */
+    public static ExpressionType valueOf(Expression expression) {
+        ExpressionType type = classToEnumMap.get(expression.getClass());
+        if (type == null) { // FIXME: this exception gets swallowed and retries happen
+            throw new IllegalArgumentException("No ExpressionType for " + expression.getClass());
+        }
+        return type;
+    }
+
+    /**
+     * Instantiates a DataAccessor based on its DataAccessorType
+     */
+    public Expression newInstance() {
+        try {
+            return clazz.newInstance();
+        } catch (InstantiationException e) {
+            throw new RuntimeException(e);
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/FloorDecimalExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/FloorDecimalExpression.java b/src/main/java/org/apache/phoenix/expression/FloorDecimalExpression.java
new file mode 100644
index 0000000..82e0a83
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/FloorDecimalExpression.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.math.MathContext;
+import java.math.RoundingMode;
+
+
+public class FloorDecimalExpression extends CeilingDecimalExpression {
+    private static final MathContext FLOOR_CONTEXT = new MathContext(0, RoundingMode.FLOOR);
+    
+    public FloorDecimalExpression() {
+    }
+    
+    public FloorDecimalExpression(Expression child) {
+        super(child);
+    }
+    
+    @Override
+    protected MathContext getMathContext() {
+        return FLOOR_CONTEXT;
+    }
+    
+    
+    @Override
+    public final String toString() {
+        StringBuilder buf = new StringBuilder("FLOOR(");
+        for (int i = 0; i < children.size() - 1; i++) {
+            buf.append(getChild().toString());
+        }
+        buf.append(")");
+        return buf.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/FloorTimestampExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/FloorTimestampExpression.java b/src/main/java/org/apache/phoenix/expression/FloorTimestampExpression.java
new file mode 100644
index 0000000..060c17d
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/FloorTimestampExpression.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+
+
+public class FloorTimestampExpression extends CeilingTimestampExpression {
+    
+    public FloorTimestampExpression() {
+    }
+    
+    public FloorTimestampExpression(Expression child) {
+        super(child);
+    }
+    
+    @Override
+    protected int getRoundUpAmount() {
+        return 0;
+    }
+
+    
+    @Override
+    public final String toString() {
+        StringBuilder buf = new StringBuilder("FLOOR(");
+        for (int i = 0; i < children.size() - 1; i++) {
+            buf.append(getChild().toString());
+        }
+        buf.append(")");
+        return buf.toString();
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/InListExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/InListExpression.java b/src/main/java/org/apache/phoenix/expression/InListExpression.java
new file mode 100644
index 0000000..7c7ad88
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/InListExpression.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.io.WritableUtils;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.apache.hbase.index.util.ImmutableBytesPtr;
+import org.apache.phoenix.expression.visitor.ExpressionVisitor;
+import org.apache.phoenix.schema.ConstraintViolationException;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.util.ByteUtil;
+
+/*
+ * Implementation of a SQL foo IN (a,b,c) expression. Other than the first
+ * expression, child expressions must be constants.
+ *
+ */
+public class InListExpression extends BaseSingleExpression {
+    private LinkedHashSet<ImmutableBytesPtr> values;
+    private ImmutableBytesPtr minValue;
+    private ImmutableBytesPtr maxValue;
+    private int valuesByteLength;
+    private boolean containsNull;
+    private int fixedWidth = -1;
+    private ImmutableBytesPtr value = new ImmutableBytesPtr();
+    private List<Expression> keyExpressions; // client side only
+
+    public static Expression create (List<Expression> children, ImmutableBytesWritable ptr) throws SQLException {
+        Expression firstChild = children.get(0);
+        PDataType firstChildType = firstChild.getDataType();
+        
+        boolean addedNull = false;
+        List<Expression> keys = Lists.newArrayListWithExpectedSize(children.size());
+        List<Expression> coercedKeyExpressions = Lists.newArrayListWithExpectedSize(children.size());
+        keys.add(firstChild);
+        coercedKeyExpressions.add(firstChild);
+        for (int i = 1; i < children.size(); i++) {
+            Expression rhs = children.get(i);
+            if (rhs.evaluate(null, ptr)) {
+                if (ptr.getLength() == 0) {
+                    if (!addedNull) {
+                        addedNull = true;
+                        keys.add(LiteralExpression.newConstant(null, PDataType.VARBINARY));
+                        coercedKeyExpressions.add(LiteralExpression.newConstant(null, firstChildType));
+                    }
+                } else {
+                    // Don't specify the firstChild column modifier here, as we specify it in the LiteralExpression creation below
+                    try {
+                        firstChildType.coerceBytes(ptr, rhs.getDataType(), rhs.getColumnModifier(), null);
+                        keys.add(LiteralExpression.newConstant(ByteUtil.copyKeyBytesIfNecessary(ptr), PDataType.VARBINARY, firstChild.getColumnModifier()));
+                        if(rhs.getDataType() == firstChildType) {
+                            coercedKeyExpressions.add(rhs);
+                        } else {
+                            coercedKeyExpressions.add(CoerceExpression.create(rhs, firstChildType));    
+                        }
+                    } catch (ConstraintViolationException e) { // Ignore and continue
+                    }
+                }
+            }
+            
+        }
+        if (keys.size() == 1) {
+            return LiteralExpression.FALSE_EXPRESSION;
+        }
+        if (keys.size() == 2 && addedNull) {
+            return LiteralExpression.newConstant(null, PDataType.BOOLEAN);
+        }
+        Expression expression;
+        // TODO: if inChildren.isEmpty() then Oracle throws a type mismatch exception. This means
+        // that none of the list elements match in type and there's no null element. We'd return
+        // false in this case. Should we throw?
+        if (keys.size() == 2) {
+            expression = new ComparisonExpression(CompareOp.EQUAL, keys);
+        } else {
+            expression = new InListExpression(keys, coercedKeyExpressions);
+        }
+        return expression;
+    }    
+    public InListExpression() {
+    }
+
+    private InListExpression(List<Expression> keys, List<Expression> keyExpressions) throws SQLException {
+        super(keyExpressions.get(0));
+        this.keyExpressions = keyExpressions.subList(1, keyExpressions.size());
+        Set<ImmutableBytesPtr> values = Sets.newHashSetWithExpectedSize(keys.size()-1);
+        int fixedWidth = -1;
+        boolean isFixedLength = true;
+        for (int i = 1; i < keys.size(); i++) {
+            ImmutableBytesPtr ptr = new ImmutableBytesPtr();
+            Expression child = keys.get(i);
+            assert(child.getDataType() == PDataType.VARBINARY);
+            child.evaluate(null, ptr);
+            if (ptr.getLength() == 0) {
+                containsNull = true;
+            } else {
+                if (values.add(ptr)) {
+                    int length = ptr.getLength();
+                    if (fixedWidth == -1) {
+                        fixedWidth = length;
+                    } else {
+                        isFixedLength &= fixedWidth == length;
+                    }
+                    
+                    valuesByteLength += ptr.getLength();
+                }
+            }
+        }
+        this.fixedWidth = isFixedLength ? fixedWidth : -1;
+        // Sort values by byte value so we can get min/max easily
+        ImmutableBytesPtr[] valuesArray = values.toArray(new ImmutableBytesPtr[values.size()]);
+        Arrays.sort(valuesArray, ByteUtil.BYTES_PTR_COMPARATOR);
+        this.minValue = valuesArray[0];
+        this.maxValue = valuesArray[valuesArray.length-1];
+        this.values = new LinkedHashSet<ImmutableBytesPtr>(Arrays.asList(valuesArray));
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        if (!getChild().evaluate(tuple, ptr)) {
+            return false;
+        }
+        value.set(ptr);
+        if (values.contains(value)) {
+            ptr.set(PDataType.TRUE_BYTES);
+            return true;
+        }
+        if (containsNull) { // If any null value and value not found
+            ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
+            return true;
+        }
+        ptr.set(PDataType.FALSE_BYTES);
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (containsNull ? 1231 : 1237);
+        result = prime * result + values.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
+        InListExpression other = (InListExpression)obj;
+        if (containsNull != other.containsNull) return false;
+        if (!values.equals(other.values)) return false;
+        return true;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PDataType.BOOLEAN;
+    }
+
+    @Override
+    public boolean isNullable() {
+        return super.isNullable() || containsNull;
+    }
+
+    private int readValue(DataInput input, byte[] valuesBytes, int offset, ImmutableBytesPtr ptr) throws IOException {
+        int valueLen = fixedWidth == -1 ? WritableUtils.readVInt(input) : fixedWidth;
+        values.add(new ImmutableBytesPtr(valuesBytes,offset,valueLen));
+        return offset + valueLen;
+    }
+    
+    @Override
+    public void readFields(DataInput input) throws IOException {
+        super.readFields(input);
+        containsNull = input.readBoolean();
+        fixedWidth = WritableUtils.readVInt(input);
+        byte[] valuesBytes = Bytes.readByteArray(input);
+        valuesByteLength = valuesBytes.length;
+        int len = fixedWidth == -1 ? WritableUtils.readVInt(input) : valuesByteLength / fixedWidth;
+        values = Sets.newLinkedHashSetWithExpectedSize(len);
+        int offset = 0;
+        int i  = 0;
+        if (i < len) {
+            offset = readValue(input, valuesBytes, offset, minValue = new ImmutableBytesPtr());
+            while (++i < len-1) {
+                offset = readValue(input, valuesBytes, offset, new ImmutableBytesPtr());
+            }
+            if (i < len) {
+                offset = readValue(input, valuesBytes, offset, maxValue = new ImmutableBytesPtr());
+            } else {
+                maxValue = minValue;
+            }
+        } else {
+            minValue = maxValue = new ImmutableBytesPtr(ByteUtil.EMPTY_BYTE_ARRAY);
+        }
+    }
+
+    @Override
+    public void write(DataOutput output) throws IOException {
+        super.write(output);
+        output.writeBoolean(containsNull);
+        WritableUtils.writeVInt(output, fixedWidth);
+        WritableUtils.writeVInt(output, valuesByteLength);
+        for (ImmutableBytesPtr ptr : values) {
+            output.write(ptr.get(), ptr.getOffset(), ptr.getLength());
+        }
+        if (fixedWidth == -1) {
+            WritableUtils.writeVInt(output, values.size());
+            for (ImmutableBytesPtr ptr : values) {
+                WritableUtils.writeVInt(output, ptr.getLength());
+            }
+        }
+    }
+
+    @Override
+    public final <T> T accept(ExpressionVisitor<T> visitor) {
+        List<T> l = acceptChildren(visitor, visitor.visitEnter(this));
+        T t = visitor.visitLeave(this, l);
+        if (t == null) {
+            t = visitor.defaultReturn(this, l);
+        }
+        return t;
+    }
+
+    public List<Expression> getKeyExpressions() {
+        return keyExpressions;
+    }
+
+    public ImmutableBytesWritable getMinKey() {
+        return minValue;
+    }
+
+    public ImmutableBytesWritable getMaxKey() {
+        return maxValue;
+    }
+
+    @Override
+    public String toString() {
+        int maxToStringLen = 200;
+        Expression firstChild = children.get(0);
+        PDataType type = firstChild.getDataType();
+        StringBuilder buf = new StringBuilder(firstChild + " IN (");
+        if (containsNull) {
+            buf.append("null,");
+        }
+        for (ImmutableBytesPtr value : values) {
+            if (firstChild.getColumnModifier() != null) {
+                type.coerceBytes(value, type, firstChild.getColumnModifier(), null);
+            }
+            buf.append(type.toStringLiteral(value, null));
+            buf.append(',');
+            if (buf.length() >= maxToStringLen) {
+                buf.append("... ");
+                break;
+            }
+        }
+        buf.setCharAt(buf.length()-1,')');
+        return buf.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/IndexKeyValueColumnExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/IndexKeyValueColumnExpression.java b/src/main/java/org/apache/phoenix/expression/IndexKeyValueColumnExpression.java
new file mode 100644
index 0000000..fb066c1
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/IndexKeyValueColumnExpression.java
@@ -0,0 +1,26 @@
+package org.apache.phoenix.expression;
+
+import org.apache.hadoop.hbase.util.Bytes;
+
+import org.apache.phoenix.schema.PColumn;
+import org.apache.phoenix.util.IndexUtil;
+import org.apache.phoenix.util.SchemaUtil;
+
+public class IndexKeyValueColumnExpression extends KeyValueColumnExpression {
+    public IndexKeyValueColumnExpression() {
+    }
+
+    public IndexKeyValueColumnExpression(PColumn column) {
+        super(column);
+    }
+    
+    @Override
+    public String toString() {
+        // Translate to the data table column name
+        String indexColumnName = Bytes.toString(this.getColumnName());
+        String dataFamilyName = IndexUtil.getDataColumnFamilyName(indexColumnName);
+        String dataColumnName = IndexUtil.getDataColumnName(indexColumnName);
+        return SchemaUtil.getColumnDisplayName(dataFamilyName, dataColumnName);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/IsNullExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/IsNullExpression.java b/src/main/java/org/apache/phoenix/expression/IsNullExpression.java
new file mode 100644
index 0000000..e6ef621
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/IsNullExpression.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.io.*;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.expression.visitor.ExpressionVisitor;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+
+/**
+ * 
+ * Implementation of IS NULL and IS NOT NULL expression
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class IsNullExpression extends BaseSingleExpression {
+    private boolean isNegate;
+
+    public IsNullExpression() {
+    }
+    
+    public IsNullExpression(Expression expression, boolean negate) {
+        super(expression);
+        this.isNegate = negate;
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        boolean evaluated = getChild().evaluate(tuple, ptr);
+        if (evaluated) {
+            ptr.set(isNegate ^ ptr.getLength() == 0 ? PDataType.TRUE_BYTES : PDataType.FALSE_BYTES);
+            return true;
+        }
+        if (tuple.isImmutable()) {
+            ptr.set(isNegate ? PDataType.FALSE_BYTES : PDataType.TRUE_BYTES);
+            return true;
+        }
+        
+        return false;
+    }
+
+    public boolean isNegate() {
+        return isNegate;
+    }
+    
+    @Override
+    public void readFields(DataInput input) throws IOException {
+        super.readFields(input);
+        isNegate = input.readBoolean();
+    }
+
+    @Override
+    public void write(DataOutput output) throws IOException {
+        super.write(output);
+        output.writeBoolean(isNegate);
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PDataType.BOOLEAN;
+    }
+    
+    @Override
+    public final <T> T accept(ExpressionVisitor<T> visitor) {
+        List<T> l = acceptChildren(visitor, visitor.visitEnter(this));
+        T t = visitor.visitLeave(this, l);
+        if (t == null) {
+            t = visitor.defaultReturn(this, l);
+        }
+        return t;
+    }
+    
+    @Override
+    public String toString() {
+        StringBuilder buf = new StringBuilder(children.get(0).toString());
+        if (isNegate) {
+            buf.append(" IS NOT NULL");
+        } else {
+            buf.append(" IS NULL");
+        }
+        return buf.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/KeyValueColumnExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/expression/KeyValueColumnExpression.java b/src/main/java/org/apache/phoenix/expression/KeyValueColumnExpression.java
new file mode 100644
index 0000000..7cc76fa
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/expression/KeyValueColumnExpression.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.hadoop.hbase.util.Bytes;
+
+import org.apache.phoenix.expression.visitor.ExpressionVisitor;
+import org.apache.phoenix.schema.PColumn;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.util.SchemaUtil;
+
+
+/**
+ * 
+ * Class to access a column value stored in a KeyValue
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class KeyValueColumnExpression extends ColumnExpression {
+    private byte[] cf;
+    private byte[] cq;
+
+    public KeyValueColumnExpression() {
+    }
+
+    public KeyValueColumnExpression(PColumn column) {
+        super(column);
+        this.cf = column.getFamilyName().getBytes();
+        this.cq = column.getName().getBytes();
+    }
+
+    public byte[] getColumnFamily() {
+        return cf;
+    }
+
+    public byte[] getColumnName() {
+        return cq;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + Arrays.hashCode(cf);
+        result = prime * result + Arrays.hashCode(cq);
+        return result;
+    }
+
+    // TODO: assumes single table
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
+        KeyValueColumnExpression other = (KeyValueColumnExpression)obj;
+        if (!Arrays.equals(cf, other.cf)) return false;
+        if (!Arrays.equals(cq, other.cq)) return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return SchemaUtil.getColumnDisplayName(cf, cq);
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        KeyValue keyValue = tuple.getValue(cf, cq);
+        if (keyValue != null) {
+            ptr.set(keyValue.getBuffer(), keyValue.getValueOffset(), keyValue.getValueLength());
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void readFields(DataInput input) throws IOException {
+        super.readFields(input);
+        cf = Bytes.readByteArray(input);
+        cq = Bytes.readByteArray(input);
+    }
+
+    @Override
+    public void write(DataOutput output) throws IOException {
+        super.write(output);
+        Bytes.writeByteArray(output, cf);
+        Bytes.writeByteArray(output, cq);
+    }
+
+    @Override
+    public final <T> T accept(ExpressionVisitor<T> visitor) {
+        return visitor.visit(this);
+    }
+}