3071 lines
150 KiB
PHP
3071 lines
150 KiB
PHP
<?php
|
|
|
|
/**
|
|
* MySQL lexer.
|
|
*
|
|
* An exhaustive lexer for the MySQL SQL dialect with multi-version support.
|
|
* It scans the provided SQL input payload and generates MySQL token objects.
|
|
* The lexer is intended to cover 100% of the MySQL SQL syntax for all MySQL
|
|
* versions starting from 5.7. It's likely to support older versions as well.
|
|
*
|
|
* The lexer is implemented with zero dependencies, it doesn't require any PHP
|
|
* extensions, and it doesn't use PCRE or any other regular expression engines.
|
|
*
|
|
* This lexer is based on the MySQL Workbench lexer grammar.
|
|
* See:
|
|
* https://github.com/mysql/mysql-workbench/blob/8.0.38/library/parsers/grammars/MySQLLexer.g4
|
|
* https://github.com/mysql/mysql-workbench/blob/8.0.38/library/parsers/grammars/predefined.tokens
|
|
* https://github.com/mysql/mysql-workbench/blob/8.0.38/library/parsers/mysql/MySQLBaseLexer.cpp
|
|
*/
|
|
class WP_MySQL_Lexer {
|
|
/**
|
|
* The SQL modes that affect the lexer behavior.
|
|
*
|
|
* These values are intended to be used in a bitmask. See "$this->sql_modes".
|
|
* The list of the SQL modes is not exhaustive. Only the ones that influence
|
|
* the lexer behavior are included in this list.
|
|
*
|
|
* See:
|
|
* https://dev.mysql.com/doc/refman/8.4/en/sql-mode.html
|
|
*/
|
|
const SQL_MODE_HIGH_NOT_PRECEDENCE = 1;
|
|
const SQL_MODE_PIPES_AS_CONCAT = 2;
|
|
const SQL_MODE_IGNORE_SPACE = 4;
|
|
const SQL_MODE_NO_BACKSLASH_ESCAPES = 8;
|
|
|
|
/**
|
|
* Character masks for frequently used character classes.
|
|
*
|
|
* These are intended to be used with "strspn()" and "strcspn()" functions
|
|
* for fast character class matching in the SQL payload.
|
|
*/
|
|
const WHITESPACE_MASK = " \t\n\r\f";
|
|
const DIGIT_MASK = '0123456789';
|
|
const HEX_DIGIT_MASK = '0123456789abcdefABCDEF';
|
|
|
|
/**
|
|
* Tokens from the MySQL Workbench "predefined.tokens" list.
|
|
*
|
|
* This list preserves the token names and IDs from the MySQL Workbench
|
|
* "predefined.tokens" list, adding some tokens missing from the list.
|
|
*
|
|
* See:
|
|
* https://github.com/mysql/mysql-workbench/blob/8.0.38/library/parsers/grammars/predefined.tokens
|
|
*/
|
|
const ACCESSIBLE_SYMBOL = 1;
|
|
const ACCOUNT_SYMBOL = 2;
|
|
const ACTION_SYMBOL = 3;
|
|
const ADD_SYMBOL = 4;
|
|
const ADDDATE_SYMBOL = 5;
|
|
const AFTER_SYMBOL = 6;
|
|
const AGAINST_SYMBOL = 7;
|
|
const AGGREGATE_SYMBOL = 8;
|
|
const ALGORITHM_SYMBOL = 9;
|
|
const ALL_SYMBOL = 10;
|
|
const ALTER_SYMBOL = 11;
|
|
const ALWAYS_SYMBOL = 12;
|
|
const ANALYSE_SYMBOL = 13;
|
|
const ANALYZE_SYMBOL = 14;
|
|
const AND_SYMBOL = 15;
|
|
const ANY_SYMBOL = 16;
|
|
const AS_SYMBOL = 17;
|
|
const ASC_SYMBOL = 18;
|
|
const ASCII_SYMBOL = 19;
|
|
const ASENSITIVE_SYMBOL = 20;
|
|
const AT_SYMBOL = 21;
|
|
const AUTHORS_SYMBOL = 22;
|
|
const AUTOEXTEND_SIZE_SYMBOL = 23;
|
|
const AUTO_INCREMENT_SYMBOL = 24;
|
|
const AVG_ROW_LENGTH_SYMBOL = 25;
|
|
const AVG_SYMBOL = 26;
|
|
const BACKUP_SYMBOL = 27;
|
|
const BEFORE_SYMBOL = 28;
|
|
const BEGIN_SYMBOL = 29;
|
|
const BETWEEN_SYMBOL = 30;
|
|
const BIGINT_SYMBOL = 31;
|
|
const BINARY_SYMBOL = 32;
|
|
const BINLOG_SYMBOL = 33;
|
|
const BIN_NUM_SYMBOL = 34;
|
|
const BIT_AND_SYMBOL = 35;
|
|
const BIT_OR_SYMBOL = 36;
|
|
const BIT_SYMBOL = 37;
|
|
const BIT_XOR_SYMBOL = 38;
|
|
const BLOB_SYMBOL = 39;
|
|
const BLOCK_SYMBOL = 40;
|
|
const BOOLEAN_SYMBOL = 41;
|
|
const BOOL_SYMBOL = 42;
|
|
const BOTH_SYMBOL = 43;
|
|
const BTREE_SYMBOL = 44;
|
|
const BY_SYMBOL = 45;
|
|
const BYTE_SYMBOL = 46;
|
|
const CACHE_SYMBOL = 47;
|
|
const CALL_SYMBOL = 48;
|
|
const CASCADE_SYMBOL = 49;
|
|
const CASCADED_SYMBOL = 50;
|
|
const CASE_SYMBOL = 51;
|
|
const CAST_SYMBOL = 52;
|
|
const CATALOG_NAME_SYMBOL = 53;
|
|
const CHAIN_SYMBOL = 54;
|
|
const CHANGE_SYMBOL = 55;
|
|
const CHANGED_SYMBOL = 56;
|
|
const CHANNEL_SYMBOL = 57;
|
|
const CHARSET_SYMBOL = 58;
|
|
const CHARACTER_SYMBOL = 59;
|
|
const CHAR_SYMBOL = 60;
|
|
const CHECKSUM_SYMBOL = 61;
|
|
const CHECK_SYMBOL = 62;
|
|
const CIPHER_SYMBOL = 63;
|
|
const CLASS_ORIGIN_SYMBOL = 64;
|
|
const CLIENT_SYMBOL = 65;
|
|
const CLOSE_SYMBOL = 66;
|
|
const COALESCE_SYMBOL = 67;
|
|
const CODE_SYMBOL = 68;
|
|
const COLLATE_SYMBOL = 69;
|
|
const COLLATION_SYMBOL = 70;
|
|
const COLUMNS_SYMBOL = 71;
|
|
const COLUMN_SYMBOL = 72;
|
|
const COLUMN_NAME_SYMBOL = 73;
|
|
const COLUMN_FORMAT_SYMBOL = 74;
|
|
const COMMENT_SYMBOL = 75;
|
|
const COMMITTED_SYMBOL = 76;
|
|
const COMMIT_SYMBOL = 77;
|
|
const COMPACT_SYMBOL = 78;
|
|
const COMPLETION_SYMBOL = 79;
|
|
const COMPRESSED_SYMBOL = 80;
|
|
const COMPRESSION_SYMBOL = 81;
|
|
const CONCURRENT_SYMBOL = 82;
|
|
const CONDITION_SYMBOL = 83;
|
|
const CONNECTION_SYMBOL = 84;
|
|
const CONSISTENT_SYMBOL = 85;
|
|
const CONSTRAINT_SYMBOL = 86;
|
|
const CONSTRAINT_CATALOG_SYMBOL = 87;
|
|
const CONSTRAINT_NAME_SYMBOL = 88;
|
|
const CONSTRAINT_SCHEMA_SYMBOL = 89;
|
|
const CONTAINS_SYMBOL = 90;
|
|
const CONTEXT_SYMBOL = 91;
|
|
const CONTINUE_SYMBOL = 92;
|
|
const CONTRIBUTORS_SYMBOL = 93;
|
|
const CONVERT_SYMBOL = 94;
|
|
const COUNT_SYMBOL = 95;
|
|
const CPU_SYMBOL = 96;
|
|
const CREATE_SYMBOL = 97;
|
|
const CROSS_SYMBOL = 98;
|
|
const CUBE_SYMBOL = 99;
|
|
const CURDATE_SYMBOL = 100;
|
|
const CURRENT_SYMBOL = 101;
|
|
const CURRENT_DATE_SYMBOL = 102;
|
|
const CURRENT_TIME_SYMBOL = 103;
|
|
const CURRENT_TIMESTAMP_SYMBOL = 104;
|
|
const CURRENT_USER_SYMBOL = 105;
|
|
const CURSOR_SYMBOL = 106;
|
|
const CURSOR_NAME_SYMBOL = 107;
|
|
const CURTIME_SYMBOL = 108;
|
|
const DATABASE_SYMBOL = 109;
|
|
const DATABASES_SYMBOL = 110;
|
|
const DATAFILE_SYMBOL = 111;
|
|
const DATA_SYMBOL = 112;
|
|
const DATETIME_SYMBOL = 113;
|
|
const DATE_ADD_SYMBOL = 114;
|
|
const DATE_SUB_SYMBOL = 115;
|
|
const DATE_SYMBOL = 116;
|
|
const DAYOFMONTH_SYMBOL = 117;
|
|
const DAY_HOUR_SYMBOL = 118;
|
|
const DAY_MICROSECOND_SYMBOL = 119;
|
|
const DAY_MINUTE_SYMBOL = 120;
|
|
const DAY_SECOND_SYMBOL = 121;
|
|
const DAY_SYMBOL = 122;
|
|
const DEALLOCATE_SYMBOL = 123;
|
|
const DEC_SYMBOL = 124;
|
|
const DECIMAL_NUM_SYMBOL = 125;
|
|
const DECIMAL_SYMBOL = 126;
|
|
const DECLARE_SYMBOL = 127;
|
|
const DEFAULT_SYMBOL = 128;
|
|
const DEFAULT_AUTH_SYMBOL = 129;
|
|
const DEFINER_SYMBOL = 130;
|
|
const DELAYED_SYMBOL = 131;
|
|
const DELAY_KEY_WRITE_SYMBOL = 132;
|
|
const DELETE_SYMBOL = 133;
|
|
const DESC_SYMBOL = 134;
|
|
const DESCRIBE_SYMBOL = 135;
|
|
const DES_KEY_FILE_SYMBOL = 136;
|
|
const DETERMINISTIC_SYMBOL = 137;
|
|
const DIAGNOSTICS_SYMBOL = 138;
|
|
const DIRECTORY_SYMBOL = 139;
|
|
const DISABLE_SYMBOL = 140;
|
|
const DISCARD_SYMBOL = 141;
|
|
const DISK_SYMBOL = 142;
|
|
const DISTINCT_SYMBOL = 143;
|
|
const DISTINCTROW_SYMBOL = 144;
|
|
const DIV_SYMBOL = 145;
|
|
const DOUBLE_SYMBOL = 146;
|
|
const DO_SYMBOL = 147;
|
|
const DROP_SYMBOL = 148;
|
|
const DUAL_SYMBOL = 149;
|
|
const DUMPFILE_SYMBOL = 150;
|
|
const DUPLICATE_SYMBOL = 151;
|
|
const DYNAMIC_SYMBOL = 152;
|
|
const EACH_SYMBOL = 153;
|
|
const ELSE_SYMBOL = 154;
|
|
const ELSEIF_SYMBOL = 155;
|
|
const ENABLE_SYMBOL = 156;
|
|
const ENCLOSED_SYMBOL = 157;
|
|
const ENCRYPTION_SYMBOL = 158;
|
|
const END_SYMBOL = 159;
|
|
const ENDS_SYMBOL = 160;
|
|
const END_OF_INPUT_SYMBOL = 161; // defined in "predefined.tokens", but not used
|
|
const ENGINES_SYMBOL = 162;
|
|
const ENGINE_SYMBOL = 163;
|
|
const ENUM_SYMBOL = 164;
|
|
const ERROR_SYMBOL = 165;
|
|
const ERRORS_SYMBOL = 166;
|
|
const ESCAPED_SYMBOL = 167;
|
|
const ESCAPE_SYMBOL = 168;
|
|
const EVENTS_SYMBOL = 169;
|
|
const EVENT_SYMBOL = 170;
|
|
const EVERY_SYMBOL = 171;
|
|
const EXCHANGE_SYMBOL = 172;
|
|
const EXECUTE_SYMBOL = 173;
|
|
const EXISTS_SYMBOL = 174;
|
|
const EXIT_SYMBOL = 175;
|
|
const EXPANSION_SYMBOL = 176;
|
|
const EXPIRE_SYMBOL = 177;
|
|
const EXPLAIN_SYMBOL = 178;
|
|
const EXPORT_SYMBOL = 179;
|
|
const EXTENDED_SYMBOL = 180;
|
|
const EXTENT_SIZE_SYMBOL = 181;
|
|
const EXTRACT_SYMBOL = 182;
|
|
const FALSE_SYMBOL = 183;
|
|
const FAST_SYMBOL = 184;
|
|
const FAULTS_SYMBOL = 185;
|
|
const FETCH_SYMBOL = 186;
|
|
const FIELDS_SYMBOL = 187;
|
|
const FILE_SYMBOL = 188;
|
|
const FILE_BLOCK_SIZE_SYMBOL = 189;
|
|
const FILTER_SYMBOL = 190;
|
|
const FIRST_SYMBOL = 191;
|
|
const FIXED_SYMBOL = 192;
|
|
const FLOAT4_SYMBOL = 193;
|
|
const FLOAT8_SYMBOL = 194;
|
|
const FLOAT_SYMBOL = 195;
|
|
const FLUSH_SYMBOL = 196;
|
|
const FOLLOWS_SYMBOL = 197;
|
|
const FORCE_SYMBOL = 198;
|
|
const FOREIGN_SYMBOL = 199;
|
|
const FOR_SYMBOL = 200;
|
|
const FORMAT_SYMBOL = 201;
|
|
const FOUND_SYMBOL = 202;
|
|
const FROM_SYMBOL = 203;
|
|
const FULL_SYMBOL = 204;
|
|
const FULLTEXT_SYMBOL = 205;
|
|
const FUNCTION_SYMBOL = 206;
|
|
const GET_SYMBOL = 207;
|
|
const GENERAL_SYMBOL = 208;
|
|
const GENERATED_SYMBOL = 209;
|
|
const GROUP_REPLICATION_SYMBOL = 210;
|
|
const GEOMETRYCOLLECTION_SYMBOL = 211;
|
|
const GEOMETRY_SYMBOL = 212;
|
|
const GET_FORMAT_SYMBOL = 213;
|
|
const GLOBAL_SYMBOL = 214;
|
|
const GRANT_SYMBOL = 215;
|
|
const GRANTS_SYMBOL = 216;
|
|
const GROUP_SYMBOL = 217;
|
|
const GROUP_CONCAT_SYMBOL = 218;
|
|
const HANDLER_SYMBOL = 219;
|
|
const HASH_SYMBOL = 220;
|
|
const HAVING_SYMBOL = 221;
|
|
const HELP_SYMBOL = 222;
|
|
const HIGH_PRIORITY_SYMBOL = 223;
|
|
const HOST_SYMBOL = 224;
|
|
const HOSTS_SYMBOL = 225;
|
|
const HOUR_MICROSECOND_SYMBOL = 226;
|
|
const HOUR_MINUTE_SYMBOL = 227;
|
|
const HOUR_SECOND_SYMBOL = 228;
|
|
const HOUR_SYMBOL = 229;
|
|
const IDENTIFIED_SYMBOL = 230;
|
|
const IF_SYMBOL = 231;
|
|
const IGNORE_SYMBOL = 232;
|
|
const IGNORE_SERVER_IDS_SYMBOL = 233;
|
|
const IMPORT_SYMBOL = 234;
|
|
const INDEXES_SYMBOL = 235;
|
|
const INDEX_SYMBOL = 236;
|
|
const INFILE_SYMBOL = 237;
|
|
const INITIAL_SIZE_SYMBOL = 238;
|
|
const INNER_SYMBOL = 239;
|
|
const INOUT_SYMBOL = 240;
|
|
const INSENSITIVE_SYMBOL = 241;
|
|
const INSERT_SYMBOL = 242;
|
|
const INSERT_METHOD_SYMBOL = 243;
|
|
const INSTANCE_SYMBOL = 244;
|
|
const INSTALL_SYMBOL = 245;
|
|
const INTEGER_SYMBOL = 246;
|
|
const INTERVAL_SYMBOL = 247;
|
|
const INTO_SYMBOL = 248;
|
|
const INT_SYMBOL = 249;
|
|
const INVOKER_SYMBOL = 250;
|
|
const IN_SYMBOL = 251;
|
|
const IO_AFTER_GTIDS_SYMBOL = 252;
|
|
const IO_BEFORE_GTIDS_SYMBOL = 253;
|
|
const IO_THREAD_SYMBOL = 254;
|
|
const IO_SYMBOL = 255;
|
|
const IPC_SYMBOL = 256;
|
|
const IS_SYMBOL = 257;
|
|
const ISOLATION_SYMBOL = 258;
|
|
const ISSUER_SYMBOL = 259;
|
|
const ITERATE_SYMBOL = 260;
|
|
const JOIN_SYMBOL = 261;
|
|
const JSON_SYMBOL = 262;
|
|
const KEYS_SYMBOL = 263;
|
|
const KEY_BLOCK_SIZE_SYMBOL = 264;
|
|
const KEY_SYMBOL = 265;
|
|
const KILL_SYMBOL = 266;
|
|
const LANGUAGE_SYMBOL = 267;
|
|
const LAST_SYMBOL = 268;
|
|
const LEADING_SYMBOL = 269;
|
|
const LEAVES_SYMBOL = 270;
|
|
const LEAVE_SYMBOL = 271;
|
|
const LEFT_SYMBOL = 272;
|
|
const LESS_SYMBOL = 273;
|
|
const LEVEL_SYMBOL = 274;
|
|
const LIKE_SYMBOL = 275;
|
|
const LIMIT_SYMBOL = 276;
|
|
const LINEAR_SYMBOL = 277;
|
|
const LINES_SYMBOL = 278;
|
|
const LINESTRING_SYMBOL = 279;
|
|
const LIST_SYMBOL = 280;
|
|
const LOAD_SYMBOL = 281;
|
|
const LOCALTIME_SYMBOL = 282;
|
|
const LOCALTIMESTAMP_SYMBOL = 283;
|
|
const LOCAL_SYMBOL = 284;
|
|
const LOCATOR_SYMBOL = 285;
|
|
const LOCKS_SYMBOL = 286;
|
|
const LOCK_SYMBOL = 287;
|
|
const LOGFILE_SYMBOL = 288;
|
|
const LOGS_SYMBOL = 289;
|
|
const LONGBLOB_SYMBOL = 290;
|
|
const LONGTEXT_SYMBOL = 291;
|
|
const LONG_NUM_SYMBOL = 292;
|
|
const LONG_SYMBOL = 293;
|
|
const LOOP_SYMBOL = 294;
|
|
const LOW_PRIORITY_SYMBOL = 295;
|
|
const MASTER_AUTO_POSITION_SYMBOL = 296;
|
|
const MASTER_BIND_SYMBOL = 297;
|
|
const MASTER_CONNECT_RETRY_SYMBOL = 298;
|
|
const MASTER_DELAY_SYMBOL = 299;
|
|
const MASTER_HOST_SYMBOL = 300;
|
|
const MASTER_LOG_FILE_SYMBOL = 301;
|
|
const MASTER_LOG_POS_SYMBOL = 302;
|
|
const MASTER_PASSWORD_SYMBOL = 303;
|
|
const MASTER_PORT_SYMBOL = 304;
|
|
const MASTER_RETRY_COUNT_SYMBOL = 305;
|
|
const MASTER_SERVER_ID_SYMBOL = 306;
|
|
const MASTER_SSL_CAPATH_SYMBOL = 307;
|
|
const MASTER_SSL_CA_SYMBOL = 308;
|
|
const MASTER_SSL_CERT_SYMBOL = 309;
|
|
const MASTER_SSL_CIPHER_SYMBOL = 310;
|
|
const MASTER_SSL_CRL_SYMBOL = 311;
|
|
const MASTER_SSL_CRLPATH_SYMBOL = 312;
|
|
const MASTER_SSL_KEY_SYMBOL = 313;
|
|
const MASTER_SSL_SYMBOL = 314;
|
|
const MASTER_SSL_VERIFY_SERVER_CERT_SYMBOL = 315;
|
|
const MASTER_SYMBOL = 316;
|
|
const MASTER_TLS_VERSION_SYMBOL = 317;
|
|
const MASTER_USER_SYMBOL = 318;
|
|
const MASTER_HEARTBEAT_PERIOD_SYMBOL = 319;
|
|
const MATCH_SYMBOL = 320;
|
|
const MAX_CONNECTIONS_PER_HOUR_SYMBOL = 321;
|
|
const MAX_QUERIES_PER_HOUR_SYMBOL = 322;
|
|
const MAX_ROWS_SYMBOL = 323;
|
|
const MAX_SIZE_SYMBOL = 324;
|
|
const MAX_STATEMENT_TIME_SYMBOL = 325;
|
|
const MAX_SYMBOL = 326;
|
|
const MAX_UPDATES_PER_HOUR_SYMBOL = 327;
|
|
const MAX_USER_CONNECTIONS_SYMBOL = 328;
|
|
const MAXVALUE_SYMBOL = 329;
|
|
const MEDIUMBLOB_SYMBOL = 330;
|
|
const MEDIUMINT_SYMBOL = 331;
|
|
const MEDIUMTEXT_SYMBOL = 332;
|
|
const MEDIUM_SYMBOL = 333;
|
|
const MEMORY_SYMBOL = 334;
|
|
const MERGE_SYMBOL = 335;
|
|
const MESSAGE_TEXT_SYMBOL = 336;
|
|
const MICROSECOND_SYMBOL = 337;
|
|
const MID_SYMBOL = 338;
|
|
const MIDDLEINT_SYMBOL = 339;
|
|
const MIGRATE_SYMBOL = 340;
|
|
const MINUTE_MICROSECOND_SYMBOL = 341;
|
|
const MINUTE_SECOND_SYMBOL = 342;
|
|
const MINUTE_SYMBOL = 343;
|
|
const MIN_ROWS_SYMBOL = 344;
|
|
const MIN_SYMBOL = 345;
|
|
const MODE_SYMBOL = 346;
|
|
const MODIFIES_SYMBOL = 347;
|
|
const MODIFY_SYMBOL = 348;
|
|
const MOD_SYMBOL = 349;
|
|
const MONTH_SYMBOL = 350;
|
|
const MULTILINESTRING_SYMBOL = 351;
|
|
const MULTIPOINT_SYMBOL = 352;
|
|
const MULTIPOLYGON_SYMBOL = 353;
|
|
const MUTEX_SYMBOL = 354;
|
|
const MYSQL_ERRNO_SYMBOL = 355;
|
|
const NAMES_SYMBOL = 356;
|
|
const NAME_SYMBOL = 357;
|
|
const NATIONAL_SYMBOL = 358;
|
|
const NATURAL_SYMBOL = 359;
|
|
const NCHAR_STRING_SYMBOL = 360;
|
|
const NCHAR_SYMBOL = 361;
|
|
const NDB_SYMBOL = 362;
|
|
const NDBCLUSTER_SYMBOL = 363;
|
|
const NEG_SYMBOL = 364;
|
|
const NEVER_SYMBOL = 365;
|
|
const NEW_SYMBOL = 366;
|
|
const NEXT_SYMBOL = 367;
|
|
const NODEGROUP_SYMBOL = 368;
|
|
const NONE_SYMBOL = 369;
|
|
const NONBLOCKING_SYMBOL = 370;
|
|
const NOT_SYMBOL = 371;
|
|
const NOW_SYMBOL = 372;
|
|
const NO_SYMBOL = 373;
|
|
const NO_WAIT_SYMBOL = 374;
|
|
const NO_WRITE_TO_BINLOG_SYMBOL = 375;
|
|
const NULL_SYMBOL = 376;
|
|
const NUMBER_SYMBOL = 377;
|
|
const NUMERIC_SYMBOL = 378;
|
|
const NVARCHAR_SYMBOL = 379;
|
|
const OFFLINE_SYMBOL = 380;
|
|
const OFFSET_SYMBOL = 381;
|
|
const OLD_PASSWORD_SYMBOL = 382;
|
|
const ON_SYMBOL = 383;
|
|
const ONE_SYMBOL = 384;
|
|
const ONLINE_SYMBOL = 385;
|
|
const ONLY_SYMBOL = 386;
|
|
const OPEN_SYMBOL = 387;
|
|
const OPTIMIZE_SYMBOL = 388;
|
|
const OPTIMIZER_COSTS_SYMBOL = 389;
|
|
const OPTIONS_SYMBOL = 390;
|
|
const OPTION_SYMBOL = 391;
|
|
const OPTIONALLY_SYMBOL = 392;
|
|
const ORDER_SYMBOL = 393;
|
|
const OR_SYMBOL = 394;
|
|
const OUTER_SYMBOL = 395;
|
|
const OUTFILE_SYMBOL = 396;
|
|
const OUT_SYMBOL = 397;
|
|
const OWNER_SYMBOL = 398;
|
|
const PACK_KEYS_SYMBOL = 399;
|
|
const PAGE_SYMBOL = 400;
|
|
const PARSER_SYMBOL = 401;
|
|
const PARTIAL_SYMBOL = 402;
|
|
const PARTITIONING_SYMBOL = 403;
|
|
const PARTITIONS_SYMBOL = 404;
|
|
const PARTITION_SYMBOL = 405;
|
|
const PASSWORD_SYMBOL = 406;
|
|
const PHASE_SYMBOL = 407;
|
|
const PLUGINS_SYMBOL = 408;
|
|
const PLUGIN_DIR_SYMBOL = 409;
|
|
const PLUGIN_SYMBOL = 410;
|
|
const POINT_SYMBOL = 411;
|
|
const POLYGON_SYMBOL = 412;
|
|
const PORT_SYMBOL = 413;
|
|
const POSITION_SYMBOL = 414;
|
|
const PRECEDES_SYMBOL = 415;
|
|
const PRECISION_SYMBOL = 416;
|
|
const PREPARE_SYMBOL = 417;
|
|
const PRESERVE_SYMBOL = 418;
|
|
const PREV_SYMBOL = 419;
|
|
const PRIMARY_SYMBOL = 420;
|
|
const PRIVILEGES_SYMBOL = 421;
|
|
const PROCEDURE_SYMBOL = 422;
|
|
const PROCESS_SYMBOL = 423;
|
|
const PROCESSLIST_SYMBOL = 424;
|
|
const PROFILE_SYMBOL = 425;
|
|
const PROFILES_SYMBOL = 426;
|
|
const PROXY_SYMBOL = 427;
|
|
const PURGE_SYMBOL = 428;
|
|
const QUARTER_SYMBOL = 429;
|
|
const QUERY_SYMBOL = 430;
|
|
const QUICK_SYMBOL = 431;
|
|
const RANGE_SYMBOL = 432;
|
|
const READS_SYMBOL = 433;
|
|
const READ_ONLY_SYMBOL = 434;
|
|
const READ_SYMBOL = 435;
|
|
const READ_WRITE_SYMBOL = 436;
|
|
const REAL_SYMBOL = 437;
|
|
const REBUILD_SYMBOL = 438;
|
|
const RECOVER_SYMBOL = 439;
|
|
const REDOFILE_SYMBOL = 440;
|
|
const REDO_BUFFER_SIZE_SYMBOL = 441;
|
|
const REDUNDANT_SYMBOL = 442;
|
|
const REFERENCES_SYMBOL = 443;
|
|
const REGEXP_SYMBOL = 444;
|
|
const RELAY_SYMBOL = 445;
|
|
const RELAYLOG_SYMBOL = 446;
|
|
const RELAY_LOG_FILE_SYMBOL = 447;
|
|
const RELAY_LOG_POS_SYMBOL = 448;
|
|
const RELAY_THREAD_SYMBOL = 449;
|
|
const RELEASE_SYMBOL = 450;
|
|
const RELOAD_SYMBOL = 451;
|
|
const REMOVE_SYMBOL = 452;
|
|
const RENAME_SYMBOL = 453;
|
|
const REORGANIZE_SYMBOL = 454;
|
|
const REPAIR_SYMBOL = 455;
|
|
const REPEATABLE_SYMBOL = 456;
|
|
const REPEAT_SYMBOL = 457;
|
|
const REPLACE_SYMBOL = 458;
|
|
const REPLICATION_SYMBOL = 459;
|
|
const REPLICATE_DO_DB_SYMBOL = 460;
|
|
const REPLICATE_IGNORE_DB_SYMBOL = 461;
|
|
const REPLICATE_DO_TABLE_SYMBOL = 462;
|
|
const REPLICATE_IGNORE_TABLE_SYMBOL = 463;
|
|
const REPLICATE_WILD_DO_TABLE_SYMBOL = 464;
|
|
const REPLICATE_WILD_IGNORE_TABLE_SYMBOL = 465;
|
|
const REPLICATE_REWRITE_DB_SYMBOL = 466;
|
|
const REQUIRE_SYMBOL = 467;
|
|
const RESET_SYMBOL = 468;
|
|
const RESIGNAL_SYMBOL = 469;
|
|
const RESTORE_SYMBOL = 470;
|
|
const RESTRICT_SYMBOL = 471;
|
|
const RESUME_SYMBOL = 472;
|
|
const RETURNED_SQLSTATE_SYMBOL = 473;
|
|
const RETURNS_SYMBOL = 474;
|
|
const RETURN_SYMBOL = 475;
|
|
const REVERSE_SYMBOL = 476;
|
|
const REVOKE_SYMBOL = 477;
|
|
const RIGHT_SYMBOL = 478;
|
|
const RLIKE_SYMBOL = 479;
|
|
const ROLLBACK_SYMBOL = 480;
|
|
const ROLLUP_SYMBOL = 481;
|
|
const ROTATE_SYMBOL = 482;
|
|
const ROUTINE_SYMBOL = 483;
|
|
const ROWS_SYMBOL = 484;
|
|
const ROW_COUNT_SYMBOL = 485;
|
|
const ROW_FORMAT_SYMBOL = 486;
|
|
const ROW_SYMBOL = 487;
|
|
const RTREE_SYMBOL = 488;
|
|
const SAVEPOINT_SYMBOL = 489;
|
|
const SCHEDULE_SYMBOL = 490;
|
|
const SCHEMA_SYMBOL = 491;
|
|
const SCHEMA_NAME_SYMBOL = 492;
|
|
const SCHEMAS_SYMBOL = 493;
|
|
const SECOND_MICROSECOND_SYMBOL = 494;
|
|
const SECOND_SYMBOL = 495;
|
|
const SECURITY_SYMBOL = 496;
|
|
const SELECT_SYMBOL = 497;
|
|
const SENSITIVE_SYMBOL = 498;
|
|
const SEPARATOR_SYMBOL = 499;
|
|
const SERIALIZABLE_SYMBOL = 500;
|
|
const SERIAL_SYMBOL = 501;
|
|
const SESSION_SYMBOL = 502;
|
|
const SERVER_SYMBOL = 503;
|
|
const SERVER_OPTIONS_SYMBOL = 504;
|
|
const SESSION_USER_SYMBOL = 505;
|
|
const SET_SYMBOL = 506;
|
|
const SET_VAR_SYMBOL = 507;
|
|
const SHARE_SYMBOL = 508;
|
|
const SHOW_SYMBOL = 509;
|
|
const SHUTDOWN_SYMBOL = 510;
|
|
const SIGNAL_SYMBOL = 511;
|
|
const SIGNED_SYMBOL = 512;
|
|
const SIMPLE_SYMBOL = 513;
|
|
const SLAVE_SYMBOL = 514;
|
|
const SLOW_SYMBOL = 515;
|
|
const SMALLINT_SYMBOL = 516;
|
|
const SNAPSHOT_SYMBOL = 517;
|
|
const SOME_SYMBOL = 518;
|
|
const SOCKET_SYMBOL = 519;
|
|
const SONAME_SYMBOL = 520;
|
|
const SOUNDS_SYMBOL = 521;
|
|
const SOURCE_SYMBOL = 522;
|
|
const SPATIAL_SYMBOL = 523;
|
|
const SPECIFIC_SYMBOL = 524;
|
|
const SQLEXCEPTION_SYMBOL = 525;
|
|
const SQLSTATE_SYMBOL = 526;
|
|
const SQLWARNING_SYMBOL = 527;
|
|
const SQL_AFTER_GTIDS_SYMBOL = 528;
|
|
const SQL_AFTER_MTS_GAPS_SYMBOL = 529;
|
|
const SQL_BEFORE_GTIDS_SYMBOL = 530;
|
|
const SQL_BIG_RESULT_SYMBOL = 531;
|
|
const SQL_BUFFER_RESULT_SYMBOL = 532;
|
|
const SQL_CACHE_SYMBOL = 533;
|
|
const SQL_CALC_FOUND_ROWS_SYMBOL = 534;
|
|
const SQL_NO_CACHE_SYMBOL = 535;
|
|
const SQL_SMALL_RESULT_SYMBOL = 536;
|
|
const SQL_SYMBOL = 537;
|
|
const SQL_THREAD_SYMBOL = 538;
|
|
const SSL_SYMBOL = 539;
|
|
const STACKED_SYMBOL = 540;
|
|
const STARTING_SYMBOL = 541;
|
|
const STARTS_SYMBOL = 542;
|
|
const START_SYMBOL = 543;
|
|
const STATS_AUTO_RECALC_SYMBOL = 544;
|
|
const STATS_PERSISTENT_SYMBOL = 545;
|
|
const STATS_SAMPLE_PAGES_SYMBOL = 546;
|
|
const STATUS_SYMBOL = 547;
|
|
const STDDEV_SAMP_SYMBOL = 548;
|
|
const STDDEV_SYMBOL = 549;
|
|
const STDDEV_POP_SYMBOL = 550;
|
|
const STD_SYMBOL = 551;
|
|
const STOP_SYMBOL = 552;
|
|
const STORAGE_SYMBOL = 553;
|
|
const STORED_SYMBOL = 554;
|
|
const STRAIGHT_JOIN_SYMBOL = 555;
|
|
const STRING_SYMBOL = 556;
|
|
const SUBCLASS_ORIGIN_SYMBOL = 557;
|
|
const SUBDATE_SYMBOL = 558;
|
|
const SUBJECT_SYMBOL = 559;
|
|
const SUBPARTITIONS_SYMBOL = 560;
|
|
const SUBPARTITION_SYMBOL = 561;
|
|
const SUBSTR_SYMBOL = 562;
|
|
const SUBSTRING_SYMBOL = 563;
|
|
const SUM_SYMBOL = 564;
|
|
const SUPER_SYMBOL = 565;
|
|
const SUSPEND_SYMBOL = 566;
|
|
const SWAPS_SYMBOL = 567;
|
|
const SWITCHES_SYMBOL = 568;
|
|
const SYSDATE_SYMBOL = 569;
|
|
const SYSTEM_USER_SYMBOL = 570;
|
|
const TABLES_SYMBOL = 571;
|
|
const TABLESPACE_SYMBOL = 572;
|
|
const TABLE_REF_PRIORITY_SYMBOL = 573;
|
|
const TABLE_SYMBOL = 574;
|
|
const TABLE_CHECKSUM_SYMBOL = 575;
|
|
const TABLE_NAME_SYMBOL = 576;
|
|
const TEMPORARY_SYMBOL = 577;
|
|
const TEMPTABLE_SYMBOL = 578;
|
|
const TERMINATED_SYMBOL = 579;
|
|
const TEXT_SYMBOL = 580;
|
|
const THAN_SYMBOL = 581;
|
|
const THEN_SYMBOL = 582;
|
|
const TIMESTAMP_SYMBOL = 583;
|
|
const TIMESTAMP_ADD_SYMBOL = 584;
|
|
const TIMESTAMP_DIFF_SYMBOL = 585;
|
|
const TIME_SYMBOL = 586;
|
|
const TINYBLOB_SYMBOL = 587;
|
|
const TINYINT_SYMBOL = 588;
|
|
const TINYTEXT_SYMBOL = 589;
|
|
const TO_SYMBOL = 590;
|
|
const TRAILING_SYMBOL = 591;
|
|
const TRANSACTION_SYMBOL = 592;
|
|
const TRIGGERS_SYMBOL = 593;
|
|
const TRIGGER_SYMBOL = 594;
|
|
const TRIM_SYMBOL = 595;
|
|
const TRUE_SYMBOL = 596;
|
|
const TRUNCATE_SYMBOL = 597;
|
|
const TYPES_SYMBOL = 598;
|
|
const TYPE_SYMBOL = 599;
|
|
const UDF_RETURNS_SYMBOL = 600;
|
|
const UNCOMMITTED_SYMBOL = 601;
|
|
const UNDEFINED_SYMBOL = 602;
|
|
const UNDOFILE_SYMBOL = 603;
|
|
const UNDO_BUFFER_SIZE_SYMBOL = 604;
|
|
const UNDO_SYMBOL = 605;
|
|
const UNICODE_SYMBOL = 606;
|
|
const UNINSTALL_SYMBOL = 607;
|
|
const UNION_SYMBOL = 608;
|
|
const UNIQUE_SYMBOL = 609;
|
|
const UNKNOWN_SYMBOL = 610;
|
|
const UNLOCK_SYMBOL = 611;
|
|
const UNSIGNED_SYMBOL = 612;
|
|
const UNTIL_SYMBOL = 613;
|
|
const UPDATE_SYMBOL = 614;
|
|
const UPGRADE_SYMBOL = 615;
|
|
const USAGE_SYMBOL = 616;
|
|
const USER_RESOURCES_SYMBOL = 617;
|
|
const USER_SYMBOL = 618;
|
|
const USE_FRM_SYMBOL = 619;
|
|
const USE_SYMBOL = 620;
|
|
const USING_SYMBOL = 621;
|
|
const UTC_DATE_SYMBOL = 622;
|
|
const UTC_TIMESTAMP_SYMBOL = 623;
|
|
const UTC_TIME_SYMBOL = 624;
|
|
const VALIDATION_SYMBOL = 625;
|
|
const VALUES_SYMBOL = 626;
|
|
const VALUE_SYMBOL = 627;
|
|
const VARBINARY_SYMBOL = 628;
|
|
const VARCHAR_SYMBOL = 629;
|
|
const VARCHARACTER_SYMBOL = 630;
|
|
const VARIABLES_SYMBOL = 631;
|
|
const VARIANCE_SYMBOL = 632;
|
|
const VARYING_SYMBOL = 633;
|
|
const VAR_POP_SYMBOL = 634;
|
|
const VAR_SAMP_SYMBOL = 635;
|
|
const VIEW_SYMBOL = 636;
|
|
const VIRTUAL_SYMBOL = 637;
|
|
const WAIT_SYMBOL = 638;
|
|
const WARNINGS_SYMBOL = 639;
|
|
const WEEK_SYMBOL = 640;
|
|
const WEIGHT_STRING_SYMBOL = 641;
|
|
const WHEN_SYMBOL = 642;
|
|
const WHERE_SYMBOL = 643;
|
|
const WHILE_SYMBOL = 644;
|
|
const WITH_SYMBOL = 645;
|
|
const WITHOUT_SYMBOL = 646;
|
|
const WORK_SYMBOL = 647;
|
|
const WRAPPER_SYMBOL = 648;
|
|
const WRITE_SYMBOL = 649;
|
|
const X509_SYMBOL = 650;
|
|
const XA_SYMBOL = 651;
|
|
const XID_SYMBOL = 652;
|
|
const XML_SYMBOL = 653;
|
|
const XOR_SYMBOL = 654;
|
|
const YEAR_MONTH_SYMBOL = 655;
|
|
const YEAR_SYMBOL = 656;
|
|
const ZEROFILL_SYMBOL = 657;
|
|
const PERSIST_SYMBOL = 658;
|
|
const ROLE_SYMBOL = 659;
|
|
const ADMIN_SYMBOL = 660;
|
|
const INVISIBLE_SYMBOL = 661;
|
|
const VISIBLE_SYMBOL = 662;
|
|
const EXCEPT_SYMBOL = 663;
|
|
const COMPONENT_SYMBOL = 664;
|
|
const RECURSIVE_SYMBOL = 665;
|
|
const JSON_OBJECTAGG_SYMBOL = 666;
|
|
const JSON_ARRAYAGG_SYMBOL = 667;
|
|
const OF_SYMBOL = 668;
|
|
const SKIP_SYMBOL = 669;
|
|
const LOCKED_SYMBOL = 670;
|
|
const NOWAIT_SYMBOL = 671;
|
|
const GROUPING_SYMBOL = 672;
|
|
const PERSIST_ONLY_SYMBOL = 673;
|
|
const HISTOGRAM_SYMBOL = 674;
|
|
const BUCKETS_SYMBOL = 675;
|
|
const REMOTE_SYMBOL = 676;
|
|
const CLONE_SYMBOL = 677;
|
|
const CUME_DIST_SYMBOL = 678;
|
|
const DENSE_RANK_SYMBOL = 679;
|
|
const EXCLUDE_SYMBOL = 680;
|
|
const FIRST_VALUE_SYMBOL = 681;
|
|
const FOLLOWING_SYMBOL = 682;
|
|
const GROUPS_SYMBOL = 683;
|
|
const LAG_SYMBOL = 684;
|
|
const LAST_VALUE_SYMBOL = 685;
|
|
const LEAD_SYMBOL = 686;
|
|
const NTH_VALUE_SYMBOL = 687;
|
|
const NTILE_SYMBOL = 688;
|
|
const NULLS_SYMBOL = 689;
|
|
const OTHERS_SYMBOL = 690;
|
|
const OVER_SYMBOL = 691;
|
|
const PERCENT_RANK_SYMBOL = 692;
|
|
const PRECEDING_SYMBOL = 693;
|
|
const RANK_SYMBOL = 694;
|
|
const RESPECT_SYMBOL = 695;
|
|
const ROW_NUMBER_SYMBOL = 696;
|
|
const TIES_SYMBOL = 697;
|
|
const UNBOUNDED_SYMBOL = 698;
|
|
const WINDOW_SYMBOL = 699;
|
|
const EMPTY_SYMBOL = 700;
|
|
const JSON_TABLE_SYMBOL = 701;
|
|
const NESTED_SYMBOL = 702;
|
|
const ORDINALITY_SYMBOL = 703;
|
|
const PATH_SYMBOL = 704;
|
|
const HISTORY_SYMBOL = 705;
|
|
const REUSE_SYMBOL = 706;
|
|
const SRID_SYMBOL = 707;
|
|
const THREAD_PRIORITY_SYMBOL = 708;
|
|
const RESOURCE_SYMBOL = 709;
|
|
const SYSTEM_SYMBOL = 710;
|
|
const VCPU_SYMBOL = 711;
|
|
const MASTER_PUBLIC_KEY_PATH_SYMBOL = 712;
|
|
const GET_MASTER_PUBLIC_KEY_SYMBOL = 713;
|
|
const RESTART_SYMBOL = 714;
|
|
const DEFINITION_SYMBOL = 715;
|
|
const DESCRIPTION_SYMBOL = 716;
|
|
const ORGANIZATION_SYMBOL = 717;
|
|
const REFERENCE_SYMBOL = 718;
|
|
const OPTIONAL_SYMBOL = 719;
|
|
const SECONDARY_SYMBOL = 720;
|
|
const SECONDARY_ENGINE_SYMBOL = 721;
|
|
const SECONDARY_LOAD_SYMBOL = 722;
|
|
const SECONDARY_UNLOAD_SYMBOL = 723;
|
|
const ACTIVE_SYMBOL = 724;
|
|
const INACTIVE_SYMBOL = 725;
|
|
const LATERAL_SYMBOL = 726;
|
|
const RETAIN_SYMBOL = 727;
|
|
const OLD_SYMBOL = 728;
|
|
const NETWORK_NAMESPACE_SYMBOL = 729;
|
|
const ENFORCED_SYMBOL = 730;
|
|
const ARRAY_SYMBOL = 731;
|
|
const OJ_SYMBOL = 732;
|
|
const MEMBER_SYMBOL = 733;
|
|
const RANDOM_SYMBOL = 734;
|
|
const MASTER_COMPRESSION_ALGORITHM_SYMBOL = 735;
|
|
const MASTER_ZSTD_COMPRESSION_LEVEL_SYMBOL = 736;
|
|
const PRIVILEGE_CHECKS_USER_SYMBOL = 737;
|
|
const MASTER_TLS_CIPHERSUITES_SYMBOL = 738;
|
|
const REQUIRE_ROW_FORMAT_SYMBOL = 739;
|
|
const PASSWORD_LOCK_TIME_SYMBOL = 740;
|
|
const FAILED_LOGIN_ATTEMPTS_SYMBOL = 741;
|
|
const REQUIRE_TABLE_PRIMARY_KEY_CHECK_SYMBOL = 742;
|
|
const STREAM_SYMBOL = 743;
|
|
const OFF_SYMBOL = 744;
|
|
|
|
/**
|
|
* Additional tokens, mostly mirroring the MySQL Workbench lexer grammar.
|
|
*
|
|
* These tokens are defined in the MySQL Workbench "MySQLLexer.g4" grammar.
|
|
*
|
|
* See:
|
|
* https://github.com/mysql/mysql-workbench/blob/8.0.38/library/parsers/grammars/MySQLLexer.g4
|
|
*/
|
|
|
|
// Punctuators
|
|
const AT_AT_SIGN_SYMBOL = 745;
|
|
const AT_SIGN_SYMBOL = 746;
|
|
const CLOSE_CURLY_SYMBOL = 747;
|
|
const CLOSE_PAR_SYMBOL = 748;
|
|
const COLON_SYMBOL = 749;
|
|
const COMMA_SYMBOL = 750;
|
|
const DOT_SYMBOL = 751;
|
|
const OPEN_CURLY_SYMBOL = 752;
|
|
const OPEN_PAR_SYMBOL = 753;
|
|
const PARAM_MARKER = 754;
|
|
const SEMICOLON_SYMBOL = 755;
|
|
|
|
// Operators
|
|
const ASSIGN_OPERATOR = 756;
|
|
const BITWISE_AND_OPERATOR = 757;
|
|
const BITWISE_NOT_OPERATOR = 758;
|
|
const BITWISE_OR_OPERATOR = 759;
|
|
const BITWISE_XOR_OPERATOR = 760;
|
|
const CONCAT_PIPES_SYMBOL = 761;
|
|
const DIV_OPERATOR = 762;
|
|
const EQUAL_OPERATOR = 763;
|
|
const GREATER_OR_EQUAL_OPERATOR = 764;
|
|
const GREATER_THAN_OPERATOR = 765;
|
|
const JSON_SEPARATOR_SYMBOL = 766;
|
|
const JSON_UNQUOTED_SEPARATOR_SYMBOL = 767;
|
|
const LESS_OR_EQUAL_OPERATOR = 768;
|
|
const LESS_THAN_OPERATOR = 769;
|
|
const LOGICAL_AND_OPERATOR = 770;
|
|
const LOGICAL_NOT_OPERATOR = 771;
|
|
const LOGICAL_OR_OPERATOR = 772;
|
|
const MINUS_OPERATOR = 773;
|
|
const MOD_OPERATOR = 774;
|
|
const MULT_OPERATOR = 775;
|
|
const NOT_EQUAL_OPERATOR = 776;
|
|
const NULL_SAFE_EQUAL_OPERATOR = 777;
|
|
const PLUS_OPERATOR = 778;
|
|
const SHIFT_LEFT_OPERATOR = 779;
|
|
const SHIFT_RIGHT_OPERATOR = 780;
|
|
|
|
// Literals
|
|
const BACK_TICK_QUOTED_ID = 781;
|
|
const BIN_NUMBER = 782;
|
|
const DECIMAL_NUMBER = 783;
|
|
const DOUBLE_QUOTED_TEXT = 784;
|
|
const FLOAT_NUMBER = 785;
|
|
const HEX_NUMBER = 786;
|
|
const INT_NUMBER = 787;
|
|
const LONG_NUMBER = 788;
|
|
const NCHAR_TEXT = 789;
|
|
const SINGLE_QUOTED_TEXT = 790;
|
|
const ULONGLONG_NUMBER = 791;
|
|
|
|
// Identifier-like tokens
|
|
const AT_TEXT_SUFFIX = 792;
|
|
const IDENTIFIER = 793;
|
|
const UNDERSCORE_CHARSET = 794;
|
|
|
|
// Other tokens
|
|
const INT1_SYMBOL = 795;
|
|
const INT2_SYMBOL = 796;
|
|
const INT3_SYMBOL = 797;
|
|
const INT4_SYMBOL = 798;
|
|
const INT8_SYMBOL = 799;
|
|
const NOT2_SYMBOL = 800;
|
|
const NULL2_SYMBOL = 801;
|
|
const SQL_TSI_DAY_SYMBOL = 802;
|
|
const SQL_TSI_HOUR_SYMBOL = 803;
|
|
const SQL_TSI_MICROSECOND_SYMBOL = 804;
|
|
const SQL_TSI_MINUTE_SYMBOL = 805;
|
|
const SQL_TSI_MONTH_SYMBOL = 806;
|
|
const SQL_TSI_QUARTER_SYMBOL = 807;
|
|
const SQL_TSI_SECOND_SYMBOL = 808;
|
|
const SQL_TSI_WEEK_SYMBOL = 809;
|
|
const SQL_TSI_YEAR_SYMBOL = 810;
|
|
|
|
/**
|
|
* Other tokens, missing in the MySQL Workbench "MySQLLexer.g4" grammar.
|
|
*
|
|
* These tokens are missing in the "MySQLLexer.g4" grammar, because the MySQL
|
|
* Workbench lexer and parser don't cover 100% of the MySQL syntax.
|
|
*/
|
|
const INTERSECT_SYMBOL = 811;
|
|
const ATTRIBUTE_SYMBOL = 812;
|
|
const SOURCE_AUTO_POSITION_SYMBOL = 813;
|
|
const SOURCE_BIND_SYMBOL = 814;
|
|
const SOURCE_COMPRESSION_ALGORITHM_SYMBOL = 815;
|
|
const SOURCE_CONNECT_RETRY_SYMBOL = 816;
|
|
const SOURCE_CONNECTION_AUTO_FAILOVER_SYMBOL = 817;
|
|
const SOURCE_DELAY_SYMBOL = 818;
|
|
const SOURCE_HEARTBEAT_PERIOD_SYMBOL = 819;
|
|
const SOURCE_HOST_SYMBOL = 820;
|
|
const SOURCE_LOG_FILE_SYMBOL = 821;
|
|
const SOURCE_LOG_POS_SYMBOL = 822;
|
|
const SOURCE_PASSWORD_SYMBOL = 823;
|
|
const SOURCE_PORT_SYMBOL = 824;
|
|
const SOURCE_PUBLIC_KEY_PATH_SYMBOL = 825;
|
|
const SOURCE_RETRY_COUNT_SYMBOL = 826;
|
|
const SOURCE_SSL_SYMBOL = 827;
|
|
const SOURCE_SSL_CA_SYMBOL = 828;
|
|
const SOURCE_SSL_CAPATH_SYMBOL = 829;
|
|
const SOURCE_SSL_CERT_SYMBOL = 830;
|
|
const SOURCE_SSL_CIPHER_SYMBOL = 831;
|
|
const SOURCE_SSL_CRL_SYMBOL = 832;
|
|
const SOURCE_SSL_CRLPATH_SYMBOL = 833;
|
|
const SOURCE_SSL_KEY_SYMBOL = 834;
|
|
const SOURCE_SSL_VERIFY_SERVER_CERT_SYMBOL = 835;
|
|
const SOURCE_TLS_CIPHERSUITES_SYMBOL = 836;
|
|
const SOURCE_TLS_VERSION_SYMBOL = 837;
|
|
const SOURCE_USER_SYMBOL = 838;
|
|
const SOURCE_ZSTD_COMPRESSION_LEVEL_SYMBOL = 839;
|
|
const GET_SOURCE_PUBLIC_KEY_SYMBOL = 840;
|
|
const GTID_ONLY_SYMBOL = 841;
|
|
const ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS_SYMBOL = 842;
|
|
const ZONE_SYMBOL = 843;
|
|
const INNODB_SYMBOL = 844; // From 5.7.11 defined as is_identifier(..., "INNODB") in "sql_yacc.yy".
|
|
const TLS_SYMBOL = 845; // Added in 8.0.21. From 8.0.16 defined as is_identifier(..., "TLS") in "sql_yacc.yy".
|
|
const REDO_LOG_SYMBOL = 846; // From 8.0.21 defined as is_identifier(..., "REDO_LOG") in "sql_yacc.yy".
|
|
const KEYRING_SYMBOL = 847;
|
|
const ENGINE_ATTRIBUTE_SYMBOL = 848;
|
|
const SECONDARY_ENGINE_ATTRIBUTE_SYMBOL = 849;
|
|
const JSON_VALUE_SYMBOL = 850;
|
|
const RETURNING_SYMBOL = 851;
|
|
const GEOMCOLLECTION_SYMBOL = 852;
|
|
|
|
// Comments
|
|
const COMMENT = 900;
|
|
const MYSQL_COMMENT_START = 901;
|
|
const MYSQL_COMMENT_END = 902;
|
|
|
|
// Special tokens
|
|
const WHITESPACE = 0;
|
|
const EOF = -1;
|
|
|
|
/**
|
|
* A map of SQL keyword string values to their corresponding token types.
|
|
*
|
|
* This is used for a fast lookup of MySQL keywords during tokenization.
|
|
*/
|
|
const TOKENS = array(
|
|
// Tokens from MySQL 5.7:
|
|
'ACCESSIBLE' => self::ACCESSIBLE_SYMBOL,
|
|
'ACCOUNT' => self::ACCOUNT_SYMBOL,
|
|
'ACTION' => self::ACTION_SYMBOL,
|
|
'ADD' => self::ADD_SYMBOL,
|
|
'ADDDATE' => self::ADDDATE_SYMBOL,
|
|
'AFTER' => self::AFTER_SYMBOL,
|
|
'AGAINST' => self::AGAINST_SYMBOL,
|
|
'AGGREGATE' => self::AGGREGATE_SYMBOL,
|
|
'ALGORITHM' => self::ALGORITHM_SYMBOL,
|
|
'ALL' => self::ALL_SYMBOL,
|
|
'ALTER' => self::ALTER_SYMBOL,
|
|
'ALWAYS' => self::ALWAYS_SYMBOL,
|
|
'ANALYSE' => self::ANALYSE_SYMBOL,
|
|
'ANALYZE' => self::ANALYZE_SYMBOL,
|
|
'AND' => self::AND_SYMBOL,
|
|
'ANY' => self::ANY_SYMBOL,
|
|
'AS' => self::AS_SYMBOL,
|
|
'ASC' => self::ASC_SYMBOL,
|
|
'ASCII' => self::ASCII_SYMBOL,
|
|
'ASENSITIVE' => self::ASENSITIVE_SYMBOL,
|
|
'AT' => self::AT_SYMBOL,
|
|
'ATTRIBUTE' => self::ATTRIBUTE_SYMBOL,
|
|
'AUTHORS' => self::AUTHORS_SYMBOL,
|
|
'AUTO_INCREMENT' => self::AUTO_INCREMENT_SYMBOL,
|
|
'AUTOEXTEND_SIZE' => self::AUTOEXTEND_SIZE_SYMBOL,
|
|
'AVG' => self::AVG_SYMBOL,
|
|
'AVG_ROW_LENGTH' => self::AVG_ROW_LENGTH_SYMBOL,
|
|
'BACKUP' => self::BACKUP_SYMBOL,
|
|
'BEFORE' => self::BEFORE_SYMBOL,
|
|
'BEGIN' => self::BEGIN_SYMBOL,
|
|
'BETWEEN' => self::BETWEEN_SYMBOL,
|
|
'BIGINT' => self::BIGINT_SYMBOL,
|
|
'BIN_NUM' => self::BIN_NUM_SYMBOL,
|
|
'BINARY' => self::BINARY_SYMBOL,
|
|
'BINLOG' => self::BINLOG_SYMBOL,
|
|
'BIT' => self::BIT_SYMBOL,
|
|
'BIT_AND' => self::BIT_AND_SYMBOL,
|
|
'BIT_OR' => self::BIT_OR_SYMBOL,
|
|
'BIT_XOR' => self::BIT_XOR_SYMBOL,
|
|
'BLOB' => self::BLOB_SYMBOL,
|
|
'BLOCK' => self::BLOCK_SYMBOL,
|
|
'BOOL' => self::BOOL_SYMBOL,
|
|
'BOOLEAN' => self::BOOLEAN_SYMBOL,
|
|
'BOTH' => self::BOTH_SYMBOL,
|
|
'BTREE' => self::BTREE_SYMBOL,
|
|
'BY' => self::BY_SYMBOL,
|
|
'BYTE' => self::BYTE_SYMBOL,
|
|
'CACHE' => self::CACHE_SYMBOL,
|
|
'CALL' => self::CALL_SYMBOL,
|
|
'CASCADE' => self::CASCADE_SYMBOL,
|
|
'CASCADED' => self::CASCADED_SYMBOL,
|
|
'CASE' => self::CASE_SYMBOL,
|
|
'CAST' => self::CAST_SYMBOL,
|
|
'CATALOG_NAME' => self::CATALOG_NAME_SYMBOL,
|
|
'CHAIN' => self::CHAIN_SYMBOL,
|
|
'CHANGE' => self::CHANGE_SYMBOL,
|
|
'CHANGED' => self::CHANGED_SYMBOL,
|
|
'CHANNEL' => self::CHANNEL_SYMBOL,
|
|
'CHAR' => self::CHAR_SYMBOL,
|
|
'CHARACTER' => self::CHARACTER_SYMBOL,
|
|
'CHARSET' => self::CHARSET_SYMBOL,
|
|
'CHECK' => self::CHECK_SYMBOL,
|
|
'CHECKSUM' => self::CHECKSUM_SYMBOL,
|
|
'CIPHER' => self::CIPHER_SYMBOL,
|
|
'CLASS_ORIGIN' => self::CLASS_ORIGIN_SYMBOL,
|
|
'CLIENT' => self::CLIENT_SYMBOL,
|
|
'CLOSE' => self::CLOSE_SYMBOL,
|
|
'COALESCE' => self::COALESCE_SYMBOL,
|
|
'CODE' => self::CODE_SYMBOL,
|
|
'COLLATE' => self::COLLATE_SYMBOL,
|
|
'COLLATION' => self::COLLATION_SYMBOL,
|
|
'COLUMN' => self::COLUMN_SYMBOL,
|
|
'COLUMN_FORMAT' => self::COLUMN_FORMAT_SYMBOL,
|
|
'COLUMN_NAME' => self::COLUMN_NAME_SYMBOL,
|
|
'COLUMNS' => self::COLUMNS_SYMBOL,
|
|
'COMMENT' => self::COMMENT_SYMBOL,
|
|
'COMMIT' => self::COMMIT_SYMBOL,
|
|
'COMMITTED' => self::COMMITTED_SYMBOL,
|
|
'COMPACT' => self::COMPACT_SYMBOL,
|
|
'COMPLETION' => self::COMPLETION_SYMBOL,
|
|
'COMPRESSED' => self::COMPRESSED_SYMBOL,
|
|
'COMPRESSION' => self::COMPRESSION_SYMBOL,
|
|
'CONCURRENT' => self::CONCURRENT_SYMBOL,
|
|
'CONDITION' => self::CONDITION_SYMBOL,
|
|
'CONNECTION' => self::CONNECTION_SYMBOL,
|
|
'CONSISTENT' => self::CONSISTENT_SYMBOL,
|
|
'CONSTRAINT' => self::CONSTRAINT_SYMBOL,
|
|
'CONSTRAINT_CATALOG' => self::CONSTRAINT_CATALOG_SYMBOL,
|
|
'CONSTRAINT_NAME' => self::CONSTRAINT_NAME_SYMBOL,
|
|
'CONSTRAINT_SCHEMA' => self::CONSTRAINT_SCHEMA_SYMBOL,
|
|
'CONTAINS' => self::CONTAINS_SYMBOL,
|
|
'CONTEXT' => self::CONTEXT_SYMBOL,
|
|
'CONTINUE' => self::CONTINUE_SYMBOL,
|
|
'CONTRIBUTORS' => self::CONTRIBUTORS_SYMBOL,
|
|
'CONVERT' => self::CONVERT_SYMBOL,
|
|
'COUNT' => self::COUNT_SYMBOL,
|
|
'CPU' => self::CPU_SYMBOL,
|
|
'CREATE' => self::CREATE_SYMBOL,
|
|
'CROSS' => self::CROSS_SYMBOL,
|
|
'CUBE' => self::CUBE_SYMBOL,
|
|
'CURDATE' => self::CURDATE_SYMBOL,
|
|
'CURRENT' => self::CURRENT_SYMBOL,
|
|
'CURRENT_DATE' => self::CURRENT_DATE_SYMBOL,
|
|
'CURRENT_TIME' => self::CURRENT_TIME_SYMBOL,
|
|
'CURRENT_TIMESTAMP' => self::CURRENT_TIMESTAMP_SYMBOL,
|
|
'CURRENT_USER' => self::CURRENT_USER_SYMBOL,
|
|
'CURSOR' => self::CURSOR_SYMBOL,
|
|
'CURSOR_NAME' => self::CURSOR_NAME_SYMBOL,
|
|
'CURTIME' => self::CURTIME_SYMBOL,
|
|
'DATA' => self::DATA_SYMBOL,
|
|
'DATABASE' => self::DATABASE_SYMBOL,
|
|
'DATABASES' => self::DATABASES_SYMBOL,
|
|
'DATAFILE' => self::DATAFILE_SYMBOL,
|
|
'DATE' => self::DATE_SYMBOL,
|
|
'DATE_ADD' => self::DATE_ADD_SYMBOL,
|
|
'DATE_SUB' => self::DATE_SUB_SYMBOL,
|
|
'DATETIME' => self::DATETIME_SYMBOL,
|
|
'DAY' => self::DAY_SYMBOL,
|
|
'DAY_HOUR' => self::DAY_HOUR_SYMBOL,
|
|
'DAY_MICROSECOND' => self::DAY_MICROSECOND_SYMBOL,
|
|
'DAY_MINUTE' => self::DAY_MINUTE_SYMBOL,
|
|
'DAY_SECOND' => self::DAY_SECOND_SYMBOL,
|
|
'DAYOFMONTH' => self::DAYOFMONTH_SYMBOL,
|
|
'DEALLOCATE' => self::DEALLOCATE_SYMBOL,
|
|
'DEC' => self::DEC_SYMBOL,
|
|
'DECIMAL' => self::DECIMAL_SYMBOL,
|
|
'DECIMAL_NUM' => self::DECIMAL_NUM_SYMBOL,
|
|
'DECLARE' => self::DECLARE_SYMBOL,
|
|
'DEFAULT' => self::DEFAULT_SYMBOL,
|
|
'DEFAULT_AUTH' => self::DEFAULT_AUTH_SYMBOL,
|
|
'DEFINER' => self::DEFINER_SYMBOL,
|
|
'DELAY_KEY_WRITE' => self::DELAY_KEY_WRITE_SYMBOL,
|
|
'DELAYED' => self::DELAYED_SYMBOL,
|
|
'DELETE' => self::DELETE_SYMBOL,
|
|
'DES_KEY_FILE' => self::DES_KEY_FILE_SYMBOL,
|
|
'DESC' => self::DESC_SYMBOL,
|
|
'DESCRIBE' => self::DESCRIBE_SYMBOL,
|
|
'DETERMINISTIC' => self::DETERMINISTIC_SYMBOL,
|
|
'DIAGNOSTICS' => self::DIAGNOSTICS_SYMBOL,
|
|
'DIRECTORY' => self::DIRECTORY_SYMBOL,
|
|
'DISABLE' => self::DISABLE_SYMBOL,
|
|
'DISCARD' => self::DISCARD_SYMBOL,
|
|
'DISK' => self::DISK_SYMBOL,
|
|
'DISTINCT' => self::DISTINCT_SYMBOL,
|
|
'DISTINCTROW' => self::DISTINCTROW_SYMBOL,
|
|
'DIV' => self::DIV_SYMBOL,
|
|
'DO' => self::DO_SYMBOL,
|
|
'DOUBLE' => self::DOUBLE_SYMBOL,
|
|
'DROP' => self::DROP_SYMBOL,
|
|
'DUAL' => self::DUAL_SYMBOL,
|
|
'DUMPFILE' => self::DUMPFILE_SYMBOL,
|
|
'DUPLICATE' => self::DUPLICATE_SYMBOL,
|
|
'DYNAMIC' => self::DYNAMIC_SYMBOL,
|
|
'EACH' => self::EACH_SYMBOL,
|
|
'ELSE' => self::ELSE_SYMBOL,
|
|
'ELSEIF' => self::ELSEIF_SYMBOL,
|
|
'ENABLE' => self::ENABLE_SYMBOL,
|
|
'ENCLOSED' => self::ENCLOSED_SYMBOL,
|
|
'ENCRYPTION' => self::ENCRYPTION_SYMBOL,
|
|
'END' => self::END_SYMBOL,
|
|
'END_OF_INPUT' => self::EOF,
|
|
'ENDS' => self::ENDS_SYMBOL,
|
|
'ENGINE' => self::ENGINE_SYMBOL,
|
|
'ENGINES' => self::ENGINES_SYMBOL,
|
|
'ENUM' => self::ENUM_SYMBOL,
|
|
'ERROR' => self::ERROR_SYMBOL,
|
|
'ERRORS' => self::ERRORS_SYMBOL,
|
|
'ESCAPE' => self::ESCAPE_SYMBOL,
|
|
'ESCAPED' => self::ESCAPED_SYMBOL,
|
|
'EVENT' => self::EVENT_SYMBOL,
|
|
'EVENTS' => self::EVENTS_SYMBOL,
|
|
'EVERY' => self::EVERY_SYMBOL,
|
|
'EXCHANGE' => self::EXCHANGE_SYMBOL,
|
|
'EXECUTE' => self::EXECUTE_SYMBOL,
|
|
'EXISTS' => self::EXISTS_SYMBOL,
|
|
'EXIT' => self::EXIT_SYMBOL,
|
|
'EXPANSION' => self::EXPANSION_SYMBOL,
|
|
'EXPIRE' => self::EXPIRE_SYMBOL,
|
|
'EXPLAIN' => self::EXPLAIN_SYMBOL,
|
|
'EXPORT' => self::EXPORT_SYMBOL,
|
|
'EXTENDED' => self::EXTENDED_SYMBOL,
|
|
'EXTENT_SIZE' => self::EXTENT_SIZE_SYMBOL,
|
|
'EXTRACT' => self::EXTRACT_SYMBOL,
|
|
'FALSE' => self::FALSE_SYMBOL,
|
|
'FAST' => self::FAST_SYMBOL,
|
|
'FAULTS' => self::FAULTS_SYMBOL,
|
|
'FETCH' => self::FETCH_SYMBOL,
|
|
'FIELDS' => self::FIELDS_SYMBOL,
|
|
'FILE' => self::FILE_SYMBOL,
|
|
'FILE_BLOCK_SIZE' => self::FILE_BLOCK_SIZE_SYMBOL,
|
|
'FILTER' => self::FILTER_SYMBOL,
|
|
'FIRST' => self::FIRST_SYMBOL,
|
|
'FIXED' => self::FIXED_SYMBOL,
|
|
'FLOAT' => self::FLOAT_SYMBOL,
|
|
'FLOAT4' => self::FLOAT4_SYMBOL,
|
|
'FLOAT8' => self::FLOAT8_SYMBOL,
|
|
'FLUSH' => self::FLUSH_SYMBOL,
|
|
'FOLLOWS' => self::FOLLOWS_SYMBOL,
|
|
'FOR' => self::FOR_SYMBOL,
|
|
'FORCE' => self::FORCE_SYMBOL,
|
|
'FOREIGN' => self::FOREIGN_SYMBOL,
|
|
'FORMAT' => self::FORMAT_SYMBOL,
|
|
'FOUND' => self::FOUND_SYMBOL,
|
|
'FROM' => self::FROM_SYMBOL,
|
|
'FULL' => self::FULL_SYMBOL,
|
|
'FULLTEXT' => self::FULLTEXT_SYMBOL,
|
|
'FUNCTION' => self::FUNCTION_SYMBOL,
|
|
'GENERAL' => self::GENERAL_SYMBOL,
|
|
'GENERATED' => self::GENERATED_SYMBOL,
|
|
'GEOMCOLLECTION' => self::GEOMCOLLECTION_SYMBOL,
|
|
'GEOMETRY' => self::GEOMETRY_SYMBOL,
|
|
'GEOMETRYCOLLECTION' => self::GEOMETRYCOLLECTION_SYMBOL,
|
|
'GET' => self::GET_SYMBOL,
|
|
'GET_FORMAT' => self::GET_FORMAT_SYMBOL,
|
|
'GLOBAL' => self::GLOBAL_SYMBOL,
|
|
'GRANT' => self::GRANT_SYMBOL,
|
|
'GRANTS' => self::GRANTS_SYMBOL,
|
|
'GROUP' => self::GROUP_SYMBOL,
|
|
'GROUP_CONCAT' => self::GROUP_CONCAT_SYMBOL,
|
|
'GROUP_REPLICATION' => self::GROUP_REPLICATION_SYMBOL,
|
|
'HANDLER' => self::HANDLER_SYMBOL,
|
|
'HASH' => self::HASH_SYMBOL,
|
|
'HAVING' => self::HAVING_SYMBOL,
|
|
'HELP' => self::HELP_SYMBOL,
|
|
'HIGH_PRIORITY' => self::HIGH_PRIORITY_SYMBOL,
|
|
'HOST' => self::HOST_SYMBOL,
|
|
'HOSTS' => self::HOSTS_SYMBOL,
|
|
'HOUR' => self::HOUR_SYMBOL,
|
|
'HOUR_MICROSECOND' => self::HOUR_MICROSECOND_SYMBOL,
|
|
'HOUR_MINUTE' => self::HOUR_MINUTE_SYMBOL,
|
|
'HOUR_SECOND' => self::HOUR_SECOND_SYMBOL,
|
|
'IDENTIFIED' => self::IDENTIFIED_SYMBOL,
|
|
'IF' => self::IF_SYMBOL,
|
|
'IGNORE' => self::IGNORE_SYMBOL,
|
|
'IGNORE_SERVER_IDS' => self::IGNORE_SERVER_IDS_SYMBOL,
|
|
'IMPORT' => self::IMPORT_SYMBOL,
|
|
'IN' => self::IN_SYMBOL,
|
|
'INDEX' => self::INDEX_SYMBOL,
|
|
'INDEXES' => self::INDEXES_SYMBOL,
|
|
'INFILE' => self::INFILE_SYMBOL,
|
|
'INITIAL_SIZE' => self::INITIAL_SIZE_SYMBOL,
|
|
'INNER' => self::INNER_SYMBOL,
|
|
'INNODB' => self::INNODB_SYMBOL,
|
|
'INOUT' => self::INOUT_SYMBOL,
|
|
'INSENSITIVE' => self::INSENSITIVE_SYMBOL,
|
|
'INSERT' => self::INSERT_SYMBOL,
|
|
'INSERT_METHOD' => self::INSERT_METHOD_SYMBOL,
|
|
'INSTALL' => self::INSTALL_SYMBOL,
|
|
'INSTANCE' => self::INSTANCE_SYMBOL,
|
|
'INT' => self::INT_SYMBOL,
|
|
'INT1' => self::INT1_SYMBOL,
|
|
'INT2' => self::INT2_SYMBOL,
|
|
'INT3' => self::INT3_SYMBOL,
|
|
'INT4' => self::INT4_SYMBOL,
|
|
'INT8' => self::INT8_SYMBOL,
|
|
'INTEGER' => self::INTEGER_SYMBOL,
|
|
'INTERVAL' => self::INTERVAL_SYMBOL,
|
|
'INTO' => self::INTO_SYMBOL,
|
|
'INVOKER' => self::INVOKER_SYMBOL,
|
|
'IO' => self::IO_SYMBOL,
|
|
'IO_AFTER_GTIDS' => self::IO_AFTER_GTIDS_SYMBOL,
|
|
'IO_BEFORE_GTIDS' => self::IO_BEFORE_GTIDS_SYMBOL,
|
|
'IO_THREAD' => self::IO_THREAD_SYMBOL,
|
|
'IPC' => self::IPC_SYMBOL,
|
|
'IS' => self::IS_SYMBOL,
|
|
'ISOLATION' => self::ISOLATION_SYMBOL,
|
|
'ISSUER' => self::ISSUER_SYMBOL,
|
|
'ITERATE' => self::ITERATE_SYMBOL,
|
|
'JOIN' => self::JOIN_SYMBOL,
|
|
'JSON' => self::JSON_SYMBOL,
|
|
'KEY' => self::KEY_SYMBOL,
|
|
'KEY_BLOCK_SIZE' => self::KEY_BLOCK_SIZE_SYMBOL,
|
|
'KEYS' => self::KEYS_SYMBOL,
|
|
'KILL' => self::KILL_SYMBOL,
|
|
'LANGUAGE' => self::LANGUAGE_SYMBOL,
|
|
'LAST' => self::LAST_SYMBOL,
|
|
'LEADING' => self::LEADING_SYMBOL,
|
|
'LEAVE' => self::LEAVE_SYMBOL,
|
|
'LEAVES' => self::LEAVES_SYMBOL,
|
|
'LEFT' => self::LEFT_SYMBOL,
|
|
'LESS' => self::LESS_SYMBOL,
|
|
'LEVEL' => self::LEVEL_SYMBOL,
|
|
'LIKE' => self::LIKE_SYMBOL,
|
|
'LIMIT' => self::LIMIT_SYMBOL,
|
|
'LINEAR' => self::LINEAR_SYMBOL,
|
|
'LINES' => self::LINES_SYMBOL,
|
|
'LINESTRING' => self::LINESTRING_SYMBOL,
|
|
'LIST' => self::LIST_SYMBOL,
|
|
'LOAD' => self::LOAD_SYMBOL,
|
|
'LOCAL' => self::LOCAL_SYMBOL,
|
|
'LOCALTIME' => self::LOCALTIME_SYMBOL,
|
|
'LOCALTIMESTAMP' => self::LOCALTIMESTAMP_SYMBOL,
|
|
'LOCATOR' => self::LOCATOR_SYMBOL,
|
|
'LOCK' => self::LOCK_SYMBOL,
|
|
'LOCKS' => self::LOCKS_SYMBOL,
|
|
'LOGFILE' => self::LOGFILE_SYMBOL,
|
|
'LOGS' => self::LOGS_SYMBOL,
|
|
'LONG' => self::LONG_SYMBOL,
|
|
'LONG_NUM' => self::LONG_NUM_SYMBOL,
|
|
'LONGBLOB' => self::LONGBLOB_SYMBOL,
|
|
'LONGTEXT' => self::LONGTEXT_SYMBOL,
|
|
'LOOP' => self::LOOP_SYMBOL,
|
|
'LOW_PRIORITY' => self::LOW_PRIORITY_SYMBOL,
|
|
'MASTER' => self::MASTER_SYMBOL,
|
|
'MASTER_AUTO_POSITION' => self::MASTER_AUTO_POSITION_SYMBOL,
|
|
'MASTER_BIND' => self::MASTER_BIND_SYMBOL,
|
|
'MASTER_CONNECT_RETRY' => self::MASTER_CONNECT_RETRY_SYMBOL,
|
|
'MASTER_DELAY' => self::MASTER_DELAY_SYMBOL,
|
|
'MASTER_HEARTBEAT_PERIOD' => self::MASTER_HEARTBEAT_PERIOD_SYMBOL,
|
|
'MASTER_HOST' => self::MASTER_HOST_SYMBOL,
|
|
'MASTER_LOG_FILE' => self::MASTER_LOG_FILE_SYMBOL,
|
|
'MASTER_LOG_POS' => self::MASTER_LOG_POS_SYMBOL,
|
|
'MASTER_PASSWORD' => self::MASTER_PASSWORD_SYMBOL,
|
|
'MASTER_PORT' => self::MASTER_PORT_SYMBOL,
|
|
'MASTER_RETRY_COUNT' => self::MASTER_RETRY_COUNT_SYMBOL,
|
|
'MASTER_SERVER_ID' => self::MASTER_SERVER_ID_SYMBOL,
|
|
'MASTER_SSL' => self::MASTER_SSL_SYMBOL,
|
|
'MASTER_SSL_CA' => self::MASTER_SSL_CA_SYMBOL,
|
|
'MASTER_SSL_CAPATH' => self::MASTER_SSL_CAPATH_SYMBOL,
|
|
'MASTER_SSL_CERT' => self::MASTER_SSL_CERT_SYMBOL,
|
|
'MASTER_SSL_CIPHER' => self::MASTER_SSL_CIPHER_SYMBOL,
|
|
'MASTER_SSL_CRL' => self::MASTER_SSL_CRL_SYMBOL,
|
|
'MASTER_SSL_CRLPATH' => self::MASTER_SSL_CRLPATH_SYMBOL,
|
|
'MASTER_SSL_KEY' => self::MASTER_SSL_KEY_SYMBOL,
|
|
'MASTER_SSL_VERIFY_SERVER_CERT' => self::MASTER_SSL_VERIFY_SERVER_CERT_SYMBOL,
|
|
'MASTER_TLS_VERSION' => self::MASTER_TLS_VERSION_SYMBOL,
|
|
'MASTER_USER' => self::MASTER_USER_SYMBOL,
|
|
'MATCH' => self::MATCH_SYMBOL,
|
|
'MAX' => self::MAX_SYMBOL,
|
|
'MAX_CONNECTIONS_PER_HOUR' => self::MAX_CONNECTIONS_PER_HOUR_SYMBOL,
|
|
'MAX_QUERIES_PER_HOUR' => self::MAX_QUERIES_PER_HOUR_SYMBOL,
|
|
'MAX_ROWS' => self::MAX_ROWS_SYMBOL,
|
|
'MAX_SIZE' => self::MAX_SIZE_SYMBOL,
|
|
'MAX_STATEMENT_TIME' => self::MAX_STATEMENT_TIME_SYMBOL,
|
|
'MAX_UPDATES_PER_HOUR' => self::MAX_UPDATES_PER_HOUR_SYMBOL,
|
|
'MAX_USER_CONNECTIONS' => self::MAX_USER_CONNECTIONS_SYMBOL,
|
|
'MAXVALUE' => self::MAXVALUE_SYMBOL,
|
|
'MEDIUM' => self::MEDIUM_SYMBOL,
|
|
'MEDIUMBLOB' => self::MEDIUMBLOB_SYMBOL,
|
|
'MEDIUMINT' => self::MEDIUMINT_SYMBOL,
|
|
'MEDIUMTEXT' => self::MEDIUMTEXT_SYMBOL,
|
|
'MEMORY' => self::MEMORY_SYMBOL,
|
|
'MERGE' => self::MERGE_SYMBOL,
|
|
'MESSAGE_TEXT' => self::MESSAGE_TEXT_SYMBOL,
|
|
'MICROSECOND' => self::MICROSECOND_SYMBOL,
|
|
'MID' => self::MID_SYMBOL,
|
|
'MIDDLEINT' => self::MIDDLEINT_SYMBOL,
|
|
'MIGRATE' => self::MIGRATE_SYMBOL,
|
|
'MIN' => self::MIN_SYMBOL,
|
|
'MIN_ROWS' => self::MIN_ROWS_SYMBOL,
|
|
'MINUTE' => self::MINUTE_SYMBOL,
|
|
'MINUTE_MICROSECOND' => self::MINUTE_MICROSECOND_SYMBOL,
|
|
'MINUTE_SECOND' => self::MINUTE_SECOND_SYMBOL,
|
|
'MOD' => self::MOD_SYMBOL,
|
|
'MODE' => self::MODE_SYMBOL,
|
|
'MODIFIES' => self::MODIFIES_SYMBOL,
|
|
'MODIFY' => self::MODIFY_SYMBOL,
|
|
'MONTH' => self::MONTH_SYMBOL,
|
|
'MULTILINESTRING' => self::MULTILINESTRING_SYMBOL,
|
|
'MULTIPOINT' => self::MULTIPOINT_SYMBOL,
|
|
'MULTIPOLYGON' => self::MULTIPOLYGON_SYMBOL,
|
|
'MUTEX' => self::MUTEX_SYMBOL,
|
|
'MYSQL_ERRNO' => self::MYSQL_ERRNO_SYMBOL,
|
|
'NAME' => self::NAME_SYMBOL,
|
|
'NAMES' => self::NAMES_SYMBOL,
|
|
'NATIONAL' => self::NATIONAL_SYMBOL,
|
|
'NATURAL' => self::NATURAL_SYMBOL,
|
|
'NCHAR' => self::NCHAR_SYMBOL,
|
|
'NCHAR_STRING' => self::NCHAR_STRING_SYMBOL,
|
|
'NDB' => self::NDB_SYMBOL,
|
|
'NDBCLUSTER' => self::NDBCLUSTER_SYMBOL,
|
|
'NEG' => self::NEG_SYMBOL,
|
|
'NEVER' => self::NEVER_SYMBOL,
|
|
'NEW' => self::NEW_SYMBOL,
|
|
'NEXT' => self::NEXT_SYMBOL,
|
|
'NO' => self::NO_SYMBOL,
|
|
'NO_WAIT' => self::NO_WAIT_SYMBOL,
|
|
'NO_WRITE_TO_BINLOG' => self::NO_WRITE_TO_BINLOG_SYMBOL,
|
|
'NODEGROUP' => self::NODEGROUP_SYMBOL,
|
|
'NONBLOCKING' => self::NONBLOCKING_SYMBOL,
|
|
'NONE' => self::NONE_SYMBOL,
|
|
'NOT' => self::NOT_SYMBOL,
|
|
'NOW' => self::NOW_SYMBOL,
|
|
'NULL' => self::NULL_SYMBOL,
|
|
'NUMBER' => self::NUMBER_SYMBOL,
|
|
'NUMERIC' => self::NUMERIC_SYMBOL,
|
|
'NVARCHAR' => self::NVARCHAR_SYMBOL,
|
|
'OFFLINE' => self::OFFLINE_SYMBOL,
|
|
'OFFSET' => self::OFFSET_SYMBOL,
|
|
'OLD_PASSWORD' => self::OLD_PASSWORD_SYMBOL,
|
|
'ON' => self::ON_SYMBOL,
|
|
'ONE' => self::ONE_SYMBOL,
|
|
'ONLINE' => self::ONLINE_SYMBOL,
|
|
'ONLY' => self::ONLY_SYMBOL,
|
|
'OPEN' => self::OPEN_SYMBOL,
|
|
'OPTIMIZE' => self::OPTIMIZE_SYMBOL,
|
|
'OPTIMIZER_COSTS' => self::OPTIMIZER_COSTS_SYMBOL,
|
|
'OPTION' => self::OPTION_SYMBOL,
|
|
'OPTIONALLY' => self::OPTIONALLY_SYMBOL,
|
|
'OPTIONS' => self::OPTIONS_SYMBOL,
|
|
'OR' => self::OR_SYMBOL,
|
|
'ORDER' => self::ORDER_SYMBOL,
|
|
'OUT' => self::OUT_SYMBOL,
|
|
'OUTER' => self::OUTER_SYMBOL,
|
|
'OUTFILE' => self::OUTFILE_SYMBOL,
|
|
'OWNER' => self::OWNER_SYMBOL,
|
|
'PACK_KEYS' => self::PACK_KEYS_SYMBOL,
|
|
'PAGE' => self::PAGE_SYMBOL,
|
|
'PARSER' => self::PARSER_SYMBOL,
|
|
'PARTIAL' => self::PARTIAL_SYMBOL,
|
|
'PARTITION' => self::PARTITION_SYMBOL,
|
|
'PARTITIONING' => self::PARTITIONING_SYMBOL,
|
|
'PARTITIONS' => self::PARTITIONS_SYMBOL,
|
|
'PASSWORD' => self::PASSWORD_SYMBOL,
|
|
'PHASE' => self::PHASE_SYMBOL,
|
|
'PLUGIN' => self::PLUGIN_SYMBOL,
|
|
'PLUGIN_DIR' => self::PLUGIN_DIR_SYMBOL,
|
|
'PLUGINS' => self::PLUGINS_SYMBOL,
|
|
'POINT' => self::POINT_SYMBOL,
|
|
'POLYGON' => self::POLYGON_SYMBOL,
|
|
'PORT' => self::PORT_SYMBOL,
|
|
'POSITION' => self::POSITION_SYMBOL,
|
|
'PRECEDES' => self::PRECEDES_SYMBOL,
|
|
'PRECISION' => self::PRECISION_SYMBOL,
|
|
'PREPARE' => self::PREPARE_SYMBOL,
|
|
'PRESERVE' => self::PRESERVE_SYMBOL,
|
|
'PREV' => self::PREV_SYMBOL,
|
|
'PRIMARY' => self::PRIMARY_SYMBOL,
|
|
'PRIVILEGES' => self::PRIVILEGES_SYMBOL,
|
|
'PROCEDURE' => self::PROCEDURE_SYMBOL,
|
|
'PROCESS' => self::PROCESS_SYMBOL,
|
|
'PROCESSLIST' => self::PROCESSLIST_SYMBOL,
|
|
'PROFILE' => self::PROFILE_SYMBOL,
|
|
'PROFILES' => self::PROFILES_SYMBOL,
|
|
'PROXY' => self::PROXY_SYMBOL,
|
|
'PURGE' => self::PURGE_SYMBOL,
|
|
'QUARTER' => self::QUARTER_SYMBOL,
|
|
'QUERY' => self::QUERY_SYMBOL,
|
|
'QUICK' => self::QUICK_SYMBOL,
|
|
'RANGE' => self::RANGE_SYMBOL,
|
|
'READ' => self::READ_SYMBOL,
|
|
'READ_ONLY' => self::READ_ONLY_SYMBOL,
|
|
'READ_WRITE' => self::READ_WRITE_SYMBOL,
|
|
'READS' => self::READS_SYMBOL,
|
|
'REAL' => self::REAL_SYMBOL,
|
|
'REBUILD' => self::REBUILD_SYMBOL,
|
|
'RECOVER' => self::RECOVER_SYMBOL,
|
|
'REDO_BUFFER_SIZE' => self::REDO_BUFFER_SIZE_SYMBOL,
|
|
'REDOFILE' => self::REDOFILE_SYMBOL,
|
|
'REDUNDANT' => self::REDUNDANT_SYMBOL,
|
|
'REFERENCES' => self::REFERENCES_SYMBOL,
|
|
'REGEXP' => self::REGEXP_SYMBOL,
|
|
'RELAY' => self::RELAY_SYMBOL,
|
|
'RELAY_LOG_FILE' => self::RELAY_LOG_FILE_SYMBOL,
|
|
'RELAY_LOG_POS' => self::RELAY_LOG_POS_SYMBOL,
|
|
'RELAY_THREAD' => self::RELAY_THREAD_SYMBOL,
|
|
'RELAYLOG' => self::RELAYLOG_SYMBOL,
|
|
'RELEASE' => self::RELEASE_SYMBOL,
|
|
'RELOAD' => self::RELOAD_SYMBOL,
|
|
'REMOVE' => self::REMOVE_SYMBOL,
|
|
'RENAME' => self::RENAME_SYMBOL,
|
|
'REORGANIZE' => self::REORGANIZE_SYMBOL,
|
|
'REPAIR' => self::REPAIR_SYMBOL,
|
|
'REPEAT' => self::REPEAT_SYMBOL,
|
|
'REPEATABLE' => self::REPEATABLE_SYMBOL,
|
|
'REPLACE' => self::REPLACE_SYMBOL,
|
|
'REPLICATE_DO_DB' => self::REPLICATE_DO_DB_SYMBOL,
|
|
'REPLICATE_DO_TABLE' => self::REPLICATE_DO_TABLE_SYMBOL,
|
|
'REPLICATE_IGNORE_DB' => self::REPLICATE_IGNORE_DB_SYMBOL,
|
|
'REPLICATE_IGNORE_TABLE' => self::REPLICATE_IGNORE_TABLE_SYMBOL,
|
|
'REPLICATE_REWRITE_DB' => self::REPLICATE_REWRITE_DB_SYMBOL,
|
|
'REPLICATE_WILD_DO_TABLE' => self::REPLICATE_WILD_DO_TABLE_SYMBOL,
|
|
'REPLICATE_WILD_IGNORE_TABLE' => self::REPLICATE_WILD_IGNORE_TABLE_SYMBOL,
|
|
'REPLICATION' => self::REPLICATION_SYMBOL,
|
|
'REQUIRE' => self::REQUIRE_SYMBOL,
|
|
'RESET' => self::RESET_SYMBOL,
|
|
'RESIGNAL' => self::RESIGNAL_SYMBOL,
|
|
'RESTORE' => self::RESTORE_SYMBOL,
|
|
'RESTRICT' => self::RESTRICT_SYMBOL,
|
|
'RESUME' => self::RESUME_SYMBOL,
|
|
'RETURN' => self::RETURN_SYMBOL,
|
|
'RETURNED_SQLSTATE' => self::RETURNED_SQLSTATE_SYMBOL,
|
|
'RETURNS' => self::RETURNS_SYMBOL,
|
|
'REVERSE' => self::REVERSE_SYMBOL,
|
|
'REVOKE' => self::REVOKE_SYMBOL,
|
|
'RIGHT' => self::RIGHT_SYMBOL,
|
|
'RLIKE' => self::RLIKE_SYMBOL,
|
|
'ROLLBACK' => self::ROLLBACK_SYMBOL,
|
|
'ROLLUP' => self::ROLLUP_SYMBOL,
|
|
'ROTATE' => self::ROTATE_SYMBOL,
|
|
'ROUTINE' => self::ROUTINE_SYMBOL,
|
|
'ROW' => self::ROW_SYMBOL,
|
|
'ROW_COUNT' => self::ROW_COUNT_SYMBOL,
|
|
'ROW_FORMAT' => self::ROW_FORMAT_SYMBOL,
|
|
'ROWS' => self::ROWS_SYMBOL,
|
|
'RTREE' => self::RTREE_SYMBOL,
|
|
'SAVEPOINT' => self::SAVEPOINT_SYMBOL,
|
|
'SCHEDULE' => self::SCHEDULE_SYMBOL,
|
|
'SCHEMA' => self::SCHEMA_SYMBOL,
|
|
'SCHEMA_NAME' => self::SCHEMA_NAME_SYMBOL,
|
|
'SCHEMAS' => self::SCHEMAS_SYMBOL,
|
|
'SECOND' => self::SECOND_SYMBOL,
|
|
'SECOND_MICROSECOND' => self::SECOND_MICROSECOND_SYMBOL,
|
|
'SECURITY' => self::SECURITY_SYMBOL,
|
|
'SELECT' => self::SELECT_SYMBOL,
|
|
'SENSITIVE' => self::SENSITIVE_SYMBOL,
|
|
'SEPARATOR' => self::SEPARATOR_SYMBOL,
|
|
'SERIAL' => self::SERIAL_SYMBOL,
|
|
'SERIALIZABLE' => self::SERIALIZABLE_SYMBOL,
|
|
'SERVER' => self::SERVER_SYMBOL,
|
|
'SERVER_OPTIONS' => self::SERVER_OPTIONS_SYMBOL,
|
|
'SESSION' => self::SESSION_SYMBOL,
|
|
'SESSION_USER' => self::SESSION_USER_SYMBOL,
|
|
'SET' => self::SET_SYMBOL,
|
|
'SET_VAR' => self::SET_VAR_SYMBOL,
|
|
'SHARE' => self::SHARE_SYMBOL,
|
|
'SHOW' => self::SHOW_SYMBOL,
|
|
'SHUTDOWN' => self::SHUTDOWN_SYMBOL,
|
|
'SIGNAL' => self::SIGNAL_SYMBOL,
|
|
'SIGNED' => self::SIGNED_SYMBOL,
|
|
'SIMPLE' => self::SIMPLE_SYMBOL,
|
|
'SLAVE' => self::SLAVE_SYMBOL,
|
|
'SLOW' => self::SLOW_SYMBOL,
|
|
'SMALLINT' => self::SMALLINT_SYMBOL,
|
|
'SNAPSHOT' => self::SNAPSHOT_SYMBOL,
|
|
'SOCKET' => self::SOCKET_SYMBOL,
|
|
'SOME' => self::SOME_SYMBOL,
|
|
'SONAME' => self::SONAME_SYMBOL,
|
|
'SOUNDS' => self::SOUNDS_SYMBOL,
|
|
'SOURCE' => self::SOURCE_SYMBOL,
|
|
'SPATIAL' => self::SPATIAL_SYMBOL,
|
|
'SPECIFIC' => self::SPECIFIC_SYMBOL,
|
|
'SQL' => self::SQL_SYMBOL,
|
|
'SQL_AFTER_GTIDS' => self::SQL_AFTER_GTIDS_SYMBOL,
|
|
'SQL_AFTER_MTS_GAPS' => self::SQL_AFTER_MTS_GAPS_SYMBOL,
|
|
'SQL_BEFORE_GTIDS' => self::SQL_BEFORE_GTIDS_SYMBOL,
|
|
'SQL_BIG_RESULT' => self::SQL_BIG_RESULT_SYMBOL,
|
|
'SQL_BUFFER_RESULT' => self::SQL_BUFFER_RESULT_SYMBOL,
|
|
'SQL_CACHE' => self::SQL_CACHE_SYMBOL,
|
|
'SQL_CALC_FOUND_ROWS' => self::SQL_CALC_FOUND_ROWS_SYMBOL,
|
|
'SQL_NO_CACHE' => self::SQL_NO_CACHE_SYMBOL,
|
|
'SQL_SMALL_RESULT' => self::SQL_SMALL_RESULT_SYMBOL,
|
|
'SQL_THREAD' => self::SQL_THREAD_SYMBOL,
|
|
'SQL_TSI_DAY' => self::SQL_TSI_DAY_SYMBOL,
|
|
'SQL_TSI_HOUR' => self::SQL_TSI_HOUR_SYMBOL,
|
|
'SQL_TSI_MICROSECOND' => self::SQL_TSI_MICROSECOND_SYMBOL,
|
|
'SQL_TSI_MINUTE' => self::SQL_TSI_MINUTE_SYMBOL,
|
|
'SQL_TSI_MONTH' => self::SQL_TSI_MONTH_SYMBOL,
|
|
'SQL_TSI_QUARTER' => self::SQL_TSI_QUARTER_SYMBOL,
|
|
'SQL_TSI_SECOND' => self::SQL_TSI_SECOND_SYMBOL,
|
|
'SQL_TSI_WEEK' => self::SQL_TSI_WEEK_SYMBOL,
|
|
'SQL_TSI_YEAR' => self::SQL_TSI_YEAR_SYMBOL,
|
|
'SQLEXCEPTION' => self::SQLEXCEPTION_SYMBOL,
|
|
'SQLSTATE' => self::SQLSTATE_SYMBOL,
|
|
'SQLWARNING' => self::SQLWARNING_SYMBOL,
|
|
'SSL' => self::SSL_SYMBOL,
|
|
'STACKED' => self::STACKED_SYMBOL,
|
|
'START' => self::START_SYMBOL,
|
|
'STARTING' => self::STARTING_SYMBOL,
|
|
'STARTS' => self::STARTS_SYMBOL,
|
|
'STATS_AUTO_RECALC' => self::STATS_AUTO_RECALC_SYMBOL,
|
|
'STATS_PERSISTENT' => self::STATS_PERSISTENT_SYMBOL,
|
|
'STATS_SAMPLE_PAGES' => self::STATS_SAMPLE_PAGES_SYMBOL,
|
|
'STATUS' => self::STATUS_SYMBOL,
|
|
'STD' => self::STD_SYMBOL,
|
|
'STDDEV' => self::STDDEV_SYMBOL,
|
|
'STDDEV_POP' => self::STDDEV_POP_SYMBOL,
|
|
'STDDEV_SAMP' => self::STDDEV_SAMP_SYMBOL,
|
|
'STOP' => self::STOP_SYMBOL,
|
|
'STORAGE' => self::STORAGE_SYMBOL,
|
|
'STORED' => self::STORED_SYMBOL,
|
|
'STRAIGHT_JOIN' => self::STRAIGHT_JOIN_SYMBOL,
|
|
'STRING' => self::STRING_SYMBOL,
|
|
'SUBCLASS_ORIGIN' => self::SUBCLASS_ORIGIN_SYMBOL,
|
|
'SUBDATE' => self::SUBDATE_SYMBOL,
|
|
'SUBJECT' => self::SUBJECT_SYMBOL,
|
|
'SUBPARTITION' => self::SUBPARTITION_SYMBOL,
|
|
'SUBPARTITIONS' => self::SUBPARTITIONS_SYMBOL,
|
|
'SUBSTR' => self::SUBSTR_SYMBOL,
|
|
'SUBSTRING' => self::SUBSTRING_SYMBOL,
|
|
'SUM' => self::SUM_SYMBOL,
|
|
'SUPER' => self::SUPER_SYMBOL,
|
|
'SUSPEND' => self::SUSPEND_SYMBOL,
|
|
'SWAPS' => self::SWAPS_SYMBOL,
|
|
'SWITCHES' => self::SWITCHES_SYMBOL,
|
|
'SYSDATE' => self::SYSDATE_SYMBOL,
|
|
'SYSTEM_USER' => self::SYSTEM_USER_SYMBOL,
|
|
'TABLE' => self::TABLE_SYMBOL,
|
|
'TABLE_CHECKSUM' => self::TABLE_CHECKSUM_SYMBOL,
|
|
'TABLE_NAME' => self::TABLE_NAME_SYMBOL,
|
|
'TABLE_REF_PRIORITY' => self::TABLE_REF_PRIORITY_SYMBOL,
|
|
'TABLES' => self::TABLES_SYMBOL,
|
|
'TABLESPACE' => self::TABLESPACE_SYMBOL,
|
|
'TEMPORARY' => self::TEMPORARY_SYMBOL,
|
|
'TEMPTABLE' => self::TEMPTABLE_SYMBOL,
|
|
'TERMINATED' => self::TERMINATED_SYMBOL,
|
|
'TEXT' => self::TEXT_SYMBOL,
|
|
'THAN' => self::THAN_SYMBOL,
|
|
'THEN' => self::THEN_SYMBOL,
|
|
'TIME' => self::TIME_SYMBOL,
|
|
'TIMESTAMP' => self::TIMESTAMP_SYMBOL,
|
|
'TIMESTAMP_ADD' => self::TIMESTAMP_ADD_SYMBOL,
|
|
'TIMESTAMP_DIFF' => self::TIMESTAMP_DIFF_SYMBOL,
|
|
'TINYBLOB' => self::TINYBLOB_SYMBOL,
|
|
'TINYINT' => self::TINYINT_SYMBOL,
|
|
'TINYTEXT' => self::TINYTEXT_SYMBOL,
|
|
'TO' => self::TO_SYMBOL,
|
|
'TRAILING' => self::TRAILING_SYMBOL,
|
|
'TRANSACTION' => self::TRANSACTION_SYMBOL,
|
|
'TRIGGER' => self::TRIGGER_SYMBOL,
|
|
'TRIGGERS' => self::TRIGGERS_SYMBOL,
|
|
'TRIM' => self::TRIM_SYMBOL,
|
|
'TRUE' => self::TRUE_SYMBOL,
|
|
'TRUNCATE' => self::TRUNCATE_SYMBOL,
|
|
'TYPE' => self::TYPE_SYMBOL,
|
|
'TYPES' => self::TYPES_SYMBOL,
|
|
'UDF_RETURNS' => self::UDF_RETURNS_SYMBOL,
|
|
'UNCOMMITTED' => self::UNCOMMITTED_SYMBOL,
|
|
'UNDEFINED' => self::UNDEFINED_SYMBOL,
|
|
'UNDO' => self::UNDO_SYMBOL,
|
|
'UNDO_BUFFER_SIZE' => self::UNDO_BUFFER_SIZE_SYMBOL,
|
|
'UNDOFILE' => self::UNDOFILE_SYMBOL,
|
|
'UNICODE' => self::UNICODE_SYMBOL,
|
|
'UNINSTALL' => self::UNINSTALL_SYMBOL,
|
|
'UNION' => self::UNION_SYMBOL,
|
|
'UNIQUE' => self::UNIQUE_SYMBOL,
|
|
'UNKNOWN' => self::UNKNOWN_SYMBOL,
|
|
'UNLOCK' => self::UNLOCK_SYMBOL,
|
|
'UNSIGNED' => self::UNSIGNED_SYMBOL,
|
|
'UNTIL' => self::UNTIL_SYMBOL,
|
|
'UPDATE' => self::UPDATE_SYMBOL,
|
|
'UPGRADE' => self::UPGRADE_SYMBOL,
|
|
'USAGE' => self::USAGE_SYMBOL,
|
|
'USE' => self::USE_SYMBOL,
|
|
'USE_FRM' => self::USE_FRM_SYMBOL,
|
|
'USER' => self::USER_SYMBOL,
|
|
'USER_RESOURCES' => self::USER_RESOURCES_SYMBOL,
|
|
'USING' => self::USING_SYMBOL,
|
|
'UTC_DATE' => self::UTC_DATE_SYMBOL,
|
|
'UTC_TIME' => self::UTC_TIME_SYMBOL,
|
|
'UTC_TIMESTAMP' => self::UTC_TIMESTAMP_SYMBOL,
|
|
'VALIDATION' => self::VALIDATION_SYMBOL,
|
|
'VALUE' => self::VALUE_SYMBOL,
|
|
'VALUES' => self::VALUES_SYMBOL,
|
|
'VAR_POP' => self::VAR_POP_SYMBOL,
|
|
'VAR_SAMP' => self::VAR_SAMP_SYMBOL,
|
|
'VARBINARY' => self::VARBINARY_SYMBOL,
|
|
'VARCHAR' => self::VARCHAR_SYMBOL,
|
|
'VARCHARACTER' => self::VARCHARACTER_SYMBOL,
|
|
'VARIABLES' => self::VARIABLES_SYMBOL,
|
|
'VARIANCE' => self::VARIANCE_SYMBOL,
|
|
'VARYING' => self::VARYING_SYMBOL,
|
|
'VIEW' => self::VIEW_SYMBOL,
|
|
'VIRTUAL' => self::VIRTUAL_SYMBOL,
|
|
'WAIT' => self::WAIT_SYMBOL,
|
|
'WARNINGS' => self::WARNINGS_SYMBOL,
|
|
'WEEK' => self::WEEK_SYMBOL,
|
|
'WEIGHT_STRING' => self::WEIGHT_STRING_SYMBOL,
|
|
'WHEN' => self::WHEN_SYMBOL,
|
|
'WHERE' => self::WHERE_SYMBOL,
|
|
'WHILE' => self::WHILE_SYMBOL,
|
|
'WITH' => self::WITH_SYMBOL,
|
|
'WITHOUT' => self::WITHOUT_SYMBOL,
|
|
'WORK' => self::WORK_SYMBOL,
|
|
'WRAPPER' => self::WRAPPER_SYMBOL,
|
|
'WRITE' => self::WRITE_SYMBOL,
|
|
'X509' => self::X509_SYMBOL,
|
|
'XA' => self::XA_SYMBOL,
|
|
'XID' => self::XID_SYMBOL,
|
|
'XML' => self::XML_SYMBOL,
|
|
'XOR' => self::XOR_SYMBOL,
|
|
'YEAR' => self::YEAR_SYMBOL,
|
|
'YEAR_MONTH' => self::YEAR_MONTH_SYMBOL,
|
|
'ZEROFILL' => self::ZEROFILL_SYMBOL,
|
|
|
|
// Tokens from MySQL 8.0:
|
|
'ACTIVE' => self::ACTIVE_SYMBOL,
|
|
'ADMIN' => self::ADMIN_SYMBOL,
|
|
'ARRAY' => self::ARRAY_SYMBOL,
|
|
'ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS' => self::ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS_SYMBOL,
|
|
'BUCKETS' => self::BUCKETS_SYMBOL,
|
|
'CLONE' => self::CLONE_SYMBOL,
|
|
'COMPONENT' => self::COMPONENT_SYMBOL,
|
|
'CUME_DIST' => self::CUME_DIST_SYMBOL,
|
|
'DEFINITION' => self::DEFINITION_SYMBOL,
|
|
'DENSE_RANK' => self::DENSE_RANK_SYMBOL,
|
|
'DESCRIPTION' => self::DESCRIPTION_SYMBOL,
|
|
'EMPTY' => self::EMPTY_SYMBOL,
|
|
'ENFORCED' => self::ENFORCED_SYMBOL,
|
|
'ENGINE_ATTRIBUTE' => self::ENGINE_ATTRIBUTE_SYMBOL,
|
|
'EXCEPT' => self::EXCEPT_SYMBOL,
|
|
'EXCLUDE' => self::EXCLUDE_SYMBOL,
|
|
'FAILED_LOGIN_ATTEMPTS' => self::FAILED_LOGIN_ATTEMPTS_SYMBOL,
|
|
'FIRST_VALUE' => self::FIRST_VALUE_SYMBOL,
|
|
'FOLLOWING' => self::FOLLOWING_SYMBOL,
|
|
'GET_MASTER_PUBLIC_KEY_SYM' => self::GET_MASTER_PUBLIC_KEY_SYMBOL,
|
|
'GET_SOURCE_PUBLIC_KEY' => self::GET_SOURCE_PUBLIC_KEY_SYMBOL,
|
|
'GROUPING' => self::GROUPING_SYMBOL,
|
|
'GROUPS' => self::GROUPS_SYMBOL,
|
|
'GTID_ONLY' => self::GTID_ONLY_SYMBOL,
|
|
'HISTOGRAM' => self::HISTOGRAM_SYMBOL,
|
|
'HISTORY' => self::HISTORY_SYMBOL,
|
|
'INACTIVE' => self::INACTIVE_SYMBOL,
|
|
'INTERSECT' => self::INTERSECT_SYMBOL,
|
|
'INVISIBLE' => self::INVISIBLE_SYMBOL,
|
|
'JSON_ARRAYAGG' => self::JSON_ARRAYAGG_SYMBOL,
|
|
'JSON_OBJECTAGG' => self::JSON_OBJECTAGG_SYMBOL,
|
|
'JSON_TABLE' => self::JSON_TABLE_SYMBOL,
|
|
'JSON_VALUE' => self::JSON_VALUE_SYMBOL,
|
|
'KEYRING' => self::KEYRING_SYMBOL,
|
|
'LAG' => self::LAG_SYMBOL,
|
|
'LAST_VALUE' => self::LAST_VALUE_SYMBOL,
|
|
'LATERAL' => self::LATERAL_SYMBOL,
|
|
'LEAD' => self::LEAD_SYMBOL,
|
|
'LOCKED' => self::LOCKED_SYMBOL,
|
|
'MASTER_COMPRESSION_ALGORITHM' => self::MASTER_COMPRESSION_ALGORITHM_SYMBOL,
|
|
'MASTER_PUBLIC_KEY_PATH' => self::MASTER_PUBLIC_KEY_PATH_SYMBOL,
|
|
'MASTER_TLS_CIPHERSUITES' => self::MASTER_TLS_CIPHERSUITES_SYMBOL,
|
|
'MASTER_ZSTD_COMPRESSION_LEVEL' => self::MASTER_ZSTD_COMPRESSION_LEVEL_SYMBOL,
|
|
'MEMBER' => self::MEMBER_SYMBOL,
|
|
'NESTED' => self::NESTED_SYMBOL,
|
|
'NETWORK_NAMESPACE' => self::NETWORK_NAMESPACE_SYMBOL,
|
|
'NOWAIT' => self::NOWAIT_SYMBOL,
|
|
'NTH_VALUE' => self::NTH_VALUE_SYMBOL,
|
|
'NTILE' => self::NTILE_SYMBOL,
|
|
'NULLS' => self::NULLS_SYMBOL,
|
|
'OF' => self::OF_SYMBOL,
|
|
'OFF' => self::OFF_SYMBOL,
|
|
'OJ' => self::OJ_SYMBOL,
|
|
'OLD' => self::OLD_SYMBOL,
|
|
'OPTIONAL' => self::OPTIONAL_SYMBOL,
|
|
'ORDINALITY' => self::ORDINALITY_SYMBOL,
|
|
'ORGANIZATION' => self::ORGANIZATION_SYMBOL,
|
|
'OTHERS' => self::OTHERS_SYMBOL,
|
|
'OVER' => self::OVER_SYMBOL,
|
|
'PASSWORD_LOCK_TIME' => self::PASSWORD_LOCK_TIME_SYMBOL,
|
|
'PATH' => self::PATH_SYMBOL,
|
|
'PERCENT_RANK' => self::PERCENT_RANK_SYMBOL,
|
|
'PERSIST' => self::PERSIST_SYMBOL,
|
|
'PERSIST_ONLY' => self::PERSIST_ONLY_SYMBOL,
|
|
'PRECEDING' => self::PRECEDING_SYMBOL,
|
|
'PRIVILEGE_CHECKS_USER' => self::PRIVILEGE_CHECKS_USER_SYMBOL,
|
|
'RANDOM' => self::RANDOM_SYMBOL,
|
|
'RANK' => self::RANK_SYMBOL,
|
|
'RECURSIVE' => self::RECURSIVE_SYMBOL,
|
|
'REDO_LOG' => self::REDO_LOG_SYMBOL,
|
|
'REFERENCE' => self::REFERENCE_SYMBOL,
|
|
'REMOTE' => self::REMOTE_SYMBOL,
|
|
'REQUIRE_ROW_FORMAT' => self::REQUIRE_ROW_FORMAT_SYMBOL,
|
|
'REQUIRE_TABLE_PRIMARY_KEY_CHECK' => self::REQUIRE_TABLE_PRIMARY_KEY_CHECK_SYMBOL,
|
|
'RESOURCE' => self::RESOURCE_SYMBOL,
|
|
'RESPECT' => self::RESPECT_SYMBOL,
|
|
'RESTART' => self::RESTART_SYMBOL,
|
|
'RETAIN' => self::RETAIN_SYMBOL,
|
|
'RETURNING' => self::RETURNING_SYMBOL,
|
|
'REUSE' => self::REUSE_SYMBOL,
|
|
'ROLE' => self::ROLE_SYMBOL,
|
|
'ROW_NUMBER' => self::ROW_NUMBER_SYMBOL,
|
|
'SECONDARY' => self::SECONDARY_SYMBOL,
|
|
'SECONDARY_ENGINE' => self::SECONDARY_ENGINE_SYMBOL,
|
|
'SECONDARY_ENGINE_ATTRIBUTE' => self::SECONDARY_ENGINE_ATTRIBUTE_SYMBOL,
|
|
'SECONDARY_LOAD' => self::SECONDARY_LOAD_SYMBOL,
|
|
'SECONDARY_UNLOAD' => self::SECONDARY_UNLOAD_SYMBOL,
|
|
'SKIP' => self::SKIP_SYMBOL,
|
|
'SOURCE_AUTO_POSITION' => self::SOURCE_AUTO_POSITION_SYMBOL,
|
|
'SOURCE_BIND' => self::SOURCE_BIND_SYMBOL,
|
|
'SOURCE_COMPRESSION_ALGORITHM' => self::SOURCE_COMPRESSION_ALGORITHM_SYMBOL,
|
|
'SOURCE_CONNECT_RETRY' => self::SOURCE_CONNECT_RETRY_SYMBOL,
|
|
'SOURCE_CONNECTION_AUTO_FAILOVER' => self::SOURCE_CONNECTION_AUTO_FAILOVER_SYMBOL,
|
|
'SOURCE_DELAY' => self::SOURCE_DELAY_SYMBOL,
|
|
'SOURCE_HEARTBEAT_PERIOD' => self::SOURCE_HEARTBEAT_PERIOD_SYMBOL,
|
|
'SOURCE_HOST' => self::SOURCE_HOST_SYMBOL,
|
|
'SOURCE_LOG_FILE' => self::SOURCE_LOG_FILE_SYMBOL,
|
|
'SOURCE_LOG_POS' => self::SOURCE_LOG_POS_SYMBOL,
|
|
'SOURCE_PASSWORD' => self::SOURCE_PASSWORD_SYMBOL,
|
|
'SOURCE_PORT' => self::SOURCE_PORT_SYMBOL,
|
|
'SOURCE_PUBLIC_KEY_PATH' => self::SOURCE_PUBLIC_KEY_PATH_SYMBOL,
|
|
'SOURCE_RETRY_COUNT' => self::SOURCE_RETRY_COUNT_SYMBOL,
|
|
'SOURCE_SSL' => self::SOURCE_SSL_SYMBOL,
|
|
'SOURCE_SSL_CA' => self::SOURCE_SSL_CA_SYMBOL,
|
|
'SOURCE_SSL_CAPATH' => self::SOURCE_SSL_CAPATH_SYMBOL,
|
|
'SOURCE_SSL_CERT' => self::SOURCE_SSL_CERT_SYMBOL,
|
|
'SOURCE_SSL_CIPHER' => self::SOURCE_SSL_CIPHER_SYMBOL,
|
|
'SOURCE_SSL_CRL' => self::SOURCE_SSL_CRL_SYMBOL,
|
|
'SOURCE_SSL_CRLPATH' => self::SOURCE_SSL_CRLPATH_SYMBOL,
|
|
'SOURCE_SSL_KEY' => self::SOURCE_SSL_KEY_SYMBOL,
|
|
'SOURCE_SSL_VERIFY_SERVER_CERT' => self::SOURCE_SSL_VERIFY_SERVER_CERT_SYMBOL,
|
|
'SOURCE_TLS_CIPHERSUITES' => self::SOURCE_TLS_CIPHERSUITES_SYMBOL,
|
|
'SOURCE_TLS_VERSION' => self::SOURCE_TLS_VERSION_SYMBOL,
|
|
'SOURCE_USER' => self::SOURCE_USER_SYMBOL,
|
|
'SOURCE_ZSTD_COMPRESSION_LEVEL' => self::SOURCE_ZSTD_COMPRESSION_LEVEL_SYMBOL,
|
|
'SRID' => self::SRID_SYMBOL,
|
|
'STREAM' => self::STREAM_SYMBOL,
|
|
'SYSTEM' => self::SYSTEM_SYMBOL,
|
|
'THREAD_PRIORITY' => self::THREAD_PRIORITY_SYMBOL,
|
|
'TIES' => self::TIES_SYMBOL,
|
|
'TLS' => self::TLS_SYMBOL,
|
|
'UNBOUNDED' => self::UNBOUNDED_SYMBOL,
|
|
'VCPU' => self::VCPU_SYMBOL,
|
|
'VISIBLE' => self::VISIBLE_SYMBOL,
|
|
'WINDOW' => self::WINDOW_SYMBOL,
|
|
'ZONE' => self::ZONE_SYMBOL,
|
|
);
|
|
|
|
/**
|
|
* Tokens that represent function calls when followed by a parenthesis.
|
|
*/
|
|
const FUNCTIONS = array(
|
|
self::ADDDATE_SYMBOL => true,
|
|
self::BIT_AND_SYMBOL => true,
|
|
self::BIT_OR_SYMBOL => true,
|
|
self::BIT_XOR_SYMBOL => true,
|
|
self::CAST_SYMBOL => true,
|
|
self::COUNT_SYMBOL => true,
|
|
self::CURDATE_SYMBOL => true,
|
|
self::CURRENT_DATE_SYMBOL => true,
|
|
self::CURRENT_TIME_SYMBOL => true,
|
|
self::CURTIME_SYMBOL => true,
|
|
self::DATE_ADD_SYMBOL => true,
|
|
self::DATE_SUB_SYMBOL => true,
|
|
self::EXTRACT_SYMBOL => true,
|
|
self::GROUP_CONCAT_SYMBOL => true,
|
|
self::MAX_SYMBOL => true,
|
|
self::MID_SYMBOL => true,
|
|
self::MIN_SYMBOL => true,
|
|
self::NOW_SYMBOL => true,
|
|
self::POSITION_SYMBOL => true,
|
|
self::SESSION_USER_SYMBOL => true,
|
|
self::STD_SYMBOL => true,
|
|
self::STDDEV_POP_SYMBOL => true,
|
|
self::STDDEV_SAMP_SYMBOL => true,
|
|
self::STDDEV_SYMBOL => true,
|
|
self::SUBDATE_SYMBOL => true,
|
|
self::SUBSTR_SYMBOL => true,
|
|
self::SUBSTRING_SYMBOL => true,
|
|
self::SUM_SYMBOL => true,
|
|
self::SYSDATE_SYMBOL => true,
|
|
self::SYSTEM_USER_SYMBOL => true,
|
|
self::TRIM_SYMBOL => true,
|
|
self::VAR_POP_SYMBOL => true,
|
|
self::VAR_SAMP_SYMBOL => true,
|
|
self::VARIANCE_SYMBOL => true,
|
|
);
|
|
|
|
/**
|
|
* Tokens that are functionally equivalent and can be used interchangeably.
|
|
*
|
|
* Some of the synonyms may have a different keyword or function status and
|
|
* version constraints, hence the synonym conversion needs to be applied
|
|
* at the end of the tokenization process, after all other transformations.
|
|
*
|
|
* E.g.: NOW is a non-reserved keyword that needs to be used with "()" while
|
|
* CURRENT_TIMESTAMP is a reserved keyword that can be used without "()".
|
|
*/
|
|
const SYNONYMS = array(
|
|
self::CHARACTER_SYMBOL => self::CHAR_SYMBOL,
|
|
self::CURRENT_DATE_SYMBOL => self::CURDATE_SYMBOL,
|
|
self::CURRENT_TIME_SYMBOL => self::CURTIME_SYMBOL,
|
|
self::CURRENT_TIMESTAMP_SYMBOL => self::NOW_SYMBOL,
|
|
self::DAYOFMONTH_SYMBOL => self::DAY_SYMBOL,
|
|
self::DEC_SYMBOL => self::DECIMAL_SYMBOL,
|
|
self::DISTINCTROW_SYMBOL => self::DISTINCT_SYMBOL,
|
|
self::FIELDS_SYMBOL => self::COLUMNS_SYMBOL,
|
|
self::FLOAT4_SYMBOL => self::FLOAT_SYMBOL,
|
|
self::FLOAT8_SYMBOL => self::DOUBLE_SYMBOL,
|
|
self::GEOMCOLLECTION_SYMBOL => self::GEOMETRYCOLLECTION_SYMBOL,
|
|
self::INT1_SYMBOL => self::TINYINT_SYMBOL,
|
|
self::INT2_SYMBOL => self::SMALLINT_SYMBOL,
|
|
self::INT3_SYMBOL => self::MEDIUMINT_SYMBOL,
|
|
self::INT4_SYMBOL => self::INT_SYMBOL,
|
|
self::INT8_SYMBOL => self::BIGINT_SYMBOL,
|
|
self::INTEGER_SYMBOL => self::INT_SYMBOL,
|
|
self::IO_THREAD_SYMBOL => self::RELAY_THREAD_SYMBOL,
|
|
self::LOCALTIME_SYMBOL => self::NOW_SYMBOL,
|
|
self::LOCALTIMESTAMP_SYMBOL => self::NOW_SYMBOL,
|
|
self::MID_SYMBOL => self::SUBSTRING_SYMBOL,
|
|
self::MIDDLEINT_SYMBOL => self::MEDIUMINT_SYMBOL,
|
|
self::NDB_SYMBOL => self::NDBCLUSTER_SYMBOL,
|
|
self::RLIKE_SYMBOL => self::REGEXP_SYMBOL,
|
|
self::SCHEMA_SYMBOL => self::DATABASE_SYMBOL,
|
|
self::SCHEMAS_SYMBOL => self::DATABASES_SYMBOL,
|
|
self::SESSION_USER_SYMBOL => self::USER_SYMBOL,
|
|
self::SOME_SYMBOL => self::ANY_SYMBOL,
|
|
self::SQL_TSI_DAY_SYMBOL => self::DAY_SYMBOL,
|
|
self::SQL_TSI_HOUR_SYMBOL => self::HOUR_SYMBOL,
|
|
self::SQL_TSI_MICROSECOND_SYMBOL => self::MICROSECOND_SYMBOL,
|
|
self::SQL_TSI_MINUTE_SYMBOL => self::MINUTE_SYMBOL,
|
|
self::SQL_TSI_MONTH_SYMBOL => self::MONTH_SYMBOL,
|
|
self::SQL_TSI_QUARTER_SYMBOL => self::QUARTER_SYMBOL,
|
|
self::SQL_TSI_SECOND_SYMBOL => self::SECOND_SYMBOL,
|
|
self::SQL_TSI_WEEK_SYMBOL => self::WEEK_SYMBOL,
|
|
self::SQL_TSI_YEAR_SYMBOL => self::YEAR_SYMBOL,
|
|
self::STDDEV_POP_SYMBOL => self::STD_SYMBOL,
|
|
self::STDDEV_SYMBOL => self::STD_SYMBOL,
|
|
self::SUBSTR_SYMBOL => self::SUBSTRING_SYMBOL,
|
|
self::SYSTEM_USER_SYMBOL => self::USER_SYMBOL,
|
|
self::VAR_POP_SYMBOL => self::VARIANCE_SYMBOL,
|
|
self::VARCHARACTER_SYMBOL => self::VARCHAR_SYMBOL,
|
|
);
|
|
|
|
/**
|
|
* Version constraints for version-specific tokens.
|
|
*
|
|
* This is a map of tokens to the MySQL server versions in which they were
|
|
* introduced (positive number) or removed (negative number). Tokens that
|
|
* were both introduced and later removed are not included in this list
|
|
* and are handled by manual version checks in the tokenization process.
|
|
*
|
|
* See:
|
|
* https://dev.mysql.com/doc/mysqld-version-reference/en/keywords.html
|
|
*
|
|
* @TODO Verify the version specifiers and ranges against the list above.
|
|
*
|
|
* Positive number: >= <version> (introduced in <version>)
|
|
* Negative number: < <version> (removed in <version>)
|
|
*/
|
|
const VERSIONS = array(
|
|
// MySQL 5
|
|
self::ACCOUNT_SYMBOL => 50707,
|
|
self::ALWAYS_SYMBOL => 50707,
|
|
self::ANALYSE_SYMBOL => -80000,
|
|
self::AUTHORS_SYMBOL => -50700,
|
|
self::CHANNEL_SYMBOL => 50706,
|
|
self::COMPRESSION_SYMBOL => 50707,
|
|
self::CONTRIBUTORS_SYMBOL => -50700,
|
|
self::CURRENT_SYMBOL => 50604,
|
|
self::DEFAULT_AUTH_SYMBOL => 50604,
|
|
self::DES_KEY_FILE_SYMBOL => -80003,
|
|
self::ENCRYPTION_SYMBOL => 50711,
|
|
self::EXPIRE_SYMBOL => 50606,
|
|
self::EXPORT_SYMBOL => 50606,
|
|
self::FILE_BLOCK_SIZE_SYMBOL => 50707,
|
|
self::FILTER_SYMBOL => 50700,
|
|
self::FOLLOWS_SYMBOL => 50700,
|
|
self::GENERATED_SYMBOL => 50707,
|
|
self::GET_SYMBOL => 50604,
|
|
self::GROUP_REPLICATION_SYMBOL => 50707,
|
|
self::INNODB_SYMBOL => 50711,
|
|
self::INSTANCE_SYMBOL => 50713,
|
|
self::JSON_SYMBOL => 50708,
|
|
self::MASTER_AUTO_POSITION_SYMBOL => 50605,
|
|
self::MASTER_BIND_SYMBOL => 50602,
|
|
self::MASTER_RETRY_COUNT_SYMBOL => 50601,
|
|
self::MASTER_SSL_CRL_SYMBOL => 50603,
|
|
self::MASTER_SSL_CRLPATH_SYMBOL => 50603,
|
|
self::MASTER_TLS_VERSION_SYMBOL => 50713,
|
|
self::NEVER_SYMBOL => 50704,
|
|
self::NUMBER_SYMBOL => 50606,
|
|
self::OLD_PASSWORD_SYMBOL => -50706,
|
|
self::ONLY_SYMBOL => 50605,
|
|
self::OPTIMIZER_COSTS_SYMBOL => 50706,
|
|
self::PLUGIN_DIR_SYMBOL => 50604,
|
|
self::PRECEDES_SYMBOL => 50700,
|
|
self::REDOFILE_SYMBOL => -80000,
|
|
self::REPLICATE_DO_DB_SYMBOL => 50700,
|
|
self::REPLICATE_DO_TABLE_SYMBOL => 50700,
|
|
self::REPLICATE_IGNORE_DB_SYMBOL => 50700,
|
|
self::REPLICATE_IGNORE_TABLE_SYMBOL => 50700,
|
|
self::REPLICATE_REWRITE_DB_SYMBOL => 50700,
|
|
self::REPLICATE_WILD_DO_TABLE_SYMBOL => 50700,
|
|
self::REPLICATE_WILD_IGNORE_TABLE_SYMBOL => 50700,
|
|
self::ROTATE_SYMBOL => 50713,
|
|
self::SQL_AFTER_MTS_GAPS_SYMBOL => 50606,
|
|
self::SQL_CACHE_SYMBOL => -80000,
|
|
self::STACKED_SYMBOL => 50700,
|
|
self::STORED_SYMBOL => 50707,
|
|
self::TABLE_REF_PRIORITY_SYMBOL => -80000,
|
|
self::VALIDATION_SYMBOL => 50706,
|
|
self::VIRTUAL_SYMBOL => 50707,
|
|
self::XID_SYMBOL => 50704,
|
|
|
|
// MySQL 8
|
|
self::ACTIVE_SYMBOL => 80014,
|
|
self::ADMIN_SYMBOL => 80000,
|
|
self::ARRAY_SYMBOL => 80017,
|
|
self::ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS_SYMBOL => 80000,
|
|
self::ATTRIBUTE_SYMBOL => 80021,
|
|
self::BUCKETS_SYMBOL => 80000,
|
|
self::CLONE_SYMBOL => 80000,
|
|
self::COMPONENT_SYMBOL => 80000,
|
|
self::CUME_DIST_SYMBOL => 80000,
|
|
self::DEFINITION_SYMBOL => 80011,
|
|
self::DENSE_RANK_SYMBOL => 80000,
|
|
self::DESCRIPTION_SYMBOL => 80011,
|
|
self::EMPTY_SYMBOL => 80000,
|
|
self::ENFORCED_SYMBOL => 80017,
|
|
self::ENGINE_ATTRIBUTE_SYMBOL => 80021,
|
|
self::EXCEPT_SYMBOL => 80000,
|
|
self::EXCLUDE_SYMBOL => 80000,
|
|
self::FAILED_LOGIN_ATTEMPTS_SYMBOL => 80019,
|
|
self::FIRST_VALUE_SYMBOL => 80000,
|
|
self::FOLLOWING_SYMBOL => 80000,
|
|
self::GEOMCOLLECTION_SYMBOL => 80000,
|
|
self::GET_MASTER_PUBLIC_KEY_SYMBOL => 80000,
|
|
self::GET_SOURCE_PUBLIC_KEY_SYMBOL => 80000,
|
|
self::GROUPING_SYMBOL => 80000,
|
|
self::GROUPS_SYMBOL => 80000,
|
|
self::GTID_ONLY_SYMBOL => 80000,
|
|
self::HISTOGRAM_SYMBOL => 80000,
|
|
self::HISTORY_SYMBOL => 80000,
|
|
self::INACTIVE_SYMBOL => 80014,
|
|
self::INTERSECT_SYMBOL => 80031,
|
|
self::INVISIBLE_SYMBOL => 80000,
|
|
self::JSON_ARRAYAGG_SYMBOL => 80000,
|
|
self::JSON_OBJECTAGG_SYMBOL => 80000,
|
|
self::JSON_TABLE_SYMBOL => 80000,
|
|
self::JSON_VALUE_SYMBOL => 80021,
|
|
self::KEYRING_SYMBOL => 80024,
|
|
self::LAG_SYMBOL => 80000,
|
|
self::LAST_VALUE_SYMBOL => 80000,
|
|
self::LATERAL_SYMBOL => 80014,
|
|
self::LEAD_SYMBOL => 80000,
|
|
self::LOCKED_SYMBOL => 80000,
|
|
self::MASTER_COMPRESSION_ALGORITHM_SYMBOL => 80018,
|
|
self::MASTER_PUBLIC_KEY_PATH_SYMBOL => 80000,
|
|
self::MASTER_TLS_CIPHERSUITES_SYMBOL => 80018,
|
|
self::MASTER_ZSTD_COMPRESSION_LEVEL_SYMBOL => 80018,
|
|
self::MEMBER_SYMBOL => 80017,
|
|
self::NESTED_SYMBOL => 80000,
|
|
self::NETWORK_NAMESPACE_SYMBOL => 80017,
|
|
self::NOWAIT_SYMBOL => 80000,
|
|
self::NTH_VALUE_SYMBOL => 80000,
|
|
self::NTILE_SYMBOL => 80000,
|
|
self::NULLS_SYMBOL => 80000,
|
|
self::OF_SYMBOL => 80000,
|
|
self::OFF_SYMBOL => 80019,
|
|
self::OJ_SYMBOL => 80017,
|
|
self::OLD_SYMBOL => 80014,
|
|
self::OPTIONAL_SYMBOL => 80013,
|
|
self::ORDINALITY_SYMBOL => 80000,
|
|
self::ORGANIZATION_SYMBOL => 80011,
|
|
self::OTHERS_SYMBOL => 80000,
|
|
self::OVER_SYMBOL => 80000,
|
|
self::PASSWORD_LOCK_TIME_SYMBOL => 80019,
|
|
self::PATH_SYMBOL => 80000,
|
|
self::PERCENT_RANK_SYMBOL => 80000,
|
|
self::PERSIST_ONLY_SYMBOL => 80000,
|
|
self::PERSIST_SYMBOL => 80000,
|
|
self::PRECEDING_SYMBOL => 80000,
|
|
self::PRIVILEGE_CHECKS_USER_SYMBOL => 80018,
|
|
self::RANDOM_SYMBOL => 80018,
|
|
self::RANK_SYMBOL => 80000,
|
|
self::RECURSIVE_SYMBOL => 80000,
|
|
self::REDO_LOG_SYMBOL => 80021,
|
|
self::REFERENCE_SYMBOL => 80011,
|
|
self::REQUIRE_ROW_FORMAT_SYMBOL => 80019,
|
|
self::REQUIRE_TABLE_PRIMARY_KEY_CHECK_SYMBOL => 80019,
|
|
self::RESOURCE_SYMBOL => 80000,
|
|
self::RESPECT_SYMBOL => 80000,
|
|
self::RESTART_SYMBOL => 80011,
|
|
self::RETAIN_SYMBOL => 80014,
|
|
self::REUSE_SYMBOL => 80000,
|
|
self::RETURNING_SYMBOL => 80021,
|
|
self::ROLE_SYMBOL => 80000,
|
|
self::ROW_NUMBER_SYMBOL => 80000,
|
|
self::SECONDARY_ENGINE_ATTRIBUTE_SYMBOL => 80021,
|
|
self::SECONDARY_ENGINE_SYMBOL => 80013,
|
|
self::SECONDARY_LOAD_SYMBOL => 80013,
|
|
self::SECONDARY_SYMBOL => 80013,
|
|
self::SECONDARY_UNLOAD_SYMBOL => 80013,
|
|
self::SKIP_SYMBOL => 80000,
|
|
self::SOURCE_AUTO_POSITION_SYMBOL => 80000,
|
|
self::SOURCE_BIND_SYMBOL => 80000,
|
|
self::SOURCE_COMPRESSION_ALGORITHM_SYMBOL => 80000,
|
|
self::SOURCE_CONNECT_RETRY_SYMBOL => 80000,
|
|
self::SOURCE_CONNECTION_AUTO_FAILOVER_SYMBOL => 80000,
|
|
self::SOURCE_DELAY_SYMBOL => 80000,
|
|
self::SOURCE_HEARTBEAT_PERIOD_SYMBOL => 80000,
|
|
self::SOURCE_HOST_SYMBOL => 80000,
|
|
self::SOURCE_LOG_FILE_SYMBOL => 80000,
|
|
self::SOURCE_LOG_POS_SYMBOL => 80000,
|
|
self::SOURCE_PASSWORD_SYMBOL => 80000,
|
|
self::SOURCE_PORT_SYMBOL => 80000,
|
|
self::SOURCE_PUBLIC_KEY_PATH_SYMBOL => 80000,
|
|
self::SOURCE_RETRY_COUNT_SYMBOL => 80000,
|
|
self::SOURCE_SSL_CA_SYMBOL => 80000,
|
|
self::SOURCE_SSL_CAPATH_SYMBOL => 80000,
|
|
self::SOURCE_SSL_CERT_SYMBOL => 80000,
|
|
self::SOURCE_SSL_CIPHER_SYMBOL => 80000,
|
|
self::SOURCE_SSL_CRL_SYMBOL => 80000,
|
|
self::SOURCE_SSL_CRLPATH_SYMBOL => 80000,
|
|
self::SOURCE_SSL_KEY_SYMBOL => 80000,
|
|
self::SOURCE_SSL_SYMBOL => 80000,
|
|
self::SOURCE_SSL_VERIFY_SERVER_CERT_SYMBOL => 80000,
|
|
self::SOURCE_TLS_CIPHERSUITES_SYMBOL => 80000,
|
|
self::SOURCE_TLS_VERSION_SYMBOL => 80000,
|
|
self::SOURCE_USER_SYMBOL => 80000,
|
|
self::SOURCE_ZSTD_COMPRESSION_LEVEL_SYMBOL => 80000,
|
|
self::SRID_SYMBOL => 80000,
|
|
self::STREAM_SYMBOL => 80019,
|
|
self::SYSTEM_SYMBOL => 80000,
|
|
self::THREAD_PRIORITY_SYMBOL => 80000,
|
|
self::TIES_SYMBOL => 80000,
|
|
self::TLS_SYMBOL => 80016,
|
|
self::UNBOUNDED_SYMBOL => 80000,
|
|
self::VCPU_SYMBOL => 80000,
|
|
self::VISIBLE_SYMBOL => 80000,
|
|
self::WINDOW_SYMBOL => 80000,
|
|
self::ZONE_SYMBOL => 80022,
|
|
);
|
|
|
|
/**
|
|
* Identifier-like strings that may represent underscore-prefixed charset names.
|
|
*
|
|
* Includes charsets from both MySQL 5 and 8; via "SHOW CHARACTER SET"/docs:
|
|
* https://dev.mysql.com/doc/refman/5.7/en/charset-charsets.html
|
|
* https://dev.mysql.com/doc/refman/8.4/en/charset-charsets.html
|
|
*
|
|
* @TODO: Make the list respect the MySQL version. The _utf8 underscore charset
|
|
* exists only on MySQL 5, and maybe some others are version-dependant too.
|
|
* We can check this using SHOW CHARACTER SET on different MySQL versions.
|
|
*/
|
|
const UNDERSCORE_CHARSETS = array(
|
|
'_armscii8' => true,
|
|
'_ascii' => true,
|
|
'_big5' => true,
|
|
'_binary' => true,
|
|
'_cp1250' => true,
|
|
'_cp1251' => true,
|
|
'_cp1256' => true,
|
|
'_cp1257' => true,
|
|
'_cp850' => true,
|
|
'_cp852' => true,
|
|
'_cp866' => true,
|
|
'_cp932' => true,
|
|
'_dec8' => true,
|
|
'_eucjpms' => true,
|
|
'_euckr' => true,
|
|
'_gb18030' => true,
|
|
'_gb2312' => true,
|
|
'_gbk' => true,
|
|
'_geostd8' => true,
|
|
'_greek' => true,
|
|
'_hebrew' => true,
|
|
'_hp8' => true,
|
|
'_keybcs2' => true,
|
|
'_koi8r' => true,
|
|
'_koi8u' => true,
|
|
'_latin1' => true,
|
|
'_latin2' => true,
|
|
'_latin5' => true,
|
|
'_latin7' => true,
|
|
'_macce' => true,
|
|
'_macroman' => true,
|
|
'_sjis' => true,
|
|
'_swe7' => true,
|
|
'_tis620' => true,
|
|
'_ucs2' => true,
|
|
'_ujis' => true,
|
|
'_utf16' => true,
|
|
'_utf16le' => true,
|
|
'_utf32' => true,
|
|
'_utf8' => true,
|
|
'_utf8mb3' => true,
|
|
'_utf8mb4' => true,
|
|
);
|
|
|
|
/**
|
|
* The SQL payload to tokenize.
|
|
*
|
|
* @var string
|
|
*/
|
|
private $sql;
|
|
|
|
/**
|
|
* Byte length of the SQL payload.
|
|
*
|
|
* @var int
|
|
*/
|
|
private $sql_length;
|
|
|
|
/**
|
|
* The version of the MySQL server that the SQL payload is intended for.
|
|
*
|
|
* This is used to determine which tokens are valid for the given MySQL
|
|
* version, and how some tokens should be interpreted.
|
|
*
|
|
* @var int
|
|
*/
|
|
private $mysql_version;
|
|
|
|
/**
|
|
* The SQL modes that should be considered active during tokenization.
|
|
*
|
|
* This is an integer that represents currently active SQL modes as a bitmask.
|
|
* The SQL modes are defined as "SQL_MODE_"-prefixed constants in this class.
|
|
* The list of the SQL modes isn't exhaustive, as only some affect tokenization.
|
|
*
|
|
* @var int
|
|
*/
|
|
private $sql_modes = 0;
|
|
|
|
/**
|
|
* How many bytes from the original SQL payload have been read and tokenized.
|
|
*
|
|
* This is an internal cursor that is used to track the current position in
|
|
* the SQL payload during tokenization. When used as an index in the SQL
|
|
* payload, it points to the next byte to read.
|
|
*
|
|
* @var int
|
|
*/
|
|
private $bytes_already_read = 0;
|
|
|
|
/**
|
|
* Byte offset in the SQL payload where current token starts.
|
|
*
|
|
* This is used to extract the token bytes after the token is processed.
|
|
* The bytes of the current token are represented by "$this->sql" in range
|
|
* from "$this->token_starts_at" to "$this->bytes_already_read - 1".
|
|
*
|
|
* @var int
|
|
*/
|
|
private $token_starts_at = 0;
|
|
|
|
/**
|
|
* The type of the current token.
|
|
*
|
|
* When a token is successfully recognized and read, this value is set to the
|
|
* constant representing the token type. When no token was read yet, or the
|
|
* end of the SQL payload or an invalid token is reached, this value is null.
|
|
*
|
|
* @var int|null
|
|
*/
|
|
private $token_type;
|
|
|
|
/**
|
|
* Whether the tokenizer is inside an active MySQL-specific comment.
|
|
*
|
|
* MySQL supports a special comment syntax whose content is recognized as
|
|
* a comment by most database engines, but can be treated as SQL by MySQL:
|
|
*
|
|
* 1. /*! ... - The content is treated as SQL.
|
|
* 2. /*!12345 - The content is treated as SQL when "MySQL version >= 12345".
|
|
*
|
|
* @var bool
|
|
*/
|
|
private $in_mysql_comment = false;
|
|
|
|
/**
|
|
* @param string $sql The SQL payload to tokenize.
|
|
* @param int $mysql_version The version of the MySQL server that the SQL payload is intended for.
|
|
* @param string[] $sql_modes The SQL modes that should be considered active during tokenization.
|
|
*/
|
|
public function __construct(
|
|
string $sql,
|
|
int $mysql_version = 80038,
|
|
array $sql_modes = array()
|
|
) {
|
|
$this->sql = $sql;
|
|
$this->sql_length = strlen( $sql );
|
|
$this->mysql_version = $mysql_version;
|
|
|
|
foreach ( $sql_modes as $sql_mode ) {
|
|
$sql_mode = strtoupper( $sql_mode );
|
|
if ( 'HIGH_NOT_PRECEDENCE' === $sql_mode ) {
|
|
$this->sql_modes |= self::SQL_MODE_HIGH_NOT_PRECEDENCE;
|
|
} elseif ( 'PIPES_AS_CONCAT' === $sql_mode ) {
|
|
$this->sql_modes |= self::SQL_MODE_PIPES_AS_CONCAT;
|
|
} elseif ( 'IGNORE_SPACE' === $sql_mode ) {
|
|
$this->sql_modes |= self::SQL_MODE_IGNORE_SPACE;
|
|
} elseif ( 'NO_BACKSLASH_ESCAPES' === $sql_mode ) {
|
|
$this->sql_modes |= self::SQL_MODE_NO_BACKSLASH_ESCAPES;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Read the next token from the SQL payload and return it as a token object.
|
|
*
|
|
* This method reads bytes from the SQL payload until a token is recognized.
|
|
* It starts from "$this->sql[ $this->bytes_already_read ]", advances the
|
|
* number of bytes read, and returns a boolean indicating whether a token
|
|
* was successfully recognized and read. When the end of the SQL payload
|
|
* or an invalid token is reached, the method returns false.
|
|
*
|
|
* @return bool Whether a token was successfully recognized and read.
|
|
*/
|
|
public function next_token(): bool {
|
|
// We already reached the end of the SQL payload or an invalid token.
|
|
// Don't attempt to read any more bytes, and bail out immediately.
|
|
if (
|
|
self::EOF === $this->token_type
|
|
|| ( null === $this->token_type && $this->bytes_already_read > 0 )
|
|
) {
|
|
$this->token_type = null;
|
|
return false;
|
|
}
|
|
|
|
// Skip leading whitespace inline for optimal performance.
|
|
$this->bytes_already_read += strspn( $this->sql, self::WHITESPACE_MASK, $this->bytes_already_read );
|
|
|
|
do {
|
|
$this->token_starts_at = $this->bytes_already_read;
|
|
$this->token_type = $this->read_next_token();
|
|
} while (
|
|
self::WHITESPACE === $this->token_type
|
|
|| self::COMMENT === $this->token_type
|
|
|| self::MYSQL_COMMENT_START === $this->token_type
|
|
|| self::MYSQL_COMMENT_END === $this->token_type
|
|
);
|
|
|
|
// Invalid input.
|
|
if ( null === $this->token_type ) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Return the current token represented as a WP_MySQL_Token object.
|
|
*
|
|
* When no token was read yet, or the end of the SQL payload or an invalid
|
|
* token is reached, the method returns null.
|
|
*
|
|
* @TODO: Consider referential stability ($lexer->get_token() === $lexer->get_token()),
|
|
* or separate getters for the token type and token bytes (no token objects).
|
|
*
|
|
* @return WP_MySQL_Token|null An object representing the next recognized token or null.
|
|
*/
|
|
public function get_token(): ?WP_MySQL_Token {
|
|
if ( null === $this->token_type ) {
|
|
return null;
|
|
}
|
|
return new WP_MySQL_Token(
|
|
$this->token_type,
|
|
$this->token_starts_at,
|
|
$this->bytes_already_read - $this->token_starts_at,
|
|
$this->sql,
|
|
$this->is_sql_mode_active( self::SQL_MODE_NO_BACKSLASH_ESCAPES )
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Read all remaining tokens from the SQL payload and return them as an array.
|
|
*
|
|
* This method starts from the current position in the SQL payload, as marked
|
|
* by "$this->sql[ $this->bytes_already_read ]", and reads all tokens until
|
|
* the end of the SQL payload is reached, returning an array of token objects.
|
|
*
|
|
* When an invalid token is reached, the method stops and returns the partial
|
|
* sequence of valid tokens. In this case, the EOF token will not be included.
|
|
*
|
|
* This method can be used to tokenize the whole SQL payload at once, at the
|
|
* expense of storing all token objects in memory at the same time.
|
|
*
|
|
* @return WP_MySQL_Token[] An array of token objects representing the remaining tokens.
|
|
*/
|
|
public function remaining_tokens(): array {
|
|
$tokens = array();
|
|
$no_backslash_escapes_sql_mode_set = $this->is_sql_mode_active(
|
|
self::SQL_MODE_NO_BACKSLASH_ESCAPES
|
|
);
|
|
|
|
while ( true ) {
|
|
// Bail on EOF, or on a null token type once at least one byte has
|
|
// been consumed (read_next_token() hit invalid input mid-stream).
|
|
if (
|
|
self::EOF === $this->token_type
|
|
|| ( null === $this->token_type && $this->bytes_already_read > 0 )
|
|
) {
|
|
$this->token_type = null;
|
|
break;
|
|
}
|
|
|
|
// Skip leading whitespace inline for optimal performance.
|
|
$this->bytes_already_read += strspn( $this->sql, self::WHITESPACE_MASK, $this->bytes_already_read );
|
|
|
|
do {
|
|
$this->token_starts_at = $this->bytes_already_read;
|
|
$this->token_type = $this->read_next_token();
|
|
} while (
|
|
self::WHITESPACE === $this->token_type
|
|
|| self::COMMENT === $this->token_type
|
|
|| self::MYSQL_COMMENT_START === $this->token_type
|
|
|| self::MYSQL_COMMENT_END === $this->token_type
|
|
);
|
|
|
|
if ( null === $this->token_type ) {
|
|
break;
|
|
}
|
|
|
|
$tokens[] = new WP_MySQL_Token(
|
|
$this->token_type,
|
|
$this->token_starts_at,
|
|
$this->bytes_already_read - $this->token_starts_at,
|
|
$this->sql,
|
|
$no_backslash_escapes_sql_mode_set
|
|
);
|
|
|
|
if ( self::EOF === $this->token_type ) {
|
|
$this->token_type = null;
|
|
break;
|
|
}
|
|
}
|
|
return $tokens;
|
|
}
|
|
|
|
/**
|
|
* The version of the MySQL server that the SQL payload is intended for.
|
|
*
|
|
* This represents the MySQL server version that the lexer is set up to
|
|
* consider when tokenizing the SQL payload.
|
|
*
|
|
* @return int The MySQL server version that the lexer is set up to consider.
|
|
*/
|
|
public function get_mysql_version(): int {
|
|
return $this->mysql_version;
|
|
}
|
|
|
|
/**
|
|
* Whether an SQL mode is set to be considered as active during tokenization.
|
|
* The SQL modes are defined as "SQL_MODE_"-prefixed constants in this class.
|
|
*
|
|
* @param int $mode The SQL mode to check, an "SQL_MODE_"-prefixed constant.
|
|
* @return bool Whether the given SQL mode is active.
|
|
*/
|
|
public function is_sql_mode_active( int $mode ): bool {
|
|
return ( $this->sql_modes & $mode ) !== 0;
|
|
}
|
|
|
|
/**
|
|
* Get the numeric token ID for a given token name.
|
|
*
|
|
* @param string $token_name The name of the token.
|
|
* @return int|null The token ID for the given token name; null when not found.
|
|
*/
|
|
public static function get_token_id( string $token_name ): ?int {
|
|
$constant_name = self::class . '::' . $token_name;
|
|
if ( ! defined( $constant_name ) ) {
|
|
return null;
|
|
}
|
|
return constant( $constant_name );
|
|
}
|
|
|
|
/**
|
|
* Get the name of a token for a given token ID.
|
|
*
|
|
* This method is intended to be used only for testing and debugging purposes,
|
|
* when tokens need to be presented by their names in a human-readable form.
|
|
* It should not be used in production code, as it's not performance-optimized.
|
|
*
|
|
* @param int $token_id The numeric token ID.
|
|
* @return string The token name for the given token ID; null when not found.
|
|
*/
|
|
public static function get_token_name( int $token_id ): ?string {
|
|
$reflection = new ReflectionClass( self::class );
|
|
// Reverse the array, as some constant values in the class can conflict,
|
|
// and tokens are defined at the end of the class constant definitions.
|
|
// @TODO: Consider are more robust way to determine the token name.
|
|
// E.g., prefix all token constant names with a common prefix.
|
|
$constants = array_reverse( $reflection->getConstants() );
|
|
$token_name = array_search( $token_id, $constants, true );
|
|
return $token_name ? $token_name : null;
|
|
}
|
|
|
|
private function read_next_token(): ?int {
|
|
$byte = $this->sql[ $this->bytes_already_read ] ?? null;
|
|
$next_byte = $this->sql[ $this->bytes_already_read + 1 ] ?? null;
|
|
|
|
// A map for a single-byte symbol fast path.
|
|
static $single_byte_ops = array(
|
|
'(' => self::OPEN_PAR_SYMBOL,
|
|
')' => self::CLOSE_PAR_SYMBOL,
|
|
',' => self::COMMA_SYMBOL,
|
|
';' => self::SEMICOLON_SYMBOL,
|
|
'+' => self::PLUS_OPERATOR,
|
|
'~' => self::BITWISE_NOT_OPERATOR,
|
|
'%' => self::MOD_OPERATOR,
|
|
'^' => self::BITWISE_XOR_OPERATOR,
|
|
'?' => self::PARAM_MARKER,
|
|
'{' => self::OPEN_CURLY_SYMBOL,
|
|
'}' => self::CLOSE_CURLY_SYMBOL,
|
|
'=' => self::EQUAL_OPERATOR,
|
|
);
|
|
|
|
// Fast path for keywords and identifiers.
|
|
// `$byte > "\x7F"` catches any non-ASCII byte (0x80-0xFF); read_identifier()
|
|
// restricts the accepted identifier codepoints to U+0080-U+FFFF.
|
|
// `"'" !== $next_byte` defers x'..', n'..' and similar special
|
|
// literals to their dedicated branches below; only single quotes
|
|
// form those, regardless of SQL mode.
|
|
if (
|
|
(
|
|
( $byte >= 'a' && $byte <= 'z' )
|
|
|| ( $byte >= 'A' && $byte <= 'Z' )
|
|
|| $byte > "\x7F"
|
|
)
|
|
&& "'" !== $next_byte
|
|
) {
|
|
$started_at = $this->bytes_already_read;
|
|
$type = $this->read_identifier();
|
|
if (
|
|
self::IDENTIFIER === $type
|
|
// When preceded by a dot, it is always an identifier.
|
|
&& ! ( $started_at > 0 && '.' === $this->sql[ $started_at - 1 ] )
|
|
) {
|
|
// Inline the keyword lookup on the hot identifier path: most
|
|
// identifiers are not keywords, so this avoids two method calls
|
|
// (token-bytes extraction + keyword determination) per token.
|
|
$keyword = self::TOKENS[ strtoupper(
|
|
substr( $this->sql, $started_at, $this->bytes_already_read - $started_at )
|
|
) ] ?? self::IDENTIFIER;
|
|
if ( self::IDENTIFIER !== $keyword ) {
|
|
$type = $this->resolve_keyword_type( $keyword );
|
|
}
|
|
}
|
|
} elseif ( null !== $byte && isset( $single_byte_ops[ $byte ] ) ) {
|
|
// Fast path for single-byte symbols.
|
|
$this->bytes_already_read += 1;
|
|
$type = $single_byte_ops[ $byte ];
|
|
} elseif ( "'" === $byte || '"' === $byte || '`' === $byte ) {
|
|
$type = $this->read_quoted_text();
|
|
} elseif ( null !== $byte && strspn( $byte, self::DIGIT_MASK ) > 0 ) {
|
|
$type = $this->read_number();
|
|
} elseif ( '.' === $byte ) {
|
|
if ( null !== $next_byte && strspn( $next_byte, self::DIGIT_MASK ) > 0 ) {
|
|
$type = $this->read_number();
|
|
} else {
|
|
$this->bytes_already_read += 1;
|
|
$type = self::DOT_SYMBOL;
|
|
}
|
|
} elseif ( ':' === $byte ) {
|
|
$this->bytes_already_read += 1; // Consume the ':'.
|
|
if ( '=' === $next_byte ) {
|
|
$this->bytes_already_read += 1; // Consume the '='.
|
|
$type = self::ASSIGN_OPERATOR;
|
|
} else {
|
|
$type = self::COLON_SYMBOL;
|
|
}
|
|
} elseif ( '<' === $byte ) {
|
|
$this->bytes_already_read += 1; // Consume the '<'.
|
|
if ( '=' === $next_byte ) {
|
|
$this->bytes_already_read += 1; // Consume the '='.
|
|
if ( '>' === ( $this->sql[ $this->bytes_already_read ] ?? null ) ) {
|
|
$this->bytes_already_read += 1; // Consume the '>'.
|
|
$type = self::NULL_SAFE_EQUAL_OPERATOR;
|
|
} else {
|
|
$type = self::LESS_OR_EQUAL_OPERATOR;
|
|
}
|
|
} elseif ( '>' === $next_byte ) {
|
|
$this->bytes_already_read += 1; // Consume the '>'.
|
|
$type = self::NOT_EQUAL_OPERATOR;
|
|
} elseif ( '<' === $next_byte ) {
|
|
$this->bytes_already_read += 1; // Consume the '<'.
|
|
$type = self::SHIFT_LEFT_OPERATOR;
|
|
} else {
|
|
$type = self::LESS_THAN_OPERATOR;
|
|
}
|
|
} elseif ( '>' === $byte ) {
|
|
$this->bytes_already_read += 1; // Consume the '>'.
|
|
if ( '=' === $next_byte ) {
|
|
$this->bytes_already_read += 1; // Consume the '='.
|
|
$type = self::GREATER_OR_EQUAL_OPERATOR;
|
|
} elseif ( '>' === $next_byte ) {
|
|
$this->bytes_already_read += 1; // Consume the '>'.
|
|
$type = self::SHIFT_RIGHT_OPERATOR;
|
|
} else {
|
|
$type = self::GREATER_THAN_OPERATOR;
|
|
}
|
|
} elseif ( '!' === $byte ) {
|
|
$this->bytes_already_read += 1; // Consume the '!'.
|
|
if ( '=' === $next_byte ) {
|
|
$this->bytes_already_read += 1; // Consume the '='.
|
|
$type = self::NOT_EQUAL_OPERATOR;
|
|
} else {
|
|
$type = self::LOGICAL_NOT_OPERATOR;
|
|
}
|
|
} elseif ( '-' === $byte ) {
|
|
if (
|
|
'-' === $next_byte
|
|
&& $this->bytes_already_read + 2 < $this->sql_length
|
|
&& strspn( $this->sql[ $this->bytes_already_read + 2 ], self::WHITESPACE_MASK ) > 0
|
|
) {
|
|
$type = $this->read_line_comment();
|
|
} elseif ( '>' === $next_byte ) {
|
|
$this->bytes_already_read += 2; // Consume the '->'.
|
|
if ( '>' === ( $this->sql[ $this->bytes_already_read ] ?? null ) ) {
|
|
$this->bytes_already_read += 1; // Consume the '>'.
|
|
if ( $this->mysql_version >= 50713 ) {
|
|
$type = self::JSON_UNQUOTED_SEPARATOR_SYMBOL;
|
|
} else {
|
|
return null; // Invalid input.
|
|
}
|
|
} else {
|
|
if ( $this->mysql_version >= 50708 ) {
|
|
$type = self::JSON_SEPARATOR_SYMBOL;
|
|
} else {
|
|
return null; // Invalid input.
|
|
}
|
|
}
|
|
} else {
|
|
$this->bytes_already_read += 1; // Consume the '-'.
|
|
$type = self::MINUS_OPERATOR;
|
|
}
|
|
} elseif ( '*' === $byte ) {
|
|
$this->bytes_already_read += 1;
|
|
if ( '/' === $next_byte && $this->in_mysql_comment ) {
|
|
$this->bytes_already_read += 1; // Consume the '/'.
|
|
$type = self::MYSQL_COMMENT_END;
|
|
$this->in_mysql_comment = false;
|
|
} else {
|
|
$type = self::MULT_OPERATOR;
|
|
}
|
|
} elseif ( '/' === $byte ) {
|
|
if ( '*' === $next_byte ) {
|
|
if ( '!' === ( $this->sql[ $this->bytes_already_read + 2 ] ?? null ) ) {
|
|
$type = $this->read_mysql_comment();
|
|
} else {
|
|
$this->bytes_already_read += 2; // Consume the '/*'.
|
|
$this->read_comment_content();
|
|
$type = self::COMMENT;
|
|
}
|
|
} else {
|
|
$this->bytes_already_read += 1;
|
|
$type = self::DIV_OPERATOR;
|
|
}
|
|
} elseif ( '&' === $byte ) {
|
|
$this->bytes_already_read += 1; // Consume the '&'.
|
|
if ( '&' === $next_byte ) {
|
|
$this->bytes_already_read += 1; // Consume the '&'.
|
|
$type = self::LOGICAL_AND_OPERATOR;
|
|
} else {
|
|
$type = self::BITWISE_AND_OPERATOR;
|
|
}
|
|
} elseif ( '|' === $byte ) {
|
|
$this->bytes_already_read += 1; // Consume the '|'.
|
|
if ( '|' === $next_byte ) {
|
|
$this->bytes_already_read += 1; // Consume the '|'.
|
|
$type = $this->is_sql_mode_active( self::SQL_MODE_PIPES_AS_CONCAT )
|
|
? self::CONCAT_PIPES_SYMBOL
|
|
: self::LOGICAL_OR_OPERATOR;
|
|
} else {
|
|
$type = self::BITWISE_OR_OPERATOR;
|
|
}
|
|
} elseif ( '@' === $byte ) {
|
|
$this->bytes_already_read += 1; // Consume the '@'.
|
|
|
|
if ( '@' === $next_byte ) {
|
|
$this->bytes_already_read += 1; // Consume the second '@'.
|
|
$type = self::AT_AT_SIGN_SYMBOL;
|
|
} else {
|
|
/**
|
|
* Check whether the '@' marks an unquoted user-defined variable:
|
|
* https://dev.mysql.com/doc/refman/8.4/en/user-variables.html
|
|
*
|
|
* Rules:
|
|
* 1. Starts with a '@'.
|
|
* 2. Allowed following characters are ASCII a-z, A-Z, 0-9, _, ., $.
|
|
*/
|
|
$length = strspn( $this->sql, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.$', $this->bytes_already_read );
|
|
if ( $length > 0 ) {
|
|
$this->bytes_already_read += $length;
|
|
$type = self::AT_TEXT_SUFFIX;
|
|
} else {
|
|
$type = self::AT_SIGN_SYMBOL;
|
|
}
|
|
}
|
|
} elseif ( '\\' === $byte ) {
|
|
$this->bytes_already_read += 1; // Consume the '\'.
|
|
if ( 'N' === $next_byte ) {
|
|
$this->bytes_already_read += 1; // Consume the 'N'.
|
|
$type = self::NULL2_SYMBOL;
|
|
} else {
|
|
return null; // Invalid input.
|
|
}
|
|
} elseif ( '#' === $byte ) {
|
|
$type = $this->read_line_comment();
|
|
} elseif ( null !== $byte && strspn( $byte, self::WHITESPACE_MASK ) > 0 ) {
|
|
$this->bytes_already_read += strspn( $this->sql, self::WHITESPACE_MASK, $this->bytes_already_read );
|
|
$type = self::WHITESPACE;
|
|
} elseif ( ( 'x' === $byte || 'X' === $byte || 'b' === $byte || 'B' === $byte ) && "'" === $next_byte ) {
|
|
$type = $this->read_number();
|
|
} elseif ( ( 'n' === $byte || 'N' === $byte ) && "'" === $next_byte ) {
|
|
$this->bytes_already_read += 1; // n/N
|
|
$type = $this->read_quoted_text( "'" );
|
|
if ( self::SINGLE_QUOTED_TEXT === $type ) {
|
|
$type = self::NCHAR_TEXT;
|
|
}
|
|
} elseif ( null === $byte ) {
|
|
$type = self::EOF;
|
|
} else {
|
|
$started_at = $this->bytes_already_read;
|
|
$type = $this->read_identifier();
|
|
if ( self::IDENTIFIER === $type ) {
|
|
// When preceded by a dot, it is always an identifier.
|
|
if ( $started_at > 0 && '.' === $this->sql[ $started_at - 1 ] ) {
|
|
$type = self::IDENTIFIER;
|
|
} elseif ( '_' === $byte && isset( self::UNDERSCORE_CHARSETS[ strtolower( $this->get_current_token_bytes() ) ] ) ) {
|
|
$type = self::UNDERSCORE_CHARSET;
|
|
} else {
|
|
$type = $this->determine_identifier_or_keyword_type( $this->get_current_token_bytes() );
|
|
}
|
|
}
|
|
}
|
|
return $type;
|
|
}
|
|
|
|
private function get_current_token_bytes(): string {
|
|
return substr(
|
|
$this->sql,
|
|
$this->token_starts_at,
|
|
$this->bytes_already_read - $this->token_starts_at
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Read an unquoted identifier.
|
|
*
|
|
* This function reads characters that are allowed in an unquoted identifier.
|
|
* An identifier cannot consist solely of digits, but this function doesn't
|
|
* ensure that explicitly, as numbers are processed before identifiers in
|
|
* the tokenization process, recognizing all digit-only sequences as numbers.
|
|
*
|
|
* Rules:
|
|
* 1. Allowed characters are ASCII a-z, A-Z, 0-9, _, $, and Unicode U+0080-U+FFFF.
|
|
* 2. Unquoted identifiers may begin with a digit but may not consist solely of digits.
|
|
*
|
|
* See:
|
|
* https://dev.mysql.com/doc/refman/8.4/en/identifiers.html
|
|
*/
|
|
private function read_identifier(): ?int {
|
|
$started_at = $this->bytes_already_read;
|
|
while ( true ) {
|
|
// First, let's try to parse an ASCII sequence.
|
|
$this->bytes_already_read += strspn(
|
|
$this->sql,
|
|
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$',
|
|
$this->bytes_already_read
|
|
);
|
|
|
|
// Check if the following byte can be part of a multibyte character
|
|
// in the range of U+0080 to U+FFFF before looking at further bytes.
|
|
// If it can't, bail out early to avoid unnecessary UTF-8 decoding.
|
|
// Identifiers are usually ASCII-only, so we can optimize for that.
|
|
$byte_1 = ord(
|
|
$this->sql[ $this->bytes_already_read ] ?? "\0"
|
|
);
|
|
if ( $byte_1 < 0xC2 || $byte_1 > 0xEF ) {
|
|
break;
|
|
}
|
|
|
|
// Look for a valid 2-byte UTF-8 symbol. Covers range U+0080 - U+07FF.
|
|
$byte_2 = ord(
|
|
$this->sql[ $this->bytes_already_read + 1 ] ?? "\0"
|
|
);
|
|
if (
|
|
$byte_1 <= 0xDF
|
|
&& $byte_2 >= 0x80 && $byte_2 <= 0xBF
|
|
) {
|
|
$this->bytes_already_read += 2;
|
|
continue;
|
|
}
|
|
|
|
// Look for a valid 3-byte UTF-8 symbol in range U+0800 - U+FFFF.
|
|
$byte_3 = ord(
|
|
$this->sql[ $this->bytes_already_read + 2 ] ?? "\0"
|
|
);
|
|
if (
|
|
$byte_1 <= 0xEF
|
|
&& $byte_2 >= 0x80 && $byte_2 <= 0xBF
|
|
&& $byte_3 >= 0x80 && $byte_3 <= 0xBF
|
|
// Exclude surrogate range U+D800 to U+DFFF:
|
|
&& ! ( 0xED === $byte_1 && $byte_2 >= 0xA0 )
|
|
// Exclude overlong encodings:
|
|
&& ! ( 0xE0 === $byte_1 && $byte_2 < 0xA0 )
|
|
) {
|
|
$this->bytes_already_read += 3;
|
|
continue;
|
|
}
|
|
|
|
// Not a valid identifier character.
|
|
break;
|
|
}
|
|
|
|
// An identifier cannot consist solely of digits, but we don't need to
|
|
// ensure that explicitly, as numbers are processed before identifiers.
|
|
|
|
return $this->bytes_already_read - $started_at > 0
|
|
? self::IDENTIFIER
|
|
: null; // Invalid input.
|
|
}
|
|
|
|
private function read_number(): ?int {
|
|
// @TODO: Support numeric-only identifier parts after "." (e.g., 1ea10.1).
|
|
|
|
$byte = $this->sql[ $this->bytes_already_read ] ?? null;
|
|
$next_byte = $this->sql[ $this->bytes_already_read + 1 ] ?? null;
|
|
$third_byte = $this->sql[ $this->bytes_already_read + 2 ] ?? null;
|
|
|
|
if (
|
|
// HEX number in the form of 0xN.
|
|
(
|
|
'0' === $byte
|
|
&& 'x' === $next_byte
|
|
&& null !== $third_byte
|
|
&& strspn( $third_byte, self::HEX_DIGIT_MASK ) > 0
|
|
)
|
|
// HEX number in the form of x'N' or X'N'.
|
|
|| ( ( 'x' === $byte || 'X' === $byte ) && "'" === $next_byte )
|
|
) {
|
|
$is_quoted = "'" === $next_byte;
|
|
$this->bytes_already_read += 2; // Consume "0x" or "x'".
|
|
$this->bytes_already_read += strspn( $this->sql, self::HEX_DIGIT_MASK, $this->bytes_already_read );
|
|
if ( $is_quoted ) {
|
|
if (
|
|
$this->bytes_already_read >= $this->sql_length
|
|
|| "'" !== $this->sql[ $this->bytes_already_read ]
|
|
) {
|
|
return null; // Invalid input.
|
|
}
|
|
$this->bytes_already_read += 1; // Consume the "'".
|
|
}
|
|
$type = self::HEX_NUMBER;
|
|
} elseif (
|
|
// BIN number in the form of 0bN.
|
|
(
|
|
'0' === $byte
|
|
&& 'b' === $next_byte
|
|
&& ( '0' === $third_byte || '1' === $third_byte )
|
|
)
|
|
// BIN number in the form of b'N' or B'N'.
|
|
|| ( ( 'b' === $byte || 'B' === $byte ) && "'" === $next_byte )
|
|
) {
|
|
$is_quoted = "'" === $next_byte;
|
|
$this->bytes_already_read += 2; // Consume "0b" or "b'".
|
|
$this->bytes_already_read += strspn( $this->sql, '01', $this->bytes_already_read );
|
|
if ( $is_quoted ) {
|
|
if (
|
|
$this->bytes_already_read >= $this->sql_length
|
|
|| "'" !== $this->sql[ $this->bytes_already_read ]
|
|
) {
|
|
return null; // Invalid input.
|
|
}
|
|
$this->bytes_already_read += 1; // Consume the "'".
|
|
}
|
|
$type = self::BIN_NUMBER;
|
|
} else {
|
|
// Here, we have a sequence starting with N or .N, where N is a digit.
|
|
|
|
// 1. Try integer first.
|
|
$this->bytes_already_read += strspn( $this->sql, self::DIGIT_MASK, $this->bytes_already_read );
|
|
$type = self::INT_NUMBER;
|
|
|
|
// 2. In case of N. or .N, it's a decimal or float number.
|
|
if ( '.' === ( $this->sql[ $this->bytes_already_read ] ?? null ) ) {
|
|
$this->bytes_already_read += 1;
|
|
$type = self::DECIMAL_NUMBER;
|
|
$this->bytes_already_read += strspn( $this->sql, self::DIGIT_MASK, $this->bytes_already_read );
|
|
}
|
|
|
|
// 3. When exponent is present, it's a float number.
|
|
$byte = $this->sql[ $this->bytes_already_read ] ?? null;
|
|
$next_byte = $this->sql[ $this->bytes_already_read + 1 ] ?? null;
|
|
$has_exponent =
|
|
( 'e' === $byte || 'E' === $byte )
|
|
&& null !== $next_byte
|
|
&& (
|
|
strspn( $next_byte, self::DIGIT_MASK ) > 0
|
|
|| (
|
|
( '+' === $next_byte || '-' === $next_byte )
|
|
&& $this->bytes_already_read + 2 < $this->sql_length
|
|
&& strspn( $this->sql[ $this->bytes_already_read + 2 ], self::DIGIT_MASK ) > 0
|
|
)
|
|
);
|
|
if ( $has_exponent ) {
|
|
$this->bytes_already_read += 1; // Consume the 'e' or 'E'.
|
|
$this->bytes_already_read += 1; // Consume the '+', '-', or digit.
|
|
$this->bytes_already_read += strspn( $this->sql, self::DIGIT_MASK, $this->bytes_already_read );
|
|
$type = self::FLOAT_NUMBER;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* In MySQL, when an input matches both a number and an identifier, the
|
|
* number always wins. However, if the number is followed by a non-numeric
|
|
* identifier-like character, then it is recognized as an identifier...
|
|
* Unless it's a float number, which ignores any subsequent input.
|
|
*
|
|
* Examples:
|
|
* - "1234" (integer) vs. "1234a" (identifier)
|
|
* - "0b01" (bin) vs. "0b012" (identifier)
|
|
* - "0xa1" (hex) vs. "0xa1x" (identifier)
|
|
* - "12.3" (decimal) vs. "12.3a" (identifier)
|
|
* - "1e10" (float) vs. "1e10a" (float, followed by identifier)
|
|
*/
|
|
$text = $this->get_current_token_bytes();
|
|
$possible_identifier_prefix =
|
|
self::INT_NUMBER === $type
|
|
|| ( '0' === $text[0] && ( 'b' === $text[1] || 'x' === $text[1] ) );
|
|
|
|
/*
|
|
* When we match some subsequent identifier bytes, it's an identifier.
|
|
* Note that the "$this->read_identifier()" method doesn't check that
|
|
* the identifier doesn't consist solely of digits. This is an advantage
|
|
* here, as we can look only at subsequent bytes instead of backtracking
|
|
* to the beginning of the number (for valid identifiers like 0b019).
|
|
*/
|
|
if ( $possible_identifier_prefix && self::IDENTIFIER === $this->read_identifier() ) {
|
|
$type = self::IDENTIFIER;
|
|
}
|
|
|
|
// Determine integer type.
|
|
if ( self::INT_NUMBER === $type ) {
|
|
// Fast path for most integers.
|
|
$bytes = $this->get_current_token_bytes();
|
|
if ( strlen( $bytes ) < 10 ) {
|
|
return self::INT_NUMBER;
|
|
}
|
|
|
|
// Remove leading zeros.
|
|
$bytes = substr( $bytes, strspn( $bytes, '0' ) );
|
|
$length = strlen( $bytes );
|
|
|
|
// Determine integer type based on its length and value.
|
|
if ( $length < 10 ) {
|
|
return self::INT_NUMBER;
|
|
} elseif ( 10 === $length ) {
|
|
return strcmp( $bytes, '2147483647' ) > 0
|
|
? self::LONG_NUMBER
|
|
: self::INT_NUMBER;
|
|
} elseif ( $length < 19 ) {
|
|
return self::LONG_NUMBER;
|
|
} elseif ( 19 === $length ) {
|
|
return strcmp( $bytes, '9223372036854775807' ) > 0
|
|
? self::ULONGLONG_NUMBER
|
|
: self::LONG_NUMBER;
|
|
} elseif ( 20 === $length ) {
|
|
return strcmp( $bytes, '18446744073709551615' ) > 0
|
|
? self::DECIMAL_NUMBER
|
|
: self::ULONGLONG_NUMBER;
|
|
} else {
|
|
return self::DECIMAL_NUMBER;
|
|
}
|
|
}
|
|
return $type;
|
|
}
|
|
|
|
/**
|
|
* Quoted literals and identifiers:
|
|
* https://dev.mysql.com/doc/refman/8.4/en/string-literals.html
|
|
* https://dev.mysql.com/doc/refman/8.4/en/identifiers.html
|
|
*
|
|
* Rules:
|
|
* 1. Quotes can be escaped by doubling them ('', "", ``).
|
|
* 2. Backslashes escape the next character, unless NO_BACKSLASH_ESCAPES is set.
|
|
*/
|
|
private function read_quoted_text(): ?int {
|
|
$quote = $this->sql[ $this->bytes_already_read ];
|
|
$this->bytes_already_read += 1; // Consume the quote.
|
|
|
|
$no_backslash_escapes = $this->is_sql_mode_active(
|
|
self::SQL_MODE_NO_BACKSLASH_ESCAPES
|
|
);
|
|
|
|
// We need to look for the closing quote in a loop, as it can be escaped,
|
|
// in which case the escape sequence is consumed and the loop continues.
|
|
$at = $this->bytes_already_read;
|
|
while ( true ) {
|
|
$quote_at = strpos( $this->sql, $quote, $at );
|
|
if ( false === $quote_at ) {
|
|
return null; // Invalid input.
|
|
}
|
|
$at = $quote_at;
|
|
|
|
/*
|
|
* By default, quotes can be escaped with a "\".
|
|
* When NO_BACKSLASH_ESCAPES SQL mode is active, the "\" treated as
|
|
* a regular character.
|
|
*
|
|
* The quote is escaped only when the number of preceding backslashes
|
|
* is odd - "\" is an escape sequence, "\\" is an escaped backslash,
|
|
* "\\\" is an escaped backslash and an escape sequence, and so on.
|
|
*
|
|
* The `($at - $i - 1) >= 0` guard prevents PHP's negative-string-
|
|
* offset wraparound (PHP 7.1+) when the closing-quote candidate
|
|
* sits at the very start of the input. The `?? null` covers
|
|
* positive out-of-range indexes belt-and-suspenders.
|
|
*/
|
|
if ( ! $no_backslash_escapes ) {
|
|
$i = 0;
|
|
while ( ( $at - $i - 1 ) >= 0 && '\\' === ( $this->sql[ $at - $i - 1 ] ?? null ) ) {
|
|
$i += 1;
|
|
}
|
|
if ( 1 === $i % 2 ) {
|
|
$at += 1;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// Check if the quote is doubled.
|
|
if ( ( $this->sql[ $at + 1 ] ?? null ) === $quote ) {
|
|
$at += 2;
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
$at += 1;
|
|
|
|
$this->bytes_already_read = $at;
|
|
|
|
if ( '`' === $quote ) {
|
|
return self::BACK_TICK_QUOTED_ID;
|
|
} elseif ( '"' === $quote ) {
|
|
return self::DOUBLE_QUOTED_TEXT;
|
|
} else {
|
|
return self::SINGLE_QUOTED_TEXT;
|
|
}
|
|
}
|
|
|
|
private function read_line_comment(): int {
|
|
$this->bytes_already_read += strcspn( $this->sql, "\r\n", $this->bytes_already_read );
|
|
return self::COMMENT;
|
|
}
|
|
|
|
private function read_mysql_comment(): int {
|
|
// @TODO: Consider supporting optimizer hints (/*+ ... */) or document
|
|
// that they are not supported.
|
|
// @TODO: Implement six-digit version number support (from MySQL 8.4).
|
|
|
|
// MySQL-specific comment in one of the following forms:
|
|
// 1. /*! ... */ - The content is treated as SQL.
|
|
// 2. /*!12345 ... */ - The content is treated as SQL when "MySQL version >= 12345".
|
|
$this->bytes_already_read += 3; // Consume the '/*!'.
|
|
|
|
// Check if the next 5 characters are digits.
|
|
$digit_count = strspn( $this->sql, self::DIGIT_MASK, $this->bytes_already_read, 5 );
|
|
$is_version_comment = 5 === $digit_count;
|
|
|
|
// For version comments, extract the version number.
|
|
$version = $is_version_comment
|
|
? (int) substr( $this->sql, $this->bytes_already_read, $digit_count )
|
|
: 0;
|
|
|
|
if ( $this->mysql_version < $version ) {
|
|
// Version not satisfied. Treat the content as a regular comment.
|
|
$this->read_comment_content();
|
|
return self::COMMENT;
|
|
} else {
|
|
// Version satisfied or not specified. Treat the content as SQL code.
|
|
$this->bytes_already_read += $digit_count; // Skip the version number.
|
|
$this->in_mysql_comment = true;
|
|
return self::MYSQL_COMMENT_START;
|
|
}
|
|
}
|
|
|
|
private function read_comment_content(): void {
|
|
$comment_end = strpos( $this->sql, '*/', $this->bytes_already_read );
|
|
if ( false === $comment_end ) {
|
|
$this->bytes_already_read = $this->sql_length;
|
|
} else {
|
|
$this->bytes_already_read = $comment_end + 2;
|
|
}
|
|
}
|
|
|
|
private function determine_identifier_or_keyword_type( string $value ): int {
|
|
$type = self::TOKENS[ strtoupper( $value ) ] ?? self::IDENTIFIER;
|
|
if ( self::IDENTIFIER === $type ) {
|
|
return self::IDENTIFIER;
|
|
}
|
|
return $this->resolve_keyword_type( $type );
|
|
}
|
|
|
|
/**
|
|
* Resolve a keyword token id matched in self::TOKENS, applying version gating,
|
|
* function-call lookahead, the SQL_MODE_HIGH_NOT_PRECEDENCE rule, and synonyms.
|
|
*
|
|
* @param int $type A token id already matched in self::TOKENS (never IDENTIFIER).
|
|
*/
|
|
private function resolve_keyword_type( int $type ): int {
|
|
|
|
// Apply MySQL version specifics (positive number: >= <version>, negative number: < <version>).
|
|
if ( isset( self::VERSIONS[ $type ] ) ) {
|
|
$version = self::VERSIONS[ $type ];
|
|
if ( $this->mysql_version < $version || -$version >= $this->mysql_version ) {
|
|
return self::IDENTIFIER;
|
|
}
|
|
}
|
|
|
|
// Apply MySQL version ranges manually.
|
|
if (
|
|
self::MAX_STATEMENT_TIME_SYMBOL === $type
|
|
&& ! ( $this->mysql_version >= 50704 && $this->mysql_version < 50708 )
|
|
) {
|
|
return self::IDENTIFIER;
|
|
}
|
|
|
|
if (
|
|
self::NONBLOCKING_SYMBOL === $type
|
|
&& ! ( $this->mysql_version >= 50700 && $this->mysql_version < 50706 )
|
|
) {
|
|
return self::IDENTIFIER;
|
|
}
|
|
|
|
if (
|
|
self::REMOTE_SYMBOL === $type
|
|
&& ( $this->mysql_version >= 80003 && $this->mysql_version < 80014 )
|
|
) {
|
|
return self::IDENTIFIER;
|
|
}
|
|
|
|
// Determine function calls.
|
|
if ( isset( self::FUNCTIONS[ $type ] ) ) {
|
|
// Skip any whitespace character if the SQL mode says they should be ignored.
|
|
if ( $this->is_sql_mode_active( self::SQL_MODE_IGNORE_SPACE ) ) {
|
|
$this->bytes_already_read += strspn( $this->sql, self::WHITESPACE_MASK, $this->bytes_already_read );
|
|
}
|
|
if ( '(' !== ( $this->sql[ $this->bytes_already_read ] ?? null ) ) {
|
|
return self::IDENTIFIER;
|
|
}
|
|
}
|
|
|
|
// With "SQL_MODE_HIGH_NOT_PRECEDENCE" enabled, "NOT" needs to be emitted as a higher priority NOT2 symbol.
|
|
if ( self::NOT_SYMBOL === $type && $this->is_sql_mode_active( self::SQL_MODE_HIGH_NOT_PRECEDENCE ) ) {
|
|
$type = self::NOT2_SYMBOL;
|
|
}
|
|
|
|
// Apply synonyms.
|
|
return self::SYNONYMS[ $type ] ?? $type;
|
|
}
|
|
}
|