phoenix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ramkris...@apache.org
Subject git commit: Phoenix-952 Support ANY and ALL built-ins for ARRAYs (Ram)
Date Fri, 04 Jul 2014 09:40:00 GMT
Repository: phoenix
Updated Branches:
  refs/heads/4.0 686c17548 -> 8496d76ac


Phoenix-952 Support ANY and ALL built-ins for ARRAYs (Ram)


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/8496d76a
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/8496d76a
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/8496d76a

Branch: refs/heads/4.0
Commit: 8496d76ac0de2f2f3916b1a8d2c5870eb85bf969
Parents: 686c175
Author: Ramkrishna <ramkrishna.s.vasudevan@intel.com>
Authored: Fri Jul 4 15:09:14 2014 +0530
Committer: Ramkrishna <ramkrishna.s.vasudevan@intel.com>
Committed: Fri Jul 4 15:09:14 2014 +0530

----------------------------------------------------------------------
 .../org/apache/phoenix/end2end/ArrayIT.java     | 179 +++++++++++++++++++
 phoenix-core/src/main/antlr3/PhoenixSQL.g       |  19 +-
 .../phoenix/compile/ExpressionCompiler.java     |  35 ++++
 .../phoenix/compile/StatementNormalizer.java    |   4 +-
 .../phoenix/expression/ExpressionType.java      |   8 +-
 .../function/ArrayAllComparisonExpression.java  |  45 +++++
 .../function/ArrayAnyComparisonExpression.java  |  78 ++++++++
 .../expression/function/ArrayIndexFunction.java |  12 +-
 .../function/InlineArrayElemRefExpression.java  |  73 ++++++++
 .../phoenix/parse/ArrayAllComparisonNode.java   |  46 +++++
 .../phoenix/parse/ArrayAnyComparisonNode.java   |  46 +++++
 .../apache/phoenix/parse/ArrayElemRefNode.java  |  38 ++++
 .../apache/phoenix/parse/ParseNodeFactory.java  |  12 ++
 .../apache/phoenix/parse/ParseNodeRewriter.java |  18 +-
 .../apache/phoenix/parse/ParseNodeVisitor.java  |  11 ++
 .../parse/TraverseAllParseNodeVisitor.java      |  30 ++++
 .../parse/TraverseNoParseNodeVisitor.java       |  29 +++
 .../parse/UnsupportedAllParseNodeVisitor.java   |  20 +++
 .../apache/phoenix/schema/PArrayDataType.java   |  60 +++++++
 19 files changed, 741 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java
index bfff64a..47d7265 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java
@@ -364,7 +364,186 @@ public class ArrayIT extends BaseClientManagedTimeIT {
             }
         }
     }
