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);
+ }
+}