diff --git a/tests/WP_MySQL_Parser_Tests.php b/tests/WP_MySQL_Parser_Tests.php new file mode 100644 index 00000000..e0e12ec5 --- /dev/null +++ b/tests/WP_MySQL_Parser_Tests.php @@ -0,0 +1,281 @@ +query(); + + // Fake assertion to keep PHPUnit happy and still verify that the query + // parsed without fatal errors and exceptions. + $this->assertEquals(1, 1); + } + + public static function mysqlQueries() { + return array( + // CREATE + 'createDatabase' => ['CREATE DATABASE mydatabase;'], + 'createTable' => [<< [<< [<< [<< [<< 5 + ) c ON o.customer_id = c.customer_id + SET o.`status` = 'Shipped'; + SQL], + 'updateSubQuery' => [<< [<< [<< [<< [<< [<< [<< [<< ['ALTER TABLE products + MODIFY COLUMN product_name VARCHAR(200) NOT NULL;'], + 'alterIndex' => ['ALTER TABLE products + DROP INDEX idx_col_h_i, + ADD INDEX idx_col_h_i_j (`col_h`, `col_i`, `col_j`);'], + + // SELECT + 'simple' => ['SELECT 1'], + 'complexSelect' => [<< ['DROP TABLE products;'], + 'dropIndex' => ['DROP INDEX idx_col_h_i_j ON products;'], + 'dropColumn' => ['ALTER TABLE products DROP COLUMN product_name;'], + 'dropConstraint' => ['ALTER TABLE products DROP FOREIGN KEY fk_product_id;'], + 'dropDatabase' => ['DROP DATABASE mydatabase;'], + + // GRANT + 'grantAll' => ['GRANT ALL ON mydatabase TO myuser@localhost;'], + 'grantSelect' => ['GRANT SELECT ON mydatabase TO myuser@localhost;'], + 'grantInsert' => ['GRANT INSERT ON mydatabase TO myuser@localhost;'], + 'grantUpdate' => ['GRANT UPDATE ON mydatabase TO myuser@localhost;'], + 'grantDelete' => ['GRANT DELETE ON mydatabase TO myuser@localhost;'], + 'grantCreate' => ['GRANT CREATE ON mydatabase TO myuser@localhost;'], + 'grantDrop' => ['GRANT DROP ON mydatabase TO myuser@localhost;'], + 'grantAlter' => ['GRANT ALTER ON mydatabase TO myuser@localhost;'], + 'grantIndex' => ['GRANT INDEX ON mydatabase TO myuser@localhost;'], + 'grantCreateView' => ['GRANT CREATE VIEW ON mydatabase TO myuser@localhost;'], + 'grantShowView' => ['GRANT SHOW VIEW ON mydatabase TO myuser@localhost;'], + 'grantCreateRoutine' => ['GRANT CREATE ROUTINE ON mydatabase TO myuser@localhost;'], + 'grantAlterRoutine' => ['GRANT ALTER ROUTINE ON mydatabase TO myuser@localhost;'], + 'grantExecute' => ['GRANT EXECUTE ON mydatabase TO myuser@localhost;'], + 'grantEvent' => ['GRANT EVENT ON mydatabase TO myuser@localhost;'], + 'grantTrigger' => ['GRANT TRIGGER ON mydatabase TO myuser@localhost;'], + 'grantLockTables' => ['GRANT LOCK TABLES ON mydatabase TO myuser@localhost;'], + 'grantReferences' => ['GRANT REFERENCES ON mydatabase TO myuser@localhost;'], + 'grantCreateTemporaryTables' => ['GRANT CREATE TEMPORARY TABLES ON mydatabase TO myuser@localhost;'], + 'grantShowDatabases' => ['GRANT SHOW DATABASES ON mydatabase TO myuser@localhost;'], + 'grantSuper' => ['GRANT SUPER ON mydatabase TO myuser@localhost;'], + 'grantReload' => ['GRANT RELOAD ON mydatabase TO myuser@localhost;'], + 'grantShutdown' => ['GRANT SHUTDOWN ON mydatabase TO myuser@localhost;', 80017], + 'grantProcess' => ['GRANT PROCESS ON mydatabase TO myuser@localhost;'], + 'grantFile' => ['GRANT FILE ON mydatabase TO myuser@localhost;'], + 'grantSelectOnAllTables' => ['GRANT SELECT ON mydatabase.* TO myuser@localhost;', 80000], + 'grantSelectOnTable' => ['GRANT SELECT ON mydatabase.mytable TO myuser@localhost;', 80017], + + // SHOW + 'showDatabases' => ['SHOW DATABASES;'], + 'showTables' => ['SHOW TABLES;'], + 'showColumns' => ['SHOW COLUMNS FROM products;'], + 'showIndexes' => ['SHOW INDEXES FROM products;'], + 'showExtendedIndexes' => ['SHOW EXTENDED INDEXES FROM products;'], + 'showConstraints' => ['SHOW CONSTRAINTS FROM products;'], + 'showCreateTable' => ['SHOW CREATE TABLE products;'], + 'showStatus' => ['SHOW STATUS;'], + 'showVariables' => ['SHOW VARIABLES;'], + 'showProcesslist' => ['SHOW PROCESSLIST;'], + 'showGrants' => ['SHOW GRANTS;'], + 'showPrivileges' => ['SHOW PRIVILEGES;'], + 'showEngines' => ['SHOW ENGINES;'], + 'showStorageEngines' => ['SHOW STORAGE ENGINES;'], + 'showPlugins' => ['SHOW PLUGINS;'], + 'showWarnings' => ['SHOW WARNINGS;'], + 'showErrors' => ['SHOW ERRORS;'], + 'showEvents' => ['SHOW EVENTS;'], + 'showTriggers' => ['SHOW TRIGGERS;'], + 'showCreate' => ['SHOW CREATE EVENT myevent;'], + 'showCreateTrigger' => ['SHOW CREATE TRIGGER mytrigger;'], + 'showCreateFunction' => ['SHOW CREATE FUNCTION myfunction;'], + 'showCreateProcedure' => ['SHOW CREATE PROCEDURE myprocedure;'], + 'showCreateView' => ['SHOW CREATE VIEW myview;'], + 'showCreateUser' => ['SHOW CREATE USER myuser;'], + 'showCreateRole' => ['SHOW CREATE ROLE myrole;'], + 'showCreateTablespace' => ['SHOW CREATE TABLESPACE mytablespace;', 80017], + 'showCreateDatabase' => ['SHOW CREATE DATABASE mydatabase;'], + 'showCreateDatabaseIfNotExists' => ['SHOW CREATE DATABASE IF NOT EXISTS myevent;'], + 'showExtended' => ['SHOW EXTENDED COLUMNS FROM products;'], + 'showFull' => ['SHOW FULL COLUMNS FROM products;'], + 'showExtendedFull' => ['SHOW EXTENDED FULL COLUMNS FROM products;'], + + // SET + 'setVariable' => ['SET @myvar = 1;'], + 'setGlobalVariable' => ['SET GLOBAL myvar = 1;'], + 'setSessionVariable' => ['SET SESSION myvar = 1;'], + 'setTransaction' => ['SET TRANSACTION ISOLATION LEVEL READ COMMITTED;'], + 'setAutocommit' => ['SET AUTOCOMMIT = 0;'], + 'setNames' => ['SET NAMES utf8;'], + 'setCharacter' => ["SET CHARACTER SET utf8;"], + 'setCharacterQuotes' => ["SET CHARACTER SET 'utf8';"], + 'setNamesCollate' => ["SET NAMES 'utf8' COLLATE utf8_general_ci;"], + 'setNamesCollateDefault' => ["SET NAMES 'utf8' COLLATE DEFAULT;"], + 'setSqlMode' => ['SET SQL_MODE = "ANSI_QUOTES";'], + 'setTimeZone' => ['SET TIME_ZONE = "+00:00";'], + 'setPassword' => ["SET PASSWORD = 'newpassword';"], + + // Transactions + 'begin' => ['BEGIN;'], + 'commit' => ['COMMIT;'], + 'rollback' => ['ROLLBACK;'], + 'savepoint' => ['SAVEPOINT mysavepoint;'], + 'releaseSavepoint' => ['RELEASE SAVEPOINT mysavepoint;'], + 'rollbackToSavepoint' => ['ROLLBACK TO SAVEPOINT mysavepoint;'], + 'lockTable' => ['LOCK TABLES products WRITE;'], + 'unlockTable' => ['UNLOCK TABLES;'], + 'flush' => ['FLUSH PRIVILEGES;'], + 'flushTables' => ['FLUSH TABLES;'], + 'flushLogs' => ['FLUSH LOGS;'], + 'flushStatus' => ['FLUSH STATUS;'], + 'flushTablesWithReadLock' => ['FLUSH TABLES WITH READ LOCK;'], + 'flushHosts' => ['FLUSH HOSTS;'], + 'flushOptimizerCosts' => ['FLUSH OPTIMIZER_COSTS;'], + ); + } +} diff --git a/wp-content/plugins/sqlite-database-integration/wp-includes/mysql-parser/MySQLLexer.g4 b/wp-content/plugins/sqlite-database-integration/wp-includes/mysql-parser/MySQLLexer.g4 new file mode 100644 index 00000000..cbd2a76f --- /dev/null +++ b/wp-content/plugins/sqlite-database-integration/wp-includes/mysql-parser/MySQLLexer.g4 @@ -0,0 +1,1162 @@ +lexer grammar MySQLLexer; + +/* + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2.0, + * as published by the Free Software Foundation. + * + * This program is designed to work with certain software (including + * but not limited to OpenSSL) that is licensed under separate terms, as + * designated in a particular file or component or in included license + * documentation. The authors of MySQL hereby grant you an additional + * permission to link the program and your derivative works with the + * separately licensed software that they have either included with + * the program or referenced in the documentation. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License, version 2.0, for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Merged in all changes up to mysql-trunk git revision [6d4f66a] (16. January 2020). + * + * MySQL grammar for ANTLR 4.5+ with language features from MySQL 5.6.0 up to MySQL 8.0. + * The server version in the generated parser can be switched at runtime, making it so possible + * to switch the supported feature set dynamically. + * + * The coverage of the MySQL language should be 100%, but there might still be bugs or omissions. + * + * To use this grammar you will need a few support classes (which should be close to where you found this grammar). + * These classes implement the target specific action code, so we don't clutter the grammar with that + * and make it simpler to adjust it for other targets. See the demo/test project for further details. + * + * Written by Mike Lischke. Direct all bug reports, omissions etc. to mike.lischke@oracle.com. + */ + +//------------------------------------------------------------------------------------------------- + +// $antlr-format alignTrailingComments on, columnLimit 150, maxEmptyLinesToKeep 1, reflowComments off, useTab off +// $antlr-format allowShortRulesOnASingleLine on, alignSemicolons ownLine + +options { + superClass = MySQLBaseLexer; + tokenVocab = predefined; // Keyword tokens in a predefined order for simpler checks. + exportMacro = PARSERS_PUBLIC_TYPE; +} + +tokens { + NOT2_SYMBOL, + CONCAT_PIPES_SYMBOL, + + // Tokens assigned in NUMBER rule. + INT_NUMBER, // NUM in sql_yacc.yy + LONG_NUMBER, + ULONGLONG_NUMBER +} + +@postinclude { +#include "MySQLBaseLexer.h" +} + +//------------------------------------------------------------------------------------------------- + +@header {/* + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2.0, + * as published by the Free Software Foundation. + * + * This program is designed to work with certain software (including + * but not limited to OpenSSL) that is licensed under separate terms, as + * designated in a particular file or component or in included license + * documentation. The authors of MySQL hereby grant you an additional + * permission to link the program and your derivative works with the + * separately licensed software that they have either included with + * the program or referenced in the documentation. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License, version 2.0, for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +} + +//------------------------------------------------------------------------------------------------- + +// Operators +EQUAL_OPERATOR: '='; // Also assign. +ASSIGN_OPERATOR: ':='; +NULL_SAFE_EQUAL_OPERATOR: '<=>'; +GREATER_OR_EQUAL_OPERATOR: '>='; +GREATER_THAN_OPERATOR: '>'; +LESS_OR_EQUAL_OPERATOR: '<='; +LESS_THAN_OPERATOR: '<'; +NOT_EQUAL_OPERATOR: '!='; +NOT_EQUAL2_OPERATOR: '<>' -> type(NOT_EQUAL_OPERATOR); + +PLUS_OPERATOR: '+'; +MINUS_OPERATOR: '-'; +MULT_OPERATOR: '*'; +DIV_OPERATOR: '/'; + +MOD_OPERATOR: '%'; + +LOGICAL_NOT_OPERATOR: '!'; +BITWISE_NOT_OPERATOR: '~'; + +SHIFT_LEFT_OPERATOR: '<<'; +SHIFT_RIGHT_OPERATOR: '>>'; + +LOGICAL_AND_OPERATOR: '&&'; +BITWISE_AND_OPERATOR: '&'; + +BITWISE_XOR_OPERATOR: '^'; + +LOGICAL_OR_OPERATOR: + '||' { setType(isSqlModeActive(PipesAsConcat) ? CONCAT_PIPES_SYMBOL : LOGICAL_OR_OPERATOR); } +; +BITWISE_OR_OPERATOR: '|'; + +DOT_SYMBOL: '.'; +COMMA_SYMBOL: ','; +SEMICOLON_SYMBOL: ';'; +COLON_SYMBOL: ':'; +OPEN_PAR_SYMBOL: '('; +CLOSE_PAR_SYMBOL: ')'; +OPEN_CURLY_SYMBOL: '{'; +CLOSE_CURLY_SYMBOL: '}'; +UNDERLINE_SYMBOL: '_'; + +JSON_SEPARATOR_SYMBOL: '->' {serverVersion >= 50708}?; // MYSQL +JSON_UNQUOTED_SEPARATOR_SYMBOL: '->>' {serverVersion >= 50713}?; // MYSQL + +// The MySQL server parser uses custom code in its lexer to allow base alphanum chars (and ._$) as variable name. +// For this it handles user variables in 2 different ways and we have to model this to match that behavior. +AT_SIGN_SYMBOL: '@'; +AT_TEXT_SUFFIX: '@' SIMPLE_IDENTIFIER; + +AT_AT_SIGN_SYMBOL: '@@'; + +NULL2_SYMBOL: '\\N'; +PARAM_MARKER: '?'; + +fragment A: [aA]; +fragment B: [bB]; +fragment C: [cC]; +fragment D: [dD]; +fragment E: [eE]; +fragment F: [fF]; +fragment G: [gG]; +fragment H: [hH]; +fragment I: [iI]; +fragment J: [jJ]; +fragment K: [kK]; +fragment L: [lL]; +fragment M: [mM]; +fragment N: [nN]; +fragment O: [oO]; +fragment P: [pP]; +fragment Q: [qQ]; +fragment R: [rR]; +fragment S: [sS]; +fragment T: [tT]; +fragment U: [uU]; +fragment V: [vV]; +fragment W: [wW]; +fragment X: [xX]; +fragment Y: [yY]; +fragment Z: [zZ]; + +fragment DIGIT: [0-9]; +fragment DIGITS: DIGIT+; +fragment HEXDIGIT: [0-9a-fA-F]; + +// Only lower case 'x' and 'b' count for hex + bin numbers. Otherwise it's an identifier. +HEX_NUMBER: ('0x' HEXDIGIT+) | ('x\'' HEXDIGIT+ '\''); +BIN_NUMBER: ('0b' [01]+) | ('b\'' [01]+ '\''); + +INT_NUMBER: DIGITS { setType(determineNumericType(getText())); }; + +// Float types must be handled first or the DOT_IDENTIIFER rule will make them to identifiers +// (if there is no leading digit before the dot). +DECIMAL_NUMBER: DIGITS? DOT_SYMBOL DIGITS; +FLOAT_NUMBER: (DIGITS? DOT_SYMBOL)? DIGITS [eE] (MINUS_OPERATOR | PLUS_OPERATOR)? DIGITS; + +// Special rule that should also match all keywords if they are directly preceded by a dot. +// Hence it's defined before all keywords. +// Here we make use of the ability in our base lexer to emit multiple tokens with a single rule. +DOT_IDENTIFIER: + DOT_SYMBOL LETTER_WHEN_UNQUOTED_NO_DIGIT LETTER_WHEN_UNQUOTED* { emitDot(); } -> type(IDENTIFIER) +; + +/* + The following comment is from the server grammar and gives some information about the source of tokens. + Additionally there is a section describing how to handle tokens there, which does not apply to this ANTLR grammar. + + MAINTAINER: + + 1) Comments for TOKENS. + + For each token, please include in the same line a comment that contains + one of the following tags: + SQL-2015-R : Reserved keyword as per SQL-2015 draft + SQL-2003-R : Reserved keyword as per SQL-2003 + SQL-2003-N : Non Reserved keyword as per SQL-2003 + SQL-1999-R : Reserved keyword as per SQL-1999 + SQL-1999-N : Non Reserved keyword as per SQL-1999 + MYSQL : MySQL extension (unspecified) + MYSQL-FUNC : MySQL extension, function + INTERNAL : Not a real token, lex optimization + OPERATOR : SQL operator + FUTURE-USE : Reserved for futur use + + This makes the code grep-able, and helps maintenance. + + 2) About token values + + Token values are assigned by bison, in order of declaration. + + Token values are used in query DIGESTS. + To make DIGESTS stable, it is desirable to avoid changing token values. + + In practice, this means adding new tokens at the end of the list, + in the current release section (8.0), + instead of adding them in the middle of the list. + + Failing to comply with instructions below will trigger build failure, + as this process is enforced by gen_lex_token. + + 3) Instructions to add a new token: + + Add the new token at the end of the list, + in the MySQL 8.0 section. + + 4) Instructions to remove an old token: + + Do not remove the token, rename it as follows: + %token OBSOLETE_TOKEN_ / * was: TOKEN_FOO * / + where NNN is the token value (found in sql_yacc.h) + + For example, see OBSOLETE_TOKEN_820 +*/ + +/* + Tokens from MySQL 5.7, keep in alphabetical order. +*/ + +// $antlr-format groupedAlignments off, alignTrailers on + +//ABORT_SYMBOL: 'ABORT'; // INTERNAL (used in lex) +ACCESSIBLE_SYMBOL: A C C E S S I B L E; +ACCOUNT_SYMBOL: A C C O U N T {serverVersion >= 50707}?; +ACTION_SYMBOL: A C T I O N; // SQL-2003-N +ADD_SYMBOL: A D D; // SQL-2003-R +ADDDATE_SYMBOL: A D D D A T E { setType(determineFunction(ADDDATE_SYMBOL)); }; // MYSQL-FUNC +AFTER_SYMBOL: A F T E R; // SQL-2003-N +AGAINST_SYMBOL: A G A I N S T; +AGGREGATE_SYMBOL: A G G R E G A T E; +ALGORITHM_SYMBOL: A L G O R I T H M; +ALL_SYMBOL: A L L; // SQL-2003-R +ALTER_SYMBOL: A L T E R; // SQL-2003-R +ALWAYS_SYMBOL: A L W A Y S {serverVersion >= 50707}?; +ANALYSE_SYMBOL: A N A L Y S E {serverVersion < 80000}?; +ANALYZE_SYMBOL: A N A L Y Z E; +AND_SYMBOL: A N D; // SQL-2003-R +ANY_SYMBOL: A N Y; // SQL-2003-R +AS_SYMBOL: A S; // SQL-2003-R +ASC_SYMBOL: A S C; // SQL-2003-N +ASCII_SYMBOL: A S C I I; // MYSQL-FUNC +ASENSITIVE_SYMBOL: A S E N S I T I V E; // FUTURE-USE +AT_SYMBOL: A T; +AUTHORS_SYMBOL: A U T H O R S {serverVersion < 50700}?; +AUTOEXTEND_SIZE_SYMBOL: A U T O E X T E N D '_' S I Z E; +AUTO_INCREMENT_SYMBOL: A U T O '_' I N C R E M E N T; +AVG_ROW_LENGTH_SYMBOL: A V G '_' R O W '_' L E N G T H; +AVG_SYMBOL: A V G; // SQL-2003-N +BACKUP_SYMBOL: B A C K U P; +BEFORE_SYMBOL: B E F O R E; // SQL-2003-N +BEGIN_SYMBOL: B E G I N; // SQL-2003-R +BETWEEN_SYMBOL: B E T W E E N; // SQL-2003-R +BIGINT_SYMBOL: B I G I N T; // SQL-2003-R +BINARY_SYMBOL: B I N A R Y; // SQL-2003-R +BINLOG_SYMBOL: B I N L O G; +BIN_NUM_SYMBOL: B I N '_' N U M; +BIT_AND_SYMBOL: B I T '_' A N D { setType(determineFunction(BIT_AND_SYMBOL)); }; // MYSQL-FUNC +BIT_OR_SYMBOL: B I T '_' O R { setType(determineFunction(BIT_OR_SYMBOL)); }; // MYSQL-FUNC +BIT_SYMBOL: B I T; // MYSQL-FUNC +BIT_XOR_SYMBOL: B I T '_' X O R { setType(determineFunction(BIT_XOR_SYMBOL)); }; // MYSQL-FUNC +BLOB_SYMBOL: B L O B; // SQL-2003-R +BLOCK_SYMBOL: B L O C K; +BOOLEAN_SYMBOL: B O O L E A N; // SQL-2003-R +BOOL_SYMBOL: B O O L; +BOTH_SYMBOL: B O T H; // SQL-2003-R +BTREE_SYMBOL: B T R E E; +BY_SYMBOL: B Y; // SQL-2003-R +BYTE_SYMBOL: B Y T E; +CACHE_SYMBOL: C A C H E; +CALL_SYMBOL: C A L L; // SQL-2003-R +CASCADE_SYMBOL: C A S C A D E; // SQL-2003-N +CASCADED_SYMBOL: C A S C A D E D; // SQL-2003-R +CASE_SYMBOL: C A S E; // SQL-2003-R +CAST_SYMBOL: C A S T { setType(determineFunction(CAST_SYMBOL)); }; // SQL-2003-R +CATALOG_NAME_SYMBOL: C A T A L O G '_' N A M E; // SQL-2003-N +CHAIN_SYMBOL: C H A I N; // SQL-2003-N +CHANGE_SYMBOL: C H A N G E; +CHANGED_SYMBOL: C H A N G E D; +CHANNEL_SYMBOL: C H A N N E L {serverVersion >= 50706}?; +CHARSET_SYMBOL: C H A R S E T; +CHARACTER_SYMBOL: C H A R A C T E R -> type(CHAR_SYMBOL); // Synonym +CHAR_SYMBOL: C H A R; // SQL-2003-R +CHECKSUM_SYMBOL: C H E C K S U M; +CHECK_SYMBOL: C H E C K; // SQL-2003-R +CIPHER_SYMBOL: C I P H E R; +CLASS_ORIGIN_SYMBOL: C L A S S '_' O R I G I N; // SQL-2003-N +CLIENT_SYMBOL: C L I E N T; +CLOSE_SYMBOL: C L O S E; // SQL-2003-R +COALESCE_SYMBOL: C O A L E S C E; // SQL-2003-N +CODE_SYMBOL: C O D E; +COLLATE_SYMBOL: C O L L A T E; // SQL-2003-R +COLLATION_SYMBOL: C O L L A T I O N; // SQL-2003-N +COLUMNS_SYMBOL: C O L U M N S; +COLUMN_SYMBOL: C O L U M N; // SQL-2003-R +COLUMN_NAME_SYMBOL: C O L U M N '_' N A M E; // SQL-2003-N +COLUMN_FORMAT_SYMBOL: C O L U M N '_' F O R M A T; +COMMENT_SYMBOL: C O M M E N T; +COMMITTED_SYMBOL: C O M M I T T E D; // SQL-2003-N +COMMIT_SYMBOL: C O M M I T; // SQL-2003-R +COMPACT_SYMBOL: C O M P A C T; +COMPLETION_SYMBOL: C O M P L E T I O N; +COMPRESSED_SYMBOL: C O M P R E S S E D; +COMPRESSION_SYMBOL: C O M P R E S S I O N {serverVersion >= 50707}?; +CONCURRENT_SYMBOL: C O N C U R R E N T; +CONDITION_SYMBOL: C O N D I T I O N; // SQL-2003-R, SQL-2008-R +CONNECTION_SYMBOL: C O N N E C T I O N; +CONSISTENT_SYMBOL: C O N S I S T E N T; +CONSTRAINT_SYMBOL: C O N S T R A I N T; // SQL-2003-R +CONSTRAINT_CATALOG_SYMBOL: C O N S T R A I N T '_' C A T A L O G; // SQL-2003-N +CONSTRAINT_NAME_SYMBOL: C O N S T R A I N T '_' N A M E; // SQL-2003-N +CONSTRAINT_SCHEMA_SYMBOL: C O N S T R A I N T '_' S C H E M A; // SQL-2003-N +CONTAINS_SYMBOL: C O N T A I N S; // SQL-2003-N +CONTEXT_SYMBOL: C O N T E X T; +CONTINUE_SYMBOL: C O N T I N U E; // SQL-2003-R +CONTRIBUTORS_SYMBOL: C O N T R I B U T O R S {serverVersion < 50700}?; +CONVERT_SYMBOL: C O N V E R T; // SQL-2003-N +COUNT_SYMBOL: C O U N T { setType(determineFunction(COUNT_SYMBOL)); }; // SQL-2003-N +CPU_SYMBOL: C P U; +CREATE_SYMBOL: C R E A T E; // SQL-2003-R +CROSS_SYMBOL: C R O S S; // SQL-2003-R +CUBE_SYMBOL: C U B E; // SQL-2003-R +CURDATE_SYMBOL: C U R D A T E { setType(determineFunction(CURDATE_SYMBOL)); }; // MYSQL-FUNC +CURRENT_SYMBOL: C U R R E N T {serverVersion >= 50604}?; +CURRENT_DATE_SYMBOL: + C U R R E N T '_' D A T E { setType(determineFunction(CURDATE_SYMBOL)); } +; // Synonym, MYSQL-FUNC +CURRENT_TIME_SYMBOL: + C U R R E N T '_' T I M E { setType(determineFunction(CURTIME_SYMBOL)); } +; // Synonym, MYSQL-FUNC +CURRENT_TIMESTAMP_SYMBOL: C U R R E N T '_' T I M E S T A M P -> type(NOW_SYMBOL); // Synonym +CURRENT_USER_SYMBOL: C U R R E N T '_' U S E R; // SQL-2003-R +CURSOR_SYMBOL: C U R S O R; // SQL-2003-R +CURSOR_NAME_SYMBOL: C U R S O R '_' N A M E; // SQL-2003-N +CURTIME_SYMBOL: C U R T I M E { setType(determineFunction(CURTIME_SYMBOL)); }; // MYSQL-FUNC +DATABASE_SYMBOL: D A T A B A S E; +DATABASES_SYMBOL: D A T A B A S E S; +DATAFILE_SYMBOL: D A T A F I L E; +DATA_SYMBOL: D A T A; // SQL-2003-N +DATETIME_SYMBOL: D A T E T I M E; // MYSQL +DATE_ADD_SYMBOL: D A T E '_' A D D { setType(determineFunction(DATE_ADD_SYMBOL)); }; +DATE_SUB_SYMBOL: D A T E '_' S U B { setType(determineFunction(DATE_SUB_SYMBOL)); }; +DATE_SYMBOL: D A T E; // SQL-2003-R +DAYOFMONTH_SYMBOL: D A Y O F M O N T H -> type(DAY_SYMBOL); // Synonym +DAY_HOUR_SYMBOL: D A Y '_' H O U R; +DAY_MICROSECOND_SYMBOL: D A Y '_' M I C R O S E C O N D; +DAY_MINUTE_SYMBOL: D A Y '_' M I N U T E; +DAY_SECOND_SYMBOL: D A Y '_' S E C O N D; +DAY_SYMBOL: D A Y; // SQL-2003-R +DEALLOCATE_SYMBOL: D E A L L O C A T E; // SQL-2003-R +DEC_SYMBOL: D E C -> type(DECIMAL_SYMBOL); // Synonym +DECIMAL_NUM_SYMBOL: D E C I M A L '_' N U M; +DECIMAL_SYMBOL: D E C I M A L; // SQL-2003-R +DECLARE_SYMBOL: D E C L A R E; // SQL-2003-R +DEFAULT_SYMBOL: D E F A U L T; // SQL-2003-R +DEFAULT_AUTH_SYMBOL: D E F A U L T '_' A U T H {serverVersion >= 50604}?; // Internal +DEFINER_SYMBOL: D E F I N E R; +DELAYED_SYMBOL: D E L A Y E D; +DELAY_KEY_WRITE_SYMBOL: D E L A Y '_' K E Y '_' W R I T E; +DELETE_SYMBOL: D E L E T E; // SQL-2003-R +DESC_SYMBOL: D E S C; // SQL-2003-N +DESCRIBE_SYMBOL: D E S C R I B E; // SQL-2003-R +DES_KEY_FILE_SYMBOL: D E S '_' K E Y '_' F I L E {serverVersion < 80000}?; +DETERMINISTIC_SYMBOL: D E T E R M I N I S T I C; // SQL-2003-R +DIAGNOSTICS_SYMBOL: D I A G N O S T I C S; +DIRECTORY_SYMBOL: D I R E C T O R Y; +DISABLE_SYMBOL: D I S A B L E; +DISCARD_SYMBOL: D I S C A R D; +DISK_SYMBOL: D I S K; +DISTINCT_SYMBOL: D I S T I N C T; // SQL-2003-R +DISTINCTROW_SYMBOL: D I S T I N C T R O W -> type(DISTINCT_SYMBOL); // Synonym +DIV_SYMBOL: D I V; +DOUBLE_SYMBOL: D O U B L E; // SQL-2003-R +DO_SYMBOL: D O; +DROP_SYMBOL: D R O P; // SQL-2003-R +DUAL_SYMBOL: D U A L; +DUMPFILE_SYMBOL: D U M P F I L E; +DUPLICATE_SYMBOL: D U P L I C A T E; +DYNAMIC_SYMBOL: D Y N A M I C; // SQL-2003-R +EACH_SYMBOL: E A C H; // SQL-2003-R +ELSE_SYMBOL: E L S E; // SQL-2003-R +ELSEIF_SYMBOL: E L S E I F; +ENABLE_SYMBOL: E N A B L E; +ENCLOSED_SYMBOL: E N C L O S E D; +ENCRYPTION_SYMBOL: E N C R Y P T I O N {serverVersion >= 50711}?; +END_SYMBOL: E N D; // SQL-2003-R +ENDS_SYMBOL: E N D S; +END_OF_INPUT_SYMBOL: E N D '_' O F '_' I N P U T; // INTERNAL +ENGINES_SYMBOL: E N G I N E S; +ENGINE_SYMBOL: E N G I N E; +ENUM_SYMBOL: E N U M; // MYSQL +ERROR_SYMBOL: E R R O R; +ERRORS_SYMBOL: E R R O R S; +ESCAPED_SYMBOL: E S C A P E D; +ESCAPE_SYMBOL: E S C A P E; // SQL-2003-R +EVENTS_SYMBOL: E V E N T S; +EVENT_SYMBOL: E V E N T; +EVERY_SYMBOL: E V E R Y; // SQL-2003-N +EXCHANGE_SYMBOL: E X C H A N G E; +EXECUTE_SYMBOL: E X E C U T E; // SQL-2003-R +EXISTS_SYMBOL: E X I S T S; // SQL-2003-R +EXIT_SYMBOL: E X I T; +EXPANSION_SYMBOL: E X P A N S I O N; +EXPIRE_SYMBOL: E X P I R E {serverVersion >= 50606}?; +EXPLAIN_SYMBOL: E X P L A I N; // SQL-2003-R +EXPORT_SYMBOL: E X P O R T {serverVersion >= 50606}?; +EXTENDED_SYMBOL: E X T E N D E D; +EXTENT_SIZE_SYMBOL: E X T E N T '_' S I Z E; +EXTRACT_SYMBOL: E X T R A C T { setType(determineFunction(EXTRACT_SYMBOL)); }; // SQL-2003-N +FALSE_SYMBOL: F A L S E; // SQL-2003-R +FAST_SYMBOL: F A S T; +FAULTS_SYMBOL: F A U L T S; +FETCH_SYMBOL: F E T C H; // SQL-2003-R +FIELDS_SYMBOL: F I E L D S -> type(COLUMNS_SYMBOL); // Synonym +FILE_SYMBOL: F I L E; +FILE_BLOCK_SIZE_SYMBOL: F I L E '_' B L O C K '_' S I Z E {serverVersion >= 50707}?; +FILTER_SYMBOL: F I L T E R {serverVersion >= 50700}?; +FIRST_SYMBOL: F I R S T; // SQL-2003-N +FIXED_SYMBOL: F I X E D; +FLOAT4_SYMBOL: F L O A T '4' -> type(FLOAT_SYMBOL); // Synonym +FLOAT8_SYMBOL: F L O A T '8' -> type(DOUBLE_SYMBOL); // Synonym +FLOAT_SYMBOL: F L O A T; // SQL-2003-R +FLUSH_SYMBOL: F L U S H; +FOLLOWS_SYMBOL: F O L L O W S {serverVersion >= 50700}?; +FORCE_SYMBOL: F O R C E; +FOREIGN_SYMBOL: F O R E I G N; // SQL-2003-R +FOR_SYMBOL: F O R; // SQL-2003-R +FORMAT_SYMBOL: F O R M A T; +FOUND_SYMBOL: F O U N D; // SQL-2003-R +FROM_SYMBOL: F R O M; +FULL_SYMBOL: F U L L; // SQL-2003-R +FULLTEXT_SYMBOL: F U L L T E X T; +FUNCTION_SYMBOL: F U N C T I O N; // SQL-2003-R +GET_SYMBOL: G E T {serverVersion >= 50604}?; +GENERAL_SYMBOL: G E N E R A L; +GENERATED_SYMBOL: G E N E R A T E D {serverVersion >= 50707}?; +GROUP_REPLICATION_SYMBOL: G R O U P '_' R E P L I C A T I O N {serverVersion >= 50707}?; +GEOMETRYCOLLECTION_SYMBOL: G E O M E T R Y C O L L E C T I O N; // MYSQL +GEOMETRY_SYMBOL: G E O M E T R Y; +GET_FORMAT_SYMBOL: G E T '_' F O R M A T; // MYSQL-FUNC +GLOBAL_SYMBOL: G L O B A L; // SQL-2003-R +GRANT_SYMBOL: G R A N T; // SQL-2003-R +GRANTS_SYMBOL: G R A N T S; +GROUP_SYMBOL: G R O U P; // SQL-2003-R +GROUP_CONCAT_SYMBOL: + G R O U P '_' C O N C A T { setType(determineFunction(GROUP_CONCAT_SYMBOL)); } +; +HANDLER_SYMBOL: H A N D L E R; +HASH_SYMBOL: H A S H; +HAVING_SYMBOL: H A V I N G; // SQL-2003-R +HELP_SYMBOL: H E L P; +HIGH_PRIORITY_SYMBOL: H I G H '_' P R I O R I T Y; +HOST_SYMBOL: H O S T; +HOSTS_SYMBOL: H O S T S; +HOUR_MICROSECOND_SYMBOL: H O U R '_' M I C R O S E C O N D; +HOUR_MINUTE_SYMBOL: H O U R '_' M I N U T E; +HOUR_SECOND_SYMBOL: H O U R '_' S E C O N D; +HOUR_SYMBOL: H O U R; // SQL-2003-R +IDENTIFIED_SYMBOL: I D E N T I F I E D; +IF_SYMBOL: I F; +IGNORE_SYMBOL: I G N O R E; +IGNORE_SERVER_IDS_SYMBOL: I G N O R E '_' S E R V E R '_' I D S; +IMPORT_SYMBOL: I M P O R T; +INDEXES_SYMBOL: I N D E X E S; +INDEX_SYMBOL: I N D E X; +INFILE_SYMBOL: I N F I L E; +INITIAL_SIZE_SYMBOL: I N I T I A L '_' S I Z E; +INNER_SYMBOL: I N N E R; // SQL-2003-R +INOUT_SYMBOL: I N O U T; // SQL-2003-R +INSENSITIVE_SYMBOL: I N S E N S I T I V E; // SQL-2003-R +INSERT_SYMBOL: I N S E R T; // SQL-2003-R +INSERT_METHOD_SYMBOL: I N S E R T '_' M E T H O D; +INSTANCE_SYMBOL: I N S T A N C E {serverVersion >= 50713}?; +INSTALL_SYMBOL: I N S T A L L; +INTEGER_SYMBOL: I N T E G E R -> type(INT_SYMBOL); // Synonym +INTERVAL_SYMBOL: I N T E R V A L; // SQL-2003-R +INTO_SYMBOL: I N T O; // SQL-2003-R +INT_SYMBOL: I N T; // SQL-2003-R +INVOKER_SYMBOL: I N V O K E R; +IN_SYMBOL: I N; // SQL-2003-R +IO_AFTER_GTIDS_SYMBOL: I O '_' A F T E R '_' G T I D S; // MYSQL, FUTURE-USE +IO_BEFORE_GTIDS_SYMBOL: I O '_' B E F O R E '_' G T I D S; // MYSQL, FUTURE-USE +IO_THREAD_SYMBOL: I O '_' T H R E A D -> type(RELAY_THREAD_SYMBOL); // Synonym +IO_SYMBOL: I O; +IPC_SYMBOL: I P C; +IS_SYMBOL: I S; // SQL-2003-R +ISOLATION_SYMBOL: I S O L A T I O N; // SQL-2003-R +ISSUER_SYMBOL: I S S U E R; +ITERATE_SYMBOL: I T E R A T E; +JOIN_SYMBOL: J O I N; // SQL-2003-R +JSON_SYMBOL: J S O N {serverVersion >= 50708}?; // MYSQL +KEYS_SYMBOL: K E Y S; +KEY_BLOCK_SIZE_SYMBOL: K E Y '_' B L O C K '_' S I Z E; +KEY_SYMBOL: K E Y; // SQL-2003-N +KILL_SYMBOL: K I L L; +LANGUAGE_SYMBOL: L A N G U A G E; // SQL-2003-R +LAST_SYMBOL: L A S T; // SQL-2003-N +LEADING_SYMBOL: L E A D I N G; // SQL-2003-R +LEAVES_SYMBOL: L E A V E S; +LEAVE_SYMBOL: L E A V E; +LEFT_SYMBOL: L E F T; // SQL-2003-R +LESS_SYMBOL: L E S S; +LEVEL_SYMBOL: L E V E L; +LIKE_SYMBOL: L I K E; // SQL-2003-R +LIMIT_SYMBOL: L I M I T; +LINEAR_SYMBOL: L I N E A R; +LINES_SYMBOL: L I N E S; +LINESTRING_SYMBOL: L I N E S T R I N G; // MYSQL +LIST_SYMBOL: L I S T; +LOAD_SYMBOL: L O A D; +LOCALTIME_SYMBOL: L O C A L T I M E -> type(NOW_SYMBOL); // Synonym +LOCALTIMESTAMP_SYMBOL: L O C A L T I M E S T A M P -> type(NOW_SYMBOL); // Synonym +LOCAL_SYMBOL: L O C A L; // SQL-2003-R +LOCATOR_SYMBOL: L O C A T O R; // SQL-2003-N +LOCKS_SYMBOL: L O C K S; +LOCK_SYMBOL: L O C K; +LOGFILE_SYMBOL: L O G F I L E; +LOGS_SYMBOL: L O G S; +LONGBLOB_SYMBOL: L O N G B L O B; // MYSQL +LONGTEXT_SYMBOL: L O N G T E X T; // MYSQL +LONG_NUM_SYMBOL: L O N G '_' N U M; +LONG_SYMBOL: L O N G; +LOOP_SYMBOL: L O O P; +LOW_PRIORITY_SYMBOL: L O W '_' P R I O R I T Y; +MASTER_AUTO_POSITION_SYMBOL: M A S T E R '_' A U T O '_' P O S I T I O N {serverVersion >= 50605}?; +MASTER_BIND_SYMBOL: M A S T E R '_' B I N D {serverVersion >= 50602}?; +MASTER_CONNECT_RETRY_SYMBOL: M A S T E R '_' C O N N E C T '_' R E T R Y; +MASTER_DELAY_SYMBOL: M A S T E R '_' D E L A Y; +MASTER_HOST_SYMBOL: M A S T E R '_' H O S T; +MASTER_LOG_FILE_SYMBOL: M A S T E R '_' L O G '_' F I L E; +MASTER_LOG_POS_SYMBOL: M A S T E R '_' L O G '_' P O S; +MASTER_PASSWORD_SYMBOL: M A S T E R '_' P A S S W O R D; +MASTER_PORT_SYMBOL: M A S T E R '_' P O R T; +MASTER_RETRY_COUNT_SYMBOL: M A S T E R '_' R E T R Y '_' C O U N T {serverVersion >= 50601}?; +MASTER_SERVER_ID_SYMBOL: M A S T E R '_' S E R V E R '_' I D; +MASTER_SSL_CAPATH_SYMBOL: M A S T E R '_' S S L '_' C A P A T H; +MASTER_SSL_CA_SYMBOL: M A S T E R '_' S S L '_' C A; +MASTER_SSL_CERT_SYMBOL: M A S T E R '_' S S L '_' C E R T; +MASTER_SSL_CIPHER_SYMBOL: M A S T E R '_' S S L '_' C I P H E R; +MASTER_SSL_CRL_SYMBOL: M A S T E R '_' S S L '_' C R L {serverVersion >= 50603}?; +MASTER_SSL_CRLPATH_SYMBOL: M A S T E R '_' S S L '_' C R L P A T H {serverVersion >= 50603}?; +MASTER_SSL_KEY_SYMBOL: M A S T E R '_' S S L '_' K E Y; +MASTER_SSL_SYMBOL: M A S T E R '_' S S L; +MASTER_SSL_VERIFY_SERVER_CERT_SYMBOL: + M A S T E R '_' S S L '_' V E R I F Y '_' S E R V E R '_' C E R T? +; +MASTER_SYMBOL: M A S T E R; +MASTER_TLS_VERSION_SYMBOL: M A S T E R '_' T L S '_' V E R S I O N {serverVersion >= 50713}?; +MASTER_USER_SYMBOL: M A S T E R '_' U S E R; +MASTER_HEARTBEAT_PERIOD_SYMBOL: M A S T E R '_' H E A R T B E A T '_' P E R I O D?; +MATCH_SYMBOL: M A T C H; // SQL-2003-R +MAX_CONNECTIONS_PER_HOUR_SYMBOL: M A X '_' C O N N E C T I O N S '_' P E R '_' H O U R; +MAX_QUERIES_PER_HOUR_SYMBOL: M A X '_' Q U E R I E S '_' P E R '_' H O U R; +MAX_ROWS_SYMBOL: M A X '_' R O W S; +MAX_SIZE_SYMBOL: M A X '_' S I Z E; +MAX_STATEMENT_TIME_SYMBOL: + M A X '_' S T A T E M E N T '_' T I M E {50704 < serverVersion && serverVersion < 50708}? +; +MAX_SYMBOL: M A X { setType(determineFunction(MAX_SYMBOL)); }; // SQL-2003-N +MAX_UPDATES_PER_HOUR_SYMBOL: M A X '_' U P D A T E S '_' P E R '_' H O U R; +MAX_USER_CONNECTIONS_SYMBOL: M A X '_' U S E R '_' C O N N E C T I O N S; +MAXVALUE_SYMBOL: M A X V A L U E; // SQL-2003-N +MEDIUMBLOB_SYMBOL: M E D I U M B L O B; // MYSQL +MEDIUMINT_SYMBOL: M E D I U M I N T; // MYSQL +MEDIUMTEXT_SYMBOL: M E D I U M T E X T; // MYSQL +MEDIUM_SYMBOL: M E D I U M; +MEMORY_SYMBOL: M E M O R Y; +MERGE_SYMBOL: M E R G E; // SQL-2003-R +MESSAGE_TEXT_SYMBOL: M E S S A G E '_' T E X T; // SQL-2003-N +MICROSECOND_SYMBOL: M I C R O S E C O N D; // MYSQL-FUNC +MID_SYMBOL: M I D { setType(determineFunction(SUBSTRING_SYMBOL)); }; // Synonym +MIDDLEINT_SYMBOL: M I D D L E I N T -> type(MEDIUMINT_SYMBOL); // Synonym (for Powerbuilder) +MIGRATE_SYMBOL: M I G R A T E; +MINUTE_MICROSECOND_SYMBOL: M I N U T E '_' M I C R O S E C O N D; +MINUTE_SECOND_SYMBOL: M I N U T E '_' S E C O N D; +MINUTE_SYMBOL: M I N U T E; // SQL-2003-R +MIN_ROWS_SYMBOL: M I N '_' R O W S; +MIN_SYMBOL: M I N { setType(determineFunction(MIN_SYMBOL)); }; // SQL-2003-N +MODE_SYMBOL: M O D E; +MODIFIES_SYMBOL: M O D I F I E S; // SQL-2003-R +MODIFY_SYMBOL: M O D I F Y; +MOD_SYMBOL: M O D; // SQL-2003-N +MONTH_SYMBOL: M O N T H; // SQL-2003-R +MULTILINESTRING_SYMBOL: M U L T I L I N E S T R I N G; // MYSQL +MULTIPOINT_SYMBOL: M U L T I P O I N T; // MYSQL +MULTIPOLYGON_SYMBOL: M U L T I P O L Y G O N; // MYSQL +MUTEX_SYMBOL: M U T E X; +MYSQL_ERRNO_SYMBOL: M Y S Q L '_' E R R N O; +NAMES_SYMBOL: N A M E S; // SQL-2003-N +NAME_SYMBOL: N A M E; // SQL-2003-N +NATIONAL_SYMBOL: N A T I O N A L; // SQL-2003-R +NATURAL_SYMBOL: N A T U R A L; // SQL-2003-R +NCHAR_STRING_SYMBOL: N C H A R '_' S T R I N G; +NCHAR_SYMBOL: N C H A R; // SQL-2003-R +NDB_SYMBOL: N D B -> type(NDBCLUSTER_SYMBOL); //Synonym +NDBCLUSTER_SYMBOL: N D B C L U S T E R; +NEG_SYMBOL: N E G; +NEVER_SYMBOL: N E V E R {serverVersion >= 50704}?; +NEW_SYMBOL: N E W; // SQL-2003-R +NEXT_SYMBOL: N E X T; // SQL-2003-N +NODEGROUP_SYMBOL: N O D E G R O U P; +NONE_SYMBOL: N O N E; // SQL-2003-R +NONBLOCKING_SYMBOL: N O N B L O C K I N G {50700 < serverVersion && serverVersion < 50706}?; +NOT_SYMBOL: + N O T { setType(isSqlModeActive(HighNotPrecedence) ? NOT2_SYMBOL: NOT_SYMBOL); } +; // SQL-2003-R +NOW_SYMBOL: N O W { setType(determineFunction(NOW_SYMBOL)); }; +NO_SYMBOL: N O; // SQL-2003-R +NO_WAIT_SYMBOL: N O '_' W A I T; +NO_WRITE_TO_BINLOG_SYMBOL: N O '_' W R I T E '_' T O '_' B I N L O G; +NULL_SYMBOL: N U L L; // SQL-2003-R +NUMBER_SYMBOL: N U M B E R {serverVersion >= 50606}?; +NUMERIC_SYMBOL: N U M E R I C; // SQL-2003-R +NVARCHAR_SYMBOL: N V A R C H A R; +OFFLINE_SYMBOL: O F F L I N E; +OFFSET_SYMBOL: O F F S E T; +OLD_PASSWORD_SYMBOL: O L D '_' P A S S W O R D {serverVersion < 50706}?; +ON_SYMBOL: O N; // SQL-2003-R +ONE_SYMBOL: O N E; +ONLINE_SYMBOL: O N L I N E; +ONLY_SYMBOL: O N L Y {serverVersion >= 50605}?; +OPEN_SYMBOL: O P E N; // SQL-2003-R +OPTIMIZE_SYMBOL: O P T I M I Z E; +OPTIMIZER_COSTS_SYMBOL: O P T I M I Z E R '_' C O S T S {serverVersion >= 50706}?; +OPTIONS_SYMBOL: O P T I O N S; +OPTION_SYMBOL: O P T I O N; // SQL-2003-N +OPTIONALLY_SYMBOL: O P T I O N A L L Y; +ORDER_SYMBOL: O R D E R; // SQL-2003-R +OR_SYMBOL: O R; // SQL-2003-R +OUTER_SYMBOL: O U T E R; +OUTFILE_SYMBOL: O U T F I L E; +OUT_SYMBOL: O U T; // SQL-2003-R +OWNER_SYMBOL: O W N E R; +PACK_KEYS_SYMBOL: P A C K '_' K E Y S; +PAGE_SYMBOL: P A G E; +PARSER_SYMBOL: P A R S E R; +PARTIAL_SYMBOL: P A R T I A L; // SQL-2003-N +PARTITIONING_SYMBOL: P A R T I T I O N I N G; +PARTITIONS_SYMBOL: P A R T I T I O N S; +PARTITION_SYMBOL: P A R T I T I O N; // SQL-2003-R +PASSWORD_SYMBOL: P A S S W O R D; +PHASE_SYMBOL: P H A S E; +PLUGINS_SYMBOL: P L U G I N S; +PLUGIN_DIR_SYMBOL: P L U G I N '_' D I R {serverVersion >= 50604}?; // Internal +PLUGIN_SYMBOL: P L U G I N; +POINT_SYMBOL: P O I N T; +POLYGON_SYMBOL: P O L Y G O N; // MYSQL +PORT_SYMBOL: P O R T; +POSITION_SYMBOL: P O S I T I O N { setType(determineFunction(POSITION_SYMBOL)); }; // SQL-2003-N +PRECEDES_SYMBOL: P R E C E D E S {serverVersion >= 50700}?; +PRECISION_SYMBOL: P R E C I S I O N; // SQL-2003-R +PREPARE_SYMBOL: P R E P A R E; // SQL-2003-R +PRESERVE_SYMBOL: P R E S E R V E; +PREV_SYMBOL: P R E V; +PRIMARY_SYMBOL: P R I M A R Y; // SQL-2003-R +PRIVILEGES_SYMBOL: P R I V I L E G E S; // SQL-2003-N +PROCEDURE_SYMBOL: P R O C E D U R E; // SQL-2003-R +PROCESS_SYMBOL: P R O C E S S; +PROCESSLIST_SYMBOL: P R O C E S S L I S T; +PROFILE_SYMBOL: P R O F I L E; +PROFILES_SYMBOL: P R O F I L E S; +PROXY_SYMBOL: P R O X Y; +PURGE_SYMBOL: P U R G E; +QUARTER_SYMBOL: Q U A R T E R; +QUERY_SYMBOL: Q U E R Y; +QUICK_SYMBOL: Q U I C K; +RANGE_SYMBOL: R A N G E; // SQL-2003-R +READS_SYMBOL: R E A D S; // SQL-2003-R +READ_ONLY_SYMBOL: R E A D '_' O N L Y; +READ_SYMBOL: R E A D; // SQL-2003-N +READ_WRITE_SYMBOL: R E A D '_' W R I T E; +REAL_SYMBOL: R E A L; // SQL-2003-R +REBUILD_SYMBOL: R E B U I L D; +RECOVER_SYMBOL: R E C O V E R; +REDOFILE_SYMBOL: R E D O F I L E {serverVersion < 80000}?; +REDO_BUFFER_SIZE_SYMBOL: R E D O '_' B U F F E R '_' S I Z E; +REDUNDANT_SYMBOL: R E D U N D A N T; +REFERENCES_SYMBOL: R E F E R E N C E S; // SQL-2003-R +REGEXP_SYMBOL: R E G E X P; +RELAY_SYMBOL: R E L A Y; +RELAYLOG_SYMBOL: R E L A Y L O G; +RELAY_LOG_FILE_SYMBOL: R E L A Y '_' L O G '_' F I L E; +RELAY_LOG_POS_SYMBOL: R E L A Y '_' L O G '_' P O S; +RELAY_THREAD_SYMBOL: R E L A Y '_' T H R E A D; +RELEASE_SYMBOL: R E L E A S E; // SQL-2003-R +RELOAD_SYMBOL: R E L O A D; +REMOVE_SYMBOL: R E M O V E; +RENAME_SYMBOL: R E N A M E; +REORGANIZE_SYMBOL: R E O R G A N I Z E; +REPAIR_SYMBOL: R E P A I R; +REPEATABLE_SYMBOL: R E P E A T A B L E; // SQL-2003-N +REPEAT_SYMBOL: R E P E A T; // MYSQL-FUNC +REPLACE_SYMBOL: R E P L A C E; // MYSQL-FUNC +REPLICATION_SYMBOL: R E P L I C A T I O N; +REPLICATE_DO_DB_SYMBOL: R E P L I C A T E '_' D O '_' D B {serverVersion >= 50700}?; +REPLICATE_IGNORE_DB_SYMBOL: R E P L I C A T E '_' I G N O R E '_' D B {serverVersion >= 50700}?; +REPLICATE_DO_TABLE_SYMBOL: R E P L I C A T E '_' D O '_' T A B L E {serverVersion >= 50700}?; +REPLICATE_IGNORE_TABLE_SYMBOL: + R E P L I C A T E '_' I G N O R E '_' T A B L E {serverVersion >= 50700}? +; +REPLICATE_WILD_DO_TABLE_SYMBOL: + R E P L I C A T E '_' W I L D '_' D O '_' T A B L E {serverVersion >= 50700}? +; +REPLICATE_WILD_IGNORE_TABLE_SYMBOL: + R E P L I C A T E '_' W I L D '_' I G N O R E '_' T A B L E {serverVersion >= 50700}? +; +REPLICATE_REWRITE_DB_SYMBOL: R E P L I C A T E '_' R E W R I T E '_' D B {serverVersion >= 50700}?; +REQUIRE_SYMBOL: R E Q U I R E; +RESET_SYMBOL: R E S E T; +RESIGNAL_SYMBOL: R E S I G N A L; // SQL-2003-R +RESTORE_SYMBOL: R E S T O R E; +RESTRICT_SYMBOL: R E S T R I C T; +RESUME_SYMBOL: R E S U M E; +RETURNED_SQLSTATE_SYMBOL: R E T U R N E D '_' S Q L S T A T E; +RETURNS_SYMBOL: R E T U R N S; // SQL-2003-R +RETURN_SYMBOL: R E T U R N?; // SQL-2003-R +REVERSE_SYMBOL: R E V E R S E; +REVOKE_SYMBOL: R E V O K E; // SQL-2003-R +RIGHT_SYMBOL: R I G H T; // SQL-2003-R +RLIKE_SYMBOL: R L I K E -> type(REGEXP_SYMBOL); // Synonym (like in mSQL2) +ROLLBACK_SYMBOL: R O L L B A C K; // SQL-2003-R +ROLLUP_SYMBOL: R O L L U P; // SQL-2003-R +ROTATE_SYMBOL: R O T A T E {serverVersion >= 50713}?; +ROUTINE_SYMBOL: R O U T I N E; // SQL-2003-N +ROWS_SYMBOL: R O W S; // SQL-2003-R +ROW_COUNT_SYMBOL: R O W '_' C O U N T; +ROW_FORMAT_SYMBOL: R O W '_' F O R M A T; +ROW_SYMBOL: R O W; // SQL-2003-R +RTREE_SYMBOL: R T R E E; +SAVEPOINT_SYMBOL: S A V E P O I N T; // SQL-2003-R +SCHEDULE_SYMBOL: S C H E D U L E; +SCHEMA_SYMBOL: S C H E M A -> type(DATABASE_SYMBOL); // Synonym +SCHEMA_NAME_SYMBOL: S C H E M A '_' N A M E; // SQL-2003-N +SCHEMAS_SYMBOL: S C H E M A S -> type(DATABASES_SYMBOL); // Synonym +SECOND_MICROSECOND_SYMBOL: S E C O N D '_' M I C R O S E C O N D; +SECOND_SYMBOL: S E C O N D; // SQL-2003-R +SECURITY_SYMBOL: S E C U R I T Y; // SQL-2003-N +SELECT_SYMBOL: S E L E C T; // SQL-2003-R +SENSITIVE_SYMBOL: S E N S I T I V E; // FUTURE-USE +SEPARATOR_SYMBOL: S E P A R A T O R; +SERIALIZABLE_SYMBOL: S E R I A L I Z A B L E; // SQL-2003-N +SERIAL_SYMBOL: S E R I A L; +SESSION_SYMBOL: S E S S I O N; // SQL-2003-N +SERVER_SYMBOL: S E R V E R; +SERVER_OPTIONS_SYMBOL: S E R V E R '_' O P T I O N S; +SESSION_USER_SYMBOL: + S E S S I O N '_' U S E R { setType(determineFunction(USER_SYMBOL)); } +; // Synonym +SET_SYMBOL: S E T; // SQL-2003-R +SET_VAR_SYMBOL: S E T '_' V A R; +SHARE_SYMBOL: S H A R E; +SHOW_SYMBOL: S H O W; +SHUTDOWN_SYMBOL: S H U T D O W N; +SIGNAL_SYMBOL: S I G N A L; // SQL-2003-R +SIGNED_SYMBOL: S I G N E D; +SIMPLE_SYMBOL: S I M P L E; // SQL-2003-N +SLAVE_SYMBOL: S L A V E; +SLOW_SYMBOL: S L O W; +SMALLINT_SYMBOL: S M A L L I N T; // SQL-2003-R +SNAPSHOT_SYMBOL: S N A P S H O T; +SOME_SYMBOL: S O M E -> type(ANY_SYMBOL); // Synonym +SOCKET_SYMBOL: S O C K E T; +SONAME_SYMBOL: S O N A M E; +SOUNDS_SYMBOL: S O U N D S; +SOURCE_SYMBOL: S O U R C E; +SPATIAL_SYMBOL: S P A T I A L; +SPECIFIC_SYMBOL: S P E C I F I C; // SQL-2003-R +SQLEXCEPTION_SYMBOL: S Q L E X C E P T I O N; // SQL-2003-R +SQLSTATE_SYMBOL: S Q L S T A T E; // SQL-2003-R +SQLWARNING_SYMBOL: S Q L W A R N I N G; // SQL-2003-R +SQL_AFTER_GTIDS_SYMBOL: S Q L '_' A F T E R '_' G T I D S; // MYSQL +SQL_AFTER_MTS_GAPS_SYMBOL: + S Q L '_' A F T E R '_' M T S '_' G A P S {serverVersion >= 50606}? +; // MYSQL +SQL_BEFORE_GTIDS_SYMBOL: S Q L '_' B E F O R E '_' G T I D S; // MYSQL +SQL_BIG_RESULT_SYMBOL: S Q L '_' B I G '_' R E S U L T; +SQL_BUFFER_RESULT_SYMBOL: S Q L '_' B U F F E R '_' R E S U L T; +SQL_CACHE_SYMBOL: S Q L '_' C A C H E {serverVersion < 80000}?; +SQL_CALC_FOUND_ROWS_SYMBOL: S Q L '_' C A L C '_' F O U N D '_' R O W S; +SQL_NO_CACHE_SYMBOL: S Q L '_' N O '_' C A C H E; +SQL_SMALL_RESULT_SYMBOL: S Q L '_' S M A L L '_' R E S U L T; +SQL_SYMBOL: S Q L; // SQL-2003-R +SQL_THREAD_SYMBOL: S Q L '_' T H R E A D; +SSL_SYMBOL: S S L; +STACKED_SYMBOL: S T A C K E D {serverVersion >= 50700}?; +STARTING_SYMBOL: S T A R T I N G; +STARTS_SYMBOL: S T A R T S; +START_SYMBOL: S T A R T; // SQL-2003-R +STATS_AUTO_RECALC_SYMBOL: S T A T S '_' A U T O '_' R E C A L C; +STATS_PERSISTENT_SYMBOL: S T A T S '_' P E R S I S T E N T; +STATS_SAMPLE_PAGES_SYMBOL: S T A T S '_' S A M P L E '_' P A G E S; +STATUS_SYMBOL: S T A T U S; +STDDEV_SAMP_SYMBOL: + S T D D E V '_' S A M P { setType(determineFunction(STDDEV_SAMP_SYMBOL)); } +; // SQL-2003-N +STDDEV_SYMBOL: S T D D E V { setType(determineFunction(STD_SYMBOL)); }; // Synonym +STDDEV_POP_SYMBOL: S T D D E V '_' P O P { setType(determineFunction(STD_SYMBOL)); }; // Synonym +STD_SYMBOL: S T D { setType(determineFunction(STD_SYMBOL)); }; +STOP_SYMBOL: S T O P; +STORAGE_SYMBOL: S T O R A G E; +STORED_SYMBOL: S T O R E D {serverVersion >= 50707}?; +STRAIGHT_JOIN_SYMBOL: S T R A I G H T '_' J O I N; +STRING_SYMBOL: S T R I N G; +SUBCLASS_ORIGIN_SYMBOL: S U B C L A S S '_' O R I G I N; // SQL-2003-N +SUBDATE_SYMBOL: S U B D A T E { setType(determineFunction(SUBDATE_SYMBOL)); }; +SUBJECT_SYMBOL: S U B J E C T; +SUBPARTITIONS_SYMBOL: S U B P A R T I T I O N S; +SUBPARTITION_SYMBOL: S U B P A R T I T I O N; +SUBSTR_SYMBOL: S U B S T R { setType(determineFunction(SUBSTRING_SYMBOL)); }; // Synonym +SUBSTRING_SYMBOL: S U B S T R I N G { setType(determineFunction(SUBSTRING_SYMBOL)); }; // SQL-2003-N +SUM_SYMBOL: S U M { setType(determineFunction(SUM_SYMBOL)); }; // SQL-2003-N +SUPER_SYMBOL: S U P E R; +SUSPEND_SYMBOL: S U S P E N D; +SWAPS_SYMBOL: S W A P S; +SWITCHES_SYMBOL: S W I T C H E S; +SYSDATE_SYMBOL: S Y S D A T E { setType(determineFunction(SYSDATE_SYMBOL)); }; +SYSTEM_USER_SYMBOL: S Y S T E M '_' U S E R { setType(determineFunction(USER_SYMBOL)); }; +TABLES_SYMBOL: T A B L E S; +TABLESPACE_SYMBOL: T A B L E S P A C E; +TABLE_REF_PRIORITY_SYMBOL: T A B L E '_' R E F '_' P R I O R I T Y {serverVersion < 80000}?; +TABLE_SYMBOL: T A B L E; // SQL-2003-R +TABLE_CHECKSUM_SYMBOL: T A B L E '_' C H E C K S U M; +TABLE_NAME_SYMBOL: T A B L E '_' N A M E; // SQL-2003-N +TEMPORARY_SYMBOL: T E M P O R A R Y; // SQL-2003-N +TEMPTABLE_SYMBOL: T E M P T A B L E; +TERMINATED_SYMBOL: T E R M I N A T E D; +TEXT_SYMBOL: T E X T; +THAN_SYMBOL: T H A N; +THEN_SYMBOL: T H E N; // SQL-2003-R +TIMESTAMP_SYMBOL: T I M E S T A M P; // SQL-2003-R +TIMESTAMP_ADD_SYMBOL: T I M E S T A M P '_' A D D; +TIMESTAMP_DIFF_SYMBOL: T I M E S T A M P '_' D I F F; +TIME_SYMBOL: T I M E; // SQL-2003-R +TINYBLOB_SYMBOL: T I N Y B L O B; // MYSQL +TINYINT_SYMBOL: T I N Y I N T; // MYSQL +TINYTEXT_SYMBOL: T I N Y T E X T; // MYSQL +TO_SYMBOL: T O; // SQL-2003-R +TRAILING_SYMBOL: T R A I L I N G; // SQL-2003-R +TRANSACTION_SYMBOL: T R A N S A C T I O N; +TRIGGERS_SYMBOL: T R I G G E R S; +TRIGGER_SYMBOL: T R I G G E R; // SQL-2003-R +TRIM_SYMBOL: T R I M { setType(determineFunction(TRIM_SYMBOL)); }; // SQL-2003-N +TRUE_SYMBOL: T R U E; // SQL-2003-R +TRUNCATE_SYMBOL: T R U N C A T E; +TYPES_SYMBOL: T Y P E S; +TYPE_SYMBOL: T Y P E; // SQL-2003-N +UDF_RETURNS_SYMBOL: U D F '_' R E T U R N S; +UNCOMMITTED_SYMBOL: U N C O M M I T T E D; // SQL-2003-N +UNDEFINED_SYMBOL: U N D E F I N E D; +UNDOFILE_SYMBOL: U N D O F I L E; +UNDO_BUFFER_SIZE_SYMBOL: U N D O '_' B U F F E R '_' S I Z E; +UNDO_SYMBOL: U N D O; // FUTURE-USE +UNICODE_SYMBOL: U N I C O D E; +UNINSTALL_SYMBOL: U N I N S T A L L; +UNION_SYMBOL: U N I O N; // SQL-2003-R +UNIQUE_SYMBOL: U N I Q U E; +UNKNOWN_SYMBOL: U N K N O W N; // SQL-2003-R +UNLOCK_SYMBOL: U N L O C K; +UNSIGNED_SYMBOL: U N S I G N E D; // MYSQL +UNTIL_SYMBOL: U N T I L; +UPDATE_SYMBOL: U P D A T E; // SQL-2003-R +UPGRADE_SYMBOL: U P G R A D E; +USAGE_SYMBOL: U S A G E; // SQL-2003-N +USER_RESOURCES_SYMBOL: + U S E R '_' R E S O U R C E S +; // Represented only as RESOURCES in server grammar. +USER_SYMBOL: U S E R; // SQL-2003-R +USE_FRM_SYMBOL: U S E '_' F R M; +USE_SYMBOL: U S E; +USING_SYMBOL: U S I N G; // SQL-2003-R +UTC_DATE_SYMBOL: U T C '_' D A T E; +UTC_TIMESTAMP_SYMBOL: U T C '_' T I M E S T A M P; +UTC_TIME_SYMBOL: U T C '_' T I M E; +VALIDATION_SYMBOL: V A L I D A T I O N {serverVersion >= 50706}?; +VALUES_SYMBOL: V A L U E S; // SQL-2003-R +VALUE_SYMBOL: V A L U E; // SQL-2003-R +VARBINARY_SYMBOL: V A R B I N A R Y; // SQL-2008-R +VARCHAR_SYMBOL: V A R C H A R; // SQL-2003-R +VARCHARACTER_SYMBOL: V A R C H A R A C T E R -> type(VARCHAR_SYMBOL); // Synonym +VARIABLES_SYMBOL: V A R I A B L E S; +VARIANCE_SYMBOL: V A R I A N C E { setType(determineFunction(VARIANCE_SYMBOL)); }; +VARYING_SYMBOL: V A R Y I N G; // SQL-2003-R +VAR_POP_SYMBOL: V A R '_' P O P { setType(determineFunction(VARIANCE_SYMBOL)); }; // Synonym +VAR_SAMP_SYMBOL: V A R '_' S A M P { setType(determineFunction(VAR_SAMP_SYMBOL)); }; +VIEW_SYMBOL: V I E W; // SQL-2003-N +VIRTUAL_SYMBOL: V I R T U A L {serverVersion >= 50707}?; +WAIT_SYMBOL: W A I T; +WARNINGS_SYMBOL: W A R N I N G S; +WEEK_SYMBOL: W E E K; +WEIGHT_STRING_SYMBOL: W E I G H T '_' S T R I N G; +WHEN_SYMBOL: W H E N; // SQL-2003-R +WHERE_SYMBOL: W H E R E; // SQL-2003-R +WHILE_SYMBOL: W H I L E; +WITH_SYMBOL: W I T H; // SQL-2003-R +WITHOUT_SYMBOL: W I T H O U T; // SQL-2003-R +WORK_SYMBOL: W O R K; // SQL-2003-N +WRAPPER_SYMBOL: W R A P P E R; +WRITE_SYMBOL: W R I T E; // SQL-2003-N +X509_SYMBOL: X '509'; +XA_SYMBOL: X A; +XID_SYMBOL: X I D {serverVersion >= 50704}?; +XML_SYMBOL: X M L; +XOR_SYMBOL: X O R; +YEAR_MONTH_SYMBOL: Y E A R '_' M O N T H; +YEAR_SYMBOL: Y E A R; // SQL-2003-R +ZEROFILL_SYMBOL: Z E R O F I L L; // MYSQL + +/* + Tokens from MySQL 8.0 +*/ +PERSIST_SYMBOL: P E R S I S T {serverVersion >= 80000}?; +ROLE_SYMBOL: R O L E {serverVersion >= 80000}?; // SQL-1999-R +ADMIN_SYMBOL: A D M I N {serverVersion >= 80000}?; // SQL-1999-R +INVISIBLE_SYMBOL: I N V I S I B L E {serverVersion >= 80000}?; +VISIBLE_SYMBOL: V I S I B L E {serverVersion >= 80000}?; +EXCEPT_SYMBOL: E X C E P T {serverVersion >= 80000}?; // SQL-1999-R +COMPONENT_SYMBOL: C O M P O N E N T {serverVersion >= 80000}?; // MYSQL +RECURSIVE_SYMBOL: R E C U R S I V E {serverVersion >= 80000}?; // SQL-1999-R +JSON_OBJECTAGG_SYMBOL: J S O N '_' O B J E C T A G G {serverVersion >= 80000}?; // SQL-2015-R +JSON_ARRAYAGG_SYMBOL: J S O N '_' A R R A Y A G G {serverVersion >= 80000}?; // SQL-2015-R +OF_SYMBOL: O F {serverVersion >= 80000}?; // SQL-1999-R +SKIP_SYMBOL: S K I P {serverVersion >= 80000}?; // MYSQL +LOCKED_SYMBOL: L O C K E D {serverVersion >= 80000}?; // MYSQL +NOWAIT_SYMBOL: N O W A I T {serverVersion >= 80000}?; // MYSQL +GROUPING_SYMBOL: G R O U P I N G {serverVersion >= 80000}?; // SQL-2011-R +PERSIST_ONLY_SYMBOL: P E R S I S T '_' O N L Y {serverVersion >= 80000}?; // MYSQL +HISTOGRAM_SYMBOL: H I S T O G R A M {serverVersion >= 80000}?; // MYSQL +BUCKETS_SYMBOL: B U C K E T S {serverVersion >= 80000}?; // MYSQL +REMOTE_SYMBOL: R E M O T E {serverVersion >= 80003 && serverVersion < 80014}?; // MYSQL +CLONE_SYMBOL: C L O N E {serverVersion >= 80000}?; // MYSQL +CUME_DIST_SYMBOL: C U M E '_' D I S T {serverVersion >= 80000}?; // SQL-2003-R +DENSE_RANK_SYMBOL: D E N S E '_' R A N K {serverVersion >= 80000}?; // SQL-2003-R +EXCLUDE_SYMBOL: E X C L U D E {serverVersion >= 80000}?; // SQL-2003-N +FIRST_VALUE_SYMBOL: F I R S T '_' V A L U E {serverVersion >= 80000}?; // SQL-2011-R +FOLLOWING_SYMBOL: F O L L O W I N G {serverVersion >= 80000}?; // SQL-2003-N +GROUPS_SYMBOL: G R O U P S {serverVersion >= 80000}?; // SQL-2011-R +LAG_SYMBOL: L A G {serverVersion >= 80000}?; // SQL-2011-R +LAST_VALUE_SYMBOL: L A S T '_' V A L U E {serverVersion >= 80000}?; // SQL-2011-R +LEAD_SYMBOL: L E A D {serverVersion >= 80000}?; // SQL-2011-R +NTH_VALUE_SYMBOL: N T H '_' V A L U E {serverVersion >= 80000}?; // SQL-2011-R +NTILE_SYMBOL: N T I L E {serverVersion >= 80000}?; // SQL-2011-R +NULLS_SYMBOL: N U L L S {serverVersion >= 80000}?; // SQL-2003-N +OTHERS_SYMBOL: O T H E R S {serverVersion >= 80000}?; // SQL-2003-N +OVER_SYMBOL: O V E R {serverVersion >= 80000}?; // SQL-2003-R +PERCENT_RANK_SYMBOL: P E R C E N T '_' R A N K {serverVersion >= 80000}?; // SQL-2003-R +PRECEDING_SYMBOL: P R E C E D I N G {serverVersion >= 80000}?; // SQL-2003-N +RANK_SYMBOL: R A N K {serverVersion >= 80000}?; // SQL-2003-R +RESPECT_SYMBOL: R E S P E C T {serverVersion >= 80000}?; // SQL_2011-N +ROW_NUMBER_SYMBOL: R O W '_' N U M B E R {serverVersion >= 80000}?; // SQL-2003-R +TIES_SYMBOL: T I E S {serverVersion >= 80000}?; // SQL-2003-N +UNBOUNDED_SYMBOL: U N B O U N D E D {serverVersion >= 80000}?; // SQL-2003-N +WINDOW_SYMBOL: W I N D O W {serverVersion >= 80000}?; // SQL-2003-R +EMPTY_SYMBOL: E M P T Y {serverVersion >= 80000}?; // SQL-2016-R +JSON_TABLE_SYMBOL: J S O N '_' T A B L E {serverVersion >= 80000}?; // SQL-2016-R +NESTED_SYMBOL: N E S T E D {serverVersion >= 80000}?; // SQL-2016-N +ORDINALITY_SYMBOL: O R D I N A L I T Y {serverVersion >= 80000}?; // SQL-2003-N +PATH_SYMBOL: P A T H {serverVersion >= 80000}?; // SQL-2003-N +HISTORY_SYMBOL: H I S T O R Y {serverVersion >= 80000}?; // MYSQL +REUSE_SYMBOL: R E U S E {serverVersion >= 80000}?; // MYSQL +SRID_SYMBOL: S R I D {serverVersion >= 80000}?; // MYSQL +THREAD_PRIORITY_SYMBOL: T H R E A D '_' P R I O R I T Y {serverVersion >= 80000}?; // MYSQL +RESOURCE_SYMBOL: R E S O U R C E {serverVersion >= 80000}?; // MYSQL +SYSTEM_SYMBOL: S Y S T E M {serverVersion >= 80000}?; // SQL-2003-R +VCPU_SYMBOL: V C P U {serverVersion >= 80000}?; // MYSQL +MASTER_PUBLIC_KEY_PATH_SYMBOL: + M A S T E R '_' P U B L I C '_' K E Y '_' P A T H {serverVersion >= 80000}? +; // MYSQL +GET_MASTER_PUBLIC_KEY_SYMBOL: + G E T '_' M A S T E R '_' P U B L I C '_' K E Y '_' S Y M {serverVersion >= 80000}? +; // MYSQL +RESTART_SYMBOL: R E S T A R T {serverVersion >= 80011}?; // SQL-2003-N +DEFINITION_SYMBOL: D E F I N I T I O N {serverVersion >= 80011}?; // MYSQL +DESCRIPTION_SYMBOL: D E S C R I P T I O N {serverVersion >= 80011}?; // MYSQL +ORGANIZATION_SYMBOL: O R G A N I Z A T I O N {serverVersion >= 80011}?; // MYSQL +REFERENCE_SYMBOL: R E F E R E N C E {serverVersion >= 80011}?; // MYSQL + +OPTIONAL_SYMBOL: O P T I O N A L {serverVersion >= 80013}?; // MYSQL +SECONDARY_SYMBOL: S E C O N D A R Y {serverVersion >= 80013}?; // MYSQL +SECONDARY_ENGINE_SYMBOL: S E C O N D A R Y '_' E N G I N E {serverVersion >= 80013}?; // MYSQL +SECONDARY_LOAD_SYMBOL: S E C O N D A R Y '_' L O A D {serverVersion >= 80013}?; // MYSQL +SECONDARY_UNLOAD_SYMBOL: S E C O N D A R Y '_' U N L O A D {serverVersion >= 80013}?; // MYSQL + +ACTIVE_SYMBOL: A C T I V E {serverVersion >= 80014}?; // MYSQL +INACTIVE_SYMBOL: I N A C T I V E {serverVersion >= 80014}?; // MYSQL +LATERAL_SYMBOL: L A T E R A L {serverVersion >= 80014}?; // SQL-2003-R +RETAIN_SYMBOL: R E T A I N {serverVersion >= 80014}?; // MYSQL +OLD_SYMBOL: O L D {serverVersion >= 80014}?; // SQL-2003-R + +NETWORK_NAMESPACE_SYMBOL: N E T W O R K '_' N A M E S P A C E {serverVersion >= 80017}?; // MYSQL +ENFORCED_SYMBOL: E N F O R C E D {serverVersion >= 80017}?; // SQL-2003-N +ARRAY_SYMBOL: A R R A Y {serverVersion >= 80017}?; // SQL-2003-R +OJ_SYMBOL: O J {serverVersion >= 80017}?; // ODBC +MEMBER_SYMBOL: M E M B E R {serverVersion >= 80017}?; // SQL-2003-R + +RANDOM_SYMBOL: R A N D O M {serverVersion >= 80018}?; // MYSQL +MASTER_COMPRESSION_ALGORITHM_SYMBOL: + M A S T E R '_' C O M P R E S S I O N '_' A L G O R I T H M {serverVersion >= 80018}? +; // MYSQL +MASTER_ZSTD_COMPRESSION_LEVEL_SYMBOL: + M A S T E R '_' Z S T D '_' C O M P R E S S I O N '_' L E V E L {serverVersion >= 80018}? +; // MYSQL +PRIVILEGE_CHECKS_USER_SYMBOL: + P R I V I L E G E '_' C H E C K S '_' U S E R {serverVersion >= 80018}? +; // MYSQL +MASTER_TLS_CIPHERSUITES_SYMBOL: + M A S T E R '_' T L S '_' C I P H E R S U I T E S {serverVersion >= 80018}? +; // MYSQL + +REQUIRE_ROW_FORMAT_SYMBOL: + R E Q U I R E '_' R O W '_' F O R M A T {serverVersion >= 80019}? +; // MYSQL +PASSWORD_LOCK_TIME_SYMBOL: + P A S S W O R D '_' L O C K '_' T I M E {serverVersion >= 80019}? +; // MYSQL +FAILED_LOGIN_ATTEMPTS_SYMBOL: + F A I L E D '_' L O G I N '_' A T T E M P T S {serverVersion >= 80019}? +; // MYSQL +REQUIRE_TABLE_PRIMARY_KEY_CHECK_SYMBOL: + R E Q U I R E '_' T A B L E '_' P R I M A R Y '_' K E Y '_' C H E C K {serverVersion >= 80019}? +; // MYSQL +STREAM_SYMBOL: S T R E A M {serverVersion >= 80019}?; // MYSQL +OFF_SYMBOL: O F F {serverVersion >= 80019}?; // SQL-1999-R + +// $antlr-format groupedAlignments on, alignTrailers off, alignLexerCommands on + +// Additional tokens which are mapped to existing tokens. +INT1_SYMBOL: I N T '1' -> type(TINYINT_SYMBOL); // Synonym +INT2_SYMBOL: I N T '2' -> type(SMALLINT_SYMBOL); // Synonym +INT3_SYMBOL: I N T '3' -> type(MEDIUMINT_SYMBOL); // Synonym +INT4_SYMBOL: I N T '4' -> type(INT_SYMBOL); // Synonym +INT8_SYMBOL: I N T '8' -> type(BIGINT_SYMBOL); // Synonym + +SQL_TSI_SECOND_SYMBOL: S Q L '_' T S I '_' S E C O N D -> type(SECOND_SYMBOL); // Synonym +SQL_TSI_MINUTE_SYMBOL: S Q L '_' T S I '_' M I N U T E -> type(MINUTE_SYMBOL); // Synonym +SQL_TSI_HOUR_SYMBOL: S Q L '_' T S I '_' H O U R -> type(HOUR_SYMBOL); // Synonym +SQL_TSI_DAY_SYMBOL: S Q L '_' T S I '_' D A Y -> type(DAY_SYMBOL); // Synonym +SQL_TSI_WEEK_SYMBOL: S Q L '_' T S I '_' W E E K -> type(WEEK_SYMBOL); // Synonym +SQL_TSI_MONTH_SYMBOL: S Q L '_' T S I '_' M O N T H -> type(MONTH_SYMBOL); // Synonym +SQL_TSI_QUARTER_SYMBOL: S Q L '_' T S I '_' Q U A R T E R -> type(QUARTER_SYMBOL); // Synonym +SQL_TSI_YEAR_SYMBOL: S Q L '_' T S I '_' Y E A R -> type(YEAR_SYMBOL); // Synonym + +// White space handling +WHITESPACE: [ \t\f\r\n] -> channel(HIDDEN); // Ignore whitespaces. + +// Input not covered elsewhere (unless quoted). +INVALID_INPUT: + [\u0001-\u0008] // Control codes. + | '\u000B' // Line tabulation. + | '\u000C' // Form feed. + | [\u000E-\u001F] // More control codes. + | '[' + | ']' +; + +// String and text types. + +// The underscore charset token is used to defined the repertoire of a string, though it conflicts +// with normal identifiers, which also can start with an underscore. +UNDERSCORE_CHARSET: UNDERLINE_SYMBOL [a-z0-9]+ { setType(checkCharset(getText())); }; + +// Identifiers might start with a digit, even though it is discouraged, and may not consist entirely of digits only. +// All keywords above are automatically excluded. +IDENTIFIER: + DIGITS+ [eE] (LETTER_WHEN_UNQUOTED_NO_DIGIT LETTER_WHEN_UNQUOTED*)? // Have to exclude float pattern, as this rule matches more. + | DIGITS+ LETTER_WITHOUT_FLOAT_PART LETTER_WHEN_UNQUOTED* + | LETTER_WHEN_UNQUOTED_NO_DIGIT LETTER_WHEN_UNQUOTED* // INT_NUMBER matches first if there are only digits. +; + +NCHAR_TEXT: [nN] SINGLE_QUOTED_TEXT; + +// MySQL supports automatic concatenation of multiple single and double quoted strings if they follow each other as separate +// tokens. This is reflected in the `textLiteral` parser rule. +// Here we handle duplication of quotation chars only (which must be replaced by a single char in the target code). + +fragment BACK_TICK: '`'; +fragment SINGLE_QUOTE: '\''; +fragment DOUBLE_QUOTE: '"'; + +BACK_TICK_QUOTED_ID: BACK_TICK (({!isSqlModeActive(NoBackslashEscapes)}? '\\')? .)*? BACK_TICK; + +DOUBLE_QUOTED_TEXT: ( + DOUBLE_QUOTE (({!isSqlModeActive(NoBackslashEscapes)}? '\\' .)? .)*? DOUBLE_QUOTE + )+ +; + +SINGLE_QUOTED_TEXT: ( + SINGLE_QUOTE (({!isSqlModeActive(NoBackslashEscapes)}? '\\')? .)*? SINGLE_QUOTE + )+ +; + +// There are 3 types of block comments: +// /* ... */ - The standard multi line comment. +// /*! ... */ - A comment used to mask code for other clients. In MySQL the content is handled as normal code. +// /*!12345 ... */ - Same as the previous one except code is only used when the given number is lower +// than the current server version (specifying so the minimum server version the code can run with). +VERSION_COMMENT_START: ('/*!' DIGITS) ( + {checkVersion(getText())}? // Will set inVersionComment if the number matches. + | .*? '*/' + ) -> channel(HIDDEN) +; + +// inVersionComment is a variable in the base lexer. +// TODO: use a lexer mode instead of a member variable. +MYSQL_COMMENT_START: '/*!' { inVersionComment = true; } -> channel(HIDDEN); +VERSION_COMMENT_END: '*/' {inVersionComment}? { inVersionComment = false; } -> channel(HIDDEN); +BLOCK_COMMENT: ( '/**/' | '/*' ~[!] .*? '*/') -> channel(HIDDEN); + +POUND_COMMENT: '#' ~([\n\r])* -> channel(HIDDEN); +DASHDASH_COMMENT: DOUBLE_DASH ([ \t] (~[\n\r])* | LINEBREAK | EOF) -> channel(HIDDEN); + +fragment DOUBLE_DASH: '--'; +fragment LINEBREAK: [\n\r]; + +fragment SIMPLE_IDENTIFIER: (DIGIT | [a-zA-Z_$] | DOT_SYMBOL)+; + +fragment ML_COMMENT_HEAD: '/*'; +fragment ML_COMMENT_END: '*/'; + +// As defined in https://dev.mysql.com/doc/refman/8.0/en/identifiers.html. +fragment LETTER_WHEN_UNQUOTED: DIGIT | LETTER_WHEN_UNQUOTED_NO_DIGIT; + +fragment LETTER_WHEN_UNQUOTED_NO_DIGIT: [a-zA-Z_$\u0080-\uffff]; + +// Any letter but without e/E and digits (which are used to match a decimal number). +fragment LETTER_WITHOUT_FLOAT_PART: [a-df-zA-DF-Z_$\u0080-\uffff]; diff --git a/wp-content/plugins/sqlite-database-integration/wp-includes/mysql-parser/MySQLLexer.php b/wp-content/plugins/sqlite-database-integration/wp-includes/mysql-parser/MySQLLexer.php new file mode 100644 index 00000000..4126e1b8 --- /dev/null +++ b/wp-content/plugins/sqlite-database-integration/wp-includes/mysql-parser/MySQLLexer.php @@ -0,0 +1,9061 @@ +input = $input; + $this->serverVersion = $serverVersion; + $this->sqlModes = $sqlModes; + } + + const PipesAsConcat = 1; + const HighNotPrecedence = 2; + const NoBackslashEscapes = 4; + public const ANSI_QUOTES = 8; + + public function isSqlModeActive(int $mode): bool + { + return ($this->sqlModes & $mode) !== 0; + } + + public function getServerVersion() + { + return $this->serverVersion; + } + + public static function getTokenName(int $tokenType): string + { + if (isset(self::$tokenNames[$tokenType])) { + return self::$tokenNames[$tokenType]; + } + + return ''; + } + + public function getText(): string + { + return $this->text; + } + + public function getType(): int + { + return $this->type; + } + + public function setType(int $type): void + { + $this->type = $type; + } + + public function getNextToken() + { + $this->nextToken(); + return $this->tokenInstance; + } + + private function nextToken() + { + while (true) { + $this->text = ''; + $this->type = null; + $this->tokenInstance = null; + $this->channel = self::DEFAULT_TOKEN_CHANNEL; + + $la = $this->LA(1); + + if ($la === "'") { + $this->SINGLE_QUOTED_TEXT(); + } elseif ($la === '"') { + $this->DOUBLE_QUOTED_TEXT(); + } elseif ($la === '`') { + $this->BACK_TICK_QUOTED_ID(); + } elseif (safe_ctype_digit($la)) { + $this->NUMBER(); + } elseif ($la === '.') { + if (safe_ctype_digit($this->LA(2))) { + $this->NUMBER(); + } else { + $this->DOT_IDENTIFIER(); + } + } elseif ($la === '=') { + $this->EQUAL_OPERATOR(); + } elseif ($la === ':') { + if ($this->LA(2) === '=') { + $this->ASSIGN_OPERATOR(); + } else { + $this->COLON_SYMBOL(); + } + } elseif ($la === '<') { + if ($this->LA(2) === '=') { + if ($this->LA(3) === '>') { + $this->NULL_SAFE_EQUAL_OPERATOR(); + } else { + $this->LESS_OR_EQUAL_OPERATOR(); + } + } elseif ($this->LA(2) === '>') { + $this->NOT_EQUAL2_OPERATOR(); + } elseif ($this->LA(2) === '<') { + $this->SHIFT_LEFT_OPERATOR(); + } else { + $this->LESS_THAN_OPERATOR(); + } + } elseif ($la === '>') { + if ($this->LA(2) === '=') { + $this->GREATER_OR_EQUAL_OPERATOR(); + } elseif ($this->LA(2) === '>') { + $this->SHIFT_RIGHT_OPERATOR(); + } else { + $this->GREATER_THAN_OPERATOR(); + } + } elseif ($la === '!') { + if ($this->LA(2) === '=') { + $this->NOT_EQUAL_OPERATOR(); + } else { + $this->LOGICAL_NOT_OPERATOR(); + } + } elseif ($la === '+') { + $this->PLUS_OPERATOR(); + } elseif ($la === '-') { + if ($this->LA(2) === '>') { + if ($this->LA(3) === '>') { + $this->JSON_UNQUOTED_SEPARATOR_SYMBOL(); + } else { + $this->JSON_SEPARATOR_SYMBOL(); + } + } else { + $this->MINUS_OPERATOR(); + } + } elseif ($la === '*') { + $this->MULT_OPERATOR(); + } elseif ($la === '/') { + if ($this->LA(2) === '*') { + $this->blockComment(); + } else { + $this->DIV_OPERATOR(); + } + } elseif ($la === '%') { + $this->MOD_OPERATOR(); + } elseif ($la === '&') { + if ($this->LA(2) === '&') { + $this->LOGICAL_AND_OPERATOR(); + } else { + $this->BITWISE_AND_OPERATOR(); + } + } elseif ($la === '^') { + $this->BITWISE_XOR_OPERATOR(); + } elseif ($la === '|') { + if ($this->LA(2) === '|') { + $this->LOGICAL_OR_OPERATOR(); + } else { + $this->BITWISE_OR_OPERATOR(); + } + } elseif ($la === '~') { + $this->BITWISE_NOT_OPERATOR(); + } elseif ($la === ',') { + $this->COMMA_SYMBOL(); + } elseif ($la === ';') { + $this->SEMICOLON_SYMBOL(); + } elseif ($la === '(') { + $this->OPEN_PAR_SYMBOL(); + } elseif ($la === ')') { + $this->CLOSE_PAR_SYMBOL(); + } elseif ($la === '{') { + $this->OPEN_CURLY_SYMBOL(); + } elseif ($la === '}') { + $this->CLOSE_CURLY_SYMBOL(); + } elseif ($la === '_') { + $this->UNDERLINE_SYMBOL(); + } elseif ($la === '@') { + if ($this->LA(2) === '@') { + $this->AT_AT_SIGN_SYMBOL(); + } else { + $this->AT_SIGN_SYMBOL(); + } + } elseif ($la === '?') { + $this->PARAM_MARKER(); + } elseif ($la === '\\') { + if ($this->LA(2) === 'N') { + $this->NULL2_SYMBOL(); + } else { + $this->INVALID_INPUT(); + } + } elseif ($la === '#') { + $this->POUND_COMMENT(); + } elseif ($la === '-' && $this->LA(2) === '-') { + $this->DASHDASH_COMMENT(); + } elseif (safe_ctype_space($la)) { + $this->WHITESPACE(); + } elseif ($la === '0' && ($this->LA(2) === 'x' || $this->LA(2) === 'b')) { + $this->NUMBER(); + } elseif (safe_ctype_alpha($la)) { + $this->IDENTIFIER_OR_KEYWORD(); + } elseif ($la === null) { + $this->matchEOF(); + $this->tokenInstance = new MySQLToken(self::EOF, ''); + return false; + } else { + $this->INVALID_INPUT(); + } + + if(null !== $this->type) { + break; + } + } + + $this->tokenInstance = new MySQLToken($this->type, $this->text, $this->channel); + return true; + } + + public function getToken() + { + return $this->tokenInstance; + } + + public function peekNextToken(int $k=1) + { + if ($k <= 0) { + throw new \InvalidArgumentException('k must be greater than 0.'); + } + + $pos = $this->position; + $c = $this->c; + $n = $this->n; + $token = $this->token; + $text = $this->text; + $type = $this->type; + $channel = $this->channel; + $tokenInstance = $this->tokenInstance; + + $token = null; + for ($i = 1; $i <= $k; ++$i) { + $token = $this->getNextToken(); + } + + $this->position = $pos; + $this->c = $c; + $this->n = $n; + $this->token = $token; + $this->text = $text; + $this->type = $type; + $this->channel = $channel; + $this->tokenInstance = $tokenInstance; + + return $token; + } + + protected function LA(int $i): ?string + { + if(null === $this->c) { + $this->c = $this->input[$this->position] ?? null; + } + if ($i === 1) { + return $this->c; + } elseif ($i === 2) { + return $this->n; + } else { + if ($this->position + $i - 1 >= strlen($this->input)) { + return null; + } else { + return $this->input[$this->position + $i - 1]; + } + } + } + + protected function consume(): void + { + $this->text .= $this->c; + + if ($this->position < strlen($this->input)) { + ++$this->position; + $this->c = $this->input[$this->position] ?? null; + $this->n = $this->input[$this->position + 1] ?? null; + } else { + $this->c = null; + $this->n = null; + } + } + + protected function matchEOF(): void + { + if ($this->c === null) { + $this->matchAny(); + } else { + throw new \RuntimeException('Current character is not EOF.'); + } + } + + protected function matchAny(): void + { + $this->consume(); + } + + protected function match(string $x): void + { + if ($this->c === $x) { + $this->consume(); + } else { + throw new \RuntimeException(sprintf("Expecting '%s', found '%s'", $x, $this->c)); + } + } + + /** + * This is a place holder to support features of MySQLBaseLexer which are not yet implemented + * in the PHP target. + * + * @return bool + */ + protected function checkVersion(string $text): bool + { + return false; + } + + /** + * This is a place holder to support features of MySQLBaseLexer which are not yet implemented + * in the PHP target. + * + * @return int + */ + protected function checkCharset(string $text): int + { + return 0; + } + + /** + * This is a place holder to support features of MySQLBaseLexer which are not yet implemented + * in the PHP target. + * + * @return void + */ + protected function emitDot(): void + { + return; + } + + protected static $tokenNames = [ + self::EQUAL_OPERATOR => 'EQUAL_OPERATOR', + self::ASSIGN_OPERATOR => 'ASSIGN_OPERATOR', + self::NULL_SAFE_EQUAL_OPERATOR => 'NULL_SAFE_EQUAL_OPERATOR', + self::GREATER_OR_EQUAL_OPERATOR => 'GREATER_OR_EQUAL_OPERATOR', + self::GREATER_THAN_OPERATOR => 'GREATER_THAN_OPERATOR', + self::LESS_OR_EQUAL_OPERATOR => 'LESS_OR_EQUAL_OPERATOR', + self::LESS_THAN_OPERATOR => 'LESS_THAN_OPERATOR', + self::NOT_EQUAL_OPERATOR => 'NOT_EQUAL_OPERATOR', + self::PLUS_OPERATOR => 'PLUS_OPERATOR', + self::MINUS_OPERATOR => 'MINUS_OPERATOR', + self::MULT_OPERATOR => 'MULT_OPERATOR', + self::DIV_OPERATOR => 'DIV_OPERATOR', + self::MOD_OPERATOR => 'MOD_OPERATOR', + self::LOGICAL_NOT_OPERATOR => 'LOGICAL_NOT_OPERATOR', + self::BITWISE_NOT_OPERATOR => 'BITWISE_NOT_OPERATOR', + self::SHIFT_LEFT_OPERATOR => 'SHIFT_LEFT_OPERATOR', + self::SHIFT_RIGHT_OPERATOR => 'SHIFT_RIGHT_OPERATOR', + self::LOGICAL_AND_OPERATOR => 'LOGICAL_AND_OPERATOR', + self::BITWISE_AND_OPERATOR => 'BITWISE_AND_OPERATOR', + self::BITWISE_XOR_OPERATOR => 'BITWISE_XOR_OPERATOR', + self::LOGICAL_OR_OPERATOR => 'LOGICAL_OR_OPERATOR', + self::BITWISE_OR_OPERATOR => 'BITWISE_OR_OPERATOR', + self::DOT_SYMBOL => 'DOT_SYMBOL', + self::COMMA_SYMBOL => 'COMMA_SYMBOL', + self::SEMICOLON_SYMBOL => 'SEMICOLON_SYMBOL', + self::COLON_SYMBOL => 'COLON_SYMBOL', + self::OPEN_PAR_SYMBOL => 'OPEN_PAR_SYMBOL', + self::CLOSE_PAR_SYMBOL => 'CLOSE_PAR_SYMBOL', + self::OPEN_CURLY_SYMBOL => 'OPEN_CURLY_SYMBOL', + self::CLOSE_CURLY_SYMBOL => 'CLOSE_CURLY_SYMBOL', + self::UNDERLINE_SYMBOL => 'UNDERLINE_SYMBOL', + self::JSON_SEPARATOR_SYMBOL => 'JSON_SEPARATOR_SYMBOL', + self::JSON_UNQUOTED_SEPARATOR_SYMBOL => 'JSON_UNQUOTED_SEPARATOR_SYMBOL', + self::AT_SIGN_SYMBOL => 'AT_SIGN_SYMBOL', + self::AT_TEXT_SUFFIX => 'AT_TEXT_SUFFIX', + self::AT_AT_SIGN_SYMBOL => 'AT_AT_SIGN_SYMBOL', + self::NULL2_SYMBOL => 'NULL2_SYMBOL', + self::PARAM_MARKER => 'PARAM_MARKER', + self::INT_SYMBOL => 'INT_SYMBOL', + self::TINYINT_SYMBOL => 'TINYINT_SYMBOL', + self::SMALLINT_SYMBOL => 'SMALLINT_SYMBOL', + self::MEDIUMINT_SYMBOL => 'MEDIUMINT_SYMBOL', + self::BIGINT_SYMBOL => 'BIGINT_SYMBOL', + self::REAL_SYMBOL => 'REAL_SYMBOL', + self::DOUBLE_SYMBOL => 'DOUBLE_SYMBOL', + self::FLOAT_SYMBOL => 'FLOAT_SYMBOL', + self::DECIMAL_SYMBOL => 'DECIMAL_SYMBOL', + self::NUMERIC_SYMBOL => 'NUMERIC_SYMBOL', + self::DATE_SYMBOL => 'DATE_SYMBOL', + self::TIME_SYMBOL => 'TIME_SYMBOL', + self::TIMESTAMP_SYMBOL => 'TIMESTAMP_SYMBOL', + self::DATETIME_SYMBOL => 'DATETIME_SYMBOL', + self::YEAR_SYMBOL => 'YEAR_SYMBOL', + self::CHAR_SYMBOL => 'CHAR_SYMBOL', + self::VARCHAR_SYMBOL => 'VARCHAR_SYMBOL', + self::BINARY_SYMBOL => 'BINARY_SYMBOL', + self::VARBINARY_SYMBOL => 'VARBINARY_SYMBOL', + self::TINYBLOB_SYMBOL => 'TINYBLOB_SYMBOL', + self::BLOB_SYMBOL => 'BLOB_SYMBOL', + self::MEDIUMBLOB_SYMBOL => 'MEDIUMBLOB_SYMBOL', + self::LONGBLOB_SYMBOL => 'LONGBLOB_SYMBOL', + self::TINYTEXT_SYMBOL => 'TINYTEXT_SYMBOL', + self::TEXT_SYMBOL => 'TEXT_SYMBOL', + self::MEDIUMTEXT_SYMBOL => 'MEDIUMTEXT_SYMBOL', + self::LONGTEXT_SYMBOL => 'LONGTEXT_SYMBOL', + self::ENUM_SYMBOL => 'ENUM_SYMBOL', + self::SET_SYMBOL => 'SET_SYMBOL', + self::JSON_SYMBOL => 'JSON_SYMBOL', + self::GEOMETRY_SYMBOL => 'GEOMETRY_SYMBOL', + self::POINT_SYMBOL => 'POINT_SYMBOL', + self::LINESTRING_SYMBOL => 'LINESTRING_SYMBOL', + self::POLYGON_SYMBOL => 'POLYGON_SYMBOL', + self::GEOMETRYCOLLECTION_SYMBOL => 'GEOMETRYCOLLECTION_SYMBOL', + self::MULTIPOINT_SYMBOL => 'MULTIPOINT_SYMBOL', + self::MULTILINESTRING_SYMBOL => 'MULTILINESTRING_SYMBOL', + self::MULTIPOLYGON_SYMBOL => 'MULTIPOLYGON_SYMBOL', + self::ACCESSIBLE_SYMBOL => 'ACCESSIBLE_SYMBOL', + self::ACCOUNT_SYMBOL => 'ACCOUNT_SYMBOL', + self::ACTION_SYMBOL => 'ACTION_SYMBOL', + self::ADD_SYMBOL => 'ADD_SYMBOL', + self::AFTER_SYMBOL => 'AFTER_SYMBOL', + self::AGAINST_SYMBOL => 'AGAINST_SYMBOL', + self::AGGREGATE_SYMBOL => 'AGGREGATE_SYMBOL', + self::ALGORITHM_SYMBOL => 'ALGORITHM_SYMBOL', + self::ALL_SYMBOL => 'ALL_SYMBOL', + self::ALTER_SYMBOL => 'ALTER_SYMBOL', + self::ALWAYS_SYMBOL => 'ALWAYS_SYMBOL', + self::ANALYSE_SYMBOL => 'ANALYSE_SYMBOL', + self::ANALYZE_SYMBOL => 'ANALYZE_SYMBOL', + self::AND_SYMBOL => 'AND_SYMBOL', + self::ANY_SYMBOL => 'ANY_SYMBOL', + self::AS_SYMBOL => 'AS_SYMBOL', + self::ASC_SYMBOL => 'ASC_SYMBOL', + self::ASENSITIVE_SYMBOL => 'ASENSITIVE_SYMBOL', + self::AT_SYMBOL => 'AT_SYMBOL', + self::AUTOEXTEND_SIZE_SYMBOL => 'AUTOEXTEND_SIZE_SYMBOL', + self::AUTO_INCREMENT_SYMBOL => 'AUTO_INCREMENT_SYMBOL', + self::AVG_ROW_LENGTH_SYMBOL => 'AVG_ROW_LENGTH_SYMBOL', + self::AVG_SYMBOL => 'AVG_SYMBOL', + self::BACKUP_SYMBOL => 'BACKUP_SYMBOL', + self::BEFORE_SYMBOL => 'BEFORE_SYMBOL', + self::BEGIN_SYMBOL => 'BEGIN_SYMBOL', + self::BETWEEN_SYMBOL => 'BETWEEN_SYMBOL', + self::BINLOG_SYMBOL => 'BINLOG_SYMBOL', + self::BIT_AND_SYMBOL => 'BIT_AND_SYMBOL', + self::BIT_OR_SYMBOL => 'BIT_OR_SYMBOL', + self::BIT_XOR_SYMBOL => 'BIT_XOR_SYMBOL', + self::BLOCK_SYMBOL => 'BLOCK_SYMBOL', + self::BOOL_SYMBOL => 'BOOL_SYMBOL', + self::BOOLEAN_SYMBOL => 'BOOLEAN_SYMBOL', + self::BOTH_SYMBOL => 'BOTH_SYMBOL', + self::BTREE_SYMBOL => 'BTREE_SYMBOL', + self::BY_SYMBOL => 'BY_SYMBOL', + self::BYTE_SYMBOL => 'BYTE_SYMBOL', + self::CACHE_SYMBOL => 'CACHE_SYMBOL', + self::CALL_SYMBOL => 'CALL_SYMBOL', + self::CASCADE_SYMBOL => 'CASCADE_SYMBOL', + self::CASCADED_SYMBOL => 'CASCADED_SYMBOL', + self::CASE_SYMBOL => 'CASE_SYMBOL', + self::CAST_SYMBOL => 'CAST_SYMBOL', + self::CATALOG_NAME_SYMBOL => 'CATALOG_NAME_SYMBOL', + self::CHAIN_SYMBOL => 'CHAIN_SYMBOL', + self::CHANGE_SYMBOL => 'CHANGE_SYMBOL', + self::CHANGED_SYMBOL => 'CHANGED_SYMBOL', + self::CHANNEL_SYMBOL => 'CHANNEL_SYMBOL', + self::CHARSET_SYMBOL => 'CHARSET_SYMBOL', + self::CHARACTER_SYMBOL => 'CHARACTER_SYMBOL', + self::CHECK_SYMBOL => 'CHECK_SYMBOL', + self::CHECKSUM_SYMBOL => 'CHECKSUM_SYMBOL', + self::CIPHER_SYMBOL => 'CIPHER_SYMBOL', + self::CLASS_ORIGIN_SYMBOL => 'CLASS_ORIGIN_SYMBOL', + self::CLIENT_SYMBOL => 'CLIENT_SYMBOL', + self::CLOSE_SYMBOL => 'CLOSE_SYMBOL', + self::COALESCE_SYMBOL => 'COALESCE_SYMBOL', + self::CODE_SYMBOL => 'CODE_SYMBOL', + self::COLLATE_SYMBOL => 'COLLATE_SYMBOL', + self::COLLATION_SYMBOL => 'COLLATION_SYMBOL', + self::COLUMN_FORMAT_SYMBOL => 'COLUMN_FORMAT_SYMBOL', + self::COLUMN_NAME_SYMBOL => 'COLUMN_NAME_SYMBOL', + self::COLUMNS_SYMBOL => 'COLUMNS_SYMBOL', + self::COLUMN_SYMBOL => 'COLUMN_SYMBOL', + self::COMMENT_SYMBOL => 'COMMENT_SYMBOL', + self::COMMITTED_SYMBOL => 'COMMITTED_SYMBOL', + self::COMMIT_SYMBOL => 'COMMIT_SYMBOL', + self::COMPACT_SYMBOL => 'COMPACT_SYMBOL', + self::COMPLETION_SYMBOL => 'COMPLETION_SYMBOL', + self::COMPRESSED_SYMBOL => 'COMPRESSED_SYMBOL', + self::COMPRESSION_SYMBOL => 'COMPRESSION_SYMBOL', + self::CONCURRENT_SYMBOL => 'CONCURRENT_SYMBOL', + self::CONDITION_SYMBOL => 'CONDITION_SYMBOL', + self::CONNECTION_SYMBOL => 'CONNECTION_SYMBOL', + self::CONSISTENT_SYMBOL => 'CONSISTENT_SYMBOL', + self::CONSTRAINT_SYMBOL => 'CONSTRAINT_SYMBOL', + self::CONSTRAINT_CATALOG_SYMBOL => 'CONSTRAINT_CATALOG_SYMBOL', + self::CONSTRAINT_NAME_SYMBOL => 'CONSTRAINT_NAME_SYMBOL', + self::CONSTRAINT_SCHEMA_SYMBOL => 'CONSTRAINT_SCHEMA_SYMBOL', + self::CONTAINS_SYMBOL => 'CONTAINS_SYMBOL', + self::CONTEXT_SYMBOL => 'CONTEXT_SYMBOL', + self::CONTINUE_SYMBOL => 'CONTINUE_SYMBOL', + self::CONTRIBUTORS_SYMBOL => 'CONTRIBUTORS_SYMBOL', + self::CONVERT_SYMBOL => 'CONVERT_SYMBOL', + self::COUNT_SYMBOL => 'COUNT_SYMBOL', + self::CPU_SYMBOL => 'CPU_SYMBOL', + self::CREATE_SYMBOL => 'CREATE_SYMBOL', + self::CROSS_SYMBOL => 'CROSS_SYMBOL', + self::CUBE_SYMBOL => 'CUBE_SYMBOL', + self::CURDATE_SYMBOL => 'CURDATE_SYMBOL', + self::CURRENT_DATE_SYMBOL => 'CURRENT_DATE_SYMBOL', + self::CURRENT_TIME_SYMBOL => 'CURRENT_TIME_SYMBOL', + self::CURRENT_TIMESTAMP_SYMBOL => 'CURRENT_TIMESTAMP_SYMBOL', + self::CURRENT_USER_SYMBOL => 'CURRENT_USER_SYMBOL', + self::CURRENT_SYMBOL => 'CURRENT_SYMBOL', + self::CURSOR_SYMBOL => 'CURSOR_SYMBOL', + self::CURSOR_NAME_SYMBOL => 'CURSOR_NAME_SYMBOL', + self::CURTIME_SYMBOL => 'CURTIME_SYMBOL', + self::DATABASE_SYMBOL => 'DATABASE_SYMBOL', + self::DATABASES_SYMBOL => 'DATABASES_SYMBOL', + self::DATAFILE_SYMBOL => 'DATAFILE_SYMBOL', + self::DATA_SYMBOL => 'DATA_SYMBOL', + self::DATE_ADD_SYMBOL => 'DATE_ADD_SYMBOL', + self::DATE_SUB_SYMBOL => 'DATE_SUB_SYMBOL', + self::DAY_HOUR_SYMBOL => 'DAY_HOUR_SYMBOL', + self::DAY_MICROSECOND_SYMBOL => 'DAY_MICROSECOND_SYMBOL', + self::DAY_MINUTE_SYMBOL => 'DAY_MINUTE_SYMBOL', + self::DAY_SECOND_SYMBOL => 'DAY_SECOND_SYMBOL', + self::DAY_SYMBOL => 'DAY_SYMBOL', + self::DAYOFMONTH_SYMBOL => 'DAYOFMONTH_SYMBOL', + self::DEALLOCATE_SYMBOL => 'DEALLOCATE_SYMBOL', + self::DEC_SYMBOL => 'DEC_SYMBOL', + self::DECLARE_SYMBOL => 'DECLARE_SYMBOL', + self::DEFAULT_SYMBOL => 'DEFAULT_SYMBOL', + self::DEFAULT_AUTH_SYMBOL => 'DEFAULT_AUTH_SYMBOL', + self::DEFINER_SYMBOL => 'DEFINER_SYMBOL', + self::DELAYED_SYMBOL => 'DELAYED_SYMBOL', + self::DELAY_KEY_WRITE_SYMBOL => 'DELAY_KEY_WRITE_SYMBOL', + self::DELETE_SYMBOL => 'DELETE_SYMBOL', + self::DESC_SYMBOL => 'DESC_SYMBOL', + self::DESCRIBE_SYMBOL => 'DESCRIBE_SYMBOL', + self::DES_KEY_FILE_SYMBOL => 'DES_KEY_FILE_SYMBOL', + self::DETERMINISTIC_SYMBOL => 'DETERMINISTIC_SYMBOL', + self::DIAGNOSTICS_SYMBOL => 'DIAGNOSTICS_SYMBOL', + self::DIRECTORY_SYMBOL => 'DIRECTORY_SYMBOL', + self::DISABLE_SYMBOL => 'DISABLE_SYMBOL', + self::DISCARD_SYMBOL => 'DISCARD_SYMBOL', + self::DISK_SYMBOL => 'DISK_SYMBOL', + self::DISTINCT_SYMBOL => 'DISTINCT_SYMBOL', + self::DISTINCTROW_SYMBOL => 'DISTINCTROW_SYMBOL', + self::DIV_SYMBOL => 'DIV_SYMBOL', + self::DO_SYMBOL => 'DO_SYMBOL', + self::DROP_SYMBOL => 'DROP_SYMBOL', + self::DUAL_SYMBOL => 'DUAL_SYMBOL', + self::DUMPFILE_SYMBOL => 'DUMPFILE_SYMBOL', + self::DUPLICATE_SYMBOL => 'DUPLICATE_SYMBOL', + self::DYNAMIC_SYMBOL => 'DYNAMIC_SYMBOL', + self::EACH_SYMBOL => 'EACH_SYMBOL', + self::ELSE_SYMBOL => 'ELSE_SYMBOL', + self::ELSEIF_SYMBOL => 'ELSEIF_SYMBOL', + self::EMPTY_SYMBOL => 'EMPTY_SYMBOL', + self::ENABLE_SYMBOL => 'ENABLE_SYMBOL', + self::ENCLOSED_SYMBOL => 'ENCLOSED_SYMBOL', + self::ENCRYPTION_SYMBOL => 'ENCRYPTION_SYMBOL', + self::END_SYMBOL => 'END_SYMBOL', + self::ENDS_SYMBOL => 'ENDS_SYMBOL', + self::ENFORCED_SYMBOL => 'ENFORCED_SYMBOL', + self::ENGINES_SYMBOL => 'ENGINES_SYMBOL', + self::ENGINE_SYMBOL => 'ENGINE_SYMBOL', + self::ERROR_SYMBOL => 'ERROR_SYMBOL', + self::ERRORS_SYMBOL => 'ERRORS_SYMBOL', + self::ESCAPED_SYMBOL => 'ESCAPED_SYMBOL', + self::ESCAPE_SYMBOL => 'ESCAPE_SYMBOL', + self::EVENT_SYMBOL => 'EVENT_SYMBOL', + self::EVENTS_SYMBOL => 'EVENTS_SYMBOL', + self::EVERY_SYMBOL => 'EVERY_SYMBOL', + self::EXCHANGE_SYMBOL => 'EXCHANGE_SYMBOL', + self::EXCEPT_SYMBOL => 'EXCEPT_SYMBOL', + self::EXECUTE_SYMBOL => 'EXECUTE_SYMBOL', + self::EXISTS_SYMBOL => 'EXISTS_SYMBOL', + self::EXIT_SYMBOL => 'EXIT_SYMBOL', + self::EXPANSION_SYMBOL => 'EXPANSION_SYMBOL', + self::EXPIRE_SYMBOL => 'EXPIRE_SYMBOL', + self::EXPLAIN_SYMBOL => 'EXPLAIN_SYMBOL', + self::EXPORT_SYMBOL => 'EXPORT_SYMBOL', + self::EXTENDED_SYMBOL => 'EXTENDED_SYMBOL', + self::EXTENT_SIZE_SYMBOL => 'EXTENT_SIZE_SYMBOL', + self::EXTRACT_SYMBOL => 'EXTRACT_SYMBOL', + self::FALSE_SYMBOL => 'FALSE_SYMBOL', + self::FAST_SYMBOL => 'FAST_SYMBOL', + self::FAULTS_SYMBOL => 'FAULTS_SYMBOL', + self::FETCH_SYMBOL => 'FETCH_SYMBOL', + self::FIELDS_SYMBOL => 'FIELDS_SYMBOL', + self::FILE_BLOCK_SIZE_SYMBOL => 'FILE_BLOCK_SIZE_SYMBOL', + self::FILE_SYMBOL => 'FILE_SYMBOL', + self::FILTER_SYMBOL => 'FILTER_SYMBOL', + self::FIRST_SYMBOL => 'FIRST_SYMBOL', + self::FIRST_VALUE_SYMBOL => 'FIRST_VALUE_SYMBOL', + self::FIXED_SYMBOL => 'FIXED_SYMBOL', + self::FLOAT4_SYMBOL => 'FLOAT4_SYMBOL', + self::FLOAT8_SYMBOL => 'FLOAT8_SYMBOL', + self::FLUSH_SYMBOL => 'FLUSH_SYMBOL', + self::FOLLOWS_SYMBOL => 'FOLLOWS_SYMBOL', + self::FORCE_SYMBOL => 'FORCE_SYMBOL', + self::FOREIGN_SYMBOL => 'FOREIGN_SYMBOL', + self::FOR_SYMBOL => 'FOR_SYMBOL', + self::FORMAT_SYMBOL => 'FORMAT_SYMBOL', + self::FOUND_SYMBOL => 'FOUND_SYMBOL', + self::FROM_SYMBOL => 'FROM_SYMBOL', + self::FULLTEXT_SYMBOL => 'FULLTEXT_SYMBOL', + self::FULL_SYMBOL => 'FULL_SYMBOL', + self::FUNCTION_SYMBOL => 'FUNCTION_SYMBOL', + self::GENERATED_SYMBOL => 'GENERATED_SYMBOL', + self::GENERAL_SYMBOL => 'GENERAL_SYMBOL', + self::GET_FORMAT_SYMBOL => 'GET_FORMAT_SYMBOL', + self::GET_MASTER_PUBLIC_KEY_SYMBOL => 'GET_MASTER_PUBLIC_KEY_SYMBOL', + self::GLOBAL_SYMBOL => 'GLOBAL_SYMBOL', + self::GRANT_SYMBOL => 'GRANT_SYMBOL', + self::GRANTS_SYMBOL => 'GRANTS_SYMBOL', + self::GROUP_CONCAT_SYMBOL => 'GROUP_CONCAT_SYMBOL', + self::GROUP_REPLICATION_SYMBOL => 'GROUP_REPLICATION_SYMBOL', + self::GROUP_SYMBOL => 'GROUP_SYMBOL', + self::HANDLER_SYMBOL => 'HANDLER_SYMBOL', + self::HASH_SYMBOL => 'HASH_SYMBOL', + self::HAVING_SYMBOL => 'HAVING_SYMBOL', + self::HELP_SYMBOL => 'HELP_SYMBOL', + self::HIGH_PRIORITY_SYMBOL => 'HIGH_PRIORITY_SYMBOL', + self::HISTOGRAM_SYMBOL => 'HISTOGRAM_SYMBOL', + self::HISTORY_SYMBOL => 'HISTORY_SYMBOL', + self::HOST_SYMBOL => 'HOST_SYMBOL', + self::HOSTS_SYMBOL => 'HOSTS_SYMBOL', + self::HOUR_MICROSECOND_SYMBOL => 'HOUR_MICROSECOND_SYMBOL', + self::HOUR_MINUTE_SYMBOL => 'HOUR_MINUTE_SYMBOL', + self::HOUR_SECOND_SYMBOL => 'HOUR_SECOND_SYMBOL', + self::HOUR_SYMBOL => 'HOUR_SYMBOL', + self::IDENTIFIED_SYMBOL => 'IDENTIFIED_SYMBOL', + self::IF_SYMBOL => 'IF_SYMBOL', + self::IGNORE_SYMBOL => 'IGNORE_SYMBOL', + self::IGNORE_SERVER_IDS_SYMBOL => 'IGNORE_SERVER_IDS_SYMBOL', + self::IMPORT_SYMBOL => 'IMPORT_SYMBOL', + self::IN_SYMBOL => 'IN_SYMBOL', + self::INDEXES_SYMBOL => 'INDEXES_SYMBOL', + self::INDEX_SYMBOL => 'INDEX_SYMBOL', + self::INFILE_SYMBOL => 'INFILE_SYMBOL', + self::INITIAL_SIZE_SYMBOL => 'INITIAL_SIZE_SYMBOL', + self::INNER_SYMBOL => 'INNER_SYMBOL', + self::INOUT_SYMBOL => 'INOUT_SYMBOL', + self::INSENSITIVE_SYMBOL => 'INSENSITIVE_SYMBOL', + self::INSERT_SYMBOL => 'INSERT_SYMBOL', + self::INSERT_METHOD_SYMBOL => 'INSERT_METHOD_SYMBOL', + self::INSTANCE_SYMBOL => 'INSTANCE_SYMBOL', + self::INSTALL_SYMBOL => 'INSTALL_SYMBOL', + self::INTEGER_SYMBOL => 'INTEGER_SYMBOL', + self::INTERVAL_SYMBOL => 'INTERVAL_SYMBOL', + self::INTO_SYMBOL => 'INTO_SYMBOL', + self::INVISIBLE_SYMBOL => 'INVISIBLE_SYMBOL', + self::INVOKER_SYMBOL => 'INVOKER_SYMBOL', + self::IO_SYMBOL => 'IO_SYMBOL', + self::IPC_SYMBOL => 'IPC_SYMBOL', + self::IS_SYMBOL => 'IS_SYMBOL', + self::ISOLATION_SYMBOL => 'ISOLATION_SYMBOL', + self::ISSUER_SYMBOL => 'ISSUER_SYMBOL', + self::ITERATE_SYMBOL => 'ITERATE_SYMBOL', + self::JOIN_SYMBOL => 'JOIN_SYMBOL', + self::JSON_TABLE_SYMBOL => 'JSON_TABLE_SYMBOL', + self::JSON_ARRAYAGG_SYMBOL => 'JSON_ARRAYAGG_SYMBOL', + self::JSON_OBJECTAGG_SYMBOL => 'JSON_OBJECTAGG_SYMBOL', + self::KEYS_SYMBOL => 'KEYS_SYMBOL', + self::KEY_BLOCK_SIZE_SYMBOL => 'KEY_BLOCK_SIZE_SYMBOL', + self::KEY_SYMBOL => 'KEY_SYMBOL', + self::KILL_SYMBOL => 'KILL_SYMBOL', + self::LANGUAGE_SYMBOL => 'LANGUAGE_SYMBOL', + self::LAST_SYMBOL => 'LAST_SYMBOL', + self::LAST_VALUE_SYMBOL => 'LAST_VALUE_SYMBOL', + self::LATERAL_SYMBOL => 'LATERAL_SYMBOL', + self::LEAD_SYMBOL => 'LEAD_SYMBOL', + self::LEADING_SYMBOL => 'LEADING_SYMBOL', + self::LEAVE_SYMBOL => 'LEAVE_SYMBOL', + self::LEAVES_SYMBOL => 'LEAVES_SYMBOL', + self::LEFT_SYMBOL => 'LEFT_SYMBOL', + self::LESS_SYMBOL => 'LESS_SYMBOL', + self::LEVEL_SYMBOL => 'LEVEL_SYMBOL', + self::LIKE_SYMBOL => 'LIKE_SYMBOL', + self::LIMIT_SYMBOL => 'LIMIT_SYMBOL', + self::LINEAR_SYMBOL => 'LINEAR_SYMBOL', + self::LINES_SYMBOL => 'LINES_SYMBOL', + self::LIST_SYMBOL => 'LIST_SYMBOL', + self::LOAD_SYMBOL => 'LOAD_SYMBOL', + self::LOCALTIME_SYMBOL => 'LOCALTIME_SYMBOL', + self::LOCALTIMESTAMP_SYMBOL => 'LOCALTIMESTAMP_SYMBOL', + self::LOCAL_SYMBOL => 'LOCAL_SYMBOL', + self::LOCATOR_SYMBOL => 'LOCATOR_SYMBOL', + self::LOCK_SYMBOL => 'LOCK_SYMBOL', + self::LOCKS_SYMBOL => 'LOCKS_SYMBOL', + self::LOGFILE_SYMBOL => 'LOGFILE_SYMBOL', + self::LOGS_SYMBOL => 'LOGS_SYMBOL', + self::LOOP_SYMBOL => 'LOOP_SYMBOL', + self::LOW_PRIORITY_SYMBOL => 'LOW_PRIORITY_SYMBOL', + self::MASTER_SYMBOL => 'MASTER_SYMBOL', + self::MASTER_AUTO_POSITION_SYMBOL => 'MASTER_AUTO_POSITION_SYMBOL', + self::MASTER_BIND_SYMBOL => 'MASTER_BIND_SYMBOL', + self::MASTER_CONNECT_RETRY_SYMBOL => 'MASTER_CONNECT_RETRY_SYMBOL', + self::MASTER_DELAY_SYMBOL => 'MASTER_DELAY_SYMBOL', + self::MASTER_HEARTBEAT_PERIOD_SYMBOL => 'MASTER_HEARTBEAT_PERIOD_SYMBOL', + self::MASTER_HOST_SYMBOL => 'MASTER_HOST_SYMBOL', + self::NETWORK_NAMESPACE_SYMBOL => 'NETWORK_NAMESPACE_SYMBOL', + self::MASTER_LOG_FILE_SYMBOL => 'MASTER_LOG_FILE_SYMBOL', + self::MASTER_LOG_POS_SYMBOL => 'MASTER_LOG_POS_SYMBOL', + self::MASTER_PASSWORD_SYMBOL => 'MASTER_PASSWORD_SYMBOL', + self::MASTER_PORT_SYMBOL => 'MASTER_PORT_SYMBOL', + self::MASTER_PUBLIC_KEY_PATH_SYMBOL => 'MASTER_PUBLIC_KEY_PATH_SYMBOL', + self::MASTER_RETRY_COUNT_SYMBOL => 'MASTER_RETRY_COUNT_SYMBOL', + self::MASTER_SERVER_ID_SYMBOL => 'MASTER_SERVER_ID_SYMBOL', + self::MASTER_SSL_CAPATH_SYMBOL => 'MASTER_SSL_CAPATH_SYMBOL', + self::MASTER_SSL_CA_SYMBOL => 'MASTER_SSL_CA_SYMBOL', + self::MASTER_SSL_CERT_SYMBOL => 'MASTER_SSL_CERT_SYMBOL', + self::MASTER_SSL_CIPHER_SYMBOL => 'MASTER_SSL_CIPHER_SYMBOL', + self::MASTER_SSL_CRL_SYMBOL => 'MASTER_SSL_CRL_SYMBOL', + self::MASTER_SSL_CRLPATH_SYMBOL => 'MASTER_SSL_CRLPATH_SYMBOL', + self::MASTER_SSL_KEY_SYMBOL => 'MASTER_SSL_KEY_SYMBOL', + self::MASTER_SSL_SYMBOL => 'MASTER_SSL_SYMBOL', + self::MASTER_SSL_VERIFY_SERVER_CERT_SYMBOL => 'MASTER_SSL_VERIFY_SERVER_CERT_SYMBOL', + self::MASTER_TLS_VERSION_SYMBOL => 'MASTER_TLS_VERSION_SYMBOL', + self::MASTER_TLS_CIPHERSUITES_SYMBOL => 'MASTER_TLS_CIPHERSUITES_SYMBOL', + self::MASTER_USER_SYMBOL => 'MASTER_USER_SYMBOL', + self::MASTER_ZSTD_COMPRESSION_LEVEL_SYMBOL => 'MASTER_ZSTD_COMPRESSION_LEVEL_SYMBOL', + self::MATCH_SYMBOL => 'MATCH_SYMBOL', + self::MAX_CONNECTIONS_PER_HOUR_SYMBOL => 'MAX_CONNECTIONS_PER_HOUR_SYMBOL', + self::MAX_QUERIES_PER_HOUR_SYMBOL => 'MAX_QUERIES_PER_HOUR_SYMBOL', + self::MAX_ROWS_SYMBOL => 'MAX_ROWS_SYMBOL', + self::MAX_SIZE_SYMBOL => 'MAX_SIZE_SYMBOL', + self::MAX_STATEMENT_TIME_SYMBOL => 'MAX_STATEMENT_TIME_SYMBOL', + self::MAX_UPDATES_PER_HOUR_SYMBOL => 'MAX_UPDATES_PER_HOUR_SYMBOL', + self::MAX_USER_CONNECTIONS_SYMBOL => 'MAX_USER_CONNECTIONS_SYMBOL', + self::MAXVALUE_SYMBOL => 'MAXVALUE_SYMBOL', + self::MAX_SYMBOL => 'MAX_SYMBOL', + self::MEDIUM_SYMBOL => 'MEDIUM_SYMBOL', + self::MEMBER_SYMBOL => 'MEMBER_SYMBOL', + self::MEMORY_SYMBOL => 'MEMORY_SYMBOL', + self::MERGE_SYMBOL => 'MERGE_SYMBOL', + self::MESSAGE_TEXT_SYMBOL => 'MESSAGE_TEXT_SYMBOL', + self::MICROSECOND_SYMBOL => 'MICROSECOND_SYMBOL', + self::MIDDLEINT_SYMBOL => 'MIDDLEINT_SYMBOL', + self::MIGRATE_SYMBOL => 'MIGRATE_SYMBOL', + self::MINUTE_MICROSECOND_SYMBOL => 'MINUTE_MICROSECOND_SYMBOL', + self::MINUTE_SECOND_SYMBOL => 'MINUTE_SECOND_SYMBOL', + self::MINUTE_SYMBOL => 'MINUTE_SYMBOL', + self::MIN_ROWS_SYMBOL => 'MIN_ROWS_SYMBOL', + self::MIN_SYMBOL => 'MIN_SYMBOL', + self::MODE_SYMBOL => 'MODE_SYMBOL', + self::MODIFIES_SYMBOL => 'MODIFIES_SYMBOL', + self::MODIFY_SYMBOL => 'MODIFY_SYMBOL', + self::MOD_SYMBOL => 'MOD_SYMBOL', + self::MONTH_SYMBOL => 'MONTH_SYMBOL', + self::MUTEX_SYMBOL => 'MUTEX_SYMBOL', + self::MYSQL_ERRNO_SYMBOL => 'MYSQL_ERRNO_SYMBOL', + self::NAME_SYMBOL => 'NAME_SYMBOL', + self::NAMES_SYMBOL => 'NAMES_SYMBOL', + self::NATIONAL_SYMBOL => 'NATIONAL_SYMBOL', + self::NATURAL_SYMBOL => 'NATURAL_SYMBOL', + self::NCHAR_SYMBOL => 'NCHAR_SYMBOL', + self::NDBCLUSTER_SYMBOL => 'NDBCLUSTER_SYMBOL', + self::NDB_SYMBOL => 'NDB_SYMBOL', + self::NEG_SYMBOL => 'NEG_SYMBOL', + self::NESTED_SYMBOL => 'NESTED_SYMBOL', + self::NEVER_SYMBOL => 'NEVER_SYMBOL', + self::NEW_SYMBOL => 'NEW_SYMBOL', + self::NEXT_SYMBOL => 'NEXT_SYMBOL', + self::NODEGROUP_SYMBOL => 'NODEGROUP_SYMBOL', + self::NONE_SYMBOL => 'NONE_SYMBOL', + self::NONBLOCKING_SYMBOL => 'NONBLOCKING_SYMBOL', + self::NOT_SYMBOL => 'NOT_SYMBOL', + self::NOWAIT_SYMBOL => 'NOWAIT_SYMBOL', + self::NO_WAIT_SYMBOL => 'NO_WAIT_SYMBOL', + self::NO_WRITE_TO_BINLOG_SYMBOL => 'NO_WRITE_TO_BINLOG_SYMBOL', + self::NULL_SYMBOL => 'NULL_SYMBOL', + self::NULLS_SYMBOL => 'NULLS_SYMBOL', + self::NUMBER_SYMBOL => 'NUMBER_SYMBOL', + self::NVARCHAR_SYMBOL => 'NVARCHAR_SYMBOL', + self::NTH_VALUE_SYMBOL => 'NTH_VALUE_SYMBOL', + self::NTILE_SYMBOL => 'NTILE_SYMBOL', + self::OF_SYMBOL => 'OF_SYMBOL', + self::OFF_SYMBOL => 'OFF_SYMBOL', + self::OFFLINE_SYMBOL => 'OFFLINE_SYMBOL', + self::OFFSET_SYMBOL => 'OFFSET_SYMBOL', + self::OJ_SYMBOL => 'OJ_SYMBOL', + self::OLD_PASSWORD_SYMBOL => 'OLD_PASSWORD_SYMBOL', + self::OLD_SYMBOL => 'OLD_SYMBOL', + self::ON_SYMBOL => 'ON_SYMBOL', + self::ONLINE_SYMBOL => 'ONLINE_SYMBOL', + self::ONE_SYMBOL => 'ONE_SYMBOL', + self::ONLY_SYMBOL => 'ONLY_SYMBOL', + self::OPEN_SYMBOL => 'OPEN_SYMBOL', + self::OPTIONAL_SYMBOL => 'OPTIONAL_SYMBOL', + self::OPTIONALLY_SYMBOL => 'OPTIONALLY_SYMBOL', + self::OPTIONS_SYMBOL => 'OPTIONS_SYMBOL', + self::OPTION_SYMBOL => 'OPTION_SYMBOL', + self::OPTIMIZE_SYMBOL => 'OPTIMIZE_SYMBOL', + self::OPTIMIZER_COSTS_SYMBOL => 'OPTIMIZER_COSTS_SYMBOL', + self::ORDER_SYMBOL => 'ORDER_SYMBOL', + self::ORDINALITY_SYMBOL => 'ORDINALITY_SYMBOL', + self::ORGANIZATION_SYMBOL => 'ORGANIZATION_SYMBOL', + self::OR_SYMBOL => 'OR_SYMBOL', + self::OTHERS_SYMBOL => 'OTHERS_SYMBOL', + self::OUTER_SYMBOL => 'OUTER_SYMBOL', + self::OUTFILE_SYMBOL => 'OUTFILE_SYMBOL', + self::OUT_SYMBOL => 'OUT_SYMBOL', + self::OWNER_SYMBOL => 'OWNER_SYMBOL', + self::PACK_KEYS_SYMBOL => 'PACK_KEYS_SYMBOL', + self::PAGE_SYMBOL => 'PAGE_SYMBOL', + self::PARSER_SYMBOL => 'PARSER_SYMBOL', + self::PARTIAL_SYMBOL => 'PARTIAL_SYMBOL', + self::PARTITIONING_SYMBOL => 'PARTITIONING_SYMBOL', + self::PARTITIONS_SYMBOL => 'PARTITIONS_SYMBOL', + self::PARTITION_SYMBOL => 'PARTITION_SYMBOL', + self::PASSWORD_SYMBOL => 'PASSWORD_SYMBOL', + self::PATH_SYMBOL => 'PATH_SYMBOL', + self::PERCENT_RANK_SYMBOL => 'PERCENT_RANK_SYMBOL', + self::PERSIST_SYMBOL => 'PERSIST_SYMBOL', + self::PERSIST_ONLY_SYMBOL => 'PERSIST_ONLY_SYMBOL', + self::PHASE_SYMBOL => 'PHASE_SYMBOL', + self::PLUGIN_SYMBOL => 'PLUGIN_SYMBOL', + self::PLUGINS_SYMBOL => 'PLUGINS_SYMBOL', + self::PLUGIN_DIR_SYMBOL => 'PLUGIN_DIR_SYMBOL', + self::PORT_SYMBOL => 'PORT_SYMBOL', + self::POSITION_SYMBOL => 'POSITION_SYMBOL', + self::PRECEDES_SYMBOL => 'PRECEDES_SYMBOL', + self::PRECEDING_SYMBOL => 'PRECEDING_SYMBOL', + self::PRECISION_SYMBOL => 'PRECISION_SYMBOL', + self::PREPARE_SYMBOL => 'PREPARE_SYMBOL', + self::PRESERVE_SYMBOL => 'PRESERVE_SYMBOL', + self::PREV_SYMBOL => 'PREV_SYMBOL', + self::PRIMARY_SYMBOL => 'PRIMARY_SYMBOL', + self::PRIVILEGES_SYMBOL => 'PRIVILEGES_SYMBOL', + self::PRIVILEGE_CHECKS_USER_SYMBOL => 'PRIVILEGE_CHECKS_USER_SYMBOL', + self::PROCEDURE_SYMBOL => 'PROCEDURE_SYMBOL', + self::PROCESS_SYMBOL => 'PROCESS_SYMBOL', + self::PROCESSLIST_SYMBOL => 'PROCESSLIST_SYMBOL', + self::PROFILES_SYMBOL => 'PROFILES_SYMBOL', + self::PROFILE_SYMBOL => 'PROFILE_SYMBOL', + self::PROXY_SYMBOL => 'PROXY_SYMBOL', + self::PURGE_SYMBOL => 'PURGE_SYMBOL', + self::QUARTER_SYMBOL => 'QUARTER_SYMBOL', + self::QUERY_SYMBOL => 'QUERY_SYMBOL', + self::QUICK_SYMBOL => 'QUICK_SYMBOL', + self::RANDOM_SYMBOL => 'RANDOM_SYMBOL', + self::RANGE_SYMBOL => 'RANGE_SYMBOL', + self::RANK_SYMBOL => 'RANK_SYMBOL', + self::READS_SYMBOL => 'READS_SYMBOL', + self::READ_ONLY_SYMBOL => 'READ_ONLY_SYMBOL', + self::READ_SYMBOL => 'READ_SYMBOL', + self::READ_WRITE_SYMBOL => 'READ_WRITE_SYMBOL', + self::REBUILD_SYMBOL => 'REBUILD_SYMBOL', + self::RECOVER_SYMBOL => 'RECOVER_SYMBOL', + self::REDOFILE_SYMBOL => 'REDOFILE_SYMBOL', + self::REDO_BUFFER_SIZE_SYMBOL => 'REDO_BUFFER_SIZE_SYMBOL', + self::REDUNDANT_SYMBOL => 'REDUNDANT_SYMBOL', + self::REFERENCES_SYMBOL => 'REFERENCES_SYMBOL', + self::RECURSIVE_SYMBOL => 'RECURSIVE_SYMBOL', + self::REGEXP_SYMBOL => 'REGEXP_SYMBOL', + self::RELAYLOG_SYMBOL => 'RELAYLOG_SYMBOL', + self::RELAY_SYMBOL => 'RELAY_SYMBOL', + self::RELAY_LOG_FILE_SYMBOL => 'RELAY_LOG_FILE_SYMBOL', + self::RELAY_LOG_POS_SYMBOL => 'RELAY_LOG_POS_SYMBOL', + self::RELAY_THREAD_SYMBOL => 'RELAY_THREAD_SYMBOL', + self::RELEASE_SYMBOL => 'RELEASE_SYMBOL', + self::RELOAD_SYMBOL => 'RELOAD_SYMBOL', + self::REMOTE_SYMBOL => 'REMOTE_SYMBOL', + self::REMOVE_SYMBOL => 'REMOVE_SYMBOL', + self::RENAME_SYMBOL => 'RENAME_SYMBOL', + self::REORGANIZE_SYMBOL => 'REORGANIZE_SYMBOL', + self::REPAIR_SYMBOL => 'REPAIR_SYMBOL', + self::REPEAT_SYMBOL => 'REPEAT_SYMBOL', + self::REPEATABLE_SYMBOL => 'REPEATABLE_SYMBOL', + self::REPLACE_SYMBOL => 'REPLACE_SYMBOL', + self::REPLICATION_SYMBOL => 'REPLICATION_SYMBOL', + self::REPLICATE_DO_DB_SYMBOL => 'REPLICATE_DO_DB_SYMBOL', + self::REPLICATE_IGNORE_DB_SYMBOL => 'REPLICATE_IGNORE_DB_SYMBOL', + self::REPLICATE_DO_TABLE_SYMBOL => 'REPLICATE_DO_TABLE_SYMBOL', + self::REPLICATE_IGNORE_TABLE_SYMBOL => 'REPLICATE_IGNORE_TABLE_SYMBOL', + self::REPLICATE_WILD_DO_TABLE_SYMBOL => 'REPLICATE_WILD_DO_TABLE_SYMBOL', + self::REPLICATE_WILD_IGNORE_TABLE_SYMBOL => 'REPLICATE_WILD_IGNORE_TABLE_SYMBOL', + self::REPLICATE_REWRITE_DB_SYMBOL => 'REPLICATE_REWRITE_DB_SYMBOL', + self::REQUIRE_SYMBOL => 'REQUIRE_SYMBOL', + self::REQUIRE_ROW_FORMAT_SYMBOL => 'REQUIRE_ROW_FORMAT_SYMBOL', + self::REQUIRE_TABLE_PRIMARY_KEY_CHECK_SYMBOL => 'REQUIRE_TABLE_PRIMARY_KEY_CHECK_SYMBOL', + self::RESET_SYMBOL => 'RESET_SYMBOL', + self::RESIGNAL_SYMBOL => 'RESIGNAL_SYMBOL', + self::RESOURCE_SYMBOL => 'RESOURCE_SYMBOL', + self::RESPECT_SYMBOL => 'RESPECT_SYMBOL', + self::RESTART_SYMBOL => 'RESTART_SYMBOL', + self::RESTORE_SYMBOL => 'RESTORE_SYMBOL', + self::RESTRICT_SYMBOL => 'RESTRICT_SYMBOL', + self::RESUME_SYMBOL => 'RESUME_SYMBOL', + self::RETAIN_SYMBOL => 'RETAIN_SYMBOL', + self::RETURNED_SQLSTATE_SYMBOL => 'RETURNED_SQLSTATE_SYMBOL', + self::RETURNS_SYMBOL => 'RETURNS_SYMBOL', + self::REUSE_SYMBOL => 'REUSE_SYMBOL', + self::REVERSE_SYMBOL => 'REVERSE_SYMBOL', + self::REVOKE_SYMBOL => 'REVOKE_SYMBOL', + self::RIGHT_SYMBOL => 'RIGHT_SYMBOL', + self::RLIKE_SYMBOL => 'RLIKE_SYMBOL', + self::ROLE_SYMBOL => 'ROLE_SYMBOL', + self::ROLLBACK_SYMBOL => 'ROLLBACK_SYMBOL', + self::ROLLUP_SYMBOL => 'ROLLUP_SYMBOL', + self::ROTATE_SYMBOL => 'ROTATE_SYMBOL', + self::ROW_SYMBOL => 'ROW_SYMBOL', + self::ROWS_SYMBOL => 'ROWS_SYMBOL', + self::ROW_COUNT_SYMBOL => 'ROW_COUNT_SYMBOL', + self::ROW_FORMAT_SYMBOL => 'ROW_FORMAT_SYMBOL', + self::ROW_NUMBER_SYMBOL => 'ROW_NUMBER_SYMBOL', + self::RTREE_SYMBOL => 'RTREE_SYMBOL', + self::SAVEPOINT_SYMBOL => 'SAVEPOINT_SYMBOL', + self::SCHEMA_SYMBOL => 'SCHEMA_SYMBOL', + self::SCHEMAS_SYMBOL => 'SCHEMAS_SYMBOL', + self::SCHEMA_NAME_SYMBOL => 'SCHEMA_NAME_SYMBOL', + self::SCHEDULE_SYMBOL => 'SCHEDULE_SYMBOL', + self::SECOND_MICROSECOND_SYMBOL => 'SECOND_MICROSECOND_SYMBOL', + self::SECOND_SYMBOL => 'SECOND_SYMBOL', + self::SECONDARY_SYMBOL => 'SECONDARY_SYMBOL', + self::SECONDARY_ENGINE_SYMBOL => 'SECONDARY_ENGINE_SYMBOL', + self::SECONDARY_LOAD_SYMBOL => 'SECONDARY_LOAD_SYMBOL', + self::SECONDARY_UNLOAD_SYMBOL => 'SECONDARY_UNLOAD_SYMBOL', + self::SECURITY_SYMBOL => 'SECURITY_SYMBOL', + self::SELECT_SYMBOL => 'SELECT_SYMBOL', + self::SENSITIVE_SYMBOL => 'SENSITIVE_SYMBOL', + self::SEPARATOR_SYMBOL => 'SEPARATOR_SYMBOL', + self::SERIALIZABLE_SYMBOL => 'SERIALIZABLE_SYMBOL', + self::SERIAL_SYMBOL => 'SERIAL_SYMBOL', + self::SERVER_SYMBOL => 'SERVER_SYMBOL', + self::SERVER_OPTIONS_SYMBOL => 'SERVER_OPTIONS_SYMBOL', + self::SESSION_SYMBOL => 'SESSION_SYMBOL', + self::SESSION_USER_SYMBOL => 'SESSION_USER_SYMBOL', + self::SET_VAR_SYMBOL => 'SET_VAR_SYMBOL', + self::SHARE_SYMBOL => 'SHARE_SYMBOL', + self::SHOW_SYMBOL => 'SHOW_SYMBOL', + self::SHUTDOWN_SYMBOL => 'SHUTDOWN_SYMBOL', + self::SIGNAL_SYMBOL => 'SIGNAL_SYMBOL', + self::SIGNED_SYMBOL => 'SIGNED_SYMBOL', + self::SIMPLE_SYMBOL => 'SIMPLE_SYMBOL', + self::SKIP_SYMBOL => 'SKIP_SYMBOL', + self::SLAVE_SYMBOL => 'SLAVE_SYMBOL', + self::SLOW_SYMBOL => 'SLOW_SYMBOL', + self::SNAPSHOT_SYMBOL => 'SNAPSHOT_SYMBOL', + self::SOME_SYMBOL => 'SOME_SYMBOL', + self::SOCKET_SYMBOL => 'SOCKET_SYMBOL', + self::SONAME_SYMBOL => 'SONAME_SYMBOL', + self::SOUNDS_SYMBOL => 'SOUNDS_SYMBOL', + self::SOURCE_SYMBOL => 'SOURCE_SYMBOL', + self::SPATIAL_SYMBOL => 'SPATIAL_SYMBOL', + self::SQL_SYMBOL => 'SQL_SYMBOL', + self::SQLEXCEPTION_SYMBOL => 'SQLEXCEPTION_SYMBOL', + self::SQLSTATE_SYMBOL => 'SQLSTATE_SYMBOL', + self::SQLWARNING_SYMBOL => 'SQLWARNING_SYMBOL', + self::SQL_AFTER_GTIDS_SYMBOL => 'SQL_AFTER_GTIDS_SYMBOL', + self::SQL_AFTER_MTS_GAPS_SYMBOL => 'SQL_AFTER_MTS_GAPS_SYMBOL', + self::SQL_BEFORE_GTIDS_SYMBOL => 'SQL_BEFORE_GTIDS_SYMBOL', + self::SQL_BIG_RESULT_SYMBOL => 'SQL_BIG_RESULT_SYMBOL', + self::SQL_BUFFER_RESULT_SYMBOL => 'SQL_BUFFER_RESULT_SYMBOL', + self::SQL_CALC_FOUND_ROWS_SYMBOL => 'SQL_CALC_FOUND_ROWS_SYMBOL', + self::SQL_CACHE_SYMBOL => 'SQL_CACHE_SYMBOL', + self::SQL_NO_CACHE_SYMBOL => 'SQL_NO_CACHE_SYMBOL', + self::SQL_SMALL_RESULT_SYMBOL => 'SQL_SMALL_RESULT_SYMBOL', + self::SQL_THREAD_SYMBOL => 'SQL_THREAD_SYMBOL', + self::SQL_TSI_DAY_SYMBOL => 'SQL_TSI_DAY_SYMBOL', + self::SQL_TSI_HOUR_SYMBOL => 'SQL_TSI_HOUR_SYMBOL', + self::SQL_TSI_MICROSECOND_SYMBOL => 'SQL_TSI_MICROSECOND_SYMBOL', + self::SQL_TSI_MINUTE_SYMBOL => 'SQL_TSI_MINUTE_SYMBOL', + self::SQL_TSI_MONTH_SYMBOL => 'SQL_TSI_MONTH_SYMBOL', + self::SQL_TSI_QUARTER_SYMBOL => 'SQL_TSI_QUARTER_SYMBOL', + self::SQL_TSI_SECOND_SYMBOL => 'SQL_TSI_SECOND_SYMBOL', + self::SQL_TSI_WEEK_SYMBOL => 'SQL_TSI_WEEK_SYMBOL', + self::SQL_TSI_YEAR_SYMBOL => 'SQL_TSI_YEAR_SYMBOL', + self::SRID_SYMBOL => 'SRID_SYMBOL', + self::SSL_SYMBOL => 'SSL_SYMBOL', + self::STACKED_SYMBOL => 'STACKED_SYMBOL', + self::STARTING_SYMBOL => 'STARTING_SYMBOL', + self::START_SYMBOL => 'START_SYMBOL', + self::STARTS_SYMBOL => 'STARTS_SYMBOL', + self::STATS_AUTO_RECALC_SYMBOL => 'STATS_AUTO_RECALC_SYMBOL', + self::STATS_PERSISTENT_SYMBOL => 'STATS_PERSISTENT_SYMBOL', + self::STATS_SAMPLE_PAGES_SYMBOL => 'STATS_SAMPLE_PAGES_SYMBOL', + self::STATUS_SYMBOL => 'STATUS_SYMBOL', + self::STD_SYMBOL => 'STD_SYMBOL', + self::STDDEV_POP_SYMBOL => 'STDDEV_POP_SYMBOL', + self::STDDEV_SAMP_SYMBOL => 'STDDEV_SAMP_SYMBOL', + self::STDDEV_SYMBOL => 'STDDEV_SYMBOL', + self::STOP_SYMBOL => 'STOP_SYMBOL', + self::STORAGE_SYMBOL => 'STORAGE_SYMBOL', + self::STORED_SYMBOL => 'STORED_SYMBOL', + self::STRAIGHT_JOIN_SYMBOL => 'STRAIGHT_JOIN_SYMBOL', + self::STREAM_SYMBOL => 'STREAM_SYMBOL', + self::STRING_SYMBOL => 'STRING_SYMBOL', + self::SUBCLASS_ORIGIN_SYMBOL => 'SUBCLASS_ORIGIN_SYMBOL', + self::SUBDATE_SYMBOL => 'SUBDATE_SYMBOL', + self::SUBJECT_SYMBOL => 'SUBJECT_SYMBOL', + self::SUBPARTITIONS_SYMBOL => 'SUBPARTITIONS_SYMBOL', + self::SUBPARTITION_SYMBOL => 'SUBPARTITION_SYMBOL', + self::SUBSTR_SYMBOL => 'SUBSTR_SYMBOL', + self::SUBSTRING_SYMBOL => 'SUBSTRING_SYMBOL', + self::SUM_SYMBOL => 'SUM_SYMBOL', + self::SUPER_SYMBOL => 'SUPER_SYMBOL', + self::SUSPEND_SYMBOL => 'SUSPEND_SYMBOL', + self::SWAPS_SYMBOL => 'SWAPS_SYMBOL', + self::SWITCHES_SYMBOL => 'SWITCHES_SYMBOL', + self::SYSDATE_SYMBOL => 'SYSDATE_SYMBOL', + self::SYSTEM_SYMBOL => 'SYSTEM_SYMBOL', + self::SYSTEM_USER_SYMBOL => 'SYSTEM_USER_SYMBOL', + self::TABLE_SYMBOL => 'TABLE_SYMBOL', + self::TABLES_SYMBOL => 'TABLES_SYMBOL', + self::TABLESPACE_SYMBOL => 'TABLESPACE_SYMBOL', + self::TABLE_CHECKSUM_SYMBOL => 'TABLE_CHECKSUM_SYMBOL', + self::TABLE_NAME_SYMBOL => 'TABLE_NAME_SYMBOL', + self::TEMPORARY_SYMBOL => 'TEMPORARY_SYMBOL', + self::TEMPTABLE_SYMBOL => 'TEMPTABLE_SYMBOL', + self::TERMINATED_SYMBOL => 'TERMINATED_SYMBOL', + self::THAN_SYMBOL => 'THAN_SYMBOL', + self::THEN_SYMBOL => 'THEN_SYMBOL', + self::THREAD_PRIORITY_SYMBOL => 'THREAD_PRIORITY_SYMBOL', + self::TIES_SYMBOL => 'TIES_SYMBOL', + self::TIMESTAMP_ADD_SYMBOL => 'TIMESTAMP_ADD_SYMBOL', + self::TIMESTAMP_DIFF_SYMBOL => 'TIMESTAMP_DIFF_SYMBOL', + self::TO_SYMBOL => 'TO_SYMBOL', + self::TRAILING_SYMBOL => 'TRAILING_SYMBOL', + self::TRANSACTION_SYMBOL => 'TRANSACTION_SYMBOL', + self::TRIGGER_SYMBOL => 'TRIGGER_SYMBOL', + self::TRIGGERS_SYMBOL => 'TRIGGERS_SYMBOL', + self::TRIM_SYMBOL => 'TRIM_SYMBOL', + self::TRUE_SYMBOL => 'TRUE_SYMBOL', + self::TRUNCATE_SYMBOL => 'TRUNCATE_SYMBOL', + self::TYPES_SYMBOL => 'TYPES_SYMBOL', + self::TYPE_SYMBOL => 'TYPE_SYMBOL', + self::UDF_RETURNS_SYMBOL => 'UDF_RETURNS_SYMBOL', + self::UNBOUNDED_SYMBOL => 'UNBOUNDED_SYMBOL', + self::UNCOMMITTED_SYMBOL => 'UNCOMMITTED_SYMBOL', + self::UNDEFINED_SYMBOL => 'UNDEFINED_SYMBOL', + self::UNDO_BUFFER_SIZE_SYMBOL => 'UNDO_BUFFER_SIZE_SYMBOL', + self::UNDOFILE_SYMBOL => 'UNDOFILE_SYMBOL', + self::UNDO_SYMBOL => 'UNDO_SYMBOL', + self::UNICODE_SYMBOL => 'UNICODE_SYMBOL', + self::UNION_SYMBOL => 'UNION_SYMBOL', + self::UNIQUE_SYMBOL => 'UNIQUE_SYMBOL', + self::UNKNOWN_SYMBOL => 'UNKNOWN_SYMBOL', + self::UNINSTALL_SYMBOL => 'UNINSTALL_SYMBOL', + self::UNSIGNED_SYMBOL => 'UNSIGNED_SYMBOL', + self::UPDATE_SYMBOL => 'UPDATE_SYMBOL', + self::UPGRADE_SYMBOL => 'UPGRADE_SYMBOL', + self::USAGE_SYMBOL => 'USAGE_SYMBOL', + self::USER_RESOURCES_SYMBOL => 'USER_RESOURCES_SYMBOL', + self::USER_SYMBOL => 'USER_SYMBOL', + self::USE_FRM_SYMBOL => 'USE_FRM_SYMBOL', + self::USE_SYMBOL => 'USE_SYMBOL', + self::USING_SYMBOL => 'USING_SYMBOL', + self::UTC_DATE_SYMBOL => 'UTC_DATE_SYMBOL', + self::UTC_TIME_SYMBOL => 'UTC_TIME_SYMBOL', + self::UTC_TIMESTAMP_SYMBOL => 'UTC_TIMESTAMP_SYMBOL', + self::VALIDATION_SYMBOL => 'VALIDATION_SYMBOL', + self::VALUE_SYMBOL => 'VALUE_SYMBOL', + self::VALUES_SYMBOL => 'VALUES_SYMBOL', + self::VARCHARACTER_SYMBOL => 'VARCHARACTER_SYMBOL', + self::VARIABLES_SYMBOL => 'VARIABLES_SYMBOL', + self::VARIANCE_SYMBOL => 'VARIANCE_SYMBOL', + self::VARYING_SYMBOL => 'VARYING_SYMBOL', + self::VAR_POP_SYMBOL => 'VAR_POP_SYMBOL', + self::VAR_SAMP_SYMBOL => 'VAR_SAMP_SYMBOL', + self::VCPU_SYMBOL => 'VCPU_SYMBOL', + self::VIEW_SYMBOL => 'VIEW_SYMBOL', + self::VIRTUAL_SYMBOL => 'VIRTUAL_SYMBOL', + self::VISIBLE_SYMBOL => 'VISIBLE_SYMBOL', + self::WAIT_SYMBOL => 'WAIT_SYMBOL', + self::WARNINGS_SYMBOL => 'WARNINGS_SYMBOL', + self::WEEK_SYMBOL => 'WEEK_SYMBOL', + self::WHEN_SYMBOL => 'WHEN_SYMBOL', + self::WEIGHT_STRING_SYMBOL => 'WEIGHT_STRING_SYMBOL', + self::WHERE_SYMBOL => 'WHERE_SYMBOL', + self::WHILE_SYMBOL => 'WHILE_SYMBOL', + self::WINDOW_SYMBOL => 'WINDOW_SYMBOL', + self::WITH_SYMBOL => 'WITH_SYMBOL', + self::WITHOUT_SYMBOL => 'WITHOUT_SYMBOL', + self::WORK_SYMBOL => 'WORK_SYMBOL', + self::WRAPPER_SYMBOL => 'WRAPPER_SYMBOL', + self::WRITE_SYMBOL => 'WRITE_SYMBOL', + self::XA_SYMBOL => 'XA_SYMBOL', + self::X509_SYMBOL => 'X509_SYMBOL', + self::XID_SYMBOL => 'XID_SYMBOL', + self::XML_SYMBOL => 'XML_SYMBOL', + self::XOR_SYMBOL => 'XOR_SYMBOL', + self::YEAR_MONTH_SYMBOL => 'YEAR_MONTH_SYMBOL', + self::ZEROFILL_SYMBOL => 'ZEROFILL_SYMBOL', + self::INT1_SYMBOL => 'INT1_SYMBOL', + self::INT2_SYMBOL => 'INT2_SYMBOL', + self::INT3_SYMBOL => 'INT3_SYMBOL', + self::INT4_SYMBOL => 'INT4_SYMBOL', + self::INT8_SYMBOL => 'INT8_SYMBOL', + self::IDENTIFIER => 'IDENTIFIER', + self::BACK_TICK_QUOTED_ID => 'BACK_TICK_QUOTED_ID', + self::DOUBLE_QUOTED_TEXT => 'DOUBLE_QUOTED_TEXT', + self::SINGLE_QUOTED_TEXT => 'SINGLE_QUOTED_TEXT', + self::HEX_NUMBER => 'HEX_NUMBER', + self::BIN_NUMBER => 'BIN_NUMBER', + self::DECIMAL_NUMBER => 'DECIMAL_NUMBER', + self::FLOAT_NUMBER => 'FLOAT_NUMBER', + self::UNDERSCORE_CHARSET => 'UNDERSCORE_CHARSET', + self::DOT_IDENTIFIER => 'DOT_IDENTIFIER', + self::INVALID_INPUT => 'INVALID_INPUT', + self::LINEBREAK => 'LINEBREAK', + ]; + + protected function IDENTIFIER_OR_KEYWORD() + { + // Match the longest possible keyword. + while (safe_ctype_alnum($this->LA(1)) || $this->LA(1) === '_' || $this->LA(1) === '$') { + $this->consume(); + } + $text = $this->getText(); + + // Check for keywords that are also identifiers. + switch (strtoupper($text)) { + case 'ACCESSIBLE': + $this->ACCESSIBLE_SYMBOL(); + break; + case 'ACCOUNT': + if ($this->serverVersion >= 50707) { + $this->ACCOUNT_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'ACTION': + $this->ACTION_SYMBOL(); + break; + case 'ADD': + $this->ADD_SYMBOL(); + break; + case 'ADDDATE': + $this->ADDDATE_SYMBOL(); + break; + case 'AFTER': + $this->AFTER_SYMBOL(); + break; + case 'AGAINST': + $this->AGAINST_SYMBOL(); + break; + case 'AGGREGATE': + $this->AGGREGATE_SYMBOL(); + break; + case 'ALGORITHM': + $this->ALGORITHM_SYMBOL(); + break; + case 'ALL': + $this->ALL_SYMBOL(); + break; + case 'ALTER': + $this->ALTER_SYMBOL(); + break; + case 'ALWAYS': + if ($this->serverVersion >= 50707) { + $this->ALWAYS_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'ANALYSE': + if ($this->serverVersion < 80000) { + $this->ANALYSE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'ANALYZE': + $this->ANALYZE_SYMBOL(); + break; + case 'AND': + $this->AND_SYMBOL(); + break; + case 'ANY': + $this->ANY_SYMBOL(); + break; + case 'AS': + $this->AS_SYMBOL(); + break; + case 'ASC': + $this->ASC_SYMBOL(); + break; + case 'ASCII': + $this->ASCII_SYMBOL(); + break; + case 'ASENSITIVE': + $this->ASENSITIVE_SYMBOL(); + break; + case 'AT': + $this->AT_SYMBOL(); + break; + case 'AUTHORS': + if ($this->serverVersion < 50700) { + $this->AUTHORS_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'AUTOEXTEND_SIZE': + $this->AUTOEXTEND_SIZE_SYMBOL(); + break; + case 'AUTO_INCREMENT': + $this->AUTO_INCREMENT_SYMBOL(); + break; + case 'AVG': + $this->AVG_SYMBOL(); + break; + case 'AVG_ROW_LENGTH': + $this->AVG_ROW_LENGTH_SYMBOL(); + break; + case 'BACKUP': + $this->BACKUP_SYMBOL(); + break; + case 'BEFORE': + $this->BEFORE_SYMBOL(); + break; + case 'BEGIN': + $this->BEGIN_SYMBOL(); + break; + case 'BETWEEN': + $this->BETWEEN_SYMBOL(); + break; + case 'BIGINT': + $this->BIGINT_SYMBOL(); + break; + case 'BINARY': + $this->BINARY_SYMBOL(); + break; + case 'BINLOG': + $this->BINLOG_SYMBOL(); + break; + case 'BIT': + $this->BIT_SYMBOL(); + break; + case 'BIT_AND': + $this->BIT_AND_SYMBOL(); + break; + case 'BIT_OR': + $this->BIT_OR_SYMBOL(); + break; + case 'BIT_XOR': + $this->BIT_XOR_SYMBOL(); + break; + case 'BLOB': + $this->BLOB_SYMBOL(); + break; + case 'BLOCK': + $this->BLOCK_SYMBOL(); + break; + case 'BOOL': + $this->BOOL_SYMBOL(); + break; + case 'BOOLEAN': + $this->BOOLEAN_SYMBOL(); + break; + case 'BOTH': + $this->BOTH_SYMBOL(); + break; + case 'BTREE': + $this->BTREE_SYMBOL(); + break; + case 'BY': + $this->BY_SYMBOL(); + break; + case 'BYTE': + $this->BYTE_SYMBOL(); + break; + case 'CACHE': + $this->CACHE_SYMBOL(); + break; + case 'CALL': + $this->CALL_SYMBOL(); + break; + case 'CASCADE': + $this->CASCADE_SYMBOL(); + break; + case 'CASCADED': + $this->CASCADED_SYMBOL(); + break; + case 'CASE': + $this->CASE_SYMBOL(); + break; + case 'CAST': + $this->CAST_SYMBOL(); + break; + case 'CATALOG_NAME': + $this->CATALOG_NAME_SYMBOL(); + break; + case 'CHAIN': + $this->CHAIN_SYMBOL(); + break; + case 'CHANGE': + $this->CHANGE_SYMBOL(); + break; + case 'CHANGED': + $this->CHANGED_SYMBOL(); + break; + case 'CHANNEL': + if ($this->serverVersion >= 50706) { + $this->CHANNEL_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'CHAR': + $this->CHAR_SYMBOL(); + break; + case 'CHARSET': + $this->CHARSET_SYMBOL(); + break; + case 'CHARACTER': + $this->CHAR_SYMBOL(); // Synonym + break; + case 'CHECK': + $this->CHECK_SYMBOL(); + break; + case 'CHECKSUM': + $this->CHECKSUM_SYMBOL(); + break; + case 'CIPHER': + $this->CIPHER_SYMBOL(); + break; + case 'CLASS_ORIGIN': + $this->CLASS_ORIGIN_SYMBOL(); + break; + case 'CLIENT': + $this->CLIENT_SYMBOL(); + break; + case 'CLOSE': + $this->CLOSE_SYMBOL(); + break; + case 'COALESCE': + $this->COALESCE_SYMBOL(); + break; + case 'CODE': + $this->CODE_SYMBOL(); + break; + case 'COLLATE': + $this->COLLATE_SYMBOL(); + break; + case 'COLLATION': + $this->COLLATION_SYMBOL(); + break; + case 'COLUMN': + $this->COLUMN_SYMBOL(); + break; + case 'COLUMNS': + $this->COLUMNS_SYMBOL(); + break; + case 'COLUMN_FORMAT': + $this->COLUMN_FORMAT_SYMBOL(); + break; + case 'COLUMN_NAME': + $this->COLUMN_NAME_SYMBOL(); + break; + case 'COMMENT': + $this->COMMENT_SYMBOL(); + break; + case 'COMMITTED': + $this->COMMITTED_SYMBOL(); + break; + case 'COMMIT': + $this->COMMIT_SYMBOL(); + break; + case 'COMPACT': + $this->COMPACT_SYMBOL(); + break; + case 'COMPLETION': + $this->COMPLETION_SYMBOL(); + break; + case 'COMPRESSED': + $this->COMPRESSED_SYMBOL(); + break; + case 'COMPRESSION': + if ($this->serverVersion >= 50707) { + $this->COMPRESSION_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'CONCURRENT': + $this->CONCURRENT_SYMBOL(); + break; + case 'CONDITION': + $this->CONDITION_SYMBOL(); + break; + case 'CONNECTION': + $this->CONNECTION_SYMBOL(); + break; + case 'CONSISTENT': + $this->CONSISTENT_SYMBOL(); + break; + case 'CONSTRAINT': + $this->CONSTRAINT_SYMBOL(); + break; + case 'CONSTRAINTS': + $this->CONSTRAINTS_SYMBOL(); + break; + case 'CONSTRAINT_CATALOG': + $this->CONSTRAINT_CATALOG_SYMBOL(); + break; + case 'CONSTRAINT_NAME': + $this->CONSTRAINT_NAME_SYMBOL(); + break; + case 'CONSTRAINT_SCHEMA': + $this->CONSTRAINT_SCHEMA_SYMBOL(); + break; + case 'CONTAINS': + $this->CONTAINS_SYMBOL(); + break; + case 'CONTEXT': + $this->CONTEXT_SYMBOL(); + break; + case 'CONTINUE': + $this->CONTINUE_SYMBOL(); + break; + case 'CONTRIBUTORS': + if ($this->serverVersion < 50700) { + $this->CONTRIBUTORS_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'CONVERT': + $this->CONVERT_SYMBOL(); + break; + case 'COUNT': + $this->COUNT_SYMBOL(); + break; + case 'CPU': + $this->CPU_SYMBOL(); + break; + case 'CREATE': + $this->CREATE_SYMBOL(); + break; + case 'CROSS': + $this->CROSS_SYMBOL(); + break; + case 'CUBE': + if ($this->serverVersion < 80000) { + $this->CUBE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'CURDATE': + $this->CURDATE_SYMBOL(); + break; + case 'CURRENT': + if ($this->serverVersion >= 50604) { + $this->CURRENT_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'CURRENT_DATE': + $this->CURDATE_SYMBOL(); // Synonym + break; + case 'CURRENT_TIME': + $this->CURTIME_SYMBOL(); // Synonym + break; + case 'CURRENT_TIMESTAMP': + $this->NOW_SYMBOL(); // Synonym + break; + case 'CURRENT_USER': + $this->CURRENT_USER_SYMBOL(); + break; + case 'CURSOR': + $this->CURSOR_SYMBOL(); + break; + case 'CURSOR_NAME': + $this->CURSOR_NAME_SYMBOL(); + break; + case 'CURTIME': + $this->CURTIME_SYMBOL(); + break; + case 'DATABASE': + $this->DATABASE_SYMBOL(); + break; + case 'DATABASES': + $this->DATABASES_SYMBOL(); + break; + case 'DATAFILE': + $this->DATAFILE_SYMBOL(); + break; + case 'DATA': + $this->DATA_SYMBOL(); + break; + case 'DATETIME': + $this->DATETIME_SYMBOL(); + break; + case 'DATE': + $this->DATE_SYMBOL(); + break; + case 'DATE_ADD': + $this->DATE_ADD_SYMBOL(); + break; + case 'DATE_SUB': + $this->DATE_SUB_SYMBOL(); + break; + case 'DAY': + $this->DAY_SYMBOL(); + break; + case 'DAY_HOUR': + $this->DAY_HOUR_SYMBOL(); + break; + case 'DAY_MICROSECOND': + $this->DAY_MICROSECOND_SYMBOL(); + break; + case 'DAY_MINUTE': + $this->DAY_MINUTE_SYMBOL(); + break; + case 'DAY_SECOND': + $this->DAY_SECOND_SYMBOL(); + break; + case 'DAYOFMONTH': + $this->DAY_SYMBOL(); // Synonym + break; + case 'DEALLOCATE': + $this->DEALLOCATE_SYMBOL(); + break; + case 'DEC': + $this->DECIMAL_SYMBOL(); // Synonym + break; + case 'DECIMAL': + $this->DECIMAL_SYMBOL(); + break; + case 'DECLARE': + $this->DECLARE_SYMBOL(); + break; + case 'DEFAULT': + $this->DEFAULT_SYMBOL(); + break; + case 'DEFAULT_AUTH': + if ($this->serverVersion >= 50604) { + $this->DEFAULT_AUTH_SYMBOL(); // Internal + } else { + $this->IDENTIFIER(); + } + break; + case 'DEFINER': + $this->DEFINER_SYMBOL(); + break; + case 'DEFINITION': + if ($this->serverVersion >= 80011) { + $this->DEFINITION_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'DELAYED': + $this->DELAYED_SYMBOL(); + break; + case 'DELAY_KEY_WRITE': + $this->DELAY_KEY_WRITE_SYMBOL(); + break; + case 'DELETE': + $this->DELETE_SYMBOL(); + break; + case 'DENSE_RANK': + if ($this->serverVersion >= 80000) { + $this->DENSE_RANK_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'DESC': + $this->DESC_SYMBOL(); + break; + case 'DESCRIBE': + $this->DESCRIBE_SYMBOL(); + break; + case 'DESCRIPTION': + if ($this->serverVersion >= 80011) { + $this->DESCRIPTION_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'DES_KEY_FILE': + if ($this->serverVersion < 80000) { + $this->DES_KEY_FILE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'DETERMINISTIC': + $this->DETERMINISTIC_SYMBOL(); + break; + case 'DIAGNOSTICS': + $this->DIAGNOSTICS_SYMBOL(); + break; + case 'DIRECTORY': + $this->DIRECTORY_SYMBOL(); + break; + case 'DISABLE': + $this->DISABLE_SYMBOL(); + break; + case 'DISCARD': + $this->DISCARD_SYMBOL(); + break; + case 'DISK': + $this->DISK_SYMBOL(); + break; + case 'DISTINCT': + $this->DISTINCT_SYMBOL(); + break; + case 'DISTINCTROW': + $this->DISTINCT_SYMBOL(); // Synonym + break; + case 'DIV': + $this->DIV_SYMBOL(); + break; + case 'DOUBLE': + $this->DOUBLE_SYMBOL(); + break; + case 'DO': + $this->DO_SYMBOL(); + break; + case 'DROP': + $this->DROP_SYMBOL(); + break; + case 'DUAL': + $this->DUAL_SYMBOL(); + break; + case 'DUMPFILE': + $this->DUMPFILE_SYMBOL(); + break; + case 'DUPLICATE': + $this->DUPLICATE_SYMBOL(); + break; + case 'DYNAMIC': + $this->DYNAMIC_SYMBOL(); + break; + case 'EACH': + $this->EACH_SYMBOL(); + break; + case 'ELSE': + $this->ELSE_SYMBOL(); + break; + case 'ELSEIF': + $this->ELSEIF_SYMBOL(); + break; + case 'EMPTY': + if ($this->serverVersion >= 80000) { + $this->EMPTY_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'ENABLE': + $this->ENABLE_SYMBOL(); + break; + case 'ENCLOSED': + $this->ENCLOSED_SYMBOL(); + break; + case 'ENCRYPTION': + if ($this->serverVersion >= 50711) { + $this->ENCRYPTION_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'END': + $this->END_SYMBOL(); + break; + case 'ENDS': + $this->ENDS_SYMBOL(); + break; + case 'ENGINE': + $this->ENGINE_SYMBOL(); + break; + case 'ENGINES': + $this->ENGINES_SYMBOL(); + break; + case 'ENFORCED': + if ($this->serverVersion >= 80017) { + $this->ENFORCED_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'ENUM': + $this->ENUM_SYMBOL(); + break; + case 'ERRORS': + $this->ERRORS_SYMBOL(); + break; + case 'ERROR': + $this->ERROR_SYMBOL(); + break; + case 'ESCAPED': + $this->ESCAPED_SYMBOL(); + break; + case 'ESCAPE': + $this->ESCAPE_SYMBOL(); + break; + case 'EVENT': + $this->EVENT_SYMBOL(); + break; + case 'EVENTS': + $this->EVENTS_SYMBOL(); + break; + case 'EVERY': + $this->EVERY_SYMBOL(); + break; + case 'EXCEPT': + if ($this->serverVersion >= 80000) { + $this->EXCEPT_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'EXCHANGE': + $this->EXCHANGE_SYMBOL(); + break; + case 'EXCLUDE': + if ($this->serverVersion >= 80000) { + $this->EXCLUDE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'EXECUTE': + $this->EXECUTE_SYMBOL(); + break; + case 'EXISTS': + $this->EXISTS_SYMBOL(); + break; + case 'EXIT': + $this->EXIT_SYMBOL(); + break; + case 'EXPANSION': + $this->EXPANSION_SYMBOL(); + break; + case 'EXPIRE': + if ($this->serverVersion >= 50606) { + $this->EXPIRE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'EXPLAIN': + $this->EXPLAIN_SYMBOL(); + break; + case 'EXPORT': + if ($this->serverVersion >= 50606) { + $this->EXPORT_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'EXTENDED': + $this->EXTENDED_SYMBOL(); + break; + case 'EXTENT_SIZE': + $this->EXTENT_SIZE_SYMBOL(); + break; + case 'EXTRACT': + $this->EXTRACT_SYMBOL(); + break; + case 'FALSE': + $this->FALSE_SYMBOL(); + break; + case 'FAILED_LOGIN_ATTEMPTS': + if ($this->serverVersion >= 80019) { + $this->FAILED_LOGIN_ATTEMPTS_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'FAST': + $this->FAST_SYMBOL(); + break; + case 'FAULTS': + $this->FAULTS_SYMBOL(); + break; + case 'FETCH': + $this->FETCH_SYMBOL(); + break; + case 'FIELDS': + $this->COLUMNS_SYMBOL(); // Synonym + break; + case 'FILE': + $this->FILE_SYMBOL(); + break; + case 'FILE_BLOCK_SIZE': + if ($this->serverVersion >= 50707) { + $this->FILE_BLOCK_SIZE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'FILTER': + if ($this->serverVersion >= 50700) { + $this->FILTER_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'FIRST': + $this->FIRST_SYMBOL(); + break; + case 'FIRST_VALUE': + if ($this->serverVersion >= 80000) { + $this->FIRST_VALUE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'FIXED': + $this->FIXED_SYMBOL(); + break; + case 'FLOAT': + $this->FLOAT_SYMBOL(); + break; + case 'FLOAT4': + $this->FLOAT_SYMBOL(); // Synonym + break; + case 'FLOAT8': + $this->DOUBLE_SYMBOL(); // Synonym + break; + case 'FLUSH': + $this->FLUSH_SYMBOL(); + break; + case 'FOLLOWS': + if ($this->serverVersion >= 50700) { + $this->FOLLOWS_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'FOLLOWING': + if ($this->serverVersion >= 80000) { + $this->FOLLOWING_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'FORCE': + $this->FORCE_SYMBOL(); + break; + case 'FOR': + $this->FOR_SYMBOL(); + break; + case 'FOREIGN': + $this->FOREIGN_SYMBOL(); + break; + case 'FORMAT': + $this->FORMAT_SYMBOL(); + break; + case 'FOUND': + $this->FOUND_SYMBOL(); + break; + case 'FROM': + $this->FROM_SYMBOL(); + break; + case 'FULL': + $this->FULL_SYMBOL(); + break; + case 'FULLTEXT': + $this->FULLTEXT_SYMBOL(); + break; + case 'FUNCTION': + if ($this->serverVersion < 80000) { + $this->FUNCTION_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'GENERATED': + if ($this->serverVersion >= 50707) { + $this->GENERATED_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'GENERAL': + $this->GENERAL_SYMBOL(); + break; + case 'GEOMETRYCOLLECTION': + $this->GEOMETRYCOLLECTION_SYMBOL(); + break; + case 'GEOMETRY': + $this->GEOMETRY_SYMBOL(); + break; + case 'GET': + if ($this->serverVersion >= 50604) { + $this->GET_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'GET_FORMAT': + $this->GET_FORMAT_SYMBOL(); + break; + case 'GLOBAL': + $this->GLOBAL_SYMBOL(); + break; + case 'GRANT': + $this->GRANT_SYMBOL(); + break; + case 'GRANTS': + $this->GRANTS_SYMBOL(); + break; + case 'GROUP': + $this->GROUP_SYMBOL(); + break; + case 'GROUP_CONCAT': + $this->GROUP_CONCAT_SYMBOL(); + break; + case 'GROUP_REPLICATION': + if ($this->serverVersion >= 50707) { + $this->GROUP_REPLICATION_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'GROUPING': + if ($this->serverVersion >= 80000) { + $this->GROUPING_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'GROUPS': + if ($this->serverVersion >= 80000) { + $this->GROUPS_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'HANDLER': + $this->HANDLER_SYMBOL(); + break; + case 'HASH': + $this->HASH_SYMBOL(); + break; + case 'HAVING': + $this->HAVING_SYMBOL(); + break; + case 'HELP': + $this->HELP_SYMBOL(); + break; + case 'HIGH_PRIORITY': + $this->HIGH_PRIORITY_SYMBOL(); + break; + case 'HISTOGRAM': + if ($this->serverVersion >= 80000) { + $this->HISTOGRAM_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'HISTORY': + if ($this->serverVersion >= 80000) { + $this->HISTORY_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'HOST': + $this->HOST_SYMBOL(); + break; + case 'HOSTS': + $this->HOSTS_SYMBOL(); + break; + case 'HOUR': + $this->HOUR_SYMBOL(); + break; + case 'HOUR_MICROSECOND': + $this->HOUR_MICROSECOND_SYMBOL(); + break; + case 'HOUR_MINUTE': + $this->HOUR_MINUTE_SYMBOL(); + break; + case 'HOUR_SECOND': + $this->HOUR_SECOND_SYMBOL(); + break; + case 'IDENTIFIED': + $this->IDENTIFIED_SYMBOL(); + break; + case 'IF': + $this->IF_SYMBOL(); + break; + case 'IGNORE': + $this->IGNORE_SYMBOL(); + break; + case 'IGNORE_SERVER_IDS': + $this->IGNORE_SERVER_IDS_SYMBOL(); + break; + case 'IMPORT': + if ($this->serverVersion < 80000) { + $this->IMPORT_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'IN': + $this->IN_SYMBOL(); + break; + case 'INDEX': + $this->INDEX_SYMBOL(); + break; + case 'INDEXES': + $this->INDEXES_SYMBOL(); + break; + case 'INFILE': + $this->INFILE_SYMBOL(); + break; + case 'INITIAL_SIZE': + $this->INITIAL_SIZE_SYMBOL(); + break; + case 'INNER': + $this->INNER_SYMBOL(); + break; + case 'INOUT': + $this->INOUT_SYMBOL(); + break; + case 'INSENSITIVE': + $this->INSENSITIVE_SYMBOL(); + break; + case 'INSERT': + $this->INSERT_SYMBOL(); + break; + case 'INSERT_METHOD': + $this->INSERT_METHOD_SYMBOL(); + break; + case 'INSTANCE': + if ($this->serverVersion >= 50713) { + $this->INSTANCE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'INSTALL': + $this->INSTALL_SYMBOL(); + break; + case 'INT': + $this->INT_SYMBOL(); + break; + case 'INTEGER': + $this->INT_SYMBOL(); // Synonym + break; + case 'INTERVAL': + $this->INTERVAL_SYMBOL(); + break; + case 'INTO': + $this->INTO_SYMBOL(); + break; + case 'INVISIBLE': + if ($this->serverVersion >= 80000) { + $this->INVISIBLE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'INVOKER': + $this->INVOKER_SYMBOL(); + break; + case 'IO_THREAD': + $this->RELAY_THREAD_SYMBOL(); // Synonym + break; + case 'IO_AFTER_GTIDS': + $this->IDENTIFIER(); // MYSQL, FUTURE-USE + break; + case 'IO_BEFORE_GTIDS': + $this->IDENTIFIER(); // MYSQL, FUTURE-USE + break; + case 'IO': + $this->IO_SYMBOL(); + break; + case 'IPC': + $this->IPC_SYMBOL(); + break; + case 'IS': + $this->IS_SYMBOL(); + break; + case 'ISOLATION': + $this->ISOLATION_SYMBOL(); + break; + case 'ISSUER': + $this->ISSUER_SYMBOL(); + break; + case 'ITERATE': + $this->ITERATE_SYMBOL(); + break; + case 'JOIN': + $this->JOIN_SYMBOL(); + break; + case 'JSON': + if ($this->serverVersion >= 50708) { + $this->JSON_SYMBOL(); // MYSQL + } else { + $this->IDENTIFIER(); + } + break; + case 'JSON_TABLE': + if ($this->serverVersion >= 80000) { + $this->JSON_TABLE_SYMBOL(); // SQL-2016-R + } else { + $this->IDENTIFIER(); + } + break; + case 'JSON_ARRAYAGG': + if ($this->serverVersion >= 80000) { + $this->JSON_ARRAYAGG_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'JSON_OBJECTAGG': + if ($this->serverVersion >= 80000) { + $this->JSON_OBJECTAGG_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'KEY': + $this->KEY_SYMBOL(); + break; + case 'KEYS': + $this->KEYS_SYMBOL(); + break; + case 'KEY_BLOCK_SIZE': + $this->KEY_BLOCK_SIZE_SYMBOL(); + break; + case 'KILL': + $this->KILL_SYMBOL(); + break; + case 'LAG': + if ($this->serverVersion >= 80000) { + $this->LAG_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'LANGUAGE': + $this->LANGUAGE_SYMBOL(); + break; + case 'LAST': + $this->LAST_SYMBOL(); + break; + case 'LAST_VALUE': + if ($this->serverVersion >= 80000) { + $this->LAST_VALUE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'LATERAL': + if ($this->serverVersion >= 80014) { + $this->LATERAL_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'LEAD': + if ($this->serverVersion >= 80000) { + $this->LEAD_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'LEADING': + $this->LEADING_SYMBOL(); + break; + case 'LEAVE': + $this->LEAVE_SYMBOL(); + break; + case 'LEAVES': + $this->LEAVES_SYMBOL(); + break; + case 'LEFT': + $this->LEFT_SYMBOL(); + break; + case 'LESS': + $this->LESS_SYMBOL(); + break; + case 'LEVEL': + $this->LEVEL_SYMBOL(); + break; + case 'LIKE': + $this->LIKE_SYMBOL(); + break; + case 'LIMIT': + $this->LIMIT_SYMBOL(); + break; + case 'LINEAR': + $this->LINEAR_SYMBOL(); + break; + case 'LINES': + $this->LINES_SYMBOL(); + break; + case 'LINESTRING': + $this->LINESTRING_SYMBOL(); + break; + case 'LIST': + $this->LIST_SYMBOL(); + break; + case 'LOAD': + $this->LOAD_SYMBOL(); + break; + case 'LOCAL': + $this->LOCAL_SYMBOL(); + break; + case 'LOCALTIME': + $this->NOW_SYMBOL(); // Synonym + break; + case 'LOCALTIMESTAMP': + $this->NOW_SYMBOL(); // Synonym + break; + case 'LOCATOR': + $this->LOCATOR_SYMBOL(); + break; + case 'LOCK': + $this->LOCK_SYMBOL(); + break; + case 'LOCKS': + $this->LOCKS_SYMBOL(); + break; + case 'LOGFILE': + $this->LOGFILE_SYMBOL(); + break; + case 'LOGS': + $this->LOGS_SYMBOL(); + break; + case 'LONGBLOB': + $this->LONGBLOB_SYMBOL(); + break; + case 'LONGTEXT': + $this->LONGTEXT_SYMBOL(); + break; + case 'LONG': + $this->LONG_SYMBOL(); + break; + case 'LOOP': + $this->LOOP_SYMBOL(); + break; + case 'LOW_PRIORITY': + $this->LOW_PRIORITY_SYMBOL(); + break; + case 'MASTER': + $this->MASTER_SYMBOL(); + break; + case 'MASTER_AUTO_POSITION': + if ($this->serverVersion >= 50605) { + $this->MASTER_AUTO_POSITION_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'MASTER_BIND': + if ($this->serverVersion >= 50602) { + $this->MASTER_BIND_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'MASTER_COMPRESSION_ALGORITHM': + if ($this->serverVersion >= 80018) { + $this->MASTER_COMPRESSION_ALGORITHM_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'MASTER_CONNECT_RETRY': + $this->MASTER_CONNECT_RETRY_SYMBOL(); + break; + case 'MASTER_DELAY': + $this->MASTER_DELAY_SYMBOL(); + break; + case 'MASTER_HEARTBEAT_PERIOD': + $this->MASTER_HEARTBEAT_PERIOD_SYMBOL(); + break; + case 'MASTER_HOST': + $this->MASTER_HOST_SYMBOL(); + break; + case 'MASTER_LOG_FILE': + $this->MASTER_LOG_FILE_SYMBOL(); + break; + case 'MASTER_LOG_POS': + $this->MASTER_LOG_POS_SYMBOL(); + break; + case 'MASTER_PASSWORD': + $this->MASTER_PASSWORD_SYMBOL(); + break; + case 'MASTER_PORT': + $this->MASTER_PORT_SYMBOL(); + break; + case 'MASTER_PUBLIC_KEY_PATH': + if ($this->serverVersion >= 80000) { + $this->MASTER_PUBLIC_KEY_PATH_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'MASTER_RETRY_COUNT': + if ($this->serverVersion >= 50601) { + $this->MASTER_RETRY_COUNT_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'MASTER_SERVER_ID': + $this->MASTER_SERVER_ID_SYMBOL(); + break; + case 'MASTER_SSL': + $this->MASTER_SSL_SYMBOL(); + break; + case 'MASTER_SSL_CA': + $this->MASTER_SSL_CA_SYMBOL(); + break; + case 'MASTER_SSL_CAPATH': + $this->MASTER_SSL_CAPATH_SYMBOL(); + break; + case 'MASTER_SSL_CERT': + $this->MASTER_SSL_CERT_SYMBOL(); + break; + case 'MASTER_SSL_CIPHER': + $this->MASTER_SSL_CIPHER_SYMBOL(); + break; + case 'MASTER_SSL_CRL': + if ($this->serverVersion >= 50603) { + $this->MASTER_SSL_CRL_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'MASTER_SSL_CRLPATH': + if ($this->serverVersion >= 50603) { + $this->MASTER_SSL_CRLPATH_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'MASTER_SSL_KEY': + $this->MASTER_SSL_KEY_SYMBOL(); + break; + case 'MASTER_SSL_VERIFY_SERVER_CERT': + $this->MASTER_SSL_VERIFY_SERVER_CERT_SYMBOL(); + break; + case 'MASTER_TLS_CIPHERSUITES': + if ($this->serverVersion >= 80018) { + $this->MASTER_TLS_CIPHERSUITES_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'MASTER_TLS_VERSION': + if ($this->serverVersion >= 50713) { + $this->MASTER_TLS_VERSION_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'MASTER_USER': + $this->MASTER_USER_SYMBOL(); + break; + case 'MASTER_ZSTD_COMPRESSION_LEVEL': + if ($this->serverVersion >= 80018) { + $this->MASTER_ZSTD_COMPRESSION_LEVEL_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'MATCH': + $this->MATCH_SYMBOL(); + break; + case 'MAX': + $this->MAX_SYMBOL(); + break; + case 'MAX_CONNECTIONS_PER_HOUR': + $this->MAX_CONNECTIONS_PER_HOUR_SYMBOL(); + break; + case 'MAX_QUERIES_PER_HOUR': + $this->MAX_QUERIES_PER_HOUR_SYMBOL(); + break; + case 'MAX_ROWS': + $this->MAX_ROWS_SYMBOL(); + break; + case 'MAX_SIZE': + $this->MAX_SIZE_SYMBOL(); + break; + case 'MAX_STATEMENT_TIME': + if (50704 < $this->serverVersion && $this->serverVersion < 50708) { + $this->MAX_STATEMENT_TIME_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'MAX_UPDATES_PER_HOUR': + $this->MAX_UPDATES_PER_HOUR_SYMBOL(); + break; + case 'MAX_USER_CONNECTIONS': + $this->MAX_USER_CONNECTIONS_SYMBOL(); + break; + case 'MAXVALUE': + $this->MAXVALUE_SYMBOL(); + break; + case 'MEDIUM': + $this->MEDIUM_SYMBOL(); + break; + case 'MEDIUMBLOB': + $this->MEDIUMBLOB_SYMBOL(); + break; + case 'MEDIUMINT': + $this->MEDIUMINT_SYMBOL(); + break; + case 'MEDIUMTEXT': + $this->MEDIUMTEXT_SYMBOL(); + break; + case 'MEMBER': + if ($this->serverVersion >= 80017) { + $this->MEMBER_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'MEMORY': + $this->MEMORY_SYMBOL(); + break; + case 'MERGE': + $this->MERGE_SYMBOL(); + break; + case 'MESSAGE_TEXT': + $this->MESSAGE_TEXT_SYMBOL(); + break; + case 'MICROSECOND': + $this->MICROSECOND_SYMBOL(); + break; + case 'MIDDLEINT': + $this->MEDIUMINT_SYMBOL(); // Synonym + break; + case 'MIGRATE': + $this->MIGRATE_SYMBOL(); + break; + case 'MINUTE': + $this->MINUTE_SYMBOL(); + break; + case 'MINUTE_MICROSECOND': + $this->MINUTE_MICROSECOND_SYMBOL(); + break; + case 'MINUTE_SECOND': + $this->MINUTE_SECOND_SYMBOL(); + break; + case 'MIN': + $this->MIN_SYMBOL(); + break; + case 'MIN_ROWS': + $this->MIN_ROWS_SYMBOL(); + break; + case 'MODE': + $this->MODE_SYMBOL(); + break; + case 'MODIFIES': + $this->MODIFIES_SYMBOL(); + break; + case 'MODIFY': + $this->MODIFY_SYMBOL(); + break; + case 'MOD': + $this->MOD_SYMBOL(); + break; + case 'MONTH': + $this->MONTH_SYMBOL(); + break; + case 'MULTILINESTRING': + $this->MULTILINESTRING_SYMBOL(); + break; + case 'MULTIPOINT': + $this->MULTIPOINT_SYMBOL(); + break; + case 'MULTIPOLYGON': + $this->MULTIPOLYGON_SYMBOL(); + break; + case 'MUTEX': + $this->MUTEX_SYMBOL(); + break; + case 'MYSQL_ERRNO': + $this->MYSQL_ERRNO_SYMBOL(); + break; + case 'NAME': + $this->NAME_SYMBOL(); + break; + case 'NAMES': + $this->NAMES_SYMBOL(); + break; + case 'NATIONAL': + $this->NATIONAL_SYMBOL(); + break; + case 'NATURAL': + $this->NATURAL_SYMBOL(); + break; + case 'NCHAR': + $this->NCHAR_SYMBOL(); + break; + case 'NDB': + $this->NDBCLUSTER_SYMBOL(); // Synonym + break; + case 'NDBCLUSTER': + $this->NDBCLUSTER_SYMBOL(); + break; + case 'NETWORK_NAMESPACE': + if ($this->serverVersion >= 80017) { + $this->NETWORK_NAMESPACE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'NEG': + $this->NEG_SYMBOL(); + break; + case 'NESTED': + if ($this->serverVersion >= 80000) { + $this->NESTED_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'NEVER': + if ($this->serverVersion >= 50704) { + $this->NEVER_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'NEW': + $this->NEW_SYMBOL(); + break; + case 'NEXT': + $this->NEXT_SYMBOL(); + break; + case 'NODEGROUP': + $this->NODEGROUP_SYMBOL(); + break; + case 'NONE': + $this->NONE_SYMBOL(); + break; + case 'NONBLOCKING': + if (50700 < $this->serverVersion && $this->serverVersion < 50706) { + $this->NONBLOCKING_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'NOT': + $this->NOT_SYMBOL(); + break; + case 'NOW': + $this->NOW_SYMBOL(); + break; + case 'NOWAIT': + if ($this->serverVersion >= 80000) { + $this->NOWAIT_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'NO': + $this->NO_SYMBOL(); + break; + case 'NO_WAIT': + $this->NO_WAIT_SYMBOL(); + break; + case 'NO_WRITE_TO_BINLOG': + $this->NO_WRITE_TO_BINLOG_SYMBOL(); + break; + case 'NULL': + $this->NULL_SYMBOL(); + break; + case 'NULLS': + if ($this->serverVersion >= 80000) { + $this->NULLS_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'NUMBER': + if ($this->serverVersion >= 50606) { + $this->NUMBER_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'NUMERIC': + $this->NUMERIC_SYMBOL(); + break; + case 'NVARCHAR': + $this->NVARCHAR_SYMBOL(); + break; + case 'NTH_VALUE': + if ($this->serverVersion >= 80000) { + $this->NTH_VALUE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'NTILE': + if ($this->serverVersion >= 80000) { + $this->NTILE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'OFF': + if ($this->serverVersion >= 80019) { + $this->OFF_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'OF': + if ($this->serverVersion >= 80000) { + $this->OF_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'OFFLINE': + $this->OFFLINE_SYMBOL(); + break; + case 'OFFSET': + $this->OFFSET_SYMBOL(); + break; + case 'OJ': + if ($this->serverVersion >= 80017) { + $this->OJ_SYMBOL(); // ODBC + } else { + $this->IDENTIFIER(); + } + break; + case 'OLD': + if ($this->serverVersion >= 80014) { + $this->OLD_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'OLD_PASSWORD': + if ($this->serverVersion < 50706) { + $this->OLD_PASSWORD_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'ON': + $this->ON_SYMBOL(); + break; + case 'ONE': + $this->ONE_SYMBOL(); + break; + case 'ONLINE': + $this->ONLINE_SYMBOL(); + break; + case 'ONLY': + if ($this->serverVersion >= 50605) { + $this->ONLY_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'OPEN': + $this->OPEN_SYMBOL(); + break; + case 'OPTIONAL': + if ($this->serverVersion >= 80013) { + $this->OPTIONAL_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'OPTIONALLY': + $this->OPTIONALLY_SYMBOL(); + break; + case 'OPTION': + $this->OPTION_SYMBOL(); + break; + case 'OPTIONS': + $this->OPTIONS_SYMBOL(); + break; + case 'OPTIMIZE': + $this->OPTIMIZE_SYMBOL(); + break; + case 'OPTIMIZER_COSTS': + if ($this->serverVersion >= 50706) { + $this->OPTIMIZER_COSTS_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'OR': + $this->OR_SYMBOL(); + break; + case 'ORDER': + $this->ORDER_SYMBOL(); + break; + case 'ORDINALITY': + if ($this->serverVersion >= 80000) { + $this->ORDINALITY_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'ORGANIZATION': + if ($this->serverVersion >= 80011) { + $this->ORGANIZATION_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'OTHERS': + if ($this->serverVersion >= 80000) { + $this->OTHERS_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'OUTER': + $this->OUTER_SYMBOL(); + break; + case 'OUTFILE': + $this->OUTFILE_SYMBOL(); + break; + case 'OUT': + $this->OUT_SYMBOL(); + break; + case 'OWNER': + $this->OWNER_SYMBOL(); + break; + case 'PACK_KEYS': + $this->PACK_KEYS_SYMBOL(); + break; + case 'PAGE': + $this->PAGE_SYMBOL(); + break; + case 'PARSER': + $this->PARSER_SYMBOL(); + break; + case 'PARTIAL': + $this->PARTIAL_SYMBOL(); + break; + case 'PARTITION': + $this->PARTITION_SYMBOL(); + break; + case 'PARTITIONING': + $this->PARTITIONING_SYMBOL(); + break; + case 'PARTITIONS': + $this->PARTITIONS_SYMBOL(); + break; + case 'PASSWORD': + $this->PASSWORD_SYMBOL(); + break; + case 'PASSWORD_LOCK_TIME': + if ($this->serverVersion >= 80019) { + $this->PASSWORD_LOCK_TIME_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'PATH': + if ($this->serverVersion >= 80000) { + $this->PATH_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'PERCENT_RANK': + if ($this->serverVersion >= 80000) { + $this->PERCENT_RANK_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'PERSIST': + if ($this->serverVersion >= 80000) { + $this->PERSIST_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'PERSIST_ONLY': + if ($this->serverVersion >= 80000) { + $this->PERSIST_ONLY_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'PHASE': + $this->PHASE_SYMBOL(); + break; + case 'PLUGIN': + $this->PLUGIN_SYMBOL(); + break; + case 'PLUGINS': + $this->PLUGINS_SYMBOL(); + break; + case 'PLUGIN_DIR': + if ($this->serverVersion >= 50604) { + $this->PLUGIN_DIR_SYMBOL(); // Internal + } else { + $this->IDENTIFIER(); + } + break; + case 'POINT': + $this->POINT_SYMBOL(); + break; + case 'POLYGON': + $this->POLYGON_SYMBOL(); + break; + case 'PORT': + $this->PORT_SYMBOL(); + break; + case 'POSITION': + $this->POSITION_SYMBOL(); + break; + case 'PRECEDES': + if ($this->serverVersion >= 50700) { + $this->PRECEDES_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'PRECEDING': + if ($this->serverVersion >= 80000) { + $this->PRECEDING_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'PRECISION': + $this->PRECISION_SYMBOL(); + break; + case 'PREPARE': + $this->PREPARE_SYMBOL(); + break; + case 'PRESERVE': + $this->PRESERVE_SYMBOL(); + break; + case 'PREV': + $this->PREV_SYMBOL(); + break; + case 'PRIMARY': + $this->PRIMARY_SYMBOL(); + break; + case 'PRIVILEGE_CHECKS_USER': + if ($this->serverVersion >= 80018) { + $this->PRIVILEGE_CHECKS_USER_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'PRIVILEGES': + $this->PRIVILEGES_SYMBOL(); + break; + case 'PROCEDURE': + $this->PROCEDURE_SYMBOL(); + break; + case 'PROCESS': + $this->PROCESS_SYMBOL(); + break; + case 'PROCESSLIST': + $this->PROCESSLIST_SYMBOL(); + break; + case 'PROFILE': + $this->PROFILE_SYMBOL(); + break; + case 'PROFILES': + $this->PROFILES_SYMBOL(); + break; + case 'PROXY': + $this->PROXY_SYMBOL(); + break; + case 'PURGE': + $this->PURGE_SYMBOL(); + break; + case 'QUARTER': + $this->QUARTER_SYMBOL(); + break; + case 'QUERY': + $this->QUERY_SYMBOL(); + break; + case 'QUICK': + $this->QUICK_SYMBOL(); + break; + case 'RANDOM': + if ($this->serverVersion >= 80018) { + $this->RANDOM_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'RANGE': + $this->RANGE_SYMBOL(); + break; + case 'RANK': + if ($this->serverVersion >= 80000) { + $this->RANK_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'READ': + $this->READ_SYMBOL(); + break; + case 'READS': + $this->READS_SYMBOL(); + break; + case 'READ_ONLY': + $this->READ_ONLY_SYMBOL(); + break; + case 'READ_WRITE': + $this->READ_WRITE_SYMBOL(); + break; + case 'REAL': + $this->REAL_SYMBOL(); + break; + case 'REBUILD': + $this->REBUILD_SYMBOL(); + break; + case 'RECOVER': + $this->RECOVER_SYMBOL(); + break; + case 'RECURSIVE': + if ($this->serverVersion >= 80000) { + $this->RECURSIVE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'REDOFILE': + if ($this->serverVersion < 80000) { + $this->REDOFILE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'REDO_BUFFER_SIZE': + $this->REDO_BUFFER_SIZE_SYMBOL(); + break; + case 'REDUNDANT': + $this->REDUNDANT_SYMBOL(); + break; + case 'REFERENCE': + if ($this->serverVersion >= 80011) { + $this->REFERENCE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'REFERENCES': + $this->REFERENCES_SYMBOL(); + break; + case 'REGEXP': + $this->REGEXP_SYMBOL(); + break; + case 'RELAY': + $this->RELAY_SYMBOL(); + break; + case 'RELAYLOG': + $this->RELAYLOG_SYMBOL(); + break; + case 'RELAY_LOG_FILE': + $this->RELAY_LOG_FILE_SYMBOL(); + break; + case 'RELAY_LOG_POS': + $this->RELAY_LOG_POS_SYMBOL(); + break; + case 'RELAY_THREAD': + $this->RELAY_THREAD_SYMBOL(); + break; + case 'RELEASE': + $this->RELEASE_SYMBOL(); + break; + case 'RELOAD': + $this->RELOAD_SYMBOL(); + break; + case 'REMOTE': + if ($this->serverVersion >= 80003 && $this->serverVersion < 80014) { + $this->REMOTE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'REMOVE': + $this->REMOVE_SYMBOL(); + break; + case 'RENAME': + $this->RENAME_SYMBOL(); + break; + case 'REORGANIZE': + $this->REORGANIZE_SYMBOL(); + break; + case 'REPAIR': + $this->REPAIR_SYMBOL(); + break; + case 'REPEAT': + $this->REPEAT_SYMBOL(); + break; + case 'REPEATABLE': + $this->REPEATABLE_SYMBOL(); + break; + case 'REPLACE': + $this->REPLACE_SYMBOL(); + break; + case 'REPLICATION': + $this->REPLICATION_SYMBOL(); + break; + case 'REPLICATE_DO_DB': + if ($this->serverVersion >= 50700) { + $this->REPLICATE_DO_DB_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'REPLICATE_IGNORE_DB': + if ($this->serverVersion >= 50700) { + $this->REPLICATE_IGNORE_DB_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'REPLICATE_DO_TABLE': + if ($this->serverVersion >= 50700) { + $this->REPLICATE_DO_TABLE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'REPLICATE_IGNORE_TABLE': + if ($this->serverVersion >= 50700) { + $this->REPLICATE_IGNORE_TABLE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'REPLICATE_WILD_DO_TABLE': + if ($this->serverVersion >= 50700) { + $this->REPLICATE_WILD_DO_TABLE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'REPLICATE_WILD_IGNORE_TABLE': + if ($this->serverVersion >= 50700) { + $this->REPLICATE_WILD_IGNORE_TABLE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'REPLICATE_REWRITE_DB': + if ($this->serverVersion >= 50700) { + $this->REPLICATE_REWRITE_DB_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'REQUIRE': + $this->REQUIRE_SYMBOL(); + break; + case 'REQUIRE_ROW_FORMAT': + if ($this->serverVersion >= 80019) { + $this->REQUIRE_ROW_FORMAT_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'REQUIRE_TABLE_PRIMARY_KEY_CHECK': + if ($this->serverVersion >= 80019) { + $this->REQUIRE_TABLE_PRIMARY_KEY_CHECK_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'RESOURCE': + if ($this->serverVersion >= 80000) { + $this->RESOURCE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'RESPECT': + if ($this->serverVersion >= 80000) { + $this->RESPECT_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'RESTART': + if ($this->serverVersion >= 80011) { + $this->RESTART_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'RESTORE': + $this->RESTORE_SYMBOL(); + break; + case 'RESTRICT': + $this->RESTRICT_SYMBOL(); + break; + case 'RESUME': + $this->RESUME_SYMBOL(); + break; + case 'RETAIN': + if ($this->serverVersion >= 80014) { + $this->RETAIN_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'RETURNED_SQLSTATE': + $this->RETURNED_SQLSTATE_SYMBOL(); + break; + case 'RETURNS': + $this->RETURNS_SYMBOL(); + break; + case 'RETURN': + $this->RETURN_SYMBOL(); + break; + case 'REUSE': + if ($this->serverVersion >= 80000) { + $this->REUSE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'REVERSE': + $this->REVERSE_SYMBOL(); + break; + case 'REVOKE': + $this->REVOKE_SYMBOL(); + break; + case 'RIGHT': + $this->RIGHT_SYMBOL(); + break; + case 'RLIKE': + $this->REGEXP_SYMBOL(); // Synonym + break; + case 'ROLE': + if ($this->serverVersion >= 80000) { + $this->ROLE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'ROLLBACK': + $this->ROLLBACK_SYMBOL(); + break; + case 'ROLLUP': + $this->ROLLUP_SYMBOL(); + break; + case 'ROTATE': + if ($this->serverVersion >= 50713) { + $this->ROTATE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'ROUTINE': + $this->ROUTINE_SYMBOL(); + break; + case 'ROW': + if ($this->serverVersion < 80000) { + $this->ROW_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'ROWS': + if ($this->serverVersion < 80000) { + $this->ROWS_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'ROW_COUNT': + $this->ROW_COUNT_SYMBOL(); + break; + case 'ROW_FORMAT': + $this->ROW_FORMAT_SYMBOL(); + break; + case 'ROW_NUMBER': + if ($this->serverVersion >= 80000) { + $this->ROW_NUMBER_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'RTREE': + $this->RTREE_SYMBOL(); + break; + case 'SAVEPOINT': + $this->SAVEPOINT_SYMBOL(); + break; + case 'SCHEDULE': + $this->SCHEDULE_SYMBOL(); + break; + case 'SCHEMA': + $this->DATABASE_SYMBOL(); // Synonym + break; + case 'SCHEMAS': + $this->DATABASES_SYMBOL(); // Synonym + break; + case 'SCHEMA_NAME': + $this->SCHEMA_NAME_SYMBOL(); + break; + case 'SECOND': + $this->SECOND_SYMBOL(); + break; + case 'SECOND_MICROSECOND': + $this->SECOND_MICROSECOND_SYMBOL(); + break; + case 'SECONDARY': + if ($this->serverVersion >= 80013) { + $this->SECONDARY_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'SECONDARY_ENGINE': + if ($this->serverVersion >= 80013) { + $this->SECONDARY_ENGINE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'SECONDARY_LOAD': + if ($this->serverVersion >= 80013) { + $this->SECONDARY_LOAD_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'SECONDARY_UNLOAD': + if ($this->serverVersion >= 80013) { + $this->SECONDARY_UNLOAD_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'SECURITY': + $this->SECURITY_SYMBOL(); + break; + case 'SELECT': + $this->SELECT_SYMBOL(); + break; + case 'SENSITIVE': + $this->SENSITIVE_SYMBOL(); + break; + case 'SEPARATOR': + $this->SEPARATOR_SYMBOL(); + break; + case 'SERIALIZABLE': + $this->SERIALIZABLE_SYMBOL(); + break; + case 'SERIAL': + $this->SERIAL_SYMBOL(); + break; + case 'SERVER': + $this->SERVER_SYMBOL(); + break; + case 'SERVER_OPTIONS': + $this->SERVER_OPTIONS_SYMBOL(); + break; + case 'SESSION': + $this->SESSION_SYMBOL(); + break; + case 'SESSION_USER': + $this->USER_SYMBOL(); // Synonym + break; + case 'SET': + $this->SET_SYMBOL(); + break; + case 'SET_VAR': + $this->SET_VAR_SYMBOL(); + break; + case 'SHARE': + $this->SHARE_SYMBOL(); + break; + case 'SHOW': + $this->SHOW_SYMBOL(); + break; + case 'SHUTDOWN': + if ($this->serverVersion < 50709) { + $this->SHUTDOWN_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'SIGNAL': + $this->SIGNAL_SYMBOL(); + break; + case 'SIGNED': + $this->SIGNED_SYMBOL(); + break; + case 'SIMPLE': + $this->SIMPLE_SYMBOL(); + break; + case 'SKIP': + if ($this->serverVersion >= 80000) { + $this->SKIP_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'SLAVE': + $this->SLAVE_SYMBOL(); + break; + case 'SLOW': + $this->SLOW_SYMBOL(); + break; + case 'SMALLINT': + $this->SMALLINT_SYMBOL(); + break; + case 'SNAPSHOT': + $this->SNAPSHOT_SYMBOL(); + break; + case 'SOME': + $this->ANY_SYMBOL(); // Synonym + break; + case 'SOCKET': + $this->SOCKET_SYMBOL(); + break; + case 'SONAME': + $this->SONAME_SYMBOL(); + break; + case 'SOUNDS': + $this->SOUNDS_SYMBOL(); + break; + case 'SOURCE': + $this->SOURCE_SYMBOL(); + break; + case 'SPATIAL': + $this->SPATIAL_SYMBOL(); + break; + case 'SPECIFIC': + $this->SPECIFIC_SYMBOL(); + break; + case 'SQL': + $this->SQL_SYMBOL(); + break; + case 'SQLEXCEPTION': + $this->SQLEXCEPTION_SYMBOL(); + break; + case 'SQLSTATE': + $this->SQLSTATE_SYMBOL(); + break; + case 'SQLWARNING': + $this->SQLWARNING_SYMBOL(); + break; + case 'SQL_AFTER_GTIDS': + $this->SQL_AFTER_GTIDS_SYMBOL(); + break; + case 'SQL_AFTER_MTS_GAPS': + if ($this->serverVersion >= 50606) { + $this->SQL_AFTER_MTS_GAPS_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'SQL_BEFORE_GTIDS': + $this->SQL_BEFORE_GTIDS_SYMBOL(); + break; + case 'SQL_BIG_RESULT': + $this->SQL_BIG_RESULT_SYMBOL(); + break; + case 'SQL_BUFFER_RESULT': + $this->SQL_BUFFER_RESULT_SYMBOL(); + break; + case 'SQL_CALC_FOUND_ROWS': + $this->SQL_CALC_FOUND_ROWS_SYMBOL(); + break; + case 'SQL_CACHE': + if ($this->serverVersion < 80000) { + $this->SQL_CACHE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'SQL_NO_CACHE': + $this->SQL_NO_CACHE_SYMBOL(); + break; + case 'SQL_SMALL_RESULT': + $this->SQL_SMALL_RESULT_SYMBOL(); + break; + case 'SQL_THREAD': + $this->SQL_THREAD_SYMBOL(); + break; + case 'SQL_TSI_SECOND': + $this->SECOND_SYMBOL(); // Synonym + break; + case 'SQL_TSI_MINUTE': + $this->MINUTE_SYMBOL(); // Synonym + break; + case 'SQL_TSI_HOUR': + $this->HOUR_SYMBOL(); // Synonym + break; + case 'SQL_TSI_DAY': + $this->DAY_SYMBOL(); // Synonym + break; + case 'SQL_TSI_WEEK': + $this->WEEK_SYMBOL(); // Synonym + break; + case 'SQL_TSI_MONTH': + $this->MONTH_SYMBOL(); // Synonym + break; + case 'SQL_TSI_QUARTER': + $this->QUARTER_SYMBOL(); // Synonym + break; + case 'SQL_TSI_YEAR': + $this->YEAR_SYMBOL(); // Synonym + break; + case 'SRID': + if ($this->serverVersion >= 80000) { + $this->SRID_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'SSL': + $this->SSL_SYMBOL(); + break; + case 'STACKED': + if ($this->serverVersion >= 50700) { + $this->STACKED_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'STARTING': + $this->STARTING_SYMBOL(); + break; + case 'STARTS': + $this->STARTS_SYMBOL(); + break; + case 'START': + $this->START_SYMBOL(); + break; + case 'STATS_AUTO_RECALC': + $this->STATS_AUTO_RECALC_SYMBOL(); + break; + case 'STATS_PERSISTENT': + $this->STATS_PERSISTENT_SYMBOL(); + break; + case 'STATS_SAMPLE_PAGES': + $this->STATS_SAMPLE_PAGES_SYMBOL(); + break; + case 'STATUS': + $this->STATUS_SYMBOL(); + break; + case 'STD': + $this->STD_SYMBOL(); + break; + case 'STDDEV': + $this->STD_SYMBOL(); // Synonym + break; + case 'STDDEV_POP': + $this->STD_SYMBOL(); // Synonym + break; + case 'STDDEV_SAMP': + $this->STDDEV_SAMP_SYMBOL(); + break; + case 'STOP': + $this->STOP_SYMBOL(); + break; + case 'STORAGE': + $this->STORAGE_SYMBOL(); + break; + case 'STORED': + if ($this->serverVersion >= 50707) { + $this->STORED_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'STRAIGHT_JOIN': + $this->STRAIGHT_JOIN_SYMBOL(); + break; + case 'STREAM': + if ($this->serverVersion >= 80019) { + $this->STREAM_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'STRING': + $this->STRING_SYMBOL(); + break; + case 'SUBCLASS_ORIGIN': + $this->SUBCLASS_ORIGIN_SYMBOL(); + break; + case 'SUBDATE': + $this->SUBDATE_SYMBOL(); + break; + case 'SUBJECT': + $this->SUBJECT_SYMBOL(); + break; + case 'SUBPARTITION': + $this->SUBPARTITION_SYMBOL(); + break; + case 'SUBPARTITIONS': + $this->SUBPARTITIONS_SYMBOL(); + break; + case 'SUBSTR': + $this->SUBSTRING_SYMBOL(); // Synonym + break; + case 'SUBSTRING': + $this->SUBSTRING_SYMBOL(); + break; + case 'SUM': + $this->SUM_SYMBOL(); + break; + case 'SUPER': + $this->SUPER_SYMBOL(); + break; + case 'SUSPEND': + $this->SUSPEND_SYMBOL(); + break; + case 'SWAPS': + $this->SWAPS_SYMBOL(); + break; + case 'SWITCHES': + $this->SWITCHES_SYMBOL(); + break; + case 'SYSDATE': + $this->SYSDATE_SYMBOL(); + break; + case 'SYSTEM': + if ($this->serverVersion >= 80000) { + $this->SYSTEM_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'SYSTEM_USER': + $this->USER_SYMBOL(); // Synonym + break; + case 'TABLE': + $this->TABLE_SYMBOL(); + break; + case 'TABLES': + $this->TABLES_SYMBOL(); + break; + case 'TABLESPACE': + $this->TABLESPACE_SYMBOL(); + break; + case 'TABLE_CHECKSUM': + $this->TABLE_CHECKSUM_SYMBOL(); + break; + case 'TABLE_NAME': + $this->TABLE_NAME_SYMBOL(); + break; + case 'TEMPORARY': + $this->TEMPORARY_SYMBOL(); + break; + case 'TEMPTABLE': + $this->TEMPTABLE_SYMBOL(); + break; + case 'TERMINATED': + $this->TERMINATED_SYMBOL(); + break; + case 'TEXT': + $this->TEXT_SYMBOL(); + break; + case 'THAN': + $this->THAN_SYMBOL(); + break; + case 'THEN': + $this->THEN_SYMBOL(); + break; + case 'THREAD_PRIORITY': + if ($this->serverVersion >= 80000) { + $this->THREAD_PRIORITY_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'TIES': + if ($this->serverVersion >= 80000) { + $this->TIES_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'TIME': + $this->TIME_SYMBOL(); + break; + case 'TIMESTAMP': + $this->TIMESTAMP_SYMBOL(); + break; + case 'TIMESTAMPADD': + $this->TIMESTAMP_ADD_SYMBOL(); + break; + case 'TIMESTAMPDIFF': + $this->TIMESTAMP_DIFF_SYMBOL(); + break; + case 'TINYBLOB': + $this->TINYBLOB_SYMBOL(); + break; + case 'TINYINT': + $this->TINYINT_SYMBOL(); + break; + case 'TINYTEXT': + $this->TINYTEXT_SYMBOL(); + break; + case 'TO': + $this->TO_SYMBOL(); + break; + case 'TRAILING': + $this->TRAILING_SYMBOL(); + break; + case 'TRANSACTION': + $this->TRANSACTION_SYMBOL(); + break; + case 'TRIGGER': + $this->TRIGGER_SYMBOL(); + break; + case 'TRIGGERS': + $this->TRIGGERS_SYMBOL(); + break; + case 'TRIM': + $this->TRIM_SYMBOL(); + break; + case 'TRUE': + $this->TRUE_SYMBOL(); + break; + case 'TRUNCATE': + $this->TRUNCATE_SYMBOL(); + break; + case 'TYPES': + $this->TYPES_SYMBOL(); + break; + case 'TYPE': + $this->TYPE_SYMBOL(); + break; + case 'UDF_RETURNS': + $this->UDF_RETURNS_SYMBOL(); + break; + case 'UNBOUNDED': + if ($this->serverVersion >= 80000) { + $this->UNBOUNDED_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'UNCOMMITTED': + $this->UNCOMMITTED_SYMBOL(); + break; + case 'UNDEFINED': + $this->UNDEFINED_SYMBOL(); + break; + case 'UNDO': + $this->UNDO_SYMBOL(); + break; + case 'UNDO_BUFFER_SIZE': + $this->UNDO_BUFFER_SIZE_SYMBOL(); + break; + case 'UNDOFILE': + $this->UNDOFILE_SYMBOL(); + break; + case 'UNICODE': + $this->UNICODE_SYMBOL(); + break; + case 'UNION': + $this->UNION_SYMBOL(); + break; + case 'UNIQUE': + $this->UNIQUE_SYMBOL(); + break; + case 'UNKNOWN': + $this->UNKNOWN_SYMBOL(); + break; + case 'UNINSTALL': + $this->UNINSTALL_SYMBOL(); + break; + case 'UNLOCK': + $this->UNLOCK_SYMBOL(); + break; + case 'UNSIGNED': + $this->UNSIGNED_SYMBOL(); + break; + case 'UPDATE': + $this->UPDATE_SYMBOL(); + break; + case 'UPGRADE': + $this->UPGRADE_SYMBOL(); + break; + case 'USAGE': + $this->USAGE_SYMBOL(); + break; + case 'USER': + $this->USER_SYMBOL(); + break; + case 'USER_RESOURCES': + $this->USER_RESOURCES_SYMBOL(); + break; + case 'USE': + $this->USE_SYMBOL(); + break; + case 'USE_FRM': + $this->USE_FRM_SYMBOL(); + break; + case 'USING': + $this->USING_SYMBOL(); + break; + case 'UTC_DATE': + $this->UTC_DATE_SYMBOL(); + break; + case 'UTC_TIME': + $this->UTC_TIME_SYMBOL(); + break; + case 'UTC_TIMESTAMP': + $this->UTC_TIMESTAMP_SYMBOL(); + break; + case 'VALIDATION': + if ($this->serverVersion >= 50706) { + $this->VALIDATION_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'VALUE': + $this->VALUE_SYMBOL(); + break; + case 'VALUES': + $this->VALUES_SYMBOL(); + break; + case 'VARBINARY': + $this->VARBINARY_SYMBOL(); + break; + case 'VARCHAR': + $this->VARCHAR_SYMBOL(); + break; + case 'VARCHARACTER': + $this->VARCHAR_SYMBOL(); // Synonym + break; + case 'VARIABLES': + $this->VARIABLES_SYMBOL(); + break; + case 'VARIANCE': + $this->VARIANCE_SYMBOL(); + break; + case 'VARYING': + $this->VARYING_SYMBOL(); + break; + case 'VAR_POP': + $this->VARIANCE_SYMBOL(); // Synonym + break; + case 'VAR_SAMP': + $this->VAR_SAMP_SYMBOL(); + break; + case 'VCPU': + if ($this->serverVersion >= 80000) { + $this->VCPU_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'VIEW': + $this->VIEW_SYMBOL(); + break; + case 'VIRTUAL': + if ($this->serverVersion >= 50707) { + $this->VIRTUAL_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'VISIBLE': + if ($this->serverVersion >= 80000) { + $this->VISIBLE_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'WAIT': + $this->WAIT_SYMBOL(); + break; + case 'WARNINGS': + $this->WARNINGS_SYMBOL(); + break; + case 'WEEK': + $this->WEEK_SYMBOL(); + break; + case 'WHEN': + $this->WHEN_SYMBOL(); + break; + case 'WEIGHT_STRING': + $this->WEIGHT_STRING_SYMBOL(); + break; + case 'WHERE': + $this->WHERE_SYMBOL(); + break; + case 'WHILE': + $this->WHILE_SYMBOL(); + break; + case 'WINDOW': + if ($this->serverVersion >= 80000) { + $this->WINDOW_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'WITH': + $this->WITH_SYMBOL(); + break; + case 'WITHOUT': + if ($this->serverVersion >= 80000) { + $this->WITHOUT_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'WORK': + $this->WORK_SYMBOL(); + break; + case 'WRAPPER': + $this->WRAPPER_SYMBOL(); + break; + case 'WRITE': + $this->WRITE_SYMBOL(); + break; + case 'XA': + $this->XA_SYMBOL(); + break; + case 'X509': + $this->X509_SYMBOL(); + break; + case 'XID': + if ($this->serverVersion >= 50704) { + $this->XID_SYMBOL(); + } else { + $this->IDENTIFIER(); + } + break; + case 'XML': + $this->XML_SYMBOL(); + break; + case 'XOR': + $this->XOR_SYMBOL(); + break; + case 'YEAR': + $this->YEAR_SYMBOL(); + break; + case 'YEAR_MONTH': + $this->YEAR_MONTH_SYMBOL(); + break; + case 'ZEROFILL': + $this->ZEROFILL_SYMBOL(); + break; + case 'INT1': + $this->INT1_SYMBOL(); + break; + case 'INT2': + $this->INT2_SYMBOL(); + break; + case 'INT3': + $this->INT3_SYMBOL(); + break; + case 'INT4': + $this->INT4_SYMBOL(); + break; + case 'INT8': + $this->INT8_SYMBOL(); + break; + default: + // Not a keyword, emit as identifier. + $this->IDENTIFIER(); + } + } + + protected function blockComment() + { + $this->consume(); // Consume the '/'. + $this->consume(); // Consume the '*'. + + // If the next character is '!', it could be a version comment. + if ($this->c === '!') { + $this->consume(); // Consume the '!'. + + // If the next character is a digit, it's a version comment. + if (safe_ctype_digit($this->c)) { + // Consume all digits. + while (safe_ctype_digit($this->c)) { + $this->consume(); + } + + // Check if the version comment is active for the current server version. + if ($this->checkVersion($this->getText())) { + // If it's active, treat the content as regular SQL code. + $this->MYSQL_COMMENT_START(); + $this->sqlCodeInComment(); + } else { + // If it's not active, skip the comment content. + $this->skipCommentContent(); + } + } else { + // If it's not a version comment, treat it as a regular multi-line comment. + $this->MYSQL_COMMENT_START(); + $this->skipCommentContent(); + } + } else { + // If the next character is not '!', it's a regular multi-line comment. + $this->skipCommentContent(); + } + + // Set the channel to HIDDEN for block comments. + $this->channel = self::HIDDEN; + } + + protected function skipCommentContent(): void + { + while ($this->c !== null) { + if ($this->c === '*' && $this->n === '/') { + $this->consume(); // Consume the '*'. + $this->consume(); // Consume the '/'. + break; + } + $this->consume(); + } + } + + protected function sqlCodeInComment(): void + { + $this->skipCommentContent(); + $this->VERSION_COMMENT_END(); + } + + protected function DOT_IDENTIFIER() + { + $this->consume(); // Consume the '.'. + $this->IDENTIFIER(); + $this->setType(self::DOT_SYMBOL);//@TODO: DOT_IDENTIFIER); + } + + protected function NUMBER() + { + if ($this->c === '0' && $this->n === 'x') { + $this->HEX_NUMBER(); + } elseif ($this->c === '0' && $this->n === 'b') { + $this->BIN_NUMBER(); + } elseif ($this->c === '.' && safe_ctype_digit($this->LA(2))) { + $this->DECIMAL_NUMBER(); + } else { + $this->INT_NUMBER(); + + if ($this->c === '.') { + $this->consume(); + + if (safe_ctype_digit($this->c)) { + while (safe_ctype_digit($this->c)) { + $this->consume(); + } + + if ($this->c === 'e' || $this->c === 'E') { + $this->consume(); + if ($this->c === '+' || $this->c === '-') { + $this->consume(); + } + while (safe_ctype_digit($this->c)) { + $this->consume(); + } + $this->setType(self::FLOAT_NUMBER); + } else { + $this->setType(self::DECIMAL_NUMBER); + } + } else { + // If there is no digit after the '.', it's a DOT_IDENTIFIER. + $this->emitDot(); + $this->setType(self::IDENTIFIER); + } + } elseif ($this->c === 'e' || $this->c === 'E') { + $this->consume(); + if ($this->c === '+' || $this->c === '-') { + $this->consume(); + } + while (safe_ctype_digit($this->c)) { + $this->consume(); + } + $this->setType(self::FLOAT_NUMBER); + } + } + } + + protected function SINGLE_QUOTED_TEXT() + { + do { + $this->consume(); // Consume the first single quote. + while ($this->c !== null) { + if ($this->c === '\\' && !$this->isSqlModeActive(MySQLLexer::NoBackslashEscapes)) { + // If it's an escape sequence, consume the backslash and the next character. + $this->consume(); + $this->consume(); + } elseif ($this->c === "'") { + $this->consume(); // Consume the second single quote. + break; + } else { + $this->consume(); + } + } + } while ($this->c === "'"); // Continue if there's another single quote. + + $this->setType(self::SINGLE_QUOTED_TEXT); + } + + protected function DOUBLE_QUOTED_TEXT() + { + do { + $this->consume(); // Consume the first double quote. + while ($this->c !== null) { + if ($this->c === '\\' && !$this->isSqlModeActive(MySQLLexer::NoBackslashEscapes)) { + // If it's an escape sequence, consume the backslash and the next character. + $this->consume(); + $this->consume(); + } elseif ($this->c === '"') { + $this->consume(); // Consume the second double quote. + break; + } else { + $this->consume(); + } + } + } while ($this->c === '"'); // Continue if there's another double quote. + + $this->setType(self::DOUBLE_QUOTED_TEXT); + } + + protected function BACK_TICK_QUOTED_ID() + { + $this->consume(); // Consume the first back tick. + while ($this->c !== null) { + if ($this->c === '\\' && !$this->isSqlModeActive(MySQLLexer::NoBackslashEscapes)) { + // If it's an escape sequence, consume the backslash and the next character. + $this->consume(); + $this->consume(); + } elseif ($this->c === '`') { + $this->consume(); // Consume the second back tick. + break; + } else { + $this->consume(); + } + } + + $this->setType(self::BACK_TICK_QUOTED_ID); + } + + protected function HEX_NUMBER() + { + $this->consume(); // Consume the '0'. + $this->consume(); // Consume the 'x'. + while (ctype_xdigit($this->c)) { + $this->consume(); + } + $this->setType(self::HEX_NUMBER); + } + + protected function BIN_NUMBER() + { + $this->consume(); // Consume the '0'. + $this->consume(); // Consume the 'b'. + while ($this->c === '0' || $this->c === '1') { + $this->consume(); + } + $this->setType(self::BIN_NUMBER); + } + + protected function INT_NUMBER() + { + while (safe_ctype_digit($this->c)) { + $this->consume(); + } + $this->setType(self::DECIMAL_NUMBER); + } + + protected function DECIMAL_NUMBER() + { + $this->consume(); // Consume the '.'. + while (safe_ctype_digit($this->c)) { + $this->consume(); + } + $this->setType(self::DECIMAL_NUMBER); + } + + protected function FLOAT_NUMBER() + { + // This rule is never actually called, as FLOAT_NUMBER tokens are emitted by NUMBER(). + throw new \BadMethodCallException('FLOAT_NUMBER() should never be called directly.'); + } + + protected function EQUAL_OPERATOR() + { + $this->consume(); + $this->setType(self::EQUAL_OPERATOR); + } + + protected function ASSIGN_OPERATOR() + { + $this->consume(); // Consume the ':'. + $this->consume(); // Consume the '='. + $this->setType(self::ASSIGN_OPERATOR); + } + + protected function NULL_SAFE_EQUAL_OPERATOR() + { + $this->consume(); // Consume the '<'. + $this->consume(); // Consume the '='. + $this->consume(); // Consume the '>'. + $this->setType(self::NULL_SAFE_EQUAL_OPERATOR); + } + + protected function GREATER_OR_EQUAL_OPERATOR() + { + $this->consume(); // Consume the '>'. + $this->consume(); // Consume the '='. + $this->setType(self::GREATER_OR_EQUAL_OPERATOR); + } + + protected function GREATER_THAN_OPERATOR() + { + $this->consume(); + $this->setType(self::GREATER_THAN_OPERATOR); + } + + protected function LESS_OR_EQUAL_OPERATOR() + { + $this->consume(); // Consume the '<'. + $this->consume(); // Consume the '='. + $this->setType(self::LESS_OR_EQUAL_OPERATOR); + } + + protected function LESS_THAN_OPERATOR() + { + $this->consume(); + $this->setType(self::LESS_THAN_OPERATOR); + } + + protected function NOT_EQUAL_OPERATOR() + { + $this->consume(); // Consume the '!'. + $this->consume(); // Consume the '='. + $this->setType(self::NOT_EQUAL_OPERATOR); + } + + protected function NOT_EQUAL2_OPERATOR() + { + $this->consume(); // Consume the '<'. + $this->consume(); // Consume the '>'. + $this->setType(self::NOT_EQUAL_OPERATOR); + } + + protected function PLUS_OPERATOR() + { + $this->consume(); + $this->setType(self::PLUS_OPERATOR); + } + + protected function MINUS_OPERATOR() + { + $this->consume(); + $this->setType(self::MINUS_OPERATOR); + } + + protected function MULT_OPERATOR() + { + $this->consume(); + $this->setType(self::MULT_OPERATOR); + } + + protected function DIV_OPERATOR() + { + $this->consume(); + $this->setType(self::DIV_OPERATOR); + } + + protected function MOD_OPERATOR() + { + $this->consume(); + $this->setType(self::MOD_OPERATOR); + } + + protected function LOGICAL_NOT_OPERATOR() + { + $this->consume(); + $this->setType(self::LOGICAL_NOT_OPERATOR); + } + + protected function BITWISE_NOT_OPERATOR() + { + $this->consume(); + $this->setType(self::BITWISE_NOT_OPERATOR); + } + + protected function SHIFT_LEFT_OPERATOR() + { + $this->consume(); // Consume the '<'. + $this->consume(); // Consume the '<'. + $this->setType(self::SHIFT_LEFT_OPERATOR); + } + + protected function SHIFT_RIGHT_OPERATOR() + { + $this->consume(); // Consume the '>'. + $this->consume(); // Consume the '>'. + $this->setType(self::SHIFT_RIGHT_OPERATOR); + } + + protected function LOGICAL_AND_OPERATOR() + { + $this->consume(); // Consume the '&'. + $this->consume(); // Consume the '&'. + $this->setType(self::LOGICAL_AND_OPERATOR); + } + + protected function BITWISE_AND_OPERATOR() + { + $this->consume(); + $this->setType(self::BITWISE_AND_OPERATOR); + } + + protected function BITWISE_XOR_OPERATOR() + { + $this->consume(); + $this->setType(self::BITWISE_XOR_OPERATOR); + } + + protected function LOGICAL_OR_OPERATOR() + { + $this->consume(); // Consume the '|'. + $this->consume(); // Consume the '|'. + + if ($this->isSqlModeActive(MySQLLexer::PipesAsConcat)) { + $this->setType(self::CONCAT_PIPES_SYMBOL); + } else { + $this->setType(self::LOGICAL_OR_OPERATOR); + } + } + + protected function BITWISE_OR_OPERATOR() + { + $this->consume(); + $this->setType(self::BITWISE_OR_OPERATOR); + } + + protected function DOT_SYMBOL() + { + $this->consume(); + $this->setType(self::DOT_SYMBOL); + } + + protected function COMMA_SYMBOL() + { + $this->consume(); + $this->setType(self::COMMA_SYMBOL); + } + + protected function SEMICOLON_SYMBOL() + { + $this->consume(); + $this->setType(self::SEMICOLON_SYMBOL); + } + + protected function COLON_SYMBOL() + { + $this->consume(); + $this->setType(self::COLON_SYMBOL); + } + + protected function OPEN_PAR_SYMBOL() + { + $this->consume(); + $this->setType(self::OPEN_PAR_SYMBOL); + } + + protected function CLOSE_PAR_SYMBOL() + { + $this->consume(); + $this->setType(self::CLOSE_PAR_SYMBOL); + } + + protected function OPEN_CURLY_SYMBOL() + { + $this ->consume(); + $this->setType(self::OPEN_CURLY_SYMBOL); + } + + protected function CLOSE_CURLY_SYMBOL() + { + $this->consume(); + $this->setType(self::CLOSE_CURLY_SYMBOL); + } + + protected function UNDERLINE_SYMBOL() + { + $this->consume(); + + if (safe_ctype_alpha($this->LA(1))) { + // If the next character is a letter, it's a charset. + while (ctype_alnum($this->LA(1))) { + $this->consume(); + } + + $this->setType($this->checkCharset($this->getText())); + } else { + $this->setType(self::UNDERLINE_SYMBOL); + } + } + + protected function JSON_SEPARATOR_SYMBOL() + { + if ($this->serverVersion >= 50708) { + $this->consume(); // Consume the '-'. + $this->consume(); // Consume the '>'. + $this->setType(self::JSON_SEPARATOR_SYMBOL); + } else { + $this->setType(self::INVALID_INPUT); + } + } + + protected function JSON_UNQUOTED_SEPARATOR_SYMBOL() + { + if ($this->serverVersion >= 50713) { + $this->consume(); // Consume the '-'. + $this->consume(); // Consume the '>'. + $this->consume(); // Consume the '>'. + $this->setType(self::JSON_UNQUOTED_SEPARATOR_SYMBOL); + } else { + $this->setType(self::INVALID_INPUT); + } + } + + protected function AT_SIGN_SYMBOL() + { + $this->consume(); + $this->setType(self::AT_SIGN_SYMBOL); + } + + protected function AT_AT_SIGN_SYMBOL() + { + $this->consume(); // Consume the '@'. + $this->consume(); // Consume the '@'. + $this->setType(self::AT_AT_SIGN_SYMBOL); + } + + protected function NULL2_SYMBOL() + { + $this->consume(); // Consume the '\'. + $this->consume(); // Consume the 'N'. + $this->setType(self::NULL2_SYMBOL); + } + + protected function PARAM_MARKER() + { + $this->consume(); + $this->setType(self::PARAM_MARKER); + } + + protected function WHITESPACE() + { + while (safe_ctype_space($this->c)) { + $this->consume(); + } + + $this->channel = self::HIDDEN; + } + + protected function INVALID_INPUT() + { + $this->consume(); + $this->setType(self::INVALID_INPUT); + } + + protected function POUND_COMMENT() + { + $this->consume(); + + while ($this->c !== null) { + if ($this->c === "\n" || $this->c === "\r") { + break; + } + $this->consume(); + } + + $this->channel = self::HIDDEN; + } + + protected function DASHDASH_COMMENT() + { + $this->consume(); // Consume the '-'. + $this->consume(); // Consume the '-'. + + while (safe_ctype_space($this->c)) { + $this->consume(); + } + + while ($this->c !== null) { + if ($this->c === "\n" || $this->c === "\r") { + break; + } + $this->consume(); + } + + $this->channel = self::HIDDEN; + } + + protected function ACCESSIBLE_SYMBOL() + { + $this->setType(self::ACCESSIBLE_SYMBOL); + } + + protected function ACCOUNT_SYMBOL() + { + $this->setType(self::ACCOUNT_SYMBOL); + } + + protected function ACTION_SYMBOL() + { + $this->setType(self::ACTION_SYMBOL); + } + + protected function ADD_SYMBOL() + { + $this->setType(self::ADD_SYMBOL); + } + + protected function ADDDATE_SYMBOL() + { + $this->setType($this->determineFunction(self::ADDDATE_SYMBOL)); // MYSQL-FUNC + } + + protected function AFTER_SYMBOL() + { + $this->setType(self::AFTER_SYMBOL); + } + + protected function AGAINST_SYMBOL() + { + $this->setType(self::AGAINST_SYMBOL); + } + + protected function AGGREGATE_SYMBOL() + { + $this->setType(self::AGGREGATE_SYMBOL); + } + + protected function ALGORITHM_SYMBOL() + { + $this->setType(self::ALGORITHM_SYMBOL); + } + + protected function ALL_SYMBOL() + { + $this->setType(self::ALL_SYMBOL); + } + + protected function ALTER_SYMBOL() + { + $this->setType(self::ALTER_SYMBOL); + } + + protected function ALWAYS_SYMBOL() + { + $this->setType(self::ALWAYS_SYMBOL); + } + + protected function ANALYSE_SYMBOL() + { + $this->setType(self::ANALYSE_SYMBOL); + } + + protected function ANALYZE_SYMBOL() + { + $this->setType(self::ANALYZE_SYMBOL); + } + + protected function AND_SYMBOL() + { + $this->setType(self::AND_SYMBOL); + } + + protected function ANY_SYMBOL() + { + $this->setType(self::ANY_SYMBOL); + } + + protected function AS_SYMBOL() + { + $this->setType(self::AS_SYMBOL); + } + + protected function ASC_SYMBOL() + { + $this->setType(self::ASC_SYMBOL); + } + + protected function ASCII_SYMBOL() + { + $this->setType(self::ASCII_SYMBOL); + } + + protected function ASENSITIVE_SYMBOL() + { + $this->setType(self::ASENSITIVE_SYMBOL); + } + + protected function AT_SYMBOL() + { + $this->setType(self::AT_SYMBOL); + } + + protected function AUTHORS_SYMBOL() + { + $this->setType(self::AUTHORS_SYMBOL); + } + + protected function AUTOEXTEND_SIZE_SYMBOL() + { + $this->setType(self::AUTOEXTEND_SIZE_SYMBOL); + } + + protected function AUTO_INCREMENT_SYMBOL() + { + $this->setType(self::AUTO_INCREMENT_SYMBOL); + } + + protected function AVG_SYMBOL() + { + $this->setType(self::AVG_SYMBOL); + } + + protected function AVG_ROW_LENGTH_SYMBOL() + { + $this->setType(self::AVG_ROW_LENGTH_SYMBOL); + } + + protected function BACKUP_SYMBOL() + { + $this->setType(self::BACKUP_SYMBOL); + } + + protected function BEFORE_SYMBOL() + { + $this->setType(self::BEFORE_SYMBOL); + } + + protected function BEGIN_SYMBOL() + { + $this->setType(self::BEGIN_SYMBOL); + } + + protected function BETWEEN_SYMBOL() + { + $this->setType(self::BETWEEN_SYMBOL); + } + + protected function BIGINT_SYMBOL() + { + $this->setType(self::BIGINT_SYMBOL); + } + + protected function BINARY_SYMBOL() + { + $this->setType(self::BINARY_SYMBOL); + } + + protected function BINLOG_SYMBOL() + { + $this->setType(self::BINLOG_SYMBOL); + } + + protected function BIT_AND_SYMBOL() + { + $this->setType($this->determineFunction(self::BIT_AND_SYMBOL)); // MYSQL-FUNC + } + + protected function BIT_OR_SYMBOL() + { + $this->setType($this->determineFunction(self::BIT_OR_SYMBOL)); // MYSQL-FUNC + } + + protected function BIT_SYMBOL() + { + $this->setType(self::BIT_SYMBOL); + } + + protected function BIT_XOR_SYMBOL() + { + $this->setType($this->determineFunction(self::BIT_XOR_SYMBOL)); // MYSQL-FUNC + } + + protected function BLOB_SYMBOL() + { + $this->setType(self::BLOB_SYMBOL); + } + + protected function BLOCK_SYMBOL() + { + $this->setType(self::BLOCK_SYMBOL); + } + + protected function BOOLEAN_SYMBOL() + { + $this->setType(self::BOOLEAN_SYMBOL); + } + + protected function BOOL_SYMBOL() + { + $this->setType(self::BOOL_SYMBOL); + } + + protected function BOTH_SYMBOL() + { + $this->setType(self::BOTH_SYMBOL); + } + + protected function BTREE_SYMBOL() + { + $this->setType(self::BTREE_SYMBOL); + } + + protected function BUCKETS_SYMBOL() + { + $this->setType(self::BUCKETS_SYMBOL); + } + + protected function BY_SYMBOL() + { + $this->setType(self::BY_SYMBOL); + } + + protected function BYTE_SYMBOL() + { + $this->setType(self::BYTE_SYMBOL); + } + + protected function CACHE_SYMBOL() + { + $this->setType(self::CACHE_SYMBOL); + } + + protected function CALL_SYMBOL() + { + $this->setType(self::CALL_SYMBOL); + } + + protected function CASCADE_SYMBOL() + { + $this->setType(self::CASCADE_SYMBOL); + } + + protected function CASCADED_SYMBOL() + { + $this->setType(self::CASCADED_SYMBOL); + } + + protected function CASE_SYMBOL() + { + $this->setType(self::CASE_SYMBOL); + } + + protected function CAST_SYMBOL() + { + $this->setType($this->determineFunction(self::CAST_SYMBOL)); // SQL-2003-R + } + + protected function CATALOG_NAME_SYMBOL() + { + $this->setType(self::CATALOG_NAME_SYMBOL); + } + + protected function CHAIN_SYMBOL() + { + $this->setType(self::CHAIN_SYMBOL); + } + + protected function CHANGE_SYMBOL() + { + $this->setType(self::CHANGE_SYMBOL); + } + + protected function CHANGED_SYMBOL() + { + $this->setType(self::CHANGED_SYMBOL); + } + + protected function CHANNEL_SYMBOL() + { + $this->setType(self::CHANNEL_SYMBOL); + } + + protected function CHAR_SYMBOL() + { + $this->setType(self::CHAR_SYMBOL); + } + + protected function CHARSET_SYMBOL() + { + $this->setType(self::CHARSET_SYMBOL); + } + + protected function CHECK_SYMBOL() + { + $this->setType(self::CHECK_SYMBOL); + } + + protected function CHECKSUM_SYMBOL() + { + $this->setType(self::CHECKSUM_SYMBOL); + } + + protected function CIPHER_SYMBOL() + { + $this->setType(self::CIPHER_SYMBOL); + } + + protected function CLASS_ORIGIN_SYMBOL() + { + $this->setType(self::CLASS_ORIGIN_SYMBOL); + } + + protected function CLIENT_SYMBOL() + { + $this->setType(self::CLIENT_SYMBOL); + } + + protected function CLONE_SYMBOL() + { + $this->setType(self::CLONE_SYMBOL); + } + + protected function CLOSE_SYMBOL() + { + $this->setType(self::CLOSE_SYMBOL); + } + + protected function COALESCE_SYMBOL() + { + $this->setType(self::COALESCE_SYMBOL); + } + + protected function CODE_SYMBOL() + { + $this->setType(self::CODE_SYMBOL); + } + + protected function COLLATE_SYMBOL() + { + $this->setType(self::COLLATE_SYMBOL); + } + + protected function COLLATION_SYMBOL() + { + $this->setType(self::COLLATION_SYMBOL); + } + + protected function COLUMN_FORMAT_SYMBOL() + { + $this->setType(self::COLUMN_FORMAT_SYMBOL); + } + + protected function COLUMN_NAME_SYMBOL() + { + $this->setType(self::COLUMN_NAME_SYMBOL); + } + + protected function COLUMNS_SYMBOL() + { + $this->setType(self::COLUMNS_SYMBOL); + } + + protected function COLUMN_SYMBOL() + { + $this->setType(self::COLUMN_SYMBOL); + } + + protected function COMMENT_SYMBOL() + { + $this->setType(self::COMMENT_SYMBOL); + } + + protected function COMMIT_SYMBOL() + { + $this->setType(self::COMMIT_SYMBOL); + } + + protected function COMMITTED_SYMBOL() + { + $this->setType(self::COMMITTED_SYMBOL); + } + + protected function COMPACT_SYMBOL() + { + $this->setType(self::COMPACT_SYMBOL); + } + + protected function COMPLETION_SYMBOL() + { + $this->setType(self::COMPLETION_SYMBOL); + } + + protected function COMPONENT_SYMBOL() + { + $this->setType(self::COMPONENT_SYMBOL); + } + + protected function COMPRESSED_SYMBOL() + { + $this->setType(self::COMPRESSED_SYMBOL); + } + + protected function COMPRESSION_SYMBOL() + { + $this->setType(self::COMPRESSION_SYMBOL); + } + + protected function CONCURRENT_SYMBOL() + { + $this->setType(self::CONCURRENT_SYMBOL); + } + + protected function CONDITION_SYMBOL() + { + $this->setType(self::CONDITION_SYMBOL); + } + + protected function CONNECTION_SYMBOL() + { + $this->setType(self::CONNECTION_SYMBOL); + } + + protected function CONSISTENT_SYMBOL() + { + $this->setType(self::CONSISTENT_SYMBOL); + } + + protected function CONSTRAINT_SYMBOL() + { + $this->setType(self::CONSTRAINT_SYMBOL); + } + + protected function CONSTRAINTS_SYMBOL() + { + $this->setType(self::CONSTRAINTS_SYMBOL); + } + + protected function CONSTRAINT_CATALOG_SYMBOL() + { + $this->setType(self::CONSTRAINT_CATALOG_SYMBOL); + } + + protected function CONSTRAINT_NAME_SYMBOL() + { + $this->setType(self::CONSTRAINT_NAME_SYMBOL); + } + + protected function CONSTRAINT_SCHEMA_SYMBOL() + { + $this->setType(self::CONSTRAINT_SCHEMA_SYMBOL); + } + + protected function CONTAINS_SYMBOL() + { + $this->setType(self::CONTAINS_SYMBOL); + } + + protected function CONTEXT_SYMBOL() + { + $this->setType(self::CONTEXT_SYMBOL); + } + + protected function CONTINUE_SYMBOL() + { + $this->setType(self::CONTINUE_SYMBOL); + } + + protected function CONTRIBUTORS_SYMBOL() + { + $this->setType(self::CONTRIBUTORS_SYMBOL); + } + + protected function CONVERT_SYMBOL() + { + $this->setType(self::CONVERT_SYMBOL); + } + + protected function COUNT_SYMBOL() + { + $this->setType($this->determineFunction(self::COUNT_SYMBOL)); // SQL-2003-N + } + + protected function CPU_SYMBOL() + { + $this->setType(self::CPU_SYMBOL); + } + + protected function CREATE_SYMBOL() + { + $this->setType(self::CREATE_SYMBOL); + } + + protected function CROSS_SYMBOL() + { + $this->setType(self::CROSS_SYMBOL); + } + + protected function CUBE_SYMBOL() + { + $this->setType(self::CUBE_SYMBOL); + } + + protected function CURDATE_SYMBOL() + { + $this->setType($this->determineFunction(self::CURDATE_SYMBOL)); // MYSQL-FUNC + } + + protected function CURRENT_SYMBOL() + { + $this->setType(self::CURRENT_SYMBOL); + } + + protected function CURRENT_DATE_SYMBOL() + { + $this->setType($this->determineFunction(self::CURDATE_SYMBOL)); // Synonym, MYSQL-FUNC + } + + protected function CURRENT_TIME_SYMBOL() + { + $this->setType($this->determineFunction(self::CURTIME_SYMBOL)); // Synonym, MYSQL-FUNC + } + + protected function CURRENT_TIMESTAMP_SYMBOL() + { + $this->setType(self::NOW_SYMBOL); // Synonym + } + + protected function CURRENT_USER_SYMBOL() + { + $this->setType(self::CURRENT_USER_SYMBOL); + } + + protected function CURSOR_SYMBOL() + { + $this->setType(self::CURSOR_SYMBOL); + } + + protected function CURSOR_NAME_SYMBOL() + { + $this->setType(self::CURSOR_NAME_SYMBOL); + } + + protected function CURTIME_SYMBOL() + { + $this->setType($this->determineFunction(self::CURTIME_SYMBOL)); // MYSQL-FUNC + } + + protected function DATABASE_SYMBOL() + { + $this->setType(self::DATABASE_SYMBOL); + } + + protected function DATABASES_SYMBOL() + { + $this->setType(self::DATABASES_SYMBOL); + } + + protected function DATAFILE_SYMBOL() + { + $this->setType(self::DATAFILE_SYMBOL); + } + + protected function DATA_SYMBOL() + { + $this->setType(self::DATA_SYMBOL); + } + + protected function DATETIME_SYMBOL() + { + $this->setType(self::DATETIME_SYMBOL); + } + + protected function DATE_ADD_SYMBOL() + { + $this->setType($this->determineFunction(self::DATE_ADD_SYMBOL)); + } + + protected function DATE_SUB_SYMBOL() + { + $this->setType($this->determineFunction(self::DATE_SUB_SYMBOL)); + } + + protected function DATE_SYMBOL() + { + $this->setType(self::DATE_SYMBOL); + } + + protected function DAY_HOUR_SYMBOL() + { + $this->setType(self::DAY_HOUR_SYMBOL); + } + + protected function DAY_MICROSECOND_SYMBOL() + { + $this->setType(self::DAY_MICROSECOND_SYMBOL); + } + + protected function DAY_MINUTE_SYMBOL() + { + $this->setType(self::DAY_MINUTE_SYMBOL); + } + + protected function DAY_SECOND_SYMBOL() + { + $this->setType(self::DAY_SECOND_SYMBOL); + } + + protected function DAY_SYMBOL() + { + $this->setType(self::DAY_SYMBOL); + } + + protected function DAYOFMONTH_SYMBOL() + { + $this->setType(self::DAY_SYMBOL); // Synonym + } + + protected function DEALLOCATE_SYMBOL() + { + $this->setType(self::DEALLOCATE_SYMBOL); + } + + protected function DECIMAL_SYMBOL() + { + $this->setType(self::DECIMAL_SYMBOL); + } + + protected function DEC_SYMBOL() + { + $this->setType(self::DECIMAL_SYMBOL); // Synonym + } + + protected function DECLARE_SYMBOL() + { + $this->setType(self::DECLARE_SYMBOL); + } + + protected function DEFAULT_SYMBOL() + { + $this->setType(self::DEFAULT_SYMBOL); + } + + protected function DEFAULT_AUTH_SYMBOL() + { + $this->setType(self::DEFAULT_AUTH_SYMBOL); + } + + protected function DEFINER_SYMBOL() + { + $this->setType(self::DEFINER_SYMBOL); + } + + protected function DEFINITION_SYMBOL() + { + $this->setType(self::DEFINITION_SYMBOL); + } + + protected function DELAYED_SYMBOL() + { + $this->setType(self::DELAYED_SYMBOL); + } + + protected function DELAY_KEY_WRITE_SYMBOL() + { + $this->setType(self::DELAY_KEY_WRITE_SYMBOL); + } + + protected function DELETE_SYMBOL() + { + $this->setType(self::DELETE_SYMBOL); + } + + protected function DENSE_RANK_SYMBOL() + { + $this->setType(self::DENSE_RANK_SYMBOL); + } + + protected function DESC_SYMBOL() + { + $this->setType(self::DESC_SYMBOL); + } + + protected function DESCRIBE_SYMBOL() + { + $this->setType(self::DESCRIBE_SYMBOL); + } + + protected function DESCRIPTION_SYMBOL() + { + $this->setType(self::DESCRIPTION_SYMBOL); + } + + protected function DES_KEY_FILE_SYMBOL() + { + $this->setType(self::DES_KEY_FILE_SYMBOL); + } + + protected function DETERMINISTIC_SYMBOL() + { + $this->setType(self::DETERMINISTIC_SYMBOL); + } + + protected function DIAGNOSTICS_SYMBOL() + { + $this->setType(self::DIAGNOSTICS_SYMBOL); + } + + protected function DIRECTORY_SYMBOL() + { + $this->setType(self::DIRECTORY_SYMBOL); + } + + protected function DISABLE_SYMBOL() + { + $this->setType(self::DISABLE_SYMBOL); + } + + protected function DISCARD_SYMBOL() + { + $this->setType(self::DISCARD_SYMBOL); + } + + protected function DISK_SYMBOL() + { + $this->setType(self::DISK_SYMBOL); + } + + protected function DISTINCT_SYMBOL() + { + $this->setType(self::DISTINCT_SYMBOL); + } + + protected function DISTINCTROW_SYMBOL() + { + $this->setType(self::DISTINCT_SYMBOL); // Synonym + } + + protected function DIV_SYMBOL() + { + $this->setType(self::DIV_SYMBOL); + } + + protected function DOUBLE_SYMBOL() + { + $this->setType(self::DOUBLE_SYMBOL); + } + + protected function DO_SYMBOL() + { + $this->setType(self::DO_SYMBOL); + } + + protected function DROP_SYMBOL() + { + $this->setType(self::DROP_SYMBOL); + } + + protected function DUAL_SYMBOL() + { + $this->setType(self::DUAL_SYMBOL); + } + + protected function DUMPFILE_SYMBOL() + { + $this->setType(self::DUMPFILE_SYMBOL); + } + + protected function DUPLICATE_SYMBOL() + { + $this->setType(self::DUPLICATE_SYMBOL); + } + + protected function DYNAMIC_SYMBOL() + { + $this->setType(self::DYNAMIC_SYMBOL); + } + + protected function EACH_SYMBOL() + { + $this->setType(self::EACH_SYMBOL); + } + + protected function ELSE_SYMBOL() + { + $this->setType(self::ELSE_SYMBOL); + } + + protected function ELSEIF_SYMBOL() + { + $this->setType(self::ELSEIF_SYMBOL); + } + + protected function EMPTY_SYMBOL() + { + $this->setType(self::EMPTY_SYMBOL); + } + + protected function ENABLE_SYMBOL() + { + $this->setType(self::ENABLE_SYMBOL); + } + + protected function ENCLOSED_SYMBOL() + { + $this->setType(self::ENCLOSED_SYMBOL); + } + + protected function ENCRYPTION_SYMBOL() + { + $this->setType(self::ENCRYPTION_SYMBOL); + } + + protected function END_SYMBOL() + { + $this->setType(self::END_SYMBOL); + } + + protected function ENDS_SYMBOL() + { + $this->setType(self::ENDS_SYMBOL); + } + + protected function ENFORCED_SYMBOL() + { + $this->setType(self::ENFORCED_SYMBOL); + } + + protected function ENGINE_SYMBOL() + { + $this->setType(self::ENGINE_SYMBOL); + } + + protected function ENGINES_SYMBOL() + { + $this->setType(self::ENGINES_SYMBOL); + } + + protected function ENUM_SYMBOL() + { + $this->setType(self::ENUM_SYMBOL); + } + + protected function ERROR_SYMBOL() + { + $this->setType(self::ERROR_SYMBOL); + } + + protected function ERRORS_SYMBOL() + { + $this->setType(self::ERRORS_SYMBOL); + } + + protected function ESCAPED_SYMBOL() + { + $this->setType(self::ESCAPED_SYMBOL); + } + + protected function ESCAPE_SYMBOL() + { + $this->setType(self::ESCAPE_SYMBOL); + } + + protected function EVENT_SYMBOL() + { + $this->setType(self::EVENT_SYMBOL); + } + + protected function EVENTS_SYMBOL() + { + $this->setType(self::EVENTS_SYMBOL); + } + + protected function EVERY_SYMBOL() + { + $this->setType(self::EVERY_SYMBOL); + } + + protected function EXCHANGE_SYMBOL() + { + $this->setType(self::EXCHANGE_SYMBOL); + } + + protected function EXCEPT_SYMBOL() + { + $this->setType(self::EXCEPT_SYMBOL); + } + + protected function EXECUTE_SYMBOL() + { + $this->setType(self::EXECUTE_SYMBOL); + } + + protected function EXISTS_SYMBOL() + { + $this->setType(self::EXISTS_SYMBOL); + } + + protected function EXIT_SYMBOL() + { + $this->setType(self::EXIT_SYMBOL); + } + + protected function EXPANSION_SYMBOL() + { + $this->setType(self::EXPANSION_SYMBOL); + } + + protected function EXPIRE_SYMBOL() + { + $this->setType(self::EXPIRE_SYMBOL); + } + + protected function EXPLAIN_SYMBOL() + { + $this->setType(self::EXPLAIN_SYMBOL); + } + + protected function EXPORT_SYMBOL() + { + $this->setType(self::EXPORT_SYMBOL); + } + + protected function EXTENDED_SYMBOL() + { + $this->setType(self::EXTENDED_SYMBOL); + } + + protected function EXTENT_SIZE_SYMBOL() + { + $this->setType(self::EXTENT_SIZE_SYMBOL); + } + + protected function EXTRACT_SYMBOL() + { + $this->setType($this->determineFunction(self::EXTRACT_SYMBOL)); // SQL-2003-N + } + + protected function FALSE_SYMBOL() + { + $this->setType(self::FALSE_SYMBOL); + } + + protected function FAILED_LOGIN_ATTEMPTS_SYMBOL() + { + $this->setType(self::FAILED_LOGIN_ATTEMPTS_SYMBOL); + } + + protected function FAST_SYMBOL() + { + $this->setType(self::FAST_SYMBOL); + } + + protected function FAULTS_SYMBOL() + { + $this->setType(self::FAULTS_SYMBOL); + } + + protected function FETCH_SYMBOL() + { + $this->setType(self::FETCH_SYMBOL); + } + + protected function FIELDS_SYMBOL() + { + $this->setType(self::COLUMNS_SYMBOL); // Synonym + } + + protected function FILE_BLOCK_SIZE_SYMBOL() + { + $this->setType(self::FILE_BLOCK_SIZE_SYMBOL); + } + + protected function FILE_SYMBOL() + { + $this->setType(self::FILE_SYMBOL); + } + + protected function FILTER_SYMBOL() + { + $this->setType(self::FILTER_SYMBOL); + } + + protected function FIRST_SYMBOL() + { + $this->setType(self::FIRST_SYMBOL); + } + + protected function FIRST_VALUE_SYMBOL() + { + $this->setType(self::FIRST_VALUE_SYMBOL); + } + + protected function FIXED_SYMBOL() + { + $this->setType(self::FIXED_SYMBOL); + } + + protected function FLOAT4_SYMBOL() + { + $this->setType(self::FLOAT_SYMBOL); // Synonym + } + + protected function FLOAT8_SYMBOL() + { + $this->setType(self::DOUBLE_SYMBOL); // Synonym + } + + protected function FLOAT_SYMBOL() + { + $this->setType(self::FLOAT_SYMBOL); + } + + protected function FLUSH_SYMBOL() + { + $this->setType(self::FLUSH_SYMBOL); + } + + protected function FOLLOWS_SYMBOL() + { + $this->setType(self::FOLLOWS_SYMBOL); + } + + protected function FOLLOWING_SYMBOL() + { + $this->setType(self::FOLLOWING_SYMBOL); + } + + protected function FORCE_SYMBOL() + { + $this->setType(self::FORCE_SYMBOL); + } + + protected function FOR_SYMBOL() + { + $this->setType(self::FOR_SYMBOL); + } + + protected function FOREIGN_SYMBOL() + { + $this->setType(self::FOREIGN_SYMBOL); + } + + protected function FORMAT_SYMBOL() + { + $this->setType(self::FORMAT_SYMBOL); + } + + protected function FOUND_SYMBOL() + { + $this->setType(self::FOUND_SYMBOL); + } + + protected function FROM_SYMBOL() + { + $this->setType(self::FROM_SYMBOL); + } + + protected function FULLTEXT_SYMBOL() + { + $this->setType(self::FULLTEXT_SYMBOL); + } + + protected function FULL_SYMBOL() + { + $this->setType(self::FULL_SYMBOL); + } + + protected function FUNCTION_SYMBOL() + { + $this->setType(self::FUNCTION_SYMBOL); + } + + protected function GENERATED_SYMBOL() + { + $this->setType(self::GENERATED_SYMBOL); + } + + protected function GENERAL_SYMBOL() + { + $this->setType(self::GENERAL_SYMBOL); + } + + protected function GEOMETRYCOLLECTION_SYMBOL() + { + $this->setType(self::GEOMETRYCOLLECTION_SYMBOL); + } + + protected function GEOMETRY_SYMBOL() + { + $this->setType(self::GEOMETRY_SYMBOL); + } + + protected function GET_SYMBOL() + { + $this->setType(self::GET_SYMBOL); + } + + protected function GET_FORMAT_SYMBOL() + { + $this->setType(self::GET_FORMAT_SYMBOL); + } + + protected function GET_MASTER_PUBLIC_KEY_SYMBOL() + { + $this->setType(self::GET_MASTER_PUBLIC_KEY_SYMBOL); + } + + protected function GLOBAL_SYMBOL() + { + $this->setType(self::GLOBAL_SYMBOL); + } + + protected function GRANT_SYMBOL() + { + $this->setType(self::GRANT_SYMBOL); + } + + protected function GRANTS_SYMBOL() + { + $this->setType(self::GRANTS_SYMBOL); + } + + protected function GROUP_CONCAT_SYMBOL() + { + $this->setType($this->determineFunction(self::GROUP_CONCAT_SYMBOL)); + } + + protected function GROUP_SYMBOL() + { + $this->setType(self::GROUP_SYMBOL); + } + + protected function GROUP_REPLICATION_SYMBOL() + { + $this->setType(self::GROUP_REPLICATION_SYMBOL); + } + + protected function GROUPING_SYMBOL() + { + $this->setType(self::GROUPING_SYMBOL); + } + + protected function GROUPS_SYMBOL() + { + $this->setType(self::GROUPS_SYMBOL); + } + + protected function HANDLER_SYMBOL() + { + $this->setType(self::HANDLER_SYMBOL); + } + + protected function HASH_SYMBOL() + { + $this->setType(self::HASH_SYMBOL); + } + + protected function HAVING_SYMBOL() + { + $this->setType(self::HAVING_SYMBOL); + } + + protected function HELP_SYMBOL() + { + $this->setType(self::HELP_SYMBOL); + } + + protected function HIGH_PRIORITY_SYMBOL() + { + $this->setType(self::HIGH_PRIORITY_SYMBOL); + } + + protected function HISTOGRAM_SYMBOL() + { + $this->setType(self::HISTOGRAM_SYMBOL); + } + + protected function HISTORY_SYMBOL() + { + $this->setType(self::HISTORY_SYMBOL); + } + + protected function HOSTS_SYMBOL() + { + $this->setType(self::HOSTS_SYMBOL); + } + + protected function HOST_SYMBOL() + { + $this->setType(self::HOST_SYMBOL); + } + + protected function HOUR_SYMBOL() + { + $this->setType(self::HOUR_SYMBOL); + } + + protected function HOUR_MICROSECOND_SYMBOL() + { + $this->setType(self::HOUR_MICROSECOND_SYMBOL); + } + + protected function HOUR_MINUTE_SYMBOL() + { + $this->setType(self::HOUR_MINUTE_SYMBOL); + } + + protected function HOUR_SECOND_SYMBOL() + { + $this->setType(self::HOUR_SECOND_SYMBOL); + } + + protected function IDENTIFIED_SYMBOL() + { + $this->setType(self::IDENTIFIED_SYMBOL); + } + + protected function IF_SYMBOL() + { + $this->setType(self::IF_SYMBOL); + } + + protected function IGNORE_SYMBOL() + { + $this->setType(self::IGNORE_SYMBOL); + } + + protected function IGNORE_SERVER_IDS_SYMBOL() + { + $this->setType(self::IGNORE_SERVER_IDS_SYMBOL); + } + + protected function IMPORT_SYMBOL() + { + $this->setType(self::IMPORT_SYMBOL); + } + + protected function IN_SYMBOL() + { + $this->setType(self::IN_SYMBOL); + } + + protected function INDEX_SYMBOL() + { + $this->setType(self::INDEX_SYMBOL); + } + + protected function INDEXES_SYMBOL() + { + $this->setType(self::INDEXES_SYMBOL); + } + + protected function INFILE_SYMBOL() + { + $this->setType(self::INFILE_SYMBOL); + } + + protected function INITIAL_SIZE_SYMBOL() + { + $this->setType(self::INITIAL_SIZE_SYMBOL); + } + + protected function INNER_SYMBOL() + { + $this->setType(self::INNER_SYMBOL); + } + + protected function INOUT_SYMBOL() + { + $this->setType(self::INOUT_SYMBOL); + } + + protected function INSENSITIVE_SYMBOL() + { + $this->setType(self::INSENSITIVE_SYMBOL); + } + + protected function INSERT_SYMBOL() + { + $this->setType(self::INSERT_SYMBOL); + } + + protected function INSERT_METHOD_SYMBOL() + { + $this->setType(self::INSERT_METHOD_SYMBOL); + } + + protected function INSTANCE_SYMBOL() + { + $this->setType(self::INSTANCE_SYMBOL); + } + + protected function INSTALL_SYMBOL() + { + $this->setType(self::INSTALL_SYMBOL); + } + + protected function INT_SYMBOL() + { + $this->setType(self::INT_SYMBOL); + } + + protected function INTEGER_SYMBOL() + { + $this->setType(self::INT_SYMBOL); // Synonym + } + + protected function INTERVAL_SYMBOL() + { + $this->setType(self::INTERVAL_SYMBOL); + } + + protected function INTO_SYMBOL() + { + $this->setType(self::INTO_SYMBOL); + } + + protected function INVISIBLE_SYMBOL() + { + $this->setType(self::INVISIBLE_SYMBOL); + } + + protected function INVOKER_SYMBOL() + { + $this->setType(self::INVOKER_SYMBOL); + } + + protected function IO_SYMBOL() + { + $this->setType(self::IO_SYMBOL); + } + + protected function IPC_SYMBOL() + { + $this->setType(self::IPC_SYMBOL); + } + + protected function IS_SYMBOL() + { + $this->setType(self::IS_SYMBOL); + } + + protected function ISOLATION_SYMBOL() + { + $this->setType(self::ISOLATION_SYMBOL); + } + + protected function ISSUER_SYMBOL() + { + $this->setType(self::ISSUER_SYMBOL); + } + + protected function ITERATE_SYMBOL() + { + $this->setType(self::ITERATE_SYMBOL); + } + + protected function JOIN_SYMBOL() + { + $this->setType(self::JOIN_SYMBOL); + } + + protected function JSON_SYMBOL() + { + $this->setType(self::JSON_SYMBOL); + } + + protected function JSON_TABLE_SYMBOL() + { + $this->setType(self::JSON_TABLE_SYMBOL); + } + + protected function JSON_ARRAYAGG_SYMBOL() + { + $this->setType(self::JSON_ARRAYAGG_SYMBOL); + } + + protected function JSON_OBJECTAGG_SYMBOL() + { + $this->setType(self::JSON_OBJECTAGG_SYMBOL); + } + + protected function KEYS_SYMBOL() + { + $this->setType(self::KEYS_SYMBOL); + } + + protected function KEY_SYMBOL() + { + $this->setType(self::KEY_SYMBOL); + } + + protected function KEY_BLOCK_SIZE_SYMBOL() + { + $this->setType(self::KEY_BLOCK_SIZE_SYMBOL); + } + + protected function KILL_SYMBOL() + { + $this->setType(self::KILL_SYMBOL); + } + + protected function LAG_SYMBOL() + { + $this->setType(self::LAG_SYMBOL); + } + + protected function LANGUAGE_SYMBOL() + { + $this->setType(self::LANGUAGE_SYMBOL); + } + + protected function LAST_SYMBOL() + { + $this->setType(self::LAST_SYMBOL); + } + + protected function LAST_VALUE_SYMBOL() + { + $this->setType(self::LAST_VALUE_SYMBOL); + } + + protected function LATERAL_SYMBOL() + { + $this->setType(self::LATERAL_SYMBOL); + } + + protected function LEAD_SYMBOL() + { + $this->setType(self::LEAD_SYMBOL); + } + + protected function LEADING_SYMBOL() + { + $this->setType(self::LEADING_SYMBOL); + } + + protected function LEAVE_SYMBOL() + { + $this->setType(self::LEAVE_SYMBOL); + } + + protected function LEAVES_SYMBOL() + { + $this->setType(self::LEAVES_SYMBOL); + } + + protected function LEFT_SYMBOL() + { + $this->setType(self::LEFT_SYMBOL); + } + + protected function LESS_SYMBOL() + { + $this->setType(self::LESS_SYMBOL); + } + + protected function LEVEL_SYMBOL() + { + $this->setType(self::LEVEL_SYMBOL); + } + + protected function LIKE_SYMBOL() + { + $this->setType(self::LIKE_SYMBOL); + } + + protected function LIMIT_SYMBOL() + { + $this->setType(self::LIMIT_SYMBOL); + } + + protected function LINEAR_SYMBOL() + { + $this->setType(self::LINEAR_SYMBOL); + } + + protected function LINES_SYMBOL() + { + $this->setType(self::LINES_SYMBOL); + } + + protected function LINESTRING_SYMBOL() + { + $this->setType(self::LINESTRING_SYMBOL); + } + + protected function LIST_SYMBOL() + { + $this->setType(self::LIST_SYMBOL); + } + + protected function LOAD_SYMBOL() + { + $this->setType(self::LOAD_SYMBOL); + } + + protected function LOCALTIME_SYMBOL() + { + $this->setType(self::NOW_SYMBOL); // Synonym + } + + protected function LOCALTIMESTAMP_SYMBOL() + { + $this->setType(self::NOW_SYMBOL); // Synonym + } + + protected function LOCAL_SYMBOL() + { + $this->setType(self::LOCAL_SYMBOL); + } + + protected function LOCATOR_SYMBOL() + { + $this->setType(self::LOCATOR_SYMBOL); + } + + protected function LOCK_SYMBOL() + { + $this->setType(self::LOCK_SYMBOL); + } + + protected function LOCKS_SYMBOL() + { + $this->setType(self::LOCKS_SYMBOL); + } + + protected function LOGFILE_SYMBOL() + { + $this->setType(self::LOGFILE_SYMBOL); + } + + protected function LOGS_SYMBOL() + { + $this->setType(self::LOGS_SYMBOL); + } + + protected function LONGBLOB_SYMBOL() + { + $this->setType(self::LONGBLOB_SYMBOL); + } + + protected function LONGTEXT_SYMBOL() + { + $this->setType(self::LONGTEXT_SYMBOL); + } + + protected function LONG_SYMBOL() + { + $this->setType(self::LONG_SYMBOL); + } + + protected function LOOP_SYMBOL() + { + $this->setType(self::LOOP_SYMBOL); + } + + protected function LOW_PRIORITY_SYMBOL() + { + $this->setType(self::LOW_PRIORITY_SYMBOL); + } + + protected function MASTER_SYMBOL() + { + $this->setType(self::MASTER_SYMBOL); + } + + protected function MASTER_AUTO_POSITION_SYMBOL() + { + $this->setType(self::MASTER_AUTO_POSITION_SYMBOL); + } + + protected function MASTER_BIND_SYMBOL() + { + $this->setType(self::MASTER_BIND_SYMBOL); + } + + protected function MASTER_COMPRESSION_ALGORITHM_SYMBOL() + { + $this->setType(self::MASTER_COMPRESSION_ALGORITHM_SYMBOL); + } + + protected function MASTER_CONNECT_RETRY_SYMBOL() + { + $this->setType(self::MASTER_CONNECT_RETRY_SYMBOL); + } + + protected function MASTER_DELAY_SYMBOL() + { + $this->setType(self::MASTER_DELAY_SYMBOL); + } + + protected function MASTER_HEARTBEAT_PERIOD_SYMBOL() + { + $this->setType(self::MASTER_HEARTBEAT_PERIOD_SYMBOL); + } + + protected function MASTER_HOST_SYMBOL() + { + $this->setType(self::MASTER_HOST_SYMBOL); + } + + protected function NETWORK_NAMESPACE_SYMBOL() + { + $this->setType(self::NETWORK_NAMESPACE_SYMBOL); + } + + protected function MASTER_LOG_FILE_SYMBOL() + { + $this->setType(self::MASTER_LOG_FILE_SYMBOL); + } + + protected function MASTER_LOG_POS_SYMBOL() + { + $this->setType(self::MASTER_LOG_POS_SYMBOL); + } + + protected function MASTER_PASSWORD_SYMBOL() + { + $this->setType(self::MASTER_PASSWORD_SYMBOL); + } + + protected function MASTER_PORT_SYMBOL() + { + $this->setType(self::MASTER_PORT_SYMBOL); + } + + protected function MASTER_PUBLIC_KEY_PATH_SYMBOL() + { + $this->setType(self::MASTER_PUBLIC_KEY_PATH_SYMBOL); + } + + protected function MASTER_RETRY_COUNT_SYMBOL() + { + $this->setType(self::MASTER_RETRY_COUNT_SYMBOL); + } + + protected function MASTER_SERVER_ID_SYMBOL() + { + $this->setType(self::MASTER_SERVER_ID_SYMBOL); + } + + protected function MASTER_SSL_CAPATH_SYMBOL() + { + $this->setType(self::MASTER_SSL_CAPATH_SYMBOL); + } + + protected function MASTER_SSL_CA_SYMBOL() + { + $this->setType(self::MASTER_SSL_CA_SYMBOL); + } + + protected function MASTER_SSL_CERT_SYMBOL() + { + $this->setType(self::MASTER_SSL_CERT_SYMBOL); + } + + protected function MASTER_SSL_CIPHER_SYMBOL() + { + $this->setType(self::MASTER_SSL_CIPHER_SYMBOL); + } + + protected function MASTER_SSL_CRL_SYMBOL() + { + $this->setType(self::MASTER_SSL_CRL_SYMBOL); + } + + protected function MASTER_SSL_CRLPATH_SYMBOL() + { + $this->setType(self::MASTER_SSL_CRLPATH_SYMBOL); + } + + protected function MASTER_SSL_KEY_SYMBOL() + { + $this->setType(self::MASTER_SSL_KEY_SYMBOL); + } + + protected function MASTER_SSL_SYMBOL() + { + $this->setType(self::MASTER_SSL_SYMBOL); + } + + protected function MASTER_SSL_VERIFY_SERVER_CERT_SYMBOL() + { + $this->setType(self::MASTER_SSL_VERIFY_SERVER_CERT_SYMBOL); + } + + protected function MASTER_TLS_VERSION_SYMBOL() + { + $this->setType(self::MASTER_TLS_VERSION_SYMBOL); + } + + protected function MASTER_TLS_CIPHERSUITES_SYMBOL() + { + $this->setType(self::MASTER_TLS_CIPHERSUITES_SYMBOL); + } + + protected function MASTER_USER_SYMBOL() + { + $this->setType(self::MASTER_USER_SYMBOL); + } + + protected function MASTER_ZSTD_COMPRESSION_LEVEL_SYMBOL() + { + $this->setType(self::MASTER_ZSTD_COMPRESSION_LEVEL_SYMBOL); + } + + protected function MATCH_SYMBOL() + { + $this->setType(self::MATCH_SYMBOL); + } + + protected function MAX_SYMBOL() + { + $this->setType($this->determineFunction(self::MAX_SYMBOL)); // SQL-2003-N + } + + protected function MAX_CONNECTIONS_PER_HOUR_SYMBOL() + { + $this->setType(self::MAX_CONNECTIONS_PER_HOUR_SYMBOL); + } + + protected function MAX_QUERIES_PER_HOUR_SYMBOL() + { + $this->setType(self::MAX_QUERIES_PER_HOUR_SYMBOL); + } + + protected function MAX_ROWS_SYMBOL() + { + $this->setType(self::MAX_ROWS_SYMBOL); + } + + protected function MAX_SIZE_SYMBOL() + { + $this->setType(self::MAX_SIZE_SYMBOL); + } + + protected function MAX_STATEMENT_TIME_SYMBOL() + { + $this->setType(self::MAX_STATEMENT_TIME_SYMBOL); + } + + protected function MAX_UPDATES_PER_HOUR_SYMBOL() + { + $this->setType(self::MAX_UPDATES_PER_HOUR_SYMBOL); + } + + protected function MAX_USER_CONNECTIONS_SYMBOL() + { + $this->setType(self::MAX_USER_CONNECTIONS_SYMBOL); + } + + protected function MAXVALUE_SYMBOL() + { + $this->setType(self::MAXVALUE_SYMBOL); + } + + protected function MEDIUM_SYMBOL() + { + $this->setType(self::MEDIUM_SYMBOL); + } + + protected function MEDIUMBLOB_SYMBOL() + { + $this->setType(self::MEDIUMBLOB_SYMBOL); + } + + protected function MEDIUMINT_SYMBOL() + { + $this->setType(self::MEDIUMINT_SYMBOL); + } + + protected function MEDIUMTEXT_SYMBOL() + { + $this->setType(self::MEDIUMTEXT_SYMBOL); + } + + protected function MEMBER_SYMBOL() + { + $this->setType(self::MEMBER_SYMBOL); + } + + protected function MEMORY_SYMBOL() + { + $this->setType(self::MEMORY_SYMBOL); + } + + protected function MERGE_SYMBOL() + { + $this->setType(self::MERGE_SYMBOL); + } + + protected function MESSAGE_TEXT_SYMBOL() + { + $this->setType(self::MESSAGE_TEXT_SYMBOL); + } + + protected function MICROSECOND_SYMBOL() + { + $this->setType(self::MICROSECOND_SYMBOL); + } + + protected function MIDDLEINT_SYMBOL() + { + $this->setType(self::MEDIUMINT_SYMBOL); // Synonym + } + + protected function MIGRATE_SYMBOL() + { + $this->setType(self::MIGRATE_SYMBOL); + } + + protected function MINUTE_SYMBOL() + { + $this->setType(self::MINUTE_SYMBOL); + } + + protected function MINUTE_MICROSECOND_SYMBOL() + { + $this->setType(self::MINUTE_MICROSECOND_SYMBOL); + } + + protected function MINUTE_SECOND_SYMBOL() + { + $this->setType(self::MINUTE_SECOND_SYMBOL); + } + + protected function MIN_SYMBOL() + { + $this->setType($this->determineFunction(self::MIN_SYMBOL)); // SQL-2003-N + } + + protected function MIN_ROWS_SYMBOL() + { + $this->setType(self::MIN_ROWS_SYMBOL); + } + + protected function MODE_SYMBOL() + { + $this->setType(self::MODE_SYMBOL); + } + + protected function MODIFIES_SYMBOL() + { + $this->setType(self::MODIFIES_SYMBOL); + } + + protected function MODIFY_SYMBOL() + { + $this->setType(self::MODIFY_SYMBOL); + } + + protected function MOD_SYMBOL() + { + $this->setType(self::MOD_SYMBOL); + } + + protected function MONTH_SYMBOL() + { + $this->setType(self::MONTH_SYMBOL); + } + + protected function MULTILINESTRING_SYMBOL() + { + $this->setType(self::MULTILINESTRING_SYMBOL); + } + + protected function MULTIPOINT_SYMBOL() + { + $this->setType(self::MULTIPOINT_SYMBOL); + } + + protected function MULTIPOLYGON_SYMBOL() + { + $this->setType(self::MULTIPOLYGON_SYMBOL); + } + + protected function MUTEX_SYMBOL() + { + $this->setType(self::MUTEX_SYMBOL); + } + + protected function MYSQL_ERRNO_SYMBOL() + { + $this->setType(self::MYSQL_ERRNO_SYMBOL); + } + + protected function NAME_SYMBOL() + { + $this->setType(self::NAME_SYMBOL); + } + + protected function NAMES_SYMBOL() + { + $this->setType(self::NAMES_SYMBOL); + } + + protected function NATIONAL_SYMBOL() + { + $this->setType(self::NATIONAL_SYMBOL); + } + + protected function NATURAL_SYMBOL() + { + $this->setType(self::NATURAL_SYMBOL); + } + + protected function NCHAR_SYMBOL() + { + $this->setType(self::NCHAR_SYMBOL); + } + + protected function NDBCLUSTER_SYMBOL() + { + $this->setType(self::NDBCLUSTER_SYMBOL); + } + + protected function NDB_SYMBOL() + { + $this->setType(self::NDBCLUSTER_SYMBOL); // Synonym + } + + protected function NEG_SYMBOL() + { + $this->setType(self::NEG_SYMBOL); + } + + protected function NESTED_SYMBOL() + { + $this->setType(self::NESTED_SYMBOL); + } + + protected function NEVER_SYMBOL() + { + $this->setType(self::NEVER_SYMBOL); + } + + protected function NEW_SYMBOL() + { + $this->setType(self::NEW_SYMBOL); + } + + protected function NEXT_SYMBOL() + { + $this->setType(self::NEXT_SYMBOL); + } + + protected function NODEGROUP_SYMBOL() + { + $this->setType(self::NODEGROUP_SYMBOL); + } + + protected function NONE_SYMBOL() + { + $this->setType(self::NONE_SYMBOL); + } + + protected function NONBLOCKING_SYMBOL() + { + $this->setType(self::NONBLOCKING_SYMBOL); + } + + protected function NOT2_SYMBOL() + { + $this->setType(self::NOT2_SYMBOL); + } + + protected function NOT_SYMBOL() + { + if ($this->isSqlModeActive(MySQLLexer::HighNotPrecedence)) { + $this->setType(self::NOT2_SYMBOL); + } else { + $this->setType(self::NOT_SYMBOL); + } + } + + protected function NOW_SYMBOL() + { + $this->setType($this->determineFunction(self::NOW_SYMBOL)); + } + + protected function NOWAIT_SYMBOL() + { + $this->setType(self::NOWAIT_SYMBOL); + } + + protected function NO_SYMBOL() + { + $this->setType(self::NO_SYMBOL); + } + + protected function NO_WAIT_SYMBOL() + { + $this->setType(self::NO_WAIT_SYMBOL); + } + + protected function NO_WRITE_TO_BINLOG_SYMBOL() + { + $this->setType(self::NO_WRITE_TO_BINLOG_SYMBOL); + } + + protected function NULL_SYMBOL() + { + $this->setType(self::NULL_SYMBOL); + } + + protected function NULLS_SYMBOL() + { + $this->setType(self::NULLS_SYMBOL); + } + + protected function NUMBER_SYMBOL() + { + $this->setType(self::NUMBER_SYMBOL); + } + + protected function NUMERIC_SYMBOL() + { + $this->setType(self::NUMERIC_SYMBOL); + } + + protected function NVARCHAR_SYMBOL() + { + $this->setType(self::NVARCHAR_SYMBOL); + } + + protected function NTH_VALUE_SYMBOL() + { + $this->setType(self::NTH_VALUE_SYMBOL); + } + + protected function NTILE_SYMBOL() + { + $this->setType(self::NTILE_SYMBOL); + } + + protected function OF_SYMBOL() + { + $this->setType(self::OF_SYMBOL); + } + + protected function OFF_SYMBOL() + { + $this->setType(self::OFF_SYMBOL); + } + + protected function OFFLINE_SYMBOL() + { + $this->setType(self::OFFLINE_SYMBOL); + } + + protected function OFFSET_SYMBOL() + { + $this->setType(self::OFFSET_SYMBOL); + } + + protected function OJ_SYMBOL() + { + $this->setType(self::OJ_SYMBOL); + } + + protected function OLD_PASSWORD_SYMBOL() + { + $this->setType(self::OLD_PASSWORD_SYMBOL); + } + + protected function OLD_SYMBOL() + { + $this->setType(self::OLD_SYMBOL); + } + + protected function ON_SYMBOL() + { + $this->setType(self::ON_SYMBOL); + } + + protected function ONLINE_SYMBOL() + { + $this->setType(self::ONLINE_SYMBOL); + } + + protected function ONE_SYMBOL() + { + $this->setType(self::ONE_SYMBOL); + } + + protected function ONLY_SYMBOL() + { + $this->setType(self::ONLY_SYMBOL); + } + + protected function OPEN_SYMBOL() + { + $this->setType(self::OPEN_SYMBOL); + } + + protected function OPTIONAL_SYMBOL() + { + $this->setType(self::OPTIONAL_SYMBOL); + } + + protected function OPTIONALLY_SYMBOL() + { + $this->setType(self::OPTIONALLY_SYMBOL); + } + + protected function OPTION_SYMBOL() + { + $this->setType(self::OPTION_SYMBOL); + } + + protected function OPTIONS_SYMBOL() + { + $this->setType(self::OPTIONS_SYMBOL); + } + + protected function OPTIMIZE_SYMBOL() + { + $this->setType(self::OPTIMIZE_SYMBOL); + } + + protected function OPTIMIZER_COSTS_SYMBOL() + { + $this->setType(self::OPTIMIZER_COSTS_SYMBOL); + } + + protected function ORDER_SYMBOL() + { + $this->setType(self::ORDER_SYMBOL); + } + + protected function ORDINALITY_SYMBOL() + { + $this->setType(self::ORDINALITY_SYMBOL); + } + + protected function ORGANIZATION_SYMBOL() + { + $this->setType(self::ORGANIZATION_SYMBOL); + } + + protected function OR_SYMBOL() + { + $this->setType(self::OR_SYMBOL); + } + + protected function OTHERS_SYMBOL() + { + $this->setType(self::OTHERS_SYMBOL); + } + + protected function OUTER_SYMBOL() + { + $this->setType(self::OUTER_SYMBOL); + } + + protected function OUTFILE_SYMBOL() + { + $this->setType(self::OUTFILE_SYMBOL); + } + + protected function OUT_SYMBOL() + { + $this->setType(self::OUT_SYMBOL); + } + + protected function OWNER_SYMBOL() + { + $this->setType(self::OWNER_SYMBOL); + } + + protected function PACK_KEYS_SYMBOL() + { + $this->setType(self::PACK_KEYS_SYMBOL); + } + + protected function PAGE_SYMBOL() + { + $this->setType(self::PAGE_SYMBOL); + } + + protected function PARSER_SYMBOL() + { + $this->setType(self::PARSER_SYMBOL); + } + + protected function PARTITIONS_SYMBOL() + { + $this->setType(self::PARTITIONS_SYMBOL); + } + + protected function PARTITION_SYMBOL() + { + $this->setType(self::PARTITION_SYMBOL); + } + + protected function PARTIAL_SYMBOL() + { + $this->setType(self::PARTIAL_SYMBOL); + } + + protected function PARTITIONING_SYMBOL() + { + $this->setType(self::PARTITIONING_SYMBOL); + } + + protected function PASSWORD_SYMBOL() + { + $this->setType(self::PASSWORD_SYMBOL); + } + + protected function PATH_SYMBOL() + { + $this->setType(self::PATH_SYMBOL); + } + + protected function PERCENT_RANK_SYMBOL() + { + $this->setType(self::PERCENT_RANK_SYMBOL); + } + + protected function PERSIST_SYMBOL() + { + $this->setType(self::PERSIST_SYMBOL); + } + + protected function PERSIST_ONLY_SYMBOL() + { + $this->setType(self::PERSIST_ONLY_SYMBOL); + } + + protected function PHASE_SYMBOL() + { + $this->setType(self::PHASE_SYMBOL); + } + + protected function PLUGIN_SYMBOL() + { + $this->setType(self::PLUGIN_SYMBOL); + } + + protected function PLUGINS_SYMBOL() + { + $this->setType(self::PLUGINS_SYMBOL); + } + + protected function PLUGIN_DIR_SYMBOL() + { + $this->setType(self::PLUGIN_DIR_SYMBOL); + } + + protected function POINT_SYMBOL() + { + $this->setType(self::POINT_SYMBOL); + } + + protected function POLYGON_SYMBOL() + { + $this->setType(self::POLYGON_SYMBOL); + } + + protected function PORT_SYMBOL() + { + $this->setType(self::PORT_SYMBOL); + } + + protected function POSITION_SYMBOL() + { + $this->setType($this->determineFunction(self::POSITION_SYMBOL)); // SQL-2003-N + } + + protected function PRECEDES_SYMBOL() + { + $this->setType(self::PRECEDES_SYMBOL); + } + + protected function PRECEDING_SYMBOL() + { + $this->setType(self::PRECEDING_SYMBOL); + } + + protected function PRECISION_SYMBOL() + { + $this->setType(self::PRECISION_SYMBOL); + } + + protected function PREPARE_SYMBOL() + { + $this->setType(self::PREPARE_SYMBOL); + } + + protected function PRESERVE_SYMBOL() + { + $this->setType(self::PRESERVE_SYMBOL); + } + + protected function PREV_SYMBOL() + { + $this->setType(self::PREV_SYMBOL); + } + + protected function PRIMARY_SYMBOL() + { + $this->setType(self::PRIMARY_SYMBOL); + } + + protected function PRIVILEGES_SYMBOL() + { + $this->setType(self::PRIVILEGES_SYMBOL); + } + + protected function PRIVILEGE_CHECKS_USER_SYMBOL() + { + $this->setType(self::PRIVILEGE_CHECKS_USER_SYMBOL); + } + + protected function PROCEDURE_SYMBOL() + { + $this->setType(self::PROCEDURE_SYMBOL); + } + + protected function PROCESS_SYMBOL() + { + $this->setType(self::PROCESS_SYMBOL); + } + + protected function PROCESSLIST_SYMBOL() + { + $this->setType(self::PROCESSLIST_SYMBOL); + } + + protected function PROFILE_SYMBOL() + { + $this->setType(self::PROFILE_SYMBOL); + } + + protected function PROFILES_SYMBOL() + { + $this->setType(self::PROFILES_SYMBOL); + } + + protected function PROXY_SYMBOL() + { + $this->setType(self::PROXY_SYMBOL); + } + + protected function PURGE_SYMBOL() + { + $this->setType(self::PURGE_SYMBOL); + } + + protected function QUARTER_SYMBOL() + { + $this->setType(self::QUARTER_SYMBOL); + } + + protected function QUERY_SYMBOL() + { + $this->setType(self::QUERY_SYMBOL); + } + + protected function QUICK_SYMBOL() + { + $this->setType(self::QUICK_SYMBOL); + } + + protected function RANDOM_SYMBOL() + { + $this->setType(self::RANDOM_SYMBOL); + } + + protected function RANGE_SYMBOL() + { + $this->setType(self::RANGE_SYMBOL); + } + + protected function RANK_SYMBOL() + { + $this->setType(self::RANK_SYMBOL); + } + + protected function READS_SYMBOL() + { + $this->setType(self::READS_SYMBOL); + } + + protected function READ_ONLY_SYMBOL() + { + $this->setType(self::READ_ONLY_SYMBOL); + } + + protected function READ_SYMBOL() + { + $this->setType(self::READ_SYMBOL); + } + + protected function READ_WRITE_SYMBOL() + { + $this->setType(self::READ_WRITE_SYMBOL); + } + + protected function REAL_SYMBOL() + { + $this->setType(self::REAL_SYMBOL); + } + + protected function REBUILD_SYMBOL() + { + $this->setType(self::REBUILD_SYMBOL); + } + + protected function RECOVER_SYMBOL() + { + $this->setType(self::RECOVER_SYMBOL); + } + + protected function REDOFILE_SYMBOL() + { + $this->setType(self::REDOFILE_SYMBOL); + } + + protected function REDO_BUFFER_SIZE_SYMBOL() + { + $this->setType(self::REDO_BUFFER_SIZE_SYMBOL); + } + + protected function REDUNDANT_SYMBOL() + { + $this->setType(self::REDUNDANT_SYMBOL); + } + + protected function REFERENCES_SYMBOL() + { + $this->setType(self::REFERENCES_SYMBOL); + } + + protected function REFERENCE_SYMBOL() + { + $this->setType(self::REFERENCE_SYMBOL); + } + + protected function RECURSIVE_SYMBOL() + { + $this->setType(self::RECURSIVE_SYMBOL); + } + + protected function REGEXP_SYMBOL() + { + $this->setType(self::REGEXP_SYMBOL); + } + + protected function RELAY_SYMBOL() + { + $this->setType(self::RELAY_SYMBOL); + } + + protected function RELAYLOG_SYMBOL() + { + $this->setType(self::RELAYLOG_SYMBOL); + } + + protected function RELAY_LOG_FILE_SYMBOL() + { + $this->setType(self::RELAY_LOG_FILE_SYMBOL); + } + + protected function RELAY_LOG_POS_SYMBOL() + { + $this->setType(self::RELAY_LOG_POS_SYMBOL); + } + + protected function RELAY_THREAD_SYMBOL() + { + $this->setType(self::RELAY_THREAD_SYMBOL); + } + + protected function RELEASE_SYMBOL() + { + $this->setType(self::RELEASE_SYMBOL); + } + + protected function RELOAD_SYMBOL() + { + $this->setType(self::RELOAD_SYMBOL); + } + + protected function REMOTE_SYMBOL() + { + $this->setType(self::REMOTE_SYMBOL); + } + + protected function REMOVE_SYMBOL() + { + $this->setType(self::REMOVE_SYMBOL); + } + + protected function RENAME_SYMBOL() + { + $this->setType(self::RENAME_SYMBOL); + } + + protected function REORGANIZE_SYMBOL() + { + $this->setType(self::REORGANIZE_SYMBOL); + } + + protected function REPAIR_SYMBOL() + { + $this->setType(self::REPAIR_SYMBOL); + } + + protected function REPEAT_SYMBOL() + { + $this->setType(self::REPEAT_SYMBOL); + } + + protected function REPEATABLE_SYMBOL() + { + $this->setType(self::REPEATABLE_SYMBOL); + } + + protected function REPLACE_SYMBOL() + { + $this->setType(self::REPLACE_SYMBOL); + } + + protected function REPLICATION_SYMBOL() + { + $this->setType(self::REPLICATION_SYMBOL); + } + + protected function REPLICATE_DO_DB_SYMBOL() + { + $this->setType(self::REPLICATE_DO_DB_SYMBOL); + } + + protected function REPLICATE_DO_TABLE_SYMBOL() + { + $this->setType(self::REPLICATE_DO_TABLE_SYMBOL); + } + + protected function REPLICATE_IGNORE_DB_SYMBOL() + { + $this->setType(self::REPLICATE_IGNORE_DB_SYMBOL); + } + + protected function REPLICATE_IGNORE_TABLE_SYMBOL() + { + $this->setType(self::REPLICATE_IGNORE_TABLE_SYMBOL); + } + + protected function REPLICATE_REWRITE_DB_SYMBOL() + { + $this->setType(self::REPLICATE_REWRITE_DB_SYMBOL); + } + + protected function REPLICATE_WILD_DO_TABLE_SYMBOL() + { + $this->setType(self::REPLICATE_WILD_DO_TABLE_SYMBOL); + } + + protected function REPLICATE_WILD_IGNORE_TABLE_SYMBOL() + { + $this->setType(self::REPLICATE_WILD_IGNORE_TABLE_SYMBOL); + } + + protected function REQUIRE_SYMBOL() + { + $this->setType(self::REQUIRE_SYMBOL); + } + + protected function REQUIRE_ROW_FORMAT_SYMBOL() + { + $this->setType(self::REQUIRE_ROW_FORMAT_SYMBOL); + } + + protected function REQUIRE_TABLE_PRIMARY_KEY_CHECK_SYMBOL() + { + $this->setType(self::REQUIRE_TABLE_PRIMARY_KEY_CHECK_SYMBOL); + } + + protected function RESOURCE_SYMBOL() + { + $this->setType(self::RESOURCE_SYMBOL); + } + + protected function RESPECT_SYMBOL() + { + $this->setType(self::RESPECT_SYMBOL); + } + + protected function RESTART_SYMBOL() + { + $this->setType(self::RESTART_SYMBOL); + } + + protected function RESTORE_SYMBOL() + { + $this->setType(self::RESTORE_SYMBOL); + } + + protected function RESTRICT_SYMBOL() + { + $this->setType(self::RESTRICT_SYMBOL); + } + + protected function RESUME_SYMBOL() + { + $this->setType(self::RESUME_SYMBOL); + } + + protected function RETAIN_SYMBOL() + { + $this->setType(self::RETAIN_SYMBOL); + } + + protected function RETURN_SYMBOL() + { + $this->setType(self::RETURN_SYMBOL); + } + + protected function RETURNED_SQLSTATE_SYMBOL() + { + $this->setType(self::RETURNED_SQLSTATE_SYMBOL); + } + + protected function RETURNS_SYMBOL() + { + $this->setType(self::RETURNS_SYMBOL); + } + + protected function REUSE_SYMBOL() + { + $this->setType(self::REUSE_SYMBOL); + } + + protected function REVERSE_SYMBOL() + { + $this->setType(self::REVERSE_SYMBOL); + } + + protected function REVOKE_SYMBOL() + { + $this->setType(self::REVOKE_SYMBOL); + } + + protected function RIGHT_SYMBOL() + { + $this->setType(self::RIGHT_SYMBOL); + } + + protected function RLIKE_SYMBOL() + { + $this->setType(self::REGEXP_SYMBOL); // Synonym + } + + protected function ROLE_SYMBOL() + { + $this->setType(self::ROLE_SYMBOL); + } + + protected function ROLLBACK_SYMBOL() + { + $this->setType(self::ROLLBACK_SYMBOL); + } + + protected function ROLLUP_SYMBOL() + { + $this->setType(self::ROLLUP_SYMBOL); + } + + protected function ROTATE_SYMBOL() + { + $this->setType(self::ROTATE_SYMBOL); + } + + protected function ROW_SYMBOL() + { + $this->setType(self::ROW_SYMBOL); + } + + protected function ROWS_SYMBOL() + { + $this->setType(self::ROWS_SYMBOL); + } + + protected function ROW_COUNT_SYMBOL() + { + $this->setType(self::ROW_COUNT_SYMBOL); + } + + protected function ROW_FORMAT_SYMBOL() + { + $this->setType(self::ROW_FORMAT_SYMBOL); + } + + protected function ROW_NUMBER_SYMBOL() + { + $this->setType(self::ROW_NUMBER_SYMBOL); + } + + protected function RTREE_SYMBOL() + { + $this->setType(self::RTREE_SYMBOL); + } + + protected function SAVEPOINT_SYMBOL() + { + $this->setType(self::SAVEPOINT_SYMBOL); + } + + protected function SCHEMA_NAME_SYMBOL() + { + $this->setType(self::SCHEMA_NAME_SYMBOL); + } + + protected function SCHEMAS_SYMBOL() + { + $this->setType(self::DATABASES_SYMBOL); // Synonym + } + + protected function SCHEMA_SYMBOL() + { + $this->setType(self::DATABASE_SYMBOL); // Synonym + } + + protected function SCHEDULE_SYMBOL() + { + $this->setType(self::SCHEDULE_SYMBOL); + } + + protected function SECOND_SYMBOL() + { + $this->setType(self::SECOND_SYMBOL); + } + + protected function SECOND_MICROSECOND_SYMBOL() + { + $this->setType(self::SECOND_MICROSECOND_SYMBOL); + } + + protected function SECONDARY_SYMBOL() + { + $this->setType(self::SECONDARY_SYMBOL); + } + + protected function SECONDARY_ENGINE_SYMBOL() + { + $this->setType(self::SECONDARY_ENGINE_SYMBOL); + } + + protected function SECONDARY_LOAD_SYMBOL() + { + $this->setType(self::SECONDARY_LOAD_SYMBOL); + } + + protected function SECONDARY_UNLOAD_SYMBOL() + { + $this->setType(self::SECONDARY_UNLOAD_SYMBOL); + } + + protected function SECURITY_SYMBOL() + { + $this->setType(self::SECURITY_SYMBOL); + } + + protected function SELECT_SYMBOL() + { + $this->setType(self::SELECT_SYMBOL); + } + + protected function SENSITIVE_SYMBOL() + { + $this->setType(self::SENSITIVE_SYMBOL); + } + + protected function SEPARATOR_SYMBOL() + { + $this->setType(self::SEPARATOR_SYMBOL); + } + + protected function SERIALIZABLE_SYMBOL() + { + $this->setType(self::SERIALIZABLE_SYMBOL); + } + + protected function SERIAL_SYMBOL() + { + $this->setType(self::SERIAL_SYMBOL); + } + + protected function SERVER_SYMBOL() + { + $this->setType(self::SERVER_SYMBOL); + } + + protected function SERVER_OPTIONS_SYMBOL() + { + $this->setType(self::SERVER_OPTIONS_SYMBOL); + } + + protected function SESSION_SYMBOL() + { + $this->setType(self::SESSION_SYMBOL); + } + + protected function SESSION_USER_SYMBOL() + { + $this->setType($this->determineFunction(self::USER_SYMBOL)); // Synonym + } + + protected function SET_SYMBOL() + { + $this->setType(self::SET_SYMBOL); + } + + protected function SET_VAR_SYMBOL() + { + $this->setType(self::SET_VAR_SYMBOL); + } + + protected function SHARE_SYMBOL() + { + $this->setType(self::SHARE_SYMBOL); + } + + protected function SHOW_SYMBOL() + { + $this->setType(self::SHOW_SYMBOL); + } + + protected function SHUTDOWN_SYMBOL() + { + $this->setType(self::SHUTDOWN_SYMBOL); + } + + protected function SIGNAL_SYMBOL() + { + $this->setType(self::SIGNAL_SYMBOL); + } + + protected function SIGNED_SYMBOL() + { + $this->setType(self::SIGNED_SYMBOL); + } + + protected function SIMPLE_SYMBOL() + { + $this->setType(self::SIMPLE_SYMBOL); + } + + protected function SKIP_SYMBOL() + { + $this->setType(self::SKIP_SYMBOL); + } + + protected function SLAVE_SYMBOL() + { + $this->setType(self::SLAVE_SYMBOL); + } + + protected function SLOW_SYMBOL() + { + $this->setType(self::SLOW_SYMBOL); + } + + protected function SMALLINT_SYMBOL() + { + $this->setType(self::SMALLINT_SYMBOL); + } + + protected function SNAPSHOT_SYMBOL() + { + $this->setType(self::SNAPSHOT_SYMBOL); + } + + protected function SOME_SYMBOL() + { + $this->setType(self::ANY_SYMBOL); // Synonym + } + + protected function SOCKET_SYMBOL() + { + $this->setType(self::SOCKET_SYMBOL); + } + + protected function SONAME_SYMBOL() + { + $this->setType(self::SONAME_SYMBOL); + } + + protected function SOUNDS_SYMBOL() + { + $this->setType(self::SOUNDS_SYMBOL); + } + + protected function SOURCE_SYMBOL() + { + $this->setType(self::SOURCE_SYMBOL); + } + + protected function SPATIAL_SYMBOL() + { + $this->setType(self::SPATIAL_SYMBOL); + } + + protected function SPECIFIC_SYMBOL() + { + $this->setType(self::SPECIFIC_SYMBOL); + } + + protected function SQLEXCEPTION_SYMBOL() + { + $this->setType(self::SQLEXCEPTION_SYMBOL); + } + + protected function SQLSTATE_SYMBOL() + { + $this->setType(self::SQLSTATE_SYMBOL); + } + + protected function SQLWARNING_SYMBOL() + { + $this->setType(self::SQLWARNING_SYMBOL); + } + + protected function SQL_AFTER_GTIDS_SYMBOL() + { + $this->setType(self::SQL_AFTER_GTIDS_SYMBOL); + } + + protected function SQL_AFTER_MTS_GAPS_SYMBOL() + { + $this->setType(self::SQL_AFTER_MTS_GAPS_SYMBOL); + } + + protected function SQL_BEFORE_GTIDS_SYMBOL() + { + $this->setType(self::SQL_BEFORE_GTIDS_SYMBOL); + } + + protected function SQL_BIG_RESULT_SYMBOL() + { + $this->setType(self::SQL_BIG_RESULT_SYMBOL); + } + + protected function SQL_BUFFER_RESULT_SYMBOL() + { + $this->setType(self::SQL_BUFFER_RESULT_SYMBOL); + } + + protected function SQL_CALC_FOUND_ROWS_SYMBOL() + { + $this->setType(self::SQL_CALC_FOUND_ROWS_SYMBOL); + } + + protected function SQL_CACHE_SYMBOL() + { + $this->setType(self::SQL_CACHE_SYMBOL); + } + + protected function SQL_NO_CACHE_SYMBOL() + { + $this->setType(self::SQL_NO_CACHE_SYMBOL); + } + + protected function SQL_SMALL_RESULT_SYMBOL() + { + $this->setType(self::SQL_SMALL_RESULT_SYMBOL); + } + + protected function SQL_SYMBOL() + { + $this->setType(self::SQL_SYMBOL); + } + + protected function SQL_THREAD_SYMBOL() + { + $this->setType(self::SQL_THREAD_SYMBOL); + } + + protected function SQL_TSI_SECOND_SYMBOL() + { + $this->setType(self::SECOND_SYMBOL); // Synonym + } + + protected function SQL_TSI_MINUTE_SYMBOL() + { + $this->setType(self::MINUTE_SYMBOL); // Synonym + } + + protected function SQL_TSI_HOUR_SYMBOL() + { + $this->setType(self::HOUR_SYMBOL); // Synonym + } + + protected function SQL_TSI_DAY_SYMBOL() + { + $this->setType(self::DAY_SYMBOL); // Synonym + } + + protected function SQL_TSI_WEEK_SYMBOL() + { + $this->setType(self::WEEK_SYMBOL); // Synonym + } + + protected function SQL_TSI_MONTH_SYMBOL() + { + $this->setType(self::MONTH_SYMBOL); // Synonym + } + + protected function SQL_TSI_QUARTER_SYMBOL() + { + $this->setType(self::QUARTER_SYMBOL); // Synonym + } + + protected function SQL_TSI_YEAR_SYMBOL() + { + $this->setType(self::YEAR_SYMBOL); // Synonym + } + + protected function SRID_SYMBOL() + { + $this->setType(self::SRID_SYMBOL); + } + + protected function SSL_SYMBOL() + { + $this->setType(self::SSL_SYMBOL); + } + + protected function STACKED_SYMBOL() + { + $this->setType(self::STACKED_SYMBOL); + } + + protected function STARTING_SYMBOL() + { + $this->setType(self::STARTING_SYMBOL); + } + + protected function STARTS_SYMBOL() + { + $this->setType(self::STARTS_SYMBOL); + } + + protected function START_SYMBOL() + { + $this->setType(self::START_SYMBOL); + } + + protected function STATS_AUTO_RECALC_SYMBOL() + { + $this->setType(self::STATS_AUTO_RECALC_SYMBOL); + } + + protected function STATS_PERSISTENT_SYMBOL() + { + $this->setType(self::STATS_PERSISTENT_SYMBOL); + } + + protected function STATS_SAMPLE_PAGES_SYMBOL() + { + $this->setType(self::STATS_SAMPLE_PAGES_SYMBOL); + } + + protected function STATUS_SYMBOL() + { + $this->setType(self::STATUS_SYMBOL); + } + + protected function STD_SYMBOL() + { + $this->setType($this->determineFunction(self::STD_SYMBOL)); + } + + protected function STDDEV_SYMBOL() + { + $this->setType($this->determineFunction(self::STD_SYMBOL)); // Synonym + } + + protected function STDDEV_POP_SYMBOL() + { + $this->setType($this->determineFunction(self::STD_SYMBOL)); // Synonym + } + + protected function STDDEV_SAMP_SYMBOL() + { + $this->setType($this->determineFunction(self::STDDEV_SAMP_SYMBOL)); // SQL-2003-N + } + + protected function STOP_SYMBOL() + { + $this->setType(self::STOP_SYMBOL); + } + + protected function STORAGE_SYMBOL() + { + $this->setType(self::STORAGE_SYMBOL); + } + + protected function STORED_SYMBOL() + { + $this->setType(self::STORED_SYMBOL); + } + + protected function STRAIGHT_JOIN_SYMBOL() + { + $this->setType(self::STRAIGHT_JOIN_SYMBOL); + } + + protected function STREAM_SYMBOL() + { + $this->setType(self::STREAM_SYMBOL); + } + + protected function STRING_SYMBOL() + { + $this->setType(self::STRING_SYMBOL); + } + + protected function SUBCLASS_ORIGIN_SYMBOL() + { + $this->setType(self::SUBCLASS_ORIGIN_SYMBOL); + } + + protected function SUBDATE_SYMBOL() + { + $this->setType($this->determineFunction(self::SUBDATE_SYMBOL)); + } + + protected function SUBJECT_SYMBOL() + { + $this->setType(self::SUBJECT_SYMBOL); + } + + protected function SUBPARTITION_SYMBOL() + { + $this->setType(self::SUBPARTITION_SYMBOL); + } + + protected function SUBPARTITIONS_SYMBOL() + { + $this->setType(self::SUBPARTITIONS_SYMBOL); + } + + protected function SUBSTR_SYMBOL() + { + $this->setType($this->determineFunction(self::SUBSTRING_SYMBOL)); // Synonym + } + + protected function SUBSTRING_SYMBOL() + { + $this->setType($this->determineFunction(self::SUBSTRING_SYMBOL)); // SQL-2003-N + } + + protected function SUM_SYMBOL() + { + $this->setType($this->determineFunction(self::SUM_SYMBOL)); // SQL-2003-N + } + + protected function SUPER_SYMBOL() + { + $this->setType(self::SUPER_SYMBOL); + } + + protected function SUSPEND_SYMBOL() + { + $this->setType(self::SUSPEND_SYMBOL); + } + + protected function SWAPS_SYMBOL() + { + $this->setType(self::SWAPS_SYMBOL); + } + + protected function SWITCHES_SYMBOL() + { + $this->setType(self::SWITCHES_SYMBOL); + } + + protected function SYSDATE_SYMBOL() + { + $this->setType($this->determineFunction(self::SYSDATE_SYMBOL)); + } + + protected function SYSTEM_SYMBOL() + { + $this->setType(self::SYSTEM_SYMBOL); + } + + protected function SYSTEM_USER_SYMBOL() + { + $this->setType($this->determineFunction(self::USER_SYMBOL)); + } + + protected function TABLE_CHECKSUM_SYMBOL() + { + $this->setType(self::TABLE_CHECKSUM_SYMBOL); + } + + protected function TABLE_SYMBOL() + { + $this->setType(self::TABLE_SYMBOL); + } + + protected function TABLES_SYMBOL() + { + $this->setType(self::TABLES_SYMBOL); + } + + protected function TABLESPACE_SYMBOL() + { + $this->setType(self::TABLESPACE_SYMBOL); + } + + protected function TABLE_NAME_SYMBOL() + { + $this->setType(self::TABLE_NAME_SYMBOL); + } + + protected function TEMPORARY_SYMBOL() + { + $this->setType(self::TEMPORARY_SYMBOL); + } + + protected function TEMPTABLE_SYMBOL() + { + $this->setType(self::TEMPTABLE_SYMBOL); + } + + protected function TERMINATED_SYMBOL() + { + $this->setType(self::TERMINATED_SYMBOL); + } + + protected function TEXT_SYMBOL() + { + $this->setType(self::TEXT_SYMBOL); + } + + protected function THAN_SYMBOL() + { + $this->setType(self::THAN_SYMBOL); + } + + protected function THEN_SYMBOL() + { + $this->setType(self::THEN_SYMBOL); + } + + protected function THREAD_PRIORITY_SYMBOL() + { + $this->setType(self::THREAD_PRIORITY_SYMBOL); + } + + protected function TIES_SYMBOL() + { + $this->setType(self::TIES_SYMBOL); + } + + protected function TIME_SYMBOL() + { + $this->setType(self::TIME_SYMBOL); + } + + protected function TIMESTAMP_SYMBOL() + { + $this->setType(self::TIMESTAMP_SYMBOL); + } + + protected function TIMESTAMP_ADD_SYMBOL() + { + $this->setType(self::TIMESTAMP_ADD_SYMBOL); + } + + protected function TIMESTAMP_DIFF_SYMBOL() + { + $this->setType(self::TIMESTAMP_DIFF_SYMBOL); + } + + protected function TINYBLOB_SYMBOL() + { + $this->setType(self::TINYBLOB_SYMBOL); + } + + protected function TINYINT_SYMBOL() + { + $this->setType(self::TINYINT_SYMBOL); + } + + protected function TINYTEXT_SYMBOL() + { + $this->setType(self::TINYTEXT_SYMBOL); + } + + protected function TO_SYMBOL() + { + $this->setType(self::TO_SYMBOL); + } + + protected function TRAILING_SYMBOL() + { + $this->setType(self::TRAILING_SYMBOL); + } + + protected function TRANSACTION_SYMBOL() + { + $this->setType(self::TRANSACTION_SYMBOL); + } + + protected function TRIGGERS_SYMBOL() + { + $this->setType(self::TRIGGERS_SYMBOL); + } + + protected function TRIGGER_SYMBOL() + { + $this->setType(self::TRIGGER_SYMBOL); + } + + protected function TRIM_SYMBOL() + { + $this->setType($this->determineFunction(self::TRIM_SYMBOL)); // SQL-2003-N + } + + protected function TRUE_SYMBOL() + { + $this->setType(self::TRUE_SYMBOL); + } + + protected function TRUNCATE_SYMBOL() + { + $this->setType(self::TRUNCATE_SYMBOL); + } + + protected function TYPES_SYMBOL() + { + $this->setType(self::TYPES_SYMBOL); + } + + protected function TYPE_SYMBOL() + { + $this->setType(self::TYPE_SYMBOL); + } + + protected function UDF_RETURNS_SYMBOL() + { + $this->setType(self::UDF_RETURNS_SYMBOL); + } + + protected function UNBOUNDED_SYMBOL() + { + $this->setType(self::UNBOUNDED_SYMBOL); + } + + protected function UNCOMMITTED_SYMBOL() + { + $this->setType(self::UNCOMMITTED_SYMBOL); + } + + protected function UNDEFINED_SYMBOL() + { + $this->setType(self::UNDEFINED_SYMBOL); + } + + protected function UNDO_BUFFER_SIZE_SYMBOL() + { + $this->setType(self::UNDO_BUFFER_SIZE_SYMBOL); + } + + protected function UNDOFILE_SYMBOL() + { + $this->setType(self::UNDOFILE_SYMBOL); + } + + protected function UNDO_SYMBOL() + { + $this->setType(self::UNDO_SYMBOL); + } + + protected function UNICODE_SYMBOL() + { + $this->setType(self::UNICODE_SYMBOL); + } + + protected function UNION_SYMBOL() + { + $this->setType(self::UNION_SYMBOL); + } + + protected function UNIQUE_SYMBOL() + { + $this->setType(self::UNIQUE_SYMBOL); + } + + protected function UNKNOWN_SYMBOL() + { + $this->setType(self::UNKNOWN_SYMBOL); + } + + protected function UNINSTALL_SYMBOL() + { + $this->setType(self::UNINSTALL_SYMBOL); + } + + protected function UNLOCK_SYMBOL() + { + $this->setType(self::UNLOCK_SYMBOL); + } + + protected function UNSIGNED_SYMBOL() + { + $this->setType(self::UNSIGNED_SYMBOL); + } + + protected function UPDATE_SYMBOL() + { + $this->setType(self::UPDATE_SYMBOL); + } + + protected function UPGRADE_SYMBOL() + { + $this->setType(self::UPGRADE_SYMBOL); + } + + protected function USAGE_SYMBOL() + { + $this->setType(self::USAGE_SYMBOL); + } + + protected function USER_RESOURCES_SYMBOL() + { + $this->setType(self::USER_RESOURCES_SYMBOL); + } + + protected function USER_SYMBOL() + { + $this->setType(self::USER_SYMBOL); + } + + protected function USE_FRM_SYMBOL() + { + $this->setType(self::USE_FRM_SYMBOL); + } + + protected function USE_SYMBOL() + { + $this->setType(self::USE_SYMBOL); + } + + protected function USING_SYMBOL() + { + $this->setType(self::USING_SYMBOL); + } + + protected function UTC_DATE_SYMBOL() + { + $this->setType(self::UTC_DATE_SYMBOL); + } + + protected function UTC_TIME_SYMBOL() + { + $this->setType(self::UTC_TIME_SYMBOL); + } + + protected function UTC_TIMESTAMP_SYMBOL() + { + $this->setType(self::UTC_TIMESTAMP_SYMBOL); + } + + protected function VALIDATION_SYMBOL() + { + $this->setType(self::VALIDATION_SYMBOL); + } + + protected function VALUE_SYMBOL() + { + $this->setType(self::VALUE_SYMBOL); + } + + protected function VALUES_SYMBOL() + { + $this->setType(self::VALUES_SYMBOL); + } + + protected function VARBINARY_SYMBOL() + { + $this->setType(self::VARBINARY_SYMBOL); + } + + protected function VARCHAR_SYMBOL() + { + $this->setType(self::VARCHAR_SYMBOL); + } + + protected function VARCHARACTER_SYMBOL() + { + $this->setType(self::VARCHAR_SYMBOL); // Synonym + } + + protected function VARIABLES_SYMBOL() + { + $this->setType(self::VARIABLES_SYMBOL); + } + + protected function VARIANCE_SYMBOL() + { + $this->setType($this->determineFunction(self::VARIANCE_SYMBOL)); + } + + protected function VARYING_SYMBOL() + { + $this->setType(self::VARYING_SYMBOL); + } + + protected function VAR_POP_SYMBOL() + { + $this->setType($this->determineFunction(self::VARIANCE_SYMBOL)); // Synonym + } + + protected function VAR_SAMP_SYMBOL() + { + $this->setType($this->determineFunction(self::VAR_SAMP_SYMBOL)); + } + + protected function VCPU_SYMBOL() + { + $this->setType(self::VCPU_SYMBOL); + } + + protected function VIEW_SYMBOL() + { + $this->setType(self::VIEW_SYMBOL); + } + + protected function VIRTUAL_SYMBOL() + { + $this->setType(self::VIRTUAL_SYMBOL); + } + + protected function VISIBLE_SYMBOL() + { + $this->setType(self::VISIBLE_SYMBOL); + } + + protected function WAIT_SYMBOL() + { + $this->setType(self::WAIT_SYMBOL); + } + + protected function WARNINGS_SYMBOL() + { + $this->setType(self::WARNINGS_SYMBOL); + } + + protected function WEEK_SYMBOL() + { + $this->setType(self::WEEK_SYMBOL); + } + + protected function WHEN_SYMBOL() + { + $this->setType(self::WHEN_SYMBOL); + } + + protected function WEIGHT_STRING_SYMBOL() + { + $this->setType(self::WEIGHT_STRING_SYMBOL); + } + + protected function WHERE_SYMBOL() + { + $this->setType(self::WHERE_SYMBOL); + } + + protected function WHILE_SYMBOL() + { + $this->setType(self::WHILE_SYMBOL); + } + + protected function WINDOW_SYMBOL() + { + $this->setType(self::WINDOW_SYMBOL); + } + + protected function WITH_SYMBOL() + { + $this->setType(self::WITH_SYMBOL); + } + + protected function WITHOUT_SYMBOL() + { + $this->setType(self::WITHOUT_SYMBOL); + } + + protected function WORK_SYMBOL() + { + $this->setType(self::WORK_SYMBOL); + } + + protected function WRAPPER_SYMBOL() + { + $this->setType(self::WRAPPER_SYMBOL); + } + + protected function WRITE_SYMBOL() + { + $this->setType(self::WRITE_SYMBOL); + } + + protected function XA_SYMBOL() + { + $this->setType(self::XA_SYMBOL); + } + + protected function X509_SYMBOL() + { + $this->setType(self::X509_SYMBOL); + } + + protected function XID_SYMBOL() + { + $this->setType(self::XID_SYMBOL); + } + + protected function XML_SYMBOL() + { + $this->setType(self::XML_SYMBOL); + } + + protected function XOR_SYMBOL() + { + $this->setType(self::XOR_SYMBOL); + } + + protected function YEAR_MONTH_SYMBOL() + { + $this->setType(self::YEAR_MONTH_SYMBOL); + } + + protected function YEAR_SYMBOL() + { + $this->setType(self::YEAR_SYMBOL); + } + + protected function ZEROFILL_SYMBOL() + { + $this->setType(self::ZEROFILL_SYMBOL); + } + + protected function INT1_SYMBOL() + { + $this->setType(self::TINYINT_SYMBOL); // Synonym + } + + protected function INT2_SYMBOL() + { + $this->setType(self::SMALLINT_SYMBOL); // Synonym + } + + protected function INT3_SYMBOL() + { + $this->setType(self::MEDIUMINT_SYMBOL); // Synonym + } + + protected function INT4_SYMBOL() + { + $this->setType(self::INT_SYMBOL); // Synonym + } + + protected function INT8_SYMBOL() + { + $this->setType(self::BIGINT_SYMBOL); // Synonym + } + + protected function IDENTIFIER() + { + $this->setType(self::IDENTIFIER); + } + + protected function ROUTINE_SYMBOL() + { + $this->setType(self::ROUTINE_SYMBOL); + } + + protected function MYSQL_COMMENT_START() + { + // TODO: use a lexer mode instead of a member variable. + // Currently not used by the PHP target. + return; + } + + protected function VERSION_COMMENT_END() + { + // Currently not used by the PHP target. + return; + } + + protected function VERSION_COMMENT_START() + { + $this->consume(); // Consume the '/*'. + $this->consume(); // Consume the '!'. + while (safe_ctype_digit($this->c)) { + $this->consume(); + } + if ($this->checkVersion($this->getText())) { + // If the version check passes, consume the rest of the comment + while ($this->c !== null) { + if ($this->c === '*' && $this->n === '/') { + $this->consume(); // Consume the '*'. + $this->consume(); // Consume the '/'. + break; + } + $this->consume(); + } + } else { + // If the version check fails, skip to the end of the comment. + $this->skipCommentContent(); + } + + $this->channel = self::HIDDEN; + } + + protected function BLOCK_COMMENT() + { + $this->consume(); // Consume the '/'. + $this->consume(); // Consume the '*'. + $this->skipCommentContent(); + $this->channel = self::HIDDEN; + } + + // Helper functions ----------------------------------------------------------------------------------------------------- + + private function determineNumericType($text): int + { + if (preg_match('/^0[xX][0-9a-fA-F]+$/', $text)) { + return self::HEX_NUMBER; + } elseif (preg_match('/^0[bB][01]+$/', $text)) { + return self::BIN_NUMBER; + } elseif (preg_match('/^\d+$/', $text)) { + if (PHP_INT_MAX >= (int)$text) { + return self::INT_NUMBER; + } + return self::LONG_NUMBER; + } + return self::INVALID_INPUT; + } + + /** + * This is a place holder to support features of MySQLBaseLexer which are not yet implemented + * in the PHP target. + * + * @return int + */ + protected function determineFunction(int $type): int + { + return $type; + } +} + +class MySQLToken +{ + private $type; + private $text; + private $channel; + + public function __construct($type, $text, $channel=null) + { + $this->type = $type; + $this->text = $text; + $this->channel = $channel; + } + + public function getType() + { + return $this->type; + } + + public function getText() + { + return $this->text; + } + + public function getChannel() + { + return $this->channel; + } + + public function __toString() + { + return $this->text . ' (' . $this->type . ')'; + } +} diff --git a/wp-content/plugins/sqlite-database-integration/wp-includes/mysql-parser/MySQLParser.g4 b/wp-content/plugins/sqlite-database-integration/wp-includes/mysql-parser/MySQLParser.g4 new file mode 100644 index 00000000..33103041 --- /dev/null +++ b/wp-content/plugins/sqlite-database-integration/wp-includes/mysql-parser/MySQLParser.g4 @@ -0,0 +1,5023 @@ +parser grammar MySQLParser; + +/* + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2.0, + * as published by the Free Software Foundation. + * + * This program is designed to work with certain software (including + * but not limited to OpenSSL) that is licensed under separate terms, as + * designated in a particular file or component or in included license + * documentation. The authors of MySQL hereby grant you an additional + * permission to link the program and your derivative works with the + * separately licensed software that they have either included with + * the program or referenced in the documentation. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License, version 2.0, for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Merged in all changes up to mysql-trunk git revision [6d4f66a] (16. January 2020). + * + * MySQL grammar for ANTLR 4.5+ with language features from MySQL 5.6.0 up to MySQL 8.0. + * The server version in the generated parser can be switched at runtime, making it so possible + * to switch the supported feature set dynamically. + * + * The coverage of the MySQL language should be 100%, but there might still be bugs or omissions. + * + * To use this grammar you will need a few support classes (which should be close to where you found this grammar). + * These classes implement the target specific action code, so we don't clutter the grammar with that + * and make it simpler to adjust it for other targets. See the demo/test project for further details. + * + * Written by Mike Lischke. Direct all bug reports, omissions etc. to mike.lischke@oracle.com. + */ + +//---------------------------------------------------------------------------------------------------------------------- + +// $antlr-format alignTrailingComments on, columnLimit 130, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments off +// $antlr-format useTab off, allowShortRulesOnASingleLine off, allowShortBlocksOnASingleLine on, alignSemicolons ownLine + +options { + superClass = MySQLBaseRecognizer; + tokenVocab = MySQLLexer; + exportMacro = PARSERS_PUBLIC_TYPE; +} + +//---------------------------------------------------------------------------------------------------------------------- + +@header {/* + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2.0, + * as published by the Free Software Foundation. + * + * This program is designed to work with certain software (including + * but not limited to OpenSSL) that is licensed under separate terms, as + * designated in a particular file or component or in included license + * documentation. The authors of MySQL hereby grant you an additional + * permission to link the program and your derivative works with the + * separately licensed software that they have either included with + * the program or referenced in the documentation. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License, version 2.0, for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +} + +@postinclude { +#include "MySQLBaseRecognizer.h" +} + +//---------------------------------------------------------------------------------------------------------------------- + +query: + EOF + | (simpleStatement | beginWork) (SEMICOLON_SYMBOL EOF? | EOF) +; + +simpleStatement: + // DDL + alterStatement + | createStatement + | dropStatement + | renameTableStatement + | truncateTableStatement + | {serverVersion >= 80000}? importStatement + + // DML + | callStatement + | deleteStatement + | doStatement + | handlerStatement + | insertStatement + | loadStatement + | replaceStatement + | selectStatement + | updateStatement + | transactionOrLockingStatement + | replicationStatement + | preparedStatement + + // Data Directory + | {serverVersion >= 80000}? cloneStatement + + // Database administration + | accountManagementStatement + | tableAdministrationStatement + | installUninstallStatment + | setStatement // SET PASSWORD is handled in accountManagementStatement. + | showStatement + | {serverVersion >= 80000}? resourceGroupManagement + | otherAdministrativeStatement + + // MySQL utilitity statements + | utilityStatement + | {serverVersion >= 50604}? getDiagnostics + | signalStatement + | resignalStatement +; + +//----------------- DDL statements ------------------------------------------------------------------------------------- + +alterStatement: + ALTER_SYMBOL ( + alterTable + | alterDatabase + | PROCEDURE_SYMBOL procedureRef routineAlterOptions? + | FUNCTION_SYMBOL functionRef routineAlterOptions? + | alterView + | alterEvent + | alterTablespace + | {serverVersion >= 80014}? alterUndoTablespace + | alterLogfileGroup + | alterServer + // ALTER USER is part of the user management rule. + | {serverVersion >= 50713}? INSTANCE_SYMBOL ROTATE_SYMBOL textOrIdentifier MASTER_SYMBOL KEY_SYMBOL + ) +; + +alterDatabase: + DATABASE_SYMBOL schemaRef ( + createDatabaseOption+ + | {serverVersion < 80000}? UPGRADE_SYMBOL DATA_SYMBOL DIRECTORY_SYMBOL NAME_SYMBOL + ) +; + +alterEvent: + definerClause? EVENT_SYMBOL eventRef (ON_SYMBOL SCHEDULE_SYMBOL schedule)? ( + ON_SYMBOL COMPLETION_SYMBOL NOT_SYMBOL? PRESERVE_SYMBOL + )? (RENAME_SYMBOL TO_SYMBOL identifier)? ( + ENABLE_SYMBOL + | DISABLE_SYMBOL (ON_SYMBOL SLAVE_SYMBOL)? + )? (COMMENT_SYMBOL textLiteral)? (DO_SYMBOL compoundStatement)? +; + +alterLogfileGroup: + LOGFILE_SYMBOL GROUP_SYMBOL logfileGroupRef ADD_SYMBOL UNDOFILE_SYMBOL textLiteral alterLogfileGroupOptions? +; + +alterLogfileGroupOptions: + alterLogfileGroupOption (COMMA_SYMBOL? alterLogfileGroupOption)* +; + +alterLogfileGroupOption: + tsOptionInitialSize + | tsOptionEngine + | tsOptionWait +; + +alterServer: + SERVER_SYMBOL serverRef serverOptions +; + +alterTable: + onlineOption? ({serverVersion < 50700}? IGNORE_SYMBOL)? TABLE_SYMBOL tableRef alterTableActions? +; + +alterTableActions: + alterCommandList (partitionClause | removePartitioning)? + | partitionClause + | removePartitioning + | (alterCommandsModifierList COMMA_SYMBOL)? standaloneAlterCommands +; + +alterCommandList: + alterCommandsModifierList + | (alterCommandsModifierList COMMA_SYMBOL)? alterList +; + +alterCommandsModifierList: + alterCommandsModifier (COMMA_SYMBOL alterCommandsModifier)* +; + +standaloneAlterCommands: + DISCARD_SYMBOL TABLESPACE_SYMBOL + | IMPORT_SYMBOL TABLESPACE_SYMBOL + | alterPartition + | {serverVersion >= 80014}? (SECONDARY_LOAD_SYMBOL | SECONDARY_UNLOAD_SYMBOL) +; + +alterPartition: + ADD_SYMBOL PARTITION_SYMBOL noWriteToBinLog? ( + partitionDefinitions + | PARTITIONS_SYMBOL real_ulong_number + ) + | DROP_SYMBOL PARTITION_SYMBOL identifierList + | REBUILD_SYMBOL PARTITION_SYMBOL noWriteToBinLog? allOrPartitionNameList + + // yes, twice "no write to bin log". + | OPTIMIZE_SYMBOL PARTITION_SYMBOL noWriteToBinLog? allOrPartitionNameList noWriteToBinLog? + | ANALYZE_SYMBOL PARTITION_SYMBOL noWriteToBinLog? allOrPartitionNameList + | CHECK_SYMBOL PARTITION_SYMBOL allOrPartitionNameList checkOption* + | REPAIR_SYMBOL PARTITION_SYMBOL noWriteToBinLog? allOrPartitionNameList repairType* + | COALESCE_SYMBOL PARTITION_SYMBOL noWriteToBinLog? real_ulong_number + | TRUNCATE_SYMBOL PARTITION_SYMBOL allOrPartitionNameList + | REORGANIZE_SYMBOL PARTITION_SYMBOL noWriteToBinLog? ( + identifierList INTO_SYMBOL partitionDefinitions + )? + | EXCHANGE_SYMBOL PARTITION_SYMBOL identifier WITH_SYMBOL TABLE_SYMBOL tableRef withValidation? + | {serverVersion >= 50704}? DISCARD_SYMBOL PARTITION_SYMBOL allOrPartitionNameList TABLESPACE_SYMBOL + | {serverVersion >= 50704}? IMPORT_SYMBOL PARTITION_SYMBOL allOrPartitionNameList TABLESPACE_SYMBOL +; + +alterList: + (alterListItem | createTableOptionsSpaceSeparated) ( + COMMA_SYMBOL ( + alterListItem + | alterCommandsModifier + | createTableOptionsSpaceSeparated + ) + )* +; + +alterCommandsModifier: + alterAlgorithmOption + | alterLockOption + | withValidation +; + +alterListItem: + ADD_SYMBOL COLUMN_SYMBOL? ( + identifier fieldDefinition checkOrReferences? place? + | OPEN_PAR_SYMBOL tableElementList CLOSE_PAR_SYMBOL + ) + | ADD_SYMBOL tableConstraintDef + | CHANGE_SYMBOL COLUMN_SYMBOL? columnInternalRef identifier fieldDefinition place? + | MODIFY_SYMBOL COLUMN_SYMBOL? columnInternalRef fieldDefinition place? + | DROP_SYMBOL ( + COLUMN_SYMBOL? columnInternalRef restrict? + | FOREIGN_SYMBOL KEY_SYMBOL ( + // This part is no longer optional starting with 5.7. + {serverVersion >= 50700}? columnInternalRef + | {serverVersion < 50700}? columnInternalRef? + ) + | PRIMARY_SYMBOL KEY_SYMBOL + | keyOrIndex indexRef + | {serverVersion >= 80017}? CHECK_SYMBOL identifier + | {serverVersion >= 80019}? CONSTRAINT_SYMBOL identifier + ) + | DISABLE_SYMBOL KEYS_SYMBOL + | ENABLE_SYMBOL KEYS_SYMBOL + | ALTER_SYMBOL COLUMN_SYMBOL? columnInternalRef ( + SET_SYMBOL DEFAULT_SYMBOL ( + {serverVersion >= 80014}? exprWithParentheses + | signedLiteral + ) + | DROP_SYMBOL DEFAULT_SYMBOL + ) + | {serverVersion >= 80000}? ALTER_SYMBOL INDEX_SYMBOL indexRef visibility + | {serverVersion >= 80017}? ALTER_SYMBOL CHECK_SYMBOL identifier constraintEnforcement + | {serverVersion >= 80019}? ALTER_SYMBOL CONSTRAINT_SYMBOL identifier constraintEnforcement + | {serverVersion >= 80000}? RENAME_SYMBOL COLUMN_SYMBOL columnInternalRef TO_SYMBOL identifier + | RENAME_SYMBOL (TO_SYMBOL | AS_SYMBOL)? tableName + | {serverVersion >= 50700}? RENAME_SYMBOL keyOrIndex indexRef TO_SYMBOL indexName + | CONVERT_SYMBOL TO_SYMBOL charset ( + {serverVersion >= 80014}? DEFAULT_SYMBOL + | charsetName + ) collate? + | FORCE_SYMBOL + | ORDER_SYMBOL BY_SYMBOL alterOrderList + | {serverVersion >= 50708 && serverVersion < 80000}? UPGRADE_SYMBOL PARTITIONING_SYMBOL +; + +place: + AFTER_SYMBOL identifier + | FIRST_SYMBOL +; + +restrict: + RESTRICT_SYMBOL + | CASCADE_SYMBOL +; + +alterOrderList: + identifier direction? (COMMA_SYMBOL identifier direction?)* +; + +alterAlgorithmOption: + ALGORITHM_SYMBOL EQUAL_OPERATOR? (DEFAULT_SYMBOL | identifier) +; + +alterLockOption: + LOCK_SYMBOL EQUAL_OPERATOR? (DEFAULT_SYMBOL | identifier) +; + +indexLockAndAlgorithm: + alterAlgorithmOption alterLockOption? + | alterLockOption alterAlgorithmOption? +; + +withValidation: + {serverVersion >= 50706}? (WITH_SYMBOL | WITHOUT_SYMBOL) VALIDATION_SYMBOL +; + +removePartitioning: + REMOVE_SYMBOL PARTITIONING_SYMBOL +; + +allOrPartitionNameList: + ALL_SYMBOL + | identifierList +; + +alterTablespace: + TABLESPACE_SYMBOL tablespaceRef ( + (ADD_SYMBOL | DROP_SYMBOL) DATAFILE_SYMBOL textLiteral alterTablespaceOptions? + | {serverVersion < 80000}? ( + | CHANGE_SYMBOL DATAFILE_SYMBOL textLiteral ( + changeTablespaceOption (COMMA_SYMBOL? changeTablespaceOption)* + )? + | (READ_ONLY_SYMBOL | READ_WRITE_SYMBOL) + | NOT_SYMBOL ACCESSIBLE_SYMBOL + ) + | RENAME_SYMBOL TO_SYMBOL identifier + | {serverVersion >= 80014}? alterTablespaceOptions + ) +; + +alterUndoTablespace: + UNDO_SYMBOL TABLESPACE_SYMBOL tablespaceRef SET_SYMBOL ( + ACTIVE_SYMBOL + | INACTIVE_SYMBOL + ) undoTableSpaceOptions? +; + +undoTableSpaceOptions: + undoTableSpaceOption (COMMA_SYMBOL? undoTableSpaceOption)* +; + +undoTableSpaceOption: + tsOptionEngine +; + +alterTablespaceOptions: + alterTablespaceOption (COMMA_SYMBOL? alterTablespaceOption)* +; + +alterTablespaceOption: + INITIAL_SIZE_SYMBOL EQUAL_OPERATOR? sizeNumber + | tsOptionAutoextendSize + | tsOptionMaxSize + | tsOptionEngine + | tsOptionWait + | tsOptionEncryption +; + +changeTablespaceOption: + INITIAL_SIZE_SYMBOL EQUAL_OPERATOR? sizeNumber + | tsOptionAutoextendSize + | tsOptionMaxSize +; + +alterView: + viewAlgorithm? definerClause? viewSuid? VIEW_SYMBOL viewRef viewTail +; + +// This is not the full view_tail from sql_yacc.yy as we have either a view name or a view reference, +// depending on whether we come from createView or alterView. Everything until this difference is duplicated in those rules. +viewTail: + columnInternalRefList? AS_SYMBOL viewSelect +; + +viewSelect: + queryExpressionOrParens viewCheckOption? +; + +viewCheckOption: + WITH_SYMBOL (CASCADED_SYMBOL | LOCAL_SYMBOL)? CHECK_SYMBOL OPTION_SYMBOL +; + +//---------------------------------------------------------------------------------------------------------------------- + +createStatement: + CREATE_SYMBOL ( + createDatabase + | createTable + | createFunction + | createProcedure + | createUdf + | createLogfileGroup + | createView + | createTrigger + | createIndex + | createServer + | createTablespace + | createEvent + | {serverVersion >= 80000}? createRole + | {serverVersion >= 80011}? createSpatialReference + | {serverVersion >= 80014}? createUndoTablespace + ) +; + +createDatabase: + DATABASE_SYMBOL ifNotExists? schemaName createDatabaseOption* +; + +createDatabaseOption: + defaultCharset + | defaultCollation + | {serverVersion >= 80016}? defaultEncryption +; + +createTable: + TEMPORARY_SYMBOL? TABLE_SYMBOL ifNotExists? tableName ( + (OPEN_PAR_SYMBOL tableElementList CLOSE_PAR_SYMBOL)? createTableOptions? partitionClause? duplicateAsQueryExpression? + | LIKE_SYMBOL tableRef + | OPEN_PAR_SYMBOL LIKE_SYMBOL tableRef CLOSE_PAR_SYMBOL + ) +; + +tableElementList: + tableElement (COMMA_SYMBOL tableElement)* +; + +tableElement: + columnDefinition + | tableConstraintDef +; + +duplicateAsQueryExpression: (REPLACE_SYMBOL | IGNORE_SYMBOL)? AS_SYMBOL? queryExpressionOrParens +; + +queryExpressionOrParens: + queryExpression + | queryExpressionParens +; + +createRoutine: // Rule for external use only. + CREATE_SYMBOL (createProcedure | createFunction | createUdf) SEMICOLON_SYMBOL? EOF +; + +createProcedure: + definerClause? PROCEDURE_SYMBOL procedureName OPEN_PAR_SYMBOL ( + procedureParameter (COMMA_SYMBOL procedureParameter)* + )? CLOSE_PAR_SYMBOL routineCreateOption* compoundStatement +; + +createFunction: + definerClause? FUNCTION_SYMBOL functionName OPEN_PAR_SYMBOL ( + functionParameter (COMMA_SYMBOL functionParameter)* + )? CLOSE_PAR_SYMBOL RETURNS_SYMBOL typeWithOptCollate routineCreateOption* compoundStatement +; + +createUdf: + AGGREGATE_SYMBOL? FUNCTION_SYMBOL udfName RETURNS_SYMBOL type = ( + STRING_SYMBOL + | INT_SYMBOL + | REAL_SYMBOL + | DECIMAL_SYMBOL + ) SONAME_SYMBOL textLiteral +; + +routineCreateOption: + routineOption + | NOT_SYMBOL? DETERMINISTIC_SYMBOL +; + +routineAlterOptions: + routineCreateOption+ +; + +routineOption: + option = COMMENT_SYMBOL textLiteral + | option = LANGUAGE_SYMBOL SQL_SYMBOL + | option = NO_SYMBOL SQL_SYMBOL + | option = CONTAINS_SYMBOL SQL_SYMBOL + | option = READS_SYMBOL SQL_SYMBOL DATA_SYMBOL + | option = MODIFIES_SYMBOL SQL_SYMBOL DATA_SYMBOL + | option = SQL_SYMBOL SECURITY_SYMBOL security = ( + DEFINER_SYMBOL + | INVOKER_SYMBOL + ) +; + +createIndex: + onlineOption? ( + UNIQUE_SYMBOL? type = INDEX_SYMBOL ( + {serverVersion >= 80014}? indexName indexTypeClause? + | indexNameAndType? + ) createIndexTarget indexOption* + | type = FULLTEXT_SYMBOL INDEX_SYMBOL indexName createIndexTarget fulltextIndexOption* + | type = SPATIAL_SYMBOL INDEX_SYMBOL indexName createIndexTarget spatialIndexOption* + ) indexLockAndAlgorithm? +; + +/* + The syntax for defining an index is: + + ... INDEX [index_name] [USING|TYPE] ... + + The problem is that whereas USING is a reserved word, TYPE is not. We can + still handle it if an index name is supplied, i.e.: + + ... INDEX type TYPE ... + + here the index's name is unmbiguously 'type', but for this: + + ... INDEX TYPE ... + + it's impossible to know what this actually mean - is 'type' the name or the + type? For this reason we accept the TYPE syntax only if a name is supplied. +*/ +indexNameAndType: + indexName (USING_SYMBOL indexType)? + | indexName TYPE_SYMBOL indexType +; + +createIndexTarget: + ON_SYMBOL tableRef keyListVariants +; + +createLogfileGroup: + LOGFILE_SYMBOL GROUP_SYMBOL logfileGroupName ADD_SYMBOL ( + UNDOFILE_SYMBOL + | REDOFILE_SYMBOL // No longer used from 8.0 onwards. Taken out by lexer. + ) textLiteral logfileGroupOptions? +; + +logfileGroupOptions: + logfileGroupOption (COMMA_SYMBOL? logfileGroupOption)* +; + +logfileGroupOption: + tsOptionInitialSize + | tsOptionUndoRedoBufferSize + | tsOptionNodegroup + | tsOptionEngine + | tsOptionWait + | tsOptionComment +; + +createServer: + SERVER_SYMBOL serverName FOREIGN_SYMBOL DATA_SYMBOL WRAPPER_SYMBOL textOrIdentifier serverOptions +; + +serverOptions: + OPTIONS_SYMBOL OPEN_PAR_SYMBOL serverOption (COMMA_SYMBOL serverOption)* CLOSE_PAR_SYMBOL +; + +// Options for CREATE/ALTER SERVER, used for the federated storage engine. +serverOption: + option = HOST_SYMBOL textLiteral + | option = DATABASE_SYMBOL textLiteral + | option = USER_SYMBOL textLiteral + | option = PASSWORD_SYMBOL textLiteral + | option = SOCKET_SYMBOL textLiteral + | option = OWNER_SYMBOL textLiteral + | option = PORT_SYMBOL ulong_number +; + +createTablespace: + TABLESPACE_SYMBOL tablespaceName tsDataFileName ( + USE_SYMBOL LOGFILE_SYMBOL GROUP_SYMBOL logfileGroupRef + )? tablespaceOptions? +; + +createUndoTablespace: + UNDO_SYMBOL TABLESPACE_SYMBOL tablespaceName ADD_SYMBOL tsDataFile undoTableSpaceOptions? +; + +tsDataFileName: + {serverVersion >= 80014}? (ADD_SYMBOL tsDataFile)? + | ADD_SYMBOL tsDataFile +; + +tsDataFile: + DATAFILE_SYMBOL textLiteral +; + +tablespaceOptions: + tablespaceOption (COMMA_SYMBOL? tablespaceOption)* +; + +tablespaceOption: + tsOptionInitialSize + | tsOptionAutoextendSize + | tsOptionMaxSize + | tsOptionExtentSize + | tsOptionNodegroup + | tsOptionEngine + | tsOptionWait + | tsOptionComment + | {serverVersion >= 50707}? tsOptionFileblockSize + | {serverVersion >= 80014}? tsOptionEncryption +; + +tsOptionInitialSize: + INITIAL_SIZE_SYMBOL EQUAL_OPERATOR? sizeNumber +; + +tsOptionUndoRedoBufferSize: + (UNDO_BUFFER_SIZE_SYMBOL | REDO_BUFFER_SIZE_SYMBOL) EQUAL_OPERATOR? sizeNumber +; + +tsOptionAutoextendSize: + AUTOEXTEND_SIZE_SYMBOL EQUAL_OPERATOR? sizeNumber +; + +tsOptionMaxSize: + MAX_SIZE_SYMBOL EQUAL_OPERATOR? sizeNumber +; + +tsOptionExtentSize: + EXTENT_SIZE_SYMBOL EQUAL_OPERATOR? sizeNumber +; + +tsOptionNodegroup: + NODEGROUP_SYMBOL EQUAL_OPERATOR? real_ulong_number +; + +tsOptionEngine: + STORAGE_SYMBOL? ENGINE_SYMBOL EQUAL_OPERATOR? engineRef +; + +tsOptionWait: (WAIT_SYMBOL | NO_WAIT_SYMBOL) +; + +tsOptionComment: + COMMENT_SYMBOL EQUAL_OPERATOR? textLiteral +; + +tsOptionFileblockSize: + FILE_BLOCK_SIZE_SYMBOL EQUAL_OPERATOR? sizeNumber +; + +tsOptionEncryption: + ENCRYPTION_SYMBOL EQUAL_OPERATOR? textStringLiteral +; + +createView: + viewReplaceOrAlgorithm? definerClause? viewSuid? VIEW_SYMBOL viewName viewTail +; + +viewReplaceOrAlgorithm: + OR_SYMBOL REPLACE_SYMBOL viewAlgorithm? + | viewAlgorithm +; + +viewAlgorithm: + ALGORITHM_SYMBOL EQUAL_OPERATOR algorithm = ( + UNDEFINED_SYMBOL + | MERGE_SYMBOL + | TEMPTABLE_SYMBOL + ) +; + +viewSuid: + SQL_SYMBOL SECURITY_SYMBOL (DEFINER_SYMBOL | INVOKER_SYMBOL) +; + +createTrigger: + definerClause? TRIGGER_SYMBOL triggerName timing = (BEFORE_SYMBOL | AFTER_SYMBOL) event = ( + INSERT_SYMBOL + | UPDATE_SYMBOL + | DELETE_SYMBOL + ) ON_SYMBOL tableRef FOR_SYMBOL EACH_SYMBOL ROW_SYMBOL triggerFollowsPrecedesClause? compoundStatement +; + +triggerFollowsPrecedesClause: + {serverVersion >= 50700}? ordering = (FOLLOWS_SYMBOL | PRECEDES_SYMBOL) textOrIdentifier // not a trigger reference! +; + +createEvent: + definerClause? EVENT_SYMBOL ifNotExists? eventName ON_SYMBOL SCHEDULE_SYMBOL schedule ( + ON_SYMBOL COMPLETION_SYMBOL NOT_SYMBOL? PRESERVE_SYMBOL + )? (ENABLE_SYMBOL | DISABLE_SYMBOL (ON_SYMBOL SLAVE_SYMBOL)?)? ( + COMMENT_SYMBOL textLiteral + )? DO_SYMBOL compoundStatement +; + +createRole: + // The server grammar has a clear_privileges rule here, which is only used to clear internal state. + ROLE_SYMBOL ifNotExists? roleList +; + +createSpatialReference: + OR_SYMBOL REPLACE_SYMBOL SPATIAL_SYMBOL REFERENCE_SYMBOL SYSTEM_SYMBOL real_ulonglong_number srsAttribute* + | SPATIAL_SYMBOL REFERENCE_SYMBOL SYSTEM_SYMBOL ifNotExists? real_ulonglong_number srsAttribute* +; + +srsAttribute: + NAME_SYMBOL TEXT_SYMBOL textStringNoLinebreak + | DEFINITION_SYMBOL TEXT_SYMBOL textStringNoLinebreak + | ORGANIZATION_SYMBOL textStringNoLinebreak IDENTIFIED_SYMBOL BY_SYMBOL real_ulonglong_number + | DESCRIPTION_SYMBOL TEXT_SYMBOL textStringNoLinebreak +; + +//---------------------------------------------------------------------------------------------------------------------- + +dropStatement: + DROP_SYMBOL ( + dropDatabase + | dropEvent + | dropFunction + | dropProcedure + | dropIndex + | dropLogfileGroup + | dropServer + | dropTable + | dropTableSpace + | dropTrigger + | dropView + | {serverVersion >= 80000}? dropRole + | {serverVersion >= 80011}? dropSpatialReference + | {serverVersion >= 80014}? dropUndoTablespace + ) +; + +dropDatabase: + DATABASE_SYMBOL ifExists? schemaRef +; + +dropEvent: + EVENT_SYMBOL ifExists? eventRef +; + +dropFunction: + FUNCTION_SYMBOL ifExists? functionRef // Including UDFs. +; + +dropProcedure: + PROCEDURE_SYMBOL ifExists? procedureRef +; + +dropIndex: + onlineOption? type = INDEX_SYMBOL indexRef ON_SYMBOL tableRef indexLockAndAlgorithm? +; + +dropLogfileGroup: + LOGFILE_SYMBOL GROUP_SYMBOL logfileGroupRef ( + dropLogfileGroupOption (COMMA_SYMBOL? dropLogfileGroupOption)* + )? +; + +dropLogfileGroupOption: + tsOptionWait + | tsOptionEngine +; + +dropServer: + SERVER_SYMBOL ifExists? serverRef +; + +dropTable: + TEMPORARY_SYMBOL? type = (TABLE_SYMBOL | TABLES_SYMBOL) ifExists? tableRefList ( + RESTRICT_SYMBOL + | CASCADE_SYMBOL + )? +; + +dropTableSpace: + TABLESPACE_SYMBOL tablespaceRef ( + dropLogfileGroupOption (COMMA_SYMBOL? dropLogfileGroupOption)* + )? +; + +dropTrigger: + TRIGGER_SYMBOL ifExists? triggerRef +; + +dropView: + VIEW_SYMBOL ifExists? viewRefList (RESTRICT_SYMBOL | CASCADE_SYMBOL)? +; + +dropRole: + ROLE_SYMBOL ifExists? roleList +; + +dropSpatialReference: + SPATIAL_SYMBOL REFERENCE_SYMBOL SYSTEM_SYMBOL ifExists? real_ulonglong_number +; + +dropUndoTablespace: + UNDO_SYMBOL TABLESPACE_SYMBOL tablespaceRef undoTableSpaceOptions? +; + +//---------------------------------------------------------------------------------------------------------------------- + +renameTableStatement: + RENAME_SYMBOL (TABLE_SYMBOL | TABLES_SYMBOL) renamePair (COMMA_SYMBOL renamePair)* +; + +renamePair: + tableRef TO_SYMBOL tableName +; + +//---------------------------------------------------------------------------------------------------------------------- + +truncateTableStatement: + TRUNCATE_SYMBOL TABLE_SYMBOL? tableRef +; + +//---------------------------------------------------------------------------------------------------------------------- + +importStatement: + IMPORT_SYMBOL TABLE_SYMBOL FROM_SYMBOL textStringLiteralList +; + +//--------------- DML statements --------------------------------------------------------------------------------------- + +callStatement: + CALL_SYMBOL procedureRef (OPEN_PAR_SYMBOL exprList? CLOSE_PAR_SYMBOL)? +; + +deleteStatement: + ({serverVersion >= 80000}? withClause)? DELETE_SYMBOL deleteStatementOption* ( + FROM_SYMBOL ( + tableAliasRefList USING_SYMBOL tableReferenceList whereClause? // Multi table variant 1. + | tableRef ({serverVersion >= 80017}? tableAlias)? partitionDelete? + whereClause? orderClause? simpleLimitClause? // Single table delete. + ) + | tableAliasRefList FROM_SYMBOL tableReferenceList whereClause? // Multi table variant 2. + ) +; + +partitionDelete: + {serverVersion >= 50602}? PARTITION_SYMBOL OPEN_PAR_SYMBOL identifierList CLOSE_PAR_SYMBOL +; + +deleteStatementOption: // opt_delete_option in sql_yacc.yy, but the name collides with another rule (delete_options). + QUICK_SYMBOL + | LOW_PRIORITY_SYMBOL + | QUICK_SYMBOL + | IGNORE_SYMBOL +; + +doStatement: + DO_SYMBOL ( + {serverVersion < 50709}? exprList + | {serverVersion >= 50709}? selectItemList + ) +; + +handlerStatement: + HANDLER_SYMBOL ( + tableRef OPEN_SYMBOL tableAlias? + | identifier ( + CLOSE_SYMBOL + | READ_SYMBOL handlerReadOrScan whereClause? limitClause? + ) + ) +; + +handlerReadOrScan: + (FIRST_SYMBOL | NEXT_SYMBOL) // Scan function. + | identifier ( + // The rkey part. + (FIRST_SYMBOL | NEXT_SYMBOL | PREV_SYMBOL | LAST_SYMBOL) + | ( + EQUAL_OPERATOR + | LESS_THAN_OPERATOR + | GREATER_THAN_OPERATOR + | LESS_OR_EQUAL_OPERATOR + | GREATER_OR_EQUAL_OPERATOR + ) OPEN_PAR_SYMBOL values CLOSE_PAR_SYMBOL + ) +; + +//---------------------------------------------------------------------------------------------------------------------- + +insertStatement: + INSERT_SYMBOL insertLockOption? IGNORE_SYMBOL? INTO_SYMBOL? tableRef usePartition? ( + insertFromConstructor ({ serverVersion >= 80018}? valuesReference)? + | SET_SYMBOL updateList ({ serverVersion >= 80018}? valuesReference)? + | insertQueryExpression + ) insertUpdateList? +; + +insertLockOption: + LOW_PRIORITY_SYMBOL + | DELAYED_SYMBOL // Only allowed if no select is used. Check in the semantic phase. + | HIGH_PRIORITY_SYMBOL +; + +insertFromConstructor: + (OPEN_PAR_SYMBOL fields? CLOSE_PAR_SYMBOL)? insertValues +; + +fields: + insertIdentifier (COMMA_SYMBOL insertIdentifier)* +; + +insertValues: + (VALUES_SYMBOL | VALUE_SYMBOL) valueList +; + +insertQueryExpression: + queryExpressionOrParens + | OPEN_PAR_SYMBOL fields? CLOSE_PAR_SYMBOL queryExpressionOrParens +; + +valueList: + OPEN_PAR_SYMBOL values? CLOSE_PAR_SYMBOL ( + COMMA_SYMBOL OPEN_PAR_SYMBOL values? CLOSE_PAR_SYMBOL + )* +; + +values: + (expr | DEFAULT_SYMBOL) (COMMA_SYMBOL (expr | DEFAULT_SYMBOL))* +; + +valuesReference: + AS_SYMBOL identifier columnInternalRefList? +; + +insertUpdateList: + ON_SYMBOL DUPLICATE_SYMBOL KEY_SYMBOL UPDATE_SYMBOL updateList +; + +//---------------------------------------------------------------------------------------------------------------------- + +loadStatement: + LOAD_SYMBOL dataOrXml (LOW_PRIORITY_SYMBOL | CONCURRENT_SYMBOL)? LOCAL_SYMBOL? INFILE_SYMBOL textLiteral ( + REPLACE_SYMBOL + | IGNORE_SYMBOL + )? INTO_SYMBOL TABLE_SYMBOL tableRef usePartition? charsetClause? xmlRowsIdentifiedBy? fieldsClause? linesClause? + loadDataFileTail +; + +dataOrXml: + DATA_SYMBOL + | XML_SYMBOL +; + +xmlRowsIdentifiedBy: + ROWS_SYMBOL IDENTIFIED_SYMBOL BY_SYMBOL textString +; + +loadDataFileTail: + (IGNORE_SYMBOL INT_NUMBER (LINES_SYMBOL | ROWS_SYMBOL))? loadDataFileTargetList? ( + SET_SYMBOL updateList + )? +; + +loadDataFileTargetList: + OPEN_PAR_SYMBOL fieldOrVariableList? CLOSE_PAR_SYMBOL +; + +fieldOrVariableList: + (columnRef | userVariable) (COMMA_SYMBOL (columnRef | userVariable))* +; + +//---------------------------------------------------------------------------------------------------------------------- + +replaceStatement: + REPLACE_SYMBOL (LOW_PRIORITY_SYMBOL | DELAYED_SYMBOL)? INTO_SYMBOL? tableRef usePartition? ( + insertFromConstructor + | SET_SYMBOL updateList + | insertQueryExpression + ) +; + +//---------------------------------------------------------------------------------------------------------------------- + +selectStatement: + queryExpression lockingClauseList? + | queryExpressionParens + | selectStatementWithInto +; + +/* + From the server grammar: + + MySQL has a syntax extension that allows into clauses in any one of two + places. They may appear either before the from clause or at the end. All in + a top-level select statement. This extends the standard syntax in two + ways. First, we don't have the restriction that the result can contain only + one row: the into clause might be INTO OUTFILE/DUMPFILE in which case any + number of rows is allowed. Hence MySQL does not have any special case for + the standard's syntax all the way down to the . So instead we solve it by writing an ambiguous grammar and use + precedence rules to sort out the shift/reduce conflict. + + The problem is when the parser has seen SELECT . Secondly, and this has more + severe implications for the parser, it makes the grammar ambiguous, because + in a from-clause-less select statement with an into clause, it is not clear + whether the into clause is the leading or the trailing one. + + While it's possible to write an unambiguous grammar, it would force us to + duplicate the entire , and sees an + INTO token. It can now either shift it or reduce what it has to a table-less + query expression. If it shifts the token, it will accept seeing a FROM token + next and hence the INTO will be interpreted as the leading INTO. If it + reduces what it has seen to a table-less select, however, it will interpret + INTO as the trailing into. But what if the next token is FROM? Obviously, + we want to always shift INTO. We do this by two precedence declarations: We + make the INTO token right-associative, and we give it higher precedence than + an empty from clause, using the artificial token EMPTY_FROM_CLAUSE. + + The remaining problem is that now we allow the leading INTO anywhere, when + it should be allowed on the top level only. We solve this by manually + throwing parse errors whenever we reduce a nested query expression if it + contains an into clause. +*/ + public function selectStatementWithInto() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->selectStatementWithInto(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } elseif ($token->getType() === MySQLLexer::SELECT_SYMBOL || + $token->getType() === MySQLLexer::WITH_SYMBOL) { + $children[] = $this->queryExpression(); + $children[] = $this->intoClause(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::LOCK_SYMBOL) { + $children[] = $this->lockingClauseList(); + } + } else { + throw new \Exception('Unexpected token in selectStatementWithInto: ' . $token->getText()); + } + + return new ASTNode('selectStatementWithInto', $children); + } + + public function queryExpression() + { + $children = []; + + if ($this->serverVersion >= 80000 && $this->lexer->peekNextToken()->getType() === MySQLLexer::WITH_SYMBOL) { + $children[] = $this->withClause(); + } + + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::SELECT_SYMBOL || + $token->getType() === MySQLLexer::VALUES_SYMBOL || + ($this->serverVersion >= 80019 && $token->getType() === MySQLLexer::TABLE_SYMBOL) || + $this->isSimpleExprStart($token)) { + $children[] = $this->queryExpressionBody(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ORDER_SYMBOL) { + $children[] = $this->orderClause(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIMIT_SYMBOL) { + $children[] = $this->limitClause(); + } + } elseif ($token->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->queryExpressionParens(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ORDER_SYMBOL) { + $children[] = $this->orderClause(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIMIT_SYMBOL) { + $children[] = $this->limitClause(); + } + } else { + throw new \Exception('Unexpected token in queryExpression: ' . $token->getText()); + } + + if ($this->serverVersion < 80000 && $this->lexer->peekNextToken()->getType() === MySQLLexer::PROCEDURE_SYMBOL) { + $children[] = $this->procedureAnalyseClause(); + } + + return new ASTNode('queryExpression', $children); + } + + public function queryExpressionBody() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::SELECT_SYMBOL || + $token->getType() === MySQLLexer::VALUES_SYMBOL || + ($this->serverVersion >= 80019 && $token->getType() === MySQLLexer::TABLE_SYMBOL) || + $this->isSimpleExprStart($token)) { + $children[] = $this->queryPrimary(); + } elseif ($token->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->queryExpressionParens(); + $children[] = $this->match(MySQLLexer::UNION_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ALL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DISTINCT_SYMBOL) { + $children[] = $this->unionOption(); + } + + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::SELECT_SYMBOL || + $token->getType() === MySQLLexer::VALUES_SYMBOL || + ($this->serverVersion >= 80019 && $token->getType() === MySQLLexer::TABLE_SYMBOL) || + $this->isSimpleExprStart($token)) { + $children[] = $this->queryPrimary(); + } elseif ($token->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->queryExpressionParens(); + } else { + throw new \Exception('Unexpected token in queryExpressionBody: ' . $token->getText()); + } + } else { + throw new \Exception('Unexpected token in queryExpressionBody: ' . $token->getText()); + } + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::UNION_SYMBOL) { + $children[] = $this->match(MySQLLexer::UNION_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ALL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DISTINCT_SYMBOL) { + $children[] = $this->unionOption(); + } + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::SELECT_SYMBOL || + $token->getType() === MySQLLexer::VALUES_SYMBOL || + ($this->serverVersion >= 80019 && $token->getType() === MySQLLexer::TABLE_SYMBOL) || + $this->isSimpleExprStart($token)) { + $children[] = $this->queryPrimary(); + } elseif ($token->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->queryExpressionParens(); + } else { + throw new \Exception('Unexpected token in queryExpressionBody: ' . $token->getText()); + } + } + + return new ASTNode('queryExpressionBody', $children); + } + + public function queryExpressionParens() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->queryExpressionParens(); + } else { + $children[] = $this->queryExpression(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::LOCK_SYMBOL) { + $children[] = $this->lockingClauseList(); + } + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + + return new ASTNode('queryExpressionParens', $children); + } + + public function queryPrimary() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::SELECT_SYMBOL) { + return $this->querySpecification(); + } elseif ($this->serverVersion >= 80019 && $token->getType() === MySQLLexer::VALUES_SYMBOL) { + return $this->tableValueConstructor(); + } elseif ($this->serverVersion >= 80019 && $token->getType() === MySQLLexer::TABLE_SYMBOL) { + return $this->explicitTable(); + } elseif ($this->isSimpleExprStart($token)) { + $children = []; + $children[] = $this->simpleExpr(); + return new ASTNode('queryPrimary', $children); + } else { + throw new \Exception('Unexpected token in queryPrimary: ' . $token->getText()); + } + } + + public function querySpecification() + { + $children = []; + + $children[] = $this->match(MySQLLexer::SELECT_SYMBOL); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::ALL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DISTINCT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::STRAIGHT_JOIN_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::HIGH_PRIORITY_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::SQL_SMALL_RESULT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::SQL_BIG_RESULT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::SQL_BUFFER_RESULT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::SQL_CALC_FOUND_ROWS_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::SQL_NO_CACHE_SYMBOL || + ($this->serverVersion < 80000 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::SQL_CACHE_SYMBOL) || + ($this->serverVersion >= 50704 && $this->serverVersion < 50708 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::MAX_STATEMENT_TIME_SYMBOL)) { + $children[] = $this->selectOption(); + } + + $children[] = $this->selectItemList(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::INTO_SYMBOL) { + $children[] = $this->intoClause(); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FROM_SYMBOL) { + $children[] = $this->fromClause(); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->whereClause(); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::GROUP_SYMBOL) { + $children[] = $this->groupByClause(); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::HAVING_SYMBOL) { + $children[] = $this->havingClause(); + } + + if ($this->serverVersion >= 80000 && $this->lexer->peekNextToken()->getType() === MySQLLexer::WINDOW_SYMBOL) { + $children[] = $this->windowClause(); + } + + return new ASTNode('querySpecification', $children); + } + + public function subquery() + { + return $this->queryExpressionParens(); + } + + public function querySpecOption() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::ALL_SYMBOL) { + return $this->match(MySQLLexer::ALL_SYMBOL); + } elseif ($token->getType() === MySQLLexer::DISTINCT_SYMBOL) { + return $this->match(MySQLLexer::DISTINCT_SYMBOL); + } elseif ($token->getType() === MySQLLexer::STRAIGHT_JOIN_SYMBOL) { + return $this->match(MySQLLexer::STRAIGHT_JOIN_SYMBOL); + } elseif ($token->getType() === MySQLLexer::HIGH_PRIORITY_SYMBOL) { + return $this->match(MySQLLexer::HIGH_PRIORITY_SYMBOL); + } elseif ($token->getType() === MySQLLexer::SQL_SMALL_RESULT_SYMBOL) { + return $this->match(MySQLLexer::SQL_SMALL_RESULT_SYMBOL); + } elseif ($token->getType() === MySQLLexer::SQL_BIG_RESULT_SYMBOL) { + return $this->match(MySQLLexer::SQL_BIG_RESULT_SYMBOL); + } elseif ($token->getType() === MySQLLexer::SQL_BUFFER_RESULT_SYMBOL) { + return $this->match(MySQLLexer::SQL_BUFFER_RESULT_SYMBOL); + } elseif ($token->getType() === MySQLLexer::SQL_CALC_FOUND_ROWS_SYMBOL) { + return $this->match(MySQLLexer::SQL_CALC_FOUND_ROWS_SYMBOL); + } elseif ($token->getType() === MySQLLexer::SQL_NO_CACHE_SYMBOL) { + return $this->match(MySQLLexer::SQL_NO_CACHE_SYMBOL); + } elseif ($this->serverVersion < 80000 && $token->getType() === MySQLLexer::SQL_CACHE_SYMBOL) { + return $this->match(MySQLLexer::SQL_CACHE_SYMBOL); + } else { + throw new \Exception('Unexpected token in querySpecOption: ' . $token->getText()); + } + } + + public function limitClause() + { + $children = []; + + $children[] = $this->match(MySQLLexer::LIMIT_SYMBOL); + $children[] = $this->limitOptions(); + return new ASTNode('limitClause', $children); + } + + public function simpleLimitClause() + { + $children = []; + + $children[] = $this->match(MySQLLexer::LIMIT_SYMBOL); + $children[] = $this->limitOption(); + return new ASTNode('simpleLimitClause', $children); + } + + public function limitOptions() + { + $children = []; + + $children[] = $this->limitOption(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::OFFSET_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::OFFSET_SYMBOL); + } + $children[] = $this->limitOption(); + } + + return new ASTNode('limitOptions', $children); + } + + public function limitOption() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token)) { + return $this->identifier(); + } elseif ($token->getType() === MySQLLexer::PARAM_MARKER || + $token->getType() === MySQLLexer::ULONGLONG_NUMBER || + $token->getType() === MySQLLexer::LONG_NUMBER || + $token->getType() === MySQLLexer::INT_NUMBER) { + $this->match($this->lexer->peekNextToken()->getType()); + return new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + } else { + throw new \Exception('Unexpected token in limitOption: ' . $token->getText()); + } + } + + public function intoClause() + { + $children = []; + + $children[] = $this->match(MySQLLexer::INTO_SYMBOL); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::OUTFILE_SYMBOL) { + $children[] = $this->match(MySQLLexer::OUTFILE_SYMBOL); + $children[] = $this->textStringLiteral(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::CHARSET_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::CHAR_SYMBOL) { + $children[] = $this->charsetClause(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FIELDS_SYMBOL) { + $children[] = $this->fieldsClause(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LINES_SYMBOL) { + $children[] = $this->linesClause(); + } + } elseif ($token->getType() === MySQLLexer::DUMPFILE_SYMBOL) { + $children[] = $this->match(MySQLLexer::DUMPFILE_SYMBOL); + $children[] = $this->textStringLiteral(); + } elseif ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT || + $token->getType() === MySQLLexer::AT_SIGN_SYMBOL || + $token->getType() === MySQLLexer::AT_TEXT_SUFFIX) { + $children[] = $this->textOrIdentifier(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->textOrIdentifier(); + } + } else { + throw new \Exception('Unexpected token in intoClause: ' . $token->getText()); + } + + return new ASTNode('intoClause', $children); + } + + public function procedureAnalyseClause() + { + $children = []; + + $children[] = $this->match(MySQLLexer::PROCEDURE_SYMBOL); + $children[] = $this->match(MySQLLexer::ANALYSE_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::INT_NUMBER) { + $children[] = $this->match(MySQLLexer::INT_NUMBER); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->match(MySQLLexer::INT_NUMBER); + } + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + + return new ASTNode('procedureAnalyseClause', $children); + } + + public function havingClause() + { + $children = []; + + $children[] = $this->match(MySQLLexer::HAVING_SYMBOL); + $children[] = $this->expr(); + + return new ASTNode('havingClause', $children); + } + + public function windowClause() + { + $children = []; + + $children[] = $this->match(MySQLLexer::WINDOW_SYMBOL); + $children[] = $this->windowDefinition(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->windowDefinition(); + } + + return new ASTNode('windowClause', $children); + } + + public function windowDefinition() + { + $children = []; + + $children[] = $this->windowName(); + $children[] = $this->match(MySQLLexer::AS_SYMBOL); + $children[] = $this->windowSpec(); + + return new ASTNode('windowDefinition', $children); + } + + public function windowSpec() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->windowSpecDetails(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + + return new ASTNode('windowSpec', $children); + } + + public function windowSpecDetails() + { + $children = []; + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + $children[] = $this->windowName(); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::PARTITION_SYMBOL) { + $children[] = $this->match(MySQLLexer::PARTITION_SYMBOL); + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + $children[] = $this->orderList(); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ORDER_SYMBOL) { + $children[] = $this->orderClause(); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ROWS_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::RANGE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::GROUPS_SYMBOL) { + $children[] = $this->windowFrameClause(); + } + + return new ASTNode('windowSpecDetails', $children); + } + + public function windowFrameClause() + { + $children = []; + + $children[] = $this->windowFrameUnits(); + $children[] = $this->windowFrameExtent(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EXCLUDE_SYMBOL) { + $children[] = $this->windowFrameExclusion(); + } + + return new ASTNode('windowFrameClause', $children); + } + + public function windowFrameUnits() +{ + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::ROWS_SYMBOL: + case MySQLLexer::RANGE_SYMBOL: + case MySQLLexer::GROUPS_SYMBOL: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in indexType: ' . $token->getText()); + } +} + + public function windowFrameExtent() + { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::BETWEEN_SYMBOL) { + return $this->windowFrameBetween(); + } else { + return $this->windowFrameStart(); + } + } + + public function windowFrameStart() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::UNBOUNDED_SYMBOL) { + $children[] = $this->match(MySQLLexer::UNBOUNDED_SYMBOL); + $children[] = $this->match(MySQLLexer::PRECEDING_SYMBOL); + } elseif ($token->getType() === MySQLLexer::ULONGLONG_NUMBER) { + $children[] = $this->match(MySQLLexer::ULONGLONG_NUMBER); + $children[] = $this->match(MySQLLexer::PRECEDING_SYMBOL); + } elseif ($token->getType() === MySQLLexer::PARAM_MARKER) { + $children[] = $this->match(MySQLLexer::PARAM_MARKER); + $children[] = $this->match(MySQLLexer::PRECEDING_SYMBOL); + } elseif ($token->getType() === MySQLLexer::INTERVAL_SYMBOL) { + $children[] = $this->match(MySQLLexer::INTERVAL_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->interval(); + $children[] = $this->match(MySQLLexer::PRECEDING_SYMBOL); + } elseif ($token->getType() === MySQLLexer::CURRENT_SYMBOL) { + $children[] = $this->match(MySQLLexer::CURRENT_SYMBOL); + $children[] = $this->match(MySQLLexer::ROW_SYMBOL); + } else { + throw new \Exception('Unexpected token in windowFrameStart: ' . $token->getText()); + } + + return new ASTNode('windowFrameStart', $children); + } + + public function windowFrameBetween() + { + $children = []; + + $children[] = $this->match(MySQLLexer::BETWEEN_SYMBOL); + $children[] = $this->windowFrameBound(); + $children[] = $this->match(MySQLLexer::AND_SYMBOL); + $children[] = $this->windowFrameBound(); + + return new ASTNode('windowFrameBetween', $children); + } + + public function windowFrameBound() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::UNBOUNDED_SYMBOL || + $token->getType() === MySQLLexer::ULONGLONG_NUMBER || + $token->getType() === MySQLLexer::PARAM_MARKER || + $token->getType() === MySQLLexer::INTERVAL_SYMBOL) { + return $this->windowFrameStart(); + } elseif ($token->getType() === MySQLLexer::UNBOUNDED_SYMBOL) { + $children = []; + $children[] = $this->match(MySQLLexer::UNBOUNDED_SYMBOL); + $children[] = $this->match(MySQLLexer::FOLLOWING_SYMBOL); + return new ASTNode('windowFrameBound', $children); + } else { + throw new \Exception('Unexpected token in windowFrameBound: ' . $token->getText()); + } + } + + public function windowFrameExclusion() + { + $children = []; + + $children[] = $this->match(MySQLLexer::EXCLUDE_SYMBOL); + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::CURRENT_SYMBOL) { + $children[] = $this->match(MySQLLexer::CURRENT_SYMBOL); + $children[] = $this->match(MySQLLexer::ROW_SYMBOL); + } elseif ($token->getType() === MySQLLexer::GROUP_SYMBOL) { + $children[] = $this->match(MySQLLexer::GROUP_SYMBOL); + } elseif ($token->getType() === MySQLLexer::TIES_SYMBOL) { + $children[] = $this->match(MySQLLexer::TIES_SYMBOL); + } elseif ($token->getType() === MySQLLexer::NO_SYMBOL) { + $children[] = $this->match(MySQLLexer::NO_SYMBOL); + $children[] = $this->match(MySQLLexer::OTHERS_SYMBOL); + } else { + throw new \Exception('Unexpected token in windowFrameExclusion: ' . $token->getText()); + } + + return new ASTNode('windowFrameExclusion', $children); + } + + public function withClause() + { + $children = []; + + $children[] = $this->match(MySQLLexer::WITH_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::RECURSIVE_SYMBOL) { + $children[] = $this->match(MySQLLexer::RECURSIVE_SYMBOL); + } + + $children[] = $this->commonTableExpression(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->commonTableExpression(); + } + + return new ASTNode('withClause', $children); + } + + public function commonTableExpression() + { + $children = []; + + $children[] = $this->identifier(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->columnInternalRefList(); + } + $children[] = $this->match(MySQLLexer::AS_SYMBOL); + $children[] = $this->subquery(); + return new ASTNode('commonTableExpression', $children); + } + + public function groupByClause() + { + $children = []; + + $children[] = $this->match(MySQLLexer::GROUP_SYMBOL); + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + $children[] = $this->orderList(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::WITH_SYMBOL) { + $children[] = $this->olapOption(); + } + + return new ASTNode('groupByClause', $children); + } + + public function olapOption() + { + $children = []; + + $children[] = $this->match(MySQLLexer::WITH_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ROLLUP_SYMBOL) { + $children[] = $this->match(MySQLLexer::ROLLUP_SYMBOL); + } elseif ($this->serverVersion < 80000 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::CUBE_SYMBOL) { + $children[] = $this->match(MySQLLexer::CUBE_SYMBOL); + } else { + throw new \Exception('Unexpected token in olapOption: ' . $this->lexer->peekNextToken()->getText()); + } + + return new ASTNode('olapOption', $children); + } + + public function orderClause() + { + $children = []; + + $children[] = $this->match(MySQLLexer::ORDER_SYMBOL); + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + $children[] = $this->orderList(); + + return new ASTNode('orderClause', $children); + } + + public function direction() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::ASC_SYMBOL) { + $this->match(MySQLLexer::ASC_SYMBOL); + return new ASTNode(MySQLLexer::getTokenName(MySQLLexer::ASC_SYMBOL )); + } elseif ($token->getType() === MySQLLexer::DESC_SYMBOL) { + return $this->match(MySQLLexer::DESC_SYMBOL); + } else { + throw new \Exception('Unexpected token in direction: ' . $token->getText()); + } + } + + public function fromClause() + { + $children = []; + + $children[] = $this->match(MySQLLexer::FROM_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DUAL_SYMBOL) { + $children[] = $this->match(MySQLLexer::DUAL_SYMBOL); + } else { + $children[] = $this->tableReferenceList(); + } + + return new ASTNode('fromClause', $children); + } + + public function tableReferenceList() + { + $children = []; + + $children[] = $this->tableReference(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->tableReference(); + } + + return new ASTNode('tableReferenceList', $children); + } + + public function tableValueConstructor() + { + $children = []; + + $children[] = $this->match(MySQLLexer::VALUES_SYMBOL); + $children[] = $this->rowValueExplicit(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->rowValueExplicit(); + } + + return new ASTNode('tableValueConstructor', $children); + } + + public function explicitTable() + { + $children = []; + + $children[] = $this->match(MySQLLexer::TABLE_SYMBOL); + $children[] = $this->tableRef(); + return new ASTNode('explicitTable', $children); + } + + public function rowValueExplicit() + { + $children = []; + + $children[] = $this->match(MySQLLexer::ROW_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + if ($this->isExprStart($this->lexer->peekNextToken()) || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->values(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + + return new ASTNode('rowValueExplicit', $children); + } + + public function selectOption() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::ALL_SYMBOL || + $token->getType() === MySQLLexer::DISTINCT_SYMBOL || + $token->getType() === MySQLLexer::STRAIGHT_JOIN_SYMBOL || + $token->getType() === MySQLLexer::HIGH_PRIORITY_SYMBOL || + $token->getType() === MySQLLexer::SQL_SMALL_RESULT_SYMBOL || + $token->getType() === MySQLLexer::SQL_BIG_RESULT_SYMBOL || + $token->getType() === MySQLLexer::SQL_BUFFER_RESULT_SYMBOL || + $token->getType() === MySQLLexer::SQL_CALC_FOUND_ROWS_SYMBOL || + $token->getType() === MySQLLexer::SQL_NO_CACHE_SYMBOL || + ($this->serverVersion < 80000 && + $token->getType() === MySQLLexer::SQL_CACHE_SYMBOL)) { + return $this->querySpecOption(); + } elseif ($this->serverVersion >= 50704 && $this->serverVersion < 50708 && + $token->getType() === MySQLLexer::MAX_STATEMENT_TIME_SYMBOL) { + $children = []; + $children[] = $this->match(MySQLLexer::MAX_STATEMENT_TIME_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->real_ulong_number(); + return new ASTNode('selectOption', $children); + } else { + throw new \Exception('Unexpected token in selectOption: ' . $token->getText()); + } + } + + public function lockingClauseList() + { + $children = []; + + do { + $children[] = $this->lockingClause(); + } while ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::LOCK_SYMBOL); + + return new ASTNode('lockingClauseList', $children); + } + + public function lockingClause() + { + $token = $this->lexer->peekNextToken(); + $children = []; + if ($token->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->lockStrengh(); + + if ($this->serverVersion >= 80000 && $this->lexer->peekNextToken()->getType() === MySQLLexer::OF_SYMBOL) { + $children[] = $this->match(MySQLLexer::OF_SYMBOL); + $children[] = $this->tableAliasRefList(); + } + + if ($this->serverVersion >= 80000 && + ($this->lexer->peekNextToken()->getType() === MySQLLexer::SKIP_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NOWAIT_SYMBOL)) { + $children[] = $this->lockedRowAction(); + } + } elseif ($token->getType() === MySQLLexer::LOCK_SYMBOL) { + $children[] = $this->match(MySQLLexer::LOCK_SYMBOL); + $children[] = $this->match(MySQLLexer::IN_SYMBOL); + $children[] = $this->match(MySQLLexer::SHARE_SYMBOL); + $children[] = $this->match(MySQLLexer::MODE_SYMBOL); + } else { + throw new \Exception('Unexpected token in lockingClalockingClause: ' . $token->getText()); + } + + return new ASTNode('lockingClause', $children); + } + + public function lockStrengh() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::UPDATE_SYMBOL) { + return $this->match(MySQLLexer::UPDATE_SYMBOL); + } elseif ($this->serverVersion >= 80000 && $token->getType() === MySQLLexer::SHARE_SYMBOL) { + return $this->match(MySQLLexer::SHARE_SYMBOL); + } else { + throw new \Exception('Unexpected token in lockStrengh: ' . $token->getText()); + } + } + + public function lockedRowAction() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::SKIP_SYMBOL) { + $this->match(MySQLLexer::SKIP_SYMBOL); + $children = [ + new ASTNode(MySQLLexer::getTokenName(MySQLLexer::SKIP_SYMBOL)), + ]; + $children[] = $this->match(MySQLLexer::LOCKED_SYMBOL); + return new ASTNode('lockedRowAction', $children); + } elseif ($token->getType() === MySQLLexer::NOWAIT_SYMBOL) { + return $this->match(MySQLLexer::NOWAIT_SYMBOL); + } else { + throw new \Exception('Unexpected token in lockedRowAction: ' . $token->getText()); + } + } + + public function selectItemList() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::MULT_OPERATOR) { + $children[] = $this->match(MySQLLexer::MULT_OPERATOR); + } elseif ($this->isSimpleExprStart($token) || + ($this->serverVersion >= 80000 && + ($token->getType() === MySQLLexer::ROW_NUMBER_SYMBOL || + $token->getType() === MySQLLexer::RANK_SYMBOL || + $token->getType() === MySQLLexer::DENSE_RANK_SYMBOL || + $token->getType() === MySQLLexer::CUME_DIST_SYMBOL || + $token->getType() === MySQLLexer::PERCENT_RANK_SYMBOL)) || + ($this->serverVersion < 80000 && $token->getType() === MySQLLexer::ROW_SYMBOL) || + $token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->selectItem(); + } else { + throw new \Exception('Unexpected token in selectItemList: ' . $token->getText()); + } + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->selectItem(); + } + + return new ASTNode('selectItemList', $children); + } + + public function selectItem() + { + $token1 = $this->lexer->peekNextToken(); + $token2 = $this->lexer->peekNextToken(2); + $children = []; + + if ($token1->getType() === MySQLLexer::IDENTIFIER && + $token2->getType() === MySQLLexer::DOT_SYMBOL && + $this->lexer->peekNextToken(3)->getType() === MySQLLexer::MULT_OPERATOR) { + $children[] = $this->tableWild(); + } else { + $children[] = $this->expr(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::AS_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken()) || + $this->lexer->peekNextToken()->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + $children[] = $this->selectAlias(); + } + } + + return new ASTNode('selectItem', $children); + } + + public function selectAlias() + { + $children = []; + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::AS_SYMBOL) { + $children[] = $this->match(MySQLLexer::AS_SYMBOL); + } + + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token)) { + $children[] = $this->identifier(); + } elseif ($token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + $children[] = $this->textStringLiteral(); + } else { + throw new \Exception('Unexpected token in selectAlias: ' . $token->getText()); + } + + return new ASTNode('selectAlias', $children); + } + + public function whereClause() + { + $children = []; + + $children[] = $this->match(MySQLLexer::WHERE_SYMBOL); + $children[] = $this->expr(); + return new ASTNode('whereClause', $children); + } + + public function tableReference() + { + $token = $this->lexer->peekNextToken(); + $children = []; + if ($token->getType() === MySQLLexer::OPEN_PAR_SYMBOL || + $token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::DOT_SYMBOL || + ($this->serverVersion >= 80014 && $token->getType() === MySQLLexer::LATERAL_SYMBOL) || + ($this->serverVersion >= 80004 && $token->getType() === MySQLLexer::JSON_TABLE_SYMBOL)) { + $children[] = $this->tableFactor(); + } elseif ($token->getType() === MySQLLexer::OPEN_CURLY_SYMBOL) { + $children[] = $this->match(MySQLLexer::OPEN_CURLY_SYMBOL); + if ($this->serverVersion < 80017) { + $children[] = $this->identifier(); + } else { + $children[] = $this->match(MySQLLexer::OJ_SYMBOL); + } + $children[] = $this->escapedTableReference(); + $children[] = $this->match(MySQLLexer::CLOSE_CURLY_SYMBOL); + } else { + throw new \Exception('Unexpected token in tableReference: ' . $token->getText()); + } + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::JOIN_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INNER_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::CROSS_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::STRAIGHT_JOIN_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::LEFT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::RIGHT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NATURAL_SYMBOL) { + $children[] = $this->joinedTable(); + } + + return new ASTNode('tableReference', $children); + } + + public function escapedTableReference() + { + $children = []; + $children[] = $this->tableFactor(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::JOIN_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INNER_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::CROSS_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::STRAIGHT_JOIN_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::LEFT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::RIGHT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NATURAL_SYMBOL) { + $children[] = $this->joinedTable(); + } + + return new ASTNode('escapedTableReference', $children); + } + + public function joinedTable() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::NATURAL_SYMBOL) { + $children[] = $this->naturalJoinType(); + $children[] = $this->tableFactor(); + } elseif ($token->getType() === MySQLLexer::INNER_SYMBOL || + $token->getType() === MySQLLexer::CROSS_SYMBOL || + $token->getType() === MySQLLexer::JOIN_SYMBOL || + $token->getType() === MySQLLexer::STRAIGHT_JOIN_SYMBOL) { + $children[] = $this->innerJoinType(); + $children[] = $this->tableReference(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ON_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::USING_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ON_SYMBOL) { + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + $children[] = $this->expr(); + } else { + $children[] = $this->match(MySQLLexer::USING_SYMBOL); + $children[] = $this->identifierListWithParentheses(); + } + } + } elseif ($token->getType() === MySQLLexer::LEFT_SYMBOL || + $token->getType() === MySQLLexer::RIGHT_SYMBOL) { + $children[] = $this->outerJoinType(); + $children[] = $this->tableReference(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ON_SYMBOL) { + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + $children[] = $this->expr(); + } else { + $children[] = $this->match(MySQLLexer::USING_SYMBOL); + $children[] = $this->identifierListWithParentheses(); + } + } else { + throw new \Exception('Unexpected token in joinedTable: ' . $token->getText()); + } + + return new ASTNode('joinedTable', $children); + } + + public function naturalJoinType() + { + $children = []; + + $children[] = $this->match(MySQLLexer::NATURAL_SYMBOL); + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::INNER_SYMBOL || + $token->getType() === MySQLLexer::JOIN_SYMBOL) { + if ($token->getType() === MySQLLexer::INNER_SYMBOL) { + $children[] = $this->match(MySQLLexer::INNER_SYMBOL); + } + + $children[] = $this->match(MySQLLexer::JOIN_SYMBOL); + return new ASTNode('naturalJoinType', $children); + } elseif ($token->getType() === MySQLLexer::LEFT_SYMBOL || + $token->getType() === MySQLLexer::RIGHT_SYMBOL) { + if ($token->getType() === MySQLLexer::LEFT_SYMBOL) { + $children[] = $this->match(MySQLLexer::LEFT_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::RIGHT_SYMBOL); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OUTER_SYMBOL) { + $children[] = $this->match(MySQLLexer::OUTER_SYMBOL); + } + + $children[] = $this->match(MySQLLexer::JOIN_SYMBOL); + return new ASTNode('naturalJoinType', $children); + } else { + throw new \Exception('Unexpected token in naturalJoinType: ' . $token->getText()); + } + } + + public function innerJoinType() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::INNER_SYMBOL || + $token->getType() === MySQLLexer::CROSS_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::INNER_SYMBOL) { + $children[] = $this->match(MySQLLexer::INNER_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::CROSS_SYMBOL); + } + $children[] = $this->match(MySQLLexer::JOIN_SYMBOL); + } elseif ($token->getType() === MySQLLexer::JOIN_SYMBOL) { + $children[] = $this->match(MySQLLexer::JOIN_SYMBOL); + } elseif ($token->getType() === MySQLLexer::STRAIGHT_JOIN_SYMBOL) { + $children[] = $this->match(MySQLLexer::STRAIGHT_JOIN_SYMBOL); + } else { + throw new \Exception('Unexpected token in innerJoinType: ' . $token->getText()); + } + + return new ASTNode('innerJoinType', $children); + } + + public function outerJoinType() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::LEFT_SYMBOL) { + $children[] = $this->match(MySQLLexer::LEFT_SYMBOL); + } elseif ($token->getType() === MySQLLexer::RIGHT_SYMBOL) { + $children[] = $this->match(MySQLLexer::RIGHT_SYMBOL); + } else { + throw new \Exception('Unexpected token in outerJoinType: ' . $token->getText()); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OUTER_SYMBOL) { + $children[] = $this->match(MySQLLexer::OUTER_SYMBOL); + } + $children[] = $this->match(MySQLLexer::JOIN_SYMBOL); + + return new ASTNode('outerJoinType', $children); + } + + /** + * MySQL has a syntax extension where a comma-separated list of table + * references is allowed as a table reference in itself, for instance + * + * SELECT * FROM (t1, t2) JOIN t3 ON 1 + * + * which is not allowed in standard SQL. The syntax is equivalent to + * + * SELECT * FROM (t1 CROSS JOIN t2) JOIN t3 ON 1 + * + * We call this rule tableReferenceListParens. + */ + public function tableFactor() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::DOT_SYMBOL) { + return $this->singleTable(); + } elseif ($token->getType() === MySQLLexer::OPEN_PAR_SYMBOL && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::SELECT_SYMBOL) { + return $this->derivedTable(); + } elseif ($token->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + return $this->tableReferenceListParens(); + } elseif ($this->serverVersion >= 80014 && $token->getType() === MySQLLexer::LATERAL_SYMBOL) { + return $this->derivedTable(); + } elseif ($this->serverVersion >= 80004 && $token->getType() === MySQLLexer::JSON_TABLE_SYMBOL) { + return $this->tableFunction(); + } else { + throw new \Exception('Unexpected token in tableFactor: ' . $token->getText()); + } + } + + public function singleTable() + { + $children = []; + $children[] = $this->tableRef(); + if ($this->serverVersion >= 50602 && $this->lexer->peekNextToken()->getType() === MySQLLexer::PARTITION_SYMBOL) { + $children[] = $this->usePartition(); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::AS_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeywordsUnambiguous($this->lexer->peekNextToken())) { + $children[] = $this->tableAlias(); + } + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::USE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::FORCE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IGNORE_SYMBOL) { + $children[] = $this->indexHintList(); + } + return new ASTNode('singleTable', $children); + } + + public function tableReferenceListParens() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::OPEN_PAR_SYMBOL || + $token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::DOT_SYMBOL || + ($this->serverVersion >= 80014 && $token->getType() === MySQLLexer::LATERAL_SYMBOL) || + ($this->serverVersion >= 80004 && $token->getType() === MySQLLexer::JSON_TABLE_SYMBOL)) { + $children[] = $this->tableReferenceList(); + } elseif ($token->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->tableReferenceListParens(); + } else { + throw new \Exception('Unexpected token in tableReferenceListParens: ' . $token->getText()); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + + return new ASTNode('tableReferenceListParens', $children); + } + + public function tableFunction() + { + $children = []; + + $children[] = $this->match(MySQLLexer::JSON_TABLE_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->textStringLiteral(); + $children[] = $this->columnsClause(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::AS_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + $children[] = $this->tableAlias(); + } + + return new ASTNode('tableFunction', $children); + } + + public function columnsClause() + { + $children = []; + + $children[] = $this->match(MySQLLexer::COLUMNS_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->jtColumn(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->jtColumn(); + } + + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('columnsClause', $children); + } + + public function jtColumn() + { + $token1 = $this->lexer->peekNextToken(); + $token2 = $this->lexer->peekNextToken(2); + $children = []; + + if ($token1->getType() === MySQLLexer::IDENTIFIER && + $token2->getType() === MySQLLexer::FOR_SYMBOL && + $this->lexer->peekNextToken(3)->getType() === MySQLLexer::ORDINALITY_SYMBOL) { + $children[] = $this->identifier(); + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->match(MySQLLexer::ORDINALITY_SYMBOL); + } elseif (($token1->getType() === MySQLLexer::IDENTIFIER || + $token1->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token1->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token1)) && + ($token2->getType() === MySQLLexer::INT_SYMBOL || + $token2->getType() === MySQLLexer::TINYINT_SYMBOL || + $token2->getType() === MySQLLexer::SMALLINT_SYMBOL || + $token2->getType() === MySQLLexer::MEDIUMINT_SYMBOL || + $token2->getType() === MySQLLexer::BIGINT_SYMBOL || + $token2->getType() === MySQLLexer::REAL_SYMBOL || + $token2->getType() === MySQLLexer::DOUBLE_SYMBOL || + $token2->getType() === MySQLLexer::FLOAT_SYMBOL || + $token2->getType() === MySQLLexer::DECIMAL_SYMBOL || + $token2->getType() === MySQLLexer::NUMERIC_SYMBOL || + $token2->getType() === MySQLLexer::FIXED_SYMBOL || + $token2->getType() === MySQLLexer::BIT_SYMBOL || + $token2->getType() === MySQLLexer::BOOL_SYMBOL || + $token2->getType() === MySQLLexer::BOOLEAN_SYMBOL || + $token2->getType() === MySQLLexer::CHAR_SYMBOL || + $token2->getType() === MySQLLexer::NCHAR_SYMBOL || + $token2->getType() === MySQLLexer::NATIONAL_SYMBOL || + $token2->getType() === MySQLLexer::BINARY_SYMBOL || + $token2->getType() === MySQLLexer::VARBINARY_SYMBOL || + $token2->getType() === MySQLLexer::TINYBLOB_SYMBOL || + $token2->getType() === MySQLLexer::BLOB_SYMBOL || + $token2->getType() === MySQLLexer::MEDIUMBLOB_SYMBOL || + $token2->getType() === MySQLLexer::LONGBLOB_SYMBOL || + $token2->getType() === MySQLLexer::TINYTEXT_SYMBOL || + $token2->getType() === MySQLLexer::TEXT_SYMBOL || + $token2->getType() === MySQLLexer::MEDIUMTEXT_SYMBOL || + $token2->getType() === MySQLLexer::LONGTEXT_SYMBOL || + $token2->getType() === MySQLLexer::ENUM_SYMBOL || + $token2->getType() === MySQLLexer::SET_SYMBOL || + ($this->serverVersion >= 50708 && + $token2->getType() === MySQLLexer::JSON_SYMBOL) || + $token2->getType() === MySQLLexer::GEOMETRY_SYMBOL || + $token2->getType() === MySQLLexer::POINT_SYMBOL || + $token2->getType() === MySQLLexer::LINESTRING_SYMBOL || + $token2->getType() === MySQLLexer::POLYGON_SYMBOL || + $token2->getType() === MySQLLexer::GEOMETRYCOLLECTION_SYMBOL || + $token2->getType() === MySQLLexer::MULTIPOINT_SYMBOL || + $token2->getType() === MySQLLexer::MULTILINESTRING_SYMBOL || + $token2->getType() === MySQLLexer::MULTIPOLYGON_SYMBOL || + $token2->getType() === MySQLLexer::YEAR_SYMBOL || + $token2->getType() === MySQLLexer::DATE_SYMBOL || + $token2->getType() === MySQLLexer::TIME_SYMBOL || + $token2->getType() === MySQLLexer::TIMESTAMP_SYMBOL || + $token2->getType() === MySQLLexer::DATETIME_SYMBOL)) { + $children[] = $this->identifier(); + $children[] = $this->dataType(); + if ($this->serverVersion >= 80014 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::COLLATE_SYMBOL) { + $children[] = $this->collate(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EXISTS_SYMBOL) { + $children[] = $this->match(MySQLLexer::EXISTS_SYMBOL); + } + $children[] = $this->match(MySQLLexer::PATH_SYMBOL); + $children[] = $this->textStringLiteral(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ERROR_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NULL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DEFAULT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::EMPTY_SYMBOL) { + $children[] = $this->onEmptyOrError(); + } + } elseif ($token1->getType() === MySQLLexer::NESTED_SYMBOL && + $token2->getType() === MySQLLexer::PATH_SYMBOL) { + $children[] = $this->match(MySQLLexer::NESTED_SYMBOL); + $children[] = $this->match(MySQLLexer::PATH_SYMBOL); + $children[] = $this->textStringLiteral(); + $children[] = $this->columnsClause(); + } else { + throw new \Exception('Unexpected token in jtColumn: ' . $token1->getText()); + } + + return new ASTNode('jtColumn', $children); + } + + public function onEmptyOrError() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::ERROR_SYMBOL || + $token->getType() === MySQLLexer::NULL_SYMBOL || + $token->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->onEmpty(); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::ERROR_SYMBOL || + $token->getType() === MySQLLexer::NULL_SYMBOL || + $token->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->onError(); + } + return new ASTNode('onEmptyOrError', $children); + } elseif ($token->getType() === MySQLLexer::ERROR_SYMBOL) { + $children[] = $this->onError(); + $children[] = $this->onEmpty(); + return new ASTNode('onEmptyOrError', $children); + } else { + throw new \Exception('Unexpected token in onEmptyOrError: ' . $token->getText()); + } + } + + public function onEmpty() + { + $children = []; + + $children[] = $this->jtOnResponse(); + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + $children[] = $this->match(MySQLLexer::EMPTY_SYMBOL); + + return new ASTNode('onEmpty', $children); + } + + public function onError() + { + $children = []; + + $children[] = $this->jtOnResponse(); + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + $children[] = $this->match(MySQLLexer::ERROR_SYMBOL); + + return new ASTNode('onError', $children); + } + + public function jtOnResponse() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::ERROR_SYMBOL) { + return $this->match(MySQLLexer::ERROR_SYMBOL); + } elseif ($token->getType() === MySQLLexer::NULL_SYMBOL) { + return $this->match(MySQLLexer::NULL_SYMBOL); + } elseif ($token->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children = []; + $children[] = $this->match(MySQLLexer::DEFAULT_SYMBOL); + $children[] = $this->textStringLiteral(); + return new ASTNode('jtOnResponse', $children); + } else { + throw new \Exception('Unexpected token in jtOnResponse: ' . $token->getText()); + } + } + + public function unionOption() +{ + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::DISTINCT_SYMBOL: + case MySQLLexer::ALL_SYMBOL: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in indexType: ' . $token->getText()); + } +} + + public function tableAlias() + { + $children = []; + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::AS_SYMBOL) { + $children[] = $this->match(MySQLLexer::AS_SYMBOL); + } elseif ($this->serverVersion < 80017 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + + $children[] = $this->identifier(); + + return new ASTNode('tableAlias', $children); + } + + public function indexHintList() + { + $children = []; + + $children[] = $this->indexHint(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->indexHint(); + } + + return new ASTNode('indexHintList', $children); + } + + public function indexHint() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::USE_SYMBOL) { + $children[] = $this->match(MySQLLexer::USE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_SYMBOL) { + $children[] = $this->match(MySQLLexer::KEY_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::INDEX_SYMBOL) { + $children[] = $this->match(MySQLLexer::INDEX_SYMBOL); + } else { + throw new \Exception('Unexpected token in indexHint: ' . $this->lexer->peekNextToken()->getText()); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->indexHintClause(); + } + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken()) || + $this->lexer->peekNextToken()->getType() === MySQLLexer::PRIMARY_SYMBOL) { + $children[] = $this->indexList(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } elseif ($token->getType() === MySQLLexer::FORCE_SYMBOL || $token->getType() === MySQLLexer::IGNORE_SYMBOL) { + $children[] = $this->indexHintType(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_SYMBOL) { + $children[] = $this->match(MySQLLexer::KEY_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::INDEX_SYMBOL) { + $children[] = $this->match(MySQLLexer::INDEX_SYMBOL); + } else { + throw new \Exception('Unexpected token in indexHint: ' . $this->lexer->peekNextToken()->getText()); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->indexHintClause(); + } + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->indexList(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } else { + throw new \Exception('Unexpected token in indexHint: ' . $token->getText()); + } + + return new ASTNode('indexHint', $children); + } + + public function indexHintType() +{ + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::FORCE_SYMBOL: + case MySQLLexer::IGNORE_SYMBOL: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in indexType: ' . $token->getText()); + } +} + + public function indexHintClause() + { + $children = []; + + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::JOIN_SYMBOL) { + $children[] = $this->match(MySQLLexer::JOIN_SYMBOL); + } elseif ($token->getType() === MySQLLexer::ORDER_SYMBOL) { + $children[] = $this->match(MySQLLexer::ORDER_SYMBOL); + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + } elseif ($token->getType() === MySQLLexer::GROUP_SYMBOL) { + $children[] = $this->match(MySQLLexer::GROUP_SYMBOL); + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + } else { + throw new \Exception('Unexpected token in indexHintClause: ' . $token->getText()); + } + + return new ASTNode('indexHintClause', $children); + } + + public function indexList() + { + $children = []; + + $children[] = $this->indexListElement(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->indexListElement(); + } + + return new ASTNode('indexList', $children); + } + + public function indexListElement() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token)) { + return $this->identifier(); + } elseif ($token->getType() === MySQLLexer::PRIMARY_SYMBOL) { + return $this->match(MySQLLexer::PRIMARY_SYMBOL); + } else { + throw new \Exception('Unexpected token in indexListElement: ' . $token->getText()); + } + } + + //---------------------------------------------------------------------------------------------------------------------- + + public function updateStatement() + { + $children = []; + + if ($this->serverVersion >= 80000 && $this->lexer->peekNextToken()->getType() === MySQLLexer::WITH_SYMBOL) { + $children[] = $this->withClause(); + } + + $children[] = $this->match(MySQLLexer::UPDATE_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LOW_PRIORITY_SYMBOL) { + $children[] = $this->match(MySQLLexer::LOW_PRIORITY_SYMBOL); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IGNORE_SYMBOL) { + $children[] = $this->match(MySQLLexer::IGNORE_SYMBOL); + } + + $children[] = $this->tableReferenceList(); + $children[] = $this->match(MySQLLexer::SET_SYMBOL); + $children[] = $this->updateList(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->whereClause(); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ORDER_SYMBOL) { + $children[] = $this->orderClause(); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIMIT_SYMBOL) { + $children[] = $this->simpleLimitClause(); + } + + return new ASTNode('updateStatement', $children); + } + + //---------------------------------------------------------------------------------------------------------------------- + + public function transactionOrLockingStatement() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::START_SYMBOL || + $token->getType() === MySQLLexer::COMMIT_SYMBOL) { + return $this->transactionStatement(); + } elseif ($token->getType() === MySQLLexer::SAVEPOINT_SYMBOL || + $token->getType() === MySQLLexer::ROLLBACK_SYMBOL || + $token->getType() === MySQLLexer::RELEASE_SYMBOL) { + return $this->savepointStatement(); + } elseif ($token->getType() === MySQLLexer::LOCK_SYMBOL || + $token->getType() === MySQLLexer::UNLOCK_SYMBOL) { + return $this->lockStatement(); + } elseif ($token->getType() === MySQLLexer::XA_SYMBOL) { + return $this->xaStatement(); + } else { + throw new \Exception('Unexpected token in transactionOrLockingStatement: ' . $token->getText()); + } + } + + // BEGIN WORK is separated from transactional statements as it must not appear as part of a stored program. + public function beginWork() + { + $children = []; + + $children[] = $this->match(MySQLLexer::BEGIN_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::WORK_SYMBOL) { + $children[] = $this->match(MySQLLexer::WORK_SYMBOL); + } + + return new ASTNode('beginWork', $children); + } + + public function transactionStatement() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::START_SYMBOL) { + $children[] = $this->match(MySQLLexer::START_SYMBOL); + $children[] = $this->match(MySQLLexer::TRANSACTION_SYMBOL); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::WITH_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::READ_SYMBOL) { + $children[] = $this->transactionCharacteristic(); + } + } elseif ($token->getType() === MySQLLexer::COMMIT_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMIT_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::WORK_SYMBOL) { + $children[] = $this->match(MySQLLexer::WORK_SYMBOL); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::AND_SYMBOL) { + $children[] = $this->match(MySQLLexer::AND_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::NO_SYMBOL) { + $children[] = $this->match(MySQLLexer::NO_SYMBOL); + } + $children[] = $this->match(MySQLLexer::CHAIN_SYMBOL); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::RELEASE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NO_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::NO_SYMBOL) { + $children[] = $this->match(MySQLLexer::NO_SYMBOL); + } + $children[] = $this->match(MySQLLexer::RELEASE_SYMBOL); + } + } else { + throw new \Exception('Unexpected token in transactionStatement: ' . $token->getText()); + } + + return new ASTNode('transactionStatement', $children); + } + + public function transactionCharacteristic() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::WITH_SYMBOL) { + $children = []; + + $children[] = $this->match(MySQLLexer::WITH_SYMBOL); + $children[] = $this->match(MySQLLexer::CONSISTENT_SYMBOL); + $children[] = $this->match(MySQLLexer::SNAPSHOT_SYMBOL); + + return new ASTNode('transactionCharacteristic', $children); + } elseif ($this->serverVersion >= 50605 && $token->getType() === MySQLLexer::READ_SYMBOL) { + $children = []; + + $children[] = $this->match(MySQLLexer::READ_SYMBOL); + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::WRITE_SYMBOL) { + $children[] = $this->match(MySQLLexer::WRITE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::ONLY_SYMBOL) { + $children[] = $this->match(MySQLLexer::ONLY_SYMBOL); + } else { + throw new \Exception('Unexpected token in transactionCharacteristic: ' . $token->getText()); + } + + return new ASTNode('transactionCharacteristic', $children); + } else { + throw new \Exception('Unexpected token in transactionCharacteristic: ' . $token->getText()); + } + } + + public function savepointStatement() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::SAVEPOINT_SYMBOL) { + $children[] = $this->match(MySQLLexer::SAVEPOINT_SYMBOL); + $children[] = $this->identifier(); + } elseif ($token->getType() === MySQLLexer::ROLLBACK_SYMBOL) { + $children[] = $this->match(MySQLLexer::ROLLBACK_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::WORK_SYMBOL) { + $children[] = $this->match(MySQLLexer::WORK_SYMBOL); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::TO_SYMBOL) { + $children[] = $this->match(MySQLLexer::TO_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::SAVEPOINT_SYMBOL) { + $children[] = $this->match(MySQLLexer::SAVEPOINT_SYMBOL); + } + $children[] = $this->identifier(); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::AND_SYMBOL) { + $children[] = $this->match(MySQLLexer::AND_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::NO_SYMBOL) { + $children[] = $this->match(MySQLLexer::NO_SYMBOL); + } + $children[] = $this->match(MySQLLexer::CHAIN_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::RELEASE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NO_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::NO_SYMBOL) { + $children[] = $this->match(MySQLLexer::NO_SYMBOL); + } + $children[] = $this->match(MySQLLexer::RELEASE_SYMBOL); + } + } + } elseif ($token->getType() === MySQLLexer::RELEASE_SYMBOL) { + $children[] = $this->match(MySQLLexer::RELEASE_SYMBOL); + $children[] = $this->match(MySQLLexer::SAVEPOINT_SYMBOL); + $children[] = $this->identifier(); + } else { + throw new \Exception('Unexpected token in savepointStatement: ' . $token->getText()); + } + + return new ASTNode('savepointStatement', $children); + } + + public function lockStatement() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::LOCK_SYMBOL) { + $children[] = $this->match(MySQLLexer::LOCK_SYMBOL); + + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::TABLES_SYMBOL) { + $children[] = $this->match(MySQLLexer::TABLES_SYMBOL); + } elseif ($token->getType() === MySQLLexer::TABLE_SYMBOL) { + $children[] = $this->match(MySQLLexer::TABLE_SYMBOL); + } elseif ($this->serverVersion >= 80000 && $token->getType() === MySQLLexer::INSTANCE_SYMBOL) { + $children[] = $this->match(MySQLLexer::INSTANCE_SYMBOL); + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->match(MySQLLexer::BACKUP_SYMBOL); + } else { + throw new \Exception('Unexpected token in lockStatement: ' . $token->getText()); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken()) || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->lockItem(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->lockItem(); + } + } + } elseif ($token->getType() === MySQLLexer::UNLOCK_SYMBOL) { + $children[] = $this->match(MySQLLexer::UNLOCK_SYMBOL); + + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::TABLES_SYMBOL) { + $children[] = $this->match(MySQLLexer::TABLES_SYMBOL); + } elseif ($token->getType() === MySQLLexer::TABLE_SYMBOL) { + $children[] = $this->match(MySQLLexer::TABLE_SYMBOL); + } elseif ($this->serverVersion >= 80000 && $token->getType() === MySQLLexer::INSTANCE_SYMBOL) { + $children[] = $this->match(MySQLLexer::INSTANCE_SYMBOL); + } else { + throw new \Exception('Unexpected token in lockStatement: ' . $token->getText()); + } + } else { + throw new \Exception('Unexpected token in lockStatement: ' . $token->getText()); + } + + return new ASTNode('lockStatement', $children); + } + + public function lockItem() + { + $children = []; + + $children[] = $this->tableRef(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::AS_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + $children[] = $this->tableAlias(); + } + $children[] = $this->lockOption(); + + return new ASTNode('lockItem', $children); + } + + public function lockOption() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::READ_SYMBOL || + ($this->serverVersion < 50700 && $token->getType() === MySQLLexer::LOW_PRIORITY_SYMBOL)) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LOW_PRIORITY_SYMBOL) { + $children[] = $this->match(MySQLLexer::LOW_PRIORITY_SYMBOL); + } + $children[] = $this->match(MySQLLexer::READ_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LOCAL_SYMBOL) { + $this->match(MySQLLexer::LOCAL_SYMBOL); + $children[] = ASTNode::fromToken($token); + } + } elseif ($token->getType() === MySQLLexer::WRITE_SYMBOL) { + $children[] = $this->match(MySQLLexer::WRITE_SYMBOL); + } else { + throw new \Exception('Unexpected token in lockOption: ' . $token->getText()); + } + + return new ASTNode('lockOption', $children); + } + + public function xaStatement() + { + $children = []; + + $children[] = $this->match(MySQLLexer::XA_SYMBOL); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::START_SYMBOL || + $token->getType() === MySQLLexer::BEGIN_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::START_SYMBOL) { + $children[] = $this->match(MySQLLexer::START_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::BEGIN_SYMBOL); + } + $children[] = $this->xid(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::JOIN_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::RESUME_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::JOIN_SYMBOL) { + $children[] = $this->match(MySQLLexer::JOIN_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::RESUME_SYMBOL); + } + } + } elseif ($token->getType() === MySQLLexer::END_SYMBOL) { + $children[] = $this->match(MySQLLexer::END_SYMBOL); + $children[] = $this->xid(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::SUSPEND_SYMBOL) { + $children[] = $this->match(MySQLLexer::SUSPEND_SYMBOL); + if ( + $this->lexer->peekNextToken()->getType() === MySQLLexer::IF_SYMBOL && + $this->lexer->peekNextToken()->getType(2) === MySQLLexer::MIGRATE_SYMBOL) { + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->match(MySQLLexer::MIGRATE_SYMBOL); + } + } + } elseif ($token->getType() === MySQLLexer::PREPARE_SYMBOL) { + $this->match(MySQLLexer::PREPARE_SYMBOL); + $children[] = ASTNode::fromToken($token); + $children[] = $this->xid(); + } elseif ($token->getType() === MySQLLexer::COMMIT_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMIT_SYMBOL); + $children[] = $this->xid(); + if ( + $this->lexer->peekNextToken()->getType() === MySQLLexer::ONE_SYMBOL && + $this->lexer->peekNextToken()->getType(2) === MySQLLexer::PHASE_SYMBOL) { + $children[] = $this->match(MySQLLexer::ONE_SYMBOL); + $this->match(MySQLLexer::PHASE_SYMBOL); + $children[] = ASTNode::fromToken($token); + } + } elseif ($token->getType() === MySQLLexer::ROLLBACK_SYMBOL) { + $children[] = $this->match(MySQLLexer::ROLLBACK_SYMBOL); + $children[] = $this->xid(); + } elseif ($token->getType() === MySQLLexer::RECOVER_SYMBOL) { + $children[] = $this->match(MySQLLexer::RECOVER_SYMBOL); + $children[] = $this->xaConvert(); + } else { + throw new \Exception('Unexpected token in xaStatement: ' . $token->getText()); + } + + return new ASTNode('xaStatement', $children); + } + + public function xaConvert() + { + $token = $this->lexer->peekNextToken(); + if ($this->serverVersion >= 50704 && $token->getType() === MySQLLexer::CONVERT_SYMBOL) { + $this->match(MySQLLexer::CONVERT_SYMBOL); + $children = [ + new ASTNode(MySQLLexer::getTokenName(MySQLLexer::CONVERT_SYMBOL)), + ]; + $children[] = $this->match(MySQLLexer::XID_SYMBOL); + return new ASTNode('xaConvert', $children); + } else { + return new ASTNode('xaConvert', []); + } + } + + public function xid() + { + $children = []; + + $children[] = $this->textString(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->textString(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->ulong_number(); + } + } + + return new ASTNode('xid', $children); + } + + //---------------------------------------------------------------------------------------------------------------------- + + public function replicationStatement() + { + $token1 = $this->lexer->peekNextToken(); + $token2 = $this->lexer->peekNextToken(2); + $children = []; + + if ($token1->getType() === MySQLLexer::PURGE_SYMBOL) { + $children[] = $this->match(MySQLLexer::PURGE_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::BINARY_SYMBOL) { + $children[] = $this->match(MySQLLexer::BINARY_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::MASTER_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_SYMBOL); + } else { + throw new \Exception('Unexpected token in replicationStatement: ' . $token1->getText()); + } + + $children[] = $this->match(MySQLLexer::LOGS_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::TO_SYMBOL) { + $children[] = $this->match(MySQLLexer::TO_SYMBOL); + $children[] = $this->textLiteral(); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::BEFORE_SYMBOL) { + $children[] = $this->match(MySQLLexer::BEFORE_SYMBOL); + $children[] = $this->expr(); + } else { + throw new \Exception('Unexpected token in replicationStatement: ' . $this->lexer->peekNextToken()->getText()); + } + } elseif ($token1->getType() === MySQLLexer::CHANGE_SYMBOL && $token2->getType() === MySQLLexer::MASTER_SYMBOL) { + return $this->changeMaster(); + } elseif ($token1->getType() === MySQLLexer::RESET_SYMBOL && + ($token2->getType() === MySQLLexer::MASTER_SYMBOL || + ($this->serverVersion < 80000 && $token2->getType() === MySQLLexer::QUERY_SYMBOL) || + $token2->getType() === MySQLLexer::SLAVE_SYMBOL)) { + return $this->resetOption(); + } elseif ($this->serverVersion > 80000 && + $token1->getType() === MySQLLexer::RESET_SYMBOL && + $token2->getType() === MySQLLexer::PERSIST_SYMBOL) { + $children[] = $this->match(MySQLLexer::RESET_SYMBOL); + $children[] = $this->match(MySQLLexer::PERSIST_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IF_SYMBOL) { + $children[] = $this->ifExists(); + $children[] = $this->identifier(); + } + + return new ASTNode('replicationStatement', $children); + } elseif (($token1->getType() === MySQLLexer::START_SYMBOL || + $token1->getType() === MySQLLexer::STOP_SYMBOL) && + $token2->getType() === MySQLLexer::SLAVE_SYMBOL) { + return $this->slave(); + } elseif ($this->serverVersion >= 50700 && + $token1->getType() === MySQLLexer::CHANGE_SYMBOL && + $token2->getType() === MySQLLexer::REPLICATION_SYMBOL) { + return $this->changeReplication(); + } elseif ($token1->getType() === MySQLLexer::LOAD_SYMBOL && + ($token2->getType() === MySQLLexer::DATA_SYMBOL || + $token2->getType() === MySQLLexer::TABLE_SYMBOL)) { + return $this->replicationLoad(); + } elseif ($this->serverVersion > 50706 && + ($token1->getType() === MySQLLexer::START_SYMBOL || + $token1->getType() === MySQLLexer::STOP_SYMBOL) && + $token2->getType() === MySQLLexer::GROUP_REPLICATION_SYMBOL) { + return $this->groupReplication(); + } else { + throw new \Exception('Unexpected token in replicationStatement: ' . $token1->getText()); + } + + return new ASTNode('replicationStatement', $children); + } + + public function replicationLoad() + { + $children = []; + + $children[] = $this->match(MySQLLexer::LOAD_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DATA_SYMBOL) { + $children[] = $this->match(MySQLLexer::DATA_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::TABLE_SYMBOL) { + $children[] = $this->match(MySQLLexer::TABLE_SYMBOL); + $children[] = $this->tableRef(); + } else { + throw new \Exception('Unexpected token in replicationLoad: ' . $this->lexer->peekNextToken()->getText()); + } + + $children[] = $this->match(MySQLLexer::FROM_SYMBOL); + $children[] = $this->match(MySQLLexer::MASTER_SYMBOL); + + return new ASTNode('replicationLoad', $children); + } + + public function changeMaster() + { + $children = []; + + $children[] = $this->match(MySQLLexer::CHANGE_SYMBOL); + $children[] = $this->match(MySQLLexer::MASTER_SYMBOL); + $children[] = $this->match(MySQLLexer::TO_SYMBOL); + $children[] = $this->changeMasterOptions(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->channel(); + } + + return new ASTNode('changeMaster', $children); + } + + public function changeMasterOptions() + { + $children = []; + + $children[] = $this->masterOption(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->masterOption(); + } + + return new ASTNode('changeMasterOptions', $children); + } + + public function masterOption() + { + $token = $this->lexer->peekNextToken(); + $children = []; + if ($token->getType() === MySQLLexer::MASTER_HOST_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_HOST_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textStringNoLinebreak(); + } elseif ($token->getType() === MySQLLexer::MASTER_USER_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_USER_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textStringNoLinebreak(); + } elseif ($token->getType() === MySQLLexer::MASTER_PASSWORD_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_PASSWORD_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textStringNoLinebreak(); + } elseif ($token->getType() === MySQLLexer::MASTER_PORT_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_PORT_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::MASTER_CONNECT_RETRY_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_CONNECT_RETRY_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::MASTER_RETRY_COUNT_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_RETRY_COUNT_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::MASTER_DELAY_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_DELAY_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::MASTER_SSL_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_SSL_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::MASTER_SSL_CA_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_SSL_CA_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textStringNoLinebreak(); + } elseif ($token->getType() === MySQLLexer::MASTER_SSL_CAPATH_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_SSL_CAPATH_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textStringNoLinebreak(); + } elseif ($token->getType() === MySQLLexer::MASTER_TLS_VERSION_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_TLS_VERSION_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textStringNoLinebreak(); + } elseif ($token->getType() === MySQLLexer::MASTER_SSL_CERT_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_SSL_CERT_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textStringNoLinebreak(); + } elseif ($token->getType() === MySQLLexer::MASTER_TLS_CIPHERSUITES_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_TLS_CIPHERSUITES_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->masterTlsCiphersuitesDef(); + } elseif ($token->getType() === MySQLLexer::MASTER_SSL_CIPHER_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_SSL_CIPHER_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textStringNoLinebreak(); + } elseif ($token->getType() === MySQLLexer::MASTER_SSL_KEY_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_SSL_KEY_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textStringNoLinebreak(); + } elseif ($token->getType() === MySQLLexer::MASTER_SSL_CRL_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_SSL_CRL_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textLiteral(); + } elseif ($token->getType() === MySQLLexer::MASTER_SSL_CRLPATH_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_SSL_CRLPATH_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textStringNoLinebreak(); + } elseif ($token->getType() === MySQLLexer::MASTER_SSL_VERIFY_SERVER_CERT_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_SSL_VERIFY_SERVER_CERT_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::MASTER_HEARTBEAT_PERIOD_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_HEARTBEAT_PERIOD_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::MASTER_LOG_FILE_SYMBOL || + $token->getType() === MySQLLexer::MASTER_LOG_POS_SYMBOL || + $token->getType() === MySQLLexer::RELAY_LOG_FILE_SYMBOL || + $token->getType() === MySQLLexer::RELAY_LOG_POS_SYMBOL) { + return $this->masterFileDef(); + } elseif ($token->getType() === MySQLLexer::MASTER_PUBLIC_KEY_PATH_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_PUBLIC_KEY_PATH_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textStringNoLinebreak(); + } elseif ($token->getType() === MySQLLexer::GET_MASTER_PUBLIC_KEY_SYMBOL) { + $children[] = $this->match(MySQLLexer::GET_MASTER_PUBLIC_KEY_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->ulong_number(); + } elseif ($this->serverVersion >= 80017 && $token->getType() === MySQLLexer::NETWORK_NAMESPACE_SYMBOL) { + $children[] = $this->match(MySQLLexer::NETWORK_NAMESPACE_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textStringNoLinebreak(); + } elseif ($this->serverVersion >= 50602 && $token->getType() === MySQLLexer::MASTER_BIND_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_BIND_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textStringNoLinebreak(); + } elseif ($token->getType() === MySQLLexer::IGNORE_SERVER_IDS_SYMBOL) { + $children[] = $this->match(MySQLLexer::IGNORE_SERVER_IDS_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->serverIdList(); + } elseif ($this->serverVersion >= 80018 && + $token->getType() === MySQLLexer::MASTER_COMPRESSION_ALGORITHM_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_COMPRESSION_ALGORITHM_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textStringLiteral(); + } elseif ($this->serverVersion >= 80018 && + $token->getType() === MySQLLexer::MASTER_ZSTD_COMPRESSION_LEVEL_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_ZSTD_COMPRESSION_LEVEL_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->ulong_number(); + } elseif ($this->serverVersion >= 50605 && + $token->getType() === MySQLLexer::MASTER_AUTO_POSITION_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_AUTO_POSITION_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->ulong_number(); + } elseif ($this->serverVersion >= 80018 && + $token->getType() === MySQLLexer::PRIVILEGE_CHECKS_USER_SYMBOL) { + $children[] = $this->match(MySQLLexer::PRIVILEGE_CHECKS_USER_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->privilegeCheckDef(); + } elseif ($this->serverVersion >= 80019 && + $token->getType() === MySQLLexer::REQUIRE_ROW_FORMAT_SYMBOL) { + $children[] = $this->match(MySQLLexer::REQUIRE_ROW_FORMAT_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->ulong_number(); + } elseif ($this->serverVersion >= 80019 && + $token->getType() === MySQLLexer::REQUIRE_TABLE_PRIMARY_KEY_CHECK_SYMBOL) { + $children[] = $this->match(MySQLLexer::REQUIRE_TABLE_PRIMARY_KEY_CHECK_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->tablePrimaryKeyCheckDef(); + } else { + throw new \Exception('Unexpected token in masterOption: ' . $token->getText()); + } + + return new ASTNode('masterOption', $children); + } + + public function privilegeCheckDef() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT || + $token->getType() === MySQLLexer::AT_SIGN_SYMBOL || + $token->getType() === MySQLLexer::AT_TEXT_SUFFIX) { + return $this->userIdentifierOrText(); + } elseif ($token->getType() === MySQLLexer::NULL_SYMBOL) { + return $this->match(MySQLLexer::NULL_SYMBOL); + } else { + throw new \Exception('Unexpected token in privilegeCheckDef: ' . $token->getText()); + } + } + + public function tablePrimaryKeyCheckDef() +{ + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::STREAM_SYMBOL: + case MySQLLexer::ON_SYMBOL: + case MySQLLexer::OFF_SYMBOL: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in indexType: ' . $token->getText()); + } +} + + public function masterTlsCiphersuitesDef() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + return $this->textStringNoLinebreak(); + } elseif ($token->getType() === MySQLLexer::NULL_SYMBOL) { + return $this->match(MySQLLexer::NULL_SYMBOL); + } else { + throw new \Exception('Unexpected token in masterTlsCiphersuitesDef: ' . $token->getText()); + } + } + + public function masterFileDef() + { + $token = $this->lexer->peekNextToken(); + $children = []; + if ($token->getType() === MySQLLexer::MASTER_LOG_FILE_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_LOG_FILE_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textStringNoLinebreak(); + } elseif ($token->getType() === MySQLLexer::MASTER_LOG_POS_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_LOG_POS_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->ulonglong_number(); + } elseif ($token->getType() === MySQLLexer::RELAY_LOG_FILE_SYMBOL) { + $children[] = $this->match(MySQLLexer::RELAY_LOG_FILE_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textStringNoLinebreak(); + } elseif ($token->getType() === MySQLLexer::RELAY_LOG_POS_SYMBOL) { + $children[] = $this->match(MySQLLexer::RELAY_LOG_POS_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->ulong_number(); + } else { + throw new \Exception('Unexpected token in masterFileDef: ' . $token->getText()); + } + + return new ASTNode('masterFileDef', $children); + } + + public function serverIdList() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ULONGLONG_NUMBER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::LONG_NUMBER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INT_NUMBER) { + $children[] = $this->ulong_number(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->ulong_number(); + } + } + + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + + return new ASTNode('serverIdList', $children); + } + + public function changeReplication() + { + $children = []; + + $children[] = $this->match(MySQLLexer::CHANGE_SYMBOL); + $children[] = $this->match(MySQLLexer::REPLICATION_SYMBOL); + $children[] = $this->match(MySQLLexer::FILTER_SYMBOL); + $children[] = $this->filterDefinition(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->filterDefinition(); + } + if ($this->serverVersion >= 80000 && $this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->channel(); + } + + return new ASTNode('changeReplication', $children); + } + + public function filterDefinition() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::REPLICATE_DO_DB_SYMBOL) { + $children[] = $this->match(MySQLLexer::REPLICATE_DO_DB_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + $children[] = $this->filterDbList(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } elseif ($token->getType() === MySQLLexer::REPLICATE_IGNORE_DB_SYMBOL) { + $children[] = $this->match(MySQLLexer::REPLICATE_IGNORE_DB_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + $children[] = $this->filterDbList(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } elseif ($token->getType() === MySQLLexer::REPLICATE_DO_TABLE_SYMBOL) { + $children[] = $this->match(MySQLLexer::REPLICATE_DO_TABLE_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken()) || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->filterTableList(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } elseif ($token->getType() === MySQLLexer::REPLICATE_IGNORE_TABLE_SYMBOL) { + $children[] = $this->match(MySQLLexer::REPLICATE_IGNORE_TABLE_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken()) || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->filterTableList(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } elseif ($token->getType() === MySQLLexer::REPLICATE_WILD_DO_TABLE_SYMBOL) { + $children[] = $this->match(MySQLLexer::REPLICATE_WILD_DO_TABLE_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + $children[] = $this->filterStringList(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } elseif ($token->getType() === MySQLLexer::REPLICATE_WILD_IGNORE_TABLE_SYMBOL) { + $children[] = $this->match(MySQLLexer::REPLICATE_WILD_IGNORE_TABLE_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + $children[] = $this->filterStringList(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } elseif ($token->getType() === MySQLLexer::REPLICATE_REWRITE_DB_SYMBOL) { + $children[] = $this->match(MySQLLexer::REPLICATE_REWRITE_DB_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->filterDbPairList(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } else { + throw new \Exception('Unexpected token in filterDefinition: ' . $token->getText()); + } + + return new ASTNode('filterDefinition', $children); + } + + public function filterDbList() + { + $children = []; + + $children[] = $this->schemaRef(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->schemaRef(); + } + + return new ASTNode('filterDbList', $children); + } + + public function filterTableList() + { + $children = []; + + $children[] = $this->filterTableRef(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->filterTableRef(); + } + + return new ASTNode('filterTableList', $children); + } + + public function filterStringList() + { + $children = []; + + $children[] = $this->filterWildDbTableString(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->filterWildDbTableString(); + } + + return new ASTNode('filterStringList', $children); + } + + public function filterWildDbTableString() + { + return $this->textStringNoLinebreak(); + } + + public function filterDbPairList() + { + $children = []; + + $children[] = $this->schemaIdentifierPair(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->schemaIdentifierPair(); + } + + return new ASTNode('filterDbPairList', $children); + } + + public function resetOption() + { + $this->match(MySQLLexer::RESET_SYMBOL); + $children = [new ASTNode(MySQLLexer::getTokenName(MySQLLexer::RESET_SYMBOL))]; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::MASTER_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_SYMBOL); + + if ($this->serverVersion >= 80000 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::TO_SYMBOL) { + $children[] = $this->masterResetOptions(); + } + } elseif ($this->serverVersion < 80000 && $token->getType() === MySQLLexer::QUERY_SYMBOL) { + $children[] = $this->match(MySQLLexer::QUERY_SYMBOL); + $children[] = $this->match(MySQLLexer::CACHE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::SLAVE_SYMBOL) { + $children[] = $this->match(MySQLLexer::SLAVE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ALL_SYMBOL) { + $children[] = $this->match(MySQLLexer::ALL_SYMBOL); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->channel(); + } + } else { + throw new \Exception('Unexpected token in resetOption: ' . $token->getText()); + } + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::MASTER_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_SYMBOL); + + if ($this->serverVersion >= 80000 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::TO_SYMBOL) { + $children[] = $this->masterResetOptions(); + } + } elseif ($this->serverVersion < 80000 && $token->getType() === MySQLLexer::QUERY_SYMBOL) { + $children[] = $this->match(MySQLLexer::QUERY_SYMBOL); + $children[] = $this->match(MySQLLexer::CACHE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::SLAVE_SYMBOL) { + $children[] = $this->match(MySQLLexer::SLAVE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ALL_SYMBOL) { + $children[] = $this->match(MySQLLexer::ALL_SYMBOL); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->channel(); + } + } else { + throw new \Exception('Unexpected token in resetOption: ' . $token->getText()); + } + } + + return new ASTNode('resetOption', $children); + } + + public function masterResetOptions() + { + $children = []; + + $children[] = $this->match(MySQLLexer::TO_SYMBOL); + if ($this->serverVersion >= 80017 && $this->isReal_ulonglong_numberStart($this->lexer->peekNextToken())) { + $children[] = $this->real_ulonglong_number(); + } elseif ($this->isReal_ulong_numberStart($this->lexer->peekNextToken())) { + $children[] = $this->real_ulong_number(); + } else { + throw new \Exception('Unexpected token in masterResetOptions: ' . $this->lexer->peekNextToken()->getText()); + } + + return new ASTNode('masterResetOptions', $children); + } + + public function slave() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::START_SYMBOL) { + $children[] = $this->match(MySQLLexer::START_SYMBOL); + $children[] = $this->match(MySQLLexer::SLAVE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::RELAY_THREAD_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::SQL_THREAD_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IO_THREAD_SYMBOL) { + $children[] = $this->slaveThreadOptions(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::UNTIL_SYMBOL) { + $children[] = $this->match(MySQLLexer::UNTIL_SYMBOL); + $children[] = $this->slaveUntilOptions(); + } + if ($this->serverVersion >= 50604 && + ($this->lexer->peekNextToken()->getType() === MySQLLexer::USER_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::PASSWORD_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DEFAULT_AUTH_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::PLUGIN_DIR_SYMBOL)) { + $children[] = $this->slaveConnectionOptions(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->channel(); + } + } elseif ($token->getType() === MySQLLexer::STOP_SYMBOL) { + $children[] = $this->match(MySQLLexer::STOP_SYMBOL); + $children[] = $this->match(MySQLLexer::SLAVE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::RELAY_THREAD_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::SQL_THREAD_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IO_THREAD_SYMBOL) { + $children[] = $this->slaveThreadOptions(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->channel(); + } + } else { + throw new \Exception('Unexpected token in slave: ' . $token->getText()); + } + + return new ASTNode('slave', $children); + } + + public function slaveUntilOptions() + { + $children = []; + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::MASTER_LOG_FILE_SYMBOL || + $token->getType() === MySQLLexer::MASTER_LOG_POS_SYMBOL || + $token->getType() === MySQLLexer::RELAY_LOG_FILE_SYMBOL || + $token->getType() === MySQLLexer::RELAY_LOG_POS_SYMBOL || + ($this->serverVersion >= 50606 && + ($token->getType() === MySQLLexer::SQL_BEFORE_GTIDS_SYMBOL || + $token->getType() === MySQLLexer::SQL_AFTER_GTIDS_SYMBOL || + $token->getType() === MySQLLexer::SQL_AFTER_MTS_GAPS_SYMBOL))) { + if ($token->getType() === MySQLLexer::MASTER_LOG_FILE_SYMBOL || + $token->getType() === MySQLLexer::MASTER_LOG_POS_SYMBOL || + $token->getType() === MySQLLexer::RELAY_LOG_FILE_SYMBOL || + $token->getType() === MySQLLexer::RELAY_LOG_POS_SYMBOL) { + $children[] = $this->masterFileDef(); + } elseif ($this->serverVersion >= 50606) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::SQL_BEFORE_GTIDS_SYMBOL) { + $children[] = $this->match(MySQLLexer::SQL_BEFORE_GTIDS_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::SQL_AFTER_GTIDS_SYMBOL) { + $children[] = $this->match(MySQLLexer::SQL_AFTER_GTIDS_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::SQL_AFTER_MTS_GAPS_SYMBOL) { + $children[] = $this->match(MySQLLexer::SQL_AFTER_MTS_GAPS_SYMBOL); + } else { + throw new \Exception('Unexpected token in slaveUntilOptions: ' . $this->lexer->peekNextToken()->getText()); + } + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textString(); + } else { + throw new \Exception('Unexpected token in slaveUntilOptions: ' . $this->lexer->peekNextToken()->getText()); + } + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->masterFileDef(); + } + } + + return new ASTNode('slaveUntilOptions', $children); + } + + public function slaveConnectionOptions() + { + $children = []; + $token1 = $this->lexer->peekNextToken(); + $token2 = $this->lexer->peekNextToken(2); + + if ($token1->getType() === MySQLLexer::USER_SYMBOL && $token2->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::USER_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textString(); + } + + $token1 = $this->lexer->peekNextToken(); + $token2 = $this->lexer->peekNextToken(2); + if ($token1->getType() === MySQLLexer::PASSWORD_SYMBOL && $token2->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::PASSWORD_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textString(); + } + + $token1 = $this->lexer->peekNextToken(); + $token2 = $this->lexer-> peekNextToken(2); + if ($token1->getType() === MySQLLexer::DEFAULT_AUTH_SYMBOL && + $token2->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::DEFAULT_AUTH_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textString(); + } + + $token1 = $this->lexer->peekNextToken(); + $token2 = $this->lexer->peekNextToken(2); + if ($token1->getType() === MySQLLexer::PLUGIN_DIR_SYMBOL && + $token2->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::PLUGIN_DIR_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textString(); + } + + return new ASTNode('slaveConnectionOptions', $children); + } + + public function slaveThreadOptions() + { + $children = []; + + $children[] = $this->slaveThreadOption(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->slaveThreadOption(); + } + + return new ASTNode('slaveThreadOptions', $children); + } + + public function slaveThreadOption() +{ + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::RELAY_THREAD_SYMBOL: + case MySQLLexer::SQL_THREAD_SYMBOL: + case MySQLLexer::IO_THREAD_SYMBOL: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in indexType: ' . $token->getText()); + } +} + + public function groupReplication() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::START_SYMBOL) { + $this->match(MySQLLexer::START_SYMBOL); + $children = [ + new ASTNode(MySQLLexer::getTokenName(MySQLLexer::START_SYMBOL)), + ]; + } elseif ($token->getType() === MySQLLexer::STOP_SYMBOL) { + $this->match(MySQLLexer::STOP_SYMBOL); + $children = [ + new ASTNode(MySQLLexer::getTokenName(MySQLLexer::STOP_SYMBOL)), + ]; + } else { + throw new \Exception('Unexpected token in groupReplication: ' . $token->getText()); + } + + $children[] = $this->match(MySQLLexer::GROUP_REPLICATION_SYMBOL); + + return new ASTNode('groupReplication', $children); + } + + //---------------------------------------------------------------------------------------------------------------------- + + public function preparedStatement() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::PREPARE_SYMBOL) { + $this->match(MySQLLexer::PREPARE_SYMBOL); + $children[] = ASTNode::fromToken($token); + $children[] = $this->identifier(); + $children[] = $this->match(MySQLLexer::FROM_SYMBOL); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + $children[] = $this->textLiteral(); + } elseif ($token->getType() === MySQLLexer::AT_SIGN_SYMBOL || + $token->getType() === MySQLLexer::AT_TEXT_SUFFIX) { + $children[] = $this->userVariable(); + } else { + throw new \Exception('Unexpected token in preparedStatement: ' . $token->getText()); + } + } elseif ($token->getType() === MySQLLexer::EXECUTE_SYMBOL) { + return $this->executeStatement(); + } elseif ($token->getType() === MySQLLexer::DEALLOCATE_SYMBOL || + $token->getType() === MySQLLexer::DROP_SYMBOL) { + if ($token->getType() === MySQLLexer::DEALLOCATE_SYMBOL) { + $children[] = $this->match(MySQLLexer::DEALLOCATE_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::DROP_SYMBOL); + } + $this->match(MySQLLexer::PREPARE_SYMBOL); + $children[] = ASTNode::fromToken($token); + $children[] = $this->identifier(); + } else { + throw new \Exception('Unexpected token in preparedStatement: ' . $token->getText()); + } + + return new ASTNode('preparedStatement', $children); + } + + public function executeStatement() + { + $children = []; + + $children[] = $this->match(MySQLLexer::EXECUTE_SYMBOL); + $children[] = $this->identifier(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::USING_SYMBOL) { + $children[] = $this->match(MySQLLexer::USING_SYMBOL); + $children[] = $this->executeVarList(); + } + + return new ASTNode('executeStatement', $children); + } + + public function executeVarList() + { + $children = []; + + $children[] = $this->userVariable(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->userVariable(); + } + + return new ASTNode('executeVarList', $children); + } + + //---------------------------------------------------------------------------------------------------------------------- + + public function cloneStatement() + { + $children = []; + + $children[] = $this->match(MySQLLexer::CLONE_SYMBOL); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::LOCAL_SYMBOL) { + $this->match(MySQLLexer::LOCAL_SYMBOL); + $children[] = ASTNode::fromToken($token); + $children[] = $this->match(MySQLLexer::DATA_SYMBOL); + $children[] = $this->match(MySQLLexer::DIRECTORY_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ASSIGN_OPERATOR) { + $children[] = $this->equal(); + } + $children[] = $this->textStringLiteral(); + } elseif ($this->serverVersion < 80014 && $token->getType() === MySQLLexer::REMOTE_SYMBOL) { + $children[] = $this->match(MySQLLexer::REMOTE_SYMBOL); + if ( + $this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL && + $this->lexer->peekNextToken()->getType(2) === MySQLLexer::REPLICATION_SYMBOL) { + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->match(MySQLLexer::REPLICATION_SYMBOL); + } + } elseif ($this->serverVersion >= 80014 && $token->getType() === MySQLLexer::INSTANCE_SYMBOL) { + $children[] = $this->match(MySQLLexer::INSTANCE_SYMBOL); + $children[] = $this->match(MySQLLexer::FROM_SYMBOL); + $children[] = $this->user(); + $children[] = $this->match(MySQLLexer::COLON_SYMBOL); + $children[] = $this->ulong_number(); + $children[] = $this->match(MySQLLexer::IDENTIFIED_SYMBOL); + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + $children[] = $this->textStringLiteral(); + $children[] = $this->dataDirSSL(); + } else { + throw new \Exception('Unexpected token in cloneStatement: ' . $token->getText()); + } + + return new ASTNode('cloneStatement', $children); + } + + public function createView() + { + $children = []; + + $children[] = $this->viewReplaceOrAlgorithm(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DEFINER_SYMBOL) { + $children[] = $this->definerClause(); + } + if ( + $this->lexer->peekNextToken()->getType() === MySQLLexer::SQL_SYMBOL && + $this->lexer->peekNextToken()->getType(2) === MySQLLexer::SECURITY_SYMBOL) { + $children[] = $this->viewSuid(); + } + $this->match(MySQLLexer::VIEW_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::VIEW_SYMBOL)); + $children[] = $this->viewName(); + $children[] = $this->viewTail(); + + return new ASTNode('createView', $children); + } + + public function viewSuid() + { + $children = []; + $this->match(MySQLLexer::SQL_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::SQL_SYMBOL)); + $this->match(MySQLLexer::SECURITY_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::SECURITY_SYMBOL)); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DEFINER_SYMBOL) { + $children[] = $this->match(MySQLLexer::DEFINER_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::INVOKER_SYMBOL); + } + return new ASTNode('viewSuid', $children); + } + + public function viewAlgorithm() + { + $children = []; + + $this->match(MySQLLexer::ALGORITHM_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::ALGORITHM_SYMBOL)); + $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::EQUAL_OPERATOR)); + $children[] = $this->match($this->lexer->peekNextToken()->getType()); + + return new ASTNode('viewAlgorithm', $children); + } + + public function createSpatialReference() + { + $children = []; + + if ( + $this->lexer->peekNextToken()->getType() === MySQLLexer::OR_SYMBOL && + $this->lexer->peekNextToken()->getType(2) === MySQLLexer::REPLACE_SYMBOL) { + $this->match(MySQLLexer::OR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::OR_SYMBOL)); + $this->match(MySQLLexer::REPLACE_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::REPLACE_SYMBOL)); + } + $this->match(MySQLLexer::SPATIAL_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::SPATIAL_SYMBOL)); + $this->match(MySQLLexer::REFERENCE_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::REFERENCE_SYMBOL)); + $this->match(MySQLLexer::SYSTEM_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::SYSTEM_SYMBOL)); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IF_SYMBOL) { + $children[] = $this->ifNotExists(); + } + $children[] = $this->real_ulonglong_number(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::NAME_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DEFINITION_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ORGANIZATION_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DESCRIPTION_SYMBOL) { + $children[] = $this->srsAttribute(); + } + + return new ASTNode('createSpatialReference', $children); + } + + public function dataDirSSL() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::REQUIRE_SYMBOL) { + return $this->ssl(); + } elseif ($token->getType() === MySQLLexer::DATA_SYMBOL) { + $children[] = $this->match(MySQLLexer::DATA_SYMBOL); + $children[] = $this->match(MySQLLexer::DIRECTORY_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ASSIGN_OPERATOR) { + $children[] = $this->equal(); + } + + $children[] = $this->textStringLiteral(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::REQUIRE_SYMBOL) { + $children[] = $this->ssl(); + } + + return new ASTNode('dataDirSSL', $children); + } else { + throw new \Exception('Unexpected token in dataDirSSL: ' . $token->getText()); + } + } + + public function ssl() + { + $children = []; + + $children[] = $this->match(MySQLLexer::REQUIRE_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::NO_SYMBOL) { + $children[] = $this->match(MySQLLexer::NO_SYMBOL); + } + + $children[] = $this->match(MySQLLexer::SSL_SYMBOL); + + return new ASTNode('ssl', $children); + } + + //---------------------------------------------------------------------------------------------------------------------- + + // Note: SET PASSWORD is part of the SET statement. + public function accountManagementStatement() + { + $token = $this->lexer->peekNextToken(); + + if ($this->serverVersion >= 50606 && $token->getType() === MySQLLexer::ALTER_SYMBOL) { + return $this->alterUser(); + } elseif ($token->getType() === MySQLLexer::CREATE_SYMBOL) { + return $this->createUser(); + } elseif ($token->getType() === MySQLLexer::DROP_SYMBOL) { + return $this->dropUser(); + } elseif ($token->getType() === MySQLLexer::GRANT_SYMBOL) { + return $this->grant(); + } elseif ($token->getType() === MySQLLexer::RENAME_SYMBOL) { + return $this->renameUser(); + } elseif ($token->getType() === MySQLLexer::REVOKE_SYMBOL) { + return $this->revoke(); + } elseif ($this->serverVersion >= 80000 && $token->getType() === MySQLLexer::SET_SYMBOL) { + return $this->setRole(); + } else { + throw new \Exception('Unexpected token in accountManagementStatement: ' . $token->getText()); + } + } + + public function alterUser() + { + $children = []; + + $children[] = $this->match(MySQLLexer::ALTER_SYMBOL); + $children[] = $this->match(MySQLLexer::USER_SYMBOL); + + if ($this->serverVersion >= 50706 && $this->lexer->peekNextToken()->getType() === MySQLLexer::IF_SYMBOL) { + $children[] = $this->ifExists(); + } + + $children[] = $this->alterUserTail(); + return new ASTNode('alterUser', $children); + } + + public function alterUserTail() + { + $token1 = $this->lexer->peekNextToken(); + $token2 = $this->lexer->peekNextToken(2); + $children = []; + + if (($token1->getType() === MySQLLexer::IDENTIFIER || + $token1->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token1->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token1) || + $token1->getType() === MySQLLexer::SINGLE_QUOTED_TEXT || + $token1->getType() === MySQLLexer::CURRENT_USER_SYMBOL || + $token1->getType() === MySQLLexer::AT_SIGN_SYMBOL || + $token1->getType() === MySQLLexer::AT_TEXT_SUFFIX) && + ($token2->getType() === MySQLLexer::COMMA_SYMBOL || + $token2->getType() === MySQLLexer::IDENTIFIED_SYMBOL || + $token2->getType() === MySQLLexer::DISCARD_SYMBOL || + $token2->getType() === MySQLLexer::DEFAULT_SYMBOL || + ($this->serverVersion >= 80000 && $token2->getType() === MySQLLexer::ACCOUNT_SYMBOL) || + ($this->serverVersion >= 80000 && $token2->getType() === MySQLLexer::PASSWORD_SYMBOL) || + ($this->serverVersion >= 80019 && + $token2->getType() === MySQLLexer::FAILED_LOGIN_ATTEMPTS_SYMBOL) || + ($this->serverVersion >= 80019 && + $token2->getType() === MySQLLexer::PASSWORD_LOCK_TIME_SYMBOL))) { + if ($this->serverVersion < 80014) { + $children[] = $this->createUserList(); + } else { + $children[] = $this->alterUserList(); + } + + $children[] = $this->alterUserTail(); + } elseif (($token1->getType() === MySQLLexer::IDENTIFIER || + $token1->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token1->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token1) || + $token1->getType() === MySQLLexer::SINGLE_QUOTED_TEXT || + $token1->getType() === MySQLLexer::CURRENT_USER_SYMBOL || + $token1->getType() === MySQLLexer::AT_SIGN_SYMBOL || + $token1->getType() === MySQLLexer::AT_TEXT_SUFFIX) && + $token2->getType() === MySQLLexer::IDENTIFIED_SYMBOL) { + $children[] = $this->user(); + $children[] = $this->match(MySQLLexer::IDENTIFIED_SYMBOL); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::BY_SYMBOL) { + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + $children[] = $this->textString(); + if ($this->serverVersion >= 80014 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::REPLACE_SYMBOL) { + $children[] = $this->replacePassword(); + } + if ($this->serverVersion >= 80014 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::RETAIN_SYMBOL) { + $children[] = $this->retainCurrentPassword(); + } + } elseif ($this->serverVersion >= 80018 && $token->getType() === MySQLLexer::WITH_SYMBOL) { + $children[] = $this->match(MySQLLexer::WITH_SYMBOL); + $children[] = $this->textOrIdentifier(); + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + $children[] = $this->match(MySQLLexer::RANDOM_SYMBOL); + $children[] = $this->match(MySQLLexer::PASSWORD_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::RETAIN_SYMBOL) { + $children[] = $this->retainCurrentPassword(); + } + } else { + throw new \Exception('Unexpected token in alterUserTail: ' . $token->getText()); + } + } elseif (($token1->getType() === MySQLLexer::IDENTIFIER || + $token1->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token1->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token1) || + $token1->getType() === MySQLLexer::SINGLE_QUOTED_TEXT || + $token1->getType() === MySQLLexer::CURRENT_USER_SYMBOL || + $token1->getType() === MySQLLexer::AT_SIGN_SYMBOL || + $token1->getType() === MySQLLexer::AT_TEXT_SUFFIX) && + ($this->serverVersion >= 80014 && $token2->getType() === MySQLLexer::DISCARD_SYMBOL)) { + $children[] = $this->user(); + $children[] = $this->discardOldPassword(); + } elseif (($token1->getType() === MySQLLexer::IDENTIFIER || + $token1->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token1->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token1) || + $token1->getType() === MySQLLexer::SINGLE_QUOTED_TEXT || + $token1->getType() === MySQLLexer::CURRENT_USER_SYMBOL || + $token1->getType() === MySQLLexer::AT_SIGN_SYMBOL || + $token1->getType() === MySQLLexer::AT_TEXT_SUFFIX) && + ($this->serverVersion >= 80000 && $token2->getType() === MySQLLexer::DEFAULT_SYMBOL)) { + $children[] = $this->user(); + $children[] = $this->match(MySQLLexer::DEFAULT_SYMBOL); + $children[] = $this->match(MySQLLexer::ROLE_SYMBOL); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::ALL_SYMBOL) { + $children[] = $this->match(MySQLLexer::ALL_SYMBOL); + } elseif ($token->getType() === MySQLLexer::NONE_SYMBOL) { + $children[] = $this->match(MySQLLexer::NONE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + $children[] = $this->roleList(); + } else { + throw new \Exception('Unexpected token in alterUserTail: ' . $token->getText()); + } + } elseif ($this->serverVersion >= 80019 && + $token1->getType() === MySQLLexer::FAILED_LOGIN_ATTEMPTS_SYMBOL) { + $children[] = $this->match(MySQLLexer::FAILED_LOGIN_ATTEMPTS_SYMBOL); + $children[] = $this->real_ulong_number(); + } elseif ($this->serverVersion >= 80019 && + $token1->getType() === MySQLLexer::PASSWORD_LOCK_TIME_SYMBOL) { + $children[] = $this->match(MySQLLexer::PASSWORD_LOCK_TIME_SYMBOL); + if ($this->isReal_ulong_numberStart($this->lexer->peekNextToken())) { + $children[] = $this->real_ulong_number(); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::UNBOUNDED_SYMBOL) { + $children[] = $this->match(MySQLLexer::UNBOUNDED_SYMBOL); + } else { + throw new \Exception('Unexpected token in alterUserTail: ' . $this->lexer->peekNextToken()->getText()); + } + } else { + throw new \Exception('Unexpected token in alterUserTail: ' . $token1->getText()); + } + + return new ASTNode('alterUserTail', $children); + } + + public function userFunction() + { + $children = []; + + $children[] = $this->match(MySQLLexer::USER_SYMBOL); + $children[] = $this->parentheses(); + return new ASTNode('userFunction', $children); + } + + public function createUser() + { + $children = []; + + $children[] = $this->match(MySQLLexer::CREATE_SYMBOL); + $children[] = $this->match(MySQLLexer::USER_SYMBOL); + + if ($this->serverVersion >= 50706 && $this->lexer->peekNextToken()->getType() === MySQLLexer::IF_SYMBOL) { + $children[] = $this->ifNotExists(); + } + + $children[] = $this->createUserList(); + + if ($this->serverVersion >= 80000 && $this->lexer->peekNextToken()->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->defaultRoleClause(); + } + + if ($this->serverVersion >= 50706 && + ($this->lexer->peekNextToken()->getType() === MySQLLexer::REQUIRE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WITH_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ACCOUNT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::PASSWORD_SYMBOL)) { + $children[] = $this->createUserTail(); + } + + return new ASTNode('createUser', $children); + } + + public function defaultRoleClause() + { + $children = []; + + $children[] = $this->match(MySQLLexer::DEFAULT_SYMBOL); + $children[] = $this->match(MySQLLexer::ROLE_SYMBOL); + $children[] = $this->roleList(); + return new ASTNode('defaultRoleClause', $children); + } + + public function requireClause() + { + $this->match(MySQLLexer::REQUIRE_SYMBOL); + $children = [new ASTNode(MySQLLexer::getTokenName(MySQLLexer::REQUIRE_SYMBOL))]; + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::CIPHER_SYMBOL || + $token->getType() === MySQLLexer::ISSUER_SYMBOL || + $token->getType() === MySQLLexer::SUBJECT_SYMBOL) { + $children[] = $this->requireList(); + } elseif ($token->getType() === MySQLLexer::SSL_SYMBOL) { + $children[] = $this->match(MySQLLexer::SSL_SYMBOL); + } elseif ($token->getType() === MySQLLexer::X509_SYMBOL) { + $children[] = $this->match(MySQLLexer::X509_SYMBOL); + } elseif ($token->getType() === MySQLLexer::NONE_SYMBOL) { + $children[] = $this->match(MySQLLexer::NONE_SYMBOL); + } else { + throw new \Exception('Unexpected token in requireClause: ' . $token->getText()); + } + + return new ASTNode('requireClause', $children); + } + + public function connectOptions() + { + $children = []; + + $children[] = $this->match(MySQLLexer::WITH_SYMBOL); + + do { + $token = $this->lexer->peekNextToken(); + $temp = []; + + if ($token->getType() === MySQLLexer::MAX_QUERIES_PER_HOUR_SYMBOL) { + $this->match(MySQLLexer::MAX_QUERIES_PER_HOUR_SYMBOL); + $temp[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::MAX_QUERIES_PER_HOUR_SYMBOL)); + $temp[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::MAX_UPDATES_PER_HOUR_SYMBOL) { + $this->match(MySQLLexer::MAX_UPDATES_PER_HOUR_SYMBOL); + $temp[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::MAX_UPDATES_PER_HOUR_SYMBOL)); + $temp[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::MAX_CONNECTIONS_PER_HOUR_SYMBOL) { + $this->match(MySQLLexer::MAX_CONNECTIONS_PER_HOUR_SYMBOL); + $temp[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::MAX_CONNECTIONS_PER_HOUR_SYMBOL)); + $temp[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::MAX_USER_CONNECTIONS_SYMBOL) { + $this->match(MySQLLexer::MAX_USER_CONNECTIONS_SYMBOL); + $temp[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::MAX_USER_CONNECTIONS_SYMBOL)); + $temp[] = $this->ulong_number(); + } else { + throw new \Exception('Unexpected token in connectOptions: ' . $token->getText()); + } + + $children[] = new ASTNode('', $temp); + } while ($this->lexer->peekNextToken()->getType() === MySQLLexer::MAX_QUERIES_PER_HOUR_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::MAX_UPDATES_PER_HOUR_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::MAX_CONNECTIONS_PER_HOUR_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::MAX_USER_CONNECTIONS_SYMBOL); + + return new ASTNode('connectOptions', $children); + } + + public function accountLockPasswordExpireOptions() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::ACCOUNT_SYMBOL) { + $children[] = $this->match(MySQLLexer::ACCOUNT_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LOCK_SYMBOL) { + $children[] = $this->match(MySQLLexer::LOCK_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::UNLOCK_SYMBOL) { + $children[] = $this->match(MySQLLexer::UNLOCK_SYMBOL); + } else { + throw new \Exception( + 'Unexpected token in accountLockPasswordExpireOptions: ' . + $this->lexer->peekNextToken()->getText() + ); + } + } elseif ($token->getType() === MySQLLexer::PASSWORD_SYMBOL) { + $children[] = $this->match(MySQLLexer::PASSWORD_SYMBOL); + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::EXPIRE_SYMBOL) { + $children[] = $this->match(MySQLLexer::EXPIRE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::INTERVAL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NEVER_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DEFAULT_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::INTERVAL_SYMBOL) { + $children[] = $this->match(MySQLLexer::INTERVAL_SYMBOL); + $children[] = $this->real_ulong_number(); + $this->match(MySQLLexer:: DAY_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::DAY_SYMBOL)); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::NEVER_SYMBOL) { + $children[] = $this->match(MySQLLexer::NEVER_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->match(MySQLLexer::DEFAULT_SYMBOL); + } else { + throw new \Exception( + 'Unexpected token in accountLockPasswordExpireOptions: ' . + $this->lexer->peekNextToken()->getText() + ); + } + } + } elseif ($token->getType() === MySQLLexer::HISTORY_SYMBOL) { + $children[] = $this->match(MySQLLexer::HISTORY_SYMBOL); + if ($this->isReal_ulong_numberStart($this->lexer->peekNextToken())) { + $children[] = $this->real_ulong_number(); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->match(MySQLLexer::DEFAULT_SYMBOL); + } else { + throw new \Exception( + 'Unexpected token in accountLockPasswordExpireOptions: ' . + $this->lexer->peekNextToken()->getText() + ); + } + } elseif ($token->getType() === MySQLLexer::REUSE_SYMBOL) { + $children[] = $this->match(MySQLLexer::REUSE_SYMBOL); + $children[] = $this->match(MySQLLexer::INTERVAL_SYMBOL); + if ($this->isReal_ulong_numberStart($this->lexer->peekNextToken())) { + $children[] = $this->real_ulong_number(); + $children[] = $this->match(MySQLLexer::DAY_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->match(MySQLLexer::DEFAULT_SYMBOL); + } else { + throw new \Exception( + 'Unexpected token in accountLockPasswordExpireOptions: ' . + $this->lexer->peekNextToken()->getText() + ); + } + } elseif ($this->serverVersion >= 80014 && $token->getType() === MySQLLexer::REQUIRE_SYMBOL) { + $children[] = $this->match(MySQLLexer::REQUIRE_SYMBOL); + $children[] = $this->match(MySQLLexer::CURRENT_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DEFAULT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::OPTIONAL_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->match(MySQLLexer::DEFAULT_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::OPTIONAL_SYMBOL); + } + } + } else { + throw new \Exception( + 'Unexpected token in accountLockPasswordExpireOptions: ' . $token->getText() + ); + } + } else { + throw new \Exception('Unexpected token in accountLockPasswordExpireOptions: ' . $token->getText()); + } + + return new ASTNode('accountLockPasswordExpireOptions', $children); + } + + public function dropUser() + { + $children = []; + + $children[] = $this->match(MySQLLexer::DROP_SYMBOL); + $children[] = $this->match(MySQLLexer::USER_SYMBOL); + if ($this->serverVersion >= 50706 && $this->lexer->peekNextToken()->getType() === MySQLLexer::IF_SYMBOL) { + $children[] = $this->ifExists(); + } + $children[] = $this->userList(); + + return new ASTNode('dropUser', $children); + } + + public function grant() + { + $children = []; + + $children[] = $this->match(MySQLLexer::GRANT_SYMBOL); + $token = $this->lexer->peekNextToken(); + + if ($this->serverVersion >= 80000 && + ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) && + $this->lexer->peekNextToken(2)->getType() !== MySQLLexer::ON_SYMBOL) { + $children[] = $this->roleOrPrivilegesList(); + $children[] = $this->match(MySQLLexer::TO_SYMBOL); + $children[] = $this->userList(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::WITH_SYMBOL) { + $children[] = $this->match(MySQLLexer::WITH_SYMBOL); + $children[] = $this->match(MySQLLexer::ADMIN_SYMBOL); + $children[] = $this->match(MySQLLexer::OPTION_SYMBOL); + } + } elseif ($token->getType() === MySQLLexer::SELECT_SYMBOL || + $token->getType() === MySQLLexer::INSERT_SYMBOL || + $token->getType() === MySQLLexer::UPDATE_SYMBOL || + $token->getType() === MySQLLexer::REFERENCES_SYMBOL || + ($this->serverVersion > 80000 && + ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT)) || + $token->getType() === MySQLLexer::DELETE_SYMBOL || + $token->getType() === MySQLLexer::USAGE_SYMBOL || + $token->getType() === MySQLLexer::INDEX_SYMBOL || + $token->getType() === MySQLLexer::DROP_SYMBOL || + $token->getType() === MySQLLexer::EXECUTE_SYMBOL || + $token->getType() === MySQLLexer::RELOAD_SYMBOL || + $token->getType() === MySQLLexer::SHUTDOWN_SYMBOL || + $token->getType() === MySQLLexer::PROCESS_SYMBOL || + $token->getType() === MySQLLexer::FILE_SYMBOL || + $token->getType() === MySQLLexer::PROXY_SYMBOL || + $token->getType() === MySQLLexer::SUPER_SYMBOL || + $token->getType() === MySQLLexer::EVENT_SYMBOL || + $token->getType() === MySQLLexer::TRIGGER_SYMBOL || + $token->getType() === MySQLLexer::CREATE_SYMBOL || + ($this->serverVersion < 80000 && $token->getType() === MySQLLexer::FUNCTION_SYMBOL) || + $token->getType() === MySQLLexer::LOCK_SYMBOL || + $token->getType() === MySQLLexer::REPLICATION_SYMBOL || + $token->getType() === MySQLLexer::SHOW_SYMBOL || + $token->getType() === MySQLLexer::ALTER_SYMBOL || + ($this->serverVersion > 80000 && + ($token->getType() === MySQLLexer::CREATE_SYMBOL || $token->getType() === MySQLLexer::DROP_SYMBOL)) || + $token->getType() === MySQLLexer::GRANT_SYMBOL || + $token->getType() === MySQLLexer::ALL_SYMBOL + ) { + if ($token->getType() === MySQLLexer::ALL_SYMBOL) { + $children[] = $this->match(MySQLLexer::ALL_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::PRIVILEGES_SYMBOL) { + $this->match(MySQLLexer::PRIVILEGES_SYMBOL); + $children[] = ASTNode::fromToken($token); + } + } else { + $children[] = $this->roleOrPrivilegesList(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ROUTINE_SYMBOL) { + $children[] = $this->match(MySQLLexer::ROUTINE_SYMBOL); + } + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::TABLE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::FUNCTION_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::PROCEDURE_SYMBOL) { + $children[] = $this->aclType(); + } + $children[] = $this->grantIdentifier(); + $children[] = $this->match(MySQLLexer::TO_SYMBOL); + $children[] = $this->grantTargetList(); + if ($this->serverVersion < 80011 && $this->lexer->peekNextToken()->getType() === MySQLLexer::REQUIRE_SYMBOL) { + $children[] = $this->versionedRequireClause(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::WITH_SYMBOL) { + $children[] = $this->grantOptions(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::AS_SYMBOL) { + $children[] = $this->grantAs(); + } + } elseif ($token->getType() === MySQLLexer::PROXY_SYMBOL) { + $children[] = $this->match(MySQLLexer::PROXY_SYMBOL); + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + $children[] = $this->user(); + $children[] = $this->match(MySQLLexer::TO_SYMBOL); + $children[] = $this->grantTargetList(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::WITH_SYMBOL) { + $children[] = $this->match(MySQLLexer::WITH_SYMBOL); + $children[] = $this->match(MySQLLexer::GRANT_SYMBOL); + $children[] = $this->match(MySQLLexer::OPTION_SYMBOL); + } + } else { + throw new \Exception('Unexpected token in grant: ' . $token->getText()); + } + + return new ASTNode('grant', $children); + } + + public function grantTargetList() + { + if ($this->serverVersion < 80011) { + return $this->createUserList(); + } else { + return $this->userList(); + } + } + + public function grantOptions() + { + $children = []; + + $children[] = $this->match(MySQLLexer::WITH_SYMBOL); + $token = $this->lexer->peekNextToken(2); + if ($this->serverVersion < 80011 && $token->getType() !== MySQLLexer::GRANT_SYMBOL) { + do { + $children[] = $this->grantOption(); + } while ($this->lexer->peekNextToken()->getType() === MySQLLexer::GRANT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::MAX_QUERIES_PER_HOUR_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::MAX_UPDATES_PER_HOUR_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::MAX_CONNECTIONS_PER_HOUR_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::MAX_USER_CONNECTIONS_SYMBOL); + } elseif ($token->getType() === MySQLLexer::GRANT_SYMBOL) { + $children[] = $this->match(MySQLLexer::GRANT_SYMBOL); + $children[] = $this->match(MySQLLexer::OPTION_SYMBOL); + } else { + throw new \Exception('Unexpected token in grantOptions: ' . $this->lexer->peekNextToken()->getText()); + } + + return new ASTNode('grantOptions', $children); + } + + public function exceptRoleList() + { + $children = []; + + $children[] = $this->match(MySQLLexer::EXCEPT_SYMBOL); + $children[] = $this->roleList(); + + return new ASTNode('exceptRoleList', $children); + } + + public function withRoles() + { + $children = []; + + $children[] = $this->match(MySQLLexer::WITH_SYMBOL); + $children[] = $this->match(MySQLLexer::ROLE_SYMBOL); + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + $children[] = $this->roleList(); + } elseif ($token->getType() === MySQLLexer::ALL_SYMBOL) { + $children[] = $this->match(MySQLLexer::ALL_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EXCEPT_SYMBOL) { + $children[] = $this->exceptRoleList(); + } + } elseif ($token->getType() === MySQLLexer::NONE_SYMBOL) { + $children[] = $this->match(MySQLLexer::NONE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->match(MySQLLexer::DEFAULT_SYMBOL); + } else { + throw new \Exception('Unexpected token in withRoles: ' . $token->getText()); + } + + return new ASTNode('withRoles', $children); + } + + public function grantAs() + { + $children = []; + + $children[] = $this->match(MySQLLexer::AS_SYMBOL); + $children[] = $this->match(MySQLLexer::USER_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::WITH_SYMBOL) { + $children[] = $this->withRoles(); + } + + return new ASTNode('grantAs', $children); + } + + public function versionedRequireClause() + { + return $this->requireClause(); + } + + public function renameUser() + { + $children = []; + + $children[] = $this->match(MySQLLexer::RENAME_SYMBOL); + $children[] = $this->match(MySQLLexer::USER_SYMBOL); + $children[] = $this->user(); + $children[] = $this->match(MySQLLexer::TO_SYMBOL); + $children[] = $this->user(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->user(); + $children[] = $this->match(MySQLLexer::TO_SYMBOL); + $children[] = $this->user(); + } + + return new ASTNode('renameUser', $children); + } + + public function revoke() + { + $children = []; + + $children[] = $this->match(MySQLLexer::REVOKE_SYMBOL); + + $token = $this->lexer->peekNextToken(); + if ($this->serverVersion >= 80000 && + ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) && + $this->lexer->peekNextToken(2)->getType() !== MySQLLexer::ON_SYMBOL) { + $children[] = $this->roleOrPrivilegesList(); + $children[] = $this->match(MySQLLexer::FROM_SYMBOL); + $children[] = $this->userList(); + } elseif (($token->getType() === MySQLLexer::SELECT_SYMBOL || + $token->getType() === MySQLLexer::INSERT_SYMBOL || + $token->getType() === MySQLLexer::UPDATE_SYMBOL || + $token->getType() === MySQLLexer::REFERENCES_SYMBOL || + ($this->serverVersion > 80000 && + ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT)) || + $token->getType() === MySQLLexer::DELETE_SYMBOL || + $token->getType() === MySQLLexer::USAGE_SYMBOL || + $token->getType() === MySQLLexer::INDEX_SYMBOL || + $token->getType() === MySQLLexer::DROP_SYMBOL || + $token->getType() === MySQLLexer::EXECUTE_SYMBOL || + $token->getType() === MySQLLexer::RELOAD_SYMBOL || + $token->getType() === MySQLLexer::SHUTDOWN_SYMBOL || + $token->getType() === MySQLLexer::PROCESS_SYMBOL || + $token->getType() === MySQLLexer::FILE_SYMBOL || + $token->getType() === MySQLLexer::PROXY_SYMBOL || + $token->getType() === MySQLLexer::SUPER_SYMBOL || + $token->getType() === MySQLLexer::EVENT_SYMBOL || + $token->getType() === MySQLLexer::TRIGGER_SYMBOL || + $token->getType() === MySQLLexer::CREATE_SYMBOL || + ($this->serverVersion < 80000 && + $token->getType() === MySQLLexer::FUNCTION_SYMBOL) || + $token->getType() === MySQLLexer::LOCK_SYMBOL || + $token->getType() === MySQLLexer::REPLICATION_SYMBOL || + $token->getType() === MySQLLexer::GRANT_SYMBOL || + $token->getType() === MySQLLexer::SHOW_SYMBOL || + ($this->serverVersion > 80000 && + ($token->getType() === MySQLLexer::CREATE_SYMBOL || + $token->getType() === MySQLLexer::DROP_SYMBOL)) || + $token->getType() === MySQLLexer::ALL_SYMBOL) && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::ON_SYMBOL) { + $children[] = $this->roleOrPrivilegesList(); + $children[] = $this->onTypeTo(); + $children[] = $this->match(MySQLLexer::FROM_SYMBOL); + $children[] = $this->userList(); + } elseif ($token->getType() === MySQLLexer::ALL_SYMBOL) { + $children[] = $this->match(MySQLLexer::ALL_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::PRIVILEGES_SYMBOL) { + $this->match(MySQLLexer::PRIVILEGES_SYMBOL); + $children[] = ASTNode::fromToken($token); + } + + if ($this->serverVersion >= 80000 && $this->lexer->peekNextToken()->getType() === MySQLLexer::ON_SYMBOL) { + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::TABLE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::FUNCTION_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::PROCEDURE_SYMBOL) { + $children[] = $this->aclType(); + } + $children[] = $this->grantIdentifier(); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->match(MySQLLexer::GRANT_SYMBOL); + $children[] = $this->match(MySQLLexer::OPTION_SYMBOL); + $children[] = $this->match(MySQLLexer::FROM_SYMBOL); + $children[] = $this->userList(); + } + } elseif ($token->getType() === MySQLLexer::PROXY_SYMBOL) { + $children[] = $this->match(MySQLLexer::PROXY_SYMBOL); + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + $children[] = $this->user(); + $children[] = $this->match(MySQLLexer::FROM_SYMBOL); + $children[] = $this->userList(); + } else { + throw new \Exception('Unexpected token in revoke: ' . $token->getText()); + } + + return new ASTNode('revoke', $children); + } + + public function onTypeTo() + { + $token1 = $this->lexer->peekNextToken(); + $token2 = $this->lexer->peekNextToken(2); + $children = []; + if ($token1->getType() === MySQLLexer::ON_SYMBOL) { + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::TABLE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::FUNCTION_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::PROCEDURE_SYMBOL) { + $children[] = $this->aclType(); + } + $children[] = $this->grantIdentifier(); + return new ASTNode('onTypeTo', $children); + } elseif ($this->serverVersion >= 80000 && + ($token1->getType() === MySQLLexer::TABLE_SYMBOL || + $token1->getType() === MySQLLexer::FUNCTION_SYMBOL || + $token1->getType() === MySQLLexer::PROCEDURE_SYMBOL || + $token1->getType() === MySQLLexer::MULT_OPERATOR || + $token1->getType() === MySQLLexer::IDENTIFIER || + $token1->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token1->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token1) || + $token1->getType() === MySQLLexer::DOT_SYMBOL)) { + if ($this->serverVersion >= 80000 && $this->lexer->peekNextToken()->getType() === MySQLLexer::ON_SYMBOL) { + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::TABLE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::FUNCTION_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::PROCEDURE_SYMBOL) { + $children[] = $this->aclType(); + } + $children[] = $this->grantIdentifier(); + return new ASTNode('onTypeTo', $children); + } elseif ($this->serverVersion < 80000) { + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::TABLE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::FUNCTION_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::PROCEDURE_SYMBOL) { + $children[] = $this->aclType(); + } + $children[] = $this->grantIdentifier(); + return new ASTNode('onTypeTo', $children); + } else { + throw new \Exception('Unexpected token in onTypeTo: ' . $token1->getText()); + } + } + + public function roleOrPrivilegesList() + { + $children = []; + + $children[] = $this->roleOrPrivilege(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->roleOrPrivilege(); + } + + return new ASTNode('roleOrPrivilegesList', $children); + } + + public function roleOrPrivilege() + { + $token1 = $this->lexer->peekNextToken(); + $token2 = $this->lexer->peekNextToken(2); + $children = []; + if (($token1->getType() === MySQLLexer::SELECT_SYMBOL || + $token1->getType() === MySQLLexer::INSERT_SYMBOL || + $token1->getType() === MySQLLexer::UPDATE_SYMBOL || + $token1->getType() === MySQLLexer::REFERENCES_SYMBOL)) { + if ($token1->getType() === MySQLLexer::SELECT_SYMBOL) { + $children[] = $this->match(MySQLLexer::SELECT_SYMBOL); + } elseif ($token1->getType() === MySQLLexer::INSERT_SYMBOL) { + $children[] = $this->match(MySQLLexer::INSERT_SYMBOL); + } elseif ($token1->getType() === MySQLLexer::UPDATE_SYMBOL) { + $children[] = $this->match(MySQLLexer::UPDATE_SYMBOL); + } elseif ($token1->getType() === MySQLLexer::REFERENCES_SYMBOL) { + $children[] = $this->match(MySQLLexer::REFERENCES_SYMBOL); + } else { + throw new \Exception('Unexpected token in roleOrPrivilege: ' . $token1->getText()); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children = $this->columnInternalRefList(); + } + + return new ASTNode('roleOrPrivilege', $children); + } elseif ($token1->getType() === MySQLLexer::DELETE_SYMBOL || + $token1->getType() === MySQLLexer::USAGE_SYMBOL || + $token1->getType() === MySQLLexer::INDEX_SYMBOL || + $token1->getType() === MySQLLexer::DROP_SYMBOL || + $token1->getType() === MySQLLexer::EXECUTE_SYMBOL || + $token1->getType() === MySQLLexer::RELOAD_SYMBOL || + $token1->getType() === MySQLLexer::SHUTDOWN_SYMBOL || + $token1->getType() === MySQLLexer::PROCESS_SYMBOL || + $token1->getType() === MySQLLexer::FILE_SYMBOL || + $token1->getType() === MySQLLexer::PROXY_SYMBOL || + $token1->getType() === MySQLLexer::SUPER_SYMBOL || + $token1->getType() === MySQLLexer::EVENT_SYMBOL || + $token1->getType() === MySQLLexer::TRIGGER_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + return new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + } elseif ($token1->getType() === MySQLLexer::GRANT_SYMBOL) { + $children[] = $this->match(MySQLLexer::GRANT_SYMBOL); + $children[] = $this->match(MySQLLexer::OPTION_SYMBOL); + return new ASTNode('roleOrPrivilege', $children); + } elseif ($token1->getType() === MySQLLexer::SHOW_SYMBOL && $token2->getType() === MySQLLexer::DATABASES_SYMBOL) { + $children[] = $this->match(MySQLLexer::SHOW_SYMBOL); + $children[] = $this->match(MySQLLexer::DATABASES_SYMBOL); + return new ASTNode('roleOrPrivilege', $children); + } elseif ($token1->getType() === MySQLLexer::SHOW_SYMBOL && $token2->getType() === MySQLLexer::VIEW_SYMBOL) { + $children[] = $this->match(MySQLLexer::SHOW_SYMBOL); + $children[] = $this->match(MySQLLexer::VIEW_SYMBOL); + return new ASTNode('roleOrPrivilege', $children); + } elseif ($token1->getType() === MySQLLexer::CREATE_SYMBOL) { + $children[] = $this->match(MySQLLexer::CREATE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::TEMPORARY_SYMBOL) { + $children[] = $this->match(MySQLLexer::TEMPORARY_SYMBOL); + $children[] = $this->match(MySQLLexer::TABLES_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::ROUTINE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::TABLESPACE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::USER_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::VIEW_SYMBOL) { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::ROUTINE_SYMBOL) { + $children[] = $this->match(MySQLLexer::ROUTINE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::TABLESPACE_SYMBOL) { + $children[] = $this->match(MySQLLexer::TABLESPACE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::USER_SYMBOL) { + $children[] = $this->match(MySQLLexer::USER_SYMBOL); + } elseif ($token->getType() === MySQLLexer::VIEW_SYMBOL) { + $children[] = $this->match(MySQLLexer::VIEW_SYMBOL); + } else { + throw new \Exception('Unexpected token in roleOrPrivilege: ' . $token->getText()); + } + } + return new ASTNode('roleOrPrivilege', $children); + } elseif ($token1->getType() === MySQLLexer::LOCK_SYMBOL) { + $children[] = $this->match(MySQLLexer::LOCK_SYMBOL); + $children[] = $this->match(MySQLLexer::TABLES_SYMBOL); + return new ASTNode('roleOrPrivilege', $children); + } elseif ($token1->getType() === MySQLLexer::REPLICATION_SYMBOL) { + $children[] = $this->match(MySQLLexer::REPLICATION_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::CLIENT_SYMBOL) { + $children[] = $this->match(MySQLLexer::CLIENT_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::SLAVE_SYMBOL) { + $children[] = $this->match(MySQLLexer::SLAVE_SYMBOL); + } else { + throw new \Exception('Unexpected token in roleOrPrivilege: ' . $this->lexer->peekNextToken()->getText()); + } + return new ASTNode('roleOrPrivilege', $children); + } elseif ($token1->getType() === MySQLLexer::ALTER_SYMBOL) { + $children[] = $this->match(MySQLLexer::ALTER_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ROUTINE_SYMBOL) { + $children[] = $this->match(MySQLLexer::ROUTINE_SYMBOL); + } + return new ASTNode('roleOrPrivilege', $children); + } elseif ($this->serverVersion > 80000 && + ($token1->getType() === MySQLLexer::CREATE_SYMBOL || + $token1->getType() === MySQLLexer::DROP_SYMBOL)) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::CREATE_SYMBOL) { + $children[] = $this->match(MySQLLexer::CREATE_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::DROP_SYMBOL); + } + $children[] = $this->match(MySQLLexer::ROLE_SYMBOL); + return new ASTNode('roleOrPrivilege', $children); + } elseif ($this->serverVersion > 80000 && + ($token1->getType() === MySQLLexer::IDENTIFIER || + $token1->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token1->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token1) || + $token1->getType() === MySQLLexer::SINGLE_QUOTED_TEXT)) { + $children[] = $this->roleIdentifierOrText(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->columnInternalRefList(); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::AT_TEXT_SUFFIX || + $this->lexer->peekNextToken()->getType() === MySQLLexer::AT_SIGN_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::AT_TEXT_SUFFIX) { + $children[] = $this->match(MySQLLexer::AT_TEXT_SUFFIX); + } else { + $children[] = $this->match(MySQLLexer::AT_SIGN_SYMBOL); + $children[] = $this->textOrIdentifier(); + } + } + + return new ASTNode('roleOrPrivilege', $children); + } else { + throw new \Exception('Unexpected token in roleOrPrivilege: ' . $token1->getText()); + } + } + + public function grantIdentifier() + { + $token1 = $this->lexer->peekNextToken(); + $token2 = $this->lexer->peekNextToken(2); + $children = []; + + if ($token1->getType() === MySQLLexer::MULT_OPERATOR) { + $children[] = $this->match(MySQLLexer::MULT_OPERATOR); + + if ($token2->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->match(MySQLLexer::DOT_SYMBOL); + $children[] = $this->match(MySQLLexer::MULT_OPERATOR); + } + + return new ASTNode('grantIdentifier', $children); + } elseif ($token1->getType() === MySQLLexer::IDENTIFIER || + $token1->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token1->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token1)) { + if ($this->serverVersion >= 80017 && $token2->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->schemaRef(); + $children[] = $this->match(MySQLLexer::DOT_SYMBOL); + $children[] = $this->tableRef(); + } else { + $children[] = $this->schemaRef(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->match(MySQLLexer::DOT_SYMBOL); + $children[] = $this->match(MySQLLexer::MULT_OPERATOR); + } + } + + return new ASTNode('grantIdentifier', $children); + } else { + throw new \Exception('Unexpected token in grantIdentifier: ' . $token1->getText()); + } + } + + public function requireList() + { + $children = []; + + $children[] = $this->requireListElement(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::AND_SYMBOL) { + $children[] = $this->match(MySQLLexer::AND_SYMBOL); + $children[] = $this->requireListElement(); + } + + return new ASTNode('requireList', $children); + } + + public function requireListElement() + { + $children = []; + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::CIPHER_SYMBOL) { + $children[] = $this->match(MySQLLexer::CIPHER_SYMBOL); + $children[] = $this->textString(); + } elseif ($token->getType() === MySQLLexer::ISSUER_SYMBOL) { + $children[] = $this->match(MySQLLexer::ISSUER_SYMBOL); + $children[] = $this->textString(); + } elseif ($token->getType() === MySQLLexer::SUBJECT_SYMBOL) { + $children[] = $this->match(MySQLLexer::SUBJECT_SYMBOL); + $children[] = $this->textString(); + } else { + throw new \Exception('Unexpected token in requireListElement: ' . $token->getText()); + } + return new ASTNode('requireListElement', $children); + } + + public function grantOption() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::GRANT_SYMBOL) { + $children[] = $this->match(MySQLLexer::GRANT_SYMBOL); + $children[] = $this->match(MySQLLexer::OPTION_SYMBOL); + } elseif ($token->getType() === MySQLLexer::MAX_QUERIES_PER_HOUR_SYMBOL) { + $children[] = $this->match(MySQLLexer::MAX_QUERIES_PER_HOUR_SYMBOL); + $children[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::MAX_UPDATES_PER_HOUR_SYMBOL) { + $children[] = $this->match(MySQLLexer::MAX_UPDATES_PER_HOUR_SYMBOL); + $children[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::MAX_CONNECTIONS_PER_HOUR_SYMBOL) { + $children[] = $this->match(MySQLLexer::MAX_CONNECTIONS_PER_HOUR_SYMBOL); + $children[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::MAX_USER_CONNECTIONS_SYMBOL) { + $children[] = $this->match(MySQLLexer::MAX_USER_CONNECTIONS_SYMBOL); + $children[] = $this->ulong_number(); + } else { + throw new \Exception('Unexpected token in grantOption: ' . $token->getText()); + } + + return new ASTNode('grantOption', $children); + } + + public function setRole() + { + $children = []; + + $children[] = $this->match(MySQLLexer::SET_SYMBOL); + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->match(MySQLLexer::DEFAULT_SYMBOL); + $children[] = $this->match(MySQLLexer::ROLE_SYMBOL); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + $children[] = $this->roleList(); + } elseif ($token->getType() === MySQLLexer::NONE_SYMBOL) { + $children[] = $this->match(MySQLLexer::NONE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::ALL_SYMBOL) { + $children[] = $this->match(MySQLLexer::ALL_SYMBOL); + } else { + throw new \Exception('Unexpected token in setRole: ' . $token->getText()); + } + } elseif ($token->getType() === MySQLLexer::ROLE_SYMBOL) { + $children[] = $this->match(MySQLLexer::ROLE_SYMBOL); + $token = $this->lexer->peekNextToken(); + if (($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) && + $this->lexer->peekNextToken(2)->getType() !== MySQLLexer::TO_SYMBOL) { + $children[] = $this->roleList(); + } elseif ($token->getType() === MySQLLexer::NONE_SYMBOL) { + $children[] = $this->match(MySQLLexer::NONE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->match(MySQLLexer::DEFAULT_SYMBOL); + } elseif ($token->getType() === MySQLLexer::ALL_SYMBOL) { + $children[] = $this->match(MySQLLexer::ALL_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EXCEPT_SYMBOL) { + $children[] = $this->exceptRoleList(); + } + } else { + throw new \Exception('Unexpected token in setRole: ' . $token->getText()); + } + } else { + throw new \Exception('Unexpected token in setRole: ' . $token->getText()); + } + + return new ASTNode('setRole', $children); + } + + public function roleList() + { + $children = []; + + $children[] = $this->role(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->role(); + } + + return new ASTNode('roleList', $children); + } + + public function role() + { + $children = []; + + $children[] = $this->roleIdentifierOrText(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::AT_SIGN_SYMBOL) { + $children[] = $this->match(MySQLLexer::AT_SIGN_SYMBOL); + $children[] = $this->textOrIdentifier(); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::AT_TEXT_SUFFIX) { + $children[] = $this->match(MySQLLexer::AT_TEXT_SUFFIX); + } + + return new ASTNode('role', $children); + } + + //---------------------------------------------------------------------------------------------------------------------- + + public function tableAdministrationStatement() + { + $children = []; + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::ANALYZE_SYMBOL) { + $children[] = $this->match(MySQLLexer::ANALYZE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LOCAL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NO_WRITE_TO_BINLOG_SYMBOL) { + $children[] = $this->noWriteToBinLog(); + } + $children[] = $this->match(MySQLLexer::TABLE_SYMBOL); + $children[] = $this->tableRefList(); + if ($this->serverVersion >= 80000 && + ($this->lexer->peekNextToken()->getType() === MySQLLexer::UPDATE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DROP_SYMBOL)) { + $children[] = $this->histogram(); + } + } elseif ($token->getType() === MySQLLexer::CHECK_SYMBOL) { + $children[] = $this->match(MySQLLexer::CHECK_SYMBOL); + $children[] = $this->match(MySQLLexer::TABLE_SYMBOL); + $children[] = $this->tableRefList(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::QUICK_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::FAST_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::MEDIUM_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::EXTENDED_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::CHANGED_SYMBOL) { + $children[] = $this->checkOption(); + } + } elseif ($token->getType() === MySQLLexer::CHECKSUM_SYMBOL) { + $children[] = $this->match(MySQLLexer::CHECKSUM_SYMBOL); + $children[] = $this->match(MySQLLexer::TABLE_SYMBOL); + $children[] = $this->tableRefList(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::QUICK_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::EXTENDED_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::QUICK_SYMBOL) { + $children[] = $this->match(MySQLLexer::QUICK_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::EXTENDED_SYMBOL); + } + } + } elseif ($token->getType() === MySQLLexer::OPTIMIZE_SYMBOL) { + $children[] = $this->match(MySQLLexer::OPTIMIZE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LOCAL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NO_WRITE_TO_BINLOG_SYMBOL) { + $children[] = $this->noWriteToBinLog(); + } + $children[] = $this->match(MySQLLexer::TABLE_SYMBOL); + $children[] = $this->tableRefList(); + } elseif ($token->getType() === MySQLLexer::REPAIR_SYMBOL) { + $children[] = $this->match(MySQLLexer::REPAIR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LOCAL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NO_WRITE_TO_BINLOG_SYMBOL) { + $children[] = $this->noWriteToBinLog(); + } + $children[] = $this->match(MySQLLexer::TABLE_SYMBOL); + $children[] = $this->tableRefList(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::QUICK_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::EXTENDED_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::USE_FRM_SYMBOL) { + $children[] = $this->repairType(); + } + } else { + throw new \Exception('Unexpected token in tableAdministrationStatement: ' . $token->getText()); + } + + return new ASTNode('tableAdministrationStatement', $children); + } + + public function histogram() + { + $token = $this->lexer->peekNextToken(); + $children = []; + if ($token->getType() === MySQLLexer::UPDATE_SYMBOL) { + $children[] = $this->match(MySQLLexer::UPDATE_SYMBOL); + $children[] = $this->match(MySQLLexer::HISTOGRAM_SYMBOL); + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + $children[] = $this->identifierList(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::WITH_SYMBOL) { + $children[] = $this->match(MySQLLexer::WITH_SYMBOL); + $children[] = $this->match(MySQLLexer::INT_NUMBER); + $children[] = $this->match(MySQLLexer::BUCKETS_SYMBOL); + } + } elseif ($token->getType() === MySQLLexer::DROP_SYMBOL) { + $children[] = $this->match(MySQLLexer::DROP_SYMBOL); + $children[] = $this->match(MySQLLexer::HISTOGRAM_SYMBOL); + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + $children[] = $this->identifierList(); + } else { + throw new \Exception('Unexpected token in histogram: ' . $token->getText()); + } + + return new ASTNode('histogram', $children); + } + + //---------------------------------------------------------------------------------------------------------------------- + + public function installUninstallStatment() + { + $children = []; + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::INSTALL_SYMBOL) { + $children[] = $this->match(MySQLLexer::INSTALL_SYMBOL); + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::PLUGIN_SYMBOL) { + $this->match(MySQLLexer::PLUGIN_SYMBOL); + $children[] = ASTNode::fromToken($token); + $children[] = $this->identifier(); + $children[] = $this->match(MySQLLexer::SONAME_SYMBOL); + $children[] = $this->textStringLiteral(); + } elseif ($token->getType() === MySQLLexer::COMPONENT_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMPONENT_SYMBOL); + $children[] = $this->textStringLiteralList(); + } else { + throw new \Exception('Unexpected token in installUninstallStatment: ' . $token->getText()); + } + } elseif ($token->getType() === MySQLLexer::UNINSTALL_SYMBOL) { + $children[] = $this->match(MySQLLexer::UNINSTALL_SYMBOL); + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::PLUGIN_SYMBOL) { + $this->match(MySQLLexer::PLUGIN_SYMBOL); + $children[] = ASTNode::fromToken($token); + $children[] = $this->pluginRef(); + } elseif ($token->getType() === MySQLLexer::COMPONENT_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMPONENT_SYMBOL); + $children[] = $this->componentRef(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->componentRef(); + } + } else { + throw new \Exception('Unexpected token in installUninstallStatment: ' . $token->getText()); + } + } else { + throw new \Exception('Unexpected token in installUninstallStatment: ' . $token->getText()); + } + + return new ASTNode('installUninstallStatment', $children); + } + + //---------------------------------------------------------------------------------------------------------------------- + + public function setStatement() + { + $children = []; + + $children[] = $this->match(MySQLLexer::SET_SYMBOL); + $children[] = $this->startOptionValueList(); + + return new ASTNode('setStatement', $children); + } + + public function startOptionValueList() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::TRANSACTION_SYMBOL) { + $this->match(MySQLLexer::TRANSACTION_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::TRANSACTION_SYMBOL)); + $children[] = $this->transactionCharacteristics(); + } elseif ($token->getType() === MySQLLexer::PASSWORD_SYMBOL) { + $this->match(MySQLLexer::PASSWORD_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::PASSWORD_SYMBOL)); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::FOR_SYMBOL)); + $children[] = $this->user(); + } + $children[] = $this->equal(); + $children[] = new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + $token = $this->lexer->peekNextToken(); + if ($this->serverVersion < 80014 && + ($token->getType() === MySQLLexer::OLD_PASSWORD_SYMBOL || + $token->getType() === MySQLLexer::PASSWORD_SYMBOL)) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OLD_PASSWORD_SYMBOL) { + $this->match(MySQLLexer::OLD_PASSWORD_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::OLD_PASSWORD_SYMBOL)); + } else { + $this->match(MySQLLexer::PASSWORD_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::PASSWORD_SYMBOL)); + } + $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::OPEN_PAR_SYMBOL)); + $children[] = $this->textString(); + $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::CLOSE_PAR_SYMBOL)); + } elseif ($this->isTextLiteralStart($token)) { + $children[] = $this->textString(); + if ($this->serverVersion >= 80014 && $this->lexer->peekNextToken()->getType() === MySQLLexer::REPLACE_SYMBOL) { + $children[] = $this->replacePassword(); + } + if ($this->serverVersion >= 80014 && $this->lexer->peekNextToken()->getType() === MySQLLexer::RETAIN_SYMBOL) { + $children[] = $this->retainCurrentPassword(); + } + } elseif ($this->serverVersion >= 80018 && $token->getType() === MySQLLexer::TO_SYMBOL) { + $this->match(MySQLLexer::TO_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::TO_SYMBOL)); + $this->match(MySQLLexer::RANDOM_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::RANDOM_SYMBOL)); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::REPLACE_SYMBOL) { + $children[] = $this->replacePassword(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::RETAIN_SYMBOL) { + $children[] = $this->retainCurrentPassword(); + } + } else { + throw new \Exception('Unexpected token in startOptionValueList: ' . $token->getText()); + } + } elseif ($this->isOptionValueStart($this->lexer->peekNextToken())) { + $children[] = $this->optionValue(); + $children[] = $this->optionValueListContinued(); + } else { + throw new \Exception('Unexpected token in startOptionValueList: ' . $token->getText()); + } + + return new ASTNode('startOptionValueList', $children); + } + + private function isOptionValueStart($token) + { + return ($token->getType() === MySQLLexer::GLOBAL_SYMBOL || + $token->getType() === MySQLLexer::LOCAL_SYMBOL || + $token->getType() === MySQLLexer::SESSION_SYMBOL || + ($this->serverVersion >= 80000 && + ($token->getType() === MySQLLexer::PERSIST_SYMBOL || + $token->getType() === MySQLLexer::PERSIST_ONLY_SYMBOL))) || + $this->isOptionValueNoOptionTypeStart($token); + } + + private function isOptionValueNoOptionTypeStart($token) + { + return $token->getType() === MySQLLexer::AT_SIGN_SYMBOL || + $token->getType() === MySQLLexer::AT_TEXT_SUFFIX || + $token->getType() === MySQLLexer::AT_AT_SIGN_SYMBOL || + $this->isInternalVariableNameStart($token) || + $token->getType() === MySQLLexer::CHARSET_SYMBOL || + $token->getType() === MySQLLexer::CHAR_SYMBOL || + $token->getType() === MySQLLexer::NAMES_SYMBOL; + } + + private function isInternalVariableNameStart($token) + { + return $token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::DOT_SYMBOL || + $token->getType() === MySQLLexer::DEFAULT_SYMBOL; + } + + public function transactionCharacteristics() + { + $children = []; + $token1 = $this->lexer->peekNextToken(); + $token2 = $this->lexer->peekNextToken(2); + + if ($token1->getType() === MySQLLexer::READ_SYMBOL && + ($token2->getType() === MySQLLexer::WRITE_SYMBOL || $token2->getType() === MySQLLexer::ONLY_SYMBOL)) { + $children[] = $this->transactionAccessMode(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ISOLATION_SYMBOL) { + $children[] = $this->isolationLevel(); + } + } elseif ($token1->getType() === MySQLLexer::ISOLATION_SYMBOL) { + $children[] = $this->isolationLevel(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->transactionAccessMode(); + } + } else { + throw new \Exception('Unexpected token in transactionCharacteristics: ' . $token1->getText()); + } + + return new ASTNode('transactionCharacteristics', $children); + } + + public function transactionAccessMode() + { + $children = []; + + $children[] = $this->match(MySQLLexer::READ_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::WRITE_SYMBOL) { + $children[] = $this->match(MySQLLexer::WRITE_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::ONLY_SYMBOL) { + $children[] = $this->match(MySQLLexer::ONLY_SYMBOL); + } else { + throw new \Exception('Unexpected token in transactionAccessMode: ' . $this->lexer->peekNextToken()->getText()); + } + + return new ASTNode('transactionAccessMode', $children); + } + + public function isolationLevel() + { + $children = []; + + $children[] = $this->match(MySQLLexer::ISOLATION_SYMBOL); + $children[] = $this->match(MySQLLexer::LEVEL_SYMBOL); + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::REPEATABLE_SYMBOL) { + $children[] = $this->match(MySQLLexer::REPEATABLE_SYMBOL); + $children[] = $this->match(MySQLLexer::READ_SYMBOL); + } elseif ($token->getType() === MySQLLexer::READ_SYMBOL) { + $children[] = $this->match(MySQLLexer::READ_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMITTED_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMITTED_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::UNCOMMITTED_SYMBOL) { + $children[] = $this->match(MySQLLexer::UNCOMMITTED_SYMBOL); + } else { + throw new \Exception('Unexpected token in isolationLevel: ' . $this->lexer->peekNextToken()->getText()); + } + } elseif ($token->getType() === MySQLLexer::SERIALIZABLE_SYMBOL) { + $children[] = $this->match(MySQLLexer::SERIALIZABLE_SYMBOL); + } else { + throw new \Exception('Unexpected token in isolationLevel: ' . $token->getText()); + } + + return new ASTNode('isolationLevel', $children); + } + + public function optionValueListContinued() + { + $children = []; + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->optionValue(); + } + return new ASTNode('optionValueListContinued', $children); + } + + public function optionValueNoOptionType() + { + $children = []; + $token1 = $this->lexer->peekNextToken(); + if (($token1->getType() === MySQLLexer::AT_SIGN_SYMBOL || + $token1->getType() === MySQLLexer::AT_TEXT_SUFFIX)) { + $children[] = $this->userVariable(); + $children[] = $this->equal(); + $children[] = $this->expr(); + } elseif ($token1->getType() === MySQLLexer::NAMES_SYMBOL) { + $children[] = $this->match(MySQLLexer::NAMES_SYMBOL); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::EQUAL_OPERATOR || + $token->getType() === MySQLLexer::ASSIGN_OPERATOR) { + $children[] = $this->equal(); + $children[] = $this->expr(); + } elseif ($this->isCharsetName($token)) { + $children[] = $this->charsetName(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COLLATE_SYMBOL) { + $children[] = $this->collate(); + } + } elseif ($this->serverVersion >= 80011 && $token->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->match(MySQLLexer::DEFAULT_SYMBOL); + } else { + throw new \Exception('Unexpected token in optionValueNoOptionType: ' . $token->getText()); + } + } elseif ($token1->getType() === MySQLLexer::CHARSET_SYMBOL || $token1->getType() === MySQLLexer::CHAR_SYMBOL) { + $children[] = $this->charsetClause(); + } elseif (($token1->getType() === MySQLLexer::AT_AT_SIGN_SYMBOL || + $token1->getType() === MySQLLexer::IDENTIFIER || + $token1->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token1->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token1) || + $token1->getType() === MySQLLexer::DOT_SYMBOL || + $token1->getType() === MySQLLexer::DEFAULT_SYMBOL)) { + $children[] = $this->setSystemVariable(); + $children[] = $this->equal(); + $children[] = $this->setExprOrDefault(); + } else { + $children[] = $this->internalVariableName(); + $children[] = $this->equal(); + $children[] = $this->setExprOrDefault(); + } + + return new ASTNode('optionValueNoOptionType', $children); + } + + public function optionValue() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::GLOBAL_SYMBOL || + $token->getType() === MySQLLexer::LOCAL_SYMBOL || + $token->getType() === MySQLLexer::SESSION_SYMBOL || + ($this->serverVersion >= 80000 && + ($token->getType() === MySQLLexer::PERSIST_SYMBOL || + $token->getType() === MySQLLexer::PERSIST_ONLY_SYMBOL))) { + $children = []; + $children[] = $this->optionType(); + $children[] = $this->internalVariableName(); + $children[] = $this->equal(); + $children[] = new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + $children[] = $this->setExprOrDefault(); + return new ASTNode('optionValue', $children); + } else { + return $this->optionValueNoOptionType(); + } + } + + public function setSystemVariable() + { + $children = []; + + if($this->lexer->peekNextToken()->getType() === MySQLLexer::AT_SIGN_SYMBOL) { + $children[] = $this->match(MySQLLexer::AT_SIGN_SYMBOL); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::GLOBAL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::LOCAL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::SESSION_SYMBOL || + ($this->serverVersion >= 80000 && + ($this->lexer->peekNextToken()->getType() === MySQLLexer::PERSIST_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::PERSIST_ONLY_SYMBOL))) { + $children[] = $this->setVarIdentType(); + } + + $children[] = $this->internalVariableName(); + return new ASTNode('setSystemVariable', $children); + } + + public function startOptionValueListFollowingOptionType() + { + $children = []; + + $children[] = $this->optionValueFollowingOptionType(); + $children[] = $this->optionValueListContinued(); + + return new ASTNode('startOptionValueListFollowingOptionType', $children); + } + + public function optionValueFollowingOptionType() + { + $children = []; + + $children[] = $this->internalVariableName(); + $children[] = $this->equal(); + $children[] = new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + $children[] = $this->setExprOrDefault(); + return new ASTNode('optionValueFollowingOptionType', $children); + } + + public function setExprOrDefault() + { + $token = $this->lexer->peekNextToken(); + + if ($this->isBoolPriStart($token)) { + return $this->expr(); + } elseif ($token->getType() === MySQLLexer::DEFAULT_SYMBOL || + $token->getType() === MySQLLexer::ON_SYMBOL || + $token->getType() === MySQLLexer::ALL_SYMBOL || + $token->getType() === MySQLLexer::BINARY_SYMBOL || + ($this->serverVersion >= 80000 && + ($token->getType() === MySQLLexer::ROW_SYMBOL || $token->getType() === MySQLLexer::SYSTEM_SYMBOL))) { + if ($token->getType() === MySQLLexer::ROW_SYMBOL) { + $this->match(MySQLLexer::ROW_SYMBOL); + $children = [ + new ASTNode(MySQLLexer::getTokenName(MySQLLexer::ROW_SYMBOL)), + ]; + return new ASTNode('setExprOrDefault', $children); + } elseif ($token->getType() === MySQLLexer::SYSTEM_SYMBOL) { + $this->match(MySQLLexer::SYSTEM_SYMBOL); + $children = [ + new ASTNode(MySQLLexer::getTokenName(MySQLLexer::SYSTEM_SYMBOL)), + ]; + return new ASTNode('setExprOrDefault', $children); + } else { + $this->match($this->lexer->peekNextToken()->getType()); + return new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + } + } else { + throw new \Exception('Unexpected token in setExprOrDefault: ' . $token->getText()); + } + } + + //---------------------------------------------------------------------------------------------------------------------- + public function showStatement() + { + $children = []; + + $children[] = $this->match(MySQLLexer::SHOW_SYMBOL); + + $token1 = $this->lexer->peekNextToken(); + $token2 = $this->lexer->peekNextToken(2); + $token3 = $this->lexer->peekNextToken(3); + + + if ($this->serverVersion < 50700 && $token1->getType() === MySQLLexer::AUTHORS_SYMBOL) { + $children[] = $this->match(MySQLLexer::AUTHORS_SYMBOL); + } elseif ($token1->getType() === MySQLLexer::BINARY_SYMBOL && $token2->getType() === MySQLLexer::LOGS_SYMBOL) { + $children[] = $this->match(MySQLLexer::BINARY_SYMBOL); + $children[] = $this->match(MySQLLexer::LOGS_SYMBOL); + } elseif ($token1->getType() === MySQLLexer::BINLOG_SYMBOL && $token2->getType() === MySQLLexer::EVENTS_SYMBOL) { + $children[] = $this->match(MySQLLexer::BINLOG_SYMBOL); + $children[] = $this->match(MySQLLexer::EVENTS_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IN_SYMBOL) { + $children[] = $this->match(MySQLLexer::IN_SYMBOL); + $children[] = $this->textString(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FROM_SYMBOL) { + $children[] = $this->match(MySQLLexer::FROM_SYMBOL); + $children[] = $this->ulonglong_number(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIMIT_SYMBOL) { + $children[] = $this->limitClause(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->channel(); + } + } elseif (($token1->getType() === MySQLLexer::CHARSET_SYMBOL || $token1->getType() === MySQLLexer::CHAR_SYMBOL) && + $token2->getType() !== MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->charset(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIKE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->likeOrWhere(); + } + } elseif ($token1->getType() === MySQLLexer::COLLATION_SYMBOL) { + $children[] = $this->match(MySQLLexer::COLLATION_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIKE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->likeOrWhere(); + } + } elseif ( + $token1->getType() === MySQLLexer::COLUMNS_SYMBOL || + ( + $this->isShowCommandType($token1, $token2) && + ( + $token2->getType() === MySQLLexer::COLUMNS_SYMBOL || + $token3->getType() === MySQLLexer::COLUMNS_SYMBOL + ) + ) + ) { + + if($this->isShowCommandType($token1, $token2)) { + $children[] = $this->showCommandType(); + } + $children[] = $this->match(MySQLLexer::COLUMNS_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FROM_SYMBOL) { + $children[] = $this->match(MySQLLexer::FROM_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::IN_SYMBOL); + } + + $children[] = $this->tableRef(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FROM_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IN_SYMBOL) { + $children[] = $this->inDb(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIKE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->likeOrWhere(); + } + } elseif ($token1->getType() === MySQLLexer::COMPONENT_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMPONENT_SYMBOL); + $children[] = $this->textStringLiteral(); + $children[] = $this->match(MySQLLexer::STATUS_SYMBOL); + } elseif ($this->serverVersion < 50700 && $token1->getType() === MySQLLexer::CONTRIBUTORS_SYMBOL) { + $children[] = $this->match(MySQLLexer::CONTRIBUTORS_SYMBOL); + } elseif ($token1->getType() === MySQLLexer::COUNT_SYMBOL && + $token2->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::COUNT_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->match(MySQLLexer::MULT_OPERATOR); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::WARNINGS_SYMBOL) { + $children[] = $this->match(MySQLLexer::WARNINGS_SYMBOL); + } elseif ($token->getType() === MySQLLexer::ERRORS_SYMBOL) { + $children[] = $this->match(MySQLLexer::ERRORS_SYMBOL); + } else { + throw new \Exception('Unexpected token in showStatement: ' . $token->getText()); + } + } elseif ($token1->getType() === MySQLLexer::CREATE_SYMBOL) { + $children[] = $this->match(MySQLLexer::CREATE_SYMBOL); + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::DATABASE_SYMBOL) { + $children[] = $this->match(MySQLLexer::DATABASE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IF_SYMBOL) { + $children[] = $this->ifNotExists(); + } + $children[] = $this->schemaRef(); + } elseif ($token->getType() === MySQLLexer::EVENT_SYMBOL) { + $children[] = $this->match(MySQLLexer::EVENT_SYMBOL); + $children[] = $this->eventRef(); + } elseif ( + ( + $this->serverVersion < 80000 && + $token->getType() === MySQLLexer::FUNCTION_SYMBOL + ) || + ( + $this->serverVersion >= 80000 && + $token->getType() === MySQLLexer::IDENTIFIER && + strtoupper($token->getText()) === 'FUNCTION' + ) + ) { + $children[] = ASTNode::fromToken($this->lexer->getNextToken()); + $children[] = $this->functionRef(); + } elseif ($token->getType() === MySQLLexer::PROCEDURE_SYMBOL) { + $children[] = $this->match(MySQLLexer::PROCEDURE_SYMBOL); + $children[] = $this->procedureRef(); + } elseif ($token->getType() === MySQLLexer::TABLE_SYMBOL) { + $children[] = $this->match(MySQLLexer::TABLE_SYMBOL); + $children[] = $this->tableRef(); + } elseif ($token->getType() === MySQLLexer::TRIGGER_SYMBOL) { + $children[] = $this->match(MySQLLexer::TRIGGER_SYMBOL); + $children[] = $this->triggerRef(); + } elseif ($this->serverVersion >= 50704 && $token->getType() === MySQLLexer::USER_SYMBOL) { + $children[] = $this->match(MySQLLexer::USER_SYMBOL); + $children[] = $this->user(); + } elseif ($token->getType() === MySQLLexer::VIEW_SYMBOL) { + $children[] = $this->match(MySQLLexer::VIEW_SYMBOL); + $children[] = $this->viewRef(); + } elseif ($token->getType() === MySQLLexer::ROLE_SYMBOL) { + $children[] = $this->match(MySQLLexer::ROLE_SYMBOL); + $children[] = $this->roleRef(); + } else if($token->getType() === MySQLLexer::INDEX_SYMBOL) { + $children[] = $this->match(MySQLLexer::INDEX_SYMBOL); + $children[] = $this->indexRef(); + } else if( + $this->serverVersion >= 80014 && + $token->getType() === MySQLLexer::TABLESPACE_SYMBOL + ) { + $children[] = $this->match(MySQLLexer::TABLESPACE_SYMBOL); + $children[] = $this->tablespaceRef(); + } else if($token->getType() === MySQLLexer::SPATIAL_SYMBOL) { + $children[] = $this->match(MySQLLexer::SPATIAL_SYMBOL); + $children[] = $this->match(MySQLLexer::REFERENCE_SYMBOL); + $children[] = $this->match(MySQLLexer::SYSTEM_SYMBOL); + $children[] = $this->real_ulonglong_number(); + } else { + throw new \Exception('Unexpected token in showStatement: ' . $token->getText()); + } + } elseif ($token1->getType() === MySQLLexer::DATABASES_SYMBOL) { + $children[] = $this->match(MySQLLexer::DATABASES_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIKE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->likeOrWhere(); + } + } elseif ($token1->getType() === MySQLLexer::ENGINE_SYMBOL) { + $children[] = $this->match(MySQLLexer::ENGINE_SYMBOL); + + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + $children[] = $this->engineRef(); + } elseif ($token->getType() === MySQLLexer::ALL_SYMBOL) { + $children[] = $this->match(MySQLLexer::ALL_SYMBOL); + } else { + throw new \Exception('Unexpected token in showStatement: ' . $token->getText()); + } + + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::STATUS_SYMBOL) { + $children[] = $this->match(MySQLLexer::STATUS_SYMBOL); + } elseif ($token->getType() === MySQLLexer::MUTEX_SYMBOL) { + $children[] = $this->match(MySQLLexer::MUTEX_SYMBOL); + } elseif ($token->getType() === MySQLLexer::LOGS_SYMBOL) { + $children[] = $this->match(MySQLLexer::LOGS_SYMBOL); + } else { + throw new \Exception('Unexpected token in showStatement: ' . $token->getText()); + } + } elseif ($token1->getType() === MySQLLexer::ERRORS_SYMBOL) { + $children[] = $this->match(MySQLLexer::ERRORS_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIMIT_SYMBOL) { + $children[] = $this->limitClause(); + } + } elseif ( + $token1->getType() === MySQLLexer::TRIGGERS_SYMBOL + || ( + $token1->getType() === MySQLLexer::FROM_SYMBOL || + $token2->getType() === MySQLLexer::TRIGGERS_SYMBOL + ) + ) { + if($this->isShowCommandType($token1, $token2)) { + $children[] = $this->showCommandType(); + } + $children[] = $this->match(MySQLLexer::TRIGGERS_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FROM_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IN_SYMBOL) { + $children[] = $this->inDb(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIKE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->likeOrWhere(); + } + } elseif ( + ( + $this->isShowCommandType($token1, $token2) && + ( + $token2->getType() === MySQLLexer::TABLES_SYMBOL || + $token3->getType() === MySQLLexer::TABLES_SYMBOL + ) + ) + || $token1->getType() === MySQLLexer::TABLES_SYMBOL + ) { + if($this->isShowCommandType($token1, $token2)) { + $children[] = $this->showCommandType(); + } + $children[] = $this->match(MySQLLexer::TABLES_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FROM_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IN_SYMBOL) { + $children[] = $this->inDb(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIKE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->likeOrWhere(); + } + } elseif ($token1->getType() === MySQLLexer::EVENTS_SYMBOL) { + $children[] = $this->match(MySQLLexer::EVENTS_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FROM_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IN_SYMBOL) { + $children[] = $this->inDb(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIKE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->likeOrWhere(); + } + } elseif ( + ( + $this->serverVersion >= 80000 && + $token1->getType() === MySQLLexer::EXTENDED_SYMBOL && ( + $token2->getType() === MySQLLexer::INDEX_SYMBOL || + $token2->getType() === MySQLLexer::INDEXES_SYMBOL || + $token2->getType() === MySQLLexer::KEYS_SYMBOL + ) + ) || + $token1->getType() === MySQLLexer::INDEX_SYMBOL || + $token1->getType() === MySQLLexer::INDEXES_SYMBOL || + $token1->getType() === MySQLLexer::KEYS_SYMBOL + ) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EXTENDED_SYMBOL) { + $children[] = $this->match(MySQLLexer::EXTENDED_SYMBOL); + } + + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::INDEX_SYMBOL) { + $children[] = $this->match(MySQLLexer::INDEX_SYMBOL); + } elseif ($token->getType() === MySQLLexer::INDEXES_SYMBOL) { + $children[] = $this->match(MySQLLexer::INDEXES_SYMBOL); + } elseif ($token->getType() === MySQLLexer::KEYS_SYMBOL) { + $children[] = $this->match(MySQLLexer::KEYS_SYMBOL); + } else { + throw new \Exception('Unexpected token in showStatement: ' . $token->getText()); + } + + $children[] = $this->fromOrIn(); + $children[] = $this->tableRef(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FROM_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IN_SYMBOL) { + $children[] = $this->inDb(); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->whereClause(); + } + } elseif ( + ($token1->getType() === MySQLLexer::FULL_SYMBOL && + $token2->getType() === MySQLLexer::PROCESSLIST_SYMBOL) + || $token1->getType() === MySQLLexer::PROCESSLIST_SYMBOL + ) { + if($token1->getType() === MySQLLexer::FULL_SYMBOL) { + $children[] = $this->match(MySQLLexer::FULL_SYMBOL); + } + $children[] = $this->match(MySQLLexer::PROCESSLIST_SYMBOL); + } elseif ($token1->getType() === MySQLLexer::FUNCTION_SYMBOL && + $token2->getType() === MySQLLexer::STATUS_SYMBOL) { + $children[] = $this->match(MySQLLexer::FUNCTION_SYMBOL); + $children[] = $this->match(MySQLLexer::STATUS_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIKE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->likeOrWhere(); + } + } elseif ($token1->getType() === MySQLLexer::FUNCTION_SYMBOL && + $token2->getType() === MySQLLexer::CODE_SYMBOL) { + $children[] = $this->match(MySQLLexer::FUNCTION_SYMBOL); + $children[] = $this->match(MySQLLexer::CODE_SYMBOL); + $children[] = $this->functionRef(); + } elseif ($token1->getType() === MySQLLexer::GRANTS_SYMBOL) { + $children[] = $this->match(MySQLLexer::GRANTS_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL && + $this->lexer->peekNextToken(2)->getType() !== MySQLLexer::USER_SYMBOL) { + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->user(); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->user(); + $children[] = $this->match(MySQLLexer::USING_SYMBOL); + $children[] = $this->userList(); + } + } elseif (($token1->getType() === MySQLLexer::GLOBAL_SYMBOL || + $token1->getType() === MySQLLexer::LOCAL_SYMBOL || + $token1->getType() === MySQLLexer::SESSION_SYMBOL || + ($this->serverVersion >= 80000 && + ($token1->getType() === MySQLLexer::PERSIST_SYMBOL || + $token1->getType() === MySQLLexer::PERSIST_ONLY_SYMBOL))) && + ($token2->getType() === MySQLLexer::STATUS_SYMBOL || + $token2->getType() === MySQLLexer::VARIABLES_SYMBOL)) { + $children[] = $this->optionType(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::STATUS_SYMBOL) { + $children[] = $this->match(MySQLLexer::STATUS_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::VARIABLES_SYMBOL) { + $children[] = $this->match(MySQLLexer::VARIABLES_SYMBOL); + } else { + throw new \Exception('Unexpected token in showStatement: ' . $this->lexer->peekNextToken()->getText()); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIKE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->likeOrWhere(); + } + } elseif ($token1->getType() === MySQLLexer::MASTER_SYMBOL && + $token2->getType() === MySQLLexer::STATUS_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_SYMBOL); + $children[] = $this->match(MySQLLexer::STATUS_SYMBOL); + if ($this->serverVersion >= 50700 && $this->serverVersion < 50706 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::NONBLOCKING_SYMBOL) { + $children[] = $this->match(MySQLLexer::NONBLOCKING_SYMBOL); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->channel(); + } + } elseif ($token1->getType() === MySQLLexer::MASTER_SYMBOL && $token2->getType() === MySQLLexer::LOGS_SYMBOL) { + $children[] = $this->match(MySQLLexer::MASTER_SYMBOL); + $children[] = $this->match(MySQLLexer::LOGS_SYMBOL); + } elseif ($token1->getType() === MySQLLexer::OPEN_SYMBOL && $token2->getType() === MySQLLexer::TABLES_SYMBOL) { + $children[] = $this->match(MySQLLexer::OPEN_SYMBOL); + $children[] = $this->match(MySQLLexer::TABLES_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FROM_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IN_SYMBOL) { + $children[] = $this->inDb(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIKE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->likeOrWhere(); + } + } elseif ($token1->getType() === MySQLLexer::PLUGINS_SYMBOL) { + $children[] = $this->match(MySQLLexer::PLUGINS_SYMBOL); + } elseif ($token1->getType() === MySQLLexer::PROCEDURE_SYMBOL && + $token2->getType() === MySQLLexer::CODE_SYMBOL) { + $children[] = $this->match(MySQLLexer::PROCEDURE_SYMBOL); + $children[] = $this->match(MySQLLexer::CODE_SYMBOL); + $children[] = $this->procedureRef(); + } elseif ($token1->getType() === MySQLLexer::PROCEDURE_SYMBOL && + $token2->getType() === MySQLLexer::STATUS_SYMBOL) { + $children[] = $this->match(MySQLLexer::PROCEDURE_SYMBOL); + $children[] = $this->match(MySQLLexer::STATUS_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIKE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->likeOrWhere(); + } + } elseif ($token1->getType() === MySQLLexer::PROFILE_SYMBOL) { + $children[] = $this->match(MySQLLexer::PROFILE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ALL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BLOCK_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::CONTEXT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::CPU_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IPC_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::MEMORY_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::PAGE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::SOURCE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::SWAPS_SYMBOL) { + $children[] = $this->profileType(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->profileType(); + } + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->match(MySQLLexer::QUERY_SYMBOL); + $children[] = $this->match(MySQLLexer::INT_NUMBER); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIMIT_SYMBOL) { + $children[] = $this->limitClause(); + } + } elseif ($token1->getType() === MySQLLexer::PROFILES_SYMBOL) { + $children[] = $this->match(MySQLLexer::PROFILES_SYMBOL); + } elseif ($token1->getType() === MySQLLexer::RELAYLOG_SYMBOL && $token2->getType() === MySQLLexer::EVENTS_SYMBOL) { + $children[] = $this->match(MySQLLexer::RELAYLOG_SYMBOL); + $children[] = $this->match(MySQLLexer::EVENTS_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IN_SYMBOL) { + $children[] = $this->match(MySQLLexer::IN_SYMBOL); + $children[] = $this->textString(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FROM_SYMBOL) { + $children[] = $this->match(MySQLLexer::FROM_SYMBOL); + $children[] = $this->ulonglong_number(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIMIT_SYMBOL) { + $children[] = $this->limitClause(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->channel(); + } + } elseif ($token1->getType() === MySQLLexer::REPLICA_SYMBOL || + $token1->getType() === MySQLLexer::SOURCE_SYMBOL) { + if ($token1->getType() === MySQLLexer::REPLICA_SYMBOL) { + $children[] = $this->match(MySQLLexer::REPLICA_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::SOURCE_SYMBOL); + } + + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::STATUS_SYMBOL) { + $children[] = $this->match(MySQLLexer::STATUS_SYMBOL); + } elseif ($token->getType() === MySQLLexer::HOSTS_SYMBOL) { + $children[] = $this->match(MySQLLexer::HOSTS_SYMBOL); + } else { + throw new \Exception('Unexpected token in showStatement: ' . $token->getText()); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->channel(); + } + } elseif ($token1->getType() === MySQLLexer::SLAVE_SYMBOL) { + $children[] = $this->match(MySQLLexer::SLAVE_SYMBOL); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::HOSTS_SYMBOL) { + $children[] = $this->match(MySQLLexer::HOSTS_SYMBOL); + } elseif ($token->getType() === MySQLLexer::STATUS_SYMBOL) { + $children[] = $this->match(MySQLLexer::STATUS_SYMBOL); + if ($this->serverVersion >= 50700 && $this->serverVersion < 50706) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::NONBLOCKING_SYMBOL) { + $children[] = $this->nonBlocking(); + } + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->channel(); + } + } else { + throw new \Exception('Unexpected token in showStatement: ' . $token->getText()); + } + } elseif ( + $token1->getType() === MySQLLexer::ENGINES_SYMBOL || ( + $token1->getType() === MySQLLexer::STORAGE_SYMBOL && + $token2->getType() === MySQLLexer::ENGINES_SYMBOL + ) + ) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::STORAGE_SYMBOL) { + $children[] = $this->match(MySQLLexer::STORAGE_SYMBOL); + } + $children[] = $this->match(MySQLLexer::ENGINES_SYMBOL); + } elseif ( + $token1->getType() === MySQLLexer::TABLE_SYMBOL && + $token2->getType() === MySQLLexer::STATUS_SYMBOL + ) { + $children[] = $this->match(MySQLLexer::TABLE_SYMBOL); + $children[] = $this->match(MySQLLexer::STATUS_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FROM_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IN_SYMBOL) { + $children[] = $this->inDb(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIKE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->likeOrWhere(); + } + } elseif ( + (($token1->getType() === MySQLLexer::EXTENDED_SYMBOL || + $token1->getType() === MySQLLexer::FULL_SYMBOL) && + $token2->getType() === MySQLLexer::TABLES_SYMBOL) + || $token1->getType() === MySQLLexer::TABLES_SYMBOL + ) { + $children[] = $this->showCommandType(); + $children[] = $this->match(MySQLLexer::TABLES_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FROM_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IN_SYMBOL) { + $children[] = $this->inDb(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIKE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->likeOrWhere(); + } + } elseif ($token1->getType() === MySQLLexer::TRIGGERS_SYMBOL) { + $children[] = $this->match(MySQLLexer::TRIGGERS_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FROM_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IN_SYMBOL) { + $children[] = $this->inDb(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIKE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->likeOrWhere(); + } + } elseif ($token1->getType() === MySQLLexer::WARNINGS_SYMBOL) { + $children[] = $this->match(MySQLLexer::WARNINGS_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIMIT_SYMBOL) { + $children[] = $this->limitClause(); + } + } elseif ($token1->getType() === MySQLLexer::STATUS_SYMBOL || + $token1->getType() === MySQLLexer::VARIABLES_SYMBOL) { + if ($token1->getType() === MySQLLexer::STATUS_SYMBOL) { + $children[] = $this->match(MySQLLexer::STATUS_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::VARIABLES_SYMBOL); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIKE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + $children[] = $this->likeOrWhere(); + } + } elseif ($token1->getType() === MySQLLexer::PRIVILEGES_SYMBOL) { + $children[] = $this->match(MySQLLexer::PRIVILEGES_SYMBOL); + } elseif ($token1->getType() === MySQLLexer::CONSTRAINTS_SYMBOL || + $token1->getType() === MySQLLexer::INDEXES_SYMBOL || + $token1->getType() === MySQLLexer::KEYS_SYMBOL) { + if ($token1->getType() === MySQLLexer::CONSTRAINTS_SYMBOL) { + $children[] = $this->match(MySQLLexer::CONSTRAINTS_SYMBOL); + } elseif ($token1->getType() === MySQLLexer::INDEXES_SYMBOL) { + $children[] = $this->match(MySQLLexer::INDEXES_SYMBOL); + } elseif ($token1->getType() === MySQLLexer::KEYS_SYMBOL) { + $children[] = $this->match(MySQLLexer::KEYS_SYMBOL); + } else { + throw new \Exception('Unexpected token in showStatement: ' . $token1->getText()); + } + $children[] = $this->match(MySQLLexer::FROM_SYMBOL); + $children[] = $this->tableRef(); + } else { + throw new \Exception('Unexpected token in showStatement: ' . $token1->getText()); + } + + return new ASTNode('showStatement', $children); + } + + public function showCommandType() + { + $token = $this->lexer->peekNextToken(); + $children = []; + if ($token->getType() === MySQLLexer::EXTENDED_SYMBOL) { + $children[] = $this->match(MySQLLexer::EXTENDED_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FULL_SYMBOL) { + $children[] = $this->match(MySQLLexer::FULL_SYMBOL); + } + } elseif ($token->getType() === MySQLLexer::FULL_SYMBOL) { + $children[] = $this->match(MySQLLexer::FULL_SYMBOL); + if ($this->serverVersion >= 80000 && $this->lexer->peekNextToken()->getType() === MySQLLexer::EXTENDED_SYMBOL) { + $children[] = $this->match(MySQLLexer::EXTENDED_SYMBOL); + } + } else { + throw new \Exception('Unexpected token in showCommandType: ' . $token->getText()); + } + return new ASTNode('showCommandType', $children); + } + + public function nonBlocking() + { + return $this->match(MySQLLexer::NONBLOCKING_SYMBOL); + } + + public function isShowCommandType($token1, $token2) + { + if($token1->getType() === MySQLLexer::FULL_SYMBOL){ + return true; + } + if($this->serverVersion >= 80000 && $token1->getType() === MySQLLexer::EXTENDED_SYMBOL){ + return true; + } + } + + public function fromOrIn() +{ + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::FROM_SYMBOL: + case MySQLLexer::IN_SYMBOL: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in indexType: ' . $token->getText()); + } +} + + public function inDb() + { + $children = []; + + $children[] = $this->fromOrIn(); + $children[] = $this->identifier(); + + return new ASTNode('inDb', $children); + } + + public function profileType() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::BLOCK_SYMBOL) { + $this->match(MySQLLexer::BLOCK_SYMBOL); + $children = [ + new ASTNode(MySQLLexer::getTokenName(MySQLLexer::BLOCK_SYMBOL)), + ]; + $children[] = $this->match(MySQLLexer::IO_SYMBOL); + } elseif ($token->getType() === MySQLLexer::CONTEXT_SYMBOL) { + $this->match(MySQLLexer::CONTEXT_SYMBOL); + $children = [ + new ASTNode(MySQLLexer::getTokenName(MySQLLexer::CONTEXT_SYMBOL)), + ]; + $children[] = $this->match(MySQLLexer::SWITCHES_SYMBOL); + } elseif ($token->getType() === MySQLLexer::PAGE_SYMBOL) { + $this->match(MySQLLexer::PAGE_SYMBOL); + $children = [ + new ASTNode(MySQLLexer::getTokenName(MySQLLexer::PAGE_SYMBOL)), + ]; + $children[] = $this->match(MySQLLexer::FAULTS_SYMBOL); + } elseif ($token->getType() === MySQLLexer::ALL_SYMBOL || + $token->getType() === MySQLLexer::CPU_SYMBOL || + $token->getType() === MySQLLexer::IPC_SYMBOL || + $token->getType() === MySQLLexer::MEMORY_SYMBOL || + $token->getType() === MySQLLexer::SOURCE_SYMBOL || + $token->getType() === MySQLLexer::SWAPS_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + $children = [new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType()))]; + } else { + throw new \Exception('Unexpected token in profileType: ' . $token->getText()); + } + + return new ASTNode('profileType', $children); + } + + //---------------------------------------------------------------------------------------------------------------------- + + public function otherAdministrativeStatement() + { + $children = []; + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::BINLOG_SYMBOL) { + $children[] = $this->match(MySQLLexer::BINLOG_SYMBOL); + $children[] = $this->textLiteral(); + } elseif ($token->getType() === MySQLLexer::CACHE_SYMBOL) { + $children[] = $this->match(MySQLLexer::CACHE_SYMBOL); + $children[] = $this->match(MySQLLexer::INDEX_SYMBOL); + $children[] = $this->keyCacheListOrParts(); + $children[] = $this->match(MySQLLexer::IN_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + $children[] = $this->identifier(); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->match(MySQLLexer::DEFAULT_SYMBOL); + } else { + throw new \Exception('Unexpected token in otherAdministrativeStatement: ' . $this->lexer->peekNextToken()->getText()); + } + } elseif ($token->getType() === MySQLLexer::FLUSH_SYMBOL) { + $children[] = $this->match(MySQLLexer::FLUSH_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LOCAL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NO_WRITE_TO_BINLOG_SYMBOL) { + $children[] = $this->noWriteToBinLog(); + } + + $token = $this->lexer->peekNextToken(); + if (($token->getType() === MySQLLexer::TABLES_SYMBOL || + $token->getType() === MySQLLexer::TABLE_SYMBOL)) { + $children[] = $this->flushTables(); + } elseif ($this->isFlushOptionStart($token)) { + $children[] = $this->flushOption(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->flushOption(); + } + } else { + throw new \Exception('Unexpected token in otherAdministrativeStatement: ' . $token->getText()); + } + } elseif ($token->getType() === MySQLLexer::KILL_SYMBOL) { + $children[] = $this->match(MySQLLexer::KILL_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::CONNECTION_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::QUERY_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::CONNECTION_SYMBOL) { + $children[] = $this->match(MySQLLexer::CONNECTION_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::QUERY_SYMBOL); + } + } + + $children[] = $this->expr(); + } elseif ($token->getType() === MySQLLexer::LOAD_SYMBOL) { + $children[] = $this->match(MySQLLexer::LOAD_SYMBOL); + $children[] = $this->match(MySQLLexer::INDEX_SYMBOL); + $children[] = $this->match(MySQLLexer::INTO_SYMBOL); + $children[] = $this->match(MySQLLexer::CACHE_SYMBOL); + $children[] = $this->preloadTail(); + } elseif ($token->getType() === MySQLLexer::SHUTDOWN_SYMBOL) { + $children[] = $this->match(MySQLLexer::SHUTDOWN_SYMBOL); + } else { + throw new \Exception('Unexpected token in otherAdministrativeStatement: ' . $token->getText()); + } + + return new ASTNode('otherAdministrativeStatement', $children); + } + + private function isFlushOptionStart($token) + { + return $token->getType() === MySQLLexer::DES_KEY_FILE_SYMBOL || + $token->getType() === MySQLLexer::HOSTS_SYMBOL || + $token->getType() === MySQLLexer::LOGS_SYMBOL || + ($this->serverVersion < 80000 && $token->getType() === MySQLLexer::QUERY_SYMBOL) || + $token->getType() === MySQLLexer::PRIVILEGES_SYMBOL || + ($this->serverVersion >= 50706 && $token->getType() === MySQLLexer::OPTIMIZER_COSTS_SYMBOL) || + $token->getType() === MySQLLexer::RELAY_SYMBOL || + ($token->getType() === MySQLLexer::BINARY_SYMBOL && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::LOGS_SYMBOL) || + ($token->getType() === MySQLLexer::ENGINE_SYMBOL && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::LOGS_SYMBOL) || + ($token->getType() === MySQLLexer::ERROR_SYMBOL && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::LOGS_SYMBOL) || + ($token->getType() === MySQLLexer::GENERAL_SYMBOL && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::LOGS_SYMBOL) || + ($token->getType() === MySQLLexer::SLOW_SYMBOL && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::LOGS_SYMBOL) || + $token->getType() === MySQLLexer::STATUS_SYMBOL || + $token->getType() === MySQLLexer::USER_RESOURCES_SYMBOL; + } + + public function keyCacheListOrParts() + { + if ($this->lexer->peekNextToken(2)->getType() === MySQLLexer::PARTITION_SYMBOL) { + return $this->assignToKeycachePartition(); + } else { + return $this->keyCacheList(); + } + } + + public function keyCacheList() + { + $children = []; + + $children[] = $this->assignToKeycache(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->assignToKeycache(); + } + + return new ASTNode('keyCacheList', $children); + } + + public function assignToKeycache() + { + $children = []; + + $children[] = $this->tableRef(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INDEX_SYMBOL) { + $children[] = $this->cacheKeyList(); + } + + return new ASTNode('assignToKeycache', $children); + } + + public function assignToKeycachePartition() + { + $children = []; + + $children[] = $this->tableRef(); + $children[] = $this->match(MySQLLexer::PARTITION_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->allOrPartitionNameList(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INDEX_SYMBOL) { + $children[] = $this->cacheKeyList(); + } + + return new ASTNode('assignToKeycachePartition', $children); + } + + public function cacheKeyList() + { + $children = []; + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::KEY_SYMBOL) { + $children[] = $this->match(MySQLLexer::KEY_SYMBOL); + } elseif ($token->getType() === MySQLLexer::INDEX_SYMBOL) { + $children[] = $this->match(MySQLLexer::INDEX_SYMBOL); + } else { + throw new \Exception('Unexpected token in cacheKeyList: ' . $token->getText()); + } + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken()) || + $this->lexer->peekNextToken()->getType() === MySQLLexer::PRIMARY_SYMBOL) { + $children[] = $this->keyUsageList(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + + return new ASTNode('cacheKeyList', $children); + } + + public function keyUsageList() + { + $children = []; + + $children[] = $this->keyUsageElement(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->keyUsageElement(); + } + + return new ASTNode('keyUsageList', $children); + } + + public function keyUsageElement() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token)) { + return $this->identifier(); + } elseif ($token->getType() === MySQLLexer::PRIMARY_SYMBOL) { + return $this->match(MySQLLexer::PRIMARY_SYMBOL); + } else { + throw new \Exception('Unexpected token in keyUsageElement: ' . $token->getText()); + } + } + + public function flushOption() + { + $children = []; + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::DES_KEY_FILE_SYMBOL) { + $children[] = $this->match(MySQLLexer::DES_KEY_FILE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::HOSTS_SYMBOL) { + $children[] = $this->match(MySQLLexer::HOSTS_SYMBOL); + } elseif ($token->getType() === MySQLLexer::LOGS_SYMBOL) { + $children[] = $this->match(MySQLLexer::LOGS_SYMBOL); + } elseif ($this->serverVersion < 80000 && $token->getType() === MySQLLexer::QUERY_SYMBOL) { + $children[] = $this->match(MySQLLexer::QUERY_SYMBOL); + $children[] = $this->match(MySQLLexer::CACHE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::PRIVILEGES_SYMBOL) { + $this->match(MySQLLexer::PRIVILEGES_SYMBOL); + $children[] = ASTNode::fromToken($token); + } elseif ($this->serverVersion >= 50706 && $token->getType() === MySQLLexer::OPTIMIZER_COSTS_SYMBOL) { + $children[] = $this->match(MySQLLexer::OPTIMIZER_COSTS_SYMBOL); + } elseif ($token->getType() === MySQLLexer::RELAY_SYMBOL) { + $children[] = $this->match(MySQLLexer::RELAY_SYMBOL); + $children[] = $this->match(MySQLLexer::LOGS_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->channel(); + } + } elseif (($token->getType() === MySQLLexer::BINARY_SYMBOL || + $token->getType() === MySQLLexer::ENGINE_SYMBOL || + $token->getType() === MySQLLexer::ERROR_SYMBOL || + $token->getType() === MySQLLexer::GENERAL_SYMBOL || + $token->getType() === MySQLLexer::SLOW_SYMBOL) && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::LOGS_SYMBOL) { + if ($token->getType() === MySQLLexer::BINARY_SYMBOL) { + $children[] = $this->match(MySQLLexer::BINARY_SYMBOL); + } elseif ($token->getType() === MySQLLexer::ENGINE_SYMBOL) { + $children[] = $this->match(MySQLLexer::ENGINE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::ERROR_SYMBOL) { + $children[] = $this->match(MySQLLexer::ERROR_SYMBOL); + } elseif ($token->getType() === MySQLLexer::GENERAL_SYMBOL) { + $children[] = $this->match(MySQLLexer::GENERAL_SYMBOL); + } elseif ($token->getType() === MySQLLexer::SLOW_SYMBOL) { + $children[] = $this->match(MySQLLexer::SLOW_SYMBOL); + } else { + throw new \Exception('Unexpected token in flushOption: ' . $token->getText()); + } + $children[] = $this->match(MySQLLexer::LOGS_SYMBOL); + } elseif ($token->getType() === MySQLLexer::STATUS_SYMBOL) { + $children[] = $this->match(MySQLLexer::STATUS_SYMBOL); + } elseif ($token->getType() === MySQLLexer::USER_RESOURCES_SYMBOL) { + $children[] = $this->match(MySQLLexer::USER_RESOURCES_SYMBOL); + } else { + throw new \Exception('Unexpected token in flushOption: ' . $token->getText()); + } + + return new ASTNode('flushOption', $children); + } + + public function flushTables() + { + $children = []; + + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::TABLES_SYMBOL) { + $children[] = $this->match(MySQLLexer::TABLES_SYMBOL); + } elseif ($token->getType() === MySQLLexer::TABLE_SYMBOL) { + $children[] = $this->match(MySQLLexer::TABLE_SYMBOL); + } else { + throw new \Exception('Unexpected token in flushTables: ' . $token->getText()); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::WITH_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::WITH_SYMBOL) { + $children[] = $this->match(MySQLLexer::WITH_SYMBOL); + $children[] = $this->match(MySQLLexer::READ_SYMBOL); + $children[] = $this->match(MySQLLexer::LOCK_SYMBOL); + } else { + $children[] = $this->identifierList(); + if ($this->serverVersion >= 50606 && + ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WITH_SYMBOL)) { + $children[] = $this->flushTablesOptions(); + } + } + } + + return new ASTNode('flushTables', $children); + } + + public function preloadTail() + { + $token = $this->lexer->peekNextToken(); + $children = []; + if ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->tableRef(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::PARTITION_SYMBOL) { + $children[] = $this->adminPartition(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INDEX_SYMBOL) { + $children[] = $this->cacheKeyList(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IGNORE_SYMBOL) { + $children[] = $this->match(MySQLLexer::IGNORE_SYMBOL); + $children[] = $this->match(MySQLLexer::LEAVES_SYMBOL); + } + } else { + $children[] = $this->preloadList(); + } + return new ASTNode('preloadTail', $children); + } + + public function preloadList() + { + $children = []; + + $children[] = $this->preloadKeys(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->preloadKeys(); + } + + return new ASTNode('preloadList', $children); + } + + public function preloadKeys() + { + $children = []; + $children[] = $this->tableRef(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INDEX_SYMBOL) { + $children[] = $this->cacheKeyList(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IGNORE_SYMBOL) { + $children[] = $this->match(MySQLLexer::IGNORE_SYMBOL); + $children[] = $this->match(MySQLLexer::LEAVES_SYMBOL); + } + return new ASTNode('preloadKeys', $children); + } + + public function adminPartition() + { + $children = []; + + $children[] = $this->match(MySQLLexer::PARTITION_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->allOrPartitionNameList(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + + return new ASTNode('adminPartition', $children); + } + + //---------------------------------------------------------------------------------------------------------------------- + + public function resourceGroupManagement() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::CREATE_SYMBOL) { + return $this->createResourceGroup(); + } elseif ($token->getType() === MySQLLexer::ALTER_SYMBOL) { + return $this->alterResourceGroup(); + } elseif ($token->getType() === MySQLLexer::SET_SYMBOL) { + return $this->setResourceGroup(); + } elseif ($token->getType() === MySQLLexer::DROP_SYMBOL) { + return $this->dropResourceGroup(); + } else { + throw new \Exception('Unexpected token in resourceGroupManagement: ' . $token->getText()); + } + } + + public function createResourceGroup() + { + $children = []; + + $children[] = $this->match(MySQLLexer::CREATE_SYMBOL); + $children[] = $this->match(MySQLLexer::RESOURCE_SYMBOL); + $children[] = $this->match(MySQLLexer::GROUP_SYMBOL); + $children[] = $this->identifier(); + $children[] = $this->match(MySQLLexer::TYPE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ASSIGN_OPERATOR) { + $children[] = $this->equal(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::USER_SYMBOL) { + $children[] = $this->match(MySQLLexer::USER_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::SYSTEM_SYMBOL) { + $children[] = $this->match(MySQLLexer::SYSTEM_SYMBOL); + } else { + throw new \Exception( + 'Unexpected token in createResourceGroup: ' . $this->lexer->peekNextToken()->getText() + ); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::VCPU_SYMBOL) { + $children[] = $this->resourceGroupVcpuList(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::THREAD_PRIORITY_SYMBOL) { + $children[] = $this->resourceGroupPriority(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ENABLE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DISABLE_SYMBOL) { + $children[] = $this->resourceGroupEnableDisable(); + } + + return new ASTNode('createResourceGroup', $children); + } + + public function resourceGroupVcpuList() + { + $children = []; + + $children[] = $this->match(MySQLLexer::VCPU_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ASSIGN_OPERATOR) { + $children[] = $this->equal(); + } + + $children[] = $this->vcpuNumOrRange(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->vcpuNumOrRange(); + } + return new ASTNode('resourceGroupVcpuList', $children); + } + + public function vcpuNumOrRange() + { + $children = []; + + $children[] = $this->match(MySQLLexer::INT_NUMBER); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::MINUS_OPERATOR) { + $children[] = $this->match(MySQLLexer::MINUS_OPERATOR); + $children[] = $this->match(MySQLLexer::INT_NUMBER); + } + return new ASTNode('vcpuNumOrRange', $children); + } + + public function resourceGroupPriority() + { + $children = []; + $children[] = $this->match(MySQLLexer::THREAD_PRIORITY_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ASSIGN_OPERATOR) { + $children[] = $this->equal(); + } + $children[] = $this->match(MySQLLexer::INT_NUMBER); + return new ASTNode('resourceGroupPriority', $children); + } + + public function resourceGroupEnableDisable() + { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ENABLE_SYMBOL) { + return $this->match(MySQLLexer::ENABLE_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::DISABLE_SYMBOL) { + return $this->match(MySQLLexer::DISABLE_SYMBOL); + } else { + throw new \Exception( + 'Unexpected token in resourceGroupEnableDisable: ' . $this->lexer->peekNextToken()->getText() + ); + } + } + + public function alterResourceGroup() + { + $children = []; + + $children[] = $this->match(MySQLLexer::ALTER_SYMBOL); + $children[] = $this->match(MySQLLexer::RESOURCE_SYMBOL); + $children[] = $this->match(MySQLLexer::GROUP_SYMBOL); + $children[] = $this->resourceGroupRef(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::VCPU_SYMBOL) { + $children[] = $this->resourceGroupVcpuList(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::THREAD_PRIORITY_SYMBOL) { + $children[] = $this->resourceGroupPriority(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ENABLE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DISABLE_SYMBOL) { + $children[] = $this->resourceGroupEnableDisable(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FORCE_SYMBOL) { + $children[] = $this->match(MySQLLexer::FORCE_SYMBOL); + } + return new ASTNode('alterResourceGroup', $children); + } + + public function setResourceGroup() + { + $children = []; + + $children[] = $this->match(MySQLLexer::SET_SYMBOL); + $children[] = $this->match(MySQLLexer::RESOURCE_SYMBOL); + $children[] = $this->match(MySQLLexer::GROUP_SYMBOL); + $children[] = $this->identifier(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->threadIdList(); + } + + return new ASTNode('setResourceGroup', $children); + } + + public function threadIdList() + { + $children = []; + $children[] = $this->real_ulong_number(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->real_ulong_number(); + } + return new ASTNode('threadIdList', $children); + } + + public function dropResourceGroup() + { + $children = []; + + $children[] = $this->match(MySQLLexer::DROP_SYMBOL); + $children[] = $this->match(MySQLLexer::RESOURCE_SYMBOL); + $children[] = $this->match(MySQLLexer::GROUP_SYMBOL); + $children[] = $this->resourceGroupRef(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::FORCE_SYMBOL) { + $children[] = $this->match(MySQLLexer::FORCE_SYMBOL); + } + return new ASTNode('dropResourceGroup', $children); + } + + //---------------------------------------------------------------------------------------------------------------------- + + public function utilityStatement() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::EXPLAIN_SYMBOL || + $token->getType() === MySQLLexer::DESCRIBE_SYMBOL || + $token->getType() === MySQLLexer::DESC_SYMBOL) { + return $this->explainStatement(); + } elseif ($token->getType() === MySQLLexer::HELP_SYMBOL) { + return $this->helpCommand(); + } elseif ($token->getType() === MySQLLexer::USE_SYMBOL) { + return $this->useCommand(); + } elseif ($this->serverVersion >= 80011 && $token->getType() === MySQLLexer::RESTART_SYMBOL) { + return $this->restartServer(); + } else { + throw new \Exception('Unexpected token in utilityStatement: ' . $token->getText()); + } + } + + public function describeStatement() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::DESCRIBE_SYMBOL) { + $children[] = $this->match(MySQLLexer::DESCRIBE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::DESC_SYMBOL) { + $children[] = $this->match(MySQLLexer::DESC_SYMBOL); + } elseif ($token->getType() === MySQLLexer::EXPLAIN_SYMBOL) { + $children[] = $this->match(MySQLLexer::EXPLAIN_SYMBOL); + } else { + throw new \Exception('Unexpected token in describeStatement: ' . $token->getText()); + } + + $children[] = $this->tableRef(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + $children[] = $this->textString(); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken()) || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->columnRef(); + } + return new ASTNode('describeStatement', $children); + } + + public function explainStatement() + { + $children = []; + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::DESCRIBE_SYMBOL) { + $children[] = $this->match(MySQLLexer::DESCRIBE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::DESC_SYMBOL) { + $children[] = $this->match(MySQLLexer::DESC_SYMBOL); + } elseif ($token->getType() === MySQLLexer::EXPLAIN_SYMBOL) { + $children[] = $this->match(MySQLLexer::EXPLAIN_SYMBOL); + } else { + throw new \Exception('Unexpected token in explainStatement: ' . $token->getText()); + } + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::EXTENDED_SYMBOL || + ($this->serverVersion < 80000 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::PARTITIONS_SYMBOL) || + $this->lexer->peekNextToken()->getType() === MySQLLexer::FORMAT_SYMBOL || + ($this->serverVersion >= 80018 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::ANALYZE_SYMBOL)) { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::EXTENDED_SYMBOL) { + $children[] = $this->match(MySQLLexer::EXTENDED_SYMBOL); + } elseif ($this->serverVersion < 80000 && $token->getType() === MySQLLexer::PARTITIONS_SYMBOL) { + $children[] = $this->match(MySQLLexer::PARTITIONS_SYMBOL); + } elseif ($this->serverVersion >= 50605 && $token->getType() === MySQLLexer::FORMAT_SYMBOL) { + $children[] = $this->match(MySQLLexer::FORMAT_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textOrIdentifier(); + } elseif ($this->serverVersion >= 80018 && $token->getType() === MySQLLexer::ANALYZE_SYMBOL && + $this->lexer->peekNextToken(2)->getType() !== MySQLLexer::FORMAT_SYMBOL) { + $children[] = $this->match(MySQLLexer::ANALYZE_SYMBOL); + } elseif ($this->serverVersion >= 80019 && $token->getType() === MySQLLexer::ANALYZE_SYMBOL) { + $children[] = $this->match(MySQLLexer::ANALYZE_SYMBOL); + $children[] = $this->match(MySQLLexer::FORMAT_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->textOrIdentifier(); + } else { + throw new \Exception('Unexpected token in explainStatement: ' . $token->getText()); + } + } + + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::SELECT_SYMBOL || + $token->getType() === MySQLLexer::WITH_SYMBOL || + $token->getType() === MySQLLexer::OPEN_PAR_SYMBOL || + ($this->serverVersion >= 50603 && + ($token->getType() === MySQLLexer::DELETE_SYMBOL || + $token->getType() === MySQLLexer::INSERT_SYMBOL || + $token->getType() === MySQLLexer::REPLACE_SYMBOL || + $token->getType() === MySQLLexer::UPDATE_SYMBOL))) { + $children[] = $this->explainableStatement(); + } elseif ($this->serverVersion >= 50700 && $token->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->match(MySQLLexer::CONNECTION_SYMBOL); + $children[] = $this->real_ulong_number(); + } else { + throw new \Exception('Unexpected token in explainStatement: ' . $token->getText()); + } + + return new ASTNode('explainStatement', $children); + } + + // Before server version 5.6 only select statements were explainable. + public function explainableStatement() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::SELECT_SYMBOL || + $token->getType() === MySQLLexer::WITH_SYMBOL || + $token->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + return $this->selectStatement(); + } elseif ($this->serverVersion >= 50603 && + ($token->getType() === MySQLLexer::DELETE_SYMBOL || + $token->getType() === MySQLLexer::INSERT_SYMBOL || + $token->getType() === MySQLLexer::REPLACE_SYMBOL || + $token->getType() === MySQLLexer::UPDATE_SYMBOL)) { + if ($token->getType() === MySQLLexer::DELETE_SYMBOL) { + return $this->deleteStatement(); + } elseif ($token->getType() === MySQLLexer::INSERT_SYMBOL) { + return $this->insertStatement(); + } elseif ($token->getType() === MySQLLexer::REPLACE_SYMBOL) { + return $this->replaceStatement(); + } elseif ($token->getType() === MySQLLexer::UPDATE_SYMBOL) { + return $this->updateStatement(); + } else { + throw new \Exception('Unexpected token in explainableStatement: ' . $token->getText()); + } + } elseif ($this->serverVersion >= 50700 && $token->getType() === MySQLLexer::FOR_SYMBOL) { + $children = []; + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->match(MySQLLexer::CONNECTION_SYMBOL); + $children[] = $this->real_ulong_number(); + return new ASTNode('explainableStatement', $children); + } else { + throw new \Exception('Unexpected token in explainableStatement: ' . $token->getText()); + } + } + + public function helpCommand() + { + $children = []; + + $children[] = $this->match(MySQLLexer::HELP_SYMBOL); + $children[] = $this->textOrIdentifier(); + + return new ASTNode('helpCommand', $children); + } + + public function useCommand() + { + $children = []; + + $children[] = $this->match(MySQLLexer::USE_SYMBOL); + $children[] = $this->identifier(); + + return new ASTNode('useCommand', $children); + } + + public function restartServer() + { + return $this->match(MySQLLexer::RESTART_SYMBOL); + } + + //----------------- Expression support --------------------------------------------------------------------------------- + + public function expr() + { + $children = []; + $token = $this->lexer->peekNextToken(); + if($this->isBoolPriStart($token)) { + $children[] = $this->boolPri(); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::IS_SYMBOL) { + $children[] = $this->match(MySQLLexer::IS_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::NOT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NOT2_SYMBOL) { + $children[] = $this->notRule(); + } + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::TRUE_SYMBOL: + case MySQLLexer::FALSE_SYMBOL: + case MySQLLexer::UNKNOWN_SYMBOL: + $children[] = ASTNode::fromToken($this->lexer->getNextToken()); + break; + default: + throw new \Exception('Unexpected token in expr: ' . $token->getText()); + } + } + + if ($token->getType() === MySQLLexer::AND_SYMBOL || + $token->getType() === MySQLLexer::LOGICAL_AND_OPERATOR || + $token->getType() === MySQLLexer::XOR_SYMBOL || + $token->getType() === MySQLLexer::OR_SYMBOL || + $token->getType() === MySQLLexer::LOGICAL_OR_OPERATOR + ) { + $children[] = ASTNode::fromToken($this->lexer->getNextToken()); + $children[] = $this->expr(); + } + } elseif ($token->getType() === MySQLLexer::NOT_SYMBOL) { + $children[] = $this->notRule(); + $children[] = $this->expr(); + } else { + throw new \Exception('Unexpected token in expr: ' . $token->getText()); + } + + return new ASTNode('expr', $children); + } + + private function isCompoundStatementStart($token) + { + return $this->isSimpleStatementStart($token) || + $token->getType() === MySQLLexer::RETURN_SYMBOL || + $token->getType() === MySQLLexer::DECLARE_SYMBOL || + $token->getType() === MySQLLexer::IF_SYMBOL || + $token->getType() === MySQLLexer::CASE_SYMBOL || + $token->getType() === MySQLLexer::BEGIN_SYMBOL || + $token->getType() === MySQLLexer::LOOP_SYMBOL || + $token->getType() === MySQLLexer::REPEAT_SYMBOL || + $token->getType() === MySQLLexer::WHILE_SYMBOL || + $token->getType() === MySQLLexer::LEAVE_SYMBOL || + $token->getType() === MySQLLexer::ITERATE_SYMBOL; + } + + public function elseStatement() + { + $this->match(MySQLLexer::ELSE_SYMBOL); + $children = [new ASTNode(MySQLLexer::getTokenName(MySQLLexer::ELSE_SYMBOL)), $this->compoundStatementList()]; + return new ASTNode('elseStatement', $children); + } + + public function indexTypeClause() + { + $children = []; + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::USING_SYMBOL) { + $this->match(MySQLLexer::USING_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::USING_SYMBOL)); + } else { + $this->match(MySQLLexer::TYPE_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::TYPE_SYMBOL)); + } + + $children[] = $this->indexType(); + + return new ASTNode('indexTypeClause', $children); + } + + public function visibility() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::VISIBLE_SYMBOL) { + return $this->match(MySQLLexer::VISIBLE_SYMBOL); + } else { + return $this->match(MySQLLexer::INVISIBLE_SYMBOL); + } + } + + public function systemVariable() + { + $children = []; + + $this->match(MySQLLexer::AT_AT_SIGN_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::AT_AT_SIGN_SYMBOL)); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::GLOBAL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::LOCAL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::SESSION_SYMBOL) { + $children[] = $this->setVarIdentType(); + } + $children[] = $this->textOrIdentifier(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->dotIdentifier(); + } + return new ASTNode('systemVariable', $children); + } + + public function windowFunctionCall() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::ROW_NUMBER_SYMBOL || + $token->getType() === MySQLLexer::RANK_SYMBOL || + $token->getType() === MySQLLexer::DENSE_RANK_SYMBOL || + $token->getType() === MySQLLexer::CUME_DIST_SYMBOL || + $token->getType() === MySQLLexer::PERCENT_RANK_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + $children[] = new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + $children[] = $this->parentheses(); + } elseif ($token->getType() === MySQLLexer::NTILE_SYMBOL) { + $this->match(MySQLLexer::NTILE_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::NTILE_SYMBOL)); + $children[] = $this->simpleExprWithParentheses(); + } elseif ($token->getType() === MySQLLexer::LEAD_SYMBOL || + $token->getType() === MySQLLexer::LAG_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + $children[] = new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::OPEN_PAR_SYMBOL)); + $children[] = $this->expr(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->leadLagInfo(); + } + $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::CLOSE_PAR_SYMBOL)); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::RESPECT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::IGNORE_SYMBOL) { + $children[] = $this->nullTreatment(); + } + } else { + throw new \Exception('Unexpected token in windowFunctionCall: ' . $token->getText()); + } + $children[] = $this->windowingClause(); + return new ASTNode('windowFunctionCall', $children); + } + + public function sumExpr() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::AVG_SYMBOL || + $token->getType() === MySQLLexer::BIT_AND_SYMBOL || + $token->getType() === MySQLLexer::BIT_OR_SYMBOL || + $token->getType() === MySQLLexer::BIT_XOR_SYMBOL || + $token->getType() === MySQLLexer::COUNT_SYMBOL || + $token->getType() === MySQLLexer::MAX_SYMBOL || + $token->getType() === MySQLLexer::MIN_SYMBOL || + $token->getType() === MySQLLexer::STD_SYMBOL || + $token->getType() === MySQLLexer::SUM_SYMBOL || + $token->getType() === MySQLLexer::VARIANCE_SYMBOL || + $token->getType() === MySQLLexer::STDDEV_POP_SYMBOL || + $token->getType() === MySQLLexer::VAR_POP_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + $children[] = new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::OPEN_PAR_SYMBOL)); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DISTINCT_SYMBOL) { + $this->match(MySQLLexer::DISTINCT_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::DISTINCT_SYMBOL)); + } + $children[] = $this->expr(); + $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::CLOSE_PAR_SYMBOL)); + } elseif ($token->getType() === MySQLLexer::STDDEV_SAMP_SYMBOL || + $token->getType() === MySQLLexer::VAR_SAMP_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + $children[] = new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::OPEN_PAR_SYMBOL)); + $children[] = $this->expr(); + $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::CLOSE_PAR_SYMBOL)); + } elseif ($token->getType() === MySQLLexer::GROUP_CONCAT_SYMBOL) { + $this->match(MySQLLexer::GROUP_CONCAT_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::GROUP_CONCAT_SYMBOL)); + $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::OPEN_PAR_SYMBOL)); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DISTINCT_SYMBOL) { + $this->match(MySQLLexer::DISTINCT_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::DISTINCT_SYMBOL)); + } + $children[] = $this->exprList(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ORDER_SYMBOL) { + $children[] = $this->orderClause(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::SEPARATOR_SYMBOL) { + $this->match(MySQLLexer::SEPARATOR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::SEPARATOR_SYMBOL)); + $children[] = $this->textLiteral(); + } + $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::CLOSE_PAR_SYMBOL)); + } else { + throw new \Exception('Unexpected token in sumExpr: ' . $token->getText()); + } + if ($this->serverVersion >= 80000 && $this->lexer->peekNextToken()->getType() === MySQLLexer::OVER_SYMBOL) { + $children[] = $this->windowingClause(); + } + return new ASTNode('columnRefOrLiteral', $children); + } + + public function leadLagInfo() + { + $children = []; + + $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::COMMA_SYMBOL)); + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::ULONGLONG_NUMBER) { + $this->match(MySQLLexer::ULONGLONG_NUMBER); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::ULONGLONG_NUMBER)); + } elseif ($token->getType() === MySQLLexer::PARAM_MARKER) { + $this->match(MySQLLexer::PARAM_MARKER); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::PARAM_MARKER)); + } else { + throw new \Exception('Unexpected token in leadLagInfo: ' . $token->getText()); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::COMMA_SYMBOL)); + $children[] = $this->expr(); + } + + return new ASTNode('leadLagInfo', $children); + } + + public function nullTreatment() + { + $children = []; + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::RESPECT_SYMBOL) { + $this->match(MySQLLexer::RESPECT_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::RESPECT_SYMBOL)); + } else { + $this->match(MySQLLexer::IGNORE_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::IGNORE_SYMBOL)); + } + $this->match(MySQLLexer::NULLS_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::NULLS_SYMBOL)); + return new ASTNode('nullTreatment', $children); + } + + public function windowingClause() + { + $children = []; + $this->match(MySQLLexer::OVER_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::OVER_SYMBOL)); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->windowSpec(); + } else { + $children[] = $this->windowName(); + } + return new ASTNode('windowingClause', $children); + } + + public function boolPri() + { + $children = []; + $children[] = $this->predicate(); + $token = $this->lexer->peekNextToken(); + while ($token->getType() === MySQLLexer::IS_SYMBOL || + $this->isCompOp($token) || + ($this->serverVersion >= 80017 && $token->getType() === MySQLLexer::MEMBER_SYMBOL) || + $token->getType() === MySQLLexer::SOUNDS_SYMBOL) { + if ($token->getType() === MySQLLexer::IS_SYMBOL) { + $children[] = $this->match(MySQLLexer::IS_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::NOT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NOT2_SYMBOL) { + $children[] = $this->notRule(); + } + $children[] = $this->match(MySQLLexer::NULL_SYMBOL); + } elseif ($this->isCompOp($token)) { + $this->compOp(); + $children[] = new ASTNode(MySQLLexer::getTokenName($token->getType())); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ALL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ANY_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ALL_SYMBOL) { + $children[] = $this->match(MySQLLexer::ALL_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::ANY_SYMBOL); + } + $children[] = $this->subquery(); + } else { + $children[] = $this->predicate(); + } + } elseif ($this->serverVersion >= 80017 && $token->getType() === MySQLLexer::MEMBER_SYMBOL) { + $children[] = $this->match(MySQLLexer::MEMBER_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OF_SYMBOL) { + $children[] = $this->match(MySQLLexer::OF_SYMBOL); + } + $children[] = $this->simpleExprWithParentheses(); + } elseif ($token->getType() === MySQLLexer::SOUNDS_SYMBOL) { + $children[] = $this->match(MySQLLexer::SOUNDS_SYMBOL); + $children[] = $this->match(MySQLLexer::LIKE_SYMBOL); + $children[] = $this->bitExpr(); + } else { + throw new \Exception('Unexpected token in boolPri: ' . $token->getText()); + } + $token = $this->lexer->peekNextToken(); + } + return new ASTNode('boolPri', $children); + } + + public function compOp() + { + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::EQUAL_OPERATOR: + case MySQLLexer::NULL_SAFE_EQUAL_OPERATOR: + case MySQLLexer::GREATER_OR_EQUAL_OPERATOR: + case MySQLLexer::GREATER_THAN_OPERATOR: + case MySQLLexer::LESS_OR_EQUAL_OPERATOR: + case MySQLLexer::LESS_THAN_OPERATOR: + case MySQLLexer::NOT_EQUAL_OPERATOR: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in compOp: ' . $token->getText()); + } + } + + public function predicate() + { + $children = []; + $children[] = $this->bitExpr(); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::NOT_SYMBOL || + $token->getType() === MySQLLexer::NOT2_SYMBOL || + $token->getType() === MySQLLexer::IN_SYMBOL || + $token->getType() === MySQLLexer::BETWEEN_SYMBOL || + $token->getType() === MySQLLexer::LIKE_SYMBOL || + $token->getType() === MySQLLexer::REGEXP_SYMBOL || + ($this->serverVersion >= 80017 && $token->getType() === MySQLLexer::MEMBER_SYMBOL) || + $token->getType() === MySQLLexer::SOUNDS_SYMBOL) { + if ($token->getType() === MySQLLexer::NOT_SYMBOL || + $token->getType() === MySQLLexer::NOT2_SYMBOL || + $token->getType() === MySQLLexer::IN_SYMBOL || + $token->getType() === MySQLLexer::BETWEEN_SYMBOL || + $token->getType() === MySQLLexer::LIKE_SYMBOL || + $token->getType() === MySQLLexer::REGEXP_SYMBOL) { + if ($token->getType() === MySQLLexer::NOT_SYMBOL || $token->getType() === MySQLLexer::NOT2_SYMBOL) { + $children[] = $this->notRule(); + } + $children[] = $this->predicateOperations(); + } elseif ($this->serverVersion >= 80017 && $token->getType() === MySQLLexer::MEMBER_SYMBOL) { + $children[] = $this->match(MySQLLexer::MEMBER_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OF_SYMBOL) { + $children[] = $this->match(MySQLLexer::OF_SYMBOL); + } + $children[] = $this->simpleExprWithParentheses(); + } elseif ($token->getType() === MySQLLexer::SOUNDS_SYMBOL) { + $children[] = $this->match(MySQLLexer::SOUNDS_SYMBOL); + $children[] = $this->match(MySQLLexer::LIKE_SYMBOL); + $children[] = $this->bitExpr(); + } else { + throw new \Exception('Unexpected token in predicate: ' . $token->getText()); + } + } + + return new ASTNode('predicate', $children); + } + + public function predicateOperations() + { + $token = $this->lexer->peekNextToken(); + $children = []; + if ($token->getType() === MySQLLexer::IN_SYMBOL) { + $children[] = $this->match(MySQLLexer::IN_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL && + ($this->lexer->peekNextToken(2)->getType() === MySQLLexer::SELECT_SYMBOL || + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::WITH_SYMBOL || + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::OPEN_PAR_SYMBOL)) { + $children[] = $this->subquery(); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->exprList(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } else { + throw new \Exception('Unexpected token in predicateOperations: ' . $this->lexer->peekNextToken()->getText()); + } + return new ASTNode('predicateOperations', $children); + } elseif ($token->getType() === MySQLLexer::BETWEEN_SYMBOL) { + $children[] = $this->match(MySQLLexer::BETWEEN_SYMBOL); + $children[] = $this->bitExpr(); + $children[] = $this->match(MySQLLexer::AND_SYMBOL); + $children[] = $this->predicate(); + return new ASTNode('predicateOperations', $children); + } elseif ($token->getType() === MySQLLexer::LIKE_SYMBOL) { + $children[] = $this->match(MySQLLexer::LIKE_SYMBOL); + $children[] = $this->simpleExpr(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ESCAPE_SYMBOL) { + $children[] = $this->match(MySQLLexer::ESCAPE_SYMBOL); + $children[] = $this->simpleExpr(); + } + return new ASTNode('predicateOperations', $children); + } elseif ($token->getType() === MySQLLexer::REGEXP_SYMBOL) { + $children[] = $this->match(MySQLLexer::REGEXP_SYMBOL); + $children[] = $this->bitExpr(); + return new ASTNode('predicateOperations', $children); + } else { + throw new \Exception('Unexpected token in predicateOperations: ' . $token->getText()); + } + } + + public function bitExpr() + { + $children = []; + $children[] = $this->simpleExpr(); + $token = $this->lexer->peekNextToken(); + + while ( + $token->getType() === MySQLLexer::BITWISE_XOR_OPERATOR || + $token->getType() === MySQLLexer::MULT_OPERATOR || + $token->getType() === MySQLLexer::DIV_OPERATOR || + $token->getType() === MySQLLexer::MOD_OPERATOR || + $token->getType() === MySQLLexer::DIV_SYMBOL || + $token->getType() === MySQLLexer::MOD_SYMBOL || + $token->getType() === MySQLLexer::PLUS_OPERATOR || + $token->getType() === MySQLLexer::MINUS_OPERATOR || + $token->getType() === MySQLLexer::SHIFT_LEFT_OPERATOR || + $token->getType() === MySQLLexer::SHIFT_RIGHT_OPERATOR || + $token->getType() === MySQLLexer::BITWISE_AND_OPERATOR || + $token->getType() === MySQLLexer::BITWISE_OR_OPERATOR + ) { + if ($this->lexer->peekNextToken(2)->getType() === MySQLLexer::INTERVAL_SYMBOL) { + break; + } + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::BITWISE_XOR_OPERATOR) { + $children[] = $this->match(MySQLLexer::BITWISE_XOR_OPERATOR); + $children[] = $this->bitExpr(); + } elseif ($token->getType() === MySQLLexer::MULT_OPERATOR || + $token->getType() === MySQLLexer::DIV_OPERATOR || + $token->getType() === MySQLLexer::MOD_OPERATOR || + $token->getType() === MySQLLexer::DIV_SYMBOL || + $token->getType() === MySQLLexer::MOD_SYMBOL) { + $this->match($token->getType()); + $children[] = new ASTNode(MySQLLexer::getTokenName($token->getType())); + $children[] = $this->bitExpr(); + } elseif ($token->getType() === MySQLLexer::PLUS_OPERATOR || + $token->getType() === MySQLLexer::MINUS_OPERATOR) { + $this->match($token->getType()); + $children[] = new ASTNode(MySQLLexer::getTokenName($token->getType())); + $children[] = $this->bitExpr(); + } elseif ($token->getType() === MySQLLexer::SHIFT_LEFT_OPERATOR || + $token->getType() === MySQLLexer::SHIFT_RIGHT_OPERATOR) { + $this->match($token->getType()); + $children[] = new ASTNode(MySQLLexer::getTokenName($token->getType())); + $children[] = $this->bitExpr(); + } elseif ($token->getType() === MySQLLexer::BITWISE_AND_OPERATOR) { + $children[] = $this->match(MySQLLexer::BITWISE_AND_OPERATOR); + $children[] = $this->bitExpr(); + } elseif ($token->getType() === MySQLLexer::BITWISE_OR_OPERATOR) { + $children[] = $this->match(MySQLLexer::BITWISE_OR_OPERATOR); + $children[] = $this->bitExpr(); + } else { + throw new \Exception('Unexpected token in bitExpr: ' . $token->getText()); + } + + $token = $this->lexer->peekNextToken(); + } + + if ($token->getType() === MySQLLexer::PLUS_OPERATOR || + $token->getType() === MySQLLexer::MINUS_OPERATOR) { + $this->match($token->getType()); + $children[] = new ASTNode(MySQLLexer::getTokenName($token->getType())); + $children[] = $this->match(MySQLLexer::INTERVAL_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->interval(); + } + + return new ASTNode('bitExpr', $children); + } + + public function simpleExpr() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::AT_SIGN_SYMBOL || + $token->getType() === MySQLLexer::AT_TEXT_SUFFIX) { + $children[] = $this->variable(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ASSIGN_OPERATOR || + $this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->equal(); + $children[] = new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + $children[] = $this->expr(); + } + return new ASTNode('simpleExpr', $children); + } elseif ($this->isUnambiguousIdentifierStart($token)) { + if ($this->lexer->peekNextToken(2)->getType() !== MySQLLexer::OPEN_PAR_SYMBOL) { + return $this->columnRefOrLiteral(); + } + return $this->functionCall(); + } elseif ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->columnRef(); + if ($this->serverVersion >= 50708 && + ($this->lexer->peekNextToken()->getType() === MySQLLexer::JSON_SEPARATOR_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::JSON_UNQUOTED_SEPARATOR_SYMBOL)) { + $children[] = $this->jsonOperator(); + } + return new ASTNode('simpleExpr', $children); + } elseif ($this->isRuntimeFunctionCallStart($token)) { + $children[] = $this->runtimeFunctionCall(); + return new ASTNode('simpleExpr', $children); + } elseif ($this->isLiteralStart($token)) { + $children[] = $this->literal(); + return new ASTNode('simpleExpr', $children); + } elseif ($token->getType() === MySQLLexer::PARAM_MARKER) { + $children[] = $this->match(MySQLLexer::PARAM_MARKER); + return new ASTNode('simpleExpr', $children); + } elseif ($this->isSumExprStart($token)) { + $children[] = $this->sumExpr(); + return new ASTNode('simpleExpr', $children); + } elseif ($this->serverVersion >= 80000 && $token->getType() === MySQLLexer::GROUPING_SYMBOL) { + $children[] = $this->match(MySQLLexer::GROUPING_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->exprList(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('simpleExpr', $children); + } elseif ($this->serverVersion >= 80000 && $this->isWindowFunctionCallStart($token)) { + $children[] = $this->windowFunctionCall(); + return new ASTNode('simpleExpr', $children); + } elseif ($token->getType() === MySQLLexer::PLUS_OPERATOR || + $token->getType() === MySQLLexer::MINUS_OPERATOR || + $token->getType() === MySQLLexer::BITWISE_NOT_OPERATOR) { + $this->match($this->lexer->peekNextToken()->getType()); + $children[] = new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + $children[] = $this->simpleExpr(); + return new ASTNode('simpleExpr', $children); + } elseif ( + $token->getType() === MySQLLexer::LOGICAL_NOT_OPERATOR || + $token->getType() === MySQLLexer::NOT2_SYMBOL + ) { + $children[] = $this->not2Rule(); + $children[] = $this->simpleExpr(); + return new ASTNode('simpleExpr', $children); + } elseif ($this->serverVersion < 80000 && $token->getType() === MySQLLexer::ROW_SYMBOL) { + $children[] = $this->match(MySQLLexer::ROW_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->exprList(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('simpleExpr', $children); + } elseif ($token->getType() === MySQLLexer::EXISTS_SYMBOL || + $this->isSubqueryStart($this->lexer->peekNextToken(2))) { + if ($token->getType() === MySQLLexer::EXISTS_SYMBOL) { + $children[] = $this->match(MySQLLexer::EXISTS_SYMBOL); + } + $children[] = $this->subquery(); + return new ASTNode('simpleExpr', $children); + } elseif ($token->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->exprList(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('simpleExpr', $children); + } elseif ($token->getType() === MySQLLexer::OPEN_CURLY_SYMBOL) { + $children[] = $this->match(MySQLLexer::OPEN_CURLY_SYMBOL); + $children[] = $this->identifier(); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::CLOSE_CURLY_SYMBOL); + return new ASTNode('simpleExpr', $children); + } elseif ($token->getType() === MySQLLexer::MATCH_SYMBOL) { + $children[] = $this->match(MySQLLexer::MATCH_SYMBOL); + $children[] = $this->identListArg(); + $children[] = $this->match(MySQLLexer::AGAINST_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->bitExpr(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IN_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WITH_SYMBOL) { + $children[] = $this->fulltextOptions(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('simpleExpr', $children); + } elseif ($token->getType() === MySQLLexer::BINARY_SYMBOL) { + $children[] = $this->match(MySQLLexer::BINARY_SYMBOL); + $children[] = $this->simpleExpr(); + return new ASTNode('simpleExpr', $children); + } elseif ($token->getType() === MySQLLexer::CAST_SYMBOL) { + $children[] = $this->match(MySQLLexer::CAST_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::AS_SYMBOL); + $children[] = $this->castType(); + if ($this->serverVersion >= 80017 && $this->lexer->peekNextToken()->getType() === MySQLLexer::ARRAY_SYMBOL) { + $children[] = $this->arrayCast(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('simpleExpr', $children); + } elseif ($token->getType() === MySQLLexer::CASE_SYMBOL) { + $children[] = $this->match(MySQLLexer::CASE_SYMBOL); + if ($this->isBoolPriStart($this->lexer->peekNextToken())) { + $children[] = $this->expr(); + } + do { + $children[] = $this->whenExpression(); + $children[] = $this->thenExpression(); + } while ($this->lexer->peekNextToken()->getType() === MySQLLexer::WHEN_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ELSE_SYMBOL) { + $children[] = $this->elseExpression(); + } + $children[] = $this->match(MySQLLexer::END_SYMBOL); + return new ASTNode('simpleExpr', $children); + } elseif ($token->getType() === MySQLLexer::CONVERT_SYMBOL) { + $children[] = $this->match(MySQLLexer::CONVERT_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->expr(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->castType(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::USING_SYMBOL) { + $children[] = $this->match(MySQLLexer::USING_SYMBOL); + $children[] = $this->charsetName(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } else { + throw new \Exception('Unexpected token in simpleExpr: ' . $this->lexer->peekNextToken()->getText()); + } + return new ASTNode('simpleExpr', $children); + } elseif ($token->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->match(MySQLLexer::DEFAULT_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->simpleIdentifier(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('simpleExpr', $children); + } elseif ($token->getType() === MySQLLexer::VALUES_SYMBOL) { + $children[] = $this->match(MySQLLexer::VALUES_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->simpleIdentifier(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('simpleExpr', $children); + } elseif ($token->getType() === MySQLLexer::INTERVAL_SYMBOL) { + $children[] = $this->match(MySQLLexer::INTERVAL_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->interval(); + $children[] = $this->match(MySQLLexer::PLUS_OPERATOR); + $children[] = $this->expr(); + return new ASTNode('simpleExpr', $children); + } elseif ($this->isSimpleExprStart($token) && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::COLLATE_SYMBOL) { + $children[] = $this->simpleExpr(); + $children[] = $this->match(MySQLLexer::COLLATE_SYMBOL); + $children[] = $this->textOrIdentifier(); + return new ASTNode('simpleExpr', $children); + } elseif ($this->isSimpleExprStart($token) && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::CONCAT_PIPES_SYMBOL) { + $children[] = $this->simpleExpr(); + $children[] = $this->match(MySQLLexer::CONCAT_PIPES_SYMBOL); + $children[] = $this->simpleExpr(); + return new ASTNode('simpleExpr', $children); + } else { + throw new \Exception('Unexpected token in simpleExpr: ' . $token->getText()); + } + } + + public function identListArg() + { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + return $this->identListWithParentheses(); + } else { + return $this->identList(); + } + } + + public function identList() + { + $children = []; + $children[] = $this->simpleIdentifier(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::COMMA_SYMBOL)); + $children[] = $this->simpleIdentifier(); + } + return new ASTNode('identList', $children); + } + + public function internalVariableName() + { + $token = $this->lexer->peekNextToken(); + $children = []; + if ($token->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $this->match(MySQLLexer::DEFAULT_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::DEFAULT_SYMBOL)); + $children[] = $this->dotIdentifier(); + } else { + $children[] = $this->identifier(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->dotIdentifier(); + } + } + + return new ASTNode('internalVariableName', $children); + } + + public function ternaryOption() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::ULONGLONG_NUMBER) { + return $this->ulonglong_number(); + } else { + return $this->match(MySQLLexer::DEFAULT_SYMBOL); + } + } + + public function identListWithParentheses() + { + $children = []; + + $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::OPEN_PAR_SYMBOL)); + $children[] = $this->identList(); + $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::CLOSE_PAR_SYMBOL)); + return new ASTNode('identListWithParentheses', $children); + } + + public function fulltextOptions() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::IN_SYMBOL) { + $this->match(MySQLLexer::IN_SYMBOL); + $children = [new ASTNode(MySQLLexer::getTokenName(MySQLLexer::IN_SYMBOL))]; + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::BOOLEAN_SYMBOL) { + $this->match(MySQLLexer::BOOLEAN_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::BOOLEAN_SYMBOL)); + } else { + $this->match(MySQLLexer::NATURAL_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::NATURAL_SYMBOL)); + } + $this->match(MySQLLexer::LANGUAGE_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::LANGUAGE_SYMBOL)); + $this->match(MySQLLexer::MODE_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::MODE_SYMBOL)); + return new ASTNode('fulltextOptions', $children); + } else { + $this->match(MySQLLexer::WITH_SYMBOL); + $children = [new ASTNode(MySQLLexer::getTokenName(MySQLLexer::WITH_SYMBOL))]; + $this->match(MySQLLexer::QUERY_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::QUERY_SYMBOL)); + $this->match(MySQLLexer::EXPANSION_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::EXPANSION_SYMBOL)); + return new ASTNode('fulltextOptions', $children); + } + } + + public function arrayCast() + { + return $this->match(MySQLLexer::ARRAY_SYMBOL); + } + + private function isRuntimeFunctionCallStart($token) + { + switch ($token->getType()) { + case MySQLLexer::CHAR_SYMBOL: + case MySQLLexer::CURRENT_USER_SYMBOL: + case MySQLLexer::DATE_SYMBOL: + case MySQLLexer::DAY_SYMBOL: + case MySQLLexer::HOUR_SYMBOL: + case MySQLLexer::INSERT_SYMBOL: + case MySQLLexer::INTERVAL_SYMBOL: + case MySQLLexer::LEFT_SYMBOL: + case MySQLLexer::MICROSECOND_SYMBOL: + case MySQLLexer::MINUTE_SYMBOL: + case MySQLLexer::MONTH_SYMBOL: + case MySQLLexer::RIGHT_SYMBOL: + case MySQLLexer::SECOND_SYMBOL: + case MySQLLexer::TIME_SYMBOL: + case MySQLLexer::TIMESTAMP_SYMBOL: + case MySQLLexer::TRIM_SYMBOL: + case MySQLLexer::USER_SYMBOL: + case MySQLLexer::VALUES_SYMBOL: + case MySQLLexer::YEAR_SYMBOL: + case MySQLLexer::ADDDATE_SYMBOL: + case MySQLLexer::SUBDATE_SYMBOL: + case MySQLLexer::CURDATE_SYMBOL: + case MySQLLexer::CURTIME_SYMBOL: + case MySQLLexer::DATE_ADD_SYMBOL: + case MySQLLexer::DATE_SUB_SYMBOL: + case MySQLLexer::EXTRACT_SYMBOL: + case MySQLLexer::GET_FORMAT_SYMBOL: + case MySQLLexer::NOW_SYMBOL: + case MySQLLexer::POSITION_SYMBOL: + case MySQLLexer::SUBSTR_SYMBOL: + case MySQLLexer::SUBSTRING_SYMBOL: + case MySQLLexer::SYSDATE_SYMBOL: + case MySQLLexer::TIMESTAMP_ADD_SYMBOL: + case MySQLLexer::TIMESTAMP_DIFF_SYMBOL: + case MySQLLexer::UTC_DATE_SYMBOL: + case MySQLLexer::UTC_TIME_SYMBOL: + case MySQLLexer::UTC_TIMESTAMP_SYMBOL: + case MySQLLexer::ASCII_SYMBOL: + case MySQLLexer::CHARSET_SYMBOL: + case MySQLLexer::COALESCE_SYMBOL: + case MySQLLexer::COLLATION_SYMBOL: + case MySQLLexer::CONCAT_SYMBOL: + case MySQLLexer::DATABASE_SYMBOL: + case MySQLLexer::IF_SYMBOL: + case MySQLLexer::FORMAT_SYMBOL: + case MySQLLexer::FOUND_ROWS_SYMBOL: + case MySQLLexer::MOD_SYMBOL: + return true; + case MySQLLexer::OLD_PASSWORD_SYMBOL: + return $this->serverVersion < 50607; + case MySQLLexer::PASSWORD_SYMBOL: + return $this->serverVersion < 80011; + case MySQLLexer::QUARTER_SYMBOL: + case MySQLLexer::REPEAT_SYMBOL: + case MySQLLexer::REPLACE_SYMBOL: + case MySQLLexer::REVERSE_SYMBOL: + case MySQLLexer::ROW_COUNT_SYMBOL: + case MySQLLexer::SCHEMA_SYMBOL: + case MySQLLexer::SESSION_USER_SYMBOL: + case MySQLLexer::SYSTEM_USER_SYMBOL: + case MySQLLexer::TRUNCATE_SYMBOL: + case MySQLLexer::WEEK_SYMBOL: + case MySQLLexer::WEIGHT_STRING_SYMBOL: + return true; + case MySQLLexer::CONTAINS_SYMBOL: + return $this->serverVersion < 50706; + case MySQLLexer::GEOMETRYCOLLECTION_SYMBOL: + case MySQLLexer::LINESTRING_SYMBOL: + case MySQLLexer::MULTILINESTRING_SYMBOL: + case MySQLLexer::MULTIPOINT_SYMBOL: + case MySQLLexer::MULTIPOLYGON_SYMBOL: + case MySQLLexer::POINT_SYMBOL: + case MySQLLexer::POLYGON_SYMBOL: + return true; + default: + return false; + } + } + + public function variable() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::AT_SIGN_SYMBOL || + $token->getType() === MySQLLexer::AT_TEXT_SUFFIX) { + return $this->userVariable(); + } elseif ($token->getType() === MySQLLexer::AT_AT_SIGN_SYMBOL) { + return $this->systemVariable(); + } else { + throw new \Exception('Unexpected token in variable: ' . $token->getText()); + } + } + + public function whenExpression() + { + $children = []; + + $children[] = $this->match(MySQLLexer::WHEN_SYMBOL); + $children[] = $this->expr(); + + return new ASTNode('whenExpression', $children); + } + + public function thenExpression() + { + $children = []; + + $children[] = $this->match(MySQLLexer::THEN_SYMBOL); + $children[] = $this->expr(); + + return new ASTNode('thenExpression', $children); + } + + public function elseExpression() + { + $children = []; + + $children[] = $this->match(MySQLLexer::ELSE_SYMBOL); + $children[] = $this->expr(); + + return new ASTNode('elseExpression', $children); + } + + public function castType() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::BINARY_SYMBOL) { + $children[] = $this->match(MySQLLexer::BINARY_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->fieldLength(); + } + } elseif ($token->getType() === MySQLLexer::CHAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::CHAR_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->fieldLength(); + } + + if ($this->isCharsetWithOptBinaryStart($this->lexer->peekNextToken())) { + $children[] = $this->charsetWithOptBinary(); + } + } elseif ($token->getType() === MySQLLexer::NCHAR_SYMBOL || + $token->getType() === MySQLLexer::NATIONAL_SYMBOL) { + $children[] = $this->nchar(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->fieldLength(); + } + } elseif ($token->getType() === MySQLLexer::DATE_SYMBOL) { + $children[] = $this->match(MySQLLexer::DATE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::TIME_SYMBOL) { + $children[] = $this->match(MySQLLexer::TIME_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->typeDatetimePrecision(); + } + } elseif ($token->getType() === MySQLLexer::TIMESTAMP_SYMBOL) { + $children[] = $this->match(MySQLLexer::TIMESTAMP_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->typeDatetimePrecision(); + } + } elseif ($token->getType() === MySQLLexer::DATETIME_SYMBOL) { + $children[] = $this->match(MySQLLexer::DATETIME_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->typeDatetimePrecision(); + } + } elseif ($token->getType() === MySQLLexer::DECIMAL_SYMBOL) { + $children[] = $this->match(MySQLLexer::DECIMAL_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->floatOptions(); + } + } elseif ($this->serverVersion >= 50708 && $token->getType() === MySQLLexer::JSON_SYMBOL) { + $children[] = $this->match(MySQLLexer::JSON_SYMBOL); + } elseif ($this->serverVersion >= 80017 && + ($token->getType() === MySQLLexer::REAL_SYMBOL || + $token->getType() === MySQLLexer::DOUBLE_SYMBOL)) { + $children[] = $this->realType(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->precision(); + } + } elseif ($this->serverVersion >= 80017 && $token->getType() === MySQLLexer::FLOAT_SYMBOL) { + $children[] = $this->match(MySQLLexer::FLOAT_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->standardFloatOptions(); + } + } elseif ($token->getType() === MySQLLexer::SIGNED_SYMBOL) { + $children[] = $this->match(MySQLLexer::SIGNED_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::INT_SYMBOL) { + $children[] = $this->match(MySQLLexer::INT_SYMBOL); + } + } elseif ($token->getType() === MySQLLexer::UNSIGNED_SYMBOL) { + $children[] = $this->match(MySQLLexer::UNSIGNED_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::INT_SYMBOL) { + $children[] = $this->match(MySQLLexer::INT_SYMBOL); + } + } else { + throw new \Exception('Unexpected token in castType: ' . $token->getText()); + } + + return new ASTNode('castType', $children); + } + + private function isCharsetWithOptBinaryStart($token) + { + return $token->getType() === MySQLLexer::CHAR_SYMBOL || + $token->getType() === MySQLLexer::CHAR_SYMBOL || + $token->getType() === MySQLLexer::BINARY_SYMBOL || + $this->isAsciiStart($token) || + $this->isUnicodeStart($token) || + $this->isCharsetName($token); + } + + private function isCharsetName($token) + { + switch($token->getType()) { + case MySQLLexer::IDENTIFIER: + case MySQLLexer::BACK_TICK_QUOTED_ID: + case MySQLLexer::DOUBLE_QUOTED_TEXT: + case MySQLLexer::SINGLE_QUOTED_TEXT: + return true; + case MySQLLexer::DEFAULT_SYMBOL: + if ($this->serverVersion < 80011) { + return true; + } + case MySQLLexer::BINARY_SYMBOL: + return true; + default: + return $this->isIdentifierKeyword($token); + } + } + + public function exprList() + { + $children = []; + + $children[] = $this->expr(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->expr(); + } + return new ASTNode('exprList', $children); + } + + + public function likeClause() + { + $children = []; + $children[] = $this->match(MySQLLexer::LIKE_SYMBOL); + $children[] = $this->textStringLiteral(); + + return new ASTNode('likeClause', $children); + } + public function createUserTail() + { + return $this->match(MySQLLexer::SESSION_SYMBOL); + } + + public function jsonOperator() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::JSON_SEPARATOR_SYMBOL) { + return $this->match(MySQLLexer::JSON_SEPARATOR_SYMBOL); + } else { + return $this->match(MySQLLexer::JSON_UNQUOTED_SEPARATOR_SYMBOL); + } + } + public function replacePassword() + { + $children = []; + + $this->match(MySQLLexer::REPLACE_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::REPLACE_SYMBOL)); + $children[] = $this->textString(); + + return new ASTNode('replacePassword', $children); + } + + public function retainCurrentPassword() + { + return $this->match(MySQLLexer::RETAIN_SYMBOL); + } + + public function discardOldPassword() + { + $children = []; + + $this->match(MySQLLexer::DISCARD_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::DISCARD_SYMBOL)); + $this->match(MySQLLexer::OLD_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::OLD_SYMBOL)); + $this->match(MySQLLexer::PASSWORD_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::PASSWORD_SYMBOL)); + + return new ASTNode('discardOldPassword', $children); + } + public function aclType() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::TABLE_SYMBOL) { + return $this->match(MySQLLexer::TABLE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::FUNCTION_SYMBOL) { + return $this->match(MySQLLexer::FUNCTION_SYMBOL); + } else { + return $this->match(MySQLLexer::PROCEDURE_SYMBOL); + } + } + + public function charset() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::CHAR_SYMBOL) { + $this->match(MySQLLexer::CHAR_SYMBOL); + $children = [ + new ASTNode(MySQLLexer::getTokenName(MySQLLexer::CHAR_SYMBOL)), + ]; + $children[] = $this->match(MySQLLexer::SET_SYMBOL); + return new ASTNode('charset', $children); + } elseif ($token->getType() === MySQLLexer::CHARSET_SYMBOL) { + return $this->match(MySQLLexer::CHARSET_SYMBOL); + } else { + throw new \Exception('Unexpected token in charset: ' . $token->getText()); + } + } + + public function notRule() +{ + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::NOT_SYMBOL: + case MySQLLexer::NOT2_SYMBOL: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in indexType: ' . $token->getText()); + } +} + + public function not2Rule() +{ + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::LOGICAL_NOT_OPERATOR: + case MySQLLexer::NOT2_SYMBOL: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in indexType: ' . $token->getText()); + } +} + + // None of the microsecond variants can be used in schedules (e.g. events). + public function interval() + { + $token = $this->lexer->peekNextToken(); + if ($this->isIntervalTimeStampStart($token)) { + return $this->intervalTimeStamp(); + } elseif ($token->getType() === MySQLLexer::SECOND_MICROSECOND_SYMBOL || + $token->getType() === MySQLLexer::MINUTE_MICROSECOND_SYMBOL || + $token->getType() === MySQLLexer::MINUTE_SECOND_SYMBOL || + $token->getType() === MySQLLexer::HOUR_MICROSECOND_SYMBOL || + $token->getType() === MySQLLexer::HOUR_SECOND_SYMBOL || + $token->getType() === MySQLLexer::HOUR_MINUTE_SYMBOL || + $token->getType() === MySQLLexer::DAY_MICROSECOND_SYMBOL || + $token->getType() === MySQLLexer::DAY_SECOND_SYMBOL || + $token->getType() === MySQLLexer::DAY_MINUTE_SYMBOL || + $token->getType() === MySQLLexer::DAY_HOUR_SYMBOL || + $token->getType() === MySQLLexer::YEAR_MONTH_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + return new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + } else { + throw new \Exception('Unexpected token in interval: ' . $token->getText()); + } + } + + // Support for SQL_TSI_* units is added by mapping those to tokens without SQL_TSI_ prefix. + public function intervalTimeStamp() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::MICROSECOND_SYMBOL || + $token->getType() === MySQLLexer::SQL_TSI_MICROSECOND_SYMBOL) { + return $this->match(MySQLLexer::MICROSECOND_SYMBOL); + } elseif ($token->getType() === MySQLLexer::SECOND_SYMBOL || + $token->getType() === MySQLLexer::SQL_TSI_SECOND_SYMBOL) { + return $this->match(MySQLLexer::SECOND_SYMBOL); + } elseif ($token->getType() === MySQLLexer::MINUTE_SYMBOL || + $token->getType() === MySQLLexer::SQL_TSI_MINUTE_SYMBOL) { + return $this->match(MySQLLexer::MINUTE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::HOUR_SYMBOL || + $token->getType() === MySQLLexer::SQL_TSI_HOUR_SYMBOL) { + return $this->match(MySQLLexer::HOUR_SYMBOL); + } elseif ($token->getType() === MySQLLexer::DAY_SYMBOL || + $token->getType() === MySQLLexer::SQL_TSI_DAY_SYMBOL) { + return $this->match(MySQLLexer::DAY_SYMBOL); + } elseif ($token->getType() === MySQLLexer::WEEK_SYMBOL || + $token->getType() === MySQLLexer::SQL_TSI_WEEK_SYMBOL) { + return $this->match(MySQLLexer::WEEK_SYMBOL); + } elseif ($token->getType() === MySQLLexer::MONTH_SYMBOL || + $token->getType() === MySQLLexer::SQL_TSI_MONTH_SYMBOL) { + return $this->match(MySQLLexer::MONTH_SYMBOL); + } elseif ($token->getType() === MySQLLexer::QUARTER_SYMBOL || + $token->getType() === MySQLLexer::SQL_TSI_QUARTER_SYMBOL) { + return $this->match(MySQLLexer::QUARTER_SYMBOL); + } elseif ($token->getType() === MySQLLexer::YEAR_SYMBOL || + $token->getType() === MySQLLexer::SQL_TSI_YEAR_SYMBOL) { + return $this->match(MySQLLexer::YEAR_SYMBOL); + } else { + throw new \Exception('Unexpected token in intervalTimeStamp: ' . $token->getText()); + } + } + + public function exprListWithParentheses() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->exprList(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('exprListWithParentheses', $children); + } + + public function exprWithParentheses() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('exprWithParentheses', $children); + } + + public function simpleExprWithParentheses() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->simpleExpr(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + + return new ASTNode('simpleExprWithParentheses', $children); + } + + public function functionCall() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($this->isQualifiedIdentifierStart($token)) { + $children[] = $this->qualifiedIdentifier(); + } else { + $children[] = $this->pureIdentifier(); + } + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + + if ($this->isExprStart($this->lexer->peekNextToken())) { + $children[] = $this->exprList(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('functionCall', $children); + } + + public function orderList() + { + $children = []; + $children[] = $this->orderExpression(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->orderExpression(); + } + return new ASTNode('orderList', $children); + } + + public function orderExpression() + { + $children = []; + $children[] = $this->expr(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ASC_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DESC_SYMBOL) { + $children[] = $this->direction(); + } + return new ASTNode('orderExpression', $children); + } + + public function groupList() + { + $children = []; + $children[] = $this->groupingExpression(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->groupingExpression(); + } + + return new ASTNode('groupList', $children); + } + + public function groupingExpression() + { + return $this->expr(); + } + + //----------------- Stored routines rules ------------------------------------------------------------------------------ + + // Compound syntax for stored procedures, stored functions, triggers and events. + // Implements both, sp_proc_stmt and ev_sql_stmt_inner from the server grammar. + public function compoundStatement() + { + $token = $this->lexer->peekNextToken(); + if ($this->isSimpleStatementStart($token) || + $token->getType() === MySQLLexer::BEGIN_SYMBOL) { + return $this->simpleStatement(); + } elseif ($token->getType() === MySQLLexer::RETURN_SYMBOL) { + return $this->returnStatement(); + } elseif ($token->getType() === MySQLLexer::DECLARE_SYMBOL) { + return $this->spDeclarations(); + } elseif ($token->getType() === MySQLLexer::IF_SYMBOL) { + return $this->ifStatement(); + } elseif ($token->getType() === MySQLLexer::CASE_SYMBOL) { + return $this->caseStatement(); + } elseif (($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isLabelKeyword($token)) && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::COLON_SYMBOL) { + return $this->labeledBlock(); + } elseif ($token->getType() === MySQLLexer::BEGIN_SYMBOL) { + return $this->unlabeledBlock(); + } elseif (($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isLabelKeyword($token)) && + ($this->lexer->peekNextToken(2)->getType() === MySQLLexer::LOOP_SYMBOL || + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::REPEAT_SYMBOL || + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::WHILE_SYMBOL)) { + return $this->labeledControl(); + } elseif ($token->getType() === MySQLLexer::LOOP_SYMBOL || + $token->getType() === MySQLLexer::REPEAT_SYMBOL || + $token->getType() === MySQLLexer::WHILE_SYMBOL) { + return $this->unlabeledControl(); + } elseif ($token->getType() === MySQLLexer::LEAVE_SYMBOL) { + return $this->leaveStatement(); + } elseif ($token->getType() === MySQLLexer::ITERATE_SYMBOL) { + return $this->iterateStatement(); + } elseif ($token->getType() === MySQLLexer::OPEN_SYMBOL) { + return $this->cursorOpen(); + } elseif ($token->getType() === MySQLLexer::FETCH_SYMBOL) { + return $this->cursorFetch(); + } elseif ($token->getType() === MySQLLexer::CLOSE_SYMBOL) { + return $this->cursorClose(); + } else { + throw new \Exception('Unexpected token in compoundStatement: ' . $token->getText()); + } + } + + public function returnStatement() + { + $children = []; + + $children[] = $this->match(MySQLLexer::RETURN_SYMBOL); + $children[] = $this->expr(); + return new ASTNode('returnStatement', $children); + } + + public function ifStatement() + { + $children = []; + $children[] = $this->match(MySQLLexer::IF_SYMBOL); + $children[] = $this->ifBody(); + $children[] = $this->match(MySQLLexer::END_SYMBOL); + $children[] = $this->match(MySQLLexer::IF_SYMBOL); + return new ASTNode('ifStatement', $children); + } + + public function ifBody() + { + $children = []; + $children[] = $this->expr(); + $children[] = $this->thenStatement(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ELSEIF_SYMBOL) { + $children[] = $this->match(MySQLLexer::ELSEIF_SYMBOL); + $children[] = $this->ifBody(); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::ELSE_SYMBOL) { + $children[] = $this->match(MySQLLexer::ELSE_SYMBOL); + $children[] = $this->compoundStatementList(); + } + + return new ASTNode('ifBody', $children); + } + + public function thenStatement() + { + $children = []; + $children[] = $this->match(MySQLLexer::THEN_SYMBOL); + $children[] = $this->compoundStatementList(); + return new ASTNode('thenStatement', $children); + } + + public function compoundStatementList() + { + $children = []; + do { + $children[] = $this->compoundStatement(); + $children[] = $this->match(MySQLLexer::SEMICOLON_SYMBOL); + } while ($this->isCompoundStatementStart($this->lexer->peekNextToken())); + return new ASTNode('compoundStatementList', $children); + } + + public function caseStatement() + { + $children = []; + + $children[] = $this->match(MySQLLexer::CASE_SYMBOL); + if ($this->isBoolPriStart($this->lexer->peekNextToken())) { + $children[] = $this->expr(); + } + do { + $children[] = $this->whenExpression(); + $children[] = $this->thenStatement(); + } while ($this->lexer->peekNextToken()->getType() === MySQLLexer::WHEN_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ELSE_SYMBOL) { + $children[] = $this->elseStatement(); + } + + $children[] = $this->match(MySQLLexer::END_SYMBOL); + $children[] = $this->match(MySQLLexer::CASE_SYMBOL); + + return new ASTNode('caseStatement', $children); + } + + public function labeledBlock() + { + $children = []; + + $children[] = $this->label(); + $children[] = $this->beginEndBlock(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isLabelKeyword($this->lexer->peekNextToken())) { + $children[] = $this->labelRef(); + } + + return new ASTNode('labeledBlock', $children); + } + + public function unlabeledBlock() + { + return $this->beginEndBlock(); + } + + public function label() + { + $children = []; + $children[] = $this->labelIdentifier(); + $children[] = $this->match(MySQLLexer::COLON_SYMBOL); + return new ASTNode('label', $children); + } + + public function beginEndBlock() + { + $children = []; + + $children[] = $this->match(MySQLLexer::BEGIN_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DECLARE_SYMBOL) { + $children[] = $this->spDeclarations(); + } + + if ($this->isCompoundStatementStart($this->lexer->peekNextToken())) { + $children[] = $this->compoundStatementList(); + } + + $children[] = $this->match(MySQLLexer::END_SYMBOL); + return new ASTNode('beginEndBlock', $children); + } + + public function labeledControl() + { + $children = []; + $children[] = $this->label(); + $children[] = $this->unlabeledControl(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isLabelKeyword($this->lexer->peekNextToken())) { + $children[] = $this->labelRef(); + } + return new ASTNode('labeledControl', $children); + } + + public function unlabeledControl() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::LOOP_SYMBOL) { + return $this->loopBlock(); + } elseif ($token->getType() === MySQLLexer::WHILE_SYMBOL) { + return $this->whileDoBlock(); + } elseif ($token->getType() === MySQLLexer::REPEAT_SYMBOL) { + return $this->repeatUntilBlock(); + } else { + throw new \Exception('Unexpected token in unlabeledControl: ' . $token->getText()); + } + } + + public function loopBlock() + { + $children = []; + + $children[] = $this->match(MySQLLexer::LOOP_SYMBOL); + $children[] = $this->compoundStatementList(); + $children[] = $this->match(MySQLLexer::END_SYMBOL); + $children[] = $this->match(MySQLLexer::LOOP_SYMBOL); + return new ASTNode('loopBlock', $children); + } + + public function whileDoBlock() + { + $children = []; + + $children[] = $this->match(MySQLLexer::WHILE_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::DO_SYMBOL); + $children[] = $this->compoundStatementList(); + $children[] = $this->match(MySQLLexer::END_SYMBOL); + $children[] = $this->match(MySQLLexer::WHILE_SYMBOL); + return new ASTNode('whileDoBlock', $children); + } + + public function repeatUntilBlock() + { + $children = []; + + $children[] = $this->match(MySQLLexer::REPEAT_SYMBOL); + $children[] = $this->compoundStatementList(); + $children[] = $this->match(MySQLLexer::UNTIL_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::END_SYMBOL); + $children[] = $this->match(MySQLLexer::REPEAT_SYMBOL); + + return new ASTNode('repeatUntilBlock', $children); + } + + public function spDeclarations() + { + $children = []; + do { + $children[] = $this->spDeclaration(); + $children[] = $this->match(MySQLLexer::SEMICOLON_SYMBOL); + } while ($this->lexer->peekNextToken()->getType() === MySQLLexer::DECLARE_SYMBOL); + return new ASTNode('spDeclarations', $children); + } + + public function spDeclaration() + { + $children = []; + $children[] = $this->match(MySQLLexer::DECLARE_SYMBOL); + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token)) { + $children[] = $this->variableDeclaration(); + } elseif ($token->getType() === MySQLLexer::CONDITION_SYMBOL) { + $children[] = $this->conditionDeclaration(); + } elseif ($token->getType() === MySQLLexer::CONTINUE_SYMBOL || + $token->getType() === MySQLLexer::EXIT_SYMBOL || + $token->getType() === MySQLLexer::UNDO_SYMBOL) { + $children[] = $this->handlerDeclaration(); + } elseif ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token)) { + $children[] = $this->cursorDeclaration(); + } else { + throw new \Exception('Unexpected token in spDeclaration: ' . $token->getText()); + } + return new ASTNode('spDeclaration', $children); + } + + public function variableDeclaration() + { + $children = []; + + $children[] = $this->identifierList(); + $children[] = $this->dataType(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COLLATE_SYMBOL) { + $children[] = $this->collate(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->match(MySQLLexer::DEFAULT_SYMBOL); + $children[] = $this->expr(); + } + return new ASTNode('variableDeclaration', $children); + } + + public function conditionDeclaration() + { + $children = []; + + $children[] = $this->match(MySQLLexer::CONDITION_SYMBOL); + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->spCondition(); + + return new ASTNode('conditionDeclaration', $children); + } + + public function spCondition() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::ULONGLONG_NUMBER || + $token->getType() === MySQLLexer::LONG_NUMBER || + $token->getType() === MySQLLexer::INT_NUMBER) { + return $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::SQLSTATE_SYMBOL) { + return $this->sqlstate(); + } else { + throw new \Exception('Unexpected token in spCondition: ' . $token->getText()); + } + } + + public function sqlstate() + { + $children = []; + + $children[] = $this->match(MySQLLexer::SQLSTATE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::VALUE_SYMBOL) { + $children[] = $this->match(MySQLLexer::VALUE_SYMBOL); + } + $children[] = $this->textLiteral(); + + return new ASTNode('sqlstate', $children); + } + + public function handlerDeclaration() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::CONTINUE_SYMBOL) { + $children[] = $this->match(MySQLLexer::CONTINUE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::EXIT_SYMBOL) { + $children[] = $this->match(MySQLLexer::EXIT_SYMBOL); + } elseif ($token->getType() === MySQLLexer::UNDO_SYMBOL) { + $children[] = $this->match(MySQLLexer::UNDO_SYMBOL); + } else { + throw new \Exception('Unexpected token in handlerDeclaration: ' . $token->getText()); + } + + $children[] = $this->match(MySQLLexer::HANDLER_SYMBOL); + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->handlerCondition(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->handlerCondition(); + } + + $children[] = $this->compoundStatement(); + return new ASTNode('handlerDeclaration', $children); + } + + public function handlerCondition() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::SQLSTATE_SYMBOL || + $this->isUlong_numberStart($token)) { + return $this->spCondition(); + } elseif ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token)) { + return $this->identifier(); + } elseif ($token->getType() === MySQLLexer::SQLWARNING_SYMBOL) { + return $this->match(MySQLLexer::SQLWARNING_SYMBOL); + } elseif ($token->getType() === MySQLLexer::NOT_SYMBOL) { + $children = []; + $children[] = $this->match(MySQLLexer::NOT_SYMBOL); + $children[] = $this->match(MySQLLexer::FOUND_SYMBOL); + return new ASTNode('handlerCondition', $children); + } elseif ($token->getType() === MySQLLexer::SQLEXCEPTION_SYMBOL) { + return $this->match(MySQLLexer::SQLEXCEPTION_SYMBOL); + } else { + throw new \Exception('Unexpected token in handlerCondition: ' . $token->getText()); + } + } + + public function cursorDeclaration() + { + $children = []; + $children[] = $this->identifier(); + $children[] = $this->match(MySQLLexer::CURSOR_SYMBOL); + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->selectStatement(); + return new ASTNode('cursorDeclaration', $children); + } + + public function iterateStatement() + { + $children = []; + + $children[] = $this->match(MySQLLexer::ITERATE_SYMBOL); + $children[] = $this->labelRef(); + return new ASTNode('iterateStatement', $children); + } + + public function leaveStatement() + { + $children = []; + + $children[] = $this->match(MySQLLexer::LEAVE_SYMBOL); + $children[] = $this->labelRef(); + return new ASTNode('leaveStatement', $children); + } + + public function getDiagnostics() + { + $children = []; + + $children[] = $this->match(MySQLLexer::GET_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::CURRENT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::STACKED_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::CURRENT_SYMBOL) { + $children[] = $this->match(MySQLLexer::CURRENT_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::STACKED_SYMBOL); + } + } + $children[] = $this->match(MySQLLexer::DIAGNOSTICS_SYMBOL); + $token = $this->lexer->peekNextToken(); + if (($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::AT_SIGN_SYMBOL || + $token->getType() === MySQLLexer::AT_TEXT_SUFFIX) && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->statementInformationItem(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->statementInformationItem(); + } + } elseif ($token->getType() === MySQLLexer::CONDITION_SYMBOL) { + $children[] = $this->match(MySQLLexer::CONDITION_SYMBOL); + $children[] = $this->signalAllowedExpr(); + $children[] = $this->conditionInformationItem(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->conditionInformationItem(); + } + } else { + throw new \Exception('Unexpected token in getDiagnostics: ' . $token->getText()); + } + return new ASTNode('getDiagnostics', $children); + } + + // Only a limited subset of expr is allowed in SIGNAL/RESIGNAL/CONDITIONS. + public function signalAllowedExpr() + { + $token = $this->lexer->peekNextToken(); + + if ($this->isLiteralStart($token)) { + return $this->literal(); + } elseif ($token->getType() === MySQLLexer::AT_SIGN_SYMBOL || + $token->getType() === MySQLLexer::AT_TEXT_SUFFIX) { + return $this->variable(); + } elseif ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::DOT_SYMBOL) { + return $this->qualifiedIdentifier(); + } else { + throw new \Exception('Unexpected token in signalAllowedExpr: ' . $token->getText()); + } + } + + public function statementInformationItem() + { + $children = []; + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::AT_SIGN_SYMBOL || + $token->getType() === MySQLLexer::AT_TEXT_SUFFIX) { + $children[] = $this->variable(); + } elseif ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token)) { + $children[] = $this->identifier(); + } else { + throw new \Exception('Unexpected token in statementInformationItem: ' . $token->getText()); + } + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::NUMBER_SYMBOL) { + $children[] = $this->match(MySQLLexer::NUMBER_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::ROW_COUNT_SYMBOL) { + $children[] = $this->match(MySQLLexer::ROW_COUNT_SYMBOL); + } else { + throw new \Exception( + 'Unexpected token in statementInformationItem: ' . $this->lexer->peekNextToken()->getText() + ); + } + return new ASTNode('statementInformationItem', $children); + } + + public function conditionInformationItem() + { + $children = []; + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::AT_SIGN_SYMBOL || + $token->getType() === MySQLLexer::AT_TEXT_SUFFIX) { + $children[] = $this->variable(); + } elseif ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token)) { + $children[] = $this->identifier(); + } else { + throw new \Exception('Unexpected token in conditionInformationItem: ' . $token->getText()); + } + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::CLASS_ORIGIN_SYMBOL || + $token->getType() === MySQLLexer::SUBCLASS_ORIGIN_SYMBOL || + $token->getType() === MySQLLexer::CONSTRAINT_CATALOG_SYMBOL || + $token->getType() === MySQLLexer::CONSTRAINT_SCHEMA_SYMBOL || + $token->getType() === MySQLLexer::CONSTRAINT_NAME_SYMBOL || + $token->getType() === MySQLLexer::CATALOG_NAME_SYMBOL || + $token->getType() === MySQLLexer::SCHEMA_NAME_SYMBOL || + $token->getType() === MySQLLexer::TABLE_NAME_SYMBOL || + $token->getType() === MySQLLexer::COLUMN_NAME_SYMBOL || + $token->getType() === MySQLLexer::CURSOR_NAME_SYMBOL || + $token->getType() === MySQLLexer::MESSAGE_TEXT_SYMBOL || + $token->getType() === MySQLLexer::MYSQL_ERRNO_SYMBOL) { + $children[] = $this->signalInformationItemName(); + } elseif ($token->getType() === MySQLLexer::RETURNED_SQLSTATE_SYMBOL) { + $children[] = $this->match(MySQLLexer::RETURNED_SQLSTATE_SYMBOL); + } else { + throw new \Exception('Unexpected token in conditionInformationItem: ' . $token->getText()); + } + + return new ASTNode('conditionInformationItem', $children); + } + + public function signalStatement() + { + $children = []; + + $children[] = $this->match(MySQLLexer::SIGNAL_SYMBOL); + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token)) { + $children[] = $this->identifier(); + } elseif ($token->getType() === MySQLLexer::SQLSTATE_SYMBOL) { + $children[] = $this->sqlstate(); + } else { + throw new \Exception('Unexpected token in signalStatement: ' . $token->getText()); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::SET_SYMBOL) { + $children[] = $this->match(MySQLLexer::SET_SYMBOL); + $children[] = $this->signalInformationItem(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->signalInformationItem(); + } + } + + return new ASTNode('signalStatement', $children); + } + + public function resignalStatement() + { + $children = []; + + $children[] = $this->match(MySQLLexer::RESIGNAL_SYMBOL); + + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::SQLSTATE_SYMBOL) { + if ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token)) { + $children[] = $this->identifier(); + } else { + $children[] = $this->sqlstate(); + } + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::SET_SYMBOL) { + $children[] = $this->match(MySQLLexer::SET_SYMBOL); + $children[] = $this->signalInformationItem(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->signalInformationItem(); + } + } + + return new ASTNode('resignalStatement', $children); + } + + public function signalInformationItem() + { + $children = []; + + $children[] = $this->signalInformationItemName(); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->signalAllowedExpr(); + return new ASTNode('signalInformationItem', $children); + } + + public function signalInformationItemName() +{ + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::CLASS_ORIGIN_SYMBOL: + case MySQLLexer::SUBCLASS_ORIGIN_SYMBOL: + case MySQLLexer::CONSTRAINT_CATALOG_SYMBOL: + case MySQLLexer::CONSTRAINT_SCHEMA_SYMBOL: + case MySQLLexer::CONSTRAINT_NAME_SYMBOL: + case MySQLLexer::CATALOG_NAME_SYMBOL: + case MySQLLexer::SCHEMA_NAME_SYMBOL: + case MySQLLexer::TABLE_NAME_SYMBOL: + case MySQLLexer::COLUMN_NAME_SYMBOL: + case MySQLLexer::CURSOR_NAME_SYMBOL: + case MySQLLexer::MESSAGE_TEXT_SYMBOL: + case MySQLLexer::MYSQL_ERRNO_SYMBOL: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in indexType: ' . $token->getText()); + } +} + + public function cursorOpen() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_SYMBOL); + $children[] = $this->identifier(); + return new ASTNode('cursorOpen', $children); + } + + public function cursorFetch() + { + $children = []; + + $children[] = $this->match(MySQLLexer::FETCH_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::NEXT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::FROM_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::NEXT_SYMBOL) { + $children[] = $this->match(MySQLLexer::NEXT_SYMBOL); + } + $children[] = $this->match(MySQLLexer::FROM_SYMBOL); + } + $children[] = $this->identifier(); + $children[] = $this->match(MySQLLexer::INTO_SYMBOL); + $children[] = $this->identifierList(); + return new ASTNode('cursorFetch', $children); + } + + public function cursorClose() + { + $children = []; + + $children[] = $this->match(MySQLLexer::CLOSE_SYMBOL); + $children[] = $this->identifier(); + return new ASTNode('cursorClose', $children); + } + + //----------------- Supplemental rules --------------------------------------------------------------------------------- + + // Schedules in CREATE/ALTER EVENT. + public function schedule() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::AT_SYMBOL) { + $children[] = $this->match(MySQLLexer::AT_SYMBOL); + $children[] = $this->expr(); + } elseif ($token->getType() === MySQLLexer::EVERY_SYMBOL) { + $children[] = $this->match(MySQLLexer::EVERY_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->interval(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::STARTS_SYMBOL) { + $children[] = $this->match(MySQLLexer::STARTS_SYMBOL); + $children[] = $this->expr(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ENDS_SYMBOL) { + $children[] = $this->match(MySQLLexer::ENDS_SYMBOL); + $children[] = $this->expr(); + } + } else { + throw new \Exception('Unexpected token in schedule: ' . $token->getText()); + } + + return new ASTNode('schedule', $children); + } + + public function columnDefinition() + { + $children = []; + $children[] = $this->columnName(); + $children[] = $this->fieldDefinition(); + if ($this->serverVersion < 80016 && + ($this->lexer->peekNextToken()->getType() === MySQLLexer::CHECK_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::REFERENCES_SYMBOL)) { + $children[] = $this->checkOrReferences(); + } + + return new ASTNode('columnDefinition', $children); + } + + public function checkOrReferences() + { + if ($this->serverVersion < 80016) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::CHECK_SYMBOL) { + return $this->checkConstraint(); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::REFERENCES_SYMBOL) { + return $this->references(); + } else { + throw new \Exception('Unexpected token in checkOrReferences: ' . $this->lexer->peekNextToken()->getText()); + } + } else { + return $this->references(); + } + } + + public function constraintEnforcement() + { + $children = []; + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::NOT_SYMBOL) { + $children[] = $this->match(MySQLLexer::NOT_SYMBOL); + } + $children[] = $this->match(MySQLLexer::ENFORCED_SYMBOL); + + return new ASTNode('constraintEnforcement', $children); + } + + public function tableConstraintDef() + { + $children = []; + $token1 = $this->lexer->peekNextToken(); + $token2 = $this->lexer->peekNextToken(2); + + if ($token1->getType() === MySQLLexer::CONSTRAINT_SYMBOL) { + $children[] = $this->constraintName(); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::PRIMARY_SYMBOL || + $token->getType() === MySQLLexer::UNIQUE_SYMBOL) { + $children[] = $this->constraintKeyType(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken()) || + $this->lexer->peekNextToken()->getType() === MySQLLexer::USING_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::TYPE_SYMBOL) { + $children[] = $this->indexNameAndType(); + } + $children[] = $this->keyListVariants(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMENT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_BLOCK_SIZE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::USING_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::TYPE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::VISIBLE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INVISIBLE_SYMBOL) { + $children[] = $this->indexOption(); + } + } elseif ($token->getType() === MySQLLexer::FOREIGN_SYMBOL) { + $children[] = $this->match(MySQLLexer::FOREIGN_SYMBOL); + $children[] = $this->match(MySQLLexer::KEY_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + $children[] = $this->indexName(); + } + + $children[] = $this->keyList(); + $children[] = $this->references(); + } elseif ($token->getType() === MySQLLexer::CHECK_SYMBOL) { + $children[] = $this->checkConstraint(); + if ($this->serverVersion >= 80017 && + ($this->lexer->peekNextToken()->getType() === MySQLLexer::NOT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ENFORCED_SYMBOL)) { + $children[] = $this->constraintEnforcement(); + } + } else { + throw new \Exception('Unexpected token in tableConstraintDef: ' . $token->getText()); + } + } elseif ($token1->getType() === MySQLLexer::PRIMARY_SYMBOL || + $token1->getType() === MySQLLexer::UNIQUE_SYMBOL) { + $children[] = $this->constraintKeyType(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken()) || + $this->lexer->peekNextToken()->getType() === MySQLLexer::USING_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::TYPE_SYMBOL) { + $children[] = $this->indexNameAndType(); + } + $children[] = $this->keyListVariants(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMENT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_BLOCK_SIZE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::USING_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::TYPE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::VISIBLE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INVISIBLE_SYMBOL) { + $children[] = $this->indexOption(); + } + } elseif ($token1->getType() === MySQLLexer::FOREIGN_SYMBOL && $token2->getType() === MySQLLexer::KEY_SYMBOL) { + $children[] = $this->match(MySQLLexer::FOREIGN_SYMBOL); + $children[] = $this->match(MySQLLexer::KEY_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + $children[] = $this->indexName(); + } + + $children[] = $this->keyList(); + $children[] = $this->references(); + } elseif ($token1->getType() === MySQLLexer::CHECK_SYMBOL) { + $children[] = $this->checkConstraint(); + if ($this->serverVersion >= 80017 && + ($this->lexer->peekNextToken()->getType() === MySQLLexer::NOT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ENFORCED_SYMBOL)) { + $children[] = $this->constraintEnforcement(); + } + } elseif (($token1->getType() === MySQLLexer::KEY_SYMBOL || $token1->getType() === MySQLLexer::INDEX_SYMBOL) && + ($token2->getType() === MySQLLexer::IDENTIFIER || + $token2->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token2->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token2) || + $token2->getType() === MySQLLexer::USING_SYMBOL || + $token2->getType() === MySQLLexer::TYPE_SYMBOL || + $token2->getType() === MySQLLexer::OPEN_PAR_SYMBOL)) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_SYMBOL) { + $children[] = $this->match(MySQLLexer::KEY_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::INDEX_SYMBOL); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken()) || + $this->lexer->peekNextToken()->getType() === MySQLLexer::USING_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::TYPE_SYMBOL) { + $children[] = $this->indexNameAndType(); + } + + $children[] = $this->keyListVariants(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMENT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_BLOCK_SIZE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::USING_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::TYPE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::VISIBLE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INVISIBLE_SYMBOL) { + $children[] = $this->indexOption(); + } + } elseif ($token1->getType() === MySQLLexer::FULLTEXT_SYMBOL) { + $children[] = $this->match(MySQLLexer::FULLTEXT_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INDEX_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_SYMBOL) { + $children[] = $this->match(MySQLLexer::KEY_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::INDEX_SYMBOL); + } + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + $children[] = $this->indexName(); + } + + $children[] = $this->keyListVariants(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMENT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_BLOCK_SIZE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::WITH_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::VISIBLE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INVISIBLE_SYMBOL) { + $children[] = $this->fulltextIndexOption(); + } + } elseif ($token1->getType() === MySQLLexer::SPATIAL_SYMBOL) { + $children[] = $this->match(MySQLLexer::SPATIAL_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INDEX_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_SYMBOL) { + $children[] = $this->match(MySQLLexer::KEY_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::INDEX_SYMBOL); + } + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + $children[] = $this->indexName(); + } + $children[] = $this->keyListVariants(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMENT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_BLOCK_SIZE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::VISIBLE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INVISIBLE_SYMBOL) { + $children[] = $this->spatialIndexOption(); + } + } else { + throw new \Exception('Unexpected token in tableConstraintDef: ' . $token1->getText()); + } + return new ASTNode('tableConstraintDef', $children); + } + + public function constraintName() + { + $children = []; + + $children[] = $this->match(MySQLLexer::CONSTRAINT_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + $children[] = $this->identifier(); + } + + return new ASTNode('constraintName', $children); + } + + public function fieldDefinition() + { + $children = []; + $children[] = $this->dataType(); + + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::COLLATE_SYMBOL) { + $children[] = $this->collate(); + + if ($this->serverVersion >= 50707 && $this->lexer->peekNextToken()->getType() === MySQLLexer::GENERATED_SYMBOL) { + $children[] = $this->match(MySQLLexer::GENERATED_SYMBOL); + $children[] = $this->match(MySQLLexer::ALWAYS_SYMBOL); + } + + $children[] = $this->match(MySQLLexer::AS_SYMBOL); + $children[] = $this->exprWithParentheses(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::VIRTUAL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::STORED_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::VIRTUAL_SYMBOL) { + $children[] = $this->match(MySQLLexer::VIRTUAL_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::STORED_SYMBOL); + } + } + + if ($this->serverVersion < 80000) { + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::UNIQUE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::COMMENT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NOT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NULL_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::PRIMARY_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_SYMBOL) { + $children[] = $this->gcolAttribute(); + } + } elseif ($this->isColumnAttributeStart($this->lexer->peekNextToken())) { + do { + $children[] = $this->columnAttribute(); + } while ($this->isColumnAttributeStart($this->lexer->peekNextToken())); + } + } elseif ($this->isColumnAttributeStart($token)) { + do { + $children[] = $this->columnAttribute(); + } while ($this->isColumnAttributeStart($this->lexer->peekNextToken())); + } + + return new ASTNode('fieldDefinition', $children); + } + public function columnAttribute() + { + $children = []; + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::NOT_SYMBOL: + $children[] = ASTNode::fromToken($token); + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::NULL_SYMBOL: + $children[] = ASTNode::fromToken($token); + break; + case MySQLLexer::SECONDARY_SYMBOL: + if ($this->serverVersion >= 80014) { + $children[] = ASTNode::fromToken($token); + break; + } + default: + throw new \Exception('Unexpected token in columnAttribute: ' . $token->getText()); + } + break; + case MySQLLexer::NULL_SYMBOL: + $children[] = ASTNode::fromToken($token); + break; + case MySQLLexer::DEFAULT_SYMBOL: + $children[] = ASTNode::fromToken($token); + $token = $this->lexer->peekNextToken(); + if ($this->isSignedLiteralStart($token)) { + $children[] = $this->signedLiteral(); + } elseif ($token->getType() === MySQLLexer::NOW_SYMBOL) { + $this->match(MySQLLexer::NOW_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::NOW_SYMBOL)); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->timeFunctionParameters(); + } + } elseif ($this->serverVersion >= 80013 && $token->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->exprWithParentheses(); + } else { + throw new \Exception('Unexpected token in columnAttribute: ' . $token->getText()); + } + break; + case MySQLLexer::ON_SYMBOL: + $children[] = ASTNode::fromToken($token); + $this->match(MySQLLexer::UPDATE_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::UPDATE_SYMBOL)); + $this->match(MySQLLexer::NOW_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::NOW_SYMBOL)); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->timeFunctionParameters(); + } + break; + case MySQLLexer::AUTO_INCREMENT_SYMBOL: + $children[] = ASTNode::fromToken($token); + break; + case MySQLLexer::SERIAL_SYMBOL: + $children[] = ASTNode::fromToken($token); + $this->match(MySQLLexer::DEFAULT_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::DEFAULT_SYMBOL)); + $this->match(MySQLLexer::VALUE_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::VALUE_SYMBOL)); + break; + case MySQLLexer::PRIMARY_SYMBOL: + $children[] = ASTNode::fromToken($token); + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::KEY_SYMBOL: + $children[] = ASTNode::fromToken($token); + break; + default: + throw new \Exception('Unexpected token in columnAttribute: ' . $token->getText()); + } + break; + case MySQLLexer::KEY_SYMBOL: + $children[] = ASTNode::fromToken($token); + break; + case MySQLLexer::UNIQUE_SYMBOL: + $children[] = ASTNode::fromToken($token); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_SYMBOL) { + $this->match(MySQLLexer::KEY_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::KEY_SYMBOL)); + } + break; + case MySQLLexer::COMMENT_SYMBOL: + $children[] = ASTNode::fromToken($token); + $children[] = $this->textLiteral(); + break; + case MySQLLexer::COLLATE_SYMBOL: + $children[] = $this->collate(); + break; + case MySQLLexer::COLUMN_FORMAT_SYMBOL: + $children[] = ASTNode::fromToken($token); + $children[] = $this->columnFormat(); + break; + case MySQLLexer::STORAGE_SYMBOL: + $children[] = ASTNode::fromToken($token); + $children[] = $this->storageMedia(); + break; + case MySQLLexer::SRID_SYMBOL: + if ($this->serverVersion >= 80000) { + $children[] = ASTNode::fromToken($token); + $children[] = $this->real_ulonglong_number(); + break; + } + case MySQLLexer::CONSTRAINT_SYMBOL: + if ($this->serverVersion >= 80017) { + $children[] = $this->constraintName(); + $children[] = $this->checkConstraint(); + break; + } + case MySQLLexer::ENFORCED_SYMBOL: + if ($this->serverVersion >= 80017) { + $children[] = $this->constraintEnforcement(); + break; + } + default: + throw new \Exception('Unexpected token in columnAttribute: ' . $token->getText()); + } + + return new ASTNode('columnAttribute', $children); + } + + private function isColumnAttributeStart($token) + { + return $token->getType() === MySQLLexer::NOT_SYMBOL || + $token->getType() === MySQLLexer::NULL_SYMBOL || + $token->getType() === MySQLLexer::DEFAULT_SYMBOL || + $token->getType() === MySQLLexer::ON_SYMBOL || + $token->getType() === MySQLLexer::AUTO_INCREMENT_SYMBOL || + $token->getType() === MySQLLexer::SERIAL_SYMBOL || + $token->getType() === MySQLLexer::PRIMARY_SYMBOL || + $token->getType() === MySQLLexer::KEY_SYMBOL || + $token->getType() === MySQLLexer::UNIQUE_SYMBOL || + $token->getType() === MySQLLexer::COMMENT_SYMBOL || + $token->getType() === MySQLLexer::COLLATE_SYMBOL || + $token->getType() === MySQLLexer::COLUMN_FORMAT_SYMBOL || + $token->getType() === MySQLLexer::STORAGE_SYMBOL || + ($this->serverVersion >= 80000 && $token->getType() === MySQLLexer::SRID_SYMBOL) || + ($this->serverVersion >= 80017 && + ($token->getType() === MySQLLexer::CONSTRAINT_SYMBOL || + $token->getType() === MySQLLexer::ENFORCED_SYMBOL)); + } + + public function references() + { + $children = []; + + $children[] = $this->match(MySQLLexer::REFERENCES_SYMBOL); + $children[] = $this->tableRef(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->identifierListWithParentheses(); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::MATCH_SYMBOL) { + $children[] = $this->match(MySQLLexer::MATCH_SYMBOL); + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::FULL_SYMBOL) { + $children[] = $this->match(MySQLLexer::FULL_SYMBOL); + } elseif ($token->getType() === MySQLLexer::PARTIAL_SYMBOL) { + $children[] = $this->match(MySQLLexer::PARTIAL_SYMBOL); + } elseif ($token->getType() === MySQLLexer::SIMPLE_SYMBOL) { + $children[] = $this->match(MySQLLexer::SIMPLE_SYMBOL); + } else { + throw new \Exception('Unexpected token in references: ' . $token->getText()); + } + } + + $token = $this->lexer->peekNextToken(2); + + if ($token->getType() === MySQLLexer::UPDATE_SYMBOL) { + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + $children[] = $this->match(MySQLLexer::UPDATE_SYMBOL); + $children[] = $this->deleteOption(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ON_SYMBOL) { + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + $children[] = $this->match(MySQLLexer::DELETE_SYMBOL); + $children[] = $this->deleteOption(); + } + } elseif ($token->getType() === MySQLLexer::DELETE_SYMBOL) { + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + $children[] = $this->match(MySQLLexer::DELETE_SYMBOL); + $children[] = $this->deleteOption(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ON_SYMBOL) { + $children[] = $this->match(MySQLLexer::ON_SYMBOL); + $children[] = $this->match(MySQLLexer::UPDATE_SYMBOL); + $children[] = $this->deleteOption(); + } + } + + return new ASTNode('references', $children); + } + + public function keyList() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->keyPart(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->keyPart(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('keyList', $children); + } + + public function keyPart() + { + $children = []; + $children[] = $this->identifier(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->fieldLength(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ASC_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DESC_SYMBOL) { + $children[] = $this->direction(); + } + return new ASTNode('keyPart', $children); + } + + public function keyListWithExpression() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->keyPartOrExpression(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->keyPartOrExpression(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + + return new ASTNode('keyListWithExpression', $children); + } + + public function keyPartOrExpression() + { + $children = []; + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->exprWithParentheses(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::ASC_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DESC_SYMBOL) { + $children[] = $this->direction(); + } + } elseif ($this->isIdentifierStart($this->lexer->peekNextToken())) { + $children[] = $this->keyPart(); + } else { + throw new \Exception('Unexpected token in keyPartOrExpression: ' . $this->lexer->peekNextToken()->getText()); + } + + return new ASTNode('keyPartOrExpression', $children); + } + + public function keyListVariants() + { + if ($this->serverVersion >= 80013) { + return $this->keyListWithExpression(); + } else { + return $this->keyList(); + } + } + + public function indexType() +{ + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::BTREE_SYMBOL: + case MySQLLexer::HASH_SYMBOL: + case MySQLLexer::RTREE_SYMBOL: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in indexType: ' . $token->getText()); + } +} + + public function checkOption() + { + $token = $this->lexer->peekNextToken(); + $children = []; + if ($token->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->match(MySQLLexer::UPGRADE_SYMBOL); + return new ASTNode('checkOption', $children); + } elseif ($token->getType() === MySQLLexer::QUICK_SYMBOL) { + return $this->match(MySQLLexer::QUICK_SYMBOL); + } elseif ($token->getType() === MySQLLexer::FAST_SYMBOL) { + return $this->match(MySQLLexer::FAST_SYMBOL); + } elseif ($token->getType() === MySQLLexer::MEDIUM_SYMBOL) { + return $this->match(MySQLLexer::MEDIUM_SYMBOL); + } elseif ($token->getType() === MySQLLexer::EXTENDED_SYMBOL) { + return $this->match(MySQLLexer::EXTENDED_SYMBOL); + } elseif ($token->getType() === MySQLLexer::CHANGED_SYMBOL) { + return $this->match(MySQLLexer::CHANGED_SYMBOL); + } else { + throw new \Exception('Unexpected token in checkOption: ' . $token->getText()); + } + } + + public function runtimeFunctionCall() + { + $token = $this->lexer->peekNextToken(); + $children = []; + if ($token->getType() === MySQLLexer::CHAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::CHAR_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->exprList(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::USING_SYMBOL) { + $children[] = $this->match(MySQLLexer::USING_SYMBOL); + $children[] = $this->charsetName(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::CURRENT_USER_SYMBOL) { + $children[] = $this->match(MySQLLexer::CURRENT_USER_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->parentheses(); + } + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::DATE_SYMBOL) { + $children[] = $this->match(MySQLLexer::DATE_SYMBOL); + $children[] = $this->exprWithParentheses(); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::DAY_SYMBOL) { + $children[] = $this->match(MySQLLexer::DAY_SYMBOL); + $children[] = $this->exprWithParentheses(); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::HOUR_SYMBOL) { + $children[] = $this->match(MySQLLexer::HOUR_SYMBOL); + $children[] = $this->exprWithParentheses(); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::INSERT_SYMBOL) { + $children[] = $this->match(MySQLLexer::INSERT_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::INTERVAL_SYMBOL) { + $children[] = $this->match(MySQLLexer::INTERVAL_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->expr(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->expr(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::LEFT_SYMBOL) { + $children[] = $this->match(MySQLLexer::LEFT_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::MICROSECOND_SYMBOL) { + $children[] = $this->match(MySQLLexer::MICROSECOND_SYMBOL); + $children[] = $this->exprWithParentheses(); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::MINUTE_SYMBOL) { + $children[] = $this->match(MySQLLexer::MINUTE_SYMBOL); + $children[] = $this->exprWithParentheses(); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::MONTH_SYMBOL) { + $children[] = $this->match(MySQLLexer::MONTH_SYMBOL); + $children[] = $this->exprWithParentheses(); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::RIGHT_SYMBOL) { + $children[] = $this->match(MySQLLexer::RIGHT_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::SECOND_SYMBOL) { + $children[] = $this->match(MySQLLexer::SECOND_SYMBOL); + $children[] = $this->exprWithParentheses(); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::TIME_SYMBOL) { + $children[] = $this->match(MySQLLexer::TIME_SYMBOL); + $children[] = $this->exprWithParentheses(); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::TIMESTAMP_SYMBOL) { + $children[] = $this->match(MySQLLexer::TIMESTAMP_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->expr(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->expr(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::TRIM_SYMBOL) { + return $this->trimFunction(); + } elseif ($token->getType() === MySQLLexer::USER_SYMBOL) { + $children[] = $this->match(MySQLLexer::USER_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->parentheses(); + } + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::VALUES_SYMBOL) { + $children[] = $this->match(MySQLLexer::VALUES_SYMBOL); + $children[] = $this->exprWithParentheses(); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::YEAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::YEAR_SYMBOL); + $children[] = $this->exprWithParentheses(); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::ADDDATE_SYMBOL || + $token->getType() === MySQLLexer::SUBDATE_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::INTERVAL_SYMBOL) { + $children[] = $this->match(MySQLLexer::INTERVAL_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->interval(); + } else { + $children[] = $this->expr(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::CURDATE_SYMBOL) { + $children[] = $this->match(MySQLLexer::CURDATE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->parentheses(); + } + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::CURTIME_SYMBOL) { + $children[] = $this->match(MySQLLexer::CURTIME_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->timeFunctionParameters(); + } + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::DATE_ADD_SYMBOL || + $token->getType() === MySQLLexer::DATE_SUB_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->match(MySQLLexer::INTERVAL_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->interval(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::EXTRACT_SYMBOL) { + $children[] = $this->match(MySQLLexer::EXTRACT_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->interval(); + $children[] = $this->match(MySQLLexer::FROM_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::GET_FORMAT_SYMBOL) { + $children[] = $this->match(MySQLLexer::GET_FORMAT_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->dateTimeTtype(); + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::NOW_SYMBOL) { + $children[] = $this->match(MySQLLexer::NOW_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->timeFunctionParameters(); + } + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::POSITION_SYMBOL) { + $children[] = $this->match(MySQLLexer::POSITION_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->bitExpr(); + $children[] = $this->match(MySQLLexer::IN_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::SUBSTRING_SYMBOL || + $token->getType() === MySQLLexer::SUBSTR_SYMBOL) { + return $this->substringFunction(); + } elseif ($token->getType() === MySQLLexer::SYSDATE_SYMBOL) { + $children[] = $this->match(MySQLLexer::SYSDATE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->timeFunctionParameters(); + } + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::TIMESTAMP_ADD_SYMBOL || + $token->getType() === MySQLLexer::TIMESTAMP_DIFF_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->intervalTimeStamp(); + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::UTC_DATE_SYMBOL) { + $children[] = $this->match(MySQLLexer::UTC_DATE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->parentheses(); + } + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::UTC_TIME_SYMBOL) { + $children[] = $this->match(MySQLLexer::UTC_TIME_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->timeFunctionParameters(); + } + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($token->getType() === MySQLLexer::UTC_TIMESTAMP_SYMBOL) { + $children[] = $this->match(MySQLLexer::UTC_TIMESTAMP_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->timeFunctionParameters(); + } + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($this->isRuntimeFunctionCallStart($token)) { + $children[] = $this->identifierKeyword(); + $children[] = $this->exprWithParentheses(); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($this->isRuntimeFunctionCallStart($token)) { + $children[] = $this->identifierKeyword(); + $children[] = $this->exprListWithParentheses(); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($this->isRuntimeFunctionCallStart($token)) { + $children[] = $this->identifierKeyword(); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->expr(); + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->expr(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->expr(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('runtimeFunctionCall', $children); + } elseif ($this->isRuntimeFunctionCallStart($token)) { + $children[] = $this->identifierKeyword(); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->expr(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->expr(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('runtimeFunctionCall', $children); + } else { + throw new \Exception('Unexpected token in runtimeFunctionCall: ' . $token->getText()); + } + } + + + public function repairType() +{ + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::QUICK_SYMBOL: + case MySQLLexer::EXTENDED_SYMBOL: + case MySQLLexer::USE_FRM_SYMBOL: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in indexType: ' . $token->getText()); + } +} + + // Partition rules for CREATE/ALTER TABLE. + public function partitionClause() + { + $children = []; + + $children[] = $this->match(MySQLLexer::PARTITION_SYMBOL); + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + $children[] = $this->partitionTypeDef(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::PARTITIONS_SYMBOL) { + $children[] = $this->match(MySQLLexer::PARTITIONS_SYMBOL); + $children[] = $this->real_ulong_number(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::SUBPARTITION_SYMBOL) { + $children[] = $this->subPartitions(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->partitionDefinitions(); + } + + return new ASTNode('partitionClause', $children); + } + + public function partitionTypeDef() + { + $children = []; + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::LINEAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::LINEAR_SYMBOL); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::KEY_SYMBOL) { + $children[] = $this->match(MySQLLexer::KEY_SYMBOL); + if ($this->serverVersion >= 50700 && $this->lexer->peekNextToken()->getType() === MySQLLexer::ALGORITHM_SYMBOL) { + $children[] = $this->partitionKeyAlgorithm(); + } + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + $children[] = $this->identifierList(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('partitionTypeDef', $children); + } elseif ($token->getType() === MySQLLexer::HASH_SYMBOL) { + $children[] = $this->match(MySQLLexer::HASH_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->bitExpr(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('partitionTypeDef', $children); + } else { + throw new \Exception('Unexpected token in partitionTypeDef: ' . $token->getText()); + } + } elseif ($token->getType() === MySQLLexer::KEY_SYMBOL) { + $children[] = $this->match(MySQLLexer::KEY_SYMBOL); + if ($this->serverVersion >= 50700 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::ALGORITHM_SYMBOL) { + $children[] = $this->partitionKeyAlgorithm(); + } + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + $children[] = $this->identifierList(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('partitionTypeDef', $children); + } elseif ($token->getType() === MySQLLexer::HASH_SYMBOL) { + $children[] = $this->match(MySQLLexer::HASH_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->bitExpr(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('partitionTypeDef', $children); + } elseif ($token->getType() === MySQLLexer::RANGE_SYMBOL || + $token->getType() === MySQLLexer::LIST_SYMBOL) { + if ($token->getType() === MySQLLexer::RANGE_SYMBOL) { + $children[] = $this->match(MySQLLexer::RANGE_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::LIST_SYMBOL); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COLUMNS_SYMBOL) { + $children[] = $this->match(MySQLLexer::COLUMNS_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + $children[] = $this->identifierList(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->bitExpr(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } + + return new ASTNode('partitionTypeDef', $children); + } else { + throw new \Exception('Unexpected token in partitionTypeDef: ' . $token->getText()); + } + } + + public function subPartitions() + { + $children = []; + + $children[] = $this->match(MySQLLexer::SUBPARTITION_SYMBOL); + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LINEAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::LINEAR_SYMBOL); + } + + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::HASH_SYMBOL) { + $children[] = $this->match(MySQLLexer::HASH_SYMBOL); + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->bitExpr(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } elseif ($token->getType() === MySQLLexer::KEY_SYMBOL) { + $children[] = $this->match(MySQLLexer::KEY_SYMBOL); + + if ($this->serverVersion >= 50700 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::ALGORITHM_SYMBOL) { + $children[] = $this->partitionKeyAlgorithm(); + } + + $children[] = $this->identifierListWithParentheses(); + } else { + throw new \Exception('Unexpected token in subPartitions: ' . $token->getText()); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::SUBPARTITIONS_SYMBOL) { + $children[] = $this->match(MySQLLexer::SUBPARTITIONS_SYMBOL); + $children[] = $this->real_ulong_number(); + } + + return new ASTNode('subPartitions', $children); + } + + public function partitionKeyAlgorithm() + { + $children = []; + + $children[] = $this->match(MySQLLexer::ALGORITHM_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->real_ulong_number(); + + return new ASTNode('partitionKeyAlgorithm', $children); + } + + public function partitionDefinitions() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->partitionDefinition(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->partitionDefinition(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + + return new ASTNode('partitionDefinitions', $children); + } + + public function partitionDefinition() + { + $children = []; + + $children[] = $this->match(MySQLLexer::PARTITION_SYMBOL); + $children[] = $this->identifier(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::VALUES_SYMBOL) { + $children[] = $this->match(MySQLLexer::VALUES_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LESS_SYMBOL) { + $children[] = $this->match(MySQLLexer::LESS_SYMBOL); + $children[] = $this->match(MySQLLexer::THAN_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->partitionValueItemListParen(); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::MAXVALUE_SYMBOL) { + $children[] = $this->match(MySQLLexer::MAXVALUE_SYMBOL); + } else { + throw new \Exception( + 'Unexpected token in partitionDefinition: ' . $this->lexer->peekNextToken()->getText() + ); + } + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::IN_SYMBOL) { + $children[] = $this->match(MySQLLexer::IN_SYMBOL); + $children[] = $this->partitionValuesIn(); + } else { + throw new \Exception('Unexpected token in partitionDefinition: ' . $this->lexer->peekNextToken()->getText()); + } + } + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::ENGINE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NODEGROUP_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::MAX_ROWS_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::MIN_ROWS_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DATA_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INDEX_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::COMMENT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::TABLESPACE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::STORAGE_SYMBOL) { + $children[] = $this->partitionOption(); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->subpartitionDefinition(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->subpartitionDefinition(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } + + return new ASTNode('partitionDefinition', $children); + } + + public function partitionValuesIn() + { + if ($this->lexer->peekNextToken(2)->getType() === MySQLLexer::COMMA_SYMBOL) { + $children = []; + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->partitionValueItemListParen(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->partitionValueItemListParen(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('partitionValuesIn', $children); + } else { + return $this->partitionValueItemListParen(); + } + } + + public function partitionOption() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::COMMENT_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMENT_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + + $children[] = $this->textLiteral(); + } elseif (($token->getType() === MySQLLexer::DATA_SYMBOL || $token->getType() === MySQLLexer::INDEX_SYMBOL) && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::DIRECTORY_SYMBOL) { + if ($token->getType() === MySQLLexer::DATA_SYMBOL) { + $children[] = $this->match(MySQLLexer::DATA_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::INDEX_SYMBOL); + } + + $children[] = $this->match(MySQLLexer::DIRECTORY_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + + $children[] = $this->textLiteral(); + } elseif ($token->getType() === MySQLLexer::ENGINE_SYMBOL) { + $children[] = $this->match(MySQLLexer::ENGINE_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + + $children[] = $this->engineRef(); + } elseif (($token->getType() === MySQLLexer::STORAGE_SYMBOL || + $token->getType() === MySQLLexer::ENGINE_SYMBOL) && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::ENGINE_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::STORAGE_SYMBOL) { + $children[] = $this->match(MySQLLexer::STORAGE_SYMBOL); + } + + $children[] = $this->match(MySQLLexer::ENGINE_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + + $children[] = $this->engineRef(); + } elseif ($token->getType() === MySQLLexer::MAX_ROWS_SYMBOL || $token->getType() === MySQLLexer::MIN_ROWS_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + $children[] = new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->real_ulong_number(); + } elseif ($token->getType() === MySQLLexer::NODEGROUP_SYMBOL) { + $children[] = $this->match(MySQLLexer::NODEGROUP_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->real_ulong_number(); + } elseif ($token->getType() === MySQLLexer::TABLESPACE_SYMBOL) { + $children[] = $this->match(MySQLLexer::TABLESPACE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->identifier(); + } else { + throw new \Exception('Unexpected token in partitionOption: ' . $token->getText()); + } + + return new ASTNode('partitionOption', $children); + } + + public function subpartitionDefinition() + { + $children = []; + + $children[] = $this->match(MySQLLexer::SUBPARTITION_SYMBOL); + $children[] = $this->textOrIdentifier(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::ENGINE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::NODEGROUP_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::MAX_ROWS_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::MIN_ROWS_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DATA_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INDEX_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::COMMENT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::TABLESPACE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::STORAGE_SYMBOL) { + $children[] = $this->partitionOption(); + } + + return new ASTNode('subpartitionDefinition', $children); + } + + public function partitionValueItemListParen() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->partitionValueItem(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->partitionValueItem(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('partitionValueItemListParen', $children); + } + + public function partitionValueItem() + { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::MAXVALUE_SYMBOL) { + return $this->match(MySQLLexer::MAXVALUE_SYMBOL); + } else { + return $this->bitExpr(); + } + } + + public function definerClause() + { + $children = []; + + $children[] = $this->match(MySQLLexer::DEFINER_SYMBOL); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = $this->user(); + return new ASTNode('definerClause', $children); + } + + public function ifExists() + { + $children = []; + + $children[] = $this->match(MySQLLexer::IF_SYMBOL); + $children[] = $this->match(MySQLLexer::EXISTS_SYMBOL); + return new ASTNode('ifExists', $children); + } + + public function ifNotExists() + { + $children = []; + + $children[] = $this->match(MySQLLexer::IF_SYMBOL); + $children[] = $this->notRule(); + $children[] = $this->match(MySQLLexer::EXISTS_SYMBOL); + + return new ASTNode('ifNotExists', $children); + } + + public function procedureParameter() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::IN_SYMBOL) { + $children[] = $this->match(MySQLLexer::IN_SYMBOL); + } elseif ($token->getType() === MySQLLexer::OUT_SYMBOL) { + $children[] = $this->match(MySQLLexer::OUT_SYMBOL); + } elseif ($token->getType() === MySQLLexer::INOUT_SYMBOL) { + $children[] = $this->match(MySQLLexer::INOUT_SYMBOL); + } + + $children[] = $this->functionParameter(); + return new ASTNode('procedureParameter', $children); + } + + public function functionParameter() + { + $children = []; + + $children[] = $this->parameterName(); + $children[] = $this->typeWithOptCollate(); + return new ASTNode('functionParameter', $children); + } + + public function collate() + { + $children = []; + + $children[] = $this->match(MySQLLexer::COLLATE_SYMBOL); + $children[] = $this->collationName(); + return new ASTNode('collate', $children); + } + + public function typeWithOptCollate() + { + $children = []; + + $children[] = $this->dataType(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::COLLATE_SYMBOL) { + $children[] = $this->collate(); + } + return new ASTNode('typeWithOptCollate', $children); + } + + public function allOrPartitionNameList() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::ALL_SYMBOL) { + return $this->match(MySQLLexer::ALL_SYMBOL); + } elseif ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token)) { + return $this->identifierList(); + } else { + throw new \Exception('Unexpected token in allOrPartitionNameList: ' . $token->getText()); + } + } + + public function schemaIdentifierPair() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->schemaRef(); + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->schemaRef(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + + return new ASTNode('schemaIdentifierPair', $children); + } + + public function viewRefList() + { + $children = []; + + $children[] = $this->viewRef(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->viewRef(); + } + + return new ASTNode('viewRefList', $children); + } + + public function updateList() + { + $children = []; + $children[] = $this->updateElement(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->updateElement(); + } + return new ASTNode('updateList', $children); + } + + public function updateElement() + { + $children = []; + $children[] = $this->columnRef(); + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + $token = $this->lexer->peekNextToken(); + + if ($this->isExprStart($token)) { + $children[] = $this->expr(); + } elseif ($token->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->match(MySQLLexer::DEFAULT_SYMBOL); + } else { + throw new \Exception('Unexpected token in updateElement: ' . $token->getText()); + } + + return new ASTNode('updateElement', $children); + } + + public function charsetClause() + { + $children = []; + $children[] = $this->charset(); + $children[] = $this->charsetName(); + return new ASTNode('charsetClause', $children); + } + + public function fieldsClause() + { + $children = []; + $children[] = $this->match(MySQLLexer::FIELDS_SYMBOL); + do { + $children[] = $this->fieldTerm(); + } while ($this->lexer->peekNextToken()->getType() === MySQLLexer::TERMINATED_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::OPTIONALLY_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ENCLOSED_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ESCAPED_SYMBOL); + return new ASTNode('fieldsClause', $children); + } + + public function fieldTerm() + { + $children = []; + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::TERMINATED_SYMBOL) { + $children[] = $this->match(MySQLLexer::TERMINATED_SYMBOL); + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + $children[] = $this->textString(); + } elseif ($token->getType() === MySQLLexer::OPTIONALLY_SYMBOL || + $token->getType() === MySQLLexer::ENCLOSED_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPTIONALLY_SYMBOL) { + $children[] = $this->match(MySQLLexer::OPTIONALLY_SYMBOL); + } + $children[] = $this->match(MySQLLexer::ENCLOSED_SYMBOL); + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + $children[] = $this->textString(); + } elseif ($token->getType() === MySQLLexer::ESCAPED_SYMBOL) { + $children[] = $this->match(MySQLLexer::ESCAPED_SYMBOL); + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + $children[] = $this->textString(); + } else { + throw new \Exception('Unexpected token in fieldTerm: ' . $token->getText()); + } + return new ASTNode('fieldTerm', $children); + } + + public function linesClause() + { + $children = []; + $children[] = $this->match(MySQLLexer::LINES_SYMBOL); + do { + $children[] = $this->lineTerm(); + } while ($this->lexer->peekNextToken()->getType() === MySQLLexer::TERMINATED_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::STARTING_SYMBOL); + return new ASTNode('linesClause', $children); + } + + public function lineTerm() + { + $children = []; + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::STARTING_SYMBOL) { + $children[] = $this->match(MySQLLexer::STARTING_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::TERMINATED_SYMBOL) { + $children[] = $this->match(MySQLLexer::TERMINATED_SYMBOL); + } else { + throw new \Exception('Unexpected token in lineTerm: ' . $this->lexer->peekNextToken()->getText()); + } + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + $children[] = $this->textString(); + + return new ASTNode('lineTerm', $children); + } + + public function userList() + { + $children = []; + $children[] = $this->user(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->user(); + } + return new ASTNode('userList', $children); + } + + public function createUserList() + { + $children = []; + $children[] = $this->createUserEntry(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->createUserEntry(); + } + return new ASTNode('createUserList', $children); + } + + public function alterUserList() + { + $children = []; + $children[] = $this->alterUserEntry(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->alterUserEntry(); + } + return new ASTNode('alterUserList', $children); + } + + public function createUserEntry() + { + $children = []; + $children[] = $this->user(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIED_SYMBOL) { + $children[] = $this->match(MySQLLexer::IDENTIFIED_SYMBOL); + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::BY_SYMBOL) { + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + if ($this->serverVersion < 80011 && $this->lexer->peekNextToken()->getType() === MySQLLexer::PASSWORD_SYMBOL) { + $children[] = $this->match(MySQLLexer::PASSWORD_SYMBOL); + } + $children[] = $this->textString(); + } elseif ($token->getType() === MySQLLexer::WITH_SYMBOL) { + $children[] = $this->match(MySQLLexer::WITH_SYMBOL); + $children[] = $this->textOrIdentifier(); + + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::AS_SYMBOL) { + $children[] = $this->match(MySQLLexer::AS_SYMBOL); + $children[] = $this->textStringHash(); + } elseif ($this->serverVersion >= 50706 && $token->getType() === MySQLLexer::BY_SYMBOL) { + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + $children[] = $this->textString(); + } elseif ($this->serverVersion >= 80018 && $token->getType() === MySQLLexer::BY_SYMBOL) { + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + $children[] = $this->match(MySQLLexer::RANDOM_SYMBOL); + $children[] = $this->match(MySQLLexer::PASSWORD_SYMBOL); + } else { + throw new \Exception('Unexpected token in createUserEntry: ' . $token->getText()); + } + } else { + throw new \Exception('Unexpected token in createUserEntry: ' . $token->getText()); + } + } + return new ASTNode('createUserEntry', $children); + } + + public function alterUserEntry() + { + $children = []; + $children[] = $this->user(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIED_SYMBOL) { + $children[] = $this->match(MySQLLexer::IDENTIFIED_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::WITH_SYMBOL) { + $children[] = $this->match(MySQLLexer::WITH_SYMBOL); + $children[] = $this->textOrIdentifier(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::AS_SYMBOL) { + $children[] = $this->match(MySQLLexer::AS_SYMBOL); + $children[] = $this->textStringHash(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::RETAIN_SYMBOL) { + $children[] = $this->retainCurrentPassword(); + } + } else { + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + $children[] = $this->textString(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::REPLACE_SYMBOL) { + $children[] = $this->match(MySQLLexer::REPLACE_SYMBOL); + $children[] = $this->textString(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::RETAIN_SYMBOL) { + $children[] = $this->retainCurrentPassword(); + } + } + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::BY_SYMBOL) { + $children[] = $this->match(MySQLLexer::BY_SYMBOL); + $children[] = $this->textString(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::REPLACE_SYMBOL) { + $children[] = $this->replacePassword(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::RETAIN_SYMBOL) { + $children[] = $this->retainCurrentPassword(); + } + } else { + throw new \Exception('Unexpected token in alterUserEntry: ' . $this->lexer->peekNextToken()->getText()); + } + } elseif ($this->serverVersion >= 80014 && $this->lexer->peekNextToken()->getType() === MySQLLexer::DISCARD_SYMBOL) { + $children[] = $this->discardOldPassword(); + } + return new ASTNode('alterUserEntry', $children); + } + + public function indexOption() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::KEY_BLOCK_SIZE_SYMBOL || + $token->getType() === MySQLLexer::COMMENT_SYMBOL || + ($this->serverVersion >= 80000 && + ($token->getType() === MySQLLexer::VISIBLE_SYMBOL || + $token->getType() === MySQLLexer::INVISIBLE_SYMBOL))) { + return $this->commonIndexOption(); + } elseif ($token->getType() === MySQLLexer::USING_SYMBOL || $token->getType() === MySQLLexer::TYPE_SYMBOL) { + return $this->indexTypeClause(); + } else { + throw new \Exception('Unexpected token in indexOption: ' . $token->getText()); + } + } + + // These options are common for all index types. + public function commonIndexOption() + { + $token = $this->lexer->peekNextToken(); + $children = []; + if ($token->getType() === MySQLLexer::KEY_BLOCK_SIZE_SYMBOL) { + $children[] = $this->match(MySQLLexer::KEY_BLOCK_SIZE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::COMMENT_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMENT_SYMBOL); + $children[] = $this->textLiteral(); + } elseif ($this->serverVersion >= 80000 && + ($token->getType() === MySQLLexer::VISIBLE_SYMBOL || + $token->getType() === MySQLLexer::INVISIBLE_SYMBOL)) { + $children[] = $this->visibility(); + } else { + throw new \Exception('Unexpected token in commonIndexOption: ' . $token->getText()); + } + return new ASTNode('commonIndexOption', $children); + } + public function precision() + { + $children = []; + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->match(MySQLLexer::INT_NUMBER); + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->match(MySQLLexer::INT_NUMBER); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('precision', $children); + } + + public function channel() + { + $children = []; + if ($this->serverVersion >= 50706) { + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->match(MySQLLexer::CHANNEL_SYMBOL); + $children[] = $this->textStringNoLinebreak(); + + return new ASTNode('channel', $children); + } + throw new \Exception('Unexpected token in channel: ' . $this->lexer->peekNextToken()->getText()); + } + + public function userVariable() + { + $children = []; + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::AT_SIGN_SYMBOL: + $children[] = ASTNode::fromToken($token); + $children[] = $this->textOrIdentifier(); + break; + case MySQLLexer::AT_TEXT_SUFFIX: + $children[] = ASTNode::fromToken($token); + break; + default: + throw new \Exception('Unexpected token in userVariable: ' . $token->getText()); + } + + return new ASTNode('userVariable', $children); + } + + public function user() + { + $children = []; + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::IDENTIFIER: + case MySQLLexer::BACK_TICK_QUOTED_ID: + case MySQLLexer::DOUBLE_QUOTED_TEXT: + case MySQLLexer::SINGLE_QUOTED_TEXT: + $children[] = ASTNode::fromToken($token); + break; + case MySQLLexer::CURRENT_USER_SYMBOL: + $children[] = ASTNode::fromToken($token); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->parentheses(); + } + break; + case MySQLLexer::AT_SIGN_SYMBOL: + $children[] = ASTNode::fromToken($token); + $children[] = $this->textOrIdentifier(); + break; + case MySQLLexer::AT_TEXT_SUFFIX: + $children[] = ASTNode::fromToken($token); + break; + default: + if ($this->isIdentifierKeyword($token)) { + $children[] = $this->identifierKeyword(); + break; + } + throw new \Exception('Unexpected token in user: ' . $token->getText()); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::AT_SIGN_SYMBOL) { + $this->match(MySQLLexer::AT_SIGN_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::AT_SIGN_SYMBOL)); + $children[] = $this->textOrIdentifier(); + } + + return new ASTNode('user', $children); + } + + public function parentheses() + { + $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + + return new ASTNode('parentheses'); + } + + public function fulltextIndexOption() + { + $token = $this->lexer->peekNextToken(); + $children = []; + if ($token->getType() === MySQLLexer::KEY_BLOCK_SIZE_SYMBOL || + $token->getType() === MySQLLexer::COMMENT_SYMBOL || + ($this->serverVersion >= 80000 && + ($token->getType() === MySQLLexer::VISIBLE_SYMBOL || + $token->getType() === MySQLLexer::INVISIBLE_SYMBOL))) { + return $this->commonIndexOption(); + } elseif ($token->getType() === MySQLLexer::WITH_SYMBOL) { + $children[] = $this->match(MySQLLexer::WITH_SYMBOL); + $children[] = $this->match(MySQLLexer::PARSER_SYMBOL); + $children[] = $this->identifier(); + } else { + throw new \Exception('Unexpected token in fulltextIndexOption: ' . $token->getText()); + } + + return new ASTNode('fulltextIndexOption', $children); + } + + public function spatialIndexOption() + { + return $this->commonIndexOption(); + } + + public function dataTypeDefinition() + { + $children = []; + $children[] = $this->dataType(); + return new ASTNode('dataTypeDefinition', $children); + } + + public function dataType() + { + $children = []; + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::TINYINT_SYMBOL || + $token->getType() === MySQLLexer::SMALLINT_SYMBOL || + $token->getType() === MySQLLexer::MEDIUMINT_SYMBOL || + $token->getType() === MySQLLexer::INT_SYMBOL || + $token->getType() === MySQLLexer::BIGINT_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + $children[] = new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->fieldLength(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::SIGNED_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::UNSIGNED_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ZEROFILL_SYMBOL) { + $children[] = $this->fieldOptions(); + } + } elseif ($token->getType() === MySQLLexer::REAL_SYMBOL || $token->getType() === MySQLLexer::DOUBLE_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + $children[] = new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::PRECISION_SYMBOL) { + $this->match(MySQLLexer::PRECISION_SYMBOL); + $children[] = ASTNode::fromToken($token); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->precision(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::SIGNED_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::UNSIGNED_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ZEROFILL_SYMBOL) { + $children[] = $this->fieldOptions(); + } + } elseif ($token->getType() === MySQLLexer::FLOAT_SYMBOL || + $token->getType() === MySQLLexer::DECIMAL_SYMBOL || + $token->getType() === MySQLLexer::NUMERIC_SYMBOL || + $token->getType() === MySQLLexer::FIXED_SYMBOL) { + $children[] = ASTNode::fromToken($this->lexer->getNextToken()); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->floatOptions(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::SIGNED_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::UNSIGNED_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ZEROFILL_SYMBOL) { + $children[] = $this->fieldOptions(); + } + } elseif ($token->getType() === MySQLLexer::BIT_SYMBOL) { + $children[] = $this->match(MySQLLexer::BIT_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->fieldLength(); + } + } elseif ($token->getType() === MySQLLexer::BOOL_SYMBOL || $token->getType() === MySQLLexer::BOOLEAN_SYMBOL) { + if ($token->getType() === MySQLLexer::BOOL_SYMBOL) { + $children[] = $this->match(MySQLLexer::BOOL_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::BOOLEAN_SYMBOL); + } + } elseif ($token->getType() === MySQLLexer::CHAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::CHAR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->fieldLength(); + } + if ($this->isCharsetWithOptBinaryStart($this->lexer->peekNextToken())) { + $children[] = $this->charsetWithOptBinary(); + } + } elseif ($token->getType() === MySQLLexer::NCHAR_SYMBOL || + $token->getType() === MySQLLexer::NATIONAL_SYMBOL) { + $children[] = $this->nchar(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->fieldLength(); + } + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::BINARY_SYMBOL) { + $children[] = $this->match(MySQLLexer::BINARY_SYMBOL); + } + } elseif ($token->getType() === MySQLLexer::BINARY_SYMBOL) { + $children[] = $this->match(MySQLLexer::BINARY_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->fieldLength(); + } + } elseif ( + $token->getType() === MySQLLexer::CHAR_SYMBOL || + $token->getType() === MySQLLexer::VARCHAR_SYMBOL + ) { + if ($token->getType() === MySQLLexer::CHAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::CHAR_SYMBOL); + $children[] = $this->match(MySQLLexer::VARYING_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::VARCHAR_SYMBOL); + } + $children[] = $this->fieldLength(); + if($this->isCharsetWithOptBinaryStart($this->lexer->peekNextToken())) { + $children[] = $this->charsetWithOptBinary(); + } + } elseif ($token->getType() === MySQLLexer::NATIONAL_SYMBOL || + $token->getType() === MySQLLexer::NVARCHAR_SYMBOL || + $token->getType() === MySQLLexer::NCHAR_SYMBOL) { + if ($token->getType() === MySQLLexer::NATIONAL_SYMBOL) { + $children[] = $this->match(MySQLLexer::NATIONAL_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::VARCHAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::VARCHAR_SYMBOL); + } elseif ( + $this->lexer->peekNextToken()->getType() === MySQLLexer::CHAR_SYMBOL && + $this->lexer->peekNextToken()->getType(2) === MySQLLexer::VARYING_SYMBOL + ) { + $children[] = $this->match(MySQLLexer::CHAR_SYMBOL); + $children[] = $this->match(MySQLLexer::VARYING_SYMBOL); + } else { + throw new \Exception('Unexpected token in dataType: ' . $this->lexer->peekNextToken()->getText()); + } + } elseif ($token->getType() === MySQLLexer::NVARCHAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::NVARCHAR_SYMBOL); + } elseif ($token->getType() === MySQLLexer::NCHAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::NCHAR_SYMBOL); + $children[] = $this->match(MySQLLexer::VARYING_SYMBOL); + } else { + throw new \Exception('Unexpected token in dataType: ' . $this->lexer->peekNextToken()->getText()); + } + $children[] = $this->fieldLength(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::BINARY_SYMBOL) { + $children[] = $this->match(MySQLLexer::BINARY_SYMBOL); + } + } elseif ($token->getType() === MySQLLexer::VARBINARY_SYMBOL) { + $children[] = $this->match(MySQLLexer::VARBINARY_SYMBOL); + $children[] = $this->fieldLength(); + } elseif ( + $this->lexer->peekNextToken()->getType() === MySQLLexer::LONG_SYMBOL && + $this->lexer->peekNextToken()->getType(2) === MySQLLexer::VARBINARY_SYMBOL + ) { + $children[] = $this->match(MySQLLexer::LONG_SYMBOL); + $children[] = $this->match(MySQLLexer::VARBINARY_SYMBOL); + } elseif ($token->getType() === MySQLLexer::YEAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::YEAR_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->fieldLength(); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::SIGNED_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::UNSIGNED_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ZEROFILL_SYMBOL) { + $children[] = $this->fieldOptions(); + } + } elseif ($token->getType() === MySQLLexer::DATE_SYMBOL) { + $children[] = $this->match(MySQLLexer::DATE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::TIME_SYMBOL) { + $children[] = $this->match(MySQLLexer::TIME_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->typeDatetimePrecision(); + } + } elseif ($token->getType() === MySQLLexer::TIMESTAMP_SYMBOL) { + $children[] = $this->match(MySQLLexer::TIMESTAMP_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->typeDatetimePrecision(); + } + } elseif ($token->getType() === MySQLLexer::DATETIME_SYMBOL) { + $children[] = $this->match(MySQLLexer::DATETIME_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->typeDatetimePrecision(); + } + } elseif ($token->getType() === MySQLLexer::TINYBLOB_SYMBOL) { + $children[] = $this->match(MySQLLexer::TINYBLOB_SYMBOL); + } elseif ($token->getType() === MySQLLexer::BLOB_SYMBOL) { + $children[] = $this->match(MySQLLexer::BLOB_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->fieldLength(); + } + } elseif ($token->getType() === MySQLLexer::MEDIUMBLOB_SYMBOL || + $token->getType() === MySQLLexer::LONGBLOB_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + $children[] = new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + } elseif ($token->getType() === MySQLLexer::LONG_SYMBOL) { + $children[] = $this->match(MySQLLexer::LONG_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::VARBINARY_SYMBOL) { + $children[] = $this->match(MySQLLexer::VARBINARY_SYMBOL); + } elseif ( + $this->lexer->peekNextToken()->getType() === MySQLLexer::CHAR_SYMBOL && + $this->lexer->peekNextToken()->getType(2) === MySQLLexer::VARYING_SYMBOL + ) { + $children[] = $this->match(MySQLLexer::CHAR_SYMBOL); + $this->match(MySQLLexer::VARYING_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::VARYING_SYMBOL)); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::VARCHAR_SYMBOL) { + $children[] = $this->match(MySQLLexer::VARCHAR_SYMBOL); + } + if ($this->isCharsetWithOptBinaryStart($this->lexer->peekNextToken())) { + $children[] = $this->charsetWithOptBinary(); + } + } elseif ($token->getType() === MySQLLexer::TINYTEXT_SYMBOL) { + $children[] = $this->match(MySQLLexer::TINYTEXT_SYMBOL); + if ($this->isCharsetWithOptBinaryStart($this->lexer->peekNextToken())) { + $children[] = $this->charsetWithOptBinary(); + } + } elseif ($token->getType() === MySQLLexer::TEXT_SYMBOL) { + $children[] = $this->match(MySQLLexer::TEXT_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->fieldLength(); + } + if ($this->isCharsetWithOptBinaryStart($this->lexer->peekNextToken())) { + $children[] = $this->charsetWithOptBinary(); + } + } elseif ($token->getType() === MySQLLexer::MEDIUMTEXT_SYMBOL) { + $children[] = $this->match(MySQLLexer::MEDIUMTEXT_SYMBOL); + if ($this->isCharsetWithOptBinaryStart($this->lexer->peekNextToken())) { + $children[] = $this->charsetWithOptBinary(); + } + } elseif ($token->getType() === MySQLLexer::LONGTEXT_SYMBOL) { + $children[] = $this->match(MySQLLexer::LONGTEXT_SYMBOL); + if ($this->isCharsetWithOptBinaryStart($this->lexer->peekNextToken())) { + $children[] = $this->charsetWithOptBinary(); + } + } elseif ($token->getType() === MySQLLexer::ENUM_SYMBOL) { + $children[] = $this->match(MySQLLexer::ENUM_SYMBOL); + $children[] = $this->stringList(); + if ($this->isCharsetWithOptBinaryStart($this->lexer->peekNextToken())) { + $children[] = $this->charsetWithOptBinary(); + } + } elseif ($token->getType() === MySQLLexer::SET_SYMBOL) { + $children[] = $this->match(MySQLLexer::SET_SYMBOL); + $children[] = $this->stringList(); + if ($this->isCharsetWithOptBinaryStart($this->lexer->peekNextToken())) { + $children[] = $this->charsetWithOptBinary(); + } + } elseif ($token->getType() === MySQLLexer::SERIAL_SYMBOL) { + $children[] = $this->match(MySQLLexer::SERIAL_SYMBOL); + } elseif ($this->serverVersion >= 50708 && $token->getType() === MySQLLexer::JSON_SYMBOL) { + $children[] = $this->match(MySQLLexer::JSON_SYMBOL); + } elseif ($token->getType() === MySQLLexer::GEOMETRY_SYMBOL || + $token->getType() === MySQLLexer::POINT_SYMBOL || + $token->getType() === MySQLLexer::LINESTRING_SYMBOL || + $token->getType() === MySQLLexer::POLYGON_SYMBOL || + $token->getType() === MySQLLexer::GEOMETRYCOLLECTION_SYMBOL || + $token->getType() === MySQLLexer::MULTIPOINT_SYMBOL || + $token->getType() === MySQLLexer::MULTILINESTRING_SYMBOL || + $token->getType() === MySQLLexer::MULTIPOLYGON_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + $children[] = new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + } else { + throw new \Exception('Unexpected token in dataType: ' . $token->getText()); + } + return new ASTNode('dataType', $children); + } + + public function nchar() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::NCHAR_SYMBOL) { + return $this->match(MySQLLexer::NCHAR_SYMBOL); + } elseif ($token->getType() === MySQLLexer::NATIONAL_SYMBOL) { + $children = []; + $children[] = $this->match(MySQLLexer::NATIONAL_SYMBOL); + $children[] = $this->match(MySQLLexer::CHAR_SYMBOL); + return new ASTNode('nchar', $children); + } else { + throw new \Exception('Unexpected token in nchar: ' . $token->getText()); + } + } + + public function realType() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::REAL_SYMBOL) { + $this->match(MySQLLexer::REAL_SYMBOL); + $children[] = ASTNode::fromToken($token); + } elseif ($token->getType() === MySQLLexer::DOUBLE_SYMBOL) { + $this->match(MySQLLexer::DOUBLE_SYMBOL); + $children[] = ASTNode::fromToken($token); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::PRECISION_SYMBOL) { + $this->match(MySQLLexer::PRECISION_SYMBOL); + $children[] = ASTNode::fromToken($this->lexer->peekNextToken()); + } + } else { + throw new \Exception('Unexpected token in realType: ' . $token->getText()); + } + + return new ASTNode('realType', $children); + } + + public function fieldLength() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $token = $this->lexer->peekNextToken(); + + if ($this->isReal_ulonglong_numberStart($token)) { + $children[] = $this->real_ulonglong_number(); + } elseif ($token->getType() === MySQLLexer::DECIMAL_NUMBER) { + return $this->match(MySQLLexer::DECIMAL_NUMBER); + } else { + throw new \Exception('Unexpected token in fieldLength: ' . $token->getText()); + } + + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('fieldLength', $children); + } + + public function fieldOptions() + { + $children = []; + + do { + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::SIGNED_SYMBOL: + case MySQLLexer::UNSIGNED_SYMBOL: + case MySQLLexer::ZEROFILL_SYMBOL: + $children[] = ASTNode::fromToken($token); + break; + default: + throw new \Exception('Unexpected token in fieldOptions: ' . $token->getText()); + } + } while ($this->lexer->peekNextToken()->getType() === MySQLLexer::SIGNED_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::UNSIGNED_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ZEROFILL_SYMBOL); + return new ASTNode('fieldOptions', $children); + } + + public function charsetWithOptBinary() + { + $children = []; + + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::ASCII_SYMBOL: + case MySQLLexer::UNICODE_SYMBOL: + case MySQLLexer::BYTE_SYMBOL: + $children[] = ASTNode::fromToken($token); + break; + case MySQLLexer::CHARSET_SYMBOL: + case MySQLLexer::CHAR_SYMBOL: + $children[] = ASTNode::fromToken($token); + $children[] = $this->charsetName(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::BINARY_SYMBOL) { + $children[] = $this->match(MySQLLexer::BINARY_SYMBOL); + } + break; + case MySQLLexer::BINARY_SYMBOL: + $children[] = ASTNode::fromToken($token); + $nextTokenType = $this->lexer->peekNextToken()->getType(); + if ($nextTokenType === MySQLLexer::CHARSET_SYMBOL || + $nextTokenType === MySQLLexer::CHAR_SYMBOL) { + $children[] = $this->charset(); + $children[] = $this->charsetName(); + } + break; + default: + throw new \Exception('Unexpected token in charsetWithOptBinary: ' . $token->getText()); + } + return new ASTNode('charsetWithOptBinary', $children); + } + + public function ascii() + { + $children = []; + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::ASCII_SYMBOL: + $children[] = ASTNode::fromToken($token); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::BINARY_SYMBOL) { + $this->match(MySQLLexer::BINARY_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::BINARY_SYMBOL)); + } + break; + case MySQLLexer::BINARY_SYMBOL: + $children[] = ASTNode::fromToken($token); + $this->match(MySQLLexer::ASCII_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::ASCII_SYMBOL)); + break; + default: + throw new \Exception('Unexpected token in ascii: ' . $token->getText()); + } + + return new ASTNode('ascii', $children); + } + + public function unicode() + { + $children = []; + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::UNICODE_SYMBOL: + $children[] = ASTNode::fromToken($token); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::BINARY_SYMBOL) { + $this->match(MySQLLexer::BINARY_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::BINARY_SYMBOL)); + } + break; + case MySQLLexer::BINARY_SYMBOL: + $children[] = ASTNode::fromToken($token); + $this->match(MySQLLexer::UNICODE_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::UNICODE_SYMBOL)); + break; + default: + throw new \Exception('Unexpected token in unicode: ' . $token->getText()); + } + + return new ASTNode('unicode', $children); + } + + public function charsetName() + { + $token = $this->lexer->peekNextToken(); + switch ($token->getType()) { + case MySQLLexer::IDENTIFIER: + case MySQLLexer::BACK_TICK_QUOTED_ID: + case MySQLLexer::DOUBLE_QUOTED_TEXT: + case MySQLLexer::SINGLE_QUOTED_TEXT: + return ASTNode::fromToken($this->lexer->getNextToken()); + case MySQLLexer::DEFAULT_SYMBOL: + if ($this->serverVersion < 80011) { + return ASTNode::fromToken($this->lexer->getNextToken()); + } + case MySQLLexer::BINARY_SYMBOL: + return ASTNode::fromToken($this->lexer->getNextToken()); + default: + if ($this->isIdentifierKeyword($token)) { + return $this->identifierKeyword(); + } + + throw new \Exception('Unexpected token in charsetName: ' . $token->getText()); + } + } + + private function isAsciiStart($token) + { + return $token->getType() === MySQLLexer::ASCII_SYMBOL || + ($token->getType() === MySQLLexer::BINARY_SYMBOL && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::ASCII_SYMBOL); + } + + private function isUnicodeStart($token) + { + return $token->getType() === MySQLLexer::UNICODE_SYMBOL || + ($token->getType() === MySQLLexer::BINARY_SYMBOL && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::UNICODE_SYMBOL); + } + + public function wsNumCodepoints() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->real_ulong_number(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('wsNumCodepoints', $children); + } + + public function createTableOptions() + { + $children = []; + $children[] = $this->createTableOption(); + while ($this->isCreateTableOptionStart($this->lexer->peekNextToken())) { + if($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + } + $children[] = $this->createTableOption(); + } + return new ASTNode('createTableOptions', $children); + } + + private function isCreateTableOptionStart($token) + { + return $token->getType() === MySQLLexer::ENGINE_SYMBOL || + ($this->serverVersion >= 80014 && $token->getType() === MySQLLexer::SECONDARY_ENGINE_SYMBOL) || + $token->getType() === MySQLLexer::MAX_ROWS_SYMBOL || + $token->getType() === MySQLLexer::MIN_ROWS_SYMBOL || + $token->getType() === MySQLLexer::AVG_ROW_LENGTH_SYMBOL || + $token->getType() === MySQLLexer::PASSWORD_SYMBOL || + $token->getType() === MySQLLexer::COMMENT_SYMBOL || + ($this->serverVersion >= 50708 && $token->getType() === MySQLLexer::COMPRESSION_SYMBOL) || + ($this->serverVersion >= 50711 && $token->getType() === MySQLLexer::ENCRYPTION_SYMBOL) || + $token->getType() === MySQLLexer::AUTO_INCREMENT_SYMBOL || + $token->getType() === MySQLLexer::PACK_KEYS_SYMBOL || + $token->getType() === MySQLLexer::STATS_AUTO_RECALC_SYMBOL || + $token->getType() === MySQLLexer::STATS_PERSISTENT_SYMBOL || + $token->getType() === MySQLLexer::STATS_SAMPLE_PAGES_SYMBOL || + $token->getType() === MySQLLexer::CHECKSUM_SYMBOL || + $token->getType() === MySQLLexer::TABLE_CHECKSUM_SYMBOL || + $token->getType() === MySQLLexer::DELAY_KEY_WRITE_SYMBOL || + $token->getType() === MySQLLexer::ROW_FORMAT_SYMBOL || + $token->getType() === MySQLLexer::UNION_SYMBOL || + $token->getType() === MySQLLexer::DEFAULT_SYMBOL || + $token->getType() === MySQLLexer::COLLATE_SYMBOL || + $token->getType() === MySQLLexer::CHARSET_SYMBOL || + $token->getType() === MySQLLexer::CHAR_SYMBOL || + $token->getType() === MySQLLexer::INSERT_METHOD_SYMBOL || + $token->getType() === MySQLLexer::DATA_SYMBOL || + $token->getType() === MySQLLexer::INDEX_SYMBOL || + $token->getType() === MySQLLexer::TABLESPACE_SYMBOL || + $token->getType() === MySQLLexer::STORAGE_SYMBOL || + $token->getType() === MySQLLexer::CONNECTION_SYMBOL || + $token->getType() === MySQLLexer::KEY_BLOCK_SIZE_SYMBOL; + } + + public function createTableOptionsSpaceSeparated() + { + $children = []; + do { + $children[] = $this->createTableOption(); + } while ($this->lexer->peekNextToken()->getType() === MySQLLexer::ENGINE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::AUTO_INCREMENT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::AVG_ROW_LENGTH_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::CHECKSUM_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::TABLE_CHECKSUM_SYMBOL || + ($this->serverVersion >= 50708 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::COMPRESSION_SYMBOL) || + $this->lexer->peekNextToken()->getType() === MySQLLexer::CONNECTION_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DATA_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DEFAULT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::COLLATE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::COLLATION_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::CHARACTER_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DELAY_KEY_WRITE_SYMBOL || + ($this->serverVersion >= 50711 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::ENCRYPTION_SYMBOL) || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INDEX_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INSERT_METHOD_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_BLOCK_SIZE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::MAX_ROWS_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::MIN_ROWS_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::PACK_KEYS_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::PASSWORD_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ROW_FORMAT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::STATS_AUTO_RECALC_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::STATS_PERSISTENT_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::STATS_SAMPLE_PAGES_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::STORAGE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::TABLESPACE_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::UNION_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::CHARSET_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::CHAR_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::COLLATE_SYMBOL || + ($this->serverVersion >= 80014 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::SECONDARY_ENGINE_SYMBOL)); + return new ASTNode('createTableOptionsSpaceSeparated', $children); + } + + public function createTableOption() + { + $token = $this->lexer->peekNextToken(); + $children = []; + if ($token->getType() === MySQLLexer::ENGINE_SYMBOL) { + $children[] = $this->match(MySQLLexer::ENGINE_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + + $children[] = $this->engineRef(); + } elseif ($this->serverVersion >= 80014 && $token->getType() === MySQLLexer::SECONDARY_ENGINE_SYMBOL) { + $children[] = $this->match(MySQLLexer::SECONDARY_ENGINE_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR || + $this->lexer->peekNextToken()->getType() === MySQLLexer::ASSIGN_OPERATOR) { + $children[] = $this->equal(); + } + + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::NULL_SYMBOL) { + $children[] = $this->match(MySQLLexer::NULL_SYMBOL); + } elseif ($this->isTextOrIdentifierStart($token)) { + $children[] = $this->textOrIdentifier(); + } else { + throw new \Exception('Unexpected token in createTableOption: ' . $token->getText()); + } + } elseif ($token->getType() === MySQLLexer::MAX_ROWS_SYMBOL) { + $children[] = $this->match(MySQLLexer::MAX_ROWS_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + + $children[] = $this->ulonglong_number(); + } elseif ($token->getType() === MySQLLexer::MIN_ROWS_SYMBOL) { + $children[] = $this->match(MySQLLexer::MIN_ROWS_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + + $children[] = $this->ulonglong_number(); + } elseif ($token->getType() === MySQLLexer::AVG_ROW_LENGTH_SYMBOL) { + $children[] = $this->match(MySQLLexer::AVG_ROW_LENGTH_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + + $children[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::PASSWORD_SYMBOL) { + $children[] = $this->match(MySQLLexer::PASSWORD_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->textStringLiteral(); + } elseif ($token->getType() === MySQLLexer::COMMENT_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMENT_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $this->match(MySQLLexer::EQUAL_OPERATOR); + $children[] = new ASTNode(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->textStringLiteral(); + } elseif ($this->serverVersion >= 50708 && $token->getType() === MySQLLexer::COMPRESSION_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMPRESSION_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->textString(); + } elseif ($this->serverVersion >= 50711 && $token->getType() === MySQLLexer::ENCRYPTION_SYMBOL) { + $children[] = $this->match(MySQLLexer::ENCRYPTION_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->textString(); + } elseif ($token->getType() === MySQLLexer::AUTO_INCREMENT_SYMBOL) { + $children[] = $this->match(MySQLLexer::AUTO_INCREMENT_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->ulonglong_number(); + } elseif ($token->getType() === MySQLLexer::PACK_KEYS_SYMBOL) { + $children[] = $this->match(MySQLLexer::PACK_KEYS_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->ternaryOption(); + } elseif ($token->getType() === MySQLLexer::STATS_AUTO_RECALC_SYMBOL || + $token->getType() === MySQLLexer::STATS_PERSISTENT_SYMBOL || + $token->getType() === MySQLLexer::STATS_SAMPLE_PAGES_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + $children[] = new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->ternaryOption(); + } elseif ($token->getType() === MySQLLexer::CHECKSUM_SYMBOL || + $token->getType() === MySQLLexer::TABLE_CHECKSUM_SYMBOL) { + if ($token->getType() === MySQLLexer::CHECKSUM_SYMBOL) { + $children[] = $this->match(MySQLLexer::CHECKSUM_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::TABLE_CHECKSUM_SYMBOL); + } + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::DELAY_KEY_WRITE_SYMBOL) { + $children[] = $this->match(MySQLLexer::DELAY_KEY_WRITE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->ulong_number(); + } elseif ($token->getType() === MySQLLexer::ROW_FORMAT_SYMBOL) { + $children[] = $this->match(MySQLLexer::ROW_FORMAT_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::DEFAULT_SYMBOL) { + $children[] = $this->match(MySQLLexer::DEFAULT_SYMBOL); + } elseif ($token->getType() === MySQLLexer::DYNAMIC_SYMBOL) { + $children[] = $this->match(MySQLLexer::DYNAMIC_SYMBOL); + } elseif ($token->getType() === MySQLLexer::FIXED_SYMBOL) { + $children[] = $this->match(MySQLLexer::FIXED_SYMBOL); + } elseif ($token->getType() === MySQLLexer::COMPRESSED_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMPRESSED_SYMBOL); + } elseif ($token->getType() === MySQLLexer::REDUNDANT_SYMBOL) { + $children[] = $this->match(MySQLLexer::REDUNDANT_SYMBOL); + } elseif ($token->getType() === MySQLLexer::COMPACT_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMPACT_SYMBOL); + } else { + throw new \Exception('Unexpected token in createTableOption: ' . $token->getText()); + } + } elseif ($token->getType() === MySQLLexer::UNION_SYMBOL) { + $children[] = $this->match(MySQLLexer::UNION_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->tableRefList(); + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + } elseif ( + ( + $token->getType() === MySQLLexer::DEFAULT_SYMBOL && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::COLLATE_SYMBOL + ) || $token->getType() === MySQLLexer::COLLATE_SYMBOL + ) { + $children[] = $this->defaultCollation(); + } elseif (( + $token->getType() === MySQLLexer::DEFAULT_SYMBOL && ( + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::CHARSET_SYMBOL || + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::CHAR_SYMBOL) + ) || $token->getType() === MySQLLexer::CHARSET_SYMBOL || $token->getType() === MySQLLexer::CHAR_SYMBOL){ + $children[] = $this->defaultCharset(); + } elseif ($token->getType() === MySQLLexer::INSERT_METHOD_SYMBOL) { + $children[] = $this->match(MySQLLexer::INSERT_METHOD_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::NO_SYMBOL) { + $children[] = $this->match(MySQLLexer::NO_SYMBOL); + } elseif ($token->getType() === MySQLLexer::FIRST_SYMBOL) { + $children[] = $this->match(MySQLLexer::FIRST_SYMBOL); + } elseif ($token->getType() === MySQLLexer::LAST_SYMBOL) { + $children[] = $this->match(MySQLLexer::LAST_SYMBOL); + } else { + throw new \Exception('Unexpected token in createTableOption: ' . $token->getText()); + } + } elseif ($token->getType() === MySQLLexer::DATA_SYMBOL) { + $children[] = $this->match(MySQLLexer::DATA_SYMBOL); + $children[] = $this->match(MySQLLexer::DIRECTORY_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->textString(); + } elseif ($token->getType() === MySQLLexer::INDEX_SYMBOL) { + $children[] = $this->match(MySQLLexer::INDEX_SYMBOL); + $children[] = $this->match(MySQLLexer::DIRECTORY_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->textString(); + } elseif ($token->getType() === MySQLLexer::TABLESPACE_SYMBOL) { + $children[] = $this->match(MySQLLexer::TABLESPACE_SYMBOL); + if ($this->serverVersion >= 50707 && $this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->identifier(); + } elseif ($token->getType() === MySQLLexer::STORAGE_SYMBOL) { + $children[] = $this->match(MySQLLexer::STORAGE_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DISK_SYMBOL) { + $children[] = $this->match(MySQLLexer::DISK_SYMBOL); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::MEMORY_SYMBOL) { + $children[] = $this->match(MySQLLexer::MEMORY_SYMBOL); + } else { + throw new \Exception('Unexpected token in createTableOption: ' . $this->lexer->peekNextToken()->getText()); + } + } elseif ($token->getType() === MySQLLexer::CONNECTION_SYMBOL) { + $children[] = $this->match(MySQLLexer::CONNECTION_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->textString(); + } elseif ($token->getType() === MySQLLexer::KEY_BLOCK_SIZE_SYMBOL) { + $children[] = $this->match(MySQLLexer::KEY_BLOCK_SIZE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::EQUAL_OPERATOR) { + $children[] = $this->match(MySQLLexer::EQUAL_OPERATOR); + } + $children[] = $this->ulong_number(); + } else { + throw new \Exception('Unexpected token in createTableOption: ' . $token->getText()); + } + + return new ASTNode('createTableOption', $children); + } + + //----------------- Object names and references ------------------------------------------------------------------------ + + // For each object we have at least 2 rules here: + // 1) The name when creating that object. + // 2) The name when used to reference it from other rules. + // + // Sometimes we need additional reference rules with different form, depending on the place such a reference is used. + + // A name for a field (column/index). Can be qualified with the current schema + table (although it's not a reference). + public function fieldIdentifier() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token)) { + $children[] = $this->identifier(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->dotIdentifier(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->dotIdentifier(); + } + } + + return new ASTNode('fieldIdentifier', $children); + } elseif ($token->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->dotIdentifier(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->dotIdentifier(); + } + + return new ASTNode('fieldIdentifier', $children); + } else { + throw new \Exception('Unexpected token in fieldIdentifier: ' . $token->getText()); + } + } + + public function columnName() + { + if ($this->serverVersion >= 80000) { + return $this->identifier(); + } else { + return $this->fieldIdentifier(); + } + } + + // A reference to a column of the object we are working on. + public function columnInternalRef() + { + return $this->identifier(); + } + + // column_list (+ parentheses) + opt_derived_column_list in sql_yacc.yy + public function columnInternalRefList() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->columnInternalRef(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->columnInternalRef(); + } + + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + + return new ASTNode('columnInternalRefList', $children); + } + + // A field identifier that can reference any schema/table. + public function columnRef() + { + return $this->fieldIdentifier(); + } + + public function insertIdentifier() + { + $token = $this->lexer->peekNextToken(2); + if ($token->getType() === MySQLLexer::DOT_SYMBOL && $this->lexer->peekNextToken(3)->getType() === MySQLLexer::MULT_OPERATOR) { + return $this->tableWild(); + } else { + return $this->columnRef(); + } + } + + public function indexName() + { + return $this->identifier(); + } + + // Always internal reference. Still all qualification variations are accepted. + public function indexRef() + { + return $this->fieldIdentifier(); + } + + public function tableWild() + { + $children = []; + $children[] = $this->identifier(); + + $children[] = $this->match(MySQLLexer::DOT_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::IDENTIFIER || + $this->lexer->peekNextToken()->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + $children[] = $this->identifier(); + $children[] = $this->match(MySQLLexer::DOT_SYMBOL); + } + + $children[] = $this->match(MySQLLexer::MULT_OPERATOR); + + return new ASTNode('tableWild', $children); + } + + //---------------------------------------------------------------------------------------------------------------------- + + public function checkConstraint() + { + $children = []; + + $children[] = $this->match(MySQLLexer::CHECK_SYMBOL); + $children[] = $this->exprWithParentheses(); + return new ASTNode('checkConstraint', $children); + } + + //---------------------------------------------------------------------------------------------------------------------- + + public function constraintKeyType() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::PRIMARY_SYMBOL) { + $children[] = $this->match(MySQLLexer::PRIMARY_SYMBOL); + $children[] = $this->match(MySQLLexer::KEY_SYMBOL); + } elseif ($token->getType() === MySQLLexer::UNIQUE_SYMBOL) { + $children[] = $this->match(MySQLLexer::UNIQUE_SYMBOL); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::INDEX_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_SYMBOL) { + $children[] = $this->match(MySQLLexer::KEY_SYMBOL); + } else { + $children[] = $this->match(MySQLLexer::INDEX_SYMBOL); + } + } + } else { + throw new \Exception('Unexpected token in constraintKeyType: ' . $token->getText()); + } + + return new ASTNode('constraintKeyType', $children); + } + + //---------------------------------------------------------------------------------------------------------------------- + + public function deleteOption() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::RESTRICT_SYMBOL) { + return $this->match(MySQLLexer::RESTRICT_SYMBOL); + } elseif ($token->getType() === MySQLLexer::CASCADE_SYMBOL) { + return $this->match(MySQLLexer::CASCADE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::SET_SYMBOL) { + $children[] = $this->match(MySQLLexer::SET_SYMBOL); + $children[] = $this->nullLiteral(); + } elseif ($token->getType() === MySQLLexer::NO_SYMBOL) { + $children[] = $this->match(MySQLLexer::NO_SYMBOL); + $children[] = $this->match(MySQLLexer::ACTION_SYMBOL); + } else { + throw new \Exception('Unexpected token in deleteOption: ' . $token->getText()); + } + + return new ASTNode('deleteOption', $children); + } + + //---------------------------------------------------------------------------------------------------------------------- + + public function gcolAttribute() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::UNIQUE_SYMBOL) { + $children[] = $this->match(MySQLLexer::UNIQUE_SYMBOL); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::KEY_SYMBOL) { + $children[] = $this->match(MySQLLexer::KEY_SYMBOL); + } + } elseif ($token->getType() === MySQLLexer::COMMENT_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMENT_SYMBOL); + $children[] = $this->textString(); + } elseif ($token->getType() === MySQLLexer::NOT_SYMBOL) { + $children[] = $this->match(MySQLLexer::NOT_SYMBOL); + $children[] = $this->match(MySQLLexer::NULL_SYMBOL); + } elseif ($token->getType() === MySQLLexer::NULL_SYMBOL) { + $children[] = $this->match(MySQLLexer::NULL_SYMBOL); + } elseif ($token->getType() === MySQLLexer::PRIMARY_SYMBOL || + $token->getType() === MySQLLexer::KEY_SYMBOL) { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::PRIMARY_SYMBOL) { + $children[] = $this->match(MySQLLexer::PRIMARY_SYMBOL); + } + $children[] = $this->match(MySQLLexer::KEY_SYMBOL); + } else { + throw new \Exception('Unexpected token in gcolAttribute: ' . $token->getText()); + } + return new ASTNode('gcolAttribute', $children); + } + + //---------------------------------------------------------------------------------------------------------------------- + + public function likeOrWhere() + { + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LIKE_SYMBOL) { + return $this->likeClause(); + } elseif ($this->lexer->peekNextToken()->getType() === MySQLLexer::WHERE_SYMBOL) { + return $this->whereClause(); + } else { + throw new \Exception('Unexpected token in likeOrWhere: ' . $this->lexer->peekNextToken()->getText()); + } + } + + public function onlineOption() +{ + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::ONLINE_SYMBOL: + case MySQLLexer::OFFLINE_SYMBOL: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in indexType: ' . $token->getText()); + } +} + + public function noWriteToBinLog() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::LOCAL_SYMBOL) { + $this->match(MySQLLexer::LOCAL_SYMBOL); + return ASTNode::fromToken($token); + } elseif ($token->getType() === MySQLLexer::NO_WRITE_TO_BINLOG_SYMBOL) { + return $this->match(MySQLLexer::NO_WRITE_TO_BINLOG_SYMBOL); + } else { + throw new \Exception('Unexpected token in noWriteToBinLog: ' . $token->getText()); + } + } + + public function usePartition() + { + $children = []; + + $children[] = $this->match(MySQLLexer::PARTITION_SYMBOL); + $children[] = $this->identifierListWithParentheses(); + + return new ASTNode('usePartition', $children); + } + + //----------------- Common basic rules --------------------------------------------------------------------------------- + + public function identifier() + { + $token = $this->lexer->peekNextToken(); + if ($this->isPureIdentifierStart($token)) { + return $this->pureIdentifier(); + } elseif ($this->isIdentifierKeyword($token)) { + return $this->identifierKeyword(); + } else { + throw new \Exception('Unexpected token for identifier: ' . $token->getText()); + } + } + + public function identifierList() + { + $children = []; + + $children[] = $this->identifier(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->identifier(); + } + + return new ASTNode('identifierList', $children); + } + + public function identifierListWithParentheses() + { + $children = []; + $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::OPEN_PAR_SYMBOL)); + $children[] = $this->identifierList(); + $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + $children[] = new ASTNode(MySQLLexer::getTokenName(MySQLLexer::CLOSE_PAR_SYMBOL)); + return new ASTNode('identifierListWithParentheses', $children); + } + + public function qualifiedIdentifier() + { + $children = []; + + $children[] = $this->identifier(); + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->dotIdentifier(); + } + + return new ASTNode('qualifiedIdentifier', $children); + } + + public function simpleIdentifier() + { + $children = []; + $token = $this->lexer->peekNextToken(2); + if ($token->getType() === MySQLLexer::DOT_SYMBOL) { + if ($this->lexer->peekNextToken(4)->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->identifier(); + $children[] = $this->dotIdentifier(); + $children[] = $this->dotIdentifier(); + return new ASTNode('simpleIdentifier', $children); + } else { + $children[] = $this->identifier(); + $children[] = $this->dotIdentifier(); + return new ASTNode('simpleIdentifier', $children); + } + } elseif ($this->serverVersion < 80000 && $token->getType() === MySQLLexer::EOF) { + $children[] = $this->dotIdentifier(); + $children[] = $this->dotIdentifier(); + return new ASTNode('simpleIdentifier', $children); + } elseif ($this->isIdentifierStart($this->lexer->peekNextToken()) || + $this->isIdentifierKeyword($this->lexer->peekNextToken())) { + $children[] = $this->identifier(); + + if ($this->serverVersion < 80000 && + $this->lexer->peekNextToken()->getType() === MySQLLexer::DOT_SYMBOL && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->dotIdentifier(); + $children[] = $this->dotIdentifier(); + } + + return new ASTNode('simpleIdentifier', $children); + } else { + throw new \Exception('Unexpected token in simpleIdentifier: ' . $this->lexer->peekNextToken()->getText()); + } + } + + private function isUlong_numberStart($token) + { + return $this->isReal_ulong_numberStart($token) || + $token->getType() === MySQLLexer::DECIMAL_NUMBER || + $token->getType() === MySQLLexer::FLOAT_NUMBER; + } + + public function dotIdentifier() + { + $children = []; + $children[] = $this->match(MySQLLexer::DOT_SYMBOL); + $children[] = $this->identifier(); + return new ASTNode('dotIdentifier', $children); + } + + public function ulong_number() + { + $token = $this->lexer->peekNextToken(); + + if ($this->isReal_ulong_numberStart($token)) { + return $this->real_ulong_number(); + } elseif ($token->getType() === MySQLLexer::DECIMAL_NUMBER) { + return $this->match(MySQLLexer::DECIMAL_NUMBER); + } elseif ($token->getType() === MySQLLexer::FLOAT_NUMBER) { + return $this->match(MySQLLexer::FLOAT_NUMBER); + } else { + throw new \Exception('Unexpected token in ulong_number: ' . $token->getText()); + } + } + + public function real_ulong_number() +{ + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::INT_NUMBER: + case MySQLLexer::HEX_NUMBER: + case MySQLLexer::LONG_NUMBER: + case MySQLLexer::ULONGLONG_NUMBER: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in indexType: ' . $token->getText()); + } +} + + private function isUlonglong_numberStart($token) + { + return $this->isReal_ulonglong_numberStart($token) || + $token->getType() === MySQLLexer::DECIMAL_NUMBER || + $token->getType() === MySQLLexer::FLOAT_NUMBER; + } + + public function ulonglong_number() + { + $token = $this->lexer->peekNextToken(); + if ($this->isReal_ulonglong_numberStart($token)) { + return $this->real_ulonglong_number(); + } elseif ($token->getType() === MySQLLexer::DECIMAL_NUMBER) { + return $this->match(MySQLLexer::DECIMAL_NUMBER); + } elseif ($token->getType() === MySQLLexer::FLOAT_NUMBER) { + return $this->match(MySQLLexer::FLOAT_NUMBER); + } else { + throw new \Exception('Unexpected token in ulonglong_number: ' . $token->getText()); + } + } + + public function real_ulonglong_number() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::INT_NUMBER) { + return $this->match(MySQLLexer::INT_NUMBER); + } elseif ($this->serverVersion >= 80017 && $token->getType() === MySQLLexer::HEX_NUMBER) { + return $this->match(MySQLLexer::HEX_NUMBER); + } elseif ($token->getType() === MySQLLexer::ULONGLONG_NUMBER) { + return $this->match(MySQLLexer::ULONGLONG_NUMBER); + } elseif ($token->getType() === MySQLLexer::LONG_NUMBER) { + return $this->match(MySQLLexer::LONG_NUMBER); + } else { + throw new \Exception('Unexpected token in real_ulonglong_number: ' . $token->getText()); + } + } + + public function literal() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($this->isTextLiteralStart($token)) { + $children[] = $this->textLiteral(); + } elseif ($this->isNumLiteralStart($token)) { + $children[] = $this->numLiteral(); + } elseif ($this->isTemporalLiteralStart($token)) { + $children[] = $this->temporalLiteral(); + } elseif ($this->isNullLiteralStart($token)) { + $children[] = $this->nullLiteral(); + } elseif ($this->isBoolLiteralStart($token)) { + $children[] = $this->boolLiteral(); + } elseif ($token->getType() === MySQLLexer::UNDERSCORE_CHARSET) { + $children[] = $this->match(MySQLLexer::UNDERSCORE_CHARSET); + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::HEX_NUMBER) { + $children[] = $this->match(MySQLLexer::HEX_NUMBER); + } elseif ($token->getType() === MySQLLexer::BIN_NUMBER) { + $children[] = $this->match(MySQLLexer::BIN_NUMBER); + } else { + throw new \Exception('Unexpected token in literal: ' . $token->getText()); + } + } else { + throw new \Exception('Unexpected token in literal: ' . $token->getText()); + } + + return new ASTNode('literal', $children); + } + + + public function columnRefOrLiteral() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->fieldIdentifier(); + } elseif ($this->isLiteralStart($token)) { + $children[] = $this->literal(); + } else { + throw new \Exception( + 'Unexpected token in columnRefOrLiteral: ' . $token->getText() + ); + } + + if ($this->serverVersion >= 50708 && + ($this->lexer->peekNextToken()->getType() === MySQLLexer::JSON_SEPARATOR_SYMBOL || + $this->lexer->peekNextToken()->getType() === MySQLLexer::JSON_UNQUOTED_SEPARATOR_SYMBOL)) { + $children[] = $this->jsonOperator(); + } + + return new ASTNode('columnRefOrLiteral', $children); + } + + public function signedLiteral() + { + $token = $this->lexer->peekNextToken(); + $children = []; + if ($token->getType() === MySQLLexer::PLUS_OPERATOR || + $token->getType() === MySQLLexer::MINUS_OPERATOR) { + $this->match($this->lexer->peekNextToken()->getType()); + $children[] = new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + $children[] = $this->ulong_number(); + } elseif ($this->isLiteralStart($token)) { + return $this->literal(); + } else { + throw new \Exception('Unexpected token in signedLiteral: ' . $token->getText()); + } + return new ASTNode('signedLiteral', $children); + } + + public function stringList() + { + $children = []; + + $children[] = $this->match(MySQLLexer::OPEN_PAR_SYMBOL); + $children[] = $this->textString(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->textString(); + } + $children[] = $this->match(MySQLLexer::CLOSE_PAR_SYMBOL); + return new ASTNode('stringList', $children); + } + + // TEXT_STRING_sys + TEXT_STRING_literal + TEXT_STRING_filesystem + TEXT_STRING + TEXT_STRING_password + + // TEXT_STRING_validated in sql_yacc.yy. + public function textStringLiteral() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + $this->match(MySQLLexer::SINGLE_QUOTED_TEXT); + return ASTNode::fromToken($token); + } elseif (!$this->lexer->isSqlModeActive(MySQLLexer::ANSI_QUOTES) && + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT) { + $this->match(MySQLLexer::DOUBLE_QUOTED_TEXT); + return ASTNode::fromToken($token); + } else { + throw new \Exception('Unexpected token in textStringLiteral: ' . $token->getText()); + } + } + + public function textString() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + return $this->textStringLiteral(); + } elseif ($token->getType() === MySQLLexer::HEX_NUMBER) { + return $this->match(MySQLLexer::HEX_NUMBER); + } elseif ($token->getType() === MySQLLexer::BIN_NUMBER) { + return $this->match(MySQLLexer::BIN_NUMBER); + } else { + throw new \Exception('Unexpected token in textString: ' . $token->getText()); + } + } + + public function textStringHash() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + return $this->textStringLiteral(); + } elseif ($this->serverVersion >= 80017 && $token->getType() === MySQLLexer::HEX_NUMBER) { + return $this->match(MySQLLexer::HEX_NUMBER); + } else { + throw new \Exception('Unexpected token in textStringHash: ' . $token->getText()); + } + } + + public function textLiteral() + { + $children = []; + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::UNDERSCORE_CHARSET) { + $children[] = $this->match(MySQLLexer::UNDERSCORE_CHARSET); + $children[] = $this->textStringLiteral(); + } elseif ($token->getType() === MySQLLexer::NCHAR_TEXT) { + $children[] = $this->match(MySQLLexer::NCHAR_TEXT); + } elseif ($token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + $children[] = $this->textStringLiteral(); + } else { + throw new \Exception('Unexpected token in textLiteral: ' . $token->getText()); + } + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + $children[] = $this->textStringLiteral(); + } + + return new ASTNode('textLiteral', $children); + } + + // A special variant of a text string that must not contain a linebreak (TEXT_STRING_sys_nonewline in sql_yacc.yy). + // Check validity in semantic phase. + public function textStringNoLinebreak() + { + return $this->textStringLiteral(); + } + + public function textStringLiteralList() + { + $children = []; + + $children[] = $this->textStringLiteral(); + + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->textStringLiteral(); + } + + return new ASTNode('textStringLiteralList', $children); + } + + public function numLiteral() + { + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::INT_NUMBER: + case MySQLLexer::LONG_NUMBER: + case MySQLLexer::ULONGLONG_NUMBER: + case MySQLLexer::DECIMAL_NUMBER: + case MySQLLexer::FLOAT_NUMBER: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in numLiteral: ' . $token->getText()); + } + } + public function boolLiteral() + { + $token = $this->lexer->getNextToken(); + + switch ($token->getType()) { + case MySQLLexer::TRUE_SYMBOL: + case MySQLLexer::FALSE_SYMBOL: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in boolLiteral: ' . $token->getText()); + } + } + + public function nullLiteral() + { + $token = $this->lexer->getNextToken(); + + switch ($token->getType()) { + case MySQLLexer::NULL_SYMBOL: + case MySQLLexer::NULL2_SYMBOL: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in nullLiteral: ' . $token->getText()); + } + } + + public function temporalLiteral() + { + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::DATE_SYMBOL: + case MySQLLexer::TIME_SYMBOL: + case MySQLLexer::TIMESTAMP_SYMBOL: + $children[] = ASTNode::fromToken($token); + break; + default: + throw new \Exception('Unexpected token in temporalLiteral: ' . $token->getText()); + } + + $children[] = $this->match(MySQLLexer::SINGLE_QUOTED_TEXT); + + return new ASTNode('temporalLiteral', $children); + } + + public function floatOptions() + { + if ($this->lexer->peekNextToken(3)->getType() === MySQLLexer::COMMA_SYMBOL) { + return $this->precision(); + } else { + return $this->fieldLength(); + } + } + + public function standardFloatOptions() + { + return $this->precision(); + } + + public function textOrIdentifier() + { + $token = $this->lexer->peekNextToken(); + if ($this->isIdentifierStart($token) || + $this->isIdentifierKeyword($token)) { + return $this->identifier(); + } elseif ($token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + return $this->textStringLiteral(); + } else { + throw new \Exception('Unexpected token in textOrIdentifier: ' . $token->getText()); + } + } + + public function lValueIdentifier() + { + $token = $this->lexer->peekNextToken(); + + if ($this->isPureIdentifierStart($token)) { + return $this->pureIdentifier(); + } elseif ($this->isLValueKeyword($token)) { + return $this->lValueKeyword(); + } else { + throw new \Exception('Unexpected token for identifier: ' . $token->getText()); + } + } + + public function roleIdentifierOrText() + { + $token = $this->lexer->peekNextToken(); + + if ($this->isRoleIdentifierStart($token)) { + return $this->roleIdentifier(); + } elseif ($token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT) { + return $this->textStringLiteral(); + } else { + throw new \Exception('Unexpected token for identifier: ' . $token->getText()); + } + } + + public function sizeNumber() + { + $token = $this->lexer->peekNextToken(); + if ($this->isReal_ulonglong_numberStart($token)) { + return $this->real_ulonglong_number(); + } elseif ($token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT) { + return $this->pureIdentifier(); + } else { + throw new \Exception('Unexpected token in sizeNumber: ' . $token->getText()); + } + } + + public function equal() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::EQUAL_OPERATOR) { + $this->match(MySQLLexer::EQUAL_OPERATOR); + } elseif ($token->getType() === MySQLLexer::ASSIGN_OPERATOR) { + $this->match(MySQLLexer::ASSIGN_OPERATOR); + } else { + throw new \Exception('Unexpected token in equal: ' . $token->getText()); + } + + return new ASTNode(MySQLLexer::getTokenName($token->getType())); + } + + public function optionType() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::GLOBAL_SYMBOL) { + return $this->match(MySQLLexer::GLOBAL_SYMBOL); + } elseif ($token->getType() === MySQLLexer::LOCAL_SYMBOL) { + $this->match(MySQLLexer::LOCAL_SYMBOL); + return ASTNode::fromToken($token); + } elseif ($token->getType() === MySQLLexer::SESSION_SYMBOL) { + $this->match(MySQLLexer::SESSION_SYMBOL); + return ASTNode::fromToken($token); + } elseif ($this->serverVersion >= 80000 && $token->getType() === MySQLLexer::PERSIST_SYMBOL) { + $this->match(MySQLLexer::PERSIST_SYMBOL); + return ASTNode::fromToken($token); + } elseif ($this->serverVersion >= 80000 && $token->getType() === MySQLLexer::PERSIST_ONLY_SYMBOL) { + $this->match(MySQLLexer::PERSIST_ONLY_SYMBOL); + return ASTNode::fromToken($token); + } else { + throw new \Exception('Unexpected token in optionType: ' . $token->getText()); + } + } + + public function flushTablesOptions() + { + $token = $this->lexer->peekNextToken(); + $children = []; + + if ($token->getType() === MySQLLexer::FOR_SYMBOL) { + $children[] = $this->match(MySQLLexer::FOR_SYMBOL); + $children[] = $this->match(MySQLLexer::EXPORT_SYMBOL); + } elseif ($token->getType() === MySQLLexer::WITH_SYMBOL) { + $children[] = $this->match(MySQLLexer::WITH_SYMBOL); + $children[] = $this->match(MySQLLexer::READ_SYMBOL); + $children[] = $this->match(MySQLLexer::LOCK_SYMBOL); + } else { + throw new \Exception('Unexpected token in flushTablesOptions: ' . $token->getText()); + } + + return new ASTNode('flushTablesOptions', $children); + } + + private function isReal_ulonglong_numberStart($token) + { + return $token->getType() === MySQLLexer::INT_NUMBER || + ($this->serverVersion >= 80017 && $token->getType() === MySQLLexer::HEX_NUMBER) || + $token->getType() === MySQLLexer::ULONGLONG_NUMBER || + $token->getType() === MySQLLexer::LONG_NUMBER; + } + + private function isReal_ulong_numberStart($token) + { + switch ($token->getType()) { + case MySQLLexer::INT_NUMBER: + case MySQLLexer::HEX_NUMBER: + case MySQLLexer::ULONGLONG_NUMBER: + case MySQLLexer::LONG_NUMBER: + return true; + default: + return false; + } + + } + + private function isTextLiteralStart($token) + { + switch ($token->getType()) { + case MySQLLexer::SINGLE_QUOTED_TEXT: + case MySQLLexer::HEX_NUMBER: + case MySQLLexer::BIN_NUMBER: + case MySQLLexer::NCHAR_TEXT: + case MySQLLexer::UNDERSCORE_CHARSET: + return true; + case MySQLLexer::DOUBLE_QUOTED_TEXT: + if ($this->lexer->isSqlModeActive(MySQLLexer::ANSI_QUOTES)) { + return true; + } + default: + return false; + } + + } + + private function isNumLiteralStart($token) + { + switch ($token->getType()) { + case MySQLLexer::INT_NUMBER: + case MySQLLexer::LONG_NUMBER: + case MySQLLexer::ULONGLONG_NUMBER: + case MySQLLexer::DECIMAL_NUMBER: + case MySQLLexer::FLOAT_NUMBER: + return true; + default: + return false; + } + + } + + private function isTemporalLiteralStart($token) + { + switch ($token->getType()) { + case MySQLLexer::DATE_SYMBOL: + case MySQLLexer::TIME_SYMBOL: + case MySQLLexer::TIMESTAMP_SYMBOL: + return true; + default: + return false; + } + + } + + private function isIdentifierStart($token) + { + return $this->isPureIdentifierStart($token) || $this->isIdentifierKeyword($token); + } + + private function isSignedLiteralStart($token) + { + return $token->getType() === MySQLLexer::PLUS_OPERATOR || + $token->getType() === MySQLLexer::MINUS_OPERATOR || + $this->isLiteralStart($token); + } + + private function isLiteralStart($token) + { + return $this->isTextLiteralStart($token) || + $this->isNumLiteralStart($token) || + $this->isTemporalLiteralStart($token) || + $this->isNullLiteralStart($token) || + + $this->isBoolLiteralStart($token); + } + + private function isCompOp($token) + { + switch ($token->getType()) { + case MySQLLexer::EQUAL_OPERATOR: + case MySQLLexer::NULL_SAFE_EQUAL_OPERATOR: + case MySQLLexer::GREATER_OR_EQUAL_OPERATOR: + case MySQLLexer::GREATER_THAN_OPERATOR: + case MySQLLexer::LESS_OR_EQUAL_OPERATOR: + case MySQLLexer::LESS_THAN_OPERATOR: + case MySQLLexer::NOT_EQUAL_OPERATOR: + return true; + default: + return false; + } + + } + + private function isNullLiteralStart($token) + { + switch ($token->getType()) { + case MySQLLexer::NULL_SYMBOL: + case MySQLLexer::NULL2_SYMBOL: + return true; + default: + return false; + } + + } + + private function isBoolLiteralStart($token) + { + switch ($token->getType()) { + case MySQLLexer::TRUE_SYMBOL: + case MySQLLexer::FALSE_SYMBOL: + return true; + default: + return false; + } + + } + + private function isBoolPriStart($token) + { + return $this->isSimpleExprStart($token); + } + + private function isSimpleExprStart($token) + { + return $this->isVariableStart($token) || + $this->isColumnRefStart($token) || + $this->isRuntimeFunctionCallStart($token) || + ($this->isUnambiguousIdentifierStart($token) && + $this->lexer->peekNextToken(2)->getType() === MySQLLexer::OPEN_PAR_SYMBOL) || + $this->isLiteralStart($token) || + $token->getType() === MySQLLexer::PARAM_MARKER || + $this->isSumExprStart($token) || + ($this->serverVersion >= 80000 && $token->getType() === MySQLLexer::GROUPING_SYMBOL) || + ($this->serverVersion >= 80000 && $this->isWindowFunctionCallStart($token)) || + $token->getType() === MySQLLexer::PLUS_OPERATOR || + $token->getType() === MySQLLexer::MINUS_OPERATOR || + $token->getType() === MySQLLexer::BITWISE_NOT_OPERATOR || + $token->getType() === MySQLLexer::LOGICAL_NOT_OPERATOR || + $token->getType() === MySQLLexer::NOT2_SYMBOL || + ($this->serverVersion < 80000 && $token->getType() === MySQLLexer::ROW_SYMBOL) || + $token->getType() === MySQLLexer::OPEN_PAR_SYMBOL || + ($token->getType() === MySQLLexer::EXISTS_SYMBOL || + $this->isSubqueryStart($this->lexer->peekNextToken(2))) || + $token->getType() === MySQLLexer::OPEN_CURLY_SYMBOL || + $token->getType() === MySQLLexer::MATCH_SYMBOL || + $token->getType() === MySQLLexer::BINARY_SYMBOL || + $token->getType() === MySQLLexer::CAST_SYMBOL || + $token->getType() === MySQLLexer::CASE_SYMBOL || + $token->getType() === MySQLLexer::CONVERT_SYMBOL || + $token->getType() === MySQLLexer::DEFAULT_SYMBOL || + $token->getType() === MySQLLexer::VALUES_SYMBOL || + $token->getType() === MySQLLexer::INTERVAL_SYMBOL; + } + + private function isVariableStart($token) + { + switch ($token->getType()) { + case MySQLLexer::AT_SIGN_SYMBOL: + case MySQLLexer::AT_TEXT_SUFFIX: + case MySQLLexer::AT_AT_SIGN_SYMBOL: + return true; + default: + return false; + } + + } + + private function isColumnRefStart($token) + { + return $this->isFieldIdentifierStart($token); + } + + private function isSubqueryStart($token) + { + switch ($token->getType()) { + case MySQLLexer::SELECT_SYMBOL: + case MySQLLexer::WITH_SYMBOL: + case MySQLLexer::OPEN_PAR_SYMBOL: + return true; + default: + return false; + } + + } + + private function isSumExprStart($token) + { + return $token->getType() === MySQLLexer::AVG_SYMBOL || + $token->getType() === MySQLLexer::BIT_AND_SYMBOL || + $token->getType() === MySQLLexer::BIT_OR_SYMBOL || + $token->getType() === MySQLLexer::BIT_XOR_SYMBOL || + $token->getType() === MySQLLexer::COUNT_SYMBOL || + $token->getType() === MySQLLexer::GROUP_CONCAT_SYMBOL || + $this->isJsonFunctionStart($token) || + $token->getType() === MySQLLexer::MAX_SYMBOL || + $token->getType() === MySQLLexer::MIN_SYMBOL || + $token->getType() === MySQLLexer::STD_SYMBOL || + $token->getType() === MySQLLexer::SUM_SYMBOL || + $token->getType() === MySQLLexer::VARIANCE_SYMBOL || + $token->getType() === MySQLLexer::STDDEV_POP_SYMBOL || + $token->getType() === MySQLLexer::VAR_POP_SYMBOL || + $token->getType() === MySQLLexer::STDDEV_SAMP_SYMBOL || + $token->getType() === MySQLLexer::VAR_SAMP_SYMBOL; + } + + private function isJsonFunctionStart($token) + { + switch ($token->getType()) { + case MySQLLexer::JSON_ARRAYAGG_SYMBOL: + case MySQLLexer::JSON_OBJECTAGG_SYMBOL: + return true; + default: + return false; + } + + } + + private function isWindowFunctionCallStart($token) + { + switch ($token->getType()) { + case MySQLLexer::ROW_NUMBER_SYMBOL: + case MySQLLexer::RANK_SYMBOL: + case MySQLLexer::DENSE_RANK_SYMBOL: + case MySQLLexer::CUME_DIST_SYMBOL: + case MySQLLexer::PERCENT_RANK_SYMBOL: + case MySQLLexer::NTILE_SYMBOL: + case MySQLLexer::LEAD_SYMBOL: + case MySQLLexer::LAG_SYMBOL: + case MySQLLexer::FIRST_VALUE_SYMBOL: + case MySQLLexer::LAST_VALUE_SYMBOL: + case MySQLLexer::NTH_VALUE_SYMBOL: + return true; + default: + return false; + } + + } + + private function isFieldIdentifierStart($token) + { + return $token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::DOT_SYMBOL; + } + + private function isPureIdentifierStart($token) + { + switch ($token->getType()) { + case MySQLLexer::IDENTIFIER: + case MySQLLexer::BACK_TICK_QUOTED_ID: + case MySQLLexer::DOUBLE_QUOTED_TEXT: + return true; + default: + return false; + } + + } + + private function isIdentifierKeyword($token) + { + if ($this->serverVersion < 80017) { + return $this->isLabelKeyword($token) || + $this->isRoleOrIdentifierKeyword($token) || + $token->getType() === MySQLLexer::EXECUTE_SYMBOL || + ($this->serverVersion >= 50709 && $token->getType() === MySQLLexer::SHUTDOWN_SYMBOL) || + ($this->serverVersion >= 80011 && $token->getType() === MySQLLexer::RESTART_SYMBOL); + } else { + return $this->isIdentifierKeywordsUnambiguous($token) || + $this->isIdentifierKeywordsAmbiguous1RolesAndLabels($token) || + $this->isIdentifierKeywordsAmbiguous2Labels($token) || + $this->isIdentifierKeywordsAmbiguous3Roles($token) || + $this->isIdentifierKeywordsAmbiguous4SystemVariables($token); + } + } + + private function isLabelKeyword($token) + { + if ($this->serverVersion < 80017) { + return $this->isRoleOrLabelKeyword($token) || + $this->isRoleOrIdentifierKeyword($token) || + $token->getType() === MySQLLexer::EVENT_SYMBOL || + $token->getType() === MySQLLexer::FILE_SYMBOL || + $token->getType() === MySQLLexer::NONE_SYMBOL || + $token->getType() === MySQLLexer::PROCESS_SYMBOL || + $token->getType() === MySQLLexer::PROXY_SYMBOL || + $token->getType() === MySQLLexer::RELOAD_SYMBOL || + $token->getType() === MySQLLexer::REPLICATION_SYMBOL || + $token->getType() === MySQLLexer::RESOURCE_SYMBOL || + $token->getType() === MySQLLexer::SUPER_SYMBOL; + } else { + return $this->isIdentifierKeywordsUnambiguous($token) || + $this->isIdentifierKeywordsAmbiguous3Roles($token) || + $this->isIdentifierKeywordsAmbiguous4SystemVariables($token); + } + } + + private function isRoleKeyword($token) + { + if ($this->serverVersion < 80017) { + return $this->isRoleOrLabelKeyword($token) || + $this->isRoleOrIdentifierKeyword($token); + } else { + return $this->isIdentifierKeywordsUnambiguous($token) || + $this->isIdentifierKeywordsAmbiguous2Labels($token) || + $this->isIdentifierKeywordsAmbiguous4SystemVariables($token); + } + } + + private function isLValueKeyword($token) + { + return $this->isIdentifierKeywordsUnambiguous($token) || + $this->isIdentifierKeywordsAmbiguous1RolesAndLabels($token) || + $this->isIdentifierKeywordsAmbiguous2Labels($token) || + $this->isIdentifierKeywordsAmbiguous3Roles($token); + } + + private function isRoleOrIdentifierKeyword($token) + { + if ($token->getType() === MySQLLexer::IMPORT_SYMBOL) { + return $this->serverVersion < 80000; + } + + if ($token->getType() === MySQLLexer::SHUTDOWN_SYMBOL) { + return $this->serverVersion < 50709; + } + + switch ($token->getType()) { + case MySQLLexer::ACCOUNT_SYMBOL: + case MySQLLexer::ASCII_SYMBOL: + case MySQLLexer::ALWAYS_SYMBOL: + case MySQLLexer::BACKUP_SYMBOL: + case MySQLLexer::BEGIN_SYMBOL: + case MySQLLexer::BYTE_SYMBOL: + case MySQLLexer::CACHE_SYMBOL: + case MySQLLexer::CHARSET_SYMBOL: + case MySQLLexer::CHECKSUM_SYMBOL: + case MySQLLexer::CLONE_SYMBOL: + case MySQLLexer::CLOSE_SYMBOL: + case MySQLLexer::COMMENT_SYMBOL: + case MySQLLexer::COMMIT_SYMBOL: + case MySQLLexer::CONTAINS_SYMBOL: + case MySQLLexer::DEALLOCATE_SYMBOL: + case MySQLLexer::DO_SYMBOL: + case MySQLLexer::END_SYMBOL: + case MySQLLexer::FLUSH_SYMBOL: + case MySQLLexer::FOLLOWS_SYMBOL: + case MySQLLexer::FORMAT_SYMBOL: + case MySQLLexer::GROUP_REPLICATION_SYMBOL: + case MySQLLexer::HANDLER_SYMBOL: + case MySQLLexer::HELP_SYMBOL: + case MySQLLexer::HOST_SYMBOL: + case MySQLLexer::INSTALL_SYMBOL: + case MySQLLexer::INVISIBLE_SYMBOL: + case MySQLLexer::LANGUAGE_SYMBOL: + case MySQLLexer::NO_SYMBOL: + case MySQLLexer::OPEN_SYMBOL: + case MySQLLexer::OPTIONS_SYMBOL: + case MySQLLexer::OWNER_SYMBOL: + case MySQLLexer::PARSER_SYMBOL: + case MySQLLexer::PARTITION_SYMBOL: + case MySQLLexer::PORT_SYMBOL: + case MySQLLexer::PRECEDES_SYMBOL: + case MySQLLexer::PREPARE_SYMBOL: + case MySQLLexer::REMOVE_SYMBOL: + case MySQLLexer::REPAIR_SYMBOL: + case MySQLLexer::RESET_SYMBOL: + case MySQLLexer::RESTORE_SYMBOL: + case MySQLLexer::ROLE_SYMBOL: + case MySQLLexer::ROLLBACK_SYMBOL: + case MySQLLexer::SAVEPOINT_SYMBOL: + case MySQLLexer::SECONDARY_SYMBOL: + case MySQLLexer::SECONDARY_ENGINE_SYMBOL: + case MySQLLexer::SECONDARY_LOAD_SYMBOL: + case MySQLLexer::SECONDARY_UNLOAD_SYMBOL: + case MySQLLexer::SECURITY_SYMBOL: + case MySQLLexer::SERVER_SYMBOL: + case MySQLLexer::SIGNED_SYMBOL: + case MySQLLexer::SLAVE_SYMBOL: + case MySQLLexer::SOCKET_SYMBOL: + case MySQLLexer::SONAME_SYMBOL: + case MySQLLexer::START_SYMBOL: + case MySQLLexer::STOP_SYMBOL: + case MySQLLexer::TRUNCATE_SYMBOL: + case MySQLLexer::UNICODE_SYMBOL: + case MySQLLexer::UNINSTALL_SYMBOL: + case MySQLLexer::UPGRADE_SYMBOL: + case MySQLLexer::VISIBLE_SYMBOL: + case MySQLLexer::WRAPPER_SYMBOL: + case MySQLLexer::XA_SYMBOL: + return true; + default: + return false; + } + + } + + public function fractionalPrecision() + { + return $this->match(MySQLLexer::INT_NUMBER); + } + + + private function isRoleOrLabelKeyword($token) + { + if ($this->serverVersion >= 80000) { + if ($token->getType() === MySQLLexer::ADMIN_SYMBOL || + $token->getType() === MySQLLexer::EXCHANGE_SYMBOL || + $token->getType() === MySQLLexer::EXPIRE_SYMBOL || + $token->getType() === MySQLLexer::ONLY_SYMBOL || + $token->getType() === MySQLLexer::SUPER_SYMBOL || + $token->getType() === MySQLLexer::VALIDATION_SYMBOL || + $token->getType() === MySQLLexer::WITHOUT_SYMBOL) { + return true; + } + } + + if ($this->serverVersion < 80000) { + if ($token->getType() === MySQLLexer::CUBE_SYMBOL || + $token->getType() === MySQLLexer::FUNCTION_SYMBOL || + $token->getType() === MySQLLexer::IMPORT_SYMBOL || + $token->getType() === MySQLLexer::ROW_SYMBOL || + $token->getType() === MySQLLexer::ROWS_SYMBOL) { + return true; + } + } + + return $this->isIdentifierKeywordsUnambiguous($token); + } + + public function derivedTable() + { + $children = []; + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::LATERAL_SYMBOL) { + $children[] = $this->match(MySQLLexer::LATERAL_SYMBOL); + } + + $children[] = $this->subquery(); + $children[] = $this->tableAlias(); + + if ($this->serverVersion >= 80000 && $this->lexer->peekNextToken()->getType() === MySQLLexer::OPEN_PAR_SYMBOL) { + $children[] = $this->columnInternalRefList(); + } + + return new ASTNode( + 'derivedTable', + $children + ); + } + + + + private function isIdentifierKeywordsUnambiguous($token) + { + switch($token->getType()) { + case MySQLLexer::ACTION_SYMBOL: + case MySQLLexer::ACCOUNT_SYMBOL: + case MySQLLexer::ACTIVE_SYMBOL: + case MySQLLexer::ADDDATE_SYMBOL: + case MySQLLexer::ADMIN_SYMBOL: + case MySQLLexer::AFTER_SYMBOL: + case MySQLLexer::AGAINST_SYMBOL: + case MySQLLexer::AGGREGATE_SYMBOL: + case MySQLLexer::ALGORITHM_SYMBOL: + case MySQLLexer::ALWAYS_SYMBOL: + case MySQLLexer::ANY_SYMBOL: + case MySQLLexer::AT_SYMBOL: + case MySQLLexer::AUTOEXTEND_SIZE_SYMBOL: + case MySQLLexer::AUTO_INCREMENT_SYMBOL: + case MySQLLexer::AVG_ROW_LENGTH_SYMBOL: + case MySQLLexer::AVG_SYMBOL: + case MySQLLexer::BACKUP_SYMBOL: + case MySQLLexer::BINLOG_SYMBOL: + case MySQLLexer::BIT_SYMBOL: + case MySQLLexer::BLOCK_SYMBOL: + case MySQLLexer::BOOLEAN_SYMBOL: + case MySQLLexer::BOOL_SYMBOL: + case MySQLLexer::BTREE_SYMBOL: + case MySQLLexer::BUCKETS_SYMBOL: + case MySQLLexer::CASCADED_SYMBOL: + case MySQLLexer::CATALOG_NAME_SYMBOL: + case MySQLLexer::CHAIN_SYMBOL: + case MySQLLexer::CHANGED_SYMBOL: + case MySQLLexer::CHANNEL_SYMBOL: + case MySQLLexer::CIPHER_SYMBOL: + case MySQLLexer::CLASS_ORIGIN_SYMBOL: + case MySQLLexer::CLIENT_SYMBOL: + case MySQLLexer::CLOSE_SYMBOL: + case MySQLLexer::COALESCE_SYMBOL: + case MySQLLexer::CODE_SYMBOL: + case MySQLLexer::COLLATION_SYMBOL: + case MySQLLexer::COLUMNS_SYMBOL: + case MySQLLexer::COLUMN_FORMAT_SYMBOL: + case MySQLLexer::COLUMN_NAME_SYMBOL: + case MySQLLexer::COMMITTED_SYMBOL: + case MySQLLexer::COMPACT_SYMBOL: + case MySQLLexer::COMPLETION_SYMBOL: + case MySQLLexer::COMPONENT_SYMBOL: + case MySQLLexer::COMPRESSED_SYMBOL: + case MySQLLexer::COMPRESSION_SYMBOL: + case MySQLLexer::CONCURRENT_SYMBOL: + case MySQLLexer::CONNECTION_SYMBOL: + case MySQLLexer::CONSISTENT_SYMBOL: + case MySQLLexer::CONSTRAINT_CATALOG_SYMBOL: + case MySQLLexer::CONSTRAINT_NAME_SYMBOL: + case MySQLLexer::CONSTRAINT_SCHEMA_SYMBOL: + case MySQLLexer::CONTEXT_SYMBOL: + case MySQLLexer::CPU_SYMBOL: + case MySQLLexer::CURRENT_SYMBOL: // not reserved in MySQL per WL#2111 specification + case MySQLLexer::CURSOR_NAME_SYMBOL: + case MySQLLexer::DATAFILE_SYMBOL: + case MySQLLexer::DATA_SYMBOL: + case MySQLLexer::DATETIME_SYMBOL: + case MySQLLexer::DATE_SYMBOL: + case MySQLLexer::DAY_SYMBOL: + case MySQLLexer::DEFAULT_AUTH_SYMBOL: + case MySQLLexer::DEFINER_SYMBOL: + case MySQLLexer::DEFINITION_SYMBOL: + case MySQLLexer::DELAY_KEY_WRITE_SYMBOL: + case MySQLLexer::DESCRIPTION_SYMBOL: + case MySQLLexer::DIAGNOSTICS_SYMBOL: + case MySQLLexer::DIRECTORY_SYMBOL: + case MySQLLexer::DISABLE_SYMBOL: + case MySQLLexer::DISCARD_SYMBOL: + case MySQLLexer::DISK_SYMBOL: + case MySQLLexer::DUMPFILE_SYMBOL: + case MySQLLexer::DUPLICATE_SYMBOL: + case MySQLLexer::DYNAMIC_SYMBOL: + case MySQLLexer::ENABLE_SYMBOL: + case MySQLLexer::ENCRYPTION_SYMBOL: + case MySQLLexer::ENDS_SYMBOL: + case MySQLLexer::ENFORCED_SYMBOL: + case MySQLLexer::ENGINES_SYMBOL: + case MySQLLexer::ENGINE_SYMBOL: + case MySQLLexer::ENUM_SYMBOL: + case MySQLLexer::ERRORS_SYMBOL: + case MySQLLexer::ERROR_SYMBOL: + case MySQLLexer::ESCAPE_SYMBOL: + case MySQLLexer::EVENTS_SYMBOL: + case MySQLLexer::EVERY_SYMBOL: + case MySQLLexer::EXCHANGE_SYMBOL: + case MySQLLexer::EXCLUDE_SYMBOL: + case MySQLLexer::EXPANSION_SYMBOL: + case MySQLLexer::EXPIRE_SYMBOL: + case MySQLLexer::EXPORT_SYMBOL: + case MySQLLexer::EXTENDED_SYMBOL: + case MySQLLexer::EXTENT_SIZE_SYMBOL: + case MySQLLexer::FAST_SYMBOL: + case MySQLLexer::FAULTS_SYMBOL: + case MySQLLexer::FILE_BLOCK_SIZE_SYMBOL: + case MySQLLexer::FILTER_SYMBOL: + case MySQLLexer::FIRST_SYMBOL: + case MySQLLexer::FIXED_SYMBOL: + case MySQLLexer::FOLLOWING_SYMBOL: + case MySQLLexer::FORMAT_SYMBOL: + case MySQLLexer::FOUND_SYMBOL: + case MySQLLexer::FULL_SYMBOL: + case MySQLLexer::GENERAL_SYMBOL: + case MySQLLexer::GEOMETRYCOLLECTION_SYMBOL: + case MySQLLexer::GEOMETRY_SYMBOL: + case MySQLLexer::GET_FORMAT_SYMBOL: + case MySQLLexer::GET_MASTER_PUBLIC_KEY_SYMBOL: + case MySQLLexer::GRANTS_SYMBOL: + case MySQLLexer::GROUP_REPLICATION_SYMBOL: + case MySQLLexer::HASH_SYMBOL: + case MySQLLexer::HISTOGRAM_SYMBOL: + case MySQLLexer::HISTORY_SYMBOL: + case MySQLLexer::HOSTS_SYMBOL: + case MySQLLexer::HOST_SYMBOL: + case MySQLLexer::HOUR_SYMBOL: + case MySQLLexer::IDENTIFIED_SYMBOL: + case MySQLLexer::IGNORE_SERVER_IDS_SYMBOL: + case MySQLLexer::INACTIVE_SYMBOL: + case MySQLLexer::INDEXES_SYMBOL: + case MySQLLexer::INITIAL_SIZE_SYMBOL: + case MySQLLexer::INSERT_METHOD_SYMBOL: + case MySQLLexer::INSTANCE_SYMBOL: + case MySQLLexer::INVISIBLE_SYMBOL: + case MySQLLexer::INVOKER_SYMBOL: + case MySQLLexer::IO_SYMBOL: + case MySQLLexer::IPC_SYMBOL: + case MySQLLexer::ISOLATION_SYMBOL: + case MySQLLexer::ISSUER_SYMBOL: + case MySQLLexer::JSON_SYMBOL: + case MySQLLexer::KEY_BLOCK_SIZE_SYMBOL: + case MySQLLexer::LAST_SYMBOL: + case MySQLLexer::LEAVES_SYMBOL: + case MySQLLexer::LESS_SYMBOL: + case MySQLLexer::LEVEL_SYMBOL: + case MySQLLexer::LINESTRING_SYMBOL: + case MySQLLexer::LIST_SYMBOL: + case MySQLLexer::LOCKED_SYMBOL: + case MySQLLexer::LOCKS_SYMBOL: + case MySQLLexer::LOGFILE_SYMBOL: + case MySQLLexer::LOGS_SYMBOL: + case MySQLLexer::MASTER_AUTO_POSITION_SYMBOL: + case MySQLLexer::MASTER_COMPRESSION_ALGORITHM_SYMBOL: + case MySQLLexer::MASTER_CONNECT_RETRY_SYMBOL: + case MySQLLexer::MASTER_DELAY_SYMBOL: + case MySQLLexer::MASTER_HEARTBEAT_PERIOD_SYMBOL: + case MySQLLexer::MASTER_HOST_SYMBOL: + case MySQLLexer::NETWORK_NAMESPACE_SYMBOL: + case MySQLLexer::MASTER_LOG_FILE_SYMBOL: + case MySQLLexer::MASTER_LOG_POS_SYMBOL: + case MySQLLexer::MASTER_PASSWORD_SYMBOL: + case MySQLLexer::MASTER_PORT_SYMBOL: + case MySQLLexer::MASTER_PUBLIC_KEY_PATH_SYMBOL: + case MySQLLexer::MASTER_RETRY_COUNT_SYMBOL: + case MySQLLexer::MASTER_SERVER_ID_SYMBOL: + case MySQLLexer::MASTER_SSL_CAPATH_SYMBOL: + case MySQLLexer::MASTER_SSL_CA_SYMBOL: + case MySQLLexer::MASTER_SSL_CERT_SYMBOL: + case MySQLLexer::MASTER_SSL_CIPHER_SYMBOL: + case MySQLLexer::MASTER_SSL_CRLPATH_SYMBOL: + case MySQLLexer::MASTER_SSL_CRL_SYMBOL: + case MySQLLexer::MASTER_SSL_KEY_SYMBOL: + case MySQLLexer::MASTER_SSL_SYMBOL: + case MySQLLexer::MASTER_SYMBOL: + case MySQLLexer::MASTER_TLS_CIPHERSUITES_SYMBOL: + case MySQLLexer::MASTER_TLS_VERSION_SYMBOL: + case MySQLLexer::MASTER_USER_SYMBOL: + case MySQLLexer::MASTER_ZSTD_COMPRESSION_LEVEL_SYMBOL: + case MySQLLexer::MAX_CONNECTIONS_PER_HOUR_SYMBOL: + case MySQLLexer::MAX_QUERIES_PER_HOUR_SYMBOL: + case MySQLLexer::MAX_ROWS_SYMBOL: + case MySQLLexer::MAX_SIZE_SYMBOL: + case MySQLLexer::MAX_UPDATES_PER_HOUR_SYMBOL: + case MySQLLexer::MAX_USER_CONNECTIONS_SYMBOL: + case MySQLLexer::MEDIUM_SYMBOL: + case MySQLLexer::MEMORY_SYMBOL: + case MySQLLexer::MERGE_SYMBOL: + case MySQLLexer::MESSAGE_TEXT_SYMBOL: + case MySQLLexer::MICROSECOND_SYMBOL: + case MySQLLexer::MIGRATE_SYMBOL: + case MySQLLexer::MINUTE_SYMBOL: + case MySQLLexer::MIN_ROWS_SYMBOL: + case MySQLLexer::MODE_SYMBOL: + case MySQLLexer::MODIFY_SYMBOL: + case MySQLLexer::MONTH_SYMBOL: + case MySQLLexer::MULTILINESTRING_SYMBOL: + case MySQLLexer::MULTIPOINT_SYMBOL: + case MySQLLexer::MULTIPOLYGON_SYMBOL: + case MySQLLexer::MUTEX_SYMBOL: + case MySQLLexer::MYSQL_ERRNO_SYMBOL: + case MySQLLexer::NAMES_SYMBOL: + case MySQLLexer::NAME_SYMBOL: + case MySQLLexer::NATIONAL_SYMBOL: + case MySQLLexer::NCHAR_SYMBOL: + case MySQLLexer::NDBCLUSTER_SYMBOL: + case MySQLLexer::NESTED_SYMBOL: + case MySQLLexer::NEVER_SYMBOL: + case MySQLLexer::NEW_SYMBOL: + case MySQLLexer::NEXT_SYMBOL: + case MySQLLexer::NODEGROUP_SYMBOL: + case MySQLLexer::NOWAIT_SYMBOL: + case MySQLLexer::NO_WAIT_SYMBOL: + case MySQLLexer::NULLS_SYMBOL: + case MySQLLexer::NUMBER_SYMBOL: + case MySQLLexer::NVARCHAR_SYMBOL: + case MySQLLexer::OFFSET_SYMBOL: + case MySQLLexer::OJ_SYMBOL: + case MySQLLexer::OLD_SYMBOL: + case MySQLLexer::ONE_SYMBOL: + case MySQLLexer::ONLY_SYMBOL: + case MySQLLexer::OPEN_SYMBOL: + case MySQLLexer::OPTIONAL_SYMBOL: + case MySQLLexer::OPTIONS_SYMBOL: + case MySQLLexer::ORDINALITY_SYMBOL: + case MySQLLexer::ORGANIZATION_SYMBOL: + case MySQLLexer::OTHERS_SYMBOL: + case MySQLLexer::OWNER_SYMBOL: + case MySQLLexer::PACK_KEYS_SYMBOL: + case MySQLLexer::PAGE_SYMBOL: + case MySQLLexer::PARSER_SYMBOL: + case MySQLLexer::PARTIAL_SYMBOL: + case MySQLLexer::PARTITIONING_SYMBOL: + case MySQLLexer::PARTITIONS_SYMBOL: + case MySQLLexer::PASSWORD_SYMBOL: + case MySQLLexer::PATH_SYMBOL: + case MySQLLexer::PHASE_SYMBOL: + case MySQLLexer::PLUGINS_SYMBOL: + case MySQLLexer::PLUGIN_DIR_SYMBOL: + case MySQLLexer::PLUGIN_SYMBOL: + case MySQLLexer::POINT_SYMBOL: + case MySQLLexer::POLYGON_SYMBOL: + case MySQLLexer::PORT_SYMBOL: + case MySQLLexer::PRECEDING_SYMBOL: + case MySQLLexer::PRESERVE_SYMBOL: + case MySQLLexer::PREV_SYMBOL: + case MySQLLexer::PRIVILEGES_SYMBOL: + case MySQLLexer::PRIVILEGE_CHECKS_USER_SYMBOL: + case MySQLLexer::PROCESSLIST_SYMBOL: + case MySQLLexer::PROFILES_SYMBOL: + case MySQLLexer::PROFILE_SYMBOL: + case MySQLLexer::QUARTER_SYMBOL: + case MySQLLexer::QUERY_SYMBOL: + case MySQLLexer::QUICK_SYMBOL: + case MySQLLexer::READ_ONLY_SYMBOL: + case MySQLLexer::REBUILD_SYMBOL: + case MySQLLexer::RECOVER_SYMBOL: + case MySQLLexer::REDO_BUFFER_SIZE_SYMBOL: + case MySQLLexer::REDUNDANT_SYMBOL: + case MySQLLexer::REFERENCE_SYMBOL: + case MySQLLexer::RELAY_SYMBOL: + case MySQLLexer::RELAYLOG_SYMBOL: + case MySQLLexer::RELAY_LOG_FILE_SYMBOL: + case MySQLLexer::RELAY_LOG_POS_SYMBOL: + case MySQLLexer::RELAY_THREAD_SYMBOL: + case MySQLLexer::REMOVE_SYMBOL: + case MySQLLexer::REORGANIZE_SYMBOL: + case MySQLLexer::REPEATABLE_SYMBOL: + case MySQLLexer::REPLICATE_DO_DB_SYMBOL: + case MySQLLexer::REPLICATE_DO_TABLE_SYMBOL: + case MySQLLexer::REPLICATE_IGNORE_DB_SYMBOL: + case MySQLLexer::REPLICATE_IGNORE_TABLE_SYMBOL: + case MySQLLexer::REPLICATE_REWRITE_DB_SYMBOL: + case MySQLLexer::REPLICATE_WILD_DO_TABLE_SYMBOL: + case MySQLLexer::REPLICATE_WILD_IGNORE_TABLE_SYMBOL: + case MySQLLexer::USER_RESOURCES_SYMBOL: + case MySQLLexer::RESPECT_SYMBOL: + case MySQLLexer::RESTORE_SYMBOL: + case MySQLLexer::RESUME_SYMBOL: + case MySQLLexer::RETAIN_SYMBOL: + case MySQLLexer::RETURNED_SQLSTATE_SYMBOL: + case MySQLLexer::RETURNS_SYMBOL: + case MySQLLexer::REUSE_SYMBOL: + case MySQLLexer::REVERSE_SYMBOL: + case MySQLLexer::ROLE_SYMBOL: + case MySQLLexer::ROLLUP_SYMBOL: + case MySQLLexer::ROTATE_SYMBOL: + case MySQLLexer::ROUTINE_SYMBOL: + case MySQLLexer::ROW_COUNT_SYMBOL: + case MySQLLexer::ROW_FORMAT_SYMBOL: + case MySQLLexer::RTREE_SYMBOL: + case MySQLLexer::SCHEDULE_SYMBOL: + case MySQLLexer::SCHEMA_NAME_SYMBOL: + case MySQLLexer::SECONDARY_ENGINE_SYMBOL: + case MySQLLexer::SECONDARY_LOAD_SYMBOL: + case MySQLLexer::SECONDARY_SYMBOL: + case MySQLLexer::SECONDARY_UNLOAD_SYMBOL: + case MySQLLexer::SECOND_SYMBOL: + case MySQLLexer::SECURITY_SYMBOL: + case MySQLLexer::SERIALIZABLE_SYMBOL: + case MySQLLexer::SERIAL_SYMBOL: + case MySQLLexer::SERVER_SYMBOL: + case MySQLLexer::SHARE_SYMBOL: + case MySQLLexer::SIMPLE_SYMBOL: + case MySQLLexer::SKIP_SYMBOL: + case MySQLLexer::SLOW_SYMBOL: + case MySQLLexer::SNAPSHOT_SYMBOL: + case MySQLLexer::SOCKET_SYMBOL: + case MySQLLexer::SONAME_SYMBOL: + case MySQLLexer::SOUNDS_SYMBOL: + case MySQLLexer::SOURCE_SYMBOL: + case MySQLLexer::SQL_AFTER_GTIDS_SYMBOL: + case MySQLLexer::SQL_AFTER_MTS_GAPS_SYMBOL: + case MySQLLexer::SQL_BEFORE_GTIDS_SYMBOL: + case MySQLLexer::SQL_BUFFER_RESULT_SYMBOL: + case MySQLLexer::SQL_NO_CACHE_SYMBOL: + case MySQLLexer::SQL_THREAD_SYMBOL: + case MySQLLexer::SRID_SYMBOL: + case MySQLLexer::STACKED_SYMBOL: + case MySQLLexer::STARTS_SYMBOL: + case MySQLLexer::STATS_AUTO_RECALC_SYMBOL: + case MySQLLexer::STATS_PERSISTENT_SYMBOL: + case MySQLLexer::STATS_SAMPLE_PAGES_SYMBOL: + case MySQLLexer::STATUS_SYMBOL: + case MySQLLexer::STORAGE_SYMBOL: + case MySQLLexer::STRING_SYMBOL: + case MySQLLexer::SUBCLASS_ORIGIN_SYMBOL: + case MySQLLexer::SUBDATE_SYMBOL: + case MySQLLexer::SUBJECT_SYMBOL: + case MySQLLexer::SUBPARTITIONS_SYMBOL: + case MySQLLexer::SUBPARTITION_SYMBOL: + case MySQLLexer::SUSPEND_SYMBOL: + case MySQLLexer::SWAPS_SYMBOL: + case MySQLLexer::SWITCHES_SYMBOL: + case MySQLLexer::TABLES_SYMBOL: + case MySQLLexer::TABLESPACE_SYMBOL: + case MySQLLexer::TABLE_CHECKSUM_SYMBOL: + case MySQLLexer::TABLE_NAME_SYMBOL: + case MySQLLexer::TEMPORARY_SYMBOL: + case MySQLLexer::TEMPTABLE_SYMBOL: + case MySQLLexer::TEXT_SYMBOL: + case MySQLLexer::THAN_SYMBOL: + case MySQLLexer::THREAD_PRIORITY_SYMBOL: + case MySQLLexer::TIES_SYMBOL: + case MySQLLexer::TIMESTAMP_ADD_SYMBOL: + case MySQLLexer::TIMESTAMP_DIFF_SYMBOL: + case MySQLLexer::TIMESTAMP_SYMBOL: + case MySQLLexer::TIME_SYMBOL: + case MySQLLexer::TRANSACTION_SYMBOL: + case MySQLLexer::TRIGGERS_SYMBOL: + case MySQLLexer::TYPES_SYMBOL: + case MySQLLexer::TYPE_SYMBOL: + case MySQLLexer::UNBOUNDED_SYMBOL: + case MySQLLexer::UNCOMMITTED_SYMBOL: + case MySQLLexer::UNDEFINED_SYMBOL: + case MySQLLexer::UNDOFILE_SYMBOL: + case MySQLLexer::UNDO_BUFFER_SIZE_SYMBOL: + case MySQLLexer::UNKNOWN_SYMBOL: + case MySQLLexer::UNTIL_SYMBOL: + case MySQLLexer::UPGRADE_SYMBOL: + case MySQLLexer::USER_SYMBOL: + case MySQLLexer::USE_FRM_SYMBOL: + case MySQLLexer::VALIDATION_SYMBOL: + case MySQLLexer::VALUE_SYMBOL: + case MySQLLexer::VARIABLES_SYMBOL: + case MySQLLexer::VCPU_SYMBOL: + case MySQLLexer::VIEW_SYMBOL: + case MySQLLexer::VISIBLE_SYMBOL: + case MySQLLexer::WAIT_SYMBOL: + case MySQLLexer::WARNINGS_SYMBOL: + case MySQLLexer::WEEK_SYMBOL: + case MySQLLexer::WEIGHT_STRING_SYMBOL: + case MySQLLexer::WITHOUT_SYMBOL: + case MySQLLexer::WORK_SYMBOL: + case MySQLLexer::WRAPPER_SYMBOL: + case MySQLLexer::X509_SYMBOL: + case MySQLLexer::XID_SYMBOL: + case MySQLLexer::XML_SYMBOL: + case MySQLLexer::YEAR_SYMBOL: + case MySQLLexer::ARRAY_SYMBOL: + case MySQLLexer::FAILED_LOGIN_ATTEMPTS_SYMBOL: + case MySQLLexer::MEMBER_SYMBOL: + case MySQLLexer::OFF_SYMBOL: + case MySQLLexer::PASSWORD_LOCK_TIME_SYMBOL: + case MySQLLexer::RANDOM_SYMBOL: + case MySQLLexer::REQUIRE_ROW_FORMAT_SYMBOL: + case MySQLLexer::REQUIRE_TABLE_PRIMARY_KEY_CHECK_SYMBOL: + case MySQLLexer::STREAM_SYMBOL: + return true; + + default: + return false; + } + } + + private function isIdentifierKeywordsAmbiguous1RolesAndLabels($token) + { + switch ($token->getType()) { + case MySQLLexer::EXECUTE_SYMBOL: + case MySQLLexer::RESTART_SYMBOL: + case MySQLLexer::SHUTDOWN_SYMBOL: + return true; + default: + return false; + } + + } + + private function isIdentifierKeywordsAmbiguous2Labels($token) + { + switch ($token->getType()) { + case MySQLLexer::ASCII_SYMBOL: + case MySQLLexer::BEGIN_SYMBOL: + case MySQLLexer::BYTE_SYMBOL: + case MySQLLexer::CACHE_SYMBOL: + case MySQLLexer::CHARSET_SYMBOL: + case MySQLLexer::CHECKSUM_SYMBOL: + case MySQLLexer::CLONE_SYMBOL: + case MySQLLexer::COMMENT_SYMBOL: + case MySQLLexer::COMMIT_SYMBOL: + case MySQLLexer::CONTAINS_SYMBOL: + case MySQLLexer::DEALLOCATE_SYMBOL: + case MySQLLexer::DO_SYMBOL: + case MySQLLexer::END_SYMBOL: + case MySQLLexer::FLUSH_SYMBOL: + case MySQLLexer::FOLLOWS_SYMBOL: + case MySQLLexer::HANDLER_SYMBOL: + case MySQLLexer::HELP_SYMBOL: + case MySQLLexer::IMPORT_SYMBOL: + case MySQLLexer::INSTALL_SYMBOL: + case MySQLLexer::LANGUAGE_SYMBOL: + case MySQLLexer::NO_SYMBOL: + case MySQLLexer::PRECEDES_SYMBOL: + case MySQLLexer::PREPARE_SYMBOL: + case MySQLLexer::REPAIR_SYMBOL: + case MySQLLexer::RESET_SYMBOL: + case MySQLLexer::ROLLBACK_SYMBOL: + case MySQLLexer::SAVEPOINT_SYMBOL: + case MySQLLexer::SIGNED_SYMBOL: + case MySQLLexer::SLAVE_SYMBOL: + case MySQLLexer::START_SYMBOL: + case MySQLLexer::STOP_SYMBOL: + case MySQLLexer::TRUNCATE_SYMBOL: + case MySQLLexer::UNICODE_SYMBOL: + case MySQLLexer::UNINSTALL_SYMBOL: + case MySQLLexer::XA_SYMBOL: + return true; + default: + return false; + } + + } + + private function isIdentifierKeywordsAmbiguous3Roles($token) + { + switch ($token->getType()) { + case MySQLLexer::EVENT_SYMBOL: + case MySQLLexer::FILE_SYMBOL: + case MySQLLexer::NONE_SYMBOL: + case MySQLLexer::PROCESS_SYMBOL: + case MySQLLexer::PROXY_SYMBOL: + case MySQLLexer::RELOAD_SYMBOL: + case MySQLLexer::REPLICATION_SYMBOL: + case MySQLLexer::RESOURCE_SYMBOL: + case MySQLLexer::SUPER_SYMBOL: + return true; + default: + return false; + } + + } + + private function isIdentifierKeywordsAmbiguous4SystemVariables($token) + { + switch ($token->getType()) { + case MySQLLexer::GLOBAL_SYMBOL: + case MySQLLexer::LOCAL_SYMBOL: + case MySQLLexer::PERSIST_SYMBOL: + case MySQLLexer::PERSIST_ONLY_SYMBOL: + case MySQLLexer::SESSION_SYMBOL: + return true; + default: + return false; + } + + } + + public function identifierKeywordsAmbiguous1RolesAndLabels() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::EXECUTE_SYMBOL) { + return $this->match(MySQLLexer::EXECUTE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::RESTART_SYMBOL) { + return $this->match(MySQLLexer::RESTART_SYMBOL); + } elseif ($token->getType() === MySQLLexer::SHUTDOWN_SYMBOL) { + return $this->match(MySQLLexer::SHUTDOWN_SYMBOL); + } else { + throw new \Exception( + 'Unexpected token in identifierKeywordsAmbiguous1RolesAndLabels: ' . $token->getText() + ); + } + } + + public function identifierKeywordsAmbiguous2Labels() + { + $token = $this->lexer->peekNextToken(); + + if ($token->getType() === MySQLLexer::ASCII_SYMBOL) { + return $this->match(MySQLLexer::ASCII_SYMBOL); + } elseif ($token->getType() === MySQLLexer::BEGIN_SYMBOL) { + return $this->match(MySQLLexer::BEGIN_SYMBOL); + } elseif ($token->getType() === MySQLLexer::BYTE_SYMBOL) { + return $this->match(MySQLLexer::BYTE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::CACHE_SYMBOL) { + return $this->match(MySQLLexer::CACHE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::CHARSET_SYMBOL) { + return $this->match(MySQLLexer::CHARSET_SYMBOL); + } elseif ($token->getType() === MySQLLexer::CHECKSUM_SYMBOL) { + return $this->match(MySQLLexer::CHECKSUM_SYMBOL); + } elseif ($token->getType() === MySQLLexer::CLONE_SYMBOL) { + return $this->match(MySQLLexer::CLONE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::COMMENT_SYMBOL) { + return $this->match(MySQLLexer::COMMENT_SYMBOL); + } elseif ($token->getType() === MySQLLexer::COMMIT_SYMBOL) { + return $this->match(MySQLLexer::COMMIT_SYMBOL); + } elseif ($token->getType() === MySQLLexer::CONTAINS_SYMBOL) { + return $this->match(MySQLLexer::CONTAINS_SYMBOL); + } elseif ($token->getType() === MySQLLexer::DEALLOCATE_SYMBOL) { + return $this->match(MySQLLexer::DEALLOCATE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::DO_SYMBOL) { + return $this->match(MySQLLexer::DO_SYMBOL); + } elseif ($token->getType() === MySQLLexer::END_SYMBOL) { + return $this->match(MySQLLexer::END_SYMBOL); + } elseif ($token->getType() === MySQLLexer::FLUSH_SYMBOL) { + return $this->match(MySQLLexer::FLUSH_SYMBOL); + } elseif ($token->getType() === MySQLLexer::FOLLOWS_SYMBOL) { + return $this->match(MySQLLexer::FOLLOWS_SYMBOL); + } elseif ($token->getType() === MySQLLexer::HANDLER_SYMBOL) { + return $this->match(MySQLLexer::HANDLER_SYMBOL); + } elseif ($token->getType() === MySQLLexer::HELP_SYMBOL) { + return $this->match(MySQLLexer::HELP_SYMBOL); + } elseif ($token->getType() === MySQLLexer::IMPORT_SYMBOL) { + return $this->match(MySQLLexer::IMPORT_SYMBOL); + } elseif ($token->getType() === MySQLLexer::INSTALL_SYMBOL) { + return $this->match(MySQLLexer::INSTALL_SYMBOL); + } elseif ($token->getType() === MySQLLexer::LANGUAGE_SYMBOL) { + return $this->match(MySQLLexer::LANGUAGE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::NO_SYMBOL) { + return $this->match(MySQLLexer::NO_SYMBOL); + } elseif ($token->getType() === MySQLLexer::PRECEDES_SYMBOL) { + return $this->match(MySQLLexer::PRECEDES_SYMBOL); + } elseif ($token->getType() === MySQLLexer::PREPARE_SYMBOL) { + $this->match(MySQLLexer::PREPARE_SYMBOL); + return ASTNode::fromToken($token); + } elseif ($token->getType() === MySQLLexer::REPAIR_SYMBOL) { + return $this->match(MySQLLexer::REPAIR_SYMBOL); + } elseif ($token->getType() === MySQLLexer::RESET_SYMBOL) { + return $this->match(MySQLLexer::RESET_SYMBOL); + } elseif ($token->getType() === MySQLLexer::ROLLBACK_SYMBOL) { + return $this->match(MySQLLexer::ROLLBACK_SYMBOL); + } elseif ($token->getType() === MySQLLexer::SAVEPOINT_SYMBOL) { + return $this->match(MySQLLexer::SAVEPOINT_SYMBOL); + } elseif ($token->getType() === MySQLLexer::SIGNED_SYMBOL) { + return $this->match(MySQLLexer::SIGNED_SYMBOL); + } elseif ($token->getType() === MySQLLexer::SLAVE_SYMBOL) { + return $this->match(MySQLLexer::SLAVE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::START_SYMBOL) { + return $this->match(MySQLLexer::START_SYMBOL); + } elseif ($token->getType() === MySQLLexer::STOP_SYMBOL) { + return $this->match(MySQLLexer::STOP_SYMBOL); + } elseif ($token->getType() === MySQLLexer::TRUNCATE_SYMBOL) { + return $this->match(MySQLLexer::TRUNCATE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::UNICODE_SYMBOL) { + return $this->match(MySQLLexer::UNICODE_SYMBOL); + } elseif ($token->getType() === MySQLLexer::UNINSTALL_SYMBOL) { + return $this->match(MySQLLexer::UNINSTALL_SYMBOL); + } elseif ($token->getType() === MySQLLexer::XA_SYMBOL) { + return $this->match(MySQLLexer::XA_SYMBOL); + } else { + throw new \Exception('Unexpected token in identifierKeywordsAmbiguous2Labels: ' . $token->getText()); + } + } + + public function identifierKeywordsAmbiguous3Roles() +{ + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::EVENT_SYMBOL: + case MySQLLexer::FILE_SYMBOL: + case MySQLLexer::NONE_SYMBOL: + case MySQLLexer::PROCESS_SYMBOL: + case MySQLLexer::PROXY_SYMBOL: + case MySQLLexer::RELOAD_SYMBOL: + case MySQLLexer::REPLICATION_SYMBOL: + case MySQLLexer::RESOURCE_SYMBOL: + case MySQLLexer::SUPER_SYMBOL: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in indexType: ' . $token->getText()); + } +} + + public function identifierKeywordsAmbiguous4SystemVariables() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::GLOBAL_SYMBOL) { + return $this->match(MySQLLexer::GLOBAL_SYMBOL); + } elseif ($token->getType() === MySQLLexer::LOCAL_SYMBOL) { + $this->match(MySQLLexer::LOCAL_SYMBOL); + return ASTNode::fromToken($token); + } elseif ($token->getType() === MySQLLexer::SESSION_SYMBOL) { + $this->match(MySQLLexer::SESSION_SYMBOL); + return ASTNode::fromToken($token); + } elseif ($token->getType() === MySQLLexer::PERSIST_SYMBOL) { + $this->match(MySQLLexer::PERSIST_SYMBOL); + return ASTNode::fromToken($token); + } elseif ($token->getType() === MySQLLexer::PERSIST_ONLY_SYMBOL) { + $this->match(MySQLLexer::PERSIST_ONLY_SYMBOL); + return ASTNode::fromToken($token); + } else { + throw new \Exception('Unexpected token in identifierKeywordsAmbiguous4SystemVariables: ' . $token->getText()); + } + } + + public function roleOrLabelKeyword() + { + if ($this->serverVersion < 80000) { + $token = $this->lexer->getNextToken(); + if ($token->getType() === MySQLLexer::CUBE_SYMBOL || + $token->getType() === MySQLLexer::FUNCTION_SYMBOL || + $token->getType() === MySQLLexer::IMPORT_SYMBOL || + $token->getType() === MySQLLexer::ROW_SYMBOL || + $token->getType() === MySQLLexer::ROWS_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + return new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + } + } + + if ($this->serverVersion >= 80000) { + $token = $this->lexer->getNextToken(); + if ($token->getType() === MySQLLexer::ADMIN_SYMBOL || + $token->getType() === MySQLLexer::EXCHANGE_SYMBOL || + $token->getType() === MySQLLexer::EXPIRE_SYMBOL || + $token->getType() === MySQLLexer::ONLY_SYMBOL || + $token->getType() === MySQLLexer::SUPER_SYMBOL || + $token->getType() === MySQLLexer::VALIDATION_SYMBOL || + $token->getType() === MySQLLexer::WITHOUT_SYMBOL) { + $this->match($this->lexer->peekNextToken()->getType()); + return new ASTNode(MySQLLexer::getTokenName($this->lexer->peekNextToken()->getType())); + } + } + + $token = $this->lexer->getNextToken(); + switch($token->getType()) { + case MySQLLexer::ACTION_SYMBOL: + case MySQLLexer::ACTIVE_SYMBOL: + case MySQLLexer::ADDDATE_SYMBOL: + case MySQLLexer::AFTER_SYMBOL: + case MySQLLexer::AGAINST_SYMBOL: + case MySQLLexer::AGGREGATE_SYMBOL: + case MySQLLexer::ALGORITHM_SYMBOL: + case MySQLLexer::ANALYZE_SYMBOL: + case MySQLLexer::ANY_SYMBOL: + case MySQLLexer::AT_SYMBOL: + case MySQLLexer::AUTHORS_SYMBOL: + case MySQLLexer::AUTO_INCREMENT_SYMBOL: + case MySQLLexer::AUTOEXTEND_SIZE_SYMBOL: + case MySQLLexer::AVG_ROW_LENGTH_SYMBOL: + case MySQLLexer::AVG_SYMBOL: + case MySQLLexer::BINLOG_SYMBOL: + case MySQLLexer::BIT_SYMBOL: + case MySQLLexer::BLOCK_SYMBOL: + case MySQLLexer::BOOL_SYMBOL: + case MySQLLexer::BOOLEAN_SYMBOL: + case MySQLLexer::BTREE_SYMBOL: + case MySQLLexer::BUCKETS_SYMBOL: + case MySQLLexer::CASCADED_SYMBOL: + case MySQLLexer::CATALOG_NAME_SYMBOL: + case MySQLLexer::CHAIN_SYMBOL: + case MySQLLexer::CHANGED_SYMBOL: + case MySQLLexer::CHANNEL_SYMBOL: + case MySQLLexer::CIPHER_SYMBOL: + case MySQLLexer::CLIENT_SYMBOL: + case MySQLLexer::CLASS_ORIGIN_SYMBOL: + case MySQLLexer::CLOSE_SYMBOL: + case MySQLLexer::COALESCE_SYMBOL: + case MySQLLexer::CODE_SYMBOL: + case MySQLLexer::COLLATION_SYMBOL: + case MySQLLexer::COLUMN_NAME_SYMBOL: + case MySQLLexer::COLUMN_FORMAT_SYMBOL: + case MySQLLexer::COLUMNS_SYMBOL: + case MySQLLexer::COMMITTED_SYMBOL: + case MySQLLexer::COMPACT_SYMBOL: + case MySQLLexer::COMPLETION_SYMBOL: + case MySQLLexer::COMPONENT_SYMBOL: + case MySQLLexer::COMPRESSED_SYMBOL: + case MySQLLexer::COMPRESSION_SYMBOL: + case MySQLLexer::CONCURRENT_SYMBOL: + case MySQLLexer::CONNECTION_SYMBOL: + case MySQLLexer::CONSISTENT_SYMBOL: + case MySQLLexer::CONSTRAINT_CATALOG_SYMBOL: + case MySQLLexer::CONSTRAINT_NAME_SYMBOL: + case MySQLLexer::CONSTRAINT_SCHEMA_SYMBOL: + case MySQLLexer::CONTEXT_SYMBOL: + case MySQLLexer::CONTRIBUTORS_SYMBOL: + case MySQLLexer::CPU_SYMBOL: + case MySQLLexer::CURRENT_SYMBOL: + case MySQLLexer::CURSOR_NAME_SYMBOL: + case MySQLLexer::DATA_SYMBOL: + case MySQLLexer::DATAFILE_SYMBOL: + case MySQLLexer::DATETIME_SYMBOL: + case MySQLLexer::DATE_SYMBOL: + case MySQLLexer::DAY_SYMBOL: + case MySQLLexer::DEFAULT_AUTH_SYMBOL: + case MySQLLexer::DEFINER_SYMBOL: + case MySQLLexer::DELAY_KEY_WRITE_SYMBOL: + case MySQLLexer::DES_KEY_FILE_SYMBOL: + case MySQLLexer::DESCRIPTION_SYMBOL: + case MySQLLexer::DIAGNOSTICS_SYMBOL: + case MySQLLexer::DIRECTORY_SYMBOL: + case MySQLLexer::DISABLE_SYMBOL: + case MySQLLexer::DISCARD_SYMBOL: + case MySQLLexer::DISK_SYMBOL: + case MySQLLexer::DUMPFILE_SYMBOL: + case MySQLLexer::DUPLICATE_SYMBOL: + case MySQLLexer::DYNAMIC_SYMBOL: + case MySQLLexer::ENABLE_SYMBOL: + case MySQLLexer::ENCRYPTION_SYMBOL: + case MySQLLexer::ENDS_SYMBOL: + case MySQLLexer::ENUM_SYMBOL: + case MySQLLexer::ENGINE_SYMBOL: + case MySQLLexer::ENGINES_SYMBOL: + case MySQLLexer::ERROR_SYMBOL: + case MySQLLexer::ERRORS_SYMBOL: + case MySQLLexer::ESCAPED_SYMBOL: + case MySQLLexer::ESCAPE_SYMBOL: + case MySQLLexer::EVENTS_SYMBOL: + case MySQLLexer::EVERY_SYMBOL: + case MySQLLexer::EXCLUDE_SYMBOL: + case MySQLLexer::EXPANSION_SYMBOL: + case MySQLLexer::EXPORT_SYMBOL: + case MySQLLexer::EXTENDED_SYMBOL: + case MySQLLexer::EXTENT_SIZE_SYMBOL: + case MySQLLexer::FAULTS_SYMBOL: + case MySQLLexer::FAST_SYMBOL: + case MySQLLexer::FILE_BLOCK_SIZE_SYMBOL: + case MySQLLexer::FILTER_SYMBOL: + case MySQLLexer::FIRST_SYMBOL: + case MySQLLexer::FIXED_SYMBOL: + case MySQLLexer::FOLLOWING_SYMBOL: + case MySQLLexer::FOUND_SYMBOL: + case MySQLLexer::FOUND_ROWS_SYMBOL: + case MySQLLexer::FULL_SYMBOL: + case MySQLLexer::GENERAL_SYMBOL: + case MySQLLexer::GEOMETRY_SYMBOL: + case MySQLLexer::GEOMETRYCOLLECTION_SYMBOL: + case MySQLLexer::GET_FORMAT_SYMBOL: + case MySQLLexer::GRANTS_SYMBOL: + case MySQLLexer::GLOBAL_SYMBOL: + case MySQLLexer::HASH_SYMBOL: + case MySQLLexer::HISTOGRAM_SYMBOL: + case MySQLLexer::HISTORY_SYMBOL: + case MySQLLexer::HOSTS_SYMBOL: + case MySQLLexer::HOUR_SYMBOL: + case MySQLLexer::IDENTIFIED_SYMBOL: + case MySQLLexer::IGNORE_SERVER_IDS_SYMBOL: + case MySQLLexer::INACTIVE_SYMBOL: + case MySQLLexer::INDEXES_SYMBOL: + case MySQLLexer::INITIAL_SIZE_SYMBOL: + case MySQLLexer::INSTANCE_SYMBOL: + case MySQLLexer::INVOKER_SYMBOL: + case MySQLLexer::IO_SYMBOL: + case MySQLLexer::IPC_SYMBOL: + case MySQLLexer::ISOLATION_SYMBOL: + case MySQLLexer::ISSUER_SYMBOL: + case MySQLLexer::INSERT_METHOD_SYMBOL: + case MySQLLexer::JSON_SYMBOL: + case MySQLLexer::KEY_BLOCK_SIZE_SYMBOL: + case MySQLLexer::LAST_SYMBOL: + case MySQLLexer::LEAVES_SYMBOL: + case MySQLLexer::LESS_SYMBOL: + case MySQLLexer::LEVEL_SYMBOL: + case MySQLLexer::LINESTRING_SYMBOL: + case MySQLLexer::LIST_SYMBOL: + case MySQLLexer::LOCAL_SYMBOL: + case MySQLLexer::LOCK_SYMBOL: + case MySQLLexer::LOCKS_SYMBOL: + case MySQLLexer::LOCKED_SYMBOL: + case MySQLLexer::LOGFILE_SYMBOL: + case MySQLLexer::LOGS_SYMBOL: + case MySQLLexer::MASTER_SYMBOL: + case MySQLLexer::MASTER_AUTO_POSITION_SYMBOL: + case MySQLLexer::MASTER_BIND_SYMBOL: + case MySQLLexer::MASTER_COMPRESSION_ALGORITHM_SYMBOL: + case MySQLLexer::MASTER_CONNECT_RETRY_SYMBOL: + case MySQLLexer::MASTER_DELAY_SYMBOL: + case MySQLLexer::MASTER_HEARTBEAT_PERIOD_SYMBOL: + case MySQLLexer::MASTER_HOST_SYMBOL: + case MySQLLexer::MASTER_LOG_FILE_SYMBOL: + case MySQLLexer::MASTER_LOG_POS_SYMBOL: + case MySQLLexer::MASTER_PASSWORD_SYMBOL: + case MySQLLexer::MASTER_PORT_SYMBOL: + case MySQLLexer::MASTER_PUBLIC_KEY_PATH_SYMBOL: + case MySQLLexer::MASTER_RETRY_COUNT_SYMBOL: + case MySQLLexer::MASTER_SERVER_ID_SYMBOL: + case MySQLLexer::MASTER_SSL_CAPATH_SYMBOL: + case MySQLLexer::MASTER_SSL_CA_SYMBOL: + case MySQLLexer::MASTER_SSL_CERT_SYMBOL: + case MySQLLexer::MASTER_SSL_CIPHER_SYMBOL: + case MySQLLexer::MASTER_SSL_CRL_SYMBOL: + case MySQLLexer::MASTER_SSL_CRLPATH_SYMBOL: + case MySQLLexer::MASTER_SSL_KEY_SYMBOL: + case MySQLLexer::MASTER_SSL_SYMBOL: + case MySQLLexer::MASTER_SSL_VERIFY_SERVER_CERT_SYMBOL: + case MySQLLexer::MASTER_TLS_CIPHERSUITES_SYMBOL: + case MySQLLexer::MASTER_TLS_VERSION_SYMBOL: + case MySQLLexer::MASTER_USER_SYMBOL: + case MySQLLexer::MASTER_ZSTD_COMPRESSION_LEVEL_SYMBOL: + case MySQLLexer::MATCH_SYMBOL: + case MySQLLexer::MAX_CONNECTIONS_PER_HOUR_SYMBOL: + case MySQLLexer::MAX_QUERIES_PER_HOUR_SYMBOL: + case MySQLLexer::MAX_ROWS_SYMBOL: + case MySQLLexer::MAX_SIZE_SYMBOL: + case MySQLLexer::MAX_STATEMENT_TIME_SYMBOL: + case MySQLLexer::MAX_UPDATES_PER_HOUR_SYMBOL: + case MySQLLexer::MAX_USER_CONNECTIONS_SYMBOL: + case MySQLLexer::MAXVALUE_SYMBOL: + case MySQLLexer::MAX_SYMBOL: + case MySQLLexer::MEDIUM_SYMBOL: + case MySQLLexer::MEDIUMBLOB_SYMBOL: + case MySQLLexer::MEDIUMINT_SYMBOL: + case MySQLLexer::MEDIUMTEXT_SYMBOL: + case MySQLLexer::MEMBER_SYMBOL: + case MySQLLexer::MEMORY_SYMBOL: + case MySQLLexer::MERGE_SYMBOL: + case MySQLLexer::MESSAGE_TEXT_SYMBOL: + case MySQLLexer::MICROSECOND_SYMBOL: + case MySQLLexer::MIDDLEINT_SYMBOL: + case MySQLLexer::MIGRATE_SYMBOL: + case MySQLLexer::MINUTE_SYMBOL: + case MySQLLexer::MIN_ROWS_SYMBOL: + case MySQLLexer::MIN_SYMBOL: + case MySQLLexer::MODE_SYMBOL: + case MySQLLexer::MODIFIES_SYMBOL: + case MySQLLexer::MODIFY_SYMBOL: + case MySQLLexer::MOD_SYMBOL: + case MySQLLexer::MONTH_SYMBOL: + case MySQLLexer::MULTILINESTRING_SYMBOL: + case MySQLLexer::MULTIPOINT_SYMBOL: + case MySQLLexer::MULTIPOLYGON_SYMBOL: + case MySQLLexer::MUTEX_SYMBOL: + case MySQLLexer::MYSQL_ERRNO_SYMBOL: + case MySQLLexer::NAME_SYMBOL: + case MySQLLexer::NAMES_SYMBOL: + case MySQLLexer::NATIONAL_SYMBOL: + case MySQLLexer::NETWORK_NAMESPACE_SYMBOL: + case MySQLLexer::NCHAR_SYMBOL: + case MySQLLexer::NDBCLUSTER_SYMBOL: + case MySQLLexer::NDB_SYMBOL: + case MySQLLexer::NEG_SYMBOL: + case MySQLLexer::NESTED_SYMBOL: + case MySQLLexer::NEVER_SYMBOL: + case MySQLLexer::NEW_SYMBOL: + case MySQLLexer::NEXT_SYMBOL: + case MySQLLexer::NODEGROUP_SYMBOL: + case MySQLLexer::NONE_SYMBOL: + case MySQLLexer::NONBLOCKING_SYMBOL: + case MySQLLexer::NO_WAIT_SYMBOL: + case MySQLLexer::NO_WRITE_TO_BINLOG_SYMBOL: + case MySQLLexer::NULL_SYMBOL: + case MySQLLexer::NULLS_SYMBOL: + case MySQLLexer::NUMBER_SYMBOL: + case MySQLLexer::NUMERIC_SYMBOL: + case MySQLLexer::NVARCHAR_SYMBOL: + case MySQLLexer::OFFSET_SYMBOL: + case MySQLLexer::OLD_PASSWORD_SYMBOL: + case MySQLLexer::OLD_SYMBOL: + case MySQLLexer::ONE_SYMBOL: + case MySQLLexer::OPTIONAL_SYMBOL: + case MySQLLexer::OPTIONALLY_SYMBOL: + case MySQLLexer::OPTION_SYMBOL: + case MySQLLexer::OPTIONS_SYMBOL: + case MySQLLexer::OPTIMIZE_SYMBOL: + case MySQLLexer::OPTIMIZER_COSTS_SYMBOL: + case MySQLLexer::ORDINALITY_SYMBOL: + case MySQLLexer::ORGANIZATION_SYMBOL: + case MySQLLexer::OTHERS_SYMBOL: + case MySQLLexer::OUTER_SYMBOL: + case MySQLLexer::OUTFILE_SYMBOL: + case MySQLLexer::OUT_SYMBOL: + case MySQLLexer::OWNER_SYMBOL: + case MySQLLexer::PACK_KEYS_SYMBOL: + case MySQLLexer::PAGE_SYMBOL: + case MySQLLexer::PARSER_SYMBOL: + case MySQLLexer::PARTIAL_SYMBOL: + case MySQLLexer::PARTITIONING_SYMBOL: + case MySQLLexer::PARTITION_SYMBOL: + case MySQLLexer::PARTITIONS_SYMBOL: + case MySQLLexer::PASSWORD_SYMBOL: + + // $this->serverVersion >= 80019 + case MySQLLexer::PASSWORD_LOCK_TIME_SYMBOL: + case MySQLLexer::PATH_SYMBOL: + case MySQLLexer::PERCENT_RANK_SYMBOL: + + // $this->serverVersion >= 80000 + case MySQLLexer::PERSIST_SYMBOL: + + // $this->serverVersion >= 80000 + case MySQLLexer::PERSIST_ONLY_SYMBOL: + case MySQLLexer::PHASE_SYMBOL: + case MySQLLexer::PLUGIN_DIR_SYMBOL: + case MySQLLexer::PLUGINS_SYMBOL: + case MySQLLexer::PLUGIN_SYMBOL: + case MySQLLexer::POINT_SYMBOL: + case MySQLLexer::POLYGON_SYMBOL: + case MySQLLexer::PORT_SYMBOL: + case MySQLLexer::POSITION_SYMBOL: + case MySQLLexer::PRECEDES_SYMBOL: + case MySQLLexer::PRECEDING_SYMBOL: + case MySQLLexer::PRECISION_SYMBOL: + case MySQLLexer::PREPARE_SYMBOL: + case MySQLLexer::PRESERVE_SYMBOL: + case MySQLLexer::PREV_SYMBOL: + case MySQLLexer::THREAD_PRIORITY_SYMBOL: + case MySQLLexer::PRIVILEGES_SYMBOL: + case MySQLLexer::PROCESSLIST_SYMBOL: + case MySQLLexer::PROFILE_SYMBOL: + case MySQLLexer::PROFILES_SYMBOL: + case MySQLLexer::QUARTER_SYMBOL: + case MySQLLexer::QUERY_SYMBOL: + case MySQLLexer::QUICK_SYMBOL: + case MySQLLexer::READ_ONLY_SYMBOL: + case MySQLLexer::REBUILD_SYMBOL: + case MySQLLexer::RECOVER_SYMBOL: + case MySQLLexer::REDOFILE_SYMBOL: + case MySQLLexer::REDO_BUFFER_SIZE_SYMBOL: + case MySQLLexer::REDUNDANT_SYMBOL: + case MySQLLexer::REFERENCES_SYMBOL: + case MySQLLexer::REFERENCE_SYMBOL: + case MySQLLexer::RELAY_SYMBOL: + case MySQLLexer::RELAYLOG_SYMBOL: + case MySQLLexer::RELAY_LOG_FILE_SYMBOL: + case MySQLLexer::RELAY_LOG_POS_SYMBOL: + case MySQLLexer::RELAY_THREAD_SYMBOL: + case MySQLLexer::REMOTE_SYMBOL: + case MySQLLexer::REORGANIZE_SYMBOL: + case MySQLLexer::REPEATABLE_SYMBOL: + case MySQLLexer::REPLICATE_DO_DB_SYMBOL: + case MySQLLexer::REPLICATE_IGNORE_DB_SYMBOL: + case MySQLLexer::REPLICATE_DO_TABLE_SYMBOL: + case MySQLLexer::REPLICATE_IGNORE_TABLE_SYMBOL: + case MySQLLexer::REPLICATE_REWRITE_DB_SYMBOL: + case MySQLLexer::REPLICATE_WILD_DO_TABLE_SYMBOL: + case MySQLLexer::REPLICATE_WILD_IGNORE_TABLE_SYMBOL: + case MySQLLexer::USER_RESOURCES_SYMBOL: + + // $this->serverVersion >= 80000 + case MySQLLexer::RESPECT_SYMBOL: + + // $this->serverVersion >= 80000 + case MySQLLexer::RESUME_SYMBOL: + + // $this->serverVersion >= 80000 + case MySQLLexer::RETAIN_SYMBOL: + case MySQLLexer::RETURNED_SQLSTATE_SYMBOL: + case MySQLLexer::RETURNS_SYMBOL: + case MySQLLexer::REUSE_SYMBOL: + case MySQLLexer::REVERSE_SYMBOL: + case MySQLLexer::ROLLUP_SYMBOL: + case MySQLLexer::ROTATE_SYMBOL: + case MySQLLexer::ROUTINE_SYMBOL: + case MySQLLexer::ROW_COUNT_SYMBOL: + case MySQLLexer::ROW_FORMAT_SYMBOL: + case MySQLLexer::RTREE_SYMBOL: + case MySQLLexer::SCHEDULE_SYMBOL: + case MySQLLexer::SCHEMA_NAME_SYMBOL: + case MySQLLexer::SECOND_SYMBOL: + case MySQLLexer::SECURITY_SYMBOL: + case MySQLLexer::SERIAL_SYMBOL: + case MySQLLexer::SERIALIZABLE_SYMBOL: + case MySQLLexer::SESSION_SYMBOL: + case MySQLLexer::SHARE_SYMBOL: + case MySQLLexer::SIMPLE_SYMBOL: + case MySQLLexer::SKIP_SYMBOL: + case MySQLLexer::SLOW_SYMBOL: + case MySQLLexer::SNAPSHOT_SYMBOL: + case MySQLLexer::SOUNDS_SYMBOL: + case MySQLLexer::SOURCE_SYMBOL: + case MySQLLexer::SPATIAL_SYMBOL: + case MySQLLexer::SQL_AFTER_GTIDS_SYMBOL: + case MySQLLexer::SQL_AFTER_MTS_GAPS_SYMBOL: + case MySQLLexer::SQL_BEFORE_GTIDS_SYMBOL: + case MySQLLexer::SQL_BIG_RESULT_SYMBOL: + case MySQLLexer::SQL_BUFFER_RESULT_SYMBOL: + case MySQLLexer::SQL_CALC_FOUND_ROWS_SYMBOL: + case MySQLLexer::SQL_CACHE_SYMBOL: + case MySQLLexer::SQL_NO_CACHE_SYMBOL: + case MySQLLexer::SQL_SMALL_RESULT_SYMBOL: + case MySQLLexer::SQL_THREAD_SYMBOL: + + // $this->serverVersion >= 80000 + case MySQLLexer::SRID_SYMBOL: + case MySQLLexer::STACKED_SYMBOL: + case MySQLLexer::STARTS_SYMBOL: + case MySQLLexer::STATS_AUTO_RECALC_SYMBOL: + case MySQLLexer::STATS_PERSISTENT_SYMBOL: + case MySQLLexer::STATS_SAMPLE_PAGES_SYMBOL: + case MySQLLexer::STATUS_SYMBOL: + case MySQLLexer::STD_SYMBOL: + case MySQLLexer::STDDEV_POP_SYMBOL: + case MySQLLexer::STDDEV_SAMP_SYMBOL: + case MySQLLexer::STDDEV_SYMBOL: + case MySQLLexer::STORAGE_SYMBOL: + case MySQLLexer::STORED_SYMBOL: + case MySQLLexer::STRAIGHT_JOIN_SYMBOL: + + // $this->serverVersion >= 80000 + case MySQLLexer::STREAM_SYMBOL: + case MySQLLexer::STRING_SYMBOL: + case MySQLLexer::SUBCLASS_ORIGIN_SYMBOL: + case MySQLLexer::SUBDATE_SYMBOL: + case MySQLLexer::SUBJECT_SYMBOL: + case MySQLLexer::SUBPARTITION_SYMBOL: + case MySQLLexer::SUBPARTITIONS_SYMBOL: + case MySQLLexer::SUBSTR_SYMBOL: + case MySQLLexer::SUBSTRING_SYMBOL: + case MySQLLexer::SUM_SYMBOL: + case MySQLLexer::SUPER_SYMBOL: + case MySQLLexer::SUSPEND_SYMBOL: + case MySQLLexer::SWAPS_SYMBOL: + case MySQLLexer::SWITCHES_SYMBOL: + case MySQLLexer::SYSDATE_SYMBOL: + case MySQLLexer::SYSTEM_SYMBOL: + case MySQLLexer::SYSTEM_USER_SYMBOL: + case MySQLLexer::TABLE_NAME_SYMBOL: + case MySQLLexer::TABLE_CHECKSUM_SYMBOL: + case MySQLLexer::TABLES_SYMBOL: + case MySQLLexer::TABLESPACE_SYMBOL: + case MySQLLexer::TEMPORARY_SYMBOL: + case MySQLLexer::TEMPTABLE_SYMBOL: + case MySQLLexer::TERMINATED_SYMBOL: + case MySQLLexer::TEXT_SYMBOL: + case MySQLLexer::THAN_SYMBOL: + case MySQLLexer::TIES_SYMBOL: + case MySQLLexer::TIME_SYMBOL: + case MySQLLexer::TIMESTAMP_SYMBOL: + case MySQLLexer::TIMESTAMP_ADD_SYMBOL: + case MySQLLexer::TIMESTAMP_DIFF_SYMBOL: + case MySQLLexer::TINYBLOB_SYMBOL: + case MySQLLexer::TINYINT_SYMBOL: + case MySQLLexer::TINYTEXT_SYMBOL: + case MySQLLexer::TYPES_SYMBOL: + case MySQLLexer::TYPE_SYMBOL: + case MySQLLexer::UDF_RETURNS_SYMBOL: + case MySQLLexer::UNBOUNDED_SYMBOL: + case MySQLLexer::UNCOMMITTED_SYMBOL: + case MySQLLexer::UNDO_BUFFER_SIZE_SYMBOL: + case MySQLLexer::UNDOFILE_SYMBOL: + case MySQLLexer::UNKNOWN_SYMBOL: + case MySQLLexer::UNTIL_SYMBOL: + case MySQLLexer::UPGRADE_SYMBOL: + case MySQLLexer::USER_SYMBOL: + case MySQLLexer::USE_FRM_SYMBOL: + case MySQLLexer::VALIDATION_SYMBOL: + case MySQLLexer::VALUE_SYMBOL: + case MySQLLexer::VALUES_SYMBOL: + case MySQLLexer::VARBINARY_SYMBOL: + case MySQLLexer::VARCHAR_SYMBOL: + case MySQLLexer::VARIABLES_SYMBOL: + case MySQLLexer::VARIANCE_SYMBOL: + case MySQLLexer::VARYING_SYMBOL: + case MySQLLexer::VAR_POP_SYMBOL: + case MySQLLexer::VAR_SAMP_SYMBOL: + case MySQLLexer::VCPU_SYMBOL: + case MySQLLexer::VIEW_SYMBOL: + case MySQLLexer::VIRTUAL_SYMBOL: + case MySQLLexer::VISIBLE_SYMBOL: + case MySQLLexer::WAIT_SYMBOL: + case MySQLLexer::WARNINGS_SYMBOL: + case MySQLLexer::WEEK_SYMBOL: + case MySQLLexer::WEIGHT_STRING_SYMBOL: + case MySQLLexer::WHEN_SYMBOL: + case MySQLLexer::WHERE_SYMBOL: + case MySQLLexer::WHILE_SYMBOL: + case MySQLLexer::WINDOW_SYMBOL: + case MySQLLexer::WITH_SYMBOL: + case MySQLLexer::WITHOUT_SYMBOL: + case MySQLLexer::WORK_SYMBOL: + case MySQLLexer::WRAPPER_SYMBOL: + case MySQLLexer::WRITE_SYMBOL: + case MySQLLexer::XA_SYMBOL: + case MySQLLexer::X509_SYMBOL: + case MySQLLexer::XID_SYMBOL: + case MySQLLexer::XML_SYMBOL: + case MySQLLexer::XOR_SYMBOL: + case MySQLLexer::YEAR_SYMBOL: + case MySQLLexer::YEAR_MONTH_SYMBOL: + case MySQLLexer::ZEROFILL_SYMBOL: + return ASTNode::fromToken($token); + default: + throw new \Exception('Unexpected token in identifierKeywordsUnambiguous: ' . $token->getText()); + } + } + + private function isUnambiguousIdentifierStart($token) + { + return $this->isPureIdentifierStart($token) || $this->isIdentifierKeyword($token); + } + + private function isExprStart($token) + { + return $this->isBoolPriStart($token); + } + + private function isIntervalTimeStampStart($token) + { + switch ($token->getType()) { + case MySQLLexer::MICROSECOND_SYMBOL: + case MySQLLexer::SECOND_SYMBOL: + case MySQLLexer::MINUTE_SYMBOL: + case MySQLLexer::HOUR_SYMBOL: + case MySQLLexer::DAY_SYMBOL: + case MySQLLexer::WEEK_SYMBOL: + case MySQLLexer::MONTH_SYMBOL: + case MySQLLexer::QUARTER_SYMBOL: + case MySQLLexer::YEAR_SYMBOL: + case MySQLLexer::SQL_TSI_SECOND_SYMBOL: + case MySQLLexer::SQL_TSI_MINUTE_SYMBOL: + case MySQLLexer::SQL_TSI_HOUR_SYMBOL: + case MySQLLexer::SQL_TSI_DAY_SYMBOL: + case MySQLLexer::SQL_TSI_WEEK_SYMBOL: + case MySQLLexer::SQL_TSI_MONTH_SYMBOL: + case MySQLLexer::SQL_TSI_QUARTER_SYMBOL: + case MySQLLexer::SQL_TSI_YEAR_SYMBOL: + return true; + default: + return false; + } + + } + + private function isTextOrIdentifierStart($token) + { + return $token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token) || + $token->getType() === MySQLLexer::SINGLE_QUOTED_TEXT; + } + + private function isRoleIdentifierStart($token) + { + return $this->isPureIdentifierStart($token) || $this->isRoleKeyword($token); + } + + public function schemaName() + { + return $this->identifier(); + } + + public function schemaRef() + { + return $this->identifier(); + } + + public function procedureName() + { + return $this->qualifiedIdentifier(); + } + + public function procedureRef() + { + return $this->qualifiedIdentifier(); + } + + public function functionName() + { + return $this->qualifiedIdentifier(); + } + + public function functionRef() + { + return $this->qualifiedIdentifier(); + } + + public function triggerName() + { + return $this->qualifiedIdentifier(); + } + + public function triggerRef() + { + return $this->qualifiedIdentifier(); + } + + public function viewName() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::DOT_SYMBOL) { + return $this->dotIdentifier(); + } elseif ($this->isQualifiedIdentifierStart($token)) { + return $this->qualifiedIdentifier(); + } else { + throw new \Exception('Unexpected token in viewName: ' . $token->getText()); + } + } + + public function viewRef() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::DOT_SYMBOL) { + return $this->dotIdentifier(); + } elseif ($this->isQualifiedIdentifierStart($token)) { + return $this->qualifiedIdentifier(); + } else { + throw new \Exception('Unexpected token in viewRef: ' . $token->getText()); + } + } + + public function tablespaceName() + { + return $this->identifier(); + } + + public function tablespaceRef() + { + return $this->identifier(); + } + + public function logfileGroupName() + { + return $this->identifier(); + } + + public function logfileGroupRef() + { + return $this->identifier(); + } + + public function eventName() + { + return $this->qualifiedIdentifier(); + } + + public function eventRef() + { + return $this->qualifiedIdentifier(); + } + + public function serverName() + { + return $this->textOrIdentifier(); + } + + public function serverRef() + { + return $this->textOrIdentifier(); + } + + public function engineRef() + { + return $this->textOrIdentifier(); + } + + public function tableName() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::DOT_SYMBOL) { + return $this->dotIdentifier(); + } elseif ($this->isQualifiedIdentifierStart($token)) { + return $this->qualifiedIdentifier(); + } else { + throw new \Exception('Unexpected token in tableName: ' . $token->getText()); + } + } + + public function filterTableRef() + { + $children = []; + + $children[] = $this->schemaRef(); + $children[] = $this->dotIdentifier(); + + return new ASTNode('filterTableRef', $children); + } + + public function tableRefWithWildcard() + { + $children = []; + $children[] = $this->identifier(); + + if ($this->lexer->peekNextToken()->getType() === MySQLLexer::DOT_SYMBOL) { + $children[] = $this->match(MySQLLexer::DOT_SYMBOL); + if ($this->lexer->peekNextToken()->getType() !== MySQLLexer::MULT_OPERATOR) { + $children[] = $this->identifier(); + $children[] = $this->match(MySQLLexer::DOT_SYMBOL); + } + $children[] = $this->match(MySQLLexer::MULT_OPERATOR); + } + + return new ASTNode('tableRefWithWildcard', $children); + } + + public function tableRef() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::DOT_SYMBOL) { + return $this->dotIdentifier(); + } elseif ($this->isQualifiedIdentifierStart($token)) { + return $this->qualifiedIdentifier(); + } else { + throw new \Exception('Unexpected token in tableRef: ' . $token->getText()); + } + } + + public function tableRefList() + { + $children = []; + $children[] = $this->tableRef(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->tableRef(); + } + return new ASTNode('tableRefList', $children); + } + + public function tableAliasRefList() + { + $children = []; + $children[] = $this->tableRefWithWildcard(); + while ($this->lexer->peekNextToken()->getType() === MySQLLexer::COMMA_SYMBOL) { + $children[] = $this->match(MySQLLexer::COMMA_SYMBOL); + $children[] = $this->tableRefWithWildcard(); + } + return new ASTNode('tableAliasRefList', $children); + } + + public function parameterName() + { + return $this->identifier(); + } + + public function labelIdentifier() + { + $token = $this->lexer->peekNextToken(); + + if ($this->isPureIdentifierStart($token)) { + return $this->pureIdentifier(); + } elseif ($this->isLabelKeyword($token)) { + return $this->labelKeyword(); + } else { + throw new \Exception('Unexpected token for labelIdentifier: ' . $token->getText()); + } + } + + public function labelRef() + { + return $this->labelIdentifier(); + } + + public function udfName() + { + return $this->identifier(); + } + + public function pluginRef() + { + return $this->identifier(); + } + + public function componentRef() + { + return $this->textStringLiteral(); + } + + public function resourceGroupRef() + { + return $this->identifier(); + } + + public function windowName() + { + return $this->identifier(); + } + + public function roleIdentifier() + { + $token = $this->lexer->peekNextToken(); + if ($this->isPureIdentifierStart($token)) { + return $this->pureIdentifier(); + } elseif ($this->isRoleKeyword($token)) { + return $this->roleKeyword(); + } else { + throw new \Exception('Unexpected token for identifier: ' . $token->getText()); + } + } + + public function roleRef() + { + return $this->roleIdentifier(); + } + + public function identifierKeyword() + { + $token = $this->lexer->peekNextToken(); + + if ($this->isIdentifierKeywordsUnambiguous($token)) { + return $this->identifierKeywordsUnambiguous(); + } elseif ($this->isIdentifierKeywordsAmbiguous1RolesAndLabels($token)) { + return $this->identifierKeywordsAmbiguous1RolesAndLabels(); + } elseif ($this->isIdentifierKeywordsAmbiguous2Labels($token)) { + return $this->identifierKeywordsAmbiguous2Labels(); + } elseif ($this->isIdentifierKeywordsAmbiguous3Roles($token)) { + return $this->identifierKeywordsAmbiguous3Roles(); + } elseif ($this->isIdentifierKeywordsAmbiguous4SystemVariables($token)) { + return $this->identifierKeywordsAmbiguous4SystemVariables(); + } else { + throw new \Exception('Unexpected token in identifierKeyword: ' . $token->getText()); + } + } + + private function identifierKeywordsUnambiguous() { + $token = $this->lexer->getNextToken(); + if(!$this->isIdentifierKeywordsUnambiguous($token)) { + throw new \Exception('Unexpected token in identifierKeywordsUnambiguous: ' . $token->getText()); + } + return ASTNode::fromToken($token); + } + + public function labelKeyword() + { + if ($this->serverVersion < 80017) { + if ($this->isRoleOrLabelKeyword($this->lexer->peekNextToken())) { + return $this->roleOrLabelKeyword(); + } + $token = $this->lexer->getNextToken(); + switch ($token->getType()) { + case MySQLLexer::EVENT_SYMBOL: + case MySQLLexer::FILE_SYMBOL: + case MySQLLexer::NONE_SYMBOL: + case MySQLLexer::PROCESS_SYMBOL: + case MySQLLexer::PROXY_SYMBOL: + case MySQLLexer::RELOAD_SYMBOL: + case MySQLLexer::REPLICATION_SYMBOL: + case MySQLLexer::RESOURCE_SYMBOL: + case MySQLLexer::SUPER_SYMBOL: + return ASTNode::fromToken($token); + + default: + // Handle unexpected token + throw new \Exception('Unexpected token: ' . $this->lexer->peekNextToken()->getText()); + } + } + + $token = $this->lexer->peekNextToken(); + + if ($this->isIdentifierKeywordsUnambiguous($token)) { + return $this->identifierKeywordsUnambiguous(); + } elseif ($this->isIdentifierKeywordsAmbiguous3Roles($token)) { + return $this->identifierKeywordsAmbiguous3Roles(); + } elseif ($this->isIdentifierKeywordsAmbiguous4SystemVariables($token)) { + return $this->identifierKeywordsAmbiguous4SystemVariables(); + } else { + throw new \Exception('Unexpected token in labelKeyword: ' . $token->getText()); + } + } + + public function roleKeyword() + { + if ($this->serverVersion < 80017) { + if ($this->isRoleOrIdentifierKeyword($this->lexer->peekNextToken())) { + return $this->lexer->getNextToken(); + } elseif ($this->isRoleOrLabelKeyword($this->lexer->peekNextToken())) { + return $this->roleOrLabelKeyword(); + } + } + + $token = $this->lexer->peekNextToken(); + + if ($this->isIdentifierKeywordsUnambiguous($token)) { + return $this->identifierKeywordsUnambiguous(); + } elseif ($this->isIdentifierKeywordsAmbiguous2Labels($token)) { + return $this->identifierKeywordsAmbiguous2Labels(); + } elseif ($this->isIdentifierKeywordsAmbiguous4SystemVariables($token)) { + return $this->identifierKeywordsAmbiguous4SystemVariables(); + } else { + throw new \Exception('Unexpected token in roleKeyword: ' . $token->getText()); + } + } + + public function lValueKeyword() + { + $token = $this->lexer->peekNextToken(); + + if ($this->isIdentifierKeywordsUnambiguous($token)) { + return $this->identifierKeywordsUnambiguous(); + } elseif ($this->isIdentifierKeywordsAmbiguous1RolesAndLabels($token)) { + return $this->identifierKeywordsAmbiguous1RolesAndLabels(); + } elseif ($this->isIdentifierKeywordsAmbiguous2Labels($token)) { + return $this->identifierKeywordsAmbiguous2Labels(); + } elseif ($this->isIdentifierKeywordsAmbiguous3Roles($token)) { + return $this->identifierKeywordsAmbiguous3Roles(); + } else { + throw new \Exception('Unexpected token in lValueKeyword: ' . $token->getText()); + } + } + + public function pureIdentifier() + { + $token = $this->lexer->getNextToken(); + if ($token->getType() === MySQLLexer::IDENTIFIER) { + return ASTNode::fromToken($token); + } elseif ($token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID) { + return ASTNode::fromToken($token); + } elseif ($token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT) { + return ASTNode::fromToken($token); + } else { + throw new \Exception('Unexpected token in pureIdentifier: ' . $token->getText()); + } + } + + public function columnFormat() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::FIXED_SYMBOL) { + return $this->match(MySQLLexer::FIXED_SYMBOL); + } elseif ($token->getType() === MySQLLexer::DYNAMIC_SYMBOL) { + return $this->match(MySQLLexer::DYNAMIC_SYMBOL); + } else { + return $this->match(MySQLLexer::DEFAULT_SYMBOL); + } + } + + public function storageMedia() + { + $token = $this->lexer->peekNextToken(); + if ($token->getType() === MySQLLexer::DISK_SYMBOL) { + return $this->match(MySQLLexer::DISK_SYMBOL); + } elseif ($token->getType() === MySQLLexer::MEMORY_SYMBOL) { + return $this->match(MySQLLexer::MEMORY_SYMBOL); + } else { + return $this->match(MySQLLexer::DEFAULT_SYMBOL); + } + } + + public function varIdentType() + { + $children = []; + $token = $this->lexer->getNextToken(); + + switch ($token->getType()) { + case MySQLLexer::GLOBAL_SYMBOL: + case MySQLLexer::LOCAL_SYMBOL: + case MySQLLexer::SESSION_SYMBOL: + $children[] = ASTNode::fromToken($token); + break; + default: + throw new \Exception('Unexpected token in varIdentType: ' . $token->getText()); + } + $children[] = $this->match(MySQLLexer::DOT_SYMBOL); + return new ASTNode('varIdentType', $children); + } + + public function setVarIdentType() + { + $token = $this->lexer->getNextToken(); + $children = []; + switch ($token->getType()) { + case MySQLLexer::GLOBAL_SYMBOL: + case MySQLLexer::LOCAL_SYMBOL: + case MySQLLexer::SESSION_SYMBOL: + case MySQLLexer::PERSIST_SYMBOL: + case MySQLLexer::PERSIST_ONLY_SYMBOL: + $children[] = ASTNode::fromToken($token); + break; + default: + throw new \Exception('Unexpected token in setVarIdentType: ' . $token->getText()); + } + $children[] = $this->match(MySQLLexer::DOT_SYMBOL); + return new ASTNode('setVarIdentType', $children); + } + + private function isQualifiedIdentifierStart($token) + { + return $token->getType() === MySQLLexer::IDENTIFIER || + $token->getType() === MySQLLexer::BACK_TICK_QUOTED_ID || + $token->getType() === MySQLLexer::DOUBLE_QUOTED_TEXT || + $this->isIdentifierKeyword($token); + } + + private function match($expectedType) + { + $token = $this->lexer->getNextToken(); + + if ($token->getType() === $expectedType) { + $node = new ASTNode(MySQLLexer::getTokenName($token->getType()), $token->getText()); + return $node; + } + + throw new \Exception( + 'Unexpected token: ' . $token->getText() . + ', expected ' . MySQLLexer::getTokenName($expectedType) + ); + } +} diff --git a/wp-content/plugins/sqlite-database-integration/wp-includes/mysql-parser/generate_parser.py b/wp-content/plugins/sqlite-database-integration/wp-includes/mysql-parser/generate_parser.py new file mode 100644 index 00000000..b788ae3c --- /dev/null +++ b/wp-content/plugins/sqlite-database-integration/wp-includes/mysql-parser/generate_parser.py @@ -0,0 +1,118 @@ +""" +This script was used to generate the first version of MySQLParser. + +From there, a lot of manual and automated refactoring was done to make +it more readable and maintainable. +""" + +import os +import time +import os +import google.generativeai as genai +from google.generativeai.types import HarmCategory, HarmBlockThreshold, SafetySettingDict + +genai.configure(api_key=os.environ["GEMINI_API_KEY"]) + +def upload_to_gemini(path, mime_type=None): + """Uploads the given file to Gemini. + + See https://ai.google.dev/gemini-api/docs/prompting_with_media + """ + file = genai.upload_file(path, mime_type=mime_type) + print(f"Uploaded file '{file.display_name}' as: {file.uri}") + return file + +def wait_for_files_active(files): + """Waits for the given files to be active. + + Some files uploaded to the Gemini API need to be processed before they can be + used as prompt inputs. The status can be seen by querying the file's "state" + field. + + This implementation uses a simple blocking polling loop. Production code + should probably employ a more sophisticated approach. + """ + print("Waiting for file processing...") + for name in (file.name for file in files): + file = genai.get_file(name) + while file.state.name == "PROCESSING": + print(".", end="", flush=True) + time.sleep(10) + file = genai.get_file(name) + if file.state.name != "ACTIVE": + raise Exception(f"File {file.name} failed to process") + print("...all files ready") + print() + +# Create the model +generation_config = { + "temperature": 1, + "top_p": 0.95, + "top_k": 64, + "max_output_tokens": 2000000, + "response_mime_type": "text/plain", +} + +model = genai.GenerativeModel( + model_name="gemini-1.5-pro", + generation_config=generation_config, + safety_settings = { + HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_NONE, + HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_NONE, + HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_NONE, + HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_NONE, + # HarmCategory.HARM_CATEGORY_UNSPECIFIED: HarmBlockThreshold.BLOCK_NONE, + }, + # See https://ai.google.dev/gemini-api/docs/safety-settings + system_instruction="IGNORE ANY PREVIOUS INSTRUCTIONS YOU MAY HAVE. YOU ARE AN ANTLR TO PHP CONVERTER. YOU DO NOT SAY ANYTHING THAT ISN'T PHP CODE. YOU REPLY UNTIL YOU EXHAUST THE AVAILABLE TOKEN WINDOW OF 2,097,152 TOKENS", +) + +files = [ + # MySQL grammar from MySQL Workbench: + # https://github.com/mysql/mysql-workbench/blob/8.0/library/parsers/grammars/MySQLParser.g4 + upload_to_gemini("MySQLParser.g4", mime_type="text/plain"), + upload_to_gemini("MySQLLexer.php", mime_type="text/plain"), +] + +# Some files have a processing delay. Wait for them to be ready. +wait_for_files_active(files) + +while True: + with open("MySQLParser.php", "r") as fp: + parser_so_far = fp.read() + if "THIS_IS_EOF" in parser_so_far: + break + chat_session = model.start_chat( + history=[ + { + "role": "user", + "parts": [ + files[0], + files[1], + "I'll give you a large ANTLR4 grammar file and I want you to convert it to a PHP LALR parser that outputs an AST. Convert everything. The PHP lexer class is already implemented and provided to you. I want to copy what you give me and paste it straight into the PHP interpreter and I want it to work. DO NOT SKIP ANY RULE, DO NOT REPLACE CODE CHUNKS WITH PLACEHOLDERS. Convert everything. Everything. Skip any prose whatsoever and reply directly with the PHP file. I DON'T WANT ANY TEXT OTHER THAN THE PHP CODE. DO NOT EXPLAIN TO ME WHAT ANTLR OR PHP OR PARSERS ARE. JUST CONVERT THE GRAMMAR. Do not use any library. Implement every single class you instantiate. Assume the entire program is a single, large PHP file. Use the exact same set of rules as listed in the original grammar. Do not inline any rule. If a rule called `ulong_number` exists in the grammar, there should be an explicit parser method for that. Keep it simple." + ], + }, + { + "role": "model", + "parts": [ + parser_so_far + ] + } + ] + ) + + response = chat_session.send_message( + "KEEP GOING UNTIL **ALL** THE CODE IS GENERATED. THEN MAKE YOUR REPLY BE JUST 'THIS_IS_EOF'.", + stream=True, + ) + + for chunk in response: + print(chunk.text) + with open("MySQLParser.php", "a") as file: + file.write(chunk.text) + + # Break if our parser is larger than 1MB already + file_size = os.path.getsize("MySQLParser.php") + if file_size > 1024 * 1024: + break + diff --git a/wp-content/plugins/sqlite-database-integration/wp-includes/mysql-parser/sql-playground.php b/wp-content/plugins/sqlite-database-integration/wp-includes/mysql-parser/sql-playground.php new file mode 100644 index 00000000..47f4c7b0 --- /dev/null +++ b/wp-content/plugins/sqlite-database-integration/wp-includes/mysql-parser/sql-playground.php @@ -0,0 +1,65 @@ + ['SELECT 1'], + 'grantSelectOnAll' => ['GRANT SELECT ON mydatabase.* TO myuser@localhost;'], +]; + +foreach ($queries as $key => $query) { + printAST(parse($query[0])); +} +// benchmarkParser($queries['acidTest']); + +die(); + +function benchmarkParser($query) { + $start = microtime(true); + + for ($i = 0; $i < 500; $i++) { + parse($query); + } + + $end = microtime(true); + $executionTime = ($end - $start); + + echo "Execution time: " . $executionTime . " seconds"; +} + +function parse($query) { + $lexer = new MySQLLexer($query, 80000); + $parser = new MySQLParser($lexer); + return $parser->query(); +} + +function printAST(ASTNode $ast, $indent = 0) { + echo str_repeat(' ', $indent) . $ast . PHP_EOL; + foreach($ast->children as $child) { + printAST($child, $indent + 2); + } +} + +function printParserTree($parser) { + $parser->query(); + $parser->printTree(); +} + +function printLexerTokens($lexer) { + while($lexer->getNextToken()) { + echo $lexer->getToken() . PHP_EOL; + // var_dump($lexer->getToken()->getType()); + if($lexer->getToken()->getType() === MySQLLexer::EOF) { + break; + } + } +}