+    
+    @Test
+    public void testArraySelectWithORCondition() throws Exception {
+        long ts = nextTimestamp();
+        String tenantId = getOrganizationId();
+        createTableWithArray(getUrl(), getDefaultSplits(tenantId), null, ts - 2);
+        Connection conn = null;
+        try {
+            createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null, ts - 2);
+            initSimpleArrayTable(tenantId, null, ts, false);
+            Properties props = new Properties(TEST_PROPERTIES);
+            props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at timestamp 2
+            conn = DriverManager.getConnection(getUrl(), props);
+            String query = "SELECT a_double_array[1]  FROM " + SIMPLE_TABLE_WITH_ARRAY
+                    + " WHERE a_double_array[2] = 89.96d or a_char_array[0] = 'a'";
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            Double[] doubleArr = new Double[1];
+            doubleArr[0] = 64.87d;
+            Double result = rs.getDouble(1);
+            assertEquals(result, doubleArr[0]);
+            assertFalse(rs.next());
 
+        } finally {
+            if (conn != null) {
+                conn.close();
+            }
+        }
+    }
+
+    @Test
+    public void testArraySelectWithANY() throws Exception {
+        long ts = nextTimestamp();
+        String tenantId = getOrganizationId();
+        createTableWithArray(getUrl(), getDefaultSplits(tenantId), null, ts - 2);
+        Connection conn = null;
+        try {
+            createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null, ts - 2);
+            initSimpleArrayTable(tenantId, null, ts, false);
+            Properties props = new Properties(TEST_PROPERTIES);
+            props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at timestamp 2
+            conn = DriverManager.getConnection(getUrl(), props);
+            String query = "SELECT a_double_array[1]  FROM " + SIMPLE_TABLE_WITH_ARRAY
+                    + " WHERE 89.96d = ANY(a_double_array)";
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            Double[] doubleArr = new Double[1];
+            doubleArr[0] = 64.87d;
+            Double result = rs.getDouble(1);
+            assertEquals(result, doubleArr[0]);
+            assertFalse(rs.next());
+        } finally {
+            if (conn != null) {
+                conn.close();
+            }
+        }
+    }
+
+    @Test
+    public void testArraySelectWithALL() throws Exception {
+        long ts = nextTimestamp();
+        String tenantId = getOrganizationId();
+        createTableWithArray(getUrl(), getDefaultSplits(tenantId), null, ts - 2);
+        Connection conn = null;
+        try {
+            createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null, ts - 2);
+            initSimpleArrayTable(tenantId, null, ts, false);
+            Properties props = new Properties(TEST_PROPERTIES);
+            props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at timestamp 2
+            conn = DriverManager.getConnection(getUrl(), props);
+            String query = "SELECT a_double_array[1]  FROM " + SIMPLE_TABLE_WITH_ARRAY
+                    + " WHERE 64.87d = ALL(a_double_array)";
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertFalse(rs.next());
+        } finally {
+            if (conn != null) {
+                conn.close();
+            }
+        }
+    }
+
+    @Test
+    public void testArraySelectWithANYCombinedWithOR() throws Exception {
+        long ts = nextTimestamp();
+        String tenantId = getOrganizationId();
+        createTableWithArray(getUrl(), getDefaultSplits(tenantId), null, ts - 2);
+        Connection conn = null;
+        try {
+            createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null, ts - 2);
+            initSimpleArrayTable(tenantId, null, ts, false);
+            Properties props = new Properties(TEST_PROPERTIES);
+            props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at timestamp 2
+            conn = DriverManager.getConnection(getUrl(), props);
+            String query = "SELECT a_double_array[1]  FROM " + SIMPLE_TABLE_WITH_ARRAY
+                    + " WHERE  a_char_array[0] = 'f' or 89.96d > ANY(a_double_array)";
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            Double[] doubleArr = new Double[1];
+            doubleArr[0] = 64.87d;
+            Double result = rs.getDouble(1);
+            assertEquals(result, doubleArr[0]);
+            assertFalse(rs.next());
+        } finally {
+            if (conn != null) {
+                conn.close();
+            }
+        }
+    }
+
+    @Test
+    public void testArraySelectWithALLCombinedWithOR() throws Exception {
+        long ts = nextTimestamp();
+        String tenantId = getOrganizationId();
+        createTableWithArray(getUrl(), getDefaultSplits(tenantId), null, ts - 2);
+        Connection conn = null;
+        try {
+            createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null, ts - 2);
+            initSimpleArrayTable(tenantId, null, ts, false);
+            Properties props = new Properties(TEST_PROPERTIES);
+            props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at timestamp 2
+            conn = DriverManager.getConnection(getUrl(), props);
+            String query = "SELECT a_double_array[1], a_double_array[2]  FROM " + SIMPLE_TABLE_WITH_ARRAY
+                    + " WHERE  a_char_array[0] = 'f' or 100.0d > ALL(a_double_array)";
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            Double[] doubleArr = new Double[1];
+            doubleArr[0] = 64.87d;
+            Double result = rs.getDouble(1);
+            assertEquals(result, doubleArr[0]);
+            doubleArr = new Double[1];
+            doubleArr[0] = 89.96d;
+            result = rs.getDouble(2);
+            assertEquals(result, doubleArr[0]);
+        } finally {
+            if (conn != null) {
+                conn.close();
+            }
+        }
+    }
+
+    @Test
+    public void testArraySelectWithANYUsingVarLengthArray() throws Exception {
+        Connection conn = null;
+        try {
+            long ts = nextTimestamp();
+            String tenantId = getOrganizationId();
+            createTableWithArray(getUrl(), getDefaultSplits(tenantId), null, ts - 2);
+            initTablesWithArrays(tenantId, null, ts, false, getUrl());
+            Properties props = new Properties(TEST_PROPERTIES);
+            props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at timestamp 2
+            conn = DriverManager.getConnection(getUrl(), props);
+            String query = "SELECT a_string_array[1]  FROM " + TABLE_WITH_ARRAY
+                    + " WHERE 'XYZWER' = ANY(a_string_array)";
+            PreparedStatement statement = conn.prepareStatement(query);
+            ResultSet rs = statement.executeQuery();
+            assertTrue(rs.next());
+            String[] strArr = new String[1];
+            strArr[0] = "ABC";
+            String result = rs.getString(1);
+            assertEquals(result, strArr[0]);
+            assertFalse(rs.next());
+            query = "SELECT a_string_array[1]  FROM " + TABLE_WITH_ARRAY + " WHERE 'AB' = ANY(a_string_array)";
+            statement = conn.prepareStatement(query);
+            rs = statement.executeQuery();
+            assertTrue(rs.next());
+            result = rs.getString(1);
+            assertEquals(result, strArr[0]);
+            assertFalse(rs.next());
+        } finally {
+            if (conn != null) {
+                conn.close();
+            }
+        }
+    }
+   
     @Test
     public void testSelectWithArrayWithColumnRef() throws Exception {
         long ts = nextTimestamp();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/antlr3/PhoenixSQL.g
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/antlr3/PhoenixSQL.g b/phoenix-core/src/main/antlr3/PhoenixSQL.g
index 13b824d..73dc98f 100644
--- a/phoenix-core/src/main/antlr3/PhoenixSQL.g
+++ b/phoenix-core/src/main/antlr3/PhoenixSQL.g
@@ -99,6 +99,8 @@ tokens
     FOR='for';
     CACHE='cache';
     DERIVE='derive';
+    ANY='any';
+    SOME='some';
 }
 
 
