You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ja...@apache.org on 2014/01/27 23:15:45 UTC
[29/51] [partial] Initial commit of master branch from github
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CountAggregateFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CountAggregateFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CountAggregateFunction.java
new file mode 100644
index 0000000..5e7dceb
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CountAggregateFunction.java
@@ -0,0 +1,116 @@
+/*
+ * 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.function;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.LiteralExpression;
+import org.apache.phoenix.expression.aggregator.Aggregator;
+import org.apache.phoenix.expression.aggregator.CountAggregator;
+import org.apache.phoenix.expression.aggregator.LongSumAggregator;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.util.SchemaUtil;
+
+
+/**
+ *
+ * Built-in function for COUNT(<expression>) aggregate function,
+ * for example COUNT(foo), COUNT(1), COUNT(*)
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+@BuiltInFunction(name=CountAggregateFunction.NAME, args= {@Argument()} )
+public class CountAggregateFunction extends SingleAggregateFunction {
+ public static final String NAME = "COUNT";
+ public static final List<Expression> STAR = Arrays.<Expression>asList(LiteralExpression.newConstant(1, true));
+ public static final String NORMALIZED_NAME = SchemaUtil.normalizeIdentifier(NAME);
+
+ public CountAggregateFunction() {
+ }
+
+ public CountAggregateFunction(List<Expression> childExpressions) {
+ super(childExpressions);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ CountAggregateFunction other = (CountAggregateFunction)obj;
+ return (isConstantExpression() && other.isConstantExpression()) || children.equals(other.getChildren());
+ }
+
+ @Override
+ public int hashCode() {
+ return isConstantExpression() ? 0 : super.hashCode();
+ }
+
+ /**
+ * The COUNT function never returns null
+ */
+ @Override
+ public boolean isNullable() {
+ return false;
+ }
+
+ @Override
+ public PDataType getDataType() {
+ return PDataType.LONG;
+ }
+
+ @Override
+ public LongSumAggregator newClientAggregator() {
+ // Since COUNT can never be null, ensure the aggregator is not nullable.
+ // This allows COUNT(*) to return 0 with the initial state of ClientAggregators
+ // when no rows are returned.
+ return new LongSumAggregator(null) {
+ @Override
+ public boolean isNullable() {
+ return false;
+ }
+ };
+ }
+
+ @Override
+ public Aggregator newServerAggregator(Configuration conf) {
+ return new CountAggregator();
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public Aggregator newServerAggregator(Configuration config, ImmutableBytesWritable ptr) {
+ LongSumAggregator sumAgg = newClientAggregator();
+ sumAgg.aggregate(null, ptr);
+ return new CountAggregator(sumAgg);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CurrentDateFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CurrentDateFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CurrentDateFunction.java
new file mode 100644
index 0000000..ad9e989
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CurrentDateFunction.java
@@ -0,0 +1,69 @@
+/*
+ * 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.function;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.expression.CurrentDateTimeFunction;
+import org.apache.phoenix.parse.CurrentDateParseNode;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+
+/**
+ *
+ * Function that returns the current date accurate to the millisecond. Note that this
+ * function is never evaluated on the server-side, instead the server side date is
+ * retrieved (piggy-backed on the call to check that the metadata is up-to-date) and
+ * passed into this function at create time.
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+@BuiltInFunction(name=CurrentDateFunction.NAME, nodeClass=CurrentDateParseNode.class, args= {} )
+public class CurrentDateFunction extends CurrentDateTimeFunction {
+ public static final String NAME = "CURRENT_DATE";
+ private final ImmutableBytesWritable currentDate = new ImmutableBytesWritable(new byte[PDataType.DATE.getByteSize()]);
+
+ public CurrentDateFunction() {
+ this(System.currentTimeMillis());
+ }
+
+ public CurrentDateFunction(long timeStamp) {
+ getDataType().getCodec().encodeLong(timeStamp, currentDate);
+ }
+
+ @Override
+ public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+ ptr.set(currentDate.get(), 0, PDataType.DATE.getByteSize());
+ return true;
+ }
+
+ @Override
+ public final PDataType getDataType() {
+ return PDataType.DATE;
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CurrentTimeFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CurrentTimeFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CurrentTimeFunction.java
new file mode 100644
index 0000000..71a1602
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CurrentTimeFunction.java
@@ -0,0 +1,69 @@
+/*
+ * 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.function;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.expression.CurrentDateTimeFunction;
+import org.apache.phoenix.parse.CurrentTimeParseNode;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+
+/**
+ *
+ * Function that returns the current date accurate to the millisecond. Note that this
+ * function is never evaluated on the server-side, instead the server side date is
+ * retrieved (piggy-backed on the call to check that the metadata is up-to-date) and
+ * passed into this function at create time.
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+@BuiltInFunction(name=CurrentTimeFunction.NAME, nodeClass=CurrentTimeParseNode.class, args={} )
+public class CurrentTimeFunction extends CurrentDateTimeFunction {
+ public static final String NAME = "CURRENT_TIME";
+ private final ImmutableBytesWritable currentDate = new ImmutableBytesWritable(new byte[PDataType.TIME.getByteSize()]);
+
+ public CurrentTimeFunction() {
+ this(System.currentTimeMillis());
+ }
+
+ public CurrentTimeFunction(long timeStamp) {
+ getDataType().getCodec().encodeLong(timeStamp, currentDate);
+ }
+
+ @Override
+ public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+ ptr.set(currentDate.get(), 0, PDataType.TIME.getByteSize());
+ return true;
+ }
+
+ @Override
+ public final PDataType getDataType() {
+ return PDataType.TIME;
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DelegateConstantToCountAggregateFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DelegateConstantToCountAggregateFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DelegateConstantToCountAggregateFunction.java
new file mode 100644
index 0000000..744e5bb
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DelegateConstantToCountAggregateFunction.java
@@ -0,0 +1,75 @@
+/*
+ * 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.function;
+
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+
+/**
+ *
+ * Base class for non composite aggregation functions that optimize aggregation by
+ * delegating to {@link CountAggregateFunction} when the child expression is a
+ * constant.
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+abstract public class DelegateConstantToCountAggregateFunction extends SingleAggregateFunction {
+ private static final ImmutableBytesWritable ZERO = new ImmutableBytesWritable(PDataType.LONG.toBytes(0L));
+ private CountAggregateFunction delegate;
+
+ public DelegateConstantToCountAggregateFunction() {
+ }
+
+ public DelegateConstantToCountAggregateFunction(List<Expression> childExpressions, CountAggregateFunction delegate) {
+ super(childExpressions);
+ // Using a delegate here causes us to optimize the number of aggregators
+ // by sharing the CountAggregator across functions. On the server side,
+ // this will always be null, since if it had not been null on the client,
+ // the function would not have been transfered over (the delegate would
+ // have instead).
+ this.delegate = delegate;
+ }
+
+ @Override
+ public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+ if (delegate == null) {
+ return super.evaluate(tuple, ptr);
+ }
+ delegate.evaluate(tuple, ptr);
+ if (PDataType.LONG.compareTo(ptr,ZERO) == 0) {
+ return false;
+ }
+ return true;
+ }
+
+
+ @Override
+ protected SingleAggregateFunction getDelegate() {
+ return delegate != null ? delegate : super.getDelegate();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DistinctCountAggregateFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DistinctCountAggregateFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DistinctCountAggregateFunction.java
new file mode 100644
index 0000000..b6ea58e
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DistinctCountAggregateFunction.java
@@ -0,0 +1,124 @@
+/*
+ * 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.function;
+
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.aggregator.Aggregator;
+import org.apache.phoenix.expression.aggregator.DistinctCountClientAggregator;
+import org.apache.phoenix.expression.aggregator.DistinctValueWithCountServerAggregator;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.util.SchemaUtil;
+
+
+/**
+ *
+ * Built-in function for COUNT(distinct <expression>) aggregate function,
+ *
+ * @author anoopsjohn
+ * @since 1.2.1
+ */
+@BuiltInFunction(name=DistinctCountAggregateFunction.NAME, args= {@Argument()} )
+public class DistinctCountAggregateFunction extends DelegateConstantToCountAggregateFunction {
+ public static final String NAME = "DISTINCT_COUNT";
+ public static final String NORMALIZED_NAME = SchemaUtil.normalizeIdentifier(NAME);
+ public final static byte[] ZERO = PDataType.LONG.toBytes(0L);
+ public final static byte[] ONE = PDataType.LONG.toBytes(1L);
+
+ public DistinctCountAggregateFunction() {
+ }
+
+ public DistinctCountAggregateFunction(List<Expression> childExpressions) {
+ this(childExpressions, null);
+ }
+
+ public DistinctCountAggregateFunction(List<Expression> childExpressions,
+ CountAggregateFunction delegate) {
+ super(childExpressions, delegate);
+ assert childExpressions.size() == 1;
+ }
+
+ @Override
+ public int hashCode() {
+ return isConstantExpression() ? 0 : super.hashCode();
+ }
+
+ /**
+ * The COUNT function never returns null
+ */
+ @Override
+ public boolean isNullable() {
+ return false;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ DistinctCountAggregateFunction other = (DistinctCountAggregateFunction)obj;
+ return (isConstantExpression() && other.isConstantExpression()) || children.equals(other.getChildren());
+ }
+
+ @Override
+ public PDataType getDataType() {
+ return PDataType.LONG;
+ }
+
+ @Override
+ public DistinctCountClientAggregator newClientAggregator() {
+ return new DistinctCountClientAggregator(getAggregatorExpression().getColumnModifier());
+ }
+
+ @Override
+ public Aggregator newServerAggregator(Configuration conf) {
+ return new DistinctValueWithCountServerAggregator(conf);
+ }
+
+ @Override
+ public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+ // TODO: optimize query plan of this to run scan serially for a limit of one row
+ if (!super.evaluate(tuple, ptr)) {
+ ptr.set(ZERO); // If evaluate returns false, then no rows were found, so result is 0
+ } else if (isConstantExpression()) {
+ ptr.set(ONE); // Otherwise, we found one or more rows, so a distinct on a constant is 1
+ }
+ return true; // Always evaluates to a LONG value
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public Aggregator newServerAggregator(Configuration config, ImmutableBytesWritable ptr) {
+ DistinctCountClientAggregator clientAgg = newClientAggregator();
+ clientAgg.aggregate(null, ptr);
+ return new DistinctValueWithCountServerAggregator(config, clientAgg);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DistinctValueWithCountAggregateFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DistinctValueWithCountAggregateFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DistinctValueWithCountAggregateFunction.java
new file mode 100644
index 0000000..b12c96a
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DistinctValueWithCountAggregateFunction.java
@@ -0,0 +1,50 @@
+/*
+ * 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.function;
+
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.aggregator.Aggregator;
+import org.apache.phoenix.expression.aggregator.DistinctValueWithCountClientAggregator;
+import org.apache.phoenix.expression.aggregator.DistinctValueWithCountServerAggregator;
+
+public abstract class DistinctValueWithCountAggregateFunction extends SingleAggregateFunction {
+
+ public DistinctValueWithCountAggregateFunction() {
+ }
+
+ public DistinctValueWithCountAggregateFunction(List<Expression> children) {
+ super(children);
+ }
+
+ @Override
+ abstract public DistinctValueWithCountClientAggregator newClientAggregator();
+
+ @Override
+ public Aggregator newServerAggregator(Configuration config, ImmutableBytesWritable ptr) {
+ DistinctValueWithCountClientAggregator clientAgg = newClientAggregator();
+ clientAgg.aggregate(null, ptr);
+ return new DistinctValueWithCountServerAggregator(config, clientAgg);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDateExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDateExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDateExpression.java
new file mode 100644
index 0000000..bfc3969
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDateExpression.java
@@ -0,0 +1,88 @@
+/*
+ * 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.function;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import com.google.common.collect.Lists;
+import org.apache.phoenix.expression.CoerceExpression;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.schema.PDataType;
+
+/**
+ *
+ * Class encapsulating the FLOOR operation on
+ * a column/literal of type {@link org.apache.phoenix.schema.PDataType#DATE}.
+ *
+ * @author samarth.jain
+ * @since 3.0.0
+ */
+public class FloorDateExpression extends RoundDateExpression {
+
+ public FloorDateExpression() {}
+
+ private FloorDateExpression(List<Expression> children) {
+ super(children);
+ }
+
+ public static Expression create(List<Expression> children) throws SQLException {
+ Expression firstChild = children.get(0);
+ PDataType firstChildDataType = firstChild.getDataType();
+ if (firstChildDataType == PDataType.TIMESTAMP || firstChildDataType == PDataType.UNSIGNED_TIMESTAMP){
+ // Coerce TIMESTAMP to DATE, as the nanos has no affect
+ List<Expression> newChildren = Lists.newArrayListWithExpectedSize(children.size());
+ newChildren.add(CoerceExpression.create(firstChild, firstChildDataType == PDataType.TIMESTAMP ? PDataType.DATE : PDataType.UNSIGNED_DATE));
+ newChildren.addAll(children.subList(1, children.size()));
+ children = newChildren;
+ }
+ return new FloorDateExpression(children);
+ }
+
+ /**
+ * @param timeUnit - unit of time to round up to.
+ * Creates a {@link FloorDateExpression} with default multiplier of 1.
+ */
+ public static Expression create(Expression expr, TimeUnit timeUnit) throws SQLException {
+ return create(expr, timeUnit, 1);
+ }
+
+ /**
+ * @param timeUnit - unit of time to round up to
+ * @param multiplier - determines the roll up window size.
+ * Create a {@link FloorDateExpression}.
+ */
+ public static Expression create(Expression expr, TimeUnit timeUnit, int multiplier) throws SQLException {
+ Expression timeUnitExpr = getTimeUnitExpr(timeUnit);
+ Expression defaultMultiplierExpr = getMultiplierExpr(multiplier);
+ List<Expression> expressions = Lists.newArrayList(expr, timeUnitExpr, defaultMultiplierExpr);
+ return create(expressions);
+ }
+
+ @Override
+ protected long getRoundUpAmount() {
+ return 0;
+ }
+
+ @Override
+ public String getName() {
+ return FloorFunction.NAME;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDecimalExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDecimalExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDecimalExpression.java
new file mode 100644
index 0000000..e8353f2
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorDecimalExpression.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.function;
+
+import java.math.RoundingMode;
+import java.sql.SQLException;
+import java.util.List;
+
+import com.google.common.collect.Lists;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.LiteralExpression;
+import org.apache.phoenix.schema.PDataType;
+
+/**
+ *
+ * Class encapsulating the FLOOR operation on
+ * a column/literal of type {@link org.apache.phoenix.schema.PDataType#DECIMAL}.
+ *
+ * @author samarth.jain
+ * @since 3.0.0
+ */
+public class FloorDecimalExpression extends RoundDecimalExpression {
+
+ public FloorDecimalExpression() {}
+
+ public FloorDecimalExpression(List<Expression> children) {
+ super(children);
+ }
+
+ /**
+ * Creates a {@link FloorDecimalExpression} with rounding scale given by @param scale.
+ *
+ */
+ public static Expression create(Expression expr, int scale) throws SQLException {
+ if (expr.getDataType().isCoercibleTo(PDataType.LONG)) {
+ return expr;
+ }
+ Expression scaleExpr = LiteralExpression.newConstant(scale, PDataType.INTEGER, true);
+ List<Expression> expressions = Lists.newArrayList(expr, scaleExpr);
+ return new FloorDecimalExpression(expressions);
+ }
+
+ /**
+ * Creates a {@link FloorDecimalExpression} with a default scale of 0 used for rounding.
+ *
+ */
+ public static Expression create(Expression expr) throws SQLException {
+ return create(expr, 0);
+ }
+
+ @Override
+ protected RoundingMode getRoundingMode() {
+ return RoundingMode.FLOOR;
+ }
+
+ @Override
+ public String getName() {
+ return FloorFunction.NAME;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorFunction.java
new file mode 100644
index 0000000..cceb966
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FloorFunction.java
@@ -0,0 +1,56 @@
+/*
+ * 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.function;
+
+import java.util.List;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FloorParseNode;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.PDataType;
+/**
+ *
+ * Base class for built-in FLOOR function.
+ *
+ * @author samarth.jain
+ * @since 3.0.0
+ */
+@BuiltInFunction(name = FloorFunction.NAME,
+ nodeClass = FloorParseNode.class,
+ args = {
+ @Argument(allowedTypes={PDataType.TIMESTAMP, PDataType.DECIMAL}),
+ @Argument(allowedTypes={PDataType.VARCHAR, PDataType.INTEGER}, defaultValue = "null", isConstant=true),
+ @Argument(allowedTypes={PDataType.INTEGER}, defaultValue="1", isConstant=true)
+ }
+ )
+public abstract class FloorFunction extends ScalarFunction {
+
+ public static final String NAME = "FLOOR";
+
+ public FloorFunction(List<Expression> children) {
+ super(children);
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FunctionArgumentType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FunctionArgumentType.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FunctionArgumentType.java
new file mode 100644
index 0000000..0284caf
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FunctionArgumentType.java
@@ -0,0 +1,35 @@
+package org.apache.phoenix.expression.function;
+
+import java.text.DecimalFormat;
+import java.text.Format;
+
+import org.apache.phoenix.util.DateUtil;
+
+public enum FunctionArgumentType {
+ TEMPORAL {
+ @Override
+ public Format getFormatter(String format) {
+ return DateUtil.getDateFormatter(format);
+ }
+ },
+ NUMERIC {
+ @Override
+ public Format getFormatter(String format) {
+ return new DecimalFormat(format);
+ }
+ },
+ CHAR {
+ @Override
+ public Format getFormatter(String format) {
+ return getDecimalFormat(format);
+ }
+ };
+
+ public abstract Format getFormatter(String format);
+
+ private static DecimalFormat getDecimalFormat(String formatString) {
+ DecimalFormat result = new DecimalFormat(formatString);
+ result.setParseBigDecimal(true);
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/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
new file mode 100644
index 0000000..db305d3
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/FunctionExpression.java
@@ -0,0 +1,71 @@
+/*
+ * 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.function;
+
+import java.util.List;
+
+import org.apache.phoenix.expression.BaseCompoundExpression;
+import org.apache.phoenix.expression.Expression;
+
+/**
+ *
+ * Compiled representation of a built-in function
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public abstract class FunctionExpression extends BaseCompoundExpression {
+ public enum OrderPreserving {NO, YES_IF_LAST, YES};
+ public FunctionExpression() {
+ }
+
+ public FunctionExpression(List<Expression> children) {
+ super(children);
+ }
+
+ /**
+ * Determines whether or not the result of the function invocation
+ * will be ordered in the same way as the input to the function.
+ * Returning YES enables an optimization to occur when a
+ * GROUP BY contains function invocations using the leading PK
+ * column(s).
+ * @return YES if the function invocation will always preserve order for
+ * the inputs versus the outputs and false otherwise, YES_IF_LAST if the
+ * function preserves order, but any further column reference would not
+ * continue to preserve order, and NO if the function does not preserve
+ * order.
+ */
+ public OrderPreserving preservesOrder() {
+ return OrderPreserving.NO;
+ }
+
+ abstract public String getName();
+
+ @Override
+ public final String toString() {
+ StringBuilder buf = new StringBuilder(getName() + "(");
+ for (int i = 0; i < children.size() - 1; i++) {
+ buf.append(children.get(i) + ", ");
+ }
+ buf.append(children.get(children.size()-1) + ")");
+ return buf.toString();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/IndexStateNameFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/IndexStateNameFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/IndexStateNameFunction.java
new file mode 100644
index 0000000..41890bc
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/IndexStateNameFunction.java
@@ -0,0 +1,81 @@
+/*
+ * 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.function;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.PIndexState;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+
+/**
+ *
+ * Function used to get the index state name from the serialized byte value
+ * Usage:
+ * IndexStateName('a')
+ * will return 'ACTIVE'
+ *
+ * @author jtaylor
+ * @since 2.1
+ */
+@BuiltInFunction(name=IndexStateNameFunction.NAME, args= {
+ @Argument(allowedTypes=PDataType.CHAR)} )
+public class IndexStateNameFunction extends ScalarFunction {
+ public static final String NAME = "IndexStateName";
+
+ public IndexStateNameFunction() {
+ }
+
+ public IndexStateNameFunction(List<Expression> children) throws SQLException {
+ super(children);
+ }
+
+ @Override
+ public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+ Expression child = children.get(0);
+ if (!child.evaluate(tuple, ptr)) {
+ return false;
+ }
+ if (ptr.getLength() == 0) {
+ return true;
+ }
+ byte serializedByte = ptr.get()[ptr.getOffset()];
+ PIndexState indexState = PIndexState.fromSerializedValue(serializedByte);
+ ptr.set(indexState.toBytes());
+ return true;
+ }
+
+ @Override
+ public PDataType getDataType() {
+ return PDataType.VARCHAR;
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InvertFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InvertFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InvertFunction.java
new file mode 100644
index 0000000..72ac31a
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InvertFunction.java
@@ -0,0 +1,129 @@
+/*
+ * 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.function;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.compile.KeyPart;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.query.KeyRange;
+import org.apache.phoenix.schema.ColumnModifier;
+import org.apache.phoenix.schema.PColumn;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+@BuiltInFunction(name = InvertFunction.NAME, args = { @Argument() })
+public class InvertFunction extends ScalarFunction {
+ public static final String NAME = "INVERT";
+
+ public InvertFunction() throws SQLException {}
+
+ public InvertFunction(List<Expression> children) throws SQLException {
+ super(children);
+ }
+
+ @Override
+ public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+ if (!getChildExpression().evaluate(tuple, ptr)) { return false; }
+ if (ptr.getLength() == 0) { return true; }
+ byte[] buf = new byte[ptr.getLength()];
+ ColumnModifier.SORT_DESC.apply(ptr.get(), ptr.getOffset(), buf, 0, ptr.getLength());
+ ptr.set(buf);
+ return true;
+ }
+
+ @Override
+ public ColumnModifier getColumnModifier() {
+ return getChildExpression().getColumnModifier() == null ? ColumnModifier.SORT_DESC : null;
+ }
+
+ @Override
+ public PDataType getDataType() {
+ return getChildExpression().getDataType();
+ }
+
+ @Override
+ public Integer getMaxLength() {
+ return getChildExpression().getMaxLength();
+ }
+
+ @Override
+ public Integer getByteSize() {
+ return getChildExpression().getByteSize();
+ }
+
+ @Override
+ public boolean isNullable() {
+ return getChildExpression().isNullable();
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ /**
+ * INVERT may be optimized through
+ */
+ @Override
+ public int getKeyFormationTraversalIndex() {
+ return 0;
+ }
+
+ /**
+ * Invert the childPart key range
+ */
+ @Override
+ public KeyPart newKeyPart(final KeyPart childPart) {
+ return new KeyPart() {
+
+ @Override
+ public KeyRange getKeyRange(CompareOp op, Expression rhs) {
+ KeyRange range = childPart.getKeyRange(op, rhs);
+ return range.invert();
+ }
+
+ @Override
+ public List<Expression> getExtractNodes() {
+ return childPart.getExtractNodes();
+ }
+
+ @Override
+ public PColumn getColumn() {
+ return childPart.getColumn();
+ }
+ };
+ }
+
+ @Override
+ public OrderPreserving preservesOrder() {
+ return OrderPreserving.YES;
+ }
+
+ private Expression getChildExpression() {
+ return children.get(0);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LTrimFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LTrimFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LTrimFunction.java
new file mode 100644
index 0000000..1622f55
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LTrimFunction.java
@@ -0,0 +1,115 @@
+/*
+ * 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.function;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+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 of the LTrim(<string>) build-in function. It removes from the left end of
+ * <string> space character and other function bytes in single byte utf8 characters
+ * set.
+ *
+ * @author zhuang
+ * @since 0.1
+ */
+@BuiltInFunction(name=LTrimFunction.NAME, args={
+ @Argument(allowedTypes={PDataType.VARCHAR})})
+public class LTrimFunction extends ScalarFunction {
+ public static final String NAME = "LTRIM";
+
+ private Integer byteSize;
+
+ public LTrimFunction() { }
+
+ public LTrimFunction(List<Expression> children) throws SQLException {
+ super(children);
+ if (getStringExpression().getDataType().isFixedWidth()) {
+ byteSize = getStringExpression().getByteSize();
+ }
+ }
+
+ private Expression getStringExpression() {
+ return children.get(0);
+ }
+
+ @Override
+ public ColumnModifier getColumnModifier() {
+ return children.get(0).getColumnModifier();
+ }
+
+ @Override
+ public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+ // Starting from the front of the byte, look for all single bytes at the end of the string
+ // that is below SPACE_UTF8 (space and control characters) or 0x7f (control chars).
+ if (!getStringExpression().evaluate(tuple, ptr)) {
+ return false;
+ }
+
+ if (ptr.getLength() == 0) {
+ ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
+ return true;
+ }
+ byte[] string = ptr.get();
+ int offset = ptr.getOffset();
+ int length = ptr.getLength();
+
+ ColumnModifier columnModifier = getStringExpression().getColumnModifier();
+ // TODO: when we have ColumnModifier.REVERSE, we'll need to trim from the end instead of
+ // the beginning (just delegate to RTrimFunction or replace from ExpressionCompiler instead?)
+ int i = StringUtil.getFirstNonBlankCharIdxFromStart(string, offset, length, columnModifier);
+ if (i == offset + length) {
+ ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
+ return true;
+ }
+
+ ptr.set(string, i, offset + length - i);
+ return true;
+ }
+
+ @Override
+ public Integer getByteSize() {
+ return byteSize;
+ }
+
+ @Override
+ public PDataType getDataType() {
+ return PDataType.VARCHAR;
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LengthFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LengthFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LengthFunction.java
new file mode 100644
index 0000000..770f77a
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/LengthFunction.java
@@ -0,0 +1,96 @@
+/*
+ * 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.function;
+
+import java.io.UnsupportedEncodingException;
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+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 of the LENGTH(<string>) build-in function. <string> is the string
+ * of characters we want to find the length of. If <string> is NULL or empty, null
+ * is returned.
+ *
+ * @author zhuang
+ * @since 0.1
+ */
+@BuiltInFunction(name=LengthFunction.NAME, args={
+ @Argument(allowedTypes={PDataType.VARCHAR})} )
+public class LengthFunction extends ScalarFunction {
+ public static final String NAME = "LENGTH";
+
+ public LengthFunction() { }
+
+ public LengthFunction(List<Expression> children) throws SQLException {
+ super(children);
+ }
+
+ private Expression getStringExpression() {
+ return children.get(0);
+ }
+
+ @Override
+ public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+ Expression child = getStringExpression();
+ if (!child.evaluate(tuple, ptr)) {
+ return false;
+ }
+ if (ptr.getLength() == 0) {
+ ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
+ return true;
+ }
+ int len;
+ if (child.getDataType() == PDataType.CHAR) {
+ // Only single-byte characters allowed in CHAR
+ len = ptr.getLength();
+ } else {
+ try {
+ len = StringUtil.calculateUTF8Length(ptr.get(), ptr.getOffset(), ptr.getLength(), child.getColumnModifier());
+ } catch (UnsupportedEncodingException e) {
+ return false;
+ }
+ }
+ ptr.set(PDataType.INTEGER.toBytes(len));
+ return true;
+ }
+
+ @Override
+ public PDataType getDataType() {
+ return PDataType.INTEGER;
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MaxAggregateFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MaxAggregateFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MaxAggregateFunction.java
new file mode 100644
index 0000000..72e5984
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MaxAggregateFunction.java
@@ -0,0 +1,75 @@
+/*
+ * 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.function;
+
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.aggregator.Aggregator;
+import org.apache.phoenix.expression.aggregator.MaxAggregator;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.parse.MaxAggregateParseNode;
+import org.apache.phoenix.schema.ColumnModifier;
+import org.apache.phoenix.schema.PDataType;
+
+
+
+/**
+ * Built-in function for finding MAX.
+ *
+ * @author syyang
+ * @since 0.1
+ */
+@BuiltInFunction(name=MaxAggregateFunction.NAME, nodeClass=MaxAggregateParseNode.class, args= {@Argument()} )
+public class MaxAggregateFunction extends MinAggregateFunction {
+ public static final String NAME = "MAX";
+
+ public MaxAggregateFunction() {
+ }
+
+ public MaxAggregateFunction(List<Expression> childExpressions, CountAggregateFunction delegate) {
+ super(childExpressions, delegate);
+ }
+
+ @Override
+ public Aggregator newServerAggregator(Configuration conf) {
+ final PDataType type = getAggregatorExpression().getDataType();
+ ColumnModifier columnModifier = getAggregatorExpression().getColumnModifier();
+ return new MaxAggregator(columnModifier) {
+ @Override
+ public PDataType getDataType() {
+ return type;
+ }
+ };
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public ColumnModifier getColumnModifier() {
+ return getAggregatorExpression().getColumnModifier();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MinAggregateFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MinAggregateFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MinAggregateFunction.java
new file mode 100644
index 0000000..26e8fd9
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MinAggregateFunction.java
@@ -0,0 +1,89 @@
+/*
+ * 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.function;
+
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.aggregator.Aggregator;
+import org.apache.phoenix.expression.aggregator.MinAggregator;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.parse.MinAggregateParseNode;
+import org.apache.phoenix.schema.ColumnModifier;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+
+
+/**
+ * Built-in function for finding MIN.
+ *
+ * @author syyang
+ * @since 0.1
+ */
+@BuiltInFunction(name=MinAggregateFunction.NAME, nodeClass=MinAggregateParseNode.class, args= {@Argument()} )
+public class MinAggregateFunction extends DelegateConstantToCountAggregateFunction {
+ public static final String NAME = "MIN";
+
+ public MinAggregateFunction() {
+ }
+
+ public MinAggregateFunction(List<Expression> childExpressions, CountAggregateFunction delegate) {
+ super(childExpressions, delegate);
+ }
+
+ @Override
+ public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+ boolean wasEvaluated = super.evaluate(tuple, ptr);
+ if (!wasEvaluated) {
+ return false;
+ }
+ if (isConstantExpression()) {
+ getAggregatorExpression().evaluate(tuple, ptr);
+ }
+ return true;
+ }
+
+ @Override
+ public Aggregator newServerAggregator(Configuration conf) {
+ final PDataType type = getAggregatorExpression().getDataType();
+ ColumnModifier columnModifier = getAggregatorExpression().getColumnModifier();
+ return new MinAggregator(columnModifier) {
+ @Override
+ public PDataType getDataType() {
+ return type;
+ }
+ };
+ }
+
+ @Override
+ public ColumnModifier getColumnModifier() {
+ return getAggregatorExpression().getColumnModifier();
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PercentRankAggregateFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PercentRankAggregateFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PercentRankAggregateFunction.java
new file mode 100644
index 0000000..bf6c975
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PercentRankAggregateFunction.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.function;
+
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.aggregator.Aggregator;
+import org.apache.phoenix.expression.aggregator.DistinctValueWithCountClientAggregator;
+import org.apache.phoenix.expression.aggregator.DistinctValueWithCountServerAggregator;
+import org.apache.phoenix.expression.aggregator.PercentRankClientAggregator;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.PDataType;
+
+/**
+ *
+ * PERCENT_RANK(<expression>[,<expression>]) WITHIN GROUP (ORDER BY <expression>[,<expression>] ASC/DESC) aggregate function
+ *
+ * @author anoopsjohn
+ * @since 1.2.1
+ */
+@BuiltInFunction(name = PercentRankAggregateFunction.NAME, args = { @Argument(),
+ @Argument(allowedTypes = { PDataType.BOOLEAN }, isConstant = true), @Argument(isConstant = true) })
+public class PercentRankAggregateFunction extends DistinctValueWithCountAggregateFunction {
+ public static final String NAME = "PERCENT_RANK";
+
+ public PercentRankAggregateFunction() {
+
+ }
+
+ public PercentRankAggregateFunction(List<Expression> childern) {
+ super(childern);
+ }
+
+ @Override
+ public Aggregator newServerAggregator(Configuration conf) {
+ return new DistinctValueWithCountServerAggregator(conf);
+ }
+
+ @Override
+ public DistinctValueWithCountClientAggregator newClientAggregator() {
+ return new PercentRankClientAggregator(children, getAggregatorExpression().getColumnModifier());
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public PDataType getDataType() {
+ return PDataType.DECIMAL;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PercentileContAggregateFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PercentileContAggregateFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PercentileContAggregateFunction.java
new file mode 100644
index 0000000..703d619
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PercentileContAggregateFunction.java
@@ -0,0 +1,75 @@
+/*
+ * 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.function;
+
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.aggregator.Aggregator;
+import org.apache.phoenix.expression.aggregator.DistinctValueWithCountClientAggregator;
+import org.apache.phoenix.expression.aggregator.DistinctValueWithCountServerAggregator;
+import org.apache.phoenix.expression.aggregator.PercentileClientAggregator;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.PDataType;
+
+/**
+ *
+ * Built-in function for PERCENTILE_CONT(<expression>) WITHIN GROUP (ORDER BY <expression> ASC/DESC) aggregate function
+ *
+ * @author anoopsjohn
+ * @since 1.2.1
+ */
+@BuiltInFunction(name = PercentileContAggregateFunction.NAME, args = { @Argument(allowedTypes = { PDataType.DECIMAL }),
+ @Argument(allowedTypes = { PDataType.BOOLEAN }, isConstant = true),
+ @Argument(allowedTypes = { PDataType.DECIMAL }, isConstant = true, minValue = "0", maxValue = "1") })
+public class PercentileContAggregateFunction extends DistinctValueWithCountAggregateFunction {
+ public static final String NAME = "PERCENTILE_CONT";
+
+ public PercentileContAggregateFunction() {
+
+ }
+
+ public PercentileContAggregateFunction(List<Expression> childern) {
+ super(childern);
+ }
+
+ @Override
+ public Aggregator newServerAggregator(Configuration conf) {
+ return new DistinctValueWithCountServerAggregator(conf);
+ }
+
+ @Override
+ public DistinctValueWithCountClientAggregator newClientAggregator() {
+ return new PercentileClientAggregator(children, getAggregatorExpression().getColumnModifier());
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public PDataType getDataType() {
+ return PDataType.DECIMAL;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PercentileDiscAggregateFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PercentileDiscAggregateFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PercentileDiscAggregateFunction.java
new file mode 100644
index 0000000..7909c41
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PercentileDiscAggregateFunction.java
@@ -0,0 +1,72 @@
+/*
+ * 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.function;
+
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.aggregator.Aggregator;
+import org.apache.phoenix.expression.aggregator.DistinctValueWithCountClientAggregator;
+import org.apache.phoenix.expression.aggregator.DistinctValueWithCountServerAggregator;
+import org.apache.phoenix.expression.aggregator.PercentileDiscClientAggregator;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.schema.PDataType;
+
+
+/**
+ *
+ * Built-in function for PERCENTILE_DISC(<expression>) WITHIN GROUP (ORDER BY <expression> ASC/DESC) aggregate function
+ *
+ * @author ramkrishna
+ * @since 1.2.1
+ */
+@BuiltInFunction(name = PercentileDiscAggregateFunction.NAME, args = { @Argument(allowedTypes = { PDataType.DECIMAL }),
+ @Argument(allowedTypes = { PDataType.BOOLEAN }, isConstant = true),
+ @Argument(allowedTypes = { PDataType.DECIMAL }, isConstant = true, minValue = "0", maxValue = "1") })
+public class PercentileDiscAggregateFunction extends DistinctValueWithCountAggregateFunction {
+
+ public static final String NAME = "PERCENTILE_DISC";
+
+ public PercentileDiscAggregateFunction() {
+ }
+
+ public PercentileDiscAggregateFunction(List<Expression> childern) {
+ super(childern);
+ }
+
+ @Override
+ public Aggregator newServerAggregator(Configuration conf) {
+ return new DistinctValueWithCountServerAggregator(conf);
+ }
+
+ @Override
+ public DistinctValueWithCountClientAggregator newClientAggregator() {
+ return new PercentileDiscClientAggregator(children, getAggregatorExpression().getColumnModifier());
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PrefixFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PrefixFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PrefixFunction.java
new file mode 100644
index 0000000..2612d74
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/PrefixFunction.java
@@ -0,0 +1,83 @@
+package org.apache.phoenix.expression.function;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.compile.KeyPart;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.query.KeyRange;
+import org.apache.phoenix.schema.PColumn;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.util.ByteUtil;
+
+abstract public class PrefixFunction extends ScalarFunction {
+ public PrefixFunction() {
+ }
+
+ public PrefixFunction(List<Expression> children) {
+ super(children);
+ }
+
+ @Override
+ public int getKeyFormationTraversalIndex() {
+ return preservesOrder() == OrderPreserving.NO ? NO_TRAVERSAL : 0;
+ }
+
+ protected boolean extractNode() {
+ return false;
+ }
+
+ private static byte[] evaluateExpression(Expression rhs) {
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ rhs.evaluate(null, ptr);
+ byte[] key = ByteUtil.copyKeyBytesIfNecessary(ptr);
+ return key;
+ }
+
+ @Override
+ public KeyPart newKeyPart(final KeyPart childPart) {
+ return new KeyPart() {
+ private final List<Expression> extractNodes = extractNode() ? Collections.<Expression>singletonList(PrefixFunction.this) : Collections.<Expression>emptyList();
+
+ @Override
+ public PColumn getColumn() {
+ return childPart.getColumn();
+ }
+
+ @Override
+ public List<Expression> getExtractNodes() {
+ return extractNodes;
+ }
+
+ @Override
+ public KeyRange getKeyRange(CompareOp op, Expression rhs) {
+ byte[] key;
+ KeyRange range;
+ PDataType type = getColumn().getDataType();
+ switch (op) {
+ case EQUAL:
+ key = evaluateExpression(rhs);
+ range = type.getKeyRange(key, true, ByteUtil.nextKey(key), false);
+ break;
+ case GREATER:
+ key = evaluateExpression(rhs);
+ range = type.getKeyRange(ByteUtil.nextKey(key), true, KeyRange.UNBOUND, false);
+ break;
+ case LESS_OR_EQUAL:
+ key = evaluateExpression(rhs);
+ range = type.getKeyRange(KeyRange.UNBOUND, false, ByteUtil.nextKey(key), false);
+ break;
+ default:
+ return childPart.getKeyRange(op, rhs);
+ }
+ Integer length = getColumn().getByteSize();
+ return length == null ? range : range.fill(length);
+ }
+ };
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RTrimFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RTrimFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RTrimFunction.java
new file mode 100644
index 0000000..d7702a5
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RTrimFunction.java
@@ -0,0 +1,161 @@
+/*
+ * 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.function;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+import org.apache.phoenix.compile.KeyPart;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode.Argument;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.query.KeyRange;
+import org.apache.phoenix.schema.ColumnModifier;
+import org.apache.phoenix.schema.PColumn;
+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 of the RTrim(<string>) build-in function. It removes from the right end of
+ * <string> space character and other function bytes in single byte utf8 characters set
+ *
+ * @author zhuang
+ * @since 0.1
+ */
+@BuiltInFunction(name=RTrimFunction.NAME, args={
+ @Argument(allowedTypes={PDataType.VARCHAR})})
+public class RTrimFunction extends ScalarFunction {
+ public static final String NAME = "RTRIM";
+
+ private Integer byteSize;
+
+ public RTrimFunction() { }
+
+ public RTrimFunction(List<Expression> children) throws SQLException {
+ super(children);
+ if (getStringExpression().getDataType().isFixedWidth()) {
+ byteSize = getStringExpression().getByteSize();
+ }
+ }
+
+ private Expression getStringExpression() {
+ return children.get(0);
+ }
+
+ @Override
+ public ColumnModifier getColumnModifier() {
+ return children.get(0).getColumnModifier();
+ }
+
+ @Override
+ public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+ // Starting from the end of the byte, look for all single bytes at the end of the string
+ // that is below SPACE_UTF8 (space and control characters) or above (control chars).
+ if (!getStringExpression().evaluate(tuple, ptr)) {
+ return false;
+ }
+ if (ptr.getLength() == 0) {
+ ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
+ return true;
+ }
+ byte[] string = ptr.get();
+ int offset = ptr.getOffset();
+ int length = ptr.getLength();
+
+ ColumnModifier columnModifier = getStringExpression().getColumnModifier();
+ int i = StringUtil.getFirstNonBlankCharIdxFromEnd(string, offset, length, columnModifier);
+ if (i == offset - 1) {
+ ptr.set(ByteUtil.EMPTY_BYTE_ARRAY);
+ return true;
+ }
+ ptr.set(string, offset, i - offset + 1);
+ return true;
+ }
+
+ @Override
+ public OrderPreserving preservesOrder() {
+ return OrderPreserving.YES_IF_LAST;
+ }
+
+ @Override
+ public int getKeyFormationTraversalIndex() {
+ return 0;
+ }
+
+ @Override
+ public KeyPart newKeyPart(final KeyPart childPart) {
+ return new KeyPart() {
+ @Override
+ public KeyRange getKeyRange(CompareOp op, Expression rhs) {
+ ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+ rhs.evaluate(null, ptr);
+ byte[] key = ByteUtil.copyKeyBytesIfNecessary(ptr);
+ PDataType type = getColumn().getDataType();
+ KeyRange range;
+ switch (op) {
+ case EQUAL:
+ range = type.getKeyRange(key, true, ByteUtil.nextKey(ByteUtil.concat(key, new byte[] {StringUtil.SPACE_UTF8})), false);
+ break;
+ case LESS_OR_EQUAL:
+ range = type.getKeyRange(KeyRange.UNBOUND, false, ByteUtil.nextKey(ByteUtil.concat(key, new byte[] {StringUtil.SPACE_UTF8})), false);
+ break;
+ default:
+ range = childPart.getKeyRange(op, rhs);
+ break;
+ }
+ Integer length = getColumn().getByteSize();
+ return length == null ? range : range.fill(length);
+ }
+
+ @Override
+ public List<Expression> getExtractNodes() {
+ return Collections.<Expression>emptyList();
+ }
+
+ @Override
+ public PColumn getColumn() {
+ return childPart.getColumn();
+ }
+ };
+ }
+
+ @Override
+ public Integer getByteSize() {
+ return byteSize;
+ }
+
+ @Override
+ public PDataType getDataType() {
+ return PDataType.VARCHAR;
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/50d523f6/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RegexpReplaceFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RegexpReplaceFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RegexpReplaceFunction.java
new file mode 100644
index 0000000..1f0e28e
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RegexpReplaceFunction.java
@@ -0,0 +1,130 @@
+/*
+ * 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.function;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+
+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.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+
+/**
+ *
+ * Function similar to the regexp_replace function in Postgres, which is used to pattern
+ * match a segment of the string. Usage:
+ * REGEXP_REPLACE(<source_char>,<pattern>,<replace_string>)
+ * source_char is the string in which we want to perform string replacement. pattern is a
+ * Java compatible regular expression string, and we replace all the matching part with
+ * replace_string. The first 2 arguments are required and are {@link org.apache.phoenix.schema.PDataType#VARCHAR},
+ * the replace_string is default to empty string.
+ *
+ * The function returns a {@link org.apache.phoenix.schema.PDataType#VARCHAR}
+ *
+ * @author zhuang
+ * @since 0.1
+ */
+@BuiltInFunction(name=RegexpReplaceFunction.NAME, args= {
+ @Argument(allowedTypes={PDataType.VARCHAR}),
+ @Argument(allowedTypes={PDataType.VARCHAR}),
+ @Argument(allowedTypes={PDataType.VARCHAR},defaultValue="null")} )
+public class RegexpReplaceFunction extends ScalarFunction {
+ public static final String NAME = "REGEXP_REPLACE";
+
+ private boolean hasReplaceStr;
+ private Pattern pattern;
+
+ public RegexpReplaceFunction() { }
+
+ // Expect 1 arguments, the pattern.
+ public RegexpReplaceFunction(List<Expression> children) {
+ super(children);
+ init();
+ }
+
+ private void init() {
+ hasReplaceStr = ((LiteralExpression)getReplaceStrExpression()).getValue() != null;
+ Object patternString = ((LiteralExpression)children.get(1)).getValue();
+ if (patternString != null) {
+ pattern = Pattern.compile((String)patternString);
+ }
+ }
+
+ @Override
+ public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+ // Can't parse if there is no replacement pattern.
+ if (pattern == null) {
+ return false;
+ }
+ Expression sourceStrExpression = getSourceStrExpression();
+ if (!sourceStrExpression.evaluate(tuple, ptr)) {
+ return false;
+ }
+ String sourceStr = (String)PDataType.VARCHAR.toObject(ptr, sourceStrExpression.getColumnModifier());
+ if (sourceStr == null) {
+ return false;
+ }
+ String replaceStr;
+ if (hasReplaceStr) {
+ Expression replaceStrExpression = this.getReplaceStrExpression();
+ if (!replaceStrExpression.evaluate(tuple, ptr)) {
+ return false;
+ }
+ replaceStr = (String)PDataType.VARCHAR.toObject(ptr, replaceStrExpression.getColumnModifier());
+ } else {
+ replaceStr = "";
+ }
+ String replacedStr = pattern.matcher(sourceStr).replaceAll(replaceStr);
+ ptr.set(PDataType.VARCHAR.toBytes(replacedStr));
+ return true;
+ }
+
+ private Expression getSourceStrExpression() {
+ return children.get(0);
+ }
+
+ private Expression getReplaceStrExpression() {
+ return children.get(2);
+ }
+
+ @Override
+ public PDataType getDataType() {
+ return PDataType.VARCHAR;
+ }
+
+ @Override
+ public void readFields(DataInput input) throws IOException {
+ super.readFields(input);
+ init();
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+}