in mysqlshdk/libs/parser/MySQLBaseLexer.cpp [178:859]
MySQLQueryType MySQLBaseLexer::determineQueryType() {
std::unique_ptr<Token> tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtUnknown;
switch (tok->getType()) {
case MySQLLexer::ALTER_SYMBOL:
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtAmbiguous;
switch (tok->getType()) {
case MySQLLexer::DATABASE_SYMBOL:
return QtAlterDatabase;
case MySQLLexer::LOGFILE_SYMBOL:
return QtAlterLogFileGroup;
case MySQLLexer::FUNCTION_SYMBOL:
return QtAlterFunction;
case MySQLLexer::PROCEDURE_SYMBOL:
return QtAlterProcedure;
case MySQLLexer::SERVER_SYMBOL:
return QtAlterServer;
case MySQLLexer::TABLE_SYMBOL:
case MySQLLexer::ONLINE_SYMBOL: // Optional part of ALTER TABLE.
case MySQLLexer::OFFLINE_SYMBOL: // ditto
case MySQLLexer::IGNORE_SYMBOL:
return QtAlterTable;
case MySQLLexer::TABLESPACE_SYMBOL:
return QtAlterTableSpace;
case MySQLLexer::EVENT_SYMBOL:
return QtAlterEvent;
case MySQLLexer::VIEW_SYMBOL:
return QtAlterView;
case MySQLLexer::DEFINER_SYMBOL: // Can be both event or view.
if (!skipDefiner(tok)) return QtAmbiguous;
tok = nextDefaultChannelToken();
switch (tok->getType()) {
case MySQLLexer::EVENT_SYMBOL:
return QtAlterEvent;
case MySQLLexer::SQL_SYMBOL:
case MySQLLexer::VIEW_SYMBOL:
return QtAlterView;
}
break;
case MySQLLexer::ALGORITHM_SYMBOL: // Optional part of CREATE VIEW.
return QtAlterView;
case MySQLLexer::USER_SYMBOL:
return QtAlterUser;
}
break;
case MySQLLexer::CREATE_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtAmbiguous;
switch (tok->getType()) {
case MySQLLexer::TEMPORARY_SYMBOL: // Optional part of CREATE TABLE.
case MySQLLexer::TABLE_SYMBOL:
return QtCreateTable;
case MySQLLexer::ONLINE_SYMBOL:
case MySQLLexer::OFFLINE_SYMBOL:
case MySQLLexer::INDEX_SYMBOL:
case MySQLLexer::UNIQUE_SYMBOL:
case MySQLLexer::FULLTEXT_SYMBOL:
case MySQLLexer::SPATIAL_SYMBOL:
return QtCreateIndex;
case MySQLLexer::DATABASE_SYMBOL:
return QtCreateDatabase;
case MySQLLexer::TRIGGER_SYMBOL:
return QtCreateTrigger;
case MySQLLexer::DEFINER_SYMBOL: // Can be event, view, procedure,
// function, UDF, trigger.
{
if (!skipDefiner(tok)) return QtAmbiguous;
switch (tok->getType()) {
case MySQLLexer::EVENT_SYMBOL:
return QtCreateEvent;
case MySQLLexer::VIEW_SYMBOL:
case MySQLLexer::SQL_SYMBOL:
return QtCreateView;
case MySQLLexer::PROCEDURE_SYMBOL:
return QtCreateProcedure;
case MySQLLexer::FUNCTION_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtAmbiguous;
if (!isIdentifier(tok->getType())) return QtAmbiguous;
tok = nextDefaultChannelToken();
if (tok->getType() == MySQLLexer::RETURNS_SYMBOL)
return QtCreateUdf;
return QtCreateFunction;
}
case MySQLLexer::AGGREGATE_SYMBOL:
return QtCreateUdf;
case MySQLLexer::TRIGGER_SYMBOL:
return QtCreateTrigger;
}
return QtUnknown;
}
case MySQLLexer::VIEW_SYMBOL:
case MySQLLexer::OR_SYMBOL: // CREATE OR REPLACE ... VIEW
case MySQLLexer::ALGORITHM_SYMBOL: // CREATE ALGORITHM ... VIEW
return QtCreateView;
case MySQLLexer::EVENT_SYMBOL:
return QtCreateEvent;
case MySQLLexer::FUNCTION_SYMBOL:
return QtCreateFunction;
case MySQLLexer::AGGREGATE_SYMBOL:
return QtCreateUdf;
case MySQLLexer::PROCEDURE_SYMBOL:
return QtCreateProcedure;
case MySQLLexer::LOGFILE_SYMBOL:
return QtCreateLogFileGroup;
case MySQLLexer::SERVER_SYMBOL:
return QtCreateServer;
case MySQLLexer::TABLESPACE_SYMBOL:
return QtCreateTableSpace;
case MySQLLexer::USER_SYMBOL:
return QtCreateUser;
}
break;
}
case MySQLLexer::DROP_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtAmbiguous;
switch (tok->getType()) {
case MySQLLexer::DATABASE_SYMBOL:
return QtDropDatabase;
case MySQLLexer::EVENT_SYMBOL:
return QtDropEvent;
case MySQLLexer::PROCEDURE_SYMBOL:
return QtDropProcedure;
case MySQLLexer::FUNCTION_SYMBOL:
return QtDropFunction;
case MySQLLexer::ONLINE_SYMBOL:
case MySQLLexer::OFFLINE_SYMBOL:
case MySQLLexer::INDEX_SYMBOL:
return QtDropIndex;
case MySQLLexer::LOGFILE_SYMBOL:
return QtDropLogfileGroup;
case MySQLLexer::SERVER_SYMBOL:
return QtDropServer;
case MySQLLexer::TEMPORARY_SYMBOL:
case MySQLLexer::TABLE_SYMBOL:
case MySQLLexer::TABLES_SYMBOL:
return QtDropTable;
case MySQLLexer::TABLESPACE_SYMBOL:
return QtDropTablespace;
case MySQLLexer::TRIGGER_SYMBOL:
return QtDropTrigger;
case MySQLLexer::VIEW_SYMBOL:
return QtDropView;
case MySQLLexer::PREPARE_SYMBOL:
return QtDeallocate;
case MySQLLexer::USER_SYMBOL:
return QtDropUser;
}
return QtUnknown;
}
case MySQLLexer::TRUNCATE_SYMBOL:
return QtTruncateTable;
case MySQLLexer::CALL_SYMBOL:
return QtCall;
case MySQLLexer::DELETE_SYMBOL:
return QtDelete;
case MySQLLexer::DO_SYMBOL:
return QtDo;
case MySQLLexer::HANDLER_SYMBOL:
return QtHandler;
case MySQLLexer::INSERT_SYMBOL:
return QtInsert;
case MySQLLexer::LOAD_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtAmbiguous;
switch (tok->getType()) {
case MySQLLexer::DATA_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtAmbiguous;
if (tok->getType() == MySQLLexer::FROM_SYMBOL)
return QtLoadDataMaster;
return QtLoadData;
}
case MySQLLexer::XML_SYMBOL:
return QtLoadXML;
case MySQLLexer::TABLE_SYMBOL:
return QtLoadTableMaster;
case MySQLLexer::INDEX_SYMBOL:
return QtLoadIndex;
}
return QtUnknown;
}
case MySQLLexer::REPLACE_SYMBOL:
return QtReplace;
case MySQLLexer::SELECT_SYMBOL:
return QtSelect;
case MySQLLexer::TABLE_SYMBOL:
return QtTable;
case MySQLLexer::VALUES_SYMBOL:
return QtValues;
case MySQLLexer::UPDATE_SYMBOL:
return QtUpdate;
case MySQLLexer::OPEN_PAR_SYMBOL: // Either (((select ..))) or
// (partition...)
{
while (tok->getType() == MySQLLexer::OPEN_PAR_SYMBOL) {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtAmbiguous;
}
if (tok->getType() == MySQLLexer::SELECT_SYMBOL) return QtSelect;
return QtPartition;
}
case MySQLLexer::PARTITION_SYMBOL:
case MySQLLexer::PARTITIONS_SYMBOL:
return QtPartition;
case MySQLLexer::START_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtAmbiguous;
if (tok->getType() == MySQLLexer::TRANSACTION_SYMBOL)
return QtStartTransaction;
return QtStartSlave;
}
case MySQLLexer::BEGIN_SYMBOL: // Begin directly at the start of the query
// must be a transaction start.
return QtBeginWork;
case MySQLLexer::COMMIT_SYMBOL:
return QtCommit;
case MySQLLexer::ROLLBACK_SYMBOL: {
// We assume a transaction statement here unless we exactly know it's
// about a savepoint.
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtRollbackWork;
if (tok->getType() == MySQLLexer::WORK_SYMBOL) {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtRollbackWork;
}
if (tok->getType() == MySQLLexer::TO_SYMBOL) return QtRollbackSavepoint;
return QtRollbackWork;
}
case MySQLLexer::SET_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtSet;
switch (tok->getType()) {
case MySQLLexer::PASSWORD_SYMBOL:
return QtSetPassword;
case MySQLLexer::GLOBAL_SYMBOL:
case MySQLLexer::LOCAL_SYMBOL:
case MySQLLexer::SESSION_SYMBOL:
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtSet;
break;
case MySQLLexer::IDENTIFIER: {
std::string text = tok->getText();
std::transform(text.begin(), text.end(), text.begin(), ::tolower);
if (text == "autocommit") return QtSetAutoCommit;
break;
}
}
if (tok->getType() == MySQLLexer::TRANSACTION_SYMBOL)
return QtSetTransaction;
return QtSet;
}
case MySQLLexer::SAVEPOINT_SYMBOL:
return QtSavepoint;
case MySQLLexer::RELEASE_SYMBOL: // Release at the start of the query,
// obviously.
return QtReleaseSavepoint;
case MySQLLexer::LOCK_SYMBOL:
return QtLock;
case MySQLLexer::UNLOCK_SYMBOL:
return QtUnlock;
case MySQLLexer::XA_SYMBOL:
return QtXA;
case MySQLLexer::PURGE_SYMBOL:
return QtPurge;
case MySQLLexer::CHANGE_SYMBOL:
return QtChangeMaster;
case MySQLLexer::RESET_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtReset;
switch (tok->getType()) {
case MySQLLexer::SERVER_SYMBOL:
return QtResetMaster;
case MySQLLexer::SLAVE_SYMBOL:
return QtResetSlave;
case MySQLLexer::PERSIST_SYMBOL:
return QtResetPersist;
default:
return QtReset;
}
}
case MySQLLexer::STOP_SYMBOL:
return QtStopSlave;
case MySQLLexer::PREPARE_SYMBOL:
return QtPrepare;
case MySQLLexer::EXECUTE_SYMBOL:
return QtExecute;
case MySQLLexer::DEALLOCATE_SYMBOL:
return QtDeallocate;
case MySQLLexer::GRANT_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtAmbiguous;
if (tok->getType() == MySQLLexer::PROXY_SYMBOL) return QtGrantProxy;
return QtGrant;
}
case MySQLLexer::RENAME_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtAmbiguous;
if (tok->getType() == MySQLLexer::USER_SYMBOL) return QtRenameUser;
return QtRenameTable;
}
case MySQLLexer::REVOKE_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtAmbiguous;
if (tok->getType() == MySQLLexer::PROXY_SYMBOL) return QtRevokeProxy;
return QtRevoke;
}
case MySQLLexer::ANALYZE_SYMBOL:
return QtAnalyzeTable;
case MySQLLexer::CHECK_SYMBOL:
return QtCheckTable;
case MySQLLexer::CHECKSUM_SYMBOL:
return QtChecksumTable;
case MySQLLexer::OPTIMIZE_SYMBOL:
return QtOptimizeTable;
case MySQLLexer::REPAIR_SYMBOL:
return QtRepairTable;
case MySQLLexer::BACKUP_SYMBOL:
return QtBackUpTable;
case MySQLLexer::RESTORE_SYMBOL:
return QtRestoreTable;
case MySQLLexer::INSTALL_SYMBOL:
return QtInstallPlugin;
case MySQLLexer::UNINSTALL_SYMBOL:
return QtUninstallPlugin;
case MySQLLexer::SHOW_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtShow;
if (tok->getType() == MySQLLexer::FULL_SYMBOL) {
// Not all SHOW cases allow an optional FULL keyword, but this is not
// about checking for a valid query but to find the most likely type.
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtShow;
}
switch (tok->getType()) {
case MySQLLexer::GLOBAL_SYMBOL:
case MySQLLexer::LOCK_SYMBOL:
case MySQLLexer::SESSION_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtShow;
if (tok->getType() == MySQLLexer::STATUS_SYMBOL) return QtShowStatus;
return QtShowVariables;
}
case MySQLLexer::AUTHORS_SYMBOL:
return QtShowAuthors;
case MySQLLexer::BINARY_SYMBOL:
return QtShowBinaryLogs;
case MySQLLexer::BINLOG_SYMBOL:
return QtShowBinlogEvents;
case MySQLLexer::RELAYLOG_SYMBOL:
return QtShowRelaylogEvents;
case MySQLLexer::CHAR_SYMBOL:
return QtShowCharset;
case MySQLLexer::COLLATION_SYMBOL:
return QtShowCollation;
case MySQLLexer::COLUMNS_SYMBOL:
return QtShowColumns;
case MySQLLexer::CONTRIBUTORS_SYMBOL:
return QtShowContributors;
case MySQLLexer::COUNT_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() != MySQLLexer::OPEN_PAR_SYMBOL) return QtShow;
tok = nextDefaultChannelToken();
if (tok->getType() != MySQLLexer::MULT_OPERATOR) return QtShow;
tok = nextDefaultChannelToken();
if (tok->getType() != MySQLLexer::CLOSE_PAR_SYMBOL) return QtShow;
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtShow;
switch (tok->getType()) {
case MySQLLexer::WARNINGS_SYMBOL:
return QtShowWarnings;
case MySQLLexer::ERRORS_SYMBOL:
return QtShowErrors;
}
return QtShow;
}
case MySQLLexer::CREATE_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtShow;
switch (tok->getType()) {
case MySQLLexer::DATABASE_SYMBOL:
return QtShowCreateDatabase;
case MySQLLexer::EVENT_SYMBOL:
return QtShowCreateEvent;
case MySQLLexer::FUNCTION_SYMBOL:
return QtShowCreateFunction;
case MySQLLexer::PROCEDURE_SYMBOL:
return QtShowCreateProcedure;
case MySQLLexer::TABLE_SYMBOL:
return QtShowCreateTable;
case MySQLLexer::TRIGGER_SYMBOL:
return QtShowCreateTrigger;
case MySQLLexer::VIEW_SYMBOL:
return QtShowCreateView;
}
return QtShow;
}
case MySQLLexer::DATABASES_SYMBOL:
return QtShowDatabases;
case MySQLLexer::ENGINE_SYMBOL:
return QtShowEngineStatus;
case MySQLLexer::STORAGE_SYMBOL:
case MySQLLexer::ENGINES_SYMBOL:
return QtShowStorageEngines;
case MySQLLexer::ERRORS_SYMBOL:
return QtShowErrors;
case MySQLLexer::EVENTS_SYMBOL:
return QtShowEvents;
case MySQLLexer::FUNCTION_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtAmbiguous;
if (tok->getType() == MySQLLexer::CODE_SYMBOL)
return QtShowFunctionCode;
return QtShowFunctionStatus;
}
case MySQLLexer::GRANT_SYMBOL:
return QtShowGrants;
case MySQLLexer::INDEX_SYMBOL:
case MySQLLexer::INDEXES_SYMBOL:
case MySQLLexer::KEY_SYMBOL:
return QtShowIndexes;
case MySQLLexer::MASTER_SYMBOL:
return QtShowMasterStatus;
case MySQLLexer::OPEN_SYMBOL:
return QtShowOpenTables;
case MySQLLexer::PLUGIN_SYMBOL:
case MySQLLexer::PLUGINS_SYMBOL:
return QtShowPlugins;
case MySQLLexer::PROCEDURE_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtShow;
if (tok->getType() == MySQLLexer::STATUS_SYMBOL)
return QtShowProcedureStatus;
return QtShowProcedureCode;
}
case MySQLLexer::PRIVILEGES_SYMBOL:
return QtShowPrivileges;
case MySQLLexer::PROCESSLIST_SYMBOL:
return QtShowProcessList;
case MySQLLexer::PROFILE_SYMBOL:
return QtShowProfile;
case MySQLLexer::PROFILES_SYMBOL:
return QtShowProfiles;
case MySQLLexer::SLAVE_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtAmbiguous;
if (tok->getType() == MySQLLexer::HOSTS_SYMBOL)
return QtShowSlaveHosts;
return QtShowSlaveStatus;
}
case MySQLLexer::STATUS_SYMBOL:
return QtShowStatus;
case MySQLLexer::VARIABLES_SYMBOL:
return QtShowVariables;
case MySQLLexer::TABLE_SYMBOL:
return QtShowTableStatus;
case MySQLLexer::TABLES_SYMBOL:
return QtShowTables;
case MySQLLexer::TRIGGERS_SYMBOL:
return QtShowTriggers;
case MySQLLexer::WARNINGS_SYMBOL:
return QtShowWarnings;
}
return QtShow;
}
case MySQLLexer::CACHE_SYMBOL:
return QtCacheIndex;
case MySQLLexer::FLUSH_SYMBOL:
return QtFlush;
case MySQLLexer::KILL_SYMBOL:
return QtKill;
case MySQLLexer::DESCRIBE_SYMBOL: // EXPLAIN is converted to DESCRIBE in
// the lexer.
case MySQLLexer::DESC_SYMBOL: {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtAmbiguous;
if (isIdentifier(tok->getType()) ||
tok->getType() == MySQLLexer::DOT_SYMBOL)
return QtExplainTable;
// EXTENDED is a bit special as it can be both, a table identifier or the
// keyword.
if (tok->getType() == MySQLLexer::EXTENDED_SYMBOL) {
tok = nextDefaultChannelToken();
if (tok->getType() == Token::EOF) return QtExplainTable;
switch (tok->getType()) {
case MySQLLexer::DELETE_SYMBOL:
case MySQLLexer::INSERT_SYMBOL:
case MySQLLexer::REPLACE_SYMBOL:
case MySQLLexer::UPDATE_SYMBOL:
return QtExplainStatement;
default:
return QtExplainTable;
}
}
return QtExplainStatement;
}
case MySQLLexer::HELP_SYMBOL:
return QtHelp;
case MySQLLexer::USE_SYMBOL:
return QtUse;
}
return QtUnknown;
}