Return-Path: X-Original-To: apmail-phoenix-commits-archive@minotaur.apache.org Delivered-To: apmail-phoenix-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 3B61510DEE for ; Mon, 27 Jan 2014 19:25:07 +0000 (UTC) Received: (qmail 30496 invoked by uid 500); 27 Jan 2014 19:24:36 -0000 Delivered-To: apmail-phoenix-commits-archive@phoenix.apache.org Received: (qmail 29531 invoked by uid 500); 27 Jan 2014 19:24:06 -0000 Mailing-List: contact commits-help@phoenix.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@phoenix.incubator.apache.org Delivered-To: mailing list commits@phoenix.incubator.apache.org Received: (qmail 29439 invoked by uid 99); 27 Jan 2014 19:24:03 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 27 Jan 2014 19:24:03 +0000 X-ASF-Spam-Status: No, hits=-2000.5 required=5.0 tests=ALL_TRUSTED,RP_MATCHES_RCVD X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO mail.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with SMTP; Mon, 27 Jan 2014 19:23:29 +0000 Received: (qmail 27700 invoked by uid 99); 27 Jan 2014 19:23:04 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 27 Jan 2014 19:23:04 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 8416D9166F0; Mon, 27 Jan 2014 19:23:03 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: jamestaylor@apache.org To: commits@phoenix.incubator.apache.org Date: Mon, 27 Jan 2014 19:23:34 -0000 Message-Id: In-Reply-To: <5b6d8b961d204abab5cda9588a1b3c82@git.apache.org> References: <5b6d8b961d204abab5cda9588a1b3c82@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [33/51] [partial] Initial commit X-Virus-Checked: Checked by ClamAV on apache.org http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java b/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java new file mode 100644 index 0000000..f3e7b94 --- /dev/null +++ b/src/main/java/org/apache/phoenix/expression/ComparisonExpression.java @@ -0,0 +1,155 @@ +/* + * Copyright 2010 The Apache Software Foundation + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.expression; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.util.List; + +import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp; +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; +import org.apache.hadoop.io.WritableUtils; + +import org.apache.phoenix.expression.visitor.ExpressionVisitor; +import org.apache.phoenix.schema.ColumnModifier; +import org.apache.phoenix.schema.PDataType; +import org.apache.phoenix.schema.tuple.Tuple; +import org.apache.phoenix.util.ByteUtil; +import org.apache.phoenix.util.StringUtil; + + +/** + * + * Implementation for <,<=,>,>=,=,!= comparison expressions + * @author jtaylor + * @since 0.1 + */ +public class ComparisonExpression extends BaseCompoundExpression { + private CompareOp op; + private static final String[] CompareOpString = new String[CompareOp.values().length]; + static { + CompareOpString[CompareOp.EQUAL.ordinal()] = " = "; + CompareOpString[CompareOp.NOT_EQUAL.ordinal()] = " != "; + CompareOpString[CompareOp.GREATER.ordinal()] = " > "; + CompareOpString[CompareOp.LESS.ordinal()] = " < "; + CompareOpString[CompareOp.GREATER_OR_EQUAL.ordinal()] = " >= "; + CompareOpString[CompareOp.LESS_OR_EQUAL.ordinal()] = " <= "; + } + + public ComparisonExpression() { + } + + public ComparisonExpression(CompareOp op, List children) { + super(children); + if (op == null) { + throw new NullPointerException(); + } + this.op = op; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + op.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!super.equals(obj)) return false; + if (getClass() != obj.getClass()) return false; + ComparisonExpression other = (ComparisonExpression)obj; + if (op != other.op) return false; + return true; + } + + @Override + public PDataType getDataType() { + return PDataType.BOOLEAN; + } + + @Override + public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { + if (!children.get(0).evaluate(tuple, ptr)) { + return false; + } + byte[] lhsBytes = ptr.get(); + int lhsOffset = ptr.getOffset(); + int lhsLength = ptr.getLength(); + PDataType lhsDataType = children.get(0).getDataType(); + ColumnModifier lhsColumnModifier = children.get(0).getColumnModifier(); + + if (!children.get(1).evaluate(tuple, ptr)) { + return false; + } + + byte[] rhsBytes = ptr.get(); + int rhsOffset = ptr.getOffset(); + int rhsLength = ptr.getLength(); + PDataType rhsDataType = children.get(1).getDataType(); + ColumnModifier rhsColumnModifier = children.get(1).getColumnModifier(); + if (rhsDataType == PDataType.CHAR) { + rhsLength = StringUtil.getUnpaddedCharLength(rhsBytes, rhsOffset, rhsLength, rhsColumnModifier); + } + if (lhsDataType == PDataType.CHAR) { + lhsLength = StringUtil.getUnpaddedCharLength(lhsBytes, lhsOffset, lhsLength, lhsColumnModifier); + } + + + int comparisonResult = lhsDataType.compareTo(lhsBytes, lhsOffset, lhsLength, lhsColumnModifier, + rhsBytes, rhsOffset, rhsLength, rhsColumnModifier, rhsDataType); + ptr.set(ByteUtil.compare(op, comparisonResult) ? PDataType.TRUE_BYTES : PDataType.FALSE_BYTES); + return true; + } + + @Override + public void readFields(DataInput input) throws IOException { + op = CompareOp.values()[WritableUtils.readVInt(input)]; + super.readFields(input); + } + + @Override + public void write(DataOutput output) throws IOException { + WritableUtils.writeVInt(output, op.ordinal()); + super.write(output); + } + + @Override + public final T accept(ExpressionVisitor visitor) { + List l = acceptChildren(visitor, visitor.visitEnter(this)); + T t = visitor.visitLeave(this, l); + if (t == null) { + t = visitor.defaultReturn(this, l); + } + return t; + } + + public CompareOp getFilterOp() { + return op; + } + + @Override + public String toString() { + return (children.get(0) + CompareOpString[getFilterOp().ordinal()] + children.get(1)); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/DateAddExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/phoenix/expression/DateAddExpression.java b/src/main/java/org/apache/phoenix/expression/DateAddExpression.java new file mode 100644 index 0000000..a36bb48 --- /dev/null +++ b/src/main/java/org/apache/phoenix/expression/DateAddExpression.java @@ -0,0 +1,80 @@ +/* + * Copyright 2010 The Apache Software Foundation + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.expression; + +import java.math.BigDecimal; +import java.util.List; + +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; + +import org.apache.phoenix.query.QueryConstants; +import org.apache.phoenix.schema.ColumnModifier; +import org.apache.phoenix.schema.PDataType; +import org.apache.phoenix.schema.tuple.Tuple; + + +public class DateAddExpression extends AddExpression { + static private final BigDecimal BD_MILLIS_IN_DAY = BigDecimal.valueOf(QueryConstants.MILLIS_IN_DAY); + + public DateAddExpression() { + } + + public DateAddExpression(List children) { + super(children); + } + + @Override + public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { + long finalResult=0; + + for(int i=0;i children) { + super(children); + } + + @Override + public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { + long finalResult=0; + + for(int i=0;i children) { + super(children); + for (int i=0; i children) { + super(children); + } + + @Override + public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { + BigDecimal result = null; + for (int i=0; i children) { + super(children); + } + + @Override + public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { + BigDecimal result = null; + for (int i=0; i children) { + super(children); + for (int i=0; i children) { + super(children); + for (int i=0; i T accept(ExpressionVisitor visitor) { + List l = acceptChildren(visitor, visitor.visitEnter(this)); + T t = visitor.visitLeave(this, l); + if (t == null) { + t = visitor.defaultReturn(this, l); + } + return t; + } + + @Override + public String getOperatorString() { + return " / "; + } + + private static Integer getPrecision(Integer lp, Integer rp, Integer ls, Integer rs) { + if (ls == null || rs == null) { + return PDataType.MAX_PRECISION; + } + int val = getScale(lp, rp, ls, rs) + lp - ls + rp; + return Math.min(PDataType.MAX_PRECISION, val); + } + + private static Integer getScale(Integer lp, Integer rp, Integer ls, Integer rs) { + // If we are adding a decimal with scale and precision to a decimal + // with no precision nor scale, the scale system does not apply. + if (ls == null || rs == null) { + return null; + } + int val = Math.max(PDataType.MAX_PRECISION - lp + ls - rs, 0); + return Math.min(PDataType.MAX_PRECISION, val); + } + + @Override + public Integer getScale() { + return scale; + } + + @Override + public Integer getMaxLength() { + return maxLength; + } +} http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/DoubleAddExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/phoenix/expression/DoubleAddExpression.java b/src/main/java/org/apache/phoenix/expression/DoubleAddExpression.java new file mode 100644 index 0000000..96fc9fa --- /dev/null +++ b/src/main/java/org/apache/phoenix/expression/DoubleAddExpression.java @@ -0,0 +1,70 @@ +/* + * Copyright 2010 The Apache Software Foundation + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.expression; + +import java.util.List; + +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; + +import org.apache.phoenix.schema.PDataType; +import org.apache.phoenix.schema.tuple.Tuple; + +public class DoubleAddExpression extends AddExpression { + + public DoubleAddExpression() { + } + + public DoubleAddExpression(List children) { + super(children); + } + + @Override + public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { + double result = 0.0; + for (int i = 0; i < children.size(); i++) { + Expression child = children.get(i); + if (!child.evaluate(tuple, ptr)) { + return false; + } + if (ptr.getLength() == 0) { + return true; + } + double childvalue = child.getDataType().getCodec() + .decodeDouble(ptr, child.getColumnModifier()); + if (!Double.isNaN(childvalue) + && childvalue != Double.NEGATIVE_INFINITY + && childvalue != Double.POSITIVE_INFINITY) { + result += childvalue; + } else { + return false; + } + } + byte[] resultPtr = new byte[getDataType().getByteSize()]; + ptr.set(resultPtr); + getDataType().getCodec().encodeDouble(result, ptr); + return true; + } + + @Override + public PDataType getDataType() { + return PDataType.DOUBLE; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/DoubleDivideExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/phoenix/expression/DoubleDivideExpression.java b/src/main/java/org/apache/phoenix/expression/DoubleDivideExpression.java new file mode 100644 index 0000000..561cf90 --- /dev/null +++ b/src/main/java/org/apache/phoenix/expression/DoubleDivideExpression.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 The Apache Software Foundation + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.expression; + +import java.util.List; + +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; + +import org.apache.phoenix.schema.PDataType; +import org.apache.phoenix.schema.tuple.Tuple; + +public class DoubleDivideExpression extends DivideExpression { + + public DoubleDivideExpression() { + } + + public DoubleDivideExpression(List children) { + super(children); + } + + @Override + public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { + double result = 0.0; + for (int i = 0; i < children.size(); i++) { + Expression child = children.get(i); + if (!child.evaluate(tuple, ptr)) { + return false; + } + if (ptr.getLength() == 0) { + return true; + } + double childvalue = child.getDataType().getCodec() + .decodeDouble(ptr, child.getColumnModifier()); + if (!Double.isNaN(childvalue) + && childvalue != Double.NEGATIVE_INFINITY + && childvalue != Double.POSITIVE_INFINITY) { + if (i == 0) { + result = childvalue; + } else { + result /= childvalue; + } + } else { + return false; + } + } + byte[] resultPtr = new byte[getDataType().getByteSize()]; + ptr.set(resultPtr); + getDataType().getCodec().encodeDouble(result, ptr); + return true; + } + + @Override + public PDataType getDataType() { + return PDataType.DOUBLE; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/DoubleMultiplyExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/phoenix/expression/DoubleMultiplyExpression.java b/src/main/java/org/apache/phoenix/expression/DoubleMultiplyExpression.java new file mode 100644 index 0000000..b9e8165 --- /dev/null +++ b/src/main/java/org/apache/phoenix/expression/DoubleMultiplyExpression.java @@ -0,0 +1,70 @@ +/* + * Copyright 2010 The Apache Software Foundation + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.expression; + +import java.util.List; + +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; + +import org.apache.phoenix.schema.PDataType; +import org.apache.phoenix.schema.tuple.Tuple; + +public class DoubleMultiplyExpression extends MultiplyExpression { + + public DoubleMultiplyExpression() { + } + + public DoubleMultiplyExpression(List children) { + super(children); + } + + @Override + public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { + double result = 1.0; + for (int i = 0; i < children.size(); i++) { + Expression child = children.get(i); + if (!child.evaluate(tuple, ptr)) { + return false; + } + if (ptr.getLength() == 0) { + return true; + } + double childvalue = child.getDataType().getCodec() + .decodeDouble(ptr, child.getColumnModifier()); + if (!Double.isNaN(childvalue) + && childvalue != Double.NEGATIVE_INFINITY + && childvalue != Double.POSITIVE_INFINITY) { + result *= childvalue; + } else { + return false; + } + } + byte[] resultPtr = new byte[getDataType().getByteSize()]; + ptr.set(resultPtr); + getDataType().getCodec().encodeDouble(result, ptr); + return true; + } + + @Override + public PDataType getDataType() { + return PDataType.DOUBLE; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/DoubleSubtractExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/phoenix/expression/DoubleSubtractExpression.java b/src/main/java/org/apache/phoenix/expression/DoubleSubtractExpression.java new file mode 100644 index 0000000..8752c15 --- /dev/null +++ b/src/main/java/org/apache/phoenix/expression/DoubleSubtractExpression.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 The Apache Software Foundation + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.expression; + +import java.util.List; + +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; + +import org.apache.phoenix.schema.PDataType; +import org.apache.phoenix.schema.tuple.Tuple; + +public class DoubleSubtractExpression extends SubtractExpression { + + public DoubleSubtractExpression() { + } + + public DoubleSubtractExpression(List children) { + super(children); + } + + @Override + public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { + double result = 0.0; + for (int i = 0; i < children.size(); i++) { + Expression child = children.get(i); + if (!child.evaluate(tuple, ptr)) { + return false; + } + if (ptr.getLength() == 0) { + return true; + } + double childvalue = child.getDataType().getCodec() + .decodeDouble(ptr, child.getColumnModifier()); + if (!Double.isNaN(childvalue) + && childvalue != Double.NEGATIVE_INFINITY + && childvalue != Double.POSITIVE_INFINITY) { + if (i == 0) { + result = childvalue; + } else { + result -= childvalue; + } + } else { + return false; + } + } + byte[] resultPtr = new byte[getDataType().getByteSize()]; + ptr.set(resultPtr); + getDataType().getCodec().encodeDouble(result, ptr); + return true; + } + + @Override + public PDataType getDataType() { + return PDataType.DOUBLE; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/Expression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/phoenix/expression/Expression.java b/src/main/java/org/apache/phoenix/expression/Expression.java new file mode 100644 index 0000000..a17c23a --- /dev/null +++ b/src/main/java/org/apache/phoenix/expression/Expression.java @@ -0,0 +1,77 @@ +/* + * Copyright 2010 The Apache Software Foundation + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.expression; + +import java.util.List; + +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; +import org.apache.hadoop.io.Writable; + +import org.apache.phoenix.expression.visitor.ExpressionVisitor; +import org.apache.phoenix.schema.PDatum; +import org.apache.phoenix.schema.tuple.Tuple; + + +/** + * + * Interface for general expression evaluation + * + * @author jtaylor + * @since 0.1 + */ +public interface Expression extends PDatum, Writable { + /** + * Access the value by setting a pointer to it (as opposed to making + * a copy of it which can be expensive) + * @param tuple Single row result during scan iteration + * @param ptr Pointer to byte value being accessed + * @return true if the expression could be evaluated (i.e. ptr was set) + * and false otherwise + */ + boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr); + + /** + * Means of traversing expression tree through visitor. + * @param visitor + */ + T accept(ExpressionVisitor visitor); + + /** + * @return the child expressions + */ + List getChildren(); + + /** + * Resets the state of a expression back to its initial state and + * enables the expession to be evaluated incrementally (which + * occurs during filter evaluation where we see one key value at + * a time; it's possible to evaluate immediately rather than + * wait until all key values have been seen). Note that when + * evaluating incrementally, you must call this method before + * processing a new row. + */ + void reset(); + + /** + * @return true if the expression represents a constant value and + * false otherwise. + */ + boolean isConstant(); +} http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/ExpressionType.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/phoenix/expression/ExpressionType.java b/src/main/java/org/apache/phoenix/expression/ExpressionType.java new file mode 100644 index 0000000..c865842 --- /dev/null +++ b/src/main/java/org/apache/phoenix/expression/ExpressionType.java @@ -0,0 +1,170 @@ +/* + * Copyright 2010 The Apache Software Foundation + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.expression; + +import java.util.Map; + +import org.apache.phoenix.expression.function.CoalesceFunction; +import org.apache.phoenix.expression.function.CountAggregateFunction; +import org.apache.phoenix.expression.function.DistinctCountAggregateFunction; +import org.apache.phoenix.expression.function.IndexStateNameFunction; +import org.apache.phoenix.expression.function.InvertFunction; +import org.apache.phoenix.expression.function.LTrimFunction; +import org.apache.phoenix.expression.function.LengthFunction; +import org.apache.phoenix.expression.function.MaxAggregateFunction; +import org.apache.phoenix.expression.function.MinAggregateFunction; +import org.apache.phoenix.expression.function.PercentRankAggregateFunction; +import org.apache.phoenix.expression.function.PercentileContAggregateFunction; +import org.apache.phoenix.expression.function.PercentileDiscAggregateFunction; +import org.apache.phoenix.expression.function.RTrimFunction; +import org.apache.phoenix.expression.function.RegexpReplaceFunction; +import org.apache.phoenix.expression.function.RegexpSubstrFunction; +import org.apache.phoenix.expression.function.ReverseFunction; +import org.apache.phoenix.expression.function.RoundFunction; +import org.apache.phoenix.expression.function.SqlTableType; +import org.apache.phoenix.expression.function.SqlTypeNameFunction; +import org.apache.phoenix.expression.function.StddevPopFunction; +import org.apache.phoenix.expression.function.StddevSampFunction; +import org.apache.phoenix.expression.function.SubstrFunction; +import org.apache.phoenix.expression.function.SumAggregateFunction; +import org.apache.phoenix.expression.function.ToCharFunction; +import org.apache.phoenix.expression.function.ToDateFunction; +import org.apache.phoenix.expression.function.ToNumberFunction; +import org.apache.phoenix.expression.function.TrimFunction; +import org.apache.phoenix.expression.function.TruncFunction; + +import com.google.common.collect.Maps; + +/** + * + * Enumeration of all Expression types that may be evaluated on the server-side. + * Used during serialization and deserialization to pass Expression between client + * and server. + * + * @author jtaylor + * @since 0.1 + */ +public enum ExpressionType { + ReverseFunction(ReverseFunction.class), + RowKey(RowKeyColumnExpression.class), + KeyValue(KeyValueColumnExpression.class), + LiteralValue(LiteralExpression.class), + RoundFunction(RoundFunction.class), + TruncFunction(TruncFunction.class), + ToDateFunction(ToDateFunction.class), + ToCharFunction(ToCharFunction.class), + ToNumberFunction(ToNumberFunction.class), + CoerceFunction(CoerceExpression.class), + SubstrFunction(SubstrFunction.class), + AndExpression(AndExpression.class), + OrExpression(OrExpression.class), + ComparisonExpression(ComparisonExpression.class), + CountAggregateFunction(CountAggregateFunction.class), + SumAggregateFunction(SumAggregateFunction.class), + MinAggregateFunction(MinAggregateFunction.class), + MaxAggregateFunction(MaxAggregateFunction.class), + LikeExpression(LikeExpression.class), + NotExpression(NotExpression.class), + CaseExpression(CaseExpression.class), + InListExpression(InListExpression.class), + IsNullExpression(IsNullExpression.class), + LongSubtractExpression(LongSubtractExpression.class), + DateSubtractExpression(DateSubtractExpression.class), + DecimalSubtractExpression(DecimalSubtractExpression.class), + LongAddExpression(LongAddExpression.class), + DecimalAddExpression(DecimalAddExpression.class), + DateAddExpression(DateAddExpression.class), + LongMultiplyExpression(LongMultiplyExpression.class), + DecimalMultiplyExpression(DecimalMultiplyExpression.class), + LongDivideExpression(LongDivideExpression.class), + DecimalDivideExpression(DecimalDivideExpression.class), + CoalesceFunction(CoalesceFunction.class), + RegexpReplaceFunction(RegexpReplaceFunction.class), + SQLTypeNameFunction(SqlTypeNameFunction.class), + RegexpSubstrFunction(RegexpSubstrFunction.class), + StringConcatExpression(StringConcatExpression.class), + LengthFunction(LengthFunction.class), + LTrimFunction(LTrimFunction.class), + RTrimFunction(RTrimFunction.class), + TrimFunction(TrimFunction.class), + DistinctCountAggregateFunction(DistinctCountAggregateFunction.class), + PercentileContAggregateFunction(PercentileContAggregateFunction.class), + PercentRankAggregateFunction(PercentRankAggregateFunction.class), + StddevPopFunction(StddevPopFunction.class), + StddevSampFunction(StddevSampFunction.class), + PercentileDiscAggregateFunction(PercentileDiscAggregateFunction.class), + DoubleAddExpression(DoubleAddExpression.class), + DoubleSubtractExpression(DoubleSubtractExpression.class), + DoubleMultiplyExpression(DoubleMultiplyExpression.class), + DoubleDivideExpression(DoubleDivideExpression.class), + RowValueConstructorExpression(RowValueConstructorExpression.class), + SqlTableType(SqlTableType.class), + CeilingDecimalExpression(CeilingDecimalExpression.class), + CeilingTimestampExpression(CeilingTimestampExpression.class), + FloorDecimalExpression(FloorDecimalExpression.class), + FloorTimestampExpression(FloorTimestampExpression.class), + IndexKeyValue(IndexKeyValueColumnExpression.class), + IndexStateName(IndexStateNameFunction.class), + InvertFunction(InvertFunction.class), + TimestampAddExpression(TimestampAddExpression.class), + TimestampSubtractExpression(TimestampSubtractExpression.class), + ; + + ExpressionType(Class clazz) { + this.clazz = clazz; + } + + public Class getExpressionClass() { + return clazz; + } + + private final Class clazz; + + private static final Map,ExpressionType> classToEnumMap = Maps.newHashMapWithExpectedSize(3); + static { + for (ExpressionType type : ExpressionType.values()) { + classToEnumMap.put(type.clazz, type); + } + } + + /** + * Return the ExpressionType for a given Expression instance + */ + public static ExpressionType valueOf(Expression expression) { + ExpressionType type = classToEnumMap.get(expression.getClass()); + if (type == null) { // FIXME: this exception gets swallowed and retries happen + throw new IllegalArgumentException("No ExpressionType for " + expression.getClass()); + } + return type; + } + + /** + * Instantiates a DataAccessor based on its DataAccessorType + */ + public Expression newInstance() { + try { + return clazz.newInstance(); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/FloorDecimalExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/phoenix/expression/FloorDecimalExpression.java b/src/main/java/org/apache/phoenix/expression/FloorDecimalExpression.java new file mode 100644 index 0000000..82e0a83 --- /dev/null +++ b/src/main/java/org/apache/phoenix/expression/FloorDecimalExpression.java @@ -0,0 +1,51 @@ +/* + * Copyright 2010 The Apache Software Foundation + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.expression; + +import java.math.MathContext; +import java.math.RoundingMode; + + +public class FloorDecimalExpression extends CeilingDecimalExpression { + private static final MathContext FLOOR_CONTEXT = new MathContext(0, RoundingMode.FLOOR); + + public FloorDecimalExpression() { + } + + public FloorDecimalExpression(Expression child) { + super(child); + } + + @Override + protected MathContext getMathContext() { + return FLOOR_CONTEXT; + } + + + @Override + public final String toString() { + StringBuilder buf = new StringBuilder("FLOOR("); + for (int i = 0; i < children.size() - 1; i++) { + buf.append(getChild().toString()); + } + buf.append(")"); + return buf.toString(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/FloorTimestampExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/phoenix/expression/FloorTimestampExpression.java b/src/main/java/org/apache/phoenix/expression/FloorTimestampExpression.java new file mode 100644 index 0000000..060c17d --- /dev/null +++ b/src/main/java/org/apache/phoenix/expression/FloorTimestampExpression.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010 The Apache Software Foundation + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.expression; + + + +public class FloorTimestampExpression extends CeilingTimestampExpression { + + public FloorTimestampExpression() { + } + + public FloorTimestampExpression(Expression child) { + super(child); + } + + @Override + protected int getRoundUpAmount() { + return 0; + } + + + @Override + public final String toString() { + StringBuilder buf = new StringBuilder("FLOOR("); + for (int i = 0; i < children.size() - 1; i++) { + buf.append(getChild().toString()); + } + buf.append(")"); + return buf.toString(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/InListExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/phoenix/expression/InListExpression.java b/src/main/java/org/apache/phoenix/expression/InListExpression.java new file mode 100644 index 0000000..7c7ad88 --- /dev/null +++ b/src/main/java/org/apache/phoenix/expression/InListExpression.java @@ -0,0 +1,291 @@ +/* + * Copyright 2010 The Apache Software Foundation + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.expression; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp; +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; +import org.apache.hadoop.hbase.util.Bytes; +import org.apache.hadoop.io.WritableUtils; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import org.apache.hbase.index.util.ImmutableBytesPtr; +import org.apache.phoenix.expression.visitor.ExpressionVisitor; +import org.apache.phoenix.schema.ConstraintViolationException; +import org.apache.phoenix.schema.PDataType; +import org.apache.phoenix.schema.tuple.Tuple; +import org.apache.phoenix.util.ByteUtil; + +/* + * Implementation of a SQL foo IN (a,b,c) expression. Other than the first + * expression, child expressions must be constants. + * + */ +public class InListExpression extends BaseSingleExpression { + private LinkedHashSet values; + private ImmutableBytesPtr minValue; + private ImmutableBytesPtr maxValue; + private int valuesByteLength; + private boolean containsNull; + private int fixedWidth = -1; + private ImmutableBytesPtr value = new ImmutableBytesPtr(); + private List keyExpressions; // client side only + + public static Expression create (List children, ImmutableBytesWritable ptr) throws SQLException { + Expression firstChild = children.get(0); + PDataType firstChildType = firstChild.getDataType(); + + boolean addedNull = false; + List keys = Lists.newArrayListWithExpectedSize(children.size()); + List coercedKeyExpressions = Lists.newArrayListWithExpectedSize(children.size()); + keys.add(firstChild); + coercedKeyExpressions.add(firstChild); + for (int i = 1; i < children.size(); i++) { + Expression rhs = children.get(i); + if (rhs.evaluate(null, ptr)) { + if (ptr.getLength() == 0) { + if (!addedNull) { + addedNull = true; + keys.add(LiteralExpression.newConstant(null, PDataType.VARBINARY)); + coercedKeyExpressions.add(LiteralExpression.newConstant(null, firstChildType)); + } + } else { + // Don't specify the firstChild column modifier here, as we specify it in the LiteralExpression creation below + try { + firstChildType.coerceBytes(ptr, rhs.getDataType(), rhs.getColumnModifier(), null); + keys.add(LiteralExpression.newConstant(ByteUtil.copyKeyBytesIfNecessary(ptr), PDataType.VARBINARY, firstChild.getColumnModifier())); + if(rhs.getDataType() == firstChildType) { + coercedKeyExpressions.add(rhs); + } else { + coercedKeyExpressions.add(CoerceExpression.create(rhs, firstChildType)); + } + } catch (ConstraintViolationException e) { // Ignore and continue + } + } + } + + } + if (keys.size() == 1) { + return LiteralExpression.FALSE_EXPRESSION; + } + if (keys.size() == 2 && addedNull) { + return LiteralExpression.newConstant(null, PDataType.BOOLEAN); + } + Expression expression; + // TODO: if inChildren.isEmpty() then Oracle throws a type mismatch exception. This means + // that none of the list elements match in type and there's no null element. We'd return + // false in this case. Should we throw? + if (keys.size() == 2) { + expression = new ComparisonExpression(CompareOp.EQUAL, keys); + } else { + expression = new InListExpression(keys, coercedKeyExpressions); + } + return expression; + } + public InListExpression() { + } + + private InListExpression(List keys, List keyExpressions) throws SQLException { + super(keyExpressions.get(0)); + this.keyExpressions = keyExpressions.subList(1, keyExpressions.size()); + Set values = Sets.newHashSetWithExpectedSize(keys.size()-1); + int fixedWidth = -1; + boolean isFixedLength = true; + for (int i = 1; i < keys.size(); i++) { + ImmutableBytesPtr ptr = new ImmutableBytesPtr(); + Expression child = keys.get(i); + assert(child.getDataType() == PDataType.VARBINARY); + child.evaluate(null, ptr); + if (ptr.getLength() == 0) { + containsNull = true; + } else { + if (values.add(ptr)) { + int length = ptr.getLength(); + if (fixedWidth == -1) { + fixedWidth = length; + } else { + isFixedLength &= fixedWidth == length; + } + + valuesByteLength += ptr.getLength(); + } + } + } + this.fixedWidth = isFixedLength ? fixedWidth : -1; + // Sort values by byte value so we can get min/max easily + ImmutableBytesPtr[] valuesArray = values.toArray(new ImmutableBytesPtr[values.size()]); + Arrays.sort(valuesArray, ByteUtil.BYTES_PTR_COMPARATOR); + this.minValue = valuesArray[0]; + this.maxValue = valuesArray[valuesArray.length-1]; + this.values = new LinkedHashSet(Arrays.asList(valuesArray)); + } + + @Override + public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { + if (!getChild().evaluate(tuple, ptr)) { + return false; + } + value.set(ptr); + if (values.contains(value)) { + ptr.set(PDataType.TRUE_BYTES); + return true; + } + if (containsNull) { // If any null value and value not found + ptr.set(ByteUtil.EMPTY_BYTE_ARRAY); + return true; + } + ptr.set(PDataType.FALSE_BYTES); + return true; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (containsNull ? 1231 : 1237); + result = prime * result + values.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + InListExpression other = (InListExpression)obj; + if (containsNull != other.containsNull) return false; + if (!values.equals(other.values)) return false; + return true; + } + + @Override + public PDataType getDataType() { + return PDataType.BOOLEAN; + } + + @Override + public boolean isNullable() { + return super.isNullable() || containsNull; + } + + private int readValue(DataInput input, byte[] valuesBytes, int offset, ImmutableBytesPtr ptr) throws IOException { + int valueLen = fixedWidth == -1 ? WritableUtils.readVInt(input) : fixedWidth; + values.add(new ImmutableBytesPtr(valuesBytes,offset,valueLen)); + return offset + valueLen; + } + + @Override + public void readFields(DataInput input) throws IOException { + super.readFields(input); + containsNull = input.readBoolean(); + fixedWidth = WritableUtils.readVInt(input); + byte[] valuesBytes = Bytes.readByteArray(input); + valuesByteLength = valuesBytes.length; + int len = fixedWidth == -1 ? WritableUtils.readVInt(input) : valuesByteLength / fixedWidth; + values = Sets.newLinkedHashSetWithExpectedSize(len); + int offset = 0; + int i = 0; + if (i < len) { + offset = readValue(input, valuesBytes, offset, minValue = new ImmutableBytesPtr()); + while (++i < len-1) { + offset = readValue(input, valuesBytes, offset, new ImmutableBytesPtr()); + } + if (i < len) { + offset = readValue(input, valuesBytes, offset, maxValue = new ImmutableBytesPtr()); + } else { + maxValue = minValue; + } + } else { + minValue = maxValue = new ImmutableBytesPtr(ByteUtil.EMPTY_BYTE_ARRAY); + } + } + + @Override + public void write(DataOutput output) throws IOException { + super.write(output); + output.writeBoolean(containsNull); + WritableUtils.writeVInt(output, fixedWidth); + WritableUtils.writeVInt(output, valuesByteLength); + for (ImmutableBytesPtr ptr : values) { + output.write(ptr.get(), ptr.getOffset(), ptr.getLength()); + } + if (fixedWidth == -1) { + WritableUtils.writeVInt(output, values.size()); + for (ImmutableBytesPtr ptr : values) { + WritableUtils.writeVInt(output, ptr.getLength()); + } + } + } + + @Override + public final T accept(ExpressionVisitor visitor) { + List l = acceptChildren(visitor, visitor.visitEnter(this)); + T t = visitor.visitLeave(this, l); + if (t == null) { + t = visitor.defaultReturn(this, l); + } + return t; + } + + public List getKeyExpressions() { + return keyExpressions; + } + + public ImmutableBytesWritable getMinKey() { + return minValue; + } + + public ImmutableBytesWritable getMaxKey() { + return maxValue; + } + + @Override + public String toString() { + int maxToStringLen = 200; + Expression firstChild = children.get(0); + PDataType type = firstChild.getDataType(); + StringBuilder buf = new StringBuilder(firstChild + " IN ("); + if (containsNull) { + buf.append("null,"); + } + for (ImmutableBytesPtr value : values) { + if (firstChild.getColumnModifier() != null) { + type.coerceBytes(value, type, firstChild.getColumnModifier(), null); + } + buf.append(type.toStringLiteral(value, null)); + buf.append(','); + if (buf.length() >= maxToStringLen) { + buf.append("... "); + break; + } + } + buf.setCharAt(buf.length()-1,')'); + return buf.toString(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/IndexKeyValueColumnExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/phoenix/expression/IndexKeyValueColumnExpression.java b/src/main/java/org/apache/phoenix/expression/IndexKeyValueColumnExpression.java new file mode 100644 index 0000000..fb066c1 --- /dev/null +++ b/src/main/java/org/apache/phoenix/expression/IndexKeyValueColumnExpression.java @@ -0,0 +1,26 @@ +package org.apache.phoenix.expression; + +import org.apache.hadoop.hbase.util.Bytes; + +import org.apache.phoenix.schema.PColumn; +import org.apache.phoenix.util.IndexUtil; +import org.apache.phoenix.util.SchemaUtil; + +public class IndexKeyValueColumnExpression extends KeyValueColumnExpression { + public IndexKeyValueColumnExpression() { + } + + public IndexKeyValueColumnExpression(PColumn column) { + super(column); + } + + @Override + public String toString() { + // Translate to the data table column name + String indexColumnName = Bytes.toString(this.getColumnName()); + String dataFamilyName = IndexUtil.getDataColumnFamilyName(indexColumnName); + String dataColumnName = IndexUtil.getDataColumnName(indexColumnName); + return SchemaUtil.getColumnDisplayName(dataFamilyName, dataColumnName); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/IsNullExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/phoenix/expression/IsNullExpression.java b/src/main/java/org/apache/phoenix/expression/IsNullExpression.java new file mode 100644 index 0000000..e6ef621 --- /dev/null +++ b/src/main/java/org/apache/phoenix/expression/IsNullExpression.java @@ -0,0 +1,106 @@ +/* + * Copyright 2010 The Apache Software Foundation + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.expression; + +import java.io.*; +import java.util.List; + +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; + +import org.apache.phoenix.expression.visitor.ExpressionVisitor; +import org.apache.phoenix.schema.PDataType; +import org.apache.phoenix.schema.tuple.Tuple; + + +/** + * + * Implementation of IS NULL and IS NOT NULL expression + * + * @author jtaylor + * @since 0.1 + */ +public class IsNullExpression extends BaseSingleExpression { + private boolean isNegate; + + public IsNullExpression() { + } + + public IsNullExpression(Expression expression, boolean negate) { + super(expression); + this.isNegate = negate; + } + + @Override + public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { + boolean evaluated = getChild().evaluate(tuple, ptr); + if (evaluated) { + ptr.set(isNegate ^ ptr.getLength() == 0 ? PDataType.TRUE_BYTES : PDataType.FALSE_BYTES); + return true; + } + if (tuple.isImmutable()) { + ptr.set(isNegate ? PDataType.FALSE_BYTES : PDataType.TRUE_BYTES); + return true; + } + + return false; + } + + public boolean isNegate() { + return isNegate; + } + + @Override + public void readFields(DataInput input) throws IOException { + super.readFields(input); + isNegate = input.readBoolean(); + } + + @Override + public void write(DataOutput output) throws IOException { + super.write(output); + output.writeBoolean(isNegate); + } + + @Override + public PDataType getDataType() { + return PDataType.BOOLEAN; + } + + @Override + public final T accept(ExpressionVisitor visitor) { + List l = acceptChildren(visitor, visitor.visitEnter(this)); + T t = visitor.visitLeave(this, l); + if (t == null) { + t = visitor.defaultReturn(this, l); + } + return t; + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(children.get(0).toString()); + if (isNegate) { + buf.append(" IS NOT NULL"); + } else { + buf.append(" IS NULL"); + } + return buf.toString(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/expression/KeyValueColumnExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/phoenix/expression/KeyValueColumnExpression.java b/src/main/java/org/apache/phoenix/expression/KeyValueColumnExpression.java new file mode 100644 index 0000000..7cc76fa --- /dev/null +++ b/src/main/java/org/apache/phoenix/expression/KeyValueColumnExpression.java @@ -0,0 +1,119 @@ +/* + * Copyright 2010 The Apache Software Foundation + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.expression; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.util.Arrays; + +import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; +import org.apache.hadoop.hbase.util.Bytes; + +import org.apache.phoenix.expression.visitor.ExpressionVisitor; +import org.apache.phoenix.schema.PColumn; +import org.apache.phoenix.schema.tuple.Tuple; +import org.apache.phoenix.util.SchemaUtil; + + +/** + * + * Class to access a column value stored in a KeyValue + * + * @author jtaylor + * @since 0.1 + */ +public class KeyValueColumnExpression extends ColumnExpression { + private byte[] cf; + private byte[] cq; + + public KeyValueColumnExpression() { + } + + public KeyValueColumnExpression(PColumn column) { + super(column); + this.cf = column.getFamilyName().getBytes(); + this.cq = column.getName().getBytes(); + } + + public byte[] getColumnFamily() { + return cf; + } + + public byte[] getColumnName() { + return cq; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + Arrays.hashCode(cf); + result = prime * result + Arrays.hashCode(cq); + return result; + } + + // TODO: assumes single table + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + KeyValueColumnExpression other = (KeyValueColumnExpression)obj; + if (!Arrays.equals(cf, other.cf)) return false; + if (!Arrays.equals(cq, other.cq)) return false; + return true; + } + + @Override + public String toString() { + return SchemaUtil.getColumnDisplayName(cf, cq); + } + + @Override + public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { + KeyValue keyValue = tuple.getValue(cf, cq); + if (keyValue != null) { + ptr.set(keyValue.getBuffer(), keyValue.getValueOffset(), keyValue.getValueLength()); + return true; + } + return false; + } + + @Override + public void readFields(DataInput input) throws IOException { + super.readFields(input); + cf = Bytes.readByteArray(input); + cq = Bytes.readByteArray(input); + } + + @Override + public void write(DataOutput output) throws IOException { + super.write(output); + Bytes.writeByteArray(output, cf); + Bytes.writeByteArray(output, cq); + } + + @Override + public final T accept(ExpressionVisitor visitor) { + return visitor.visit(this); + } +}