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