http://git-wip-us.apache.org/repos/asf/phoenix/blob/5a988cb8/phoenix-core/src/main/java/org/apache/phoenix/expression/ModulusExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ModulusExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ModulusExpression.java index bac52fc..b6b669f 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/ModulusExpression.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ModulusExpression.java @@ -17,13 +17,13 @@ */ package org.apache.phoenix.expression; -import java.sql.SQLException; import java.util.List; import org.apache.hadoop.hbase.io.ImmutableBytesWritable; -import org.apache.phoenix.schema.types.PLong; -import org.apache.phoenix.schema.types.PDataType; +import org.apache.phoenix.expression.visitor.ExpressionVisitor; import org.apache.phoenix.schema.tuple.Tuple; +import org.apache.phoenix.schema.types.PDataType; +import org.apache.phoenix.schema.types.PLong; /** @@ -39,7 +39,7 @@ public class ModulusExpression extends ArithmeticExpression { public ModulusExpression() { } - public ModulusExpression(List<Expression> children) throws SQLException { + public ModulusExpression(List<Expression> children) { super(children); } @@ -93,4 +93,18 @@ public class ModulusExpression extends ArithmeticExpression { return " % "; } + @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 ArithmeticExpression clone(List<Expression> children) { + return new ModulusExpression(children); + } }
http://git-wip-us.apache.org/repos/asf/phoenix/blob/5a988cb8/phoenix-core/src/main/java/org/apache/phoenix/expression/NotExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/NotExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/NotExpression.java index c2f214e..4bbdcc4 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/NotExpression.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/NotExpression.java @@ -22,10 +22,10 @@ import java.util.List; import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.phoenix.expression.visitor.ExpressionVisitor; -import org.apache.phoenix.schema.types.PBoolean; -import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.schema.TypeMismatchException; import org.apache.phoenix.schema.tuple.Tuple; +import org.apache.phoenix.schema.types.PBoolean; +import org.apache.phoenix.schema.types.PDataType; /** @@ -58,6 +58,10 @@ public class NotExpression extends BaseSingleExpression { super(expression); } + public NotExpression(List<Expression> l) { + super(l); + } + @Override public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { if (!getChild().evaluate(tuple, ptr)) { http://git-wip-us.apache.org/repos/asf/phoenix/blob/5a988cb8/phoenix-core/src/main/java/org/apache/phoenix/expression/RowKeyExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/RowKeyExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/RowKeyExpression.java index d9f6b90..97001e8 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/RowKeyExpression.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/RowKeyExpression.java @@ -19,10 +19,10 @@ package org.apache.phoenix.expression; import org.apache.hadoop.hbase.io.ImmutableBytesWritable; - +import org.apache.phoenix.expression.visitor.ExpressionVisitor; +import org.apache.phoenix.schema.tuple.Tuple; import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.schema.types.PVarbinary; -import org.apache.phoenix.schema.tuple.Tuple; public class RowKeyExpression extends BaseTerminalExpression { public static final RowKeyExpression INSTANCE = new RowKeyExpression(); @@ -41,4 +41,10 @@ public class RowKeyExpression extends BaseTerminalExpression { return PVarbinary.INSTANCE; } + @Override + public <T> T accept(ExpressionVisitor<T> visitor) { + // TODO Auto-generated method stub + return null; + } + } http://git-wip-us.apache.org/repos/asf/phoenix/blob/5a988cb8/phoenix-core/src/main/java/org/apache/phoenix/expression/RowValueConstructorExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/RowValueConstructorExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/RowValueConstructorExpression.java index 546962e..940f909 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/RowValueConstructorExpression.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/RowValueConstructorExpression.java @@ -33,9 +33,9 @@ import java.util.List; import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.phoenix.expression.visitor.ExpressionVisitor; import org.apache.phoenix.query.QueryConstants; +import org.apache.phoenix.schema.tuple.Tuple; import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.schema.types.PVarbinary; -import org.apache.phoenix.schema.tuple.Tuple; import org.apache.phoenix.util.ByteUtil; import org.apache.phoenix.util.SchemaUtil; import org.apache.phoenix.util.TrustedByteArrayOutputStream; @@ -57,6 +57,10 @@ public class RowValueConstructorExpression extends BaseCompoundExpression { init(isConstant); } + public RowValueConstructorExpression clone(List<Expression> children) { + return new RowValueConstructorExpression(children, literalExprPtr != null); + } + public int getEstimatedSize() { return estimatedByteSize; } http://git-wip-us.apache.org/repos/asf/phoenix/blob/5a988cb8/phoenix-core/src/main/java/org/apache/phoenix/expression/TimestampAddExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/TimestampAddExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/TimestampAddExpression.java index 892a38c..f4c629b 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/TimestampAddExpression.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/TimestampAddExpression.java @@ -23,15 +23,14 @@ import java.sql.Timestamp; import java.util.List; import org.apache.hadoop.hbase.io.ImmutableBytesWritable; - import org.apache.phoenix.query.QueryConstants; +import org.apache.phoenix.schema.SortOrder; +import org.apache.phoenix.schema.tuple.Tuple; +import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.schema.types.PDecimal; import org.apache.phoenix.schema.types.PDouble; import org.apache.phoenix.schema.types.PTimestamp; import org.apache.phoenix.schema.types.PUnsignedTimestamp; -import org.apache.phoenix.schema.SortOrder; -import org.apache.phoenix.schema.types.PDataType; -import org.apache.phoenix.schema.tuple.Tuple; import org.apache.phoenix.util.DateUtil; /** @@ -88,4 +87,9 @@ public class TimestampAddExpression extends AddExpression { return PTimestamp.INSTANCE; } + @Override + public ArithmeticExpression clone(List<Expression> children) { + return new TimestampAddExpression(children); + } + } http://git-wip-us.apache.org/repos/asf/phoenix/blob/5a988cb8/phoenix-core/src/main/java/org/apache/phoenix/expression/TimestampSubtractExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/TimestampSubtractExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/TimestampSubtractExpression.java index 5718c94..87d634c 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/TimestampSubtractExpression.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/TimestampSubtractExpression.java @@ -23,14 +23,13 @@ import java.sql.Timestamp; import java.util.List; import org.apache.hadoop.hbase.io.ImmutableBytesWritable; - +import org.apache.phoenix.schema.SortOrder; +import org.apache.phoenix.schema.tuple.Tuple; +import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.schema.types.PDecimal; import org.apache.phoenix.schema.types.PDouble; import org.apache.phoenix.schema.types.PTimestamp; import org.apache.phoenix.schema.types.PUnsignedTimestamp; -import org.apache.phoenix.schema.SortOrder; -import org.apache.phoenix.schema.types.PDataType; -import org.apache.phoenix.schema.tuple.Tuple; import org.apache.phoenix.util.DateUtil; /** * @@ -88,4 +87,9 @@ public class TimestampSubtractExpression extends SubtractExpression { public final PDataType getDataType() { return PTimestamp.INSTANCE; } + + @Override + public ArithmeticExpression clone(List<Expression> children) { + return new TimestampSubtractExpression(children); + } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/5a988cb8/phoenix-core/src/main/java/org/apache/phoenix/expression/aggregator/BaseAggregator.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/aggregator/BaseAggregator.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/aggregator/BaseAggregator.java index 1a8aad6..9b673bf 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/aggregator/BaseAggregator.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/aggregator/BaseAggregator.java @@ -20,6 +20,7 @@ package org.apache.phoenix.expression.aggregator; import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.phoenix.expression.BaseTerminalExpression; +import org.apache.phoenix.expression.visitor.ExpressionVisitor; import org.apache.phoenix.schema.SortOrder; import org.apache.phoenix.util.SizedUtil; @@ -56,4 +57,10 @@ public abstract class BaseAggregator extends BaseTerminalExpression implements A ca.evaluate(null, ptr); return ptr; } + + @Override + public <T> T accept(ExpressionVisitor<T> visitor) { + return null; + } + } http://git-wip-us.apache.org/repos/asf/phoenix/blob/5a988cb8/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAnyComparisonExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAnyComparisonExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAnyComparisonExpression.java index b57901b..e6702d0 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAnyComparisonExpression.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAnyComparisonExpression.java @@ -24,10 +24,11 @@ import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.expression.BaseCompoundExpression; import org.apache.phoenix.expression.ComparisonExpression; 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.PBoolean; import org.apache.phoenix.schema.types.PDataType; -import org.apache.phoenix.schema.tuple.Tuple; public class ArrayAnyComparisonExpression extends BaseCompoundExpression { public ArrayAnyComparisonExpression () { @@ -49,7 +50,7 @@ public class ArrayAnyComparisonExpression extends BaseCompoundExpression { for (int i = 0; i < length; i++) { Expression comparisonExpr = children.get(1); Expression arrayElemRef = ((ComparisonExpression)comparisonExpr).getChildren().get(1); - ((InlineArrayElemRefExpression)arrayElemRef).setIndex(i + 1); + ((ArrayElemRefExpression)arrayElemRef).setIndex(i + 1); comparisonExpr.evaluate(tuple, ptr); if (expectedReturnResult(resultFound(ptr))) { return result(); } elementAvailable = true; @@ -76,4 +77,14 @@ public class ArrayAnyComparisonExpression extends BaseCompoundExpression { public PDataType getDataType() { return PBoolean.INSTANCE; } + + @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/5a988cb8/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/5a988cb8/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FunctionExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FunctionExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FunctionExpression.java index 45c3e15..b45706a 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FunctionExpression.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FunctionExpression.java @@ -57,7 +57,7 @@ public abstract class FunctionExpression extends BaseCompoundExpression { abstract public String getName(); @Override - public final String toString() { + public String toString() { StringBuilder buf = new StringBuilder(getName() + "("); if (children.size()==0) return buf.append(")").toString(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/5a988cb8/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/5a988cb8/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 new file mode 100644 index 0000000..535a127 --- /dev/null +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RandomFunction.java @@ -0,0 +1,133 @@ +package org.apache.phoenix.expression.function; + +import java.io.DataInput; +import java.io.IOException; +import java.util.List; +import java.util.Random; + +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; +import org.apache.phoenix.expression.Determinism; +import org.apache.phoenix.expression.Expression; +import org.apache.phoenix.expression.LiteralExpression; +import org.apache.phoenix.parse.FunctionParseNode.Argument; +import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction; +import org.apache.phoenix.schema.tuple.Tuple; +import org.apache.phoenix.schema.types.PDataType; +import org.apache.phoenix.schema.types.PDouble; +import org.apache.phoenix.schema.types.PLong; + +/** + * Random function that produces a unique value upon each invocation unless a seed is provided. + * If a seed is provided the returned value is identical across each invocation for a single row, but different across multiple rows. + * The seed must be a constant. + * <p> + * Example: + * <pre> + * 0: jdbc:phoenix:localhost> select rand(), rand(), rand(1), rand(2), rand(1) from t; + * +----------------------------+----------------------------+----------------------------+----------------------------+-----------------------+ + * | RAND() | RAND() | RAND(1) | RAND(2) | RAND(1) | + * +----------------------------+----------------------------+----------------------------+----------------------------+-----------------------+ + * | 0.18927325291276054 | 0.19335253869230284 | 0.7308781907032909 | 0.7311469360199058 | 0.7308781907032909 | + * | 0.08156917775368278 | 0.10178318739559034 | 0.41008081149220166 | 0.9014476240300544 | 0.41008081149220166 | + * +----------------------------+----------------------------+----------------------------+----------------------------+-----------------------+ + * 2 rows selected (0.096 seconds) + * 0: jdbc:phoenix:localhost> select rand(), rand(), rand(1), rand(2), rand(1) from t; + * +----------------------------+----------------------------+----------------------------+----------------------------+-----------------------+ + * | RAND() | RAND() | RAND(1) | RAND(2) | RAND(1) | + * +----------------------------+----------------------------+----------------------------+----------------------------+-----------------------+ + * | 0.6452639556507597 | 0.8167638693890659 | 0.7308781907032909 | 0.7311469360199058 | 0.7308781907032909 | + * | 0.8084646053276106 | 0.6969504742211767 | 0.41008081149220166 | 0.9014476240300544 | 0.41008081149220166 | + * +----------------------------+----------------------------+----------------------------+----------------------------+-----------------------+ + * 2 rows selected (0.098 seconds) + * </pre> + */ +@BuiltInFunction(name = RandomFunction.NAME, args = {@Argument(allowedTypes={PLong.class},defaultValue="null",isConstant=true)}) +public class RandomFunction extends ScalarFunction { + public static final String NAME = "RAND"; + private Random random; + private boolean hasSeed; + private Double current; + + public RandomFunction() { + } + + public RandomFunction(List<Expression> children) { + super(children); + init(); + } + + private void init() { + Number seed = (Number)((LiteralExpression)children.get(0)).getValue(); + random = seed == null ? new Random() : new Random(seed.longValue()); + hasSeed = seed != null; + current = null; + } + + @Override + public void readFields(DataInput input) throws IOException { + super.readFields(input); + init(); + } + + @Override + public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { + if (current == null) { + current = random.nextDouble(); + } + ptr.set(PDouble.INSTANCE.toBytes(current)); + return true; + } + + // produce a new random value for each row + @Override + public void reset() { + super.reset(); + current = null; + } + + @Override + public PDataType<?> getDataType() { + return PDouble.INSTANCE; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public Determinism getDeterminism() { + return hasSeed ? Determinism.PER_ROW : Determinism.PER_INVOCATION; + } + + @Override + public boolean isStateless() { + return true; + } + + // take the random object onto account + @Override + public int hashCode() { + int hashCode = super.hashCode(); + return hasSeed ? hashCode : (hashCode + random.hashCode()); + } + + // 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) && (hasSeed || random.equals(((RandomFunction)obj).random)); + } + + // make sure we do not show the default 'null' parameter + @Override + public final String toString() { + StringBuilder buf = new StringBuilder(getName() + "("); + if (!hasSeed) return buf.append(")").toString(); + for (int i = 0; i < children.size() - 1; i++) { + buf.append(children.get(i) + ", "); + } + buf.append(children.get(children.size()-1) + ")"); + return buf.toString(); + } +} http://git-wip-us.apache.org/repos/asf/phoenix/blob/5a988cb8/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/5a988cb8/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/5a988cb8/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/5a988cb8/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/5a988cb8/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/5a988cb8/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/5a988cb8/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/5a988cb8/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/5a988cb8/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/5a988cb8/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/5a988cb8/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/5a988cb8/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/5a988cb8/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/5a988cb8/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixResultSet.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixResultSet.java b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixResultSet.java index 1630dbd..7d91dbb 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixResultSet.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixResultSet.java @@ -49,13 +49,15 @@ import org.apache.phoenix.compile.RowProjector; import org.apache.phoenix.exception.SQLExceptionCode; import org.apache.phoenix.exception.SQLExceptionInfo; import org.apache.phoenix.iterate.ResultIterator; -import org.apache.phoenix.schema.types.PDecimal; +import org.apache.phoenix.schema.tuple.ResultTuple; +import org.apache.phoenix.schema.tuple.Tuple; import org.apache.phoenix.schema.types.PBoolean; +import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.schema.types.PDate; +import org.apache.phoenix.schema.types.PDecimal; import org.apache.phoenix.schema.types.PDouble; import org.apache.phoenix.schema.types.PFloat; import org.apache.phoenix.schema.types.PInteger; -import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.schema.types.PLong; import org.apache.phoenix.schema.types.PSmallint; import org.apache.phoenix.schema.types.PTime; @@ -63,8 +65,6 @@ import org.apache.phoenix.schema.types.PTimestamp; import org.apache.phoenix.schema.types.PTinyint; import org.apache.phoenix.schema.types.PVarbinary; import org.apache.phoenix.schema.types.PVarchar; -import org.apache.phoenix.schema.tuple.ResultTuple; -import org.apache.phoenix.schema.tuple.Tuple; import org.apache.phoenix.util.DateUtil; import org.apache.phoenix.util.SQLCloseable; @@ -762,6 +762,7 @@ public class PhoenixResultSet implements ResultSet, SQLCloseable, org.apache.pho checkOpen(); try { currentRow = scanner.next(); + rowProjector.reset(); } catch (RuntimeException e) { // FIXME: Expression.evaluate does not throw SQLException // so this will unwrap throws from that. http://git-wip-us.apache.org/repos/asf/phoenix/blob/5a988cb8/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/PhoenixRecordReader.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/PhoenixRecordReader.java b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/PhoenixRecordReader.java index 2c206ab..b8eb116 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/PhoenixRecordReader.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/PhoenixRecordReader.java @@ -109,7 +109,9 @@ public class PhoenixRecordReader<T extends DBWritable> extends RecordReader<Null iterator = new SequenceResultIterator(iterator, queryPlan.getContext().getSequenceManager()); } this.resultIterator = iterator; - this.resultSet = new PhoenixResultSet(this.resultIterator, queryPlan.getProjector(),queryPlan.getContext().getStatement()); + // Clone the row projector as it's not thread safe and would be used simultaneously by + // multiple threads otherwise. + this.resultSet = new PhoenixResultSet(this.resultIterator, queryPlan.getProjector().clone(),queryPlan.getContext().getStatement()); } catch (SQLException e) { LOG.error(String.format(" Error [%s] initializing PhoenixRecordReader. ",e.getMessage())); Throwables.propagate(e); http://git-wip-us.apache.org/repos/asf/phoenix/blob/5a988cb8/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())); - } -}
