javacc.Parser.jj Maven / Gradle / Ivy
options {
STATIC = false;
IGNORE_CASE = true;
UNICODE_INPUT = true;
}
PARSER_BEGIN(DrillParserImpl)
package org.apache.drill.exec.planner.sql.parser.impl;
import org.apache.drill.exec.planner.sql.parser.*;
import org.apache.calcite.util.*;
import java.util.*;
import org.apache.calcite.avatica.util.Casing;
import org.apache.calcite.avatica.util.DateTimeUtils;
import org.apache.calcite.avatica.util.TimeUnit;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.runtime.CalciteContextException;
import org.apache.calcite.sql.JoinConditionType;
import org.apache.calcite.sql.JoinType;
import org.apache.calcite.sql.SqlBinaryOperator;
import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlCharStringLiteral;
import org.apache.calcite.sql.SqlCollation;
import org.apache.calcite.sql.SqlDataTypeSpec;
import org.apache.calcite.sql.SqlDateLiteral;
import org.apache.calcite.sql.SqlDelete;
import org.apache.calcite.sql.SqlDynamicParam;
import org.apache.calcite.sql.SqlExplain;
import org.apache.calcite.sql.SqlExplainLevel;
import org.apache.calcite.sql.SqlFunction;
import org.apache.calcite.sql.SqlFunctionCategory;
import org.apache.calcite.sql.SqlIdentifier;
import org.apache.calcite.sql.SqlInsert;
import org.apache.calcite.sql.SqlInsertKeyword;
import org.apache.calcite.sql.SqlIntervalLiteral;
import org.apache.calcite.sql.SqlIntervalQualifier;
import org.apache.calcite.sql.SqlJdbcFunctionCall;
import org.apache.calcite.sql.SqlJoin;
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.SqlLiteral;
import org.apache.calcite.sql.SqlMerge;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlNodeList;
import org.apache.calcite.sql.SqlNumericLiteral;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlOrderBy;
import org.apache.calcite.sql.SqlPostfixOperator;
import org.apache.calcite.sql.SqlPrefixOperator;
import org.apache.calcite.sql.SqlSampleSpec;
import org.apache.calcite.sql.SqlSelect;
import org.apache.calcite.sql.SqlSelectKeyword;
import org.apache.calcite.sql.SqlSetOption;
import org.apache.calcite.sql.SqlTimeLiteral;
import org.apache.calcite.sql.SqlTimestampLiteral;
import org.apache.calcite.sql.SqlUpdate;
import org.apache.calcite.sql.SqlUtil;
import org.apache.calcite.sql.SqlWindow;
import org.apache.calcite.sql.SqlWith;
import org.apache.calcite.sql.SqlWithItem;
import org.apache.calcite.sql.fun.SqlCase;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.sql.fun.SqlTrimFunction;
import org.apache.calcite.sql.parser.SqlAbstractParserImpl;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.calcite.sql.parser.SqlParser;
import org.apache.calcite.sql.parser.SqlParserImplFactory;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.parser.SqlParserUtil;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.util.Util;
import org.apache.calcite.util.trace.CalciteTrace;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import java.io.Reader;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.apache.calcite.util.Static.RESOURCE;
/**
* SQL parser, generated from Parser.jj by JavaCC.
*
* The public wrapper for this parser is {@link SqlParser}.
*/
public class DrillParserImpl extends SqlAbstractParserImpl
{
private static final Logger LOGGER = CalciteTrace.getParserTracer();
// Can't use quoted literal because of a bug in how JavaCC translates
// backslash-backslash.
private static final char BACKSLASH = 0x5c;
private static final char DOUBLE_QUOTE = 0x22;
private static final String DQ = DOUBLE_QUOTE + "";
private static final String DQDQ = DQ + DQ;
private static Metadata metadata;
private Casing unquotedCasing;
private Casing quotedCasing;
private int identifierMaxLength;
/**
* {@link SqlParserImplFactory} implementation for creating parser.
*/
public static final SqlParserImplFactory FACTORY = new SqlParserImplFactory() {
public SqlAbstractParserImpl getParser(Reader stream) {
return new DrillParserImpl(stream);
}
};
// implement SqlAbstractParserImpl
public SqlParseException normalizeException(Throwable ex)
{
try {
if (ex instanceof ParseException) {
ex = cleanupParseException((ParseException) ex);
}
return convertException(ex);
} catch (ParseException e) {
throw new AssertionError(e);
}
}
// implement SqlAbstractParserImpl
public Metadata getMetadata()
{
synchronized (DrillParserImpl.class) {
if (metadata == null) {
metadata = new MetadataImpl(
new DrillParserImpl(new java.io.StringReader("")));
}
return metadata;
}
}
// implement SqlAbstractParserImpl
public void setTabSize(int tabSize)
{
jj_input_stream.setTabSize(tabSize);
}
// implement SqlAbstractParserImpl
public void switchTo(String stateName)
{
int state = Arrays.asList(DrillParserImplTokenManager.lexStateNames)
.indexOf(stateName);
token_source.SwitchTo(state);
}
// implement SqlAbstractParserImpl
public void setQuotedCasing(Casing quotedCasing)
{
this.quotedCasing = quotedCasing;
}
// implement SqlAbstractParserImpl
public void setUnquotedCasing(Casing unquotedCasing)
{
this.unquotedCasing = unquotedCasing;
}
// implement SqlAbstractParserImpl
public void setIdentifierMaxLength(int identifierMaxLength)
{
this.identifierMaxLength = identifierMaxLength;
}
// implement SqlAbstractParserImpl
public SqlNode parseSqlExpressionEof() throws Exception
{
return SqlExpressionEof();
}
// implement SqlAbstractParserImpl
public SqlNode parseSqlStmtEof() throws Exception
{
return SqlStmtEof();
}
private SqlNode extend(SqlNode table, SqlNodeList extendList) {
return SqlStdOperatorTable.EXTEND.createCall(
table.getParserPosition().plus(extendList.getParserPosition()),
table, extendList);
}
}
PARSER_END(DrillParserImpl)
/*****************************************
* Utility Codes for Semantical Analysis *
*****************************************/
/* For Debug */
JAVACODE
void debug_message1()
{
LOGGER.log(Level.INFO, getToken( 0 ).image
+ " , " + getToken( 1 ).image );
}
JAVACODE String unquotedIdentifier() {
return SqlParserUtil.strip(getToken(0).image, null, null, null,
unquotedCasing);
}
String NonReservedKeyWord() :
{
String kw;
}
{
kw = CommonNonReservedKeyWord()
{
return kw;
}
}
/**
* Allows parser to be extended with new types of table references. The
* default implementation of this production is empty.
*/
SqlNode ExtendedTableRef() :
{
}
{
UnusedExtension()
{
return null;
}
}
/**
* Allows an OVER clause following a table expression as an extension to
* standard SQL syntax. The default implementation of this production is empty.
*/
SqlNode TableOverOpt() :
{
}
{
{
return null;
}
}
/*
* Parses dialect-specific keywords immediately following the SELECT keyword.
*/
void SqlSelectKeywords(List keywords) :
{}
{
E()
}
/*
* Parses dialect-specific keywords immediately following the INSERT keyword.
*/
void SqlInsertKeywords(List keywords) :
{}
{
E()
}
SqlNode ExtendedBuiltinFunctionCall() :
{
}
{
UnusedExtension()
{
return null;
}
}
/*
* Parse Floor/Ceil function parameters
*/
SqlNode FloorCeilOptions(SqlParserPos pos, boolean floorFlag) :
{
SqlNode node;
}
{
node = StandardFloorCeilOptions(pos, floorFlag)
{
return node;
}
}
// End Parser.jj
/*
// This file contains the heart of a parser for SQL SELECT statements.
// code can be shared between various parsers (for example, a DDL parser and a
// DML parser) but is not a standalone JavaCC file. You need to prepend a
// parser declaration (such as that in Parser.jj).
*/
/* Epsilon */
JAVACODE
void E() {}
JAVACODE List startList(Object o)
{
List list = new ArrayList();
list.add(o);
return list;
}
/*
* NOTE jvs 6-Feb-2004: The straightforward way to implement the SQL grammar is
* to keep query expressions (SELECT, UNION, etc) separate from row expressions
* (+, LIKE, etc). However, this is not possible with an LL(k) parser, because
* both kinds of expressions allow parenthesization, so no fixed amount of left
* context is ever good enough. A subquery can be a leaf in a row expression,
* and can include operators like UNION, so it's not even possible to use a
* syntactic lookahead rule like "look past an indefinite number of parentheses
* until you see SELECT, VALUES, or TABLE" (since at that point we still
* don't know whether we're parsing a subquery like ((select ...) + x)
* vs. (select ... union select ...).
*
* The somewhat messy solution is to unify the two kinds of expression,
* and to enforce syntax rules using parameterized context. This
* is the purpose of the ExprContext parameter. It is passed to
* most expression productions, which check the expressions encountered
* against the context for correctness. When a query
* element like SELECT is encountered, the production calls
* checkQueryExpression, which will throw an exception if
* a row expression was expected instead. When a row expression like
* IN is encountered, the production calls checkNonQueryExpression
* instead. It is very important to understand how this works
* when modifying the grammar.
*
* The commingling of expressions results in some bogus ambiguities which are
* resolved with LOOKAHEAD hints. The worst example is comma. SQL allows both
* (WHERE x IN (1,2)) and (WHERE x IN (select ...)). This means when we parse
* the right-hand-side of an IN, we have to allow any kind of expression inside
* the parentheses. Now consider the expression "WHERE x IN(SELECT a FROM b
* GROUP BY c,d)". When the parser gets to "c,d" it doesn't know whether the
* comma indicates the end of the GROUP BY or the end of one item in an IN
* list. Luckily, we know that select and comma-list are mutually exclusive
* within IN, so we use maximal munch for the GROUP BY comma. However, this
* usage of hints could easily mask unintended ambiguities resulting from
* future changes to the grammar, making it very brittle.
*/
JAVACODE SqlParserPos getPos()
{
return new SqlParserPos(
token.beginLine,
token.beginColumn,
token.endLine,
token.endColumn);
}
JAVACODE void checkQueryExpression(ExprContext exprContext)
{
switch (exprContext) {
case ACCEPT_NONQUERY:
case ACCEPT_SUBQUERY:
case ACCEPT_CURSOR:
throw SqlUtil.newContextException(getPos(),
RESOURCE.illegalQueryExpression());
}
}
JAVACODE void checkNonQueryExpression(ExprContext exprContext)
{
switch (exprContext) {
case ACCEPT_QUERY:
throw SqlUtil.newContextException(getPos(),
RESOURCE.illegalNonQueryExpression());
}
}
// The date/time parse utilities have to live here, instead of in the
// SqlParserUtil class because ParseException is ambiguous, and
// CommonParser has to live in multiple packages.
JAVACODE SqlDateLiteral parseDateLiteral(String s, SqlParserPos pos) {
String dateStr = SqlParserUtil.parseString(s);
Calendar cal = DateTimeUtils.parseDateFormat(
dateStr, DateTimeUtils.DATE_FORMAT_STRING, DateTimeUtils.GMT_ZONE);
if (null == cal) {
throw SqlUtil.newContextException(pos,
RESOURCE.illegalLiteral("DATE", s,
RESOURCE.badFormat(DateTimeUtils.DATE_FORMAT_STRING).str()));
}
return SqlLiteral.createDate(cal, pos);
}
JAVACODE SqlTimeLiteral parseTimeLiteral(String s, SqlParserPos pos) {
String dateStr = SqlParserUtil.parseString(s);
DateTimeUtils.PrecisionTime pt =
DateTimeUtils.parsePrecisionDateTimeLiteral(
dateStr, DateTimeUtils.TIME_FORMAT_STRING, DateTimeUtils.GMT_ZONE);
if (null == pt) {
throw SqlUtil.newContextException(pos,
RESOURCE.illegalLiteral("TIME", s,
RESOURCE.badFormat(DateTimeUtils.TIME_FORMAT_STRING).str()));
}
return SqlLiteral.createTime(pt.getCalendar(), pt.getPrecision(), pos);
}
JAVACODE SqlTimestampLiteral parseTimestampLiteral(String s, SqlParserPos pos) {
String dateStr = SqlParserUtil.parseString(s);
DateTimeUtils.PrecisionTime pt =
DateTimeUtils.parsePrecisionDateTimeLiteral(
dateStr, DateTimeUtils.TIMESTAMP_FORMAT_STRING, DateTimeUtils.GMT_ZONE);
if (null == pt) {
throw SqlUtil.newContextException(pos,
RESOURCE.illegalLiteral("TIMESTAMP", s,
RESOURCE.badFormat(DateTimeUtils.TIMESTAMP_FORMAT_STRING).str()));
}
return SqlLiteral.createTimestamp(pt.getCalendar(), pt.getPrecision(), pos);
}
JAVACODE SqlIntervalLiteral parseIntervalLiteral(
SqlParserPos pos,
int sign,
String s,
SqlIntervalQualifier intervalQualifier) throws ParseException
{
String intervalStr = SqlParserUtil.parseString(s);
if ("".equals(intervalStr)) {
throw new ParseException(
RESOURCE.illegalIntervalLiteral(s + " "
+ intervalQualifier.toString(), pos.toString()).str());
}
return SqlLiteral.createInterval(sign, intervalStr, intervalQualifier, pos);
}
/**
* Converts a ParseException (local to this particular instantiation
* of the parser) into a SqlParseException (common to all parsers).
*/
JAVACODE SqlParseException convertException(Throwable ex)
{
if (ex instanceof SqlParseException) {
return (SqlParseException) ex;
}
SqlParserPos pos = null;
int[][] expectedTokenSequences = null;
String[] tokenImage = null;
if (ex instanceof ParseException) {
ParseException pex = (ParseException) ex;
expectedTokenSequences = pex.expectedTokenSequences;
tokenImage = pex.tokenImage;
if (pex.currentToken != null) {
final Token token = pex.currentToken.next;
pos = new SqlParserPos(
token.beginLine,
token.beginColumn,
token.endLine,
token.endColumn);
}
} else if (ex instanceof TokenMgrError) {
TokenMgrError tme = (TokenMgrError) ex;
expectedTokenSequences = null;
tokenImage = null;
// Example:
// Lexical error at line 3, column 24. Encountered "#" after "a".
final java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(
"(?s)Lexical error at line ([0-9]+), column ([0-9]+).*");
java.util.regex.Matcher matcher = pattern.matcher(ex.getMessage());
if (matcher.matches()) {
int line = Integer.parseInt(matcher.group(1));
int column = Integer.parseInt(matcher.group(2));
pos = new SqlParserPos(line, column, line, column);
}
} else if (ex instanceof CalciteContextException) {
// CalciteContextException is the standard wrapper for exceptions
// produced by the validator, but in the parser, the standard is
// SqlParseException; so, strip it away. In case you were wondering,
// the CalciteContextException appears because the parser
// occasionally calls into validator-style code such as
// SqlSpecialOperator.reduceExpr.
CalciteContextException ece =
(CalciteContextException) ex;
pos = new SqlParserPos(
ece.getPosLine(),
ece.getPosColumn(),
ece.getEndPosLine(),
ece.getEndPosColumn());
ex = ece.getCause();
}
return new SqlParseException(
ex.getMessage(), pos, expectedTokenSequences, tokenImage, ex);
}
/**
* Removes or transforms misleading information from a parse exception.
*
* @param e dirty excn
*
* @return clean excn
*/
JAVACODE ParseException cleanupParseException(ParseException ex)
{
if (ex.expectedTokenSequences == null) {
return ex;
}
int iIdentifier = java.util.Arrays.asList(ex.tokenImage).indexOf("");
// Find all sequences in the error which contain identifier. For
// example,
// {}
// {A}
// {B, C}
// {D, }
// {D, A}
// {D, B}
//
// would yield
// {}
// {D}
boolean id = false;
final List prefixList = new ArrayList();
for (int i = 0; i < ex.expectedTokenSequences.length; ++i) {
int[] seq = ex.expectedTokenSequences[i];
int j = seq.length - 1;
int i1 = seq[j];
if (i1 == iIdentifier) {
int[] prefix = new int[j];
System.arraycopy(seq, 0, prefix, 0, j);
prefixList.add(prefix);
}
}
if (prefixList.isEmpty()) {
return ex;
}
int[][] prefixes = (int[][])
prefixList.toArray(new int[prefixList.size()][]);
// Since was one of the possible productions,
// we know that the parser will also have included all
// of the non-reserved keywords (which are treated as
// identifiers in non-keyword contexts). So, now we need
// to clean those out, since they're totally irrelevant.
final List list = new ArrayList();
Metadata metadata = getMetadata();
for (int i = 0; i < ex.expectedTokenSequences.length; ++i) {
int [] seq = ex.expectedTokenSequences[i];
String tokenImage = ex.tokenImage[seq[seq.length - 1]];
String token = SqlParserUtil.getTokenVal(tokenImage);
if (token == null || !metadata.isNonReservedKeyword(token)) {
list.add(seq);
continue;
}
boolean match = matchesPrefix(seq, prefixes);
if (!match) {
list.add(seq);
}
}
ex.expectedTokenSequences =
(int [][]) list.toArray(new int [list.size()][]);
return ex;
}
JAVACODE boolean matchesPrefix(int[] seq, int[][] prefixes)
{
nextPrefix:
for (int[] prefix : prefixes) {
if (seq.length == prefix.length + 1) {
for (int k = 0; k < prefix.length; k++) {
if (prefix[k] != seq[k]) {
continue nextPrefix;
}
}
return true;
}
}
return false;
}
/*****************************************
* Syntactical Descriptions *
*****************************************/
/**
* Parses either a row expression or a query expression with an optional
* ORDER BY.
*
* Postgres syntax for limit:
*
* [ LIMIT { count | ALL } ]
* [ OFFSET start ]
*
*
SQL:2008 syntax for limit:
*
* [ OFFSET start { ROW | ROWS } ]
* [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ]
*/
SqlNode OrderedQueryOrExpr(ExprContext exprContext) :
{
SqlNode e;
SqlNodeList orderBy = null;
SqlNode start = null;
SqlNode count = null;
SqlParserPos pos = null;
}
{
(
e = QueryOrExpr(exprContext)
)
[
// use the syntactic type of the expression we just parsed
// to decide whether ORDER BY makes sense
orderBy = OrderBy(e.isA(SqlKind.QUERY))
]
[
// Postgres-style syntax. "LIMIT ... OFFSET ..."
( count = UnsignedNumericLiteral() | )
]
[
// ROW or ROWS is required in SQL:2008 but we make it optional
// because it is not present in Postgres-style syntax.
start = UnsignedNumericLiteral() [ | ]
]
[
// SQL:2008-style syntax. "OFFSET ... FETCH ...".
// If you specify both LIMIT and FETCH, FETCH wins.
( | ) count = UnsignedNumericLiteral() ( | )
]
{
if (orderBy != null || start != null || count != null) {
pos = getPos();
if (orderBy == null) {
orderBy = SqlNodeList.EMPTY;
}
e = new SqlOrderBy(pos, e, orderBy, start, count);
}
return e;
}
}
/**
* Parses a leaf in a query expression (SELECT, VALUES or TABLE).
*/
SqlNode LeafQuery(ExprContext exprContext) :
{
SqlNode e;
}
{
{
// ensure a query is legal in this context
checkQueryExpression(exprContext);
}
e = SqlSelect()
{
return e;
}
| e = TableConstructor()
{
return e;
}
| e = ExplicitTable(getPos())
{
return e;
}
}
/**
* Parses a parenthesized query or single row expression.
*/
SqlNode ParenthesizedExpression(ExprContext exprContext) :
{
SqlNode e;
}
{
{
// we've now seen left paren, so queries inside should
// be allowed as subqueries
switch (exprContext) {
case ACCEPT_SUBQUERY:
exprContext = ExprContext.ACCEPT_NONCURSOR;
break;
case ACCEPT_CURSOR:
exprContext = ExprContext.ACCEPT_ALL;
break;
}
}
e = OrderedQueryOrExpr(exprContext)
{
return e;
}
}
/**
* Parses a parenthesized query or comma-list of row expressions.
*
* REVIEW jvs 8-Feb-2004: There's a small hole in this production. It can be
* used to construct something like
*
* WHERE x IN (select count(*) from t where c=d,5)
,
*
* which should be illegal. The above is interpreted as equivalent to
*
* WHERE x IN ((select count(*) from t where c=d),5)
,
*
* which is a legal use of a subquery. The only way to fix the hole is to be
* able to remember whether a subexpression was parenthesized or not, which
* means preserving parentheses in the SqlNode tree. This is probably
* desirable anyway for use in purely syntactic parsing applications (e.g. SQL
* pretty-printer). However, if this is done, it's important to also make
* isA() on the paren node call down to its operand so that we can
* always correctly discriminate a query from a row expression.
*/
SqlNodeList ParenthesizedQueryOrCommaList(
ExprContext exprContext) :
{
SqlNode e;
List list;
ExprContext firstExprContext = exprContext;
SqlParserPos pos;
}
{
{
// we've now seen left paren, so a query by itself should
// be interpreted as a subquery
pos = getPos();
switch (exprContext) {
case ACCEPT_SUBQUERY:
firstExprContext = ExprContext.ACCEPT_NONCURSOR;
break;
case ACCEPT_CURSOR:
firstExprContext = ExprContext.ACCEPT_ALL;
break;
}
}
e = OrderedQueryOrExpr(firstExprContext)
{
list = startList(e);
}
(
{
// a comma-list can't appear where only a query is expected
checkNonQueryExpression(exprContext);
}
e = Expression(exprContext)
{
list.add(e);
}
) *
{
return new SqlNodeList(list, pos.plus(getPos()));
}
}
/**
* Parses function parameter lists including DISTINCT keyword recognition,
* DEFAULT, and named argument assignment.
*/
List FunctionParameterList(
ExprContext exprContext) :
{
SqlNode e = null;
List list = new ArrayList();
}
{
[
{
e = SqlSelectKeyword.DISTINCT.symbol(getPos());
}
|
{
e = SqlSelectKeyword.ALL.symbol(getPos());
}
]
{
list.add(e);
}
Arg0(list, exprContext)
(
{
// a comma-list can't appear where only a query is expected
checkNonQueryExpression(exprContext);
}
Arg(list, exprContext)
)*
{
return list;
}
}
void Arg0(List list, ExprContext exprContext) :
{
SqlIdentifier name = null;
SqlNode e = null;
final ExprContext firstExprContext;
{
// we've now seen left paren, so queries inside should
// be allowed as subqueries
switch (exprContext) {
case ACCEPT_SUBQUERY:
firstExprContext = ExprContext.ACCEPT_NONCURSOR;
break;
case ACCEPT_CURSOR:
firstExprContext = ExprContext.ACCEPT_ALL;
break;
default:
firstExprContext = exprContext;
break;
}
}
}
{
[
name = SimpleIdentifier()
]
(
{
e = SqlStdOperatorTable.DEFAULT.createCall(getPos());
}
|
e = OrderedQueryOrExpr(firstExprContext)
)
{
if (e != null) {
if (name != null) {
e = SqlStdOperatorTable.ARGUMENT_ASSIGNMENT.createCall(
name.getParserPosition().plus(e.getParserPosition()),
e, name);
}
list.add(e);
}
}
}
void Arg(List list, ExprContext exprContext) :
{
SqlIdentifier name = null;
SqlNode e = null;
}
{
[
name = SimpleIdentifier()
]
(
{
e = SqlStdOperatorTable.DEFAULT.createCall(getPos());
}
|
e = Expression(exprContext)
)
{
if (e != null) {
if (name != null) {
e = SqlStdOperatorTable.ARGUMENT_ASSIGNMENT.createCall(
name.getParserPosition().plus(e.getParserPosition()),
e, name);
}
list.add(e);
}
}
}
/**
* Parses a query (SELECT, UNION, INTERSECT, EXCEPT, VALUES, TABLE) followed by
* the end-of-file symbol.
*/
SqlNode SqlQueryEof() :
{
SqlNode query;
}
{
query = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY)
{ return query; }
}
/**
* Parses an SQL statement.
*/
SqlNode SqlStmt() :
{
SqlNode stmt;
}
{
(
stmt = SqlSetOption()
|
stmt = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY)
|
stmt = SqlExplain()
|
stmt = SqlInsert()
|
stmt = SqlDelete()
|
stmt = SqlUpdate()
|
stmt = SqlMerge()
|
stmt = SqlProcedureCall()
|
stmt = SqlShowTables()
|
stmt = SqlShowSchemas()
|
stmt = SqlDescribeTable()
|
stmt = SqlUseSchema()
|
stmt = SqlCreateOrReplaceView()
|
stmt = SqlDropView()
|
stmt = SqlShowFiles()
|
stmt = SqlCreateTable()
|
stmt = SqlDropTable()
|
stmt = SqlRefreshMetadata()
)
{
return stmt;
}
}
/**
* Parses an SQL statement followed by the end-of-file symbol.
*/
SqlNode SqlStmtEof() :
{
SqlNode stmt;
}
{
stmt = SqlStmt()
{
return stmt;
}
}
/**
* Parses statement
* SHOW TABLES [{FROM | IN} db_name] [LIKE 'pattern' | WHERE expr]
*/
SqlNode SqlShowTables() :
{
SqlParserPos pos;
SqlIdentifier db = null;
SqlNode likePattern = null;
SqlNode where = null;
}
{
{ pos = getPos(); }
[
( | ) { db = CompoundIdentifier(); }
]
[
{ likePattern = StringLiteral(); }
|
{ where = Expression(ExprContext.ACCEPT_SUBQUERY); }
]
{
return new SqlShowTables(pos, db, likePattern, where);
}
}
/**
* Parses statement
* SHOW FILES [{FROM | IN} schema]
*/
SqlNode SqlShowFiles() :
{
SqlParserPos pos = null;
SqlIdentifier db = null;
}
{
{ pos = getPos(); }
[
( | ) { db = CompoundIdentifier(); }
]
{
return new SqlShowFiles(pos, db);
}
}
/**
* Parses statement SHOW {DATABASES | SCHEMAS} [LIKE 'pattern' | WHERE expr]
*/
SqlNode SqlShowSchemas() :
{
SqlParserPos pos;
SqlNode likePattern = null;
SqlNode where = null;
}
{
{ pos = getPos(); }
( | )
[
{ likePattern = StringLiteral(); }
|
{ where = Expression(ExprContext.ACCEPT_SUBQUERY); }
]
{
return new SqlShowSchemas(pos, likePattern, where);
}
}
/**
* Parses statement
* { DESCRIBE | DESC } tblname [col_name | wildcard ]
*/
SqlNode SqlDescribeTable() :
{
SqlParserPos pos;
SqlIdentifier table;
SqlIdentifier column = null;
SqlNode columnPattern = null;
}
{
( | ) { pos = getPos(); }
table = CompoundIdentifier()
(
column = CompoundIdentifier()
|
columnPattern = StringLiteral()
|
E()
)
{
return new SqlDescribeTable(pos, table, column, columnPattern);
}
}
SqlNode SqlUseSchema():
{
SqlIdentifier schema;
SqlParserPos pos;
}
{