blob: ac64e031aeb83cce4d7fd4cc803f1def56cf4752 [file] [log] [blame]
/*
* 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.
*/
/** Counterpart of hive's SelectClauseParser.g. */
parser grammar SelectClauseASTParser;
options
{
output=AST;
ASTLabelType=HiveParserASTNode;
backtrack=false;
k=3;
}
@members {
@Override
public Object recoverFromMismatchedSet(IntStream input,
RecognitionException re, BitSet follow) throws RecognitionException {
throw re;
}
@Override
public void displayRecognitionError(String[] tokenNames,
RecognitionException e) {
gParent.errors.add(new HiveASTParseError(gParent, e, tokenNames));
}
protected boolean useSQL11ReservedKeywordsForIdentifier() {
return gParent.useSQL11ReservedKeywordsForIdentifier();
}
}
@rulecatch {
catch (RecognitionException e) {
throw e;
}
}
//----------------------- Rules for parsing selectClause -----------------------------
// select a,b,c ...
selectClause
@init { gParent.pushMsg("select clause", state); }
@after { gParent.popMsg(state); }
:
KW_SELECT QUERY_HINT? (((KW_ALL | dist=KW_DISTINCT)? selectList)
| (transform=KW_TRANSFORM selectTrfmClause))
-> {$transform == null && $dist == null}? ^(TOK_SELECT QUERY_HINT? selectList)
-> {$transform == null && $dist != null}? ^(TOK_SELECTDI QUERY_HINT? selectList)
-> ^(TOK_SELECT QUERY_HINT? ^(TOK_SELEXPR selectTrfmClause) )
|
trfmClause ->^(TOK_SELECT ^(TOK_SELEXPR trfmClause))
;
selectList
@init { gParent.pushMsg("select list", state); }
@after { gParent.popMsg(state); }
:
selectItem ( COMMA selectItem )* -> selectItem+
;
selectTrfmClause
@init { gParent.pushMsg("transform clause", state); }
@after { gParent.popMsg(state); }
:
LPAREN selectExpressionList RPAREN
inSerde=rowFormat inRec=recordWriter
KW_USING StringLiteral
( KW_AS ((LPAREN (aliasList | columnNameTypeList) RPAREN) | (aliasList | columnNameTypeList)))?
outSerde=rowFormat outRec=recordReader
-> ^(TOK_TRANSFORM selectExpressionList $inSerde $inRec StringLiteral $outSerde $outRec aliasList? columnNameTypeList?)
;
selectItem
@init { gParent.pushMsg("selection target", state); }
@after { gParent.popMsg(state); }
:
(tableAllColumns) => tableAllColumns -> ^(TOK_SELEXPR tableAllColumns)
|
( expression
((KW_AS? identifier) | (KW_AS LPAREN identifier (COMMA identifier)* RPAREN))?
) -> ^(TOK_SELEXPR expression identifier*)
;
trfmClause
@init { gParent.pushMsg("transform clause", state); }
@after { gParent.popMsg(state); }
:
( KW_MAP selectExpressionList
| KW_REDUCE selectExpressionList )
inSerde=rowFormat inRec=recordWriter
KW_USING StringLiteral
( KW_AS ((LPAREN (aliasList | columnNameTypeList) RPAREN) | (aliasList | columnNameTypeList)))?
outSerde=rowFormat outRec=recordReader
-> ^(TOK_TRANSFORM selectExpressionList $inSerde $inRec StringLiteral $outSerde $outRec aliasList? columnNameTypeList?)
;
selectExpression
@init { gParent.pushMsg("select expression", state); }
@after { gParent.popMsg(state); }
:
(tableAllColumns) => tableAllColumns
|
expression
;
selectExpressionList
@init { gParent.pushMsg("select expression list", state); }
@after { gParent.popMsg(state); }
:
selectExpression (COMMA selectExpression)* -> ^(TOK_EXPLIST selectExpression+)
;
//---------------------- Rules for windowing clauses -------------------------------
window_clause
@init { gParent.pushMsg("window_clause", state); }
@after { gParent.popMsg(state); }
:
KW_WINDOW window_defn (COMMA window_defn)* -> ^(KW_WINDOW window_defn+)
;
window_defn
@init { gParent.pushMsg("window_defn", state); }
@after { gParent.popMsg(state); }
:
identifier KW_AS window_specification -> ^(TOK_WINDOWDEF identifier window_specification)
;
window_specification
@init { gParent.pushMsg("window_specification", state); }
@after { gParent.popMsg(state); }
:
(identifier | ( LPAREN identifier? partitioningSpec? window_frame? RPAREN)) -> ^(TOK_WINDOWSPEC identifier? partitioningSpec? window_frame?)
;
window_frame :
window_range_expression |
window_value_expression
;
window_range_expression
@init { gParent.pushMsg("window_range_expression", state); }
@after { gParent.popMsg(state); }
:
KW_ROWS sb=window_frame_start_boundary -> ^(TOK_WINDOWRANGE $sb) |
KW_ROWS KW_BETWEEN s=window_frame_boundary KW_AND end=window_frame_boundary -> ^(TOK_WINDOWRANGE $s $end)
;
window_value_expression
@init { gParent.pushMsg("window_value_expression", state); }
@after { gParent.popMsg(state); }
:
KW_RANGE sb=window_frame_start_boundary -> ^(TOK_WINDOWVALUES $sb) |
KW_RANGE KW_BETWEEN s=window_frame_boundary KW_AND end=window_frame_boundary -> ^(TOK_WINDOWVALUES $s $end)
;
window_frame_start_boundary
@init { gParent.pushMsg("windowframestartboundary", state); }
@after { gParent.popMsg(state); }
:
KW_UNBOUNDED KW_PRECEDING -> ^(KW_PRECEDING KW_UNBOUNDED) |
KW_CURRENT KW_ROW -> ^(KW_CURRENT) |
Number KW_PRECEDING -> ^(KW_PRECEDING Number)
;
window_frame_boundary
@init { gParent.pushMsg("windowframeboundary", state); }
@after { gParent.popMsg(state); }
:
KW_UNBOUNDED (r=KW_PRECEDING|r=KW_FOLLOWING) -> ^($r KW_UNBOUNDED) |
KW_CURRENT KW_ROW -> ^(KW_CURRENT) |
Number (d=KW_PRECEDING | d=KW_FOLLOWING ) -> ^($d Number)
;