You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ma...@apache.org on 2014/09/29 04:30:56 UTC

git commit: PHOENIX-1239 IN clause (and some others) cannot get moved from HAVING clause to WHERE clause when qualified

Repository: phoenix
Updated Branches:
  refs/heads/master 0cc8115a1 -> 4fce08c90


PHOENIX-1239 IN clause (and some others) cannot get moved from HAVING clause to WHERE clause when qualified


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

Branch: refs/heads/master
Commit: 4fce08c90bf52ba29642a2aa40971c32516b7c20
Parents: 0cc8115
Author: maryannxue <ma...@apache.org>
Authored: Sun Sep 28 22:30:24 2014 -0400
Committer: maryannxue <ma...@apache.org>
Committed: Sun Sep 28 22:30:24 2014 -0400

----------------------------------------------------------------------
 .../apache/phoenix/compile/HavingCompiler.java  |  96 ++----
 .../apache/phoenix/compile/JoinCompiler.java    | 144 ++++-----
 .../phoenix/parse/BooleanParseNodeVisitor.java  | 298 +++++++++++++++++++
 .../apache/phoenix/parse/ParseNodeRewriter.java |   9 +-
 .../StatelessTraverseAllParseNodeVisitor.java   |  24 ++
 .../parse/TraverseAllParseNodeVisitor.java      |  20 --
 .../phoenix/compile/HavingCompilerTest.java     |  10 +
 7 files changed, 415 insertions(+), 186 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/4fce08c9/phoenix-core/src/main/java/org/apache/phoenix/compile/HavingCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/HavingCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/HavingCompiler.java
index a7a472f..a9f2f71 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/HavingCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/HavingCompiler.java
@@ -27,22 +27,13 @@ import org.apache.phoenix.exception.SQLExceptionCode;
 import org.apache.phoenix.exception.SQLExceptionInfo;
 import org.apache.phoenix.expression.Expression;
 import org.apache.phoenix.expression.LiteralExpression;
-import org.apache.phoenix.parse.AddParseNode;
 import org.apache.phoenix.parse.AndParseNode;
-import org.apache.phoenix.parse.BetweenParseNode;
-import org.apache.phoenix.parse.CaseParseNode;
+import org.apache.phoenix.parse.BooleanParseNodeVisitor;
 import org.apache.phoenix.parse.ColumnParseNode;
-import org.apache.phoenix.parse.ComparisonParseNode;
-import org.apache.phoenix.parse.DivideParseNode;
 import org.apache.phoenix.parse.FunctionParseNode;
-import org.apache.phoenix.parse.IsNullParseNode;
-import org.apache.phoenix.parse.MultiplyParseNode;
-import org.apache.phoenix.parse.OrParseNode;
 import org.apache.phoenix.parse.ParseNode;
 import org.apache.phoenix.parse.SelectStatement;
 import org.apache.phoenix.parse.SelectStatementRewriter;
-import org.apache.phoenix.parse.SubtractParseNode;
-import org.apache.phoenix.parse.TraverseNoParseNodeVisitor;
 import org.apache.phoenix.schema.ColumnRef;
 import org.apache.phoenix.schema.PDataType;
 import org.apache.phoenix.schema.TypeMismatchException;