@@ -129,6 +131,7 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.ListMultimap;
 import org.apache.hadoop.hbase.util.Pair;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
 import java.math.BigDecimal;
 import java.util.Arrays;
 import java.util.Collections;
@@ -685,13 +688,17 @@ not_expression returns [ParseNode ret]
     |   n=NOT? LPAREN e=expression RPAREN { $ret = n == null ? e : factory.not(e); }
     ;
 
+comparison_op returns [CompareOp ret]
+	: EQ { $ret = CompareOp.EQUAL; }
+	| LT { $ret = CompareOp.LESS; }
+	| GT { $ret = CompareOp.GREATER; }
+	| LT EQ { $ret = CompareOp.LESS_OR_EQUAL; }
+	| GT EQ { $ret = CompareOp.GREATER_OR_EQUAL; }
+	| (NOEQ1 | NOEQ2) { $ret = CompareOp.NOT_EQUAL; }
+	;
+	
 boolean_expression returns [ParseNode ret]
-    :   l=value_expression ((EQ r=value_expression {$ret = factory.equal(l,r); } )
-                  |  ((NOEQ1 | NOEQ2) r=value_expression {$ret = factory.notEqual(l,r); } )
-                  |  (LT r=value_expression {$ret = factory.lt(l,r); } )
-                  |  (GT r=value_expression {$ret = factory.gt(l,r); } )
-                  |  (LT EQ r=value_expression {$ret = factory.lte(l,r); } )
-                  |  (GT EQ r=value_expression {$ret = factory.gte(l,r); } )
+    :   l=value_expression ((op=comparison_op (r=value_expression | ((all=ALL | any=ANY) LPAREN r=value_expression RPAREN)) {$ret = all != null ? factory.wrapInAll(op, l, r) : any != null ? factory.wrapInAny(op, l, r) : factory.comparison(op,l,r); } )
                   |  (IS n=NOT? NULL {$ret = factory.isNull(l,n!=null); } )
                   |  ( n=NOT? ((LIKE r=value_expression {$ret = factory.like(l,r,n!=null); } )
                       |        (EXISTS LPAREN r=subquery_expression RPAREN {$ret = factory.exists(l,r,n!=null);} )

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
index 2d5e461..30011d6 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
@@ -61,10 +61,16 @@ import org.apache.phoenix.expression.RowValueConstructorExpression;
 import org.apache.phoenix.expression.StringConcatExpression;
 import org.apache.phoenix.expression.TimestampAddExpression;
 import org.apache.phoenix.expression.TimestampSubtractExpression;
+import org.apache.phoenix.expression.function.ArrayAllComparisonExpression;
+import org.apache.phoenix.expression.function.ArrayAnyComparisonExpression;
+import org.apache.phoenix.expression.function.InlineArrayElemRefExpression;
 import org.apache.phoenix.parse.AddParseNode;
 import org.apache.phoenix.parse.AndParseNode;
 import org.apache.phoenix.parse.ArithmeticParseNode;
+import org.apache.phoenix.parse.ArrayAllComparisonNode;
+import org.apache.phoenix.parse.ArrayAnyComparisonNode;
 import org.apache.phoenix.parse.ArrayConstructorNode;
+import org.apache.phoenix.parse.ArrayElemRefNode;
 import org.apache.phoenix.parse.BindParseNode;
 import org.apache.phoenix.parse.CaseParseNode;
 import org.apache.phoenix.parse.CastParseNode;
@@ -977,6 +983,35 @@ public class ExpressionCompiler extends UnsupportedAllParseNodeVisitor<Expressio
     }
 
     @Override
+    public boolean visitEnter(ArrayAnyComparisonNode node) throws SQLException {
+        return true;
+    }
+
+    @Override
+    public Expression visitLeave(ArrayAnyComparisonNode node, List<Expression> children) throws SQLException {
+        return new ArrayAnyComparisonExpression(children);
+    }
+
+    @Override
+    public boolean visitEnter(ArrayAllComparisonNode node) throws SQLException {
+        return true;
+    }
+    
+    @Override
+    public boolean visitEnter(ArrayElemRefNode node) throws SQLException {
+        return true;
+    }
+    
+    @Override
+    public Expression visitLeave(ArrayElemRefNode node, List<Expression> l) throws SQLException {
+        return new InlineArrayElemRefExpression(l);
+    }
+    
+    @Override
+    public Expression visitLeave(ArrayAllComparisonNode node, List<Expression> children) throws SQLException {
+        return new ArrayAllComparisonExpression(children);
+    }
+    @Override
     public boolean visitEnter(DivideParseNode node) throws SQLException {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/compile/StatementNormalizer.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/StatementNormalizer.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/StatementNormalizer.java
index 855ed75..e02f7c3 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/StatementNormalizer.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/StatementNormalizer.java
@@ -21,8 +21,6 @@ import java.sql.SQLException;
 import java.util.Collections;
 import java.util.List;
 
-import com.google.common.collect.Lists;
-
 import org.apache.phoenix.parse.AliasedNode;
 import org.apache.phoenix.parse.BetweenParseNode;
 import org.apache.phoenix.parse.BindTableNode;
@@ -43,6 +41,8 @@ import org.apache.phoenix.parse.TableWildcardParseNode;
 import org.apache.phoenix.parse.WildcardParseNode;
 import org.apache.phoenix.util.SchemaUtil;
 
+import com.google.common.collect.Lists;
+
 
 /**
  * 

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
index 5c784e7..3db58b1 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
@@ -19,6 +19,8 @@ package org.apache.phoenix.expression;
 
 import java.util.Map;
 
+import org.apache.phoenix.expression.function.ArrayAllComparisonExpression;
+import org.apache.phoenix.expression.function.ArrayAnyComparisonExpression;
 import org.apache.phoenix.expression.function.ArrayIndexFunction;
 import org.apache.phoenix.expression.function.ArrayLengthFunction;
 import org.apache.phoenix.expression.function.CeilDateExpression;
@@ -37,6 +39,7 @@ import org.apache.phoenix.expression.function.FloorDateExpression;
 import org.apache.phoenix.expression.function.FloorDecimalExpression;
 import org.apache.phoenix.expression.function.FloorFunction;
 import org.apache.phoenix.expression.function.IndexStateNameFunction;
+import org.apache.phoenix.expression.function.InlineArrayElemRefExpression;
 import org.apache.phoenix.expression.function.InvertFunction;
 import org.apache.phoenix.expression.function.LTrimFunction;
 import org.apache.phoenix.expression.function.LastValueFunction;
@@ -171,7 +174,10 @@ public enum ExpressionType {
     LpadFunction(LpadFunction.class),
     NthValueFunction(NthValueFunction.class),
     FirstValueFunction(FirstValueFunction.class),
-    LastValueFunction(LastValueFunction.class);
+    LastValueFunction(LastValueFunction.class),
+    ArrayAnyComparisonExpression(ArrayAnyComparisonExpression.class),
+    ArrayAllComparisonExpression(ArrayAllComparisonExpression.class),
+    InlineArrayElemRefExpression(InlineArrayElemRefExpression.class);
     ExpressionType(Class<? extends Expression> clazz) {
         this.clazz = clazz;
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAllComparisonExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAllComparisonExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAllComparisonExpression.java
new file mode 100644
index 0000000..9acdadb
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAllComparisonExpression.java
@@ -0,0 +1,45 @@
+/*
+ * 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.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.schema.PDataType;
+
+public class ArrayAllComparisonExpression extends ArrayAnyComparisonExpression {
+
+    public ArrayAllComparisonExpression() {}
+
+    public ArrayAllComparisonExpression(List<Expression> children) {
+        super(children);
+    }
+
+    @Override
+    protected boolean resultFound(ImmutableBytesWritable ptr) {
+        if (Bytes.equals(ptr.get(), PDataType.FALSE_BYTES)) { return true; }
+        return false;
+    }
+
+    @Override
+    protected boolean result() {
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAnyComparisonExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAnyComparisonExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAnyComparisonExpression.java
new file mode 100644
index 0000000..dd85bb7
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAnyComparisonExpression.java
@@ -0,0 +1,78 @@
+/*
+ * 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.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.expression.BaseCompoundExpression;
+import org.apache.phoenix.expression.ComparisonExpression;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.schema.PArrayDataType;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+public class ArrayAnyComparisonExpression extends BaseCompoundExpression {
+    public ArrayAnyComparisonExpression () {
+    }
+    public ArrayAnyComparisonExpression(List<Expression> children) {
+        super(children);
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        Expression arrayKVExpression = children.get(0);
+        if (!arrayKVExpression.evaluate(tuple, ptr)) {
+            return false;
+        } else if (ptr.getLength() == 0) { return true; }
+        int length = PArrayDataType.getArrayLength(ptr,
+                PDataType.fromTypeId(children.get(0).getDataType().getSqlType() - PDataType.ARRAY_TYPE_BASE),
+                arrayKVExpression.getMaxLength());
+        boolean elementAvailable = false;
+        for (int i = 0; i < length; i++) {
+            Expression comparisonExpr = children.get(1);
+            Expression arrayElemRef = ((ComparisonExpression)comparisonExpr).getChildren().get(1);
+            ((InlineArrayElemRefExpression)arrayElemRef).setIndex(i + 1);
+            comparisonExpr.evaluate(tuple, ptr);
+            if (expectedReturnResult(resultFound(ptr))) { return result(); }
+            elementAvailable = true;
+        }
+        if (!elementAvailable) { return false; }
+        return true;
+    }
+    protected boolean resultFound(ImmutableBytesWritable ptr) {
+        if(Bytes.equals(ptr.get(), PDataType.TRUE_BYTES)) {
+            return true;
+        }
+        return false;
+    }
+    
+    protected boolean result() {
+        return true;
+    }
+    
+    protected boolean expectedReturnResult(boolean result) {
+        return true == result;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PDataType.BOOLEAN;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayIndexFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayIndexFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayIndexFunction.java
index 46b0eca..a1f8b6d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayIndexFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayIndexFunction.java
@@ -58,17 +58,7 @@ public class ArrayIndexFunction extends ScalarFunction {
 			throw new ParseException("Index cannot be negative :" + index);
 		}
 		Expression arrayExpr = children.get(0);
-		if (!arrayExpr.evaluate(tuple, ptr)) {
-		  return false;
-		} else if (ptr.getLength() == 0) {
-		  return true;
-		}
-
-		// Given a ptr to the entire array, set ptr to point to a particular element within that array
-		// given the type of an array element (see comments in PDataTypeForArray)
-		PArrayDataType.positionAtArrayElement(ptr, index-1, getDataType(), getMaxLength());
-		return true;
-		
+		return PArrayDataType.positionAtArrayElement(tuple, ptr, index, arrayExpr, getDataType(), getMaxLength());
 	}
 
 	@Override

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InlineArrayElemRefExpression.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InlineArrayElemRefExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InlineArrayElemRefExpression.java
new file mode 100644
index 0000000..9082911
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/InlineArrayElemRefExpression.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression.function;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.BaseCompoundExpression;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.schema.PArrayDataType;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.tuple.Tuple;
+
+public class InlineArrayElemRefExpression extends BaseCompoundExpression {
+
+    private int index;
+
+    public InlineArrayElemRefExpression() {
+    }
+    
+    public InlineArrayElemRefExpression(List<Expression> children) {
+        super(children);
+    }
+
+    public void setIndex(int index) {
+        this.index = index;
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        Expression arrayExpr = children.get(0);
+        return PArrayDataType.positionAtArrayElement(tuple, ptr, index, arrayExpr, getDataType(), getMaxLength());
+    }
+
+    @Override
+    public Integer getMaxLength() {
+        return this.children.get(0).getMaxLength();
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PDataType.fromTypeId(children.get(0).getDataType().getSqlType() - PDataType.ARRAY_TYPE_BASE);
+    }
+    
+    @Override
+    public void write(DataOutput output) throws IOException {
+        super.write(output);
+    }
+    
+    @Override
+    public void readFields(DataInput input) throws IOException {
+        super.readFields(input);
+    }
+    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/parse/ArrayAllComparisonNode.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/ArrayAllComparisonNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/ArrayAllComparisonNode.java
new file mode 100644
index 0000000..b31b3ae
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/ArrayAllComparisonNode.java
@@ -0,0 +1,46 @@
+/*
+ * 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.parse;
+
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+/** 
+ * The Expression a = ALL(b) where b is of type array is rewritten in this
+ * node as ALL(a = b(n))
+ */
+public class ArrayAllComparisonNode extends CompoundParseNode {
+
+    ArrayAllComparisonNode(ParseNode rhs, ComparisonParseNode compareNode) {
+        super(Arrays.<ParseNode>asList(rhs, compareNode));
+    }
+    
+    public String getType() {
+        return "ALL";
+    }
+
+    @Override
+    public <T> T accept(ParseNodeVisitor<T> visitor) throws SQLException {
+        List<T> l = Collections.emptyList();
+        if (visitor.visitEnter(this)) {
+            l = acceptChildren(visitor);
+        }
+        return visitor.visitLeave(this, l);
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/parse/ArrayAnyComparisonNode.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/ArrayAnyComparisonNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/ArrayAnyComparisonNode.java
new file mode 100644
index 0000000..daca86d
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/ArrayAnyComparisonNode.java
@@ -0,0 +1,46 @@
+/*
+ * 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.parse;
+
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+/** 
+ * The Expression a = ANY(b) where b is of type array is rewritten in this
+ * node as ANY(a = b(n))
+ */
+public class ArrayAnyComparisonNode extends CompoundParseNode {
+
+    ArrayAnyComparisonNode(ParseNode rhs, ComparisonParseNode compareNode) {
+        super(Arrays.<ParseNode>asList(rhs, compareNode));
+    }
+    
+    public String getType() {
+        return "ANY";
+    }
+
+    @Override
+    public <T> T accept(ParseNodeVisitor<T> visitor) throws SQLException {
+        List<T> l = Collections.emptyList();
+        if (visitor.visitEnter(this)) {
+            l = acceptChildren(visitor);
+        }
+        return visitor.visitLeave(this, l);
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/parse/ArrayElemRefNode.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/ArrayElemRefNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/ArrayElemRefNode.java
new file mode 100644
index 0000000..da69de2
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/ArrayElemRefNode.java
@@ -0,0 +1,38 @@
+/*
+ * 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.parse;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+
+public class ArrayElemRefNode extends CompoundParseNode {
+
+    public ArrayElemRefNode(List<ParseNode> parseNode) {
+        super(parseNode);
+    }
+
+    @Override
+    public <T> T accept(ParseNodeVisitor<T> visitor) throws SQLException {
+        List<T> l = Collections.emptyList();
+        if (visitor.visitEnter(this)) {
+            l = acceptChildren(visitor);
+        }
+        return visitor.visitLeave(this, l);
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
index e01e4f9..ab38b8d 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
@@ -490,6 +490,18 @@ public class ParseNodeFactory {
         }
     }
 
+    public ArrayAnyComparisonNode wrapInAny(CompareOp op, ParseNode lhs, ParseNode rhs) {
+        return new ArrayAnyComparisonNode(rhs, comparison(op, lhs, elementRef(Arrays.<ParseNode>asList(rhs, literal(1)))));
+    }
+
+    public ArrayAllComparisonNode wrapInAll(CompareOp op, ParseNode lhs, ParseNode rhs) {
+        return new ArrayAllComparisonNode(rhs, comparison(op, lhs, elementRef(Arrays.<ParseNode>asList(rhs, literal(1)))));
+    }
+    
+    public ArrayElemRefNode elementRef(List<ParseNode> parseNode) {
+        return new ArrayElemRefNode(parseNode);
+    }
+
     public GreaterThanParseNode gt(ParseNode lhs, ParseNode rhs) {
         return new GreaterThanParseNode(lhs, rhs);
     }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeRewriter.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeRewriter.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeRewriter.java
index bff5834..88601f2 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeRewriter.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeRewriter.java
@@ -355,10 +355,9 @@ public class ParseNodeRewriter extends TraverseAllParseNodeVisitor<ParseNode> {
                 return NODE_FACTORY.comparison(node.getFilterOp(), children.get(0), children.get(1));
             }
         });
-        
         return normNode;
     }
-    
+
     @Override
     public ParseNode visitLeave(final BetweenParseNode node, List<ParseNode> nodes) throws SQLException {
         return leaveCompoundNode(node, nodes, new CompoundNodeFactory() {
@@ -532,4 +531,19 @@ public class ParseNodeRewriter extends TraverseAllParseNodeVisitor<ParseNode> {
         }
 	    
 	}
+
+	@Override
+    public ParseNode visitLeave(ArrayAnyComparisonNode node, List<ParseNode> l) throws SQLException {
+        return node;
+    }
+
+    @Override
+    public ParseNode visitLeave(ArrayAllComparisonNode node, List<ParseNode> l) throws SQLException {
+        return node;
+    }
+ 
+    @Override
+    public ParseNode visitLeave(ArrayElemRefNode node, List<ParseNode> l) throws SQLException {
+        return node;
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeVisitor.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeVisitor.java
index ee42376..a35894b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeVisitor.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/ParseNodeVisitor.java
@@ -104,4 +104,15 @@ public interface ParseNodeVisitor<E> {
     public boolean visitEnter(ArrayConstructorNode node) throws SQLException;
     public E visitLeave(ArrayConstructorNode node, List<E> l) throws SQLException;
     public E visit(SequenceValueParseNode node) throws SQLException;
+    
+    public boolean visitEnter(ArrayAllComparisonNode node) throws SQLException;
+    public E visitLeave(ArrayAllComparisonNode node, List<E> l) throws SQLException;
+    
+    public boolean visitEnter(ArrayAnyComparisonNode node) throws SQLException;
+    public E visitLeave(ArrayAnyComparisonNode node, List<E> l) throws SQLException;
+    
+    public boolean visitEnter(ArrayElemRefNode node) throws SQLException;
+    public E visitLeave(ArrayElemRefNode node, List<E> l) throws SQLException;
+    
+    
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseAllParseNodeVisitor.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseAllParseNodeVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseAllParseNodeVisitor.java
index ef80d55..f85b9b3 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseAllParseNodeVisitor.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseAllParseNodeVisitor.java
@@ -158,4 +158,34 @@ public abstract class TraverseAllParseNodeVisitor<T> extends BaseParseNodeVisito
     public boolean visitEnter(ArrayConstructorNode node) throws SQLException {
         return true;
     }
+    
+    @Override
+    public boolean visitEnter(ArrayAllComparisonNode node) throws SQLException {
+        return true;
+    }
+    
+    @Override
+    public T visitLeave(ArrayAllComparisonNode node, List<T> l) throws SQLException {
+        return null;
+    }
+    
+    @Override
+    public boolean visitEnter(ArrayAnyComparisonNode node) throws SQLException {
+        return true;
+    }
+    
+    @Override
+    public T visitLeave(ArrayAnyComparisonNode node, List<T> l) throws SQLException {
+        return null;
+    }
+    
+    @Override
+    public T visitLeave(ArrayElemRefNode node, List<T> l) throws SQLException {
+        return null;
+    }
+    
+    @Override
+    public boolean visitEnter(ArrayElemRefNode node) throws SQLException {
+        return true;
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseNoParseNodeVisitor.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseNoParseNodeVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseNoParseNodeVisitor.java
index 2021d70..18cccd5 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseNoParseNodeVisitor.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/TraverseNoParseNodeVisitor.java
@@ -242,4 +242,33 @@ public abstract class TraverseNoParseNodeVisitor<T> extends BaseParseNodeVisitor
     public T visitLeave(ArrayConstructorNode node, List<T> l) throws SQLException {
         return null;
     }
+    
+    @Override
+    public boolean visitEnter(ArrayAllComparisonNode node) throws SQLException {
+        return false;
+    }
+    @Override
+    public T visitLeave(ArrayAllComparisonNode node, List<T> l) throws SQLException {
+        return null;
+    }
+    
+    
+    @Override
+    public boolean visitEnter(ArrayAnyComparisonNode node) throws SQLException {
+        return false;
+    }
+    @Override
+    public T visitLeave(ArrayAnyComparisonNode node, List<T> l) throws SQLException {
+        return null;
+    }
+    
+    @Override
+    public boolean visitEnter(ArrayElemRefNode node) throws SQLException {
+        return false;
+    }
+    
+    @Override
+    public T visitLeave(ArrayElemRefNode node, List<T> l) throws SQLException {
+        return null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/parse/UnsupportedAllParseNodeVisitor.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/UnsupportedAllParseNodeVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/UnsupportedAllParseNodeVisitor.java
index 8688a29..9121bcc 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/UnsupportedAllParseNodeVisitor.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/UnsupportedAllParseNodeVisitor.java
@@ -228,4 +228,24 @@ abstract public class UnsupportedAllParseNodeVisitor<E> extends BaseParseNodeVis
     public E visit(SequenceValueParseNode node) throws SQLException {			
 		return null;
 	}
+
+    @Override
+    public boolean visitEnter(ArrayAnyComparisonNode node) throws SQLException {
+        throw new SQLFeatureNotSupportedException(node.toString());
+    }
+
+    @Override
+    public E visitLeave(ArrayAnyComparisonNode node, List<E> l) throws SQLException {
+        throw new SQLFeatureNotSupportedException(node.toString());
+    }
+    
+    @Override
+    public boolean visitEnter(ArrayAllComparisonNode node) throws SQLException {
+        throw new SQLFeatureNotSupportedException(node.toString());
+    }
+
+    @Override
+    public E visitLeave(ArrayAllComparisonNode node, List<E> l) throws SQLException {
+        throw new SQLFeatureNotSupportedException(node.toString());
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/8496d76a/phoenix-core/src/main/java/org/apache/phoenix/schema/PArrayDataType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PArrayDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PArrayDataType.java
index 507e9d1..6dbf017 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PArrayDataType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PArrayDataType.java
@@ -24,7 +24,9 @@ import java.nio.ByteBuffer;
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.hadoop.hbase.util.Pair;
+import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.schema.tuple.Tuple;
 import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.TrustedByteArrayOutputStream;
 
@@ -254,6 +256,17 @@ public class PArrayDataType {
 				baseType, maxLength, desiredDataType);
 	}
 
+    public static boolean positionAtArrayElement(Tuple tuple, ImmutableBytesWritable ptr, int index,
+            Expression arrayExpr, PDataType pDataType, Integer maxLen) {
+        if (!arrayExpr.evaluate(tuple, ptr)) {
+            return false;
+        } else if (ptr.getLength() == 0) { return true; }
+
+        // Given a ptr to the entire array, set ptr to point to a particular element within that array
+        // given the type of an array element (see comments in PDataTypeForArray)
+        positionAtArrayElement(ptr, index - 1, pDataType, maxLen);
+        return true;
+    }
     public static void positionAtArrayElement(ImmutableBytesWritable ptr, int arrayIndex, PDataType baseDataType,
             Integer byteSize) {
         byte[] bytes = ptr.get();
@@ -304,6 +317,53 @@ public class PArrayDataType {
             }
         }
     }
+    
+    public static void positionAtArrayElement(ImmutableBytesWritable ptr, int arrayIndex, PDataType baseDataType,
+            Integer byteSize, int offset, int length, int noOfElements, boolean first) {
+        byte[] bytes = ptr.get();
+        if (!baseDataType.isFixedWidth()) {
+            int indexOffset = Bytes.toInt(bytes, (offset + length - (Bytes.SIZEOF_BYTE + 2 * Bytes.SIZEOF_INT)))
+                    + offset;
+            boolean useShort = true;
+            if (first) {
+                int count = Bytes.toInt(bytes,
+                        (ptr.getOffset() + ptr.getLength() - (Bytes.SIZEOF_BYTE + Bytes.SIZEOF_INT)), Bytes.SIZEOF_INT);
+                if (count < 0) {
+                    count = -count;
+                    useShort = false;
+                }
+            }
+            if (arrayIndex >= noOfElements) {
+                return;
+            } else {
+                // Skip those many offsets as given in the arrayIndex
+                // If suppose there are 5 elements in the array and the arrayIndex = 3
+                // This means we need to read the 4th element of the array
+                // So inorder to know the length of the 4th element we will read the offset of 4th element and the
+                // offset of 5th element.
+                // Subtracting the offset of 5th element and 4th element will give the length of 4th element
+                // So we could just skip reading the other elements.
+                int currOffset = getOffset(bytes, arrayIndex, useShort, indexOffset);
+                int elementLength = 0;
+                if (arrayIndex == (noOfElements - 1)) {
+                    elementLength = bytes[currOffset + offset] == QueryConstants.SEPARATOR_BYTE ? 0 : indexOffset
+                            - (currOffset + offset) - 3;
+                } else {
+                    elementLength = bytes[currOffset + offset] == QueryConstants.SEPARATOR_BYTE ? 0 : getOffset(bytes,
+                            arrayIndex + 1, useShort, indexOffset) - currOffset - 1;
+                }
+                ptr.set(bytes, currOffset + offset, elementLength);
+            }
+        } else {
+            int elemByteSize = (byteSize == null ? baseDataType.getByteSize() : byteSize);
+            offset += arrayIndex * elemByteSize;
+            if (offset >= offset + length) {
+                return;
+            } else {
+                ptr.set(bytes, offset, elemByteSize);
+            }
+        }
+    }
 
     private static int getOffset(byte[] bytes, int arrayIndex, boolean useShort, int indexOffset) {
         int offset;


Mime
View raw message