http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayElemRefExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayElemRefExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayElemRefExpression.java new file mode 100644 index 0000000..6631e70 --- /dev/null +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayElemRefExpression.java @@ -0,0 +1,83 @@ +/* + * 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.function; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.util.List; + +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; +import org.apache.phoenix.expression.BaseCompoundExpression; +import org.apache.phoenix.expression.Expression; +import org.apache.phoenix.expression.visitor.ExpressionVisitor; +import org.apache.phoenix.schema.tuple.Tuple; +import org.apache.phoenix.schema.types.PArrayDataType; +import org.apache.phoenix.schema.types.PDataType; + +public class ArrayElemRefExpression extends BaseCompoundExpression { + + private int index; + + public ArrayElemRefExpression() { + } + + public ArrayElemRefExpression(List<Expression> children) { + super(children); + } + + public void setIndex(int index) { + this.index = index; + } + + @Override + public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { + Expression arrayExpr = children.get(0); + return PArrayDataType.positionAtArrayElement(tuple, ptr, index, arrayExpr, getDataType(), getMaxLength()); + } + + @Override + public Integer getMaxLength() { + return this.children.get(0).getMaxLength(); + } + + @Override + public PDataType getDataType() { + return PDataType.fromTypeId(children.get(0).getDataType().getSqlType() - PDataType.ARRAY_TYPE_BASE); + } + + @Override + public void write(DataOutput output) throws IOException { + super.write(output); + } + + @Override + public void readFields(DataInput input) throws IOException { + super.readFields(input); + } + + @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; + } +} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InlineArrayElemRefExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InlineArrayElemRefExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InlineArrayElemRefExpression.java deleted file mode 100644 index c5c1eea..0000000 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InlineArrayElemRefExpression.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.function; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.util.List; - -import org.apache.hadoop.hbase.io.ImmutableBytesWritable; -import org.apache.phoenix.expression.BaseCompoundExpression; -import org.apache.phoenix.expression.Expression; -import org.apache.phoenix.schema.types.PArrayDataType; -import org.apache.phoenix.schema.types.PDataType; -import org.apache.phoenix.schema.tuple.Tuple; - -public class InlineArrayElemRefExpression extends BaseCompoundExpression { - - private int index; - - public InlineArrayElemRefExpression() { - } - - public InlineArrayElemRefExpression(List<Expression> children) { - super(children); - } - - public void setIndex(int index) { - this.index = index; - } - - @Override - public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { - Expression arrayExpr = children.get(0); - return PArrayDataType.positionAtArrayElement(tuple, ptr, index, arrayExpr, getDataType(), getMaxLength()); - } - - @Override - public Integer getMaxLength() { - return this.children.get(0).getMaxLength(); - } - - @Override - public PDataType getDataType() { - return PDataType.fromTypeId(children.get(0).getDataType().getSqlType() - PDataType.ARRAY_TYPE_BASE); - } - - @Override - public void write(DataOutput output) throws IOException { - super.write(output); - } - - @Override - public void readFields(DataInput input) throws IOException { - super.readFields(input); - } - -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RandomFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RandomFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RandomFunction.java index ffa405b..2783300 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RandomFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RandomFunction.java @@ -114,7 +114,8 @@ public class RandomFunction extends ScalarFunction { return result; } - // take the random object onto account + // take the random object onto account, as otherwise we'll potentially collapse two + // RAND() calls into a single one. @Override public boolean equals(Object obj) { return super.equals(obj) && random.equals(((RandomFunction)obj).random); http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ScalarFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ScalarFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ScalarFunction.java index 37b8816..e694680 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ScalarFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ScalarFunction.java @@ -36,6 +36,15 @@ public abstract class ScalarFunction extends FunctionExpression { super(children); } + public ScalarFunction clone(List<Expression> children) { + try { + // FIXME: we could potentially implement this on each subclass and not use reflection + return getClass().getConstructor(List.class).newInstance(children); + } catch (Exception e) { + throw new RuntimeException(e); // Impossible, since it was originally constructed this way + } + } + protected static byte[] evaluateExpression(Expression rhs) { ImmutableBytesWritable ptr = new ImmutableBytesWritable(); rhs.evaluate(null, ptr); http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/BaseExpressionVisitor.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/BaseExpressionVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/BaseExpressionVisitor.java index 22bf195..8e8b32d 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/BaseExpressionVisitor.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/BaseExpressionVisitor.java @@ -30,36 +30,21 @@ import org.apache.phoenix.expression.DivideExpression; import org.apache.phoenix.expression.Expression; import org.apache.phoenix.expression.InListExpression; import org.apache.phoenix.expression.IsNullExpression; -import org.apache.phoenix.expression.KeyValueColumnExpression; import org.apache.phoenix.expression.LikeExpression; -import org.apache.phoenix.expression.LiteralExpression; +import org.apache.phoenix.expression.ModulusExpression; import org.apache.phoenix.expression.MultiplyExpression; import org.apache.phoenix.expression.NotExpression; import org.apache.phoenix.expression.OrExpression; -import org.apache.phoenix.expression.ProjectedColumnExpression; -import org.apache.phoenix.expression.RowKeyColumnExpression; import org.apache.phoenix.expression.RowValueConstructorExpression; import org.apache.phoenix.expression.StringConcatExpression; import org.apache.phoenix.expression.SubtractExpression; +import org.apache.phoenix.expression.function.ArrayAnyComparisonExpression; +import org.apache.phoenix.expression.function.ArrayElemRefExpression; import org.apache.phoenix.expression.function.ScalarFunction; import org.apache.phoenix.expression.function.SingleAggregateFunction; public abstract class BaseExpressionVisitor<E> implements ExpressionVisitor<E> { - @Override - public E visit(Expression node) { - return null; - } - - @Override - public Iterator<Expression> visitEnter(Expression node) { - return null; - } - - @Override - public E visitLeave(Expression node, List<E> l) { - return null; - } @Override public E defaultReturn(Expression node, List<E> l) { @@ -72,117 +57,52 @@ public abstract class BaseExpressionVisitor<E> implements ExpressionVisitor<E> { } @Override - public E visitLeave(AndExpression node, List<E> l) { - return null; - } - - @Override public Iterator<Expression> visitEnter(OrExpression node) { return null; } @Override - public E visitLeave(OrExpression node, List<E> l) { - return null; - } - - @Override public Iterator<Expression> visitEnter(ScalarFunction node) { return null; } @Override - public E visitLeave(ScalarFunction node, List<E> l) { - return null; - } - - @Override public Iterator<Expression> visitEnter(ComparisonExpression node) { return null; } @Override - public E visitLeave(ComparisonExpression node, List<E> l) { - return null; - } - - @Override public Iterator<Expression> visitEnter(LikeExpression node) { return null; } @Override - public E visitLeave(LikeExpression node, List<E> l) { - return null; - } - - @Override public Iterator<Expression> visitEnter(SingleAggregateFunction node) { return null; } @Override - public E visitLeave(SingleAggregateFunction node, List<E> l) { - return null; - } - - @Override public Iterator<Expression> visitEnter(CaseExpression node) { return null; } @Override - public E visitLeave(CaseExpression node, List<E> l) { - return null; - } - - @Override public Iterator<Expression> visitEnter(NotExpression node) { return null; } @Override - public E visitLeave(NotExpression node, List<E> l) { - return null; - } - - @Override public Iterator<Expression> visitEnter(IsNullExpression node) { return null; } @Override - public E visitLeave(IsNullExpression node, List<E> l) { - return null; - } - - @Override public Iterator<Expression> visitEnter(InListExpression node) { return null; } @Override - public E visitLeave(InListExpression node, List<E> l) { - return null; - } - - @Override - public E visit(LiteralExpression node) { - return null; - } - - @Override - public E visit(RowKeyColumnExpression node) { - return null; - } - - @Override - public E visit(KeyValueColumnExpression node) { - return null; - } - - @Override - public E visit(ProjectedColumnExpression node) { + public Iterator<Expression> visitEnter(AddExpression node) { return null; } @@ -192,71 +112,48 @@ public abstract class BaseExpressionVisitor<E> implements ExpressionVisitor<E> { } @Override - public E visitLeave(SubtractExpression node, List<E> l) { - return null; - } - - @Override - public Iterator<Expression> visitEnter(AddExpression node) { - return null; - } - @Override - public E visitLeave(AddExpression node, List<E> l) { - return null; - } - - @Override public Iterator<Expression> visitEnter(MultiplyExpression node) { return null; } - @Override - public E visitLeave(MultiplyExpression node, List<E> l) { - return null; - } @Override public Iterator<Expression> visitEnter(DivideExpression node) { return null; } - @Override - public E visitLeave(DivideExpression node, List<E> l) { - return null; - } @Override public Iterator<Expression> visitEnter(StringConcatExpression node) { return null; } - @Override - public E visitLeave(StringConcatExpression node, List<E> l) { - return null; - } @Override public Iterator<Expression> visitEnter(RowValueConstructorExpression node) { return null; } + @Override - public E visitLeave(RowValueConstructorExpression node, List<E> l) { + public Iterator<Expression> visitEnter(CoerceExpression node) { return null; } @Override - public Iterator<Expression> visitEnter(CoerceExpression node) { + public Iterator<Expression> visitEnter(ArrayConstructorExpression node) { return null; } @Override - public E visitLeave(CoerceExpression node, List<E> l) { + public Iterator<Expression> visitEnter(ModulusExpression modulusExpression) { return null; } @Override - public Iterator<Expression> visitEnter(ArrayConstructorExpression node) { + public Iterator<Expression> visitEnter(ArrayAnyComparisonExpression arrayAnyComparisonExpression) { return null; } + @Override - public E visitLeave(ArrayConstructorExpression node, List<E> l) { + public Iterator<Expression> visitEnter(ArrayElemRefExpression arrayElemRefExpression) { return null; } + } http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/CloneExpressionVisitor.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/CloneExpressionVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/CloneExpressionVisitor.java new file mode 100644 index 0000000..f415b01 --- /dev/null +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/CloneExpressionVisitor.java @@ -0,0 +1,195 @@ +/* + * 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.visitor; + +import java.util.List; + +import org.apache.phoenix.compile.SequenceValueExpression; +import org.apache.phoenix.expression.AddExpression; +import org.apache.phoenix.expression.AndExpression; +import org.apache.phoenix.expression.ArrayConstructorExpression; +import org.apache.phoenix.expression.CaseExpression; +import org.apache.phoenix.expression.CoerceExpression; +import org.apache.phoenix.expression.ComparisonExpression; +import org.apache.phoenix.expression.Determinism; +import org.apache.phoenix.expression.DivideExpression; +import org.apache.phoenix.expression.Expression; +import org.apache.phoenix.expression.InListExpression; +import org.apache.phoenix.expression.IsNullExpression; +import org.apache.phoenix.expression.KeyValueColumnExpression; +import org.apache.phoenix.expression.LikeExpression; +import org.apache.phoenix.expression.LiteralExpression; +import org.apache.phoenix.expression.ModulusExpression; +import org.apache.phoenix.expression.MultiplyExpression; +import org.apache.phoenix.expression.NotExpression; +import org.apache.phoenix.expression.OrExpression; +import org.apache.phoenix.expression.ProjectedColumnExpression; +import org.apache.phoenix.expression.RowKeyColumnExpression; +import org.apache.phoenix.expression.RowValueConstructorExpression; +import org.apache.phoenix.expression.StringConcatExpression; +import org.apache.phoenix.expression.SubtractExpression; +import org.apache.phoenix.expression.function.ArrayAnyComparisonExpression; +import org.apache.phoenix.expression.function.ArrayElemRefExpression; +import org.apache.phoenix.expression.function.ScalarFunction; +import org.apache.phoenix.expression.function.SingleAggregateFunction; + +public class CloneExpressionVisitor extends TraverseAllExpressionVisitor<Expression> { + + public CloneExpressionVisitor() { + } + + @Override + public Expression defaultReturn(Expression node, List<Expression> l) { + // Needed for Expressions derived from BaseTerminalExpression which don't + // have accept methods. TODO: get rid of those + return node; + } + + @Override + public Expression visit(LiteralExpression node) { + return node; + } + + @Override + public Expression visit(RowKeyColumnExpression node) { + return node; + } + + @Override + public Expression visit(KeyValueColumnExpression node) { + return node; + } + + @Override + public Expression visit(ProjectedColumnExpression node) { + return node; + } + + @Override + public Expression visit(SequenceValueExpression node) { + return node; + } + + @Override + public Expression visitLeave(AndExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : new AndExpression(l); + } + + @Override + public Expression visitLeave(OrExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : new OrExpression(l); + } + + @Override + public Expression visitLeave(ScalarFunction node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : node.clone(l); + } + + @Override + public Expression visitLeave(ComparisonExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : node.clone(l); + } + + @Override + public Expression visitLeave(LikeExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : new LikeExpression(l); + } + + @Override + public Expression visitLeave(SingleAggregateFunction node, List<Expression> l) { + // Do not clone aggregate functions, as they're executed on the server side, + // so any state for evaluation will live there. + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : node; + } + + @Override + public Expression visitLeave(CaseExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : new CaseExpression(l); + } + + @Override + public Expression visitLeave(NotExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : new NotExpression(l); + } + + @Override + public Expression visitLeave(InListExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : new InListExpression(l); + } + + @Override + public Expression visitLeave(IsNullExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : node.clone(l); + } + + @Override + public Expression visitLeave(SubtractExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : node.clone(l); + } + + @Override + public Expression visitLeave(MultiplyExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : node.clone(l); + } + + @Override + public Expression visitLeave(AddExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : node.clone(l); + } + + @Override + public Expression visitLeave(DivideExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : node.clone(l); + } + + @Override + public Expression visitLeave(ModulusExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : node.clone(l); + } + + @Override + public Expression visitLeave(CoerceExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : node.clone(l); + } + + @Override + public Expression visitLeave(ArrayConstructorExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : node.clone(l); + } + + @Override + public Expression visitLeave(StringConcatExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : new StringConcatExpression(l); + } + + @Override + public Expression visitLeave(RowValueConstructorExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : node.clone(l); + } + + @Override + public Expression visitLeave(ArrayAnyComparisonExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : new ArrayAnyComparisonExpression(l); + } + + @Override + public Expression visitLeave(ArrayElemRefExpression node, List<Expression> l) { + return Determinism.PER_INVOCATION.compareTo(node.getDeterminism()) > 0 ? node : new ArrayElemRefExpression(l); + } + +} http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/ExpressionVisitor.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/ExpressionVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/ExpressionVisitor.java index 794c348..0a8d3ad 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/ExpressionVisitor.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/ExpressionVisitor.java @@ -20,6 +20,7 @@ package org.apache.phoenix.expression.visitor; import java.util.Iterator; import java.util.List; +import org.apache.phoenix.compile.SequenceValueExpression; import org.apache.phoenix.expression.AddExpression; import org.apache.phoenix.expression.AndExpression; import org.apache.phoenix.expression.ArrayConstructorExpression; @@ -33,6 +34,7 @@ import org.apache.phoenix.expression.IsNullExpression; import org.apache.phoenix.expression.KeyValueColumnExpression; import org.apache.phoenix.expression.LikeExpression; import org.apache.phoenix.expression.LiteralExpression; +import org.apache.phoenix.expression.ModulusExpression; import org.apache.phoenix.expression.MultiplyExpression; import org.apache.phoenix.expression.NotExpression; import org.apache.phoenix.expression.OrExpression; @@ -41,6 +43,8 @@ import org.apache.phoenix.expression.RowKeyColumnExpression; import org.apache.phoenix.expression.RowValueConstructorExpression; import org.apache.phoenix.expression.StringConcatExpression; import org.apache.phoenix.expression.SubtractExpression; +import org.apache.phoenix.expression.function.ArrayAnyComparisonExpression; +import org.apache.phoenix.expression.function.ArrayElemRefExpression; import org.apache.phoenix.expression.function.ScalarFunction; import org.apache.phoenix.expression.function.SingleAggregateFunction; @@ -53,28 +57,6 @@ import org.apache.phoenix.expression.function.SingleAggregateFunction; * @since 0.1 */ public interface ExpressionVisitor<E> { - /** - * Default visit method when an expression subclass doesn't - * define an accept method of its own. This will end up calling - * the {@link #defaultIterator(Expression)} to iterate over the - * children calling accept on them - */ - public E visit(Expression node); - /** - * Default visitEnter method when an expression subclass doesn't - * define an accept method of its own. This will end up calling - * the {@link #defaultIterator(Expression)} to iterate over the - * children calling accept on them - */ - public Iterator<Expression> visitEnter(Expression node); - /** - * Default visitLeave method when an expression subclass doesn't - * define an accept method of its own. This will end up calling - * the {@link #defaultReturn(Expression, List)} with the list from - * the iteration over the children. - */ - public E visitLeave(Expression node, List<E> l); - public E defaultReturn(Expression node, List<E> l); public Iterator<Expression> defaultIterator(Expression node); @@ -130,11 +112,22 @@ public interface ExpressionVisitor<E> { public E visit(RowKeyColumnExpression node); public E visit(KeyValueColumnExpression node); public E visit(ProjectedColumnExpression node); + public E visit(SequenceValueExpression node); public Iterator<Expression> visitEnter(StringConcatExpression node); public E visitLeave(StringConcatExpression node, List<E> l); public Iterator<Expression> visitEnter(RowValueConstructorExpression node); public E visitLeave(RowValueConstructorExpression node, List<E> l); + + public Iterator<Expression> visitEnter(ModulusExpression modulusExpression); + public E visitLeave(ModulusExpression node, List<E> l); + + public Iterator<Expression> visitEnter(ArrayAnyComparisonExpression arrayAnyComparisonExpression); + public E visitLeave(ArrayAnyComparisonExpression node, List<E> l); + + public Iterator<Expression> visitEnter(ArrayElemRefExpression arrayElemRefExpression); + public E visitLeave(ArrayElemRefExpression node, List<E> l); + } http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/KeyValueExpressionVisitor.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/KeyValueExpressionVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/KeyValueExpressionVisitor.java index 93ce7c5..df6a30c 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/KeyValueExpressionVisitor.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/KeyValueExpressionVisitor.java @@ -30,7 +30,7 @@ import org.apache.phoenix.expression.KeyValueColumnExpression; * * @since 0.1 */ -public abstract class KeyValueExpressionVisitor extends TraverseAllExpressionVisitor<Void> { +public abstract class KeyValueExpressionVisitor extends StatelessTraverseAllExpressionVisitor<Void> { @Override abstract public Void visit(KeyValueColumnExpression node); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/RowKeyExpressionVisitor.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/RowKeyExpressionVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/RowKeyExpressionVisitor.java index a3e8fb0..4b78550 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/RowKeyExpressionVisitor.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/RowKeyExpressionVisitor.java @@ -30,7 +30,7 @@ import org.apache.phoenix.expression.RowKeyColumnExpression; * * @since 0.1 */ -public abstract class RowKeyExpressionVisitor extends TraverseAllExpressionVisitor<Void> { +public abstract class RowKeyExpressionVisitor extends StatelessTraverseAllExpressionVisitor<Void> { @Override abstract public Void visit(RowKeyColumnExpression node); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/SingleAggregateFunctionVisitor.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/SingleAggregateFunctionVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/SingleAggregateFunctionVisitor.java index 8e3644a..7981a98 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/SingleAggregateFunctionVisitor.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/SingleAggregateFunctionVisitor.java @@ -32,7 +32,7 @@ import org.apache.phoenix.expression.function.SingleAggregateFunction; * * @since 0.1 */ -public abstract class SingleAggregateFunctionVisitor extends TraverseAllExpressionVisitor<Void> { +public abstract class SingleAggregateFunctionVisitor extends StatelessTraverseAllExpressionVisitor<Void> { @Override abstract public Iterator<Expression> visitEnter(SingleAggregateFunction node); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/StatelessTraverseAllExpressionVisitor.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/StatelessTraverseAllExpressionVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/StatelessTraverseAllExpressionVisitor.java new file mode 100644 index 0000000..e7e7c67 --- /dev/null +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/StatelessTraverseAllExpressionVisitor.java @@ -0,0 +1,181 @@ +/* + * 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.visitor; + +import java.util.List; + +import org.apache.phoenix.compile.SequenceValueExpression; +import org.apache.phoenix.expression.AddExpression; +import org.apache.phoenix.expression.AndExpression; +import org.apache.phoenix.expression.ArrayConstructorExpression; +import org.apache.phoenix.expression.CaseExpression; +import org.apache.phoenix.expression.CoerceExpression; +import org.apache.phoenix.expression.ComparisonExpression; +import org.apache.phoenix.expression.DivideExpression; +import org.apache.phoenix.expression.InListExpression; +import org.apache.phoenix.expression.IsNullExpression; +import org.apache.phoenix.expression.KeyValueColumnExpression; +import org.apache.phoenix.expression.LikeExpression; +import org.apache.phoenix.expression.LiteralExpression; +import org.apache.phoenix.expression.ModulusExpression; +import org.apache.phoenix.expression.MultiplyExpression; +import org.apache.phoenix.expression.NotExpression; +import org.apache.phoenix.expression.OrExpression; +import org.apache.phoenix.expression.ProjectedColumnExpression; +import org.apache.phoenix.expression.RowKeyColumnExpression; +import org.apache.phoenix.expression.RowValueConstructorExpression; +import org.apache.phoenix.expression.StringConcatExpression; +import org.apache.phoenix.expression.SubtractExpression; +import org.apache.phoenix.expression.function.ArrayAnyComparisonExpression; +import org.apache.phoenix.expression.function.ArrayElemRefExpression; +import org.apache.phoenix.expression.function.ScalarFunction; +import org.apache.phoenix.expression.function.SingleAggregateFunction; + +public class StatelessTraverseAllExpressionVisitor<E> extends TraverseAllExpressionVisitor<E> { + + @Override + public E visitLeave(AndExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(OrExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(ScalarFunction node, List<E> l) { + return null; + } + + @Override + public E visitLeave(ComparisonExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(LikeExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(SingleAggregateFunction node, List<E> l) { + return null; + } + + @Override + public E visitLeave(CaseExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(NotExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(IsNullExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(InListExpression node, List<E> l) { + return null; + } + + @Override + public E visit(LiteralExpression node) { + return null; + } + + @Override + public E visit(RowKeyColumnExpression node) { + return null; + } + + @Override + public E visit(KeyValueColumnExpression node) { + return null; + } + + @Override + public E visit(ProjectedColumnExpression node) { + return null; + } + + @Override + public E visitLeave(AddExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(SubtractExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(MultiplyExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(DivideExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(StringConcatExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(RowValueConstructorExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(CoerceExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(ArrayConstructorExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(ModulusExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(ArrayAnyComparisonExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(ArrayElemRefExpression node, List<E> l) { + return null; + } + + @Override + public E visit(SequenceValueExpression node) { + return null; + } + +} http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/StatelessTraverseNoExpressionVisitor.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/StatelessTraverseNoExpressionVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/StatelessTraverseNoExpressionVisitor.java new file mode 100644 index 0000000..019754f --- /dev/null +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/StatelessTraverseNoExpressionVisitor.java @@ -0,0 +1,181 @@ +/* + * 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.visitor; + +import java.util.List; + +import org.apache.phoenix.compile.SequenceValueExpression; +import org.apache.phoenix.expression.AddExpression; +import org.apache.phoenix.expression.AndExpression; +import org.apache.phoenix.expression.ArrayConstructorExpression; +import org.apache.phoenix.expression.CaseExpression; +import org.apache.phoenix.expression.CoerceExpression; +import org.apache.phoenix.expression.ComparisonExpression; +import org.apache.phoenix.expression.DivideExpression; +import org.apache.phoenix.expression.InListExpression; +import org.apache.phoenix.expression.IsNullExpression; +import org.apache.phoenix.expression.KeyValueColumnExpression; +import org.apache.phoenix.expression.LikeExpression; +import org.apache.phoenix.expression.LiteralExpression; +import org.apache.phoenix.expression.ModulusExpression; +import org.apache.phoenix.expression.MultiplyExpression; +import org.apache.phoenix.expression.NotExpression; +import org.apache.phoenix.expression.OrExpression; +import org.apache.phoenix.expression.ProjectedColumnExpression; +import org.apache.phoenix.expression.RowKeyColumnExpression; +import org.apache.phoenix.expression.RowValueConstructorExpression; +import org.apache.phoenix.expression.StringConcatExpression; +import org.apache.phoenix.expression.SubtractExpression; +import org.apache.phoenix.expression.function.ArrayAnyComparisonExpression; +import org.apache.phoenix.expression.function.ArrayElemRefExpression; +import org.apache.phoenix.expression.function.ScalarFunction; +import org.apache.phoenix.expression.function.SingleAggregateFunction; + +public class StatelessTraverseNoExpressionVisitor<E> extends TraverseNoExpressionVisitor<E> { + + @Override + public E visitLeave(AndExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(OrExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(ScalarFunction node, List<E> l) { + return null; + } + + @Override + public E visitLeave(ComparisonExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(LikeExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(SingleAggregateFunction node, List<E> l) { + return null; + } + + @Override + public E visitLeave(CaseExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(NotExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(IsNullExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(InListExpression node, List<E> l) { + return null; + } + + @Override + public E visit(LiteralExpression node) { + return null; + } + + @Override + public E visit(RowKeyColumnExpression node) { + return null; + } + + @Override + public E visit(KeyValueColumnExpression node) { + return null; + } + + @Override + public E visit(ProjectedColumnExpression node) { + return null; + } + + @Override + public E visitLeave(AddExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(SubtractExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(MultiplyExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(DivideExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(StringConcatExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(RowValueConstructorExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(CoerceExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(ArrayConstructorExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(ModulusExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(ArrayAnyComparisonExpression node, List<E> l) { + return null; + } + + @Override + public E visitLeave(ArrayElemRefExpression node, List<E> l) { + return null; + } + + @Override + public E visit(SequenceValueExpression node) { + return null; + } + +} http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/TraverseAllExpressionVisitor.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/TraverseAllExpressionVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/TraverseAllExpressionVisitor.java index c770b80..126be8d 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/TraverseAllExpressionVisitor.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/TraverseAllExpressionVisitor.java @@ -17,14 +17,16 @@ */ package org.apache.phoenix.expression.visitor; -import java.util.*; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; import org.apache.phoenix.expression.Expression; -public class TraverseAllExpressionVisitor<E> extends BaseExpressionVisitor<E> { +public abstract class TraverseAllExpressionVisitor<E> extends BaseExpressionVisitor<E> { @Override public Iterator<Expression> defaultIterator(Expression node) { http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/TraverseNoExpressionVisitor.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/TraverseNoExpressionVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/TraverseNoExpressionVisitor.java index 193d98d..4d488ef 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/TraverseNoExpressionVisitor.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/visitor/TraverseNoExpressionVisitor.java @@ -19,11 +19,11 @@ package org.apache.phoenix.expression.visitor; import java.util.Iterator; +import org.apache.phoenix.expression.Expression; import com.google.common.collect.Iterators; -import org.apache.phoenix.expression.Expression; -public class TraverseNoExpressionVisitor<E> extends BaseExpressionVisitor<E> { +public abstract class TraverseNoExpressionVisitor<E> extends BaseExpressionVisitor<E> { @Override public Iterator<Expression> defaultIterator(Expression node) { http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/main/java/org/apache/phoenix/filter/MultiKeyValueComparisonFilter.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/filter/MultiKeyValueComparisonFilter.java b/phoenix-core/src/main/java/org/apache/phoenix/filter/MultiKeyValueComparisonFilter.java index 7df3b27..1cb2255 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/filter/MultiKeyValueComparisonFilter.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/filter/MultiKeyValueComparisonFilter.java @@ -30,7 +30,8 @@ import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.expression.Expression; import org.apache.phoenix.expression.KeyValueColumnExpression; -import org.apache.phoenix.expression.visitor.TraverseAllExpressionVisitor; +import org.apache.phoenix.expression.visitor.ExpressionVisitor; +import org.apache.phoenix.expression.visitor.StatelessTraverseAllExpressionVisitor; import org.apache.phoenix.schema.tuple.BaseTuple; @@ -184,7 +185,7 @@ public abstract class MultiKeyValueComparisonFilter extends BooleanExpressionFil protected void init() { cfSet = new TreeSet<byte[]>(Bytes.BYTES_COMPARATOR); - TraverseAllExpressionVisitor<Void> visitor = new TraverseAllExpressionVisitor<Void>() { + ExpressionVisitor<Void> visitor = new StatelessTraverseAllExpressionVisitor<Void>() { @Override public Void visit(KeyValueColumnExpression expression) { inputTuple.addColumn(expression.getColumnFamily(), expression.getColumnName()); http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/main/java/org/apache/phoenix/filter/SingleKeyValueComparisonFilter.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/filter/SingleKeyValueComparisonFilter.java b/phoenix-core/src/main/java/org/apache/phoenix/filter/SingleKeyValueComparisonFilter.java index 16c87ce..c7ead67 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/filter/SingleKeyValueComparisonFilter.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/filter/SingleKeyValueComparisonFilter.java @@ -25,6 +25,7 @@ import org.apache.hadoop.hbase.KeyValueUtil; import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.expression.Expression; import org.apache.phoenix.expression.KeyValueColumnExpression; +import org.apache.phoenix.expression.visitor.StatelessTraverseAllExpressionVisitor; import org.apache.phoenix.expression.visitor.TraverseAllExpressionVisitor; import org.apache.phoenix.schema.tuple.SingleKeyValueTuple; @@ -56,7 +57,7 @@ public abstract class SingleKeyValueComparisonFilter extends BooleanExpressionFi protected abstract int compare(byte[] cfBuf, int cfOffset, int cfLength, byte[] cqBuf, int cqOffset, int cqLength); private void init() { - TraverseAllExpressionVisitor<Void> visitor = new TraverseAllExpressionVisitor<Void>() { + TraverseAllExpressionVisitor<Void> visitor = new StatelessTraverseAllExpressionVisitor<Void>() { @Override public Void visit(KeyValueColumnExpression expression) { cf = expression.getColumnFamily(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/test/java/org/apache/phoenix/arithmetic/ArithmeticOperationTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/arithmetic/ArithmeticOperationTest.java b/phoenix-core/src/test/java/org/apache/phoenix/arithmetic/ArithmeticOperationTest.java deleted file mode 100644 index c0b0c20..0000000 --- a/phoenix-core/src/test/java/org/apache/phoenix/arithmetic/ArithmeticOperationTest.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * 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.arithmetic; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.math.BigDecimal; -import java.util.Arrays; -import java.util.List; - -import org.apache.hadoop.hbase.io.ImmutableBytesWritable; -import org.apache.phoenix.exception.ValueTypeIncompatibleException; -import org.apache.phoenix.expression.DecimalAddExpression; -import org.apache.phoenix.expression.DecimalDivideExpression; -import org.apache.phoenix.expression.DecimalMultiplyExpression; -import org.apache.phoenix.expression.DecimalSubtractExpression; -import org.apache.phoenix.expression.Expression; -import org.apache.phoenix.expression.LiteralExpression; -import org.apache.phoenix.schema.types.PDecimal; -import org.apache.phoenix.schema.types.PInteger; -import org.apache.phoenix.schema.types.PDataType; -import org.junit.Test; - - -public class ArithmeticOperationTest { - - // Addition - // result scale should be: max(ls, rs) - // result precision should be: max(lp - ls, rp - rs) + 1 + max(ls, rs) - @Test - public void testDecimalAddition() throws Exception { - LiteralExpression op1, op2, op3; - List<Expression> children; - ImmutableBytesWritable ptr; - DecimalAddExpression e; - boolean evaluated; - - op1 = LiteralExpression.newConstant(new BigDecimal("1234567890123456789012345678901"), PDecimal.INSTANCE, 31, 0); - op2 = LiteralExpression.newConstant(new BigDecimal("12345"), PDecimal.INSTANCE, 5, 0); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalAddExpression(children); - ptr = new ImmutableBytesWritable(); - evaluated = e.evaluate(null, ptr); - assertTrue(evaluated); - assertEqualValue(PDecimal.INSTANCE, new BigDecimal("1234567890123456789012345691246"), ptr); - - op1 = LiteralExpression.newConstant(new BigDecimal("12345"), PDecimal.INSTANCE, 5, 0); - op2 = LiteralExpression.newConstant(new BigDecimal("123.45"), PDecimal.INSTANCE, 5, 2); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalAddExpression(children); - ptr = new ImmutableBytesWritable(); - evaluated = e.evaluate(null, ptr); - assertTrue(evaluated); - assertEqualValue(PDecimal.INSTANCE, new BigDecimal("12468.45"), ptr); - - // Exceeds precision. - op1 = LiteralExpression.newConstant(new BigDecimal("99999999999999999999999999999999999999"), PDecimal.INSTANCE, 38, 0); - op2 = LiteralExpression.newConstant(new BigDecimal("123"), PDecimal.INSTANCE, 3, 0); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalAddExpression(children); - ptr = new ImmutableBytesWritable(); - try { - evaluated = e.evaluate(null, ptr); - fail("Evaluation should have failed"); - } catch (ValueTypeIncompatibleException ex) { - } - - // Pass since we roll out imposing precisioin and scale. - op1 = LiteralExpression.newConstant(new BigDecimal("99999999999999999999999999999999999999"), PDecimal.INSTANCE, 38, 0); - op2 = LiteralExpression.newConstant(new BigDecimal("123"), PDecimal.INSTANCE, 3, 0); - op3 = LiteralExpression.newConstant(new BigDecimal("-123"), PDecimal.INSTANCE, 3, 0); - children = Arrays.<Expression>asList(op1, op2, op3); - e = new DecimalAddExpression(children); - ptr = new ImmutableBytesWritable(); - evaluated = e.evaluate(null, ptr); - assertTrue(evaluated); - assertEqualValue(PDecimal.INSTANCE, new BigDecimal("99999999999999999999999999999999999999"), ptr); - - // Exceeds scale. - op1 = LiteralExpression.newConstant(new BigDecimal("12345678901234567890123456789012345678"), PDecimal.INSTANCE, 38, 0); - op2 = LiteralExpression.newConstant(new BigDecimal("123.45"), PDecimal.INSTANCE, 5, 2); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalAddExpression(children); - ptr = new ImmutableBytesWritable(); - try { - evaluated = e.evaluate(null, ptr); - fail("Evaluation should have failed"); - } catch (ValueTypeIncompatibleException ex) { - } - - // Decimal with no precision and scale. - op1 = LiteralExpression.newConstant(new BigDecimal("9999.1"), PDecimal.INSTANCE); - op2 = LiteralExpression.newConstant(new BigDecimal("1.1111"), PDecimal.INSTANCE, 5, 4); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalAddExpression(children); - ptr = new ImmutableBytesWritable(); - evaluated = e.evaluate(null, ptr); - assertTrue(evaluated); - assertEqualValue(PDecimal.INSTANCE, new BigDecimal("10000.2111"), ptr); - } - - @Test - public void testIntPlusDecimal() throws Exception { - LiteralExpression op1, op2; - List<Expression> children; - ImmutableBytesWritable ptr; - DecimalAddExpression e; - boolean evaluated; - - op1 = LiteralExpression.newConstant(new BigDecimal("1234.111"), PDecimal.INSTANCE); - assertNull(op1.getScale()); - op2 = LiteralExpression.newConstant(1, PInteger.INSTANCE); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalAddExpression(children); - ptr = new ImmutableBytesWritable(); - evaluated = e.evaluate(null, ptr); - assertTrue(evaluated); - assertEqualValue(PDecimal.INSTANCE, new BigDecimal("1235.111"), ptr); - } - - // Subtraction - // result scale should be: max(ls, rs) - // result precision should be: max(lp - ls, rp - rs) + 1 + max(ls, rs) - @Test - public void testDecimalSubtraction() throws Exception { - LiteralExpression op1, op2, op3; - List<Expression> children; - ImmutableBytesWritable ptr; - DecimalSubtractExpression e; - boolean evaluated; - - op1 = LiteralExpression.newConstant(new BigDecimal("1234567890123456789012345678901"), PDecimal.INSTANCE, 31, 0); - op2 = LiteralExpression.newConstant(new BigDecimal("12345"), PDecimal.INSTANCE, 5, 0); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalSubtractExpression(children); - ptr = new ImmutableBytesWritable(); - evaluated = e.evaluate(null, ptr); - assertTrue(evaluated); - assertEqualValue(PDecimal.INSTANCE, new BigDecimal("1234567890123456789012345666556"), ptr); - - op1 = LiteralExpression.newConstant(new BigDecimal("12345"), PDecimal.INSTANCE, 5, 0); - op2 = LiteralExpression.newConstant(new BigDecimal("123.45"), PDecimal.INSTANCE, 5, 2); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalSubtractExpression(children); - ptr = new ImmutableBytesWritable(); - evaluated = e.evaluate(null, ptr); - assertTrue(evaluated); - assertEqualValue(PDecimal.INSTANCE, new BigDecimal("12221.55"), ptr); - - // Excceds precision - op1 = LiteralExpression.newConstant(new BigDecimal("99999999999999999999999999999999999999"), PDecimal.INSTANCE, 38, 0); - op2 = LiteralExpression.newConstant(new BigDecimal("-123"), PDecimal.INSTANCE, 3, 0); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalSubtractExpression(children); - ptr = new ImmutableBytesWritable(); - try { - evaluated = e.evaluate(null, ptr); - fail("Evaluation should have failed"); - } catch (ValueTypeIncompatibleException ex) { - } - - // Pass since we roll up precision and scale imposing. - op1 = LiteralExpression.newConstant(new BigDecimal("99999999999999999999999999999999999999"), PDecimal.INSTANCE, 38, 0); - op2 = LiteralExpression.newConstant(new BigDecimal("-123"), PDecimal.INSTANCE, 3, 0); - op3 = LiteralExpression.newConstant(new BigDecimal("123"), PDecimal.INSTANCE, 3, 0); - children = Arrays.<Expression>asList(op1, op2, op3); - e = new DecimalSubtractExpression(children); - ptr = new ImmutableBytesWritable(); - evaluated = e.evaluate(null, ptr); - assertTrue(evaluated); - assertEqualValue(PDecimal.INSTANCE, new BigDecimal("99999999999999999999999999999999999999"), ptr); - - // Exceeds scale. - op1 = LiteralExpression.newConstant(new BigDecimal("12345678901234567890123456789012345678"), PDecimal.INSTANCE, 38, 0); - op2 = LiteralExpression.newConstant(new BigDecimal("123.45"), PDecimal.INSTANCE, 5, 2); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalSubtractExpression(children); - ptr = new ImmutableBytesWritable(); - try { - evaluated = e.evaluate(null, ptr); - fail("Evaluation should have failed"); - } catch (ValueTypeIncompatibleException ex) { - } - - // Decimal with no precision and scale. - op1 = LiteralExpression.newConstant(new BigDecimal("1111.1"), PDecimal.INSTANCE); - op2 = LiteralExpression.newConstant(new BigDecimal("1.1111"), PDecimal.INSTANCE, 5, 4); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalSubtractExpression(children); - ptr = new ImmutableBytesWritable(); - evaluated = e.evaluate(null, ptr); - assertTrue(evaluated); - assertEqualValue(PDecimal.INSTANCE, new BigDecimal("1109.9889"), ptr); - } - - // Multiplication - // result scale should be: ls + rs - // result precision should be: lp + rp - @Test - public void testDecimalMultiplication() throws Exception { - LiteralExpression op1, op2; - List<Expression> children; - ImmutableBytesWritable ptr; - DecimalMultiplyExpression e; - boolean evaluated; - - op1 = LiteralExpression.newConstant(new BigDecimal("12345"), PDecimal.INSTANCE, 5, 0); - op2 = LiteralExpression.newConstant(new BigDecimal("123.45"), PDecimal.INSTANCE, 5, 2); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalMultiplyExpression(children); - ptr = new ImmutableBytesWritable(); - evaluated = e.evaluate(null, ptr); - assertTrue(evaluated); - assertEqualValue(PDecimal.INSTANCE, new BigDecimal("1523990.25"), ptr); - - // Value too big, exceeds precision. - op1 = LiteralExpression.newConstant(new BigDecimal("12345678901234567890123456789012345678"), PDecimal.INSTANCE, 38, 0); - op2 = LiteralExpression.newConstant(new BigDecimal("12345"), PDecimal.INSTANCE, 5, 0); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalMultiplyExpression(children); - ptr = new ImmutableBytesWritable(); - try { - evaluated = e.evaluate(null, ptr); - fail("Evaluation should have failed"); - } catch (ValueTypeIncompatibleException ex) { - } - - // Values exceeds scale. - op1 = LiteralExpression.newConstant(new BigDecimal("12345678901234567890123456789012345678"), PDecimal.INSTANCE, 38, 0); - op2 = LiteralExpression.newConstant(new BigDecimal("1.45"), PDecimal.INSTANCE, 3, 2); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalMultiplyExpression(children); - ptr = new ImmutableBytesWritable(); - try { - evaluated = e.evaluate(null, ptr); - fail("Evaluation should have failed"); - } catch (ValueTypeIncompatibleException ex) { - } - - // Decimal with no precision and scale. - op1 = LiteralExpression.newConstant(new BigDecimal("1111.1"), PDecimal.INSTANCE); - assertNull(op1.getScale()); - op2 = LiteralExpression.newConstant(new BigDecimal("1.1111"), PDecimal.INSTANCE, 5, 4); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalMultiplyExpression(children); - ptr = new ImmutableBytesWritable(); - evaluated = e.evaluate(null, ptr); - assertTrue(evaluated); - assertEqualValue(PDecimal.INSTANCE, new BigDecimal("1234.54321"), ptr); - } - - // Division - // result scale should be: 31 - lp + ls - rs - // result precision should be: lp - ls + rp + scale - @Test - public void testDecimalDivision() throws Exception { - LiteralExpression op1, op2; - List<Expression> children; - ImmutableBytesWritable ptr; - DecimalDivideExpression e; - boolean evaluated; - - // The value should be 1234500.0000...00 because we set to scale to be 24. However, in - // PhoenixResultSet.getBigDecimal, the case to (BigDecimal) actually cause the scale to be eradicated. As - // a result, the resulting value does not have the right form. - op1 = LiteralExpression.newConstant(new BigDecimal("12345"), PDecimal.INSTANCE, 5, 0); - op2 = LiteralExpression.newConstant(new BigDecimal("0.01"), PDecimal.INSTANCE, 2, 2); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalDivideExpression(children); - ptr = new ImmutableBytesWritable(); - evaluated = e.evaluate(null, ptr); - assertTrue(evaluated); - assertEqualValue(PDecimal.INSTANCE, new BigDecimal("1.2345E+6"), ptr); - - // Exceeds precision. - op1 = LiteralExpression.newConstant(new BigDecimal("12345678901234567890123456789012345678"), PDecimal.INSTANCE, 38, 0); - op2 = LiteralExpression.newConstant(new BigDecimal("0.01"), PDecimal.INSTANCE, 2, 2); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalDivideExpression(children); - ptr = new ImmutableBytesWritable(); - try { - evaluated = e.evaluate(null, ptr); - fail("Evaluation should have failed"); - } catch (ValueTypeIncompatibleException ex) { - } - - // Decimal with no precision and scale. - op1 = LiteralExpression.newConstant(new BigDecimal("10"), PDecimal.INSTANCE); - op2 = LiteralExpression.newConstant(new BigDecimal("3"), PDecimal.INSTANCE, 5, 4); - assertEquals(Integer.valueOf(4),op2.getScale()); - children = Arrays.<Expression>asList(op1, op2); - e = new DecimalDivideExpression(children); - ptr = new ImmutableBytesWritable(); - evaluated = e.evaluate(null, ptr); - assertTrue(evaluated); - assertEqualValue(PDecimal.INSTANCE, new BigDecimal("3.3333333333333333333333333333333333333"), ptr); - } - - private static void assertEqualValue(PDataType type, Object value, ImmutableBytesWritable ptr) { - assertEquals(value, type.toObject(ptr.get())); - } -} http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/test/java/org/apache/phoenix/expression/ArithmeticOperationTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArithmeticOperationTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArithmeticOperationTest.java new file mode 100644 index 0000000..f0b983b --- /dev/null +++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArithmeticOperationTest.java @@ -0,0 +1,273 @@ +/* + * 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.List; + +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; +import org.apache.phoenix.exception.ValueTypeIncompatibleException; +import org.apache.phoenix.expression.DecimalAddExpression; +import org.apache.phoenix.expression.DecimalDivideExpression; +import org.apache.phoenix.expression.DecimalMultiplyExpression; +import org.apache.phoenix.expression.DecimalSubtractExpression; +import org.apache.phoenix.expression.Expression; +import org.apache.phoenix.expression.LiteralExpression; +import org.apache.phoenix.expression.visitor.CloneExpressionVisitor; +import org.apache.phoenix.schema.types.PDataType; +import org.apache.phoenix.schema.types.PDecimal; +import org.apache.phoenix.schema.types.PInteger; +import org.junit.Test; + + +public class ArithmeticOperationTest { + + // Addition + // result scale should be: max(ls, rs) + // result precision should be: max(lp - ls, rp - rs) + 1 + max(ls, rs) + @Test + public void testDecimalAddition() throws Exception { + LiteralExpression op1, op2, op3; + List<Expression> children; + DecimalAddExpression e; + + op1 = LiteralExpression.newConstant(new BigDecimal("1234567890123456789012345678901"), PDecimal.INSTANCE, 31, 0); + op2 = LiteralExpression.newConstant(new BigDecimal("12345"), PDecimal.INSTANCE, 5, 0); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalAddExpression(children); + assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("1234567890123456789012345691246")); + + op1 = LiteralExpression.newConstant(new BigDecimal("12345"), PDecimal.INSTANCE, 5, 0); + op2 = LiteralExpression.newConstant(new BigDecimal("123.45"), PDecimal.INSTANCE, 5, 2); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalAddExpression(children); + assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("12468.45")); + + // Exceeds precision. + op1 = LiteralExpression.newConstant(new BigDecimal("99999999999999999999999999999999999999"), PDecimal.INSTANCE, 38, 0); + op2 = LiteralExpression.newConstant(new BigDecimal("123"), PDecimal.INSTANCE, 3, 0); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalAddExpression(children); + try { + e.evaluate(null, new ImmutableBytesWritable()); + fail("Evaluation should have failed"); + } catch (ValueTypeIncompatibleException ex) { + } + + // Pass since we roll out imposing precisioin and scale. + op1 = LiteralExpression.newConstant(new BigDecimal("99999999999999999999999999999999999999"), PDecimal.INSTANCE, 38, 0); + op2 = LiteralExpression.newConstant(new BigDecimal("123"), PDecimal.INSTANCE, 3, 0); + op3 = LiteralExpression.newConstant(new BigDecimal("-123"), PDecimal.INSTANCE, 3, 0); + children = Arrays.<Expression>asList(op1, op2, op3); + e = new DecimalAddExpression(children); + assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("99999999999999999999999999999999999999")); + + // Exceeds scale. + op1 = LiteralExpression.newConstant(new BigDecimal("12345678901234567890123456789012345678"), PDecimal.INSTANCE, 38, 0); + op2 = LiteralExpression.newConstant(new BigDecimal("123.45"), PDecimal.INSTANCE, 5, 2); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalAddExpression(children); + try { + e.evaluate(null, new ImmutableBytesWritable()); + fail("Evaluation should have failed"); + } catch (ValueTypeIncompatibleException ex) { + } + + // Decimal with no precision and scale. + op1 = LiteralExpression.newConstant(new BigDecimal("9999.1"), PDecimal.INSTANCE); + op2 = LiteralExpression.newConstant(new BigDecimal("1.1111"), PDecimal.INSTANCE, 5, 4); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalAddExpression(children); + assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("10000.2111")); + } + + @Test + public void testIntPlusDecimal() throws Exception { + LiteralExpression op1, op2; + List<Expression> children; + DecimalAddExpression e; + + op1 = LiteralExpression.newConstant(new BigDecimal("1234.111"), PDecimal.INSTANCE); + assertNull(op1.getScale()); + op2 = LiteralExpression.newConstant(1, PInteger.INSTANCE); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalAddExpression(children); + assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("1235.111")); + } + + // Subtraction + // result scale should be: max(ls, rs) + // result precision should be: max(lp - ls, rp - rs) + 1 + max(ls, rs) + @Test + public void testDecimalSubtraction() throws Exception { + LiteralExpression op1, op2, op3; + List<Expression> children; + DecimalSubtractExpression e; + + op1 = LiteralExpression.newConstant(new BigDecimal("1234567890123456789012345678901"), PDecimal.INSTANCE, 31, 0); + op2 = LiteralExpression.newConstant(new BigDecimal("12345"), PDecimal.INSTANCE, 5, 0); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalSubtractExpression(children); + assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("1234567890123456789012345666556")); + + op1 = LiteralExpression.newConstant(new BigDecimal("12345"), PDecimal.INSTANCE, 5, 0); + op2 = LiteralExpression.newConstant(new BigDecimal("123.45"), PDecimal.INSTANCE, 5, 2); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalSubtractExpression(children); + assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("12221.55")); + + // Excceds precision + op1 = LiteralExpression.newConstant(new BigDecimal("99999999999999999999999999999999999999"), PDecimal.INSTANCE, 38, 0); + op2 = LiteralExpression.newConstant(new BigDecimal("-123"), PDecimal.INSTANCE, 3, 0); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalSubtractExpression(children); + try { + e.evaluate(null, new ImmutableBytesWritable()); + fail("Evaluation should have failed"); + } catch (ValueTypeIncompatibleException ex) { + } + + // Pass since we roll up precision and scale imposing. + op1 = LiteralExpression.newConstant(new BigDecimal("99999999999999999999999999999999999999"), PDecimal.INSTANCE, 38, 0); + op2 = LiteralExpression.newConstant(new BigDecimal("-123"), PDecimal.INSTANCE, 3, 0); + op3 = LiteralExpression.newConstant(new BigDecimal("123"), PDecimal.INSTANCE, 3, 0); + children = Arrays.<Expression>asList(op1, op2, op3); + e = new DecimalSubtractExpression(children); + assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("99999999999999999999999999999999999999")); + + // Exceeds scale. + op1 = LiteralExpression.newConstant(new BigDecimal("12345678901234567890123456789012345678"), PDecimal.INSTANCE, 38, 0); + op2 = LiteralExpression.newConstant(new BigDecimal("123.45"), PDecimal.INSTANCE, 5, 2); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalSubtractExpression(children); + try { + e.evaluate(null, new ImmutableBytesWritable()); + fail("Evaluation should have failed"); + } catch (ValueTypeIncompatibleException ex) { + } + + // Decimal with no precision and scale. + op1 = LiteralExpression.newConstant(new BigDecimal("1111.1"), PDecimal.INSTANCE); + op2 = LiteralExpression.newConstant(new BigDecimal("1.1111"), PDecimal.INSTANCE, 5, 4); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalSubtractExpression(children); + assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("1109.9889")); + } + + // Multiplication + // result scale should be: ls + rs + // result precision should be: lp + rp + @Test + public void testDecimalMultiplication() throws Exception { + LiteralExpression op1, op2; + List<Expression> children; + DecimalMultiplyExpression e; + + op1 = LiteralExpression.newConstant(new BigDecimal("12345"), PDecimal.INSTANCE, 5, 0); + op2 = LiteralExpression.newConstant(new BigDecimal("123.45"), PDecimal.INSTANCE, 5, 2); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalMultiplyExpression(children); + assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("1523990.25")); + + // Value too big, exceeds precision. + op1 = LiteralExpression.newConstant(new BigDecimal("12345678901234567890123456789012345678"), PDecimal.INSTANCE, 38, 0); + op2 = LiteralExpression.newConstant(new BigDecimal("12345"), PDecimal.INSTANCE, 5, 0); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalMultiplyExpression(children); + try { + e.evaluate(null, new ImmutableBytesWritable()); + fail("Evaluation should have failed"); + } catch (ValueTypeIncompatibleException ex) { + } + + // Values exceeds scale. + op1 = LiteralExpression.newConstant(new BigDecimal("12345678901234567890123456789012345678"), PDecimal.INSTANCE, 38, 0); + op2 = LiteralExpression.newConstant(new BigDecimal("1.45"), PDecimal.INSTANCE, 3, 2); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalMultiplyExpression(children); + try { + e.evaluate(null, new ImmutableBytesWritable()); + fail("Evaluation should have failed"); + } catch (ValueTypeIncompatibleException ex) { + } + + // Decimal with no precision and scale. + op1 = LiteralExpression.newConstant(new BigDecimal("1111.1"), PDecimal.INSTANCE); + assertNull(op1.getScale()); + op2 = LiteralExpression.newConstant(new BigDecimal("1.1111"), PDecimal.INSTANCE, 5, 4); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalMultiplyExpression(children); + assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("1234.54321")); + } + + // Division + // result scale should be: 31 - lp + ls - rs + // result precision should be: lp - ls + rp + scale + @Test + public void testDecimalDivision() throws Exception { + LiteralExpression op1, op2; + List<Expression> children; + DecimalDivideExpression e; + + // The value should be 1234500.0000...00 because we set to scale to be 24. However, in + // PhoenixResultSet.getBigDecimal, the case to (BigDecimal) actually cause the scale to be eradicated. As + // a result, the resulting value does not have the right form. + op1 = LiteralExpression.newConstant(new BigDecimal("12345"), PDecimal.INSTANCE, 5, 0); + op2 = LiteralExpression.newConstant(new BigDecimal("0.01"), PDecimal.INSTANCE, 2, 2); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalDivideExpression(children); + assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("1.2345E+6")); + + // Exceeds precision. + op1 = LiteralExpression.newConstant(new BigDecimal("12345678901234567890123456789012345678"), PDecimal.INSTANCE, 38, 0); + op2 = LiteralExpression.newConstant(new BigDecimal("0.01"), PDecimal.INSTANCE, 2, 2); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalDivideExpression(children); + try { + e.evaluate(null, new ImmutableBytesWritable()); + fail("Evaluation should have failed"); + } catch (ValueTypeIncompatibleException ex) { + } + + // Decimal with no precision and scale. + op1 = LiteralExpression.newConstant(new BigDecimal("10"), PDecimal.INSTANCE); + op2 = LiteralExpression.newConstant(new BigDecimal("3"), PDecimal.INSTANCE, 5, 4); + assertEquals(Integer.valueOf(4),op2.getScale()); + children = Arrays.<Expression>asList(op1, op2); + e = new DecimalDivideExpression(children); + assertEqualValue(e, PDecimal.INSTANCE, new BigDecimal("3.3333333333333333333333333333333333333")); + } + + private static void assertEqualValue(Expression e, PDataType type, Object value) { + ImmutableBytesWritable ptr = new ImmutableBytesWritable(); + boolean evaluated = e.evaluate(null, ptr); + assertTrue(evaluated); + assertEquals(value, type.toObject(ptr.get())); + CloneExpressionVisitor visitor = new CloneExpressionVisitor(); + Expression clone = e.accept(visitor); + evaluated = clone.evaluate(null, ptr); + assertTrue(evaluated); + assertEquals(value, type.toObject(ptr.get())); + } +} http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/test/java/org/apache/phoenix/expression/ILikeExpressionTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/ILikeExpressionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/ILikeExpressionTest.java index 2c4af74..3033edf 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/expression/ILikeExpressionTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/ILikeExpressionTest.java @@ -32,7 +32,7 @@ public class ILikeExpressionTest { LiteralExpression v = LiteralExpression.newConstant(value); LiteralExpression p = LiteralExpression.newConstant(expression); List<Expression> children = Arrays.<Expression>asList(v,p); - LikeExpression e = new LikeExpression(children, LikeType.CASE_INSENSITIVE); + LikeExpression e = LikeExpression.create(children, LikeType.CASE_INSENSITIVE); ImmutableBytesWritable ptr = new ImmutableBytesWritable(); boolean evaluated = e.evaluate(null, ptr); Boolean result = (Boolean)e.getDataType().toObject(ptr); http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/test/java/org/apache/phoenix/expression/LikeExpressionTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/LikeExpressionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/LikeExpressionTest.java index 81b7124..27e6547 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/expression/LikeExpressionTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/LikeExpressionTest.java @@ -32,7 +32,7 @@ public class LikeExpressionTest { LiteralExpression v = LiteralExpression.newConstant(value); LiteralExpression p = LiteralExpression.newConstant(expression); List<Expression> children = Arrays.<Expression>asList(v,p); - LikeExpression e = new LikeExpression(children, LikeType.CASE_SENSITIVE); + LikeExpression e = LikeExpression.create(children, LikeType.CASE_SENSITIVE); ImmutableBytesWritable ptr = new ImmutableBytesWritable(); boolean evaluated = e.evaluate(null, ptr); Boolean result = (Boolean)e.getDataType().toObject(ptr); http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/test/java/org/apache/phoenix/expression/SortOrderExpressionTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/SortOrderExpressionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/SortOrderExpressionTest.java index 464153d..f75bb3e 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/expression/SortOrderExpressionTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/SortOrderExpressionTest.java @@ -289,16 +289,16 @@ public class SortOrderExpressionTest { private void runCompareTest(CompareOp op, boolean expectedResult, Object lhsValue, PDataType lhsDataType, Object rhsValue, PDataType rhsDataType) throws Exception { List<Expression> args = Lists.newArrayList(getLiteral(lhsValue, lhsDataType), getLiteral(rhsValue, rhsDataType)); - evaluateAndAssertResult(new ComparisonExpression(op, args), expectedResult, "lhsDataType: " + lhsDataType + " rhsDataType: " + rhsDataType); + evaluateAndAssertResult(new ComparisonExpression(args, op), expectedResult, "lhsDataType: " + lhsDataType + " rhsDataType: " + rhsDataType); args = Lists.newArrayList(getInvertedLiteral(lhsValue, lhsDataType), getLiteral(rhsValue, rhsDataType)); - evaluateAndAssertResult(new ComparisonExpression(op, args), expectedResult, "lhs (inverted) dataType: " + lhsDataType + " rhsDataType: " + rhsDataType); + evaluateAndAssertResult(new ComparisonExpression(args, op), expectedResult, "lhs (inverted) dataType: " + lhsDataType + " rhsDataType: " + rhsDataType); args = Lists.newArrayList(getLiteral(lhsValue, lhsDataType), getInvertedLiteral(rhsValue, rhsDataType)); - evaluateAndAssertResult(new ComparisonExpression(op, args), expectedResult, "lhsDataType: " + lhsDataType + " rhs (inverted) dataType: " + rhsDataType); + evaluateAndAssertResult(new ComparisonExpression(args, op), expectedResult, "lhsDataType: " + lhsDataType + " rhs (inverted) dataType: " + rhsDataType); args = Lists.newArrayList(getInvertedLiteral(lhsValue, lhsDataType), getInvertedLiteral(rhsValue, rhsDataType)); - evaluateAndAssertResult(new ComparisonExpression(op, args), expectedResult, "lhs (inverted) dataType: " + lhsDataType + " rhs (inverted) dataType: " + rhsDataType); + evaluateAndAssertResult(new ComparisonExpression(args, op), expectedResult, "lhs (inverted) dataType: " + lhsDataType + " rhs (inverted) dataType: " + rhsDataType); } private void evaluateAndAssertResult(Expression expression, Object expectedResult) { http://git-wip-us.apache.org/repos/asf/phoenix/blob/7a2944a0/phoenix-core/src/test/java/org/apache/phoenix/expression/function/ExternalSqlTypeIdFunctionTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/function/ExternalSqlTypeIdFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/function/ExternalSqlTypeIdFunctionTest.java index 7f9cc9b..e9dff40 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/expression/function/ExternalSqlTypeIdFunctionTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/function/ExternalSqlTypeIdFunctionTest.java @@ -17,7 +17,13 @@ */ package org.apache.phoenix.expression.function; -import com.google.common.collect.Lists; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.sql.SQLException; +import java.sql.Types; +import java.util.List; + import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.phoenix.expression.Expression; import org.apache.phoenix.expression.LiteralExpression; @@ -25,11 +31,7 @@ import org.apache.phoenix.schema.types.PInteger; import org.apache.phoenix.schema.types.PIntegerArray; import org.junit.Test; -import java.sql.SQLException; -import java.sql.Types; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import com.google.common.collect.Lists; public class ExternalSqlTypeIdFunctionTest { @@ -53,6 +55,17 @@ public class ExternalSqlTypeIdFunctionTest { assertEquals(Types.ARRAY, returnValue); } + @Test + public void testClone() throws SQLException { + Expression inputArg = LiteralExpression.newConstant( + PIntegerArray.INSTANCE.getSqlType(), PInteger.INSTANCE); + List<Expression> args = Lists.newArrayList(inputArg); + ExternalSqlTypeIdFunction externalIdFunction = + new ExternalSqlTypeIdFunction(args); + ScalarFunction clone = externalIdFunction.clone(args); + assertEquals(externalIdFunction, clone); + } + private Object executeFunction(Expression inputArg) throws SQLException { ExternalSqlTypeIdFunction externalIdFunction = new ExternalSqlTypeIdFunction(Lists.newArrayList(inputArg));
