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 23:15:49 UTC

[33/51] [partial] Initial commit of master branch from github

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/AndExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/AndExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/AndExpression.java
new file mode 100644
index 0000000..c35eca5
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/AndExpression.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.util.List;
+
+import org.apache.phoenix.expression.visitor.ExpressionVisitor;
+
+
+/**
+ * 
+ * AND expression implementation
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class AndExpression extends AndOrExpression {
+    private static final String AND = "AND";
+    
+    public static String combine(String expression1, String expression2) {
+        if (expression1 == null) {
+            return expression2;
+        }
+        if (expression2 == null) {
+            return expression1;
+        }
+        return "(" + expression1 + ") " + AND + " (" + expression2 + ")";
+    }
+    
+    public AndExpression() {
+    }
+
+    public AndExpression(List<Expression> children) {
+        super(children);
+    }
+
+    @Override
+    protected boolean getStopValue() {
+        return Boolean.FALSE;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder buf = new StringBuilder("(");
+        for (int i = 0; i < children.size() - 1; i++) {
+            buf.append(children.get(i) + " " + AND + " ");
+        }
+        buf.append(children.get(children.size()-1));
+        buf.append(')');
+        return buf.toString();
+    }
+    
+    @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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/AndOrExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/AndOrExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/AndOrExpression.java
new file mode 100644
index 0000000..aebd63a
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/AndOrExpression.java
@@ -0,0 +1,99 @@
+/*
+ * 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.BitSet;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+
+/**
+ * 
+ * Abstract expression implementation for compound AND and OR expressions
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public abstract class AndOrExpression extends BaseCompoundExpression {
+    // Remember evaluation of child expression for partial evaluation
+    private BitSet partialEvalState;
+   
+    public AndOrExpression() {
+    }
+    
+    public AndOrExpression(List<Expression> children) {
+        super(children);
+    }
+    
+    @Override
+    public int hashCode() {
+        return 31 * super.hashCode() + Boolean.valueOf(this.getStopValue()).hashCode();
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PDataType.BOOLEAN;
+    }
+
+    @Override
+    public void reset() {
+        if (partialEvalState == null) {
+            partialEvalState = new BitSet(children.size());
+        } else {
+            partialEvalState.clear();
+        }
+        super.reset();
+    }
+    
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        boolean isNull = false;
+        boolean stopValue = getStopValue();
+        for (int i = 0; i < children.size(); i++) {
+            Expression child = children.get(i);
+            // If partial state is available, then use that to know we've already evaluated this
+            // child expression and do not need to do so again.
+            if (partialEvalState == null || !partialEvalState.get(i)) {
+                // Call through to child evaluate method matching parent call to allow child to optimize
+                // evaluate versus getValue code path.
+                if (child.evaluate(tuple, ptr)) {
+                    // Short circuit if we see our stop value
+                    if (Boolean.valueOf(stopValue).equals(PDataType.BOOLEAN.toObject(ptr, child.getDataType()))) {
+                        return true;
+                    } else if (partialEvalState != null) {
+                        partialEvalState.set(i);
+                    }
+                } else {
+                    isNull = true;
+                }
+            }
+        }
+        if (isNull) {
+            return false;
+        }
+        return true;
+    }
+
+    protected abstract boolean getStopValue();
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/ArithmeticExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ArithmeticExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ArithmeticExpression.java
new file mode 100644
index 0000000..622d709
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ArithmeticExpression.java
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+public abstract class ArithmeticExpression extends BaseCompoundExpression {
+
+    public ArithmeticExpression() {
+    }
+
+    public ArithmeticExpression(List<Expression> children) {
+        super(children);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder buf = new StringBuilder("(");
+        for (int i = 0; i < children.size() - 1; i++) {
+            buf.append(children.get(i) + getOperatorString());
+        }
+        buf.append(children.get(children.size()-1));
+        buf.append(')');
+        return buf.toString();
+    }
+    
+    abstract protected String getOperatorString();
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayConstructorExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayConstructorExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayConstructorExpression.java
new file mode 100644
index 0000000..6dbf865
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ArrayConstructorExpression.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.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.sql.Types;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.hadoop.io.WritableUtils;
+
+import org.apache.phoenix.schema.PArrayDataType;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.PhoenixArray;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+/**
+ * Creates an expression for Upsert with Values/Select using ARRAY
+ */
+public class ArrayConstructorExpression extends BaseCompoundExpression {
+    private PDataType baseType;
+    private int position = -1;
+    private Object[] elements;
+    
+    
+    public ArrayConstructorExpression(List<Expression> children, PDataType baseType) {
+        super(children);
+        init(baseType);
+    }
+
+    private void init(PDataType baseType) {
+        this.baseType = baseType;
+        elements = new Object[getChildren().size()];
+    }
+    
+    @Override
+    public PDataType getDataType() {
+        return PDataType.fromTypeId(baseType.getSqlType() + Types.ARRAY);
+    }
+
+    @Override
+    public void reset() {
+        super.reset();
+        position = 0;
+        Arrays.fill(elements, null);
+    }
+    
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        for (int i = position >= 0 ? position : 0; i < elements.length; i++) {
+            Expression child = children.get(i);
+            if (!child.evaluate(tuple, ptr)) {
+                if (tuple != null && !tuple.isImmutable()) {
+                    if (position >= 0) position = i;
+                    return false;
+                }
+            } else {
+                elements[i] = baseType.toObject(ptr, child.getDataType(), child.getColumnModifier());
+            }
+        }
+        if (position >= 0) position = elements.length;
+        PhoenixArray array = PArrayDataType.instantiatePhoenixArray(baseType, elements);
+        // FIXME: Need to see if this creation of an array and again back to byte[] can be avoided
+        ptr.set(getDataType().toBytes(array));
+        return true;
+    }
+    
+    @Override
+    public void readFields(DataInput input) throws IOException {
+        super.readFields(input);
+        int baseTypeOrdinal = WritableUtils.readVInt(input);
+        init(PDataType.values()[baseTypeOrdinal]);
+    }
+
+    @Override
+    public void write(DataOutput output) throws IOException {
+        super.write(output);
+        WritableUtils.writeVInt(output, baseType.ordinal());
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseAddSubtractExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseAddSubtractExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseAddSubtractExpression.java
new file mode 100644
index 0000000..1b9e4e5
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseAddSubtractExpression.java
@@ -0,0 +1,53 @@
+/*
+ * 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.schema.PDataType;
+
+
+abstract public class BaseAddSubtractExpression extends ArithmeticExpression {
+    public BaseAddSubtractExpression() {
+    }
+
+    public BaseAddSubtractExpression(List<Expression> children) {
+        super(children);
+    }
+
+    protected 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) + Math.max(lp - ls, rp - rs) + 1;
+        return Math.min(PDataType.MAX_PRECISION, val);
+    }
+
+    protected 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(ls, rs);
+        return Math.min(PDataType.MAX_PRECISION, val);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseCompoundExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseCompoundExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseCompoundExpression.java
new file mode 100644
index 0000000..82a130d
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseCompoundExpression.java
@@ -0,0 +1,145 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+
+import org.apache.hadoop.io.WritableUtils;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.phoenix.expression.visitor.ExpressionVisitor;
+
+
+public abstract class BaseCompoundExpression extends BaseExpression {
+    protected List<Expression> children;
+    private boolean isNullable;
+    private boolean isStateless;
+    private boolean isDeterministic;
+   
+    public BaseCompoundExpression() {
+    }
+    
+    public BaseCompoundExpression(List<Expression> children) {
+        init(children);
+    }
+    
+    private void init(List<Expression> children) {
+        this.children = ImmutableList.copyOf(children);
+        boolean isStateless = true;
+        boolean isDeterministic = true;
+        boolean isNullable = false;
+        for (int i = 0; i < children.size(); i++) {
+            Expression child = children.get(i);
+            isNullable |= child.isNullable();
+            isStateless &= child.isStateless();
+            isDeterministic &= child.isDeterministic();
+        }
+        this.isStateless = isStateless;
+        this.isDeterministic = isDeterministic;
+        this.isNullable = isNullable;
+    }
+    
+    @Override
+    public List<Expression> getChildren() {
+        return children;
+    }
+    
+    
+    @Override
+    public boolean isDeterministic() {
+        return isDeterministic;
+    }
+    
+    @Override
+    public boolean isStateless() {
+        return isStateless;
+    }
+
+    @Override
+    public boolean isNullable() {
+        return isNullable;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + children.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;
+        BaseCompoundExpression other = (BaseCompoundExpression)obj;
+        if (!children.equals(other.children)) return false;
+        return true;
+    }
+
+    @Override
+    public void readFields(DataInput input) throws IOException {
+        int len = WritableUtils.readVInt(input);
+        List<Expression>children = new ArrayList<Expression>(len);
+        for (int i = 0; i < len; i++) {
+            Expression child = ExpressionType.values()[WritableUtils.readVInt(input)].newInstance();
+            child.readFields(input);
+            children.add(child);
+        }
+        init(children);
+    }
+
+    @Override
+    public void write(DataOutput output) throws IOException {
+        WritableUtils.writeVInt(output, children.size());
+        for (int i = 0; i < children.size(); i++) {
+            Expression child = children.get(i);
+            WritableUtils.writeVInt(output, ExpressionType.valueOf(child).ordinal());
+            child.write(output);
+        }
+    }
+
+    @Override
+    public void reset() {
+        for (int i = 0; i < children.size(); i++) {
+            children.get(i).reset();
+        }
+    }
+    
+    @Override
+    public <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() {
+        return this.getClass().getName() + " [children=" + children + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseDecimalAddSubtractExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseDecimalAddSubtractExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseDecimalAddSubtractExpression.java
new file mode 100644
index 0000000..4f641fe
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseDecimalAddSubtractExpression.java
@@ -0,0 +1,5 @@
+package org.apache.phoenix.expression;
+
+public class BaseDecimalAddSubtractExpression {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseExpression.java
new file mode 100644
index 0000000..9bd5581
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseExpression.java
@@ -0,0 +1,108 @@
+/*
+ * 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.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.phoenix.expression.visitor.ExpressionVisitor;
+import org.apache.phoenix.schema.ColumnModifier;
+
+
+
+/**
+ * 
+ * Base class for Expression hierarchy that provides common
+ * default implementations for most methods
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public abstract class BaseExpression implements Expression {
+    @Override
+    public boolean isNullable() {
+        return false;
+    }
+
+    @Override
+    public Integer getByteSize() {
+        return getDataType().isFixedWidth() ? getDataType().getByteSize() : null;
+    }
+
+    @Override
+    public Integer getMaxLength() {
+        return null;
+    }
+
+    @Override
+    public Integer getScale() {
+        return null;
+    }
+    
+    @Override
+    public ColumnModifier getColumnModifier() {
+    	    return null;
+    }    
+
+    @Override
+    public void readFields(DataInput input) throws IOException {
+    }
+
+    @Override
+    public void write(DataOutput output) throws IOException {
+    }
+
+    @Override
+    public void reset() {
+    }
+    
+    protected final <T> List<T> acceptChildren(ExpressionVisitor<T> visitor, Iterator<Expression> iterator) {
+        if (iterator == null) {
+            iterator = visitor.defaultIterator(this);
+        }
+        List<T> l = Collections.emptyList();
+        while (iterator.hasNext()) {
+            Expression child = iterator.next();
+            T t = child.accept(visitor);
+            if (t != null) {
+                if (l.isEmpty()) {
+                    l = new ArrayList<T>(getChildren().size());
+                }
+                l.add(t);
+            }
+        }
+        return l;
+    }
+    
+    @Override
+    public boolean isDeterministic() {
+        return true;
+    }
+    
+    @Override
+    public boolean isStateless() {
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseSingleExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseSingleExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseSingleExpression.java
new file mode 100644
index 0000000..1758438
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseSingleExpression.java
@@ -0,0 +1,91 @@
+/*
+ * 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.io.WritableUtils;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.phoenix.expression.visitor.ExpressionVisitor;
+
+
+/**
+ * 
+ * Base class for expressions which have a single child expression
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public abstract class BaseSingleExpression extends BaseExpression {
+
+    protected List<Expression> children;
+    
+    public BaseSingleExpression() {
+    }
+
+    public BaseSingleExpression(Expression expression) {
+        this.children = ImmutableList.of(expression);
+    }
+
+    @Override
+    public List<Expression> getChildren() {
+        return children;
+    }
+    
+    @Override
+    public void readFields(DataInput input) throws IOException {
+        Expression expression = ExpressionType.values()[WritableUtils.readVInt(input)].newInstance();
+        expression.readFields(input);
+        children = ImmutableList.of(expression);
+    }
+
+    @Override
+    public void write(DataOutput output) throws IOException {
+        WritableUtils.writeVInt(output, ExpressionType.valueOf(children.get(0)).ordinal());
+        children.get(0).write(output);
+    }
+
+    @Override
+    public boolean isNullable() {
+        return children.get(0).isNullable();
+    }
+
+    @Override
+    public void reset() {
+        children.get(0).reset();
+    }
+
+    @Override
+    public <T> T accept(ExpressionVisitor<T> visitor) {
+        List<T> l = acceptChildren(visitor, null);
+        if (l.isEmpty()) {
+            return visitor.defaultReturn(this, l);
+        }
+        return l.get(0);
+    }
+    
+    public Expression getChild() {
+        return children.get(0);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseTerminalExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseTerminalExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseTerminalExpression.java
new file mode 100644
index 0000000..aaa4371
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/BaseTerminalExpression.java
@@ -0,0 +1,47 @@
+/*
+ * 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.Collections;
+import java.util.List;
+
+import org.apache.phoenix.expression.visitor.ExpressionVisitor;
+
+
+
+/**
+ * 
+ * Grouping class for expression that have no expression children
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public abstract class BaseTerminalExpression extends BaseExpression {
+    @Override
+    public List<Expression> getChildren() {
+        return Collections.emptyList();
+    }
+    
+    @Override
+    public <T> T accept(ExpressionVisitor<T> visitor) {
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/CaseExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/CaseExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/CaseExpression.java
new file mode 100644
index 0000000..f9a524a
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/CaseExpression.java
@@ -0,0 +1,234 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.hadoop.io.WritableUtils;
+
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.exception.SQLExceptionInfo;
+import org.apache.phoenix.expression.visitor.ExpressionVisitor;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+
+/**
+ * 
+ * CASE/WHEN expression implementation
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class CaseExpression extends BaseCompoundExpression {
+    private static final int FULLY_EVALUATE = -1;
+    
+    private short evalIndex = FULLY_EVALUATE;
+    private boolean foundIndex;
+    private PDataType returnType;
+   
+    public CaseExpression() {
+    }
+    
+    private static List<Expression> coerceIfNecessary(List<Expression> children) throws SQLException {
+        boolean isChildTypeUnknown = false;
+        PDataType returnType = children.get(0).getDataType();
+        for (int i = 2; i < children.size(); i+=2) {
+            Expression child = children.get(i);
+            PDataType childType = child.getDataType();
+            if (childType == null) {
+                isChildTypeUnknown = true;
+            } else if (returnType == null) {
+                returnType = childType;
+                isChildTypeUnknown = true;
+            } else if (returnType == childType || childType.isCoercibleTo(returnType)) {
+                continue;
+            } else if (returnType.isCoercibleTo(childType)) {
+                returnType = childType;
+            } else {
+                throw new SQLExceptionInfo.Builder(SQLExceptionCode.CANNOT_CONVERT_TYPE)
+                    .setMessage("Case expressions must have common type: " + returnType + " cannot be coerced to " + childType)
+                    .build().buildException();
+            }
+        }
+        // If we found an "unknown" child type and the return type is a number
+        // make the return type be the most general number type of DECIMAL.
+        if (isChildTypeUnknown && returnType != null && returnType.isCoercibleTo(PDataType.DECIMAL)) {
+            returnType = PDataType.DECIMAL;
+        }
+        List<Expression> newChildren = children;
+        for (int i = 0; i < children.size(); i+=2) {
+            Expression child = children.get(i);
+            PDataType childType = child.getDataType();
+            if (childType != returnType) {
+                if (newChildren == children) {
+                    newChildren = new ArrayList<Expression>(children);
+                }
+                newChildren.set(i, CoerceExpression.create(child, returnType));
+            }
+        }
+        return newChildren;
+    }
+    /**
+     * Construct CASE/WHEN expression
+     * @param expressions list of expressions in the form of:
+     *  ((<result expression>, <boolean expression>)+, [<optional else result expression>])
+     * @throws SQLException if return type of case expressions do not match and cannot
+     *  be coerced to a common type
+     */
+    public CaseExpression(List<Expression> expressions) throws SQLException {
+        super(coerceIfNecessary(expressions));
+        returnType = children.get(0).getDataType();
+    }
+    
+    private boolean isPartiallyEvaluating() {
+        return evalIndex != FULLY_EVALUATE;
+    }
+    
+    public boolean hasElse() {
+        return children.size() % 2 != 0;
+    }
+    
+    @Override
+    public boolean isNullable() {
+        // If any expression is nullable or there's no else clause
+        // return true since null may be returned.
+        if (super.isNullable() || !hasElse()) {
+            return true;
+        }
+        return children.get(children.size()-1).isNullable();
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return returnType;
+    }
+
+    @Override
+    public void reset() {
+        foundIndex = false;
+        evalIndex = 0;
+    }
+    
+    @Override
+    public void readFields(DataInput input) throws IOException {
+        super.readFields(input);
+        this.returnType = PDataType.values()[WritableUtils.readVInt(input)];
+    }
+    
+    @Override
+    public void write(DataOutput output) throws IOException {
+        super.write(output);
+        WritableUtils.writeVInt(output, this.returnType.ordinal());
+    }
+    
+    public int evaluateIndexOf(Tuple tuple, ImmutableBytesWritable ptr) {
+        if (foundIndex) {
+            return evalIndex;
+        }
+        int size = children.size();
+        // If we're doing partial evaluation, start where we left off
+        for (int i = isPartiallyEvaluating() ? evalIndex : 0; i < size; i+=2) {
+            // Short circuit if we see our stop value
+            if (i+1 == size) {
+                return i;
+            }
+            // If we get null, we have to re-evaluate from that point (special case this in filter, like is null)
+            // We may only run this when we're done/have all values
+            boolean evaluated = children.get(i+1).evaluate(tuple, ptr);
+            if (evaluated && Boolean.TRUE.equals(PDataType.BOOLEAN.toObject(ptr))) {
+                if (isPartiallyEvaluating()) {
+                    foundIndex = true;
+                }
+                return i;
+            }
+            if (isPartiallyEvaluating()) {
+                if (evaluated || tuple.isImmutable()) {
+                    evalIndex+=2;
+                } else {
+                    /*
+                     * Return early here if incrementally evaluating and we don't
+                     * have all the key values yet. We can't continue because we'd
+                     * potentially be bypassing cases which we could later evaluate
+                     * once we have more column values.
+                     */
+                    return -1;
+                }
+            }
+        }
+        // No conditions matched, return size to indicate that we were able
+        // to evaluate all cases, but didn't find any matches.
+        return size;
+    }
+    
+    /**
+     * Only expression that currently uses the isPartial flag. The IS NULL
+     * expression will use it too. TODO: We could alternatively have a non interface
+     * method, like setIsPartial in which we set to false prior to calling
+     * evaluate.
+     */
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        int index = evaluateIndexOf(tuple, ptr);
+        if (index < 0) {
+            return false;
+        } else if (index == children.size()) {
+            ptr.set(PDataType.NULL_BYTES);
+            return true;
+        }
+        if (children.get(index).evaluate(tuple, ptr)) {
+            return true;
+        }
+        return false;
+    }
+    
+    @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("CASE ");
+        for (int i = 0; i < children.size() - 1; i+=2) {
+            buf.append("WHEN ");
+            buf.append(children.get(i+1));
+            buf.append(" THEN ");
+            buf.append(children.get(i));
+        }
+        if (hasElse()) {
+            buf.append(" ELSE " + children.get(children.size()-1));
+        }
+        buf.append(" END");
+        return buf.toString();
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/CoerceExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/CoerceExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/CoerceExpression.java
new file mode 100644
index 0000000..827d70e
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/CoerceExpression.java
@@ -0,0 +1,153 @@
+/*
+ * 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.List;
+
+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;
+
+
+public class CoerceExpression extends BaseSingleExpression {
+    private PDataType toType;
+    private ColumnModifier toMod;
+    private Integer byteSize;
+    
+    public CoerceExpression() {
+    }
+
+    public static Expression create(Expression expression, PDataType toType) throws SQLException {
+        if (toType == expression.getDataType()) {
+            return expression;
+        }
+        return new CoerceExpression(expression, toType);
+    }
+    
+    //Package protected for tests
+    CoerceExpression(Expression expression, PDataType toType) {
+        this(expression, toType, null, null);
+    }
+    
+    CoerceExpression(Expression expression, PDataType toType, ColumnModifier toMod, Integer byteSize) {
+        super(expression);
+        this.toType = toType;
+        this.toMod = toMod;
+        this.byteSize = byteSize;
+    }
+
+    @Override
+    public Integer getByteSize() {
+        return byteSize;
+    }
+    
+    @Override
+    public Integer getMaxLength() {
+        return byteSize;
+    }
+    
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((byteSize == null) ? 0 : byteSize.hashCode());
+        result = prime * result + ((toMod == null) ? 0 : toMod.hashCode());
+        result = prime * result + ((toType == null) ? 0 : toType.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;
+        CoerceExpression other = (CoerceExpression)obj;
+        if (byteSize == null) {
+            if (other.byteSize != null) return false;
+        } else if (!byteSize.equals(other.byteSize)) return false;
+        if (toMod != other.toMod) return false;
+        if (toType != other.toType) return false;
+        return true;
+    }
+
+    @Override
+    public void readFields(DataInput input) throws IOException {
+        super.readFields(input);
+        toType = PDataType.values()[WritableUtils.readVInt(input)];
+        toMod = ColumnModifier.fromSystemValue(WritableUtils.readVInt(input));
+        int byteSize = WritableUtils.readVInt(input);
+        this.byteSize = byteSize == -1 ? null : byteSize;
+    }
+
+    @Override
+    public void write(DataOutput output) throws IOException {
+        super.write(output);
+        WritableUtils.writeVInt(output, toType.ordinal());
+        WritableUtils.writeVInt(output, ColumnModifier.toSystemValue(toMod));
+        WritableUtils.writeVInt(output, byteSize == null ? -1 : byteSize);
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        if (getChild().evaluate(tuple, ptr)) {
+            getDataType().coerceBytes(ptr, getChild().getDataType(), getChild().getColumnModifier(), getColumnModifier());
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return toType;
+    }
+    
+    @Override
+    public ColumnModifier getColumnModifier() {
+            return toMod;
+    }    
+
+    @Override
+    public <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("TO_" + toType.toString() + "(");
+        for (int i = 0; i < children.size() - 1; i++) {
+            buf.append(children.get(i) + ", ");
+        }
+        buf.append(children.get(children.size()-1) + ")");
+        return buf.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/ColumnExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ColumnExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ColumnExpression.java
new file mode 100644
index 0000000..bfb0d70
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ColumnExpression.java
@@ -0,0 +1,154 @@
+/*
+ * 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 org.apache.hadoop.io.WritableUtils;
+
+import com.google.common.base.Objects;
+import org.apache.phoenix.schema.ColumnModifier;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.PDatum;
+
+/**
+ * 
+ * Common base class for column value accessors
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+abstract public class ColumnExpression extends BaseTerminalExpression {
+    protected PDataType type;
+    private Integer byteSize;
+    private boolean isNullable;
+    private Integer maxLength;
+    private Integer scale;
+    private ColumnModifier columnModifier;
+
+    public ColumnExpression() {
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (isNullable() ? 1231 : 1237);
+        Integer maxLength = this.getByteSize();
+        result = prime * result + ((maxLength == null) ? 0 : maxLength.hashCode());
+        PDataType type = this.getDataType();
+        result = prime * result + ((type == null) ? 0 : type.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;
+        ColumnExpression other = (ColumnExpression)obj;
+        if (this.isNullable() != other.isNullable()) return false;
+        if (!Objects.equal(this.getByteSize(),other.getByteSize())) return false;
+        if (this.getDataType() != other.getDataType()) return false;
+        return true;
+    }
+
+    public ColumnExpression(PDatum datum) {
+        this.type = datum.getDataType();
+        this.isNullable = datum.isNullable();
+        if (type.isFixedWidth() && type.getByteSize() == null) {
+            this.byteSize = datum.getByteSize();
+        }
+        this.maxLength = datum.getMaxLength();
+        this.scale = datum.getScale();
+        this.columnModifier = datum.getColumnModifier();
+    }
+
+    @Override
+    public boolean isNullable() {
+       return isNullable;
+    }
+    
+    @Override
+    public PDataType getDataType() {
+        return type;
+    }
+    
+    @Override
+    public ColumnModifier getColumnModifier() {
+    	return columnModifier;
+    }
+
+    @Override
+    public Integer getByteSize() {
+        if (byteSize != null) {
+            return byteSize;
+        }
+        return super.getByteSize();
+    }
+
+    @Override
+    public Integer getMaxLength() {
+        return maxLength;
+    }
+
+    @Override
+    public Integer getScale() {
+        return scale;
+    }
+
+    @Override
+    public void readFields(DataInput input) throws IOException {
+        // read/write type ordinal, maxLength presence, scale presence and isNullable bit together to save space
+        int typeAndFlag = WritableUtils.readVInt(input);
+        isNullable = (typeAndFlag & 0x01) != 0;
+        if ((typeAndFlag & 0x02) != 0) {
+            scale = WritableUtils.readVInt(input);
+        }
+        if ((typeAndFlag & 0x04) != 0) {
+            maxLength = WritableUtils.readVInt(input);
+        }
+        type = PDataType.values()[typeAndFlag >>> 3];
+        if (type.isFixedWidth() && type.getByteSize() == null) {
+            byteSize = WritableUtils.readVInt(input);
+        }
+        columnModifier = ColumnModifier.fromSystemValue(WritableUtils.readVInt(input));
+    }
+
+    @Override
+    public void write(DataOutput output) throws IOException {
+        // read/write type ordinal, maxLength presence, scale presence and isNullable bit together to save space
+        int typeAndFlag = (isNullable ? 1 : 0) | ((scale != null ? 1 : 0) << 1) | ((maxLength != null ? 1 : 0) << 2)
+                | (type.ordinal() << 3);
+        WritableUtils.writeVInt(output,typeAndFlag);
+        if (scale != null) {
+            WritableUtils.writeVInt(output, scale);
+        }
+        if (maxLength != null) {
+            WritableUtils.writeVInt(output, maxLength);
+        }
+        if (type.isFixedWidth() && type.getByteSize() == null) {
+            WritableUtils.writeVInt(output, byteSize);
+        }
+        WritableUtils.writeVInt(output, ColumnModifier.toSystemValue(columnModifier));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java
new file mode 100644
index 0000000..5d3af1b
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java
@@ -0,0 +1,159 @@
+/*
+ * 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;
+    }
+    
+    public static String toString(CompareOp op, List<Expression> children) {
+        return (children.get(0) + CompareOpString[op.ordinal()] + children.get(1));
+    }
+    
+    @Override
+    public String toString() {
+        return toString(getFilterOp(), children);
+    }    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/CurrentDateTimeFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/CurrentDateTimeFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/CurrentDateTimeFunction.java
new file mode 100644
index 0000000..b221c1c
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/CurrentDateTimeFunction.java
@@ -0,0 +1,44 @@
+/*
+ * 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.function.ScalarFunction;
+
+public abstract class CurrentDateTimeFunction extends ScalarFunction {
+
+    public CurrentDateTimeFunction() {
+    }
+
+    public CurrentDateTimeFunction(List<Expression> children) {
+        super(children);
+    }
+    
+    @Override
+    public boolean isStateless() {
+        return true;
+    }
+
+    @Override
+    public boolean isDeterministic() {
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/DateAddExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/DateAddExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/DateAddExpression.java
new file mode 100644
index 0000000..a36bb48
--- /dev/null
+++ b/phoenix-core/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/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/DateSubtractExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/DateSubtractExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/DateSubtractExpression.java
new file mode 100644
index 0000000..7329aff
--- /dev/null
+++ b/phoenix-core/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/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/DecimalAddExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/DecimalAddExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/DecimalAddExpression.java
new file mode 100644
index 0000000..24444a6
--- /dev/null
+++ b/phoenix-core/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/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/DecimalDivideExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/DecimalDivideExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/DecimalDivideExpression.java
new file mode 100644
index 0000000..a1e3b34
--- /dev/null
+++ b/phoenix-core/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/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/DecimalMultiplyExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/DecimalMultiplyExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/DecimalMultiplyExpression.java
new file mode 100644
index 0000000..8b5ffae
--- /dev/null
+++ b/phoenix-core/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/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/DecimalSubtractExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/DecimalSubtractExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/DecimalSubtractExpression.java
new file mode 100644
index 0000000..a572cf2
--- /dev/null
+++ b/phoenix-core/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/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/DivideExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/DivideExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/DivideExpression.java
new file mode 100644
index 0000000..ab9d0d7
--- /dev/null
+++ b/phoenix-core/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/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/DoubleAddExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/DoubleAddExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/DoubleAddExpression.java
new file mode 100644
index 0000000..96fc9fa
--- /dev/null
+++ b/phoenix-core/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;
+    }
+
+}