Return-Path: X-Original-To: apmail-phoenix-commits-archive@minotaur.apache.org Delivered-To: apmail-phoenix-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 2D7A310459 for ; Mon, 10 Mar 2014 04:22:31 +0000 (UTC) Received: (qmail 14577 invoked by uid 500); 10 Mar 2014 04:22:30 -0000 Delivered-To: apmail-phoenix-commits-archive@phoenix.apache.org Received: (qmail 14489 invoked by uid 500); 10 Mar 2014 04:22:28 -0000 Mailing-List: contact commits-help@phoenix.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@phoenix.incubator.apache.org Delivered-To: mailing list commits@phoenix.incubator.apache.org Received: (qmail 13194 invoked by uid 99); 10 Mar 2014 04:22:06 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 10 Mar 2014 04:22:06 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED,T_RP_MATCHES_RCVD X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO mail.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with SMTP; Mon, 10 Mar 2014 04:22:02 +0000 Received: (qmail 12577 invoked by uid 99); 10 Mar 2014 04:21:40 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 10 Mar 2014 04:21:40 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id CC82793BD31; Mon, 10 Mar 2014 04:21:38 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: jeffreyz@apache.org To: commits@phoenix.incubator.apache.org Date: Mon, 10 Mar 2014 04:22:06 -0000 Message-Id: <73241f601a684630aa0ebddfda3805f6@git.apache.org> In-Reply-To: <14e4b95cc75b431ca3baf357fb7116f2@git.apache.org> References: <14e4b95cc75b431ca3baf357fb7116f2@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [35/36] git commit: PHOENIX-126 Use of BOOLEAN in index and/or group by causes exception (JamesTaylor) X-Virus-Checked: Checked by ClamAV on apache.org PHOENIX-126 Use of BOOLEAN in index and/or group by causes exception (JamesTaylor) Project: http://git-wip-us.apache.org/repos/asf/incubator-phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-phoenix/commit/441de12f Tree: http://git-wip-us.apache.org/repos/asf/incubator-phoenix/tree/441de12f Diff: http://git-wip-us.apache.org/repos/asf/incubator-phoenix/diff/441de12f Branch: refs/heads/4.0 Commit: 441de12f1ab900689cdcecab75b67429636f40c7 Parents: 240f89e Author: James Taylor Authored: Sun Mar 9 20:40:45 2014 -0700 Committer: James Taylor Committed: Sun Mar 9 20:40:45 2014 -0700 ---------------------------------------------------------------------- phoenix-core/src/main/antlr3/PhoenixSQL.g | 134 +++++++++---------- .../org/apache/phoenix/parse/SQLParser.java | 7 +- 2 files changed, 67 insertions(+), 74 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/441de12f/phoenix-core/src/main/antlr3/PhoenixSQL.g ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/antlr3/PhoenixSQL.g b/phoenix-core/src/main/antlr3/PhoenixSQL.g index cf6d03d..e0672af 100644 --- a/phoenix-core/src/main/antlr3/PhoenixSQL.g +++ b/phoenix-core/src/main/antlr3/PhoenixSQL.g @@ -361,7 +361,7 @@ create_table_node returns [CreateTableStatement ret] : CREATE TABLE (IF NOT ex=EXISTS)? t=from_table_name (LPAREN c=column_defs (pk=pk_constraint)? RPAREN) (p=fam_properties)? - (SPLIT ON s=list_expressions)? + (SPLIT ON s=value_expression_list)? {ret = factory.createTable(t, p, c, pk, s, PTableType.TABLE, ex!=null, null, null, getBindCount()); } ; @@ -371,7 +371,7 @@ create_view_node returns [CreateTableStatement ret] (LPAREN c=column_defs (pk=pk_constraint)? RPAREN)? ( AS SELECT ASTERISK FROM bt=from_table_name - (WHERE w=condition)? )? + (WHERE w=expression)? )? (p=fam_properties)? { ret = factory.createTable(t, p, c, pk, null, PTableType.VIEW, ex!=null, bt==null ? t : bt, w, getBindCount()); } ; @@ -382,7 +382,7 @@ create_index_node returns [CreateIndexStatement ret] (LPAREN pk=index_pk_constraint RPAREN) (INCLUDE (LPAREN icrefs=column_names RPAREN))? (p=fam_properties)? - (SPLIT ON v=list_expressions)? + (SPLIT ON v=value_expression_list)? {ret = factory.createIndex(i, factory.namedTable(null,t), pk, icrefs, v, p, ex!=null, getBindCount()); } ; @@ -541,9 +541,9 @@ select_node returns [SelectStatement ret] @init{ contextStack.push(new ParseContext()); } : (d=DISTINCT | ALL)? sel=select_list FROM from=parseFrom - (WHERE where=condition)? + (WHERE where=expression)? (GROUP BY group=group_by)? - (HAVING having=condition)? + (HAVING having=expression)? (ORDER BY order=order_by)? (LIMIT l=limit)? { ParseContext context = contextStack.pop(); $ret = factory.select(from, null, d!=null, sel, where, group, having, order, l, getBindCount(), context.isAggregate()); } @@ -561,7 +561,7 @@ hinted_select_node returns [SelectStatement ret] upsert_node returns [UpsertStatement ret] : UPSERT (hint=hintClause)? INTO t=from_table_name (LPAREN p=upsert_column_refs RPAREN)? - ((VALUES LPAREN v=expression_terms RPAREN) | s=select_expression) + ((VALUES LPAREN v=one_or_more_expressions RPAREN) | s=select_expression) {ret = factory.upsert(factory.namedTable(null,t,p == null ? null : p.getFirst()), hint, p == null ? null : p.getSecond(), v, s, getBindCount()); } ; @@ -574,7 +574,7 @@ upsert_column_refs returns [Pair,List> ret] // Parse a full delete expression structure. delete_node returns [DeleteStatement ret] : DELETE (hint=hintClause)? FROM t=from_table_name - (WHERE v=condition)? + (WHERE v=expression)? (ORDER BY order=order_by)? (LIMIT l=limit)? {ret = factory.delete(factory.namedTable(null,t), hint, v, order, l, getBindCount()); } @@ -607,8 +607,8 @@ selectable returns [AliasedNode ret] // Parse a group by statement group_by returns [List ret] @init{ret = new ArrayList();} - : expr=condition { ret.add(expr); } - (COMMA expr = condition {ret.add(expr); })* + : expr=expression { ret.add(expr); } + (COMMA expr = expression {ret.add(expr); })* ; // Parse an order by statement @@ -644,7 +644,7 @@ table_ref returns [TableNode ret] ; join_spec returns [TableNode ret] - : j=join_type JOIN t=table_ref ON e=condition { $ret = factory.join(j, e, t); } + : j=join_type JOIN t=table_ref ON e=expression { $ret = factory.join(j, e, t); } ; join_type returns [JoinTableNode.JoinType ret] @@ -658,43 +658,43 @@ parseAlias returns [String ret] : AS? alias=parseNoReserved { $ret = alias; } ; -// Parse a condition, such as used in a where clause - either a basic one, or an OR of (Single or AND) expressions -condition returns [ParseNode ret] - : e=condition_or { $ret = e; } +// Parse a expression, such as used in a where clause - either a basic one, or an OR of (Single or AND) expressions +expression returns [ParseNode ret] + : e=or_expression { $ret = e; } ; // A set of OR'd simple expressions -condition_or returns [ParseNode ret] +or_expression returns [ParseNode ret] @init{List l = new ArrayList(4); } - : i=condition_and {l.add(i);} (OR i=condition_and {l.add(i);})* { $ret = l.size() == 1 ? l.get(0) : factory.or(l); } + : i=and_expression {l.add(i);} (OR i=and_expression {l.add(i);})* { $ret = l.size() == 1 ? l.get(0) : factory.or(l); } ; // A set of AND'd simple expressions -condition_and returns [ParseNode ret] +and_expression returns [ParseNode ret] @init{List l = new ArrayList(4); } - : i=condition_not {l.add(i);} (AND i=condition_not {l.add(i);})* { $ret = l.size() == 1 ? l.get(0) : factory.and(l); } + : i=not_expression {l.add(i);} (AND i=not_expression {l.add(i);})* { $ret = l.size() == 1 ? l.get(0) : factory.and(l); } ; // NOT or parenthesis -condition_not returns [ParseNode ret] - : (NOT? boolean_expr ) => n=NOT? e=boolean_expr { $ret = n == null ? e : factory.not(e); } - | n=NOT? LPAREN e=condition RPAREN { $ret = n == null ? e : factory.not(e); } - ; - -boolean_expr returns [ParseNode ret] - : l=expression ((EQ r=expression {$ret = factory.equal(l,r); } ) - | ((NOEQ1 | NOEQ2) r=expression {$ret = factory.notEqual(l,r); } ) - | (LT r=expression {$ret = factory.lt(l,r); } ) - | (GT r=expression {$ret = factory.gt(l,r); } ) - | (LT EQ r=expression {$ret = factory.lte(l,r); } ) - | (GT EQ r=expression {$ret = factory.gte(l,r); } ) +not_expression returns [ParseNode ret] + : (NOT? boolean_expression ) => n=NOT? e=boolean_expression { $ret = n == null ? e : factory.not(e); } + | n=NOT? LPAREN e=expression RPAREN { $ret = n == null ? e : factory.not(e); } + ; + +boolean_expression returns [ParseNode ret] + : l=value_expression ((EQ r=value_expression {$ret = factory.equal(l,r); } ) + | ((NOEQ1 | NOEQ2) r=value_expression {$ret = factory.notEqual(l,r); } ) + | (LT r=value_expression {$ret = factory.lt(l,r); } ) + | (GT r=value_expression {$ret = factory.gt(l,r); } ) + | (LT EQ r=value_expression {$ret = factory.lte(l,r); } ) + | (GT EQ r=value_expression {$ret = factory.gte(l,r); } ) | (IS n=NOT? NULL {$ret = factory.isNull(l,n!=null); } ) - | ( n=NOT? ((LIKE r=expression {$ret = factory.like(l,r,n!=null); } ) + | ( n=NOT? ((LIKE r=value_expression {$ret = factory.like(l,r,n!=null); } ) | (EXISTS LPAREN r=subquery_expression RPAREN {$ret = factory.exists(l,r,n!=null);} ) - | (BETWEEN r1=expression AND r2=expression {$ret = factory.between(l,r1,r2,n!=null); } ) + | (BETWEEN r1=value_expression AND r2=value_expression {$ret = factory.between(l,r1,r2,n!=null); } ) | ((IN ((r=bind_expression {$ret = factory.inList(Arrays.asList(l,r),n!=null);} ) | (LPAREN r=subquery_expression RPAREN {$ret = factory.in(l,r,n!=null);} ) - | (v=list_expressions {List il = new ArrayList(v.size() + 1); il.add(l); il.addAll(v); $ret = factory.inList(il,n!=null);}) + | (LPAREN v=one_or_more_expressions RPAREN {List il = new ArrayList(v.size() + 1); il.add(l); il.addAll(v); $ret = factory.inList(il,n!=null);}) ))) )) | { $ret = l; } ) @@ -704,50 +704,50 @@ bind_expression returns [BindParseNode ret] : b=bind_name { $ret = factory.bind(b); } ; -expression returns [ParseNode ret] - : i=expression_add { $ret = i; } +value_expression returns [ParseNode ret] + : i=add_expression { $ret = i; } ; -expression_add returns [ParseNode ret] +add_expression returns [ParseNode ret] @init{List l = new ArrayList(4); } - : i=expression_sub {l.add(i);} (PLUS i=expression_sub {l.add(i);})* { $ret = l.size() == 1 ? l.get(0) : factory.add(l); } + : i=subtract_expression {l.add(i);} (PLUS i=subtract_expression {l.add(i);})* { $ret = l.size() == 1 ? l.get(0) : factory.add(l); } ; -expression_sub returns [ParseNode ret] +subtract_expression returns [ParseNode ret] @init{List l = new ArrayList(4); } - : i=expression_concat {l.add(i);} (MINUS i=expression_concat {l.add(i);})* { $ret = l.size() == 1 ? l.get(0) : factory.subtract(l); } + : i=concat_expression {l.add(i);} (MINUS i=concat_expression {l.add(i);})* { $ret = l.size() == 1 ? l.get(0) : factory.subtract(l); } ; -expression_concat returns [ParseNode ret] +concat_expression returns [ParseNode ret] @init{List l = new ArrayList(4); } - : i=expression_mult {l.add(i);} (CONCAT i=expression_mult {l.add(i);})* { $ret = l.size() == 1 ? l.get(0) : factory.concat(l); } + : i=multiply_expression {l.add(i);} (CONCAT i=multiply_expression {l.add(i);})* { $ret = l.size() == 1 ? l.get(0) : factory.concat(l); } ; -expression_mult returns [ParseNode ret] +multiply_expression returns [ParseNode ret] @init{List l = new ArrayList(4); } - : i=expression_div {l.add(i);} (ASTERISK i=expression_div {l.add(i);})* { $ret = l.size() == 1 ? l.get(0) : factory.multiply(l); } + : i=divide_expression {l.add(i);} (ASTERISK i=divide_expression {l.add(i);})* { $ret = l.size() == 1 ? l.get(0) : factory.multiply(l); } ; -expression_div returns [ParseNode ret] +divide_expression returns [ParseNode ret] @init{List l = new ArrayList(4); } - : i=expression_negate {l.add(i);} (DIVIDE i=expression_negate {l.add(i);})* { $ret = l.size() == 1 ? l.get(0) : factory.divide(l); } + : i=negate_expression {l.add(i);} (DIVIDE i=negate_expression {l.add(i);})* { $ret = l.size() == 1 ? l.get(0) : factory.divide(l); } ; -expression_negate returns [ParseNode ret] - : m=MINUS? e=expression_term { $ret = m==null ? e : factory.negate(e); } +negate_expression returns [ParseNode ret] + : m=MINUS? e=term { $ret = m==null ? e : factory.negate(e); } ; // The lowest level function, which includes literals, binds, but also parenthesized expressions, functions, and case statements. -expression_term returns [ParseNode ret] - : e=literal_or_bind_value { $ret = e; } - | e=arrayable_expression_term (LSQUARE s=expression RSQUARE)? { if (s == null) { $ret = e; } else { $ret = factory.arrayElemRef(Arrays.asList(e,s)); } } +term returns [ParseNode ret] + : e=literal_or_bind { $ret = e; } + | e=non_literal_term (LSQUARE s=value_expression RSQUARE)? { if (s == null) { $ret = e; } else { $ret = factory.arrayElemRef(Arrays.asList(e,s)); } } ; -arrayable_expression_term returns [ParseNode ret] +non_literal_term returns [ParseNode ret] : field=identifier { $ret = factory.column(null,field,field); } - | ex=ARRAY LSQUARE v=expression_terms RSQUARE {$ret = factory.upsertStmtArrayNode(v);} + | ex=ARRAY LSQUARE v=one_or_more_expressions RSQUARE {$ret = factory.upsertStmtArrayNode(v);} | tableName=table_name DOT field=identifier { $ret = factory.column(tableName, field, field); } - | field=identifier LPAREN l=expression_list RPAREN wg=(WITHIN GROUP LPAREN ORDER BY l2=expression_terms (a=ASC | DESC) RPAREN)? + | field=identifier LPAREN l=zero_or_more_expressions RPAREN wg=(WITHIN GROUP LPAREN ORDER BY l2=one_or_more_expressions (a=ASC | DESC) RPAREN)? { FunctionParseNode f = wg==null ? factory.function(field, l) : factory.function(field,l,l2,a!=null); contextStack.peek().setAggregate(f.isAggregate()); @@ -762,14 +762,14 @@ arrayable_expression_term returns [ParseNode ret] contextStack.peek().setAggregate(f.isAggregate()); $ret = f; } - | field=identifier LPAREN t=DISTINCT l=expression_list RPAREN + | field=identifier LPAREN t=DISTINCT l=zero_or_more_expressions RPAREN { FunctionParseNode f = factory.functionDistinct(field, l); contextStack.peek().setAggregate(f.isAggregate()); $ret = f; } | e=case_statement { $ret = e; } - | LPAREN l=expression_terms RPAREN + | LPAREN l=one_or_more_expressions RPAREN { if(l.size() == 1) { $ret = l.get(0); @@ -782,16 +782,21 @@ arrayable_expression_term returns [ParseNode ret] | (n=NEXT | CURRENT) VALUE FOR s=from_table_name { $ret = n==null ? factory.currentValueFor(s) : factory.nextValueFor(s);} ; -expression_terms returns [List ret] +one_or_more_expressions returns [List ret] @init{ret = new ArrayList(); } : e = expression {$ret.add(e);} (COMMA e = expression {$ret.add(e);} )* ; -expression_list returns [List ret] +zero_or_more_expressions returns [List ret] @init{ret = new ArrayList(); } : (v = expression {$ret.add(v);})? (COMMA v = expression {$ret.add(v);} )* ; +value_expression_list returns [List ret] +@init{ret = new ArrayList(); } + : LPAREN e = value_expression {$ret.add(e);} (COMMA e = value_expression {$ret.add(e);} )* RPAREN +; + index_name returns [NamedNode ret] : name=identifier {$ret = factory.indexName(name); } ; @@ -809,7 +814,7 @@ from_table_name returns [TableName ret] ; // The lowest level function, which includes literals, binds, but also parenthesized expressions, functions, and case statements. -literal_or_bind_value returns [ParseNode ret] +literal_or_bind returns [ParseNode ret] : e=literal { $ret = e; } | b=bind_name { $ret = factory.bind(b); } ; @@ -871,20 +876,9 @@ double_literal returns [LiteralParseNode ret] } ; -list_expressions returns [List ret] -@init{ret = new ArrayList(); } - : LPAREN v = expression {$ret.add(v);} (COMMA v = expression {$ret.add(v);} )* RPAREN -; - -// parse a field, if it might be a bind name. -table returns [String ret] - : b=bind_name { $ret = b; } - | n=parseNoReserved { $ret = n; } - ; - // Bind names are a colon followed by 1+ letter/digits/underscores, or '?' (unclear how Oracle acutally deals with this, but we'll just treat it as a special bind) bind_name returns [String ret] - : bname=BIND_NAME { String bnameStr = bname.getText().substring(1); updateBind(bnameStr); $ret = bnameStr; } + : n=BIND_NAME { String bind = n.getText().substring(1); updateBind(bind); $ret = bind; } | QUESTION { $ret = nextBind(); } // TODO: only support this? ; @@ -900,7 +894,7 @@ parseNoReserved returns [String ret] case_statement returns [ParseNode ret] @init{List w = new ArrayList(4);} : CASE e1=expression (WHEN e2=expression THEN t=expression {w.add(t);w.add(factory.equal(e1,e2));})+ (ELSE el=expression {w.add(el);})? END {$ret = factory.caseWhen(w);} - | CASE (WHEN c=condition THEN t=expression {w.add(t);w.add(c);})+ (ELSE el=expression {w.add(el);})? END {$ret = factory.caseWhen(w);} + | CASE (WHEN c=expression THEN t=expression {w.add(t);w.add(c);})+ (ELSE el=expression {w.add(el);})? END {$ret = factory.caseWhen(w);} ; // -------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-phoenix/blob/441de12f/phoenix-core/src/main/java/org/apache/phoenix/parse/SQLParser.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/SQLParser.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/SQLParser.java index c2c94a7..36f756c 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/parse/SQLParser.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/SQLParser.java @@ -27,7 +27,6 @@ import org.antlr.runtime.ANTLRReaderStream; import org.antlr.runtime.CharStream; import org.antlr.runtime.CommonTokenStream; import org.antlr.runtime.RecognitionException; - import org.apache.phoenix.exception.PhoenixParserException; /** @@ -45,7 +44,7 @@ public class SQLParser { public static ParseNode parseCondition(String expression) throws SQLException { if (expression == null) return null; SQLParser parser = new SQLParser(expression); - return parser.parseCondition(); + return parser.parseExpression(); } public SQLParser(String query) { @@ -144,9 +143,9 @@ public class SQLParser { * Used only in tests * @throws SQLException */ - public ParseNode parseCondition() throws SQLException { + public ParseNode parseExpression() throws SQLException { try { - ParseNode node = parser.condition(); + ParseNode node = parser.expression(); return node; } catch (RecognitionException e) { throw PhoenixParserException.newException(e, parser.getTokenNames());