2 * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 parser grammar MySQL51Parser;
22 tokenVocab=MySQL51Lexer;
23 superClass=MySQLParser;
26 import MySQL51Functions;
43 ROLLBACK_POINT; /* rollback to savepoint */
44 /* token types for the various CREATE statements */
46 /* helper tokens for column definitions */
54 package com.mysql.clusterj.jdbc.antlr;
58 : stmts+=statement (SEMI stmts+=statement)* SEMI*
78 do_stmt : DO exprList -> ^(DO exprList)
83 ( AUTHORS -> ^($show_stmt ^(AUTHORS))
84 | BINLOG EVENTS (IN logName=STRING)? (FROM NUMBER)? limit? -> ^($show_stmt ^(BINLOG $logName? NUMBER? limit?))
85 | CHARACTER SET like_or_where? -> ^($show_stmt ^(CHARACTER like_or_where?))
86 | COLLATION like_or_where? -> ^($show_stmt ^(COLLATION like_or_where?))
87 | FULL? COLUMNS (FROM|IN) simple_table_ref_no_alias ((FROM|IN) ident)? like_or_where? -> ^($show_stmt ^(COLUMNS FULL? simple_table_ref_no_alias ident? like_or_where?))
88 | CONTRIBUTORS -> ^($show_stmt ^(CONTRIBUTORS))
89 | CREATE DATABASE ident -> ^($show_stmt ^(CREATE DATABASE ident))
90 | CREATE EVENT ident -> ^($show_stmt ^(CREATE EVENT ident))
91 | CREATE FUNCTION ident -> ^($show_stmt ^(CREATE FUNCTION ident))
92 | CREATE PROCEDURE ident -> ^($show_stmt ^(CREATE PROCEDURE ident))
93 | CREATE TABLE simple_table_ref_no_alias -> ^($show_stmt ^(CREATE TABLE simple_table_ref_no_alias))
94 | CREATE TRIGGER ident -> ^($show_stmt ^(CREATE TRIGGER ident))
95 | CREATE VIEW ident -> ^($show_stmt ^(CREATE VIEW ident))
96 | DATABASES like_or_where? -> ^($show_stmt ^(DATABASES like_or_where?))
97 | ENGINE (INNODB | ident) (what=STATUS | what=MUTEX) // have to add INNODB token, because of SHOW INNODB STATUS :(
98 -> ^($show_stmt ^(ENGINE INNODB? ident? $what))
99 | STORAGE? ENGINES -> ^($show_stmt ^(ENGINES))
100 | ERRORS limit? -> ^($show_stmt ^(ERRORS limit?))
101 | FULL? EVENTS -> ^($show_stmt ^(EVENTS FULL?))
102 | FUNCTION CODE ident -> ^($show_stmt ^(CODE FUNCTION ident))
103 | FUNCTION STATUS like_or_where? -> ^($show_stmt ^(STATUS FUNCTION like_or_where?))
107 | whom=CURRENT_USER LPAREN RPAREN
108 ) -> ^($show_stmt ^(GRANTS $whom))
109 | INDEX_SYM FROM simple_table_ref_no_alias ((FROM|IN) ident)? -> ^($show_stmt ^(INDEX_SYM simple_table_ref_no_alias ident?))
110 | INNODB STATUS -> ^($show_stmt ^(ENGINE INNODB STATUS))
111 | OPEN TABLES ((FROM|IN) ident)? like_or_where? -> ^($show_stmt ^(OPEN ident? like_or_where?))
112 | PLUGINS -> ^($show_stmt ^(PLUGINS))
113 | PROCEDURE CODE ident -> ^($show_stmt ^(CODE PROCEDURE ident))
114 | PROCEDURE STATUS like_or_where? -> ^($show_stmt ^(STATUS PROCEDURE ident))
115 | PRIVILEGES -> ^($show_stmt ^(PRIVILEGES))
116 | FULL? PROCESSLIST -> ^($show_stmt ^(PROCESSLIST FULL?))
117 | PROFILE show_profile_types (FOR QUERY NUMBER)? limit? -> ^($show_stmt ^(PROFILE show_profile_types NUMBER? limit?))
118 | PROFILES -> ^($show_stmt ^(PROFILES))
119 | SCHEDULER STATUS -> ^($show_stmt ^(STATUS SCHEDULER))
120 | optScopeModifier STATUS like_or_where? -> ^($show_stmt ^(STATUS optScopeModifier? like_or_where?))
121 | TABLE STATUS ((FROM|IN) ident)? like_or_where? -> ^($show_stmt ^(STATUS TABLE ident? like_or_where?))
122 | TABLES ((FROM|IN) ident)? like_or_where? -> ^($show_stmt ^(TABLES ident? like_or_where?))
123 | TRIGGERS ((FROM|IN) ident)? like_or_where? -> ^($show_stmt ^(TRIGGERS ident? like_or_where?))
124 | optScopeModifier VARIABLES like_or_where? -> ^($show_stmt ^(VARIABLES optScopeModifier? like_or_where?))
125 | WARNINGS limit? -> ^($show_stmt ^(WARNINGS limit?))
132 | l=LOCAL -> SESSION[$l]
133 | /* empty, defaults to SESSION */ -> SESSION
149 : // behold, this is a special LIKE...does not allow expressions on the RHS
150 LIKE string_or_placeholder -> ^(LIKE string_or_placeholder)
151 | WHERE expr -> ^(WHERE expr)
155 : EXPLAIN select -> ^(EXPLAIN select)
160 boolean seenUnion = false;
163 (UNION (mod=ALL | mod=DISTINCT)? union_selects+=select_paren {seenUnion=true;})*
164 -> {seenUnion}? ^(UNION $mod? select_paren $union_selects+)
169 : LPAREN select_paren RPAREN -> select_paren
170 | select_inner -> select_inner
174 : SELECT (options{k=1;}:select_options)*
175 exprs+=select_expr (COMMA exprs+=select_expr)*
177 (FROM table_references)
178 (WHERE where=where_condition)?
180 (HAVING having=where_condition)?
183 // these procedures are not "SQL-SPs" but C++ ones. very unlikely that we'll see them.
184 (PROCEDURE procId=ident procArgs=parenOptExprList)?
185 /* TODO: what is allowed in the "STRING" below? probably not N'foobar' etc. */
186 (( INTO OUTFILE file=STRING opts=infile_options_helper
187 | INTO DUMPFILE file=STRING
188 | INTO vars+=variable (COMMA vars+=variable)*
191 (forUpdate=FOR UPDATE | lock=LOCK IN SHARE MODE)?
196 -> ^(SELECT<com.mysql.clusterj.jdbc.antlr.node.SelectNode>
197 ^(OPTIONS select_options*)?
199 ^(FROM table_references)?
200 ^(WHERE<com.mysql.clusterj.jdbc.antlr.node.WhereNode> $where)?
210 infile_options_helper
212 (TERMINATED BY fieldTerm=STRING)?
213 (optEnclosed=OPTIONALLY? ENCLOSED BY fieldEncl=STRING)? /* TODO: STRING here is one character, really */
214 (ESCAPED BY fieldEsc=STRING)? /* TODO: STRING here is one character, really */
217 (STARTING BY linesStart=STRING)?
218 (TERMINATED BY linesTerm=STRING)?
229 ( ((offset=number_or_placeholder COMMA)? lim=number_or_placeholder)
230 | (lim=number_or_placeholder offsetForm=OFFSET offset=number_or_placeholder)
232 -> ^(LIMIT $lim $offset? $offsetForm?)
235 string_or_placeholder
240 number_or_placeholder
253 elements+=order_group_by_elements (COMMA elements+=order_group_by_elements )*
254 (rollup=WITH ROLLUP)?
255 -> ^(GROUP $elements+ $rollup?)
260 elements+=order_group_by_elements (COMMA elements+=order_group_by_elements )*
261 -> ^(ORDER $elements+)
264 order_group_by_elements
266 ( asc=ASC -> ^(DIRECTION[$asc] expr)
267 | desc=DESC -> ^(DIRECTION[$desc] expr)
268 | /* implicit ASC */ -> ^(DIRECTION["ASC"] expr)
280 // the following cause parser warnings
281 // | SQL_BUFFER_RESULT
284 | SQL_CALC_FOUND_ROWS
288 : expr (AS? ident)? -> ^(SELECT_EXPR expr ^(ALIAS ident)?)
289 | star=MULT -> ^(SELECT_EXPR $star)
291 /* catch[RecognitionException re] {
292 Object errorNode = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re);
293 Object root_1 = (Object)adaptor.nil();
294 root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(SELECT_EXPR, "SELECT_EXPR"), root_1);
295 adaptor.addChild(root_1, errorNode);
296 adaptor.addChild(root_0, root_1);
297 retval.tree = (Object)adaptor.rulePostProcessing(root_0);
300 table_references returns [int table_count]
305 $table_references::count = 0;
308 $table_references.table_count = $table_references::count;
310 : ( t1=table_ref -> $t1)
311 ( COMMA t2=table_ref -> ^(COMMA_JOIN[$COMMA] $table_references $t2)
315 /* left factored to get rid of the recursion */
317 : (t1=table_factor -> $t1 )
319 (LEFT|RIGHT)=>(ltype=LEFT|ltype=RIGHT) outer=OUTER? JOIN t3=table_ref lrjoinCond=join_condition_either
320 -> ^($ltype {$tree} $t3 $lrjoinCond $outer?)
321 // join condition is not optional here
322 | (type=INNER|type=CROSS)? JOIN t2=table_factor cond1=join_condition_either
323 -> ^(JOIN {$tree} $t2 $cond1? $type?)
324 | ( type=STRAIGHT_JOIN t2=table_factor
325 ( (join_condition_on)=> cond2=join_condition_on -> ^($type {$tree} $t2 $cond2)
326 | -> ^($type {$tree} $t2)
329 | (NATURAL)=> NATURAL ((type=LEFT|type=RIGHT) outer=OUTER?)? JOIN t2=table_factor -> ^(NATURAL $type? {$tree} $t2 $outer?)
334 : simple_table_ref_alias index_hint_list? {$table_references::count++;} -> ^(TABLE simple_table_ref_alias index_hint_list?)
335 | LPAREN select_inner RPAREN AS? ident {$table_references::count++;} -> ^(SUBSELECT select_inner ^(ALIAS ident))
336 | LPAREN table_ref {$table_references::count++;} (COMMA table_ref {$table_references::count++;} )* RPAREN -> ^(TABLE table_ref+)
337 /* ident in the following should really by 'OJ', but the parser accepts any identifier in its place */
338 | LCURLY ident t1=table_ref LEFT OUTER JOIN t2=table_ref join_condition_on RCURLY
339 -> ^(ident $t1 $t2 join_condition_on)
344 : ON where_condition -> ^(ON where_condition)
347 join_condition_either
349 | USING LPAREN fields+=ident (COMMA fields+=ident)* RPAREN -> ^(USING $fields+)
352 simple_table_ref_no_alias
353 : first=ident (DOT second=ident)? -> $first $second?
356 simple_table_ref_alias
357 : first=ident (DOT second=ident)? table_alias? -> $first $second? table_alias?
361 : AS? alias=ident -> ^(ALIAS $alias)
367 boolean seenStar = false;
370 ({seenStar == false}?=>
372 ({seenStar == false}? (ident | star=MULT {seenStar = true;}) {++i <= 2}?)
375 -> ^(FIELD ident+ $star?)
376 // | (DOT)=>DOT column=field_name_column -> ^(FIELD $column)
379 /* list all keywords that can also be used as an identifier
380 This list is taken from the 5.1 YACC grammar
437 | ident_sp_label -> {$ident_sp_label.tree}
452 | tok=AUTO_INCREMENT!
453 | tok=AUTOEXTEND_SIZE!
454 | tok=AVG_ROW_LENGTH!
489 | tok=DELAY_KEY_WRITE!
520 | tok=GEOMETRYCOLLECTION!
538 | tok=KEY_BLOCK_SIZE!
553 | tok=MASTER_LOG_FILE!
554 | tok=MASTER_LOG_POS!
556 | tok=MASTER_PASSWORD!
557 | tok=MASTER_SERVER_ID!
558 | tok=MASTER_CONNECT_RETRY!
561 | tok=MASTER_SSL_CAPATH!
562 | tok=MASTER_SSL_CERT!
563 | tok=MASTER_SSL_CIPHER!
564 | tok=MASTER_SSL_KEY!
565 | tok=MAX_CONNECTIONS_PER_HOUR!
566 | tok=MAX_QUERIES_PER_HOUR!
568 | tok=MAX_UPDATES_PER_HOUR!
569 | tok=MAX_USER_CONNECTIONS!
581 | tok=MULTILINESTRING!
623 | tok=REDO_BUFFER_SIZE!
626 | tok=RELAY_LOG_FILE!
654 | tok=SQL_BUFFER_RESULT!
660 | tok=STRING_KEYWORD!
680 | tok=TIMESTAMP_DIFF!
688 | tok=UNDO_BUFFER_SIZE!
705 adaptor.addChild(root_0, (Object)adaptor.create(ID, $tok));
710 : index_hint (COMMA index_hint)* -> ^(INDEX_HINTS index_hint+)
715 boolean namesOptional;
718 $index_hint::namesOptional = false;
720 : USE {$index_hint::namesOptional = true;} index_hint_rest -> ^(USE index_hint_rest)
721 | IGNORE {$index_hint::namesOptional = false;} index_hint_rest -> ^(IGNORE index_hint_rest)
722 | FORCE {$index_hint::namesOptional = false;} index_hint_rest -> ^(FORCE index_hint_rest)
726 : (name=INDEX|name=KEY) (FOR (usage=JOIN | usage=ORDER BY | usage=GROUP BY))?
728 ( {$index_hint::namesOptional == true}?=> (names+=ident (COMMA names+=ident)*)?
729 | names+=ident (COMMA names+=ident)*
732 -> $name ^(LPAREN $names?) $usage?
737 : e+=expr (COMMA e+=expr)* -> $e+
741 : LPAREN expr RPAREN -> ^(LPAREN<com.mysql.clusterj.jdbc.antlr.node.ParensNode> expr)
745 : LPAREN exprList RPAREN -> ^(LPAREN exprList)
749 : LPAREN e+=exprList? RPAREN -> ^(LPAREN $e*)
753 : lhs=assignOrExpr (op=ASSIGN^ rhs=expr)?
757 : lhs=assignXORExpr ((op+=LOGICAL_OR^ | op+=OR<com.mysql.clusterj.jdbc.antlr.node.OrNode>^) rhs+=assignXORExpr)*
761 : lhs=assignAndExpr (op+=XOR^ rhs+=assignAndExpr)*
765 : lhs=assignNotExpr (( op+=LOGICAL_AND^ | op+=AND<com.mysql.clusterj.jdbc.antlr.node.AndNode>^ ) rhs+=assignNotExpr)*
770 | op+=NOT<com.mysql.clusterj.jdbc.antlr.node.NotNode>^ rhs+=equalityExpr
775 (op+=equalityOperator^ ((subselect_in_expr_rhs)=> subselect_in_expr_rhs | bitwiseOrExpr))*
778 subselect_in_expr_rhs
779 : (mod=ANY | mod=SOME | mod=ALL) LPAREN select RPAREN -> ^(SUBSELECT $mod select)
783 : LPAREN select_inner RPAREN -> ^(SUBSELECT select_inner)
787 : IS NOT? (value2=NULL | value2=FALSE | value2=TRUE | value2=UNKNOWN) -> ^(IS NOT? $value2)
791 : ( value=EQUALS<com.mysql.clusterj.jdbc.antlr.node.EqualsNode>
793 | value=LESS_THAN<com.mysql.clusterj.jdbc.antlr.node.LessThanNode>
794 | value=LESS_THAN_EQUAL<com.mysql.clusterj.jdbc.antlr.node.LessEqualsNode>
795 | value=GREATER_THAN<com.mysql.clusterj.jdbc.antlr.node.GreaterThanNode>
796 | value=GREATER_THAN_EQUAL<com.mysql.clusterj.jdbc.antlr.node.GreaterEqualsNode>
797 | value=NULL_SAFE_NOT_EQUAL
808 ( (op+=BITWISE_OR^ rhs+=bitwiseAndExpr)+
809 // force compiler to always recognize NOT IN regardless of whatever follows
810 | (((NOT^)? IN^)=>(NOT^)? IN^ (parenExprList | subselect))
811 | LIKE^ unaryExpr (ESCAPE STRING)? // STRING must be empty or one character long (or be "\\" if not in sql_mode NO_BACKSLASH_ESCAPES)
813 | ((NOT^)? BETWEEN^)=> (NOT<com.mysql.clusterj.jdbc.antlr.node.NotNode>^)? (BETWEEN<com.mysql.clusterj.jdbc.antlr.node.BetweenNode>^ unaryExpr AND! unaryExpr )
818 : lhs=shiftExpr (op+=BITWISE_AND^ rhs+=shiftExpr)*
822 : lhs=additiveExpr ((op+=LEFT_SHIFT^ | op+=RIGHT_SHIFT^) rhs+=additiveExpr)*
825 /* this is ugly because of INTERVAL:
826 As rightmost in an expression, it has the highest precendence.
827 Otherwise it must be followed by PLUS|MINUS.
828 TODO: It cannot be on the left of a MINUS, because that expression makes no sense.
831 // force any PLUS or MINUS to be binary not unary for this rule
832 : lhs=multiplicativeExpr ((PLUS|MINUS)=>(op+=PLUS^|op+=MINUS^) rhs+=multiplicativeExpr)*
843 : lhs=bitwiseXORExpr (op+=multOperator^ rhs+=bitwiseXORExpr)*
847 : lhs=unaryExpr (op+=BITWISE_XOR^ rhs+=unaryExpr)*
851 : op=MINUS lhs=unaryExpr -> ^(UNARY_MINUS[$op] $lhs)
852 | op=PLUS lhs=unaryExpr -> ^(UNARY_PLUS[$op] $lhs)
853 | op=BITWISE_INVERSION lhs=unaryExpr -> ^(BITWISE_INVERSION $lhs)
854 | lhsUnaryNot=unaryNotExpr -> unaryNotExpr
858 : op=NOT_OP lhs=unaryNotExpr -> ^(NOT_OP $lhs)
859 | lhsBin=binaryCollateExpr -> binaryCollateExpr
863 : op=BINARY lhs=binaryCollateExpr -> ^(BINARY $lhs)
864 | op=COLLATE lhs=binaryCollateExpr -> ^(COLLATE $lhs)
868 /* INTERVAL can bind extremely closely, if used as the rightmost subexpr of an expression, otherwise it is in additiveExpr
869 the validating predicate disallows its usage all by itself (can't select just an interval, it must be used in an additive expr)
870 defer checking that to a semantic tree phase.
873 : (INTERVAL ~(LPAREN))=> INTERVAL expr timeUnit {input.LA(1) == PLUS || input.LA(1) == MINUS}? -> ^(INTERVAL expr timeUnit)
874 | lhsPrim=primary -> primary
878 : lhsParen=parenExpr -> parenExpr
879 | lhsLit=literal -> literal
880 | subselect -> subselect
881 | EXISTS subselect -> ^(EXISTS subselect)
882 // TODO: add missing primary expressions, like ROW, DEFAULT etc.
888 | value=GLOBAL_VARIABLE
889 | value=SESSION_VARIABLE
890 | value=VALUE_PLACEHOLDER<com.mysql.clusterj.jdbc.antlr.node.PlaceholderNode>
896 | (functionCall)=>functionCall
902 : BINARY (LPAREN NUMBER RPAREN)?
903 | CHAR (LPAREN NUMBER RPAREN)?
907 | DECIMAL (LPAREN num1=NUMBER COMMA num2=NUMBER RPAREN)?
935 /* TODO: add the SQL_TSI_ prefix versions */
937 : FRAC_SECOND | MICROSECOND
954 /* generates bogus warning about RELEASE */
956 // general trx statements
957 : ( BEGIN WORK? -> ^(BEGIN WORK?)
958 | START TRANSACTION (WITH CONSISTENT SNAPSHOT)? -> ^(START SNAPSHOT?)
962 (NO? RELEASE)? -> ^(COMMIT ^(CHAIN NO?)? ^(RELEASE NO?)?)
965 (NO? RELEASE)? -> ^(ROLLBACK ^(CHAIN NO?)? ^(RELEASE NO?)?)
966 // NUMBER must be (0 | 1), no grammar checks done at this point, TODO check AUTOCOMMIT vs keywords/identifiers
967 // | SET AUTOCOMMIT EQUALS NUMBER
972 TRANSACTION ISOLATION LEVEL
973 ( READ UNCOMMITTED -> ^(ISOLATION UNCOMMITTED $txnScope)
974 | READ COMMITTED -> ^(ISOLATION COMMITTED $txnScope)
975 | REPEATABLE READ -> ^(ISOLATION REPEATABLE $txnScope)
976 | SERIALIZABLE -> ^(ISOLATION SERIALIZABLE $txnScope)
980 // TODO support for XA transactions is missing
983 // savepoint handling
985 : RELEASE? SAVEPOINT ident -> ^(SAVEPOINT ident RELEASE?)
986 | ROLLBACK WORK? TO SAVEPOINT? ident -> ^(ROLLBACK_POINT ident)
994 : INSERT (opt=LOW_PRIORITY | opt=DELAYED | opt=HIGH_PRIORITY)?
996 table=simple_table_ref_no_alias
1002 -> ^(INSERT<com.mysql.clusterj.jdbc.antlr.node.InsertNode> IGNORE? INTO? $opt? ^(TABLE $table)
1003 /* the following three lines are really alts as they cannot appear at the same time */
1011 : (LPAREN column_name_list? RPAREN)?
1012 (VALUE|VALUES) LPAREN val+=insert_default_or_expression (COMMA val+=insert_default_or_expression)* RPAREN
1013 -> ^(INSERT_VALUES column_name_list? ^(VALUES[] $val+))
1016 insert_default_or_expression
1022 : SET column_assignment (COMMA column_assignment)* -> ^(SET column_assignment+)
1026 : ON DUPLICATE KEY UPDATE
1027 column_assignment (COMMA column_assignment)* -> ^(DUPLICATE column_assignment+)
1032 ( DEFAULT -> ^(EQUALS field_name DEFAULT)
1033 | expr -> ^(EQUALS field_name expr)
1038 : field_name (COMMA field_name)* -> ^(COLUMNS field_name+)
1045 : UPDATE LOW_PRIORITY? IGNORE?
1046 table=table_references // this must be table_references because the mysql parser allows an alias here, even for single table updates (unlike DELETE)
1048 (WHERE where_condition)?
1049 /* these options are only valid if we update one table */
1050 ({$table.table_count==1}?=>
1054 -> ^(UPDATE LOW_PRIORITY? IGNORE? $table $set ^(WHERE where_condition)? order_by? ^(LIMIT NUMBER)?)
1062 /* both multi table delete trees are basically identical. The FROM and USING nodes are just in there to differentiate between the syntax used, in order to format it correctly
1063 the AST drops potential .* suffixes for the table names, as they are simply syntactic sugar.
1067 boolean multiTableDelete = false;
1070 // opts+=QUICK causes parser warnings
1071 (options{k=1;}: opts+=LOW_PRIORITY | opts+=IGNORE)* // the yacc parser accepts any combination and any number of these modifiers, so we do, too.
1073 t+=simple_table_ref_no_alias (DOT MULT {multiTableDelete = true;} )? (COMMA t+=simple_table_ref_no_alias (DOT MULT)? {multiTableDelete = true;} )*
1074 (USING tr=table_references {multiTableDelete = true;})?
1075 (WHERE where_condition)?
1076 ({multiTableDelete == false}?=>
1080 -> {multiTableDelete}? ^(DELETE<com.mysql.clusterj.jdbc.antlr.node.DeleteNode> ^(OPTIONS $opts+)? ^(TABLE $t)+ ^(USING $tr) ^(WHERE<com.mysql.clusterj.jdbc.antlr.node.WhereNode> where_condition)?)
1081 -> ^(DELETE<com.mysql.clusterj.jdbc.antlr.node.DeleteNode> ^(OPTIONS $opts+)? ^(TABLE $t) ^(WHERE<com.mysql.clusterj.jdbc.antlr.node.WhereNode> where_condition)? order_by? ^(LIMIT NUMBER)?)
1083 | t+=simple_table_ref_no_alias (DOT MULT)? (COMMA t+=simple_table_ref_no_alias (DOT MULT)?)*
1084 FROM tr=table_references
1085 (WHERE where_condition)? -> ^(DELETE ^(OPTIONS $opts+)? ^(TABLE $t)+ ^(FROM $tr) ^(WHERE<com.mysql.clusterj.jdbc.antlr.node.WhereNode> where_condition)?)
1094 : LOCK TABLES tables+=lock_table_ref (COMMA tables+=lock_table_ref)* -> ^(LOCK $tables)
1095 | UNLOCK TABLES -> ^(UNLOCK TABLES)
1099 : simple_table_ref_alias
1100 ( READ (LOCAL )? -> ^(READ simple_table_ref_alias LOCAL?)
1101 | (LOW_PRIORITY )? WRITE -> ^(WRITE simple_table_ref_alias LOW_PRIORITY?)
1114 : CREATE (TEMPORARY )? TABLE
1116 tableName=simple_table_ref_no_alias
1117 LPAREN create+=create_definition (COMMA create+=create_definition)* RPAREN
1121 simple_table_ref_no_alias
1122 ^(DEFINITIONS $create+)
1127 : colName=ident column_definition -> ^(DEFINITION $colName column_definition)
1135 (notSym=NOT NULL | nullSym=NULL)?
1136 (DEFAULT literal)? // TODO check whether literal covers all the legal values
1137 autoInc=AUTO_INCREMENT?
1138 (UNIQUE uniqueKey=KEY? | PRIMARY? generalKey=KEY)?
1140 (reference_definition )?
1141 // TODO the following two are NDB specific, skipping for now.
1142 // (COLUMN_FORMAT (FIXED|DYNAMIC|DEFAULT))?
1143 // (STORAGE (DISK|MEMORY))?
1149 UNIQUE? PRIMARY? KEY?
1155 ( LPAREN NUMBER RPAREN )?
1163 (LPAREN NUMBER RPAREN)?
1164 (SIGNED | UNSIGNED )?
1172 (LPAREN num1=NUMBER COMMA num2=NUMBER RPAREN )?
1173 (SIGNED | UNSIGNED )?
1187 LPAREN NUMBER RPAREN
1193 LPAREN NUMBER RPAREN
1205 LPAREN values+=STRING (COMMA values+=STRING)* RPAREN
1224 reference_definition