@@ -110,7 +101,7 @@ public class HavingCompiler {
      * 
      * @since 0.1
      */
-    private static class HavingClauseVisitor extends TraverseNoParseNodeVisitor<Void> {
+    private static class HavingClauseVisitor extends BooleanParseNodeVisitor<Void> {
         private ParseNode topNode = null;
         private boolean hasNoAggregateFunctions = true;
         private Boolean hasOnlyAggregateColumns;
@@ -126,37 +117,18 @@ public class HavingCompiler {
         public Set<ParseNode> getMoveToWhereClauseExpressions() {
             return moveToWhereClause;
         }
-        
-        @Override
-        public boolean visitEnter(AndParseNode node) throws SQLException {
-            return true;
-        }
-        
-        @Override
-        public boolean visitEnter(OrParseNode node) throws SQLException {
-            enterBooleanNode(node);
-            return true;
-        }
-        
-        @Override
-        public boolean visitEnter(ComparisonParseNode node) throws SQLException {
-            enterBooleanNode(node);
-            return true;
-        }
-        
+
         @Override
-        public boolean visitEnter(IsNullParseNode node) throws SQLException {
-            enterBooleanNode(node);
-            return true;
-        }
-        
-        private void enterBooleanNode(ParseNode node) {
+        protected boolean enterBooleanNode(ParseNode node) throws SQLException {
             if (topNode == null) {
                 topNode = node;
             }
+            
+            return true;
         }
-        
-        private void leaveBooleanNode(ParseNode node) {
+
+        @Override
+        protected Void leaveBooleanNode(ParseNode node, List<Void> l) throws SQLException {
             if (topNode == node) {
                 if ( hasNoAggregateFunctions && !Boolean.FALSE.equals(hasOnlyAggregateColumns)) {
                     moveToWhereClause.add(node);
@@ -165,23 +137,27 @@ public class HavingCompiler {
                 hasOnlyAggregateColumns = null;
                 topNode = null;
             }
+            
+            return null;
         }
 
         @Override
-        public Void visitLeave(OrParseNode node, List<Void> l) throws SQLException {
-            leaveBooleanNode(node);
-            return null;
+        protected boolean enterNonBooleanNode(ParseNode node) throws SQLException {
+            return true;
         }
 
         @Override
-        public Void visitLeave(ComparisonParseNode node, List<Void> l) throws SQLException {
-            leaveBooleanNode(node);
+        protected Void leaveNonBooleanNode(ParseNode node, List<Void> l) throws SQLException {
             return null;
         }
+        
+        @Override
+        public boolean visitEnter(AndParseNode node) throws SQLException {
+            return true;
+        }
 
         @Override
-        public Void visitLeave(IsNullParseNode node, List<Void> l) throws SQLException {
-            leaveBooleanNode(node);
+        public Void visitLeave(AndParseNode node, List<Void> l) throws SQLException {
             return null;
         }
 
@@ -189,12 +165,7 @@ public class HavingCompiler {
         public boolean visitEnter(FunctionParseNode node) throws SQLException {
             boolean isAggregate = node.isAggregate();
             this.hasNoAggregateFunctions = this.hasNoAggregateFunctions && !isAggregate;
-            return !isAggregate;
-        }
-
-        @Override
-        public boolean visitEnter(CaseParseNode node) throws SQLException {
-            return true;
+            return !isAggregate && super.visitEnter(node);
         }
 
         @Override
@@ -209,31 +180,6 @@ public class HavingCompiler {
             
             return null;
         }
-
-        @Override
-        public boolean visitEnter(SubtractParseNode node) throws SQLException {
-            return true;
-        }
-
-        @Override
-        public boolean visitEnter(AddParseNode node) throws SQLException {
-            return true;
-        }
-
-        @Override
-        public boolean visitEnter(MultiplyParseNode node) throws SQLException {
-            return true;
-        }
-
-        @Override
-        public boolean visitEnter(DivideParseNode node) throws SQLException {
-            return true;
-        }
-
-        @Override
-        public boolean visitEnter(BetweenParseNode node) throws SQLException {
-            return true;
-        }
 		
     }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4fce08c9/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
index 41f58e0..0a97292 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
@@ -43,27 +43,18 @@ import org.apache.phoenix.jdbc.PhoenixStatement;
 import org.apache.phoenix.join.TupleProjector;
 import org.apache.phoenix.parse.AliasedNode;
 import org.apache.phoenix.parse.AndParseNode;
-import org.apache.phoenix.parse.BetweenParseNode;
 import org.apache.phoenix.parse.BindTableNode;
-import org.apache.phoenix.parse.CaseParseNode;
-import org.apache.phoenix.parse.CastParseNode;
+import org.apache.phoenix.parse.BooleanParseNodeVisitor;
 import org.apache.phoenix.parse.ColumnDef;
 import org.apache.phoenix.parse.ColumnParseNode;
 import org.apache.phoenix.parse.ComparisonParseNode;
 import org.apache.phoenix.parse.DerivedTableNode;
 import org.apache.phoenix.parse.EqualParseNode;
-import org.apache.phoenix.parse.FunctionParseNode;
 import org.apache.phoenix.parse.HintNode;
 import org.apache.phoenix.parse.HintNode.Hint;
-import org.apache.phoenix.parse.InListParseNode;
-import org.apache.phoenix.parse.InParseNode;
-import org.apache.phoenix.parse.IsNullParseNode;
 import org.apache.phoenix.parse.JoinTableNode;
 import org.apache.phoenix.parse.JoinTableNode.JoinType;
-import org.apache.phoenix.parse.LikeParseNode;
 import org.apache.phoenix.parse.NamedTableNode;
-import org.apache.phoenix.parse.NotParseNode;
-import org.apache.phoenix.parse.OrParseNode;
 import org.apache.phoenix.parse.OrderByNode;
 import org.apache.phoenix.parse.ParseNode;
 import org.apache.phoenix.parse.ParseNodeFactory;
@@ -73,7 +64,6 @@ import org.apache.phoenix.parse.TableName;
 import org.apache.phoenix.parse.TableNode;
 import org.apache.phoenix.parse.TableNodeVisitor;
 import org.apache.phoenix.parse.TableWildcardParseNode;
-import org.apache.phoenix.parse.TraverseNoParseNodeVisitor;
 import org.apache.phoenix.parse.WildcardParseNode;
 import org.apache.phoenix.schema.AmbiguousColumnException;
 import org.apache.phoenix.schema.ColumnNotFoundException;
@@ -796,83 +786,7 @@ public class JoinCompiler {
         }
     }
     
-    private static abstract class ConditionNodeVisitor extends TraverseNoParseNodeVisitor<Void> {
-        
-        protected abstract Void leaveBooleanNode(ParseNode node, List<Void> l) throws SQLException;
-
-        @Override
-        public Void visitLeave(LikeParseNode node,
-                List<Void> l) throws SQLException {                
-            return leaveBooleanNode(node, l);
-        }
-
-        @Override
-        public boolean visitEnter(AndParseNode node) {
-            return true;
-        }
-        
-        @Override
-        public Void visitLeave(OrParseNode node, List<Void> l)
-                throws SQLException {
-            return leaveBooleanNode(node, l);
-        }
-
-        @Override
-        public Void visitLeave(ComparisonParseNode node, List<Void> l) 
-                throws SQLException {
-            return leaveBooleanNode(node, l);
-        }
-
-        @Override
-        public Void visitLeave(NotParseNode node, List<Void> l)
-                throws SQLException {
-            return leaveBooleanNode(node, l);
-        }
-
-        @Override
-        public Void visitLeave(InListParseNode node,
-                List<Void> l) throws SQLException {
-            return leaveBooleanNode(node, l);
-        }
-
-        @Override
-        public Void visitLeave(InParseNode node,
-                List<Void> l) throws SQLException {
-            return leaveBooleanNode(node, l);
-        }
-        
-        @Override
-        public Void visitLeave(IsNullParseNode node, List<Void> l) 
-                throws SQLException {
-            return leaveBooleanNode(node, l);
-        }
-        
-        @Override
-        public Void visitLeave(FunctionParseNode node, List<Void> l) 
-                throws SQLException {
-            return leaveBooleanNode(node, l);
-        }
-        
-        @Override
-        public Void visitLeave(BetweenParseNode node, List<Void> l) 
-                throws SQLException {
-            return leaveBooleanNode(node, l);
-        }
-        
-        @Override
-        public Void visitLeave(CaseParseNode node, List<Void> l) 
-                throws SQLException {
-            return leaveBooleanNode(node, l);
-        }
-        
-        @Override
-        public Void visitLeave(CastParseNode node, List<Void> l) 
-                throws SQLException {
-            return leaveBooleanNode(node, l);
-        }           
-    }
-    
-    private static class WhereNodeVisitor extends ConditionNodeVisitor {
+    private static class WhereNodeVisitor extends BooleanParseNodeVisitor<Void> {
         private ColumnResolver resolver;
         private Table table;
         private List<ParseNode> postFilters;
@@ -891,6 +805,12 @@ public class JoinCompiler {
             this.prefilterAcceptedTables = prefilterAcceptedTables;
         }
         
+        @Override
+        protected boolean enterBooleanNode(ParseNode node) throws SQLException {
+            return false;
+        }
+        
+        @Override
         protected Void leaveBooleanNode(ParseNode node,
                 List<Void> l) throws SQLException {
             ColumnParseNodeVisitor visitor = new ColumnParseNodeVisitor(resolver);
@@ -925,9 +845,29 @@ public class JoinCompiler {
             }
             return null;
         }
+        
+        @Override
+        protected boolean enterNonBooleanNode(ParseNode node) throws SQLException {
+            return false;
+        }
+        
+        @Override
+        protected Void leaveNonBooleanNode(ParseNode node, List<Void> l) throws SQLException {
+            return null;
+        }
+        
+        @Override
+        public boolean visitEnter(AndParseNode node) throws SQLException {
+            return true;
+        }
+
+        @Override
+        public Void visitLeave(AndParseNode node, List<Void> l) throws SQLException {
+            return null;
+        }
     }
     
-    private static class OnNodeVisitor extends ConditionNodeVisitor {
+    private static class OnNodeVisitor extends BooleanParseNodeVisitor<Void> {
         private ColumnResolver resolver;
         private List<ComparisonParseNode> onConditions;
         private Set<TableRef> dependencies;
@@ -941,6 +881,12 @@ public class JoinCompiler {
             this.joinTable = joinTable;
         }
         
+        @Override
+        protected boolean enterBooleanNode(ParseNode node) throws SQLException {
+            return false;
+        }
+        
+        @Override
         protected Void leaveBooleanNode(ParseNode node,
                 List<Void> l) throws SQLException {
             ColumnParseNodeVisitor visitor = new ColumnParseNodeVisitor(resolver);
@@ -954,8 +900,28 @@ public class JoinCompiler {
             }
             return null;
         }
+        
+        @Override
+        protected boolean enterNonBooleanNode(ParseNode node) throws SQLException {
+            return false;
+        }
+        
+        @Override
+        protected Void leaveNonBooleanNode(ParseNode node, List<Void> l) throws SQLException {
+            return null;
+        }
+        
+        @Override
+        public boolean visitEnter(AndParseNode node) throws SQLException {
+            return true;
+        }
 
         @Override
+        public Void visitLeave(AndParseNode node, List<Void> l) throws SQLException {
+            return null;
+        }
+        
+        @Override
         public Void visitLeave(ComparisonParseNode node, List<Void> l) 
                 throws SQLException {
             if (!(node instanceof EqualParseNode))

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4fce08c9/phoenix-core/src/main/java/org/apache/phoenix/parse/BooleanParseNodeVisitor.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/BooleanParseNodeVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/BooleanParseNodeVisitor.java
new file mode 100644
index 0000000..eb68211
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/BooleanParseNodeVisitor.java
@@ -0,0 +1,298 @@
+/*
+ * 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.List;
+
+public abstract class BooleanParseNodeVisitor<T> extends BaseParseNodeVisitor<T> {
+
+    protected abstract boolean enterBooleanNode(ParseNode node) throws SQLException;
+    protected abstract T leaveBooleanNode(ParseNode node, List<T> l) throws SQLException;
+    protected abstract boolean enterNonBooleanNode(ParseNode node) throws SQLException;
+    protected abstract T leaveNonBooleanNode(ParseNode node, List<T> l) throws SQLException;
+    
+    @Override
+    public boolean visitEnter(LikeParseNode node) throws SQLException {
+        return enterBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(LikeParseNode node, List<T> l) throws SQLException {
+        return leaveBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(OrParseNode node) throws SQLException {
+        return enterBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(OrParseNode node, List<T> l) throws SQLException {
+        return leaveBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(FunctionParseNode node) throws SQLException {
+        return enterBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(FunctionParseNode node, List<T> l) throws SQLException {
+        return leaveBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(ComparisonParseNode node) throws SQLException {
+        return enterBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(ComparisonParseNode node, List<T> l)
+            throws SQLException {
+        return leaveBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(CaseParseNode node) throws SQLException {
+        return enterBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(CaseParseNode node, List<T> l) throws SQLException {
+        return leaveBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(AddParseNode node) throws SQLException {
+        return enterNonBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(AddParseNode node, List<T> l) throws SQLException {
+        return leaveNonBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(MultiplyParseNode node) throws SQLException {
+        return enterNonBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(MultiplyParseNode node, List<T> l) throws SQLException {
+        return leaveNonBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(ModulusParseNode node) throws SQLException {
+        return enterNonBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(ModulusParseNode node, List<T> l) throws SQLException {
+        return leaveNonBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(DivideParseNode node) throws SQLException {
+        return enterNonBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(DivideParseNode node, List<T> l) throws SQLException {
+        return leaveNonBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(SubtractParseNode node) throws SQLException {
+        return enterNonBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(SubtractParseNode node, List<T> l) throws SQLException {
+        return leaveNonBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(NotParseNode node) throws SQLException {
+        return enterBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(NotParseNode node, List<T> l) throws SQLException {
+        return leaveBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(InListParseNode node) throws SQLException {
+        return enterBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(InListParseNode node, List<T> l) throws SQLException {
+        return leaveBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(InParseNode node) throws SQLException {
+        return enterBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(InParseNode node, List<T> l) throws SQLException {
+        return leaveBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(IsNullParseNode node) throws SQLException {
+        return enterBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(IsNullParseNode node, List<T> l) throws SQLException {
+        return leaveBooleanNode(node, l);
+    }
+
+    @Override
+    public T visit(ColumnParseNode node) throws SQLException {
+        return null;
+    }
+
+    @Override
+    public T visit(LiteralParseNode node) throws SQLException {
+        return null;
+    }
+
+    @Override
+    public T visit(BindParseNode node) throws SQLException {
+        return null;
+    }
+
+    @Override
+    public T visit(WildcardParseNode node) throws SQLException {
+        return null;
+    }
+
+    @Override
+    public T visit(TableWildcardParseNode node) throws SQLException {
+        return null;
+    }
+
+    @Override
+    public T visit(FamilyWildcardParseNode node) throws SQLException {
+        return null;
+    }
+
+    @Override
+    public T visit(SubqueryParseNode node) throws SQLException {
+        return null;
+    }
+
+    @Override
+    public boolean visitEnter(StringConcatParseNode node) throws SQLException {
+        return enterNonBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(StringConcatParseNode node, List<T> l)
+            throws SQLException {
+        return leaveNonBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(BetweenParseNode node) throws SQLException {
+        return enterBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(BetweenParseNode node, List<T> l) throws SQLException {
+        return leaveBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(CastParseNode node) throws SQLException {
+        return enterBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(CastParseNode node, List<T> l) throws SQLException {
+        return leaveBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(RowValueConstructorParseNode node)
+            throws SQLException {
+        return enterNonBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(RowValueConstructorParseNode node, List<T> l)
+            throws SQLException {
+        return leaveNonBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(ArrayConstructorNode node) throws SQLException {
+        return enterNonBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(ArrayConstructorNode node, List<T> l)
+            throws SQLException {
+        return leaveNonBooleanNode(node, l);
+    }
+
+    @Override
+    public T visit(SequenceValueParseNode node) throws SQLException {
+        return null;
+    }
+
+    @Override
+    public boolean visitEnter(ArrayAllComparisonNode node) throws SQLException {
+        return enterBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(ArrayAllComparisonNode node, List<T> l)
+            throws SQLException {
+        return leaveBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(ArrayAnyComparisonNode node) throws SQLException {
+        return enterBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(ArrayAnyComparisonNode node, List<T> l)
+            throws SQLException {
+        return leaveBooleanNode(node, l);
+    }
+
+    @Override
+    public boolean visitEnter(ArrayElemRefNode node) throws SQLException {
+        return enterNonBooleanNode(node);
+    }
+
+    @Override
+    public T visitLeave(ArrayElemRefNode node, List<T> l) throws SQLException {
+        return leaveNonBooleanNode(node, l);
+    }
+
+}
+

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4fce08c9/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 412fde0..be34efa 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
@@ -584,7 +584,12 @@ public class ParseNodeRewriter extends TraverseAllParseNodeVisitor<ParseNode> {
     }
  
     @Override
-    public ParseNode visitLeave(ArrayElemRefNode node, List<ParseNode> l) throws SQLException {
-        return node;
+    public ParseNode visitLeave(ArrayElemRefNode node, List<ParseNode> nodes) throws SQLException {
+        return leaveCompoundNode(node, nodes, new CompoundNodeFactory() {
+            @Override
+            public ParseNode createNode(List<ParseNode> children) {
+                return NODE_FACTORY.elementRef(children);
+            }
+        });
     }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4fce08c9/phoenix-core/src/main/java/org/apache/phoenix/parse/StatelessTraverseAllParseNodeVisitor.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/StatelessTraverseAllParseNodeVisitor.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/StatelessTraverseAllParseNodeVisitor.java
index 5e9f727..228e1be 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/parse/StatelessTraverseAllParseNodeVisitor.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/StatelessTraverseAllParseNodeVisitor.java
@@ -98,6 +98,12 @@ public class StatelessTraverseAllParseNodeVisitor extends TraverseAllParseNodeVi
     }
 
     @Override
+    public Void visitLeave(IsNullParseNode node, List<Void> l)
+            throws SQLException {
+        return null;
+    }
+
+    @Override
     public Void visitLeave(StringConcatParseNode node, List<Void> l) throws SQLException {
         return null;
     }
@@ -116,4 +122,22 @@ public class StatelessTraverseAllParseNodeVisitor extends TraverseAllParseNodeVi
     public Void visitLeave(ArrayConstructorNode node, List<Void> l) throws SQLException {
         return null;
     }
+
+    @Override
+    public Void visitLeave(ArrayAllComparisonNode node, List<Void> l)
+            throws SQLException {
+        return null;
+    }
+
+    @Override
+    public Void visitLeave(ArrayAnyComparisonNode node, List<Void> l)
+            throws SQLException {
+        return null;
+    }
+
+    @Override
+    public Void visitLeave(ArrayElemRefNode node, List<Void> l)
+            throws SQLException {
+        return null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/4fce08c9/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 d6b444f..ae24824 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
@@ -118,11 +118,6 @@ public abstract class TraverseAllParseNodeVisitor<T> extends BaseParseNodeVisito
     public T visit(ColumnParseNode node) throws SQLException {
         return null;
     }
-
-    @Override
-    public T visitLeave(IsNullParseNode node, List<T> l) throws SQLException {
-        return null;
-    }
     
     @Override
     public T visit(LiteralParseNode node) throws SQLException {
@@ -180,26 +175,11 @@ public abstract class TraverseAllParseNodeVisitor<T> extends BaseParseNodeVisito
     }
     
     @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/4fce08c9/phoenix-core/src/test/java/org/apache/phoenix/compile/HavingCompilerTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/HavingCompilerTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/HavingCompilerTest.java
index 9c64264..1c7477d 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/compile/HavingCompilerTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/HavingCompilerTest.java
@@ -132,6 +132,16 @@ public class HavingCompilerTest extends BaseConnectionlessQueryTest {
     }
     
     @Test
+    public void testInListHavingToWhere() throws SQLException {
+        String query = "select count(1) from atable group by a_string having a_string in ('foo', 'bar')";
+        List<Object> binds = Collections.emptyList();
+        Expressions expressions = compileStatement(query,binds);
+        Expression w = TestUtil.in(A_STRING,"foo","bar");
+        assertEquals(w, expressions.whereClause);
+        assertNull(expressions.havingClause);
+    }
+    
+    @Test
     public void testAggFuncInHaving() throws SQLException {
         String query = "select count(1) from atable group by a_string having count(a_string) >= 1";
         List<Object> binds = Collections.emptyList();