phoenix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jamestay...@apache.org
Subject [19/51] [partial] Initial commit
Date Mon, 27 Jan 2014 19:23:20 GMT
http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/GreaterThanParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/GreaterThanParseNode.java b/src/main/java/org/apache/phoenix/parse/GreaterThanParseNode.java
new file mode 100644
index 0000000..ff0442b
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/GreaterThanParseNode.java
@@ -0,0 +1,48 @@
+/*
+ * 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.parse;
+
+import org.apache.hadoop.hbase.filter.CompareFilter;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+
+
+/**
+ * 
+ * Node representing the greater than operator (>) in SQL
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class GreaterThanParseNode extends ComparisonParseNode {
+
+    GreaterThanParseNode(ParseNode lhs, ParseNode rhs) {
+        super(lhs, rhs);
+    }
+
+    @Override
+    public CompareOp getFilterOp() {
+        return CompareFilter.CompareOp.GREATER;
+    }
+
+    @Override
+    public CompareOp getInvertFilterOp() {
+        return CompareOp.LESS;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/HintNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/HintNode.java b/src/main/java/org/apache/phoenix/parse/HintNode.java
new file mode 100644
index 0000000..fa82382
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/HintNode.java
@@ -0,0 +1,160 @@
+/*
+ * 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.parse;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.phoenix.util.SchemaUtil;
+
+
+/**
+ * Node representing optimizer hints in SQL
+ */
+public class HintNode {
+    public static final HintNode EMPTY_HINT_NODE = new HintNode();
+    
+    public static final char SEPARATOR = ' ';
+    public static final String PREFIX = "(";
+    public static final String SUFFIX = ")";
+    // Split on whitespace and parenthesis, keeping the parenthesis in the token array
+    private static final String SPLIT_REGEXP = "\\s+|((?<=\\" + PREFIX + ")|(?=\\" + PREFIX + "))|((?<=\\" + SUFFIX + ")|(?=\\" + SUFFIX + "))";
+    
+    public enum Hint {
+        /**
+         * Forces a range scan to be used to process the query.
+         */
+        RANGE_SCAN,
+        /**
+         * Forces a skip scan to be used to process the query.
+         */
+        SKIP_SCAN,
+        /**
+         * Prevents the spawning of multiple threads during
+         * query processing.
+         */
+        NO_INTRA_REGION_PARALLELIZATION,
+        /**
+        * Prevents the usage of indexes, forcing usage
+        * of the data table for a query.
+        */
+       NO_INDEX,
+       /**
+       * Hint of the form INDEX(<table_name> <index_name>...)
+       * to suggest usage of the index if possible. The first
+       * usable index in the list of indexes will be choosen.
+       * Table and index names may be surrounded by double quotes
+       * if they are case sensitive.
+       */
+       INDEX,
+       /**
+        * All things being equal, use the data table instead of
+        * the index table when optimizing.
+        */
+       USE_DATA_OVER_INDEX_TABLE,
+       /**
+        * All things being equal, use the index table instead of
+        * the data table when optimizing.
+        */
+       USE_INDEX_OVER_DATA_TABLE,
+    };
+
+    private final Map<Hint,String> hints;
+
+    public static HintNode create(HintNode hintNode, Hint hint) {
+        return create(hintNode, hint, "");
+    }
+    
+    public static HintNode create(HintNode hintNode, Hint hint, String value) {
+        Map<Hint,String> hints = new HashMap<Hint,String>(hintNode.hints);
+        hints.put(hint, value);
+        return new HintNode(hints);
+    }
+    
+    private HintNode() {
+        hints = new HashMap<Hint,String>();
+    }
+
+    private HintNode(Map<Hint,String> hints) {
+        this.hints = ImmutableMap.copyOf(hints);
+    }
+
+    public HintNode(String hint) {
+        Map<Hint,String> hints = new HashMap<Hint,String>();
+        // Split on whitespace or parenthesis. We do not need to handle escaped or
+        // embedded whitespace/parenthesis, since we are parsing what will be HBase
+        // table names which are not allowed to contain whitespace or parenthesis.
+        String[] hintWords = hint.split(SPLIT_REGEXP);
+        for (int i = 0; i < hintWords.length; i++) {
+            String hintWord = hintWords[i];
+            if (hintWord.isEmpty()) {
+                continue;
+            }
+            try {
+                Hint key = Hint.valueOf(hintWord.toUpperCase());
+                String hintValue = "";
+                if (i+1 < hintWords.length && PREFIX.equals(hintWords[i+1])) {
+                    StringBuffer hintValueBuf = new StringBuffer(hint.length());
+                    hintValueBuf.append(PREFIX);
+                    i+=2;
+                    while (i < hintWords.length && !SUFFIX.equals(hintWords[i])) {
+                        hintValueBuf.append(SchemaUtil.normalizeIdentifier(hintWords[i++]));
+                        hintValueBuf.append(SEPARATOR);
+                    }
+                    // Replace trailing separator with suffix
+                    hintValueBuf.replace(hintValueBuf.length()-1, hintValueBuf.length(), SUFFIX);
+                    hintValue = hintValueBuf.toString();
+                }
+                String oldValue = hints.put(key, hintValue);
+                // Concatenate together any old value with the new value
+                if (oldValue != null) {
+                    hints.put(key, oldValue + hintValue);
+                }
+            } catch (IllegalArgumentException e) { // Ignore unknown/invalid hints
+            }
+        }
+        this.hints = ImmutableMap.copyOf(hints);
+    }
+    
+    public boolean isEmpty() {
+        return hints.isEmpty();
+    }
+
+    /**
+     * Gets the value of the hint or null if the hint is not present.
+     * @param hint the hint
+     * @return the value specified in parenthesis following the hint or null
+     * if the hint is not present.
+     * 
+     */
+    public String getHint(Hint hint) {
+        return hints.get(hint);
+    }
+
+    /**
+     * Tests for the presence of a hint in a query
+     * @param hint the hint
+     * @return true if the hint is present and false otherwise
+     */
+    public boolean hasHint(Hint hint) {
+        return hints.containsKey(hint);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/InListParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/InListParseNode.java b/src/main/java/org/apache/phoenix/parse/InListParseNode.java
new file mode 100644
index 0000000..807998b
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/InListParseNode.java
@@ -0,0 +1,66 @@
+/*
+ * 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.parse;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.exception.SQLExceptionInfo;
+
+
+
+/**
+ * 
+ * Node representing the IN literal list expression in SQL
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class InListParseNode extends CompoundParseNode {
+    private final boolean negate;
+
+    InListParseNode(List<ParseNode> children, boolean negate) {
+        super(children);
+        // All values in the IN must be constant. First child is the LHS
+        for (int i = 1; i < children.size(); i++) {
+            ParseNode child = children.get(i);
+            if (!child.isConstant()) {
+                throw new ParseException(new SQLExceptionInfo.Builder(SQLExceptionCode.VALUE_IN_LIST_NOT_CONSTANT)
+                .build().buildException());
+            }
+        }
+        this.negate = negate;
+    }
+    
+    public boolean isNegate() {
+        return negate;
+    }
+
+    @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/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/InParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/InParseNode.java b/src/main/java/org/apache/phoenix/parse/InParseNode.java
new file mode 100644
index 0000000..d7708fc
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/InParseNode.java
@@ -0,0 +1,55 @@
+/*
+ * 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.parse;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+
+
+
+/**
+ * 
+ * Node representing IN subquery expression in SQL
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class InParseNode extends BinaryParseNode {
+    private final boolean negate;
+
+    InParseNode(ParseNode l, ParseNode r, boolean negate) {
+        super(l, r);
+        this.negate = negate;
+    }
+    
+    public boolean isNegate() {
+        return negate;
+    }
+
+    @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/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/IndexKeyConstraint.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/IndexKeyConstraint.java b/src/main/java/org/apache/phoenix/parse/IndexKeyConstraint.java
new file mode 100644
index 0000000..6dfc744
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/IndexKeyConstraint.java
@@ -0,0 +1,39 @@
+/*
+ * 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.parse;
+
+import java.util.List;
+
+import org.apache.hadoop.hbase.util.Pair;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.phoenix.schema.ColumnModifier;
+
+public class IndexKeyConstraint {
+    private final List<Pair<ColumnParseNode, ColumnModifier>> columnNameToModifier;
+    
+    IndexKeyConstraint(List<Pair<ColumnParseNode, ColumnModifier>> columnNameAndModifier) {
+        this.columnNameToModifier = ImmutableList.copyOf(columnNameAndModifier);
+    }
+
+    public List<Pair<ColumnParseNode, ColumnModifier>> getColumns() {
+        return columnNameToModifier;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/IsNullParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/IsNullParseNode.java b/src/main/java/org/apache/phoenix/parse/IsNullParseNode.java
new file mode 100644
index 0000000..a1afc2e
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/IsNullParseNode.java
@@ -0,0 +1,55 @@
+/*
+ * 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.parse;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+
+
+
+/**
+ * 
+ * Node representing the IS NULL and IS NOT NULL expressions in SQL
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class IsNullParseNode extends UnaryParseNode {
+    private final boolean negate;
+    
+    IsNullParseNode(ParseNode expr, boolean negate) {
+        super(expr);
+        this.negate = negate;
+    }
+    
+    public boolean isNegate() {
+        return negate;
+    }
+
+    @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/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/JoinTableNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/JoinTableNode.java b/src/main/java/org/apache/phoenix/parse/JoinTableNode.java
new file mode 100644
index 0000000..2d3f287
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/JoinTableNode.java
@@ -0,0 +1,58 @@
+/*
+ * 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.parse;
+
+import java.sql.SQLException;
+
+
+
+/**
+ * 
+ * Node representing the join specified in the FROM clause of SQL
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class JoinTableNode extends TableNode {
+    public enum JoinType {Inner, Left, Right, Full};
+    
+    private final NamedTableNode table;
+    private final JoinType type;
+    
+    JoinTableNode(String alias, NamedTableNode table, ParseNode node, JoinType type) {
+        super(alias);
+        this.table = table;
+        this.type = type;
+    }
+
+    public JoinType getType() {
+        return type;
+    }
+
+    public NamedTableNode getTable() {
+        return table;
+    }
+
+    @Override
+    public void accept(TableNodeVisitor visitor) throws SQLException {
+        visitor.visit(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/LessThanOrEqualParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/LessThanOrEqualParseNode.java b/src/main/java/org/apache/phoenix/parse/LessThanOrEqualParseNode.java
new file mode 100644
index 0000000..4fb91dd
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/LessThanOrEqualParseNode.java
@@ -0,0 +1,48 @@
+/*
+ * 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.parse;
+
+import org.apache.hadoop.hbase.filter.CompareFilter;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+
+
+/**
+ * 
+ * Node representing the less than or equal to operator (<=) in SQL
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class LessThanOrEqualParseNode extends ComparisonParseNode {
+
+    LessThanOrEqualParseNode(ParseNode lhs, ParseNode rhs) {
+        super(lhs, rhs);
+    }
+
+    @Override
+    public CompareOp getFilterOp() {
+        return CompareFilter.CompareOp.LESS_OR_EQUAL;
+    }
+
+    @Override
+    public CompareOp getInvertFilterOp() {
+        return CompareOp.GREATER_OR_EQUAL;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/LessThanParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/LessThanParseNode.java b/src/main/java/org/apache/phoenix/parse/LessThanParseNode.java
new file mode 100644
index 0000000..c9f69dc
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/LessThanParseNode.java
@@ -0,0 +1,48 @@
+/*
+ * 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.parse;
+
+import org.apache.hadoop.hbase.filter.CompareFilter;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+
+
+/**
+ * 
+ * Node representing the less than operator (<) in SQL
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class LessThanParseNode extends ComparisonParseNode {
+
+    LessThanParseNode(ParseNode lhs, ParseNode rhs) {
+        super(lhs, rhs);
+    }
+
+    @Override
+    public CompareOp getFilterOp() {
+        return CompareFilter.CompareOp.LESS;
+    }
+
+    @Override
+    public CompareOp getInvertFilterOp() {
+        return CompareOp.GREATER;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/LikeParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/LikeParseNode.java b/src/main/java/org/apache/phoenix/parse/LikeParseNode.java
new file mode 100644
index 0000000..b941d56
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/LikeParseNode.java
@@ -0,0 +1,55 @@
+/*
+ * 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.parse;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+
+
+
+/**
+ * 
+ * Node representing LIKE and NOT LIKE in SQL
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class LikeParseNode extends BinaryParseNode {
+    private final boolean negate;
+
+    LikeParseNode(ParseNode lhs, ParseNode rhs, boolean negate) {
+        super(lhs, rhs);
+        this.negate = negate;
+    }
+    
+    public boolean isNegate() {
+        return negate;
+    }
+
+    @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/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/LimitNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/LimitNode.java b/src/main/java/org/apache/phoenix/parse/LimitNode.java
new file mode 100644
index 0000000..cd4d6a9
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/LimitNode.java
@@ -0,0 +1,40 @@
+/*
+ * 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.parse;
+
+
+public class LimitNode {
+    private final BindParseNode bindNode;
+    private final LiteralParseNode limitNode;
+    
+    LimitNode(BindParseNode bindNode) {
+        this.bindNode = bindNode;
+        limitNode = null;
+    }
+    
+    LimitNode(LiteralParseNode limitNode) {
+        this.limitNode = limitNode;
+        this.bindNode = null;
+    }
+    
+    public ParseNode getLimitParseNode() {
+        return bindNode == null ? limitNode : bindNode;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/LiteralParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/LiteralParseNode.java b/src/main/java/org/apache/phoenix/parse/LiteralParseNode.java
new file mode 100644
index 0000000..257f906
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/LiteralParseNode.java
@@ -0,0 +1,73 @@
+/*
+ * 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.parse;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.phoenix.schema.PDataType;
+
+
+
+/**
+ * 
+ * Node representing literal expressions such as 1,2.5,'foo', and NULL in SQL
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class LiteralParseNode extends TerminalParseNode {
+    public static final List<ParseNode> STAR = Collections.<ParseNode>singletonList(new LiteralParseNode(1));
+    private final Object value;
+    private final PDataType type;
+    
+    LiteralParseNode(Object value) {
+        this.value = value;
+        this.type = PDataType.fromLiteral(value);
+    }
+
+    public PDataType getType() {
+        return type;
+    }
+    
+    public Object getValue() {
+        return value;
+    }
+
+    @Override
+    public boolean isConstant() {
+        return true;
+    }
+    
+    @Override
+    public <T> T accept(ParseNodeVisitor<T> visitor) throws SQLException {
+        return visitor.visit(this);
+    }
+
+    public byte[] getBytes() {
+        return type == null ? null : type.toBytes(value);
+    }
+    
+    @Override
+    public String toString() {
+        return type == PDataType.VARCHAR ? ("'" + value.toString() + "'") : value == null ? "null" : value.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/MaxAggregateParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/MaxAggregateParseNode.java b/src/main/java/org/apache/phoenix/parse/MaxAggregateParseNode.java
new file mode 100644
index 0000000..6f59a72
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/MaxAggregateParseNode.java
@@ -0,0 +1,41 @@
+/*
+ * 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.parse;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.phoenix.compile.StatementContext;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.function.FunctionExpression;
+import org.apache.phoenix.expression.function.MaxAggregateFunction;
+
+
+public class MaxAggregateParseNode extends DelegateConstantToCountParseNode {
+
+    public MaxAggregateParseNode(String name, List<ParseNode> children, BuiltInFunctionInfo info) {
+        super(name, children, info);
+    }
+    
+    @Override
+    public FunctionExpression create(List<Expression> children, StatementContext context) throws SQLException {
+        return new MaxAggregateFunction(children, getDelegateFunction(children,context));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/MinAggregateParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/MinAggregateParseNode.java b/src/main/java/org/apache/phoenix/parse/MinAggregateParseNode.java
new file mode 100644
index 0000000..f6450dd
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/MinAggregateParseNode.java
@@ -0,0 +1,41 @@
+/*
+ * 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.parse;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.phoenix.compile.StatementContext;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.function.FunctionExpression;
+import org.apache.phoenix.expression.function.MinAggregateFunction;
+
+
+public class MinAggregateParseNode extends DelegateConstantToCountParseNode {
+
+    public MinAggregateParseNode(String name, List<ParseNode> children, BuiltInFunctionInfo info) {
+        super(name, children, info);
+    }
+    
+    @Override
+    public FunctionExpression create(List<Expression> children, StatementContext context) throws SQLException {
+        return new MinAggregateFunction(children, getDelegateFunction(children,context));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/MultiplyParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/MultiplyParseNode.java b/src/main/java/org/apache/phoenix/parse/MultiplyParseNode.java
new file mode 100644
index 0000000..1b100e9
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/MultiplyParseNode.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.parse;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+
+
+
+/**
+ * 
+ * Node representing multiplication in a SQL expression
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class MultiplyParseNode extends ArithmeticParseNode {
+
+    MultiplyParseNode(List<ParseNode> children) {
+        super(children);
+    }
+
+    @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/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/NamedNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/NamedNode.java b/src/main/java/org/apache/phoenix/parse/NamedNode.java
new file mode 100644
index 0000000..9c687aa
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/NamedNode.java
@@ -0,0 +1,45 @@
+package org.apache.phoenix.parse;
+
+import org.apache.phoenix.util.SchemaUtil;
+
+public class NamedNode {
+    private final String name;
+    private final boolean isCaseSensitive;
+    
+    public static NamedNode caseSensitiveNamedNode(String name) {
+        return new NamedNode(name,true);
+    }
+    
+    private NamedNode(String name, boolean isCaseSensitive) {
+        this.name = name;
+        this.isCaseSensitive = isCaseSensitive;
+    }
+
+    NamedNode(String name) {
+        this.name = SchemaUtil.normalizeIdentifier(name);
+        this.isCaseSensitive = name == null ? false : SchemaUtil.isCaseSensitive(name);
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public boolean isCaseSensitive() {
+        return isCaseSensitive;
+    }
+    
+    @Override
+    public int hashCode() {
+        return name.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
+        NamedNode other = (NamedNode)obj;
+        return name.equals(other.name);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/NamedParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/NamedParseNode.java b/src/main/java/org/apache/phoenix/parse/NamedParseNode.java
new file mode 100644
index 0000000..bd1c6cf
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/NamedParseNode.java
@@ -0,0 +1,53 @@
+/*
+ * 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.parse;
+
+
+/**
+ * 
+ * Abstract node representing named nodes such as binds and column expressions in SQL
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public abstract class NamedParseNode extends TerminalParseNode{
+    private final NamedNode namedNode;
+    
+    NamedParseNode(NamedParseNode node) {
+        this.namedNode = node.namedNode;
+    }
+
+    NamedParseNode(String name) {
+        this.namedNode = new NamedNode(name);
+    }
+
+    public String getName() {
+        return namedNode.getName();
+    }
+
+    public boolean isCaseSensitive() {
+        return namedNode.isCaseSensitive();
+    }
+    
+    @Override
+    public String toString() {
+        return getName();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/NamedTableNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/NamedTableNode.java b/src/main/java/org/apache/phoenix/parse/NamedTableNode.java
new file mode 100644
index 0000000..4be546d
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/NamedTableNode.java
@@ -0,0 +1,64 @@
+/*
+ * 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.parse;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Node representing an explicit table reference in the FROM clause of SQL
+ * 
+ * @author jtaylor
+ * @since 0.1
+ */
+public class NamedTableNode extends ConcreteTableNode {
+
+    private final List<ColumnDef> dynColumns;
+
+    public static NamedTableNode create (String alias, TableName name, List<ColumnDef> dynColumns) {
+        return new NamedTableNode(alias, name, dynColumns);
+    }
+    
+    NamedTableNode(String alias, TableName name) {
+        super(alias, name);
+        dynColumns = Collections.<ColumnDef> emptyList();
+    }
+
+    NamedTableNode(String alias, TableName name, List<ColumnDef> dynColumns) {
+        super(alias, name);
+        if (dynColumns != null) {
+            this.dynColumns = ImmutableList.copyOf(dynColumns);
+        } else {
+            this.dynColumns = Collections.<ColumnDef> emptyList();
+        }
+    }
+
+    @Override
+    public void accept(TableNodeVisitor visitor) throws SQLException {
+        visitor.visit(this);
+    }
+
+    public List<ColumnDef> getDynamicColumns() {
+        return dynColumns;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/NotEqualParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/NotEqualParseNode.java b/src/main/java/org/apache/phoenix/parse/NotEqualParseNode.java
new file mode 100644
index 0000000..7872275
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/NotEqualParseNode.java
@@ -0,0 +1,48 @@
+/*
+ * 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.parse;
+
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+
+
+
+/**
+ * 
+ * Node representing a not equal expression (!=,<>) in SQL
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class NotEqualParseNode extends ComparisonParseNode {
+
+    NotEqualParseNode(ParseNode lhs, ParseNode rhs) {
+        super(lhs, rhs);
+    }
+
+    @Override
+    public CompareOp getFilterOp() {
+        return CompareOp.NOT_EQUAL;
+    }
+
+    @Override
+    public CompareOp getInvertFilterOp() {
+        return CompareOp.NOT_EQUAL;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/NotParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/NotParseNode.java b/src/main/java/org/apache/phoenix/parse/NotParseNode.java
new file mode 100644
index 0000000..580e7ca
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/NotParseNode.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.parse;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+
+
+
+/**
+ * 
+ * Node representing the NOT in SQL
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class NotParseNode extends UnaryParseNode {
+
+    NotParseNode(ParseNode expr) {
+        super(expr);
+    }
+
+    @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/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/OrParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/OrParseNode.java b/src/main/java/org/apache/phoenix/parse/OrParseNode.java
new file mode 100644
index 0000000..0fe869f
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/OrParseNode.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.parse;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+
+
+
+/**
+ * 
+ * Node representing an OR in SQL
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class OrParseNode extends CompoundParseNode {
+
+    OrParseNode(List<ParseNode> children) {
+        super(children);
+    }
+
+    @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/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/OrderByNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/OrderByNode.java b/src/main/java/org/apache/phoenix/parse/OrderByNode.java
new file mode 100644
index 0000000..6a48d10
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/OrderByNode.java
@@ -0,0 +1,57 @@
+/*
+ * 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.parse;
+
+
+/**
+ * 
+ * Node representing an ORDER BY clause (including asc/desc and nulls first/last) in SQL
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public final class OrderByNode {
+    private final ParseNode child;
+    private final boolean nullsLast;
+    private final boolean orderAscending;
+    
+    OrderByNode(ParseNode child, boolean nullsLast, boolean orderAscending) {
+        this.child = child;
+        this.nullsLast = nullsLast;
+        this.orderAscending = orderAscending;
+    }
+    
+    public boolean isNullsLast() {
+        return nullsLast;
+    }
+    
+    public boolean isAscending() {
+        return orderAscending;
+    }
+    
+    public ParseNode getNode() {
+        return child;
+    }
+    
+    @Override
+    public String toString() {
+        return child.toString() + (orderAscending ? " asc" : " desc") + " nulls " + (nullsLast ? "last" : "first");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/OuterJoinParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/OuterJoinParseNode.java b/src/main/java/org/apache/phoenix/parse/OuterJoinParseNode.java
new file mode 100644
index 0000000..12ed92b
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/OuterJoinParseNode.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.parse;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+
+
+
+/**
+ * 
+ * Node representing an outer join qualifier (+) in SQL
+ * TODO: remove Oracle specific syntax
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class OuterJoinParseNode extends UnaryParseNode{
+    OuterJoinParseNode(ParseNode node) {
+        super(node);
+    }
+
+    @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/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/ParseContext.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/ParseContext.java b/src/main/java/org/apache/phoenix/parse/ParseContext.java
new file mode 100644
index 0000000..275ceb2
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/ParseContext.java
@@ -0,0 +1,60 @@
+/*
+ * 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.parse;
+
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+public class ParseContext {
+    private boolean isAggregate;
+    
+    public ParseContext() {
+    }
+
+    public boolean isAggregate() {
+        return isAggregate;
+    }
+
+    public void setAggregate(boolean isAggregate) {
+        this.isAggregate |= isAggregate;
+    }
+
+    public static class Stack {
+        private final List<ParseContext> stack = Lists.newArrayListWithExpectedSize(5);
+        
+        public void push(ParseContext context) {
+            stack.add(context);
+        }
+        
+        public ParseContext pop() {
+            return stack.remove(stack.size()-1);
+        }
+        
+        public ParseContext peek() {
+            return stack.get(stack.size()-1);
+        }
+        
+        public boolean isEmpty() {
+            return stack.isEmpty();
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/ParseException.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/ParseException.java b/src/main/java/org/apache/phoenix/parse/ParseException.java
new file mode 100644
index 0000000..010dd88
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/ParseException.java
@@ -0,0 +1,47 @@
+/*
+ * 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.parse;
+
+/**
+ * 
+ * RuntimeException for exceptions occurring during parsing,
+ * since ANTLR doesn't handle typed exceptions well.
+ *
+ * @author jtaylor
+ * @since 2.0
+ */
+public class ParseException extends RuntimeException {
+
+    public ParseException() {
+    }
+
+    public ParseException(String msg) {
+        super(msg);
+    }
+
+    public ParseException(Throwable t) {
+        super(t);
+    }
+
+    public ParseException(String msg, Throwable t) {
+        super(msg, t);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/ParseNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/ParseNode.java b/src/main/java/org/apache/phoenix/parse/ParseNode.java
new file mode 100644
index 0000000..4b9c3b9
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/ParseNode.java
@@ -0,0 +1,52 @@
+/*
+ * 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.parse;
+
+import java.sql.SQLException;
+import java.util.List;
+
+
+
+
+/**
+ * 
+ * Abstract base class for a parse node in SQL
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public abstract class ParseNode {
+    public abstract List<ParseNode> getChildren();
+    public abstract <T> T accept(ParseNodeVisitor<T> visitor) throws SQLException;
+    
+    public boolean isConstant() {
+        return false;
+    }
+    
+    /**
+     * Allows node to override what the alias is for a given node.
+     * Useful for a column reference, as JDBC says that the alias
+     * name for "a.b" should be "b"
+     * @return the alias to use for this node or null for no alias
+     */
+    public String getAlias() {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/c5b80246/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java b/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
new file mode 100644
index 0000000..5987ac1
--- /dev/null
+++ b/src/main/java/org/apache/phoenix/parse/ParseNodeFactory.java
@@ -0,0 +1,534 @@
+/*
+ * 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.parse;
+
+import java.lang.reflect.Constructor;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.util.Pair;
+
+import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Maps;
+import org.apache.phoenix.exception.UnknownFunctionException;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.ExpressionType;
+import org.apache.phoenix.expression.function.AvgAggregateFunction;
+import org.apache.phoenix.expression.function.CountAggregateFunction;
+import org.apache.phoenix.expression.function.CurrentDateFunction;
+import org.apache.phoenix.expression.function.CurrentTimeFunction;
+import org.apache.phoenix.expression.function.DistinctCountAggregateFunction;
+import org.apache.phoenix.expression.function.FunctionExpression;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
+import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunctionInfo;
+import org.apache.phoenix.parse.JoinTableNode.JoinType;
+import org.apache.phoenix.schema.ColumnModifier;
+import org.apache.phoenix.schema.PDataType;
+import org.apache.phoenix.schema.PIndexState;
+import org.apache.phoenix.schema.PTableType;
+import org.apache.phoenix.schema.TypeMismatchException;
+import org.apache.phoenix.util.SchemaUtil;
+
+
+/**
+ *
+ * Factory used by parser to construct object model while parsing a SQL statement
+ *
+ * @author jtaylor
+ * @since 0.1
+ */
+public class ParseNodeFactory {
+    // TODO: Use Google's Reflection library instead to find aggregate functions
+    @SuppressWarnings("unchecked")
+    private static final List<Class<? extends FunctionExpression>> CLIENT_SIDE_BUILT_IN_FUNCTIONS = Arrays.<Class<? extends FunctionExpression>>asList(
+        CurrentDateFunction.class,
+        CurrentTimeFunction.class,
+        AvgAggregateFunction.class
+        );
+    private static final Map<BuiltInFunctionKey, BuiltInFunctionInfo> BUILT_IN_FUNCTION_MAP = Maps.newHashMap();
+
+    /**
+     *
+     * Key used to look up a built-in function using the combination of
+     * the lowercase name and the number of arguments. This disambiguates
+     * the aggregate MAX(<col>) from the non aggregate MAX(<col1>,<col2>).
+     *
+     * @author jtaylor
+     * @since 0.1
+     */
+    private static class BuiltInFunctionKey {
+        private final String upperName;
+        private final int argCount;
+
+        private BuiltInFunctionKey(String lowerName, int argCount) {
+            this.upperName = lowerName;
+            this.argCount = argCount;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + argCount;
+            result = prime * result + ((upperName == null) ? 0 : upperName.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) return true;
+            if (obj == null) return false;
+            if (getClass() != obj.getClass()) return false;
+            BuiltInFunctionKey other = (BuiltInFunctionKey)obj;
+            if (argCount != other.argCount) return false;
+            if (!upperName.equals(other.upperName)) return false;
+            return true;
+        }
+    }
+
+    private static void addBuiltInFunction(Class<? extends FunctionExpression> f) throws Exception {
+        BuiltInFunction d = f.getAnnotation(BuiltInFunction.class);
+        if (d == null) {
+            return;
+        }
+        int nArgs = d.args().length;
+        BuiltInFunctionInfo value = new BuiltInFunctionInfo(f, d);
+        do {
+            // Add function to function map, throwing if conflicts found
+            // Add entry for each possible version of function based on arguments that are not required to be present (i.e. arg with default value)
+            BuiltInFunctionKey key = new BuiltInFunctionKey(value.getName(), nArgs);
+            if (BUILT_IN_FUNCTION_MAP.put(key, value) != null) {
+                throw new IllegalStateException("Multiple " + value.getName() + " functions with " + nArgs + " arguments");
+            }
+        } while (--nArgs >= 0 && d.args()[nArgs].defaultValue().length() > 0);
+
+        // Look for default values that aren't at the end and throw
+        while (--nArgs >= 0) {
+            if (d.args()[nArgs].defaultValue().length() > 0) {
+                throw new IllegalStateException("Function " + value.getName() + " has non trailing default value of '" + d.args()[nArgs].defaultValue() + "'. Only trailing arguments may have default values");
+            }
+        }
+    }
+    /**
+     * Reflect this class and populate static structures from it.
+     * Don't initialize in static block because we have a circular dependency
+     */
+    private synchronized static void initBuiltInFunctionMap() {
+        if (!BUILT_IN_FUNCTION_MAP.isEmpty()) {
+            return;
+        }
+        Class<? extends FunctionExpression> f = null;
+        try {
+            // Reflection based parsing which yields direct explicit function evaluation at runtime
+            for (int i = 0; i < CLIENT_SIDE_BUILT_IN_FUNCTIONS.size(); i++) {
+                f = CLIENT_SIDE_BUILT_IN_FUNCTIONS.get(i);
+                addBuiltInFunction(f);
+            }
+            for (ExpressionType et : ExpressionType.values()) {
+                Class<? extends Expression> ec = et.getExpressionClass();
+                if (FunctionExpression.class.isAssignableFrom(ec)) {
+                    @SuppressWarnings("unchecked")
+                    Class<? extends FunctionExpression> c = (Class<? extends FunctionExpression>)ec;
+                    addBuiltInFunction(f = c);
+                }
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("Failed initialization of built-in functions at class '" + f + "'", e);
+        }
+    }
+
+    private static BuiltInFunctionInfo getInfo(String name, List<ParseNode> children) {
+        return get(SchemaUtil.normalizeIdentifier(name), children);
+    }
+
+    public static BuiltInFunctionInfo get(String normalizedName, List<ParseNode> children) {
+        initBuiltInFunctionMap();
+        BuiltInFunctionInfo info = BUILT_IN_FUNCTION_MAP.get(new BuiltInFunctionKey(normalizedName,children.size()));
+        if (info == null) {
+            throw new UnknownFunctionException(normalizedName);
+        }
+        return info;
+    }
+
+    public ParseNodeFactory() {
+    }
+
+    public ExplainStatement explain(BindableStatement statement) {
+        return new ExplainStatement(statement);
+    }
+
+    public ShowTablesStatement showTables() {
+        return new ShowTablesStatement();
+    }
+
+    public AliasedNode aliasedNode(String alias, ParseNode expression) {
+        return new AliasedNode(alias, expression);
+    }
+
+    public AddParseNode add(List<ParseNode> children) {
+        return new AddParseNode(children);
+    }
+
+    public SubtractParseNode subtract(List<ParseNode> children) {
+        return new SubtractParseNode(children);
+    }
+
+    public MultiplyParseNode multiply(List<ParseNode> children) {
+        return new MultiplyParseNode(children);
+    }
+
+    public AndParseNode and(List<ParseNode> children) {
+        return new AndParseNode(children);
+    }
+
+    public FamilyWildcardParseNode family(String familyName){
+    	    return new FamilyWildcardParseNode(familyName, false);
+    }
+
+    public WildcardParseNode wildcard() {
+        return WildcardParseNode.INSTANCE;
+    }
+
+    public BetweenParseNode between(ParseNode l, ParseNode r1, ParseNode r2, boolean negate) {
+        return new BetweenParseNode(l, r1, r2, negate);
+    }
+
+    public BindParseNode bind(String bind) {
+        return new BindParseNode(bind);
+    }
+
+    public StringConcatParseNode concat(List<ParseNode> children) {
+        return new StringConcatParseNode(children);
+    }
+
+    public ColumnParseNode column(TableName tableName, String name, String alias) {
+        return new ColumnParseNode(tableName,name,alias);
+    }
+    
+    public ColumnName columnName(String columnName) {
+        return new ColumnName(columnName);
+    }
+
+    public ColumnName columnName(String familyName, String columnName) {
+        return new ColumnName(familyName, columnName);
+    }
+
+    public PropertyName propertyName(String propertyName) {
+        return new PropertyName(propertyName);
+    }
+
+    public PropertyName propertyName(String familyName, String propertyName) {
+        return new PropertyName(familyName, propertyName);
+    }
+
+    public ColumnDef columnDef(ColumnName columnDefName, String sqlTypeName, boolean isNull, Integer maxLength, Integer scale, boolean isPK, ColumnModifier columnModifier) {
+        return new ColumnDef(columnDefName, sqlTypeName, isNull, maxLength, scale, isPK, columnModifier);
+    }
+
+    public PrimaryKeyConstraint primaryKey(String name, List<Pair<ColumnName, ColumnModifier>> columnNameAndModifier) {
+        return new PrimaryKeyConstraint(name, columnNameAndModifier);
+    }
+    
+    public CreateTableStatement createTable(TableName tableName, ListMultimap<String,Pair<String,Object>> props, List<ColumnDef> columns, PrimaryKeyConstraint pkConstraint, List<ParseNode> splits, PTableType tableType, boolean ifNotExists, int bindCount) {
+        return new CreateTableStatement(tableName, props, columns, pkConstraint, splits, tableType, ifNotExists, bindCount);
+    }
+    
+    public CreateIndexStatement createIndex(NamedNode indexName, NamedTableNode dataTable, PrimaryKeyConstraint pkConstraint, List<ColumnName> includeColumns, List<ParseNode> splits, ListMultimap<String,Pair<String,Object>> props, boolean ifNotExists, int bindCount) {
+        return new CreateIndexStatement(indexName, dataTable, pkConstraint, includeColumns, splits, props, ifNotExists, bindCount);
+    }
+    
+    public AddColumnStatement addColumn(NamedTableNode table,  List<ColumnDef> columnDefs, boolean ifNotExists, Map<String,Object> props) {
+        return new AddColumnStatement(table, columnDefs, ifNotExists, props);
+    }
+    
+    public DropColumnStatement dropColumn(NamedTableNode table,  List<ColumnName> columnNodes, boolean ifExists) {
+        return new DropColumnStatement(table, columnNodes, ifExists);
+    }
+    
+    public DropTableStatement dropTable(TableName tableName, PTableType tableType, boolean ifExists) {
+        return new DropTableStatement(tableName, tableType, ifExists);
+    }
+    
+    public DropIndexStatement dropIndex(NamedNode indexName, TableName tableName, boolean ifExists) {
+        return new DropIndexStatement(indexName, tableName, ifExists);
+    }
+    
+    public AlterIndexStatement alterIndex(NamedTableNode indexTableNode, String dataTableName, boolean ifExists, PIndexState state) {
+        return new AlterIndexStatement(indexTableNode, dataTableName, ifExists, state);
+    }
+    
+    public TableName table(String schemaName, String tableName) {
+        return TableName.createNormalized(schemaName,tableName);
+    }
+
+    public NamedNode indexName(String name) {
+        return new NamedNode(name);
+    }
+
+    public NamedTableNode namedTable(String alias, TableName name) {
+        return new NamedTableNode(alias, name);
+    }
+
+    public NamedTableNode namedTable(String alias, TableName name ,List<ColumnDef> dyn_columns) {
+        return new NamedTableNode(alias, name,dyn_columns);
+    }
+
+    public BindTableNode bindTable(String alias, TableName name) {
+        return new BindTableNode(alias, name);
+    }
+
+    public CaseParseNode caseWhen(List<ParseNode> children) {
+        return new CaseParseNode(children);
+    }
+
+    public DivideParseNode divide(List<ParseNode> children) {
+        return new DivideParseNode(children);
+    }
+
+
+    public FunctionParseNode functionDistinct(String name, List<ParseNode> args) {
+        if (CountAggregateFunction.NAME.equals(SchemaUtil.normalizeIdentifier(name))) {
+            BuiltInFunctionInfo info = getInfo(
+                    SchemaUtil.normalizeIdentifier(DistinctCountAggregateFunction.NAME), args);
+            return new DistinctCountParseNode(name, args, info);
+        } else {
+            throw new UnsupportedOperationException("DISTINCT not supported with " + name);
+        }
+    }
+
+    public FunctionParseNode function(String name, List<ParseNode> args) {
+        BuiltInFunctionInfo info = getInfo(name, args);
+        Constructor<? extends FunctionParseNode> ctor = info.getNodeCtor();
+        if (ctor == null) {
+            return info.isAggregate()
+            ? new AggregateFunctionParseNode(name, args, info)
+            : new FunctionParseNode(name, args, info);
+        } else {
+            try {
+                return ctor.newInstance(name, args, info);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    public FunctionParseNode function(String name, List<ParseNode> valueNodes,
+            List<ParseNode> columnNodes, boolean isAscending) {
+        // Right now we support PERCENT functions on only one column
+        if (valueNodes.size() != 1 || columnNodes.size() != 1) {
+            throw new UnsupportedOperationException(name + " not supported on multiple columns");
+        }
+        List<ParseNode> children = new ArrayList<ParseNode>(3);
+        children.add(columnNodes.get(0));
+        children.add(new LiteralParseNode(Boolean.valueOf(isAscending)));
+        children.add(valueNodes.get(0));
+        return function(name, children);
+    }
+
+
+    public HintNode hint(String hint) {
+        return new HintNode(hint);
+    }
+
+    public InListParseNode inList(List<ParseNode> children, boolean negate) {
+        return new InListParseNode(children, negate);
+    }
+
+    public ExistsParseNode exists(ParseNode l, ParseNode r, boolean negate) {
+        return new ExistsParseNode(l, r, negate);
+    }
+
+    public InParseNode in(ParseNode l, ParseNode r, boolean negate) {
+        return new InParseNode(l, r, negate);
+    }
+
+    public IsNullParseNode isNull(ParseNode child, boolean negate) {
+        return new IsNullParseNode(child, negate);
+    }
+
+    public JoinTableNode join (String alias, NamedTableNode table, ParseNode on, JoinType type) {
+        return new JoinTableNode(alias, table, on, type);
+    }
+
+    public DerivedTableNode derivedTable (String alias, SelectStatement select) {
+        return new DerivedTableNode(alias, select);
+    }
+
+    public LikeParseNode like(ParseNode lhs, ParseNode rhs, boolean negate) {
+        return new LikeParseNode(lhs, rhs, negate);
+    }
+
+
+    public LiteralParseNode literal(Object value) {
+        return new LiteralParseNode(value);
+    }
+    
+    public CastParseNode cast(ParseNode expression, String dataType) {
+    	return new CastParseNode(expression, dataType);
+    }
+    
+    public CastParseNode cast(ParseNode expression, PDataType dataType) {
+    	return new CastParseNode(expression, dataType);
+    }
+    
+    public ParseNode rowValueConstructor(List<ParseNode> l) {
+        return new RowValueConstructorParseNode(l);
+    }
+    
+    private void checkTypeMatch (PDataType expectedType, PDataType actualType) throws SQLException {
+        if (!expectedType.isCoercibleTo(actualType)) {
+            throw new TypeMismatchException(expectedType, actualType);
+        }
+    }
+
+    public LiteralParseNode literal(Object value, PDataType expectedType) throws SQLException {
+        PDataType actualType = PDataType.fromLiteral(value);
+        if (actualType != null && actualType != expectedType) {
+            checkTypeMatch(expectedType, actualType);
+            value = expectedType.toObject(value, actualType);
+        }
+        return new LiteralParseNode(value);
+    }
+
+    public LiteralParseNode coerce(LiteralParseNode literalNode, PDataType expectedType) throws SQLException {
+        PDataType actualType = literalNode.getType();
+        if (actualType != null) {
+            Object before = literalNode.getValue();
+            checkTypeMatch(expectedType, actualType);
+            Object after = expectedType.toObject(before, actualType);
+            if (before != after) {
+                literalNode = literal(after);
+            }
+        }
+        return literalNode;
+    }
+
+    public ComparisonParseNode comparison(CompareOp op, ParseNode lhs, ParseNode rhs) {
+        switch (op){
+        case LESS:
+            return lt(lhs,rhs);
+        case LESS_OR_EQUAL:
+            return lte(lhs,rhs);
+        case EQUAL:
+            return equal(lhs,rhs);
+        case NOT_EQUAL:
+            return notEqual(lhs,rhs);
+        case GREATER_OR_EQUAL:
+            return gte(lhs,rhs);
+        case GREATER:
+            return gt(lhs,rhs);
+        default:
+            throw new IllegalArgumentException("Unexpcted CompareOp of " + op);
+        }
+    }
+
+    public GreaterThanParseNode gt(ParseNode lhs, ParseNode rhs) {
+        return new GreaterThanParseNode(lhs, rhs);
+    }
+
+
+    public GreaterThanOrEqualParseNode gte(ParseNode lhs, ParseNode rhs) {
+        return new GreaterThanOrEqualParseNode(lhs, rhs);
+    }
+
+    public LessThanParseNode lt(ParseNode lhs, ParseNode rhs) {
+        return new LessThanParseNode(lhs, rhs);
+    }
+
+
+    public LessThanOrEqualParseNode lte(ParseNode lhs, ParseNode rhs) {
+        return new LessThanOrEqualParseNode(lhs, rhs);
+    }
+
+    public EqualParseNode equal(ParseNode lhs, ParseNode rhs) {
+        return new EqualParseNode(lhs, rhs);
+    }
+
+
+    public MultiplyParseNode negate(ParseNode child) {
+        return new MultiplyParseNode(Arrays.asList(child,this.literal(-1)));
+    }
+
+    public NotEqualParseNode notEqual(ParseNode lhs, ParseNode rhs) {
+        return new NotEqualParseNode(lhs, rhs);
+    }
+
+    public NotParseNode not(ParseNode child) {
+        return new NotParseNode(child);
+    }
+
+
+    public OrParseNode or(List<ParseNode> children) {
+        return new OrParseNode(children);
+    }
+
+
+    public OrderByNode orderBy(ParseNode expression, boolean nullsLast, boolean orderAscending) {
+        return new OrderByNode(expression, nullsLast, orderAscending);
+    }
+
+
+    public OuterJoinParseNode outer(ParseNode node) {
+        return new OuterJoinParseNode(node);
+    }
+    
+    public SelectStatement select(List<? extends TableNode> from, HintNode hint, boolean isDistinct, List<AliasedNode> select, ParseNode where,
+            List<ParseNode> groupBy, ParseNode having, List<OrderByNode> orderBy, LimitNode limit, int bindCount, boolean isAggregate) {
+
+        return new SelectStatement(from, hint, isDistinct, select, where, groupBy == null ? Collections.<ParseNode>emptyList() : groupBy, having, orderBy == null ? Collections.<OrderByNode>emptyList() : orderBy, limit, bindCount, isAggregate);
+    }
+    
+    public UpsertStatement upsert(NamedTableNode table, HintNode hint, List<ColumnName> columns, List<ParseNode> values, SelectStatement select, int bindCount) {
+        return new UpsertStatement(table, hint, columns, values, select, bindCount);
+    }
+    
+    public DeleteStatement delete(NamedTableNode table, HintNode hint, ParseNode node, List<OrderByNode> orderBy, LimitNode limit, int bindCount) {
+        return new DeleteStatement(table, hint, node, orderBy, limit, bindCount);
+    }
+
+    public SelectStatement select(SelectStatement statement, ParseNode where, ParseNode having) {
+        return select(statement.getFrom(), statement.getHint(), statement.isDistinct(), statement.getSelect(), where, statement.getGroupBy(), having, statement.getOrderBy(), statement.getLimit(), statement.getBindCount(), statement.isAggregate());
+    }
+
+    public SelectStatement select(SelectStatement statement, List<? extends TableNode> tables) {
+        return select(tables, statement.getHint(), statement.isDistinct(), statement.getSelect(), statement.getWhere(), statement.getGroupBy(), statement.getHaving(), statement.getOrderBy(), statement.getLimit(), statement.getBindCount(), statement.isAggregate());
+    }
+
+    public SelectStatement select(SelectStatement statement, HintNode hint) {
+        return hint == null || hint.isEmpty() ? statement : select(statement.getFrom(), hint, statement.isDistinct(), statement.getSelect(), statement.getWhere(), statement.getGroupBy(), statement.getHaving(), statement.getOrderBy(), statement.getLimit(), statement.getBindCount(), statement.isAggregate());
+    }
+
+    public SubqueryParseNode subquery(SelectStatement select) {
+        return new SubqueryParseNode(select);
+    }
+
+    public LimitNode limit(BindParseNode b) {
+        return new LimitNode(b);
+    }
+
+    public LimitNode limit(LiteralParseNode l) {
+        return new LimitNode(l);
+    }
+}


Mime
View raw message