blob: 19db7e749f09230c2ddb8a0c046237de0a90a72b [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.
*/
options {
JAVA_UNICODE_ESCAPE = false;
ERROR_REPORTING = true;
STATIC = false;
// MULTI = true;
JDK_VERSION = "1.5";
// VISITOR = true;
// BUILD_NODE_FILES = true;
// NODE_FACTORY = false;
// NODE_USES_PARSER = true;
// NODE_SCOPE_HOOK = true;
// NODE_PREFIX = "SQL";
// DEBUG_PARSER = true;
// DEBUG_LOOKAHEAD = true;
// DEBUG_TOKEN_MANAGER = true;
LOOKAHEAD = 1;
// CHOICE_AMBIGUITY_CHECK = 3;
// OTHER_AMBIGUITY_CHECK = 3;
IGNORE_CASE = true;
}
PARSER_BEGIN(Parser)
package org.ofbiz.sql;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javolution.util.FastList;
import javolution.util.FastMap;
import javolution.util.FastSet;
@SuppressWarnings("all")
public final class Parser {
private boolean deleteSupportsUsing = true;
private boolean updateSupportsFrom = true;
public Parser deleteSupportsUsing(boolean value) {
deleteSupportsUsing = value;
return this;
}
public Parser updateSupportsFrom(boolean value) {
updateSupportsFrom = value;
return this;
}
private Condition reduce(List<Condition> conditions, Joiner joiner) {
if (conditions.size() == 1) {
return conditions.get(0);
}
return new ConditionList(joiner, conditions);
}
}
PARSER_END(Parser)
TOKEN_MGR_DECLS: {
private final FastList<Integer> stack = new FastList<Integer>();
void pushState(int newState) {
stack.add(curLexState);
SwitchTo(newState);
}
void popState() {
SwitchTo(stack.removeLast());
}
}
TOKEN: {
<OPEN_PAREN: "(">
| <CLOSE_PAREN: ")">
| <AND: "AND">
| <OR: "OR">
| <PERIOD: ".">
| <JOIN: "JOIN">
| <LEFT: "LEFT">
| <AS: "AS">
| <COUNT: "COUNT">
| <MAX: "MAX">
| <MIN: "MIN">
| <SUM: "SUM">
| <AVG: "AVG">
| <DISTINCT: "DISTINCT">
| <WHERE: "WHERE">
| <HAVING: "HAVING">
| <GROUP: "GROUP">
| <ORDER: "ORDER">
| <INTERSECT: "INTERSECT">
| <EXCEPT: "EXCEPT">
| <UNION: "UNION">
| <ALL: "ALL">
| <BY: "BY">
| <ON: "ON">
| <USING: "USING">
| <LIMIT: "LIMIT">
| <OFFSET: "OFFSET">
| <SELECT: "SELECT">
| <DELETE: "DELETE">
| <UPDATE: "UPDATE">
| <INSERT: "INSERT">
| <INDEX: "INDEX">
| <UNIQUE: "UNIQUE">
| <RELATION: "RELATION">
| <EXCLUDE: "EXCLUDE">
| <TYPE: "TYPE">
| <TITLE: "TITLE">
| <SET: "SET">
| <FROM: "FROM">
| <SEMI: ";">
| <STAR: "*">
| <COMMA: ",">
| <PLUS: "+">
| <MINUS: "-">
| <DESC: "DESC">
| <ASC: "ASC">
| <EQUALS: "=">
| <BETWEEN: "BETWEEN">
| <INTO: "INTO">
| <VALUES: "VALUES">
| <CREATE: "CREATE">
| <VIEW: "VIEW">
| <IS: "IS">
| <NOT: "NOT">
| <NULL: "NULL">
| <MAP: "MAP">
| <NULLS: "NULLS">
| <FIRST: "FIRST">
| <LAST: "LAST">
| <START_DQUOTE: "\""> { pushState(IN_DQUOTE); }
| <START_SQUOTE: "'"> { pushState(IN_SQUOTE); }
| <INTEGER:
"0" (
"x" (["0"-"9","a"-"b"])+
| (["0"-"7"])+
)
| ["1"-"9"] (["0"-"9"])*
>
| <NAME: ["a"-"z"] (["a"-"z","0"-"9","_","-"])*>
| <PARAMETER: "?" (["a"-"z"])+>
// | <WORD: (~["'", "\"", "/", " ", "\f", "\n", "\r", "\t", "*"])+>
}
<DEFAULT>
SKIP: {
<SPACE: " " | "\f" | "\n" | "\r" | "\t">
}
<*>
MORE: {
<COMMENT_START: "/*"> { if (curLexState != IN_COMMENT) pushState(IN_COMMENT); }
}
<IN_COMMENT>
MORE: {
<(~[])>
| <COMMENT_END: "*/"> { popState(); }
}
<IN_DQUOTE,IN_SQUOTE>
TOKEN: {
<ESCAPED: "\\" ["r", "n", "b", "t", "f"]>
}
<IN_DQUOTE>
TOKEN: {
<END_DQUOTE: "\""> { popState(); }
}
<IN_SQUOTE>
TOKEN: {
<ESCAPE_SQUOTE: "''">
| <END_SQUOTE: "'"> { popState(); }
}
<DEFAULT,IN_DQUOTE,IN_SQUOTE>
TOKEN: {
<TEXT: (~[])>
}
// -------------------
public List<SQLStatement<?>> SQLFile(): {
List<SQLStatement<?>> list = FastList.newInstance();
SQLStatement<?> statement;
} {
(
statement=Statement() ( <SEMI> )?
{ list.add(statement); }
)*
<EOF>
{ return list; }
}
public SQLStatement StandaloneStatement(): {
SQLStatement statement;
} {
statement=Statement() ( <SEMI> )? <EOF>
{ return statement; }
}
public SQLView ViewStatement(): {
SQLView sqlView;
} {
<CREATE> <VIEW> sqlView=View() ( <SEMI> )? <EOF>
{ return sqlView; }
}
public SQLSelect SelectStatement(): {
SQLSelect sqlSelect;
} {
sqlSelect=Select() ( <SEMI> )? <EOF> { return sqlSelect; }
}
public SQLDelete DeleteStatement(): {
SQLDelete sqlDelete;
} {
sqlDelete=Delete() ( <SEMI> )? <EOF> { return sqlDelete; }
}
public SQLUpdate UpdateStatement(): {
SQLUpdate sqlUpdate;
} {
sqlUpdate=Update() ( <SEMI> )? <EOF> { return sqlUpdate; }
}
public SQLInsert InsertStatement(): {
SQLInsert sqlInsert;
} {
sqlInsert=Insert() ( <SEMI> )? <EOF> { return sqlInsert; }
}
public Condition Condition(): {
Condition c;
} {
c=ConditionExpression() <EOF> { return c; }
}
public FieldAll parse_FieldAll(): {
FieldAll fieldAll;
} {
fieldAll=FieldAll() <EOF> { return fieldAll; }
}
public FieldDef parse_FieldDef(): {
FieldDef fieldDef;
} {
fieldDef=FieldDef() <EOF> { return fieldDef; }
}
public OrderByItem parse_OrderByItem(): {
OrderByItem item;
} {
item=OrderByItem() <EOF> { return item; }
}
private SQLStatement Statement(): {
SQLStatement statement;
} {
(
statement=Select() { return statement; }
| statement=Delete() { return statement; }
| statement=Update() { return statement; }
| statement=Insert() { return statement; }
| statement=Creates() { return statement; }
)
}
private SQLStatement Creates(): {
SQLStatement statement;
boolean isUnique = false;
} {
<CREATE> (
<VIEW> statement=View() { return statement; }
| ( <UNIQUE> { isUnique = true; } )?
<INDEX> statement=Index(isUnique) { return statement; }
)
}
private SQLView View(): {
String name;
SQLSelect sqlSelect;
} {
name=NamePart() <AS> sqlSelect=Select() { return new SQLView(name, sqlSelect); }
}
private SelectGroup SelectGroup(): {
boolean isDistinct = false;
List<String> groupBy = null;
Map<String, FieldDef> fieldDefs = FastMap.newInstance();
List<FieldAll> fieldAlls = FastList.newInstance();
Set<String> fieldAllAliases = FastSet.newInstance();
Table table;
Condition whereCondition = null, havingCondition = null;
} {
<SELECT> (<DISTINCT> { isDistinct = true; })? (
SelectField(fieldDefs, fieldAlls, fieldAllAliases)
( <COMMA> SelectField(fieldDefs, fieldAlls, fieldAllAliases) )*
)
<FROM> table=Table()
( <WHERE> whereCondition=ConditionExpression() )?
( <HAVING> havingCondition=ConditionExpression() )?
( <GROUP> <BY> groupBy=FieldList() )?
{ return new SelectGroup(isDistinct, fieldAlls, fieldDefs, table, whereCondition, havingCondition, groupBy); }
}
private Unioned.Operator UnionOperator(): {
} {
<UNION>
( <ALL> { return Unioned.Operator.UNION_ALL; } )?
{ return Unioned.Operator.UNION; }
| <INTERSECT>
( <ALL> { return Unioned.Operator.INTERSECT_ALL; } )?
{ return Unioned.Operator.INTERSECT; }
| <EXCEPT>
( <ALL> { return Unioned.Operator.EXCEPT_ALL; } )?
{ return Unioned.Operator.EXCEPT; }
}
private Unioned Unioned(): {
Unioned.Operator operator;
SelectGroup selectGroup;
Unioned next = null;
} {
operator=UnionOperator() selectGroup=SelectGroup() ( next=Unioned() )?
{ return new Unioned(operator, selectGroup, next); }
}
private SQLSelect Select(): {
boolean hadEarlyRelations = false;
Unioned unioned = null;
boolean isDistinct = false;
List<OrderByItem> orderBy = null;
List<String> groupBy = null;
Map<String, FieldDef> fieldDefs = FastMap.newInstance();
List<FieldAll> fieldAlls = FastList.newInstance();
Set<String> fieldAllAliases = FastSet.newInstance();
Table table;
Map<String, Relation> relations = FastMap.newInstance();
Condition whereCondition = null, havingCondition = null;
int offset = -1, limit = -1;
} {
<SELECT> (<DISTINCT> { isDistinct = true; })? (
SelectField(fieldDefs, fieldAlls, fieldAllAliases)
( <COMMA> SelectField(fieldDefs, fieldAlls, fieldAllAliases) )*
)
<FROM> table=Table()
( LOOKAHEAD(1) <RELATION> Relation(relations) { hadEarlyRelations = true; } )*
( <WHERE> whereCondition=ConditionExpression() )?
( <HAVING> havingCondition=ConditionExpression() )?
( <GROUP> <BY> groupBy=FieldList() )?
( unioned=Unioned() )?
( LOOKAHEAD(1, {!hadEarlyRelations}) <RELATION> Relation(relations) )*
( <ORDER> <BY> orderBy=OrderByList() )?
( <OFFSET> offset=Integer() )?
( <LIMIT> limit=Integer() )?
{ return new SQLSelect(new SelectGroup(isDistinct, fieldAlls, fieldDefs, table, whereCondition, havingCondition, groupBy), unioned, relations, orderBy, offset, limit); }
}
private void Relation(Map<String, Relation> relations): {
String type = null, title = null, entityName;
KeyMap keyMap;
List<KeyMap> keyMaps = FastList.newInstance();
} {
( <TYPE> type=NamePart() )?
( <TITLE> title=NamePart() )?
<NAME> { entityName = getToken(0).image; }
<MAP> keyMap=PlainKeyMap() { keyMaps.add(keyMap); } (
<COMMA>
keyMap=PlainKeyMap() { keyMaps.add(keyMap); }
)*
{
Relation relation = new Relation(type, title, entityName, keyMaps);
if (relations.containsKey(relation.getName())) throw new ParseException("Duplicate relation: " + relation);
relations.put(relation.getName(), relation);
}
}
private KeyMap PlainKeyMap(): {
String left, right;
} {
left=NamePart() (
<EQUALS> right=NamePart() { return new KeyMap(left, right); }
| { return new KeyMap(left, left); }
)
}
private SQLUpdate Update(): {
TableName tableName;
List<Table> tableList = null;
Condition whereCondition = null;
List<SetField> allSetFields = FastList.newInstance();
List<SetField> setFields;
Joined joined = null;
} {
<UPDATE> tableName=TableName()
<SET>
setFields=SetField() { allSetFields.addAll(setFields); }
( <COMMA> setFields=SetField() { allSetFields.addAll(setFields); } )*
( LOOKAHEAD(<FROM>, {updateSupportsFrom}) <FROM> joined=JoinedRest(false, tableName) )?
( <WHERE> whereCondition=ConditionExpression() )?
{ return new SQLUpdate(new Table(tableName, joined), allSetFields, whereCondition); }
}
private SQLDelete Delete(): {
TableName tableName;
List<Table> tableList = null;
Condition whereCondition = null;
Joined joined = null;
} {
<DELETE> <FROM> tableName=TableName()
( LOOKAHEAD(<USING>, {deleteSupportsUsing}) <USING> joined=JoinedRest(false, tableName) )?
( <WHERE> whereCondition=ConditionExpression() )?
{ return new SQLDelete(new Table(tableName, joined), whereCondition); }
}
private SQLIndex Index(boolean isUnique): {
String name, table, using = null;
ConstantValue value;
List<ConstantValue> values = FastList.newInstance();
} {
name=NamePart() <ON> table=NamePart()
( <USING> using=NamePart() )?
<OPEN_PAREN>
value=ConstantValue() { values.add(value); }
( <COMMA> value=ConstantValue() { values.add(value); } )*
<CLOSE_PAREN>
{ return new SQLIndex(isUnique, name, table, using, values); }
}
private SQLInsert Insert(): {
TableName tableName;
List<String> columns = FastList.newInstance();
String n;
InsertSource source;
} {
<INSERT> <INTO> tableName=TableName() (
<OPEN_PAREN>
n=NamePart() { columns.add(n); }
( <COMMA> n=NamePart() { columns.add(n); } )*
<CLOSE_PAREN>
)?
( source=InsertValues() | source=Select() )
{ return new SQLInsert(tableName, source, columns); }
}
private InsertValues InsertValues(): {
List<InsertRow> list = FastList.newInstance();
InsertRow row;
} {
<VALUES>
row=InsertRow() { list.add(row); }
( <COMMA> row=InsertRow() { list.add(row); } )*
{ return new InsertValues(list); }
}
private InsertRow InsertRow(): {
List<Value> list = FastList.newInstance();
Value v;
} {
<OPEN_PAREN>
v=InsertValue() { list.add(v); }
( <COMMA> v=InsertValue() { list.add(v); } )*
<CLOSE_PAREN>
{ return new InsertRow(list); }
}
private Value InsertValue(): {
Value v;
Integer i;
String s;
} {
v=ParameterValue() { return v; }
| i=Integer() { return new NumberValue<Integer>(i); }
| s=SQuoted() { return new StringValue(s); }
}
private List<SetField> SetField(): {
List<SetField> setFields = FastList.newInstance();
String n;
Value v;
List<String> columnList = FastList.newInstance();
List<Value> valueList = FastList.newInstance();
} {
(
n=NamePart() <EQUALS> (
v=Value() { setFields.add(new SetField(n, v)); }
| v=MathValue() { setFields.add(new SetField(n, v)); }
)
| <OPEN_PAREN>
n=NamePart() { columnList.add(n); }
( <COMMA> n=NamePart() { columnList.add(n); } )*
<CLOSE_PAREN>
<EQUALS>
<OPEN_PAREN>
( v=Value() | v=MathValue() ) { valueList.add(v); }
( <COMMA> (v=Value()|v=MathValue()) { valueList.add(v); } )*
<CLOSE_PAREN> {
if (columnList.size() != valueList.size()) throw new ParseException();
for (int i = 0; i < columnList.size(); i++) {
setFields.add(new SetField(columnList.get(i), valueList.get(i)));
}
}
)
{ return setFields; }
}
private Table Table(): {
TableName tableName;
Joined joined = null;
} {
tableName=TableName()
( joined=Joined(tableName) )?
{ return new Table(tableName, joined); }
}
private Joined Joined(TableName leftTableName): {
Boolean isOptional;
Joined joined = null;
} {
isOptional=Joiner() joined=JoinedRest(isOptional, leftTableName)
{ return joined; }
}
private Joined JoinedRest(boolean isOptional, TableName leftTableName): {
TableName rightTableName;
List<KeyMap> keyMaps;
Joined joined = null;
} {
rightTableName=TableName()
keyMaps=KeyMaps(leftTableName.getAlias(), rightTableName.getAlias())
( joined=Joined(rightTableName) )?
{ return new Joined(isOptional, rightTableName, keyMaps, joined); }
}
private List<KeyMap> KeyMaps(String leftAlias, String rightAlias): {
List<KeyMap> keyMaps = FastList.newInstance();
String n;
} {
(
<ON>
KeyMap(keyMaps, leftAlias, rightAlias)
( <AND> KeyMap(keyMaps, leftAlias, rightAlias) )*
| <USING>
n=NamePart() { keyMaps.add(new KeyMap(n, n)); }
( <COMMA> n=NamePart() { keyMaps.add(new KeyMap(n, n)); } )*
)
{ return keyMaps; }
}
private void KeyMap(List<KeyMap> keyMaps, String leftAlias, String rightAlias): {
String alias1, field1;
String alias2, field2;
} {
alias1=NamePart() <PERIOD> field1=NamePart()
<EQUALS>
alias2=NamePart() <PERIOD> field2=NamePart() {
if (alias1.equals(leftAlias)) {
if (!alias2.equals(rightAlias)) throw new ParseException("invalid right alias(" + alias2 + "), expected(" + rightAlias + ")");
keyMaps.add(new KeyMap(field1, field2));
} else if (alias1.equals(rightAlias)) {
if (!alias2.equals(leftAlias)) throw new ParseException("invalid left alias(" + alias2 + "), expected(" + leftAlias + ")");
keyMaps.add(new KeyMap(field2, field1));
} else {
throw new ParseException("invalid aliases, expected(" + leftAlias + " or " + rightAlias + ")");
}
}
}
private TableName TableName(): {
String tableName, alias = null;
} {
tableName=NamePart()
( ( <AS> )? alias=NamePart() )?
{ return new TableName(tableName, alias); }
}
private Boolean Joiner(): {
} {
<LEFT> <JOIN> { return Boolean.TRUE; }
| <JOIN> { return Boolean.FALSE; }
}
private void SelectField(Map<String, FieldDef> fieldDefs, List<FieldAll> fieldAlls, Set<String> fieldAllAliases): {
FieldAll fieldAll;
FieldDef fieldDef;
} {
LOOKAHEAD(3) fieldAll=FieldAll() {
if (fieldAllAliases.contains(fieldAll.getAlias())) throw new ParseException("Duplicate aliasAll(" + fieldAll.getAlias() + ")");
fieldAlls.add(fieldAll); return;
}
| fieldDef=FieldDef() {
if (fieldDefs.containsKey(fieldDef.getDefaultName())) throw new ParseException("duplicate alias(" + fieldDef.getDefaultName() + ")");
fieldDefs.put(fieldDef.getDefaultName(), fieldDef);
}
}
private FieldAll FieldAll(): {
String n, exc;
Set<String> excludeList = FastSet.newInstance();
} {
n=NamePart() <PERIOD> <STAR> (
<EXCLUDE> <OPEN_PAREN>
exc=NamePart() { excludeList.add(exc); }
( <COMMA> exc=NamePart() { excludeList.add(exc); } )*
<CLOSE_PAREN>
)?
{ return new FieldAll(n, excludeList); }
}
private StaticValue StaticValue(): {
StaticValue v;
String n, fieldName;
} {
(
n=NamePart() (
<PERIOD> fieldName=NamePart() { v = new FieldValue(n, fieldName); }
| v=FunctionCallRest(n)
| { v = new FieldValue(null, n); }
)
| v=MathValue()
| LOOKAHEAD(5) v=CountAll()
| v=AggregateFunction()
) { return v; }
}
private FieldDef FieldDef(): {
StaticValue v;
String fieldAlias = null;
} {
v=StaticValue() ( <AS> fieldAlias=NamePart() )? {
return new FieldDef(v, fieldAlias);
}
}
private CountAllFunction CountAll(): {
String n;
} {
<COUNT> <OPEN_PAREN> (
n=NamePart()
| { n = null; }
) <PERIOD> <STAR> <CLOSE_PAREN>
{ return new CountAllFunction(n); }
}
private StaticValue MathValue(): {
ConstantValue v;
List<ConstantValue> values = FastList.newInstance();
String operator = null, newOperator;
} {
<OPEN_PAREN> v=ConstantValue() { values.add(v); } (
newOperator=MathOperator() v=ConstantValue() {
if (operator == null) {
operator = newOperator;
} else if (!newOperator.equals(operator)) {
throw new ParseException("Different operators in complex alias(" + operator + ":" + newOperator + ")");
}
values.add(v);
}
)*
<CLOSE_PAREN> {
if (values.size() == 1 && values.get(0) instanceof StaticValue) return (StaticValue) values.get(0);
return new MathValue(operator, values);
}
}
private AggregateFunction AggregateFunction(): {
StaticValue v;
String name, n, fieldName;
boolean isDistinct = false;
} {
name=AggregateName() <OPEN_PAREN>
( <DISTINCT> { isDistinct = true; } )? (
n=NamePart() (
<PERIOD> fieldName=NamePart() { v = new FieldValue(n, fieldName); }
| v=FunctionCallRest(n)
| { v = new FieldValue(null, n); }
)
| v=MathValue()
) <CLOSE_PAREN>
{ return new AggregateFunction(name, isDistinct, v); }
}
private FunctionCall FunctionCallRest(String name): {
Value arg;
List<Value> args = FastList.newInstance();
} {
<OPEN_PAREN> (
arg=Value() { args.add(arg); }
( <COMMA> arg=Value() { args.add(arg); } )*
)?
<CLOSE_PAREN>
{ return new FunctionCall(name, args); }
}
private ConstantValue ConstantValue(): {
String n;
ConstantValue v;
int i;
String s;
} {
n=NamePart() (
v=FunctionCallRest(n) { return v; }
| v=FieldValue(n) { return v; }
)
| i=Integer() { return new NumberValue<Integer>(i); }
| s=SQuoted() { return new StringValue(s); }
| v=MathValue() { return v; }
}
private String NamePart(): {
} {
<NAME> { return getToken(0).image; }
| <TYPE> { return getToken(0).image; }
}
private String DQuoted(): {
StringBuilder sb = new StringBuilder();
} {
<START_DQUOTE> (
<TEXT> { sb.append(getToken(0).image); }
| <ESCAPED> { sb.append(getToken(0).image); }
)* <END_DQUOTE>
{ return sb.toString(); }
}
private String SQuoted(): {
StringBuilder sb = new StringBuilder();
} {
<START_SQUOTE> (
<TEXT> { sb.append(getToken(0).image); }
| <ESCAPED> { sb.append(getToken(0).image); }
| <ESCAPE_SQUOTE> { sb.append("'"); }
)* <END_SQUOTE>
{ return sb.toString(); }
}
private String Text(): {
StringBuilder sb = new StringBuilder();
} {
( <TEXT> { sb.append(getToken(0).image); } )+
{ return sb.toString(); }
}
private List<String> FieldList(): {
List<String> list = FastList.newInstance();
String n;
} {
n=NamePart() { list.add(n); }
( <COMMA> n=NamePart() { list.add(n); } )*
{ return list; }
}
private FieldValue FieldValue(String fieldName): {
String s;
} {
( <PERIOD> s=NamePart() { return new FieldValue(fieldName, s); } )?
{ return new FieldValue(fieldName); }
}
private List<OrderByItem> OrderByList(): {
List<OrderByItem> orderBy = FastList.newInstance();
OrderByItem obi;
} {
obi=OrderByItem() { orderBy.add(obi); }
( <COMMA> obi=OrderByItem() { orderBy.add(obi); } )*
{ return orderBy; }
}
public OrderByItem OrderByItem(): {
ConstantValue value;
OrderByItem.Order ordering = OrderByItem.Order.DEFAULT;
OrderByItem.Nulls nulls = OrderByItem.Nulls.DEFAULT;
} {
(
(
(
<PLUS> { ordering = OrderByItem.Order.ASCENDING; }
| <MINUS> { ordering = OrderByItem.Order.DESCENDING; }
)
value=ConstantValue()
)
| value=ConstantValue() (
<DESC> { ordering = OrderByItem.Order.DESCENDING; }
| <ASC> { ordering = OrderByItem.Order.ASCENDING; }
)?
)
(
<NULLS> (
<FIRST> { nulls = OrderByItem.Nulls.FIRST; }
| <LAST> { nulls = OrderByItem.Nulls.LAST; }
)
)?
{ return new OrderByItem(ordering, nulls, value); }
}
private Integer Integer(): {
} {
<INTEGER> { return Integer.decode(getToken(0).image); }
}
private Value Value(): {
String n;
Value v;
int i;
String s;
} {
n=NamePart() (
v=FunctionCallRest(n) { return v; }
| v=FieldValue(n) { return v; }
)
| i=Integer() { return new NumberValue<Integer>(i); }
| s=SQuoted() { return new StringValue(s); }
}
private Condition ConditionExpression(): {
Condition c;
} {
c=OrExpression() { return c; }
}
private Condition AndExpression(): {
List<Condition> list = FastList.newInstance();
Condition c;
} {
c=BooleanExpression() { list.add(c); }
( <AND> c=BooleanExpression() { list.add(c); } )*
{ return reduce(list, Joiner.AND); }
}
private Condition OrExpression(): {
List<Condition> list = FastList.newInstance();
Condition c;
} {
c=AndExpression() { list.add(c); }
( <OR> c=AndExpression() { list.add(c); } )*
{ return reduce(list, Joiner.OR); }
}
private Value RightValue(): {
Value v;
} {
v=Value() { return v; }
| v=ParameterValue() { return v; }
}
private ParameterValue ParameterValue(): {
} {
<PARAMETER> { return new ParameterValue(getToken(0).image.substring(1)); }
}
private Condition BooleanExpression(): {
Value v1, v2, v, r1, r2;
String op;
Condition c;
List<Value> list = FastList.newInstance();
} {
v1=Value() (
<BETWEEN> r1=RightValue() <AND> r2=RightValue()
{ return new BetweenCondition(v1, r1, r2); }
| <IS> (
<NULL> { op = "="; v2 = Value.NULL; }
| <NOT> <NULL> { op = "!="; v2 = Value.NULL; }
)
| op=ComparisonOperator() (
v2=RightValue()
| <OPEN_PAREN>
v=RightValue() { list.add(v); }
(
<COMMA> v=RightValue() { list.add(v); }
)*
<CLOSE_PAREN>
{ return new ListCondition(v1, op, list); }
)
)
{ return new BooleanCondition(v1, op, v2); }
| <OPEN_PAREN> c=ConditionExpression() <CLOSE_PAREN> { return c; }
}
private String ComparisonOperator(): {
StringBuilder sb = new StringBuilder();
String s;
} {
s=Text() { sb.append(s); }
(
<EQUALS> { sb.append(getToken(0).image); }
( s=Text() { sb.append(s); } )?
)*
{ return sb.toString(); }
| <NAME> { return getToken(0).image; }
| <EQUALS> { return getToken(0).image; }
}
private String MathOperator(): {
String s;
} {
s=Text() { return s; }
| <NAME> { return getToken(0).image; }
}
private String AggregateName(): {
} {
<COUNT> { return getToken(0).image; }
| <MAX> { return getToken(0).image; }
| <MIN> { return getToken(0).image; }
| <SUM> { return getToken(0).image; }
| <AVG> { return getToken(0).image; }
| <FIRST> { return getToken(0).image; }
| <LAST> { return getToken(0).image; }
}