From ee6dd2e7c06331262619cb2ee472a350e7685185 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Sat, 13 Jun 2015 13:53:01 +0300 Subject: [PATCH 01/57] Added sql-parser with a modified version of the Composer autoloader to load the library. Signed-off-by: Dan Ungureanu --- libraries/common.inc.php | 1 + libraries/sql-parser/autoload.php | 7 + libraries/sql-parser/composer/ClassLoader.php | 413 +++++++++++++ .../sql-parser/composer/autoload_psr4.php | 10 + .../sql-parser/composer/autoload_real.php | 40 ++ libraries/sql-parser/src/Context.php | 475 ++++++++++++++ .../src/Exceptions/LexerException.php | 41 ++ .../src/Exceptions/ParserException.php | 32 + libraries/sql-parser/src/Fragment.php | 30 + .../src/Fragments/ArrayFragment.php | 95 +++ .../sql-parser/src/Fragments/CallKeyword.php | 86 +++ .../src/Fragments/CreateDefFragment.php | 108 ++++ .../src/Fragments/DataTypeFragment.php | 109 ++++ .../src/Fragments/FieldDefFragment.php | 181 ++++++ .../src/Fragments/FieldFragment.php | 173 ++++++ .../sql-parser/src/Fragments/FromKeyword.php | 68 +++ .../sql-parser/src/Fragments/IntoKeyword.php | 108 ++++ .../sql-parser/src/Fragments/JoinKeyword.php | 89 +++ .../sql-parser/src/Fragments/LimitKeyword.php | 91 +++ .../src/Fragments/OptionsFragment.php | 136 +++++ .../sql-parser/src/Fragments/OrderKeyword.php | 90 +++ .../src/Fragments/ParamDefFragment.php | 128 ++++ .../src/Fragments/RenameKeyword.php | 117 ++++ .../src/Fragments/SelectKeyword.php | 68 +++ .../sql-parser/src/Fragments/SetKeyword.php | 105 ++++ .../src/Fragments/ValuesKeyword.php | 115 ++++ .../sql-parser/src/Fragments/WhereKeyword.php | 100 +++ libraries/sql-parser/src/Lexer.php | 578 ++++++++++++++++++ libraries/sql-parser/src/Parser.php | 189 ++++++ libraries/sql-parser/src/Statement.php | 145 +++++ .../src/Statements/CallStatement.php | 19 + .../src/Statements/CreateStatement.php | 81 +++ .../src/Statements/DeleteStatement.php | 74 +++ .../src/Statements/InsertStatement.php | 78 +++ .../src/Statements/RenameStatement.php | 23 + .../src/Statements/ReplaceStatement.php | 63 ++ .../src/Statements/SelectStatement.php | 130 ++++ .../src/Statements/UpdateStatement.php | 79 +++ libraries/sql-parser/src/Token.php | 253 ++++++++ libraries/sql-parser/src/TokensList.php | 118 ++++ libraries/sql-parser/src/UtfString.php | 220 +++++++ libraries/sql-parser/src/Utils/Misc.php | 91 +++ libraries/sql-parser/src/Utils/Routine.php | 46 ++ 43 files changed, 5203 insertions(+) create mode 100644 libraries/sql-parser/autoload.php create mode 100644 libraries/sql-parser/composer/ClassLoader.php create mode 100644 libraries/sql-parser/composer/autoload_psr4.php create mode 100644 libraries/sql-parser/composer/autoload_real.php create mode 100644 libraries/sql-parser/src/Context.php create mode 100644 libraries/sql-parser/src/Exceptions/LexerException.php create mode 100644 libraries/sql-parser/src/Exceptions/ParserException.php create mode 100644 libraries/sql-parser/src/Fragment.php create mode 100644 libraries/sql-parser/src/Fragments/ArrayFragment.php create mode 100644 libraries/sql-parser/src/Fragments/CallKeyword.php create mode 100644 libraries/sql-parser/src/Fragments/CreateDefFragment.php create mode 100644 libraries/sql-parser/src/Fragments/DataTypeFragment.php create mode 100644 libraries/sql-parser/src/Fragments/FieldDefFragment.php create mode 100644 libraries/sql-parser/src/Fragments/FieldFragment.php create mode 100644 libraries/sql-parser/src/Fragments/FromKeyword.php create mode 100644 libraries/sql-parser/src/Fragments/IntoKeyword.php create mode 100644 libraries/sql-parser/src/Fragments/JoinKeyword.php create mode 100644 libraries/sql-parser/src/Fragments/LimitKeyword.php create mode 100644 libraries/sql-parser/src/Fragments/OptionsFragment.php create mode 100644 libraries/sql-parser/src/Fragments/OrderKeyword.php create mode 100644 libraries/sql-parser/src/Fragments/ParamDefFragment.php create mode 100644 libraries/sql-parser/src/Fragments/RenameKeyword.php create mode 100644 libraries/sql-parser/src/Fragments/SelectKeyword.php create mode 100644 libraries/sql-parser/src/Fragments/SetKeyword.php create mode 100644 libraries/sql-parser/src/Fragments/ValuesKeyword.php create mode 100644 libraries/sql-parser/src/Fragments/WhereKeyword.php create mode 100644 libraries/sql-parser/src/Lexer.php create mode 100644 libraries/sql-parser/src/Parser.php create mode 100644 libraries/sql-parser/src/Statement.php create mode 100644 libraries/sql-parser/src/Statements/CallStatement.php create mode 100644 libraries/sql-parser/src/Statements/CreateStatement.php create mode 100644 libraries/sql-parser/src/Statements/DeleteStatement.php create mode 100644 libraries/sql-parser/src/Statements/InsertStatement.php create mode 100644 libraries/sql-parser/src/Statements/RenameStatement.php create mode 100644 libraries/sql-parser/src/Statements/ReplaceStatement.php create mode 100644 libraries/sql-parser/src/Statements/SelectStatement.php create mode 100644 libraries/sql-parser/src/Statements/UpdateStatement.php create mode 100644 libraries/sql-parser/src/Token.php create mode 100644 libraries/sql-parser/src/TokensList.php create mode 100644 libraries/sql-parser/src/UtfString.php create mode 100644 libraries/sql-parser/src/Utils/Misc.php create mode 100644 libraries/sql-parser/src/Utils/Routine.php diff --git a/libraries/common.inc.php b/libraries/common.inc.php index ee4bba0fd0..282423fe59 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -1057,6 +1057,7 @@ if (! defined('PMA_MINIMUM_COMMON')) { * SQL Parser code */ include_once './libraries/sqlparser.lib.php'; + include_once './libraries/sql-parser/autoload.php'; /** * the PMA_List_Database class diff --git a/libraries/sql-parser/autoload.php b/libraries/sql-parser/autoload.php new file mode 100644 index 0000000000..a88e87984f --- /dev/null +++ b/libraries/sql-parser/autoload.php @@ -0,0 +1,7 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0 class loader + * + * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + + private $classMapAuthoritative = false; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-0 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 + if ('\\' == $class[0]) { + $class = substr($class, 1); + } + + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative) { + return false; + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if ($file === null && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if ($file === null) { + // Remember that this class does not exist. + return $this->classMap[$class] = false; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { + if (0 === strpos($class, $prefix)) { + foreach ($this->prefixDirsPsr4[$prefix] as $dir) { + if (is_file($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/libraries/sql-parser/composer/autoload_psr4.php b/libraries/sql-parser/composer/autoload_psr4.php new file mode 100644 index 0000000000..31419d5807 --- /dev/null +++ b/libraries/sql-parser/composer/autoload_psr4.php @@ -0,0 +1,10 @@ + array($vendorDir . '/src'), +); diff --git a/libraries/sql-parser/composer/autoload_real.php b/libraries/sql-parser/composer/autoload_real.php new file mode 100644 index 0000000000..7ada1d9da6 --- /dev/null +++ b/libraries/sql-parser/composer/autoload_real.php @@ -0,0 +1,40 @@ + $path) { + $loader->setPsr4($namespace, $path); + } + + $loader->register(true); + + return $loader; + } +} + +function composerRequire($file) +{ + require $file; +} diff --git a/libraries/sql-parser/src/Context.php b/libraries/sql-parser/src/Context.php new file mode 100644 index 0000000000..2b43e568a1 --- /dev/null +++ b/libraries/sql-parser/src/Context.php @@ -0,0 +1,475 @@ + 1, 'BY' => 1, 'IF' => 1, 'IN' => 1, 'IS' => 1, 'ON' => 1, + 'OR' => 1, 'TO' => 1, + 'ADD' => 1, 'ALL' => 1, 'AND' => 1, 'ASC' => 1, 'DEC' => 1, 'DIV' => 1, + 'FOR' => 1, 'GET' => 1, 'INT' => 1, 'KEY' => 1, 'MOD' => 1, 'NOT' => 1, + 'OUT' => 1, 'SET' => 1, 'SQL' => 1, 'SSL' => 1, 'USE' => 1, 'XOR' => 1, + 'BLOB' => 1, 'BOTH' => 1, 'CALL' => 1, 'CASE' => 1, 'CHAR' => 1, + 'DESC' => 1, 'DROP' => 1, 'DUAL' => 1, 'EACH' => 1, 'ELSE' => 1, + 'EXIT' => 1, 'FROM' => 1, 'GOTO' => 1, 'INT1' => 1, 'INT2' => 1, + 'INT3' => 1, 'INT4' => 1, 'INT8' => 1, 'INTO' => 1, 'JOIN' => 1, + 'KEYS' => 1, 'KILL' => 1, 'LEFT' => 1, 'LIKE' => 1, 'LOAD' => 1, + 'LOCK' => 1, 'LONG' => 1, 'LOOP' => 1, 'NULL' => 1, 'READ' => 1, + 'REAL' => 1, 'SHOW' => 1, 'THEN' => 1, 'TRUE' => 1, 'UNDO' => 1, + 'WHEN' => 1, 'WITH' => 1, + 'ALTER' => 1, 'CHECK' => 1, 'CROSS' => 1, 'FALSE' => 1, 'FETCH' => 1, + 'FLOAT' => 1, 'FORCE' => 1, 'GRANT' => 1, 'GROUP' => 1, 'INDEX' => 1, + 'INNER' => 1, 'INOUT' => 1, 'LABEL' => 1, 'LEAVE' => 1, 'LIMIT' => 1, + 'LINES' => 1, 'MATCH' => 1, 'ORDER' => 1, 'OUTER' => 1, 'PURGE' => 1, + 'RANGE' => 1, 'READS' => 1, 'RIGHT' => 1, 'RLIKE' => 1, 'TABLE' => 1, + 'UNION' => 1, 'USAGE' => 1, 'USING' => 1, 'WHERE' => 1, 'WHILE' => 1, + 'WRITE' => 1, + 'BEFORE' => 1, 'BIGINT' => 1, 'BINARY' => 1, 'CHANGE' => 1, + 'COLUMN' => 1, 'CREATE' => 1, 'CURSOR' => 1, 'DELETE' => 1, + 'DOUBLE' => 1, 'ELSEIF' => 1, 'EXISTS' => 1, 'FLOAT4' => 1, + 'FLOAT8' => 1, 'HAVING' => 1, 'IGNORE' => 1, 'INFILE' => 1, + 'INSERT' => 1, 'LINEAR' => 1, 'OPTION' => 1, 'REGEXP' => 1, + 'RENAME' => 1, 'REPEAT' => 1, 'RETURN' => 1, 'REVOKE' => 1, + 'SCHEMA' => 1, 'SELECT' => 1, 'SIGNAL' => 1, 'SONAME' => 1, + 'UNIQUE' => 1, 'UNLOCK' => 1, 'UPDATE' => 1, 'VALUES' => 1, + 'ANALYZE' => 1, 'BETWEEN' => 1, 'CASCADE' => 1, 'COLLATE' => 1, + 'CONVERT' => 1, 'DECIMAL' => 1, 'DECLARE' => 1, 'DEFAULT' => 1, + 'DELAYED' => 1, 'ESCAPED' => 1, 'EXPLAIN' => 1, 'FOREIGN' => 1, + 'INTEGER' => 1, 'ITERATE' => 1, 'LEADING' => 1, 'NATURAL' => 1, + 'NUMERIC' => 1, 'OUTFILE' => 1, 'PRIMARY' => 1, 'RELEASE' => 1, + 'REPLACE' => 1, 'REQUIRE' => 1, 'SCHEMAS' => 1, 'SPATIAL' => 1, + 'TINYINT' => 1, 'TRIGGER' => 1, 'UPGRADE' => 1, 'VARCHAR' => 1, + 'VARYING' => 1, + 'CONTINUE' => 1, 'DATABASE' => 1, 'DAY_HOUR' => 1, 'DESCRIBE' => 1, + 'DISTINCT' => 1, 'ENCLOSED' => 1, 'FULLTEXT' => 1, 'INTERVAL' => 1, + 'LONGBLOB' => 1, 'LONGTEXT' => 1, 'MAXVALUE' => 1, 'MODIFIES' => 1, + 'OPTIMIZE' => 1, 'RESIGNAL' => 1, 'RESTRICT' => 1, 'SMALLINT' => 1, + 'SPECIFIC' => 1, 'SQLSTATE' => 1, 'STARTING' => 1, 'TINYBLOB' => 1, + 'TINYTEXT' => 1, 'TRAILING' => 1, 'UNSIGNED' => 1, 'UTC_DATE' => 1, + 'UTC_TIME' => 1, 'ZEROFILL' => 1, + 'CHARACTER' => 1, 'CONDITION' => 1, 'DATABASES' => 1, 'LOCALTIME' => 1, + 'MEDIUMINT' => 1, 'MIDDLEINT' => 1, 'PARTITION' => 1, 'PRECISION' => 1, + 'PROCEDURE' => 1, 'SENSITIVE' => 1, 'SEPARATOR' => 1, 'VARBINARY' => 1, + 'ACCESSIBLE' => 1, 'ASENSITIVE' => 1, 'CONNECTION' => 1, + 'CONSTRAINT' => 1, 'DAY_MINUTE' => 1, 'DAY_SECOND' => 1, + 'MEDIUMBLOB' => 1, 'MEDIUMTEXT' => 1, 'OPTIONALLY' => 1, + 'READ_WRITE' => 1, 'REFERENCES' => 1, 'SQLWARNING' => 1, + 'TERMINATED' => 1, 'YEAR_MONTH' => 1, + 'DISTINCTROW' => 1, 'HOUR_MINUTE' => 1, 'HOUR_SECOND' => 1, + 'INSENSITIVE' => 1, 'MASTER_BIND' => 1, + 'CURRENT_DATE' => 1, 'CURRENT_TIME' => 1, 'CURRENT_USER' => 1, + 'LOW_PRIORITY' => 1, 'SQLEXCEPTION' => 1, 'VARCHARACTER' => 1, + 'DETERMINISTIC' => 1, 'HIGH_PRIORITY' => 1, 'MINUTE_SECOND' => 1, + 'STRAIGHT_JOIN' => 1, 'UTC_TIMESTAMP' => 1, + 'IO_AFTER_GTIDS' => 1, 'LOCALTIMESTAMP' => 1, 'SQL_BIG_RESULT' => 1, + 'DAY_MICROSECOND' => 1, 'IO_BEFORE_GTIDS' => 1, 'OPTIMIZER_COSTS' => 1, + 'HOUR_MICROSECOND' => 1, 'SQL_SMALL_RESULT' => 1, + 'CURRENT_TIMESTAMP' => 1, + 'MINUTE_MICROSECOND' => 1, 'NO_WRITE_TO_BINLOG' => 1, + 'SECOND_MICROSECOND' => 1, + 'SQL_CALC_FOUND_ROWS' => 1, + 'MASTER_SSL_VERIFY_SERVER_CERT' => 1, + + /* + * Secondary group of keywords. + * + * Keywords below are either words that are used as keywords, but not + * defined as proper keywords or are group of keywords which are parsed + * easier when found grouped. + */ + + 'END' => 2, + 'INDEX' => 2, 'VALUE' => 2, + 'ENGINE' => 2, + 'CHARSET' => 2, 'COMMENT' => 2, 'RETURNS' => 2, 'STORAGE' => 2, + 'CHECKSUM' => 2, 'MAX_ROWS' => 2, 'MIN_ROWS' => 2, 'NOT NULL' => 2, + 'PASSWORD' => 2, + 'INDEX KEY' => 2, 'PACK_KEYS' => 2, + 'ROW_FORMAT' => 2, 'TABLESPACE' => 2, + 'UNIQUE KEY' => 2, + 'FOREIGN KEY' => 2, 'PRIMARY KEY' => 2, 'PRIMARY KEY' => 2, + 'SPATIAL KEY' => 2, + 'FULLTEXT KEY' => 2, 'UNIQUE INDEX' => 2, + 'CHARACTER SET' => 2, 'IF NOT EXISTS' => 2, 'INSERT_METHOD' => 2, + 'SPATIAL INDEX' => 2, + 'AUTO_INCREMENT' => 2, 'AVG_ROW_LENGTH' => 2, 'DATA DIRECTORY' => 2, + 'FULLTEXT INDEX' => 2, 'KEY_BLOCK_SIZE' => 2, + 'DEFAULT COLLATE' => 2, + 'DELAY_KEY_WRITE' => 2, 'INDEX DIRECTORY' => 2, + 'DEFAULT CHARACTER SET' => 2, + ); + + // ------------------------------------------------------------------------- + // Keys and Data Types. + + /** + * Types of keys. + * + * @var array + */ + public static $KEY_TYPES = array( + 'FOREIGN KEY' => 1, 'FULLTEXT INDEX' => 1, 'FULLTEXT KEY' => 1, + 'INDEX KEY' => 1, 'INDEX' => 1, 'KEY' => 1, 'PRIMARY KEY' => 1, + 'SPATIAL INDEX' => 1, 'SPATIAL KEY' => 1, 'UNIQUE INDEX' => 1, + 'UNIQUE KEY' => 1, 'UNIQUE' => 1, + ); + + /** + * All data types. + * + * @var array + */ + public static $DATA_TYPES = array( + 'ARRAY' => 1, 'BIGINT' => 1, 'BINARY VARYING' => 1, 'BINARY' => 1, + 'BOOLEAN' => 1, 'CHARACTER' => 1, 'CHARACTER' => 1, 'DATE' => 1, + 'DECIMAL' => 1, 'DOUBLE' => 1, 'FLOAT' => 1, 'FLOAT' => 1, 'INT' => 1, + 'INTEGER' => 1, 'INTERVAL' => 1, 'MULTISET' => 1, 'NUMERIC' => 1, + 'REAL' => 1, 'SMALLINT' => 1, 'TIME' => 1, 'TIMESTAMP' => 1, + 'VARBINARY' => 1, 'VARCHAR' => 1, 'XML' => 1, + ); + + // ------------------------------------------------------------------------- + // Operators. + + /** + * List of operators and their flags. + * + * @var array + */ + public static $OPERATORS = array( + + // Some operators (*, =) may have ambigous flags, because they depend on + // the context they are being used in. + // For example: 1. SELECT * FROM table; # SQL specific (wildcard) + // SELECT 2 * 3; # arithmetic + // 2. SELECT * FROM table WHERE foo = 'bar'; + // SET @i = 0; + + // @see Token::FLAG_OPERATOR_ARITHMETIC + '%' => 1, '*' => 1, '+' => 1, '-' => 1, '/' => 1, + + // @see Token::FLAG_OPERATOR_LOGICAL + '!' => 2, '!==' => 2, '&&' => 2, '<' => 2, '<=' => 2, + '<=>' => 2, '<>' => 2, '=' => 2, '>' => 2, '>=' => 2, + '||' => 2, + + // @see Token::FLAG_OPERATOR_BITWISE + '&' => 4, '<<' => 4, '>>' => 4, '^' => 4, '|' => 4, + '~' => 4, + + // @see Token::FLAG_OPERATOR_ASSIGNMENT + ':=' => 8, + + // @see Token::FLAG_OPERATOR_SQL + '(' => 16, ')' => 16, '.' => 16, ',' => 16, + ); + + // ------------------------------------------------------------------------- + // SQL Modes. + + /* + * Server SQL Modes + * https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html + */ + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_allow_invalid_dates + const ALLOW_INVALID_DATES = 1; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_ansi_quotes + const ANSI_QUOTES = 2; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_error_for_division_by_zero + const ERROR_FOR_DIVISION_BY_ZERO = 4; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_high_not_precedence + const HIGH_NOT_PRECEDENCE = 8; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_ignore_space + const IGNORE_SPACE = 16; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_auto_create_user + const NO_AUTO_CREATE_USER = 32; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_auto_value_on_zero + const NO_AUTO_VALUE_ON_ZERO = 64; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_backslash_escapes + const NO_BACKSLASH_ESCAPES = 128; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_dir_in_create + const NO_DIR_IN_CREATE = 256; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_dir_in_create + const NO_ENGINE_SUBSTITUTION = 512; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_field_options + const NO_FIELD_OPTIONS = 1024; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_key_options + const NO_KEY_OPTIONS = 2048; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_table_options + const NO_TABLE_OPTIONS = 4096; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_unsigned_subtraction + const NO_UNSIGNED_SUBTRACTION = 8192; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_zero_date + const NO_ZERO_DATE = 16384; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_zero_in_date + const NO_ZERO_IN_DATE = 32768; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_only_full_group_by + const ONLY_FULL_GROUP_BY = 65536; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_pipes_as_concat + const PIPES_AS_CONCAT = 131072; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_real_as_float + const REAL_AS_FLOAT = 262144; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_strict_all_tables + const STRICT_ALL_TABLES = 524288; + + // https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_strict_trans_tables + const STRICT_TRANS_TABLES = 1048576; + + /* + * Combination SQL Modes + * https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sql-mode-combo + */ + + // REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE + const SQL_MODE_ANSI = 393234; + + // PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, + // NO_TABLE_OPTIONS, NO_FIELD_OPTIONS, + const SQL_MODE_DB2 = 138258; + + // PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, + // NO_TABLE_OPTIONS, NO_FIELD_OPTIONS, NO_AUTO_CREATE_USER + const SQL_MODE_MAXDB = 138290; + + // PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, + // NO_TABLE_OPTIONS, NO_FIELD_OPTIONS + const SQL_MODE_MSSQL = 138258; + + // PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, + // NO_TABLE_OPTIONS, NO_FIELD_OPTIONS, NO_AUTO_CREATE_USER + const SQL_MODE_ORACLE = 138290; + + // PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, + // NO_TABLE_OPTIONS, NO_FIELD_OPTIONS + const SQL_MODE_POSTGRESQL = 138258; + + // STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, + // ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER + const SQL_MODE_TRADITIONAL = 1622052; + + // ------------------------------------------------------------------------- + // Keyword. + + /** + * Checks if the given string is a keyword. + * + * @param string $str + * @param bool $strict + * + * @return bool + */ + public static function isKeyword($str, $strict = false) + { + $str = strtoupper($str); + + if (isset(static::$KEYWORDS[$str])) { + return $strict ? static::$KEYWORDS[$str] === 1 : true; + } + + return false; + } + + // ------------------------------------------------------------------------- + // Operator. + + /** + * Checks if the given string is an operator. + * + * @param string $str + * + * @return int The appropriate flag for the operator. + */ + public static function isOperator($str) + { + if (!isset(static::$OPERATORS[$str])) { + return null; + } + return static::$OPERATORS[$str]; + } + + // ------------------------------------------------------------------------- + // Whitespace. + + /** + * Checks if the given character is a whitespace. + * + * @param string $ch + * + * @return bool + */ + public static function isWhitespace($ch) + { + return ($ch === ' ') || ($ch === "\r") || ($ch === "\n") || ($ch === "\t"); + } + + // ------------------------------------------------------------------------- + // Comment. + + /** + * Checks if the given string is the beginning of a whitespace. + * + * @param string $str + * + * @return int The appropriate flag for the comment type. + */ + public static function isComment($str) + { + $len = strlen($str); + if ($str[0] === '#') { + return Token::FLAG_COMMENT_BASH; + } elseif (($len > 1) && ((($str[0] === '/') && ($str[1] === '*')) || + (($str[0] === '*') && ($str[1] === '/')))) { + return Token::FLAG_COMMENT_C; + } elseif (($len > 2) && ($str[0] === '-') && + ($str[1] === '-') && ($str[2] !== "\n") && + (static::isWhitespace($str[2]))) { + return Token::FLAG_COMMENT_SQL; + } + return null; + } + + // ------------------------------------------------------------------------- + // Bool. + + /** + * Checks if the given string is a boolean value. + * This actually check only for `TRUE` and `FALSE` because `1` or `0` are + * actually numbers and are parsed by specific methods. + * + * @param string $ch + * + * @return bool + */ + public static function isBool($ch) + { + $ch = strtoupper($ch); + return ($ch === 'TRUE') || ($ch === 'FALSE'); + } + + // ------------------------------------------------------------------------- + // Number. + + /** + * Checks if the given character can be a part of a number. + * + * @param string $ch + * + * @return bool + */ + public static function isNumber($ch) + { + return (($ch >= '0') && ($ch <= '9')) || ($ch === '.') || + ($ch === '-') || ($ch === '+') || ($ch === 'e') || ($ch === 'E'); + } + + // ------------------------------------------------------------------------- + // Symbol. + + /** + * Checks if the given character is the beginning of a symbol. A symbol + * can be either a variable or a field name. + * + * @param string $ch + * + * @return int The appropriate flag for the symbol type. + */ + public static function isSymbol($ch) + { + if ($ch[0] === '@') { + return Token::FLAG_SYMBOL_VARIABLE; + } elseif ($ch[0] === '`') { + return Token::FLAG_SYMBOL_BACKTICK; + } + return null; + } + + // ------------------------------------------------------------------------- + // String. + + /** + * Checks if the given character is the beginning of a string. + * + * @param string $str + * + * @return int The appropriate flag for the string type. + */ + public static function isString($str) + { + if ($str[0] === '\'') { + return Token::FLAG_STRING_SINGLE_QUOTES; + } elseif ($str[0] === '"') { + return Token::FLAG_STRING_DOUBLE_QUOTES; + } + return null; + } + + // ------------------------------------------------------------------------- + // Delimiter. + + /** + * Checks if the given character can be a separator for two lexems. + * + * @param string $ch + * + * @return bool + */ + public static function isSeparator($ch) + { + return !ctype_alnum($ch) && $ch !== '_'; + } +} diff --git a/libraries/sql-parser/src/Exceptions/LexerException.php b/libraries/sql-parser/src/Exceptions/LexerException.php new file mode 100644 index 0000000000..f346d83dca --- /dev/null +++ b/libraries/sql-parser/src/Exceptions/LexerException.php @@ -0,0 +1,41 @@ +ch = $ch; + $this->pos = $pos; + } +} diff --git a/libraries/sql-parser/src/Exceptions/ParserException.php b/libraries/sql-parser/src/Exceptions/ParserException.php new file mode 100644 index 0000000000..e23d03daf7 --- /dev/null +++ b/libraries/sql-parser/src/Exceptions/ParserException.php @@ -0,0 +1,32 @@ +token = $token; + } +} diff --git a/libraries/sql-parser/src/Fragment.php b/libraries/sql-parser/src/Fragment.php new file mode 100644 index 0000000000..e9a4620527 --- /dev/null +++ b/libraries/sql-parser/src/Fragment.php @@ -0,0 +1,30 @@ + 1 + * + * 1 ------------------[ array element ]-----------------> 2 + * + * 2 ------------------------[ , ]-----------------------> 1 + * 2 ------------------------[ ) ]-----------------------> -1 + * + * @var int + */ + $state = 0; + + for (; $list->idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + if ($state === 0) { + if (($token->type !== Token::TYPE_OPERATOR) || ($token->value !== '(')) { + $parser->error('An open bracket was expected.', $token); + break; + } + $state = 1; + } elseif ($state === 1) { + if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ')')) { + // Empty array. + break; + } + $ret->array[] = $token->value; + $ret->tokens[] = $token; + $state = 2; + } elseif ($state === 2) { + if (($token->type !== Token::TYPE_OPERATOR) || (($token->value !== ',') && ($token->value !== ')'))) { + $parser->error('Symbols \')\' or \',\' were expected', $token); + break; + } + if ($token->value === ',') { + $state = 1; + } else { // ) + break; + } + } + + } + + return $ret; + } +} diff --git a/libraries/sql-parser/src/Fragments/CallKeyword.php b/libraries/sql-parser/src/Fragments/CallKeyword.php new file mode 100644 index 0000000000..00b7838e71 --- /dev/null +++ b/libraries/sql-parser/src/Fragments/CallKeyword.php @@ -0,0 +1,86 @@ + 1 + * + * 1 --------------------[ parameters ]-------------------> -1 + * + * @var int + */ + $state = 0; + + for (; $list->idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + if ($state === 0) { + $ret->name = $token->value; + $ret->tokens[] = $token; + $state = 1; + } elseif ($state === 1) { + if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { + $parameters = ArrayFragment::parse($parser, $list); + $ret->parameters = $parameters->array; + $ret->tokens = array_merge($ret->tokens, $parameters->tokens); + } + break; + } + + } + + return $ret; + } +} diff --git a/libraries/sql-parser/src/Fragments/CreateDefFragment.php b/libraries/sql-parser/src/Fragments/CreateDefFragment.php new file mode 100644 index 0000000000..708ce11b85 --- /dev/null +++ b/libraries/sql-parser/src/Fragments/CreateDefFragment.php @@ -0,0 +1,108 @@ + array(1, 'var'), + 'AUTO_INCREMENT' => array(2, 'var'), + 'AVG_ROW_LENGTH' => array(3, 'var'), + 'DEFAULT CHARACTER SET' => array(4, 'var'), + 'CHARACTER SET' => array(4, 'var'), + 'CHECKSUM' => array(5, 'var'), + 'DEFAULT COLLATE' => array(5, 'var'), + 'COLLATE' => array(6, 'var'), + 'COMMENT' => array(7, 'var'), + 'CONNECTION' => array(8, 'var'), + 'DATA DIRECTORY' => array(9, 'var'), + 'DELAY_KEY_WRITE' => array(10, 'var'), + 'INDEX DIRECTORY' => array(11, 'var'), + 'INSERT_METHOD' => array(12, 'var'), + 'KEY_BLOCK_SIZE' => array(13, 'var'), + 'MAX_ROWS' => array(14, 'var'), + 'MIN_ROWS' => array(15, 'var'), + 'PACK_KEYS' => array(16, 'var'), + 'PASSWORD' => array(17, 'var'), + 'ROW_FORMAT' => array(18, 'var'), + 'TABLESPACE' => array(19, 'var'), + 'STORAGE' => array(20, 'var'), + 'UNION' => array(21, 'var'), + ); + + /** + * All function options. + * + * @var array + */ + public static $FUNC_OPTIONS = array( + 'COMMENT' => array(1, 'var'), + 'LANGUAGE SQL' => 2, + 'DETERMINISTIC' => 3, + 'NOT DETERMINISTIC' => 3, + 'CONSTAINS SQL' => 4, + 'NO SQL' => 4, + 'READS SQL DATA' => 4, + 'MODIFIES SQL DATA' => 4, + 'SQL SEQURITY DEFINER' => array(5, 'var'), + ); + + /** + * The name of the new table. + * + * @var string + */ + public $name; + + /** + * @param Parser $parser + * @param TokensList $list + * @param array $options + * + * @return CreateDefFragment + */ + public static function parse(Parser $parser, TokensList $list, array $options = array()) + { + $ret = new CreateDefFragment(); + + for (; $list->idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { + break; + } + + $ret->tokens[] = $token; + $ret->name .= $token->value; + } + + --$list->idx; + return $ret; + } +} diff --git a/libraries/sql-parser/src/Fragments/DataTypeFragment.php b/libraries/sql-parser/src/Fragments/DataTypeFragment.php new file mode 100644 index 0000000000..a5c8eca7de --- /dev/null +++ b/libraries/sql-parser/src/Fragments/DataTypeFragment.php @@ -0,0 +1,109 @@ + 1, + 'CHARACTER SET' => array(2, 'var'), + 'CHARSET' => array(3, 'var'), + 'COLLATE' => 4, + 'UNSIGNED' => 5, + 'ZEROFILL' => 6, + ); + + /** + * The name of the data type. + * + * @var string + */ + public $name; + + /** + * The size of this data type. + * + * @var array + */ + public $size = array(); + + /** + * The options of this data type. + * + * @var OptionsFragment + */ + public $options = array(); + + /** + * @param Parser $parser + * @param TokensList $list + * @param array $options + * + * @return DataTypeFragment[] + */ + public static function parse(Parser $parser, TokensList $list, array $options = array()) + { + $ret = new DataTypeFragment(); + + /** + * The state of the parser. + * + * Below are the states of the parser. + * + * 0 -------------------[ data type ]--------------------> 1 + * + * 1 ----------------[ size and options ]----------------> 2 + * + * @var int + */ + $state = 0; + + for (; $list->idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + if ($state === 0) { + $ret->name = $token->value; + $ret->tokens[] = $token; + if (!isset(Context::$DATA_TYPES[$token->value])) { + $parser->error('Unrecognized data type.', $token); + } + $state = 1; + } elseif ($state === 1) { + if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { + $size = ArrayFragment::parse($parser, $list); + $ret->size = $size->array; + $ret->tokens = array_merge($ret->tokens, $size->tokens); + ++$list->idx; + } + $ret->options = OptionsFragment::parse($parser, $list, static::$OPTIONS); + ++$list->idx; + break; + } + + } + + if (empty($ret->name)) { + return null; + } + + --$list->idx; + return $ret; + } +} diff --git a/libraries/sql-parser/src/Fragments/FieldDefFragment.php b/libraries/sql-parser/src/Fragments/FieldDefFragment.php new file mode 100644 index 0000000000..fe941849a5 --- /dev/null +++ b/libraries/sql-parser/src/Fragments/FieldDefFragment.php @@ -0,0 +1,181 @@ + 1, + 'NULL' => 1, + 'DEFAULT' => array(2, 'var'), + 'AUTO_INCREMENT' => 3, + 'PRIMARY' => 4, + 'PRIMARY KEY' => 4, + 'UNIQUE' => 4, + 'UNIQUE KEY' => 4, + 'COMMENT' => array(5, 'var'), + 'COLUMN_FORMAT' => array(6, 'var'), + ); + + /** + * The name of the new column. + * + * @var string + */ + public $name; + + /** + * The data type of thew new column. + * + * @var DataTypeFragment + */ + public $type; + + /** + * The array of indexes. + * + * @var array + */ + public $indexes = array(); + + /** + * The options of the new field fragment. + * + * @var OptionsFragment + */ + public $options; + + /** + * @param Parser $parser + * @param TokensList $list + * @param array $options + * + * @return FieldDefFragment[] + */ + public static function parse(Parser $parser, TokensList $list, array $options = array()) + { + $ret = array(); + + $expr = new FieldDefFragment(); + + /** + * The state of the parser. + * + * Below are the states of the parser. + * + * 0 -----------------------[ ( ]------------------------> 1 + * + * 1 -------------------[ CONSTRAINT ]-------------------> 4 + * 1 --------------------[ key type ]--------------------> 5 + * 1 -------------------[ column name ]------------------> 2 + * + * 2 -------------------[ data type ]--------------------> 3 + * + * 3 ---------------------[ size ]---------------------> 3 + * 3 ---------------------[ options ]--------------------> 4 + * + * 4 -----------------[ CONSTRAINT name ]----------------> 4 + * 4 -----------------[ CONSTRAINT type ]----------------> 5 + * + * 5 -------------------[ index names ]------------------> 6 + * + * 6 ------------------------[ , ]-----------------------> 1 + * 6 ------------------------[ ) ]-----------------------> -1 + * + * @var int + */ + $state = 0; + + for (; $list->idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + if ($state === 0) { + if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { + $state = 1; + } + continue; + } elseif ($state === 1) { + if ($token->type === Token::TYPE_KEYWORD) { + if ($token->value === 'CONSTRAINT') { + $state = 4; + } elseif (isset(Context::$KEY_TYPES[$token->value])) { + $expr->type = $token->value; + $state = 5; + } else { + $parser->error('Unexpected keyword.', $token); + break; // TODO: Skip to the end of the query. + } + } else { + $expr->name = $token->value; + $state = 2; + } + } elseif ($state === 2) { + $expr->type = DataTypeFragment::parse($parser, $list); + $state = 3; + } elseif ($state === 3) { + $expr->options = OptionsFragment::parse($parser, $list, static::$FIELD_OPTIONS); + $state = 6; + } elseif ($state === 4) { + if (!isset(Context::$KEY_TYPES[$token->value])) { + $expr->name = $token->value; + } else { + $expr->type = $token->value; + $state = 5; + } + } elseif ($state === 5) { + $expr->indexes = ArrayFragment::parse($parser, $list); + $state = 6; + } elseif ($state === 6) { + $ret[] = $expr; + $expr = new FieldDefFragment(); + if ($token->value === ',') { + $state = 1; + continue; + } elseif ($token->value === ')') { + ++$list->idx; + break; + } + } + + $expr->tokens[] = $token; + } + + // Last iteration was not saved. + if (!empty($expr->tokens)) { + $ret[] = $expr; + } + + --$list->idx; + return $ret; + + } +} diff --git a/libraries/sql-parser/src/Fragments/FieldFragment.php b/libraries/sql-parser/src/Fragments/FieldFragment.php new file mode 100644 index 0000000000..71e1066a65 --- /dev/null +++ b/libraries/sql-parser/src/Fragments/FieldFragment.php @@ -0,0 +1,173 @@ +idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + if (($isExpr) && (!$alias)) { + $ret->expr .= $token->token; + $ret->tokens[] = $token; + } + if (($alias === 0) && (!$isExpr) && (!$period) && (!empty($ret->expr))) { + $alias = 1; + } + continue; + } + + if ($token->type === Token::TYPE_KEYWORD) { + // Keywords may be found only between brackets. + if ($brackets === 0) { + if ($token->value === 'AS') { + $alias = 2; + continue; + } + break; + } + } + + if ($token->type === Token::TYPE_OPERATOR) { + if ($token->value === '(') { + ++$brackets; + $isExpr = true; + } elseif ($token->value === ')') { + --$brackets; + if ($brackets < 0) { + $parser->error('Unexpected bracket.', $token); + $brackets = 0; + } + } elseif ($token->value === ',') { + if ($brackets === 0) { + break; + } + } + } + + if (($token->type === Token::TYPE_NUMBER) || ($token->type === Token::TYPE_BOOL) || + (($token->type === Token::TYPE_SYMBOL) && ($token->flags & Token::FLAG_SYMBOL_VARIABLE)) || + (($token->type === Token::TYPE_OPERATOR)) && ($token->value !== '.')) { + // Numbers, booleans and operators are usually part of expressions. + $isExpr = true; + } + + if ($alias) { + $ret->alias = $token->value; + $alias = 0; + } else { + if (!$isExpr) { + if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '.')) { + $ret->database = $ret->table; + $ret->table = $ret->column; + $period = true; + } else { + if (!empty($options['skipColumn'])) { + $ret->table = $token->value; + } else { + $ret->column = $token->value; + } + $period = false; + } + } else { + if ($brackets === 0) { + if (($token->type === Token::TYPE_NONE) || ($token->type === Token::TYPE_STRING) || + (($token->type === Token::TYPE_SYMBOL) && ($token->flags & Token::FLAG_SYMBOL_BACKTICK))) { + $ret->alias = $token->value; + } + } + } + + $ret->expr .= $token->token; + $ret->tokens[] = $token; + } + } + + if ($alias === 2) { + $parser->error('Alias was expected.', $token); + } + + if (empty($ret->tokens)) { + return null; + } + + --$list->idx; + return $ret; + } +} diff --git a/libraries/sql-parser/src/Fragments/FromKeyword.php b/libraries/sql-parser/src/Fragments/FromKeyword.php new file mode 100644 index 0000000000..fd11eea68e --- /dev/null +++ b/libraries/sql-parser/src/Fragments/FromKeyword.php @@ -0,0 +1,68 @@ +idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + // No keyword is expected. + if ($token->type === Token::TYPE_KEYWORD) { + break; + } + + if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) { + $ret[] = $expr; + } else { + $expr = FieldFragment::parse($parser, $list, array('skipColumn' => true)); + if ($expr === null) { + break; + } + } + + } + + // Last iteration was not saved. + if (!empty($expr->tokens)) { + $ret[] = $expr; + } + + --$list->idx; + return $ret; + } +} diff --git a/libraries/sql-parser/src/Fragments/IntoKeyword.php b/libraries/sql-parser/src/Fragments/IntoKeyword.php new file mode 100644 index 0000000000..9f6a116eab --- /dev/null +++ b/libraries/sql-parser/src/Fragments/IntoKeyword.php @@ -0,0 +1,108 @@ + 1 + * + * 1 --------------------[ field name ]-------------------> 2 + * + * 2 ------------------------[ , ]------------------------> 1 + * + * @var int + */ + $state = 0; + + for (; $list->idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + // No keyword is expected. + if ($token->type === Token::TYPE_KEYWORD) { + break; + } + + if ($token->type === Token::TYPE_OPERATOR) { + if ($token->value === '(') { + if (empty($ret->table)) { + $parser->error('Table name was expected.', $token); + } + $state = 1; + continue; + } elseif ($token->value === ',') { + if ($state !== 2) { + $parser->error('Field name was expected.', $token); + } + $state = 1; + continue; + } + + // No other operator is expected. + break; + } + + $ret->tokens[] = $token; + if ($state === 0) { + $ret->table .= $token->value; + } elseif ($state === 1) { + $ret->fields[] = $token->value; + $state = 2; + } + + } + + --$list->idx; + return $ret; + } +} diff --git a/libraries/sql-parser/src/Fragments/JoinKeyword.php b/libraries/sql-parser/src/Fragments/JoinKeyword.php new file mode 100644 index 0000000000..62f9ecd0c0 --- /dev/null +++ b/libraries/sql-parser/src/Fragments/JoinKeyword.php @@ -0,0 +1,89 @@ + 1 + * + * 1 ------------------------[ ON ]-----------------------> 2 + * + * 2 --------------------[ conditions ]-------------------> -1 + * + * @var int + */ + $state = 0; + + for (; $list->idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + if ($state === 0) { + $ret->expr = FieldFragment::parse($parser, $list, array('skipColumn' => true)); + $state = 1; + } elseif ($state === 1) { + if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'ON')) { + $state = 2; + } + } elseif ($state === 2) { + $ret->on = WhereKeyword::parse($parser, $list); + ++$list->idx; + break; + } + + } + + --$list->idx; + return $ret; + } +} diff --git a/libraries/sql-parser/src/Fragments/LimitKeyword.php b/libraries/sql-parser/src/Fragments/LimitKeyword.php new file mode 100644 index 0000000000..08fb3a43ef --- /dev/null +++ b/libraries/sql-parser/src/Fragments/LimitKeyword.php @@ -0,0 +1,91 @@ +idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + // NOTE: `OFFSET` is not a keyword. + if (($token->type === Token::TYPE_NONE) && ($token->value === 'OFFSET')) { + if ($offset) { + $parser->error('An offset was expected.'); + } + $offset = true; + continue; + } + + if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) { + $ret->offset = $ret->row_count; + $ret->row_count = 0; + continue; + } + + if ($offset) { + $ret->offset = $token->value; + $offset = false; + } else { + $ret->row_count = $token->value; + } + + $ret->tokens[] = $token; + + } + + if ($offset) { + $parser->error('An offset was expected.'); + } + + --$list->idx; + return $ret; + } +} diff --git a/libraries/sql-parser/src/Fragments/OptionsFragment.php b/libraries/sql-parser/src/Fragments/OptionsFragment.php new file mode 100644 index 0000000000..22661eb989 --- /dev/null +++ b/libraries/sql-parser/src/Fragments/OptionsFragment.php @@ -0,0 +1,136 @@ +idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + if (isset($options[$token->value])) { + $lastOption = $options[$token->value]; + $lastOptionId = is_array($lastOption) ? $lastOption[0] : $lastOption; + + // Checking for option conflicts. + // For example, in `SELECT` statements the keywords `ALL` and `DISTINCT` + // conflict and if used together, they produce an invalid query. + // Usually, tokens can be identified in the array by the option ID, + // but if conflicts occur, a psuedo option ID is used. + // The first pseudo duplicate ID is the maximum value of the real + // options (e.g. if there are 5 options, the first fake ID is 6). + if (isset($ret->options[$lastOptionId])) { + $parser->error('This option conflicts with \'' . $ret->options[$lastOptionId] . '\'.', $token); + $lastOptionId = $lastAssignedId++; + } + } else { + // There is no option to be processed. + if ($lastOption === null) { + break; + } + + // The only keywords that are expected are those which are + // options. + if ($token->type === Token::TYPE_KEYWORD) { + break; + } + + } + + if (is_array($lastOption)) { + if (empty($ret->options[$lastOptionId])) { + $ret->options[$lastOptionId] = array('name' => $token->value, 'value' => ''); + } else { + if ($token->value !== '=') { + if ($token->value === '(') { + ++$brackets; + } elseif ($token->value === ')') { + --$brackets; + } else { + $ret->options[$lastOptionId]['value'] .= $token->value; + } + if ($brackets === 0) { + $lastOption = null; + } + } + } + } else { + $ret->options[$lastOptionId] = $token->value; + $lastOption = null; + } + $ret->tokens[] = $token; + + } + + ksort($ret->options); + + --$list->idx; + return $ret; + } + + /** + * Checks if it has the specified option and returns it value or true. + * + * @param string $key + * + * @return mixed + */ + public function has($key) + { + foreach ($this->options as $option) { + if ((is_array($option)) && ($key === $option['name'])) { + return $option['value']; + } elseif ($key === $option) { + return true; + } + } + return false; + } +} diff --git a/libraries/sql-parser/src/Fragments/OrderKeyword.php b/libraries/sql-parser/src/Fragments/OrderKeyword.php new file mode 100644 index 0000000000..5ddc8efb75 --- /dev/null +++ b/libraries/sql-parser/src/Fragments/OrderKeyword.php @@ -0,0 +1,90 @@ +idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + if ($token->type === Token::TYPE_KEYWORD) { + // Type of ordering. By default, it is `ASC`. + if (($token->value === 'ASC') || ($token->value === 'DESC')) { + $expr->type = $token->value; + $expr->tokens[] = $token; + continue; + } + + // No other keyword is expected. + break; + } + + // Saving field. + if (($token->type === Token::TYPE_OPERATOR) && ($token->token === ',')) { + $ret[] = $expr; + $expr = new OrderKeyword(); + continue; + } + + $expr->tokens[] = $token; + $expr->column .= $token->token; + + } + + // Last iteration was not processed. + if (!empty($expr->tokens)) { + $ret[] = $expr; + } + + --$list->idx; + return $ret; + } +} diff --git a/libraries/sql-parser/src/Fragments/ParamDefFragment.php b/libraries/sql-parser/src/Fragments/ParamDefFragment.php new file mode 100644 index 0000000000..05bad6e663 --- /dev/null +++ b/libraries/sql-parser/src/Fragments/ParamDefFragment.php @@ -0,0 +1,128 @@ + 1 + * + * 1 ----------------[ IN / OUT / INOUT ]----------------> 1 + * 1 ----------------------[ name ]----------------------> 2 + * + * 2 -------------------[ data type ]--------------------> 3 + * + * 3 ------------------------[ , ]-----------------------> 1 + * 3 ------------------------[ ) ]-----------------------> -1 + * + * @var int + */ + $state = 0; + + for (; $list->idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + if ($state === 0) { + if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { + $state = 1; + } + continue; + } elseif ($state === 1) { + if (($token->value === 'IN') || ($token->value === 'OUT') || ($token->value === 'INOUT')) { + $expr->inOut = $token->value; + ++$list->idx; + } else if ($token->value === ')') { + ++$list->idx; + break; + } else { + $expr->name = $token->value; + $state = 2; + } + } elseif ($state === 2) { + $expr->type = DataTypeFragment::parse($parser, $list); + $state = 3; + } elseif ($state === 3) { + $ret[] = $expr; + $expr = new ParamDefFragment(); + if ($token->value === ',') { + $state = 1; + continue; + } elseif ($token->value === ')') { + ++$list->idx; + break; + } + } + + $expr->tokens[] = $token; + } + + // Last iteration was not saved. + if (!empty($expr->tokens)) { + $ret[] = $expr; + } + + --$list->idx; + return $ret; + + } +} diff --git a/libraries/sql-parser/src/Fragments/RenameKeyword.php b/libraries/sql-parser/src/Fragments/RenameKeyword.php new file mode 100644 index 0000000000..7841b2ac77 --- /dev/null +++ b/libraries/sql-parser/src/Fragments/RenameKeyword.php @@ -0,0 +1,117 @@ + 1 + * + * 1 ------------------------[ TO ]-----------------------> 2 + * + * 2 ---------------------[ old name ]--------------------> 3 + * + * 3 ------------------------[ , ]------------------------> 0 + * 3 -----------------------[ else ]----------------------> -1 + * + * @var int + */ + $state = 0; + + for (; $list->idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + if ($token->type === Token::TYPE_KEYWORD) { + if (($state === 1) && ($token->value === 'TO')) { + $state = 2; + continue; + } + + // No other keyword is expected. + break; + } + + if ($token->type === Token::TYPE_OPERATOR) { + if (($state === 3) && ($token->value === ',')) { + $ret[] = $expr; + $expr = new RenameKeyword(); + $state = 0; + continue; + } + + // No other operator is expected. + break; + } + + $expr->tokens[] = $token; + if ($state == 0) { + $expr->old = $token->value; + $state = 1; + } elseif ($state == 2) { + $expr->new = $token->value; + $state = 3; + } + + } + + // Last iteration was not saved. + if (!empty($expr->tokens)) { + $ret[] = $expr; + } + + --$list->idx; + return $ret; + } +} diff --git a/libraries/sql-parser/src/Fragments/SelectKeyword.php b/libraries/sql-parser/src/Fragments/SelectKeyword.php new file mode 100644 index 0000000000..dc8db950be --- /dev/null +++ b/libraries/sql-parser/src/Fragments/SelectKeyword.php @@ -0,0 +1,68 @@ +idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + if ($token->type === Token::TYPE_KEYWORD) { + // No keyword is expected. + break; + } + + if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) { + $ret[] = $expr; + } else { + $expr = FieldFragment::parse($parser, $list); + if ($expr === null) { + break; + } + } + + } + + // Last iteration was not processed. + if (!empty($expr->tokens)) { + $ret[] = $expr; + } + + --$list->idx; + return $ret; + } +} diff --git a/libraries/sql-parser/src/Fragments/SetKeyword.php b/libraries/sql-parser/src/Fragments/SetKeyword.php new file mode 100644 index 0000000000..1e70f27e2d --- /dev/null +++ b/libraries/sql-parser/src/Fragments/SetKeyword.php @@ -0,0 +1,105 @@ + 1 + * + * 1 ------------------------[ , ]------------------------> 0 + * 1 ----------------------[ value ]----------------------> 1 + * + * @var int + */ + $state = 0; + + for (; $list->idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + // No keyword is expected. + if ($token->type === Token::TYPE_KEYWORD) { + break; + } + + if ($token->type === Token::TYPE_OPERATOR) { + if ($token->value === ',') { + $ret[] = $expr; + $expr = new SetKeyword(); + $state = 0; + continue; + } elseif ($token->value === '=') { + $state = 1; + } + } + + $expr->tokens[] = $token; + if ($state === 0) { + $expr->column .= $token->value; + } else { // } else if ($state === 1) { + $expr->value = $token->value; + } + + } + + // Last iteration was not saved. + if (!empty($expr->tokens)) { + $ret[] = $expr; + } + + --$list->idx; + return $ret; + } +} diff --git a/libraries/sql-parser/src/Fragments/ValuesKeyword.php b/libraries/sql-parser/src/Fragments/ValuesKeyword.php new file mode 100644 index 0000000000..c6bd551772 --- /dev/null +++ b/libraries/sql-parser/src/Fragments/ValuesKeyword.php @@ -0,0 +1,115 @@ + 1 + * + * 1 ----------------------[ value ]---------------------> 2 + * + * 2 ------------------------[ , ]-----------------------> 1 + * 2 ------------------------[ ) ]-----------------------> 3 + * + * 3 ---------------------[ options ]--------------------> 4 + * + * @var int + */ + $state = 0; + + for (; $list->idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + // No keyword is expected. + if ($token->type === Token::TYPE_KEYWORD) { + break; + } + + if ($token->type === Token::TYPE_OPERATOR) { + if ($token->value === '(') { + $state = 1; + continue; + } elseif ($token->value === ',') { + if ($state !== 3) { + $expr->values[] = $value; + $value = ''; + $state = 1; + } + continue; + } elseif ($token->value === ')') { + $state = 3; + $expr->values[] = $value; + $ret[] = $expr; + $value = ''; + $expr = new ValuesKeyword(); + continue; + } + + // No other operator is expected. + break; + } + + $expr->tokens[] = $token; + if ($state === 1) { + $value .= $token->value; + $state = 2; + } + + } + + // Last iteration was not saved. + if (!empty($expr->tokens)) { + $ret[] = $expr; + } + + --$list->idx; + return $ret; + } +} diff --git a/libraries/sql-parser/src/Fragments/WhereKeyword.php b/libraries/sql-parser/src/Fragments/WhereKeyword.php new file mode 100644 index 0000000000..786efbfa9a --- /dev/null +++ b/libraries/sql-parser/src/Fragments/WhereKeyword.php @@ -0,0 +1,100 @@ +idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + // Conditions are delimited by logical operators. + if (in_array($token->value, static::$OPERATORS, true)) { + if (!empty($expr->tokens)) { + $ret[] = $expr; + } + + $expr = new WhereKeyword(); + $expr->isOperator = true; + $expr->condition = $token->value; + $epxr->tokens[] = $token; + $ret[] = $expr; + + $expr = new WhereKeyword(); + + continue; + } + + // No keyword is expected. + if ($token->type === Token::TYPE_KEYWORD) { + break; + } + + $expr->tokens[] = $token; + $expr->condition .= $token->token; + + } + + // Last iteration was not processed. + if (!empty($expr->tokens)) { + $ret[] = $expr; + } + + --$list->idx; + return $ret; + } +} diff --git a/libraries/sql-parser/src/Lexer.php b/libraries/sql-parser/src/Lexer.php new file mode 100644 index 0000000000..238d63b1f8 --- /dev/null +++ b/libraries/sql-parser/src/Lexer.php @@ -0,0 +1,578 @@ +str = $str; + $this->len = ($str instanceof UtfString) ? + $str->length() : strlen($str); + $this->strict = $strict; + $this->lex(); + } + + /** + * Parses the string and extracts lexems. + * + * @param string|UtfString $str + */ + public function lex() + { + // TODO: Sometimes, static::parse* functions make unnecessary calls to + // is* functions. For a better performance, some rules can be deduced + // from context. + // For example, in `parseBool` there is no need to compare the token + // every time with `true` and `false`. The first step would be to + // compare with 'true' only and just after that add another letter from + // context and compare again with `false`. + // Another example is `parseComment`. + + $tokens = new TokensList(); + $lastToken = NULL; + + for ($this->last = 0, $lastIdx = 0; $this->last < $this->len; $lastIdx = ++$this->last) { + /** @var Token The new token. */ + $token = null; + + foreach (static::$PARSER_METHODS as $method) { + if (($token = $this->$method())) { + break; + } + } + + if ($token === null) { + // @assert($this->last === $lastIdx); + $token = new Token($this->str[$this->last]); + if ($this->delimiter !== $this->str[$this->last]) { + $this->error('Unexpected character.', $this->str[$this->last], $this->last); + } + } else if (($token->type === Token::TYPE_SYMBOL) && ($token->flags & Token::FLAG_SYMBOL_VARIABLE) && + ($lastToken !== NULL)) { + // Handles ```... FROM 'user'@'%' ...```. + if ((($lastToken->type === Token::TYPE_SYMBOL) && ($lastToken->flags & Token::FLAG_SYMBOL_BACKTICK)) || + ($lastToken->type === Token::TYPE_STRING)) { + $lastToken->token .= $token->token; + $lastToken->type = Token::TYPE_SYMBOL; + $lastToken->flags = Token::FLAG_SYMBOL_USER; + $lastToken->value .= '@' . $token->value; + continue; + } + } + $token->position = $lastIdx; + + $tokens->tokens[$tokens->count++] = $token; + + // Handling delimiters. + if ($this->delimiter === '') { + // Updating the delimiter. + if ($token->type !== Token::TYPE_WHITESPACE) { + $this->delimiter = $token->value; + } + } elseif ($token->value === 'DELIMITER') { + // `DELIMITER` keyword found, looking for a delimiter. + $this->delimiter = ''; + } + + // Overwriting token if delimiter. + if ($token->value === $this->delimiter) { + $token->type = Token::TYPE_DELIMITER; + $token->flags = 0; + } + + $lastToken = $token; + } + + // Adding a final delimite at the end to mark the ending. + $tokens->tokens[$tokens->count++] = new Token(null, Token::TYPE_DELIMITER); + + // Saving the tokens list. + $this->tokens = $tokens; + } + + /** + * Creates a new error log. + * + * @param string $msg + * @param string $str + * @param int $code + */ + public function error($msg = '', $str = '', $pos = 0, $code = 0) + { + $error = new LexerException($msg, $str, $pos, $code); + if ($this->strict) { + throw $error; + } + $this->errors[] = $error; + } + + /** + * Parses a keyword. + * + * @return Token + */ + public function parseKeyword() + { + $token = ''; + + /** @var Token Value to be returned. */ + $ret = null; + + /** @var int The value of `$this->last` where `$token` ends in `$this->str`. */ + $iEnd = $this->last; + + for ($j = 1; $j < Context::KEYWORD_MAX_LENGTH && $this->last < $this->len; ++$j, ++$this->last) { + $token .= $this->str[$this->last]; + if (($this->last + 1 === $this->len) || (Context::isSeparator($this->str[$this->last + 1]))) { + if (Context::isKeyword($token)) { + $ret = new Token($token, Token::TYPE_KEYWORD); + $iEnd = $this->last; + // We don't break so we find longest keyword. + // For example, `OR` and `ORDER` have a common prefix `OR`. + // If we stopped at `OR`, the parsing would be invalid. + } + } + } + + $this->last = $iEnd; + return $ret; + } + + /** + * Parses an operator. + * + * @return Token + */ + public function parseOperator() + { + $token = ''; + + /** @var Token|bool Value to be returned. */ + $ret = false; + + /** @var int The value of `$this->last` where `$token` ends in `$this->str`. */ + $iEnd = $this->last; + + for ($j = 1; $j < Context::OPERATOR_MAX_LENGTH && $this->last < $this->len; ++$j, ++$this->last) { + $token .= $this->str[$this->last]; + if ($flags = Context::isOperator($token)) { + $ret = new Token($token, Token::TYPE_OPERATOR, $flags); + $iEnd = $this->last; + } + } + + $this->last = $iEnd; + return $ret; + } + + /** + * Parses a whitespace. + * + * @return Token + */ + public function parseWhitespace() + { + $token = $this->str[$this->last]; + + if (!Context::isWhitespace($token)) { + return null; + } + + while ((++$this->last < $this->len) && (Context::isWhitespace($this->str[$this->last]))) { + $token .= $this->str[$this->last]; + } + + --$this->last; + return new Token($token, Token::TYPE_WHITESPACE); + } + + /** + * Parses a comment. + * + * @return Token + */ + public function parseComment() + { + $iBak = $this->last; + $token = $this->str[$this->last]; + + // Bash style comments. (#comment\n) + if (Context::isComment($token)) { + while ((++$this->last < $this->len) && ($this->str[$this->last] !== "\n")) { + $token .= $this->str[$this->last]; + } + $token .= $this->str[$this->last]; + return new Token($token, Token::TYPE_COMMENT, Token::FLAG_COMMENT_BASH); + } + + // C style comments. (/*comment*\/) + if (++$this->last < $this->len) { + $token .= $this->str[$this->last]; + if (Context::isComment($token)) { + $flags = Token::FLAG_COMMENT_C; + if (($this->last + 1 < $this->len) && ($this->str[$this->last + 1] === '!')) { + // It is a MySQL-specific command. + $flags |= Token::FLAG_COMMENT_MYSQL_CMD; + } + while ((++$this->last < $this->len) && + (($this->str[$this->last - 1] !== '*') || ($this->str[$this->last] !== '/'))) { + $token .= $this->str[$this->last]; + } + $token .= $this->str[$this->last]; + return new Token($token, Token::TYPE_COMMENT, $flags); + } + } + + // SQL style comments. (-- comment\n) + if (++$this->last < $this->len) { + $token .= $this->str[$this->last]; + if (Context::isComment($token)) { + if ($this->str[$this->last] !== "\n") { + // Checking if this comment did not end already (```--\n```). + while ((++$this->last < $this->len) && ($this->str[$this->last] !== "\n")) { + $token .= $this->str[$this->last]; + } + if ($this->last < $this->len) { + $token .= $this->str[$this->last]; + } + } + return new Token($token, Token::TYPE_COMMENT, Token::FLAG_COMMENT_SQL); + } + } + + $this->last = $iBak; + return null; + } + + /** + * Parses a boolean. + * + * @return Token + */ + public function parseBool() + { + if ($this->last + 3 >= $this->len) { + // At least `min(strlen('TRUE'), strlen('FALSE'))` characters are + // required. + return null; + } + + $iBak = $this->last; + $token = $this->str[$this->last] . $this->str[++$this->last] + . $this->str[++$this->last] . $this->str[++$this->last]; // _TRUE_ or _FALS_e + + if (Context::isBool($token)) { + return new Token($token, Token::TYPE_BOOL); + } elseif (++$this->last < $this->len) { + $token .= $this->str[$this->last]; // fals_E_ + if (Context::isBool($token)) { + return new Token($token, Token::TYPE_BOOL, 1); + } + } + + $this->last = $iBak; + return null; + } + + /** + * Parses a number. + * + * @return Token + */ + public function parseNumber() + { + // A rudimentary state machine is being used to parse numbers due to + // the various forms of their notation. + // + // Below are the states of the machines and the conditions to change + // the state. + // + // 1 ---------------------[ + or - ]---------------------> 1 + // 1 --------------------[ 0x or 0X ]--------------------> 2 + // 1 ---------------------[ 0 to 9 ]---------------------> 3 + // 1 ------------------------[ . ]-----------------------> 4 + // + // 2 ---------------------[ 0 to F ]---------------------> 2 + // + // 3 ---------------------[ 0 to 9 ]---------------------> 3 + // 3 ------------------------[ . ]-----------------------> 4 + // 3 ---------------------[ e or E ]---------------------> 5 + // + // 4 ---------------------[ 0 to 9 ]---------------------> 4 + // 4 ---------------------[ e or E ]---------------------> 5 + // + // 5 ----------------[ + or - or 0 to 9 ]----------------> 6 + // + // State 1 may be reached by negative numbers. + // State 2 is reached only by hex numbers. + // State 4 is reached only by float numbers. + // State 5 is reached only by numbers in approximate form. + // + // Valid final states are: 2, 3, 4 and 6. Any parsing that finished in a + // state other than these is invalid. + $iBak = $this->last; + $token = ''; + $flags = 0; + $state = 1; + for (; $this->last < $this->len; ++$this->last) { + if ($state === 1) { + if ($this->str[$this->last] === '+') { + // Do nothing. + } elseif ($this->str[$this->last] === '-') { + $flags |= Token::FLAG_NUMBER_NEGATIVE; + // Do nothing. + } elseif (($this->str[$this->last] === '0') && ($this->last + 1 < $this->len) && + (($this->str[$this->last + 1] === 'x') || ($this->str[$this->last + 1] === 'X'))) { + $token .= $this->str[$this->last++]; + $state = 2; + } elseif (($this->str[$this->last] >= '0') && ($this->str[$this->last] <= '9')) { + $state = 3; + } elseif ($this->str[$this->last] === '.') { + $state = 4; + } else { + break; + } + } elseif ($state === 2) { + $flags |= Token::FLAG_NUMBER_HEX; + if ((($this->str[$this->last] >= '0') && ($this->str[$this->last] <= '9')) || + (($this->str[$this->last] >= 'A') && ($this->str[$this->last] <= 'F')) || + (($this->str[$this->last] >= 'a') && ($this->str[$this->last] <= 'f'))) { + // Do nothing. + } else { + break; + } + } elseif ($state === 3) { + if (($this->str[$this->last] >= '0') && ($this->str[$this->last] <= '9')) { + // Do nothing. + } elseif ($this->str[$this->last] === '.') { + $state = 4; + } elseif (($this->str[$this->last] === 'e') || ($this->str[$this->last] === 'E')) { + $state = 5; + } else { + break; + } + } elseif ($state === 4) { + $flags |= Token::FLAG_NUMBER_FLOAT; + if (($this->str[$this->last] >= '0') && ($this->str[$this->last] <= '9')) { + // Do nothing. + } elseif (($this->str[$this->last] === 'e') || ($this->str[$this->last] === 'E')) { + $state = 5; + } else { + break; + } + } elseif ($state === 5) { + $flags |= Token::FLAG_NUMBER_APPROXIMATE; + if (($this->str[$this->last] === '+') || ($this->str[$this->last] === '-') || + ((($this->str[$this->last] >= '0') && ($this->str[$this->last] <= '9')))) { + $state = 6; + } else { + break; + } + } elseif ($state === 6) { + if (($this->str[$this->last] >= '0') && ($this->str[$this->last] <= '9')) { + // Do nothing. + } else { + break; + } + } + $token .= $this->str[$this->last]; + } + if (($state === 2) || ($state === 3) || (($token !== '.') && ($state === 4)) || ($state === 6)) { + --$this->last; + return new Token($token, Token::TYPE_NUMBER, $flags); + } + $this->last = $iBak; + return null; + } + + /** + * Parses a string. + * + * @param string $quote Additional start symbol. + * + * @return Token + */ + public function parseString($quote = '') + { + $token = $this->str[$this->last]; + if ((!($flags = Context::isString($token))) && ($token !== $quote)) { + return null; + } + $quote = $token; + + while (++$this->last < $this->len) { + if (($this->last + 1 < $this->len) && + ((($this->str[$this->last] === $quote) && ($this->str[$this->last + 1] === $quote)) || + (($this->str[$this->last] === '\\') && ($quote !== '`')))) { + $token .= $this->str[$this->last] . $this->str[++$this->last]; + } else { + if ($this->str[$this->last] === $quote) { + break; + } + $token .= $this->str[$this->last]; + } + } + + if (($this->last >= $this->len) || ($this->str[$this->last] !== $quote)) { + $this->error('Ending quote ' . $quote . ' was expected.', '', $this->last); + } else { + $token .= $this->str[$this->last]; + } + return new Token($token, Token::TYPE_STRING, $flags); + } + + /** + * Parses a symbol. + * + * @return Token + */ + public function parseSymbol() + { + $token = $this->str[$this->last]; + if (!($flags = Context::isSymbol($token))) { + return null; + } + + if ($flags & Token::FLAG_SYMBOL_VARIABLE) { + ++$this->last; + } else { + $token = ''; + } + + if (($str = $this->parseString('`')) === null) { + if (($str = static::parseUnknown()) === null) { + $this->error('Variable name was expected.', $this->str[$this->last], $this->last); + } + } + + if ($str !== null) { + $token .= $str->token; + } + + return new Token($token, Token::TYPE_SYMBOL, $flags); + } + + /** + * Parses unknown parts of the query. + * + * @return Token + */ + public function parseUnknown() + { + $token = $this->str[$this->last]; + if (Context::isSeparator($token)) { + return null; + } + while ((++$this->last < $this->len) && (!Context::isSeparator($this->str[$this->last]))) { + $token .= $this->str[$this->last]; + } + --$this->last; + return new Token($token); + } +} diff --git a/libraries/sql-parser/src/Parser.php b/libraries/sql-parser/src/Parser.php new file mode 100644 index 0000000000..95ecf6cf63 --- /dev/null +++ b/libraries/sql-parser/src/Parser.php @@ -0,0 +1,189 @@ + '', + 'CREATE' => 'SqlParser\\Statements\\CreateStatement', + 'DROP' => '', + 'RENAME' => 'SqlParser\\Statements\\RenameStatement', + 'TRUNCATE' => '', + + // Data Manipulation Statements. + // https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-data-manipulation.html + 'CALL' => 'SqlParser\\Statements\\CallStatement', + 'DELETE' => 'SqlParser\\Statements\\DeleteStatement', + 'DO' => '', + 'HANDLER' => '', + 'INSERT' => 'SqlParser\\Statements\\InsertStatement', + 'LOAD' => '', + 'REPLACE' => 'SqlParser\\Statements\\ReplaceStatement', + 'SELECT' => 'SqlParser\\Statements\\SelectStatement', + 'UPDATE' => 'SqlParser\\Statements\\UpdateStatement', + + // Prepared Statements. + // https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html + 'PREPARE' => '', + 'EXECUTE' => '', + ); + + /** + * Array of classes that are used in parsing SQL fragments. + * + * @var array + */ + public static $KEYWORD_PARSERS = array( + + // Meta-keywords. + '_ARRAY' => 'SqlParser\\Fragments\\ArrayFragment', + '_CALL' => 'SqlParser\\Fragments\\CallKeyword', + '_CREATE_DEF' => 'SqlParser\\Fragments\\CreateDefFragment', + '_DATA_TYPE' => 'SqlParser\\Fragments\\CreateDefFragment', + '_FIELD' => 'SqlParser\\Fragments\\FieldFragment', + '_FIELD_DEF' => 'SqlParser\\Fragments\\FieldDefFragment', + '_OPTIONS' => 'SqlParser\\Fragments\\OptionsFragment', + '_RENAME' => 'SqlParser\\Fragments\\RenameKeyword', + '_SELECT' => 'SqlParser\\Fragments\\SelectKeyword', + + 'FROM' => 'SqlParser\\Fragments\\FromKeyword', + 'GROUP' => 'SqlParser\\Fragments\\GroupFragment', + 'HAVING' => 'SqlParser\\Fragments\\WhereKeyword', + 'INTO' => 'SqlParser\\Fragments\\IntoKeyword', + 'JOIN' => 'SqlParser\\Fragments\\JoinKeyword', + 'LIMIT' => 'SqlParser\\Fragments\\LimitKeyword', + 'ORDER' => 'SqlParser\\Fragments\\OrderKeyword', + 'PARTITION' => 'SqlParser\\Fragments\\ArrayFragment', + 'SET' => 'SqlParser\\Fragments\\SetKeyword', + 'VALUE' => 'SqlParser\\Fragments\\ValuesKeyword', + 'VALUES' => 'SqlParser\\Fragments\\ValuesKeyword', + 'WHERE' => 'SqlParser\\Fragments\\WhereKeyword', + + ); + + /** + * The list of tokens that are parsed. + * + * @var TokensList + */ + public $list; + + /** + * Whether errors should throw exceptions or just be stored. + * + * @var bool + * + * @see static::$errors + */ + public $strict = false; + + /** + * List of errors that occured during parsing. + * + * Usually, the parsing does not stop once an error occured because that + * error might be misdetected or a partial result (even a bad one) might be + * needed. + * + * @var ParserException[] + * + * @see Parser::error() + */ + public $errors = array(); + + /** + * List of statements parsed. + * + * @var Statement[] + */ + public $statements = array(); + + /** + * Constructor. + * + * @param mixed $list + * @param bool $strict + */ + public function __construct($list, $strict = false) + { + if ((is_string($list)) || ($list instanceof UtfString)) { + $lexer = new Lexer($list, $strict); + $this->list = $lexer->tokens; + } elseif ($list instanceof TokensList) { + $this->list = $list; + } + $this->strict = $strict; + $this->parse(); + } + + /** + * Builds the parse trees. + */ + public function parse() + { + $tokens = &$this->list->tokens; + $count = &$this->list->count; + $last = &$this->list->idx; + + for (; $last < $count; ++$last) { + /** @var Token Token parsed at this moment. */ + $token = $tokens[$last]; + + // Statements can start with keywords only. + // Comments, whitespaces, etc. are ignored. + if ($token->type !== Token::TYPE_KEYWORD) { + continue; + } + + // Checking if it is a known statement that can be parsed. + if (empty(static::$STATEMENT_PARSERS[$token->value])) { + $this->error( + 'Unrecognized statement type "' . $token->value .'".', + $token + ); + // TODO: Skip to first delimiter. + continue; + } + + /** @var string The name of the class that is used for parsing. */ + $class = static::$STATEMENT_PARSERS[$token->value]; + + /** @var Statement Processed statement. */ + $stmt = new $class(); + + $stmt->parse($this, $this->list); + $this->statements[] = $stmt; + } + } + + /** + * Creates a new error log. + * + * @param string $str + * @param Token $token + * @param int $code + */ + public function error($str = '', Token $token = null, $code = 0) + { + $error = new ParserException($str, $token, $code); + if ($this->strict) { + throw $error; + } + $this->errors[] = $error; + } +} diff --git a/libraries/sql-parser/src/Statement.php b/libraries/sql-parser/src/Statement.php new file mode 100644 index 0000000000..b1dc2c1064 --- /dev/null +++ b/libraries/sql-parser/src/Statement.php @@ -0,0 +1,145 @@ +idx < $list->count; ++$list->idx) { + /** @var Token Token parsed at this moment. */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Only keywords are relevant here. Other parts of the query are + // processed in the functions below. + if ($token->type !== Token::TYPE_KEYWORD) { + continue; + } + + /** @var string The name of the class that is used for parsing. */ + $class = null; + + if (!empty(Parser::$KEYWORD_PARSERS[$token->value])) { + $class = Parser::$KEYWORD_PARSERS[$token->value]; + } elseif (!empty(Parser::$STATEMENT_PARSERS[$token->value])) { + // The keyword we are processing right now is the beginning of a + // statement and they are usually handled differently. + } else { + $parser->error( + 'Unrecognized keyword "' . $token->value . '".', + $token + ); + continue; + } + + /** @var string The name of the field where the result is stored. */ + $field = strtolower($token->value); + + // Parsing options. + if (($class == null) && (isset(static::$OPTIONS))) { + ++$list->idx; // Skipping keyword. + $this->options = OptionsFragment::parse($parser, $list, static::$OPTIONS); + } + + // Keyword specific code. + if ($token->value === 'CALL') { + ++$list->idx; + $this->call = CallKeyword::parse($parser, $list); + } elseif ($token->value === 'CREATE') { + ++$list->idx; + $this->name = CreateDefFragment::parse($parser, $list); + if ($this->options->has('TABLE')) { + ++$list->idx; + $this->fields = FieldDefFragment::parse($parser, $list); + ++$list->idx; + $this->tableOptions = OptionsFragment::parse($parser, $list, CreateDefFragment::$TABLE_OPTIONS); + } elseif (($this->options->has('PROCEDURE')) || ($this->options->has('FUNCTION'))) { + ++$list->idx; + $this->parameters = ParamDefFragment::parse($parser, $list); + if ($this->options->has('FUNCTION')) { + $token = $list->getNextOfType(Token::TYPE_KEYWORD); + if ($token->value !== 'RETURNS') { + $parser->error('\'RETURNS\' keyword was expected.', $token); + } else { + ++$list->idx; + $this->return = DataTypeFragment::parse($parser, $list); + } + } + ++$list->idx; + $this->funcOptions = OptionsFragment::parse($parser, $list, CreateDefFragment::$FUNC_OPTIONS); + ++$list->idx; + $this->body = array(); + for (; $list->idx < $list->count; ++$list->idx) { + $token = $list->tokens[$list->idx]; + $this->body[] = $token; + if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'END')) { + break; + } + } + $class = null; // The statement has been processed here. + } + } elseif (($token->value === 'GROUP') || ($token->value === 'ORDER')) { + $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'BY'); + } elseif ($token->value === 'RENAME') { + $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'TABLE'); + ++$list->idx; + $this->renames = RenameKeyword::parse($parser, $list); + } elseif ($token->value === 'SELECT') { + ++$list->idx; // Skipping last option. + $this->expr = SelectKeyword::parse($parser, $list); + } elseif ($token->value === 'UPDATE') { + ++$list->idx; // Skipping last option. + $this->from = FromKeyword::parse($parser, $list); + } + + // Finally, processing the keyword (if possible). + if ($class !== null) { + ++$list->idx; // Skipping keyword. + $this->$field = $class::parse($parser, $list, array()); + } + } + + $this->last = --$list->idx; // Go back to last used token. + } +} diff --git a/libraries/sql-parser/src/Statements/CallStatement.php b/libraries/sql-parser/src/Statements/CallStatement.php new file mode 100644 index 0000000000..76681b52c8 --- /dev/null +++ b/libraries/sql-parser/src/Statements/CallStatement.php @@ -0,0 +1,19 @@ + 1, + 'EVENT' => 1, + 'FUNCTION' => 1, + 'INDEX' => 1, + 'PROCEDURE' => 1, + 'SERVER' => 1, + 'TABLE' => 1, + 'TABLESPACE' => 1, + 'TRIGGER' => 1, + 'VIEW' => 1, + + 'TEMPORARY' => 2, + 'IF NOT EXISTS' => 3, + 'DEFINER' => array(4, 'var'), + ); + + /** + * The name of the enw table. + * + * @var CreateDefFragment + */ + public $name; + + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; + + /** + * The parameters of this routine. + * + * @var ParamDefFragment[] + */ + public $parameters; + + /** + * The options of the table. + * + * @var OptionsFragment + * + * @see CreateDefFragment::$TABLE_OPTIONS + */ + public $tableOptions; + + /** + * Field created by this statement. + * + * @var FieldDefFragment[] + */ + public $fields; + + /** + * The body of this function or procedure. + * + * @var Token[] + */ + public $body; +} diff --git a/libraries/sql-parser/src/Statements/DeleteStatement.php b/libraries/sql-parser/src/Statements/DeleteStatement.php new file mode 100644 index 0000000000..01dd8adc2f --- /dev/null +++ b/libraries/sql-parser/src/Statements/DeleteStatement.php @@ -0,0 +1,74 @@ + 1, + 'QUICK' => 2, + 'IGNORE' => 3, + ); + + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; + + /** + * Tables used as sources for this statement. + * + * @var FieldFragment[] + */ + public $from; + + /** + * Partitions used as source for this statement. + * + * @var ArrayFragment + */ + public $partition; + + /** + * Conditions used for filtering each row of the result set. + * + * @var WhereKeyword[] + */ + public $where; + + /** + * Specifies the order of the rows in the result set. + * + * @var OrderKeyword[] + */ + public $order; + + /** + * Conditions used for limiting the size of the result set. + * + * @var LimitKeyword + */ + public $limit; +} diff --git a/libraries/sql-parser/src/Statements/InsertStatement.php b/libraries/sql-parser/src/Statements/InsertStatement.php new file mode 100644 index 0000000000..f24634ac33 --- /dev/null +++ b/libraries/sql-parser/src/Statements/InsertStatement.php @@ -0,0 +1,78 @@ + 1, + 'DELAYED' => 2, + 'HIGH_PRIORITY' => 3, + 'IGNORE' => 4, + ); + + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; + + /** + * Tables used as target for this statement. + * + * @var IntoKeyword + */ + public $into; + + /** + * Values to be inserted. + * + * @var ValuesKeyword + */ + public $values; +} diff --git a/libraries/sql-parser/src/Statements/RenameStatement.php b/libraries/sql-parser/src/Statements/RenameStatement.php new file mode 100644 index 0000000000..bd3c767d53 --- /dev/null +++ b/libraries/sql-parser/src/Statements/RenameStatement.php @@ -0,0 +1,23 @@ + 1, + 'DELAYED' => 1, + ); + + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; + + /** + * Tables used as target for this statement. + * + * @var IntoKeyword + */ + public $into; + + /** + * Values to be replaced. + * + * @var ValuesKeyword + */ + public $values; + + /** + * The replaced values. + * + * @var SetKeyword[] + */ + public $set; +} diff --git a/libraries/sql-parser/src/Statements/SelectStatement.php b/libraries/sql-parser/src/Statements/SelectStatement.php new file mode 100644 index 0000000000..d17450eb04 --- /dev/null +++ b/libraries/sql-parser/src/Statements/SelectStatement.php @@ -0,0 +1,130 @@ + 1, + 'DISTINCT' => 1, + 'DISTINCTROW' => 1, + 'HIGH_PRIORITY' => 2, + 'MAX_STATEMENT_TIME' => array(3, 'var'), + 'STRAIGHT_JOIN' => 4, + 'SQL_SMALL_RESULT' => 5, + 'SQL_BIG_RESULT' => 6, + 'SQL_BUFFER_RESULT' => 7, + 'SQL_CACHE' => 8, + 'SQL_NO_CACHE' => 8, + 'SQL_CALC_FOUND_ROWS' => 9, + ); + + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; + + /** + * Expressions that are being selected by this statement. + * + * @var FieldFragment[] + */ + public $expr; + + /** + * Tables used as sources for this statement. + * + * @var FieldFragment[] + */ + public $from; + + /** + * Partitions used as source for this statement. + * + * @var ArrayFragment[] + */ + public $partition; + + /** + * Conditions used for filtering each row of the result set. + * + * @var WhereKeyword + */ + public $where; + + /** + * Conditions used for grouping the result set. + * + * @var GroupKeyword + */ + public $group; + + /** + * Conditions used for filtering the result set. + * + * @var WhereKeyword[] + */ + public $having; + + /** + * Specifies the order of the rows in the result set. + * + * @var OrderKeyword[] + */ + public $order; + + /** + * Conditions used for limiting the size of the result set. + * + * @var LimitKeyword + */ + public $limit; + + /** + * Joins. + * + * @var JoinKeyword + */ + public $join; +} diff --git a/libraries/sql-parser/src/Statements/UpdateStatement.php b/libraries/sql-parser/src/Statements/UpdateStatement.php new file mode 100644 index 0000000000..cdeab0367f --- /dev/null +++ b/libraries/sql-parser/src/Statements/UpdateStatement.php @@ -0,0 +1,79 @@ + 1, + 'IGNORE' => 2, + ); + + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; + + /** + * Tables used as sources for this statement. + * + * @var FieldFragment[] + */ + public $from; + + /** + * The updated values. + * + * @var SetKeyword[] + */ + public $set; + + /** + * Conditions used for filtering each row of the result set. + * + * @var WhereKeyword[] + */ + public $where; + + /** + * Specifies the order of the rows in the result set. + * + * @var OrderKeyword[] + */ + public $order; + + /** + * Conditions used for limiting the size of the result set. + * + * @var LimitKeyword + */ + public $limit; +} diff --git a/libraries/sql-parser/src/Token.php b/libraries/sql-parser/src/Token.php new file mode 100644 index 0000000000..61fb16b57f --- /dev/null +++ b/libraries/sql-parser/src/Token.php @@ -0,0 +1,253 @@ +, !==, etc. + * Bitwise operators: &, |, ^, etc. + * Assignment operators: =, +=, -=, etc. + * SQL specific operators: . (e.g. .. WHERE database.table ..), + * * (e.g. SELECT * FROM ..) + * + * @var int + */ + const TYPE_OPERATOR = 2; + + /** + * Spaces, tabs, new lines, etc. + * + * @var int + */ + const TYPE_WHITESPACE = 3; + + /** + * Any type of legal comment. + * + * Bash (#), C (/* *\/) or SQL (--) comments: + * + * -- SQL-comment + * + * #Bash-like comment + * + * /*C-like comment*\/ + * + * or: + * + * /*C-like + * comment*\/ + * + * Backslashes were added to respect PHP's comments syntax. + * + * @var int + */ + const TYPE_COMMENT = 4; + + /** + * Boolean values: true or false. + * + * @var int + */ + const TYPE_BOOL = 5; + + /** + * Numbers: 4, 0x8, 15.16, 23e42, etc. + * + * @var int + */ + const TYPE_NUMBER = 6; + + /** + * Literal strings: 'string', "test". + * Some of these strings are actually symbols. + * + * @var int + */ + const TYPE_STRING = 7; + + /** + * Database, table names, variables, etc. + * For example: ```SELECT `foo`, `bar` FROM `database`.`table`;``` + * + * @var int + */ + const TYPE_SYMBOL = 8; + + /** + * Delimits an unknown string. + * For example: ```SELECT * FROM test;```, `test` is a delimiter. + * + * @var int + */ + const TYPE_DELIMITER = 9; + + // Flags that describe the tokens in more detail. + + // Numbers related flags. + const FLAG_NUMBER_HEX = 1; + const FLAG_NUMBER_FLOAT = 2; + const FLAG_NUMBER_APPROXIMATE = 4; + const FLAG_NUMBER_NEGATIVE = 8; + + // Strings related flags. + const FLAG_STRING_SINGLE_QUOTES = 1; + const FLAG_STRING_DOUBLE_QUOTES = 2; + + // Comments related flags. + const FLAG_COMMENT_BASH = 1; + const FLAG_COMMENT_C = 2; + const FLAG_COMMENT_SQL = 4; + const FLAG_COMMENT_MYSQL_CMD = 8; + + // Operators related flags. + const FLAG_OPERATOR_ARITHMETIC = 1; + const FLAG_OPERATOR_LOGICAL = 2; + const FLAG_OPERATOR_BITWISE = 4; + const FLAG_OPERATOR_ASSIGNMENT = 8; + const FLAG_OPERATOR_SQL = 16; + + // Symbols related flags. + const FLAG_SYMBOL_VARIABLE = 1; + const FLAG_SYMBOL_BACKTICK = 2; + const FLAG_SYMBOL_USER = 4; + + /** + * The token it its raw string representation. + * + * @var string + */ + public $token; + + /** + * The value this token contains (i.e. token after some evaluation) + * + * @var mixed + */ + public $value; + + /** + * The type of this token. + * + * @var int + */ + public $type; + + /** + * The flags of this token. + * + * @var int + */ + public $flags; + + /** + * The position in the inial string where this token started. + * + * @var int + */ + public $position; + + /** + * Constructor. + * + * @param string $token + * @param int $type + * @param int $flags + * @param int $position + */ + public function __construct($token, $type = 0, $flags = 0) + { + $this->token = $token; + $this->type = $type; + $this->flags = $flags; + $this->value = $this->extract(); + } + + /** + * Does little processing to the token to extract a value. + * + * If no processing can be done it will return the initial string. + * + * @return mixed + */ + public function extract() + { + switch ($this->type) { + case Token::TYPE_KEYWORD: + return strtoupper($this->token); + case Token::TYPE_WHITESPACE: + return ' '; + case Token::TYPE_BOOL: + return strtoupper($this->token) === 'TRUE'; + case Token::TYPE_NUMBER: + $ret = str_replace('--', '', $this->token); // e.g. ---42 === -42 + if ($this->flags & Token::FLAG_NUMBER_HEX) { + if ($this->flags & Token::FLAG_NUMBER_NEGATIVE) { + $ret = str_replace('-', '', $this->token); + sscanf($ret, "%x", $ret); + $ret = -$ret; + } else { + sscanf($ret, "%x", $ret); + } + } elseif (($this->flags & Token::FLAG_NUMBER_APPROXIMATE) || + ($this->flags & Token::FLAG_NUMBER_FLOAT)) { + sscanf($ret, "%f", $ret); + } else { + sscanf($ret, "%d", $ret); + } + return $ret; + case Token::TYPE_STRING: + return mb_substr($this->token, 1, -1); // trims quotes + case Token::TYPE_SYMBOL: + $str = $this->token; + if ((isset($str[0])) && ($str[0] === '@')) { + $str = mb_substr($str, 1); + } + if ((isset($str[0])) && (($str[0] === '`') || ($str[0] === '"') || ($str[0] === '\''))) { + $str = mb_substr($str, 1, -1); + } + return $str; + } + return $this->token; + } + + /** + * Converts the token into an inline token by replacing tabs and new lines. + * + * @return string + */ + public function getInlineToken() + { + return str_replace( + array("\r", "\n", "\t"), + array('\r', '\n', '\t'), + $this->token + ); + } +} diff --git a/libraries/sql-parser/src/TokensList.php b/libraries/sql-parser/src/TokensList.php new file mode 100644 index 0000000000..405f4a121b --- /dev/null +++ b/libraries/sql-parser/src/TokensList.php @@ -0,0 +1,118 @@ +tokens[$this->count++] = $token; + } + + /** + * Gets next token in list. + * + * @return Token + */ + public function getNext() + { + if ($this->idx < $this->count) { + return $this->tokens[$this->idx++]; + } + return null; + } + + /** + * Gets next token of a specified type. + * + * @param int $type + * + * @return Token + */ + public function getNextOfType($type) + { + for (; $this->idx < $this->count; ++$this->idx) { + if ($this->tokens[$this->idx]->type === $type) { + return $this->tokens[$this->idx++]; + } + } + return null; + } + + /** + * Gets next token of a specified type. + * + * @param int $type + * @param string $value + * + * @return Token + */ + public function getNextOfTypeAndValue($type, $value) + { + for (; $this->idx < $this->count; ++$this->idx) { + if (($this->tokens[$this->idx]->type === $type) && + ($this->tokens[$this->idx]->value === $value)) { + return $this->tokens[$this->idx++]; + } + } + return null; + } + + // ArrayAccess methods. + + public function offsetSet($offset, $value) + { + if ($offset === null) { + $this->tokens[$this->count++] = $value; + } else { + $this->tokens[$offset] = $value; + } + } + + public function offsetGet($offset) + { + return $offset < $this->count ? $this->tokens[$offset] : null; + } + + public function offsetExists($offset) + { + return $offset < $this->count; + } + + public function offsetUnset($offset) + { + unset($this->tokens[$offset]); + --$this->count; + for ($i = $offset; $i < $this->count; ++$i) { + $this->tokens[$i] = $this->tokens[$i + 1]; + } + unset($this->tokens[$this->count]); + } +} diff --git a/libraries/sql-parser/src/UtfString.php b/libraries/sql-parser/src/UtfString.php new file mode 100644 index 0000000000..8815e58367 --- /dev/null +++ b/libraries/sql-parser/src/UtfString.php @@ -0,0 +1,220 @@ +str = $str; + $this->byteIdx = 0; + $this->charIdx = 0; + // TODO: `strlen($str)` might return a wrong length when function + // overloading is enabled. + // https://php.net/manual/ro/mbstring.overload.php + $this->byteLen = strlen($str); + $this->charLen = mb_strlen($str); + } + + /** + * Checks if the given offset exists. + * + * @param int $offset + * + * @return bool + */ + public function offsetExists($offset) + { + return $offset < $charLen; + } + + /** + * Gets the character at given offset. + * + * @param int $offset + * + * @return string + */ + public function offsetGet($offset) + { + if (($offset < 0) || ($offset >= $this->charLen)) { + return null; + } + + $delta = $offset - $this->charIdx; + + if ($delta > 0) { + // Fast forwarding. + while ($delta-- > 0) { + $this->byteIdx += static::getCharLength($this->str[$this->byteIdx]); + ++$this->charIdx; + } + } elseif ($delta < 0) { + // Rewinding. + while ($delta++ < 0) { + do { + $byte = ord($this->str[--$this->byteIdx]); + } while ((128 <= $byte) && ($byte < 192)); + --$this->charIdx; + } + } + + $bytesCount = static::getCharLength($this->str[$this->byteIdx]); + + $ret = ''; + for ($i = 0; $bytesCount-- > 0; ++$i) { + $ret .= $this->str[$this->byteIdx + $i]; + } + + return $ret; + } + + /** + * Sets the value of a character. + * + * @param int $offset + * @param string $value + */ + public function offsetSet($offset, $value) + { + throw new \Exception('Not implemented.'); + } + + /** + * Unsets an index. + * + * @param int $offset + */ + public function offsetUnset($offset) + { + throw new \Exception('Not implemented.'); + } + + /** + * Gets the length of an UTF-8 character. + * + * According to RFC 3629, a UTF-8 character can have at most 4 bytes. + * However, this implemenation supports UTF-8 characters containing up to 6 + * bytes. + * + * @see http://tools.ietf.org/html/rfc3629 + * + * @param string $byte + * + * @return int + */ + private static function getCharLength($byte) + { + $byte = ord($byte); + if ($byte < 128) { + return 1; + } elseif ($byte < 224) { + return 2; + } elseif ($byte < 240) { + return 3; + } elseif ($byte < 248) { + return 4; + } elseif ($byte === 252) { + return 5; // unofficial + } + return 6; // unofficial + } + + /** + * Returns the number of remaining characters. + * + * @return int + */ + public function remaining() + { + if ($this->charIdx < $this->charLen) { + return $this->charLen - $this->charIdx; + } + return 0; + } + + /** + * Returns the length in characters of the string. + * + * @return int + */ + public function length() + { + return $this->charLen; + } + + /** + * Gets the values of the indexes. + * + * @param int &$byte + * @param int &$char + */ + public function getIndexes(&$byte, &$char) + { + $byte = $this->byteIdx; + $char = $this->charIdx; + } + + /** + * Sets the values of the indexes. + * + * @param int $byte + * @param int $char + */ + public function setIndexes($byte = 0, $char = 0) + { + $this->byteIdx = $byte; + $this->charIdx = $char; + } +} diff --git a/libraries/sql-parser/src/Utils/Misc.php b/libraries/sql-parser/src/Utils/Misc.php new file mode 100644 index 0000000000..aca16fe294 --- /dev/null +++ b/libraries/sql-parser/src/Utils/Misc.php @@ -0,0 +1,91 @@ +join->expr->table)) && (!empty($tree->join->expr->alias))) { + $thisDb = empty($tree->join->expr->database) ? + $db : $tree->join->expr->database; + + $retval = array( + $thisDb => array( + 'alias' => null, + 'tables' => array( + $tree->join->expr->table => array( + 'alias' => $tree->join->expr->alias, + 'columns' => array(), + ), + ), + ), + ); + + $tables[$thisDb][$tree->join->expr->alias] = $tree->join->expr->table; + } + + foreach ($tree->from as $expr) { + if (empty($expr->table)) { + continue; + } + + $thisDb = empty($expr->database) ? $db : $expr->database; + + if (!isset($retval[$thisDb])) { + $retval[$thisDb] = array( + 'alias' => null, + 'tables' => array(), + ); + } + + if (!isset($retval[$thisDb]['tables'][$expr->table])) { + $retval[$thisDb]['tables'][$expr->table] = array( + 'alias' => empty($expr->alias) ? null : $expr->alias, + 'columns' => array(), + ); + } + + if (!isset($tables[$thisDb])) { + $tables[$thisDb] = array(); + } + $tables[$thisDb][$expr->alias] = $expr->table; + } + + foreach ($tree->expr as $expr) { + if ((empty($expr->column)) || (empty($expr->alias)) ){ + continue; + } + + $thisDb = empty($expr->database) ? $db : $expr->database; + + if (empty($expr->table)) { + foreach ($retval[$thisDb]['tables'] as &$table) { + $table['columns'][$expr->column] = $expr->alias; + } + } else { + $thisTable = isset($tables[$thisDb][$expr->table]) ? + $tables[$thisDb][$expr->table] : $expr->table; + $retval[$thisDb]['tables'][$thisTable]['columns'][$expr->column] = $expr->alias; + } + } + + return $retval; + } + +} diff --git a/libraries/sql-parser/src/Utils/Routine.php b/libraries/sql-parser/src/Utils/Routine.php new file mode 100644 index 0000000000..1b694e24c5 --- /dev/null +++ b/libraries/sql-parser/src/Utils/Routine.php @@ -0,0 +1,46 @@ + 0, + 'dir' => array(), + 'name' => array(), + 'type' => array(), + 'length' => array(), + 'opts' => array(), + ); + + $idx = 0; + foreach ($tree->parameters as $param) { + $retval['dir'][$idx] = $param->inOut; + $retval['name'][$idx] = $param->name; + $retval['type'][$idx] = $param->type->name; + $retval['length'][$idx] = implode(',', $param->type->size); + $retval['opts'][$idx] = array(); + foreach ($param->type->options->options as $opt) { + $retval['opts'][$idx][] = is_string($opt) ? + $opt : $opt['value']; + } + $retval['opts'][$idx] = implode(' ', $retval['opts'][$idx]); + ++$idx; + } + + $retval['num'] = $idx; + + return $retval; + } + +} From 50a2021faf13400e8a9b9b7efdb04934c69c1f67 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Sat, 13 Jun 2015 13:53:35 +0300 Subject: [PATCH 02/57] Replaced PMA_RTN_parseAllParameters(). Signed-off-by: Dan Ungureanu --- libraries/rte/rte_list.lib.php | 17 +++++++---------- libraries/rte/rte_routines.lib.php | 14 ++++++-------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/libraries/rte/rte_list.lib.php b/libraries/rte/rte_list.lib.php index c50b0bad5d..e233a61348 100644 --- a/libraries/rte/rte_list.lib.php +++ b/libraries/rte/rte_list.lib.php @@ -220,16 +220,13 @@ function PMA_RTN_getRowForList($routine, $rowclass = '') // Check if the routine has any input parameters. If it does, // we will show a dialog to get values for these parameters, // otherwise we can execute it directly. - $params = PMA_RTN_parseAllParameters( - PMA_SQP_parse( - $GLOBALS['dbi']->getDefinition( - $db, - $routine['type'], - $routine['name'] - ) - ), - $routine['type'] - ); + + $parser = new SqlParser\Parser($GLOBALS['dbi']->getDefinition( + $db, + $routine['type'], + $routine['name'] + )); + $params = SqlParser\Utils\Routine::getParameters($parser->statements[0]); if ($routine !== false) { if (PMA_Util::currentUserHasPrivilege('EXECUTE', $db)) { $execute_action = 'execute_routine'; diff --git a/libraries/rte/rte_routines.lib.php b/libraries/rte/rte_routines.lib.php index 8f2db513ac..fdf8f5c903 100644 --- a/libraries/rte/rte_routines.lib.php +++ b/libraries/rte/rte_routines.lib.php @@ -694,14 +694,12 @@ function PMA_RTN_getDataFromName($name, $type, $all = true) // Get required data $retval['item_name'] = $routine['SPECIFIC_NAME']; $retval['item_type'] = $routine['ROUTINE_TYPE']; - $parsed_query = PMA_SQP_parse( - $GLOBALS['dbi']->getDefinition( - $db, - $routine['ROUTINE_TYPE'], - $routine['SPECIFIC_NAME'] - ) - ); - $params = PMA_RTN_parseAllParameters($parsed_query, $routine['ROUTINE_TYPE']); + $parser = new SqlParser\Parser($GLOBALS['dbi']->getDefinition( + $db, + $routine['ROUTINE_TYPE'], + $routine['SPECIFIC_NAME'] + )); + $params = SqlParser\Utils\Routine::getParameters($parser->statements[0]); $retval['item_num_params'] = $params['num']; $retval['item_param_dir'] = $params['dir']; $retval['item_param_name'] = $params['name']; From 096492438a7ca390cd029aae11f8fe21fa1e6abb Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Sat, 13 Jun 2015 13:54:06 +0300 Subject: [PATCH 03/57] Replaced PMA_SQPdata_forbidden_word with the method implemented in lexer. Signed-off-by: Dan Ungureanu --- libraries/Util.class.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libraries/Util.class.php b/libraries/Util.class.php index 20ac88a786..97a5e5322e 100644 --- a/libraries/Util.class.php +++ b/libraries/Util.class.php @@ -907,9 +907,7 @@ class PMA_Util } if (! $do_it) { - global $PMA_SQPdata_forbidden_word; - $eltNameUpper = /*overload*/mb_strtoupper($a_name); - if (!in_array($eltNameUpper, $PMA_SQPdata_forbidden_word)) { + if (!SqlParser\Context::isKeyword($a_name)) { return $a_name; } } @@ -954,9 +952,7 @@ class PMA_Util } if (! $do_it) { - global $PMA_SQPdata_forbidden_word; - $eltNameUpper = /*overload*/mb_strtoupper($a_name); - if (!in_array($eltNameUpper, $PMA_SQPdata_forbidden_word)) { + if (!SqlParser\Context::isKeyword($a_name)) { return $a_name; } } From 5d6e139dc1f4056ebef7c85c92b4e5f0459c6bd7 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Sat, 13 Jun 2015 13:54:24 +0300 Subject: [PATCH 04/57] Replaced PMA_SQP_getAliasesFromQuery(). Signed-off-by: Dan Ungureanu --- export.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/export.php b/export.php index ace2c90c09..d12976a482 100644 --- a/export.php +++ b/export.php @@ -284,14 +284,15 @@ if (!defined('TESTSUITE')) { // Merge SQL Query aliases with Export aliases from // export page, Export page aliases are given more // preference over SQL Query aliases. + $parser = SqlParser\Parser($sql_query); if (!empty($_REQUEST['aliases'])) { $aliases = PMA_mergeAliases( - PMA_SQP_getAliasesFromQuery($sql_query, $db), + SqlParser\Misc::getAliases($parser->statements[0], $db), $_REQUEST['aliases'] ); $_SESSION['tmpval']['aliases'] = $_REQUEST['aliases']; } else { - $aliases = PMA_SQP_getAliasesFromQuery($sql_query, $db); + $aliases = SqlParser\Misc::getAliases($parser->statements[0], $db); } /** From 9bb40c0abe4f12352ecbedc17d4e3252f6492c55 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Sat, 13 Jun 2015 14:33:48 +0300 Subject: [PATCH 05/57] Updated sql-parser library. Signed-off-by: Dan Ungureanu --- libraries/sql-parser/src/Parser.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/sql-parser/src/Parser.php b/libraries/sql-parser/src/Parser.php index 95ecf6cf63..9de7fd08cf 100644 --- a/libraries/sql-parser/src/Parser.php +++ b/libraries/sql-parser/src/Parser.php @@ -52,18 +52,21 @@ class Parser public static $KEYWORD_PARSERS = array( // Meta-keywords. + /* '_ARRAY' => 'SqlParser\\Fragments\\ArrayFragment', '_CALL' => 'SqlParser\\Fragments\\CallKeyword', '_CREATE_DEF' => 'SqlParser\\Fragments\\CreateDefFragment', - '_DATA_TYPE' => 'SqlParser\\Fragments\\CreateDefFragment', + '_DATA_TYPE' => 'SqlParser\\Fragments\\DataTypeFragment', '_FIELD' => 'SqlParser\\Fragments\\FieldFragment', '_FIELD_DEF' => 'SqlParser\\Fragments\\FieldDefFragment', + '_PARAM_DEF' => 'SqlParser\\Fragments\\ParamDefFragment', '_OPTIONS' => 'SqlParser\\Fragments\\OptionsFragment', '_RENAME' => 'SqlParser\\Fragments\\RenameKeyword', '_SELECT' => 'SqlParser\\Fragments\\SelectKeyword', + */ 'FROM' => 'SqlParser\\Fragments\\FromKeyword', - 'GROUP' => 'SqlParser\\Fragments\\GroupFragment', + 'GROUP' => 'SqlParser\\Fragments\\OrderKeyword', 'HAVING' => 'SqlParser\\Fragments\\WhereKeyword', 'INTO' => 'SqlParser\\Fragments\\IntoKeyword', 'JOIN' => 'SqlParser\\Fragments\\JoinKeyword', From e057ca92ce0b1d8634ef9d67dc75eb8b689271e9 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Sat, 13 Jun 2015 18:11:25 +0300 Subject: [PATCH 06/57] Replaced PMA_SQP_isKeyWord(). Signed-off-by: Dan Ungureanu --- libraries/Table.class.php | 2 +- tbl_structure.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/Table.class.php b/libraries/Table.class.php index 35d32d7da3..d1ec487863 100644 --- a/libraries/Table.class.php +++ b/libraries/Table.class.php @@ -1823,7 +1823,7 @@ class PMA_Table foreach ($columns as $column) { $temp = explode('.', $column); $column_name = $temp[2]; - if (PMA_SQP_isKeyWord($column_name)) { + if (SqlParser\Context::isKeyword($column_name, true)) { $return[] = $column_name; } } diff --git a/tbl_structure.php b/tbl_structure.php index 197495fc13..9d5178c048 100644 --- a/tbl_structure.php +++ b/tbl_structure.php @@ -51,11 +51,11 @@ if (isset($_REQUEST['reserved_word_check'])) { $columns_names = $_REQUEST['field_name']; $reserved_keywords_names = array(); foreach ($columns_names as $column) { - if (PMA_SQP_isKeyWord(trim($column))) { + if (SqlParser\Context::isKeyword(trim($column), true)) { $reserved_keywords_names[] = trim($column); } } - if (PMA_SQP_isKeyWord(trim($table))) { + if (SqlParser\Context::isKeyword(trim($table), true)) { $reserved_keywords_names[] = trim($table); } if (count($reserved_keywords_names) == 0) { From bb1c3805725202d801aabe11b34072db96e1c185 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Sun, 14 Jun 2015 02:21:37 +0300 Subject: [PATCH 07/57] Include sql-parser in tests. Signed-off-by: Dan Ungureanu --- test/bootstrap-dist.php | 1 + 1 file changed, 1 insertion(+) diff --git a/test/bootstrap-dist.php b/test/bootstrap-dist.php index 865e6f770b..8ecfd91cd9 100644 --- a/test/bootstrap-dist.php +++ b/test/bootstrap-dist.php @@ -55,6 +55,7 @@ $CFG = new PMA_Config(); // Initialize PMA_VERSION variable define('PMA_VERSION', $CFG->get('PMA_VERSION')); unset($CFG); +require_once 'libraries/sql-parser/autoload.php'; // Set proxy information from env, if available $http_proxy = getenv('http_proxy'); From 14999636327f1c4aefb7966c01f93c34c32f2c10 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Sun, 14 Jun 2015 21:45:35 +0300 Subject: [PATCH 08/57] Removed PMA_RTN_parseAllParameters(). Signed-off-by: Dan Ungureanu --- libraries/rte/rte_routines.lib.php | 79 +----------- .../rte/PMA_RTN_ParameterParser_test.php | 115 ------------------ 2 files changed, 2 insertions(+), 192 deletions(-) diff --git a/libraries/rte/rte_routines.lib.php b/libraries/rte/rte_routines.lib.php index fdf8f5c903..f326b14974 100644 --- a/libraries/rte/rte_routines.lib.php +++ b/libraries/rte/rte_routines.lib.php @@ -80,9 +80,8 @@ function PMA_RTN_main($type) } // end PMA_RTN_main() /** - * This function parses a string containing one parameter of a routine, - * as returned by PMA_RTN_parseAllParameters() and returns an array containing - * the information about this parameter. + * This function parses a string containing one parameter of a routine + * and returns an array containing the information about this parameter. * * @param string $value A string containing one parameter of a routine * @@ -156,80 +155,6 @@ function PMA_RTN_parseOneParameter($value) return $retval; } // end PMA_RTN_parseOneParameter() -/** - * This function looks through the contents of a parsed - * SHOW CREATE [PROCEDURE | FUNCTION] query and extracts - * information about the routine's parameters. - * - * @param array $parsed_query Parsed query, returned by by PMA_SQP_parse() - * @param string $routine_type Routine type: 'PROCEDURE' or 'FUNCTION' - * - * @return array Information about the parameters of a routine. - */ -function PMA_RTN_parseAllParameters($parsed_query, $routine_type) -{ - $retval = array(); - $retval['num'] = 0; - - if ($parsed_query) { - // First get the list of parameters from the query - $buffer = ''; - $params = array(); - $fetching = false; - $depth = 0; - for ($i = 0; $i < $parsed_query['len']; $i++) { - if ($parsed_query[$i]['type'] == 'alpha_reservedWord' - && $parsed_query[$i]['data'] == $routine_type - ) { - $fetching = true; - } else if ($fetching == true - && $parsed_query[$i]['type'] == 'punct_bracket_open_round' - ) { - $depth++; - if ($depth > 1) { - $buffer .= $parsed_query[$i]['data'] . ' '; - } - } else if ($fetching == true - && $parsed_query[$i]['type'] == 'punct_bracket_close_round' - ) { - $depth--; - if ($depth > 0) { - $buffer .= $parsed_query[$i]['data'] . ' '; - } else { - break; - } - } else if ($parsed_query[$i]['type'] == 'punct_listsep' && $depth == 1) { - $params[] = $buffer; - $retval['num']++; - $buffer = ''; - } else if ($fetching == true && $depth > 0) { - $buffer .= $parsed_query[$i]['data'] . ' '; - } - } - if (! empty($buffer)) { - $params[] = $buffer; - $retval['num']++; - } - // Now parse each parameter individually - foreach ($params as $key => $value) { - list($retval['dir'][], - $retval['name'][], - $retval['type'][], - $retval['length'][], - $retval['opts'][]) = PMA_RTN_parseOneParameter($value); - } - } - // Since some indices of $retval may be still undefined, we fill - // them each with an empty array to avoid E_ALL errors in PHP. - foreach (array('dir', 'name', 'type', 'length', 'opts') as $key => $index) { - if (! isset($retval[$index])) { - $retval[$index] = array(); - } - } - - return $retval; -} // end PMA_RTN_parseAllParameters() - /** * This function looks through the contents of a parsed * SHOW CREATE [PROCEDURE | FUNCTION] query and extracts diff --git a/test/libraries/rte/PMA_RTN_ParameterParser_test.php b/test/libraries/rte/PMA_RTN_ParameterParser_test.php index 2ee03142ac..cfced81a20 100644 --- a/test/libraries/rte/PMA_RTN_ParameterParser_test.php +++ b/test/libraries/rte/PMA_RTN_ParameterParser_test.php @@ -114,120 +114,5 @@ class PMA_RTN_ParameterParser_Test extends PHPUnit_Framework_TestCase ) ); } - - /** - * Test for PMA_RTN_parseAllParameters - * - * @param string $query Query - * @param string $type Type - * @param array $target Expected output - * - * @return void - * - * @depends testParseOneParameter - * @dataProvider queryProvider - */ - public function testParseAllParameters($query, $type, $target) - { - PMA_RTN_setGlobals(); - $this->assertEquals( - $target, - PMA_RTN_parseAllParameters(PMA_SQP_parse($query), $type) - ); - } - - /** - * Data provider for testParseAllParameters - * - * @return array - */ - public function queryProvider() - { - return array( - array( - 'CREATE PROCEDURE `foo`() SET @A=0', - 'PROCEDURE', - array( - 'num' => 0, - 'dir' => array(), - 'name' => array(), - 'type' => array(), - 'length' => array(), - 'opts' => array() - ) - ), - array( - 'CREATE DEFINER=`user\\`@`somehost``(` FUNCTION `foo```(`baz` INT) BEGIN SELECT NULL; END', - 'FUNCTION', - array( - 'num' => 1, - 'dir' => array( - 0 => '' - ), - 'name' => array( - 0 => 'baz' - ), - 'type' => array( - 0 => 'INT' - ), - 'length' => array( - 0 => '' - ), - 'opts' => array( - 0 => '' - ) - ) - ), - array( - 'CREATE PROCEDURE `foo`(IN `baz\\)` INT(25) zerofill unsigned) BEGIN SELECT NULL; END', - 'PROCEDURE', - array( - 'num' => 1, - 'dir' => array( - 0 => 'IN' - ), - 'name' => array( - 0 => 'baz\\)' - ), - 'type' => array( - 0 => 'INT' - ), - 'length' => array( - 0 => '25' - ), - 'opts' => array( - 0 => 'UNSIGNED ZEROFILL' - ) - ) - ), - array( - 'CREATE PROCEDURE `foo`(IN `baz\\` INT(001) zerofill, out bazz varchar(15) charset UTF8) BEGIN SELECT NULL; END', - 'PROCEDURE', - array( - 'num' => 2, - 'dir' => array( - 0 => 'IN', - 1 => 'OUT' - ), - 'name' => array( - 0 => 'baz\\', - 1 => 'bazz' - ), - 'type' => array( - 0 => 'INT', - 1 => 'VARCHAR' - ), - 'length' => array( - 0 => '1', - 1 => '15' - ), - 'opts' => array( - 0 => 'ZEROFILL', - 1 => 'utf8' - ) - ) - ), - ); - } } ?> From 02f6c7f4c06111677baa6e873d82df0d6d16c133 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Mon, 15 Jun 2015 20:04:27 +0300 Subject: [PATCH 09/57] Replaced PMA_RTN_parseOneParameter(). Updated sql-parser library. Signed-off-by: Dan Ungureanu --- libraries/rte/rte_routines.lib.php | 2 +- .../src/Fragments/DataTypeFragment.php | 4 +- .../src/Fragments/ParamDefFragment.php | 2 +- libraries/sql-parser/src/Lexer.php | 6 +- libraries/sql-parser/src/Parser.php | 8 +- libraries/sql-parser/src/Token.php | 6 +- libraries/sql-parser/src/Utils/Misc.php | 3 +- libraries/sql-parser/src/Utils/Routine.php | 75 ++++++++++++++++++- 8 files changed, 93 insertions(+), 13 deletions(-) diff --git a/libraries/rte/rte_routines.lib.php b/libraries/rte/rte_routines.lib.php index f326b14974..c36326f718 100644 --- a/libraries/rte/rte_routines.lib.php +++ b/libraries/rte/rte_routines.lib.php @@ -684,7 +684,7 @@ function PMA_RTN_getDataFromName($name, $type, $all = true) } $routine['DTD_IDENTIFIER'] = $dtd; } - $returnparam = PMA_RTN_parseOneParameter($routine['DTD_IDENTIFIER']); + $returnparam = SqlParser\Utils\Routine::getReturnType($routine['DTD_IDENTIFIER']); $retval['item_returntype'] = $returnparam[2]; $retval['item_returnlength'] = $returnparam[3]; $retval['item_returnopts_num'] = $returnparam[4]; diff --git a/libraries/sql-parser/src/Fragments/DataTypeFragment.php b/libraries/sql-parser/src/Fragments/DataTypeFragment.php index a5c8eca7de..c0a4f61a4c 100644 --- a/libraries/sql-parser/src/Fragments/DataTypeFragment.php +++ b/libraries/sql-parser/src/Fragments/DataTypeFragment.php @@ -88,7 +88,9 @@ class DataTypeFragment extends Fragment } elseif ($state === 1) { if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { $size = ArrayFragment::parse($parser, $list); - $ret->size = $size->array; + foreach ($size->tokens as $token) { + $ret->size[] = $token->token; + } $ret->tokens = array_merge($ret->tokens, $size->tokens); ++$list->idx; } diff --git a/libraries/sql-parser/src/Fragments/ParamDefFragment.php b/libraries/sql-parser/src/Fragments/ParamDefFragment.php index 05bad6e663..b7d414d509 100644 --- a/libraries/sql-parser/src/Fragments/ParamDefFragment.php +++ b/libraries/sql-parser/src/Fragments/ParamDefFragment.php @@ -91,7 +91,7 @@ class ParamDefFragment extends Fragment if (($token->value === 'IN') || ($token->value === 'OUT') || ($token->value === 'INOUT')) { $expr->inOut = $token->value; ++$list->idx; - } else if ($token->value === ')') { + } elseif ($token->value === ')') { ++$list->idx; break; } else { diff --git a/libraries/sql-parser/src/Lexer.php b/libraries/sql-parser/src/Lexer.php index 238d63b1f8..2b980ab692 100644 --- a/libraries/sql-parser/src/Lexer.php +++ b/libraries/sql-parser/src/Lexer.php @@ -135,7 +135,7 @@ class Lexer // Another example is `parseComment`. $tokens = new TokensList(); - $lastToken = NULL; + $lastToken = null; for ($this->last = 0, $lastIdx = 0; $this->last < $this->len; $lastIdx = ++$this->last) { /** @var Token The new token. */ @@ -153,8 +153,8 @@ class Lexer if ($this->delimiter !== $this->str[$this->last]) { $this->error('Unexpected character.', $this->str[$this->last], $this->last); } - } else if (($token->type === Token::TYPE_SYMBOL) && ($token->flags & Token::FLAG_SYMBOL_VARIABLE) && - ($lastToken !== NULL)) { + } elseif (($token->type === Token::TYPE_SYMBOL) && ($token->flags & Token::FLAG_SYMBOL_VARIABLE) && + ($lastToken !== null)) { // Handles ```... FROM 'user'@'%' ...```. if ((($lastToken->type === Token::TYPE_SYMBOL) && ($lastToken->flags & Token::FLAG_SYMBOL_BACKTICK)) || ($lastToken->type === Token::TYPE_STRING)) { diff --git a/libraries/sql-parser/src/Parser.php b/libraries/sql-parser/src/Parser.php index 9de7fd08cf..167e9125fa 100644 --- a/libraries/sql-parser/src/Parser.php +++ b/libraries/sql-parser/src/Parser.php @@ -122,7 +122,7 @@ class Parser * @param mixed $list * @param bool $strict */ - public function __construct($list, $strict = false) + public function __construct($list = null, $strict = false) { if ((is_string($list)) || ($list instanceof UtfString)) { $lexer = new Lexer($list, $strict); @@ -130,8 +130,12 @@ class Parser } elseif ($list instanceof TokensList) { $this->list = $list; } + $this->strict = $strict; - $this->parse(); + + if ($list !== null) { + $this->parse(); + } } /** diff --git a/libraries/sql-parser/src/Token.php b/libraries/sql-parser/src/Token.php index 61fb16b57f..9b75c02f3e 100644 --- a/libraries/sql-parser/src/Token.php +++ b/libraries/sql-parser/src/Token.php @@ -223,13 +223,17 @@ class Token } return $ret; case Token::TYPE_STRING: - return mb_substr($this->token, 1, -1); // trims quotes + $quote = $this->token[0]; + $str = str_replace($quote . $quote, $quote, $this->token); + return mb_substr($str, 1, -1); // trims quotes case Token::TYPE_SYMBOL: $str = $this->token; if ((isset($str[0])) && ($str[0] === '@')) { $str = mb_substr($str, 1); } if ((isset($str[0])) && (($str[0] === '`') || ($str[0] === '"') || ($str[0] === '\''))) { + $quote = $str[0]; + $str = str_replace($quote . $quote, $quote, $str); $str = mb_substr($str, 1, -1); } return $str; diff --git a/libraries/sql-parser/src/Utils/Misc.php b/libraries/sql-parser/src/Utils/Misc.php index aca16fe294..dc8b4386c6 100644 --- a/libraries/sql-parser/src/Utils/Misc.php +++ b/libraries/sql-parser/src/Utils/Misc.php @@ -68,7 +68,7 @@ class Misc } foreach ($tree->expr as $expr) { - if ((empty($expr->column)) || (empty($expr->alias)) ){ + if ((empty($expr->column)) || (empty($expr->alias))) { continue; } @@ -87,5 +87,4 @@ class Misc return $retval; } - } diff --git a/libraries/sql-parser/src/Utils/Routine.php b/libraries/sql-parser/src/Utils/Routine.php index 1b694e24c5..126ed539f0 100644 --- a/libraries/sql-parser/src/Utils/Routine.php +++ b/libraries/sql-parser/src/Utils/Routine.php @@ -2,9 +2,81 @@ namespace SqlParser\Utils; +use SqlParser\Lexer; +use SqlParser\Parser; +use SqlParser\Statement; +use SqlParser\Fragments\DataTypeFragment; +use SqlParser\Fragments\ParamDefFragment; + class Routine { + /** + * Parses a parameter of a routine. + * + * @param string $param Parameter's definition. + * + * @return array + */ + public function getReturnType($param) + { + $lexer = new Lexer($param); + + // A dummy parser is used for error reporting. + $param = DataTypeFragment::parse(new Parser(), $lexer->tokens); + + if ($param === null) { + return array('', '', '', '', ''); + } + + $options = array(); + foreach ($param->options->options as $opt) { + $options[] = is_string($opt) ? $opt : $opt['value']; + } + + return array( + '', + '', + $param->name, + implode(',', $param->size), + implode(' ', $options) + ); + } + + /** + * Parses a parameter of a routine. + * + * @param string $param Parameter's definition. + * + * @return array + */ + public function getParameter($param) + { + $lexer = new Lexer('(' . $param . ')'); + + // A dummy parser is used for error reporting. + $param = ParamDefFragment::parse(new Parser(), $lexer->tokens); + + if (empty($param[0])) { + return array('', '', '', '', ''); + } + + $param = $param[0]; + + $options = array(); + foreach ($param->type->options->options as $opt) { + $options[] = is_string($opt) ? $opt : $opt['value']; + } + + return array( + empty($param->inOut) ? '' : $param->inOut, + $param->name, + $param->type->name, + implode(',', $param->type->size), + implode(' ', $options) + ); + } + /** * Gets the parameters of a routine from the parse tree. * @@ -12,7 +84,7 @@ class Routine * * @return array */ - public static function getParameters($tree) + public static function getParameters(Statement $tree) { $retval = array( 'num' => 0, @@ -42,5 +114,4 @@ class Routine return $retval; } - } From bf6e14393d32cd5fc4937a210d8c82597f612947 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Mon, 15 Jun 2015 20:05:20 +0300 Subject: [PATCH 10/57] Removed PMA_RTN_parseOneParameter(). Signed-off-by: Dan Ungureanu --- libraries/rte/rte_routines.lib.php | 76 ------------------- .../rte/PMA_RTN_ParameterParser_test.php | 52 ------------- 2 files changed, 128 deletions(-) diff --git a/libraries/rte/rte_routines.lib.php b/libraries/rte/rte_routines.lib.php index c36326f718..b16926001f 100644 --- a/libraries/rte/rte_routines.lib.php +++ b/libraries/rte/rte_routines.lib.php @@ -79,82 +79,6 @@ function PMA_RTN_main($type) } } // end PMA_RTN_main() -/** - * This function parses a string containing one parameter of a routine - * and returns an array containing the information about this parameter. - * - * @param string $value A string containing one parameter of a routine - * - * @return array Parsed information about the input parameter - */ -function PMA_RTN_parseOneParameter($value) -{ - global $param_directions; - - $retval = array(0 => '', - 1 => '', - 2 => '', - 3 => '', - 4 => ''); - $parsed_param = PMA_SQP_parse($value); - $pos = 0; - if (in_array( - /*overload*/mb_strtoupper($parsed_param[$pos]['data']), - $param_directions - )) { - $retval[0] = /*overload*/mb_strtoupper($parsed_param[0]['data']); - $pos++; - } - if ($parsed_param[$pos]['type'] == 'alpha_identifier' - || $parsed_param[$pos]['type'] == 'quote_backtick' - ) { - $retval[1] = PMA_Util::unQuote( - $parsed_param[$pos]['data'] - ); - $pos++; - } - $depth = 0; - $param_length = ''; - $param_opts = array(); - for ($i = $pos; $i < $parsed_param['len']; $i++) { - if (($parsed_param[$i]['type'] == 'alpha_columnType' - || $parsed_param[$i]['type'] == 'alpha_functionName') && $depth == 0 - ) { - $retval[2] = /*overload*/mb_strtoupper($parsed_param[$i]['data']); - } else if ($parsed_param[$i]['type'] == 'punct_bracket_open_round' - && $depth == 0 - ) { - $depth = 1; - } else if ($parsed_param[$i]['type'] == 'punct_bracket_close_round' - && $depth == 1 - ) { - $depth = 0; - } else if ($depth == 1) { - $param_length .= $parsed_param[$i]['data']; - } else if ($parsed_param[$i]['type'] == 'alpha_reservedWord' - && /*overload*/mb_strtoupper($parsed_param[$i]['data']) == 'CHARSET' - && $depth == 0 - ) { - if ($parsed_param[$i+1]['type'] == 'alpha_charset' - || $parsed_param[$i+1]['type'] == 'alpha_identifier' - ) { - $param_opts[] = /*overload*/mb_strtolower( - $parsed_param[$i+1]['data'] - ); - } - } else if ($parsed_param[$i]['type'] == 'alpha_columnAttrib' - && $depth == 0 - ) { - $param_opts[] = /*overload*/mb_strtoupper($parsed_param[$i]['data']); - } - } - $retval[3] = $param_length; - sort($param_opts); - $retval[4] = implode(' ', $param_opts); - - return $retval; -} // end PMA_RTN_parseOneParameter() - /** * This function looks through the contents of a parsed * SHOW CREATE [PROCEDURE | FUNCTION] query and extracts diff --git a/test/libraries/rte/PMA_RTN_ParameterParser_test.php b/test/libraries/rte/PMA_RTN_ParameterParser_test.php index cfced81a20..d94e6c0b96 100644 --- a/test/libraries/rte/PMA_RTN_ParameterParser_test.php +++ b/test/libraries/rte/PMA_RTN_ParameterParser_test.php @@ -62,57 +62,5 @@ class PMA_RTN_ParameterParser_Test extends PHPUnit_Framework_TestCase ), ); } - - /** - * Test for PMA_RTN_parseOneParameter - * - * @param string $source Source - * @param array $target Expected output - * - * @return void - * - * @dataProvider paramProvider - */ - public function testParseOneParameter($source, $target) - { - PMA_RTN_setGlobals(); - $this->assertEquals($target, PMA_RTN_parseOneParameter($source)); - } - - /** - * Data provider for testParseOneParameter - * - * @return array - */ - public function paramProvider() - { - return array( - array('`foo` TEXT', array('', 'foo', 'TEXT', '', '')), - array('`foo` INT(20)', array('', 'foo', 'INT', '20', '')), - array('DECIMAL(5,5)', array('', '', 'DECIMAL', '5,5', '')), - array( - 'IN `fo``fo` INT UNSIGNED', - array('IN', 'fo`fo', 'INT', '', 'UNSIGNED') - ), - array( - 'OUT bar VARCHAR(1) CHARSET utf8', - array('OUT', 'bar', 'VARCHAR', '1', 'utf8') - ), - array( - '`"baz\'\'` ENUM(\'a\', \'b\') CHARSET latin1', - array('', '"baz\'\'', 'ENUM', '\'a\',\'b\'', 'latin1') - ), - array( - 'INOUT `foo` DECIMAL(5,2) UNSIGNED ZEROFILL', - array('INOUT', 'foo', 'DECIMAL', '5,2', 'UNSIGNED ZEROFILL') - ), - array( - '`foo``s func` SET(\'test\'\'esc"\', \'more\\\'esc\')', - array( - '', 'foo`s func', 'SET', '\'test\'\'esc"\',\'more\\\'esc\'', '' - ) - ) - ); - } } ?> From 30e372375dbfa50158b32cb80d076d8680767518 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Sun, 21 Jun 2015 20:04:04 +0300 Subject: [PATCH 11/57] Updated sql-parser library. Signed-off-by: Dan Ungureanu --- libraries/sql-parser/src/Context.php | 308 +++++++++++++----- .../src/Contexts/Context_MySQL50000.php | 163 +++++++++ .../src/Contexts/Context_MySQL50100.php | 177 ++++++++++ .../src/Contexts/Context_MySQL50500.php | 181 ++++++++++ .../src/Contexts/Context_MySQL50600.php | 190 +++++++++++ .../src/Contexts/Context_MySQL50700.php | 199 +++++++++++ .../src/Exceptions/LexerException.php | 12 +- .../src/Exceptions/ParserException.php | 10 +- libraries/sql-parser/src/Fragment.php | 14 +- .../src/Fragments/ArrayFragment.php | 17 +- .../sql-parser/src/Fragments/CallKeyword.php | 8 +- .../src/Fragments/CreateDefFragment.php | 7 +- .../src/Fragments/DataTypeFragment.php | 21 +- .../src/Fragments/FieldDefFragment.php | 15 +- .../src/Fragments/FieldFragment.php | 23 +- .../sql-parser/src/Fragments/FromKeyword.php | 10 +- .../sql-parser/src/Fragments/IntoKeyword.php | 9 +- .../sql-parser/src/Fragments/JoinKeyword.php | 6 +- .../sql-parser/src/Fragments/LimitKeyword.php | 12 +- .../src/Fragments/OptionsFragment.php | 15 +- .../sql-parser/src/Fragments/OrderKeyword.php | 12 +- .../src/Fragments/ParamDefFragment.php | 10 +- .../src/Fragments/RenameKeyword.php | 11 +- .../src/Fragments/SelectKeyword.php | 10 +- .../sql-parser/src/Fragments/SetKeyword.php | 12 +- .../src/Fragments/ValuesKeyword.php | 11 +- .../sql-parser/src/Fragments/WhereKeyword.php | 14 +- libraries/sql-parser/src/Lexer.php | 140 +++++--- libraries/sql-parser/src/Parser.php | 10 +- libraries/sql-parser/src/Token.php | 8 +- libraries/sql-parser/src/UtfString.php | 2 +- libraries/sql-parser/src/Utils/Misc.php | 6 +- libraries/sql-parser/src/Utils/Routine.php | 6 +- 33 files changed, 1372 insertions(+), 277 deletions(-) create mode 100644 libraries/sql-parser/src/Contexts/Context_MySQL50000.php create mode 100644 libraries/sql-parser/src/Contexts/Context_MySQL50100.php create mode 100644 libraries/sql-parser/src/Contexts/Context_MySQL50500.php create mode 100644 libraries/sql-parser/src/Contexts/Context_MySQL50600.php create mode 100644 libraries/sql-parser/src/Contexts/Context_MySQL50700.php diff --git a/libraries/sql-parser/src/Context.php b/libraries/sql-parser/src/Context.php index 2b43e568a1..9102bb2bcb 100644 --- a/libraries/sql-parser/src/Context.php +++ b/libraries/sql-parser/src/Context.php @@ -26,46 +26,70 @@ abstract class Context */ const OPERATOR_MAX_LENGTH = 4; + /** + * The name of the default content. + * + * @var string + */ + public static $defaultContext = '\\SqlParser\\Contexts\\Context_MySQL50700'; + + /** + * The name of the loaded context. + * + * @var string + */ + public static $loadedContext = '\\SqlParser\\Contexts\\Context_MySQL50700'; // ------------------------------------------------------------------------- // Keywords. /** - * List of official keywords. + * List of keywords. * * Because, PHP's associative arrays are basically hash tables, it is more * efficient to store keywords as keys instead of values. * + * There are multiple types of keyword, depending on the value associated: + * 1 - reserved keywords + * 2 - keyword + * 3 - composite keyword (unofficial); used to make the job of the lexer + * much easier by grouping keywords that may appear together + * + * Keywords below are sorted by type, length and keyword. + * * @var array */ public static $KEYWORDS = array( - 'AS' => 1, 'BY' => 1, 'IF' => 1, 'IN' => 1, 'IS' => 1, 'ON' => 1, - 'OR' => 1, 'TO' => 1, - 'ADD' => 1, 'ALL' => 1, 'AND' => 1, 'ASC' => 1, 'DEC' => 1, 'DIV' => 1, - 'FOR' => 1, 'GET' => 1, 'INT' => 1, 'KEY' => 1, 'MOD' => 1, 'NOT' => 1, - 'OUT' => 1, 'SET' => 1, 'SQL' => 1, 'SSL' => 1, 'USE' => 1, 'XOR' => 1, - 'BLOB' => 1, 'BOTH' => 1, 'CALL' => 1, 'CASE' => 1, 'CHAR' => 1, - 'DESC' => 1, 'DROP' => 1, 'DUAL' => 1, 'EACH' => 1, 'ELSE' => 1, - 'EXIT' => 1, 'FROM' => 1, 'GOTO' => 1, 'INT1' => 1, 'INT2' => 1, - 'INT3' => 1, 'INT4' => 1, 'INT8' => 1, 'INTO' => 1, 'JOIN' => 1, - 'KEYS' => 1, 'KILL' => 1, 'LEFT' => 1, 'LIKE' => 1, 'LOAD' => 1, - 'LOCK' => 1, 'LONG' => 1, 'LOOP' => 1, 'NULL' => 1, 'READ' => 1, - 'REAL' => 1, 'SHOW' => 1, 'THEN' => 1, 'TRUE' => 1, 'UNDO' => 1, - 'WHEN' => 1, 'WITH' => 1, - 'ALTER' => 1, 'CHECK' => 1, 'CROSS' => 1, 'FALSE' => 1, 'FETCH' => 1, - 'FLOAT' => 1, 'FORCE' => 1, 'GRANT' => 1, 'GROUP' => 1, 'INDEX' => 1, - 'INNER' => 1, 'INOUT' => 1, 'LABEL' => 1, 'LEAVE' => 1, 'LIMIT' => 1, - 'LINES' => 1, 'MATCH' => 1, 'ORDER' => 1, 'OUTER' => 1, 'PURGE' => 1, - 'RANGE' => 1, 'READS' => 1, 'RIGHT' => 1, 'RLIKE' => 1, 'TABLE' => 1, - 'UNION' => 1, 'USAGE' => 1, 'USING' => 1, 'WHERE' => 1, 'WHILE' => 1, - 'WRITE' => 1, + 'AS' => 1, 'BY' => 1, 'IF' => 1, 'IN' => 1, 'IS' => 1, + 'ON' => 1, 'OR' => 1, 'TO' => 1, + 'ADD' => 1, 'ALL' => 1, 'AND' => 1, 'ASC' => 1, 'DEC' => 1, + 'DIV' => 1, 'FOR' => 1, 'GET' => 1, 'INT' => 1, 'KEY' => 1, + 'MOD' => 1, 'NOT' => 1, 'OUT' => 1, 'SET' => 1, 'SQL' => 1, + 'SSL' => 1, 'USE' => 1, 'XOR' => 1, + 'BLOB' => 1, 'BOTH' => 1, 'CALL' => 1, 'CASE' => 1, + 'CHAR' => 1, 'DESC' => 1, 'DROP' => 1, 'DUAL' => 1, + 'EACH' => 1, 'ELSE' => 1, 'EXIT' => 1, 'FROM' => 1, + 'INT1' => 1, 'INT2' => 1, 'INT3' => 1, 'INT4' => 1, + 'INT8' => 1, 'INTO' => 1, 'JOIN' => 1, 'KEYS' => 1, + 'KILL' => 1, 'LEFT' => 1, 'LIKE' => 1, 'LOAD' => 1, + 'LOCK' => 1, 'LONG' => 1, 'LOOP' => 1, 'NULL' => 1, + 'READ' => 1, 'REAL' => 1, 'SHOW' => 1, 'THEN' => 1, + 'TRUE' => 1, 'UNDO' => 1, 'WHEN' => 1, 'WITH' => 1, + 'ALTER' => 1, 'CHECK' => 1, 'CROSS' => 1, 'FALSE' => 1, + 'FETCH' => 1, 'FLOAT' => 1, 'FORCE' => 1, 'GRANT' => 1, + 'GROUP' => 1, 'INDEX' => 1, 'INNER' => 1, 'INOUT' => 1, + 'LEAVE' => 1, 'LIMIT' => 1, 'LINES' => 1, 'MATCH' => 1, + 'ORDER' => 1, 'OUTER' => 1, 'PURGE' => 1, 'RANGE' => 1, + 'READS' => 1, 'RIGHT' => 1, 'RLIKE' => 1, 'TABLE' => 1, + 'UNION' => 1, 'USAGE' => 1, 'USING' => 1, 'WHERE' => 1, + 'WHILE' => 1, 'WRITE' => 1, 'BEFORE' => 1, 'BIGINT' => 1, 'BINARY' => 1, 'CHANGE' => 1, 'COLUMN' => 1, 'CREATE' => 1, 'CURSOR' => 1, 'DELETE' => 1, 'DOUBLE' => 1, 'ELSEIF' => 1, 'EXISTS' => 1, 'FLOAT4' => 1, 'FLOAT8' => 1, 'HAVING' => 1, 'IGNORE' => 1, 'INFILE' => 1, 'INSERT' => 1, 'LINEAR' => 1, 'OPTION' => 1, 'REGEXP' => 1, 'RENAME' => 1, 'REPEAT' => 1, 'RETURN' => 1, 'REVOKE' => 1, - 'SCHEMA' => 1, 'SELECT' => 1, 'SIGNAL' => 1, 'SONAME' => 1, + 'SCHEMA' => 1, 'SELECT' => 1, 'SIGNAL' => 1, 'STORED' => 1, 'UNIQUE' => 1, 'UNLOCK' => 1, 'UPDATE' => 1, 'VALUES' => 1, 'ANALYZE' => 1, 'BETWEEN' => 1, 'CASCADE' => 1, 'COLLATE' => 1, 'CONVERT' => 1, 'DECIMAL' => 1, 'DECLARE' => 1, 'DEFAULT' => 1, @@ -73,23 +97,27 @@ abstract class Context 'INTEGER' => 1, 'ITERATE' => 1, 'LEADING' => 1, 'NATURAL' => 1, 'NUMERIC' => 1, 'OUTFILE' => 1, 'PRIMARY' => 1, 'RELEASE' => 1, 'REPLACE' => 1, 'REQUIRE' => 1, 'SCHEMAS' => 1, 'SPATIAL' => 1, - 'TINYINT' => 1, 'TRIGGER' => 1, 'UPGRADE' => 1, 'VARCHAR' => 1, - 'VARYING' => 1, - 'CONTINUE' => 1, 'DATABASE' => 1, 'DAY_HOUR' => 1, 'DESCRIBE' => 1, - 'DISTINCT' => 1, 'ENCLOSED' => 1, 'FULLTEXT' => 1, 'INTERVAL' => 1, - 'LONGBLOB' => 1, 'LONGTEXT' => 1, 'MAXVALUE' => 1, 'MODIFIES' => 1, - 'OPTIMIZE' => 1, 'RESIGNAL' => 1, 'RESTRICT' => 1, 'SMALLINT' => 1, - 'SPECIFIC' => 1, 'SQLSTATE' => 1, 'STARTING' => 1, 'TINYBLOB' => 1, - 'TINYTEXT' => 1, 'TRAILING' => 1, 'UNSIGNED' => 1, 'UTC_DATE' => 1, + 'TINYINT' => 1, 'TRIGGER' => 1, 'VARCHAR' => 1, 'VARYING' => 1, + 'VIRTUAL' => 1, + 'CONTINUE' => 1, 'DATABASE' => 1, 'DAY_HOUR' => 1, + 'DESCRIBE' => 1, 'DISTINCT' => 1, 'ENCLOSED' => 1, + 'FULLTEXT' => 1, 'INTERVAL' => 1, 'LONGBLOB' => 1, + 'LONGTEXT' => 1, 'MAXVALUE' => 1, 'MODIFIES' => 1, + 'OPTIMIZE' => 1, 'RESIGNAL' => 1, 'RESTRICT' => 1, + 'SMALLINT' => 1, 'SPECIFIC' => 1, 'SQLSTATE' => 1, + 'STARTING' => 1, 'TINYBLOB' => 1, 'TINYTEXT' => 1, + 'TRAILING' => 1, 'UNSIGNED' => 1, 'UTC_DATE' => 1, 'UTC_TIME' => 1, 'ZEROFILL' => 1, - 'CHARACTER' => 1, 'CONDITION' => 1, 'DATABASES' => 1, 'LOCALTIME' => 1, - 'MEDIUMINT' => 1, 'MIDDLEINT' => 1, 'PARTITION' => 1, 'PRECISION' => 1, - 'PROCEDURE' => 1, 'SENSITIVE' => 1, 'SEPARATOR' => 1, 'VARBINARY' => 1, - 'ACCESSIBLE' => 1, 'ASENSITIVE' => 1, 'CONNECTION' => 1, - 'CONSTRAINT' => 1, 'DAY_MINUTE' => 1, 'DAY_SECOND' => 1, - 'MEDIUMBLOB' => 1, 'MEDIUMTEXT' => 1, 'OPTIONALLY' => 1, - 'READ_WRITE' => 1, 'REFERENCES' => 1, 'SQLWARNING' => 1, - 'TERMINATED' => 1, 'YEAR_MONTH' => 1, + 'CHARACTER' => 1, 'CONDITION' => 1, 'DATABASES' => 1, + 'GENERATED' => 1, 'LOCALTIME' => 1, 'MEDIUMINT' => 1, + 'MIDDLEINT' => 1, 'PARTITION' => 1, 'PRECISION' => 1, + 'PROCEDURE' => 1, 'SENSITIVE' => 1, 'SEPARATOR' => 1, + 'VARBINARY' => 1, + 'ACCESSIBLE' => 1, 'ASENSITIVE' => 1, 'CONSTRAINT' => 1, + 'DAY_MINUTE' => 1, 'DAY_SECOND' => 1, 'MEDIUMBLOB' => 1, + 'MEDIUMTEXT' => 1, 'OPTIONALLY' => 1, 'READ_WRITE' => 1, + 'REFERENCES' => 1, 'SQLWARNING' => 1, 'TERMINATED' => 1, + 'YEAR_MONTH' => 1, 'DISTINCTROW' => 1, 'HOUR_MINUTE' => 1, 'HOUR_SECOND' => 1, 'INSENSITIVE' => 1, 'MASTER_BIND' => 1, 'CURRENT_DATE' => 1, 'CURRENT_TIME' => 1, 'CURRENT_USER' => 1, @@ -105,33 +133,118 @@ abstract class Context 'SQL_CALC_FOUND_ROWS' => 1, 'MASTER_SSL_VERIFY_SERVER_CERT' => 1, - /* - * Secondary group of keywords. - * - * Keywords below are either words that are used as keywords, but not - * defined as proper keywords or are group of keywords which are parsed - * easier when found grouped. - */ + 'AT' => 2, 'DO' => 2, 'IO' => 2, 'NO' => 2, 'XA' => 2, + 'ANY' => 2, 'AVG' => 2, 'BIT' => 2, 'CPU' => 2, 'DAY' => 2, 'END' => 2, + 'IPC' => 2, 'NDB' => 2, 'NEW' => 2, 'ONE' => 2, 'ROW' => 2, 'XID' => 2, + 'XML' => 2, + 'BOOL' => 2, 'BYTE' => 2, 'CODE' => 2, 'CUBE' => 2, 'DATA' => 2, 'DATE' => 2, + 'DISK' => 2, 'ENDS' => 2, 'ENUM' => 2, 'FAST' => 2, 'FILE' => 2, 'FULL' => 2, + 'HASH' => 2, 'HELP' => 2, 'HOST' => 2, 'HOUR' => 2, 'LAST' => 2, 'LESS' => 2, + 'LIST' => 2, 'LOGS' => 2, 'MODE' => 2, 'NAME' => 2, 'NEXT' => 2, 'NONE' => 2, + 'ONLY' => 2, 'OPEN' => 2, 'PAGE' => 2, 'PORT' => 2, 'PREV' => 2, 'ROWS' => 2, + 'SLOW' => 2, 'SOME' => 2, 'STOP' => 2, 'TEXT' => 2, 'THAN' => 2, 'TIME' => 2, + 'TYPE' => 2, 'USER' => 2, 'VIEW' => 2, 'WAIT' => 2, 'WEEK' => 2, 'WORK' => 2, + 'X509' => 2, 'YEAR' => 2, + 'AFTER' => 2, 'ASCII' => 2, 'BEGIN' => 2, 'BLOCK' => 2, 'BTREE' => 2, + 'CACHE' => 2, 'CHAIN' => 2, 'CLOSE' => 2, 'ERROR' => 2, 'EVENT' => 2, + 'EVERY' => 2, 'FIRST' => 2, 'FIXED' => 2, 'FLUSH' => 2, 'FOUND' => 2, + 'HOSTS' => 2, 'LEVEL' => 2, 'LOCAL' => 2, 'LOCKS' => 2, 'MERGE' => 2, + 'MONTH' => 2, 'MUTEX' => 2, 'NAMES' => 2, 'NCHAR' => 2, 'NEVER' => 2, + 'OWNER' => 2, 'PHASE' => 2, 'POINT' => 2, 'PROXY' => 2, 'QUERY' => 2, + 'QUICK' => 2, 'RELAY' => 2, 'RESET' => 2, 'RTREE' => 2, 'SHARE' => 2, + 'SLAVE' => 2, 'START' => 2, 'SUPER' => 2, 'SWAPS' => 2, 'TYPES' => 2, + 'UNTIL' => 2, 'VALUE' => 2, + 'ACTION' => 2, 'ALWAYS' => 2, 'BACKUP' => 2, 'BINLOG' => 2, 'CIPHER' => 2, + 'CLIENT' => 2, 'COMMIT' => 2, 'ENABLE' => 2, 'ENGINE' => 2, 'ERRORS' => 2, + 'ESCAPE' => 2, 'EVENTS' => 2, 'EXPIRE' => 2, 'EXPORT' => 2, 'FAULTS' => 2, + 'FIELDS' => 2, 'FILTER' => 2, 'FORMAT' => 2, 'GLOBAL' => 2, 'GRANTS' => 2, + 'IMPORT' => 2, 'ISSUER' => 2, 'LEAVES' => 2, 'MASTER' => 2, 'MEDIUM' => 2, + 'MEMORY' => 2, 'MINUTE' => 2, 'MODIFY' => 2, 'NUMBER' => 2, 'OFFSET' => 2, + 'PARSER' => 2, 'PLUGIN' => 2, 'RELOAD' => 2, 'REMOVE' => 2, 'REPAIR' => 2, + 'RESUME' => 2, 'ROLLUP' => 2, 'SECOND' => 2, 'SERIAL' => 2, 'SERVER' => 2, + 'SIGNED' => 2, 'SIMPLE' => 2, 'SOCKET' => 2, 'SONAME' => 2, 'SOUNDS' => 2, + 'SOURCE' => 2, 'STARTS' => 2, 'STATUS' => 2, 'STRING' => 2, 'TABLES' => 2, + 'ACCOUNT' => 2, 'AGAINST' => 2, 'ANALYSE' => 2, 'BOOLEAN' => 2, 'CHANGED' => 2, + 'CHANNEL' => 2, 'CHARSET' => 2, 'COLUMNS' => 2, 'COMMENT' => 2, 'COMPACT' => 2, + 'CONTEXT' => 2, 'CURRENT' => 2, 'DEFINER' => 2, 'DISABLE' => 2, 'DISCARD' => 2, + 'DYNAMIC' => 2, 'ENGINES' => 2, 'EXECUTE' => 2, 'FOLLOWS' => 2, 'GENERAL' => 2, + 'HANDLER' => 2, 'INDEXES' => 2, 'INSTALL' => 2, 'INVOKER' => 2, 'LOGFILE' => 2, + 'MIGRATE' => 2, 'NO_WAIT' => 2, 'OPTIONS' => 2, 'PARTIAL' => 2, 'PLUGINS' => 2, + 'POLYGON' => 2, 'PREPARE' => 2, 'PROFILE' => 2, 'QUARTER' => 2, 'REBUILD' => 2, + 'RECOVER' => 2, 'RESTORE' => 2, 'RETURNS' => 2, 'REVERSE' => 2, 'ROUTINE' => 2, + 'SESSION' => 2, 'STACKED' => 2, 'STORAGE' => 2, 'SUBJECT' => 2, 'SUSPEND' => 2, + 'UNICODE' => 2, 'UNKNOWN' => 2, 'UPGRADE' => 2, 'USE_FRM' => 2, 'WITHOUT' => 2, + 'WRAPPER' => 2, + 'CASCADED' => 2, 'CHECKSUM' => 2, 'COALESCE' => 2, 'CONTAINS' => 2, + 'DATAFILE' => 2, 'DATETIME' => 2, 'DUMPFILE' => 2, 'EXCHANGE' => 2, + 'EXTENDED' => 2, 'FUNCTION' => 2, 'GEOMETRY' => 2, 'LANGUAGE' => 2, + 'MAX_ROWS' => 2, 'MAX_SIZE' => 2, 'MIN_ROWS' => 2, 'NATIONAL' => 2, + 'NVARCHAR' => 2, 'PASSWORD' => 2, 'PRECEDES' => 2, 'PRESERVE' => 2, + 'PROFILES' => 2, 'REDOFILE' => 2, 'RELAYLOG' => 2, 'ROLLBACK' => 2, + 'SCHEDULE' => 2, 'SECURITY' => 2, 'SHUTDOWN' => 2, 'SNAPSHOT' => 2, + 'SWITCHES' => 2, 'TRIGGERS' => 2, 'TRUNCATE' => 2, 'UNDOFILE' => 2, + 'WARNINGS' => 2, + 'AGGREGATE' => 2, 'ALGORITHM' => 2, 'COLLATION' => 2, 'COMMITTED' => 2, + 'DIRECTORY' => 2, 'DUPLICATE' => 2, 'EXPANSION' => 2, 'IO_THREAD' => 2, + 'ISOLATION' => 2, 'NODEGROUP' => 2, 'PACK_KEYS' => 2, 'READ_ONLY' => 2, + 'REDUNDANT' => 2, 'ROW_COUNT' => 2, 'SAVEPOINT' => 2, 'SQL_CACHE' => 2, + 'TEMPORARY' => 2, 'TEMPTABLE' => 2, 'TIMESTAMP' => 2, 'UNDEFINED' => 2, + 'UNINSTALL' => 2, 'VARIABLES' => 2, + 'COMPLETION' => 2, 'COMPRESSED' => 2, 'CONCURRENT' => 2, 'CONNECTION' => 2, + 'CONSISTENT' => 2, 'DEALLOCATE' => 2, 'GET_FORMAT' => 2, 'IDENTIFIED' => 2, + 'LINESTRING' => 2, 'MASTER_SSL' => 2, 'MULTIPOINT' => 2, 'NDBCLUSTER' => 2, + 'PARTITIONS' => 2, 'PLUGIN_DIR' => 2, 'PRIVILEGES' => 2, 'REORGANIZE' => 2, + 'REPEATABLE' => 2, 'ROW_FORMAT' => 2, 'SQL_THREAD' => 2, 'TABLESPACE' => 2, + 'TABLE_NAME' => 2, 'VALIDATION' => 2, + 'COLUMN_NAME' => 2, 'COMPRESSION' => 2, 'CURSOR_NAME' => 2, 'DIAGNOSTICS' => 2, + 'EXTENT_SIZE' => 2, 'MASTER_HOST' => 2, 'MASTER_PORT' => 2, 'MASTER_USER' => 2, + 'MICROSECOND' => 2, 'MYSQL_ERRNO' => 2, 'NONBLOCKING' => 2, 'PROCESSLIST' => 2, + 'REPLICATION' => 2, 'SCHEMA_NAME' => 2, 'SQL_TSI_DAY' => 2, 'TRANSACTION' => 2, + 'UNCOMMITTED' => 2, + 'CATALOG_NAME' => 2, 'CLASS_ORIGIN' => 2, 'DEFAULT_AUTH' => 2, + 'DES_KEY_FILE' => 2, 'INITIAL_SIZE' => 2, 'MASTER_DELAY' => 2, + 'MESSAGE_TEXT' => 2, 'MULTIPOLYGON' => 2, 'OLD_PASSWORD' => 2, + 'PARTITIONING' => 2, 'RELAY_THREAD' => 2, 'SERIALIZABLE' => 2, + 'SQL_NO_CACHE' => 2, 'SQL_TSI_HOUR' => 2, 'SQL_TSI_WEEK' => 2, + 'SQL_TSI_YEAR' => 2, 'SUBPARTITION' => 2, 'TIMESTAMPADD' => 2, + 'COLUMN_FORMAT' => 2, 'INSERT_METHOD' => 2, 'MASTER_SSL_CA' => 2, + 'RELAY_LOG_POS' => 2, 'SQL_TSI_MONTH' => 2, 'SUBPARTITIONS' => 2, + 'TIMESTAMPDIFF' => 2, 'WEIGHT_STRING' => 2, + 'AUTO_INCREMENT' => 2, 'AVG_ROW_LENGTH' => 2, 'KEY_BLOCK_SIZE' => 2, + 'MASTER_LOG_POS' => 2, 'MASTER_SSL_CRL' => 2, 'MASTER_SSL_KEY' => 2, + 'RELAY_LOG_FILE' => 2, 'SQL_TSI_MINUTE' => 2, 'SQL_TSI_SECOND' => 2, + 'TABLE_CHECKSUM' => 2, 'USER_RESOURCES' => 2, + 'AUTOEXTEND_SIZE' => 2, 'CONSTRAINT_NAME' => 2, 'DELAY_KEY_WRITE' => 2, + 'FILE_BLOCK_SIZE' => 2, 'MASTER_LOG_FILE' => 2, 'MASTER_PASSWORD' => 2, + 'MASTER_SSL_CERT' => 2, 'MULTILINESTRING' => 2, 'PARSE_GCOL_EXPR' => 2, + 'REPLICATE_DO_DB' => 2, 'SQL_AFTER_GTIDS' => 2, 'SQL_TSI_QUARTER' => 2, + 'SUBCLASS_ORIGIN' => 2, + 'MASTER_SERVER_ID' => 2, 'REDO_BUFFER_SIZE' => 2, 'SQL_BEFORE_GTIDS' => 2, + 'STATS_PERSISTENT' => 2, 'UNDO_BUFFER_SIZE' => 2, + 'CONSTRAINT_SCHEMA' => 2, 'GROUP_REPLICATION' => 2, 'IGNORE_SERVER_IDS' => 2, + 'MASTER_SSL_CAPATH' => 2, 'MASTER_SSL_CIPHER' => 2, 'RETURNED_SQLSTATE' => 2, + 'SQL_BUFFER_RESULT' => 2, 'STATS_AUTO_RECALC' => 2, + 'CONSTRAINT_CATALOG' => 2, 'GEOMETRYCOLLECTION' => 2, 'MASTER_RETRY_COUNT' => 2, + 'MASTER_SSL_CRLPATH' => 2, 'MAX_STATEMENT_TIME' => 2, 'REPLICATE_DO_TABLE' => 2, + 'SQL_AFTER_MTS_GAPS' => 2, 'STATS_SAMPLE_PAGES' => 2, + 'REPLICATE_IGNORE_DB' => 2, + 'MASTER_AUTO_POSITION' => 2, 'MASTER_CONNECT_RETRY' => 2, + 'MAX_QUERIES_PER_HOUR' => 2, 'MAX_UPDATES_PER_HOUR' => 2, + 'MAX_USER_CONNECTIONS' => 2, 'REPLICATE_REWRITE_DB' => 2, + 'REPLICATE_IGNORE_TABLE' => 2, + 'MASTER_HEARTBEAT_PERIOD' => 2, 'REPLICATE_WILD_DO_TABLE' => 2, + 'MAX_CONNECTIONS_PER_HOUR' => 2, + 'REPLICATE_WILD_IGNORE_TABLE' => 2, - 'END' => 2, - 'INDEX' => 2, 'VALUE' => 2, - 'ENGINE' => 2, - 'CHARSET' => 2, 'COMMENT' => 2, 'RETURNS' => 2, 'STORAGE' => 2, - 'CHECKSUM' => 2, 'MAX_ROWS' => 2, 'MIN_ROWS' => 2, 'NOT NULL' => 2, - 'PASSWORD' => 2, - 'INDEX KEY' => 2, 'PACK_KEYS' => 2, - 'ROW_FORMAT' => 2, 'TABLESPACE' => 2, - 'UNIQUE KEY' => 2, - 'FOREIGN KEY' => 2, 'PRIMARY KEY' => 2, 'PRIMARY KEY' => 2, - 'SPATIAL KEY' => 2, - 'FULLTEXT KEY' => 2, 'UNIQUE INDEX' => 2, - 'CHARACTER SET' => 2, 'IF NOT EXISTS' => 2, 'INSERT_METHOD' => 2, - 'SPATIAL INDEX' => 2, - 'AUTO_INCREMENT' => 2, 'AVG_ROW_LENGTH' => 2, 'DATA DIRECTORY' => 2, - 'FULLTEXT INDEX' => 2, 'KEY_BLOCK_SIZE' => 2, - 'DEFAULT COLLATE' => 2, - 'DELAY_KEY_WRITE' => 2, 'INDEX DIRECTORY' => 2, - 'DEFAULT CHARACTER SET' => 2, + 'NOT NULL' => 4, + 'INDEX KEY' => 4, + 'UNIQUE KEY' => 4, + 'FOREIGN KEY' => 4, 'PRIMARY KEY' => 4, 'PRIMARY KEY' => 4, 'SPATIAL KEY' => 4, + 'FULLTEXT KEY' => 4, 'UNIQUE INDEX' => 4, + 'CHARACTER SET' => 4, 'IF NOT EXISTS' => 4, 'SPATIAL INDEX' => 4, + 'DATA DIRECTORY' => 4, 'FULLTEXT INDEX' => 4, + 'DEFAULT COLLATE' => 4, 'INDEX DIRECTORY' => 4, + 'DEFAULT CHARACTER SET' => 4, ); // ------------------------------------------------------------------------- @@ -155,12 +268,15 @@ abstract class Context * @var array */ public static $DATA_TYPES = array( - 'ARRAY' => 1, 'BIGINT' => 1, 'BINARY VARYING' => 1, 'BINARY' => 1, - 'BOOLEAN' => 1, 'CHARACTER' => 1, 'CHARACTER' => 1, 'DATE' => 1, - 'DECIMAL' => 1, 'DOUBLE' => 1, 'FLOAT' => 1, 'FLOAT' => 1, 'INT' => 1, - 'INTEGER' => 1, 'INTERVAL' => 1, 'MULTISET' => 1, 'NUMERIC' => 1, - 'REAL' => 1, 'SMALLINT' => 1, 'TIME' => 1, 'TIMESTAMP' => 1, - 'VARBINARY' => 1, 'VARCHAR' => 1, 'XML' => 1, + 'ARRAY' => 1, 'BIGINT' => 1, 'BINARY' => 1, 'BINARY VARYING' => 1, + 'BLOB' => 1, 'BOOLEAN' => 1, 'CHAR' => 1, 'CHARACTER' => 1, 'DATE' => 1, + 'DATETIME' => 1, 'DECIMAL' => 1, 'DOUBLE' => 1, 'ENUM' => 1, + 'FLOAT' => 1, 'INT' => 1, 'INTEGER' => 1, 'INTERVAL' => 1, + 'LONGBLOB' => 1, 'LONGTEXT' => 1, 'MEDIUMBLOB' => 1, 'MEDIUMINT' => 1, + 'MEDIUMTEXT' => 1, 'MULTISET' => 1, 'NUMERIC' => 1, 'REAL' => 1, + 'SET' => 1, 'SMALLINT' => 1, 'TEXT' => 1, 'TIME' => 1, 'TIMESTAMP' => 1, + 'TINYBLOB' => 1, 'TINYINT' => 1, 'TINYTEXT' => 1, 'VARBINARY' => 1, + 'VARCHAR' => 1, 'XML' => 1, 'YEAR' => 1 ); // ------------------------------------------------------------------------- @@ -309,19 +425,24 @@ abstract class Context * Checks if the given string is a keyword. * * @param string $str - * @param bool $strict + * @param bool $isReserved * * @return bool */ - public static function isKeyword($str, $strict = false) + public static function isKeyword($str, $isReserved = false) { $str = strtoupper($str); if (isset(static::$KEYWORDS[$str])) { - return $strict ? static::$KEYWORDS[$str] === 1 : true; + if ($isReserved) { + if (!(static::$KEYWORDS[$str] & Token::FLAG_KEYWORD_RESERVED)) { + return null; + } + } + return static::$KEYWORDS[$str]; } - return false; + return null; } // ------------------------------------------------------------------------- @@ -372,12 +493,14 @@ abstract class Context $len = strlen($str); if ($str[0] === '#') { return Token::FLAG_COMMENT_BASH; - } elseif (($len > 1) && ((($str[0] === '/') && ($str[1] === '*')) || - (($str[0] === '*') && ($str[1] === '/')))) { + } elseif (($len > 1) && ((($str[0] === '/') && ($str[1] === '*')) + || (($str[0] === '*') && ($str[1] === '/'))) + ) { return Token::FLAG_COMMENT_C; - } elseif (($len > 2) && ($str[0] === '-') && - ($str[1] === '-') && ($str[2] !== "\n") && - (static::isWhitespace($str[2]))) { + } elseif (($len > 2) && ($str[0] === '-') + && ($str[1] === '-') && ($str[2] !== "\n") + && (static::isWhitespace($str[2])) + ) { return Token::FLAG_COMMENT_SQL; } return null; @@ -413,8 +536,8 @@ abstract class Context */ public static function isNumber($ch) { - return (($ch >= '0') && ($ch <= '9')) || ($ch === '.') || - ($ch === '-') || ($ch === '+') || ($ch === 'e') || ($ch === 'E'); + return (($ch >= '0') && ($ch <= '9')) || ($ch === '.') + || ($ch === '-') || ($ch === '+') || ($ch === 'e') || ($ch === 'E'); } // ------------------------------------------------------------------------- @@ -472,4 +595,27 @@ abstract class Context { return !ctype_alnum($ch) && $ch !== '_'; } + + /** + * Loads the specified context. + * + * Contexts may be used by accessing the context directly. + * + * @param string $context + */ + public static function load($context = '') + { + if (empty($context)) { + $context = self::$defaultContext; + } + if ($context[0] !== '\\') { + // Short context name (must be formatted into class name). + $context = '\\SqlParser\\Contexts\\Context_' . $context; + } + if (!class_exists($context)) { + throw new \Exception('Specified context ("' . $context . '") doesn\'t exist.'); + } + static::$loadedContext = $context; + static::$KEYWORDS = $context::$KEYWORDS; + } } diff --git a/libraries/sql-parser/src/Contexts/Context_MySQL50000.php b/libraries/sql-parser/src/Contexts/Context_MySQL50000.php new file mode 100644 index 0000000000..e1d036ef0c --- /dev/null +++ b/libraries/sql-parser/src/Contexts/Context_MySQL50000.php @@ -0,0 +1,163 @@ + 1, 'BY' => 1, 'IF' => 1, 'IN' => 1, 'IS' => 1, + 'ON' => 1, 'OR' => 1, 'TO' => 1, + 'ADD' => 1, 'ALL' => 1, 'AND' => 1, 'ASC' => 1, 'DEC' => 1, + 'DIV' => 1, 'FOR' => 1, 'INT' => 1, 'KEY' => 1, 'MOD' => 1, + 'NOT' => 1, 'OUT' => 1, 'SET' => 1, 'SQL' => 1, 'SSL' => 1, + 'USE' => 1, 'XOR' => 1, + 'BLOB' => 1, 'BOTH' => 1, 'CALL' => 1, 'CASE' => 1, + 'CHAR' => 1, 'DESC' => 1, 'DROP' => 1, 'DUAL' => 1, + 'EACH' => 1, 'ELSE' => 1, 'EXIT' => 1, 'FROM' => 1, + 'INT1' => 1, 'INT2' => 1, 'INT3' => 1, 'INT4' => 1, + 'INT8' => 1, 'INTO' => 1, 'JOIN' => 1, 'KEYS' => 1, + 'KILL' => 1, 'LEFT' => 1, 'LIKE' => 1, 'LOAD' => 1, + 'LOCK' => 1, 'LONG' => 1, 'LOOP' => 1, 'NULL' => 1, + 'READ' => 1, 'REAL' => 1, 'SHOW' => 1, 'THEN' => 1, + 'TRUE' => 1, 'UNDO' => 1, 'WHEN' => 1, 'WITH' => 1, + 'ALTER' => 1, 'CHECK' => 1, 'CROSS' => 1, 'FALSE' => 1, + 'FETCH' => 1, 'FLOAT' => 1, 'FORCE' => 1, 'GRANT' => 1, + 'GROUP' => 1, 'INDEX' => 1, 'INNER' => 1, 'INOUT' => 1, + 'LEAVE' => 1, 'LIMIT' => 1, 'LINES' => 1, 'MATCH' => 1, + 'ORDER' => 1, 'OUTER' => 1, 'PURGE' => 1, 'READS' => 1, + 'RIGHT' => 1, 'RLIKE' => 1, 'TABLE' => 1, 'UNION' => 1, + 'USAGE' => 1, 'USING' => 1, 'WHERE' => 1, 'WHILE' => 1, + 'WRITE' => 1, + 'BEFORE' => 1, 'BIGINT' => 1, 'BINARY' => 1, 'CHANGE' => 1, + 'COLUMN' => 1, 'CREATE' => 1, 'CURSOR' => 1, 'DELETE' => 1, + 'DOUBLE' => 1, 'ELSEIF' => 1, 'EXISTS' => 1, 'FLOAT4' => 1, + 'FLOAT8' => 1, 'HAVING' => 1, 'IGNORE' => 1, 'INFILE' => 1, + 'INSERT' => 1, 'OPTION' => 1, 'REGEXP' => 1, 'RENAME' => 1, + 'REPEAT' => 1, 'RETURN' => 1, 'REVOKE' => 1, 'SCHEMA' => 1, + 'SELECT' => 1, 'SONAME' => 1, 'UNIQUE' => 1, 'UNLOCK' => 1, + 'UPDATE' => 1, 'VALUES' => 1, + 'ANALYZE' => 1, 'BETWEEN' => 1, 'CASCADE' => 1, 'COLLATE' => 1, + 'CONVERT' => 1, 'DECIMAL' => 1, 'DECLARE' => 1, 'DEFAULT' => 1, + 'DELAYED' => 1, 'ESCAPED' => 1, 'EXPLAIN' => 1, 'FOREIGN' => 1, + 'INTEGER' => 1, 'ITERATE' => 1, 'LEADING' => 1, 'NATURAL' => 1, + 'NUMERIC' => 1, 'OUTFILE' => 1, 'PRIMARY' => 1, 'RELEASE' => 1, + 'REPLACE' => 1, 'REQUIRE' => 1, 'SCHEMAS' => 1, 'SPATIAL' => 1, + 'TINYINT' => 1, 'TRIGGER' => 1, 'VARCHAR' => 1, 'VARYING' => 1, + 'CONTINUE' => 1, 'DATABASE' => 1, 'DAY_HOUR' => 1, + 'DESCRIBE' => 1, 'DISTINCT' => 1, 'ENCLOSED' => 1, + 'FULLTEXT' => 1, 'INTERVAL' => 1, 'LONGBLOB' => 1, + 'LONGTEXT' => 1, 'MODIFIES' => 1, 'OPTIMIZE' => 1, + 'RESTRICT' => 1, 'SMALLINT' => 1, 'SPECIFIC' => 1, + 'SQLSTATE' => 1, 'STARTING' => 1, 'TINYBLOB' => 1, + 'TINYTEXT' => 1, 'TRAILING' => 1, 'UNSIGNED' => 1, + 'UTC_DATE' => 1, 'UTC_TIME' => 1, 'ZEROFILL' => 1, + 'CHARACTER' => 1, 'CONDITION' => 1, 'DATABASES' => 1, + 'LOCALTIME' => 1, 'MEDIUMINT' => 1, 'MIDDLEINT' => 1, + 'PRECISION' => 1, 'PROCEDURE' => 1, 'SENSITIVE' => 1, + 'SEPARATOR' => 1, 'VARBINARY' => 1, + 'ASENSITIVE' => 1, 'CONSTRAINT' => 1, 'DAY_MINUTE' => 1, + 'DAY_SECOND' => 1, 'MEDIUMBLOB' => 1, 'MEDIUMTEXT' => 1, + 'OPTIONALLY' => 1, 'REFERENCES' => 1, 'SQLWARNING' => 1, + 'TERMINATED' => 1, 'YEAR_MONTH' => 1, + 'DISTINCTROW' => 1, 'HOUR_MINUTE' => 1, 'HOUR_SECOND' => 1, + 'INSENSITIVE' => 1, + 'CURRENT_DATE' => 1, 'CURRENT_TIME' => 1, 'CURRENT_USER' => 1, + 'LOW_PRIORITY' => 1, 'SQLEXCEPTION' => 1, 'VARCHARACTER' => 1, + 'DETERMINISTIC' => 1, 'HIGH_PRIORITY' => 1, 'MINUTE_SECOND' => 1, + 'STRAIGHT_JOIN' => 1, 'UTC_TIMESTAMP' => 1, + 'LOCALTIMESTAMP' => 1, 'SQL_BIG_RESULT' => 1, + 'DAY_MICROSECOND' => 1, + 'HOUR_MICROSECOND' => 1, 'SQL_SMALL_RESULT' => 1, + 'CURRENT_TIMESTAMP' => 1, + 'MINUTE_MICROSECOND' => 1, 'NO_WRITE_TO_BINLOG' => 1, + 'SECOND_MICROSECOND' => 1, + 'SQL_CALC_FOUND_ROWS' => 1, + + 'DO' => 2, 'IO' => 2, 'NO' => 2, 'XA' => 2, + 'ANY' => 2, 'AVG' => 2, 'BDB' => 2, 'BIT' => 2, 'CPU' => 2, 'DAY' => 2, + 'END' => 2, 'IPC' => 2, 'NDB' => 2, 'NEW' => 2, 'ONE' => 2, 'ROW' => 2, + 'BOOL' => 2, 'BYTE' => 2, 'CODE' => 2, 'CUBE' => 2, 'DATA' => 2, 'DATE' => 2, + 'ENUM' => 2, 'FAST' => 2, 'FILE' => 2, 'FULL' => 2, 'HASH' => 2, 'HELP' => 2, + 'HOUR' => 2, 'LAST' => 2, 'LOGS' => 2, 'MODE' => 2, 'NAME' => 2, 'NEXT' => 2, + 'NONE' => 2, 'OPEN' => 2, 'PAGE' => 2, 'PREV' => 2, 'ROWS' => 2, 'SOME' => 2, + 'STOP' => 2, 'TEXT' => 2, 'TIME' => 2, 'TYPE' => 2, 'USER' => 2, 'VIEW' => 2, + 'WEEK' => 2, 'WORK' => 2, 'X509' => 2, 'YEAR' => 2, + 'AFTER' => 2, 'ASCII' => 2, 'BEGIN' => 2, 'BLOCK' => 2, 'BTREE' => 2, + 'CACHE' => 2, 'CHAIN' => 2, 'CLOSE' => 2, 'FIRST' => 2, 'FIXED' => 2, + 'FLUSH' => 2, 'FOUND' => 2, 'HOSTS' => 2, 'LEVEL' => 2, 'LOCAL' => 2, + 'LOCKS' => 2, 'MERGE' => 2, 'MONTH' => 2, 'MUTEX' => 2, 'NAMES' => 2, + 'NCHAR' => 2, 'PHASE' => 2, 'POINT' => 2, 'QUERY' => 2, 'QUICK' => 2, + 'RAID0' => 2, 'RESET' => 2, 'RTREE' => 2, 'SHARE' => 2, 'SLAVE' => 2, + 'START' => 2, 'SUPER' => 2, 'SWAPS' => 2, 'TYPES' => 2, 'UNTIL' => 2, + 'VALUE' => 2, + 'ACTION' => 2, 'BACKUP' => 2, 'BINLOG' => 2, 'CIPHER' => 2, 'CLIENT' => 2, + 'COMMIT' => 2, 'ENABLE' => 2, 'ENGINE' => 2, 'ERRORS' => 2, 'ESCAPE' => 2, + 'EVENTS' => 2, 'FAULTS' => 2, 'FIELDS' => 2, 'GLOBAL' => 2, 'GRANTS' => 2, + 'IMPORT' => 2, 'INNODB' => 2, 'ISSUER' => 2, 'LEAVES' => 2, 'MASTER' => 2, + 'MEDIUM' => 2, 'MEMORY' => 2, 'MINUTE' => 2, 'MODIFY' => 2, 'OFFSET' => 2, + 'RELOAD' => 2, 'REPAIR' => 2, 'RESUME' => 2, 'ROLLUP' => 2, 'SECOND' => 2, + 'SERIAL' => 2, 'SIGNED' => 2, 'SIMPLE' => 2, 'SOUNDS' => 2, 'SOURCE' => 2, + 'STATUS' => 2, 'STRING' => 2, 'TABLES' => 2, + 'AGAINST' => 2, 'BOOLEAN' => 2, 'CHANGED' => 2, 'CHARSET' => 2, 'COLUMNS' => 2, + 'COMMENT' => 2, 'COMPACT' => 2, 'CONTEXT' => 2, 'DEFINER' => 2, 'DISABLE' => 2, + 'DISCARD' => 2, 'DYNAMIC' => 2, 'ENGINES' => 2, 'EXECUTE' => 2, 'HANDLER' => 2, + 'INDEXES' => 2, 'INVOKER' => 2, 'MIGRATE' => 2, 'PARTIAL' => 2, 'POLYGON' => 2, + 'PREPARE' => 2, 'PROFILE' => 2, 'QUARTER' => 2, 'RECOVER' => 2, 'RESTORE' => 2, + 'RETURNS' => 2, 'ROUTINE' => 2, 'SESSION' => 2, 'STORAGE' => 2, 'STRIPED' => 2, + 'SUBJECT' => 2, 'SUSPEND' => 2, 'UNICODE' => 2, 'UNKNOWN' => 2, 'UPGRADE' => 2, + 'USE_FRM' => 2, + 'CASCADED' => 2, 'CHECKSUM' => 2, 'CONTAINS' => 2, 'DATETIME' => 2, + 'DUMPFILE' => 2, 'EXTENDED' => 2, 'FUNCTION' => 2, 'GEOMETRY' => 2, + 'INNOBASE' => 2, 'LANGUAGE' => 2, 'MAX_ROWS' => 2, 'MIN_ROWS' => 2, + 'NATIONAL' => 2, 'NVARCHAR' => 2, 'ONE_SHOT' => 2, 'PASSWORD' => 2, + 'PROFILES' => 2, 'ROLLBACK' => 2, 'SECURITY' => 2, 'SHUTDOWN' => 2, + 'SNAPSHOT' => 2, 'SWITCHES' => 2, 'TRIGGERS' => 2, 'TRUNCATE' => 2, + 'WARNINGS' => 2, + 'AGGREGATE' => 2, 'ALGORITHM' => 2, 'COLLATION' => 2, 'COMMITTED' => 2, + 'DIRECTORY' => 2, 'DUPLICATE' => 2, 'EXPANSION' => 2, 'IO_THREAD' => 2, + 'ISOLATION' => 2, 'PACK_KEYS' => 2, 'RAID_TYPE' => 2, 'REDUNDANT' => 2, + 'SAVEPOINT' => 2, 'SQL_CACHE' => 2, 'TEMPORARY' => 2, 'TEMPTABLE' => 2, + 'TIMESTAMP' => 2, 'UNDEFINED' => 2, 'VARIABLES' => 2, + 'BERKELEYDB' => 2, 'COMPRESSED' => 2, 'CONCURRENT' => 2, 'CONNECTION' => 2, + 'CONSISTENT' => 2, 'DEALLOCATE' => 2, 'GET_FORMAT' => 2, 'IDENTIFIED' => 2, + 'LINESTRING' => 2, 'MASTER_SSL' => 2, 'MULTIPOINT' => 2, 'NDBCLUSTER' => 2, + 'PRIVILEGES' => 2, 'REPEATABLE' => 2, 'ROW_FORMAT' => 2, 'SQL_THREAD' => 2, + 'TABLESPACE' => 2, + 'FRAC_SECOND' => 2, 'MASTER_HOST' => 2, 'MASTER_PORT' => 2, 'MASTER_USER' => 2, + 'MICROSECOND' => 2, 'PROCESSLIST' => 2, 'RAID_CHUNKS' => 2, 'REPLICATION' => 2, + 'SQL_TSI_DAY' => 2, 'TRANSACTION' => 2, 'UNCOMMITTED' => 2, + 'DES_KEY_FILE' => 2, 'MULTIPOLYGON' => 2, 'OLD_PASSWORD' => 2, + 'RELAY_THREAD' => 2, 'SERIALIZABLE' => 2, 'SQL_NO_CACHE' => 2, + 'SQL_TSI_HOUR' => 2, 'SQL_TSI_WEEK' => 2, 'SQL_TSI_YEAR' => 2, + 'TIMESTAMPADD' => 2, + 'INSERT_METHOD' => 2, 'MASTER_SSL_CA' => 2, 'RELAY_LOG_POS' => 2, + 'SQL_TSI_MONTH' => 2, 'TIMESTAMPDIFF' => 2, + 'AUTO_INCREMENT' => 2, 'AVG_ROW_LENGTH' => 2, 'MASTER_LOG_POS' => 2, + 'MASTER_SSL_KEY' => 2, 'RAID_CHUNKSIZE' => 2, 'RELAY_LOG_FILE' => 2, + 'SQL_TSI_MINUTE' => 2, 'SQL_TSI_SECOND' => 2, 'USER_RESOURCES' => 2, + 'DELAY_KEY_WRITE' => 2, 'MASTER_LOG_FILE' => 2, 'MASTER_PASSWORD' => 2, + 'MASTER_SSL_CERT' => 2, 'MULTILINESTRING' => 2, 'SQL_TSI_QUARTER' => 2, + 'MASTER_SERVER_ID' => 2, + 'MASTER_SSL_CAPATH' => 2, 'MASTER_SSL_CIPHER' => 2, 'SQL_BUFFER_RESULT' => 2, + 'GEOMETRYCOLLECTION' => 2, + 'SQL_TSI_FRAC_SECOND' => 2, + 'MASTER_CONNECT_RETRY' => 2, 'MAX_QUERIES_PER_HOUR' => 2, + 'MAX_UPDATES_PER_HOUR' => 2, 'MAX_USER_CONNECTIONS' => 2, + 'MAX_CONNECTIONS_PER_HOUR' => 2, + + 'NOT NULL' => 4, + 'INDEX KEY' => 4, + 'UNIQUE KEY' => 4, + 'FOREIGN KEY' => 4, 'PRIMARY KEY' => 4, 'PRIMARY KEY' => 4, 'SPATIAL KEY' => 4, + 'FULLTEXT KEY' => 4, 'UNIQUE INDEX' => 4, + 'CHARACTER SET' => 4, 'IF NOT EXISTS' => 4, 'SPATIAL INDEX' => 4, + 'DATA DIRECTORY' => 4, 'FULLTEXT INDEX' => 4, + 'DEFAULT COLLATE' => 4, 'INDEX DIRECTORY' => 4, + 'DEFAULT CHARACTER SET' => 4, + + ); +} diff --git a/libraries/sql-parser/src/Contexts/Context_MySQL50100.php b/libraries/sql-parser/src/Contexts/Context_MySQL50100.php new file mode 100644 index 0000000000..ce83a5f854 --- /dev/null +++ b/libraries/sql-parser/src/Contexts/Context_MySQL50100.php @@ -0,0 +1,177 @@ + 1, 'BY' => 1, 'IF' => 1, 'IN' => 1, 'IS' => 1, + 'ON' => 1, 'OR' => 1, 'TO' => 1, + 'ADD' => 1, 'ALL' => 1, 'AND' => 1, 'ASC' => 1, 'DEC' => 1, + 'DIV' => 1, 'FOR' => 1, 'INT' => 1, 'KEY' => 1, 'MOD' => 1, + 'NOT' => 1, 'OUT' => 1, 'SET' => 1, 'SQL' => 1, 'SSL' => 1, + 'USE' => 1, 'XOR' => 1, + 'BLOB' => 1, 'BOTH' => 1, 'CALL' => 1, 'CASE' => 1, + 'CHAR' => 1, 'DESC' => 1, 'DROP' => 1, 'DUAL' => 1, + 'EACH' => 1, 'ELSE' => 1, 'EXIT' => 1, 'FROM' => 1, + 'INT1' => 1, 'INT2' => 1, 'INT3' => 1, 'INT4' => 1, + 'INT8' => 1, 'INTO' => 1, 'JOIN' => 1, 'KEYS' => 1, + 'KILL' => 1, 'LEFT' => 1, 'LIKE' => 1, 'LOAD' => 1, + 'LOCK' => 1, 'LONG' => 1, 'LOOP' => 1, 'NULL' => 1, + 'READ' => 1, 'REAL' => 1, 'SHOW' => 1, 'THEN' => 1, + 'TRUE' => 1, 'UNDO' => 1, 'WHEN' => 1, 'WITH' => 1, + 'ALTER' => 1, 'CHECK' => 1, 'CROSS' => 1, 'FALSE' => 1, + 'FETCH' => 1, 'FLOAT' => 1, 'FORCE' => 1, 'GRANT' => 1, + 'GROUP' => 1, 'INDEX' => 1, 'INNER' => 1, 'INOUT' => 1, + 'LEAVE' => 1, 'LIMIT' => 1, 'LINES' => 1, 'MATCH' => 1, + 'ORDER' => 1, 'OUTER' => 1, 'PURGE' => 1, 'RANGE' => 1, + 'READS' => 1, 'RIGHT' => 1, 'RLIKE' => 1, 'TABLE' => 1, + 'UNION' => 1, 'USAGE' => 1, 'USING' => 1, 'WHERE' => 1, + 'WHILE' => 1, 'WRITE' => 1, + 'BEFORE' => 1, 'BIGINT' => 1, 'BINARY' => 1, 'CHANGE' => 1, + 'COLUMN' => 1, 'CREATE' => 1, 'CURSOR' => 1, 'DELETE' => 1, + 'DOUBLE' => 1, 'ELSEIF' => 1, 'EXISTS' => 1, 'FLOAT4' => 1, + 'FLOAT8' => 1, 'HAVING' => 1, 'IGNORE' => 1, 'INFILE' => 1, + 'INSERT' => 1, 'LINEAR' => 1, 'OPTION' => 1, 'REGEXP' => 1, + 'RENAME' => 1, 'REPEAT' => 1, 'RETURN' => 1, 'REVOKE' => 1, + 'SCHEMA' => 1, 'SELECT' => 1, 'UNIQUE' => 1, 'UNLOCK' => 1, + 'UPDATE' => 1, 'VALUES' => 1, + 'ANALYZE' => 1, 'BETWEEN' => 1, 'CASCADE' => 1, 'COLLATE' => 1, + 'CONVERT' => 1, 'DECIMAL' => 1, 'DECLARE' => 1, 'DEFAULT' => 1, + 'DELAYED' => 1, 'ESCAPED' => 1, 'EXPLAIN' => 1, 'FOREIGN' => 1, + 'INTEGER' => 1, 'ITERATE' => 1, 'LEADING' => 1, 'NATURAL' => 1, + 'NUMERIC' => 1, 'OUTFILE' => 1, 'PRIMARY' => 1, 'RELEASE' => 1, + 'REPLACE' => 1, 'REQUIRE' => 1, 'SCHEMAS' => 1, 'SPATIAL' => 1, + 'TINYINT' => 1, 'TRIGGER' => 1, 'VARCHAR' => 1, 'VARYING' => 1, + 'CONTINUE' => 1, 'DATABASE' => 1, 'DAY_HOUR' => 1, + 'DESCRIBE' => 1, 'DISTINCT' => 1, 'ENCLOSED' => 1, + 'FULLTEXT' => 1, 'INTERVAL' => 1, 'LONGBLOB' => 1, + 'LONGTEXT' => 1, 'MODIFIES' => 1, 'OPTIMIZE' => 1, + 'RESTRICT' => 1, 'SMALLINT' => 1, 'SPECIFIC' => 1, + 'SQLSTATE' => 1, 'STARTING' => 1, 'TINYBLOB' => 1, + 'TINYTEXT' => 1, 'TRAILING' => 1, 'UNSIGNED' => 1, + 'UTC_DATE' => 1, 'UTC_TIME' => 1, 'ZEROFILL' => 1, + 'CHARACTER' => 1, 'CONDITION' => 1, 'DATABASES' => 1, + 'LOCALTIME' => 1, 'MEDIUMINT' => 1, 'MIDDLEINT' => 1, + 'PRECISION' => 1, 'PROCEDURE' => 1, 'SENSITIVE' => 1, + 'SEPARATOR' => 1, 'VARBINARY' => 1, + 'ACCESSIBLE' => 1, 'ASENSITIVE' => 1, 'CONSTRAINT' => 1, + 'DAY_MINUTE' => 1, 'DAY_SECOND' => 1, 'MEDIUMBLOB' => 1, + 'MEDIUMTEXT' => 1, 'OPTIONALLY' => 1, 'READ_WRITE' => 1, + 'REFERENCES' => 1, 'SQLWARNING' => 1, 'TERMINATED' => 1, + 'YEAR_MONTH' => 1, + 'DISTINCTROW' => 1, 'HOUR_MINUTE' => 1, 'HOUR_SECOND' => 1, + 'INSENSITIVE' => 1, + 'CURRENT_DATE' => 1, 'CURRENT_TIME' => 1, 'CURRENT_USER' => 1, + 'LOW_PRIORITY' => 1, 'SQLEXCEPTION' => 1, 'VARCHARACTER' => 1, + 'DETERMINISTIC' => 1, 'HIGH_PRIORITY' => 1, 'MINUTE_SECOND' => 1, + 'STRAIGHT_JOIN' => 1, 'UTC_TIMESTAMP' => 1, + 'LOCALTIMESTAMP' => 1, 'SQL_BIG_RESULT' => 1, + 'DAY_MICROSECOND' => 1, + 'HOUR_MICROSECOND' => 1, 'SQL_SMALL_RESULT' => 1, + 'CURRENT_TIMESTAMP' => 1, + 'MINUTE_MICROSECOND' => 1, 'NO_WRITE_TO_BINLOG' => 1, + 'SECOND_MICROSECOND' => 1, + 'SQL_CALC_FOUND_ROWS' => 1, + 'MASTER_SSL_VERIFY_SERVER_CERT' => 1, + + 'AT' => 2, 'DO' => 2, 'IO' => 2, 'NO' => 2, 'XA' => 2, + 'ANY' => 2, 'AVG' => 2, 'BDB' => 2, 'BIT' => 2, 'CPU' => 2, 'DAY' => 2, + 'END' => 2, 'IPC' => 2, 'NDB' => 2, 'NEW' => 2, 'ONE' => 2, 'ROW' => 2, + 'BOOL' => 2, 'BYTE' => 2, 'CODE' => 2, 'CUBE' => 2, 'DATA' => 2, 'DATE' => 2, + 'DISK' => 2, 'ENDS' => 2, 'ENUM' => 2, 'FAST' => 2, 'FILE' => 2, 'FULL' => 2, + 'GOTO' => 2, 'HASH' => 2, 'HELP' => 2, 'HOST' => 2, 'HOUR' => 2, 'LAST' => 2, + 'LESS' => 2, 'LIST' => 2, 'LOGS' => 2, 'MODE' => 2, 'NAME' => 2, 'NEXT' => 2, + 'NONE' => 2, 'OPEN' => 2, 'PAGE' => 2, 'PORT' => 2, 'PREV' => 2, 'ROWS' => 2, + 'SOME' => 2, 'STOP' => 2, 'TEXT' => 2, 'THAN' => 2, 'TIME' => 2, 'TYPE' => 2, + 'USER' => 2, 'VIEW' => 2, 'WAIT' => 2, 'WEEK' => 2, 'WORK' => 2, 'X509' => 2, + 'YEAR' => 2, + 'AFTER' => 2, 'ASCII' => 2, 'BEGIN' => 2, 'BLOCK' => 2, 'BTREE' => 2, + 'CACHE' => 2, 'CHAIN' => 2, 'CLOSE' => 2, 'EVENT' => 2, 'EVERY' => 2, + 'FIRST' => 2, 'FIXED' => 2, 'FLUSH' => 2, 'FOUND' => 2, 'HOSTS' => 2, + 'LABEL' => 2, 'LEVEL' => 2, 'LOCAL' => 2, 'LOCKS' => 2, 'MERGE' => 2, + 'MONTH' => 2, 'MUTEX' => 2, 'NAMES' => 2, 'NCHAR' => 2, 'OWNER' => 2, + 'PHASE' => 2, 'POINT' => 2, 'QUERY' => 2, 'QUICK' => 2, 'RAID0' => 2, + 'RESET' => 2, 'RTREE' => 2, 'SHARE' => 2, 'SLAVE' => 2, 'START' => 2, + 'SUPER' => 2, 'SWAPS' => 2, 'TYPES' => 2, 'UNTIL' => 2, 'VALUE' => 2, + 'ACTION' => 2, 'BACKUP' => 2, 'BINLOG' => 2, 'CIPHER' => 2, 'CLIENT' => 2, + 'COMMIT' => 2, 'ENABLE' => 2, 'ENGINE' => 2, 'ERRORS' => 2, 'ESCAPE' => 2, + 'EVENTS' => 2, 'FAULTS' => 2, 'FIELDS' => 2, 'GLOBAL' => 2, 'GRANTS' => 2, + 'IMPORT' => 2, 'INNODB' => 2, 'ISSUER' => 2, 'LEAVES' => 2, 'MASTER' => 2, + 'MEDIUM' => 2, 'MEMORY' => 2, 'MINUTE' => 2, 'MODIFY' => 2, 'OFFSET' => 2, + 'PARSER' => 2, 'PLUGIN' => 2, 'RELOAD' => 2, 'REMOVE' => 2, 'REPAIR' => 2, + 'RESUME' => 2, 'ROLLUP' => 2, 'SECOND' => 2, 'SERIAL' => 2, 'SERVER' => 2, + 'SIGNED' => 2, 'SIMPLE' => 2, 'SOCKET' => 2, 'SONAME' => 2, 'SOUNDS' => 2, + 'SOURCE' => 2, 'STARTS' => 2, 'STATUS' => 2, 'STRING' => 2, 'TABLES' => 2, + 'AGAINST' => 2, 'AUTHORS' => 2, 'BOOLEAN' => 2, 'CHANGED' => 2, 'CHARSET' => 2, + 'COLUMNS' => 2, 'COMMENT' => 2, 'COMPACT' => 2, 'CONTEXT' => 2, 'DEFINER' => 2, + 'DISABLE' => 2, 'DISCARD' => 2, 'DYNAMIC' => 2, 'ENGINES' => 2, 'EXECUTE' => 2, + 'HANDLER' => 2, 'INDEXES' => 2, 'INSTALL' => 2, 'INVOKER' => 2, 'LOGFILE' => 2, + 'MIGRATE' => 2, 'NO_WAIT' => 2, 'OPTIONS' => 2, 'PARTIAL' => 2, 'PLUGINS' => 2, + 'POLYGON' => 2, 'PREPARE' => 2, 'PROFILE' => 2, 'QUARTER' => 2, 'REBUILD' => 2, + 'RECOVER' => 2, 'RESTORE' => 2, 'RETURNS' => 2, 'ROUTINE' => 2, 'SESSION' => 2, + 'STORAGE' => 2, 'STRIPED' => 2, 'SUBJECT' => 2, 'SUSPEND' => 2, 'UNICODE' => 2, + 'UNKNOWN' => 2, 'UPGRADE' => 2, 'USE_FRM' => 2, 'WRAPPER' => 2, + 'CASCADED' => 2, 'CHECKSUM' => 2, 'COALESCE' => 2, 'CONTAINS' => 2, + 'DATAFILE' => 2, 'DATETIME' => 2, 'DUMPFILE' => 2, 'EXTENDED' => 2, + 'FUNCTION' => 2, 'GEOMETRY' => 2, 'INNOBASE' => 2, 'LANGUAGE' => 2, + 'MAXVALUE' => 2, 'MAX_ROWS' => 2, 'MAX_SIZE' => 2, 'MIN_ROWS' => 2, + 'NATIONAL' => 2, 'NVARCHAR' => 2, 'ONE_SHOT' => 2, 'PASSWORD' => 2, + 'PRESERVE' => 2, 'PROFILES' => 2, 'REDOFILE' => 2, 'ROLLBACK' => 2, + 'SCHEDULE' => 2, 'SECURITY' => 2, 'SHUTDOWN' => 2, 'SNAPSHOT' => 2, + 'SWITCHES' => 2, 'TRIGGERS' => 2, 'TRUNCATE' => 2, 'UNDOFILE' => 2, + 'WARNINGS' => 2, + 'AGGREGATE' => 2, 'ALGORITHM' => 2, 'COLLATION' => 2, 'COMMITTED' => 2, + 'DIRECTORY' => 2, 'DUPLICATE' => 2, 'EXPANSION' => 2, 'IO_THREAD' => 2, + 'ISOLATION' => 2, 'NODEGROUP' => 2, 'PACK_KEYS' => 2, 'PARTITION' => 2, + 'RAID_TYPE' => 2, 'READ_ONLY' => 2, 'REDUNDANT' => 2, 'SAVEPOINT' => 2, + 'SCHEDULER' => 2, 'SQL_CACHE' => 2, 'TEMPORARY' => 2, 'TEMPTABLE' => 2, + 'TIMESTAMP' => 2, 'UNDEFINED' => 2, 'UNINSTALL' => 2, 'VARIABLES' => 2, + 'BERKELEYDB' => 2, 'COMPLETION' => 2, 'COMPRESSED' => 2, 'CONCURRENT' => 2, + 'CONNECTION' => 2, 'CONSISTENT' => 2, 'DEALLOCATE' => 2, 'GET_FORMAT' => 2, + 'IDENTIFIED' => 2, 'LINESTRING' => 2, 'MASTER_SSL' => 2, 'MULTIPOINT' => 2, + 'NDBCLUSTER' => 2, 'PARTITIONS' => 2, 'PRIVILEGES' => 2, 'REORGANISE' => 2, + 'REORGANIZE' => 2, 'REPEATABLE' => 2, 'ROW_FORMAT' => 2, 'SQL_THREAD' => 2, + 'TABLESPACE' => 2, + 'EXTENT_SIZE' => 2, 'FRAC_SECOND' => 2, 'MASTER_HOST' => 2, 'MASTER_PORT' => 2, + 'MASTER_USER' => 2, 'MICROSECOND' => 2, 'PROCESSLIST' => 2, 'RAID_CHUNKS' => 2, + 'REPLICATION' => 2, 'SQL_TSI_DAY' => 2, 'TRANSACTION' => 2, 'UNCOMMITTED' => 2, + 'CONTRIBUTORS' => 2, 'DES_KEY_FILE' => 2, 'INITIAL_SIZE' => 2, + 'MULTIPOLYGON' => 2, 'OLD_PASSWORD' => 2, 'PARTITIONING' => 2, + 'RELAY_THREAD' => 2, 'SERIALIZABLE' => 2, 'SQL_NO_CACHE' => 2, + 'SQL_TSI_HOUR' => 2, 'SQL_TSI_WEEK' => 2, 'SQL_TSI_YEAR' => 2, + 'SUBPARTITION' => 2, 'TIMESTAMPADD' => 2, + 'INSERT_METHOD' => 2, 'MASTER_SSL_CA' => 2, 'PAGE_CHECKSUM' => 2, + 'RELAY_LOG_POS' => 2, 'SQL_TSI_MONTH' => 2, 'SUBPARTITIONS' => 2, + 'TIMESTAMPDIFF' => 2, 'TRANSACTIONAL' => 2, + 'AUTO_INCREMENT' => 2, 'AVG_ROW_LENGTH' => 2, 'KEY_BLOCK_SIZE' => 2, + 'MASTER_LOG_POS' => 2, 'MASTER_SSL_KEY' => 2, 'RAID_CHUNKSIZE' => 2, + 'RELAY_LOG_FILE' => 2, 'SQL_TSI_MINUTE' => 2, 'SQL_TSI_SECOND' => 2, + 'TABLE_CHECKSUM' => 2, 'USER_RESOURCES' => 2, + 'AUTOEXTEND_SIZE' => 2, 'DELAY_KEY_WRITE' => 2, 'MASTER_LOG_FILE' => 2, + 'MASTER_PASSWORD' => 2, 'MASTER_SSL_CERT' => 2, 'MULTILINESTRING' => 2, + 'SQL_TSI_QUARTER' => 2, + 'MASTER_SERVER_ID' => 2, 'REDO_BUFFER_SIZE' => 2, 'UNDO_BUFFER_SIZE' => 2, + 'MASTER_SSL_CAPATH' => 2, 'MASTER_SSL_CIPHER' => 2, 'SQL_BUFFER_RESULT' => 2, + 'GEOMETRYCOLLECTION' => 2, + 'SQL_TSI_FRAC_SECOND' => 2, + 'MASTER_CONNECT_RETRY' => 2, 'MAX_QUERIES_PER_HOUR' => 2, + 'MAX_UPDATES_PER_HOUR' => 2, 'MAX_USER_CONNECTIONS' => 2, + 'MAX_CONNECTIONS_PER_HOUR' => 2, + + 'NOT NULL' => 4, + 'INDEX KEY' => 4, + 'UNIQUE KEY' => 4, + 'FOREIGN KEY' => 4, 'PRIMARY KEY' => 4, 'PRIMARY KEY' => 4, 'SPATIAL KEY' => 4, + 'FULLTEXT KEY' => 4, 'UNIQUE INDEX' => 4, + 'CHARACTER SET' => 4, 'IF NOT EXISTS' => 4, 'SPATIAL INDEX' => 4, + 'DATA DIRECTORY' => 4, 'FULLTEXT INDEX' => 4, + 'DEFAULT COLLATE' => 4, 'INDEX DIRECTORY' => 4, + 'DEFAULT CHARACTER SET' => 4, + + ); +} diff --git a/libraries/sql-parser/src/Contexts/Context_MySQL50500.php b/libraries/sql-parser/src/Contexts/Context_MySQL50500.php new file mode 100644 index 0000000000..8c3d570440 --- /dev/null +++ b/libraries/sql-parser/src/Contexts/Context_MySQL50500.php @@ -0,0 +1,181 @@ + 1, 'BY' => 1, 'IF' => 1, 'IN' => 1, 'IS' => 1, + 'ON' => 1, 'OR' => 1, 'TO' => 1, + 'ADD' => 1, 'ALL' => 1, 'AND' => 1, 'ASC' => 1, 'DEC' => 1, + 'DIV' => 1, 'FOR' => 1, 'INT' => 1, 'KEY' => 1, 'MOD' => 1, + 'NOT' => 1, 'OUT' => 1, 'SET' => 1, 'SQL' => 1, 'SSL' => 1, + 'USE' => 1, 'XOR' => 1, + 'BLOB' => 1, 'BOTH' => 1, 'CALL' => 1, 'CASE' => 1, + 'CHAR' => 1, 'DESC' => 1, 'DROP' => 1, 'DUAL' => 1, + 'EACH' => 1, 'ELSE' => 1, 'EXIT' => 1, 'FROM' => 1, + 'INT1' => 1, 'INT2' => 1, 'INT3' => 1, 'INT4' => 1, + 'INT8' => 1, 'INTO' => 1, 'JOIN' => 1, 'KEYS' => 1, + 'KILL' => 1, 'LEFT' => 1, 'LIKE' => 1, 'LOAD' => 1, + 'LOCK' => 1, 'LONG' => 1, 'LOOP' => 1, 'NULL' => 1, + 'READ' => 1, 'REAL' => 1, 'SHOW' => 1, 'THEN' => 1, + 'TRUE' => 1, 'UNDO' => 1, 'WHEN' => 1, 'WITH' => 1, + 'ALTER' => 1, 'CHECK' => 1, 'CROSS' => 1, 'FALSE' => 1, + 'FETCH' => 1, 'FLOAT' => 1, 'FORCE' => 1, 'GRANT' => 1, + 'GROUP' => 1, 'INDEX' => 1, 'INNER' => 1, 'INOUT' => 1, + 'LEAVE' => 1, 'LIMIT' => 1, 'LINES' => 1, 'MATCH' => 1, + 'ORDER' => 1, 'OUTER' => 1, 'PURGE' => 1, 'RANGE' => 1, + 'READS' => 1, 'RIGHT' => 1, 'RLIKE' => 1, 'TABLE' => 1, + 'UNION' => 1, 'USAGE' => 1, 'USING' => 1, 'WHERE' => 1, + 'WHILE' => 1, 'WRITE' => 1, + 'BEFORE' => 1, 'BIGINT' => 1, 'BINARY' => 1, 'CHANGE' => 1, + 'COLUMN' => 1, 'CREATE' => 1, 'CURSOR' => 1, 'DELETE' => 1, + 'DOUBLE' => 1, 'ELSEIF' => 1, 'EXISTS' => 1, 'FLOAT4' => 1, + 'FLOAT8' => 1, 'HAVING' => 1, 'IGNORE' => 1, 'INFILE' => 1, + 'INSERT' => 1, 'LINEAR' => 1, 'OPTION' => 1, 'REGEXP' => 1, + 'RENAME' => 1, 'REPEAT' => 1, 'RETURN' => 1, 'REVOKE' => 1, + 'SCHEMA' => 1, 'SELECT' => 1, 'SIGNAL' => 1, 'UNIQUE' => 1, + 'UNLOCK' => 1, 'UPDATE' => 1, 'VALUES' => 1, + 'ANALYZE' => 1, 'BETWEEN' => 1, 'CASCADE' => 1, 'COLLATE' => 1, + 'CONVERT' => 1, 'DECIMAL' => 1, 'DECLARE' => 1, 'DEFAULT' => 1, + 'DELAYED' => 1, 'ESCAPED' => 1, 'EXPLAIN' => 1, 'FOREIGN' => 1, + 'INTEGER' => 1, 'ITERATE' => 1, 'LEADING' => 1, 'NATURAL' => 1, + 'NUMERIC' => 1, 'OUTFILE' => 1, 'PRIMARY' => 1, 'RELEASE' => 1, + 'REPLACE' => 1, 'REQUIRE' => 1, 'SCHEMAS' => 1, 'SPATIAL' => 1, + 'TINYINT' => 1, 'TRIGGER' => 1, 'VARCHAR' => 1, 'VARYING' => 1, + 'CONTINUE' => 1, 'DATABASE' => 1, 'DAY_HOUR' => 1, + 'DESCRIBE' => 1, 'DISTINCT' => 1, 'ENCLOSED' => 1, + 'FULLTEXT' => 1, 'INTERVAL' => 1, 'LONGBLOB' => 1, + 'LONGTEXT' => 1, 'MAXVALUE' => 1, 'MODIFIES' => 1, + 'OPTIMIZE' => 1, 'RESIGNAL' => 1, 'RESTRICT' => 1, + 'SMALLINT' => 1, 'SPECIFIC' => 1, 'SQLSTATE' => 1, + 'STARTING' => 1, 'TINYBLOB' => 1, 'TINYTEXT' => 1, + 'TRAILING' => 1, 'UNSIGNED' => 1, 'UTC_DATE' => 1, + 'UTC_TIME' => 1, 'ZEROFILL' => 1, + 'CHARACTER' => 1, 'CONDITION' => 1, 'DATABASES' => 1, + 'LOCALTIME' => 1, 'MEDIUMINT' => 1, 'MIDDLEINT' => 1, + 'PRECISION' => 1, 'PROCEDURE' => 1, 'SENSITIVE' => 1, + 'SEPARATOR' => 1, 'VARBINARY' => 1, + 'ACCESSIBLE' => 1, 'ASENSITIVE' => 1, 'CONSTRAINT' => 1, + 'DAY_MINUTE' => 1, 'DAY_SECOND' => 1, 'MEDIUMBLOB' => 1, + 'MEDIUMTEXT' => 1, 'OPTIONALLY' => 1, 'READ_WRITE' => 1, + 'REFERENCES' => 1, 'SQLWARNING' => 1, 'TERMINATED' => 1, + 'YEAR_MONTH' => 1, + 'DISTINCTROW' => 1, 'HOUR_MINUTE' => 1, 'HOUR_SECOND' => 1, + 'INSENSITIVE' => 1, + 'CURRENT_DATE' => 1, 'CURRENT_TIME' => 1, 'CURRENT_USER' => 1, + 'LOW_PRIORITY' => 1, 'SQLEXCEPTION' => 1, 'VARCHARACTER' => 1, + 'DETERMINISTIC' => 1, 'HIGH_PRIORITY' => 1, 'MINUTE_SECOND' => 1, + 'STRAIGHT_JOIN' => 1, 'UTC_TIMESTAMP' => 1, + 'LOCALTIMESTAMP' => 1, 'SQL_BIG_RESULT' => 1, + 'DAY_MICROSECOND' => 1, + 'HOUR_MICROSECOND' => 1, 'SQL_SMALL_RESULT' => 1, + 'CURRENT_TIMESTAMP' => 1, + 'MINUTE_MICROSECOND' => 1, 'NO_WRITE_TO_BINLOG' => 1, + 'SECOND_MICROSECOND' => 1, + 'SQL_CALC_FOUND_ROWS' => 1, + 'MASTER_SSL_VERIFY_SERVER_CERT' => 1, + + 'AT' => 2, 'DO' => 2, 'IO' => 2, 'NO' => 2, 'XA' => 2, + 'ANY' => 2, 'AVG' => 2, 'BIT' => 2, 'CPU' => 2, 'DAY' => 2, 'END' => 2, + 'IPC' => 2, 'NDB' => 2, 'NEW' => 2, 'ONE' => 2, 'ROW' => 2, 'XML' => 2, + 'BOOL' => 2, 'BYTE' => 2, 'CODE' => 2, 'CUBE' => 2, 'DATA' => 2, 'DATE' => 2, + 'DISK' => 2, 'ENDS' => 2, 'ENUM' => 2, 'FAST' => 2, 'FILE' => 2, 'FULL' => 2, + 'HASH' => 2, 'HELP' => 2, 'HOST' => 2, 'HOUR' => 2, 'LAST' => 2, 'LESS' => 2, + 'LIST' => 2, 'LOGS' => 2, 'MODE' => 2, 'NAME' => 2, 'NEXT' => 2, 'NONE' => 2, + 'OPEN' => 2, 'PAGE' => 2, 'PORT' => 2, 'PREV' => 2, 'ROWS' => 2, 'SLOW' => 2, + 'SOME' => 2, 'STOP' => 2, 'TEXT' => 2, 'THAN' => 2, 'TIME' => 2, 'TYPE' => 2, + 'USER' => 2, 'VIEW' => 2, 'WAIT' => 2, 'WEEK' => 2, 'WORK' => 2, 'X509' => 2, + 'YEAR' => 2, + 'AFTER' => 2, 'ASCII' => 2, 'BEGIN' => 2, 'BLOCK' => 2, 'BTREE' => 2, + 'CACHE' => 2, 'CHAIN' => 2, 'CLOSE' => 2, 'ERROR' => 2, 'EVENT' => 2, + 'EVERY' => 2, 'FIRST' => 2, 'FIXED' => 2, 'FLUSH' => 2, 'FOUND' => 2, + 'HOSTS' => 2, 'LEVEL' => 2, 'LOCAL' => 2, 'LOCKS' => 2, 'MERGE' => 2, + 'MONTH' => 2, 'MUTEX' => 2, 'NAMES' => 2, 'NCHAR' => 2, 'OWNER' => 2, + 'PHASE' => 2, 'POINT' => 2, 'PROXY' => 2, 'QUERY' => 2, 'QUICK' => 2, + 'RELAY' => 2, 'RESET' => 2, 'RTREE' => 2, 'SHARE' => 2, 'SLAVE' => 2, + 'START' => 2, 'SUPER' => 2, 'SWAPS' => 2, 'TYPES' => 2, 'UNTIL' => 2, + 'VALUE' => 2, + 'ACTION' => 2, 'BACKUP' => 2, 'BINLOG' => 2, 'CIPHER' => 2, 'CLIENT' => 2, + 'COMMIT' => 2, 'ENABLE' => 2, 'ENGINE' => 2, 'ERRORS' => 2, 'ESCAPE' => 2, + 'EVENTS' => 2, 'FAULTS' => 2, 'FIELDS' => 2, 'GLOBAL' => 2, 'GRANTS' => 2, + 'IMPORT' => 2, 'INNODB' => 2, 'ISSUER' => 2, 'LEAVES' => 2, 'MASTER' => 2, + 'MEDIUM' => 2, 'MEMORY' => 2, 'MINUTE' => 2, 'MODIFY' => 2, 'OFFSET' => 2, + 'PARSER' => 2, 'PLUGIN' => 2, 'RELOAD' => 2, 'REMOVE' => 2, 'REPAIR' => 2, + 'RESUME' => 2, 'ROLLUP' => 2, 'SECOND' => 2, 'SERIAL' => 2, 'SERVER' => 2, + 'SIGNED' => 2, 'SIMPLE' => 2, 'SOCKET' => 2, 'SONAME' => 2, 'SOUNDS' => 2, + 'SOURCE' => 2, 'STARTS' => 2, 'STATUS' => 2, 'STRING' => 2, 'TABLES' => 2, + 'AGAINST' => 2, 'AUTHORS' => 2, 'BOOLEAN' => 2, 'CHANGED' => 2, 'CHARSET' => 2, + 'COLUMNS' => 2, 'COMMENT' => 2, 'COMPACT' => 2, 'CONTEXT' => 2, 'DEFINER' => 2, + 'DISABLE' => 2, 'DISCARD' => 2, 'DYNAMIC' => 2, 'ENGINES' => 2, 'EXECUTE' => 2, + 'GENERAL' => 2, 'HANDLER' => 2, 'INDEXES' => 2, 'INSTALL' => 2, 'INVOKER' => 2, + 'LOGFILE' => 2, 'MIGRATE' => 2, 'NO_WAIT' => 2, 'OPTIONS' => 2, 'PARTIAL' => 2, + 'PLUGINS' => 2, 'POLYGON' => 2, 'PREPARE' => 2, 'PROFILE' => 2, 'QUARTER' => 2, + 'REBUILD' => 2, 'RECOVER' => 2, 'RESTORE' => 2, 'RETURNS' => 2, 'ROUTINE' => 2, + 'SESSION' => 2, 'STORAGE' => 2, 'SUBJECT' => 2, 'SUSPEND' => 2, 'UNICODE' => 2, + 'UNKNOWN' => 2, 'UPGRADE' => 2, 'USE_FRM' => 2, 'WRAPPER' => 2, + 'CASCADED' => 2, 'CHECKSUM' => 2, 'COALESCE' => 2, 'CONTAINS' => 2, + 'DATAFILE' => 2, 'DATETIME' => 2, 'DUMPFILE' => 2, 'EXTENDED' => 2, + 'FUNCTION' => 2, 'GEOMETRY' => 2, 'INNOBASE' => 2, 'LANGUAGE' => 2, + 'MAX_ROWS' => 2, 'MAX_SIZE' => 2, 'MIN_ROWS' => 2, 'NATIONAL' => 2, + 'NVARCHAR' => 2, 'ONE_SHOT' => 2, 'PASSWORD' => 2, 'PRESERVE' => 2, + 'PROFILES' => 2, 'REDOFILE' => 2, 'RELAYLOG' => 2, 'ROLLBACK' => 2, + 'SCHEDULE' => 2, 'SECURITY' => 2, 'SHUTDOWN' => 2, 'SNAPSHOT' => 2, + 'SWITCHES' => 2, 'TRIGGERS' => 2, 'TRUNCATE' => 2, 'UNDOFILE' => 2, + 'WARNINGS' => 2, + 'AGGREGATE' => 2, 'ALGORITHM' => 2, 'COLLATION' => 2, 'COMMITTED' => 2, + 'DIRECTORY' => 2, 'DUPLICATE' => 2, 'EXPANSION' => 2, 'IO_THREAD' => 2, + 'ISOLATION' => 2, 'NODEGROUP' => 2, 'PACK_KEYS' => 2, 'PARTITION' => 2, + 'READ_ONLY' => 2, 'REDUNDANT' => 2, 'SAVEPOINT' => 2, 'SQL_CACHE' => 2, + 'TEMPORARY' => 2, 'TEMPTABLE' => 2, 'TIMESTAMP' => 2, 'UNDEFINED' => 2, + 'UNINSTALL' => 2, 'VARIABLES' => 2, + 'COMPLETION' => 2, 'COMPRESSED' => 2, 'CONCURRENT' => 2, 'CONNECTION' => 2, + 'CONSISTENT' => 2, 'DEALLOCATE' => 2, 'GET_FORMAT' => 2, 'IDENTIFIED' => 2, + 'LINESTRING' => 2, 'MASTER_SSL' => 2, 'MULTIPOINT' => 2, 'NDBCLUSTER' => 2, + 'PARTITIONS' => 2, 'PRIVILEGES' => 2, 'REORGANIZE' => 2, 'REPEATABLE' => 2, + 'ROW_FORMAT' => 2, 'SQL_THREAD' => 2, 'TABLESPACE' => 2, 'TABLE_NAME' => 2, + 'COLUMN_NAME' => 2, 'CURSOR_NAME' => 2, 'EXTENT_SIZE' => 2, 'FRAC_SECOND' => 2, + 'MASTER_HOST' => 2, 'MASTER_PORT' => 2, 'MASTER_USER' => 2, 'MICROSECOND' => 2, + 'MYSQL_ERRNO' => 2, 'PROCESSLIST' => 2, 'REPLICATION' => 2, 'SCHEMA_NAME' => 2, + 'SQL_TSI_DAY' => 2, 'TRANSACTION' => 2, 'UNCOMMITTED' => 2, + 'CATALOG_NAME' => 2, 'CLASS_ORIGIN' => 2, 'CONTRIBUTORS' => 2, + 'DES_KEY_FILE' => 2, 'INITIAL_SIZE' => 2, 'MESSAGE_TEXT' => 2, + 'MULTIPOLYGON' => 2, 'OLD_PASSWORD' => 2, 'PARTITIONING' => 2, + 'RELAY_THREAD' => 2, 'SERIALIZABLE' => 2, 'SQL_NO_CACHE' => 2, + 'SQL_TSI_HOUR' => 2, 'SQL_TSI_WEEK' => 2, 'SQL_TSI_YEAR' => 2, + 'SUBPARTITION' => 2, 'TIMESTAMPADD' => 2, + 'INSERT_METHOD' => 2, 'MASTER_SSL_CA' => 2, 'RELAY_LOG_POS' => 2, + 'SQL_TSI_MONTH' => 2, 'SUBPARTITIONS' => 2, 'TIMESTAMPDIFF' => 2, + 'AUTO_INCREMENT' => 2, 'AVG_ROW_LENGTH' => 2, 'KEY_BLOCK_SIZE' => 2, + 'MASTER_LOG_POS' => 2, 'MASTER_SSL_KEY' => 2, 'RELAY_LOG_FILE' => 2, + 'SQL_TSI_MINUTE' => 2, 'SQL_TSI_SECOND' => 2, 'TABLE_CHECKSUM' => 2, + 'USER_RESOURCES' => 2, + 'AUTOEXTEND_SIZE' => 2, 'CONSTRAINT_NAME' => 2, 'DELAY_KEY_WRITE' => 2, + 'MASTER_LOG_FILE' => 2, 'MASTER_PASSWORD' => 2, 'MASTER_SSL_CERT' => 2, + 'MULTILINESTRING' => 2, 'SQL_TSI_QUARTER' => 2, 'SUBCLASS_ORIGIN' => 2, + 'MASTER_SERVER_ID' => 2, 'REDO_BUFFER_SIZE' => 2, 'UNDO_BUFFER_SIZE' => 2, + 'CONSTRAINT_SCHEMA' => 2, 'IGNORE_SERVER_IDS' => 2, 'MASTER_SSL_CAPATH' => 2, + 'MASTER_SSL_CIPHER' => 2, 'SQL_BUFFER_RESULT' => 2, + 'CONSTRAINT_CATALOG' => 2, 'GEOMETRYCOLLECTION' => 2, + 'SQL_TSI_FRAC_SECOND' => 2, + 'MASTER_CONNECT_RETRY' => 2, 'MAX_QUERIES_PER_HOUR' => 2, + 'MAX_UPDATES_PER_HOUR' => 2, 'MAX_USER_CONNECTIONS' => 2, + 'MASTER_HEARTBEAT_PERIOD' => 2, + 'MAX_CONNECTIONS_PER_HOUR' => 2, + + 'NOT NULL' => 4, + 'INDEX KEY' => 4, + 'UNIQUE KEY' => 4, + 'FOREIGN KEY' => 4, 'PRIMARY KEY' => 4, 'PRIMARY KEY' => 4, 'SPATIAL KEY' => 4, + 'FULLTEXT KEY' => 4, 'UNIQUE INDEX' => 4, + 'CHARACTER SET' => 4, 'IF NOT EXISTS' => 4, 'SPATIAL INDEX' => 4, + 'DATA DIRECTORY' => 4, 'FULLTEXT INDEX' => 4, + 'DEFAULT COLLATE' => 4, 'INDEX DIRECTORY' => 4, + 'DEFAULT CHARACTER SET' => 4, + + ); +} diff --git a/libraries/sql-parser/src/Contexts/Context_MySQL50600.php b/libraries/sql-parser/src/Contexts/Context_MySQL50600.php new file mode 100644 index 0000000000..4f0b0d6c91 --- /dev/null +++ b/libraries/sql-parser/src/Contexts/Context_MySQL50600.php @@ -0,0 +1,190 @@ + 1, 'BY' => 1, 'IF' => 1, 'IN' => 1, 'IS' => 1, + 'ON' => 1, 'OR' => 1, 'TO' => 1, + 'ADD' => 1, 'ALL' => 1, 'AND' => 1, 'ASC' => 1, 'DEC' => 1, + 'DIV' => 1, 'FOR' => 1, 'GET' => 1, 'INT' => 1, 'KEY' => 1, + 'MOD' => 1, 'NOT' => 1, 'OUT' => 1, 'SET' => 1, 'SQL' => 1, + 'SSL' => 1, 'USE' => 1, 'XOR' => 1, + 'BLOB' => 1, 'BOTH' => 1, 'CALL' => 1, 'CASE' => 1, + 'CHAR' => 1, 'DESC' => 1, 'DROP' => 1, 'DUAL' => 1, + 'EACH' => 1, 'ELSE' => 1, 'EXIT' => 1, 'FROM' => 1, + 'INT1' => 1, 'INT2' => 1, 'INT3' => 1, 'INT4' => 1, + 'INT8' => 1, 'INTO' => 1, 'JOIN' => 1, 'KEYS' => 1, + 'KILL' => 1, 'LEFT' => 1, 'LIKE' => 1, 'LOAD' => 1, + 'LOCK' => 1, 'LONG' => 1, 'LOOP' => 1, 'NULL' => 1, + 'READ' => 1, 'REAL' => 1, 'SHOW' => 1, 'THEN' => 1, + 'TRUE' => 1, 'UNDO' => 1, 'WHEN' => 1, 'WITH' => 1, + 'ALTER' => 1, 'CHECK' => 1, 'CROSS' => 1, 'FALSE' => 1, + 'FETCH' => 1, 'FLOAT' => 1, 'FORCE' => 1, 'GRANT' => 1, + 'GROUP' => 1, 'INDEX' => 1, 'INNER' => 1, 'INOUT' => 1, + 'LEAVE' => 1, 'LIMIT' => 1, 'LINES' => 1, 'MATCH' => 1, + 'ORDER' => 1, 'OUTER' => 1, 'PURGE' => 1, 'RANGE' => 1, + 'READS' => 1, 'RIGHT' => 1, 'RLIKE' => 1, 'TABLE' => 1, + 'UNION' => 1, 'USAGE' => 1, 'USING' => 1, 'WHERE' => 1, + 'WHILE' => 1, 'WRITE' => 1, + 'BEFORE' => 1, 'BIGINT' => 1, 'BINARY' => 1, 'CHANGE' => 1, + 'COLUMN' => 1, 'CREATE' => 1, 'CURSOR' => 1, 'DELETE' => 1, + 'DOUBLE' => 1, 'ELSEIF' => 1, 'EXISTS' => 1, 'FLOAT4' => 1, + 'FLOAT8' => 1, 'HAVING' => 1, 'IGNORE' => 1, 'INFILE' => 1, + 'INSERT' => 1, 'LINEAR' => 1, 'OPTION' => 1, 'REGEXP' => 1, + 'RENAME' => 1, 'REPEAT' => 1, 'RETURN' => 1, 'REVOKE' => 1, + 'SCHEMA' => 1, 'SELECT' => 1, 'SIGNAL' => 1, 'UNIQUE' => 1, + 'UNLOCK' => 1, 'UPDATE' => 1, 'VALUES' => 1, + 'ANALYZE' => 1, 'BETWEEN' => 1, 'CASCADE' => 1, 'COLLATE' => 1, + 'CONVERT' => 1, 'DECIMAL' => 1, 'DECLARE' => 1, 'DEFAULT' => 1, + 'DELAYED' => 1, 'ESCAPED' => 1, 'EXPLAIN' => 1, 'FOREIGN' => 1, + 'INTEGER' => 1, 'ITERATE' => 1, 'LEADING' => 1, 'NATURAL' => 1, + 'NUMERIC' => 1, 'OUTFILE' => 1, 'PRIMARY' => 1, 'RELEASE' => 1, + 'REPLACE' => 1, 'REQUIRE' => 1, 'SCHEMAS' => 1, 'SPATIAL' => 1, + 'TINYINT' => 1, 'TRIGGER' => 1, 'VARCHAR' => 1, 'VARYING' => 1, + 'CONTINUE' => 1, 'DATABASE' => 1, 'DAY_HOUR' => 1, + 'DESCRIBE' => 1, 'DISTINCT' => 1, 'ENCLOSED' => 1, + 'FULLTEXT' => 1, 'INTERVAL' => 1, 'LONGBLOB' => 1, + 'LONGTEXT' => 1, 'MAXVALUE' => 1, 'MODIFIES' => 1, + 'OPTIMIZE' => 1, 'RESIGNAL' => 1, 'RESTRICT' => 1, + 'SMALLINT' => 1, 'SPECIFIC' => 1, 'SQLSTATE' => 1, + 'STARTING' => 1, 'TINYBLOB' => 1, 'TINYTEXT' => 1, + 'TRAILING' => 1, 'UNSIGNED' => 1, 'UTC_DATE' => 1, + 'UTC_TIME' => 1, 'ZEROFILL' => 1, + 'CHARACTER' => 1, 'CONDITION' => 1, 'DATABASES' => 1, + 'LOCALTIME' => 1, 'MEDIUMINT' => 1, 'MIDDLEINT' => 1, + 'PARTITION' => 1, 'PRECISION' => 1, 'PROCEDURE' => 1, + 'SENSITIVE' => 1, 'SEPARATOR' => 1, 'VARBINARY' => 1, + 'ACCESSIBLE' => 1, 'ASENSITIVE' => 1, 'CONSTRAINT' => 1, + 'DAY_MINUTE' => 1, 'DAY_SECOND' => 1, 'MEDIUMBLOB' => 1, + 'MEDIUMTEXT' => 1, 'OPTIONALLY' => 1, 'READ_WRITE' => 1, + 'REFERENCES' => 1, 'SQLWARNING' => 1, 'TERMINATED' => 1, + 'YEAR_MONTH' => 1, + 'DISTINCTROW' => 1, 'HOUR_MINUTE' => 1, 'HOUR_SECOND' => 1, + 'INSENSITIVE' => 1, 'MASTER_BIND' => 1, + 'CURRENT_DATE' => 1, 'CURRENT_TIME' => 1, 'CURRENT_USER' => 1, + 'LOW_PRIORITY' => 1, 'SQLEXCEPTION' => 1, 'VARCHARACTER' => 1, + 'DETERMINISTIC' => 1, 'HIGH_PRIORITY' => 1, 'MINUTE_SECOND' => 1, + 'STRAIGHT_JOIN' => 1, 'UTC_TIMESTAMP' => 1, + 'IO_AFTER_GTIDS' => 1, 'LOCALTIMESTAMP' => 1, 'SQL_BIG_RESULT' => 1, + 'DAY_MICROSECOND' => 1, 'IO_BEFORE_GTIDS' => 1, + 'HOUR_MICROSECOND' => 1, 'SQL_SMALL_RESULT' => 1, + 'CURRENT_TIMESTAMP' => 1, + 'MINUTE_MICROSECOND' => 1, 'NO_WRITE_TO_BINLOG' => 1, + 'SECOND_MICROSECOND' => 1, + 'SQL_CALC_FOUND_ROWS' => 1, + 'MASTER_SSL_VERIFY_SERVER_CERT' => 1, + + 'AT' => 2, 'DO' => 2, 'IO' => 2, 'NO' => 2, 'XA' => 2, + 'ANY' => 2, 'AVG' => 2, 'BIT' => 2, 'CPU' => 2, 'DAY' => 2, 'END' => 2, + 'IPC' => 2, 'NDB' => 2, 'NEW' => 2, 'ONE' => 2, 'ROW' => 2, 'XML' => 2, + 'BOOL' => 2, 'BYTE' => 2, 'CODE' => 2, 'CUBE' => 2, 'DATA' => 2, 'DATE' => 2, + 'DISK' => 2, 'ENDS' => 2, 'ENUM' => 2, 'FAST' => 2, 'FILE' => 2, 'FULL' => 2, + 'HASH' => 2, 'HELP' => 2, 'HOST' => 2, 'HOUR' => 2, 'LAST' => 2, 'LESS' => 2, + 'LIST' => 2, 'LOGS' => 2, 'MODE' => 2, 'NAME' => 2, 'NEXT' => 2, 'NONE' => 2, + 'ONLY' => 2, 'OPEN' => 2, 'PAGE' => 2, 'PORT' => 2, 'PREV' => 2, 'ROWS' => 2, + 'SLOW' => 2, 'SOME' => 2, 'STOP' => 2, 'TEXT' => 2, 'THAN' => 2, 'TIME' => 2, + 'TYPE' => 2, 'USER' => 2, 'VIEW' => 2, 'WAIT' => 2, 'WEEK' => 2, 'WORK' => 2, + 'X509' => 2, 'YEAR' => 2, + 'AFTER' => 2, 'ASCII' => 2, 'BEGIN' => 2, 'BLOCK' => 2, 'BTREE' => 2, + 'CACHE' => 2, 'CHAIN' => 2, 'CLOSE' => 2, 'ERROR' => 2, 'EVENT' => 2, + 'EVERY' => 2, 'FIRST' => 2, 'FIXED' => 2, 'FLUSH' => 2, 'FOUND' => 2, + 'HOSTS' => 2, 'LEVEL' => 2, 'LOCAL' => 2, 'LOCKS' => 2, 'MERGE' => 2, + 'MONTH' => 2, 'MUTEX' => 2, 'NAMES' => 2, 'NCHAR' => 2, 'OWNER' => 2, + 'PHASE' => 2, 'POINT' => 2, 'PROXY' => 2, 'QUERY' => 2, 'QUICK' => 2, + 'RELAY' => 2, 'RESET' => 2, 'RTREE' => 2, 'SHARE' => 2, 'SLAVE' => 2, + 'START' => 2, 'SUPER' => 2, 'SWAPS' => 2, 'TYPES' => 2, 'UNTIL' => 2, + 'VALUE' => 2, + 'ACTION' => 2, 'BACKUP' => 2, 'BINLOG' => 2, 'CIPHER' => 2, 'CLIENT' => 2, + 'COMMIT' => 2, 'ENABLE' => 2, 'ENGINE' => 2, 'ERRORS' => 2, 'ESCAPE' => 2, + 'EVENTS' => 2, 'EXPIRE' => 2, 'EXPORT' => 2, 'FAULTS' => 2, 'FIELDS' => 2, + 'FORMAT' => 2, 'GLOBAL' => 2, 'GRANTS' => 2, 'IMPORT' => 2, 'ISSUER' => 2, + 'LEAVES' => 2, 'MASTER' => 2, 'MEDIUM' => 2, 'MEMORY' => 2, 'MINUTE' => 2, + 'MODIFY' => 2, 'NUMBER' => 2, 'OFFSET' => 2, 'PARSER' => 2, 'PLUGIN' => 2, + 'RELOAD' => 2, 'REMOVE' => 2, 'REPAIR' => 2, 'RESUME' => 2, 'ROLLUP' => 2, + 'SECOND' => 2, 'SERIAL' => 2, 'SERVER' => 2, 'SIGNED' => 2, 'SIMPLE' => 2, + 'SOCKET' => 2, 'SONAME' => 2, 'SOUNDS' => 2, 'SOURCE' => 2, 'STARTS' => 2, + 'STATUS' => 2, 'STRING' => 2, 'TABLES' => 2, + 'AGAINST' => 2, 'ANALYSE' => 2, 'AUTHORS' => 2, 'BOOLEAN' => 2, 'CHANGED' => 2, + 'CHARSET' => 2, 'COLUMNS' => 2, 'COMMENT' => 2, 'COMPACT' => 2, 'CONTEXT' => 2, + 'CURRENT' => 2, 'DEFINER' => 2, 'DISABLE' => 2, 'DISCARD' => 2, 'DYNAMIC' => 2, + 'ENGINES' => 2, 'EXECUTE' => 2, 'GENERAL' => 2, 'HANDLER' => 2, 'INDEXES' => 2, + 'INSTALL' => 2, 'INVOKER' => 2, 'LOGFILE' => 2, 'MIGRATE' => 2, 'NO_WAIT' => 2, + 'OPTIONS' => 2, 'PARTIAL' => 2, 'PLUGINS' => 2, 'POLYGON' => 2, 'PREPARE' => 2, + 'PROFILE' => 2, 'QUARTER' => 2, 'REBUILD' => 2, 'RECOVER' => 2, 'RESTORE' => 2, + 'RETURNS' => 2, 'REVERSE' => 2, 'ROUTINE' => 2, 'SESSION' => 2, 'STORAGE' => 2, + 'SUBJECT' => 2, 'SUSPEND' => 2, 'UNICODE' => 2, 'UNKNOWN' => 2, 'UPGRADE' => 2, + 'USE_FRM' => 2, 'WRAPPER' => 2, + 'CASCADED' => 2, 'CHECKSUM' => 2, 'COALESCE' => 2, 'CONTAINS' => 2, + 'DATAFILE' => 2, 'DATETIME' => 2, 'DUMPFILE' => 2, 'EXCHANGE' => 2, + 'EXTENDED' => 2, 'FUNCTION' => 2, 'GEOMETRY' => 2, 'LANGUAGE' => 2, + 'MAX_ROWS' => 2, 'MAX_SIZE' => 2, 'MIN_ROWS' => 2, 'NATIONAL' => 2, + 'NVARCHAR' => 2, 'ONE_SHOT' => 2, 'PASSWORD' => 2, 'PRESERVE' => 2, + 'PROFILES' => 2, 'REDOFILE' => 2, 'RELAYLOG' => 2, 'ROLLBACK' => 2, + 'SCHEDULE' => 2, 'SECURITY' => 2, 'SHUTDOWN' => 2, 'SNAPSHOT' => 2, + 'SWITCHES' => 2, 'TRIGGERS' => 2, 'TRUNCATE' => 2, 'UNDOFILE' => 2, + 'WARNINGS' => 2, + 'AGGREGATE' => 2, 'ALGORITHM' => 2, 'COLLATION' => 2, 'COMMITTED' => 2, + 'DIRECTORY' => 2, 'DUPLICATE' => 2, 'EXPANSION' => 2, 'IO_THREAD' => 2, + 'ISOLATION' => 2, 'NODEGROUP' => 2, 'PACK_KEYS' => 2, 'READ_ONLY' => 2, + 'REDUNDANT' => 2, 'ROW_COUNT' => 2, 'SAVEPOINT' => 2, 'SQL_CACHE' => 2, + 'TEMPORARY' => 2, 'TEMPTABLE' => 2, 'TIMESTAMP' => 2, 'UNDEFINED' => 2, + 'UNINSTALL' => 2, 'VARIABLES' => 2, + 'COMPLETION' => 2, 'COMPRESSED' => 2, 'CONCURRENT' => 2, 'CONNECTION' => 2, + 'CONSISTENT' => 2, 'DEALLOCATE' => 2, 'GET_FORMAT' => 2, 'IDENTIFIED' => 2, + 'LINESTRING' => 2, 'MASTER_SSL' => 2, 'MULTIPOINT' => 2, 'NDBCLUSTER' => 2, + 'PARTITIONS' => 2, 'PLUGIN_DIR' => 2, 'PRIVILEGES' => 2, 'REORGANIZE' => 2, + 'REPEATABLE' => 2, 'ROW_FORMAT' => 2, 'SQL_THREAD' => 2, 'TABLESPACE' => 2, + 'TABLE_NAME' => 2, + 'COLUMN_NAME' => 2, 'CURSOR_NAME' => 2, 'DIAGNOSTICS' => 2, 'EXTENT_SIZE' => 2, + 'MASTER_HOST' => 2, 'MASTER_PORT' => 2, 'MASTER_USER' => 2, 'MICROSECOND' => 2, + 'MYSQL_ERRNO' => 2, 'PROCESSLIST' => 2, 'REPLICATION' => 2, 'SCHEMA_NAME' => 2, + 'SQL_TSI_DAY' => 2, 'TRANSACTION' => 2, 'UNCOMMITTED' => 2, + 'CATALOG_NAME' => 2, 'CLASS_ORIGIN' => 2, 'CONTRIBUTORS' => 2, + 'DEFAULT_AUTH' => 2, 'DES_KEY_FILE' => 2, 'INITIAL_SIZE' => 2, + 'MASTER_DELAY' => 2, 'MESSAGE_TEXT' => 2, 'MULTIPOLYGON' => 2, + 'OLD_PASSWORD' => 2, 'PARTITIONING' => 2, 'RELAY_THREAD' => 2, + 'SERIALIZABLE' => 2, 'SQL_NO_CACHE' => 2, 'SQL_TSI_HOUR' => 2, + 'SQL_TSI_WEEK' => 2, 'SQL_TSI_YEAR' => 2, 'SUBPARTITION' => 2, + 'TIMESTAMPADD' => 2, + 'COLUMN_FORMAT' => 2, 'INSERT_METHOD' => 2, 'MASTER_SSL_CA' => 2, + 'RELAY_LOG_POS' => 2, 'SQL_TSI_MONTH' => 2, 'SUBPARTITIONS' => 2, + 'TIMESTAMPDIFF' => 2, 'WEIGHT_STRING' => 2, + 'AUTO_INCREMENT' => 2, 'AVG_ROW_LENGTH' => 2, 'KEY_BLOCK_SIZE' => 2, + 'MASTER_LOG_POS' => 2, 'MASTER_SSL_CRL' => 2, 'MASTER_SSL_KEY' => 2, + 'RELAY_LOG_FILE' => 2, 'SQL_TSI_MINUTE' => 2, 'SQL_TSI_SECOND' => 2, + 'TABLE_CHECKSUM' => 2, 'USER_RESOURCES' => 2, + 'AUTOEXTEND_SIZE' => 2, 'CONSTRAINT_NAME' => 2, 'DELAY_KEY_WRITE' => 2, + 'MASTER_LOG_FILE' => 2, 'MASTER_PASSWORD' => 2, 'MASTER_SSL_CERT' => 2, + 'MULTILINESTRING' => 2, 'SQL_AFTER_GTIDS' => 2, 'SQL_TSI_QUARTER' => 2, + 'SUBCLASS_ORIGIN' => 2, + 'MASTER_SERVER_ID' => 2, 'REDO_BUFFER_SIZE' => 2, 'SQL_BEFORE_GTIDS' => 2, + 'STATS_PERSISTENT' => 2, 'UNDO_BUFFER_SIZE' => 2, + 'CONSTRAINT_SCHEMA' => 2, 'IGNORE_SERVER_IDS' => 2, 'MASTER_SSL_CAPATH' => 2, + 'MASTER_SSL_CIPHER' => 2, 'RETURNED_SQLSTATE' => 2, 'SQL_BUFFER_RESULT' => 2, + 'STATS_AUTO_RECALC' => 2, + 'CONSTRAINT_CATALOG' => 2, 'GEOMETRYCOLLECTION' => 2, 'MASTER_RETRY_COUNT' => 2, + 'MASTER_SSL_CRLPATH' => 2, 'SQL_AFTER_MTS_GAPS' => 2, 'STATS_SAMPLE_PAGES' => 2, + 'MASTER_AUTO_POSITION' => 2, 'MASTER_CONNECT_RETRY' => 2, + 'MAX_QUERIES_PER_HOUR' => 2, 'MAX_UPDATES_PER_HOUR' => 2, + 'MAX_USER_CONNECTIONS' => 2, + 'MASTER_HEARTBEAT_PERIOD' => 2, + 'MAX_CONNECTIONS_PER_HOUR' => 2, + + 'NOT NULL' => 4, + 'INDEX KEY' => 4, + 'UNIQUE KEY' => 4, + 'FOREIGN KEY' => 4, 'PRIMARY KEY' => 4, 'PRIMARY KEY' => 4, 'SPATIAL KEY' => 4, + 'FULLTEXT KEY' => 4, 'UNIQUE INDEX' => 4, + 'CHARACTER SET' => 4, 'IF NOT EXISTS' => 4, 'SPATIAL INDEX' => 4, + 'DATA DIRECTORY' => 4, 'FULLTEXT INDEX' => 4, + 'DEFAULT COLLATE' => 4, 'INDEX DIRECTORY' => 4, + 'DEFAULT CHARACTER SET' => 4, + + ); +} diff --git a/libraries/sql-parser/src/Contexts/Context_MySQL50700.php b/libraries/sql-parser/src/Contexts/Context_MySQL50700.php new file mode 100644 index 0000000000..578da8982b --- /dev/null +++ b/libraries/sql-parser/src/Contexts/Context_MySQL50700.php @@ -0,0 +1,199 @@ + 1, 'BY' => 1, 'IF' => 1, 'IN' => 1, 'IS' => 1, + 'ON' => 1, 'OR' => 1, 'TO' => 1, + 'ADD' => 1, 'ALL' => 1, 'AND' => 1, 'ASC' => 1, 'DEC' => 1, + 'DIV' => 1, 'FOR' => 1, 'GET' => 1, 'INT' => 1, 'KEY' => 1, + 'MOD' => 1, 'NOT' => 1, 'OUT' => 1, 'SET' => 1, 'SQL' => 1, + 'SSL' => 1, 'USE' => 1, 'XOR' => 1, + 'BLOB' => 1, 'BOTH' => 1, 'CALL' => 1, 'CASE' => 1, + 'CHAR' => 1, 'DESC' => 1, 'DROP' => 1, 'DUAL' => 1, + 'EACH' => 1, 'ELSE' => 1, 'EXIT' => 1, 'FROM' => 1, + 'INT1' => 1, 'INT2' => 1, 'INT3' => 1, 'INT4' => 1, + 'INT8' => 1, 'INTO' => 1, 'JOIN' => 1, 'KEYS' => 1, + 'KILL' => 1, 'LEFT' => 1, 'LIKE' => 1, 'LOAD' => 1, + 'LOCK' => 1, 'LONG' => 1, 'LOOP' => 1, 'NULL' => 1, + 'READ' => 1, 'REAL' => 1, 'SHOW' => 1, 'THEN' => 1, + 'TRUE' => 1, 'UNDO' => 1, 'WHEN' => 1, 'WITH' => 1, + 'ALTER' => 1, 'CHECK' => 1, 'CROSS' => 1, 'FALSE' => 1, + 'FETCH' => 1, 'FLOAT' => 1, 'FORCE' => 1, 'GRANT' => 1, + 'GROUP' => 1, 'INDEX' => 1, 'INNER' => 1, 'INOUT' => 1, + 'LEAVE' => 1, 'LIMIT' => 1, 'LINES' => 1, 'MATCH' => 1, + 'ORDER' => 1, 'OUTER' => 1, 'PURGE' => 1, 'RANGE' => 1, + 'READS' => 1, 'RIGHT' => 1, 'RLIKE' => 1, 'TABLE' => 1, + 'UNION' => 1, 'USAGE' => 1, 'USING' => 1, 'WHERE' => 1, + 'WHILE' => 1, 'WRITE' => 1, + 'BEFORE' => 1, 'BIGINT' => 1, 'BINARY' => 1, 'CHANGE' => 1, + 'COLUMN' => 1, 'CREATE' => 1, 'CURSOR' => 1, 'DELETE' => 1, + 'DOUBLE' => 1, 'ELSEIF' => 1, 'EXISTS' => 1, 'FLOAT4' => 1, + 'FLOAT8' => 1, 'HAVING' => 1, 'IGNORE' => 1, 'INFILE' => 1, + 'INSERT' => 1, 'LINEAR' => 1, 'OPTION' => 1, 'REGEXP' => 1, + 'RENAME' => 1, 'REPEAT' => 1, 'RETURN' => 1, 'REVOKE' => 1, + 'SCHEMA' => 1, 'SELECT' => 1, 'SIGNAL' => 1, 'STORED' => 1, + 'UNIQUE' => 1, 'UNLOCK' => 1, 'UPDATE' => 1, 'VALUES' => 1, + 'ANALYZE' => 1, 'BETWEEN' => 1, 'CASCADE' => 1, 'COLLATE' => 1, + 'CONVERT' => 1, 'DECIMAL' => 1, 'DECLARE' => 1, 'DEFAULT' => 1, + 'DELAYED' => 1, 'ESCAPED' => 1, 'EXPLAIN' => 1, 'FOREIGN' => 1, + 'INTEGER' => 1, 'ITERATE' => 1, 'LEADING' => 1, 'NATURAL' => 1, + 'NUMERIC' => 1, 'OUTFILE' => 1, 'PRIMARY' => 1, 'RELEASE' => 1, + 'REPLACE' => 1, 'REQUIRE' => 1, 'SCHEMAS' => 1, 'SPATIAL' => 1, + 'TINYINT' => 1, 'TRIGGER' => 1, 'VARCHAR' => 1, 'VARYING' => 1, + 'VIRTUAL' => 1, + 'CONTINUE' => 1, 'DATABASE' => 1, 'DAY_HOUR' => 1, + 'DESCRIBE' => 1, 'DISTINCT' => 1, 'ENCLOSED' => 1, + 'FULLTEXT' => 1, 'INTERVAL' => 1, 'LONGBLOB' => 1, + 'LONGTEXT' => 1, 'MAXVALUE' => 1, 'MODIFIES' => 1, + 'OPTIMIZE' => 1, 'RESIGNAL' => 1, 'RESTRICT' => 1, + 'SMALLINT' => 1, 'SPECIFIC' => 1, 'SQLSTATE' => 1, + 'STARTING' => 1, 'TINYBLOB' => 1, 'TINYTEXT' => 1, + 'TRAILING' => 1, 'UNSIGNED' => 1, 'UTC_DATE' => 1, + 'UTC_TIME' => 1, 'ZEROFILL' => 1, + 'CHARACTER' => 1, 'CONDITION' => 1, 'DATABASES' => 1, + 'GENERATED' => 1, 'LOCALTIME' => 1, 'MEDIUMINT' => 1, + 'MIDDLEINT' => 1, 'PARTITION' => 1, 'PRECISION' => 1, + 'PROCEDURE' => 1, 'SENSITIVE' => 1, 'SEPARATOR' => 1, + 'VARBINARY' => 1, + 'ACCESSIBLE' => 1, 'ASENSITIVE' => 1, 'CONSTRAINT' => 1, + 'DAY_MINUTE' => 1, 'DAY_SECOND' => 1, 'MEDIUMBLOB' => 1, + 'MEDIUMTEXT' => 1, 'OPTIONALLY' => 1, 'READ_WRITE' => 1, + 'REFERENCES' => 1, 'SQLWARNING' => 1, 'TERMINATED' => 1, + 'YEAR_MONTH' => 1, + 'DISTINCTROW' => 1, 'HOUR_MINUTE' => 1, 'HOUR_SECOND' => 1, + 'INSENSITIVE' => 1, 'MASTER_BIND' => 1, + 'CURRENT_DATE' => 1, 'CURRENT_TIME' => 1, 'CURRENT_USER' => 1, + 'LOW_PRIORITY' => 1, 'SQLEXCEPTION' => 1, 'VARCHARACTER' => 1, + 'DETERMINISTIC' => 1, 'HIGH_PRIORITY' => 1, 'MINUTE_SECOND' => 1, + 'STRAIGHT_JOIN' => 1, 'UTC_TIMESTAMP' => 1, + 'IO_AFTER_GTIDS' => 1, 'LOCALTIMESTAMP' => 1, 'SQL_BIG_RESULT' => 1, + 'DAY_MICROSECOND' => 1, 'IO_BEFORE_GTIDS' => 1, 'OPTIMIZER_COSTS' => 1, + 'HOUR_MICROSECOND' => 1, 'SQL_SMALL_RESULT' => 1, + 'CURRENT_TIMESTAMP' => 1, + 'MINUTE_MICROSECOND' => 1, 'NO_WRITE_TO_BINLOG' => 1, + 'SECOND_MICROSECOND' => 1, + 'SQL_CALC_FOUND_ROWS' => 1, + 'MASTER_SSL_VERIFY_SERVER_CERT' => 1, + + 'AT' => 2, 'DO' => 2, 'IO' => 2, 'NO' => 2, 'XA' => 2, + 'ANY' => 2, 'AVG' => 2, 'BIT' => 2, 'CPU' => 2, 'DAY' => 2, 'END' => 2, + 'IPC' => 2, 'NDB' => 2, 'NEW' => 2, 'ONE' => 2, 'ROW' => 2, 'XID' => 2, + 'XML' => 2, + 'BOOL' => 2, 'BYTE' => 2, 'CODE' => 2, 'CUBE' => 2, 'DATA' => 2, 'DATE' => 2, + 'DISK' => 2, 'ENDS' => 2, 'ENUM' => 2, 'FAST' => 2, 'FILE' => 2, 'FULL' => 2, + 'HASH' => 2, 'HELP' => 2, 'HOST' => 2, 'HOUR' => 2, 'LAST' => 2, 'LESS' => 2, + 'LIST' => 2, 'LOGS' => 2, 'MODE' => 2, 'NAME' => 2, 'NEXT' => 2, 'NONE' => 2, + 'ONLY' => 2, 'OPEN' => 2, 'PAGE' => 2, 'PORT' => 2, 'PREV' => 2, 'ROWS' => 2, + 'SLOW' => 2, 'SOME' => 2, 'STOP' => 2, 'TEXT' => 2, 'THAN' => 2, 'TIME' => 2, + 'TYPE' => 2, 'USER' => 2, 'VIEW' => 2, 'WAIT' => 2, 'WEEK' => 2, 'WORK' => 2, + 'X509' => 2, 'YEAR' => 2, + 'AFTER' => 2, 'ASCII' => 2, 'BEGIN' => 2, 'BLOCK' => 2, 'BTREE' => 2, + 'CACHE' => 2, 'CHAIN' => 2, 'CLOSE' => 2, 'ERROR' => 2, 'EVENT' => 2, + 'EVERY' => 2, 'FIRST' => 2, 'FIXED' => 2, 'FLUSH' => 2, 'FOUND' => 2, + 'HOSTS' => 2, 'LEVEL' => 2, 'LOCAL' => 2, 'LOCKS' => 2, 'MERGE' => 2, + 'MONTH' => 2, 'MUTEX' => 2, 'NAMES' => 2, 'NCHAR' => 2, 'NEVER' => 2, + 'OWNER' => 2, 'PHASE' => 2, 'POINT' => 2, 'PROXY' => 2, 'QUERY' => 2, + 'QUICK' => 2, 'RELAY' => 2, 'RESET' => 2, 'RTREE' => 2, 'SHARE' => 2, + 'SLAVE' => 2, 'START' => 2, 'SUPER' => 2, 'SWAPS' => 2, 'TYPES' => 2, + 'UNTIL' => 2, 'VALUE' => 2, + 'ACTION' => 2, 'ALWAYS' => 2, 'BACKUP' => 2, 'BINLOG' => 2, 'CIPHER' => 2, + 'CLIENT' => 2, 'COMMIT' => 2, 'ENABLE' => 2, 'ENGINE' => 2, 'ERRORS' => 2, + 'ESCAPE' => 2, 'EVENTS' => 2, 'EXPIRE' => 2, 'EXPORT' => 2, 'FAULTS' => 2, + 'FIELDS' => 2, 'FILTER' => 2, 'FORMAT' => 2, 'GLOBAL' => 2, 'GRANTS' => 2, + 'IMPORT' => 2, 'ISSUER' => 2, 'LEAVES' => 2, 'MASTER' => 2, 'MEDIUM' => 2, + 'MEMORY' => 2, 'MINUTE' => 2, 'MODIFY' => 2, 'NUMBER' => 2, 'OFFSET' => 2, + 'PARSER' => 2, 'PLUGIN' => 2, 'RELOAD' => 2, 'REMOVE' => 2, 'REPAIR' => 2, + 'RESUME' => 2, 'ROLLUP' => 2, 'SECOND' => 2, 'SERIAL' => 2, 'SERVER' => 2, + 'SIGNED' => 2, 'SIMPLE' => 2, 'SOCKET' => 2, 'SONAME' => 2, 'SOUNDS' => 2, + 'SOURCE' => 2, 'STARTS' => 2, 'STATUS' => 2, 'STRING' => 2, 'TABLES' => 2, + 'ACCOUNT' => 2, 'AGAINST' => 2, 'ANALYSE' => 2, 'BOOLEAN' => 2, 'CHANGED' => 2, + 'CHANNEL' => 2, 'CHARSET' => 2, 'COLUMNS' => 2, 'COMMENT' => 2, 'COMPACT' => 2, + 'CONTEXT' => 2, 'CURRENT' => 2, 'DEFINER' => 2, 'DISABLE' => 2, 'DISCARD' => 2, + 'DYNAMIC' => 2, 'ENGINES' => 2, 'EXECUTE' => 2, 'FOLLOWS' => 2, 'GENERAL' => 2, + 'HANDLER' => 2, 'INDEXES' => 2, 'INSTALL' => 2, 'INVOKER' => 2, 'LOGFILE' => 2, + 'MIGRATE' => 2, 'NO_WAIT' => 2, 'OPTIONS' => 2, 'PARTIAL' => 2, 'PLUGINS' => 2, + 'POLYGON' => 2, 'PREPARE' => 2, 'PROFILE' => 2, 'QUARTER' => 2, 'REBUILD' => 2, + 'RECOVER' => 2, 'RESTORE' => 2, 'RETURNS' => 2, 'REVERSE' => 2, 'ROUTINE' => 2, + 'SESSION' => 2, 'STACKED' => 2, 'STORAGE' => 2, 'SUBJECT' => 2, 'SUSPEND' => 2, + 'UNICODE' => 2, 'UNKNOWN' => 2, 'UPGRADE' => 2, 'USE_FRM' => 2, 'WITHOUT' => 2, + 'WRAPPER' => 2, + 'CASCADED' => 2, 'CHECKSUM' => 2, 'COALESCE' => 2, 'CONTAINS' => 2, + 'DATAFILE' => 2, 'DATETIME' => 2, 'DUMPFILE' => 2, 'EXCHANGE' => 2, + 'EXTENDED' => 2, 'FUNCTION' => 2, 'GEOMETRY' => 2, 'LANGUAGE' => 2, + 'MAX_ROWS' => 2, 'MAX_SIZE' => 2, 'MIN_ROWS' => 2, 'NATIONAL' => 2, + 'NVARCHAR' => 2, 'PASSWORD' => 2, 'PRECEDES' => 2, 'PRESERVE' => 2, + 'PROFILES' => 2, 'REDOFILE' => 2, 'RELAYLOG' => 2, 'ROLLBACK' => 2, + 'SCHEDULE' => 2, 'SECURITY' => 2, 'SHUTDOWN' => 2, 'SNAPSHOT' => 2, + 'SWITCHES' => 2, 'TRIGGERS' => 2, 'TRUNCATE' => 2, 'UNDOFILE' => 2, + 'WARNINGS' => 2, + 'AGGREGATE' => 2, 'ALGORITHM' => 2, 'COLLATION' => 2, 'COMMITTED' => 2, + 'DIRECTORY' => 2, 'DUPLICATE' => 2, 'EXPANSION' => 2, 'IO_THREAD' => 2, + 'ISOLATION' => 2, 'NODEGROUP' => 2, 'PACK_KEYS' => 2, 'READ_ONLY' => 2, + 'REDUNDANT' => 2, 'ROW_COUNT' => 2, 'SAVEPOINT' => 2, 'SQL_CACHE' => 2, + 'TEMPORARY' => 2, 'TEMPTABLE' => 2, 'TIMESTAMP' => 2, 'UNDEFINED' => 2, + 'UNINSTALL' => 2, 'VARIABLES' => 2, + 'COMPLETION' => 2, 'COMPRESSED' => 2, 'CONCURRENT' => 2, 'CONNECTION' => 2, + 'CONSISTENT' => 2, 'DEALLOCATE' => 2, 'GET_FORMAT' => 2, 'IDENTIFIED' => 2, + 'LINESTRING' => 2, 'MASTER_SSL' => 2, 'MULTIPOINT' => 2, 'NDBCLUSTER' => 2, + 'PARTITIONS' => 2, 'PLUGIN_DIR' => 2, 'PRIVILEGES' => 2, 'REORGANIZE' => 2, + 'REPEATABLE' => 2, 'ROW_FORMAT' => 2, 'SQL_THREAD' => 2, 'TABLESPACE' => 2, + 'TABLE_NAME' => 2, 'VALIDATION' => 2, + 'COLUMN_NAME' => 2, 'COMPRESSION' => 2, 'CURSOR_NAME' => 2, 'DIAGNOSTICS' => 2, + 'EXTENT_SIZE' => 2, 'MASTER_HOST' => 2, 'MASTER_PORT' => 2, 'MASTER_USER' => 2, + 'MICROSECOND' => 2, 'MYSQL_ERRNO' => 2, 'NONBLOCKING' => 2, 'PROCESSLIST' => 2, + 'REPLICATION' => 2, 'SCHEMA_NAME' => 2, 'SQL_TSI_DAY' => 2, 'TRANSACTION' => 2, + 'UNCOMMITTED' => 2, + 'CATALOG_NAME' => 2, 'CLASS_ORIGIN' => 2, 'DEFAULT_AUTH' => 2, + 'DES_KEY_FILE' => 2, 'INITIAL_SIZE' => 2, 'MASTER_DELAY' => 2, + 'MESSAGE_TEXT' => 2, 'MULTIPOLYGON' => 2, 'OLD_PASSWORD' => 2, + 'PARTITIONING' => 2, 'RELAY_THREAD' => 2, 'SERIALIZABLE' => 2, + 'SQL_NO_CACHE' => 2, 'SQL_TSI_HOUR' => 2, 'SQL_TSI_WEEK' => 2, + 'SQL_TSI_YEAR' => 2, 'SUBPARTITION' => 2, 'TIMESTAMPADD' => 2, + 'COLUMN_FORMAT' => 2, 'INSERT_METHOD' => 2, 'MASTER_SSL_CA' => 2, + 'RELAY_LOG_POS' => 2, 'SQL_TSI_MONTH' => 2, 'SUBPARTITIONS' => 2, + 'TIMESTAMPDIFF' => 2, 'WEIGHT_STRING' => 2, + 'AUTO_INCREMENT' => 2, 'AVG_ROW_LENGTH' => 2, 'KEY_BLOCK_SIZE' => 2, + 'MASTER_LOG_POS' => 2, 'MASTER_SSL_CRL' => 2, 'MASTER_SSL_KEY' => 2, + 'RELAY_LOG_FILE' => 2, 'SQL_TSI_MINUTE' => 2, 'SQL_TSI_SECOND' => 2, + 'TABLE_CHECKSUM' => 2, 'USER_RESOURCES' => 2, + 'AUTOEXTEND_SIZE' => 2, 'CONSTRAINT_NAME' => 2, 'DELAY_KEY_WRITE' => 2, + 'FILE_BLOCK_SIZE' => 2, 'MASTER_LOG_FILE' => 2, 'MASTER_PASSWORD' => 2, + 'MASTER_SSL_CERT' => 2, 'MULTILINESTRING' => 2, 'PARSE_GCOL_EXPR' => 2, + 'REPLICATE_DO_DB' => 2, 'SQL_AFTER_GTIDS' => 2, 'SQL_TSI_QUARTER' => 2, + 'SUBCLASS_ORIGIN' => 2, + 'MASTER_SERVER_ID' => 2, 'REDO_BUFFER_SIZE' => 2, 'SQL_BEFORE_GTIDS' => 2, + 'STATS_PERSISTENT' => 2, 'UNDO_BUFFER_SIZE' => 2, + 'CONSTRAINT_SCHEMA' => 2, 'GROUP_REPLICATION' => 2, 'IGNORE_SERVER_IDS' => 2, + 'MASTER_SSL_CAPATH' => 2, 'MASTER_SSL_CIPHER' => 2, 'RETURNED_SQLSTATE' => 2, + 'SQL_BUFFER_RESULT' => 2, 'STATS_AUTO_RECALC' => 2, + 'CONSTRAINT_CATALOG' => 2, 'GEOMETRYCOLLECTION' => 2, 'MASTER_RETRY_COUNT' => 2, + 'MASTER_SSL_CRLPATH' => 2, 'MAX_STATEMENT_TIME' => 2, 'REPLICATE_DO_TABLE' => 2, + 'SQL_AFTER_MTS_GAPS' => 2, 'STATS_SAMPLE_PAGES' => 2, + 'REPLICATE_IGNORE_DB' => 2, + 'MASTER_AUTO_POSITION' => 2, 'MASTER_CONNECT_RETRY' => 2, + 'MAX_QUERIES_PER_HOUR' => 2, 'MAX_UPDATES_PER_HOUR' => 2, + 'MAX_USER_CONNECTIONS' => 2, 'REPLICATE_REWRITE_DB' => 2, + 'REPLICATE_IGNORE_TABLE' => 2, + 'MASTER_HEARTBEAT_PERIOD' => 2, 'REPLICATE_WILD_DO_TABLE' => 2, + 'MAX_CONNECTIONS_PER_HOUR' => 2, + 'REPLICATE_WILD_IGNORE_TABLE' => 2, + + 'NOT NULL' => 4, + 'INDEX KEY' => 4, + 'UNIQUE KEY' => 4, + 'FOREIGN KEY' => 4, 'PRIMARY KEY' => 4, 'PRIMARY KEY' => 4, 'SPATIAL KEY' => 4, + 'FULLTEXT KEY' => 4, 'UNIQUE INDEX' => 4, + 'CHARACTER SET' => 4, 'IF NOT EXISTS' => 4, 'SPATIAL INDEX' => 4, + 'DATA DIRECTORY' => 4, 'FULLTEXT INDEX' => 4, + 'DEFAULT COLLATE' => 4, 'INDEX DIRECTORY' => 4, + 'DEFAULT CHARACTER SET' => 4, + + ); +} diff --git a/libraries/sql-parser/src/Exceptions/LexerException.php b/libraries/sql-parser/src/Exceptions/LexerException.php index f346d83dca..306c8b924d 100644 --- a/libraries/sql-parser/src/Exceptions/LexerException.php +++ b/libraries/sql-parser/src/Exceptions/LexerException.php @@ -27,14 +27,14 @@ class LexerException extends \Exception /** * Constructor. * - * @param string $message - * @param string $ch - * @param int $positiion - * @param int $code + * @param string $msg The message of this exception. + * @param string $ch The character that produced this exception. + * @param int $pos The position of the character. + * @param int $code The code of this error. */ - public function __construct($message = '', $ch = '', $pos = 0, $code = 0) + public function __construct($msg = '', $ch = '', $pos = 0, $code = 0) { - parent::__construct($message, $code); + parent::__construct($msg, $code); $this->ch = $ch; $this->pos = $pos; } diff --git a/libraries/sql-parser/src/Exceptions/ParserException.php b/libraries/sql-parser/src/Exceptions/ParserException.php index e23d03daf7..7332674452 100644 --- a/libraries/sql-parser/src/Exceptions/ParserException.php +++ b/libraries/sql-parser/src/Exceptions/ParserException.php @@ -20,13 +20,13 @@ class ParserException extends \Exception /** * Constructor. * - * @param string $message - * @param Token $token - * @param int $code + * @param string $msg The message of this exception. + * @param Token $token The token that produced this exception. + * @param int $code The code of this error. */ - public function __construct($message = '', Token $token = null, $code = 0) + public function __construct($msg = '', Token $token = null, $code = 0) { - parent::__construct($message, $code); + parent::__construct($msg, $code); $this->token = $token; } } diff --git a/libraries/sql-parser/src/Fragment.php b/libraries/sql-parser/src/Fragment.php index e9a4620527..63af280f26 100644 --- a/libraries/sql-parser/src/Fragment.php +++ b/libraries/sql-parser/src/Fragment.php @@ -9,20 +9,12 @@ namespace SqlParser; abstract class Fragment { - /** - * Array which contains all tokens used to popoluate data inside this - * fragment. - * - * @var array - */ - public $tokens = array(); - /** * Parses the tokens given by the lexer in the context of the given parser. * - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return array */ diff --git a/libraries/sql-parser/src/Fragments/ArrayFragment.php b/libraries/sql-parser/src/Fragments/ArrayFragment.php index 9ff8649e34..6436823be0 100644 --- a/libraries/sql-parser/src/Fragments/ArrayFragment.php +++ b/libraries/sql-parser/src/Fragments/ArrayFragment.php @@ -15,16 +15,23 @@ class ArrayFragment extends Fragment { /** - * The array. + * The array that contains the processed value of each token. * * @var array */ public $array = array(); /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * The array that contains the unprocessed value of each token. + * + * @var array + */ + public $raw = array(); + + /** + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return ArrayFragment */ @@ -74,7 +81,7 @@ class ArrayFragment extends Fragment break; } $ret->array[] = $token->value; - $ret->tokens[] = $token; + $ret->raw[] = $token->token; $state = 2; } elseif ($state === 2) { if (($token->type !== Token::TYPE_OPERATOR) || (($token->value !== ',') && ($token->value !== ')'))) { diff --git a/libraries/sql-parser/src/Fragments/CallKeyword.php b/libraries/sql-parser/src/Fragments/CallKeyword.php index 00b7838e71..6147cf4ab2 100644 --- a/libraries/sql-parser/src/Fragments/CallKeyword.php +++ b/libraries/sql-parser/src/Fragments/CallKeyword.php @@ -29,9 +29,9 @@ class CallKeyword extends Fragment public $parameters = array(); /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return CallKeyword */ @@ -68,13 +68,11 @@ class CallKeyword extends Fragment if ($state === 0) { $ret->name = $token->value; - $ret->tokens[] = $token; $state = 1; } elseif ($state === 1) { if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { $parameters = ArrayFragment::parse($parser, $list); $ret->parameters = $parameters->array; - $ret->tokens = array_merge($ret->tokens, $parameters->tokens); } break; } diff --git a/libraries/sql-parser/src/Fragments/CreateDefFragment.php b/libraries/sql-parser/src/Fragments/CreateDefFragment.php index 708ce11b85..675ad81094 100644 --- a/libraries/sql-parser/src/Fragments/CreateDefFragment.php +++ b/libraries/sql-parser/src/Fragments/CreateDefFragment.php @@ -70,9 +70,9 @@ class CreateDefFragment extends Fragment public $name; /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return CreateDefFragment */ @@ -98,7 +98,6 @@ class CreateDefFragment extends Fragment break; } - $ret->tokens[] = $token; $ret->name .= $token->value; } diff --git a/libraries/sql-parser/src/Fragments/DataTypeFragment.php b/libraries/sql-parser/src/Fragments/DataTypeFragment.php index c0a4f61a4c..ca7cfafc3b 100644 --- a/libraries/sql-parser/src/Fragments/DataTypeFragment.php +++ b/libraries/sql-parser/src/Fragments/DataTypeFragment.php @@ -18,10 +18,10 @@ class DataTypeFragment extends Fragment public static $OPTIONS = array( 'BINARY' => 1, 'CHARACTER SET' => array(2, 'var'), - 'CHARSET' => array(3, 'var'), - 'COLLATE' => 4, - 'UNSIGNED' => 5, - 'ZEROFILL' => 6, + 'CHARSET' => array(2, 'var'), + 'COLLATE' => 3, + 'UNSIGNED' => 4, + 'ZEROFILL' => 5, ); /** @@ -46,9 +46,9 @@ class DataTypeFragment extends Fragment public $options = array(); /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return DataTypeFragment[] */ @@ -80,7 +80,6 @@ class DataTypeFragment extends Fragment if ($state === 0) { $ret->name = $token->value; - $ret->tokens[] = $token; if (!isset(Context::$DATA_TYPES[$token->value])) { $parser->error('Unrecognized data type.', $token); } @@ -88,11 +87,9 @@ class DataTypeFragment extends Fragment } elseif ($state === 1) { if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { $size = ArrayFragment::parse($parser, $list); - foreach ($size->tokens as $token) { - $ret->size[] = $token->token; - } - $ret->tokens = array_merge($ret->tokens, $size->tokens); ++$list->idx; + $ret->size = (($ret->name === 'ENUM') || ($ret->name === 'SET')) ? + $size->raw : $size->array; } $ret->options = OptionsFragment::parse($parser, $list, static::$OPTIONS); ++$list->idx; diff --git a/libraries/sql-parser/src/Fragments/FieldDefFragment.php b/libraries/sql-parser/src/Fragments/FieldDefFragment.php index fe941849a5..307968133f 100644 --- a/libraries/sql-parser/src/Fragments/FieldDefFragment.php +++ b/libraries/sql-parser/src/Fragments/FieldDefFragment.php @@ -52,9 +52,9 @@ class FieldDefFragment extends Fragment /** * The array of indexes. * - * @var array + * @var ArrayFragment */ - public $indexes = array(); + public $indexes; /** * The options of the new field fragment. @@ -64,9 +64,9 @@ class FieldDefFragment extends Fragment public $options; /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return FieldDefFragment[] */ @@ -124,7 +124,7 @@ class FieldDefFragment extends Fragment } continue; } elseif ($state === 1) { - if ($token->type === Token::TYPE_KEYWORD) { + if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { if ($token->value === 'CONSTRAINT') { $state = 4; } elseif (isset(Context::$KEY_TYPES[$token->value])) { @@ -166,11 +166,10 @@ class FieldDefFragment extends Fragment } } - $expr->tokens[] = $token; } // Last iteration was not saved. - if (!empty($expr->tokens)) { + if (!empty($expr->name)) { $ret[] = $expr; } diff --git a/libraries/sql-parser/src/Fragments/FieldFragment.php b/libraries/sql-parser/src/Fragments/FieldFragment.php index 71e1066a65..9a69a2e9d6 100644 --- a/libraries/sql-parser/src/Fragments/FieldFragment.php +++ b/libraries/sql-parser/src/Fragments/FieldFragment.php @@ -50,9 +50,9 @@ class FieldFragment extends Fragment public $alias; /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return FieldFragment */ @@ -85,7 +85,6 @@ class FieldFragment extends Fragment if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { if (($isExpr) && (!$alias)) { $ret->expr .= $token->token; - $ret->tokens[] = $token; } if (($alias === 0) && (!$isExpr) && (!$period) && (!empty($ret->expr))) { $alias = 1; @@ -93,7 +92,7 @@ class FieldFragment extends Fragment continue; } - if ($token->type === Token::TYPE_KEYWORD) { + if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { // Keywords may be found only between brackets. if ($brackets === 0) { if ($token->value === 'AS') { @@ -121,9 +120,9 @@ class FieldFragment extends Fragment } } - if (($token->type === Token::TYPE_NUMBER) || ($token->type === Token::TYPE_BOOL) || - (($token->type === Token::TYPE_SYMBOL) && ($token->flags & Token::FLAG_SYMBOL_VARIABLE)) || - (($token->type === Token::TYPE_OPERATOR)) && ($token->value !== '.')) { + if (($token->type === Token::TYPE_NUMBER) || ($token->type === Token::TYPE_BOOL) + || (($token->type === Token::TYPE_SYMBOL) && ($token->flags & Token::FLAG_SYMBOL_VARIABLE)) + || (($token->type === Token::TYPE_OPERATOR)) && ($token->value !== '.')) { // Numbers, booleans and operators are usually part of expressions. $isExpr = true; } @@ -147,15 +146,15 @@ class FieldFragment extends Fragment } } else { if ($brackets === 0) { - if (($token->type === Token::TYPE_NONE) || ($token->type === Token::TYPE_STRING) || - (($token->type === Token::TYPE_SYMBOL) && ($token->flags & Token::FLAG_SYMBOL_BACKTICK))) { + if (($token->type === Token::TYPE_NONE) || ($token->type === Token::TYPE_STRING) + || (($token->type === Token::TYPE_SYMBOL) && ($token->flags & Token::FLAG_SYMBOL_BACKTICK)) + ) { $ret->alias = $token->value; } } } $ret->expr .= $token->token; - $ret->tokens[] = $token; } } @@ -163,7 +162,7 @@ class FieldFragment extends Fragment $parser->error('Alias was expected.', $token); } - if (empty($ret->tokens)) { + if (empty($ret->expr)) { return null; } diff --git a/libraries/sql-parser/src/Fragments/FromKeyword.php b/libraries/sql-parser/src/Fragments/FromKeyword.php index fd11eea68e..c7dc624111 100644 --- a/libraries/sql-parser/src/Fragments/FromKeyword.php +++ b/libraries/sql-parser/src/Fragments/FromKeyword.php @@ -15,9 +15,9 @@ class FromKeyword extends Fragment { /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return FieldFragment[] */ @@ -42,7 +42,7 @@ class FromKeyword extends Fragment } // No keyword is expected. - if ($token->type === Token::TYPE_KEYWORD) { + if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { break; } @@ -58,7 +58,7 @@ class FromKeyword extends Fragment } // Last iteration was not saved. - if (!empty($expr->tokens)) { + if ($expr !== null) { $ret[] = $expr; } diff --git a/libraries/sql-parser/src/Fragments/IntoKeyword.php b/libraries/sql-parser/src/Fragments/IntoKeyword.php index 9f6a116eab..d56293aa9f 100644 --- a/libraries/sql-parser/src/Fragments/IntoKeyword.php +++ b/libraries/sql-parser/src/Fragments/IntoKeyword.php @@ -29,9 +29,9 @@ class IntoKeyword extends Fragment public $fields; /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return IntoKeyword */ @@ -69,7 +69,7 @@ class IntoKeyword extends Fragment } // No keyword is expected. - if ($token->type === Token::TYPE_KEYWORD) { + if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { break; } @@ -92,7 +92,6 @@ class IntoKeyword extends Fragment break; } - $ret->tokens[] = $token; if ($state === 0) { $ret->table .= $token->value; } elseif ($state === 1) { diff --git a/libraries/sql-parser/src/Fragments/JoinKeyword.php b/libraries/sql-parser/src/Fragments/JoinKeyword.php index 62f9ecd0c0..411d227372 100644 --- a/libraries/sql-parser/src/Fragments/JoinKeyword.php +++ b/libraries/sql-parser/src/Fragments/JoinKeyword.php @@ -29,9 +29,9 @@ class JoinKeyword extends Fragment public $on; /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return JoinKeyword */ diff --git a/libraries/sql-parser/src/Fragments/LimitKeyword.php b/libraries/sql-parser/src/Fragments/LimitKeyword.php index 08fb3a43ef..3e6f592c9c 100644 --- a/libraries/sql-parser/src/Fragments/LimitKeyword.php +++ b/libraries/sql-parser/src/Fragments/LimitKeyword.php @@ -29,9 +29,9 @@ class LimitKeyword extends Fragment public $row_count; /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return LimitKeyword */ @@ -55,8 +55,7 @@ class LimitKeyword extends Fragment continue; } - // NOTE: `OFFSET` is not a keyword. - if (($token->type === Token::TYPE_NONE) && ($token->value === 'OFFSET')) { + if ($token->value === 'OFFSET') { if ($offset) { $parser->error('An offset was expected.'); } @@ -76,9 +75,6 @@ class LimitKeyword extends Fragment } else { $ret->row_count = $token->value; } - - $ret->tokens[] = $token; - } if ($offset) { diff --git a/libraries/sql-parser/src/Fragments/OptionsFragment.php b/libraries/sql-parser/src/Fragments/OptionsFragment.php index 22661eb989..3317f10bd5 100644 --- a/libraries/sql-parser/src/Fragments/OptionsFragment.php +++ b/libraries/sql-parser/src/Fragments/OptionsFragment.php @@ -22,9 +22,9 @@ class OptionsFragment extends Fragment public $options = array(); /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return OptionsFragment */ @@ -55,8 +55,8 @@ class OptionsFragment extends Fragment continue; } - if (isset($options[$token->value])) { - $lastOption = $options[$token->value]; + if (isset($options[strtoupper($token->value)])) { + $lastOption = $options[strtoupper($token->value)]; $lastOptionId = is_array($lastOption) ? $lastOption[0] : $lastOption; // Checking for option conflicts. @@ -78,10 +78,9 @@ class OptionsFragment extends Fragment // The only keywords that are expected are those which are // options. - if ($token->type === Token::TYPE_KEYWORD) { + if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { break; } - } if (is_array($lastOption)) { @@ -105,8 +104,6 @@ class OptionsFragment extends Fragment $ret->options[$lastOptionId] = $token->value; $lastOption = null; } - $ret->tokens[] = $token; - } ksort($ret->options); diff --git a/libraries/sql-parser/src/Fragments/OrderKeyword.php b/libraries/sql-parser/src/Fragments/OrderKeyword.php index 5ddc8efb75..4cebc1c2bc 100644 --- a/libraries/sql-parser/src/Fragments/OrderKeyword.php +++ b/libraries/sql-parser/src/Fragments/OrderKeyword.php @@ -29,9 +29,9 @@ class OrderKeyword extends Fragment public $type = 'ASC'; /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return OrderKeyword[] */ @@ -55,11 +55,10 @@ class OrderKeyword extends Fragment continue; } - if ($token->type === Token::TYPE_KEYWORD) { + if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { // Type of ordering. By default, it is `ASC`. if (($token->value === 'ASC') || ($token->value === 'DESC')) { $expr->type = $token->value; - $expr->tokens[] = $token; continue; } @@ -74,13 +73,12 @@ class OrderKeyword extends Fragment continue; } - $expr->tokens[] = $token; $expr->column .= $token->token; } // Last iteration was not processed. - if (!empty($expr->tokens)) { + if (!empty($expr->column)) { $ret[] = $expr; } diff --git a/libraries/sql-parser/src/Fragments/ParamDefFragment.php b/libraries/sql-parser/src/Fragments/ParamDefFragment.php index b7d414d509..132898fd91 100644 --- a/libraries/sql-parser/src/Fragments/ParamDefFragment.php +++ b/libraries/sql-parser/src/Fragments/ParamDefFragment.php @@ -37,9 +37,9 @@ class ParamDefFragment extends Fragment public $type; /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return ParamDefFragment[] */ @@ -112,12 +112,10 @@ class ParamDefFragment extends Fragment break; } } - - $expr->tokens[] = $token; } // Last iteration was not saved. - if (!empty($expr->tokens)) { + if (!empty($expr->name)) { $ret[] = $expr; } diff --git a/libraries/sql-parser/src/Fragments/RenameKeyword.php b/libraries/sql-parser/src/Fragments/RenameKeyword.php index 7841b2ac77..c38dae625d 100644 --- a/libraries/sql-parser/src/Fragments/RenameKeyword.php +++ b/libraries/sql-parser/src/Fragments/RenameKeyword.php @@ -29,9 +29,9 @@ class RenameKeyword extends Fragment public $new; /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return RenameKeyword */ @@ -73,7 +73,7 @@ class RenameKeyword extends Fragment continue; } - if ($token->type === Token::TYPE_KEYWORD) { + if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { if (($state === 1) && ($token->value === 'TO')) { $state = 2; continue; @@ -95,7 +95,6 @@ class RenameKeyword extends Fragment break; } - $expr->tokens[] = $token; if ($state == 0) { $expr->old = $token->value; $state = 1; @@ -107,7 +106,7 @@ class RenameKeyword extends Fragment } // Last iteration was not saved. - if (!empty($expr->tokens)) { + if (!empty($expr->old)) { $ret[] = $expr; } diff --git a/libraries/sql-parser/src/Fragments/SelectKeyword.php b/libraries/sql-parser/src/Fragments/SelectKeyword.php index dc8db950be..8848815bd5 100644 --- a/libraries/sql-parser/src/Fragments/SelectKeyword.php +++ b/libraries/sql-parser/src/Fragments/SelectKeyword.php @@ -15,9 +15,9 @@ class SelectKeyword extends Fragment { /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return FieldFragment[] */ @@ -41,7 +41,7 @@ class SelectKeyword extends Fragment continue; } - if ($token->type === Token::TYPE_KEYWORD) { + if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { // No keyword is expected. break; } @@ -58,7 +58,7 @@ class SelectKeyword extends Fragment } // Last iteration was not processed. - if (!empty($expr->tokens)) { + if ($expr !== null) { $ret[] = $expr; } diff --git a/libraries/sql-parser/src/Fragments/SetKeyword.php b/libraries/sql-parser/src/Fragments/SetKeyword.php index 1e70f27e2d..284173eab9 100644 --- a/libraries/sql-parser/src/Fragments/SetKeyword.php +++ b/libraries/sql-parser/src/Fragments/SetKeyword.php @@ -29,9 +29,9 @@ class SetKeyword extends Fragment public $value; /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return SetKeyword[] */ @@ -70,7 +70,7 @@ class SetKeyword extends Fragment } // No keyword is expected. - if ($token->type === Token::TYPE_KEYWORD) { + if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { break; } @@ -85,17 +85,15 @@ class SetKeyword extends Fragment } } - $expr->tokens[] = $token; if ($state === 0) { $expr->column .= $token->value; } else { // } else if ($state === 1) { $expr->value = $token->value; } - } // Last iteration was not saved. - if (!empty($expr->tokens)) { + if (!empty($expr->column)) { $ret[] = $expr; } diff --git a/libraries/sql-parser/src/Fragments/ValuesKeyword.php b/libraries/sql-parser/src/Fragments/ValuesKeyword.php index c6bd551772..db8c5fd2f7 100644 --- a/libraries/sql-parser/src/Fragments/ValuesKeyword.php +++ b/libraries/sql-parser/src/Fragments/ValuesKeyword.php @@ -22,9 +22,9 @@ class ValuesKeyword extends Fragment public $values; /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return ValuesKeyword */ @@ -68,7 +68,7 @@ class ValuesKeyword extends Fragment } // No keyword is expected. - if ($token->type === Token::TYPE_KEYWORD) { + if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { break; } @@ -96,7 +96,6 @@ class ValuesKeyword extends Fragment break; } - $expr->tokens[] = $token; if ($state === 1) { $value .= $token->value; $state = 2; @@ -105,7 +104,7 @@ class ValuesKeyword extends Fragment } // Last iteration was not saved. - if (!empty($expr->tokens)) { + if (!empty($expr->values)) { $ret[] = $expr; } diff --git a/libraries/sql-parser/src/Fragments/WhereKeyword.php b/libraries/sql-parser/src/Fragments/WhereKeyword.php index 786efbfa9a..c9ce460175 100644 --- a/libraries/sql-parser/src/Fragments/WhereKeyword.php +++ b/libraries/sql-parser/src/Fragments/WhereKeyword.php @@ -36,9 +36,9 @@ class WhereKeyword extends Fragment public $condition; /** - * @param Parser $parser - * @param TokensList $list - * @param array $options + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return WhereKeyword[] */ @@ -64,14 +64,13 @@ class WhereKeyword extends Fragment // Conditions are delimited by logical operators. if (in_array($token->value, static::$OPERATORS, true)) { - if (!empty($expr->tokens)) { + if (!empty($expr->condition)) { $ret[] = $expr; } $expr = new WhereKeyword(); $expr->isOperator = true; $expr->condition = $token->value; - $epxr->tokens[] = $token; $ret[] = $expr; $expr = new WhereKeyword(); @@ -80,17 +79,16 @@ class WhereKeyword extends Fragment } // No keyword is expected. - if ($token->type === Token::TYPE_KEYWORD) { + if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { break; } - $expr->tokens[] = $token; $expr->condition .= $token->token; } // Last iteration was not processed. - if (!empty($expr->tokens)) { + if (!empty($expr->condition)) { $ret[] = $expr; } diff --git a/libraries/sql-parser/src/Lexer.php b/libraries/sql-parser/src/Lexer.php index 2b980ab692..efd926881b 100644 --- a/libraries/sql-parser/src/Lexer.php +++ b/libraries/sql-parser/src/Lexer.php @@ -26,6 +26,12 @@ class Lexer // (ascending) and their occurance rate (descending). // // Conflicts: + // + // 1. `parseDelimiter` and `parseUnknown`, `parseKeyword`, `parseNumber` + // They fight over delimiter. The delimiter may be a keyword, a number + // or almost any character which makes the delimiter one of the first + // tokens that must be parsed. + // // 1. `parseNumber` and `parseOperator` // They fight over `+` and `-`. // @@ -38,9 +44,9 @@ class Lexer // 4. `parseKeyword` and `parseUnknown` // They fight over words. `parseUnknown` does not know about keywords. - 'parseWhitespace', 'parseNumber', 'parseComment', 'parseOperator', - 'parseBool', 'parseString', 'parseSymbol', 'parseKeyword', - 'parseUnknown' + 'parseDelimiter', 'parseWhitespace', 'parseNumber', 'parseComment', + 'parseOperator', 'parseBool', 'parseString', 'parseSymbol', + 'parseKeyword', 'parseUnknown' ); /** @@ -90,6 +96,17 @@ class Lexer */ public $delimiter = ';'; + /** + * The length of the delimiter. + * + * Because `parseDelimter` can be called a lot, it would perform a lot of + * calls to `strlen`, which might affect performance when the delimiter is + * big. + * + * @var int + */ + public $delimiterLen = 1; + /** * List of errors that occured during lexing. * @@ -106,8 +123,8 @@ class Lexer /** * Constructor. * - * @param string|UtfString $str - * @param bool $strict + * @param string|UtfString $str The query to be lexed. + * @param bool $strict Whether strict mode should be enabled or not. */ public function __construct($str, $strict = false) { @@ -120,8 +137,6 @@ class Lexer /** * Parses the string and extracts lexems. - * - * @param string|UtfString $str */ public function lex() { @@ -150,14 +165,16 @@ class Lexer if ($token === null) { // @assert($this->last === $lastIdx); $token = new Token($this->str[$this->last]); - if ($this->delimiter !== $this->str[$this->last]) { - $this->error('Unexpected character.', $this->str[$this->last], $this->last); - } - } elseif (($token->type === Token::TYPE_SYMBOL) && ($token->flags & Token::FLAG_SYMBOL_VARIABLE) && - ($lastToken !== null)) { + $this->error('Unexpected character.', $this->str[$this->last], $this->last); + } elseif (($token->type === Token::TYPE_SYMBOL) + && ($token->flags & Token::FLAG_SYMBOL_VARIABLE) + && ($lastToken !== null) + ) { // Handles ```... FROM 'user'@'%' ...```. - if ((($lastToken->type === Token::TYPE_SYMBOL) && ($lastToken->flags & Token::FLAG_SYMBOL_BACKTICK)) || - ($lastToken->type === Token::TYPE_STRING)) { + if ((($lastToken->type === Token::TYPE_SYMBOL) + && ($lastToken->flags & Token::FLAG_SYMBOL_BACKTICK)) + || ($lastToken->type === Token::TYPE_STRING) + ) { $lastToken->token .= $token->token; $lastToken->type = Token::TYPE_SYMBOL; $lastToken->flags = Token::FLAG_SYMBOL_USER; @@ -170,20 +187,39 @@ class Lexer $tokens->tokens[$tokens->count++] = $token; // Handling delimiters. - if ($this->delimiter === '') { - // Updating the delimiter. - if ($token->type !== Token::TYPE_WHITESPACE) { - $this->delimiter = $token->value; + if (($token->type === Token::TYPE_NONE) && ($token->value === 'DELIMITER')) { + if ($this->last + 1 >= $this->len) { + $this->error('Expected whitespace(s) before delimiter.', '', $this->last + 1); + continue; } - } elseif ($token->value === 'DELIMITER') { - // `DELIMITER` keyword found, looking for a delimiter. - $this->delimiter = ''; - } - // Overwriting token if delimiter. - if ($token->value === $this->delimiter) { - $token->type = Token::TYPE_DELIMITER; - $token->flags = 0; + // Skipping last R (from `delimiteR`) and whitespaces between + // the keyword `DELIMITER` and the actual delimiter. + $pos = ++$this->last; + if (($token = $this->parseWhitespace()) !== null) { + $token->position = $pos; + $tokens->tokens[$tokens->count++] = $token; + } + + // Preparing the token that holds the new delimiter. + if ($this->last + 1 >= $this->len) { + $this->error('Expected delimiter.', '', $this->last + 1); + continue; + } + $pos = $this->last + 1; + + // Parsing the delimiter. + $this->delimiter = ''; + while ((++$this->last < $this->len) && (!Context::isWhitespace($this->str[$this->last]))) { + $this->delimiter .= $this->str[$this->last]; + } + --$this->last; + + // Saving the delimiter and its token. + $this->delimiterLen = strlen($this->delimiter); + $token = new Token($this->delimiter, Token::TYPE_DELIMITER); + $token->position = $pos; + $tokens->tokens[$tokens->count++] = $token; } $lastToken = $token; @@ -199,9 +235,10 @@ class Lexer /** * Creates a new error log. * - * @param string $msg - * @param string $str - * @param int $code + * @param string $msg The error message. + * @param string $ch The character that produced the error. + * @param int $pos The position of the character. + * @param int $code The code of the error. */ public function error($msg = '', $str = '', $pos = 0, $code = 0) { @@ -230,8 +267,8 @@ class Lexer for ($j = 1; $j < Context::KEYWORD_MAX_LENGTH && $this->last < $this->len; ++$j, ++$this->last) { $token .= $this->str[$this->last]; if (($this->last + 1 === $this->len) || (Context::isSeparator($this->str[$this->last + 1]))) { - if (Context::isKeyword($token)) { - $ret = new Token($token, Token::TYPE_KEYWORD); + if (($flags = Context::isKeyword($token))) { + $ret = new Token($token, Token::TYPE_KEYWORD, $flags); $iEnd = $this->last; // We don't break so we find longest keyword. // For example, `OR` and `ORDER` have a common prefix `OR`. @@ -427,8 +464,9 @@ class Lexer } elseif ($this->str[$this->last] === '-') { $flags |= Token::FLAG_NUMBER_NEGATIVE; // Do nothing. - } elseif (($this->str[$this->last] === '0') && ($this->last + 1 < $this->len) && - (($this->str[$this->last + 1] === 'x') || ($this->str[$this->last + 1] === 'X'))) { + } elseif (($this->str[$this->last] === '0') && ($this->last + 1 < $this->len) + && (($this->str[$this->last + 1] === 'x') || ($this->str[$this->last + 1] === 'X')) + ) { $token .= $this->str[$this->last++]; $state = 2; } elseif (($this->str[$this->last] >= '0') && ($this->str[$this->last] <= '9')) { @@ -440,9 +478,10 @@ class Lexer } } elseif ($state === 2) { $flags |= Token::FLAG_NUMBER_HEX; - if ((($this->str[$this->last] >= '0') && ($this->str[$this->last] <= '9')) || - (($this->str[$this->last] >= 'A') && ($this->str[$this->last] <= 'F')) || - (($this->str[$this->last] >= 'a') && ($this->str[$this->last] <= 'f'))) { + if ((($this->str[$this->last] >= '0') && ($this->str[$this->last] <= '9')) + || (($this->str[$this->last] >= 'A') && ($this->str[$this->last] <= 'F')) + || (($this->str[$this->last] >= 'a') && ($this->str[$this->last] <= 'f')) + ) { // Do nothing. } else { break; @@ -494,7 +533,7 @@ class Lexer /** * Parses a string. * - * @param string $quote Additional start symbol. + * @param string $quote Additional starting symbol. * * @return Token */ @@ -507,9 +546,10 @@ class Lexer $quote = $token; while (++$this->last < $this->len) { - if (($this->last + 1 < $this->len) && - ((($this->str[$this->last] === $quote) && ($this->str[$this->last + 1] === $quote)) || - (($this->str[$this->last] === '\\') && ($quote !== '`')))) { + if (($this->last + 1 < $this->len) + && ((($this->str[$this->last] === $quote) && ($this->str[$this->last + 1] === $quote)) + || (($this->str[$this->last] === '\\') && ($quote !== '`'))) + ) { $token .= $this->str[$this->last] . $this->str[++$this->last]; } else { if ($this->str[$this->last] === $quote) { @@ -575,4 +615,24 @@ class Lexer --$this->last; return new Token($token); } + + /** + * Parses the delimiter of the query. + * + * @return Token + */ + public function parseDelimiter() + { + $idx = 0; + + while ($idx < $this->delimiterLen) { + if ($this->delimiter[$idx] !== $this->str[$this->last + $idx]) { + return null; + } + ++$idx; + } + + $this->last += $this->delimiterLen - 1; + return new Token($this->delimiter, Token::TYPE_DELIMITER); + } } diff --git a/libraries/sql-parser/src/Parser.php b/libraries/sql-parser/src/Parser.php index 167e9125fa..059faa52af 100644 --- a/libraries/sql-parser/src/Parser.php +++ b/libraries/sql-parser/src/Parser.php @@ -119,8 +119,8 @@ class Parser /** * Constructor. * - * @param mixed $list - * @param bool $strict + * @param mixed $list The list of tokens to be parsed. + * @param bool $strict Whether strict mode should be enabled or not. */ public function __construct($list = null, $strict = false) { @@ -181,9 +181,9 @@ class Parser /** * Creates a new error log. * - * @param string $str - * @param Token $token - * @param int $code + * @param string $msg The error message. + * @param Token $token The token that produced the error. + * @param int $code The code of the error. */ public function error($str = '', Token $token = null, $code = 0) { diff --git a/libraries/sql-parser/src/Token.php b/libraries/sql-parser/src/Token.php index 9b75c02f3e..7563d77d02 100644 --- a/libraries/sql-parser/src/Token.php +++ b/libraries/sql-parser/src/Token.php @@ -109,6 +109,9 @@ class Token const TYPE_DELIMITER = 9; // Flags that describe the tokens in more detail. + const FLAG_KEYWORD_RESERVED = 1; + const FLAG_KEYWORD_UNRESERVED = 2; + const FLAG_KEYWORD_COMPOSED = 4; // Numbers related flags. const FLAG_NUMBER_HEX = 1; @@ -200,7 +203,10 @@ class Token { switch ($this->type) { case Token::TYPE_KEYWORD: - return strtoupper($this->token); + if ($this->flags & Token::FLAG_KEYWORD_RESERVED) { + return strtoupper($this->token); + } + return $this->token; case Token::TYPE_WHITESPACE: return ' '; case Token::TYPE_BOOL: diff --git a/libraries/sql-parser/src/UtfString.php b/libraries/sql-parser/src/UtfString.php index 8815e58367..0f68cfe0cc 100644 --- a/libraries/sql-parser/src/UtfString.php +++ b/libraries/sql-parser/src/UtfString.php @@ -154,7 +154,7 @@ class UtfString implements \ArrayAccess * * @return int */ - private static function getCharLength($byte) + public static function getCharLength($byte) { $byte = ord($byte); if ($byte < 128) { diff --git a/libraries/sql-parser/src/Utils/Misc.php b/libraries/sql-parser/src/Utils/Misc.php index dc8b4386c6..473bf9bf99 100644 --- a/libraries/sql-parser/src/Utils/Misc.php +++ b/libraries/sql-parser/src/Utils/Misc.php @@ -2,7 +2,7 @@ namespace SqlParser\Utils; -use SqlParser\Statement; +use SqlParser\Statements\SelectStatement; class Misc { @@ -10,12 +10,12 @@ class Misc /** * Gets a list of all aliases and their original names. * - * @param Statement $tree + * @param SelectStatement $tree The tree that was generated after parsing. * @param string $db * * @return array */ - public static function getAliases($tree, $db) + public static function getAliases(SelectStatement $tree, $db) { $retval = array(); diff --git a/libraries/sql-parser/src/Utils/Routine.php b/libraries/sql-parser/src/Utils/Routine.php index 126ed539f0..36511ca529 100644 --- a/libraries/sql-parser/src/Utils/Routine.php +++ b/libraries/sql-parser/src/Utils/Routine.php @@ -4,9 +4,9 @@ namespace SqlParser\Utils; use SqlParser\Lexer; use SqlParser\Parser; -use SqlParser\Statement; use SqlParser\Fragments\DataTypeFragment; use SqlParser\Fragments\ParamDefFragment; +use SqlParser\Statements\CreateStatement; class Routine { @@ -80,11 +80,11 @@ class Routine /** * Gets the parameters of a routine from the parse tree. * - * @param Statement $tree + * @param CreateStatement $tree The tree that was generated after parsing. * * @return array */ - public static function getParameters(Statement $tree) + public static function getParameters(CreateStatement $tree) { $retval = array( 'num' => 0, From 2c341191e6f96a444e65115b43347280cd4ff80a Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Sun, 21 Jun 2015 20:04:33 +0300 Subject: [PATCH 12/57] Make use of multiple contexts. Signed-off-by: Dan Ungureanu --- libraries/common.inc.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/common.inc.php b/libraries/common.inc.php index 282423fe59..c6dea7f02d 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -1058,6 +1058,9 @@ if (! defined('PMA_MINIMUM_COMMON')) { */ include_once './libraries/sqlparser.lib.php'; include_once './libraries/sql-parser/autoload.php'; + try { + SqlParser\Context::load((PMA_DRIZZLE ? 'Drizzle' : 'MySQL') . PMA_MYSQL_INT_VERSION); + } catch (\Exception $e) {} /** * the PMA_List_Database class From 105a1275e50091486a826ac40aaa1d7b9f4a2569 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Sun, 21 Jun 2015 22:25:04 +0300 Subject: [PATCH 13/57] Fixed failing test. Signed-off-by: Dan Ungureanu --- libraries/Util.class.php | 2 +- .../common/PMA_quoting_slashing_test.php | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/libraries/Util.class.php b/libraries/Util.class.php index 97a5e5322e..3bbdee123f 100644 --- a/libraries/Util.class.php +++ b/libraries/Util.class.php @@ -907,7 +907,7 @@ class PMA_Util } if (! $do_it) { - if (!SqlParser\Context::isKeyword($a_name)) { + if (!(SqlParser\Context::isKeyword($a_name) & SqlParser\Token::FLAG_KEYWORD_RESERVED)) { return $a_name; } } diff --git a/test/libraries/common/PMA_quoting_slashing_test.php b/test/libraries/common/PMA_quoting_slashing_test.php index 2710946b89..b5d837a9e0 100644 --- a/test/libraries/common/PMA_quoting_slashing_test.php +++ b/test/libraries/common/PMA_quoting_slashing_test.php @@ -214,13 +214,18 @@ class PMA_QuotingSlashing_Test extends PHPUnit_Framework_TestCase */ public function testBackquoteForbidenWords() { - global $PMA_SQPdata_forbidden_word; - - foreach ($PMA_SQPdata_forbidden_word as $forbidden) { - $this->assertEquals( - "`" . $forbidden . "`", - PMA_Util::backquote($forbidden, false) - ); + foreach (SqlParser\Context::$KEYWORDS as $keyword => $type) { + if ($type & SqlParser\Token::FLAG_KEYWORD_RESERVED) { + $this->assertEquals( + "`" . $keyword . "`", + PMA_Util::backquote($keyword, false) + ); + } else { + $this->assertEquals( + $keyword, + PMA_Util::backquote($keyword, false) + ); + } } } } From 47280915943c18e4ec0ceb6d79c5c1731606f352 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Sun, 21 Jun 2015 22:26:01 +0300 Subject: [PATCH 14/57] Refactored PMA_RTN_getDataFromName(). Signed-off-by: Dan Ungureanu --- libraries/rte/rte_routines.lib.php | 94 ++++--------------- .../rte/PMA_RTN_ParameterParser_test.php | 66 ------------- 2 files changed, 16 insertions(+), 144 deletions(-) delete mode 100644 test/libraries/rte/PMA_RTN_ParameterParser_test.php diff --git a/libraries/rte/rte_routines.lib.php b/libraries/rte/rte_routines.lib.php index b16926001f..342bfe29a6 100644 --- a/libraries/rte/rte_routines.lib.php +++ b/libraries/rte/rte_routines.lib.php @@ -9,6 +9,8 @@ if (! defined('PHPMYADMIN')) { exit; } +require_once 'libraries/Template.class.php'; + /** * Sets required globals * @@ -79,42 +81,6 @@ function PMA_RTN_main($type) } } // end PMA_RTN_main() -/** - * This function looks through the contents of a parsed - * SHOW CREATE [PROCEDURE | FUNCTION] query and extracts - * information about the routine's definer. - * - * @param array $parsed_query Parsed query, returned by PMA_SQP_parse() - * - * @return string The definer of a routine. - */ -function PMA_RTN_parseRoutineDefiner($parsed_query) -{ - $retval = ''; - $fetching = false; - for ($i = 0; $i < $parsed_query['len']; $i++) { - if ($parsed_query[$i]['type'] == 'alpha_reservedWord' - && $parsed_query[$i]['data'] == 'DEFINER' - ) { - $fetching = true; - } else if ($fetching == true - && $parsed_query[$i]['type'] != 'quote_backtick' - && /*overload*/mb_substr($parsed_query[$i]['type'], 0, 5) != 'punct' - ) { - break; - } else if ($fetching == true - && $parsed_query[$i]['type'] == 'quote_backtick' - ) { - $retval .= PMA_Util::unQuote( - $parsed_query[$i]['data'] - ); - } else if ($fetching == true && $parsed_query[$i]['type'] == 'punct_user') { - $retval .= $parsed_query[$i]['data']; - } - } - return $retval; -} // end PMA_RTN_parseRoutineDefiner() - /** * Handles editor requests for adding or editing an item * @@ -543,12 +509,15 @@ function PMA_RTN_getDataFromName($name, $type, $all = true) // Get required data $retval['item_name'] = $routine['SPECIFIC_NAME']; $retval['item_type'] = $routine['ROUTINE_TYPE']; + $parser = new SqlParser\Parser($GLOBALS['dbi']->getDefinition( $db, $routine['ROUTINE_TYPE'], $routine['SPECIFIC_NAME'] )); - $params = SqlParser\Utils\Routine::getParameters($parser->statements[0]); + $routineStatement = $parser->statements[0]; + + $params = SqlParser\Utils\Routine::getParameters($routineStatement); $retval['item_num_params'] = $params['num']; $retval['item_param_dir'] = $params['dir']; $retval['item_param_name'] = $params['name']; @@ -571,51 +540,20 @@ function PMA_RTN_getDataFromName($name, $type, $all = true) $retval['item_returnlength'] = ''; $retval['item_returnopts_num'] = ''; $retval['item_returnopts_text'] = ''; + if (! empty($routine['DTD_IDENTIFIER'])) { - if (/*overload*/mb_strlen($routine['DTD_IDENTIFIER']) > 63) { - // If the DTD_IDENTIFIER string from INFORMATION_SCHEMA is - // at least 64 characters, then it may actually have been - // chopped because that column is a varchar(64), so we will - // parse the output of SHOW CREATE query to get accurate - // information about the return variable. - $dtd = ''; - $fetching = false; - for ($i = 0; $i < $parsed_query['len']; $i++) { - if ($parsed_query[$i]['type'] == 'alpha_reservedWord' - && /*overload*/mb_strtoupper($parsed_query[$i]['data']) == 'RETURNS' - ) { - $fetching = true; - } else if ($fetching == true - && $parsed_query[$i]['type'] == 'alpha_reservedWord' - ) { - // We will not be looking for options such as UNSIGNED - // or ZEROFILL because there is no way that a numeric - // field's DTD_IDENTIFIER can be longer than 64 - // characters. We can safely assume that the return - // datatype is either ENUM or SET, so we only look - // for CHARSET. - $word = /*overload*/mb_strtoupper($parsed_query[$i]['data']); - if ($word == 'CHARSET' - && ($parsed_query[$i+1]['type'] == 'alpha_charset' - || $parsed_query[$i+1]['type'] == 'alpha_identifier') - ) { - $dtd .= $word . ' ' . $parsed_query[$i + 1]['data']; - } - break; - } else if ($fetching == true) { - $dtd .= $parsed_query[$i]['data'] . ' '; - } - } - $routine['DTD_IDENTIFIER'] = $dtd; + $options = array(); + foreach ($routineStatement->return->options->options as $opt) { + $options[] = is_string($opt) ? $opt : $opt['value']; } - $returnparam = SqlParser\Utils\Routine::getReturnType($routine['DTD_IDENTIFIER']); - $retval['item_returntype'] = $returnparam[2]; - $retval['item_returnlength'] = $returnparam[3]; - $retval['item_returnopts_num'] = $returnparam[4]; - $retval['item_returnopts_text'] = $returnparam[4]; + + $retval['item_returntype'] = $routineStatement->return->name; + $retval['item_returnlength'] = implode(',', $routineStatement->return->size); + $retval['item_returnopts_num'] = implode(' ', $options); + $retval['item_returnopts_text'] = implode(' ', $options); } - $retval['item_definer'] = PMA_RTN_parseRoutineDefiner($parsed_query); + $retval['item_definer'] = $routineStatement->options->has('DEFINER'); $retval['item_definition'] = $routine['ROUTINE_DEFINITION']; $retval['item_isdeterministic'] = ''; if ($routine['IS_DETERMINISTIC'] == 'YES') { diff --git a/test/libraries/rte/PMA_RTN_ParameterParser_test.php b/test/libraries/rte/PMA_RTN_ParameterParser_test.php deleted file mode 100644 index d94e6c0b96..0000000000 --- a/test/libraries/rte/PMA_RTN_ParameterParser_test.php +++ /dev/null @@ -1,66 +0,0 @@ -assertEquals( - $target, - PMA_RTN_parseRoutineDefiner(PMA_SQP_parse($source)) - ); - } - - /** - * Data provider for testParseDefiner - * - * @return array - */ - public function definerProvider() - { - return array( - array('CREATE PROCEDURE FOO() SELECT NULL', ''), - array( - 'CREATE DEFINER=`root`@`localhost` PROCEDURE FOO() SELECT NULL', - 'root@localhost' - ), - array( - 'CREATE DEFINER=`root\\`@`localhost` PROCEDURE FOO() SELECT NULL', - 'root\\@localhost' - ), - ); - } -} -?> From 8c62557b2ed6732e08372eb99d75c272b8d1b3dc Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Mon, 22 Jun 2015 03:41:38 +0300 Subject: [PATCH 15/57] Added sql-parser to PHPUnit's exclude filter for code coverage. Signed-off-by: Dan Ungureanu --- phpunit.xml.dist | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 76a94195f9..d3e2fab635 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -43,12 +43,13 @@ . - libraries/tcpdf - libraries/phpseclib + libraries/php-gettext libraries/bfShapeFiles libraries/php-gettext - libraries/php-gettext + libraries/phpseclib libraries/plugins/auth/swekey/ + libraries/sql-parser + libraries/tcpdf PMAStandard From e73c7a496737ef2d0e3dbef4d9b1bf2c91ff95d0 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Mon, 22 Jun 2015 03:42:18 +0300 Subject: [PATCH 16/57] Fixed coding style. Updated sql-parser library. Signed-off-by: Dan Ungureanu --- libraries/common.inc.php | 4 +- libraries/rte/rte_list.lib.php | 12 ++- libraries/rte/rte_routines.lib.php | 12 ++- libraries/sql-parser/autoload.php | 2 - libraries/sql-parser/composer/ClassLoader.php | 2 +- .../sql-parser/composer/autoload_psr4.php | 2 - .../sql-parser/composer/autoload_real.php | 2 - libraries/sql-parser/src/Context.php | 32 ++++--- .../src/Contexts/Context_MySQL50000.php | 9 ++ .../src/Contexts/Context_MySQL50100.php | 9 ++ .../src/Contexts/Context_MySQL50500.php | 9 ++ .../src/Contexts/Context_MySQL50600.php | 9 ++ .../src/Contexts/Context_MySQL50700.php | 9 ++ .../src/Exceptions/LexerException.php | 14 ++- .../src/Exceptions/ParserException.php | 12 ++- libraries/sql-parser/src/Fragment.php | 20 ++-- .../src/Fragments/ArrayFragment.php | 19 +++- .../sql-parser/src/Fragments/CallKeyword.php | 19 +++- .../src/Fragments/CreateDefFragment.php | 27 ++++-- .../src/Fragments/DataTypeFragment.php | 19 +++- .../src/Fragments/FieldDefFragment.php | 19 +++- .../src/Fragments/FieldFragment.php | 44 ++++++--- .../sql-parser/src/Fragments/FromKeyword.php | 19 +++- .../sql-parser/src/Fragments/IntoKeyword.php | 19 +++- .../sql-parser/src/Fragments/JoinKeyword.php | 21 +++-- .../sql-parser/src/Fragments/LimitKeyword.php | 19 +++- .../src/Fragments/OptionsFragment.php | 29 ++++-- .../sql-parser/src/Fragments/OrderKeyword.php | 19 +++- .../src/Fragments/ParamDefFragment.php | 19 +++- .../src/Fragments/RenameKeyword.php | 19 +++- .../src/Fragments/SelectKeyword.php | 19 +++- .../sql-parser/src/Fragments/SetKeyword.php | 19 +++- .../src/Fragments/ValuesKeyword.php | 19 +++- .../sql-parser/src/Fragments/WhereKeyword.php | 21 +++-- libraries/sql-parser/src/Lexer.php | 55 ++++++++--- libraries/sql-parser/src/Parser.php | 39 +++++--- libraries/sql-parser/src/Statement.php | 71 +++++++++++--- .../src/Statements/CallStatement.php | 12 +++ .../src/Statements/CreateStatement.php | 6 ++ .../src/Statements/DeleteStatement.php | 5 + .../src/Statements/InsertStatement.php | 5 + .../src/Statements/RenameStatement.php | 5 + .../src/Statements/ReplaceStatement.php | 5 + .../src/Statements/SelectStatement.php | 5 + .../src/Statements/UpdateStatement.php | 5 + libraries/sql-parser/src/Token.php | 93 ++++++++++--------- libraries/sql-parser/src/TokensList.php | 60 +++++++++--- libraries/sql-parser/src/UtfString.php | 49 ++++++---- libraries/sql-parser/src/Utils/Misc.php | 18 +++- libraries/sql-parser/src/Utils/Routine.php | 9 ++ 50 files changed, 729 insertions(+), 261 deletions(-) diff --git a/libraries/common.inc.php b/libraries/common.inc.php index c6dea7f02d..9632a0709b 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -1060,7 +1060,9 @@ if (! defined('PMA_MINIMUM_COMMON')) { include_once './libraries/sql-parser/autoload.php'; try { SqlParser\Context::load((PMA_DRIZZLE ? 'Drizzle' : 'MySQL') . PMA_MYSQL_INT_VERSION); - } catch (\Exception $e) {} + } catch (\Exception $e) { + // If this fails, it will continue using the default context. + } /** * the PMA_List_Database class diff --git a/libraries/rte/rte_list.lib.php b/libraries/rte/rte_list.lib.php index e233a61348..be509c7eb7 100644 --- a/libraries/rte/rte_list.lib.php +++ b/libraries/rte/rte_list.lib.php @@ -221,11 +221,13 @@ function PMA_RTN_getRowForList($routine, $rowclass = '') // we will show a dialog to get values for these parameters, // otherwise we can execute it directly. - $parser = new SqlParser\Parser($GLOBALS['dbi']->getDefinition( - $db, - $routine['type'], - $routine['name'] - )); + $parser = new SqlParser\Parser( + $GLOBALS['dbi']->getDefinition( + $db, + $routine['type'], + $routine['name'] + ) + ); $params = SqlParser\Utils\Routine::getParameters($parser->statements[0]); if ($routine !== false) { if (PMA_Util::currentUserHasPrivilege('EXECUTE', $db)) { diff --git a/libraries/rte/rte_routines.lib.php b/libraries/rte/rte_routines.lib.php index 342bfe29a6..73980f41c4 100644 --- a/libraries/rte/rte_routines.lib.php +++ b/libraries/rte/rte_routines.lib.php @@ -510,11 +510,13 @@ function PMA_RTN_getDataFromName($name, $type, $all = true) $retval['item_name'] = $routine['SPECIFIC_NAME']; $retval['item_type'] = $routine['ROUTINE_TYPE']; - $parser = new SqlParser\Parser($GLOBALS['dbi']->getDefinition( - $db, - $routine['ROUTINE_TYPE'], - $routine['SPECIFIC_NAME'] - )); + $parser = new SqlParser\Parser( + $GLOBALS['dbi']->getDefinition( + $db, + $routine['ROUTINE_TYPE'], + $routine['SPECIFIC_NAME'] + ) + ); $routineStatement = $parser->statements[0]; $params = SqlParser\Utils\Routine::getParameters($routineStatement); diff --git a/libraries/sql-parser/autoload.php b/libraries/sql-parser/autoload.php index a88e87984f..0e42d154fd 100644 --- a/libraries/sql-parser/autoload.php +++ b/libraries/sql-parser/autoload.php @@ -1,7 +1,5 @@ classMap) { + if (!empty($this->classMap)) { $this->classMap = array_merge($this->classMap, $classMap); } else { $this->classMap = $classMap; diff --git a/libraries/sql-parser/composer/autoload_psr4.php b/libraries/sql-parser/composer/autoload_psr4.php index 31419d5807..756ce5f0a8 100644 --- a/libraries/sql-parser/composer/autoload_psr4.php +++ b/libraries/sql-parser/composer/autoload_psr4.php @@ -1,7 +1,5 @@ + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ abstract class Context { @@ -424,10 +429,10 @@ abstract class Context /** * Checks if the given string is a keyword. * - * @param string $str - * @param bool $isReserved + * @param string $str String to be checked. + * @param bool $isReserved Checks if the keyword is reserved. * - * @return bool + * @return int */ public static function isKeyword($str, $isReserved = false) { @@ -451,7 +456,7 @@ abstract class Context /** * Checks if the given string is an operator. * - * @param string $str + * @param string $str String to be checked. * * @return int The appropriate flag for the operator. */ @@ -469,7 +474,7 @@ abstract class Context /** * Checks if the given character is a whitespace. * - * @param string $ch + * @param string $ch String to be checked. * * @return bool */ @@ -484,7 +489,7 @@ abstract class Context /** * Checks if the given string is the beginning of a whitespace. * - * @param string $str + * @param string $str String to be checked. * * @return int The appropriate flag for the comment type. */ @@ -514,7 +519,7 @@ abstract class Context * This actually check only for `TRUE` and `FALSE` because `1` or `0` are * actually numbers and are parsed by specific methods. * - * @param string $ch + * @param string $ch String to be checked. * * @return bool */ @@ -530,7 +535,7 @@ abstract class Context /** * Checks if the given character can be a part of a number. * - * @param string $ch + * @param string $ch String to be checked. * * @return bool */ @@ -547,7 +552,7 @@ abstract class Context * Checks if the given character is the beginning of a symbol. A symbol * can be either a variable or a field name. * - * @param string $ch + * @param string $ch String to be checked. * * @return int The appropriate flag for the symbol type. */ @@ -567,7 +572,7 @@ abstract class Context /** * Checks if the given character is the beginning of a string. * - * @param string $str + * @param string $str String to be checked. * * @return int The appropriate flag for the string type. */ @@ -587,7 +592,7 @@ abstract class Context /** * Checks if the given character can be a separator for two lexems. * - * @param string $ch + * @param string $ch String to be checked. * * @return bool */ @@ -601,7 +606,10 @@ abstract class Context * * Contexts may be used by accessing the context directly. * - * @param string $context + * @param string $context Name of the context or full class name that + * defines the context. + * + * @return void */ public static function load($context = '') { diff --git a/libraries/sql-parser/src/Contexts/Context_MySQL50000.php b/libraries/sql-parser/src/Contexts/Context_MySQL50000.php index e1d036ef0c..830399e719 100644 --- a/libraries/sql-parser/src/Contexts/Context_MySQL50000.php +++ b/libraries/sql-parser/src/Contexts/Context_MySQL50000.php @@ -4,6 +4,15 @@ namespace SqlParser\Contexts; use SqlParser\Context; +/** + * Context for MySQL 5.0. + * + * @category Contexts + * @package SqlParser + * @subpackage Contexts + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ class Context_MySQL50000 extends Context { diff --git a/libraries/sql-parser/src/Contexts/Context_MySQL50100.php b/libraries/sql-parser/src/Contexts/Context_MySQL50100.php index ce83a5f854..f70ecef978 100644 --- a/libraries/sql-parser/src/Contexts/Context_MySQL50100.php +++ b/libraries/sql-parser/src/Contexts/Context_MySQL50100.php @@ -4,6 +4,15 @@ namespace SqlParser\Contexts; use SqlParser\Context; +/** + * Context for MySQL 5.1. + * + * @category Contexts + * @package SqlParser + * @subpackage Contexts + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ class Context_MySQL50100 extends Context { diff --git a/libraries/sql-parser/src/Contexts/Context_MySQL50500.php b/libraries/sql-parser/src/Contexts/Context_MySQL50500.php index 8c3d570440..6febe72e3c 100644 --- a/libraries/sql-parser/src/Contexts/Context_MySQL50500.php +++ b/libraries/sql-parser/src/Contexts/Context_MySQL50500.php @@ -4,6 +4,15 @@ namespace SqlParser\Contexts; use SqlParser\Context; +/** + * Context for MySQL 5.5. + * + * @category Contexts + * @package SqlParser + * @subpackage Contexts + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ class Context_MySQL50500 extends Context { diff --git a/libraries/sql-parser/src/Contexts/Context_MySQL50600.php b/libraries/sql-parser/src/Contexts/Context_MySQL50600.php index 4f0b0d6c91..dfd114ace1 100644 --- a/libraries/sql-parser/src/Contexts/Context_MySQL50600.php +++ b/libraries/sql-parser/src/Contexts/Context_MySQL50600.php @@ -4,6 +4,15 @@ namespace SqlParser\Contexts; use SqlParser\Context; +/** + * Context for MySQL 5.6. + * + * @category Contexts + * @package SqlParser + * @subpackage Contexts + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ class Context_MySQL50600 extends Context { diff --git a/libraries/sql-parser/src/Contexts/Context_MySQL50700.php b/libraries/sql-parser/src/Contexts/Context_MySQL50700.php index 578da8982b..b795b2d6e7 100644 --- a/libraries/sql-parser/src/Contexts/Context_MySQL50700.php +++ b/libraries/sql-parser/src/Contexts/Context_MySQL50700.php @@ -4,6 +4,15 @@ namespace SqlParser\Contexts; use SqlParser\Context; +/** + * Context for MySQL 5.7. + * + * @category Contexts + * @package SqlParser + * @subpackage Contexts + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ class Context_MySQL50700 extends Context { diff --git a/libraries/sql-parser/src/Exceptions/LexerException.php b/libraries/sql-parser/src/Exceptions/LexerException.php index 306c8b924d..53327ed86f 100644 --- a/libraries/sql-parser/src/Exceptions/LexerException.php +++ b/libraries/sql-parser/src/Exceptions/LexerException.php @@ -6,6 +6,12 @@ use SqlParser\Token; /** * Exception thrown by the lexer. + * + * @category Exceptions + * @package SqlParser + * @subpackage Exceptions + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class LexerException extends \Exception { @@ -27,10 +33,10 @@ class LexerException extends \Exception /** * Constructor. * - * @param string $msg The message of this exception. - * @param string $ch The character that produced this exception. - * @param int $pos The position of the character. - * @param int $code The code of this error. + * @param string $msg The message of this exception. + * @param string $ch The character that produced this exception. + * @param int $pos The position of the character. + * @param int $code The code of this error. */ public function __construct($msg = '', $ch = '', $pos = 0, $code = 0) { diff --git a/libraries/sql-parser/src/Exceptions/ParserException.php b/libraries/sql-parser/src/Exceptions/ParserException.php index 7332674452..06a6033da2 100644 --- a/libraries/sql-parser/src/Exceptions/ParserException.php +++ b/libraries/sql-parser/src/Exceptions/ParserException.php @@ -6,6 +6,12 @@ use SqlParser\Token; /** * Exception thrown by the parser. + * + * @category Exceptions + * @package SqlParser + * @subpackage Exceptions + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class ParserException extends \Exception { @@ -20,9 +26,9 @@ class ParserException extends \Exception /** * Constructor. * - * @param string $msg The message of this exception. - * @param Token $token The token that produced this exception. - * @param int $code The code of this error. + * @param string $msg The message of this exception. + * @param Token $token The token that produced this exception. + * @param int $code The code of this error. */ public function __construct($msg = '', Token $token = null, $code = 0) { diff --git a/libraries/sql-parser/src/Fragment.php b/libraries/sql-parser/src/Fragment.php index 63af280f26..51cec95922 100644 --- a/libraries/sql-parser/src/Fragment.php +++ b/libraries/sql-parser/src/Fragment.php @@ -5,18 +5,26 @@ namespace SqlParser; /** * A fragment (of a statement) is a part of a statement that is common to * multiple query types. + * + * @category Fragments + * @package SqlParser + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ abstract class Fragment { /** - * Parses the tokens given by the lexer in the context of the given parser. + * Parses the tokens contained in the given list in the context of the given + * parser. * - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * - * @return array + * @return mixed */ - abstract public static function parse(Parser $parser, TokensList $list, array $options = array()); + abstract public static function parse(Parser $parser, TokensList $list, + array $options = array() + ); } diff --git a/libraries/sql-parser/src/Fragments/ArrayFragment.php b/libraries/sql-parser/src/Fragments/ArrayFragment.php index 6436823be0..eb5a80b8ee 100644 --- a/libraries/sql-parser/src/Fragments/ArrayFragment.php +++ b/libraries/sql-parser/src/Fragments/ArrayFragment.php @@ -3,13 +3,18 @@ namespace SqlParser\Fragments; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * Parses an array. + * + * @category Fragments + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class ArrayFragment extends Fragment { @@ -29,9 +34,9 @@ class ArrayFragment extends Fragment public $raw = array(); /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return ArrayFragment */ @@ -56,7 +61,11 @@ class ArrayFragment extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. diff --git a/libraries/sql-parser/src/Fragments/CallKeyword.php b/libraries/sql-parser/src/Fragments/CallKeyword.php index 6147cf4ab2..db11120c49 100644 --- a/libraries/sql-parser/src/Fragments/CallKeyword.php +++ b/libraries/sql-parser/src/Fragments/CallKeyword.php @@ -3,13 +3,18 @@ namespace SqlParser\Fragments; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * Parses a function call. + * + * @category Keywords + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class CallKeyword extends Fragment { @@ -29,9 +34,9 @@ class CallKeyword extends Fragment public $parameters = array(); /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return CallKeyword */ @@ -53,7 +58,11 @@ class CallKeyword extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. diff --git a/libraries/sql-parser/src/Fragments/CreateDefFragment.php b/libraries/sql-parser/src/Fragments/CreateDefFragment.php index 675ad81094..58eabaaeba 100644 --- a/libraries/sql-parser/src/Fragments/CreateDefFragment.php +++ b/libraries/sql-parser/src/Fragments/CreateDefFragment.php @@ -3,13 +3,18 @@ namespace SqlParser\Fragments; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * Parses the definition that follows the `CREATE` keyword. + * + * @category Fragments + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class CreateDefFragment extends Fragment { @@ -70,9 +75,9 @@ class CreateDefFragment extends Fragment public $name; /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return CreateDefFragment */ @@ -81,7 +86,11 @@ class CreateDefFragment extends Fragment $ret = new CreateDefFragment(); for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. @@ -90,11 +99,15 @@ class CreateDefFragment extends Fragment } // Skipping whitespaces and comments. - if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + if (($token->type === Token::TYPE_WHITESPACE) + || ($token->type === Token::TYPE_COMMENT) + ) { continue; } - if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { + if (($token->type === Token::TYPE_OPERATOR) + && ($token->value === '(') + ) { break; } diff --git a/libraries/sql-parser/src/Fragments/DataTypeFragment.php b/libraries/sql-parser/src/Fragments/DataTypeFragment.php index ca7cfafc3b..7baefddb48 100644 --- a/libraries/sql-parser/src/Fragments/DataTypeFragment.php +++ b/libraries/sql-parser/src/Fragments/DataTypeFragment.php @@ -4,13 +4,18 @@ namespace SqlParser\Fragments; use SqlParser\Context; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * Parses a data type. + * + * @category Fragments + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class DataTypeFragment extends Fragment { @@ -46,9 +51,9 @@ class DataTypeFragment extends Fragment public $options = array(); /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return DataTypeFragment[] */ @@ -70,7 +75,11 @@ class DataTypeFragment extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // Skipping whitespaces and comments. diff --git a/libraries/sql-parser/src/Fragments/FieldDefFragment.php b/libraries/sql-parser/src/Fragments/FieldDefFragment.php index 307968133f..ba4b6dcd16 100644 --- a/libraries/sql-parser/src/Fragments/FieldDefFragment.php +++ b/libraries/sql-parser/src/Fragments/FieldDefFragment.php @@ -4,7 +4,6 @@ namespace SqlParser\Fragments; use SqlParser\Context; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; @@ -13,6 +12,12 @@ use SqlParser\TokensList; * Parses the definition of a field. * * Used for parsing `CREATE TABLE` statement. + * + * @category Fragments + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class FieldDefFragment extends Fragment { @@ -64,9 +69,9 @@ class FieldDefFragment extends Fragment public $options; /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return FieldDefFragment[] */ @@ -105,7 +110,11 @@ class FieldDefFragment extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. diff --git a/libraries/sql-parser/src/Fragments/FieldFragment.php b/libraries/sql-parser/src/Fragments/FieldFragment.php index 9a69a2e9d6..4adbba5a73 100644 --- a/libraries/sql-parser/src/Fragments/FieldFragment.php +++ b/libraries/sql-parser/src/Fragments/FieldFragment.php @@ -3,13 +3,18 @@ namespace SqlParser\Fragments; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * Parses a reference to a field. + * + * @category Fragments + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class FieldFragment extends Fragment { @@ -50,9 +55,9 @@ class FieldFragment extends Fragment public $alias; /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return FieldFragment */ @@ -60,20 +65,36 @@ class FieldFragment extends Fragment { $ret = new FieldFragment(); - /** @var bool Whether current tokens make an expression or a table reference. */ + /** + * Whether current tokens make an expression or a table reference. + * @var bool + */ $isExpr = false; - /** @var bool Whether a period was previously found. */ + /** + * Whether a period was previously found. + * @var bool + */ $period = false; - /** @var int Whether an alias is expected. Is 2 if `AS` keyword was found. */ + /** + * Whether an alias is expected. Is 2 if `AS` keyword was found. + * @var int + */ $alias = 0; - /** @var int Counts brackets. */ + /** + * Counts brackets. + * @var int + */ $brackets = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. @@ -122,7 +143,8 @@ class FieldFragment extends Fragment if (($token->type === Token::TYPE_NUMBER) || ($token->type === Token::TYPE_BOOL) || (($token->type === Token::TYPE_SYMBOL) && ($token->flags & Token::FLAG_SYMBOL_VARIABLE)) - || (($token->type === Token::TYPE_OPERATOR)) && ($token->value !== '.')) { + || (($token->type === Token::TYPE_OPERATOR)) && ($token->value !== '.') + ) { // Numbers, booleans and operators are usually part of expressions. $isExpr = true; } @@ -159,7 +181,7 @@ class FieldFragment extends Fragment } if ($alias === 2) { - $parser->error('Alias was expected.', $token); + $parser->error('Alias was expected.'); } if (empty($ret->expr)) { diff --git a/libraries/sql-parser/src/Fragments/FromKeyword.php b/libraries/sql-parser/src/Fragments/FromKeyword.php index c7dc624111..aea9c3edc1 100644 --- a/libraries/sql-parser/src/Fragments/FromKeyword.php +++ b/libraries/sql-parser/src/Fragments/FromKeyword.php @@ -3,21 +3,26 @@ namespace SqlParser\Fragments; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * `FROM` keyword parser. + * + * @category Keywords + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class FromKeyword extends Fragment { /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return FieldFragment[] */ @@ -28,7 +33,11 @@ class FromKeyword extends Fragment $expr = new FieldFragment(); for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. diff --git a/libraries/sql-parser/src/Fragments/IntoKeyword.php b/libraries/sql-parser/src/Fragments/IntoKeyword.php index d56293aa9f..c4211fd47d 100644 --- a/libraries/sql-parser/src/Fragments/IntoKeyword.php +++ b/libraries/sql-parser/src/Fragments/IntoKeyword.php @@ -3,13 +3,18 @@ namespace SqlParser\Fragments; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * `INTO` keyword parser. + * + * @category Keywords + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class IntoKeyword extends Fragment { @@ -29,9 +34,9 @@ class IntoKeyword extends Fragment public $fields; /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return IntoKeyword */ @@ -55,7 +60,11 @@ class IntoKeyword extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. diff --git a/libraries/sql-parser/src/Fragments/JoinKeyword.php b/libraries/sql-parser/src/Fragments/JoinKeyword.php index 411d227372..b6b2c224e5 100644 --- a/libraries/sql-parser/src/Fragments/JoinKeyword.php +++ b/libraries/sql-parser/src/Fragments/JoinKeyword.php @@ -3,13 +3,18 @@ namespace SqlParser\Fragments; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * `JOIN` keyword parser. + * + * @category Keywords + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class JoinKeyword extends Fragment { @@ -24,14 +29,14 @@ class JoinKeyword extends Fragment /** * Join conditions. * - * @var WhereKeyword + * @var WhereKeyword[] */ public $on; /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return JoinKeyword */ @@ -55,7 +60,11 @@ class JoinKeyword extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. diff --git a/libraries/sql-parser/src/Fragments/LimitKeyword.php b/libraries/sql-parser/src/Fragments/LimitKeyword.php index 3e6f592c9c..2e5b8193e5 100644 --- a/libraries/sql-parser/src/Fragments/LimitKeyword.php +++ b/libraries/sql-parser/src/Fragments/LimitKeyword.php @@ -3,13 +3,18 @@ namespace SqlParser\Fragments; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * `lIMIT` keyword parser. + * + * @category Keywords + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class LimitKeyword extends Fragment { @@ -29,9 +34,9 @@ class LimitKeyword extends Fragment public $row_count; /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return LimitKeyword */ @@ -42,7 +47,11 @@ class LimitKeyword extends Fragment $offset = false; for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. diff --git a/libraries/sql-parser/src/Fragments/OptionsFragment.php b/libraries/sql-parser/src/Fragments/OptionsFragment.php index 3317f10bd5..f002f5bd32 100644 --- a/libraries/sql-parser/src/Fragments/OptionsFragment.php +++ b/libraries/sql-parser/src/Fragments/OptionsFragment.php @@ -3,13 +3,18 @@ namespace SqlParser\Fragments; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * Parses a list of options. + * + * @category Fragments + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class OptionsFragment extends Fragment { @@ -22,9 +27,9 @@ class OptionsFragment extends Fragment public $options = array(); /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return OptionsFragment */ @@ -32,17 +37,27 @@ class OptionsFragment extends Fragment { $ret = new OptionsFragment(); - /** @var int The ID that will be assigned to duplicate options. */ + /** + * The ID that will be assigned to duplicate options. + * @var int + */ $lastAssignedId = count($options) + 1; - /** @var array The option that was processed last time. */ + /** + * The option that was processed last time. + * @var array + */ $lastOption = null; $lastOptionId = 0; $brackets = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. diff --git a/libraries/sql-parser/src/Fragments/OrderKeyword.php b/libraries/sql-parser/src/Fragments/OrderKeyword.php index 4cebc1c2bc..224a573263 100644 --- a/libraries/sql-parser/src/Fragments/OrderKeyword.php +++ b/libraries/sql-parser/src/Fragments/OrderKeyword.php @@ -3,13 +3,18 @@ namespace SqlParser\Fragments; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * `ORDER BY` keyword parser. + * + * @category Keywords + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class OrderKeyword extends Fragment { @@ -29,9 +34,9 @@ class OrderKeyword extends Fragment public $type = 'ASC'; /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return OrderKeyword[] */ @@ -42,7 +47,11 @@ class OrderKeyword extends Fragment $expr = new OrderKeyword(); for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. diff --git a/libraries/sql-parser/src/Fragments/ParamDefFragment.php b/libraries/sql-parser/src/Fragments/ParamDefFragment.php index 132898fd91..4756120651 100644 --- a/libraries/sql-parser/src/Fragments/ParamDefFragment.php +++ b/libraries/sql-parser/src/Fragments/ParamDefFragment.php @@ -4,13 +4,18 @@ namespace SqlParser\Fragments; use SqlParser\Context; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * The definition of a parameter of a function or procedure. + * + * @category Fragments + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class ParamDefFragment extends Fragment { @@ -37,9 +42,9 @@ class ParamDefFragment extends Fragment public $type; /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return ParamDefFragment[] */ @@ -69,7 +74,11 @@ class ParamDefFragment extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. diff --git a/libraries/sql-parser/src/Fragments/RenameKeyword.php b/libraries/sql-parser/src/Fragments/RenameKeyword.php index c38dae625d..9e9969c5f1 100644 --- a/libraries/sql-parser/src/Fragments/RenameKeyword.php +++ b/libraries/sql-parser/src/Fragments/RenameKeyword.php @@ -3,13 +3,18 @@ namespace SqlParser\Fragments; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * `RENAME TABLE` keyword parser. + * + * @category Keywords + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class RenameKeyword extends Fragment { @@ -29,9 +34,9 @@ class RenameKeyword extends Fragment public $new; /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return RenameKeyword */ @@ -60,7 +65,11 @@ class RenameKeyword extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. diff --git a/libraries/sql-parser/src/Fragments/SelectKeyword.php b/libraries/sql-parser/src/Fragments/SelectKeyword.php index 8848815bd5..fc59aa0261 100644 --- a/libraries/sql-parser/src/Fragments/SelectKeyword.php +++ b/libraries/sql-parser/src/Fragments/SelectKeyword.php @@ -3,21 +3,26 @@ namespace SqlParser\Fragments; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * `SELECT` keyword parser. + * + * @category Keywords + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class SelectKeyword extends Fragment { /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return FieldFragment[] */ @@ -28,7 +33,11 @@ class SelectKeyword extends Fragment $expr = null; for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. diff --git a/libraries/sql-parser/src/Fragments/SetKeyword.php b/libraries/sql-parser/src/Fragments/SetKeyword.php index 284173eab9..82f9965ba1 100644 --- a/libraries/sql-parser/src/Fragments/SetKeyword.php +++ b/libraries/sql-parser/src/Fragments/SetKeyword.php @@ -3,13 +3,18 @@ namespace SqlParser\Fragments; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * `SET` keyword parser. + * + * @category Keywords + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class SetKeyword extends Fragment { @@ -29,9 +34,9 @@ class SetKeyword extends Fragment public $value; /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return SetKeyword[] */ @@ -56,7 +61,11 @@ class SetKeyword extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. diff --git a/libraries/sql-parser/src/Fragments/ValuesKeyword.php b/libraries/sql-parser/src/Fragments/ValuesKeyword.php index db8c5fd2f7..cb470dd6d9 100644 --- a/libraries/sql-parser/src/Fragments/ValuesKeyword.php +++ b/libraries/sql-parser/src/Fragments/ValuesKeyword.php @@ -3,13 +3,18 @@ namespace SqlParser\Fragments; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * `VALUES` keyword parser. + * + * @category Keywords + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class ValuesKeyword extends Fragment { @@ -22,9 +27,9 @@ class ValuesKeyword extends Fragment public $values; /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return ValuesKeyword */ @@ -54,7 +59,11 @@ class ValuesKeyword extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. diff --git a/libraries/sql-parser/src/Fragments/WhereKeyword.php b/libraries/sql-parser/src/Fragments/WhereKeyword.php index c9ce460175..0bc60a7dd9 100644 --- a/libraries/sql-parser/src/Fragments/WhereKeyword.php +++ b/libraries/sql-parser/src/Fragments/WhereKeyword.php @@ -3,13 +3,18 @@ namespace SqlParser\Fragments; use SqlParser\Fragment; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Token; use SqlParser\TokensList; /** * `WHERE` keyword parser. + * + * @category Keywords + * @package SqlParser + * @subpackage Fragments + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class WhereKeyword extends Fragment { @@ -19,7 +24,7 @@ class WhereKeyword extends Fragment * * @var array */ - private static $OPERATORS = array('&&', '(', ')', 'AND', 'OR', 'XOR', '||'); + public static $OPERATORS = array('&&', '(', ')', 'AND', 'OR', 'XOR', '||'); /** * Whether this fragment is an operator. @@ -36,9 +41,9 @@ class WhereKeyword extends Fragment public $condition; /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. * * @return WhereKeyword[] */ @@ -49,7 +54,11 @@ class WhereKeyword extends Fragment $expr = new WhereKeyword(); for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. diff --git a/libraries/sql-parser/src/Lexer.php b/libraries/sql-parser/src/Lexer.php index efd926881b..33e7337937 100644 --- a/libraries/sql-parser/src/Lexer.php +++ b/libraries/sql-parser/src/Lexer.php @@ -10,7 +10,11 @@ use SqlParser\Exceptions\LexerException; * * The output of the lexer is affected by the context of the SQL statement. * - * @see Context + * @category Lexer + * @package SqlParser + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + * @see Context */ class Lexer { @@ -123,8 +127,8 @@ class Lexer /** * Constructor. * - * @param string|UtfString $str The query to be lexed. - * @param bool $strict Whether strict mode should be enabled or not. + * @param string|UtfString $str The query to be lexed. + * @param bool $strict Whether strict mode should be enabled or not. */ public function __construct($str, $strict = false) { @@ -137,6 +141,8 @@ class Lexer /** * Parses the string and extracts lexems. + * + * @return void */ public function lex() { @@ -153,7 +159,11 @@ class Lexer $lastToken = null; for ($this->last = 0, $lastIdx = 0; $this->last < $this->len; $lastIdx = ++$this->last) { - /** @var Token The new token. */ + + /** + * The new token. + * @var Token + */ $token = null; foreach (static::$PARSER_METHODS as $method) { @@ -235,10 +245,12 @@ class Lexer /** * Creates a new error log. * - * @param string $msg The error message. - * @param string $ch The character that produced the error. - * @param int $pos The position of the character. - * @param int $code The code of the error. + * @param string $msg The error message. + * @param string $str The character that produced the error. + * @param int $pos The position of the character. + * @param int $code The code of the error. + * + * @return void */ public function error($msg = '', $str = '', $pos = 0, $code = 0) { @@ -258,10 +270,16 @@ class Lexer { $token = ''; - /** @var Token Value to be returned. */ + /** + * Value to be returned. + * @var Token + */ $ret = null; - /** @var int The value of `$this->last` where `$token` ends in `$this->str`. */ + /** + * The value of `$this->last` where `$token` ends in `$this->str`. + * @var int + */ $iEnd = $this->last; for ($j = 1; $j < Context::KEYWORD_MAX_LENGTH && $this->last < $this->len; ++$j, ++$this->last) { @@ -290,10 +308,16 @@ class Lexer { $token = ''; - /** @var Token|bool Value to be returned. */ - $ret = false; + /** + * Value to be returned. + * @var Token|bool + */ + $ret = null; - /** @var int The value of `$this->last` where `$token` ends in `$this->str`. */ + /** + * The value of `$this->last` where `$token` ends in `$this->str`. + * @var int + */ $iEnd = $this->last; for ($j = 1; $j < Context::OPERATOR_MAX_LENGTH && $this->last < $this->len; ++$j, ++$this->last) { @@ -507,8 +531,9 @@ class Lexer } } elseif ($state === 5) { $flags |= Token::FLAG_NUMBER_APPROXIMATE; - if (($this->str[$this->last] === '+') || ($this->str[$this->last] === '-') || - ((($this->str[$this->last] >= '0') && ($this->str[$this->last] <= '9')))) { + if (($this->str[$this->last] === '+') || ($this->str[$this->last] === '-') + || ((($this->str[$this->last] >= '0') && ($this->str[$this->last] <= '9'))) + ) { $state = 6; } else { break; diff --git a/libraries/sql-parser/src/Parser.php b/libraries/sql-parser/src/Parser.php index 059faa52af..2973a03686 100644 --- a/libraries/sql-parser/src/Parser.php +++ b/libraries/sql-parser/src/Parser.php @@ -7,6 +7,11 @@ use SqlParser\Exceptions\ParserException; /** * Takes multiple tokens (contained in a Lexer instance) as input and builds a * parse tree. + * + * @category Parser + * @package SqlParser + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class Parser { @@ -119,8 +124,8 @@ class Parser /** * Constructor. * - * @param mixed $list The list of tokens to be parsed. - * @param bool $strict Whether strict mode should be enabled or not. + * @param mixed $list The list of tokens to be parsed. + * @param bool $strict Whether strict mode should be enabled or not. */ public function __construct($list = null, $strict = false) { @@ -140,6 +145,8 @@ class Parser /** * Builds the parse trees. + * + * @return void */ public function parse() { @@ -148,7 +155,11 @@ class Parser $last = &$this->list->idx; for (; $last < $count; ++$last) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $tokens[$last]; // Statements can start with keywords only. @@ -160,17 +171,23 @@ class Parser // Checking if it is a known statement that can be parsed. if (empty(static::$STATEMENT_PARSERS[$token->value])) { $this->error( - 'Unrecognized statement type "' . $token->value .'".', + 'Unrecognized statement type "' . $token->value . '".', $token ); // TODO: Skip to first delimiter. continue; } - /** @var string The name of the class that is used for parsing. */ + /** + * The name of the class that is used for parsing. + * @var string + */ $class = static::$STATEMENT_PARSERS[$token->value]; - /** @var Statement Processed statement. */ + /** + * Processed statement. + * @var Statement + */ $stmt = new $class(); $stmt->parse($this, $this->list); @@ -181,13 +198,13 @@ class Parser /** * Creates a new error log. * - * @param string $msg The error message. - * @param Token $token The token that produced the error. - * @param int $code The code of the error. + * @param string $msg The error message. + * @param Token $token The token that produced the error. + * @param int $code The code of the error. */ - public function error($str = '', Token $token = null, $code = 0) + public function error($msg = '', Token $token = null, $code = 0) { - $error = new ParserException($str, $token, $code); + $error = new ParserException($msg, $token, $code); if ($this->strict) { throw $error; } diff --git a/libraries/sql-parser/src/Statement.php b/libraries/sql-parser/src/Statement.php index b1dc2c1064..13002f4d72 100644 --- a/libraries/sql-parser/src/Statement.php +++ b/libraries/sql-parser/src/Statement.php @@ -2,11 +2,9 @@ namespace SqlParser; -use SqlParser\Lexer; use SqlParser\Parser; use SqlParser\Statement; use SqlParser\Token; - use SqlParser\Fragments\CallKeyword; use SqlParser\Fragments\CreateDefFragment; use SqlParser\Fragments\DataTypeFragment; @@ -17,6 +15,14 @@ use SqlParser\Fragments\ParamDefFragment; use SqlParser\Fragments\RenameKeyword; use SqlParser\Fragments\SelectKeyword; +/** + * Abstract statement definition. + * + * @category Statements + * @package SqlParser + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ abstract class Statement { @@ -37,13 +43,19 @@ abstract class Statement /** * Parses the statements defined by the tokens list. * - * @param Parser $parser - * @param TokensList $list + * @param Parser $parser The instance that requests parsing. + * @param TokensList $list The list of tokens to be parsed. + * + * @return void */ public function parse(Parser $parser, TokensList $list) { for (; $list->idx < $list->count; ++$list->idx) { - /** @var Token Token parsed at this moment. */ + + /** + * Token parsed at this moment. + * @var Token + */ $token = $list->tokens[$list->idx]; // End of statement. @@ -57,7 +69,10 @@ abstract class Statement continue; } - /** @var string The name of the class that is used for parsing. */ + /** + * The name of the class that is used for parsing. + * @var string + */ $class = null; if (!empty(Parser::$KEYWORD_PARSERS[$token->value])) { @@ -73,13 +88,19 @@ abstract class Statement continue; } - /** @var string The name of the field where the result is stored. */ + /** + * The name of the field where the result is stored. + * @var string + */ $field = strtolower($token->value); // Parsing options. if (($class == null) && (isset(static::$OPTIONS))) { ++$list->idx; // Skipping keyword. - $this->options = OptionsFragment::parse($parser, $list, static::$OPTIONS); + $this->options = OptionsFragment::parse( + $parser, $list, + static::$OPTIONS + ); } // Keyword specific code. @@ -93,33 +114,53 @@ abstract class Statement ++$list->idx; $this->fields = FieldDefFragment::parse($parser, $list); ++$list->idx; - $this->tableOptions = OptionsFragment::parse($parser, $list, CreateDefFragment::$TABLE_OPTIONS); - } elseif (($this->options->has('PROCEDURE')) || ($this->options->has('FUNCTION'))) { + $this->tableOptions = OptionsFragment::parse( + $parser, + $list, + CreateDefFragment::$TABLE_OPTIONS + ); + } elseif (($this->options->has('PROCEDURE')) + || ($this->options->has('FUNCTION')) + ) { ++$list->idx; $this->parameters = ParamDefFragment::parse($parser, $list); if ($this->options->has('FUNCTION')) { $token = $list->getNextOfType(Token::TYPE_KEYWORD); if ($token->value !== 'RETURNS') { - $parser->error('\'RETURNS\' keyword was expected.', $token); + $parser->error( + '\'RETURNS\' keyword was expected.', + $token + ); } else { ++$list->idx; - $this->return = DataTypeFragment::parse($parser, $list); + $this->return = DataTypeFragment::parse( + $parser, + $list + ); } } ++$list->idx; - $this->funcOptions = OptionsFragment::parse($parser, $list, CreateDefFragment::$FUNC_OPTIONS); + $this->funcOptions = OptionsFragment::parse( + $parser, + $list, + CreateDefFragment::$FUNC_OPTIONS + ); ++$list->idx; $this->body = array(); for (; $list->idx < $list->count; ++$list->idx) { $token = $list->tokens[$list->idx]; $this->body[] = $token; - if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'END')) { + if (($token->type === Token::TYPE_KEYWORD) + && ($token->value === 'END') + ) { break; } } $class = null; // The statement has been processed here. } - } elseif (($token->value === 'GROUP') || ($token->value === 'ORDER')) { + } elseif (($token->value === 'GROUP') + || ($token->value === 'ORDER') + ) { $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'BY'); } elseif ($token->value === 'RENAME') { $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'TABLE'); diff --git a/libraries/sql-parser/src/Statements/CallStatement.php b/libraries/sql-parser/src/Statements/CallStatement.php index 76681b52c8..162f50eafa 100644 --- a/libraries/sql-parser/src/Statements/CallStatement.php +++ b/libraries/sql-parser/src/Statements/CallStatement.php @@ -6,6 +6,18 @@ use SqlParser\Statement; /** * `CALL` statement. + * + * CALL sp_name([parameter[,...]]) + * + * or + * + * CALL sp_name[()] + * + * @category Statements + * @package SqlParser + * @subpackage Statements + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class CallStatement extends Statement { diff --git a/libraries/sql-parser/src/Statements/CreateStatement.php b/libraries/sql-parser/src/Statements/CreateStatement.php index 00561f54c0..7a248e9032 100644 --- a/libraries/sql-parser/src/Statements/CreateStatement.php +++ b/libraries/sql-parser/src/Statements/CreateStatement.php @@ -6,6 +6,12 @@ use SqlParser\Statement; /** * `CREATE` statement. + * + * @category Statements + * @package SqlParser + * @subpackage Statements + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class CreateStatement extends Statement { diff --git a/libraries/sql-parser/src/Statements/DeleteStatement.php b/libraries/sql-parser/src/Statements/DeleteStatement.php index 01dd8adc2f..0e88fedefb 100644 --- a/libraries/sql-parser/src/Statements/DeleteStatement.php +++ b/libraries/sql-parser/src/Statements/DeleteStatement.php @@ -13,6 +13,11 @@ use SqlParser\Statement; * [ORDER BY ...] * [LIMIT row_count] * + * @category Statements + * @package SqlParser + * @subpackage Statements + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class DeleteStatement extends Statement { diff --git a/libraries/sql-parser/src/Statements/InsertStatement.php b/libraries/sql-parser/src/Statements/InsertStatement.php index f24634ac33..db88b42beb 100644 --- a/libraries/sql-parser/src/Statements/InsertStatement.php +++ b/libraries/sql-parser/src/Statements/InsertStatement.php @@ -37,6 +37,11 @@ use SqlParser\Statement; * col_name=expr * [, col_name=expr] ... ] * + * @category Statements + * @package SqlParser + * @subpackage Statements + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class InsertStatement extends Statement { diff --git a/libraries/sql-parser/src/Statements/RenameStatement.php b/libraries/sql-parser/src/Statements/RenameStatement.php index bd3c767d53..88607ea713 100644 --- a/libraries/sql-parser/src/Statements/RenameStatement.php +++ b/libraries/sql-parser/src/Statements/RenameStatement.php @@ -10,6 +10,11 @@ use SqlParser\Statement; * RENAME TABLE tbl_name TO new_tbl_name * [, tbl_name2 TO new_tbl_name2] ... * + * @category Statements + * @package SqlParser + * @subpackage Statements + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class RenameStatement extends Statement { diff --git a/libraries/sql-parser/src/Statements/ReplaceStatement.php b/libraries/sql-parser/src/Statements/ReplaceStatement.php index 8e69207bdf..577f72c4fd 100644 --- a/libraries/sql-parser/src/Statements/ReplaceStatement.php +++ b/libraries/sql-parser/src/Statements/ReplaceStatement.php @@ -17,6 +17,11 @@ use SqlParser\Statement; * [INTO] tbl_name * SET col_name={expr | DEFAULT}, ... * + * @category Statements + * @package SqlParser + * @subpackage Statements + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class ReplaceStatement extends Statement { diff --git a/libraries/sql-parser/src/Statements/SelectStatement.php b/libraries/sql-parser/src/Statements/SelectStatement.php index d17450eb04..50ce28148d 100644 --- a/libraries/sql-parser/src/Statements/SelectStatement.php +++ b/libraries/sql-parser/src/Statements/SelectStatement.php @@ -32,6 +32,11 @@ use SqlParser\Statement; * | INTO var_name [, var_name]] * [FOR UPDATE | LOCK IN SHARE MODE]] * + * @category Statements + * @package SqlParser + * @subpackage Statements + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class SelectStatement extends Statement { diff --git a/libraries/sql-parser/src/Statements/UpdateStatement.php b/libraries/sql-parser/src/Statements/UpdateStatement.php index cdeab0367f..8dcc6f090c 100644 --- a/libraries/sql-parser/src/Statements/UpdateStatement.php +++ b/libraries/sql-parser/src/Statements/UpdateStatement.php @@ -19,6 +19,11 @@ use SqlParser\Statement; * SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ... * [WHERE where_condition] * + * @category Statements + * @package SqlParser + * @subpackage Statements + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class UpdateStatement extends Statement { diff --git a/libraries/sql-parser/src/Token.php b/libraries/sql-parser/src/Token.php index 7563d77d02..5a378ca0e4 100644 --- a/libraries/sql-parser/src/Token.php +++ b/libraries/sql-parser/src/Token.php @@ -5,6 +5,11 @@ namespace SqlParser; /** * A structure representing a lexeme that explicitly indicates its * categorization for the purpose of parsing. + * + * @category Tokens + * @package SqlParser + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class Token { @@ -179,10 +184,9 @@ class Token /** * Constructor. * - * @param string $token - * @param int $type - * @param int $flags - * @param int $position + * @param string $token The value of the token. + * @param int $type The type of the token. + * @param int $flags The flags of the token. */ public function __construct($token, $type = 0, $flags = 0) { @@ -202,47 +206,50 @@ class Token public function extract() { switch ($this->type) { - case Token::TYPE_KEYWORD: - if ($this->flags & Token::FLAG_KEYWORD_RESERVED) { - return strtoupper($this->token); - } - return $this->token; - case Token::TYPE_WHITESPACE: - return ' '; - case Token::TYPE_BOOL: - return strtoupper($this->token) === 'TRUE'; - case Token::TYPE_NUMBER: - $ret = str_replace('--', '', $this->token); // e.g. ---42 === -42 - if ($this->flags & Token::FLAG_NUMBER_HEX) { - if ($this->flags & Token::FLAG_NUMBER_NEGATIVE) { - $ret = str_replace('-', '', $this->token); - sscanf($ret, "%x", $ret); - $ret = -$ret; - } else { - sscanf($ret, "%x", $ret); - } - } elseif (($this->flags & Token::FLAG_NUMBER_APPROXIMATE) || - ($this->flags & Token::FLAG_NUMBER_FLOAT)) { - sscanf($ret, "%f", $ret); + case Token::TYPE_KEYWORD: + if ($this->flags & Token::FLAG_KEYWORD_RESERVED) { + return strtoupper($this->token); + } + return $this->token; + case Token::TYPE_WHITESPACE: + return ' '; + case Token::TYPE_BOOL: + return strtoupper($this->token) === 'TRUE'; + case Token::TYPE_NUMBER: + $ret = str_replace('--', '', $this->token); // e.g. ---42 === -42 + if ($this->flags & Token::FLAG_NUMBER_HEX) { + if ($this->flags & Token::FLAG_NUMBER_NEGATIVE) { + $ret = str_replace('-', '', $this->token); + sscanf($ret, "%x", $ret); + $ret = -$ret; } else { - sscanf($ret, "%d", $ret); + sscanf($ret, "%x", $ret); } - return $ret; - case Token::TYPE_STRING: - $quote = $this->token[0]; - $str = str_replace($quote . $quote, $quote, $this->token); - return mb_substr($str, 1, -1); // trims quotes - case Token::TYPE_SYMBOL: - $str = $this->token; - if ((isset($str[0])) && ($str[0] === '@')) { - $str = mb_substr($str, 1); - } - if ((isset($str[0])) && (($str[0] === '`') || ($str[0] === '"') || ($str[0] === '\''))) { - $quote = $str[0]; - $str = str_replace($quote . $quote, $quote, $str); - $str = mb_substr($str, 1, -1); - } - return $str; + } elseif (($this->flags & Token::FLAG_NUMBER_APPROXIMATE) + || ($this->flags & Token::FLAG_NUMBER_FLOAT) + ) { + sscanf($ret, "%f", $ret); + } else { + sscanf($ret, "%d", $ret); + } + return $ret; + case Token::TYPE_STRING: + $quote = $this->token[0]; + $str = str_replace($quote . $quote, $quote, $this->token); + return mb_substr($str, 1, -1); // trims quotes + case Token::TYPE_SYMBOL: + $str = $this->token; + if ((isset($str[0])) && ($str[0] === '@')) { + $str = mb_substr($str, 1); + } + if ((isset($str[0])) && (($str[0] === '`') + || ($str[0] === '"') || ($str[0] === '\'')) + ) { + $quote = $str[0]; + $str = str_replace($quote . $quote, $quote, $str); + $str = mb_substr($str, 1, -1); + } + return $str; } return $this->token; } diff --git a/libraries/sql-parser/src/TokensList.php b/libraries/sql-parser/src/TokensList.php index 405f4a121b..533fb0b3ab 100644 --- a/libraries/sql-parser/src/TokensList.php +++ b/libraries/sql-parser/src/TokensList.php @@ -2,6 +2,14 @@ namespace SqlParser; +/** + * A structure representing a list of tokens. + * + * @category Tokens + * @package SqlParser + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ class TokensList implements \ArrayAccess { @@ -29,7 +37,9 @@ class TokensList implements \ArrayAccess /** * Adds a new token. * - * @param Token $token + * @param Token $token Token to be added in list. + * + * @return void */ public function add(Token $token) { @@ -37,7 +47,7 @@ class TokensList implements \ArrayAccess } /** - * Gets next token in list. + * Gets the next token. * * @return Token */ @@ -50,9 +60,9 @@ class TokensList implements \ArrayAccess } /** - * Gets next token of a specified type. + * Gets the next token. * - * @param int $type + * @param int $type The type. * * @return Token */ @@ -67,26 +77,33 @@ class TokensList implements \ArrayAccess } /** - * Gets next token of a specified type. + * Gets the next token. * - * @param int $type - * @param string $value + * @param int $type The type of the token. + * @param string $value The value of the token. * * @return Token */ public function getNextOfTypeAndValue($type, $value) { for (; $this->idx < $this->count; ++$this->idx) { - if (($this->tokens[$this->idx]->type === $type) && - ($this->tokens[$this->idx]->value === $value)) { + if (($this->tokens[$this->idx]->type === $type) + && ($this->tokens[$this->idx]->value === $value) + ) { return $this->tokens[$this->idx++]; } } return null; } - // ArrayAccess methods. - + /** + * Sets an value inside the container. + * + * @param int $offset The offset to be set. + * @param Token $value The token to be saved. + * + * @return void + */ public function offsetSet($offset, $value) { if ($offset === null) { @@ -96,16 +113,37 @@ class TokensList implements \ArrayAccess } } + /** + * Gets a value from the container. + * + * @param int $offset The offset to be returned. + * + * @return Token + */ public function offsetGet($offset) { return $offset < $this->count ? $this->tokens[$offset] : null; } + /** + * Checks if an offset was previously set. + * + * @param int $offset The offset to be checked. + * + * @return bool + */ public function offsetExists($offset) { return $offset < $this->count; } + /** + * Unsets the value of an offset. + * + * @param int $offset The offset to be unset. + * + * @return void + */ public function offsetUnset($offset) { unset($this->tokens[$offset]); diff --git a/libraries/sql-parser/src/UtfString.php b/libraries/sql-parser/src/UtfString.php index 0f68cfe0cc..e98ee3f05f 100644 --- a/libraries/sql-parser/src/UtfString.php +++ b/libraries/sql-parser/src/UtfString.php @@ -6,6 +6,11 @@ namespace SqlParser; * Implements array-like access for UTF-8 strings. * * In this library, this class should be used to parse UTF-8 queries. + * + * @category Misc + * @package SqlParser + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ class UtfString implements \ArrayAccess { @@ -15,7 +20,7 @@ class UtfString implements \ArrayAccess * * @var string */ - private $str = ''; + public $str = ''; /** * The index of current byte. @@ -24,7 +29,7 @@ class UtfString implements \ArrayAccess * * @var int */ - private $byteIdx = 0; + public $byteIdx = 0; /** * The index of current character. @@ -34,26 +39,26 @@ class UtfString implements \ArrayAccess * * @var int */ - private $charIdx = 0; + public $charIdx = 0; /** * The length of the string (in bytes). * * @var int */ - private $buffLen = 0; + public $byteLen = 0; /** * The length of the string (in characters). * * @var int */ - private $charLen = 0; + public $charLen = 0; /** * Constructor. * - * @param string $str + * @param string $str The string. */ public function __construct($str) { @@ -70,19 +75,19 @@ class UtfString implements \ArrayAccess /** * Checks if the given offset exists. * - * @param int $offset + * @param int $offset The offset to be checked. * * @return bool */ public function offsetExists($offset) { - return $offset < $charLen; + return $offset < $this->charLen; } /** * Gets the character at given offset. * - * @param int $offset + * @param int $offset The offset to be returned. * * @return string */ @@ -123,8 +128,10 @@ class UtfString implements \ArrayAccess /** * Sets the value of a character. * - * @param int $offset - * @param string $value + * @param int $offset The offset to be set. + * @param string $value The value to be set. + * + * @return void */ public function offsetSet($offset, $value) { @@ -134,7 +141,9 @@ class UtfString implements \ArrayAccess /** * Unsets an index. * - * @param int $offset + * @param int $offset The value to be unset. + * + * @return void */ public function offsetUnset($offset) { @@ -148,9 +157,9 @@ class UtfString implements \ArrayAccess * However, this implemenation supports UTF-8 characters containing up to 6 * bytes. * - * @see http://tools.ietf.org/html/rfc3629 + * @param string $byte The byte to be analyzed. * - * @param string $byte + * @see http://tools.ietf.org/html/rfc3629 * * @return int */ @@ -197,8 +206,10 @@ class UtfString implements \ArrayAccess /** * Gets the values of the indexes. * - * @param int &$byte - * @param int &$char + * @param int &$byte Reference to the byte index. + * @param int &$char Reference to the character index. + * + * @return void */ public function getIndexes(&$byte, &$char) { @@ -209,8 +220,10 @@ class UtfString implements \ArrayAccess /** * Sets the values of the indexes. * - * @param int $byte - * @param int $char + * @param int $byte The byte index. + * @param int $char The character index. + * + * @return void */ public function setIndexes($byte = 0, $char = 0) { diff --git a/libraries/sql-parser/src/Utils/Misc.php b/libraries/sql-parser/src/Utils/Misc.php index 473bf9bf99..a29951e6e8 100644 --- a/libraries/sql-parser/src/Utils/Misc.php +++ b/libraries/sql-parser/src/Utils/Misc.php @@ -4,6 +4,15 @@ namespace SqlParser\Utils; use SqlParser\Statements\SelectStatement; +/** + * Miscellaneous utilities. + * + * @category Misc + * @package SqlParser + * @subpackage Utils + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ class Misc { @@ -11,7 +20,7 @@ class Misc * Gets a list of all aliases and their original names. * * @param SelectStatement $tree The tree that was generated after parsing. - * @param string $db + * @param string $db The name of the database. * * @return array */ @@ -21,7 +30,9 @@ class Misc $tables = array(); - if ((!empty($tree->join->expr->table)) && (!empty($tree->join->expr->alias))) { + if ((!empty($tree->join->expr->table)) + && (!empty($tree->join->expr->alias)) + ) { $thisDb = empty($tree->join->expr->database) ? $db : $tree->join->expr->database; @@ -81,7 +92,8 @@ class Misc } else { $thisTable = isset($tables[$thisDb][$expr->table]) ? $tables[$thisDb][$expr->table] : $expr->table; - $retval[$thisDb]['tables'][$thisTable]['columns'][$expr->column] = $expr->alias; + $retval[$thisDb]['tables'] + [$thisTable]['columns'][$expr->column] = $expr->alias; } } diff --git a/libraries/sql-parser/src/Utils/Routine.php b/libraries/sql-parser/src/Utils/Routine.php index 36511ca529..f234d97b55 100644 --- a/libraries/sql-parser/src/Utils/Routine.php +++ b/libraries/sql-parser/src/Utils/Routine.php @@ -8,6 +8,15 @@ use SqlParser\Fragments\DataTypeFragment; use SqlParser\Fragments\ParamDefFragment; use SqlParser\Statements\CreateStatement; +/** + * Routine utilities. + * + * @category Routines + * @package SqlParser + * @subpackage Utils + * @author Dan Ungureanu + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ class Routine { From ffbbf21ef674002eb81c2321a7f7c32d1ef7233a Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Mon, 22 Jun 2015 15:24:50 +0300 Subject: [PATCH 17/57] Removed dead code. Signed-off-by: Dan Ungureanu --- libraries/Table.class.php | 49 --------------------------------- test/classes/PMA_Table_test.php | 31 --------------------- 2 files changed, 80 deletions(-) diff --git a/libraries/Table.class.php b/libraries/Table.class.php index d1ec487863..f6eff4c8bb 100644 --- a/libraries/Table.class.php +++ b/libraries/Table.class.php @@ -247,55 +247,6 @@ class PMA_Table return $result ? true : false; } - /** - * Returns the analysis of 'SHOW CREATE TABLE' query for the table. - * In case of a view, the values are taken from the information_schema. - * - * @param string $db database - * @param string $table table - * - * @return array analysis of 'SHOW CREATE TABLE' query for the table - */ - static public function analyzeStructure($db = null, $table = null) - { - if (empty($db) || empty($table)) { - return false; - } - - $analyzed_sql = array(); - if (self::isView($db, $table)) { - // For a view, 'SHOW CREATE TABLE' returns the definition, - // but the structure of the view. So, we try to mock - // the result of analyzing 'SHOW CREATE TABLE' query. - $analyzed_sql[0] = array(); - $analyzed_sql[0]['create_table_fields'] = array(); - - $results = $GLOBALS['dbi']->fetchResult( - "SELECT COLUMN_NAME, DATA_TYPE - FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = '" . PMA_Util::sqlAddSlashes($db) . "' - AND TABLE_NAME = '" . PMA_Util::sqlAddSlashes($table) . "'" - ); - - foreach ($results as $result) { - $analyzed_sql[0]['create_table_fields'][$result['COLUMN_NAME']] - = array( - 'type' => /*overload*/mb_strtoupper($result['DATA_TYPE']) - ); - } - } else { - $show_create_table = $GLOBALS['dbi']->fetchValue( - 'SHOW CREATE TABLE ' - . PMA_Util::backquote($db) - . '.' . PMA_Util::backquote($table), - 0, - 1 - ); - $analyzed_sql = PMA_SQP_analyze(PMA_SQP_parse($show_create_table)); - } - return $analyzed_sql; - } - /** * sets given $value for given $param * diff --git a/test/classes/PMA_Table_test.php b/test/classes/PMA_Table_test.php index 4005ba508e..1bd637638c 100644 --- a/test/classes/PMA_Table_test.php +++ b/test/classes/PMA_Table_test.php @@ -607,37 +607,6 @@ class PMA_Table_Test extends PHPUnit_Framework_TestCase ); } - /** - * Test for analyzeStructure - * - * @return void - */ - public function testAnalyzeStructure() - { - $this->assertEquals( - false, - PMA_Table::analyzeStructure() - ); - - //validate that it is the same as DBI fetchResult - $show_create_table = PMA_Table::analyzeStructure('PMA', 'PMA_BookMark'); - $this->assertEquals( - array('type'=>'DATA_TYPE'), - $show_create_table[0]['create_table_fields']['COLUMN_NAME'] - ); - //not a view - $show_create_table = PMA_Table::analyzeStructure('PMA', 'PMA_BookMark_2'); - $this->assertEquals( - array('type'=>'INT', 'timestamp_not_null'=>false), - $show_create_table[0]['create_table_fields']['id'] - ); - $this->assertEquals( - array('type'=>'TEXT', 'timestamp_not_null'=>false), - $show_create_table[0]['create_table_fields']['username'] - ); - - } - /** * Test for isMerge * From 83c6f77716d423fc1a22a6c0ca58886d131b3c35 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Mon, 22 Jun 2015 22:09:11 +0300 Subject: [PATCH 18/57] Updated sql-parser library. Signed-off-by: Dan Ungureanu --- libraries/common.inc.php | 2 +- libraries/sql-parser/src/Context.php | 279 +++--------------- .../src/Contexts/ContextMySql50000.php | 178 +++++++++++ .../src/Contexts/ContextMySql50100.php | 192 ++++++++++++ .../src/Contexts/ContextMySql50500.php | 195 ++++++++++++ .../src/Contexts/ContextMySql50600.php | 206 +++++++++++++ .../src/Contexts/ContextMySql50700.php | 211 +++++++++++++ .../src/Fragments/DataTypeFragment.php | 4 +- .../src/Fragments/FieldDefFragment.php | 35 ++- .../src/Fragments/OptionsFragment.php | 40 ++- libraries/sql-parser/src/Token.php | 15 +- libraries/sql-parser/src/Utils/Misc.php | 12 +- libraries/sql-parser/src/Utils/Routine.php | 2 + libraries/sql-parser/src/Utils/Table.php | 69 +++++ 14 files changed, 1145 insertions(+), 295 deletions(-) create mode 100644 libraries/sql-parser/src/Contexts/ContextMySql50000.php create mode 100644 libraries/sql-parser/src/Contexts/ContextMySql50100.php create mode 100644 libraries/sql-parser/src/Contexts/ContextMySql50500.php create mode 100644 libraries/sql-parser/src/Contexts/ContextMySql50600.php create mode 100644 libraries/sql-parser/src/Contexts/ContextMySql50700.php create mode 100644 libraries/sql-parser/src/Utils/Table.php diff --git a/libraries/common.inc.php b/libraries/common.inc.php index 9632a0709b..c71ada952f 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -1059,7 +1059,7 @@ if (! defined('PMA_MINIMUM_COMMON')) { include_once './libraries/sqlparser.lib.php'; include_once './libraries/sql-parser/autoload.php'; try { - SqlParser\Context::load((PMA_DRIZZLE ? 'Drizzle' : 'MySQL') . PMA_MYSQL_INT_VERSION); + SqlParser\Context::load((PMA_DRIZZLE ? 'Drizzle' : 'MySql') . PMA_MYSQL_INT_VERSION); } catch (\Exception $e) { // If this fails, it will continue using the default context. } diff --git a/libraries/sql-parser/src/Context.php b/libraries/sql-parser/src/Context.php index e46a0478cc..eed10d3687 100644 --- a/libraries/sql-parser/src/Context.php +++ b/libraries/sql-parser/src/Context.php @@ -3,7 +3,7 @@ namespace SqlParser; /** - * Default MySQL context (based on MySQL 5.7). + * Default MySQL context. * * @category Contexts * @package SqlParser @@ -36,14 +36,22 @@ abstract class Context * * @var string */ - public static $defaultContext = '\\SqlParser\\Contexts\\Context_MySQL50700'; + public static $defaultContext = '\\SqlParser\\Contexts\\ContextMySql50700'; /** * The name of the loaded context. * * @var string */ - public static $loadedContext = '\\SqlParser\\Contexts\\Context_MySQL50700'; + public static $loadedContext = '\\SqlParser\\Contexts\\ContextMySql50700'; + + /** + * The prefix concatenated to the context name when an incomplete class name + * is specified. + * + * @var string + */ + public static $contextPrefix = '\\SqlParser\\Contexts\\Context'; // ------------------------------------------------------------------------- // Keywords. @@ -64,225 +72,7 @@ abstract class Context * * @var array */ - public static $KEYWORDS = array( - 'AS' => 1, 'BY' => 1, 'IF' => 1, 'IN' => 1, 'IS' => 1, - 'ON' => 1, 'OR' => 1, 'TO' => 1, - 'ADD' => 1, 'ALL' => 1, 'AND' => 1, 'ASC' => 1, 'DEC' => 1, - 'DIV' => 1, 'FOR' => 1, 'GET' => 1, 'INT' => 1, 'KEY' => 1, - 'MOD' => 1, 'NOT' => 1, 'OUT' => 1, 'SET' => 1, 'SQL' => 1, - 'SSL' => 1, 'USE' => 1, 'XOR' => 1, - 'BLOB' => 1, 'BOTH' => 1, 'CALL' => 1, 'CASE' => 1, - 'CHAR' => 1, 'DESC' => 1, 'DROP' => 1, 'DUAL' => 1, - 'EACH' => 1, 'ELSE' => 1, 'EXIT' => 1, 'FROM' => 1, - 'INT1' => 1, 'INT2' => 1, 'INT3' => 1, 'INT4' => 1, - 'INT8' => 1, 'INTO' => 1, 'JOIN' => 1, 'KEYS' => 1, - 'KILL' => 1, 'LEFT' => 1, 'LIKE' => 1, 'LOAD' => 1, - 'LOCK' => 1, 'LONG' => 1, 'LOOP' => 1, 'NULL' => 1, - 'READ' => 1, 'REAL' => 1, 'SHOW' => 1, 'THEN' => 1, - 'TRUE' => 1, 'UNDO' => 1, 'WHEN' => 1, 'WITH' => 1, - 'ALTER' => 1, 'CHECK' => 1, 'CROSS' => 1, 'FALSE' => 1, - 'FETCH' => 1, 'FLOAT' => 1, 'FORCE' => 1, 'GRANT' => 1, - 'GROUP' => 1, 'INDEX' => 1, 'INNER' => 1, 'INOUT' => 1, - 'LEAVE' => 1, 'LIMIT' => 1, 'LINES' => 1, 'MATCH' => 1, - 'ORDER' => 1, 'OUTER' => 1, 'PURGE' => 1, 'RANGE' => 1, - 'READS' => 1, 'RIGHT' => 1, 'RLIKE' => 1, 'TABLE' => 1, - 'UNION' => 1, 'USAGE' => 1, 'USING' => 1, 'WHERE' => 1, - 'WHILE' => 1, 'WRITE' => 1, - 'BEFORE' => 1, 'BIGINT' => 1, 'BINARY' => 1, 'CHANGE' => 1, - 'COLUMN' => 1, 'CREATE' => 1, 'CURSOR' => 1, 'DELETE' => 1, - 'DOUBLE' => 1, 'ELSEIF' => 1, 'EXISTS' => 1, 'FLOAT4' => 1, - 'FLOAT8' => 1, 'HAVING' => 1, 'IGNORE' => 1, 'INFILE' => 1, - 'INSERT' => 1, 'LINEAR' => 1, 'OPTION' => 1, 'REGEXP' => 1, - 'RENAME' => 1, 'REPEAT' => 1, 'RETURN' => 1, 'REVOKE' => 1, - 'SCHEMA' => 1, 'SELECT' => 1, 'SIGNAL' => 1, 'STORED' => 1, - 'UNIQUE' => 1, 'UNLOCK' => 1, 'UPDATE' => 1, 'VALUES' => 1, - 'ANALYZE' => 1, 'BETWEEN' => 1, 'CASCADE' => 1, 'COLLATE' => 1, - 'CONVERT' => 1, 'DECIMAL' => 1, 'DECLARE' => 1, 'DEFAULT' => 1, - 'DELAYED' => 1, 'ESCAPED' => 1, 'EXPLAIN' => 1, 'FOREIGN' => 1, - 'INTEGER' => 1, 'ITERATE' => 1, 'LEADING' => 1, 'NATURAL' => 1, - 'NUMERIC' => 1, 'OUTFILE' => 1, 'PRIMARY' => 1, 'RELEASE' => 1, - 'REPLACE' => 1, 'REQUIRE' => 1, 'SCHEMAS' => 1, 'SPATIAL' => 1, - 'TINYINT' => 1, 'TRIGGER' => 1, 'VARCHAR' => 1, 'VARYING' => 1, - 'VIRTUAL' => 1, - 'CONTINUE' => 1, 'DATABASE' => 1, 'DAY_HOUR' => 1, - 'DESCRIBE' => 1, 'DISTINCT' => 1, 'ENCLOSED' => 1, - 'FULLTEXT' => 1, 'INTERVAL' => 1, 'LONGBLOB' => 1, - 'LONGTEXT' => 1, 'MAXVALUE' => 1, 'MODIFIES' => 1, - 'OPTIMIZE' => 1, 'RESIGNAL' => 1, 'RESTRICT' => 1, - 'SMALLINT' => 1, 'SPECIFIC' => 1, 'SQLSTATE' => 1, - 'STARTING' => 1, 'TINYBLOB' => 1, 'TINYTEXT' => 1, - 'TRAILING' => 1, 'UNSIGNED' => 1, 'UTC_DATE' => 1, - 'UTC_TIME' => 1, 'ZEROFILL' => 1, - 'CHARACTER' => 1, 'CONDITION' => 1, 'DATABASES' => 1, - 'GENERATED' => 1, 'LOCALTIME' => 1, 'MEDIUMINT' => 1, - 'MIDDLEINT' => 1, 'PARTITION' => 1, 'PRECISION' => 1, - 'PROCEDURE' => 1, 'SENSITIVE' => 1, 'SEPARATOR' => 1, - 'VARBINARY' => 1, - 'ACCESSIBLE' => 1, 'ASENSITIVE' => 1, 'CONSTRAINT' => 1, - 'DAY_MINUTE' => 1, 'DAY_SECOND' => 1, 'MEDIUMBLOB' => 1, - 'MEDIUMTEXT' => 1, 'OPTIONALLY' => 1, 'READ_WRITE' => 1, - 'REFERENCES' => 1, 'SQLWARNING' => 1, 'TERMINATED' => 1, - 'YEAR_MONTH' => 1, - 'DISTINCTROW' => 1, 'HOUR_MINUTE' => 1, 'HOUR_SECOND' => 1, - 'INSENSITIVE' => 1, 'MASTER_BIND' => 1, - 'CURRENT_DATE' => 1, 'CURRENT_TIME' => 1, 'CURRENT_USER' => 1, - 'LOW_PRIORITY' => 1, 'SQLEXCEPTION' => 1, 'VARCHARACTER' => 1, - 'DETERMINISTIC' => 1, 'HIGH_PRIORITY' => 1, 'MINUTE_SECOND' => 1, - 'STRAIGHT_JOIN' => 1, 'UTC_TIMESTAMP' => 1, - 'IO_AFTER_GTIDS' => 1, 'LOCALTIMESTAMP' => 1, 'SQL_BIG_RESULT' => 1, - 'DAY_MICROSECOND' => 1, 'IO_BEFORE_GTIDS' => 1, 'OPTIMIZER_COSTS' => 1, - 'HOUR_MICROSECOND' => 1, 'SQL_SMALL_RESULT' => 1, - 'CURRENT_TIMESTAMP' => 1, - 'MINUTE_MICROSECOND' => 1, 'NO_WRITE_TO_BINLOG' => 1, - 'SECOND_MICROSECOND' => 1, - 'SQL_CALC_FOUND_ROWS' => 1, - 'MASTER_SSL_VERIFY_SERVER_CERT' => 1, - - 'AT' => 2, 'DO' => 2, 'IO' => 2, 'NO' => 2, 'XA' => 2, - 'ANY' => 2, 'AVG' => 2, 'BIT' => 2, 'CPU' => 2, 'DAY' => 2, 'END' => 2, - 'IPC' => 2, 'NDB' => 2, 'NEW' => 2, 'ONE' => 2, 'ROW' => 2, 'XID' => 2, - 'XML' => 2, - 'BOOL' => 2, 'BYTE' => 2, 'CODE' => 2, 'CUBE' => 2, 'DATA' => 2, 'DATE' => 2, - 'DISK' => 2, 'ENDS' => 2, 'ENUM' => 2, 'FAST' => 2, 'FILE' => 2, 'FULL' => 2, - 'HASH' => 2, 'HELP' => 2, 'HOST' => 2, 'HOUR' => 2, 'LAST' => 2, 'LESS' => 2, - 'LIST' => 2, 'LOGS' => 2, 'MODE' => 2, 'NAME' => 2, 'NEXT' => 2, 'NONE' => 2, - 'ONLY' => 2, 'OPEN' => 2, 'PAGE' => 2, 'PORT' => 2, 'PREV' => 2, 'ROWS' => 2, - 'SLOW' => 2, 'SOME' => 2, 'STOP' => 2, 'TEXT' => 2, 'THAN' => 2, 'TIME' => 2, - 'TYPE' => 2, 'USER' => 2, 'VIEW' => 2, 'WAIT' => 2, 'WEEK' => 2, 'WORK' => 2, - 'X509' => 2, 'YEAR' => 2, - 'AFTER' => 2, 'ASCII' => 2, 'BEGIN' => 2, 'BLOCK' => 2, 'BTREE' => 2, - 'CACHE' => 2, 'CHAIN' => 2, 'CLOSE' => 2, 'ERROR' => 2, 'EVENT' => 2, - 'EVERY' => 2, 'FIRST' => 2, 'FIXED' => 2, 'FLUSH' => 2, 'FOUND' => 2, - 'HOSTS' => 2, 'LEVEL' => 2, 'LOCAL' => 2, 'LOCKS' => 2, 'MERGE' => 2, - 'MONTH' => 2, 'MUTEX' => 2, 'NAMES' => 2, 'NCHAR' => 2, 'NEVER' => 2, - 'OWNER' => 2, 'PHASE' => 2, 'POINT' => 2, 'PROXY' => 2, 'QUERY' => 2, - 'QUICK' => 2, 'RELAY' => 2, 'RESET' => 2, 'RTREE' => 2, 'SHARE' => 2, - 'SLAVE' => 2, 'START' => 2, 'SUPER' => 2, 'SWAPS' => 2, 'TYPES' => 2, - 'UNTIL' => 2, 'VALUE' => 2, - 'ACTION' => 2, 'ALWAYS' => 2, 'BACKUP' => 2, 'BINLOG' => 2, 'CIPHER' => 2, - 'CLIENT' => 2, 'COMMIT' => 2, 'ENABLE' => 2, 'ENGINE' => 2, 'ERRORS' => 2, - 'ESCAPE' => 2, 'EVENTS' => 2, 'EXPIRE' => 2, 'EXPORT' => 2, 'FAULTS' => 2, - 'FIELDS' => 2, 'FILTER' => 2, 'FORMAT' => 2, 'GLOBAL' => 2, 'GRANTS' => 2, - 'IMPORT' => 2, 'ISSUER' => 2, 'LEAVES' => 2, 'MASTER' => 2, 'MEDIUM' => 2, - 'MEMORY' => 2, 'MINUTE' => 2, 'MODIFY' => 2, 'NUMBER' => 2, 'OFFSET' => 2, - 'PARSER' => 2, 'PLUGIN' => 2, 'RELOAD' => 2, 'REMOVE' => 2, 'REPAIR' => 2, - 'RESUME' => 2, 'ROLLUP' => 2, 'SECOND' => 2, 'SERIAL' => 2, 'SERVER' => 2, - 'SIGNED' => 2, 'SIMPLE' => 2, 'SOCKET' => 2, 'SONAME' => 2, 'SOUNDS' => 2, - 'SOURCE' => 2, 'STARTS' => 2, 'STATUS' => 2, 'STRING' => 2, 'TABLES' => 2, - 'ACCOUNT' => 2, 'AGAINST' => 2, 'ANALYSE' => 2, 'BOOLEAN' => 2, 'CHANGED' => 2, - 'CHANNEL' => 2, 'CHARSET' => 2, 'COLUMNS' => 2, 'COMMENT' => 2, 'COMPACT' => 2, - 'CONTEXT' => 2, 'CURRENT' => 2, 'DEFINER' => 2, 'DISABLE' => 2, 'DISCARD' => 2, - 'DYNAMIC' => 2, 'ENGINES' => 2, 'EXECUTE' => 2, 'FOLLOWS' => 2, 'GENERAL' => 2, - 'HANDLER' => 2, 'INDEXES' => 2, 'INSTALL' => 2, 'INVOKER' => 2, 'LOGFILE' => 2, - 'MIGRATE' => 2, 'NO_WAIT' => 2, 'OPTIONS' => 2, 'PARTIAL' => 2, 'PLUGINS' => 2, - 'POLYGON' => 2, 'PREPARE' => 2, 'PROFILE' => 2, 'QUARTER' => 2, 'REBUILD' => 2, - 'RECOVER' => 2, 'RESTORE' => 2, 'RETURNS' => 2, 'REVERSE' => 2, 'ROUTINE' => 2, - 'SESSION' => 2, 'STACKED' => 2, 'STORAGE' => 2, 'SUBJECT' => 2, 'SUSPEND' => 2, - 'UNICODE' => 2, 'UNKNOWN' => 2, 'UPGRADE' => 2, 'USE_FRM' => 2, 'WITHOUT' => 2, - 'WRAPPER' => 2, - 'CASCADED' => 2, 'CHECKSUM' => 2, 'COALESCE' => 2, 'CONTAINS' => 2, - 'DATAFILE' => 2, 'DATETIME' => 2, 'DUMPFILE' => 2, 'EXCHANGE' => 2, - 'EXTENDED' => 2, 'FUNCTION' => 2, 'GEOMETRY' => 2, 'LANGUAGE' => 2, - 'MAX_ROWS' => 2, 'MAX_SIZE' => 2, 'MIN_ROWS' => 2, 'NATIONAL' => 2, - 'NVARCHAR' => 2, 'PASSWORD' => 2, 'PRECEDES' => 2, 'PRESERVE' => 2, - 'PROFILES' => 2, 'REDOFILE' => 2, 'RELAYLOG' => 2, 'ROLLBACK' => 2, - 'SCHEDULE' => 2, 'SECURITY' => 2, 'SHUTDOWN' => 2, 'SNAPSHOT' => 2, - 'SWITCHES' => 2, 'TRIGGERS' => 2, 'TRUNCATE' => 2, 'UNDOFILE' => 2, - 'WARNINGS' => 2, - 'AGGREGATE' => 2, 'ALGORITHM' => 2, 'COLLATION' => 2, 'COMMITTED' => 2, - 'DIRECTORY' => 2, 'DUPLICATE' => 2, 'EXPANSION' => 2, 'IO_THREAD' => 2, - 'ISOLATION' => 2, 'NODEGROUP' => 2, 'PACK_KEYS' => 2, 'READ_ONLY' => 2, - 'REDUNDANT' => 2, 'ROW_COUNT' => 2, 'SAVEPOINT' => 2, 'SQL_CACHE' => 2, - 'TEMPORARY' => 2, 'TEMPTABLE' => 2, 'TIMESTAMP' => 2, 'UNDEFINED' => 2, - 'UNINSTALL' => 2, 'VARIABLES' => 2, - 'COMPLETION' => 2, 'COMPRESSED' => 2, 'CONCURRENT' => 2, 'CONNECTION' => 2, - 'CONSISTENT' => 2, 'DEALLOCATE' => 2, 'GET_FORMAT' => 2, 'IDENTIFIED' => 2, - 'LINESTRING' => 2, 'MASTER_SSL' => 2, 'MULTIPOINT' => 2, 'NDBCLUSTER' => 2, - 'PARTITIONS' => 2, 'PLUGIN_DIR' => 2, 'PRIVILEGES' => 2, 'REORGANIZE' => 2, - 'REPEATABLE' => 2, 'ROW_FORMAT' => 2, 'SQL_THREAD' => 2, 'TABLESPACE' => 2, - 'TABLE_NAME' => 2, 'VALIDATION' => 2, - 'COLUMN_NAME' => 2, 'COMPRESSION' => 2, 'CURSOR_NAME' => 2, 'DIAGNOSTICS' => 2, - 'EXTENT_SIZE' => 2, 'MASTER_HOST' => 2, 'MASTER_PORT' => 2, 'MASTER_USER' => 2, - 'MICROSECOND' => 2, 'MYSQL_ERRNO' => 2, 'NONBLOCKING' => 2, 'PROCESSLIST' => 2, - 'REPLICATION' => 2, 'SCHEMA_NAME' => 2, 'SQL_TSI_DAY' => 2, 'TRANSACTION' => 2, - 'UNCOMMITTED' => 2, - 'CATALOG_NAME' => 2, 'CLASS_ORIGIN' => 2, 'DEFAULT_AUTH' => 2, - 'DES_KEY_FILE' => 2, 'INITIAL_SIZE' => 2, 'MASTER_DELAY' => 2, - 'MESSAGE_TEXT' => 2, 'MULTIPOLYGON' => 2, 'OLD_PASSWORD' => 2, - 'PARTITIONING' => 2, 'RELAY_THREAD' => 2, 'SERIALIZABLE' => 2, - 'SQL_NO_CACHE' => 2, 'SQL_TSI_HOUR' => 2, 'SQL_TSI_WEEK' => 2, - 'SQL_TSI_YEAR' => 2, 'SUBPARTITION' => 2, 'TIMESTAMPADD' => 2, - 'COLUMN_FORMAT' => 2, 'INSERT_METHOD' => 2, 'MASTER_SSL_CA' => 2, - 'RELAY_LOG_POS' => 2, 'SQL_TSI_MONTH' => 2, 'SUBPARTITIONS' => 2, - 'TIMESTAMPDIFF' => 2, 'WEIGHT_STRING' => 2, - 'AUTO_INCREMENT' => 2, 'AVG_ROW_LENGTH' => 2, 'KEY_BLOCK_SIZE' => 2, - 'MASTER_LOG_POS' => 2, 'MASTER_SSL_CRL' => 2, 'MASTER_SSL_KEY' => 2, - 'RELAY_LOG_FILE' => 2, 'SQL_TSI_MINUTE' => 2, 'SQL_TSI_SECOND' => 2, - 'TABLE_CHECKSUM' => 2, 'USER_RESOURCES' => 2, - 'AUTOEXTEND_SIZE' => 2, 'CONSTRAINT_NAME' => 2, 'DELAY_KEY_WRITE' => 2, - 'FILE_BLOCK_SIZE' => 2, 'MASTER_LOG_FILE' => 2, 'MASTER_PASSWORD' => 2, - 'MASTER_SSL_CERT' => 2, 'MULTILINESTRING' => 2, 'PARSE_GCOL_EXPR' => 2, - 'REPLICATE_DO_DB' => 2, 'SQL_AFTER_GTIDS' => 2, 'SQL_TSI_QUARTER' => 2, - 'SUBCLASS_ORIGIN' => 2, - 'MASTER_SERVER_ID' => 2, 'REDO_BUFFER_SIZE' => 2, 'SQL_BEFORE_GTIDS' => 2, - 'STATS_PERSISTENT' => 2, 'UNDO_BUFFER_SIZE' => 2, - 'CONSTRAINT_SCHEMA' => 2, 'GROUP_REPLICATION' => 2, 'IGNORE_SERVER_IDS' => 2, - 'MASTER_SSL_CAPATH' => 2, 'MASTER_SSL_CIPHER' => 2, 'RETURNED_SQLSTATE' => 2, - 'SQL_BUFFER_RESULT' => 2, 'STATS_AUTO_RECALC' => 2, - 'CONSTRAINT_CATALOG' => 2, 'GEOMETRYCOLLECTION' => 2, 'MASTER_RETRY_COUNT' => 2, - 'MASTER_SSL_CRLPATH' => 2, 'MAX_STATEMENT_TIME' => 2, 'REPLICATE_DO_TABLE' => 2, - 'SQL_AFTER_MTS_GAPS' => 2, 'STATS_SAMPLE_PAGES' => 2, - 'REPLICATE_IGNORE_DB' => 2, - 'MASTER_AUTO_POSITION' => 2, 'MASTER_CONNECT_RETRY' => 2, - 'MAX_QUERIES_PER_HOUR' => 2, 'MAX_UPDATES_PER_HOUR' => 2, - 'MAX_USER_CONNECTIONS' => 2, 'REPLICATE_REWRITE_DB' => 2, - 'REPLICATE_IGNORE_TABLE' => 2, - 'MASTER_HEARTBEAT_PERIOD' => 2, 'REPLICATE_WILD_DO_TABLE' => 2, - 'MAX_CONNECTIONS_PER_HOUR' => 2, - 'REPLICATE_WILD_IGNORE_TABLE' => 2, - - 'NOT NULL' => 4, - 'INDEX KEY' => 4, - 'UNIQUE KEY' => 4, - 'FOREIGN KEY' => 4, 'PRIMARY KEY' => 4, 'PRIMARY KEY' => 4, 'SPATIAL KEY' => 4, - 'FULLTEXT KEY' => 4, 'UNIQUE INDEX' => 4, - 'CHARACTER SET' => 4, 'IF NOT EXISTS' => 4, 'SPATIAL INDEX' => 4, - 'DATA DIRECTORY' => 4, 'FULLTEXT INDEX' => 4, - 'DEFAULT COLLATE' => 4, 'INDEX DIRECTORY' => 4, - 'DEFAULT CHARACTER SET' => 4, - ); - - // ------------------------------------------------------------------------- - // Keys and Data Types. - - /** - * Types of keys. - * - * @var array - */ - public static $KEY_TYPES = array( - 'FOREIGN KEY' => 1, 'FULLTEXT INDEX' => 1, 'FULLTEXT KEY' => 1, - 'INDEX KEY' => 1, 'INDEX' => 1, 'KEY' => 1, 'PRIMARY KEY' => 1, - 'SPATIAL INDEX' => 1, 'SPATIAL KEY' => 1, 'UNIQUE INDEX' => 1, - 'UNIQUE KEY' => 1, 'UNIQUE' => 1, - ); - - /** - * All data types. - * - * @var array - */ - public static $DATA_TYPES = array( - 'ARRAY' => 1, 'BIGINT' => 1, 'BINARY' => 1, 'BINARY VARYING' => 1, - 'BLOB' => 1, 'BOOLEAN' => 1, 'CHAR' => 1, 'CHARACTER' => 1, 'DATE' => 1, - 'DATETIME' => 1, 'DECIMAL' => 1, 'DOUBLE' => 1, 'ENUM' => 1, - 'FLOAT' => 1, 'INT' => 1, 'INTEGER' => 1, 'INTERVAL' => 1, - 'LONGBLOB' => 1, 'LONGTEXT' => 1, 'MEDIUMBLOB' => 1, 'MEDIUMINT' => 1, - 'MEDIUMTEXT' => 1, 'MULTISET' => 1, 'NUMERIC' => 1, 'REAL' => 1, - 'SET' => 1, 'SMALLINT' => 1, 'TEXT' => 1, 'TIME' => 1, 'TIMESTAMP' => 1, - 'TINYBLOB' => 1, 'TINYINT' => 1, 'TINYTEXT' => 1, 'VARBINARY' => 1, - 'VARCHAR' => 1, 'XML' => 1, 'YEAR' => 1 - ); + public static $KEYWORDS = array(); // ------------------------------------------------------------------------- // Operators. @@ -474,13 +264,13 @@ abstract class Context /** * Checks if the given character is a whitespace. * - * @param string $ch String to be checked. + * @param string $str String to be checked. * * @return bool */ - public static function isWhitespace($ch) + public static function isWhitespace($str) { - return ($ch === ' ') || ($ch === "\r") || ($ch === "\n") || ($ch === "\t"); + return ($str === ' ') || ($str === "\r") || ($str === "\n") || ($str === "\t"); } // ------------------------------------------------------------------------- @@ -519,14 +309,14 @@ abstract class Context * This actually check only for `TRUE` and `FALSE` because `1` or `0` are * actually numbers and are parsed by specific methods. * - * @param string $ch String to be checked. + * @param string $str String to be checked. * * @return bool */ - public static function isBool($ch) + public static function isBool($str) { - $ch = strtoupper($ch); - return ($ch === 'TRUE') || ($ch === 'FALSE'); + $str = strtoupper($str); + return ($str === 'TRUE') || ($str === 'FALSE'); } // ------------------------------------------------------------------------- @@ -535,14 +325,14 @@ abstract class Context /** * Checks if the given character can be a part of a number. * - * @param string $ch String to be checked. + * @param string $str String to be checked. * * @return bool */ - public static function isNumber($ch) + public static function isNumber($str) { - return (($ch >= '0') && ($ch <= '9')) || ($ch === '.') - || ($ch === '-') || ($ch === '+') || ($ch === 'e') || ($ch === 'E'); + return (($str >= '0') && ($str <= '9')) || ($str === '.') + || ($str === '-') || ($str === '+') || ($str === 'e') || ($str === 'E'); } // ------------------------------------------------------------------------- @@ -552,15 +342,15 @@ abstract class Context * Checks if the given character is the beginning of a symbol. A symbol * can be either a variable or a field name. * - * @param string $ch String to be checked. + * @param string $str String to be checked. * * @return int The appropriate flag for the symbol type. */ - public static function isSymbol($ch) + public static function isSymbol($str) { - if ($ch[0] === '@') { + if ($str[0] === '@') { return Token::FLAG_SYMBOL_VARIABLE; - } elseif ($ch[0] === '`') { + } elseif ($str[0] === '`') { return Token::FLAG_SYMBOL_BACKTICK; } return null; @@ -592,13 +382,13 @@ abstract class Context /** * Checks if the given character can be a separator for two lexems. * - * @param string $ch String to be checked. + * @param string $str String to be checked. * * @return bool */ - public static function isSeparator($ch) + public static function isSeparator($str) { - return !ctype_alnum($ch) && $ch !== '_'; + return !ctype_alnum($str) && $str !== '_'; } /** @@ -618,12 +408,15 @@ abstract class Context } if ($context[0] !== '\\') { // Short context name (must be formatted into class name). - $context = '\\SqlParser\\Contexts\\Context_' . $context; + $context = self::$contextPrefix . $context; } if (!class_exists($context)) { throw new \Exception('Specified context ("' . $context . '") doesn\'t exist.'); } - static::$loadedContext = $context; - static::$KEYWORDS = $context::$KEYWORDS; + self::$loadedContext = $context; + self::$KEYWORDS = $context::$KEYWORDS; } } + +// Initializng the default context. +Context::load(); diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50000.php b/libraries/sql-parser/src/Contexts/ContextMySql50000.php new file mode 100644 index 0000000000..b81d687f0c --- /dev/null +++ b/libraries/sql-parser/src/Contexts/ContextMySql50000.php @@ -0,0 +1,178 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class ContextMySql50000 extends Context +{ + + public static $KEYWORDS = array( + + 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, + 'ANY' => 1, 'AVG' => 1, 'BDB' => 1, 'BIT' => 1, 'CPU' => 1, 'DAY' => 1, + 'END' => 1, 'IPC' => 1, 'NDB' => 1, 'NEW' => 1, 'ONE' => 1, 'ROW' => 1, + 'BOOL' => 1, 'BYTE' => 1, 'CODE' => 1, 'CUBE' => 1, 'DATA' => 1, 'FAST' => 1, + 'FILE' => 1, 'FULL' => 1, 'HASH' => 1, 'HELP' => 1, 'HOUR' => 1, 'LAST' => 1, + 'LOGS' => 1, 'MODE' => 1, 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'OPEN' => 1, + 'PAGE' => 1, 'PREV' => 1, 'ROWS' => 1, 'SOME' => 1, 'STOP' => 1, 'TYPE' => 1, + 'USER' => 1, 'VIEW' => 1, 'WEEK' => 1, 'WORK' => 1, 'X509' => 1, + 'AFTER' => 1, 'ASCII' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, + 'CACHE' => 1, 'CHAIN' => 1, 'CLOSE' => 1, 'FIRST' => 1, 'FIXED' => 1, + 'FLUSH' => 1, 'FOUND' => 1, 'HOSTS' => 1, 'LEVEL' => 1, 'LOCAL' => 1, + 'LOCKS' => 1, 'MERGE' => 1, 'MONTH' => 1, 'MUTEX' => 1, 'NAMES' => 1, + 'NCHAR' => 1, 'PHASE' => 1, 'POINT' => 1, 'QUERY' => 1, 'QUICK' => 1, + 'RAID0' => 1, 'RESET' => 1, 'RTREE' => 1, 'SHARE' => 1, 'SLAVE' => 1, + 'START' => 1, 'SUPER' => 1, 'SWAPS' => 1, 'TYPES' => 1, 'UNTIL' => 1, + 'VALUE' => 1, + 'ACTION' => 1, 'BACKUP' => 1, 'BINLOG' => 1, 'CIPHER' => 1, 'CLIENT' => 1, + 'COMMIT' => 1, 'ENABLE' => 1, 'ENGINE' => 1, 'ERRORS' => 1, 'ESCAPE' => 1, + 'EVENTS' => 1, 'FAULTS' => 1, 'FIELDS' => 1, 'GLOBAL' => 1, 'GRANTS' => 1, + 'IMPORT' => 1, 'INNODB' => 1, 'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1, + 'MEDIUM' => 1, 'MEMORY' => 1, 'MINUTE' => 1, 'MODIFY' => 1, 'OFFSET' => 1, + 'RELOAD' => 1, 'REPAIR' => 1, 'RESUME' => 1, 'ROLLUP' => 1, 'SECOND' => 1, + 'SERIAL' => 1, 'SIGNED' => 1, 'SIMPLE' => 1, 'SOUNDS' => 1, 'SOURCE' => 1, + 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1, + 'AGAINST' => 1, 'CHANGED' => 1, 'CHARSET' => 1, 'COLUMNS' => 1, 'COMMENT' => 1, + 'COMPACT' => 1, 'CONTEXT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1, + 'DYNAMIC' => 1, 'ENGINES' => 1, 'EXECUTE' => 1, 'HANDLER' => 1, 'INDEXES' => 1, + 'INVOKER' => 1, 'MIGRATE' => 1, 'PARTIAL' => 1, 'POLYGON' => 1, 'PREPARE' => 1, + 'PROFILE' => 1, 'QUARTER' => 1, 'RECOVER' => 1, 'RESTORE' => 1, 'RETURNS' => 1, + 'ROUTINE' => 1, 'SESSION' => 1, 'STORAGE' => 1, 'STRIPED' => 1, 'SUBJECT' => 1, + 'SUSPEND' => 1, 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1, 'USE_FRM' => 1, + 'CASCADED' => 1, 'CHECKSUM' => 1, 'CONTAINS' => 1, 'DUMPFILE' => 1, + 'EXTENDED' => 1, 'FUNCTION' => 1, 'GEOMETRY' => 1, 'INNOBASE' => 1, + 'LANGUAGE' => 1, 'MAX_ROWS' => 1, 'MIN_ROWS' => 1, 'NATIONAL' => 1, + 'NVARCHAR' => 1, 'ONE_SHOT' => 1, 'PASSWORD' => 1, 'PROFILES' => 1, + 'ROLLBACK' => 1, 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1, + 'SWITCHES' => 1, 'TRIGGERS' => 1, 'TRUNCATE' => 1, 'WARNINGS' => 1, + 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COLLATION' => 1, 'COMMITTED' => 1, + 'DIRECTORY' => 1, 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, + 'ISOLATION' => 1, 'PACK_KEYS' => 1, 'RAID_TYPE' => 1, 'REDUNDANT' => 1, + 'SAVEPOINT' => 1, 'SQL_CACHE' => 1, 'TEMPORARY' => 1, 'TEMPTABLE' => 1, + 'UNDEFINED' => 1, 'VARIABLES' => 1, + 'BERKELEYDB' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1, + 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'GET_FORMAT' => 1, 'IDENTIFIED' => 1, + 'LINESTRING' => 1, 'MASTER_SSL' => 1, 'MULTIPOINT' => 1, 'NDBCLUSTER' => 1, + 'PRIVILEGES' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, + 'TABLESPACE' => 1, + 'FRAC_SECOND' => 1, 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, + 'MICROSECOND' => 1, 'PROCESSLIST' => 1, 'RAID_CHUNKS' => 1, 'REPLICATION' => 1, + 'SQL_TSI_DAY' => 1, 'TRANSACTION' => 1, 'UNCOMMITTED' => 1, + 'DES_KEY_FILE' => 1, 'MULTIPOLYGON' => 1, 'OLD_PASSWORD' => 1, + 'RELAY_THREAD' => 1, 'SERIALIZABLE' => 1, 'SQL_NO_CACHE' => 1, + 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1, 'SQL_TSI_YEAR' => 1, + 'TIMESTAMPADD' => 1, + 'INSERT_METHOD' => 1, 'MASTER_SSL_CA' => 1, 'RELAY_LOG_POS' => 1, + 'SQL_TSI_MONTH' => 1, 'TIMESTAMPDIFF' => 1, + 'AUTO_INCREMENT' => 1, 'AVG_ROW_LENGTH' => 1, 'MASTER_LOG_POS' => 1, + 'MASTER_SSL_KEY' => 1, 'RAID_CHUNKSIZE' => 1, 'RELAY_LOG_FILE' => 1, + 'SQL_TSI_MINUTE' => 1, 'SQL_TSI_SECOND' => 1, 'USER_RESOURCES' => 1, + 'DELAY_KEY_WRITE' => 1, 'MASTER_LOG_FILE' => 1, 'MASTER_PASSWORD' => 1, + 'MASTER_SSL_CERT' => 1, 'MULTILINESTRING' => 1, 'SQL_TSI_QUARTER' => 1, + 'MASTER_SERVER_ID' => 1, + 'MASTER_SSL_CAPATH' => 1, 'MASTER_SSL_CIPHER' => 1, 'SQL_BUFFER_RESULT' => 1, + 'GEOMETRYCOLLECTION' => 1, + 'SQL_TSI_FRAC_SECOND' => 1, + 'MASTER_CONNECT_RETRY' => 1, 'MAX_QUERIES_PER_HOUR' => 1, + 'MAX_UPDATES_PER_HOUR' => 1, 'MAX_USER_CONNECTIONS' => 1, + 'MAX_CONNECTIONS_PER_HOUR' => 1, + + 'AS' => 3, 'BY' => 3, 'IF' => 3, 'IN' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, + 'TO' => 3, + 'ADD' => 3, 'ALL' => 3, 'AND' => 3, 'ASC' => 3, 'DEC' => 3, 'DIV' => 3, + 'FOR' => 3, 'MOD' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, 'SSL' => 3, + 'USE' => 3, 'XOR' => 3, + 'BOTH' => 3, 'CALL' => 3, 'CASE' => 3, 'DESC' => 3, 'DROP' => 3, 'DUAL' => 3, + 'EACH' => 3, 'ELSE' => 3, 'EXIT' => 3, 'FROM' => 3, 'INT1' => 3, 'INT2' => 3, + 'INT3' => 3, 'INT4' => 3, 'INT8' => 3, 'INTO' => 3, 'JOIN' => 3, 'KEYS' => 3, + 'KILL' => 3, 'LEFT' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, + 'LOOP' => 3, 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, + 'UNDO' => 3, 'WHEN' => 3, 'WITH' => 3, + 'ALTER' => 3, 'CHECK' => 3, 'CROSS' => 3, 'FALSE' => 3, 'FETCH' => 3, + 'FORCE' => 3, 'GRANT' => 3, 'GROUP' => 3, 'INNER' => 3, 'INOUT' => 3, + 'LEAVE' => 3, 'LIMIT' => 3, 'LINES' => 3, 'MATCH' => 3, 'ORDER' => 3, + 'OUTER' => 3, 'PURGE' => 3, 'READS' => 3, 'RIGHT' => 3, 'RLIKE' => 3, + 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, 'WHERE' => 3, + 'WHILE' => 3, 'WRITE' => 3, + 'BEFORE' => 3, 'CHANGE' => 3, 'COLUMN' => 3, 'CREATE' => 3, 'CURSOR' => 3, + 'DELETE' => 3, 'ELSEIF' => 3, 'EXISTS' => 3, 'FLOAT4' => 3, 'FLOAT8' => 3, + 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'INSERT' => 3, 'OPTION' => 3, + 'REGEXP' => 3, 'RENAME' => 3, 'REPEAT' => 3, 'RETURN' => 3, 'REVOKE' => 3, + 'SCHEMA' => 3, 'SELECT' => 3, 'SONAME' => 3, 'UNLOCK' => 3, 'UPDATE' => 3, + 'VALUES' => 3, + 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'CONVERT' => 3, + 'DECLARE' => 3, 'DEFAULT' => 3, 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, + 'FOREIGN' => 3, 'ITERATE' => 3, 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, + 'PRIMARY' => 3, 'RELEASE' => 3, 'REPLACE' => 3, 'REQUIRE' => 3, 'SCHEMAS' => 3, + 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3, + 'CONTINUE' => 3, 'DATABASE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, + 'DISTINCT' => 3, 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MODIFIES' => 3, + 'OPTIMIZE' => 3, 'RESTRICT' => 3, 'SPECIFIC' => 3, 'SQLSTATE' => 3, + 'STARTING' => 3, 'TRAILING' => 3, 'UNSIGNED' => 3, 'UTC_DATE' => 3, + 'UTC_TIME' => 3, 'ZEROFILL' => 3, + 'CONDITION' => 3, 'DATABASES' => 3, 'LOCALTIME' => 3, 'MIDDLEINT' => 3, + 'PRECISION' => 3, 'PROCEDURE' => 3, 'SENSITIVE' => 3, 'SEPARATOR' => 3, + 'ASENSITIVE' => 3, 'CONSTRAINT' => 3, 'DAY_MINUTE' => 3, 'DAY_SECOND' => 3, + 'OPTIONALLY' => 3, 'REFERENCES' => 3, 'SQLWARNING' => 3, 'TERMINATED' => 3, + 'YEAR_MONTH' => 3, + 'DISTINCTROW' => 3, 'HOUR_MINUTE' => 3, 'HOUR_SECOND' => 3, 'INSENSITIVE' => 3, + 'CURRENT_DATE' => 3, 'CURRENT_TIME' => 3, 'CURRENT_USER' => 3, + 'LOW_PRIORITY' => 3, 'SQLEXCEPTION' => 3, 'VARCHARACTER' => 3, + 'DETERMINISTIC' => 3, 'HIGH_PRIORITY' => 3, 'MINUTE_SECOND' => 3, + 'STRAIGHT_JOIN' => 3, 'UTC_TIMESTAMP' => 3, + 'LOCALTIMESTAMP' => 3, 'SQL_BIG_RESULT' => 3, + 'DAY_MICROSECOND' => 3, + 'HOUR_MICROSECOND' => 3, 'SQL_SMALL_RESULT' => 3, + 'CURRENT_TIMESTAMP' => 3, + 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3, + 'SQL_CALC_FOUND_ROWS' => 3, + + 'NOT NULL' => 5, + 'ON UPDATE' => 5, + 'CHARACTER SET' => 5, 'IF NOT EXISTS' => 5, + 'DATA DIRECTORY' => 5, + 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, + 'DEFAULT CHARACTER SET' => 5, + + 'XML' => 9, + 'DATE' => 9, 'ENUM' => 9, 'TEXT' => 9, 'TIME' => 9, 'YEAR' => 9, + 'ARRAY' => 9, + 'BOOLEAN' => 9, + 'DATETIME' => 9, 'MULTISET' => 9, + 'TIMESTAMP' => 9, + + 'INT' => 11, 'SET' => 11, + 'BLOB' => 11, 'CHAR' => 11, 'REAL' => 11, + 'FLOAT' => 11, + 'BIGINT' => 11, 'BINARY' => 11, 'DOUBLE' => 11, + 'DECIMAL' => 11, 'INTEGER' => 11, 'NUMERIC' => 11, 'TINYINT' => 11, 'VARCHAR' => 11, + 'INTERVAL' => 11, 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, + 'TINYBLOB' => 11, 'TINYTEXT' => 11, + 'CHARACTER' => 11, 'MEDIUMINT' => 11, 'VARBINARY' => 11, + 'MEDIUMBLOB' => 11, 'MEDIUMTEXT' => 11, + + 'BINARY VARYING' => 13, + + 'KEY' => 19, + 'INDEX' => 19, + 'UNIQUE' => 19, + + 'INDEX KEY' => 21, + 'UNIQUE KEY' => 21, + 'FOREIGN KEY' => 21, 'PRIMARY KEY' => 21, 'SPATIAL KEY' => 21, + 'FULLTEXT KEY' => 21, 'UNIQUE INDEX' => 21, + 'SPATIAL INDEX' => 21, + 'FULLTEXT INDEX' => 21, + + ); +} diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50100.php b/libraries/sql-parser/src/Contexts/ContextMySql50100.php new file mode 100644 index 0000000000..260925e21f --- /dev/null +++ b/libraries/sql-parser/src/Contexts/ContextMySql50100.php @@ -0,0 +1,192 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class ContextMySql50100 extends Context +{ + + public static $KEYWORDS = array( + + 'AT' => 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, + 'ANY' => 1, 'AVG' => 1, 'BDB' => 1, 'BIT' => 1, 'CPU' => 1, 'DAY' => 1, + 'END' => 1, 'IPC' => 1, 'NDB' => 1, 'NEW' => 1, 'ONE' => 1, 'ROW' => 1, + 'BOOL' => 1, 'BYTE' => 1, 'CODE' => 1, 'CUBE' => 1, 'DATA' => 1, 'DISK' => 1, + 'ENDS' => 1, 'FAST' => 1, 'FILE' => 1, 'FULL' => 1, 'GOTO' => 1, 'HASH' => 1, + 'HELP' => 1, 'HOST' => 1, 'HOUR' => 1, 'LAST' => 1, 'LESS' => 1, 'LIST' => 1, + 'LOGS' => 1, 'MODE' => 1, 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'OPEN' => 1, + 'PAGE' => 1, 'PORT' => 1, 'PREV' => 1, 'ROWS' => 1, 'SOME' => 1, 'STOP' => 1, + 'THAN' => 1, 'TYPE' => 1, 'USER' => 1, 'VIEW' => 1, 'WAIT' => 1, 'WEEK' => 1, + 'WORK' => 1, 'X509' => 1, + 'AFTER' => 1, 'ASCII' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, + 'CACHE' => 1, 'CHAIN' => 1, 'CLOSE' => 1, 'EVENT' => 1, 'EVERY' => 1, + 'FIRST' => 1, 'FIXED' => 1, 'FLUSH' => 1, 'FOUND' => 1, 'HOSTS' => 1, + 'LABEL' => 1, 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, 'MERGE' => 1, + 'MONTH' => 1, 'MUTEX' => 1, 'NAMES' => 1, 'NCHAR' => 1, 'OWNER' => 1, + 'PHASE' => 1, 'POINT' => 1, 'QUERY' => 1, 'QUICK' => 1, 'RAID0' => 1, + 'RESET' => 1, 'RTREE' => 1, 'SHARE' => 1, 'SLAVE' => 1, 'START' => 1, + 'SUPER' => 1, 'SWAPS' => 1, 'TYPES' => 1, 'UNTIL' => 1, 'VALUE' => 1, + 'ACTION' => 1, 'BACKUP' => 1, 'BINLOG' => 1, 'CIPHER' => 1, 'CLIENT' => 1, + 'COMMIT' => 1, 'ENABLE' => 1, 'ENGINE' => 1, 'ERRORS' => 1, 'ESCAPE' => 1, + 'EVENTS' => 1, 'FAULTS' => 1, 'FIELDS' => 1, 'GLOBAL' => 1, 'GRANTS' => 1, + 'IMPORT' => 1, 'INNODB' => 1, 'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1, + 'MEDIUM' => 1, 'MEMORY' => 1, 'MINUTE' => 1, 'MODIFY' => 1, 'OFFSET' => 1, + 'PARSER' => 1, 'PLUGIN' => 1, 'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, + 'RESUME' => 1, 'ROLLUP' => 1, 'SECOND' => 1, 'SERIAL' => 1, 'SERVER' => 1, + 'SIGNED' => 1, 'SIMPLE' => 1, 'SOCKET' => 1, 'SONAME' => 1, 'SOUNDS' => 1, + 'SOURCE' => 1, 'STARTS' => 1, 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1, + 'AGAINST' => 1, 'AUTHORS' => 1, 'CHANGED' => 1, 'CHARSET' => 1, 'COLUMNS' => 1, + 'COMMENT' => 1, 'COMPACT' => 1, 'CONTEXT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, + 'DISCARD' => 1, 'DYNAMIC' => 1, 'ENGINES' => 1, 'EXECUTE' => 1, 'HANDLER' => 1, + 'INDEXES' => 1, 'INSTALL' => 1, 'INVOKER' => 1, 'LOGFILE' => 1, 'MIGRATE' => 1, + 'NO_WAIT' => 1, 'OPTIONS' => 1, 'PARTIAL' => 1, 'PLUGINS' => 1, 'POLYGON' => 1, + 'PREPARE' => 1, 'PROFILE' => 1, 'QUARTER' => 1, 'REBUILD' => 1, 'RECOVER' => 1, + 'RESTORE' => 1, 'RETURNS' => 1, 'ROUTINE' => 1, 'SESSION' => 1, 'STORAGE' => 1, + 'STRIPED' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1, 'UNICODE' => 1, 'UNKNOWN' => 1, + 'UPGRADE' => 1, 'USE_FRM' => 1, 'WRAPPER' => 1, + 'CASCADED' => 1, 'CHECKSUM' => 1, 'COALESCE' => 1, 'CONTAINS' => 1, + 'DATAFILE' => 1, 'DUMPFILE' => 1, 'EXTENDED' => 1, 'FUNCTION' => 1, + 'GEOMETRY' => 1, 'INNOBASE' => 1, 'LANGUAGE' => 1, 'MAXVALUE' => 1, + 'MAX_ROWS' => 1, 'MAX_SIZE' => 1, 'MIN_ROWS' => 1, 'NATIONAL' => 1, + 'NVARCHAR' => 1, 'ONE_SHOT' => 1, 'PASSWORD' => 1, 'PRESERVE' => 1, + 'PROFILES' => 1, 'REDOFILE' => 1, 'ROLLBACK' => 1, 'SCHEDULE' => 1, + 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1, 'SWITCHES' => 1, + 'TRIGGERS' => 1, 'TRUNCATE' => 1, 'UNDOFILE' => 1, 'WARNINGS' => 1, + 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COLLATION' => 1, 'COMMITTED' => 1, + 'DIRECTORY' => 1, 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, + 'ISOLATION' => 1, 'NODEGROUP' => 1, 'PACK_KEYS' => 1, 'PARTITION' => 1, + 'RAID_TYPE' => 1, 'READ_ONLY' => 1, 'REDUNDANT' => 1, 'SAVEPOINT' => 1, + 'SCHEDULER' => 1, 'SQL_CACHE' => 1, 'TEMPORARY' => 1, 'TEMPTABLE' => 1, + 'UNDEFINED' => 1, 'UNINSTALL' => 1, 'VARIABLES' => 1, + 'BERKELEYDB' => 1, 'COMPLETION' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, + 'CONNECTION' => 1, 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'GET_FORMAT' => 1, + 'IDENTIFIED' => 1, 'LINESTRING' => 1, 'MASTER_SSL' => 1, 'MULTIPOINT' => 1, + 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PRIVILEGES' => 1, 'REORGANISE' => 1, + 'REORGANIZE' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, + 'TABLESPACE' => 1, + 'EXTENT_SIZE' => 1, 'FRAC_SECOND' => 1, 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, + 'MASTER_USER' => 1, 'MICROSECOND' => 1, 'PROCESSLIST' => 1, 'RAID_CHUNKS' => 1, + 'REPLICATION' => 1, 'SQL_TSI_DAY' => 1, 'TRANSACTION' => 1, 'UNCOMMITTED' => 1, + 'CONTRIBUTORS' => 1, 'DES_KEY_FILE' => 1, 'INITIAL_SIZE' => 1, + 'MULTIPOLYGON' => 1, 'OLD_PASSWORD' => 1, 'PARTITIONING' => 1, + 'RELAY_THREAD' => 1, 'SERIALIZABLE' => 1, 'SQL_NO_CACHE' => 1, + 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1, 'SQL_TSI_YEAR' => 1, + 'SUBPARTITION' => 1, 'TIMESTAMPADD' => 1, + 'INSERT_METHOD' => 1, 'MASTER_SSL_CA' => 1, 'PAGE_CHECKSUM' => 1, + 'RELAY_LOG_POS' => 1, 'SQL_TSI_MONTH' => 1, 'SUBPARTITIONS' => 1, + 'TIMESTAMPDIFF' => 1, 'TRANSACTIONAL' => 1, + 'AUTO_INCREMENT' => 1, 'AVG_ROW_LENGTH' => 1, 'KEY_BLOCK_SIZE' => 1, + 'MASTER_LOG_POS' => 1, 'MASTER_SSL_KEY' => 1, 'RAID_CHUNKSIZE' => 1, + 'RELAY_LOG_FILE' => 1, 'SQL_TSI_MINUTE' => 1, 'SQL_TSI_SECOND' => 1, + 'TABLE_CHECKSUM' => 1, 'USER_RESOURCES' => 1, + 'AUTOEXTEND_SIZE' => 1, 'DELAY_KEY_WRITE' => 1, 'MASTER_LOG_FILE' => 1, + 'MASTER_PASSWORD' => 1, 'MASTER_SSL_CERT' => 1, 'MULTILINESTRING' => 1, + 'SQL_TSI_QUARTER' => 1, + 'MASTER_SERVER_ID' => 1, 'REDO_BUFFER_SIZE' => 1, 'UNDO_BUFFER_SIZE' => 1, + 'MASTER_SSL_CAPATH' => 1, 'MASTER_SSL_CIPHER' => 1, 'SQL_BUFFER_RESULT' => 1, + 'GEOMETRYCOLLECTION' => 1, + 'SQL_TSI_FRAC_SECOND' => 1, + 'MASTER_CONNECT_RETRY' => 1, 'MAX_QUERIES_PER_HOUR' => 1, + 'MAX_UPDATES_PER_HOUR' => 1, 'MAX_USER_CONNECTIONS' => 1, + 'MAX_CONNECTIONS_PER_HOUR' => 1, + + 'AS' => 3, 'BY' => 3, 'IF' => 3, 'IN' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, + 'TO' => 3, + 'ADD' => 3, 'ALL' => 3, 'AND' => 3, 'ASC' => 3, 'DEC' => 3, 'DIV' => 3, + 'FOR' => 3, 'MOD' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, 'SSL' => 3, + 'USE' => 3, 'XOR' => 3, + 'BOTH' => 3, 'CALL' => 3, 'CASE' => 3, 'DESC' => 3, 'DROP' => 3, 'DUAL' => 3, + 'EACH' => 3, 'ELSE' => 3, 'EXIT' => 3, 'FROM' => 3, 'INT1' => 3, 'INT2' => 3, + 'INT3' => 3, 'INT4' => 3, 'INT8' => 3, 'INTO' => 3, 'JOIN' => 3, 'KEYS' => 3, + 'KILL' => 3, 'LEFT' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, + 'LOOP' => 3, 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, + 'UNDO' => 3, 'WHEN' => 3, 'WITH' => 3, + 'ALTER' => 3, 'CHECK' => 3, 'CROSS' => 3, 'FALSE' => 3, 'FETCH' => 3, + 'FORCE' => 3, 'GRANT' => 3, 'GROUP' => 3, 'INNER' => 3, 'INOUT' => 3, + 'LEAVE' => 3, 'LIMIT' => 3, 'LINES' => 3, 'MATCH' => 3, 'ORDER' => 3, + 'OUTER' => 3, 'PURGE' => 3, 'RANGE' => 3, 'READS' => 3, 'RIGHT' => 3, + 'RLIKE' => 3, 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, + 'WHERE' => 3, 'WHILE' => 3, 'WRITE' => 3, + 'BEFORE' => 3, 'CHANGE' => 3, 'COLUMN' => 3, 'CREATE' => 3, 'CURSOR' => 3, + 'DELETE' => 3, 'ELSEIF' => 3, 'EXISTS' => 3, 'FLOAT4' => 3, 'FLOAT8' => 3, + 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'INSERT' => 3, 'LINEAR' => 3, + 'OPTION' => 3, 'REGEXP' => 3, 'RENAME' => 3, 'REPEAT' => 3, 'RETURN' => 3, + 'REVOKE' => 3, 'SCHEMA' => 3, 'SELECT' => 3, 'UNLOCK' => 3, 'UPDATE' => 3, + 'VALUES' => 3, + 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'CONVERT' => 3, + 'DECLARE' => 3, 'DEFAULT' => 3, 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, + 'FOREIGN' => 3, 'ITERATE' => 3, 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, + 'PRIMARY' => 3, 'RELEASE' => 3, 'REPLACE' => 3, 'REQUIRE' => 3, 'SCHEMAS' => 3, + 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3, + 'CONTINUE' => 3, 'DATABASE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, + 'DISTINCT' => 3, 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MODIFIES' => 3, + 'OPTIMIZE' => 3, 'RESTRICT' => 3, 'SPECIFIC' => 3, 'SQLSTATE' => 3, + 'STARTING' => 3, 'TRAILING' => 3, 'UNSIGNED' => 3, 'UTC_DATE' => 3, + 'UTC_TIME' => 3, 'ZEROFILL' => 3, + 'CONDITION' => 3, 'DATABASES' => 3, 'LOCALTIME' => 3, 'MIDDLEINT' => 3, + 'PRECISION' => 3, 'PROCEDURE' => 3, 'SENSITIVE' => 3, 'SEPARATOR' => 3, + 'ACCESSIBLE' => 3, 'ASENSITIVE' => 3, 'CONSTRAINT' => 3, 'DAY_MINUTE' => 3, + 'DAY_SECOND' => 3, 'OPTIONALLY' => 3, 'READ_WRITE' => 3, 'REFERENCES' => 3, + 'SQLWARNING' => 3, 'TERMINATED' => 3, 'YEAR_MONTH' => 3, + 'DISTINCTROW' => 3, 'HOUR_MINUTE' => 3, 'HOUR_SECOND' => 3, 'INSENSITIVE' => 3, + 'CURRENT_DATE' => 3, 'CURRENT_TIME' => 3, 'CURRENT_USER' => 3, + 'LOW_PRIORITY' => 3, 'SQLEXCEPTION' => 3, 'VARCHARACTER' => 3, + 'DETERMINISTIC' => 3, 'HIGH_PRIORITY' => 3, 'MINUTE_SECOND' => 3, + 'STRAIGHT_JOIN' => 3, 'UTC_TIMESTAMP' => 3, + 'LOCALTIMESTAMP' => 3, 'SQL_BIG_RESULT' => 3, + 'DAY_MICROSECOND' => 3, + 'HOUR_MICROSECOND' => 3, 'SQL_SMALL_RESULT' => 3, + 'CURRENT_TIMESTAMP' => 3, + 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3, + 'SQL_CALC_FOUND_ROWS' => 3, + 'MASTER_SSL_VERIFY_SERVER_CERT' => 3, + + 'NOT NULL' => 5, + 'ON UPDATE' => 5, + 'CHARACTER SET' => 5, 'IF NOT EXISTS' => 5, + 'DATA DIRECTORY' => 5, + 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, + 'DEFAULT CHARACTER SET' => 5, + + 'XML' => 9, + 'DATE' => 9, 'ENUM' => 9, 'TEXT' => 9, 'TIME' => 9, 'YEAR' => 9, + 'ARRAY' => 9, + 'BOOLEAN' => 9, + 'DATETIME' => 9, 'MULTISET' => 9, + 'TIMESTAMP' => 9, + + 'INT' => 11, 'SET' => 11, + 'BLOB' => 11, 'CHAR' => 11, 'REAL' => 11, + 'FLOAT' => 11, + 'BIGINT' => 11, 'BINARY' => 11, 'DOUBLE' => 11, + 'DECIMAL' => 11, 'INTEGER' => 11, 'NUMERIC' => 11, 'TINYINT' => 11, 'VARCHAR' => 11, + 'INTERVAL' => 11, 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, + 'TINYBLOB' => 11, 'TINYTEXT' => 11, + 'CHARACTER' => 11, 'MEDIUMINT' => 11, 'VARBINARY' => 11, + 'MEDIUMBLOB' => 11, 'MEDIUMTEXT' => 11, + + 'BINARY VARYING' => 13, + + 'KEY' => 19, + 'INDEX' => 19, + 'UNIQUE' => 19, + + 'INDEX KEY' => 21, + 'UNIQUE KEY' => 21, + 'FOREIGN KEY' => 21, 'PRIMARY KEY' => 21, 'SPATIAL KEY' => 21, + 'FULLTEXT KEY' => 21, 'UNIQUE INDEX' => 21, + 'SPATIAL INDEX' => 21, + 'FULLTEXT INDEX' => 21, + + ); +} diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50500.php b/libraries/sql-parser/src/Contexts/ContextMySql50500.php new file mode 100644 index 0000000000..e70b931994 --- /dev/null +++ b/libraries/sql-parser/src/Contexts/ContextMySql50500.php @@ -0,0 +1,195 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class ContextMySql50500 extends Context +{ + + public static $KEYWORDS = array( + + 'AT' => 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, + 'ANY' => 1, 'AVG' => 1, 'BIT' => 1, 'CPU' => 1, 'DAY' => 1, 'END' => 1, + 'IPC' => 1, 'NDB' => 1, 'NEW' => 1, 'ONE' => 1, 'ROW' => 1, + 'BOOL' => 1, 'BYTE' => 1, 'CODE' => 1, 'CUBE' => 1, 'DATA' => 1, 'DISK' => 1, + 'ENDS' => 1, 'FAST' => 1, 'FILE' => 1, 'FULL' => 1, 'HASH' => 1, 'HELP' => 1, + 'HOST' => 1, 'HOUR' => 1, 'LAST' => 1, 'LESS' => 1, 'LIST' => 1, 'LOGS' => 1, + 'MODE' => 1, 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'OPEN' => 1, 'PAGE' => 1, + 'PORT' => 1, 'PREV' => 1, 'ROWS' => 1, 'SLOW' => 1, 'SOME' => 1, 'STOP' => 1, + 'THAN' => 1, 'TYPE' => 1, 'USER' => 1, 'VIEW' => 1, 'WAIT' => 1, 'WEEK' => 1, + 'WORK' => 1, 'X509' => 1, + 'AFTER' => 1, 'ASCII' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, + 'CACHE' => 1, 'CHAIN' => 1, 'CLOSE' => 1, 'ERROR' => 1, 'EVENT' => 1, + 'EVERY' => 1, 'FIRST' => 1, 'FIXED' => 1, 'FLUSH' => 1, 'FOUND' => 1, + 'HOSTS' => 1, 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, 'MERGE' => 1, + 'MONTH' => 1, 'MUTEX' => 1, 'NAMES' => 1, 'NCHAR' => 1, 'OWNER' => 1, + 'PHASE' => 1, 'POINT' => 1, 'PROXY' => 1, 'QUERY' => 1, 'QUICK' => 1, + 'RELAY' => 1, 'RESET' => 1, 'RTREE' => 1, 'SHARE' => 1, 'SLAVE' => 1, + 'START' => 1, 'SUPER' => 1, 'SWAPS' => 1, 'TYPES' => 1, 'UNTIL' => 1, + 'VALUE' => 1, + 'ACTION' => 1, 'BACKUP' => 1, 'BINLOG' => 1, 'CIPHER' => 1, 'CLIENT' => 1, + 'COMMIT' => 1, 'ENABLE' => 1, 'ENGINE' => 1, 'ERRORS' => 1, 'ESCAPE' => 1, + 'EVENTS' => 1, 'FAULTS' => 1, 'FIELDS' => 1, 'GLOBAL' => 1, 'GRANTS' => 1, + 'IMPORT' => 1, 'INNODB' => 1, 'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1, + 'MEDIUM' => 1, 'MEMORY' => 1, 'MINUTE' => 1, 'MODIFY' => 1, 'OFFSET' => 1, + 'PARSER' => 1, 'PLUGIN' => 1, 'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, + 'RESUME' => 1, 'ROLLUP' => 1, 'SECOND' => 1, 'SERIAL' => 1, 'SERVER' => 1, + 'SIGNED' => 1, 'SIMPLE' => 1, 'SOCKET' => 1, 'SONAME' => 1, 'SOUNDS' => 1, + 'SOURCE' => 1, 'STARTS' => 1, 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1, + 'AGAINST' => 1, 'AUTHORS' => 1, 'CHANGED' => 1, 'CHARSET' => 1, 'COLUMNS' => 1, + 'COMMENT' => 1, 'COMPACT' => 1, 'CONTEXT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, + 'DISCARD' => 1, 'DYNAMIC' => 1, 'ENGINES' => 1, 'EXECUTE' => 1, 'GENERAL' => 1, + 'HANDLER' => 1, 'INDEXES' => 1, 'INSTALL' => 1, 'INVOKER' => 1, 'LOGFILE' => 1, + 'MIGRATE' => 1, 'NO_WAIT' => 1, 'OPTIONS' => 1, 'PARTIAL' => 1, 'PLUGINS' => 1, + 'POLYGON' => 1, 'PREPARE' => 1, 'PROFILE' => 1, 'QUARTER' => 1, 'REBUILD' => 1, + 'RECOVER' => 1, 'RESTORE' => 1, 'RETURNS' => 1, 'ROUTINE' => 1, 'SESSION' => 1, + 'STORAGE' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1, 'UNICODE' => 1, 'UNKNOWN' => 1, + 'UPGRADE' => 1, 'USE_FRM' => 1, 'WRAPPER' => 1, + 'CASCADED' => 1, 'CHECKSUM' => 1, 'COALESCE' => 1, 'CONTAINS' => 1, + 'DATAFILE' => 1, 'DUMPFILE' => 1, 'EXTENDED' => 1, 'FUNCTION' => 1, + 'GEOMETRY' => 1, 'INNOBASE' => 1, 'LANGUAGE' => 1, 'MAX_ROWS' => 1, + 'MAX_SIZE' => 1, 'MIN_ROWS' => 1, 'NATIONAL' => 1, 'NVARCHAR' => 1, + 'ONE_SHOT' => 1, 'PASSWORD' => 1, 'PRESERVE' => 1, 'PROFILES' => 1, + 'REDOFILE' => 1, 'RELAYLOG' => 1, 'ROLLBACK' => 1, 'SCHEDULE' => 1, + 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1, 'SWITCHES' => 1, + 'TRIGGERS' => 1, 'TRUNCATE' => 1, 'UNDOFILE' => 1, 'WARNINGS' => 1, + 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COLLATION' => 1, 'COMMITTED' => 1, + 'DIRECTORY' => 1, 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, + 'ISOLATION' => 1, 'NODEGROUP' => 1, 'PACK_KEYS' => 1, 'PARTITION' => 1, + 'READ_ONLY' => 1, 'REDUNDANT' => 1, 'SAVEPOINT' => 1, 'SQL_CACHE' => 1, + 'TEMPORARY' => 1, 'TEMPTABLE' => 1, 'UNDEFINED' => 1, 'UNINSTALL' => 1, + 'VARIABLES' => 1, + 'COMPLETION' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1, + 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'GET_FORMAT' => 1, 'IDENTIFIED' => 1, + 'LINESTRING' => 1, 'MASTER_SSL' => 1, 'MULTIPOINT' => 1, 'NDBCLUSTER' => 1, + 'PARTITIONS' => 1, 'PRIVILEGES' => 1, 'REORGANIZE' => 1, 'REPEATABLE' => 1, + 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, 'TABLESPACE' => 1, 'TABLE_NAME' => 1, + 'COLUMN_NAME' => 1, 'CURSOR_NAME' => 1, 'EXTENT_SIZE' => 1, 'FRAC_SECOND' => 1, + 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, 'MICROSECOND' => 1, + 'MYSQL_ERRNO' => 1, 'PROCESSLIST' => 1, 'REPLICATION' => 1, 'SCHEMA_NAME' => 1, + 'SQL_TSI_DAY' => 1, 'TRANSACTION' => 1, 'UNCOMMITTED' => 1, + 'CATALOG_NAME' => 1, 'CLASS_ORIGIN' => 1, 'CONTRIBUTORS' => 1, + 'DES_KEY_FILE' => 1, 'INITIAL_SIZE' => 1, 'MESSAGE_TEXT' => 1, + 'MULTIPOLYGON' => 1, 'OLD_PASSWORD' => 1, 'PARTITIONING' => 1, + 'RELAY_THREAD' => 1, 'SERIALIZABLE' => 1, 'SQL_NO_CACHE' => 1, + 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1, 'SQL_TSI_YEAR' => 1, + 'SUBPARTITION' => 1, 'TIMESTAMPADD' => 1, + 'INSERT_METHOD' => 1, 'MASTER_SSL_CA' => 1, 'RELAY_LOG_POS' => 1, + 'SQL_TSI_MONTH' => 1, 'SUBPARTITIONS' => 1, 'TIMESTAMPDIFF' => 1, + 'AUTO_INCREMENT' => 1, 'AVG_ROW_LENGTH' => 1, 'KEY_BLOCK_SIZE' => 1, + 'MASTER_LOG_POS' => 1, 'MASTER_SSL_KEY' => 1, 'RELAY_LOG_FILE' => 1, + 'SQL_TSI_MINUTE' => 1, 'SQL_TSI_SECOND' => 1, 'TABLE_CHECKSUM' => 1, + 'USER_RESOURCES' => 1, + 'AUTOEXTEND_SIZE' => 1, 'CONSTRAINT_NAME' => 1, 'DELAY_KEY_WRITE' => 1, + 'MASTER_LOG_FILE' => 1, 'MASTER_PASSWORD' => 1, 'MASTER_SSL_CERT' => 1, + 'MULTILINESTRING' => 1, 'SQL_TSI_QUARTER' => 1, 'SUBCLASS_ORIGIN' => 1, + 'MASTER_SERVER_ID' => 1, 'REDO_BUFFER_SIZE' => 1, 'UNDO_BUFFER_SIZE' => 1, + 'CONSTRAINT_SCHEMA' => 1, 'IGNORE_SERVER_IDS' => 1, 'MASTER_SSL_CAPATH' => 1, + 'MASTER_SSL_CIPHER' => 1, 'SQL_BUFFER_RESULT' => 1, + 'CONSTRAINT_CATALOG' => 1, 'GEOMETRYCOLLECTION' => 1, + 'SQL_TSI_FRAC_SECOND' => 1, + 'MASTER_CONNECT_RETRY' => 1, 'MAX_QUERIES_PER_HOUR' => 1, + 'MAX_UPDATES_PER_HOUR' => 1, 'MAX_USER_CONNECTIONS' => 1, + 'MASTER_HEARTBEAT_PERIOD' => 1, + 'MAX_CONNECTIONS_PER_HOUR' => 1, + + 'AS' => 3, 'BY' => 3, 'IF' => 3, 'IN' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, + 'TO' => 3, + 'ADD' => 3, 'ALL' => 3, 'AND' => 3, 'ASC' => 3, 'DEC' => 3, 'DIV' => 3, + 'FOR' => 3, 'MOD' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, 'SSL' => 3, + 'USE' => 3, 'XOR' => 3, + 'BOTH' => 3, 'CALL' => 3, 'CASE' => 3, 'DESC' => 3, 'DROP' => 3, 'DUAL' => 3, + 'EACH' => 3, 'ELSE' => 3, 'EXIT' => 3, 'FROM' => 3, 'INT1' => 3, 'INT2' => 3, + 'INT3' => 3, 'INT4' => 3, 'INT8' => 3, 'INTO' => 3, 'JOIN' => 3, 'KEYS' => 3, + 'KILL' => 3, 'LEFT' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, + 'LOOP' => 3, 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, + 'UNDO' => 3, 'WHEN' => 3, 'WITH' => 3, + 'ALTER' => 3, 'CHECK' => 3, 'CROSS' => 3, 'FALSE' => 3, 'FETCH' => 3, + 'FORCE' => 3, 'GRANT' => 3, 'GROUP' => 3, 'INNER' => 3, 'INOUT' => 3, + 'LEAVE' => 3, 'LIMIT' => 3, 'LINES' => 3, 'MATCH' => 3, 'ORDER' => 3, + 'OUTER' => 3, 'PURGE' => 3, 'RANGE' => 3, 'READS' => 3, 'RIGHT' => 3, + 'RLIKE' => 3, 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, + 'WHERE' => 3, 'WHILE' => 3, 'WRITE' => 3, + 'BEFORE' => 3, 'CHANGE' => 3, 'COLUMN' => 3, 'CREATE' => 3, 'CURSOR' => 3, + 'DELETE' => 3, 'ELSEIF' => 3, 'EXISTS' => 3, 'FLOAT4' => 3, 'FLOAT8' => 3, + 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'INSERT' => 3, 'LINEAR' => 3, + 'OPTION' => 3, 'REGEXP' => 3, 'RENAME' => 3, 'REPEAT' => 3, 'RETURN' => 3, + 'REVOKE' => 3, 'SCHEMA' => 3, 'SELECT' => 3, 'SIGNAL' => 3, 'UNLOCK' => 3, + 'UPDATE' => 3, 'VALUES' => 3, + 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'CONVERT' => 3, + 'DECLARE' => 3, 'DEFAULT' => 3, 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, + 'FOREIGN' => 3, 'ITERATE' => 3, 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, + 'PRIMARY' => 3, 'RELEASE' => 3, 'REPLACE' => 3, 'REQUIRE' => 3, 'SCHEMAS' => 3, + 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3, + 'CONTINUE' => 3, 'DATABASE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, + 'DISTINCT' => 3, 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MAXVALUE' => 3, + 'MODIFIES' => 3, 'OPTIMIZE' => 3, 'RESIGNAL' => 3, 'RESTRICT' => 3, + 'SPECIFIC' => 3, 'SQLSTATE' => 3, 'STARTING' => 3, 'TRAILING' => 3, + 'UNSIGNED' => 3, 'UTC_DATE' => 3, 'UTC_TIME' => 3, 'ZEROFILL' => 3, + 'CONDITION' => 3, 'DATABASES' => 3, 'LOCALTIME' => 3, 'MIDDLEINT' => 3, + 'PRECISION' => 3, 'PROCEDURE' => 3, 'SENSITIVE' => 3, 'SEPARATOR' => 3, + 'ACCESSIBLE' => 3, 'ASENSITIVE' => 3, 'CONSTRAINT' => 3, 'DAY_MINUTE' => 3, + 'DAY_SECOND' => 3, 'OPTIONALLY' => 3, 'READ_WRITE' => 3, 'REFERENCES' => 3, + 'SQLWARNING' => 3, 'TERMINATED' => 3, 'YEAR_MONTH' => 3, + 'DISTINCTROW' => 3, 'HOUR_MINUTE' => 3, 'HOUR_SECOND' => 3, 'INSENSITIVE' => 3, + 'CURRENT_DATE' => 3, 'CURRENT_TIME' => 3, 'CURRENT_USER' => 3, + 'LOW_PRIORITY' => 3, 'SQLEXCEPTION' => 3, 'VARCHARACTER' => 3, + 'DETERMINISTIC' => 3, 'HIGH_PRIORITY' => 3, 'MINUTE_SECOND' => 3, + 'STRAIGHT_JOIN' => 3, 'UTC_TIMESTAMP' => 3, + 'LOCALTIMESTAMP' => 3, 'SQL_BIG_RESULT' => 3, + 'DAY_MICROSECOND' => 3, + 'HOUR_MICROSECOND' => 3, 'SQL_SMALL_RESULT' => 3, + 'CURRENT_TIMESTAMP' => 3, + 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3, + 'SQL_CALC_FOUND_ROWS' => 3, + 'MASTER_SSL_VERIFY_SERVER_CERT' => 3, + + 'NOT NULL' => 5, + 'ON UPDATE' => 5, + 'CHARACTER SET' => 5, 'IF NOT EXISTS' => 5, + 'DATA DIRECTORY' => 5, + 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, + 'DEFAULT CHARACTER SET' => 5, + + 'XML' => 9, + 'DATE' => 9, 'ENUM' => 9, 'TEXT' => 9, 'TIME' => 9, 'YEAR' => 9, + 'ARRAY' => 9, + 'BOOLEAN' => 9, + 'DATETIME' => 9, 'MULTISET' => 9, + 'TIMESTAMP' => 9, + + 'INT' => 11, 'SET' => 11, + 'BLOB' => 11, 'CHAR' => 11, 'REAL' => 11, + 'FLOAT' => 11, + 'BIGINT' => 11, 'BINARY' => 11, 'DOUBLE' => 11, + 'DECIMAL' => 11, 'INTEGER' => 11, 'NUMERIC' => 11, 'TINYINT' => 11, 'VARCHAR' => 11, + 'INTERVAL' => 11, 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, + 'TINYBLOB' => 11, 'TINYTEXT' => 11, + 'CHARACTER' => 11, 'MEDIUMINT' => 11, 'VARBINARY' => 11, + 'MEDIUMBLOB' => 11, 'MEDIUMTEXT' => 11, + + 'BINARY VARYING' => 13, + + 'KEY' => 19, + 'INDEX' => 19, + 'UNIQUE' => 19, + + 'INDEX KEY' => 21, + 'UNIQUE KEY' => 21, + 'FOREIGN KEY' => 21, 'PRIMARY KEY' => 21, 'SPATIAL KEY' => 21, + 'FULLTEXT KEY' => 21, 'UNIQUE INDEX' => 21, + 'SPATIAL INDEX' => 21, + 'FULLTEXT INDEX' => 21, + + ); +} diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50600.php b/libraries/sql-parser/src/Contexts/ContextMySql50600.php new file mode 100644 index 0000000000..819ec1c53f --- /dev/null +++ b/libraries/sql-parser/src/Contexts/ContextMySql50600.php @@ -0,0 +1,206 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class ContextMySql50600 extends Context +{ + + public static $KEYWORDS = array( + + 'AT' => 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, + 'ANY' => 1, 'AVG' => 1, 'BIT' => 1, 'CPU' => 1, 'DAY' => 1, 'END' => 1, + 'IPC' => 1, 'NDB' => 1, 'NEW' => 1, 'ONE' => 1, 'ROW' => 1, + 'BOOL' => 1, 'BYTE' => 1, 'CODE' => 1, 'CUBE' => 1, 'DATA' => 1, 'DISK' => 1, + 'ENDS' => 1, 'FAST' => 1, 'FILE' => 1, 'FULL' => 1, 'HASH' => 1, 'HELP' => 1, + 'HOST' => 1, 'HOUR' => 1, 'LAST' => 1, 'LESS' => 1, 'LIST' => 1, 'LOGS' => 1, + 'MODE' => 1, 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'ONLY' => 1, 'OPEN' => 1, + 'PAGE' => 1, 'PORT' => 1, 'PREV' => 1, 'ROWS' => 1, 'SLOW' => 1, 'SOME' => 1, + 'STOP' => 1, 'THAN' => 1, 'TYPE' => 1, 'USER' => 1, 'VIEW' => 1, 'WAIT' => 1, + 'WEEK' => 1, 'WORK' => 1, 'X509' => 1, + 'AFTER' => 1, 'ASCII' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, + 'CACHE' => 1, 'CHAIN' => 1, 'CLOSE' => 1, 'ERROR' => 1, 'EVENT' => 1, + 'EVERY' => 1, 'FIRST' => 1, 'FIXED' => 1, 'FLUSH' => 1, 'FOUND' => 1, + 'HOSTS' => 1, 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, 'MERGE' => 1, + 'MONTH' => 1, 'MUTEX' => 1, 'NAMES' => 1, 'NCHAR' => 1, 'OWNER' => 1, + 'PHASE' => 1, 'POINT' => 1, 'PROXY' => 1, 'QUERY' => 1, 'QUICK' => 1, + 'RELAY' => 1, 'RESET' => 1, 'RTREE' => 1, 'SHARE' => 1, 'SLAVE' => 1, + 'START' => 1, 'SUPER' => 1, 'SWAPS' => 1, 'TYPES' => 1, 'UNTIL' => 1, + 'VALUE' => 1, + 'ACTION' => 1, 'BACKUP' => 1, 'BINLOG' => 1, 'CIPHER' => 1, 'CLIENT' => 1, + 'COMMIT' => 1, 'ENABLE' => 1, 'ENGINE' => 1, 'ERRORS' => 1, 'ESCAPE' => 1, + 'EVENTS' => 1, 'EXPIRE' => 1, 'EXPORT' => 1, 'FAULTS' => 1, 'FIELDS' => 1, + 'FORMAT' => 1, 'GLOBAL' => 1, 'GRANTS' => 1, 'IMPORT' => 1, 'ISSUER' => 1, + 'LEAVES' => 1, 'MASTER' => 1, 'MEDIUM' => 1, 'MEMORY' => 1, 'MINUTE' => 1, + 'MODIFY' => 1, 'NUMBER' => 1, 'OFFSET' => 1, 'PARSER' => 1, 'PLUGIN' => 1, + 'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, 'RESUME' => 1, 'ROLLUP' => 1, + 'SECOND' => 1, 'SERIAL' => 1, 'SERVER' => 1, 'SIGNED' => 1, 'SIMPLE' => 1, + 'SOCKET' => 1, 'SONAME' => 1, 'SOUNDS' => 1, 'SOURCE' => 1, 'STARTS' => 1, + 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1, + 'AGAINST' => 1, 'ANALYSE' => 1, 'AUTHORS' => 1, 'CHANGED' => 1, 'CHARSET' => 1, + 'COLUMNS' => 1, 'COMMENT' => 1, 'COMPACT' => 1, 'CONTEXT' => 1, 'CURRENT' => 1, + 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1, 'DYNAMIC' => 1, 'ENGINES' => 1, + 'EXECUTE' => 1, 'GENERAL' => 1, 'HANDLER' => 1, 'INDEXES' => 1, 'INSTALL' => 1, + 'INVOKER' => 1, 'LOGFILE' => 1, 'MIGRATE' => 1, 'NO_WAIT' => 1, 'OPTIONS' => 1, + 'PARTIAL' => 1, 'PLUGINS' => 1, 'POLYGON' => 1, 'PREPARE' => 1, 'PROFILE' => 1, + 'QUARTER' => 1, 'REBUILD' => 1, 'RECOVER' => 1, 'RESTORE' => 1, 'RETURNS' => 1, + 'REVERSE' => 1, 'ROUTINE' => 1, 'SESSION' => 1, 'STORAGE' => 1, 'SUBJECT' => 1, + 'SUSPEND' => 1, 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1, 'USE_FRM' => 1, + 'WRAPPER' => 1, + 'CASCADED' => 1, 'CHECKSUM' => 1, 'COALESCE' => 1, 'CONTAINS' => 1, + 'DATAFILE' => 1, 'DUMPFILE' => 1, 'EXCHANGE' => 1, 'EXTENDED' => 1, + 'FUNCTION' => 1, 'GEOMETRY' => 1, 'LANGUAGE' => 1, 'MAX_ROWS' => 1, + 'MAX_SIZE' => 1, 'MIN_ROWS' => 1, 'NATIONAL' => 1, 'NVARCHAR' => 1, + 'ONE_SHOT' => 1, 'PASSWORD' => 1, 'PRESERVE' => 1, 'PROFILES' => 1, + 'REDOFILE' => 1, 'RELAYLOG' => 1, 'ROLLBACK' => 1, 'SCHEDULE' => 1, + 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1, 'SWITCHES' => 1, + 'TRIGGERS' => 1, 'TRUNCATE' => 1, 'UNDOFILE' => 1, 'WARNINGS' => 1, + 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COLLATION' => 1, 'COMMITTED' => 1, + 'DIRECTORY' => 1, 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, + 'ISOLATION' => 1, 'NODEGROUP' => 1, 'PACK_KEYS' => 1, 'READ_ONLY' => 1, + 'REDUNDANT' => 1, 'ROW_COUNT' => 1, 'SAVEPOINT' => 1, 'SQL_CACHE' => 1, + 'TEMPORARY' => 1, 'TEMPTABLE' => 1, 'UNDEFINED' => 1, 'UNINSTALL' => 1, + 'VARIABLES' => 1, + 'COMPLETION' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1, + 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'GET_FORMAT' => 1, 'IDENTIFIED' => 1, + 'LINESTRING' => 1, 'MASTER_SSL' => 1, 'MULTIPOINT' => 1, 'NDBCLUSTER' => 1, + 'PARTITIONS' => 1, 'PLUGIN_DIR' => 1, 'PRIVILEGES' => 1, 'REORGANIZE' => 1, + 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, 'TABLESPACE' => 1, + 'TABLE_NAME' => 1, + 'COLUMN_NAME' => 1, 'CURSOR_NAME' => 1, 'DIAGNOSTICS' => 1, 'EXTENT_SIZE' => 1, + 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, 'MICROSECOND' => 1, + 'MYSQL_ERRNO' => 1, 'PROCESSLIST' => 1, 'REPLICATION' => 1, 'SCHEMA_NAME' => 1, + 'SQL_TSI_DAY' => 1, 'TRANSACTION' => 1, 'UNCOMMITTED' => 1, + 'CATALOG_NAME' => 1, 'CLASS_ORIGIN' => 1, 'CONTRIBUTORS' => 1, + 'DEFAULT_AUTH' => 1, 'DES_KEY_FILE' => 1, 'INITIAL_SIZE' => 1, + 'MASTER_DELAY' => 1, 'MESSAGE_TEXT' => 1, 'MULTIPOLYGON' => 1, + 'OLD_PASSWORD' => 1, 'PARTITIONING' => 1, 'RELAY_THREAD' => 1, + 'SERIALIZABLE' => 1, 'SQL_NO_CACHE' => 1, 'SQL_TSI_HOUR' => 1, + 'SQL_TSI_WEEK' => 1, 'SQL_TSI_YEAR' => 1, 'SUBPARTITION' => 1, + 'TIMESTAMPADD' => 1, + 'COLUMN_FORMAT' => 1, 'INSERT_METHOD' => 1, 'MASTER_SSL_CA' => 1, + 'RELAY_LOG_POS' => 1, 'SQL_TSI_MONTH' => 1, 'SUBPARTITIONS' => 1, + 'TIMESTAMPDIFF' => 1, 'WEIGHT_STRING' => 1, + 'AUTO_INCREMENT' => 1, 'AVG_ROW_LENGTH' => 1, 'KEY_BLOCK_SIZE' => 1, + 'MASTER_LOG_POS' => 1, 'MASTER_SSL_CRL' => 1, 'MASTER_SSL_KEY' => 1, + 'RELAY_LOG_FILE' => 1, 'SQL_TSI_MINUTE' => 1, 'SQL_TSI_SECOND' => 1, + 'TABLE_CHECKSUM' => 1, 'USER_RESOURCES' => 1, + 'AUTOEXTEND_SIZE' => 1, 'CONSTRAINT_NAME' => 1, 'DELAY_KEY_WRITE' => 1, + 'MASTER_LOG_FILE' => 1, 'MASTER_PASSWORD' => 1, 'MASTER_SSL_CERT' => 1, + 'MULTILINESTRING' => 1, 'SQL_AFTER_GTIDS' => 1, 'SQL_TSI_QUARTER' => 1, + 'SUBCLASS_ORIGIN' => 1, + 'MASTER_SERVER_ID' => 1, 'REDO_BUFFER_SIZE' => 1, 'SQL_BEFORE_GTIDS' => 1, + 'STATS_PERSISTENT' => 1, 'UNDO_BUFFER_SIZE' => 1, + 'CONSTRAINT_SCHEMA' => 1, 'IGNORE_SERVER_IDS' => 1, 'MASTER_SSL_CAPATH' => 1, + 'MASTER_SSL_CIPHER' => 1, 'RETURNED_SQLSTATE' => 1, 'SQL_BUFFER_RESULT' => 1, + 'STATS_AUTO_RECALC' => 1, + 'CONSTRAINT_CATALOG' => 1, 'GEOMETRYCOLLECTION' => 1, 'MASTER_RETRY_COUNT' => 1, + 'MASTER_SSL_CRLPATH' => 1, 'SQL_AFTER_MTS_GAPS' => 1, 'STATS_SAMPLE_PAGES' => 1, + 'MASTER_AUTO_POSITION' => 1, 'MASTER_CONNECT_RETRY' => 1, + 'MAX_QUERIES_PER_HOUR' => 1, 'MAX_UPDATES_PER_HOUR' => 1, + 'MAX_USER_CONNECTIONS' => 1, + 'MASTER_HEARTBEAT_PERIOD' => 1, + 'MAX_CONNECTIONS_PER_HOUR' => 1, + + 'AS' => 3, 'BY' => 3, 'IF' => 3, 'IN' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, + 'TO' => 3, + 'ADD' => 3, 'ALL' => 3, 'AND' => 3, 'ASC' => 3, 'DEC' => 3, 'DIV' => 3, + 'FOR' => 3, 'GET' => 3, 'MOD' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, + 'SSL' => 3, 'USE' => 3, 'XOR' => 3, + 'BOTH' => 3, 'CALL' => 3, 'CASE' => 3, 'DESC' => 3, 'DROP' => 3, 'DUAL' => 3, + 'EACH' => 3, 'ELSE' => 3, 'EXIT' => 3, 'FROM' => 3, 'INT1' => 3, 'INT2' => 3, + 'INT3' => 3, 'INT4' => 3, 'INT8' => 3, 'INTO' => 3, 'JOIN' => 3, 'KEYS' => 3, + 'KILL' => 3, 'LEFT' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, + 'LOOP' => 3, 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, + 'UNDO' => 3, 'WHEN' => 3, 'WITH' => 3, + 'ALTER' => 3, 'CHECK' => 3, 'CROSS' => 3, 'FALSE' => 3, 'FETCH' => 3, + 'FORCE' => 3, 'GRANT' => 3, 'GROUP' => 3, 'INNER' => 3, 'INOUT' => 3, + 'LEAVE' => 3, 'LIMIT' => 3, 'LINES' => 3, 'MATCH' => 3, 'ORDER' => 3, + 'OUTER' => 3, 'PURGE' => 3, 'RANGE' => 3, 'READS' => 3, 'RIGHT' => 3, + 'RLIKE' => 3, 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, + 'WHERE' => 3, 'WHILE' => 3, 'WRITE' => 3, + 'BEFORE' => 3, 'CHANGE' => 3, 'COLUMN' => 3, 'CREATE' => 3, 'CURSOR' => 3, + 'DELETE' => 3, 'ELSEIF' => 3, 'EXISTS' => 3, 'FLOAT4' => 3, 'FLOAT8' => 3, + 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'INSERT' => 3, 'LINEAR' => 3, + 'OPTION' => 3, 'REGEXP' => 3, 'RENAME' => 3, 'REPEAT' => 3, 'RETURN' => 3, + 'REVOKE' => 3, 'SCHEMA' => 3, 'SELECT' => 3, 'SIGNAL' => 3, 'UNLOCK' => 3, + 'UPDATE' => 3, 'VALUES' => 3, + 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'CONVERT' => 3, + 'DECLARE' => 3, 'DEFAULT' => 3, 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, + 'FOREIGN' => 3, 'ITERATE' => 3, 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, + 'PRIMARY' => 3, 'RELEASE' => 3, 'REPLACE' => 3, 'REQUIRE' => 3, 'SCHEMAS' => 3, + 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3, + 'CONTINUE' => 3, 'DATABASE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, + 'DISTINCT' => 3, 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MAXVALUE' => 3, + 'MODIFIES' => 3, 'OPTIMIZE' => 3, 'RESIGNAL' => 3, 'RESTRICT' => 3, + 'SPECIFIC' => 3, 'SQLSTATE' => 3, 'STARTING' => 3, 'TRAILING' => 3, + 'UNSIGNED' => 3, 'UTC_DATE' => 3, 'UTC_TIME' => 3, 'ZEROFILL' => 3, + 'CONDITION' => 3, 'DATABASES' => 3, 'LOCALTIME' => 3, 'MIDDLEINT' => 3, + 'PARTITION' => 3, 'PRECISION' => 3, 'PROCEDURE' => 3, 'SENSITIVE' => 3, + 'SEPARATOR' => 3, + 'ACCESSIBLE' => 3, 'ASENSITIVE' => 3, 'CONSTRAINT' => 3, 'DAY_MINUTE' => 3, + 'DAY_SECOND' => 3, 'OPTIONALLY' => 3, 'READ_WRITE' => 3, 'REFERENCES' => 3, + 'SQLWARNING' => 3, 'TERMINATED' => 3, 'YEAR_MONTH' => 3, + 'DISTINCTROW' => 3, 'HOUR_MINUTE' => 3, 'HOUR_SECOND' => 3, 'INSENSITIVE' => 3, + 'MASTER_BIND' => 3, + 'CURRENT_DATE' => 3, 'CURRENT_TIME' => 3, 'CURRENT_USER' => 3, + 'LOW_PRIORITY' => 3, 'SQLEXCEPTION' => 3, 'VARCHARACTER' => 3, + 'DETERMINISTIC' => 3, 'HIGH_PRIORITY' => 3, 'MINUTE_SECOND' => 3, + 'STRAIGHT_JOIN' => 3, 'UTC_TIMESTAMP' => 3, + 'IO_AFTER_GTIDS' => 3, 'LOCALTIMESTAMP' => 3, 'SQL_BIG_RESULT' => 3, + 'DAY_MICROSECOND' => 3, 'IO_BEFORE_GTIDS' => 3, + 'HOUR_MICROSECOND' => 3, 'SQL_SMALL_RESULT' => 3, + 'CURRENT_TIMESTAMP' => 3, + 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3, + 'SQL_CALC_FOUND_ROWS' => 3, + 'MASTER_SSL_VERIFY_SERVER_CERT' => 3, + + 'NOT NULL' => 5, + 'ON UPDATE' => 5, + 'CHARACTER SET' => 5, 'IF NOT EXISTS' => 5, + 'DATA DIRECTORY' => 5, + 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, + 'DEFAULT CHARACTER SET' => 5, + + 'XML' => 9, + 'DATE' => 9, 'ENUM' => 9, 'TEXT' => 9, 'TIME' => 9, 'YEAR' => 9, + 'ARRAY' => 9, + 'BOOLEAN' => 9, + 'DATETIME' => 9, 'MULTISET' => 9, + 'TIMESTAMP' => 9, + + 'INT' => 11, 'SET' => 11, + 'BLOB' => 11, 'CHAR' => 11, 'REAL' => 11, + 'FLOAT' => 11, + 'BIGINT' => 11, 'BINARY' => 11, 'DOUBLE' => 11, + 'DECIMAL' => 11, 'INTEGER' => 11, 'NUMERIC' => 11, 'TINYINT' => 11, 'VARCHAR' => 11, + 'INTERVAL' => 11, 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, + 'TINYBLOB' => 11, 'TINYTEXT' => 11, + 'CHARACTER' => 11, 'MEDIUMINT' => 11, 'VARBINARY' => 11, + 'MEDIUMBLOB' => 11, 'MEDIUMTEXT' => 11, + + 'BINARY VARYING' => 13, + + 'KEY' => 19, + 'INDEX' => 19, + 'UNIQUE' => 19, + + 'INDEX KEY' => 21, + 'UNIQUE KEY' => 21, + 'FOREIGN KEY' => 21, 'PRIMARY KEY' => 21, 'SPATIAL KEY' => 21, + 'FULLTEXT KEY' => 21, 'UNIQUE INDEX' => 21, + 'SPATIAL INDEX' => 21, + 'FULLTEXT INDEX' => 21, + + ); +} diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50700.php b/libraries/sql-parser/src/Contexts/ContextMySql50700.php new file mode 100644 index 0000000000..db047b1c46 --- /dev/null +++ b/libraries/sql-parser/src/Contexts/ContextMySql50700.php @@ -0,0 +1,211 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class ContextMySql50700 extends Context +{ + + public static $KEYWORDS = array( + + 'AT' => 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, + 'ANY' => 1, 'AVG' => 1, 'BIT' => 1, 'CPU' => 1, 'DAY' => 1, 'END' => 1, + 'IPC' => 1, 'NDB' => 1, 'NEW' => 1, 'ONE' => 1, 'ROW' => 1, 'XID' => 1, + 'BOOL' => 1, 'BYTE' => 1, 'CODE' => 1, 'CUBE' => 1, 'DATA' => 1, 'DISK' => 1, + 'ENDS' => 1, 'FAST' => 1, 'FILE' => 1, 'FULL' => 1, 'HASH' => 1, 'HELP' => 1, + 'HOST' => 1, 'HOUR' => 1, 'LAST' => 1, 'LESS' => 1, 'LIST' => 1, 'LOGS' => 1, + 'MODE' => 1, 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'ONLY' => 1, 'OPEN' => 1, + 'PAGE' => 1, 'PORT' => 1, 'PREV' => 1, 'ROWS' => 1, 'SLOW' => 1, 'SOME' => 1, + 'STOP' => 1, 'THAN' => 1, 'TYPE' => 1, 'USER' => 1, 'VIEW' => 1, 'WAIT' => 1, + 'WEEK' => 1, 'WORK' => 1, 'X509' => 1, + 'AFTER' => 1, 'ASCII' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, + 'CACHE' => 1, 'CHAIN' => 1, 'CLOSE' => 1, 'ERROR' => 1, 'EVENT' => 1, + 'EVERY' => 1, 'FIRST' => 1, 'FIXED' => 1, 'FLUSH' => 1, 'FOUND' => 1, + 'HOSTS' => 1, 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, 'MERGE' => 1, + 'MONTH' => 1, 'MUTEX' => 1, 'NAMES' => 1, 'NCHAR' => 1, 'NEVER' => 1, + 'OWNER' => 1, 'PHASE' => 1, 'POINT' => 1, 'PROXY' => 1, 'QUERY' => 1, + 'QUICK' => 1, 'RELAY' => 1, 'RESET' => 1, 'RTREE' => 1, 'SHARE' => 1, + 'SLAVE' => 1, 'START' => 1, 'SUPER' => 1, 'SWAPS' => 1, 'TYPES' => 1, + 'UNTIL' => 1, 'VALUE' => 1, + 'ACTION' => 1, 'ALWAYS' => 1, 'BACKUP' => 1, 'BINLOG' => 1, 'CIPHER' => 1, + 'CLIENT' => 1, 'COMMIT' => 1, 'ENABLE' => 1, 'ENGINE' => 1, 'ERRORS' => 1, + 'ESCAPE' => 1, 'EVENTS' => 1, 'EXPIRE' => 1, 'EXPORT' => 1, 'FAULTS' => 1, + 'FIELDS' => 1, 'FILTER' => 1, 'FORMAT' => 1, 'GLOBAL' => 1, 'GRANTS' => 1, + 'IMPORT' => 1, 'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1, 'MEDIUM' => 1, + 'MEMORY' => 1, 'MINUTE' => 1, 'MODIFY' => 1, 'NUMBER' => 1, 'OFFSET' => 1, + 'PARSER' => 1, 'PLUGIN' => 1, 'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, + 'RESUME' => 1, 'ROLLUP' => 1, 'SECOND' => 1, 'SERIAL' => 1, 'SERVER' => 1, + 'SIGNED' => 1, 'SIMPLE' => 1, 'SOCKET' => 1, 'SONAME' => 1, 'SOUNDS' => 1, + 'SOURCE' => 1, 'STARTS' => 1, 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1, + 'ACCOUNT' => 1, 'AGAINST' => 1, 'ANALYSE' => 1, 'CHANGED' => 1, 'CHANNEL' => 1, + 'CHARSET' => 1, 'COLUMNS' => 1, 'COMMENT' => 1, 'COMPACT' => 1, 'CONTEXT' => 1, + 'CURRENT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1, 'DYNAMIC' => 1, + 'ENGINES' => 1, 'EXECUTE' => 1, 'FOLLOWS' => 1, 'GENERAL' => 1, 'HANDLER' => 1, + 'INDEXES' => 1, 'INSTALL' => 1, 'INVOKER' => 1, 'LOGFILE' => 1, 'MIGRATE' => 1, + 'NO_WAIT' => 1, 'OPTIONS' => 1, 'PARTIAL' => 1, 'PLUGINS' => 1, 'POLYGON' => 1, + 'PREPARE' => 1, 'PROFILE' => 1, 'QUARTER' => 1, 'REBUILD' => 1, 'RECOVER' => 1, + 'RESTORE' => 1, 'RETURNS' => 1, 'REVERSE' => 1, 'ROUTINE' => 1, 'SESSION' => 1, + 'STACKED' => 1, 'STORAGE' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1, 'UNICODE' => 1, + 'UNKNOWN' => 1, 'UPGRADE' => 1, 'USE_FRM' => 1, 'WITHOUT' => 1, 'WRAPPER' => 1, + 'CASCADED' => 1, 'CHECKSUM' => 1, 'COALESCE' => 1, 'CONTAINS' => 1, + 'DATAFILE' => 1, 'DUMPFILE' => 1, 'EXCHANGE' => 1, 'EXTENDED' => 1, + 'FUNCTION' => 1, 'GEOMETRY' => 1, 'LANGUAGE' => 1, 'MAX_ROWS' => 1, + 'MAX_SIZE' => 1, 'MIN_ROWS' => 1, 'NATIONAL' => 1, 'NVARCHAR' => 1, + 'PASSWORD' => 1, 'PRECEDES' => 1, 'PRESERVE' => 1, 'PROFILES' => 1, + 'REDOFILE' => 1, 'RELAYLOG' => 1, 'ROLLBACK' => 1, 'SCHEDULE' => 1, + 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1, 'SWITCHES' => 1, + 'TRIGGERS' => 1, 'TRUNCATE' => 1, 'UNDOFILE' => 1, 'WARNINGS' => 1, + 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COLLATION' => 1, 'COMMITTED' => 1, + 'DIRECTORY' => 1, 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, + 'ISOLATION' => 1, 'NODEGROUP' => 1, 'PACK_KEYS' => 1, 'READ_ONLY' => 1, + 'REDUNDANT' => 1, 'ROW_COUNT' => 1, 'SAVEPOINT' => 1, 'SQL_CACHE' => 1, + 'TEMPORARY' => 1, 'TEMPTABLE' => 1, 'UNDEFINED' => 1, 'UNINSTALL' => 1, + 'VARIABLES' => 1, + 'COMPLETION' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1, + 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'GET_FORMAT' => 1, 'IDENTIFIED' => 1, + 'LINESTRING' => 1, 'MASTER_SSL' => 1, 'MULTIPOINT' => 1, 'NDBCLUSTER' => 1, + 'PARTITIONS' => 1, 'PLUGIN_DIR' => 1, 'PRIVILEGES' => 1, 'REORGANIZE' => 1, + 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, 'TABLESPACE' => 1, + 'TABLE_NAME' => 1, 'VALIDATION' => 1, + 'COLUMN_NAME' => 1, 'COMPRESSION' => 1, 'CURSOR_NAME' => 1, 'DIAGNOSTICS' => 1, + 'EXTENT_SIZE' => 1, 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, + 'MICROSECOND' => 1, 'MYSQL_ERRNO' => 1, 'NONBLOCKING' => 1, 'PROCESSLIST' => 1, + 'REPLICATION' => 1, 'SCHEMA_NAME' => 1, 'SQL_TSI_DAY' => 1, 'TRANSACTION' => 1, + 'UNCOMMITTED' => 1, + 'CATALOG_NAME' => 1, 'CLASS_ORIGIN' => 1, 'DEFAULT_AUTH' => 1, + 'DES_KEY_FILE' => 1, 'INITIAL_SIZE' => 1, 'MASTER_DELAY' => 1, + 'MESSAGE_TEXT' => 1, 'MULTIPOLYGON' => 1, 'OLD_PASSWORD' => 1, + 'PARTITIONING' => 1, 'RELAY_THREAD' => 1, 'SERIALIZABLE' => 1, + 'SQL_NO_CACHE' => 1, 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1, + 'SQL_TSI_YEAR' => 1, 'SUBPARTITION' => 1, 'TIMESTAMPADD' => 1, + 'COLUMN_FORMAT' => 1, 'INSERT_METHOD' => 1, 'MASTER_SSL_CA' => 1, + 'RELAY_LOG_POS' => 1, 'SQL_TSI_MONTH' => 1, 'SUBPARTITIONS' => 1, + 'TIMESTAMPDIFF' => 1, 'WEIGHT_STRING' => 1, + 'AUTO_INCREMENT' => 1, 'AVG_ROW_LENGTH' => 1, 'KEY_BLOCK_SIZE' => 1, + 'MASTER_LOG_POS' => 1, 'MASTER_SSL_CRL' => 1, 'MASTER_SSL_KEY' => 1, + 'RELAY_LOG_FILE' => 1, 'SQL_TSI_MINUTE' => 1, 'SQL_TSI_SECOND' => 1, + 'TABLE_CHECKSUM' => 1, 'USER_RESOURCES' => 1, + 'AUTOEXTEND_SIZE' => 1, 'CONSTRAINT_NAME' => 1, 'DELAY_KEY_WRITE' => 1, + 'FILE_BLOCK_SIZE' => 1, 'MASTER_LOG_FILE' => 1, 'MASTER_PASSWORD' => 1, + 'MASTER_SSL_CERT' => 1, 'MULTILINESTRING' => 1, 'PARSE_GCOL_EXPR' => 1, + 'REPLICATE_DO_DB' => 1, 'SQL_AFTER_GTIDS' => 1, 'SQL_TSI_QUARTER' => 1, + 'SUBCLASS_ORIGIN' => 1, + 'MASTER_SERVER_ID' => 1, 'REDO_BUFFER_SIZE' => 1, 'SQL_BEFORE_GTIDS' => 1, + 'STATS_PERSISTENT' => 1, 'UNDO_BUFFER_SIZE' => 1, + 'CONSTRAINT_SCHEMA' => 1, 'GROUP_REPLICATION' => 1, 'IGNORE_SERVER_IDS' => 1, + 'MASTER_SSL_CAPATH' => 1, 'MASTER_SSL_CIPHER' => 1, 'RETURNED_SQLSTATE' => 1, + 'SQL_BUFFER_RESULT' => 1, 'STATS_AUTO_RECALC' => 1, + 'CONSTRAINT_CATALOG' => 1, 'GEOMETRYCOLLECTION' => 1, 'MASTER_RETRY_COUNT' => 1, + 'MASTER_SSL_CRLPATH' => 1, 'MAX_STATEMENT_TIME' => 1, 'REPLICATE_DO_TABLE' => 1, + 'SQL_AFTER_MTS_GAPS' => 1, 'STATS_SAMPLE_PAGES' => 1, + 'REPLICATE_IGNORE_DB' => 1, + 'MASTER_AUTO_POSITION' => 1, 'MASTER_CONNECT_RETRY' => 1, + 'MAX_QUERIES_PER_HOUR' => 1, 'MAX_UPDATES_PER_HOUR' => 1, + 'MAX_USER_CONNECTIONS' => 1, 'REPLICATE_REWRITE_DB' => 1, + 'REPLICATE_IGNORE_TABLE' => 1, + 'MASTER_HEARTBEAT_PERIOD' => 1, 'REPLICATE_WILD_DO_TABLE' => 1, + 'MAX_CONNECTIONS_PER_HOUR' => 1, + 'REPLICATE_WILD_IGNORE_TABLE' => 1, + + 'AS' => 3, 'BY' => 3, 'IF' => 3, 'IN' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, + 'TO' => 3, + 'ADD' => 3, 'ALL' => 3, 'AND' => 3, 'ASC' => 3, 'DEC' => 3, 'DIV' => 3, + 'FOR' => 3, 'GET' => 3, 'MOD' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, + 'SSL' => 3, 'USE' => 3, 'XOR' => 3, + 'BOTH' => 3, 'CALL' => 3, 'CASE' => 3, 'DESC' => 3, 'DROP' => 3, 'DUAL' => 3, + 'EACH' => 3, 'ELSE' => 3, 'EXIT' => 3, 'FROM' => 3, 'INT1' => 3, 'INT2' => 3, + 'INT3' => 3, 'INT4' => 3, 'INT8' => 3, 'INTO' => 3, 'JOIN' => 3, 'KEYS' => 3, + 'KILL' => 3, 'LEFT' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, + 'LOOP' => 3, 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, + 'UNDO' => 3, 'WHEN' => 3, 'WITH' => 3, + 'ALTER' => 3, 'CHECK' => 3, 'CROSS' => 3, 'FALSE' => 3, 'FETCH' => 3, + 'FORCE' => 3, 'GRANT' => 3, 'GROUP' => 3, 'INNER' => 3, 'INOUT' => 3, + 'LEAVE' => 3, 'LIMIT' => 3, 'LINES' => 3, 'MATCH' => 3, 'ORDER' => 3, + 'OUTER' => 3, 'PURGE' => 3, 'RANGE' => 3, 'READS' => 3, 'RIGHT' => 3, + 'RLIKE' => 3, 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, + 'WHERE' => 3, 'WHILE' => 3, 'WRITE' => 3, + 'BEFORE' => 3, 'CHANGE' => 3, 'COLUMN' => 3, 'CREATE' => 3, 'CURSOR' => 3, + 'DELETE' => 3, 'ELSEIF' => 3, 'EXISTS' => 3, 'FLOAT4' => 3, 'FLOAT8' => 3, + 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'INSERT' => 3, 'LINEAR' => 3, + 'OPTION' => 3, 'REGEXP' => 3, 'RENAME' => 3, 'REPEAT' => 3, 'RETURN' => 3, + 'REVOKE' => 3, 'SCHEMA' => 3, 'SELECT' => 3, 'SIGNAL' => 3, 'STORED' => 3, + 'UNLOCK' => 3, 'UPDATE' => 3, 'VALUES' => 3, + 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'CONVERT' => 3, + 'DECLARE' => 3, 'DEFAULT' => 3, 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, + 'FOREIGN' => 3, 'ITERATE' => 3, 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, + 'PRIMARY' => 3, 'RELEASE' => 3, 'REPLACE' => 3, 'REQUIRE' => 3, 'SCHEMAS' => 3, + 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3, 'VIRTUAL' => 3, + 'CONTINUE' => 3, 'DATABASE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, + 'DISTINCT' => 3, 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MAXVALUE' => 3, + 'MODIFIES' => 3, 'OPTIMIZE' => 3, 'RESIGNAL' => 3, 'RESTRICT' => 3, + 'SPECIFIC' => 3, 'SQLSTATE' => 3, 'STARTING' => 3, 'TRAILING' => 3, + 'UNSIGNED' => 3, 'UTC_DATE' => 3, 'UTC_TIME' => 3, 'ZEROFILL' => 3, + 'CONDITION' => 3, 'DATABASES' => 3, 'GENERATED' => 3, 'LOCALTIME' => 3, + 'MIDDLEINT' => 3, 'PARTITION' => 3, 'PRECISION' => 3, 'PROCEDURE' => 3, + 'SENSITIVE' => 3, 'SEPARATOR' => 3, + 'ACCESSIBLE' => 3, 'ASENSITIVE' => 3, 'CONSTRAINT' => 3, 'DAY_MINUTE' => 3, + 'DAY_SECOND' => 3, 'OPTIONALLY' => 3, 'READ_WRITE' => 3, 'REFERENCES' => 3, + 'SQLWARNING' => 3, 'TERMINATED' => 3, 'YEAR_MONTH' => 3, + 'DISTINCTROW' => 3, 'HOUR_MINUTE' => 3, 'HOUR_SECOND' => 3, 'INSENSITIVE' => 3, + 'MASTER_BIND' => 3, + 'CURRENT_DATE' => 3, 'CURRENT_TIME' => 3, 'CURRENT_USER' => 3, + 'LOW_PRIORITY' => 3, 'SQLEXCEPTION' => 3, 'VARCHARACTER' => 3, + 'DETERMINISTIC' => 3, 'HIGH_PRIORITY' => 3, 'MINUTE_SECOND' => 3, + 'STRAIGHT_JOIN' => 3, 'UTC_TIMESTAMP' => 3, + 'IO_AFTER_GTIDS' => 3, 'LOCALTIMESTAMP' => 3, 'SQL_BIG_RESULT' => 3, + 'DAY_MICROSECOND' => 3, 'IO_BEFORE_GTIDS' => 3, 'OPTIMIZER_COSTS' => 3, + 'HOUR_MICROSECOND' => 3, 'SQL_SMALL_RESULT' => 3, + 'CURRENT_TIMESTAMP' => 3, + 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3, + 'SQL_CALC_FOUND_ROWS' => 3, + 'MASTER_SSL_VERIFY_SERVER_CERT' => 3, + + 'NOT NULL' => 5, + 'ON UPDATE' => 5, + 'CHARACTER SET' => 5, 'IF NOT EXISTS' => 5, + 'DATA DIRECTORY' => 5, + 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, + 'DEFAULT CHARACTER SET' => 5, + + 'XML' => 9, + 'DATE' => 9, 'ENUM' => 9, 'TEXT' => 9, 'TIME' => 9, 'YEAR' => 9, + 'ARRAY' => 9, + 'BOOLEAN' => 9, + 'DATETIME' => 9, 'MULTISET' => 9, + 'TIMESTAMP' => 9, + + 'INT' => 11, 'SET' => 11, + 'BLOB' => 11, 'CHAR' => 11, 'REAL' => 11, + 'FLOAT' => 11, + 'BIGINT' => 11, 'BINARY' => 11, 'DOUBLE' => 11, + 'DECIMAL' => 11, 'INTEGER' => 11, 'NUMERIC' => 11, 'TINYINT' => 11, 'VARCHAR' => 11, + 'INTERVAL' => 11, 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, + 'TINYBLOB' => 11, 'TINYTEXT' => 11, + 'CHARACTER' => 11, 'MEDIUMINT' => 11, 'VARBINARY' => 11, + 'MEDIUMBLOB' => 11, 'MEDIUMTEXT' => 11, + + 'BINARY VARYING' => 13, + + 'KEY' => 19, + 'INDEX' => 19, + 'UNIQUE' => 19, + + 'INDEX KEY' => 21, + 'UNIQUE KEY' => 21, + 'FOREIGN KEY' => 21, 'PRIMARY KEY' => 21, 'SPATIAL KEY' => 21, + 'FULLTEXT KEY' => 21, 'UNIQUE INDEX' => 21, + 'SPATIAL INDEX' => 21, + 'FULLTEXT INDEX' => 21, + + ); +} diff --git a/libraries/sql-parser/src/Fragments/DataTypeFragment.php b/libraries/sql-parser/src/Fragments/DataTypeFragment.php index 7baefddb48..740fbfd85d 100644 --- a/libraries/sql-parser/src/Fragments/DataTypeFragment.php +++ b/libraries/sql-parser/src/Fragments/DataTypeFragment.php @@ -88,8 +88,8 @@ class DataTypeFragment extends Fragment } if ($state === 0) { - $ret->name = $token->value; - if (!isset(Context::$DATA_TYPES[$token->value])) { + $ret->name = strtoupper($token->value); + if (($token->type !== Token::TYPE_KEYWORD) || (!($token->flags & Token::FLAG_KEYWORD_DATA_TYPE))) { $parser->error('Unrecognized data type.', $token); } $state = 1; diff --git a/libraries/sql-parser/src/Fragments/FieldDefFragment.php b/libraries/sql-parser/src/Fragments/FieldDefFragment.php index ba4b6dcd16..f4a08bdc8d 100644 --- a/libraries/sql-parser/src/Fragments/FieldDefFragment.php +++ b/libraries/sql-parser/src/Fragments/FieldDefFragment.php @@ -38,6 +38,7 @@ class FieldDefFragment extends Fragment 'UNIQUE KEY' => 4, 'COMMENT' => array(5, 'var'), 'COLUMN_FORMAT' => array(6, 'var'), + 'ON UPDATE' => array(7, 'var'), ); /** @@ -133,16 +134,14 @@ class FieldDefFragment extends Fragment } continue; } elseif ($state === 1) { - if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { - if ($token->value === 'CONSTRAINT') { - $state = 4; - } elseif (isset(Context::$KEY_TYPES[$token->value])) { - $expr->type = $token->value; - $state = 5; - } else { - $parser->error('Unexpected keyword.', $token); - break; // TODO: Skip to the end of the query. - } + if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'CONSTRAINT')) { + $state = 4; + } elseif (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_KEY)) { + $expr->type = $token->value; + $state = 5; + } elseif (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { + $parser->error('Unexpected keyword.', $token); + break; // TODO: Skip to the end of the query. } else { $expr->name = $token->value; $state = 2; @@ -154,17 +153,23 @@ class FieldDefFragment extends Fragment $expr->options = OptionsFragment::parse($parser, $list, static::$FIELD_OPTIONS); $state = 6; } elseif ($state === 4) { - if (!isset(Context::$KEY_TYPES[$token->value])) { + if (($token->type !== Token::TYPE_KEYWORD) || (!($token->flags & Token::FLAG_KEYWORD_KEY))) { $expr->name = $token->value; } else { $expr->type = $token->value; $state = 5; } } elseif ($state === 5) { - $expr->indexes = ArrayFragment::parse($parser, $list); - $state = 6; + if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { + $expr->indexes = ArrayFragment::parse($parser, $list); + $state = 6; + } else { + $expr->name = $token->value; + } } elseif ($state === 6) { - $ret[] = $expr; + if (!empty($expr->type)) { + $ret[] = $expr; + } $expr = new FieldDefFragment(); if ($token->value === ',') { $state = 1; @@ -178,7 +183,7 @@ class FieldDefFragment extends Fragment } // Last iteration was not saved. - if (!empty($expr->name)) { + if (!empty($expr->type)) { $ret[] = $expr; } diff --git a/libraries/sql-parser/src/Fragments/OptionsFragment.php b/libraries/sql-parser/src/Fragments/OptionsFragment.php index f002f5bd32..dfb4fc98fb 100644 --- a/libraries/sql-parser/src/Fragments/OptionsFragment.php +++ b/libraries/sql-parser/src/Fragments/OptionsFragment.php @@ -70,30 +70,24 @@ class OptionsFragment extends Fragment continue; } - if (isset($options[strtoupper($token->value)])) { - $lastOption = $options[strtoupper($token->value)]; - $lastOptionId = is_array($lastOption) ? $lastOption[0] : $lastOption; + if ($lastOption === null) { + if (isset($options[strtoupper($token->value)])) { + $lastOption = $options[strtoupper($token->value)]; + $lastOptionId = is_array($lastOption) ? $lastOption[0] : $lastOption; - // Checking for option conflicts. - // For example, in `SELECT` statements the keywords `ALL` and `DISTINCT` - // conflict and if used together, they produce an invalid query. - // Usually, tokens can be identified in the array by the option ID, - // but if conflicts occur, a psuedo option ID is used. - // The first pseudo duplicate ID is the maximum value of the real - // options (e.g. if there are 5 options, the first fake ID is 6). - if (isset($ret->options[$lastOptionId])) { - $parser->error('This option conflicts with \'' . $ret->options[$lastOptionId] . '\'.', $token); - $lastOptionId = $lastAssignedId++; - } - } else { - // There is no option to be processed. - if ($lastOption === null) { - break; - } - - // The only keywords that are expected are those which are - // options. - if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { + // Checking for option conflicts. + // For example, in `SELECT` statements the keywords `ALL` and `DISTINCT` + // conflict and if used together, they produce an invalid query. + // Usually, tokens can be identified in the array by the option ID, + // but if conflicts occur, a psuedo option ID is used. + // The first pseudo duplicate ID is the maximum value of the real + // options (e.g. if there are 5 options, the first fake ID is 6). + if (isset($ret->options[$lastOptionId])) { + $parser->error('This option conflicts with \'' . $ret->options[$lastOptionId] . '\'.', $token); + $lastOptionId = $lastAssignedId++; + } + } else { + // There is no option to be processed. break; } } diff --git a/libraries/sql-parser/src/Token.php b/libraries/sql-parser/src/Token.php index 5a378ca0e4..867976c2bc 100644 --- a/libraries/sql-parser/src/Token.php +++ b/libraries/sql-parser/src/Token.php @@ -114,9 +114,12 @@ class Token const TYPE_DELIMITER = 9; // Flags that describe the tokens in more detail. - const FLAG_KEYWORD_RESERVED = 1; - const FLAG_KEYWORD_UNRESERVED = 2; + // All keywords must have flag 1 so `Context::isKeyword` method doesn't + // require strict comparison. + const FLAG_KEYWORD_RESERVED = 2; const FLAG_KEYWORD_COMPOSED = 4; + const FLAG_KEYWORD_DATA_TYPE = 8; + const FLAG_KEYWORD_KEY = 16; // Numbers related flags. const FLAG_NUMBER_HEX = 1; @@ -207,10 +210,12 @@ class Token { switch ($this->type) { case Token::TYPE_KEYWORD: - if ($this->flags & Token::FLAG_KEYWORD_RESERVED) { - return strtoupper($this->token); + if (!($this->flags & Token::FLAG_KEYWORD_RESERVED)) { + // Unreserved keywords should stay the way they are because they + // might represent field names. + return $this->token; } - return $this->token; + return strtoupper($this->token); case Token::TYPE_WHITESPACE: return ' '; case Token::TYPE_BOOL: diff --git a/libraries/sql-parser/src/Utils/Misc.php b/libraries/sql-parser/src/Utils/Misc.php index a29951e6e8..22227a8b6e 100644 --- a/libraries/sql-parser/src/Utils/Misc.php +++ b/libraries/sql-parser/src/Utils/Misc.php @@ -19,12 +19,12 @@ class Misc /** * Gets a list of all aliases and their original names. * - * @param SelectStatement $tree The tree that was generated after parsing. - * @param string $db The name of the database. + * @param SelectStatement $tree The tree that was generated after parsing. + * @param string $database The name of the database. * * @return array */ - public static function getAliases(SelectStatement $tree, $db) + public static function getAliases(SelectStatement $tree, $database) { $retval = array(); @@ -34,7 +34,7 @@ class Misc && (!empty($tree->join->expr->alias)) ) { $thisDb = empty($tree->join->expr->database) ? - $db : $tree->join->expr->database; + $database : $tree->join->expr->database; $retval = array( $thisDb => array( @@ -56,7 +56,7 @@ class Misc continue; } - $thisDb = empty($expr->database) ? $db : $expr->database; + $thisDb = empty($expr->database) ? $database : $expr->database; if (!isset($retval[$thisDb])) { $retval[$thisDb] = array( @@ -83,7 +83,7 @@ class Misc continue; } - $thisDb = empty($expr->database) ? $db : $expr->database; + $thisDb = empty($expr->database) ? $database : $expr->database; if (empty($expr->table)) { foreach ($retval[$thisDb]['tables'] as &$table) { diff --git a/libraries/sql-parser/src/Utils/Routine.php b/libraries/sql-parser/src/Utils/Routine.php index f234d97b55..9bc10f7546 100644 --- a/libraries/sql-parser/src/Utils/Routine.php +++ b/libraries/sql-parser/src/Utils/Routine.php @@ -101,6 +101,7 @@ class Routine 'name' => array(), 'type' => array(), 'length' => array(), + 'length_arr' => array(), 'opts' => array(), ); @@ -110,6 +111,7 @@ class Routine $retval['name'][$idx] = $param->name; $retval['type'][$idx] = $param->type->name; $retval['length'][$idx] = implode(',', $param->type->size); + $retval['length_arr'][$idx] = $param->type->size; $retval['opts'][$idx] = array(); foreach ($param->type->options->options as $opt) { $retval['opts'][$idx][] = is_string($opt) ? diff --git a/libraries/sql-parser/src/Utils/Table.php b/libraries/sql-parser/src/Utils/Table.php new file mode 100644 index 0000000000..7560f9d07a --- /dev/null +++ b/libraries/sql-parser/src/Utils/Table.php @@ -0,0 +1,69 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class Table +{ + + public static function getFields(CreateStatement $tree) + { + if (($tree->fields === null) || (!$tree->options->has('TABLE'))) { + return array(); + } + + $ret = array(); + + foreach ($tree->fields as $field) { + + // Skipping keys. + if (is_string($field->type)) { + continue; + } + + $ret[$field->name] = array( + 'type' => $field->type->name, + 'timestamp_not_null' => false, + ); + + if ($field->options) { + + if ($field->type->name === 'TIMESTAMP') { + if ($field->options->has('NOT NULL')) { + $ret[$field->name]['timestamp_not_null'] = true; + } + } + + if (($option = $field->options->has('DEFAULT'))) { + $ret[$field->name]['default_value'] = $option; + if ($option === 'CURRENT_TIMESTAMP') { + $ret[$field->name]['default_current_timestamp'] = true; + } + } + + if (($option = $field->options->has('ON UPDATE'))) { + if ($option === 'CURRENT_TIMESTAMP') { + $ret[$field->name]['on_update_current_timestamp'] = true; + } + } + } + + } + + return $ret; + } +} From 6c3ccb2d5643663ff4d1104b18b73e4b856119c3 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Mon, 22 Jun 2015 22:28:33 +0300 Subject: [PATCH 19/57] Use new parser in routines' execute form. Signed-off-by: Dan Ungureanu --- libraries/rte/rte_routines.lib.php | 39 ++++++++----------- .../rte/PMA_RTN_getExecuteForm_test.php | 16 ++++++++ 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/libraries/rte/rte_routines.lib.php b/libraries/rte/rte_routines.lib.php index 73980f41c4..8cb00379a0 100644 --- a/libraries/rte/rte_routines.lib.php +++ b/libraries/rte/rte_routines.lib.php @@ -520,13 +520,14 @@ function PMA_RTN_getDataFromName($name, $type, $all = true) $routineStatement = $parser->statements[0]; $params = SqlParser\Utils\Routine::getParameters($routineStatement); - $retval['item_num_params'] = $params['num']; - $retval['item_param_dir'] = $params['dir']; - $retval['item_param_name'] = $params['name']; - $retval['item_param_type'] = $params['type']; - $retval['item_param_length'] = $params['length']; - $retval['item_param_opts_num'] = $params['opts']; - $retval['item_param_opts_text'] = $params['opts']; + $retval['item_num_params'] = $params['num']; + $retval['item_param_dir'] = $params['dir']; + $retval['item_param_name'] = $params['name']; + $retval['item_param_type'] = $params['type']; + $retval['item_param_length'] = $params['length']; + $retval['item_param_length_arr'] = $params['length_arr']; + $retval['item_param_opts_num'] = $params['opts']; + $retval['item_param_opts_text'] = $params['opts']; // Get extra data if (!$all) { @@ -538,8 +539,8 @@ function PMA_RTN_getDataFromName($name, $type, $all = true) } else { $retval['item_type_toggle'] = 'FUNCTION'; } - $retval['item_returntype'] = ''; - $retval['item_returnlength'] = ''; + $retval['item_returntype'] = ''; + $retval['item_returnlength'] = ''; $retval['item_returnopts_num'] = ''; $retval['item_returnopts_text'] = ''; @@ -1543,24 +1544,18 @@ function PMA_RTN_getExecuteForm($routine) } $retval .= "\n"; if (in_array($routine['item_param_type'][$i], array('ENUM', 'SET'))) { - $tokens = PMA_SQP_parse($routine['item_param_length'][$i]); if ($routine['item_param_type'][$i] == 'ENUM') { $input_type = 'radio'; } else { $input_type = 'checkbox'; } - for ($j = 0; $j < $tokens['len']; $j++) { - if ($tokens[$j]['type'] != 'punct_listsep') { - $tokens[$j]['data'] = htmlentities( - PMA_Util::unquote($tokens[$j]['data']), - ENT_QUOTES - ); - $retval .= "" - . $tokens[$j]['data'] . "
\n"; - } + foreach ($routine['item_param_length_arr'][$i] as $value) { + $value = htmlentities(PMA_Util::unquote($value), ENT_QUOTES); + $retval .= "" + . $value . "
\n"; } } else if (in_array( /*overload*/mb_strtolower($routine['item_param_type'][$i]), diff --git a/test/libraries/rte/PMA_RTN_getExecuteForm_test.php b/test/libraries/rte/PMA_RTN_getExecuteForm_test.php index 4ac10f5285..44061c9090 100644 --- a/test/libraries/rte/PMA_RTN_getExecuteForm_test.php +++ b/test/libraries/rte/PMA_RTN_getExecuteForm_test.php @@ -113,6 +113,14 @@ class PMA_RTN_GetExecuteForm_Test extends PHPUnit_Framework_TestCase 4 => "'a','b'", 5 => "'a','b'" ), + 'item_param_length_arr' => array( + 0 => array(), + 1 => array('22'), + 2 => array(), + 3 => array(), + 4 => array("'a'", "'b'"), + 5 => array("'a'", "'b'") + ), 'item_param_opts_num' => array( 0 => '', 1 => '', @@ -241,6 +249,14 @@ class PMA_RTN_GetExecuteForm_Test extends PHPUnit_Framework_TestCase 4 => "'a','b'", 5 => "'a','b'" ), + 'item_param_length_arr' => array( + 0 => array(), + 1 => array('22'), + 2 => array(), + 3 => array(), + 4 => array("'a'", "'b'"), + 5 => array("'a'", "'b'") + ), 'item_param_opts_num' => array( 0 => '', 1 => '', From 11adecc1d80f32234f48791fe121a3a59485c28e Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Mon, 22 Jun 2015 22:36:13 +0300 Subject: [PATCH 20/57] Use new parser for table's structure. Signed-off-by: Dan Ungureanu --- libraries/display_structure.inc.php | 6 +++--- tbl_structure.php | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libraries/display_structure.inc.php b/libraries/display_structure.inc.php index a23f487644..ec561decc1 100644 --- a/libraries/display_structure.inc.php +++ b/libraries/display_structure.inc.php @@ -115,9 +115,9 @@ foreach ($fields as $row) { $attribute = $extracted_columnspec['attribute']; // prepare a common variable to reuse below; however, - // in case of a VIEW, $analyzed_sql[0]['create_table_fields'] is empty - if (isset($analyzed_sql[0]['create_table_fields'][$row['Field']])) { - $tempField = $analyzed_sql[0]['create_table_fields'][$row['Field']]; + // in case of a VIEW, $create_table_fields is empty + if (isset($create_table_fields[$row['Field']])) { + $tempField = $create_table_fields[$row['Field']]; } else { $tempField = array(); } diff --git a/tbl_structure.php b/tbl_structure.php index 9d5178c048..094356c355 100644 --- a/tbl_structure.php +++ b/tbl_structure.php @@ -199,7 +199,8 @@ $show_create_table = $GLOBALS['dbi']->fetchValue( . PMA_Util::backquote($table), 0, 1 ); -$analyzed_sql = PMA_SQP_analyze(PMA_SQP_parse($show_create_table)); +$parser = new SqlParser\Parser($show_create_table); +$create_table_fields = SqlParser\Utils\Table::getFields($parser->statements[0]); /** * prepare table infos From 484d456f59e3a3b588aaceb5d8cd551ff9a5f13b Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Tue, 23 Jun 2015 22:30:12 +0300 Subject: [PATCH 21/57] Use new parser for relations. Updated sql-parser library. Signed-off-by: Dan Ungureanu --- libraries/relation.lib.php | 11 +- libraries/sql-parser/src/Context.php | 19 +-- .../src/Contexts/ContextMySql50000.php | 19 ++- .../src/Contexts/ContextMySql50100.php | 19 ++- .../src/Contexts/ContextMySql50500.php | 19 ++- .../src/Contexts/ContextMySql50600.php | 19 ++- .../src/Contexts/ContextMySql50700.php | 19 ++- .../src/Fragments/ArrayFragment.php | 4 +- .../sql-parser/src/Fragments/CallKeyword.php | 3 +- .../src/Fragments/DataTypeFragment.php | 27 +++- .../src/Fragments/FieldDefFragment.php | 76 +++++------ .../sql-parser/src/Fragments/IntoKeyword.php | 28 +--- .../sql-parser/src/Fragments/KeyFragment.php | 124 ++++++++++++++++++ .../sql-parser/src/Fragments/LimitKeyword.php | 8 +- .../sql-parser/src/Fragments/OrderKeyword.php | 51 ++++--- .../src/Fragments/ReferencesKeyword.php | 115 ++++++++++++++++ .../src/Statements/CreateStatement.php | 1 + libraries/sql-parser/src/Utils/Misc.php | 3 +- libraries/sql-parser/src/Utils/Routine.php | 16 +-- libraries/sql-parser/src/Utils/Table.php | 45 ++++++- 20 files changed, 489 insertions(+), 137 deletions(-) create mode 100644 libraries/sql-parser/src/Fragments/KeyFragment.php create mode 100644 libraries/sql-parser/src/Fragments/ReferencesKeyword.php diff --git a/libraries/relation.lib.php b/libraries/relation.lib.php index d8b9552d64..340db7d238 100644 --- a/libraries/relation.lib.php +++ b/libraries/relation.lib.php @@ -734,15 +734,14 @@ function PMA_getForeigners($db, $table, $column = '', $source = 'both') if (($source == 'both' || $source == 'foreign') && /*overload*/mb_strlen($table) ) { - - $showCreateTableQuery = 'SHOW CREATE TABLE ' - . PMA_Util::backquote($db) . '.' . PMA_Util::backquote($table); $show_create_table = $GLOBALS['dbi']->fetchValue( - $showCreateTableQuery, 0, 1 + 'SHOW CREATE TABLE ' . PMA_Util::backquote($db) . '.' + . PMA_Util::backquote($table), + 0, 1 ); if ($show_create_table) { - $analyzed_sql = PMA_SQP_analyze(PMA_SQP_parse($show_create_table)); - $foreign['foreign_keys_data'] = $analyzed_sql[0]['foreign_keys']; + $parser = new SqlParser\Parser($show_create_table); + $foreign['foreign_keys_data'] = SqlParser\Utils\Table::getForeignKeys($parser->statements[0]); } } diff --git a/libraries/sql-parser/src/Context.php b/libraries/sql-parser/src/Context.php index eed10d3687..cbe666df57 100644 --- a/libraries/sql-parser/src/Context.php +++ b/libraries/sql-parser/src/Context.php @@ -53,30 +53,22 @@ abstract class Context */ public static $contextPrefix = '\\SqlParser\\Contexts\\Context'; - // ------------------------------------------------------------------------- - // Keywords. - /** * List of keywords. * * Because, PHP's associative arrays are basically hash tables, it is more * efficient to store keywords as keys instead of values. * - * There are multiple types of keyword, depending on the value associated: - * 1 - reserved keywords - * 2 - keyword - * 3 - composite keyword (unofficial); used to make the job of the lexer - * much easier by grouping keywords that may appear together + * The value associated to each keyword represents its flags. * - * Keywords below are sorted by type, length and keyword. + * @see Token::FLAG_KEYWORD_* + * + * Elements are sorted by flags, length and keyword. * * @var array */ public static $KEYWORDS = array(); - // ------------------------------------------------------------------------- - // Operators. - /** * List of operators and their flags. * @@ -110,9 +102,6 @@ abstract class Context '(' => 16, ')' => 16, '.' => 16, ',' => 16, ); - // ------------------------------------------------------------------------- - // SQL Modes. - /* * Server SQL Modes * https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50000.php b/libraries/sql-parser/src/Contexts/ContextMySql50000.php index b81d687f0c..f2357f2b2b 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50000.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50000.php @@ -1,5 +1,11 @@ 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, @@ -137,8 +152,8 @@ class ContextMySql50000 extends Context 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3, 'SQL_CALC_FOUND_ROWS' => 3, - 'NOT NULL' => 5, - 'ON UPDATE' => 5, + 'NOT NULL' => 5, 'SET NULL' => 5, + 'NO ACTION' => 5, 'ON DELETE' => 5, 'ON UPDATE' => 5, 'CHARACTER SET' => 5, 'IF NOT EXISTS' => 5, 'DATA DIRECTORY' => 5, 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50100.php b/libraries/sql-parser/src/Contexts/ContextMySql50100.php index 260925e21f..dcdce84850 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50100.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50100.php @@ -1,5 +1,11 @@ 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, @@ -151,8 +166,8 @@ class ContextMySql50100 extends Context 'SQL_CALC_FOUND_ROWS' => 3, 'MASTER_SSL_VERIFY_SERVER_CERT' => 3, - 'NOT NULL' => 5, - 'ON UPDATE' => 5, + 'NOT NULL' => 5, 'SET NULL' => 5, + 'NO ACTION' => 5, 'ON DELETE' => 5, 'ON UPDATE' => 5, 'CHARACTER SET' => 5, 'IF NOT EXISTS' => 5, 'DATA DIRECTORY' => 5, 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50500.php b/libraries/sql-parser/src/Contexts/ContextMySql50500.php index e70b931994..15e079e554 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50500.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50500.php @@ -1,5 +1,11 @@ 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, @@ -154,8 +169,8 @@ class ContextMySql50500 extends Context 'SQL_CALC_FOUND_ROWS' => 3, 'MASTER_SSL_VERIFY_SERVER_CERT' => 3, - 'NOT NULL' => 5, - 'ON UPDATE' => 5, + 'NOT NULL' => 5, 'SET NULL' => 5, + 'NO ACTION' => 5, 'ON DELETE' => 5, 'ON UPDATE' => 5, 'CHARACTER SET' => 5, 'IF NOT EXISTS' => 5, 'DATA DIRECTORY' => 5, 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50600.php b/libraries/sql-parser/src/Contexts/ContextMySql50600.php index 819ec1c53f..1135e52dd0 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50600.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50600.php @@ -1,5 +1,11 @@ 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, @@ -165,8 +180,8 @@ class ContextMySql50600 extends Context 'SQL_CALC_FOUND_ROWS' => 3, 'MASTER_SSL_VERIFY_SERVER_CERT' => 3, - 'NOT NULL' => 5, - 'ON UPDATE' => 5, + 'NOT NULL' => 5, 'SET NULL' => 5, + 'NO ACTION' => 5, 'ON DELETE' => 5, 'ON UPDATE' => 5, 'CHARACTER SET' => 5, 'IF NOT EXISTS' => 5, 'DATA DIRECTORY' => 5, 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50700.php b/libraries/sql-parser/src/Contexts/ContextMySql50700.php index db047b1c46..799ae1b4be 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50700.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50700.php @@ -1,5 +1,11 @@ 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, @@ -170,8 +185,8 @@ class ContextMySql50700 extends Context 'SQL_CALC_FOUND_ROWS' => 3, 'MASTER_SSL_VERIFY_SERVER_CERT' => 3, - 'NOT NULL' => 5, - 'ON UPDATE' => 5, + 'NOT NULL' => 5, 'SET NULL' => 5, + 'NO ACTION' => 5, 'ON DELETE' => 5, 'ON UPDATE' => 5, 'CHARACTER SET' => 5, 'IF NOT EXISTS' => 5, 'DATA DIRECTORY' => 5, 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, diff --git a/libraries/sql-parser/src/Fragments/ArrayFragment.php b/libraries/sql-parser/src/Fragments/ArrayFragment.php index eb5a80b8ee..a713dde228 100644 --- a/libraries/sql-parser/src/Fragments/ArrayFragment.php +++ b/libraries/sql-parser/src/Fragments/ArrayFragment.php @@ -24,7 +24,7 @@ class ArrayFragment extends Fragment * * @var array */ - public $array = array(); + public $values = array(); /** * The array that contains the unprocessed value of each token. @@ -89,7 +89,7 @@ class ArrayFragment extends Fragment // Empty array. break; } - $ret->array[] = $token->value; + $ret->values[] = $token->value; $ret->raw[] = $token->token; $state = 2; } elseif ($state === 2) { diff --git a/libraries/sql-parser/src/Fragments/CallKeyword.php b/libraries/sql-parser/src/Fragments/CallKeyword.php index db11120c49..4c1ed0c810 100644 --- a/libraries/sql-parser/src/Fragments/CallKeyword.php +++ b/libraries/sql-parser/src/Fragments/CallKeyword.php @@ -80,8 +80,7 @@ class CallKeyword extends Fragment $state = 1; } elseif ($state === 1) { if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { - $parameters = ArrayFragment::parse($parser, $list); - $ret->parameters = $parameters->array; + $ret->parameters = ArrayFragment::parse($parser, $list)->values; } break; } diff --git a/libraries/sql-parser/src/Fragments/DataTypeFragment.php b/libraries/sql-parser/src/Fragments/DataTypeFragment.php index 740fbfd85d..a8045cf3e8 100644 --- a/libraries/sql-parser/src/Fragments/DataTypeFragment.php +++ b/libraries/sql-parser/src/Fragments/DataTypeFragment.php @@ -20,7 +20,12 @@ use SqlParser\TokensList; class DataTypeFragment extends Fragment { - public static $OPTIONS = array( + /** + * All data type options. + * + * @var array + */ + public static $DATA_TYPE_OPTIONS = array( 'BINARY' => 1, 'CHARACTER SET' => array(2, 'var'), 'CHARSET' => array(2, 'var'), @@ -37,18 +42,26 @@ class DataTypeFragment extends Fragment public $name; /** - * The size of this data type. + * The parameters of this data type. + * + * Some data types have no parameters. + * Numeric types might have parameters for the maximum number of digits, + * precision, etc. + * String ypes might have parameters for the maxium length stored. + * `ENUM` and `SET` have parameters for possible values. + * + * For more information, check the MySQL manual. * * @var array */ - public $size = array(); + public $parameters = array(); /** * The options of this data type. * * @var OptionsFragment */ - public $options = array(); + public $options; /** * @param Parser $parser The parser that serves as context. @@ -97,10 +110,10 @@ class DataTypeFragment extends Fragment if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { $size = ArrayFragment::parse($parser, $list); ++$list->idx; - $ret->size = (($ret->name === 'ENUM') || ($ret->name === 'SET')) ? - $size->raw : $size->array; + $ret->parameters = (($ret->name === 'ENUM') || ($ret->name === 'SET')) ? + $size->raw : $size->values; } - $ret->options = OptionsFragment::parse($parser, $list, static::$OPTIONS); + $ret->options = OptionsFragment::parse($parser, $list, static::$DATA_TYPE_OPTIONS); ++$list->idx; break; } diff --git a/libraries/sql-parser/src/Fragments/FieldDefFragment.php b/libraries/sql-parser/src/Fragments/FieldDefFragment.php index f4a08bdc8d..20983e9e37 100644 --- a/libraries/sql-parser/src/Fragments/FieldDefFragment.php +++ b/libraries/sql-parser/src/Fragments/FieldDefFragment.php @@ -48,6 +48,13 @@ class FieldDefFragment extends Fragment */ public $name; + /** + * Whether this field is a constraint or not. + * + * @var bool + */ + public $isConstraint; + /** * The data type of thew new column. * @@ -56,11 +63,18 @@ class FieldDefFragment extends Fragment public $type; /** - * The array of indexes. + * The key. * - * @var ArrayFragment + * @var KeyFragment */ - public $indexes; + public $key; + + /** + * The table that is referenced. + * + * @var ReferencesKeyword + */ + public $references; /** * The options of the new field fragment. @@ -89,22 +103,18 @@ class FieldDefFragment extends Fragment * * 0 -----------------------[ ( ]------------------------> 1 * - * 1 -------------------[ CONSTRAINT ]-------------------> 4 - * 1 --------------------[ key type ]--------------------> 5 - * 1 -------------------[ column name ]------------------> 2 + * 1 --------------------[ CONSTRAINT ]------------------> 1 + * 1 -----------------------[ key ]----------------------> 2 + * 1 -------------[ constraint / column name ]-----------> 2 * - * 2 -------------------[ data type ]--------------------> 3 + * 2 --------------------[ data type ]-------------------> 3 * - * 3 ---------------------[ size ]---------------------> 3 * 3 ---------------------[ options ]--------------------> 4 * - * 4 -----------------[ CONSTRAINT name ]----------------> 4 - * 4 -----------------[ CONSTRAINT type ]----------------> 5 + * 4 --------------------[ REFERENCES ]------------------> 4 * - * 5 -------------------[ index names ]------------------> 6 - * - * 6 ------------------------[ , ]-----------------------> 1 - * 6 ------------------------[ ) ]-----------------------> -1 + * 5 ------------------------[ , ]-----------------------> 1 + * 5 ------------------------[ ) ]-----------------------> -1 * * @var int */ @@ -132,42 +142,34 @@ class FieldDefFragment extends Fragment if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { $state = 1; } - continue; } elseif ($state === 1) { if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'CONSTRAINT')) { - $state = 4; + $expr->isConstraint = true; } elseif (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_KEY)) { - $expr->type = $token->value; - $state = 5; - } elseif (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { - $parser->error('Unexpected keyword.', $token); - break; // TODO: Skip to the end of the query. + $expr->key = KeyFragment::parse($parser, $list); + $state = 4; } else { $expr->name = $token->value; - $state = 2; + if (!$expr->isConstraint) { + $state = 2; + } } } elseif ($state === 2) { $expr->type = DataTypeFragment::parse($parser, $list); $state = 3; } elseif ($state === 3) { $expr->options = OptionsFragment::parse($parser, $list, static::$FIELD_OPTIONS); - $state = 6; + $state = 4; } elseif ($state === 4) { - if (($token->type !== Token::TYPE_KEYWORD) || (!($token->flags & Token::FLAG_KEYWORD_KEY))) { - $expr->name = $token->value; + if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'REFERENCES')) { + ++$list->idx; // Skipping keyword 'REFERENCES'. + $expr->references = ReferencesKeyword::parse($parser, $list); } else { - $expr->type = $token->value; - $state = 5; + --$list->idx; } - } elseif ($state === 5) { - if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { - $expr->indexes = ArrayFragment::parse($parser, $list); - $state = 6; - } else { - $expr->name = $token->value; - } - } elseif ($state === 6) { - if (!empty($expr->type)) { + $state = 5; + } else if ($state === 5) { + if ((!empty($expr->type)) || (!empty($expr->key))) { $ret[] = $expr; } $expr = new FieldDefFragment(); @@ -183,7 +185,7 @@ class FieldDefFragment extends Fragment } // Last iteration was not saved. - if (!empty($expr->type)) { + if ((!empty($expr->type)) || (!empty($expr->key))) { $ret[] = $expr; } diff --git a/libraries/sql-parser/src/Fragments/IntoKeyword.php b/libraries/sql-parser/src/Fragments/IntoKeyword.php index c4211fd47d..9cf634c427 100644 --- a/libraries/sql-parser/src/Fragments/IntoKeyword.php +++ b/libraries/sql-parser/src/Fragments/IntoKeyword.php @@ -82,30 +82,12 @@ class IntoKeyword extends Fragment break; } - if ($token->type === Token::TYPE_OPERATOR) { - if ($token->value === '(') { - if (empty($ret->table)) { - $parser->error('Table name was expected.', $token); - } - $state = 1; - continue; - } elseif ($token->value === ',') { - if ($state !== 2) { - $parser->error('Field name was expected.', $token); - } - $state = 1; - continue; - } - - // No other operator is expected. + if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { + $ret->fields = ArrayFragment::parse($parser, $list)->values; + ++$list->idx; break; - } - - if ($state === 0) { - $ret->table .= $token->value; - } elseif ($state === 1) { - $ret->fields[] = $token->value; - $state = 2; + } else { + $ret->table = $token->value; } } diff --git a/libraries/sql-parser/src/Fragments/KeyFragment.php b/libraries/sql-parser/src/Fragments/KeyFragment.php new file mode 100644 index 0000000000..11f4caf015 --- /dev/null +++ b/libraries/sql-parser/src/Fragments/KeyFragment.php @@ -0,0 +1,124 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class KeyFragment extends Fragment +{ + + /** + * All key options. + * + * @var array + */ + public static $KEY_OPTIONS = array( + 'KEY_BLOCK_SIZE' => array(1, 'var'), + 'USING' => array(2, 'var'), + 'WITH PARSER' => array(3, 'var'), + ); + + /** + * The name of this key. + * + * @var string + */ + public $name; + + /** + * Columns. + * + * @var array + */ + public $columns; + + /** + * The type of this key. + * + * @var string + */ + public $type; + + /** + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. + * + * @return KeyFragment[] + */ + public static function parse(Parser $parser, TokensList $list, array $options = array()) + { + $ret = new KeyFragment(); + + /** + * The state of the parser. + * + * Below are the states of the parser. + * + * 0 ----------------------[ type ]-----------------------> 1 + * + * 1 ----------------------[ name ]-----------------------> 1 + * 1 ---------------------[ columns ]---------------------> 2 + * + * 2 ---------------------[ options ]---------------------> 3 + * + * @var int + */ + $state = 0; + + for (; $list->idx < $list->count; ++$list->idx) { + + /** + * Token parsed at this moment. + * @var Token + */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + if ($state === 0) { + $ret->type = $token->value; + $state = 1; + } elseif ($state === 1) { + if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { + $ret->columns = ArrayFragment::parse($parser, $list)->values; + $state = 2; + } else { + $ret->name = $token->value; + } + } elseif ($state === 2) { + $ret->options = OptionsFragment::parse($parser, $list, static::$KEY_OPTIONS); + ++$list->idx; + break; + } + + } + + --$list->idx; + return $ret; + + } +} diff --git a/libraries/sql-parser/src/Fragments/LimitKeyword.php b/libraries/sql-parser/src/Fragments/LimitKeyword.php index 2e5b8193e5..6e12b444d0 100644 --- a/libraries/sql-parser/src/Fragments/LimitKeyword.php +++ b/libraries/sql-parser/src/Fragments/LimitKeyword.php @@ -64,7 +64,7 @@ class LimitKeyword extends Fragment continue; } - if ($token->value === 'OFFSET') { + if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'OFFSET')) { if ($offset) { $parser->error('An offset was expected.'); } @@ -73,8 +73,8 @@ class LimitKeyword extends Fragment } if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) { - $ret->offset = $ret->row_count; - $ret->row_count = 0; + $ret->offset = $ret->rowCount; + $ret->rowCount = 0; continue; } @@ -82,7 +82,7 @@ class LimitKeyword extends Fragment $ret->offset = $token->value; $offset = false; } else { - $ret->row_count = $token->value; + $ret->rowCount = $token->value; } } diff --git a/libraries/sql-parser/src/Fragments/OrderKeyword.php b/libraries/sql-parser/src/Fragments/OrderKeyword.php index 224a573263..34744e3d1c 100644 --- a/libraries/sql-parser/src/Fragments/OrderKeyword.php +++ b/libraries/sql-parser/src/Fragments/OrderKeyword.php @@ -20,11 +20,11 @@ class OrderKeyword extends Fragment { /** - * The name of the column that is being used for ordering. + * The field that is used for ordering. * - * @var string + * @var FieldFragment */ - public $column; + public $field; /** * The order type. @@ -46,6 +46,20 @@ class OrderKeyword extends Fragment $expr = new OrderKeyword(); + /** + * The state of the parser. + * + * Below are the states of the parser. + * + * 0 ----------------------[ field ]----------------------> 1 + * + * 1 ------------------------[ , ]------------------------> 0 + * 1 -------------------[ ASC / DESC ]--------------------> 1 + * + * @var int + */ + $state = 0; + for (; $list->idx < $list->count; ++$list->idx) { /** @@ -64,30 +78,27 @@ class OrderKeyword extends Fragment continue; } - if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { - // Type of ordering. By default, it is `ASC`. - if (($token->value === 'ASC') || ($token->value === 'DESC')) { + if ($state === 0) { + $expr->field = FieldFragment::parse($parser, $list); + $state = 1; + } elseif ($state === 1) { + if (($token->type === Token::TYPE_KEYWORD) && (($token->value === 'ASC') || ($token->value === 'DESC'))) { $expr->type = $token->value; - continue; + } else if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) { + if (!empty($expr->field)) { + $ret[] = $expr; + } + $expr = new OrderKeyword(); + $state = 0; + } else { + break; } - - // No other keyword is expected. - break; } - // Saving field. - if (($token->type === Token::TYPE_OPERATOR) && ($token->token === ',')) { - $ret[] = $expr; - $expr = new OrderKeyword(); - continue; - } - - $expr->column .= $token->token; - } // Last iteration was not processed. - if (!empty($expr->column)) { + if (!empty($expr->field)) { $ret[] = $expr; } diff --git a/libraries/sql-parser/src/Fragments/ReferencesKeyword.php b/libraries/sql-parser/src/Fragments/ReferencesKeyword.php new file mode 100644 index 0000000000..939eb244ab --- /dev/null +++ b/libraries/sql-parser/src/Fragments/ReferencesKeyword.php @@ -0,0 +1,115 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class ReferencesKeyword extends Fragment +{ + + /** + * All references options. + * + * @var array + */ + public static $REFERENCES_OPTIONS = array( + 'MATCH' => array(1, 'var'), + 'ON DELETE' => array(2, 'var'), + 'ON UPDATE' => array(3, 'var'), + ); + + /** + * The referenced table. + * + * @var string + */ + public $table; + + /** + * The referenced columns. + * + * @var array + */ + public $columns; + + /** + * The options of the referencing. + * + * @var OptionsFragment + */ + public $options; + + /** + * @param Parser $parser The parser that serves as context. + * @param TokensList $list The list of tokens that are being parsed. + * @param array $options Parameters for parsing. + * + * @return ReferencesKeyword + */ + public static function parse(Parser $parser, TokensList $list, array $options = array()) + { + $ret = new ReferencesKeyword(); + + /** + * The state of the parser. + * + * Below are the states of the parser. + * + * 0 ----------------------[ table ]---------------------> 1 + * + * 1 ---------------------[ columns ]--------------------> 2 + * + * 2 ---------------------[ options ]--------------------> -1 + * + * @var int + */ + $state = 0; + + for (; $list->idx < $list->count; ++$list->idx) { + + /** + * Token parsed at this moment. + * @var Token + */ + $token = $list->tokens[$list->idx]; + + // End of statement. + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + // Skipping whitespaces and comments. + if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + continue; + } + + if ($state === 0) { + $ret->table = $token->value; + $state = 1; + } else if ($state === 1) { + $ret->columns = ArrayFragment::parse($parser, $list)->values; + $state = 2; + } else if ($state === 2) { + $ret->options = OptionsFragment::parse($parser, $list, static::$REFERENCES_OPTIONS); + ++$list->idx; + break; + } + + } + + --$list->idx; + return $ret; + } +} diff --git a/libraries/sql-parser/src/Statements/CreateStatement.php b/libraries/sql-parser/src/Statements/CreateStatement.php index 7a248e9032..edb87ea7fc 100644 --- a/libraries/sql-parser/src/Statements/CreateStatement.php +++ b/libraries/sql-parser/src/Statements/CreateStatement.php @@ -32,6 +32,7 @@ class CreateStatement extends Statement 'TABLE' => 1, 'TABLESPACE' => 1, 'TRIGGER' => 1, + 'USER' => 1, 'VIEW' => 1, 'TEMPORARY' => 2, diff --git a/libraries/sql-parser/src/Utils/Misc.php b/libraries/sql-parser/src/Utils/Misc.php index 22227a8b6e..4e818c6789 100644 --- a/libraries/sql-parser/src/Utils/Misc.php +++ b/libraries/sql-parser/src/Utils/Misc.php @@ -92,8 +92,7 @@ class Misc } else { $thisTable = isset($tables[$thisDb][$expr->table]) ? $tables[$thisDb][$expr->table] : $expr->table; - $retval[$thisDb]['tables'] - [$thisTable]['columns'][$expr->column] = $expr->alias; + $retval[$thisDb]['tables'][$thisTable]['columns'][$expr->column] = $expr->alias; } } diff --git a/libraries/sql-parser/src/Utils/Routine.php b/libraries/sql-parser/src/Utils/Routine.php index 9bc10f7546..8be7db1260 100644 --- a/libraries/sql-parser/src/Utils/Routine.php +++ b/libraries/sql-parser/src/Utils/Routine.php @@ -32,22 +32,22 @@ class Routine $lexer = new Lexer($param); // A dummy parser is used for error reporting. - $param = DataTypeFragment::parse(new Parser(), $lexer->tokens); + $type = DataTypeFragment::parse(new Parser(), $lexer->tokens); - if ($param === null) { + if ($type === null) { return array('', '', '', '', ''); } $options = array(); - foreach ($param->options->options as $opt) { + foreach ($type->options->options as $opt) { $options[] = is_string($opt) ? $opt : $opt['value']; } return array( '', '', - $param->name, - implode(',', $param->size), + $type->name, + implode(',', $type->parameters), implode(' ', $options) ); } @@ -81,7 +81,7 @@ class Routine empty($param->inOut) ? '' : $param->inOut, $param->name, $param->type->name, - implode(',', $param->type->size), + implode(',', $param->type->parameters), implode(' ', $options) ); } @@ -110,8 +110,8 @@ class Routine $retval['dir'][$idx] = $param->inOut; $retval['name'][$idx] = $param->name; $retval['type'][$idx] = $param->type->name; - $retval['length'][$idx] = implode(',', $param->type->size); - $retval['length_arr'][$idx] = $param->type->size; + $retval['length'][$idx] = implode(',', $param->type->parameters); + $retval['length_arr'][$idx] = $param->type->parameters; $retval['opts'][$idx] = array(); foreach ($param->type->options->options as $opt) { $retval['opts'][$idx][] = is_string($opt) ? diff --git a/libraries/sql-parser/src/Utils/Table.php b/libraries/sql-parser/src/Utils/Table.php index 7560f9d07a..a814075459 100644 --- a/libraries/sql-parser/src/Utils/Table.php +++ b/libraries/sql-parser/src/Utils/Table.php @@ -20,6 +20,49 @@ use SqlParser\Statements\CreateStatement; class Table { + public static function getForeignKeys(CreateStatement $tree) + { + if (($tree->fields === null) || (!$tree->options->has('TABLE'))) { + return array(); + } + + $ret = array(); + + foreach ($tree->fields as $field) { + + if ((empty($field->key)) || ($field->key->type !== 'FOREIGN KEY')) { + continue; + } + + $tmp = array( + 'constraint' => $field->name, + 'index_list' => $field->key->columns, + ); + + if (!empty($field->references)) { + $tmp['ref_table_name'] = $field->references->table; + $tmp['ref_index_list'] = $field->references->columns; + + if (($opt = $field->references->options->has('ON UPDATE'))) { + $tmp['on_update'] = str_replace(' ', '_', $opt); + } + + if (($opt = $field->references->options->has('ON DELETE'))) { + $tmp['on_delete'] = str_replace(' ', '_', $opt); + } + + // if (($opt = $field->references->options->has('MATCH'))) { + // $tmp['match'] = str_replace(' ', '_', $opt); + // } + } + + $ret[] = $tmp; + + } + + return $ret; + } + public static function getFields(CreateStatement $tree) { if (($tree->fields === null) || (!$tree->options->has('TABLE'))) { @@ -31,7 +74,7 @@ class Table foreach ($tree->fields as $field) { // Skipping keys. - if (is_string($field->type)) { + if (empty($field->type)) { continue; } From acf0dbdacfd5f0719e8d505474e34b31eca0af86 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Wed, 24 Jun 2015 19:31:57 +0300 Subject: [PATCH 22/57] Updated sql-parser library. Signed-off-by: Dan Ungureanu --- .../src/Contexts/ContextMySql50000.php | 2 + .../src/Contexts/ContextMySql50100.php | 2 + .../src/Contexts/ContextMySql50500.php | 2 + .../src/Contexts/ContextMySql50600.php | 2 + .../src/Contexts/ContextMySql50700.php | 2 + libraries/sql-parser/src/Fragment.php | 8 +- libraries/sql-parser/src/Parser.php | 90 +++++++++++++------ libraries/sql-parser/src/Statement.php | 74 ++++++++------- libraries/sql-parser/src/Utils/Misc.php | 12 ++- libraries/sql-parser/src/Utils/Routine.php | 38 ++++---- libraries/sql-parser/src/Utils/Table.php | 10 +-- 11 files changed, 147 insertions(+), 95 deletions(-) diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50000.php b/libraries/sql-parser/src/Contexts/ContextMySql50000.php index f2357f2b2b..63f4ca2780 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50000.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50000.php @@ -159,6 +159,8 @@ class ContextMySql50000 extends Context 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, 'DEFAULT CHARACTER SET' => 5, + 'GROUP BY' => 7, 'ORDER BY' => 7, + 'XML' => 9, 'DATE' => 9, 'ENUM' => 9, 'TEXT' => 9, 'TIME' => 9, 'YEAR' => 9, 'ARRAY' => 9, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50100.php b/libraries/sql-parser/src/Contexts/ContextMySql50100.php index dcdce84850..265979f8b2 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50100.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50100.php @@ -173,6 +173,8 @@ class ContextMySql50100 extends Context 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, 'DEFAULT CHARACTER SET' => 5, + 'GROUP BY' => 7, 'ORDER BY' => 7, + 'XML' => 9, 'DATE' => 9, 'ENUM' => 9, 'TEXT' => 9, 'TIME' => 9, 'YEAR' => 9, 'ARRAY' => 9, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50500.php b/libraries/sql-parser/src/Contexts/ContextMySql50500.php index 15e079e554..3a5496a9ba 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50500.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50500.php @@ -176,6 +176,8 @@ class ContextMySql50500 extends Context 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, 'DEFAULT CHARACTER SET' => 5, + 'GROUP BY' => 7, 'ORDER BY' => 7, + 'XML' => 9, 'DATE' => 9, 'ENUM' => 9, 'TEXT' => 9, 'TIME' => 9, 'YEAR' => 9, 'ARRAY' => 9, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50600.php b/libraries/sql-parser/src/Contexts/ContextMySql50600.php index 1135e52dd0..d9fcf715cd 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50600.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50600.php @@ -187,6 +187,8 @@ class ContextMySql50600 extends Context 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, 'DEFAULT CHARACTER SET' => 5, + 'GROUP BY' => 7, 'ORDER BY' => 7, + 'XML' => 9, 'DATE' => 9, 'ENUM' => 9, 'TEXT' => 9, 'TIME' => 9, 'YEAR' => 9, 'ARRAY' => 9, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50700.php b/libraries/sql-parser/src/Contexts/ContextMySql50700.php index 799ae1b4be..808de0df49 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50700.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50700.php @@ -192,6 +192,8 @@ class ContextMySql50700 extends Context 'DEFAULT COLLATE' => 5, 'INDEX DIRECTORY' => 5, 'DEFAULT CHARACTER SET' => 5, + 'GROUP BY' => 7, 'ORDER BY' => 7, + 'XML' => 9, 'DATE' => 9, 'ENUM' => 9, 'TEXT' => 9, 'TIME' => 9, 'YEAR' => 9, 'ARRAY' => 9, diff --git a/libraries/sql-parser/src/Fragment.php b/libraries/sql-parser/src/Fragment.php index 51cec95922..1c40699be3 100644 --- a/libraries/sql-parser/src/Fragment.php +++ b/libraries/sql-parser/src/Fragment.php @@ -24,7 +24,9 @@ abstract class Fragment * * @return mixed */ - abstract public static function parse(Parser $parser, TokensList $list, - array $options = array() - ); + public static function parse(Parser $parser, TokensList $list, array $options = array()) + { + return null; + } + } diff --git a/libraries/sql-parser/src/Parser.php b/libraries/sql-parser/src/Parser.php index 2973a03686..a5fe233563 100644 --- a/libraries/sql-parser/src/Parser.php +++ b/libraries/sql-parser/src/Parser.php @@ -56,32 +56,70 @@ class Parser */ public static $KEYWORD_PARSERS = array( - // Meta-keywords. - /* - '_ARRAY' => 'SqlParser\\Fragments\\ArrayFragment', - '_CALL' => 'SqlParser\\Fragments\\CallKeyword', - '_CREATE_DEF' => 'SqlParser\\Fragments\\CreateDefFragment', - '_DATA_TYPE' => 'SqlParser\\Fragments\\DataTypeFragment', - '_FIELD' => 'SqlParser\\Fragments\\FieldFragment', - '_FIELD_DEF' => 'SqlParser\\Fragments\\FieldDefFragment', - '_PARAM_DEF' => 'SqlParser\\Fragments\\ParamDefFragment', - '_OPTIONS' => 'SqlParser\\Fragments\\OptionsFragment', - '_RENAME' => 'SqlParser\\Fragments\\RenameKeyword', - '_SELECT' => 'SqlParser\\Fragments\\SelectKeyword', - */ - - 'FROM' => 'SqlParser\\Fragments\\FromKeyword', - 'GROUP' => 'SqlParser\\Fragments\\OrderKeyword', - 'HAVING' => 'SqlParser\\Fragments\\WhereKeyword', - 'INTO' => 'SqlParser\\Fragments\\IntoKeyword', - 'JOIN' => 'SqlParser\\Fragments\\JoinKeyword', - 'LIMIT' => 'SqlParser\\Fragments\\LimitKeyword', - 'ORDER' => 'SqlParser\\Fragments\\OrderKeyword', - 'PARTITION' => 'SqlParser\\Fragments\\ArrayFragment', - 'SET' => 'SqlParser\\Fragments\\SetKeyword', - 'VALUE' => 'SqlParser\\Fragments\\ValuesKeyword', - 'VALUES' => 'SqlParser\\Fragments\\ValuesKeyword', - 'WHERE' => 'SqlParser\\Fragments\\WhereKeyword', + 'CALL' => array( + 'class' => 'SqlParser\\Fragments\\CallKeyword', + 'field' => 'call', + ), + 'FROM' => array( + 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'field' => 'from', + ), + 'GROUP BY' => array( + 'class' => 'SqlParser\\Fragments\\OrderKeyword', + 'field' => 'group', + ), + 'HAVING' => array( + 'class' => 'SqlParser\\Fragments\\WhereKeyword', + 'field' => 'having', + ), + 'INTO' => array( + 'class' => 'SqlParser\\Fragments\\IntoKeyword', + 'field' => 'into', + ), + 'JOIN' => array( + 'class' => 'SqlParser\\Fragments\\JoinKeyword', + 'field' => 'join', + ), + 'LIMIT' => array( + 'class' => 'SqlParser\\Fragments\\LimitKeyword', + 'field' => 'limit', + ), + 'ORDER BY' => array( + 'class' => 'SqlParser\\Fragments\\OrderKeyword', + 'field' => 'order', + ), + 'PARTITION' => array( + 'class' => 'SqlParser\\Fragments\\ArrayFragment', + 'field' => 'partition', + ), + 'RENAME' => array( + 'class' => 'SqlParser\\Fragments\\RenameKeyword', + 'field' => 'renames', + ), + 'SET' => array( + 'class' => 'SqlParser\\Fragments\\SetKeyword', + 'field' => 'set', + ), + 'SELECT' => array( + 'class' => 'SqlParser\\Fragments\\SelectKeyword', + 'field' => 'expr', + ), + 'UPDATE' => array( + 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'field' => 'from', + ), + 'VALUE' => array( + 'class' => 'SqlParser\\Fragments\\ValuesKeyword', + 'field' => 'values', + ), + 'VALUES' => array( + 'class' => 'SqlParser\\Fragments\\ValuesKeyword', + 'field' => 'values', + ), + 'WHERE' => array( + 'class' => 'SqlParser\\Fragments\\WhereKeyword', + 'field' => 'where', + ), ); diff --git a/libraries/sql-parser/src/Statement.php b/libraries/sql-parser/src/Statement.php index 13002f4d72..0e57bfd45e 100644 --- a/libraries/sql-parser/src/Statement.php +++ b/libraries/sql-parser/src/Statement.php @@ -50,6 +50,15 @@ abstract class Statement */ public function parse(Parser $parser, TokensList $list) { + + /** + * Whether otpions were parsed or not. + * For statements that do not have any options this is set to `true` by + * default. + * @var bool + */ + $parsedOptions = isset(static::$OPTIONS) ? false : true; + for (; $list->idx < $list->count; ++$list->idx) { /** @@ -75,12 +84,30 @@ abstract class Statement */ $class = null; + /** + * The name of the field where the result of the parsing is stored. + * @var string + */ + $field = null; + if (!empty(Parser::$KEYWORD_PARSERS[$token->value])) { - $class = Parser::$KEYWORD_PARSERS[$token->value]; - } elseif (!empty(Parser::$STATEMENT_PARSERS[$token->value])) { - // The keyword we are processing right now is the beginning of a - // statement and they are usually handled differently. - } else { + $class = Parser::$KEYWORD_PARSERS[$token->value]['class']; + $field = Parser::$KEYWORD_PARSERS[$token->value]['field']; + } + + if (!empty(Parser::$STATEMENT_PARSERS[$token->value])) { + if (!$parsedOptions) { + ++$list->idx; // Skipping keyword. + $this->options = OptionsFragment::parse( + $parser, + $list, + static::$OPTIONS + ); + $parsedOptions = true; + } + } else if ($class === null) { + // There is no parser for this keyword and isn't the beggining + // of a statement (so no options) either. $parser->error( 'Unrecognized keyword "' . $token->value . '".', $token @@ -88,26 +115,8 @@ abstract class Statement continue; } - /** - * The name of the field where the result is stored. - * @var string - */ - $field = strtolower($token->value); - - // Parsing options. - if (($class == null) && (isset(static::$OPTIONS))) { - ++$list->idx; // Skipping keyword. - $this->options = OptionsFragment::parse( - $parser, $list, - static::$OPTIONS - ); - } - - // Keyword specific code. - if ($token->value === 'CALL') { - ++$list->idx; - $this->call = CallKeyword::parse($parser, $list); - } elseif ($token->value === 'CREATE') { + // Special cases. + if ($token->value === 'CREATE') { ++$list->idx; $this->name = CreateDefFragment::parse($parser, $list); if ($this->options->has('TABLE')) { @@ -158,23 +167,10 @@ abstract class Statement } $class = null; // The statement has been processed here. } - } elseif (($token->value === 'GROUP') - || ($token->value === 'ORDER') - ) { - $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'BY'); - } elseif ($token->value === 'RENAME') { + } else if ($token->value === 'RENAME') { $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'TABLE'); - ++$list->idx; - $this->renames = RenameKeyword::parse($parser, $list); - } elseif ($token->value === 'SELECT') { - ++$list->idx; // Skipping last option. - $this->expr = SelectKeyword::parse($parser, $list); - } elseif ($token->value === 'UPDATE') { - ++$list->idx; // Skipping last option. - $this->from = FromKeyword::parse($parser, $list); } - // Finally, processing the keyword (if possible). if ($class !== null) { ++$list->idx; // Skipping keyword. $this->$field = $class::parse($parser, $list, array()); diff --git a/libraries/sql-parser/src/Utils/Misc.php b/libraries/sql-parser/src/Utils/Misc.php index 4e818c6789..4332ae0642 100644 --- a/libraries/sql-parser/src/Utils/Misc.php +++ b/libraries/sql-parser/src/Utils/Misc.php @@ -2,7 +2,7 @@ namespace SqlParser\Utils; -use SqlParser\Statements\SelectStatement; +use SqlParser\Statement; /** * Miscellaneous utilities. @@ -19,13 +19,17 @@ class Misc /** * Gets a list of all aliases and their original names. * - * @param SelectStatement $tree The tree that was generated after parsing. - * @param string $database The name of the database. + * @param Statement $tree The tree that was generated after parsing. + * @param string $database The name of the database. * * @return array */ - public static function getAliases(SelectStatement $tree, $database) + public static function getAliases(Statement $tree, $database) { + if ((empty($tree->from)) || (empty($tree->expr))) { + return array(); + } + $retval = array(); $tables = array(); diff --git a/libraries/sql-parser/src/Utils/Routine.php b/libraries/sql-parser/src/Utils/Routine.php index 8be7db1260..740ace371a 100644 --- a/libraries/sql-parser/src/Utils/Routine.php +++ b/libraries/sql-parser/src/Utils/Routine.php @@ -4,9 +4,9 @@ namespace SqlParser\Utils; use SqlParser\Lexer; use SqlParser\Parser; +use SqlParser\Statement; use SqlParser\Fragments\DataTypeFragment; use SqlParser\Fragments\ParamDefFragment; -use SqlParser\Statements\CreateStatement; /** * Routine utilities. @@ -89,11 +89,11 @@ class Routine /** * Gets the parameters of a routine from the parse tree. * - * @param CreateStatement $tree The tree that was generated after parsing. + * @param Statement $tree The tree that was generated after parsing. * * @return array */ - public static function getParameters(CreateStatement $tree) + public static function getParameters(Statement $tree) { $retval = array( 'num' => 0, @@ -105,23 +105,25 @@ class Routine 'opts' => array(), ); - $idx = 0; - foreach ($tree->parameters as $param) { - $retval['dir'][$idx] = $param->inOut; - $retval['name'][$idx] = $param->name; - $retval['type'][$idx] = $param->type->name; - $retval['length'][$idx] = implode(',', $param->type->parameters); - $retval['length_arr'][$idx] = $param->type->parameters; - $retval['opts'][$idx] = array(); - foreach ($param->type->options->options as $opt) { - $retval['opts'][$idx][] = is_string($opt) ? - $opt : $opt['value']; + if (!empty($tree->parameters)) { + $idx = 0; + foreach ($tree->parameters as $param) { + $retval['dir'][$idx] = $param->inOut; + $retval['name'][$idx] = $param->name; + $retval['type'][$idx] = $param->type->name; + $retval['length'][$idx] = implode(',', $param->type->parameters); + $retval['length_arr'][$idx] = $param->type->parameters; + $retval['opts'][$idx] = array(); + foreach ($param->type->options->options as $opt) { + $retval['opts'][$idx][] = is_string($opt) ? + $opt : $opt['value']; + } + $retval['opts'][$idx] = implode(' ', $retval['opts'][$idx]); + ++$idx; } - $retval['opts'][$idx] = implode(' ', $retval['opts'][$idx]); - ++$idx; - } - $retval['num'] = $idx; + $retval['num'] = $idx; + } return $retval; } diff --git a/libraries/sql-parser/src/Utils/Table.php b/libraries/sql-parser/src/Utils/Table.php index a814075459..7be3eac5b9 100644 --- a/libraries/sql-parser/src/Utils/Table.php +++ b/libraries/sql-parser/src/Utils/Table.php @@ -4,9 +4,9 @@ namespace SqlParser\Utils; use SqlParser\Lexer; use SqlParser\Parser; +use SqlParser\Statement; use SqlParser\Fragments\DataTypeFragment; use SqlParser\Fragments\ParamDefFragment; -use SqlParser\Statements\CreateStatement; /** * Table utilities. @@ -20,9 +20,9 @@ use SqlParser\Statements\CreateStatement; class Table { - public static function getForeignKeys(CreateStatement $tree) + public static function getForeignKeys(Statement $tree) { - if (($tree->fields === null) || (!$tree->options->has('TABLE'))) { + if ((empty($tree->fields)) || (!$tree->options->has('TABLE'))) { return array(); } @@ -63,9 +63,9 @@ class Table return $ret; } - public static function getFields(CreateStatement $tree) + public static function getFields(Statement $tree) { - if (($tree->fields === null) || (!$tree->options->has('TABLE'))) { + if ((empty($tree->fields)) || (!$tree->options->has('TABLE'))) { return array(); } From 3c9aeef364c71e32da76f40f37af90f9cd76ed04 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Thu, 25 Jun 2015 20:08:49 +0300 Subject: [PATCH 23/57] Updated sql-parser library. Refactoring and coding style fixes. Signed-off-by: Dan Ungureanu --- libraries/relation.lib.php | 6 +- libraries/rte/rte_list.lib.php | 8 +- libraries/rte/rte_routines.lib.php | 16 +- libraries/sql-parser/autoload.php | 59 +++- libraries/sql-parser/composer/ClassLoader.php | 100 +++--- .../sql-parser/composer/autoload_psr4.php | 8 - .../sql-parser/composer/autoload_real.php | 38 --- .../src/Contexts/ContextMySql50000.php | 243 +++++++++----- .../src/Contexts/ContextMySql50100.php | 269 +++++++++------ .../src/Contexts/ContextMySql50500.php | 270 +++++++++------ .../src/Contexts/ContextMySql50600.php | 306 +++++++++++------ .../src/Contexts/ContextMySql50700.php | 313 ++++++++++++------ .../src/Fragments/FieldFragment.php | 61 ++++ .../sql-parser/src/Fragments/IntoKeyword.php | 42 ++- .../sql-parser/src/Fragments/KeyFragment.php | 7 + .../sql-parser/src/Fragments/LimitKeyword.php | 2 +- .../src/Fragments/OptionsFragment.php | 17 + libraries/sql-parser/src/Parser.php | 63 +++- libraries/sql-parser/src/Statement.php | 63 +++- .../src/Statements/AlterStatement.php | 48 +++ .../src/Statements/AnalyzeStatement.php | 50 +++ .../src/Statements/BackupStatement.php | 51 +++ .../src/Statements/CheckStatement.php | 53 +++ .../src/Statements/ChecsumStatement.php | 49 +++ .../src/Statements/CreateStatement.php | 26 +- .../src/Statements/DropStatement.php | 57 ++++ .../src/Statements/ExplainStatement.php | 19 ++ .../src/Statements/OptimizeStatement.php | 50 +++ .../src/Statements/RepairStatement.php | 55 +++ .../src/Statements/RestoreStatement.php | 48 +++ .../src/Statements/SelectStatement.php | 14 + .../src/Statements/ShowStatement.php | 76 +++++ libraries/sql-parser/src/Token.php | 1 + libraries/sql-parser/src/Utils/Misc.php | 7 +- libraries/sql-parser/src/Utils/Query.php | 131 ++++++++ libraries/sql-parser/src/Utils/Routine.php | 5 +- libraries/sql-parser/src/Utils/Table.php | 19 +- tbl_structure.php | 8 +- 38 files changed, 2035 insertions(+), 623 deletions(-) delete mode 100644 libraries/sql-parser/composer/autoload_psr4.php delete mode 100644 libraries/sql-parser/composer/autoload_real.php create mode 100644 libraries/sql-parser/src/Statements/AlterStatement.php create mode 100644 libraries/sql-parser/src/Statements/AnalyzeStatement.php create mode 100644 libraries/sql-parser/src/Statements/BackupStatement.php create mode 100644 libraries/sql-parser/src/Statements/CheckStatement.php create mode 100644 libraries/sql-parser/src/Statements/ChecsumStatement.php create mode 100644 libraries/sql-parser/src/Statements/DropStatement.php create mode 100644 libraries/sql-parser/src/Statements/ExplainStatement.php create mode 100644 libraries/sql-parser/src/Statements/OptimizeStatement.php create mode 100644 libraries/sql-parser/src/Statements/RepairStatement.php create mode 100644 libraries/sql-parser/src/Statements/RestoreStatement.php create mode 100644 libraries/sql-parser/src/Statements/ShowStatement.php create mode 100644 libraries/sql-parser/src/Utils/Query.php diff --git a/libraries/relation.lib.php b/libraries/relation.lib.php index 340db7d238..aac34cbdac 100644 --- a/libraries/relation.lib.php +++ b/libraries/relation.lib.php @@ -741,7 +741,11 @@ function PMA_getForeigners($db, $table, $column = '', $source = 'both') ); if ($show_create_table) { $parser = new SqlParser\Parser($show_create_table); - $foreign['foreign_keys_data'] = SqlParser\Utils\Table::getForeignKeys($parser->statements[0]); + /** + * @var CreateStatement $stmt + */ + $stmt = $parser->statements[0]; + $foreign['foreign_keys_data'] = SqlParser\Utils\Table::getForeignKeys($stmt); } } diff --git a/libraries/rte/rte_list.lib.php b/libraries/rte/rte_list.lib.php index be509c7eb7..79abd376b5 100644 --- a/libraries/rte/rte_list.lib.php +++ b/libraries/rte/rte_list.lib.php @@ -228,7 +228,13 @@ function PMA_RTN_getRowForList($routine, $rowclass = '') $routine['name'] ) ); - $params = SqlParser\Utils\Routine::getParameters($parser->statements[0]); + + /** + * @var CreateStatement $stmt + */ + $stmt = $parser->statements[0]; + + $params = SqlParser\Utils\Routine::getParameters($stmt); if ($routine !== false) { if (PMA_Util::currentUserHasPrivilege('EXECUTE', $db)) { $execute_action = 'execute_routine'; diff --git a/libraries/rte/rte_routines.lib.php b/libraries/rte/rte_routines.lib.php index 8cb00379a0..2671d620fe 100644 --- a/libraries/rte/rte_routines.lib.php +++ b/libraries/rte/rte_routines.lib.php @@ -517,9 +517,13 @@ function PMA_RTN_getDataFromName($name, $type, $all = true) $routine['SPECIFIC_NAME'] ) ); - $routineStatement = $parser->statements[0]; - $params = SqlParser\Utils\Routine::getParameters($routineStatement); + /** + * @var CreateStatement $stmt + */ + $stmt = $parser->statements[0]; + + $params = SqlParser\Utils\Routine::getParameters($stmt); $retval['item_num_params'] = $params['num']; $retval['item_param_dir'] = $params['dir']; $retval['item_param_name'] = $params['name']; @@ -546,17 +550,17 @@ function PMA_RTN_getDataFromName($name, $type, $all = true) if (! empty($routine['DTD_IDENTIFIER'])) { $options = array(); - foreach ($routineStatement->return->options->options as $opt) { + foreach ($stmt->return->options->options as $opt) { $options[] = is_string($opt) ? $opt : $opt['value']; } - $retval['item_returntype'] = $routineStatement->return->name; - $retval['item_returnlength'] = implode(',', $routineStatement->return->size); + $retval['item_returntype'] = $stmt->return->name; + $retval['item_returnlength'] = implode(',', $stmt->return->size); $retval['item_returnopts_num'] = implode(' ', $options); $retval['item_returnopts_text'] = implode(' ', $options); } - $retval['item_definer'] = $routineStatement->options->has('DEFINER'); + $retval['item_definer'] = $stmt->options->has('DEFINER'); $retval['item_definition'] = $routine['ROUTINE_DEFINITION']; $retval['item_isdeterministic'] = ''; if ($routine['IS_DETERMINISTIC'] == 'YES') { diff --git a/libraries/sql-parser/autoload.php b/libraries/sql-parser/autoload.php index 0e42d154fd..882015deaf 100644 --- a/libraries/sql-parser/autoload.php +++ b/libraries/sql-parser/autoload.php @@ -1,5 +1,60 @@ $path) { + $loader->setPsr4($namespace, $path); + } + + $loader->register(true); + + return $loader; + } +} + +// Initializing Composer's autoloader +return ComposerAutoloaderInit::getLoader( + array( + 'SqlParser\\' => array(dirname(__FILE__) . '/src'), + ) +); diff --git a/libraries/sql-parser/composer/ClassLoader.php b/libraries/sql-parser/composer/ClassLoader.php index 48ee07c4f5..d2fd53f82d 100644 --- a/libraries/sql-parser/composer/ClassLoader.php +++ b/libraries/sql-parser/composer/ClassLoader.php @@ -1,6 +1,6 @@ @@ -43,50 +43,23 @@ namespace Composer\Autoload; class ClassLoader { // PSR-4 - private $prefixLengthsPsr4 = array(); - private $prefixDirsPsr4 = array(); - private $fallbackDirsPsr4 = array(); + public $prefixLengthsPsr4 = array(); + public $prefixDirsPsr4 = array(); + public $fallbackDirsPsr4 = array(); // PSR-0 - private $prefixesPsr0 = array(); - private $fallbackDirsPsr0 = array(); + public $prefixesPsr0 = array(); + public $fallbackDirsPsr0 = array(); - private $useIncludePath = false; - private $classMap = array(); + public $useIncludePath = false; + public $classMap = array(); - private $classMapAuthoritative = false; - - public function getPrefixes() - { - if (!empty($this->prefixesPsr0)) { - return call_user_func_array('array_merge', $this->prefixesPsr0); - } - - return array(); - } - - public function getPrefixesPsr4() - { - return $this->prefixDirsPsr4; - } - - public function getFallbackDirs() - { - return $this->fallbackDirsPsr0; - } - - public function getFallbackDirsPsr4() - { - return $this->fallbackDirsPsr4; - } - - public function getClassMap() - { - return $this->classMap; - } + public $classMapAuthoritative = false; /** * @param array $classMap Class to filename map + * + * @return void */ public function addClassMap(array $classMap) { @@ -104,6 +77,8 @@ class ClassLoader * @param string $prefix The prefix * @param array|string $paths The PSR-0 root directories * @param bool $prepend Whether to prepend the directories + * + * @return void */ public function add($prefix, $paths, $prepend = false) { @@ -151,6 +126,8 @@ class ClassLoader * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException + * + * @return void */ public function addPsr4($prefix, $paths, $prepend = false) { @@ -196,6 +173,8 @@ class ClassLoader * * @param string $prefix The prefix * @param array|string $paths The PSR-0 base directories + * + * @return void */ public function set($prefix, $paths) { @@ -214,6 +193,8 @@ class ClassLoader * @param array|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException + * + * @return void */ public function setPsr4($prefix, $paths) { @@ -233,6 +214,8 @@ class ClassLoader * Turns on searching the include path for class files. * * @param bool $useIncludePath + * + * @return void */ public function setUseIncludePath($useIncludePath) { @@ -255,6 +238,8 @@ class ClassLoader * that have not been registered with the class map. * * @param bool $classMapAuthoritative + * + * @return void */ public function setClassMapAuthoritative($classMapAuthoritative) { @@ -275,6 +260,8 @@ class ClassLoader * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void */ public function register($prepend = false) { @@ -283,6 +270,8 @@ class ClassLoader /** * Unregisters this instance as an autoloader. + * + * @return void */ public function unregister() { @@ -293,6 +282,7 @@ class ClassLoader * Loads the given class or interface. * * @param string $class The name of the class + * * @return bool|null True if loaded, null otherwise */ public function loadClass($class) @@ -341,7 +331,16 @@ class ClassLoader return $file; } - private function findFileWithExtension($class, $ext) + /** + * Finds a file that defines the specified class and has the specified + * extension. + * + * @param string $class + * @param string $ext + * + * @return string + */ + public function findFileWithExtension($class, $ext) { // PSR-4 lookup $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; @@ -402,12 +401,19 @@ class ClassLoader } } -/** - * Scope isolated include. - * - * Prevents access to $this/self from included files. - */ -function includeFile($file) -{ - include $file; +if (!function_exists('Composer\Autoload\includeFile')) { + + /** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + * + * @param string $file + * + * @return void + */ + function includeFile($file) + { + include $file; + } } diff --git a/libraries/sql-parser/composer/autoload_psr4.php b/libraries/sql-parser/composer/autoload_psr4.php deleted file mode 100644 index 756ce5f0a8..0000000000 --- a/libraries/sql-parser/composer/autoload_psr4.php +++ /dev/null @@ -1,8 +0,0 @@ - array($vendorDir . '/src'), -); diff --git a/libraries/sql-parser/composer/autoload_real.php b/libraries/sql-parser/composer/autoload_real.php deleted file mode 100644 index 4972d8f566..0000000000 --- a/libraries/sql-parser/composer/autoload_real.php +++ /dev/null @@ -1,38 +0,0 @@ - $path) { - $loader->setPsr4($namespace, $path); - } - - $loader->register(true); - - return $loader; - } -} - -function composerRequire($file) -{ - require $file; -} diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50000.php b/libraries/sql-parser/src/Contexts/ContextMySql50000.php index 63f4ca2780..d4b80e1f61 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50000.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50000.php @@ -34,121 +34,111 @@ class ContextMySql50000 extends Context public static $KEYWORDS = array( 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, - 'ANY' => 1, 'AVG' => 1, 'BDB' => 1, 'BIT' => 1, 'CPU' => 1, 'DAY' => 1, - 'END' => 1, 'IPC' => 1, 'NDB' => 1, 'NEW' => 1, 'ONE' => 1, 'ROW' => 1, + 'ANY' => 1, 'BDB' => 1, 'BIT' => 1, 'CPU' => 1, 'END' => 1, 'IPC' => 1, + 'NDB' => 1, 'NEW' => 1, 'ONE' => 1, 'ROW' => 1, 'BOOL' => 1, 'BYTE' => 1, 'CODE' => 1, 'CUBE' => 1, 'DATA' => 1, 'FAST' => 1, - 'FILE' => 1, 'FULL' => 1, 'HASH' => 1, 'HELP' => 1, 'HOUR' => 1, 'LAST' => 1, - 'LOGS' => 1, 'MODE' => 1, 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'OPEN' => 1, - 'PAGE' => 1, 'PREV' => 1, 'ROWS' => 1, 'SOME' => 1, 'STOP' => 1, 'TYPE' => 1, - 'USER' => 1, 'VIEW' => 1, 'WEEK' => 1, 'WORK' => 1, 'X509' => 1, - 'AFTER' => 1, 'ASCII' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, - 'CACHE' => 1, 'CHAIN' => 1, 'CLOSE' => 1, 'FIRST' => 1, 'FIXED' => 1, - 'FLUSH' => 1, 'FOUND' => 1, 'HOSTS' => 1, 'LEVEL' => 1, 'LOCAL' => 1, - 'LOCKS' => 1, 'MERGE' => 1, 'MONTH' => 1, 'MUTEX' => 1, 'NAMES' => 1, - 'NCHAR' => 1, 'PHASE' => 1, 'POINT' => 1, 'QUERY' => 1, 'QUICK' => 1, - 'RAID0' => 1, 'RESET' => 1, 'RTREE' => 1, 'SHARE' => 1, 'SLAVE' => 1, - 'START' => 1, 'SUPER' => 1, 'SWAPS' => 1, 'TYPES' => 1, 'UNTIL' => 1, - 'VALUE' => 1, + 'FILE' => 1, 'FULL' => 1, 'HASH' => 1, 'HELP' => 1, 'LAST' => 1, 'LOGS' => 1, + 'MODE' => 1, 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'OPEN' => 1, 'PAGE' => 1, + 'PREV' => 1, 'ROWS' => 1, 'SOME' => 1, 'STOP' => 1, 'TYPE' => 1, 'VIEW' => 1, + 'WORK' => 1, 'X509' => 1, + 'AFTER' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, 'CACHE' => 1, + 'CHAIN' => 1, 'CLOSE' => 1, 'FIRST' => 1, 'FIXED' => 1, 'FLUSH' => 1, + 'FOUND' => 1, 'HOSTS' => 1, 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, + 'MERGE' => 1, 'MUTEX' => 1, 'NAMES' => 1, 'NCHAR' => 1, 'PHASE' => 1, + 'QUERY' => 1, 'QUICK' => 1, 'RAID0' => 1, 'RESET' => 1, 'RTREE' => 1, + 'SHARE' => 1, 'SLAVE' => 1, 'START' => 1, 'SUPER' => 1, 'SWAPS' => 1, + 'TYPES' => 1, 'UNTIL' => 1, 'VALUE' => 1, 'ACTION' => 1, 'BACKUP' => 1, 'BINLOG' => 1, 'CIPHER' => 1, 'CLIENT' => 1, 'COMMIT' => 1, 'ENABLE' => 1, 'ENGINE' => 1, 'ERRORS' => 1, 'ESCAPE' => 1, 'EVENTS' => 1, 'FAULTS' => 1, 'FIELDS' => 1, 'GLOBAL' => 1, 'GRANTS' => 1, 'IMPORT' => 1, 'INNODB' => 1, 'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1, - 'MEDIUM' => 1, 'MEMORY' => 1, 'MINUTE' => 1, 'MODIFY' => 1, 'OFFSET' => 1, - 'RELOAD' => 1, 'REPAIR' => 1, 'RESUME' => 1, 'ROLLUP' => 1, 'SECOND' => 1, - 'SERIAL' => 1, 'SIGNED' => 1, 'SIMPLE' => 1, 'SOUNDS' => 1, 'SOURCE' => 1, - 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1, - 'AGAINST' => 1, 'CHANGED' => 1, 'CHARSET' => 1, 'COLUMNS' => 1, 'COMMENT' => 1, - 'COMPACT' => 1, 'CONTEXT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1, - 'DYNAMIC' => 1, 'ENGINES' => 1, 'EXECUTE' => 1, 'HANDLER' => 1, 'INDEXES' => 1, - 'INVOKER' => 1, 'MIGRATE' => 1, 'PARTIAL' => 1, 'POLYGON' => 1, 'PREPARE' => 1, - 'PROFILE' => 1, 'QUARTER' => 1, 'RECOVER' => 1, 'RESTORE' => 1, 'RETURNS' => 1, - 'ROUTINE' => 1, 'SESSION' => 1, 'STORAGE' => 1, 'STRIPED' => 1, 'SUBJECT' => 1, - 'SUSPEND' => 1, 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1, 'USE_FRM' => 1, - 'CASCADED' => 1, 'CHECKSUM' => 1, 'CONTAINS' => 1, 'DUMPFILE' => 1, - 'EXTENDED' => 1, 'FUNCTION' => 1, 'GEOMETRY' => 1, 'INNOBASE' => 1, - 'LANGUAGE' => 1, 'MAX_ROWS' => 1, 'MIN_ROWS' => 1, 'NATIONAL' => 1, - 'NVARCHAR' => 1, 'ONE_SHOT' => 1, 'PASSWORD' => 1, 'PROFILES' => 1, - 'ROLLBACK' => 1, 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1, - 'SWITCHES' => 1, 'TRIGGERS' => 1, 'TRUNCATE' => 1, 'WARNINGS' => 1, - 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COLLATION' => 1, 'COMMITTED' => 1, - 'DIRECTORY' => 1, 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, - 'ISOLATION' => 1, 'PACK_KEYS' => 1, 'RAID_TYPE' => 1, 'REDUNDANT' => 1, - 'SAVEPOINT' => 1, 'SQL_CACHE' => 1, 'TEMPORARY' => 1, 'TEMPTABLE' => 1, - 'UNDEFINED' => 1, 'VARIABLES' => 1, + 'MEDIUM' => 1, 'MEMORY' => 1, 'MODIFY' => 1, 'OFFSET' => 1, 'RELOAD' => 1, + 'REPAIR' => 1, 'RESUME' => 1, 'ROLLUP' => 1, 'SERIAL' => 1, 'SIGNED' => 1, + 'SIMPLE' => 1, 'SOUNDS' => 1, 'SOURCE' => 1, 'STATUS' => 1, 'STRING' => 1, + 'TABLES' => 1, + 'AGAINST' => 1, 'CHANGED' => 1, 'COLUMNS' => 1, 'COMMENT' => 1, 'COMPACT' => 1, + 'CONTEXT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1, 'DYNAMIC' => 1, + 'ENGINES' => 1, 'EXECUTE' => 1, 'HANDLER' => 1, 'INDEXES' => 1, 'INVOKER' => 1, + 'MIGRATE' => 1, 'PARTIAL' => 1, 'PREPARE' => 1, 'PROFILE' => 1, 'RECOVER' => 1, + 'RESTORE' => 1, 'RETURNS' => 1, 'ROUTINE' => 1, 'SESSION' => 1, 'STORAGE' => 1, + 'STRIPED' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1, 'UNICODE' => 1, 'UNKNOWN' => 1, + 'UPGRADE' => 1, 'USE_FRM' => 1, + 'CASCADED' => 1, 'CHECKSUM' => 1, 'DUMPFILE' => 1, 'EXTENDED' => 1, + 'FUNCTION' => 1, 'GEOMETRY' => 1, 'INNOBASE' => 1, 'LANGUAGE' => 1, + 'MAX_ROWS' => 1, 'MIN_ROWS' => 1, 'NATIONAL' => 1, 'NVARCHAR' => 1, + 'ONE_SHOT' => 1, 'PROFILES' => 1, 'ROLLBACK' => 1, 'SECURITY' => 1, + 'SHUTDOWN' => 1, 'SNAPSHOT' => 1, 'SWITCHES' => 1, 'TRIGGERS' => 1, + 'WARNINGS' => 1, + 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COMMITTED' => 1, 'DIRECTORY' => 1, + 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, 'ISOLATION' => 1, + 'PACK_KEYS' => 1, 'RAID_TYPE' => 1, 'REDUNDANT' => 1, 'SAVEPOINT' => 1, + 'SQL_CACHE' => 1, 'TEMPORARY' => 1, 'TEMPTABLE' => 1, 'UNDEFINED' => 1, + 'VARIABLES' => 1, 'BERKELEYDB' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1, - 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'GET_FORMAT' => 1, 'IDENTIFIED' => 1, - 'LINESTRING' => 1, 'MASTER_SSL' => 1, 'MULTIPOINT' => 1, 'NDBCLUSTER' => 1, - 'PRIVILEGES' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, - 'TABLESPACE' => 1, + 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'IDENTIFIED' => 1, 'MASTER_SSL' => 1, + 'NDBCLUSTER' => 1, 'PRIVILEGES' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, + 'SQL_THREAD' => 1, 'TABLESPACE' => 1, 'FRAC_SECOND' => 1, 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, - 'MICROSECOND' => 1, 'PROCESSLIST' => 1, 'RAID_CHUNKS' => 1, 'REPLICATION' => 1, - 'SQL_TSI_DAY' => 1, 'TRANSACTION' => 1, 'UNCOMMITTED' => 1, - 'DES_KEY_FILE' => 1, 'MULTIPOLYGON' => 1, 'OLD_PASSWORD' => 1, - 'RELAY_THREAD' => 1, 'SERIALIZABLE' => 1, 'SQL_NO_CACHE' => 1, - 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1, 'SQL_TSI_YEAR' => 1, - 'TIMESTAMPADD' => 1, + 'PROCESSLIST' => 1, 'RAID_CHUNKS' => 1, 'REPLICATION' => 1, 'SQL_TSI_DAY' => 1, + 'TRANSACTION' => 1, 'UNCOMMITTED' => 1, + 'DES_KEY_FILE' => 1, 'RELAY_THREAD' => 1, 'SERIALIZABLE' => 1, + 'SQL_NO_CACHE' => 1, 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1, + 'SQL_TSI_YEAR' => 1, 'INSERT_METHOD' => 1, 'MASTER_SSL_CA' => 1, 'RELAY_LOG_POS' => 1, - 'SQL_TSI_MONTH' => 1, 'TIMESTAMPDIFF' => 1, + 'SQL_TSI_MONTH' => 1, 'AUTO_INCREMENT' => 1, 'AVG_ROW_LENGTH' => 1, 'MASTER_LOG_POS' => 1, 'MASTER_SSL_KEY' => 1, 'RAID_CHUNKSIZE' => 1, 'RELAY_LOG_FILE' => 1, 'SQL_TSI_MINUTE' => 1, 'SQL_TSI_SECOND' => 1, 'USER_RESOURCES' => 1, 'DELAY_KEY_WRITE' => 1, 'MASTER_LOG_FILE' => 1, 'MASTER_PASSWORD' => 1, - 'MASTER_SSL_CERT' => 1, 'MULTILINESTRING' => 1, 'SQL_TSI_QUARTER' => 1, + 'MASTER_SSL_CERT' => 1, 'SQL_TSI_QUARTER' => 1, 'MASTER_SERVER_ID' => 1, 'MASTER_SSL_CAPATH' => 1, 'MASTER_SSL_CIPHER' => 1, 'SQL_BUFFER_RESULT' => 1, - 'GEOMETRYCOLLECTION' => 1, 'SQL_TSI_FRAC_SECOND' => 1, 'MASTER_CONNECT_RETRY' => 1, 'MAX_QUERIES_PER_HOUR' => 1, 'MAX_UPDATES_PER_HOUR' => 1, 'MAX_USER_CONNECTIONS' => 1, 'MAX_CONNECTIONS_PER_HOUR' => 1, - 'AS' => 3, 'BY' => 3, 'IF' => 3, 'IN' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, - 'TO' => 3, + 'AS' => 3, 'BY' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, 'TO' => 3, 'ADD' => 3, 'ALL' => 3, 'AND' => 3, 'ASC' => 3, 'DEC' => 3, 'DIV' => 3, - 'FOR' => 3, 'MOD' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, 'SSL' => 3, - 'USE' => 3, 'XOR' => 3, + 'FOR' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, 'SSL' => 3, 'USE' => 3, + 'XOR' => 3, 'BOTH' => 3, 'CALL' => 3, 'CASE' => 3, 'DESC' => 3, 'DROP' => 3, 'DUAL' => 3, 'EACH' => 3, 'ELSE' => 3, 'EXIT' => 3, 'FROM' => 3, 'INT1' => 3, 'INT2' => 3, 'INT3' => 3, 'INT4' => 3, 'INT8' => 3, 'INTO' => 3, 'JOIN' => 3, 'KEYS' => 3, - 'KILL' => 3, 'LEFT' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, - 'LOOP' => 3, 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, - 'UNDO' => 3, 'WHEN' => 3, 'WITH' => 3, + 'KILL' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, 'LOOP' => 3, + 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, 'UNDO' => 3, + 'WHEN' => 3, 'WITH' => 3, 'ALTER' => 3, 'CHECK' => 3, 'CROSS' => 3, 'FALSE' => 3, 'FETCH' => 3, 'FORCE' => 3, 'GRANT' => 3, 'GROUP' => 3, 'INNER' => 3, 'INOUT' => 3, 'LEAVE' => 3, 'LIMIT' => 3, 'LINES' => 3, 'MATCH' => 3, 'ORDER' => 3, - 'OUTER' => 3, 'PURGE' => 3, 'READS' => 3, 'RIGHT' => 3, 'RLIKE' => 3, - 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, 'WHERE' => 3, - 'WHILE' => 3, 'WRITE' => 3, + 'OUTER' => 3, 'PURGE' => 3, 'READS' => 3, 'RLIKE' => 3, 'TABLE' => 3, + 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, 'WHERE' => 3, 'WHILE' => 3, + 'WRITE' => 3, 'BEFORE' => 3, 'CHANGE' => 3, 'COLUMN' => 3, 'CREATE' => 3, 'CURSOR' => 3, 'DELETE' => 3, 'ELSEIF' => 3, 'EXISTS' => 3, 'FLOAT4' => 3, 'FLOAT8' => 3, - 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'INSERT' => 3, 'OPTION' => 3, - 'REGEXP' => 3, 'RENAME' => 3, 'REPEAT' => 3, 'RETURN' => 3, 'REVOKE' => 3, - 'SCHEMA' => 3, 'SELECT' => 3, 'SONAME' => 3, 'UNLOCK' => 3, 'UPDATE' => 3, - 'VALUES' => 3, - 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'CONVERT' => 3, - 'DECLARE' => 3, 'DEFAULT' => 3, 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, - 'FOREIGN' => 3, 'ITERATE' => 3, 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, - 'PRIMARY' => 3, 'RELEASE' => 3, 'REPLACE' => 3, 'REQUIRE' => 3, 'SCHEMAS' => 3, - 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3, - 'CONTINUE' => 3, 'DATABASE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, - 'DISTINCT' => 3, 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MODIFIES' => 3, - 'OPTIMIZE' => 3, 'RESTRICT' => 3, 'SPECIFIC' => 3, 'SQLSTATE' => 3, - 'STARTING' => 3, 'TRAILING' => 3, 'UNSIGNED' => 3, 'UTC_DATE' => 3, - 'UTC_TIME' => 3, 'ZEROFILL' => 3, - 'CONDITION' => 3, 'DATABASES' => 3, 'LOCALTIME' => 3, 'MIDDLEINT' => 3, - 'PRECISION' => 3, 'PROCEDURE' => 3, 'SENSITIVE' => 3, 'SEPARATOR' => 3, + 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'OPTION' => 3, 'REGEXP' => 3, + 'RENAME' => 3, 'RETURN' => 3, 'REVOKE' => 3, 'SELECT' => 3, 'SONAME' => 3, + 'UNLOCK' => 3, 'UPDATE' => 3, + 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'DECLARE' => 3, + 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, 'FOREIGN' => 3, 'ITERATE' => 3, + 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, 'PRIMARY' => 3, 'RELEASE' => 3, + 'REQUIRE' => 3, 'SCHEMAS' => 3, 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3, + 'CONTINUE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, 'DISTINCT' => 3, + 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MODIFIES' => 3, 'OPTIMIZE' => 3, + 'RESTRICT' => 3, 'SPECIFIC' => 3, 'SQLSTATE' => 3, 'STARTING' => 3, + 'TRAILING' => 3, 'UNSIGNED' => 3, 'ZEROFILL' => 3, + 'CONDITION' => 3, 'DATABASES' => 3, 'MIDDLEINT' => 3, 'PRECISION' => 3, + 'PROCEDURE' => 3, 'SENSITIVE' => 3, 'SEPARATOR' => 3, 'ASENSITIVE' => 3, 'CONSTRAINT' => 3, 'DAY_MINUTE' => 3, 'DAY_SECOND' => 3, 'OPTIONALLY' => 3, 'REFERENCES' => 3, 'SQLWARNING' => 3, 'TERMINATED' => 3, 'YEAR_MONTH' => 3, 'DISTINCTROW' => 3, 'HOUR_MINUTE' => 3, 'HOUR_SECOND' => 3, 'INSENSITIVE' => 3, - 'CURRENT_DATE' => 3, 'CURRENT_TIME' => 3, 'CURRENT_USER' => 3, 'LOW_PRIORITY' => 3, 'SQLEXCEPTION' => 3, 'VARCHARACTER' => 3, 'DETERMINISTIC' => 3, 'HIGH_PRIORITY' => 3, 'MINUTE_SECOND' => 3, - 'STRAIGHT_JOIN' => 3, 'UTC_TIMESTAMP' => 3, - 'LOCALTIMESTAMP' => 3, 'SQL_BIG_RESULT' => 3, + 'STRAIGHT_JOIN' => 3, + 'SQL_BIG_RESULT' => 3, 'DAY_MICROSECOND' => 3, 'HOUR_MICROSECOND' => 3, 'SQL_SMALL_RESULT' => 3, - 'CURRENT_TIMESTAMP' => 3, 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3, 'SQL_CALC_FOUND_ROWS' => 3, @@ -162,19 +152,18 @@ class ContextMySql50000 extends Context 'GROUP BY' => 7, 'ORDER BY' => 7, 'XML' => 9, - 'DATE' => 9, 'ENUM' => 9, 'TEXT' => 9, 'TIME' => 9, 'YEAR' => 9, + 'ENUM' => 9, 'TEXT' => 9, 'ARRAY' => 9, 'BOOLEAN' => 9, 'DATETIME' => 9, 'MULTISET' => 9, - 'TIMESTAMP' => 9, 'INT' => 11, 'SET' => 11, - 'BLOB' => 11, 'CHAR' => 11, 'REAL' => 11, + 'BLOB' => 11, 'REAL' => 11, 'FLOAT' => 11, 'BIGINT' => 11, 'BINARY' => 11, 'DOUBLE' => 11, 'DECIMAL' => 11, 'INTEGER' => 11, 'NUMERIC' => 11, 'TINYINT' => 11, 'VARCHAR' => 11, - 'INTERVAL' => 11, 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, - 'TINYBLOB' => 11, 'TINYTEXT' => 11, + 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, 'TINYBLOB' => 11, + 'TINYTEXT' => 11, 'CHARACTER' => 11, 'MEDIUMINT' => 11, 'VARBINARY' => 11, 'MEDIUMBLOB' => 11, 'MEDIUMTEXT' => 11, @@ -191,5 +180,91 @@ class ContextMySql50000 extends Context 'SPATIAL INDEX' => 21, 'FULLTEXT INDEX' => 21, + 'X' => 33, 'Y' => 33, + 'LN' => 33, 'PI' => 33, + 'ABS' => 33, 'AVG' => 33, 'BIN' => 33, 'COS' => 33, 'COT' => 33, 'DAY' => 33, + 'ELT' => 33, 'EXP' => 33, 'HEX' => 33, 'LOG' => 33, 'MAX' => 33, 'MD5' => 33, + 'MID' => 33, 'MIN' => 33, 'NOW' => 33, 'OCT' => 33, 'ORD' => 33, 'POW' => 33, + 'SIN' => 33, 'STD' => 33, 'SUM' => 33, 'TAN' => 33, + 'ACOS' => 33, 'AREA' => 33, 'ASIN' => 33, 'ATAN' => 33, 'CAST' => 33, 'CEIL' => 33, + 'CONV' => 33, 'HOUR' => 33, 'LOG2' => 33, 'LPAD' => 33, 'RAND' => 33, 'RPAD' => 33, + 'SHA1' => 33, 'SIGN' => 33, 'SQRT' => 33, 'SRID' => 33, 'TRIM' => 33, 'USER' => 33, + 'UUID' => 33, 'WEEK' => 33, + 'ASCII' => 33, 'ATAN2' => 33, 'COUNT' => 33, 'CRC32' => 33, 'FIELD' => 33, + 'FLOOR' => 33, 'INSTR' => 33, 'LCASE' => 33, 'LEAST' => 33, 'LOG10' => 33, + 'LOWER' => 33, 'LTRIM' => 33, 'MONTH' => 33, 'POINT' => 33, 'POWER' => 33, + 'QUOTE' => 33, 'ROUND' => 33, 'RTRIM' => 33, 'SLEEP' => 33, 'SPACE' => 33, + 'UCASE' => 33, 'UNHEX' => 33, 'UPPER' => 33, + 'ASTEXT' => 33, 'BIT_OR' => 33, 'CONCAT' => 33, 'DECODE' => 33, 'ENCODE' => 33, + 'EQUALS' => 33, 'FORMAT' => 33, 'IFNULL' => 33, 'ISNULL' => 33, 'LENGTH' => 33, + 'LOCATE' => 33, 'MINUTE' => 33, 'NULLIF' => 33, 'POINTN' => 33, 'SECOND' => 33, + 'STDDEV' => 33, 'STRCMP' => 33, 'SUBSTR' => 33, 'WITHIN' => 33, + 'ADDDATE' => 33, 'ADDTIME' => 33, 'BIT_AND' => 33, 'BIT_XOR' => 33, 'CEILING' => 33, + 'CHARSET' => 33, 'CROSSES' => 33, 'CURDATE' => 33, 'CURTIME' => 33, 'DAYNAME' => 33, + 'DEGREES' => 33, 'ENCRYPT' => 33, 'EXTRACT' => 33, 'GLENGTH' => 33, 'ISEMPTY' => 33, + 'POLYGON' => 33, 'QUARTER' => 33, 'RADIANS' => 33, 'REVERSE' => 33, 'SOUNDEX' => 33, + 'SUBDATE' => 33, 'SUBTIME' => 33, 'SYSDATE' => 33, 'TOUCHES' => 33, 'TO_DAYS' => 33, + 'VAR_POP' => 33, 'VERSION' => 33, 'WEEKDAY' => 33, + 'ASBINARY' => 33, 'CENTROID' => 33, 'COALESCE' => 33, 'COMPRESS' => 33, + 'CONTAINS' => 33, 'DATEDIFF' => 33, 'DATE_ADD' => 33, 'DATE_SUB' => 33, + 'DISJOINT' => 33, 'ENDPOINT' => 33, 'ENVELOPE' => 33, 'GET_LOCK' => 33, + 'GREATEST' => 33, 'ISCLOSED' => 33, 'ISSIMPLE' => 33, 'MAKEDATE' => 33, + 'MAKETIME' => 33, 'MAKE_SET' => 33, 'MBREQUAL' => 33, 'OVERLAPS' => 33, + 'PASSWORD' => 33, 'POSITION' => 33, 'TIMEDIFF' => 33, 'TRUNCATE' => 33, + 'VARIANCE' => 33, 'VAR_SAMP' => 33, 'YEARWEEK' => 33, + 'BENCHMARK' => 33, 'BIT_COUNT' => 33, 'COLLATION' => 33, 'CONCAT_WS' => 33, + 'DAYOFWEEK' => 33, 'DAYOFYEAR' => 33, 'DIMENSION' => 33, 'FROM_DAYS' => 33, + 'GEOMETRYN' => 33, 'INET_ATON' => 33, 'INET_NTOA' => 33, 'LOAD_FILE' => 33, + 'MBRWITHIN' => 33, 'MONTHNAME' => 33, 'NUMPOINTS' => 33, 'ROW_COUNT' => 33, + 'SUBSTRING' => 33, + 'BIT_LENGTH' => 33, 'CONVERT_TZ' => 33, 'DAYOFMONTH' => 33, 'EXPORT_SET' => 33, + 'FOUND_ROWS' => 33, 'GET_FORMAT' => 33, 'INTERSECTS' => 33, 'LINESTRING' => 33, + 'MBRTOUCHES' => 33, 'MULTIPOINT' => 33, 'NAME_CONST' => 33, 'PERIOD_ADD' => 33, + 'STARTPOINT' => 33, 'STDDEV_POP' => 33, 'UNCOMPRESS' => 33, 'WEEKOFYEAR' => 33, + 'AES_DECRYPT' => 33, 'AES_ENCRYPT' => 33, 'CHAR_LENGTH' => 33, 'DATE_FORMAT' => 33, + 'DES_DECRYPT' => 33, 'DES_ENCRYPT' => 33, 'FIND_IN_SET' => 33, 'GEOMFROMWKB' => 33, + 'LINEFROMWKB' => 33, 'MBRCONTAINS' => 33, 'MBRDISJOINT' => 33, 'MBROVERLAPS' => 33, + 'MICROSECOND' => 33, 'PERIOD_DIFF' => 33, 'POLYFROMWKB' => 33, 'SEC_TO_TIME' => 33, + 'STDDEV_SAMP' => 33, 'STR_TO_DATE' => 33, 'SYSTEM_USER' => 33, 'TIME_FORMAT' => 33, + 'TIME_TO_SEC' => 33, + 'COERCIBILITY' => 33, 'EXTERIORRING' => 33, 'GEOMETRYTYPE' => 33, + 'GEOMFROMTEXT' => 33, 'GROUP_CONCAT' => 33, 'IS_FREE_LOCK' => 33, + 'IS_USED_LOCK' => 33, 'LINEFROMTEXT' => 33, 'MLINEFROMWKB' => 33, + 'MPOLYFROMWKB' => 33, 'MULTIPOLYGON' => 33, 'OCTET_LENGTH' => 33, + 'OLD_PASSWORD' => 33, 'POINTFROMWKB' => 33, 'POLYFROMTEXT' => 33, + 'RELEASE_LOCK' => 33, 'SESSION_USER' => 33, 'TIMESTAMPADD' => 33, + 'CONNECTION_ID' => 33, 'FROM_UNIXTIME' => 33, 'INTERIORRINGN' => 33, + 'MBRINTERSECTS' => 33, 'MLINEFROMTEXT' => 33, 'MPOINTFROMWKB' => 33, + 'MPOLYFROMTEXT' => 33, 'NUMGEOMETRIES' => 33, 'POINTFROMTEXT' => 33, + 'TIMESTAMPDIFF' => 33, + 'LAST_INSERT_ID' => 33, 'MPOINTFROMTEXT' => 33, 'UNIX_TIMESTAMP' => 33, + 'GEOMCOLLFROMWKB' => 33, 'MASTER_POS_WAIT' => 33, 'MULTILINESTRING' => 33, + 'SUBSTRING_INDEX' => 33, + 'CHARACTER_LENGTH' => 33, 'GEOMCOLLFROMTEXT' => 33, 'NUMINTERIORRINGS' => 33, + 'GEOMETRYCOLLECTION' => 33, + 'UNCOMPRESSED_LENGTH' => 33, + + 'IF' => 35, 'IN' => 35, + 'MOD' => 35, + 'LEFT' => 35, + 'RIGHT' => 35, + 'INSERT' => 35, 'REPEAT' => 35, 'SCHEMA' => 35, 'VALUES' => 35, + 'CONVERT' => 35, 'DEFAULT' => 35, 'REPLACE' => 35, + 'DATABASE' => 35, 'UTC_DATE' => 35, 'UTC_TIME' => 35, + 'LOCALTIME' => 35, + 'CURRENT_DATE' => 35, 'CURRENT_TIME' => 35, 'CURRENT_USER' => 35, + 'UTC_TIMESTAMP' => 35, + 'LOCALTIMESTAMP' => 35, + 'CURRENT_TIMESTAMP' => 35, + + 'NOT IN' => 37, + 'PROCEDURE ANALYSE' => 37, + + 'DATE' => 41, 'TIME' => 41, 'YEAR' => 41, + 'TIMESTAMP' => 41, + + 'CHAR' => 43, + 'INTERVAL' => 43, + ); } diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50100.php b/libraries/sql-parser/src/Contexts/ContextMySql50100.php index 265979f8b2..c6db3d5e8e 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50100.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50100.php @@ -34,134 +34,121 @@ class ContextMySql50100 extends Context public static $KEYWORDS = array( 'AT' => 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, - 'ANY' => 1, 'AVG' => 1, 'BDB' => 1, 'BIT' => 1, 'CPU' => 1, 'DAY' => 1, - 'END' => 1, 'IPC' => 1, 'NDB' => 1, 'NEW' => 1, 'ONE' => 1, 'ROW' => 1, + 'ANY' => 1, 'BDB' => 1, 'BIT' => 1, 'CPU' => 1, 'END' => 1, 'IPC' => 1, + 'NDB' => 1, 'NEW' => 1, 'ONE' => 1, 'ROW' => 1, 'BOOL' => 1, 'BYTE' => 1, 'CODE' => 1, 'CUBE' => 1, 'DATA' => 1, 'DISK' => 1, 'ENDS' => 1, 'FAST' => 1, 'FILE' => 1, 'FULL' => 1, 'GOTO' => 1, 'HASH' => 1, - 'HELP' => 1, 'HOST' => 1, 'HOUR' => 1, 'LAST' => 1, 'LESS' => 1, 'LIST' => 1, - 'LOGS' => 1, 'MODE' => 1, 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'OPEN' => 1, - 'PAGE' => 1, 'PORT' => 1, 'PREV' => 1, 'ROWS' => 1, 'SOME' => 1, 'STOP' => 1, - 'THAN' => 1, 'TYPE' => 1, 'USER' => 1, 'VIEW' => 1, 'WAIT' => 1, 'WEEK' => 1, - 'WORK' => 1, 'X509' => 1, - 'AFTER' => 1, 'ASCII' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, - 'CACHE' => 1, 'CHAIN' => 1, 'CLOSE' => 1, 'EVENT' => 1, 'EVERY' => 1, - 'FIRST' => 1, 'FIXED' => 1, 'FLUSH' => 1, 'FOUND' => 1, 'HOSTS' => 1, - 'LABEL' => 1, 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, 'MERGE' => 1, - 'MONTH' => 1, 'MUTEX' => 1, 'NAMES' => 1, 'NCHAR' => 1, 'OWNER' => 1, - 'PHASE' => 1, 'POINT' => 1, 'QUERY' => 1, 'QUICK' => 1, 'RAID0' => 1, - 'RESET' => 1, 'RTREE' => 1, 'SHARE' => 1, 'SLAVE' => 1, 'START' => 1, - 'SUPER' => 1, 'SWAPS' => 1, 'TYPES' => 1, 'UNTIL' => 1, 'VALUE' => 1, + 'HELP' => 1, 'HOST' => 1, 'LAST' => 1, 'LESS' => 1, 'LIST' => 1, 'LOGS' => 1, + 'MODE' => 1, 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'OPEN' => 1, 'PAGE' => 1, + 'PORT' => 1, 'PREV' => 1, 'ROWS' => 1, 'SOME' => 1, 'STOP' => 1, 'THAN' => 1, + 'TYPE' => 1, 'VIEW' => 1, 'WAIT' => 1, 'WORK' => 1, 'X509' => 1, + 'AFTER' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, 'CACHE' => 1, + 'CHAIN' => 1, 'CLOSE' => 1, 'EVENT' => 1, 'EVERY' => 1, 'FIRST' => 1, + 'FIXED' => 1, 'FLUSH' => 1, 'FOUND' => 1, 'HOSTS' => 1, 'LABEL' => 1, + 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, 'MERGE' => 1, 'MUTEX' => 1, + 'NAMES' => 1, 'NCHAR' => 1, 'OWNER' => 1, 'PHASE' => 1, 'QUERY' => 1, + 'QUICK' => 1, 'RAID0' => 1, 'RESET' => 1, 'RTREE' => 1, 'SHARE' => 1, + 'SLAVE' => 1, 'START' => 1, 'SUPER' => 1, 'SWAPS' => 1, 'TYPES' => 1, + 'UNTIL' => 1, 'VALUE' => 1, 'ACTION' => 1, 'BACKUP' => 1, 'BINLOG' => 1, 'CIPHER' => 1, 'CLIENT' => 1, 'COMMIT' => 1, 'ENABLE' => 1, 'ENGINE' => 1, 'ERRORS' => 1, 'ESCAPE' => 1, 'EVENTS' => 1, 'FAULTS' => 1, 'FIELDS' => 1, 'GLOBAL' => 1, 'GRANTS' => 1, 'IMPORT' => 1, 'INNODB' => 1, 'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1, - 'MEDIUM' => 1, 'MEMORY' => 1, 'MINUTE' => 1, 'MODIFY' => 1, 'OFFSET' => 1, - 'PARSER' => 1, 'PLUGIN' => 1, 'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, - 'RESUME' => 1, 'ROLLUP' => 1, 'SECOND' => 1, 'SERIAL' => 1, 'SERVER' => 1, - 'SIGNED' => 1, 'SIMPLE' => 1, 'SOCKET' => 1, 'SONAME' => 1, 'SOUNDS' => 1, - 'SOURCE' => 1, 'STARTS' => 1, 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1, - 'AGAINST' => 1, 'AUTHORS' => 1, 'CHANGED' => 1, 'CHARSET' => 1, 'COLUMNS' => 1, - 'COMMENT' => 1, 'COMPACT' => 1, 'CONTEXT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, - 'DISCARD' => 1, 'DYNAMIC' => 1, 'ENGINES' => 1, 'EXECUTE' => 1, 'HANDLER' => 1, - 'INDEXES' => 1, 'INSTALL' => 1, 'INVOKER' => 1, 'LOGFILE' => 1, 'MIGRATE' => 1, - 'NO_WAIT' => 1, 'OPTIONS' => 1, 'PARTIAL' => 1, 'PLUGINS' => 1, 'POLYGON' => 1, - 'PREPARE' => 1, 'PROFILE' => 1, 'QUARTER' => 1, 'REBUILD' => 1, 'RECOVER' => 1, - 'RESTORE' => 1, 'RETURNS' => 1, 'ROUTINE' => 1, 'SESSION' => 1, 'STORAGE' => 1, - 'STRIPED' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1, 'UNICODE' => 1, 'UNKNOWN' => 1, - 'UPGRADE' => 1, 'USE_FRM' => 1, 'WRAPPER' => 1, - 'CASCADED' => 1, 'CHECKSUM' => 1, 'COALESCE' => 1, 'CONTAINS' => 1, - 'DATAFILE' => 1, 'DUMPFILE' => 1, 'EXTENDED' => 1, 'FUNCTION' => 1, - 'GEOMETRY' => 1, 'INNOBASE' => 1, 'LANGUAGE' => 1, 'MAXVALUE' => 1, - 'MAX_ROWS' => 1, 'MAX_SIZE' => 1, 'MIN_ROWS' => 1, 'NATIONAL' => 1, - 'NVARCHAR' => 1, 'ONE_SHOT' => 1, 'PASSWORD' => 1, 'PRESERVE' => 1, - 'PROFILES' => 1, 'REDOFILE' => 1, 'ROLLBACK' => 1, 'SCHEDULE' => 1, - 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1, 'SWITCHES' => 1, - 'TRIGGERS' => 1, 'TRUNCATE' => 1, 'UNDOFILE' => 1, 'WARNINGS' => 1, - 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COLLATION' => 1, 'COMMITTED' => 1, - 'DIRECTORY' => 1, 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, - 'ISOLATION' => 1, 'NODEGROUP' => 1, 'PACK_KEYS' => 1, 'PARTITION' => 1, - 'RAID_TYPE' => 1, 'READ_ONLY' => 1, 'REDUNDANT' => 1, 'SAVEPOINT' => 1, - 'SCHEDULER' => 1, 'SQL_CACHE' => 1, 'TEMPORARY' => 1, 'TEMPTABLE' => 1, - 'UNDEFINED' => 1, 'UNINSTALL' => 1, 'VARIABLES' => 1, + 'MEDIUM' => 1, 'MEMORY' => 1, 'MODIFY' => 1, 'OFFSET' => 1, 'PARSER' => 1, + 'PLUGIN' => 1, 'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, 'RESUME' => 1, + 'ROLLUP' => 1, 'SERIAL' => 1, 'SERVER' => 1, 'SIGNED' => 1, 'SIMPLE' => 1, + 'SOCKET' => 1, 'SONAME' => 1, 'SOUNDS' => 1, 'SOURCE' => 1, 'STARTS' => 1, + 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1, + 'AGAINST' => 1, 'AUTHORS' => 1, 'CHANGED' => 1, 'COLUMNS' => 1, 'COMMENT' => 1, + 'COMPACT' => 1, 'CONTEXT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1, + 'DYNAMIC' => 1, 'ENGINES' => 1, 'EXECUTE' => 1, 'HANDLER' => 1, 'INDEXES' => 1, + 'INSTALL' => 1, 'INVOKER' => 1, 'LOGFILE' => 1, 'MIGRATE' => 1, 'NO_WAIT' => 1, + 'OPTIONS' => 1, 'PARTIAL' => 1, 'PLUGINS' => 1, 'PREPARE' => 1, 'PROFILE' => 1, + 'REBUILD' => 1, 'RECOVER' => 1, 'RESTORE' => 1, 'RETURNS' => 1, 'ROUTINE' => 1, + 'SESSION' => 1, 'STORAGE' => 1, 'STRIPED' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1, + 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1, 'USE_FRM' => 1, 'WRAPPER' => 1, + 'CASCADED' => 1, 'CHECKSUM' => 1, 'DATAFILE' => 1, 'DUMPFILE' => 1, + 'EXTENDED' => 1, 'FUNCTION' => 1, 'GEOMETRY' => 1, 'INNOBASE' => 1, + 'LANGUAGE' => 1, 'MAXVALUE' => 1, 'MAX_ROWS' => 1, 'MAX_SIZE' => 1, + 'MIN_ROWS' => 1, 'NATIONAL' => 1, 'NVARCHAR' => 1, 'ONE_SHOT' => 1, + 'PRESERVE' => 1, 'PROFILES' => 1, 'REDOFILE' => 1, 'ROLLBACK' => 1, + 'SCHEDULE' => 1, 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1, + 'SWITCHES' => 1, 'TRIGGERS' => 1, 'UNDOFILE' => 1, 'WARNINGS' => 1, + 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COMMITTED' => 1, 'DIRECTORY' => 1, + 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, 'ISOLATION' => 1, + 'NODEGROUP' => 1, 'PACK_KEYS' => 1, 'PARTITION' => 1, 'RAID_TYPE' => 1, + 'READ_ONLY' => 1, 'REDUNDANT' => 1, 'SAVEPOINT' => 1, 'SCHEDULER' => 1, + 'SQL_CACHE' => 1, 'TEMPORARY' => 1, 'TEMPTABLE' => 1, 'UNDEFINED' => 1, + 'UNINSTALL' => 1, 'VARIABLES' => 1, 'BERKELEYDB' => 1, 'COMPLETION' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, - 'CONNECTION' => 1, 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'GET_FORMAT' => 1, - 'IDENTIFIED' => 1, 'LINESTRING' => 1, 'MASTER_SSL' => 1, 'MULTIPOINT' => 1, - 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PRIVILEGES' => 1, 'REORGANISE' => 1, - 'REORGANIZE' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, - 'TABLESPACE' => 1, + 'CONNECTION' => 1, 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'IDENTIFIED' => 1, + 'MASTER_SSL' => 1, 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PRIVILEGES' => 1, + 'REORGANISE' => 1, 'REORGANIZE' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, + 'SQL_THREAD' => 1, 'TABLESPACE' => 1, 'EXTENT_SIZE' => 1, 'FRAC_SECOND' => 1, 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, - 'MASTER_USER' => 1, 'MICROSECOND' => 1, 'PROCESSLIST' => 1, 'RAID_CHUNKS' => 1, - 'REPLICATION' => 1, 'SQL_TSI_DAY' => 1, 'TRANSACTION' => 1, 'UNCOMMITTED' => 1, + 'MASTER_USER' => 1, 'PROCESSLIST' => 1, 'RAID_CHUNKS' => 1, 'REPLICATION' => 1, + 'SQL_TSI_DAY' => 1, 'TRANSACTION' => 1, 'UNCOMMITTED' => 1, 'CONTRIBUTORS' => 1, 'DES_KEY_FILE' => 1, 'INITIAL_SIZE' => 1, - 'MULTIPOLYGON' => 1, 'OLD_PASSWORD' => 1, 'PARTITIONING' => 1, - 'RELAY_THREAD' => 1, 'SERIALIZABLE' => 1, 'SQL_NO_CACHE' => 1, - 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1, 'SQL_TSI_YEAR' => 1, - 'SUBPARTITION' => 1, 'TIMESTAMPADD' => 1, + 'PARTITIONING' => 1, 'RELAY_THREAD' => 1, 'SERIALIZABLE' => 1, + 'SQL_NO_CACHE' => 1, 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1, + 'SQL_TSI_YEAR' => 1, 'SUBPARTITION' => 1, 'INSERT_METHOD' => 1, 'MASTER_SSL_CA' => 1, 'PAGE_CHECKSUM' => 1, 'RELAY_LOG_POS' => 1, 'SQL_TSI_MONTH' => 1, 'SUBPARTITIONS' => 1, - 'TIMESTAMPDIFF' => 1, 'TRANSACTIONAL' => 1, + 'TRANSACTIONAL' => 1, 'AUTO_INCREMENT' => 1, 'AVG_ROW_LENGTH' => 1, 'KEY_BLOCK_SIZE' => 1, 'MASTER_LOG_POS' => 1, 'MASTER_SSL_KEY' => 1, 'RAID_CHUNKSIZE' => 1, 'RELAY_LOG_FILE' => 1, 'SQL_TSI_MINUTE' => 1, 'SQL_TSI_SECOND' => 1, 'TABLE_CHECKSUM' => 1, 'USER_RESOURCES' => 1, 'AUTOEXTEND_SIZE' => 1, 'DELAY_KEY_WRITE' => 1, 'MASTER_LOG_FILE' => 1, - 'MASTER_PASSWORD' => 1, 'MASTER_SSL_CERT' => 1, 'MULTILINESTRING' => 1, - 'SQL_TSI_QUARTER' => 1, + 'MASTER_PASSWORD' => 1, 'MASTER_SSL_CERT' => 1, 'SQL_TSI_QUARTER' => 1, 'MASTER_SERVER_ID' => 1, 'REDO_BUFFER_SIZE' => 1, 'UNDO_BUFFER_SIZE' => 1, 'MASTER_SSL_CAPATH' => 1, 'MASTER_SSL_CIPHER' => 1, 'SQL_BUFFER_RESULT' => 1, - 'GEOMETRYCOLLECTION' => 1, 'SQL_TSI_FRAC_SECOND' => 1, 'MASTER_CONNECT_RETRY' => 1, 'MAX_QUERIES_PER_HOUR' => 1, 'MAX_UPDATES_PER_HOUR' => 1, 'MAX_USER_CONNECTIONS' => 1, 'MAX_CONNECTIONS_PER_HOUR' => 1, - 'AS' => 3, 'BY' => 3, 'IF' => 3, 'IN' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, - 'TO' => 3, + 'AS' => 3, 'BY' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, 'TO' => 3, 'ADD' => 3, 'ALL' => 3, 'AND' => 3, 'ASC' => 3, 'DEC' => 3, 'DIV' => 3, - 'FOR' => 3, 'MOD' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, 'SSL' => 3, - 'USE' => 3, 'XOR' => 3, + 'FOR' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, 'SSL' => 3, 'USE' => 3, + 'XOR' => 3, 'BOTH' => 3, 'CALL' => 3, 'CASE' => 3, 'DESC' => 3, 'DROP' => 3, 'DUAL' => 3, 'EACH' => 3, 'ELSE' => 3, 'EXIT' => 3, 'FROM' => 3, 'INT1' => 3, 'INT2' => 3, 'INT3' => 3, 'INT4' => 3, 'INT8' => 3, 'INTO' => 3, 'JOIN' => 3, 'KEYS' => 3, - 'KILL' => 3, 'LEFT' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, - 'LOOP' => 3, 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, - 'UNDO' => 3, 'WHEN' => 3, 'WITH' => 3, + 'KILL' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, 'LOOP' => 3, + 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, 'UNDO' => 3, + 'WHEN' => 3, 'WITH' => 3, 'ALTER' => 3, 'CHECK' => 3, 'CROSS' => 3, 'FALSE' => 3, 'FETCH' => 3, 'FORCE' => 3, 'GRANT' => 3, 'GROUP' => 3, 'INNER' => 3, 'INOUT' => 3, 'LEAVE' => 3, 'LIMIT' => 3, 'LINES' => 3, 'MATCH' => 3, 'ORDER' => 3, - 'OUTER' => 3, 'PURGE' => 3, 'RANGE' => 3, 'READS' => 3, 'RIGHT' => 3, - 'RLIKE' => 3, 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, - 'WHERE' => 3, 'WHILE' => 3, 'WRITE' => 3, + 'OUTER' => 3, 'PURGE' => 3, 'RANGE' => 3, 'READS' => 3, 'RLIKE' => 3, + 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, 'WHERE' => 3, + 'WHILE' => 3, 'WRITE' => 3, 'BEFORE' => 3, 'CHANGE' => 3, 'COLUMN' => 3, 'CREATE' => 3, 'CURSOR' => 3, 'DELETE' => 3, 'ELSEIF' => 3, 'EXISTS' => 3, 'FLOAT4' => 3, 'FLOAT8' => 3, - 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'INSERT' => 3, 'LINEAR' => 3, - 'OPTION' => 3, 'REGEXP' => 3, 'RENAME' => 3, 'REPEAT' => 3, 'RETURN' => 3, - 'REVOKE' => 3, 'SCHEMA' => 3, 'SELECT' => 3, 'UNLOCK' => 3, 'UPDATE' => 3, - 'VALUES' => 3, - 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'CONVERT' => 3, - 'DECLARE' => 3, 'DEFAULT' => 3, 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, - 'FOREIGN' => 3, 'ITERATE' => 3, 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, - 'PRIMARY' => 3, 'RELEASE' => 3, 'REPLACE' => 3, 'REQUIRE' => 3, 'SCHEMAS' => 3, - 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3, - 'CONTINUE' => 3, 'DATABASE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, - 'DISTINCT' => 3, 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MODIFIES' => 3, - 'OPTIMIZE' => 3, 'RESTRICT' => 3, 'SPECIFIC' => 3, 'SQLSTATE' => 3, - 'STARTING' => 3, 'TRAILING' => 3, 'UNSIGNED' => 3, 'UTC_DATE' => 3, - 'UTC_TIME' => 3, 'ZEROFILL' => 3, - 'CONDITION' => 3, 'DATABASES' => 3, 'LOCALTIME' => 3, 'MIDDLEINT' => 3, - 'PRECISION' => 3, 'PROCEDURE' => 3, 'SENSITIVE' => 3, 'SEPARATOR' => 3, + 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'LINEAR' => 3, 'OPTION' => 3, + 'REGEXP' => 3, 'RENAME' => 3, 'RETURN' => 3, 'REVOKE' => 3, 'SELECT' => 3, + 'UNLOCK' => 3, 'UPDATE' => 3, + 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'DECLARE' => 3, + 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, 'FOREIGN' => 3, 'ITERATE' => 3, + 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, 'PRIMARY' => 3, 'RELEASE' => 3, + 'REQUIRE' => 3, 'SCHEMAS' => 3, 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3, + 'CONTINUE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, 'DISTINCT' => 3, + 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MODIFIES' => 3, 'OPTIMIZE' => 3, + 'RESTRICT' => 3, 'SPECIFIC' => 3, 'SQLSTATE' => 3, 'STARTING' => 3, + 'TRAILING' => 3, 'UNSIGNED' => 3, 'ZEROFILL' => 3, + 'CONDITION' => 3, 'DATABASES' => 3, 'MIDDLEINT' => 3, 'PRECISION' => 3, + 'PROCEDURE' => 3, 'SENSITIVE' => 3, 'SEPARATOR' => 3, 'ACCESSIBLE' => 3, 'ASENSITIVE' => 3, 'CONSTRAINT' => 3, 'DAY_MINUTE' => 3, 'DAY_SECOND' => 3, 'OPTIONALLY' => 3, 'READ_WRITE' => 3, 'REFERENCES' => 3, 'SQLWARNING' => 3, 'TERMINATED' => 3, 'YEAR_MONTH' => 3, 'DISTINCTROW' => 3, 'HOUR_MINUTE' => 3, 'HOUR_SECOND' => 3, 'INSENSITIVE' => 3, - 'CURRENT_DATE' => 3, 'CURRENT_TIME' => 3, 'CURRENT_USER' => 3, 'LOW_PRIORITY' => 3, 'SQLEXCEPTION' => 3, 'VARCHARACTER' => 3, 'DETERMINISTIC' => 3, 'HIGH_PRIORITY' => 3, 'MINUTE_SECOND' => 3, - 'STRAIGHT_JOIN' => 3, 'UTC_TIMESTAMP' => 3, - 'LOCALTIMESTAMP' => 3, 'SQL_BIG_RESULT' => 3, + 'STRAIGHT_JOIN' => 3, + 'SQL_BIG_RESULT' => 3, 'DAY_MICROSECOND' => 3, 'HOUR_MICROSECOND' => 3, 'SQL_SMALL_RESULT' => 3, - 'CURRENT_TIMESTAMP' => 3, 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3, 'SQL_CALC_FOUND_ROWS' => 3, 'MASTER_SSL_VERIFY_SERVER_CERT' => 3, @@ -176,19 +163,18 @@ class ContextMySql50100 extends Context 'GROUP BY' => 7, 'ORDER BY' => 7, 'XML' => 9, - 'DATE' => 9, 'ENUM' => 9, 'TEXT' => 9, 'TIME' => 9, 'YEAR' => 9, + 'ENUM' => 9, 'TEXT' => 9, 'ARRAY' => 9, 'BOOLEAN' => 9, 'DATETIME' => 9, 'MULTISET' => 9, - 'TIMESTAMP' => 9, 'INT' => 11, 'SET' => 11, - 'BLOB' => 11, 'CHAR' => 11, 'REAL' => 11, + 'BLOB' => 11, 'REAL' => 11, 'FLOAT' => 11, 'BIGINT' => 11, 'BINARY' => 11, 'DOUBLE' => 11, 'DECIMAL' => 11, 'INTEGER' => 11, 'NUMERIC' => 11, 'TINYINT' => 11, 'VARCHAR' => 11, - 'INTERVAL' => 11, 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, - 'TINYBLOB' => 11, 'TINYTEXT' => 11, + 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, 'TINYBLOB' => 11, + 'TINYTEXT' => 11, 'CHARACTER' => 11, 'MEDIUMINT' => 11, 'VARBINARY' => 11, 'MEDIUMBLOB' => 11, 'MEDIUMTEXT' => 11, @@ -205,5 +191,102 @@ class ContextMySql50100 extends Context 'SPATIAL INDEX' => 21, 'FULLTEXT INDEX' => 21, + 'X' => 33, 'Y' => 33, + 'LN' => 33, 'PI' => 33, + 'ABS' => 33, 'AVG' => 33, 'BIN' => 33, 'COS' => 33, 'COT' => 33, 'DAY' => 33, + 'ELT' => 33, 'EXP' => 33, 'HEX' => 33, 'LOG' => 33, 'MAX' => 33, 'MD5' => 33, + 'MID' => 33, 'MIN' => 33, 'NOW' => 33, 'OCT' => 33, 'ORD' => 33, 'POW' => 33, + 'SHA' => 33, 'SIN' => 33, 'STD' => 33, 'SUM' => 33, 'TAN' => 33, + 'ACOS' => 33, 'AREA' => 33, 'ASIN' => 33, 'ATAN' => 33, 'CAST' => 33, 'CEIL' => 33, + 'CONV' => 33, 'HOUR' => 33, 'LOG2' => 33, 'LPAD' => 33, 'RAND' => 33, 'RPAD' => 33, + 'SHA1' => 33, 'SIGN' => 33, 'SQRT' => 33, 'SRID' => 33, 'TRIM' => 33, 'USER' => 33, + 'UUID' => 33, 'WEEK' => 33, + 'ASCII' => 33, 'ASWKB' => 33, 'ASWKT' => 33, 'ATAN2' => 33, 'COUNT' => 33, + 'CRC32' => 33, 'DECOD' => 33, 'FIELD' => 33, 'FLOOR' => 33, 'INSTR' => 33, + 'LCASE' => 33, 'LEAST' => 33, 'LOG10' => 33, 'LOWER' => 33, 'LTRIM' => 33, + 'MONTH' => 33, 'POINT' => 33, 'POWER' => 33, 'QUOTE' => 33, 'ROUND' => 33, + 'RTRIM' => 33, 'SLEEP' => 33, 'SPACE' => 33, 'UCASE' => 33, 'UNHEX' => 33, + 'UPPER' => 33, + 'ASTEXT' => 33, 'BIT_OR' => 33, 'CONCAT' => 33, 'ENCODE' => 33, 'EQUALS' => 33, + 'FORMAT' => 33, 'IFNULL' => 33, 'ISNULL' => 33, 'LENGTH' => 33, 'LOCATE' => 33, + 'MINUTE' => 33, 'NULLIF' => 33, 'POINTN' => 33, 'SECOND' => 33, 'STDDEV' => 33, + 'STRCMP' => 33, 'SUBSTR' => 33, 'WITHIN' => 33, + 'ADDDATE' => 33, 'ADDTIME' => 33, 'BIT_AND' => 33, 'BIT_XOR' => 33, 'CEILING' => 33, + 'CHARSET' => 33, 'CROSSES' => 33, 'CURDATE' => 33, 'CURTIME' => 33, 'DAYNAME' => 33, + 'DEGREES' => 33, 'ENCRYPT' => 33, 'EXTRACT' => 33, 'GLENGTH' => 33, 'ISEMPTY' => 33, + 'POLYGON' => 33, 'QUARTER' => 33, 'RADIANS' => 33, 'REVERSE' => 33, 'SOUNDEX' => 33, + 'SUBDATE' => 33, 'SUBTIME' => 33, 'SYSDATE' => 33, 'TOUCHES' => 33, 'TO_DAYS' => 33, + 'VAR_POP' => 33, 'VERSION' => 33, 'WEEKDAY' => 33, + 'ASBINARY' => 33, 'CENTROID' => 33, 'COALESCE' => 33, 'COMPRESS' => 33, + 'CONTAINS' => 33, 'DATEDIFF' => 33, 'DATE_ADD' => 33, 'DATE_SUB' => 33, + 'DISJOINT' => 33, 'ENDPOINT' => 33, 'ENVELOPE' => 33, 'GET_LOCK' => 33, + 'GREATEST' => 33, 'ISCLOSED' => 33, 'ISSIMPLE' => 33, 'MAKEDATE' => 33, + 'MAKETIME' => 33, 'MAKE_SET' => 33, 'MBREQUAL' => 33, 'OVERLAPS' => 33, + 'PASSWORD' => 33, 'POSITION' => 33, 'TIMEDIFF' => 33, 'TRUNCATE' => 33, + 'VARIANCE' => 33, 'VAR_SAMP' => 33, 'YEARWEEK' => 33, + 'BENCHMARK' => 33, 'BIT_COUNT' => 33, 'COLLATION' => 33, 'CONCAT_WS' => 33, + 'DAYOFWEEK' => 33, 'DAYOFYEAR' => 33, 'DIMENSION' => 33, 'FROM_DAYS' => 33, + 'GEOMETRYN' => 33, 'INET_ATON' => 33, 'INET_NTOA' => 33, 'LOAD_FILE' => 33, + 'MBRWITHIN' => 33, 'MONTHNAME' => 33, 'NUMPOINTS' => 33, 'ROW_COUNT' => 33, + 'SUBSTRING' => 33, 'UPDATEXML' => 33, + 'BIT_LENGTH' => 33, 'CONVERT_TZ' => 33, 'DAYOFMONTH' => 33, 'EXPORT_SET' => 33, + 'FOUND_ROWS' => 33, 'GET_FORMAT' => 33, 'INTERSECTS' => 33, 'LINESTRING' => 33, + 'MBRTOUCHES' => 33, 'MULTIPOINT' => 33, 'NAME_CONST' => 33, 'PERIOD_ADD' => 33, + 'STARTPOINT' => 33, 'STDDEV_POP' => 33, 'UNCOMPRESS' => 33, 'UUID_SHORT' => 33, + 'WEEKOFYEAR' => 33, + 'AES_DECRYPT' => 33, 'AES_ENCRYPT' => 33, 'CHAR_LENGTH' => 33, 'DATE_FORMAT' => 33, + 'DES_DECRYPT' => 33, 'DES_ENCRYPT' => 33, 'FIND_IN_SET' => 33, 'GEOMFROMWKB' => 33, + 'LINEFROMWKB' => 33, 'MBRCONTAINS' => 33, 'MBRDISJOINT' => 33, 'MBROVERLAPS' => 33, + 'MICROSECOND' => 33, 'PERIOD_DIFF' => 33, 'POLYFROMWKB' => 33, 'SEC_TO_TIME' => 33, + 'STDDEV_SAMP' => 33, 'STR_TO_DATE' => 33, 'SYSTEM_USER' => 33, 'TIME_FORMAT' => 33, + 'TIME_TO_SEC' => 33, + 'COERCIBILITY' => 33, 'EXTERIORRING' => 33, 'EXTRACTVALUE' => 33, + 'GEOMETRYTYPE' => 33, 'GEOMFROMTEXT' => 33, 'GROUP_CONCAT' => 33, + 'IS_FREE_LOCK' => 33, 'IS_USED_LOCK' => 33, 'LINEFROMTEXT' => 33, + 'MLINEFROMWKB' => 33, 'MPOLYFROMWKB' => 33, 'MULTIPOLYGON' => 33, + 'OCTET_LENGTH' => 33, 'OLD_PASSWORD' => 33, 'POINTFROMWKB' => 33, + 'POLYFROMTEXT' => 33, 'RELEASE_LOCK' => 33, 'SESSION_USER' => 33, + 'TIMESTAMPADD' => 33, + 'CONNECTION_ID' => 33, 'FROM_UNIXTIME' => 33, 'INTERIORRINGN' => 33, + 'MBRINTERSECTS' => 33, 'MLINEFROMTEXT' => 33, 'MPOINTFROMWKB' => 33, + 'MPOLYFROMTEXT' => 33, 'NUMGEOMETRIES' => 33, 'POINTFROMTEXT' => 33, + 'TIMESTAMPDIFF' => 33, + 'LAST_INSERT_ID' => 33, 'MPOINTFROMTEXT' => 33, 'POLYGONFROMWKB' => 33, + 'UNIX_TIMESTAMP' => 33, + 'GEOMCOLLFROMWKB' => 33, 'MASTER_POS_WAIT' => 33, 'MULTILINESTRING' => 33, + 'POLYGONFROMTEXT' => 33, 'SUBSTRING_INDEX' => 33, + 'CHARACTER_LENGTH' => 33, 'GEOMCOLLFROMTEXT' => 33, 'GEOMETRYFROMTEXT' => 33, + 'NUMINTERIORRINGS' => 33, + 'LINESTRINGFROMWKB' => 33, 'MULTIPOINTFROMWKB' => 33, + 'GEOMETRYCOLLECTION' => 33, 'MULTIPOINTFROMTEXT' => 33, + 'MULTIPOLYGONFROMWKB' => 33, 'UNCOMPRESSED_LENGTH' => 33, + 'MULTIPOLYGONFROMTEXT' => 33, + 'MULTILINESTRINGFROMWKB' => 33, + 'MULTILINESTRINGFROMTEXT' => 33, + 'GEOMETRYCOLLECTIONFROMWKB' => 33, + 'GEOMETRYCOLLECTIONFROMTEXT' => 33, + + 'IF' => 35, 'IN' => 35, + 'MOD' => 35, + 'LEFT' => 35, + 'RIGHT' => 35, + 'INSERT' => 35, 'REPEAT' => 35, 'SCHEMA' => 35, 'VALUES' => 35, + 'CONVERT' => 35, 'DEFAULT' => 35, 'REPLACE' => 35, + 'DATABASE' => 35, 'UTC_DATE' => 35, 'UTC_TIME' => 35, + 'LOCALTIME' => 35, + 'CURRENT_DATE' => 35, 'CURRENT_TIME' => 35, 'CURRENT_USER' => 35, + 'UTC_TIMESTAMP' => 35, + 'LOCALTIMESTAMP' => 35, + 'CURRENT_TIMESTAMP' => 35, + + 'NOT IN' => 37, + 'PROCEDURE ANALYSE' => 37, + + 'DATE' => 41, 'TIME' => 41, 'YEAR' => 41, + 'TIMESTAMP' => 41, + + 'CHAR' => 43, + 'INTERVAL' => 43, + ); } diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50500.php b/libraries/sql-parser/src/Contexts/ContextMySql50500.php index 3a5496a9ba..26aa40e0bc 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50500.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50500.php @@ -34,137 +34,126 @@ class ContextMySql50500 extends Context public static $KEYWORDS = array( 'AT' => 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, - 'ANY' => 1, 'AVG' => 1, 'BIT' => 1, 'CPU' => 1, 'DAY' => 1, 'END' => 1, - 'IPC' => 1, 'NDB' => 1, 'NEW' => 1, 'ONE' => 1, 'ROW' => 1, + 'ANY' => 1, 'BIT' => 1, 'CPU' => 1, 'END' => 1, 'IPC' => 1, 'NDB' => 1, + 'NEW' => 1, 'ONE' => 1, 'ROW' => 1, 'BOOL' => 1, 'BYTE' => 1, 'CODE' => 1, 'CUBE' => 1, 'DATA' => 1, 'DISK' => 1, 'ENDS' => 1, 'FAST' => 1, 'FILE' => 1, 'FULL' => 1, 'HASH' => 1, 'HELP' => 1, - 'HOST' => 1, 'HOUR' => 1, 'LAST' => 1, 'LESS' => 1, 'LIST' => 1, 'LOGS' => 1, - 'MODE' => 1, 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'OPEN' => 1, 'PAGE' => 1, - 'PORT' => 1, 'PREV' => 1, 'ROWS' => 1, 'SLOW' => 1, 'SOME' => 1, 'STOP' => 1, - 'THAN' => 1, 'TYPE' => 1, 'USER' => 1, 'VIEW' => 1, 'WAIT' => 1, 'WEEK' => 1, - 'WORK' => 1, 'X509' => 1, - 'AFTER' => 1, 'ASCII' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, - 'CACHE' => 1, 'CHAIN' => 1, 'CLOSE' => 1, 'ERROR' => 1, 'EVENT' => 1, - 'EVERY' => 1, 'FIRST' => 1, 'FIXED' => 1, 'FLUSH' => 1, 'FOUND' => 1, - 'HOSTS' => 1, 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, 'MERGE' => 1, - 'MONTH' => 1, 'MUTEX' => 1, 'NAMES' => 1, 'NCHAR' => 1, 'OWNER' => 1, - 'PHASE' => 1, 'POINT' => 1, 'PROXY' => 1, 'QUERY' => 1, 'QUICK' => 1, - 'RELAY' => 1, 'RESET' => 1, 'RTREE' => 1, 'SHARE' => 1, 'SLAVE' => 1, - 'START' => 1, 'SUPER' => 1, 'SWAPS' => 1, 'TYPES' => 1, 'UNTIL' => 1, - 'VALUE' => 1, + 'HOST' => 1, 'LAST' => 1, 'LESS' => 1, 'LIST' => 1, 'LOGS' => 1, 'MODE' => 1, + 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'OPEN' => 1, 'PAGE' => 1, 'PORT' => 1, + 'PREV' => 1, 'ROWS' => 1, 'SLOW' => 1, 'SOME' => 1, 'STOP' => 1, 'THAN' => 1, + 'TYPE' => 1, 'VIEW' => 1, 'WAIT' => 1, 'WORK' => 1, 'X509' => 1, + 'AFTER' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, 'CACHE' => 1, + 'CHAIN' => 1, 'CLOSE' => 1, 'ERROR' => 1, 'EVENT' => 1, 'EVERY' => 1, + 'FIRST' => 1, 'FIXED' => 1, 'FLUSH' => 1, 'FOUND' => 1, 'HOSTS' => 1, + 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, 'MERGE' => 1, 'MUTEX' => 1, + 'NAMES' => 1, 'NCHAR' => 1, 'OWNER' => 1, 'PHASE' => 1, 'PROXY' => 1, + 'QUERY' => 1, 'QUICK' => 1, 'RELAY' => 1, 'RESET' => 1, 'RTREE' => 1, + 'SHARE' => 1, 'SLAVE' => 1, 'START' => 1, 'SUPER' => 1, 'SWAPS' => 1, + 'TYPES' => 1, 'UNTIL' => 1, 'VALUE' => 1, 'ACTION' => 1, 'BACKUP' => 1, 'BINLOG' => 1, 'CIPHER' => 1, 'CLIENT' => 1, 'COMMIT' => 1, 'ENABLE' => 1, 'ENGINE' => 1, 'ERRORS' => 1, 'ESCAPE' => 1, 'EVENTS' => 1, 'FAULTS' => 1, 'FIELDS' => 1, 'GLOBAL' => 1, 'GRANTS' => 1, 'IMPORT' => 1, 'INNODB' => 1, 'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1, - 'MEDIUM' => 1, 'MEMORY' => 1, 'MINUTE' => 1, 'MODIFY' => 1, 'OFFSET' => 1, - 'PARSER' => 1, 'PLUGIN' => 1, 'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, - 'RESUME' => 1, 'ROLLUP' => 1, 'SECOND' => 1, 'SERIAL' => 1, 'SERVER' => 1, - 'SIGNED' => 1, 'SIMPLE' => 1, 'SOCKET' => 1, 'SONAME' => 1, 'SOUNDS' => 1, - 'SOURCE' => 1, 'STARTS' => 1, 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1, - 'AGAINST' => 1, 'AUTHORS' => 1, 'CHANGED' => 1, 'CHARSET' => 1, 'COLUMNS' => 1, - 'COMMENT' => 1, 'COMPACT' => 1, 'CONTEXT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, - 'DISCARD' => 1, 'DYNAMIC' => 1, 'ENGINES' => 1, 'EXECUTE' => 1, 'GENERAL' => 1, - 'HANDLER' => 1, 'INDEXES' => 1, 'INSTALL' => 1, 'INVOKER' => 1, 'LOGFILE' => 1, - 'MIGRATE' => 1, 'NO_WAIT' => 1, 'OPTIONS' => 1, 'PARTIAL' => 1, 'PLUGINS' => 1, - 'POLYGON' => 1, 'PREPARE' => 1, 'PROFILE' => 1, 'QUARTER' => 1, 'REBUILD' => 1, - 'RECOVER' => 1, 'RESTORE' => 1, 'RETURNS' => 1, 'ROUTINE' => 1, 'SESSION' => 1, - 'STORAGE' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1, 'UNICODE' => 1, 'UNKNOWN' => 1, - 'UPGRADE' => 1, 'USE_FRM' => 1, 'WRAPPER' => 1, - 'CASCADED' => 1, 'CHECKSUM' => 1, 'COALESCE' => 1, 'CONTAINS' => 1, - 'DATAFILE' => 1, 'DUMPFILE' => 1, 'EXTENDED' => 1, 'FUNCTION' => 1, - 'GEOMETRY' => 1, 'INNOBASE' => 1, 'LANGUAGE' => 1, 'MAX_ROWS' => 1, - 'MAX_SIZE' => 1, 'MIN_ROWS' => 1, 'NATIONAL' => 1, 'NVARCHAR' => 1, - 'ONE_SHOT' => 1, 'PASSWORD' => 1, 'PRESERVE' => 1, 'PROFILES' => 1, - 'REDOFILE' => 1, 'RELAYLOG' => 1, 'ROLLBACK' => 1, 'SCHEDULE' => 1, - 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1, 'SWITCHES' => 1, - 'TRIGGERS' => 1, 'TRUNCATE' => 1, 'UNDOFILE' => 1, 'WARNINGS' => 1, - 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COLLATION' => 1, 'COMMITTED' => 1, - 'DIRECTORY' => 1, 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, - 'ISOLATION' => 1, 'NODEGROUP' => 1, 'PACK_KEYS' => 1, 'PARTITION' => 1, - 'READ_ONLY' => 1, 'REDUNDANT' => 1, 'SAVEPOINT' => 1, 'SQL_CACHE' => 1, - 'TEMPORARY' => 1, 'TEMPTABLE' => 1, 'UNDEFINED' => 1, 'UNINSTALL' => 1, - 'VARIABLES' => 1, + 'MEDIUM' => 1, 'MEMORY' => 1, 'MODIFY' => 1, 'OFFSET' => 1, 'PARSER' => 1, + 'PLUGIN' => 1, 'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, 'RESUME' => 1, + 'ROLLUP' => 1, 'SERIAL' => 1, 'SERVER' => 1, 'SIGNED' => 1, 'SIMPLE' => 1, + 'SOCKET' => 1, 'SONAME' => 1, 'SOUNDS' => 1, 'SOURCE' => 1, 'STARTS' => 1, + 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1, + 'AGAINST' => 1, 'AUTHORS' => 1, 'CHANGED' => 1, 'COLUMNS' => 1, 'COMMENT' => 1, + 'COMPACT' => 1, 'CONTEXT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1, + 'DYNAMIC' => 1, 'ENGINES' => 1, 'EXECUTE' => 1, 'GENERAL' => 1, 'HANDLER' => 1, + 'INDEXES' => 1, 'INSTALL' => 1, 'INVOKER' => 1, 'LOGFILE' => 1, 'MIGRATE' => 1, + 'NO_WAIT' => 1, 'OPTIONS' => 1, 'PARTIAL' => 1, 'PLUGINS' => 1, 'PREPARE' => 1, + 'PROFILE' => 1, 'REBUILD' => 1, 'RECOVER' => 1, 'RESTORE' => 1, 'RETURNS' => 1, + 'ROUTINE' => 1, 'SESSION' => 1, 'STORAGE' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1, + 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1, 'USE_FRM' => 1, 'WRAPPER' => 1, + 'CASCADED' => 1, 'CHECKSUM' => 1, 'DATAFILE' => 1, 'DUMPFILE' => 1, + 'EXTENDED' => 1, 'FUNCTION' => 1, 'GEOMETRY' => 1, 'INNOBASE' => 1, + 'LANGUAGE' => 1, 'MAX_ROWS' => 1, 'MAX_SIZE' => 1, 'MIN_ROWS' => 1, + 'NATIONAL' => 1, 'NVARCHAR' => 1, 'ONE_SHOT' => 1, 'PRESERVE' => 1, + 'PROFILES' => 1, 'REDOFILE' => 1, 'RELAYLOG' => 1, 'ROLLBACK' => 1, + 'SCHEDULE' => 1, 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1, + 'SWITCHES' => 1, 'TRIGGERS' => 1, 'UNDOFILE' => 1, 'WARNINGS' => 1, + 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COMMITTED' => 1, 'DIRECTORY' => 1, + 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, 'ISOLATION' => 1, + 'NODEGROUP' => 1, 'PACK_KEYS' => 1, 'PARTITION' => 1, 'READ_ONLY' => 1, + 'REDUNDANT' => 1, 'SAVEPOINT' => 1, 'SQL_CACHE' => 1, 'TEMPORARY' => 1, + 'TEMPTABLE' => 1, 'UNDEFINED' => 1, 'UNINSTALL' => 1, 'VARIABLES' => 1, 'COMPLETION' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1, - 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'GET_FORMAT' => 1, 'IDENTIFIED' => 1, - 'LINESTRING' => 1, 'MASTER_SSL' => 1, 'MULTIPOINT' => 1, 'NDBCLUSTER' => 1, - 'PARTITIONS' => 1, 'PRIVILEGES' => 1, 'REORGANIZE' => 1, 'REPEATABLE' => 1, - 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, 'TABLESPACE' => 1, 'TABLE_NAME' => 1, + 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'IDENTIFIED' => 1, 'MASTER_SSL' => 1, + 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PRIVILEGES' => 1, 'REORGANIZE' => 1, + 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, 'TABLESPACE' => 1, + 'TABLE_NAME' => 1, 'COLUMN_NAME' => 1, 'CURSOR_NAME' => 1, 'EXTENT_SIZE' => 1, 'FRAC_SECOND' => 1, - 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, 'MICROSECOND' => 1, - 'MYSQL_ERRNO' => 1, 'PROCESSLIST' => 1, 'REPLICATION' => 1, 'SCHEMA_NAME' => 1, - 'SQL_TSI_DAY' => 1, 'TRANSACTION' => 1, 'UNCOMMITTED' => 1, + 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, 'MYSQL_ERRNO' => 1, + 'PROCESSLIST' => 1, 'REPLICATION' => 1, 'SCHEMA_NAME' => 1, 'SQL_TSI_DAY' => 1, + 'TRANSACTION' => 1, 'UNCOMMITTED' => 1, 'CATALOG_NAME' => 1, 'CLASS_ORIGIN' => 1, 'CONTRIBUTORS' => 1, 'DES_KEY_FILE' => 1, 'INITIAL_SIZE' => 1, 'MESSAGE_TEXT' => 1, - 'MULTIPOLYGON' => 1, 'OLD_PASSWORD' => 1, 'PARTITIONING' => 1, - 'RELAY_THREAD' => 1, 'SERIALIZABLE' => 1, 'SQL_NO_CACHE' => 1, - 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1, 'SQL_TSI_YEAR' => 1, - 'SUBPARTITION' => 1, 'TIMESTAMPADD' => 1, + 'PARTITIONING' => 1, 'RELAY_THREAD' => 1, 'SERIALIZABLE' => 1, + 'SQL_NO_CACHE' => 1, 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1, + 'SQL_TSI_YEAR' => 1, 'SUBPARTITION' => 1, 'INSERT_METHOD' => 1, 'MASTER_SSL_CA' => 1, 'RELAY_LOG_POS' => 1, - 'SQL_TSI_MONTH' => 1, 'SUBPARTITIONS' => 1, 'TIMESTAMPDIFF' => 1, + 'SQL_TSI_MONTH' => 1, 'SUBPARTITIONS' => 1, 'AUTO_INCREMENT' => 1, 'AVG_ROW_LENGTH' => 1, 'KEY_BLOCK_SIZE' => 1, 'MASTER_LOG_POS' => 1, 'MASTER_SSL_KEY' => 1, 'RELAY_LOG_FILE' => 1, 'SQL_TSI_MINUTE' => 1, 'SQL_TSI_SECOND' => 1, 'TABLE_CHECKSUM' => 1, 'USER_RESOURCES' => 1, 'AUTOEXTEND_SIZE' => 1, 'CONSTRAINT_NAME' => 1, 'DELAY_KEY_WRITE' => 1, 'MASTER_LOG_FILE' => 1, 'MASTER_PASSWORD' => 1, 'MASTER_SSL_CERT' => 1, - 'MULTILINESTRING' => 1, 'SQL_TSI_QUARTER' => 1, 'SUBCLASS_ORIGIN' => 1, + 'SQL_TSI_QUARTER' => 1, 'SUBCLASS_ORIGIN' => 1, 'MASTER_SERVER_ID' => 1, 'REDO_BUFFER_SIZE' => 1, 'UNDO_BUFFER_SIZE' => 1, 'CONSTRAINT_SCHEMA' => 1, 'IGNORE_SERVER_IDS' => 1, 'MASTER_SSL_CAPATH' => 1, 'MASTER_SSL_CIPHER' => 1, 'SQL_BUFFER_RESULT' => 1, - 'CONSTRAINT_CATALOG' => 1, 'GEOMETRYCOLLECTION' => 1, + 'CONSTRAINT_CATALOG' => 1, 'SQL_TSI_FRAC_SECOND' => 1, 'MASTER_CONNECT_RETRY' => 1, 'MAX_QUERIES_PER_HOUR' => 1, 'MAX_UPDATES_PER_HOUR' => 1, 'MAX_USER_CONNECTIONS' => 1, 'MASTER_HEARTBEAT_PERIOD' => 1, 'MAX_CONNECTIONS_PER_HOUR' => 1, - 'AS' => 3, 'BY' => 3, 'IF' => 3, 'IN' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, - 'TO' => 3, + 'AS' => 3, 'BY' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, 'TO' => 3, 'ADD' => 3, 'ALL' => 3, 'AND' => 3, 'ASC' => 3, 'DEC' => 3, 'DIV' => 3, - 'FOR' => 3, 'MOD' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, 'SSL' => 3, - 'USE' => 3, 'XOR' => 3, + 'FOR' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, 'SSL' => 3, 'USE' => 3, + 'XOR' => 3, 'BOTH' => 3, 'CALL' => 3, 'CASE' => 3, 'DESC' => 3, 'DROP' => 3, 'DUAL' => 3, 'EACH' => 3, 'ELSE' => 3, 'EXIT' => 3, 'FROM' => 3, 'INT1' => 3, 'INT2' => 3, 'INT3' => 3, 'INT4' => 3, 'INT8' => 3, 'INTO' => 3, 'JOIN' => 3, 'KEYS' => 3, - 'KILL' => 3, 'LEFT' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, - 'LOOP' => 3, 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, - 'UNDO' => 3, 'WHEN' => 3, 'WITH' => 3, + 'KILL' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, 'LOOP' => 3, + 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, 'UNDO' => 3, + 'WHEN' => 3, 'WITH' => 3, 'ALTER' => 3, 'CHECK' => 3, 'CROSS' => 3, 'FALSE' => 3, 'FETCH' => 3, 'FORCE' => 3, 'GRANT' => 3, 'GROUP' => 3, 'INNER' => 3, 'INOUT' => 3, 'LEAVE' => 3, 'LIMIT' => 3, 'LINES' => 3, 'MATCH' => 3, 'ORDER' => 3, - 'OUTER' => 3, 'PURGE' => 3, 'RANGE' => 3, 'READS' => 3, 'RIGHT' => 3, - 'RLIKE' => 3, 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, - 'WHERE' => 3, 'WHILE' => 3, 'WRITE' => 3, + 'OUTER' => 3, 'PURGE' => 3, 'RANGE' => 3, 'READS' => 3, 'RLIKE' => 3, + 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, 'WHERE' => 3, + 'WHILE' => 3, 'WRITE' => 3, 'BEFORE' => 3, 'CHANGE' => 3, 'COLUMN' => 3, 'CREATE' => 3, 'CURSOR' => 3, 'DELETE' => 3, 'ELSEIF' => 3, 'EXISTS' => 3, 'FLOAT4' => 3, 'FLOAT8' => 3, - 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'INSERT' => 3, 'LINEAR' => 3, - 'OPTION' => 3, 'REGEXP' => 3, 'RENAME' => 3, 'REPEAT' => 3, 'RETURN' => 3, - 'REVOKE' => 3, 'SCHEMA' => 3, 'SELECT' => 3, 'SIGNAL' => 3, 'UNLOCK' => 3, - 'UPDATE' => 3, 'VALUES' => 3, - 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'CONVERT' => 3, - 'DECLARE' => 3, 'DEFAULT' => 3, 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, - 'FOREIGN' => 3, 'ITERATE' => 3, 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, - 'PRIMARY' => 3, 'RELEASE' => 3, 'REPLACE' => 3, 'REQUIRE' => 3, 'SCHEMAS' => 3, - 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3, - 'CONTINUE' => 3, 'DATABASE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, - 'DISTINCT' => 3, 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MAXVALUE' => 3, - 'MODIFIES' => 3, 'OPTIMIZE' => 3, 'RESIGNAL' => 3, 'RESTRICT' => 3, - 'SPECIFIC' => 3, 'SQLSTATE' => 3, 'STARTING' => 3, 'TRAILING' => 3, - 'UNSIGNED' => 3, 'UTC_DATE' => 3, 'UTC_TIME' => 3, 'ZEROFILL' => 3, - 'CONDITION' => 3, 'DATABASES' => 3, 'LOCALTIME' => 3, 'MIDDLEINT' => 3, - 'PRECISION' => 3, 'PROCEDURE' => 3, 'SENSITIVE' => 3, 'SEPARATOR' => 3, + 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'LINEAR' => 3, 'OPTION' => 3, + 'REGEXP' => 3, 'RENAME' => 3, 'RETURN' => 3, 'REVOKE' => 3, 'SELECT' => 3, + 'SIGNAL' => 3, 'UNLOCK' => 3, 'UPDATE' => 3, + 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'DECLARE' => 3, + 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, 'FOREIGN' => 3, 'ITERATE' => 3, + 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, 'PRIMARY' => 3, 'RELEASE' => 3, + 'REQUIRE' => 3, 'SCHEMAS' => 3, 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3, + 'CONTINUE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, 'DISTINCT' => 3, + 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MAXVALUE' => 3, 'MODIFIES' => 3, + 'OPTIMIZE' => 3, 'RESIGNAL' => 3, 'RESTRICT' => 3, 'SPECIFIC' => 3, + 'SQLSTATE' => 3, 'STARTING' => 3, 'TRAILING' => 3, 'UNSIGNED' => 3, + 'ZEROFILL' => 3, + 'CONDITION' => 3, 'DATABASES' => 3, 'MIDDLEINT' => 3, 'PRECISION' => 3, + 'PROCEDURE' => 3, 'SENSITIVE' => 3, 'SEPARATOR' => 3, 'ACCESSIBLE' => 3, 'ASENSITIVE' => 3, 'CONSTRAINT' => 3, 'DAY_MINUTE' => 3, 'DAY_SECOND' => 3, 'OPTIONALLY' => 3, 'READ_WRITE' => 3, 'REFERENCES' => 3, 'SQLWARNING' => 3, 'TERMINATED' => 3, 'YEAR_MONTH' => 3, 'DISTINCTROW' => 3, 'HOUR_MINUTE' => 3, 'HOUR_SECOND' => 3, 'INSENSITIVE' => 3, - 'CURRENT_DATE' => 3, 'CURRENT_TIME' => 3, 'CURRENT_USER' => 3, 'LOW_PRIORITY' => 3, 'SQLEXCEPTION' => 3, 'VARCHARACTER' => 3, 'DETERMINISTIC' => 3, 'HIGH_PRIORITY' => 3, 'MINUTE_SECOND' => 3, - 'STRAIGHT_JOIN' => 3, 'UTC_TIMESTAMP' => 3, - 'LOCALTIMESTAMP' => 3, 'SQL_BIG_RESULT' => 3, + 'STRAIGHT_JOIN' => 3, + 'SQL_BIG_RESULT' => 3, 'DAY_MICROSECOND' => 3, 'HOUR_MICROSECOND' => 3, 'SQL_SMALL_RESULT' => 3, - 'CURRENT_TIMESTAMP' => 3, 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3, 'SQL_CALC_FOUND_ROWS' => 3, 'MASTER_SSL_VERIFY_SERVER_CERT' => 3, @@ -179,19 +168,18 @@ class ContextMySql50500 extends Context 'GROUP BY' => 7, 'ORDER BY' => 7, 'XML' => 9, - 'DATE' => 9, 'ENUM' => 9, 'TEXT' => 9, 'TIME' => 9, 'YEAR' => 9, + 'ENUM' => 9, 'TEXT' => 9, 'ARRAY' => 9, 'BOOLEAN' => 9, 'DATETIME' => 9, 'MULTISET' => 9, - 'TIMESTAMP' => 9, 'INT' => 11, 'SET' => 11, - 'BLOB' => 11, 'CHAR' => 11, 'REAL' => 11, + 'BLOB' => 11, 'REAL' => 11, 'FLOAT' => 11, 'BIGINT' => 11, 'BINARY' => 11, 'DOUBLE' => 11, 'DECIMAL' => 11, 'INTEGER' => 11, 'NUMERIC' => 11, 'TINYINT' => 11, 'VARCHAR' => 11, - 'INTERVAL' => 11, 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, - 'TINYBLOB' => 11, 'TINYTEXT' => 11, + 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, 'TINYBLOB' => 11, + 'TINYTEXT' => 11, 'CHARACTER' => 11, 'MEDIUMINT' => 11, 'VARBINARY' => 11, 'MEDIUMBLOB' => 11, 'MEDIUMTEXT' => 11, @@ -208,5 +196,101 @@ class ContextMySql50500 extends Context 'SPATIAL INDEX' => 21, 'FULLTEXT INDEX' => 21, + 'X' => 33, 'Y' => 33, + 'LN' => 33, 'PI' => 33, + 'ABS' => 33, 'AVG' => 33, 'BIN' => 33, 'COS' => 33, 'COT' => 33, 'DAY' => 33, + 'ELT' => 33, 'EXP' => 33, 'HEX' => 33, 'LOG' => 33, 'MAX' => 33, 'MD5' => 33, + 'MID' => 33, 'MIN' => 33, 'NOW' => 33, 'OCT' => 33, 'ORD' => 33, 'POW' => 33, + 'SHA' => 33, 'SIN' => 33, 'STD' => 33, 'SUM' => 33, 'TAN' => 33, + 'ACOS' => 33, 'AREA' => 33, 'ASIN' => 33, 'ATAN' => 33, 'CAST' => 33, 'CEIL' => 33, + 'CONV' => 33, 'HOUR' => 33, 'LOG2' => 33, 'LPAD' => 33, 'RAND' => 33, 'RPAD' => 33, + 'SHA1' => 33, 'SHA2' => 33, 'SIGN' => 33, 'SQRT' => 33, 'SRID' => 33, 'TRIM' => 33, + 'USER' => 33, 'UUID' => 33, 'WEEK' => 33, + 'ASCII' => 33, 'ASWKB' => 33, 'ASWKT' => 33, 'ATAN2' => 33, 'COUNT' => 33, + 'CRC32' => 33, 'FIELD' => 33, 'FLOOR' => 33, 'INSTR' => 33, 'LCASE' => 33, + 'LEAST' => 33, 'LOG10' => 33, 'LOWER' => 33, 'LTRIM' => 33, 'MONTH' => 33, + 'POINT' => 33, 'POWER' => 33, 'QUOTE' => 33, 'ROUND' => 33, 'RTRIM' => 33, + 'SLEEP' => 33, 'SPACE' => 33, 'UCASE' => 33, 'UNHEX' => 33, 'UPPER' => 33, + 'ASTEXT' => 33, 'BIT_OR' => 33, 'CONCAT' => 33, 'DECODE' => 33, 'ENCODE' => 33, + 'EQUALS' => 33, 'FORMAT' => 33, 'IFNULL' => 33, 'ISNULL' => 33, 'LENGTH' => 33, + 'LOCATE' => 33, 'MINUTE' => 33, 'NULLIF' => 33, 'POINTN' => 33, 'SECOND' => 33, + 'STDDEV' => 33, 'STRCMP' => 33, 'SUBSTR' => 33, 'WITHIN' => 33, + 'ADDDATE' => 33, 'ADDTIME' => 33, 'BIT_AND' => 33, 'BIT_XOR' => 33, 'CEILING' => 33, + 'CHARSET' => 33, 'CROSSES' => 33, 'CURDATE' => 33, 'CURTIME' => 33, 'DAYNAME' => 33, + 'DEGREES' => 33, 'ENCRYPT' => 33, 'EXTRACT' => 33, 'GLENGTH' => 33, 'ISEMPTY' => 33, + 'POLYGON' => 33, 'QUARTER' => 33, 'RADIANS' => 33, 'REVERSE' => 33, 'SOUNDEX' => 33, + 'SUBDATE' => 33, 'SUBTIME' => 33, 'SYSDATE' => 33, 'TOUCHES' => 33, 'TO_DAYS' => 33, + 'VAR_POP' => 33, 'VERSION' => 33, 'WEEKDAY' => 33, + 'ASBINARY' => 33, 'CENTROID' => 33, 'COALESCE' => 33, 'COMPRESS' => 33, + 'CONTAINS' => 33, 'DATEDIFF' => 33, 'DATE_ADD' => 33, 'DATE_SUB' => 33, + 'DISJOINT' => 33, 'ENDPOINT' => 33, 'ENVELOPE' => 33, 'GET_LOCK' => 33, + 'GREATEST' => 33, 'ISCLOSED' => 33, 'ISSIMPLE' => 33, 'MAKEDATE' => 33, + 'MAKETIME' => 33, 'MAKE_SET' => 33, 'MBREQUAL' => 33, 'OVERLAPS' => 33, + 'PASSWORD' => 33, 'POSITION' => 33, 'TIMEDIFF' => 33, 'TRUNCATE' => 33, + 'VARIANCE' => 33, 'VAR_SAMP' => 33, 'YEARWEEK' => 33, + 'BENCHMARK' => 33, 'BIT_COUNT' => 33, 'COLLATION' => 33, 'CONCAT_WS' => 33, + 'DAYOFWEEK' => 33, 'DAYOFYEAR' => 33, 'DIMENSION' => 33, 'FROM_DAYS' => 33, + 'GEOMETRYN' => 33, 'INET_ATON' => 33, 'INET_NTOA' => 33, 'LOAD_FILE' => 33, + 'MBRWITHIN' => 33, 'MONTHNAME' => 33, 'NUMPOINTS' => 33, 'ROW_COUNT' => 33, + 'SUBSTRING' => 33, 'UPDATEXML' => 33, + 'BIT_LENGTH' => 33, 'CONVERT_TZ' => 33, 'DAYOFMONTH' => 33, 'EXPORT_SET' => 33, + 'FOUND_ROWS' => 33, 'GET_FORMAT' => 33, 'INTERSECTS' => 33, 'LINESTRING' => 33, + 'MBRTOUCHES' => 33, 'MULTIPOINT' => 33, 'NAME_CONST' => 33, 'PERIOD_ADD' => 33, + 'STARTPOINT' => 33, 'STDDEV_POP' => 33, 'TO_SECONDS' => 33, 'UNCOMPRESS' => 33, + 'UUID_SHORT' => 33, 'WEEKOFYEAR' => 33, + 'AES_DECRYPT' => 33, 'AES_ENCRYPT' => 33, 'CHAR_LENGTH' => 33, 'DATE_FORMAT' => 33, + 'DES_DECRYPT' => 33, 'DES_ENCRYPT' => 33, 'FIND_IN_SET' => 33, 'GEOMFROMWKB' => 33, + 'LINEFROMWKB' => 33, 'MBRCONTAINS' => 33, 'MBRDISJOINT' => 33, 'MBROVERLAPS' => 33, + 'MICROSECOND' => 33, 'PERIOD_DIFF' => 33, 'POLYFROMWKB' => 33, 'SEC_TO_TIME' => 33, + 'STDDEV_SAMP' => 33, 'STR_TO_DATE' => 33, 'SYSTEM_USER' => 33, 'TIME_FORMAT' => 33, + 'TIME_TO_SEC' => 33, + 'COERCIBILITY' => 33, 'EXTERIORRING' => 33, 'EXTRACTVALUE' => 33, + 'GEOMETRYTYPE' => 33, 'GEOMFROMTEXT' => 33, 'GROUP_CONCAT' => 33, + 'IS_FREE_LOCK' => 33, 'IS_USED_LOCK' => 33, 'LINEFROMTEXT' => 33, + 'MLINEFROMWKB' => 33, 'MPOLYFROMWKB' => 33, 'MULTIPOLYGON' => 33, + 'OCTET_LENGTH' => 33, 'OLD_PASSWORD' => 33, 'POINTFROMWKB' => 33, + 'POLYFROMTEXT' => 33, 'RELEASE_LOCK' => 33, 'SESSION_USER' => 33, + 'TIMESTAMPADD' => 33, + 'CONNECTION_ID' => 33, 'FROM_UNIXTIME' => 33, 'INTERIORRINGN' => 33, + 'MBRINTERSECTS' => 33, 'MLINEFROMTEXT' => 33, 'MPOINTFROMWKB' => 33, + 'MPOLYFROMTEXT' => 33, 'NUMGEOMETRIES' => 33, 'POINTFROMTEXT' => 33, + 'TIMESTAMPDIFF' => 33, + 'LAST_INSERT_ID' => 33, 'MPOINTFROMTEXT' => 33, 'POLYGONFROMWKB' => 33, + 'UNIX_TIMESTAMP' => 33, + 'GEOMCOLLFROMWKB' => 33, 'MASTER_POS_WAIT' => 33, 'MULTILINESTRING' => 33, + 'POLYGONFROMTEXT' => 33, 'SUBSTRING_INDEX' => 33, + 'CHARACTER_LENGTH' => 33, 'GEOMCOLLFROMTEXT' => 33, 'GEOMETRYFROMTEXT' => 33, + 'NUMINTERIORRINGS' => 33, + 'LINESTRINGFROMWKB' => 33, 'MULTIPOINTFROMWKB' => 33, + 'GEOMETRYCOLLECTION' => 33, 'MULTIPOINTFROMTEXT' => 33, + 'MULTIPOLYGONFROMWKB' => 33, 'UNCOMPRESSED_LENGTH' => 33, + 'MULTIPOLYGONFROMTEXT' => 33, + 'MULTILINESTRINGFROMWKB' => 33, + 'MULTILINESTRINGFROMTEXT' => 33, + 'GEOMETRYCOLLECTIONFROMWKB' => 33, + 'GEOMETRYCOLLECTIONFROMTEXT' => 33, + + 'IF' => 35, 'IN' => 35, + 'MOD' => 35, + 'LEFT' => 35, + 'RIGHT' => 35, + 'INSERT' => 35, 'REPEAT' => 35, 'SCHEMA' => 35, 'VALUES' => 35, + 'CONVERT' => 35, 'DEFAULT' => 35, 'REPLACE' => 35, + 'DATABASE' => 35, 'UTC_DATE' => 35, 'UTC_TIME' => 35, + 'LOCALTIME' => 35, + 'CURRENT_DATE' => 35, 'CURRENT_TIME' => 35, 'CURRENT_USER' => 35, + 'UTC_TIMESTAMP' => 35, + 'LOCALTIMESTAMP' => 35, + 'CURRENT_TIMESTAMP' => 35, + + 'NOT IN' => 37, + 'PROCEDURE ANALYSE' => 37, + + 'DATE' => 41, 'TIME' => 41, 'YEAR' => 41, + 'TIMESTAMP' => 41, + + 'CHAR' => 43, + 'INTERVAL' => 43, + ); } diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50600.php b/libraries/sql-parser/src/Contexts/ContextMySql50600.php index d9fcf715cd..39521ef196 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50600.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50600.php @@ -34,148 +34,132 @@ class ContextMySql50600 extends Context public static $KEYWORDS = array( 'AT' => 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, - 'ANY' => 1, 'AVG' => 1, 'BIT' => 1, 'CPU' => 1, 'DAY' => 1, 'END' => 1, - 'IPC' => 1, 'NDB' => 1, 'NEW' => 1, 'ONE' => 1, 'ROW' => 1, + 'ANY' => 1, 'BIT' => 1, 'CPU' => 1, 'END' => 1, 'IPC' => 1, 'NDB' => 1, + 'NEW' => 1, 'ONE' => 1, 'ROW' => 1, 'BOOL' => 1, 'BYTE' => 1, 'CODE' => 1, 'CUBE' => 1, 'DATA' => 1, 'DISK' => 1, 'ENDS' => 1, 'FAST' => 1, 'FILE' => 1, 'FULL' => 1, 'HASH' => 1, 'HELP' => 1, - 'HOST' => 1, 'HOUR' => 1, 'LAST' => 1, 'LESS' => 1, 'LIST' => 1, 'LOGS' => 1, - 'MODE' => 1, 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'ONLY' => 1, 'OPEN' => 1, - 'PAGE' => 1, 'PORT' => 1, 'PREV' => 1, 'ROWS' => 1, 'SLOW' => 1, 'SOME' => 1, - 'STOP' => 1, 'THAN' => 1, 'TYPE' => 1, 'USER' => 1, 'VIEW' => 1, 'WAIT' => 1, - 'WEEK' => 1, 'WORK' => 1, 'X509' => 1, - 'AFTER' => 1, 'ASCII' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, - 'CACHE' => 1, 'CHAIN' => 1, 'CLOSE' => 1, 'ERROR' => 1, 'EVENT' => 1, - 'EVERY' => 1, 'FIRST' => 1, 'FIXED' => 1, 'FLUSH' => 1, 'FOUND' => 1, - 'HOSTS' => 1, 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, 'MERGE' => 1, - 'MONTH' => 1, 'MUTEX' => 1, 'NAMES' => 1, 'NCHAR' => 1, 'OWNER' => 1, - 'PHASE' => 1, 'POINT' => 1, 'PROXY' => 1, 'QUERY' => 1, 'QUICK' => 1, - 'RELAY' => 1, 'RESET' => 1, 'RTREE' => 1, 'SHARE' => 1, 'SLAVE' => 1, - 'START' => 1, 'SUPER' => 1, 'SWAPS' => 1, 'TYPES' => 1, 'UNTIL' => 1, - 'VALUE' => 1, + 'HOST' => 1, 'LAST' => 1, 'LESS' => 1, 'LIST' => 1, 'LOGS' => 1, 'MODE' => 1, + 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'ONLY' => 1, 'OPEN' => 1, 'PAGE' => 1, + 'PORT' => 1, 'PREV' => 1, 'ROWS' => 1, 'SLOW' => 1, 'SOME' => 1, 'STOP' => 1, + 'THAN' => 1, 'TYPE' => 1, 'VIEW' => 1, 'WAIT' => 1, 'WORK' => 1, 'X509' => 1, + 'AFTER' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, 'CACHE' => 1, + 'CHAIN' => 1, 'CLOSE' => 1, 'ERROR' => 1, 'EVENT' => 1, 'EVERY' => 1, + 'FIRST' => 1, 'FIXED' => 1, 'FLUSH' => 1, 'FOUND' => 1, 'HOSTS' => 1, + 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, 'MERGE' => 1, 'MUTEX' => 1, + 'NAMES' => 1, 'NCHAR' => 1, 'OWNER' => 1, 'PHASE' => 1, 'PROXY' => 1, + 'QUERY' => 1, 'QUICK' => 1, 'RELAY' => 1, 'RESET' => 1, 'RTREE' => 1, + 'SHARE' => 1, 'SLAVE' => 1, 'START' => 1, 'SUPER' => 1, 'SWAPS' => 1, + 'TYPES' => 1, 'UNTIL' => 1, 'VALUE' => 1, 'ACTION' => 1, 'BACKUP' => 1, 'BINLOG' => 1, 'CIPHER' => 1, 'CLIENT' => 1, 'COMMIT' => 1, 'ENABLE' => 1, 'ENGINE' => 1, 'ERRORS' => 1, 'ESCAPE' => 1, 'EVENTS' => 1, 'EXPIRE' => 1, 'EXPORT' => 1, 'FAULTS' => 1, 'FIELDS' => 1, - 'FORMAT' => 1, 'GLOBAL' => 1, 'GRANTS' => 1, 'IMPORT' => 1, 'ISSUER' => 1, - 'LEAVES' => 1, 'MASTER' => 1, 'MEDIUM' => 1, 'MEMORY' => 1, 'MINUTE' => 1, - 'MODIFY' => 1, 'NUMBER' => 1, 'OFFSET' => 1, 'PARSER' => 1, 'PLUGIN' => 1, - 'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, 'RESUME' => 1, 'ROLLUP' => 1, - 'SECOND' => 1, 'SERIAL' => 1, 'SERVER' => 1, 'SIGNED' => 1, 'SIMPLE' => 1, - 'SOCKET' => 1, 'SONAME' => 1, 'SOUNDS' => 1, 'SOURCE' => 1, 'STARTS' => 1, - 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1, - 'AGAINST' => 1, 'ANALYSE' => 1, 'AUTHORS' => 1, 'CHANGED' => 1, 'CHARSET' => 1, - 'COLUMNS' => 1, 'COMMENT' => 1, 'COMPACT' => 1, 'CONTEXT' => 1, 'CURRENT' => 1, - 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1, 'DYNAMIC' => 1, 'ENGINES' => 1, - 'EXECUTE' => 1, 'GENERAL' => 1, 'HANDLER' => 1, 'INDEXES' => 1, 'INSTALL' => 1, - 'INVOKER' => 1, 'LOGFILE' => 1, 'MIGRATE' => 1, 'NO_WAIT' => 1, 'OPTIONS' => 1, - 'PARTIAL' => 1, 'PLUGINS' => 1, 'POLYGON' => 1, 'PREPARE' => 1, 'PROFILE' => 1, - 'QUARTER' => 1, 'REBUILD' => 1, 'RECOVER' => 1, 'RESTORE' => 1, 'RETURNS' => 1, - 'REVERSE' => 1, 'ROUTINE' => 1, 'SESSION' => 1, 'STORAGE' => 1, 'SUBJECT' => 1, - 'SUSPEND' => 1, 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1, 'USE_FRM' => 1, - 'WRAPPER' => 1, - 'CASCADED' => 1, 'CHECKSUM' => 1, 'COALESCE' => 1, 'CONTAINS' => 1, - 'DATAFILE' => 1, 'DUMPFILE' => 1, 'EXCHANGE' => 1, 'EXTENDED' => 1, - 'FUNCTION' => 1, 'GEOMETRY' => 1, 'LANGUAGE' => 1, 'MAX_ROWS' => 1, - 'MAX_SIZE' => 1, 'MIN_ROWS' => 1, 'NATIONAL' => 1, 'NVARCHAR' => 1, - 'ONE_SHOT' => 1, 'PASSWORD' => 1, 'PRESERVE' => 1, 'PROFILES' => 1, - 'REDOFILE' => 1, 'RELAYLOG' => 1, 'ROLLBACK' => 1, 'SCHEDULE' => 1, - 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1, 'SWITCHES' => 1, - 'TRIGGERS' => 1, 'TRUNCATE' => 1, 'UNDOFILE' => 1, 'WARNINGS' => 1, - 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COLLATION' => 1, 'COMMITTED' => 1, - 'DIRECTORY' => 1, 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, - 'ISOLATION' => 1, 'NODEGROUP' => 1, 'PACK_KEYS' => 1, 'READ_ONLY' => 1, - 'REDUNDANT' => 1, 'ROW_COUNT' => 1, 'SAVEPOINT' => 1, 'SQL_CACHE' => 1, - 'TEMPORARY' => 1, 'TEMPTABLE' => 1, 'UNDEFINED' => 1, 'UNINSTALL' => 1, - 'VARIABLES' => 1, + 'GLOBAL' => 1, 'GRANTS' => 1, 'IMPORT' => 1, 'ISSUER' => 1, 'LEAVES' => 1, + 'MASTER' => 1, 'MEDIUM' => 1, 'MEMORY' => 1, 'MODIFY' => 1, 'NUMBER' => 1, + 'OFFSET' => 1, 'PARSER' => 1, 'PLUGIN' => 1, 'RELOAD' => 1, 'REMOVE' => 1, + 'REPAIR' => 1, 'RESUME' => 1, 'ROLLUP' => 1, 'SERIAL' => 1, 'SERVER' => 1, + 'SIGNED' => 1, 'SIMPLE' => 1, 'SOCKET' => 1, 'SONAME' => 1, 'SOUNDS' => 1, + 'SOURCE' => 1, 'STARTS' => 1, 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1, + 'AGAINST' => 1, 'ANALYSE' => 1, 'AUTHORS' => 1, 'CHANGED' => 1, 'COLUMNS' => 1, + 'COMMENT' => 1, 'COMPACT' => 1, 'CONTEXT' => 1, 'CURRENT' => 1, 'DEFINER' => 1, + 'DISABLE' => 1, 'DISCARD' => 1, 'DYNAMIC' => 1, 'ENGINES' => 1, 'EXECUTE' => 1, + 'GENERAL' => 1, 'HANDLER' => 1, 'INDEXES' => 1, 'INSTALL' => 1, 'INVOKER' => 1, + 'LOGFILE' => 1, 'MIGRATE' => 1, 'NO_WAIT' => 1, 'OPTIONS' => 1, 'PARTIAL' => 1, + 'PLUGINS' => 1, 'PREPARE' => 1, 'PROFILE' => 1, 'REBUILD' => 1, 'RECOVER' => 1, + 'RESTORE' => 1, 'RETURNS' => 1, 'ROUTINE' => 1, 'SESSION' => 1, 'STORAGE' => 1, + 'SUBJECT' => 1, 'SUSPEND' => 1, 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1, + 'USE_FRM' => 1, 'WRAPPER' => 1, + 'CASCADED' => 1, 'CHECKSUM' => 1, 'DATAFILE' => 1, 'DUMPFILE' => 1, + 'EXCHANGE' => 1, 'EXTENDED' => 1, 'FUNCTION' => 1, 'GEOMETRY' => 1, + 'LANGUAGE' => 1, 'MAX_ROWS' => 1, 'MAX_SIZE' => 1, 'MIN_ROWS' => 1, + 'NATIONAL' => 1, 'NVARCHAR' => 1, 'ONE_SHOT' => 1, 'PRESERVE' => 1, + 'PROFILES' => 1, 'REDOFILE' => 1, 'RELAYLOG' => 1, 'ROLLBACK' => 1, + 'SCHEDULE' => 1, 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1, + 'SWITCHES' => 1, 'TRIGGERS' => 1, 'UNDOFILE' => 1, 'WARNINGS' => 1, + 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COMMITTED' => 1, 'DIRECTORY' => 1, + 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, 'ISOLATION' => 1, + 'NODEGROUP' => 1, 'PACK_KEYS' => 1, 'READ_ONLY' => 1, 'REDUNDANT' => 1, + 'SAVEPOINT' => 1, 'SQL_CACHE' => 1, 'TEMPORARY' => 1, 'TEMPTABLE' => 1, + 'UNDEFINED' => 1, 'UNINSTALL' => 1, 'VARIABLES' => 1, 'COMPLETION' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1, - 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'GET_FORMAT' => 1, 'IDENTIFIED' => 1, - 'LINESTRING' => 1, 'MASTER_SSL' => 1, 'MULTIPOINT' => 1, 'NDBCLUSTER' => 1, - 'PARTITIONS' => 1, 'PLUGIN_DIR' => 1, 'PRIVILEGES' => 1, 'REORGANIZE' => 1, - 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, 'TABLESPACE' => 1, - 'TABLE_NAME' => 1, + 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'IDENTIFIED' => 1, 'MASTER_SSL' => 1, + 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PLUGIN_DIR' => 1, 'PRIVILEGES' => 1, + 'REORGANIZE' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, + 'TABLESPACE' => 1, 'TABLE_NAME' => 1, 'COLUMN_NAME' => 1, 'CURSOR_NAME' => 1, 'DIAGNOSTICS' => 1, 'EXTENT_SIZE' => 1, - 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, 'MICROSECOND' => 1, - 'MYSQL_ERRNO' => 1, 'PROCESSLIST' => 1, 'REPLICATION' => 1, 'SCHEMA_NAME' => 1, - 'SQL_TSI_DAY' => 1, 'TRANSACTION' => 1, 'UNCOMMITTED' => 1, + 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, 'MYSQL_ERRNO' => 1, + 'PROCESSLIST' => 1, 'REPLICATION' => 1, 'SCHEMA_NAME' => 1, 'SQL_TSI_DAY' => 1, + 'TRANSACTION' => 1, 'UNCOMMITTED' => 1, 'CATALOG_NAME' => 1, 'CLASS_ORIGIN' => 1, 'CONTRIBUTORS' => 1, 'DEFAULT_AUTH' => 1, 'DES_KEY_FILE' => 1, 'INITIAL_SIZE' => 1, - 'MASTER_DELAY' => 1, 'MESSAGE_TEXT' => 1, 'MULTIPOLYGON' => 1, - 'OLD_PASSWORD' => 1, 'PARTITIONING' => 1, 'RELAY_THREAD' => 1, - 'SERIALIZABLE' => 1, 'SQL_NO_CACHE' => 1, 'SQL_TSI_HOUR' => 1, - 'SQL_TSI_WEEK' => 1, 'SQL_TSI_YEAR' => 1, 'SUBPARTITION' => 1, - 'TIMESTAMPADD' => 1, + 'MASTER_DELAY' => 1, 'MESSAGE_TEXT' => 1, 'PARTITIONING' => 1, + 'RELAY_THREAD' => 1, 'SERIALIZABLE' => 1, 'SQL_NO_CACHE' => 1, + 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1, 'SQL_TSI_YEAR' => 1, + 'SUBPARTITION' => 1, 'COLUMN_FORMAT' => 1, 'INSERT_METHOD' => 1, 'MASTER_SSL_CA' => 1, 'RELAY_LOG_POS' => 1, 'SQL_TSI_MONTH' => 1, 'SUBPARTITIONS' => 1, - 'TIMESTAMPDIFF' => 1, 'WEIGHT_STRING' => 1, 'AUTO_INCREMENT' => 1, 'AVG_ROW_LENGTH' => 1, 'KEY_BLOCK_SIZE' => 1, 'MASTER_LOG_POS' => 1, 'MASTER_SSL_CRL' => 1, 'MASTER_SSL_KEY' => 1, 'RELAY_LOG_FILE' => 1, 'SQL_TSI_MINUTE' => 1, 'SQL_TSI_SECOND' => 1, 'TABLE_CHECKSUM' => 1, 'USER_RESOURCES' => 1, 'AUTOEXTEND_SIZE' => 1, 'CONSTRAINT_NAME' => 1, 'DELAY_KEY_WRITE' => 1, 'MASTER_LOG_FILE' => 1, 'MASTER_PASSWORD' => 1, 'MASTER_SSL_CERT' => 1, - 'MULTILINESTRING' => 1, 'SQL_AFTER_GTIDS' => 1, 'SQL_TSI_QUARTER' => 1, - 'SUBCLASS_ORIGIN' => 1, + 'SQL_AFTER_GTIDS' => 1, 'SQL_TSI_QUARTER' => 1, 'SUBCLASS_ORIGIN' => 1, 'MASTER_SERVER_ID' => 1, 'REDO_BUFFER_SIZE' => 1, 'SQL_BEFORE_GTIDS' => 1, 'STATS_PERSISTENT' => 1, 'UNDO_BUFFER_SIZE' => 1, 'CONSTRAINT_SCHEMA' => 1, 'IGNORE_SERVER_IDS' => 1, 'MASTER_SSL_CAPATH' => 1, 'MASTER_SSL_CIPHER' => 1, 'RETURNED_SQLSTATE' => 1, 'SQL_BUFFER_RESULT' => 1, 'STATS_AUTO_RECALC' => 1, - 'CONSTRAINT_CATALOG' => 1, 'GEOMETRYCOLLECTION' => 1, 'MASTER_RETRY_COUNT' => 1, - 'MASTER_SSL_CRLPATH' => 1, 'SQL_AFTER_MTS_GAPS' => 1, 'STATS_SAMPLE_PAGES' => 1, + 'CONSTRAINT_CATALOG' => 1, 'MASTER_RETRY_COUNT' => 1, 'MASTER_SSL_CRLPATH' => 1, + 'SQL_AFTER_MTS_GAPS' => 1, 'STATS_SAMPLE_PAGES' => 1, 'MASTER_AUTO_POSITION' => 1, 'MASTER_CONNECT_RETRY' => 1, 'MAX_QUERIES_PER_HOUR' => 1, 'MAX_UPDATES_PER_HOUR' => 1, 'MAX_USER_CONNECTIONS' => 1, 'MASTER_HEARTBEAT_PERIOD' => 1, 'MAX_CONNECTIONS_PER_HOUR' => 1, - 'AS' => 3, 'BY' => 3, 'IF' => 3, 'IN' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, - 'TO' => 3, + 'AS' => 3, 'BY' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, 'TO' => 3, 'ADD' => 3, 'ALL' => 3, 'AND' => 3, 'ASC' => 3, 'DEC' => 3, 'DIV' => 3, - 'FOR' => 3, 'GET' => 3, 'MOD' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, - 'SSL' => 3, 'USE' => 3, 'XOR' => 3, + 'FOR' => 3, 'GET' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, 'SSL' => 3, + 'USE' => 3, 'XOR' => 3, 'BOTH' => 3, 'CALL' => 3, 'CASE' => 3, 'DESC' => 3, 'DROP' => 3, 'DUAL' => 3, 'EACH' => 3, 'ELSE' => 3, 'EXIT' => 3, 'FROM' => 3, 'INT1' => 3, 'INT2' => 3, 'INT3' => 3, 'INT4' => 3, 'INT8' => 3, 'INTO' => 3, 'JOIN' => 3, 'KEYS' => 3, - 'KILL' => 3, 'LEFT' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, - 'LOOP' => 3, 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, - 'UNDO' => 3, 'WHEN' => 3, 'WITH' => 3, + 'KILL' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, 'LOOP' => 3, + 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, 'UNDO' => 3, + 'WHEN' => 3, 'WITH' => 3, 'ALTER' => 3, 'CHECK' => 3, 'CROSS' => 3, 'FALSE' => 3, 'FETCH' => 3, 'FORCE' => 3, 'GRANT' => 3, 'GROUP' => 3, 'INNER' => 3, 'INOUT' => 3, 'LEAVE' => 3, 'LIMIT' => 3, 'LINES' => 3, 'MATCH' => 3, 'ORDER' => 3, - 'OUTER' => 3, 'PURGE' => 3, 'RANGE' => 3, 'READS' => 3, 'RIGHT' => 3, - 'RLIKE' => 3, 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, - 'WHERE' => 3, 'WHILE' => 3, 'WRITE' => 3, + 'OUTER' => 3, 'PURGE' => 3, 'RANGE' => 3, 'READS' => 3, 'RLIKE' => 3, + 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, 'WHERE' => 3, + 'WHILE' => 3, 'WRITE' => 3, 'BEFORE' => 3, 'CHANGE' => 3, 'COLUMN' => 3, 'CREATE' => 3, 'CURSOR' => 3, 'DELETE' => 3, 'ELSEIF' => 3, 'EXISTS' => 3, 'FLOAT4' => 3, 'FLOAT8' => 3, - 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'INSERT' => 3, 'LINEAR' => 3, - 'OPTION' => 3, 'REGEXP' => 3, 'RENAME' => 3, 'REPEAT' => 3, 'RETURN' => 3, - 'REVOKE' => 3, 'SCHEMA' => 3, 'SELECT' => 3, 'SIGNAL' => 3, 'UNLOCK' => 3, - 'UPDATE' => 3, 'VALUES' => 3, - 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'CONVERT' => 3, - 'DECLARE' => 3, 'DEFAULT' => 3, 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, - 'FOREIGN' => 3, 'ITERATE' => 3, 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, - 'PRIMARY' => 3, 'RELEASE' => 3, 'REPLACE' => 3, 'REQUIRE' => 3, 'SCHEMAS' => 3, - 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3, - 'CONTINUE' => 3, 'DATABASE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, - 'DISTINCT' => 3, 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MAXVALUE' => 3, - 'MODIFIES' => 3, 'OPTIMIZE' => 3, 'RESIGNAL' => 3, 'RESTRICT' => 3, - 'SPECIFIC' => 3, 'SQLSTATE' => 3, 'STARTING' => 3, 'TRAILING' => 3, - 'UNSIGNED' => 3, 'UTC_DATE' => 3, 'UTC_TIME' => 3, 'ZEROFILL' => 3, - 'CONDITION' => 3, 'DATABASES' => 3, 'LOCALTIME' => 3, 'MIDDLEINT' => 3, - 'PARTITION' => 3, 'PRECISION' => 3, 'PROCEDURE' => 3, 'SENSITIVE' => 3, - 'SEPARATOR' => 3, + 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'LINEAR' => 3, 'OPTION' => 3, + 'REGEXP' => 3, 'RENAME' => 3, 'RETURN' => 3, 'REVOKE' => 3, 'SELECT' => 3, + 'SIGNAL' => 3, 'UNLOCK' => 3, 'UPDATE' => 3, + 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'DECLARE' => 3, + 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, 'FOREIGN' => 3, 'ITERATE' => 3, + 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, 'PRIMARY' => 3, 'RELEASE' => 3, + 'REQUIRE' => 3, 'SCHEMAS' => 3, 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3, + 'CONTINUE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, 'DISTINCT' => 3, + 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MAXVALUE' => 3, 'MODIFIES' => 3, + 'OPTIMIZE' => 3, 'RESIGNAL' => 3, 'RESTRICT' => 3, 'SPECIFIC' => 3, + 'SQLSTATE' => 3, 'STARTING' => 3, 'TRAILING' => 3, 'UNSIGNED' => 3, + 'ZEROFILL' => 3, + 'CONDITION' => 3, 'DATABASES' => 3, 'MIDDLEINT' => 3, 'PARTITION' => 3, + 'PRECISION' => 3, 'PROCEDURE' => 3, 'SENSITIVE' => 3, 'SEPARATOR' => 3, 'ACCESSIBLE' => 3, 'ASENSITIVE' => 3, 'CONSTRAINT' => 3, 'DAY_MINUTE' => 3, 'DAY_SECOND' => 3, 'OPTIONALLY' => 3, 'READ_WRITE' => 3, 'REFERENCES' => 3, 'SQLWARNING' => 3, 'TERMINATED' => 3, 'YEAR_MONTH' => 3, 'DISTINCTROW' => 3, 'HOUR_MINUTE' => 3, 'HOUR_SECOND' => 3, 'INSENSITIVE' => 3, 'MASTER_BIND' => 3, - 'CURRENT_DATE' => 3, 'CURRENT_TIME' => 3, 'CURRENT_USER' => 3, 'LOW_PRIORITY' => 3, 'SQLEXCEPTION' => 3, 'VARCHARACTER' => 3, 'DETERMINISTIC' => 3, 'HIGH_PRIORITY' => 3, 'MINUTE_SECOND' => 3, - 'STRAIGHT_JOIN' => 3, 'UTC_TIMESTAMP' => 3, - 'IO_AFTER_GTIDS' => 3, 'LOCALTIMESTAMP' => 3, 'SQL_BIG_RESULT' => 3, + 'STRAIGHT_JOIN' => 3, + 'IO_AFTER_GTIDS' => 3, 'SQL_BIG_RESULT' => 3, 'DAY_MICROSECOND' => 3, 'IO_BEFORE_GTIDS' => 3, 'HOUR_MICROSECOND' => 3, 'SQL_SMALL_RESULT' => 3, - 'CURRENT_TIMESTAMP' => 3, 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3, 'SQL_CALC_FOUND_ROWS' => 3, 'MASTER_SSL_VERIFY_SERVER_CERT' => 3, @@ -190,19 +174,18 @@ class ContextMySql50600 extends Context 'GROUP BY' => 7, 'ORDER BY' => 7, 'XML' => 9, - 'DATE' => 9, 'ENUM' => 9, 'TEXT' => 9, 'TIME' => 9, 'YEAR' => 9, + 'ENUM' => 9, 'TEXT' => 9, 'ARRAY' => 9, 'BOOLEAN' => 9, 'DATETIME' => 9, 'MULTISET' => 9, - 'TIMESTAMP' => 9, 'INT' => 11, 'SET' => 11, - 'BLOB' => 11, 'CHAR' => 11, 'REAL' => 11, + 'BLOB' => 11, 'REAL' => 11, 'FLOAT' => 11, 'BIGINT' => 11, 'BINARY' => 11, 'DOUBLE' => 11, 'DECIMAL' => 11, 'INTEGER' => 11, 'NUMERIC' => 11, 'TINYINT' => 11, 'VARCHAR' => 11, - 'INTERVAL' => 11, 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, - 'TINYBLOB' => 11, 'TINYTEXT' => 11, + 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, 'TINYBLOB' => 11, + 'TINYTEXT' => 11, 'CHARACTER' => 11, 'MEDIUMINT' => 11, 'VARBINARY' => 11, 'MEDIUMBLOB' => 11, 'MEDIUMTEXT' => 11, @@ -219,5 +202,126 @@ class ContextMySql50600 extends Context 'SPATIAL INDEX' => 21, 'FULLTEXT INDEX' => 21, + 'X' => 33, 'Y' => 33, + 'LN' => 33, 'PI' => 33, + 'ABS' => 33, 'AVG' => 33, 'BIN' => 33, 'COS' => 33, 'COT' => 33, 'DAY' => 33, + 'ELT' => 33, 'EXP' => 33, 'HEX' => 33, 'LOG' => 33, 'MAX' => 33, 'MD5' => 33, + 'MID' => 33, 'MIN' => 33, 'NOW' => 33, 'OCT' => 33, 'ORD' => 33, 'POW' => 33, + 'SHA' => 33, 'SIN' => 33, 'STD' => 33, 'SUM' => 33, 'TAN' => 33, + 'ACOS' => 33, 'AREA' => 33, 'ASIN' => 33, 'ATAN' => 33, 'CAST' => 33, 'CEIL' => 33, + 'CONV' => 33, 'HOUR' => 33, 'LOG2' => 33, 'LPAD' => 33, 'RAND' => 33, 'RPAD' => 33, + 'SHA1' => 33, 'SHA2' => 33, 'SIGN' => 33, 'SQRT' => 33, 'SRID' => 33, 'ST_X' => 33, + 'ST_Y' => 33, 'TRIM' => 33, 'USER' => 33, 'UUID' => 33, 'WEEK' => 33, + 'ASCII' => 33, 'ASWKB' => 33, 'ASWKT' => 33, 'ATAN2' => 33, 'COUNT' => 33, + 'CRC32' => 33, 'FIELD' => 33, 'FLOOR' => 33, 'INSTR' => 33, 'LCASE' => 33, + 'LEAST' => 33, 'LOG10' => 33, 'LOWER' => 33, 'LTRIM' => 33, 'MONTH' => 33, + 'POINT' => 33, 'POWER' => 33, 'QUOTE' => 33, 'ROUND' => 33, 'RTRIM' => 33, + 'SLEEP' => 33, 'SPACE' => 33, 'UCASE' => 33, 'UNHEX' => 33, 'UPPER' => 33, + 'ASTEXT' => 33, 'BIT_OR' => 33, 'BUFFER' => 33, 'CONCAT' => 33, 'DECODE' => 33, + 'ENCODE' => 33, 'EQUALS' => 33, 'FORMAT' => 33, 'IFNULL' => 33, 'ISNULL' => 33, + 'LENGTH' => 33, 'LOCATE' => 33, 'MINUTE' => 33, 'NULLIF' => 33, 'POINTN' => 33, + 'SECOND' => 33, 'STDDEV' => 33, 'STRCMP' => 33, 'SUBSTR' => 33, 'WITHIN' => 33, + 'ADDDATE' => 33, 'ADDTIME' => 33, 'BIT_AND' => 33, 'BIT_XOR' => 33, 'CEILING' => 33, + 'CHARSET' => 33, 'CROSSES' => 33, 'CURDATE' => 33, 'CURTIME' => 33, 'DAYNAME' => 33, + 'DEGREES' => 33, 'ENCRYPT' => 33, 'EXTRACT' => 33, 'GLENGTH' => 33, 'ISEMPTY' => 33, + 'IS_IPV4' => 33, 'IS_IPV6' => 33, 'POLYGON' => 33, 'QUARTER' => 33, 'RADIANS' => 33, + 'REVERSE' => 33, 'SOUNDEX' => 33, 'ST_AREA' => 33, 'ST_SRID' => 33, 'SUBDATE' => 33, + 'SUBTIME' => 33, 'SYSDATE' => 33, 'TOUCHES' => 33, 'TO_DAYS' => 33, 'VAR_POP' => 33, + 'VERSION' => 33, 'WEEKDAY' => 33, + 'ASBINARY' => 33, 'CENTROID' => 33, 'COALESCE' => 33, 'COMPRESS' => 33, + 'CONTAINS' => 33, 'DATEDIFF' => 33, 'DATE_ADD' => 33, 'DATE_SUB' => 33, + 'DISJOINT' => 33, 'ENDPOINT' => 33, 'ENVELOPE' => 33, 'GET_LOCK' => 33, + 'GREATEST' => 33, 'ISCLOSED' => 33, 'ISSIMPLE' => 33, 'MAKEDATE' => 33, + 'MAKETIME' => 33, 'MAKE_SET' => 33, 'MBREQUAL' => 33, 'OVERLAPS' => 33, + 'PASSWORD' => 33, 'POSITION' => 33, 'ST_ASWKB' => 33, 'ST_ASWKT' => 33, + 'ST_UNION' => 33, 'TIMEDIFF' => 33, 'TRUNCATE' => 33, 'VARIANCE' => 33, + 'VAR_SAMP' => 33, 'YEARWEEK' => 33, + 'BENCHMARK' => 33, 'BIT_COUNT' => 33, 'COLLATION' => 33, 'CONCAT_WS' => 33, + 'DAYOFWEEK' => 33, 'DAYOFYEAR' => 33, 'DIMENSION' => 33, 'FROM_DAYS' => 33, + 'GEOMETRYN' => 33, 'INET_ATON' => 33, 'INET_NTOA' => 33, 'LOAD_FILE' => 33, + 'MBRWITHIN' => 33, 'MONTHNAME' => 33, 'NUMPOINTS' => 33, 'ROW_COUNT' => 33, + 'ST_ASTEXT' => 33, 'ST_BUFFER' => 33, 'ST_EQUALS' => 33, 'ST_POINTN' => 33, + 'ST_WITHIN' => 33, 'SUBSTRING' => 33, 'TO_BASE64' => 33, 'UPDATEXML' => 33, + 'BIT_LENGTH' => 33, 'CONVERT_TZ' => 33, 'DAYOFMONTH' => 33, 'EXPORT_SET' => 33, + 'FOUND_ROWS' => 33, 'GET_FORMAT' => 33, 'INET6_ATON' => 33, 'INET6_NTOA' => 33, + 'INTERSECTS' => 33, 'LINESTRING' => 33, 'MBRTOUCHES' => 33, 'MULTIPOINT' => 33, + 'NAME_CONST' => 33, 'PERIOD_ADD' => 33, 'STARTPOINT' => 33, 'STDDEV_POP' => 33, + 'ST_CROSSES' => 33, 'ST_ISEMPTY' => 33, 'ST_TOUCHES' => 33, 'TO_SECONDS' => 33, + 'UNCOMPRESS' => 33, 'UUID_SHORT' => 33, 'WEEKOFYEAR' => 33, + 'AES_DECRYPT' => 33, 'AES_ENCRYPT' => 33, 'CHAR_LENGTH' => 33, 'DATE_FORMAT' => 33, + 'DES_DECRYPT' => 33, 'DES_ENCRYPT' => 33, 'FIND_IN_SET' => 33, 'FROM_BASE64' => 33, + 'GEOMFROMWKB' => 33, 'GTID_SUBSET' => 33, 'LINEFROMWKB' => 33, 'MBRCONTAINS' => 33, + 'MBRDISJOINT' => 33, 'MBROVERLAPS' => 33, 'MICROSECOND' => 33, 'PERIOD_DIFF' => 33, + 'POLYFROMWKB' => 33, 'SEC_TO_TIME' => 33, 'STDDEV_SAMP' => 33, 'STR_TO_DATE' => 33, + 'ST_ASBINARY' => 33, 'ST_CENTROID' => 33, 'ST_CONTAINS' => 33, 'ST_DISJOINT' => 33, + 'ST_DISTANCE' => 33, 'ST_ENDPOINT' => 33, 'ST_ENVELOPE' => 33, 'ST_ISCLOSED' => 33, + 'ST_ISSIMPLE' => 33, 'ST_OVERLAPS' => 33, 'SYSTEM_USER' => 33, 'TIME_FORMAT' => 33, + 'TIME_TO_SEC' => 33, + 'COERCIBILITY' => 33, 'EXTERIORRING' => 33, 'EXTRACTVALUE' => 33, + 'GEOMETRYTYPE' => 33, 'GEOMFROMTEXT' => 33, 'GROUP_CONCAT' => 33, + 'IS_FREE_LOCK' => 33, 'IS_USED_LOCK' => 33, 'LINEFROMTEXT' => 33, + 'MLINEFROMWKB' => 33, 'MPOLYFROMWKB' => 33, 'MULTIPOLYGON' => 33, + 'OCTET_LENGTH' => 33, 'OLD_PASSWORD' => 33, 'POINTFROMWKB' => 33, + 'POLYFROMTEXT' => 33, 'RANDOM_BYTES' => 33, 'RELEASE_LOCK' => 33, + 'SESSION_USER' => 33, 'ST_DIMENSION' => 33, 'ST_GEOMETRYN' => 33, + 'ST_NUMPOINTS' => 33, 'TIMESTAMPADD' => 33, + 'CONNECTION_ID' => 33, 'CREATE_DIGEST' => 33, 'FROM_UNIXTIME' => 33, + 'GTID_SUBTRACT' => 33, 'INTERIORRINGN' => 33, 'MBRINTERSECTS' => 33, + 'MLINEFROMTEXT' => 33, 'MPOINTFROMWKB' => 33, 'MPOLYFROMTEXT' => 33, + 'NUMGEOMETRIES' => 33, 'POINTFROMTEXT' => 33, 'ST_DIFFERENCE' => 33, + 'ST_INTERSECTS' => 33, 'ST_STARTPOINT' => 33, 'TIMESTAMPDIFF' => 33, + 'WEIGHT_STRING' => 33, + 'IS_IPV4_COMPAT' => 33, 'IS_IPV4_MAPPED' => 33, 'LAST_INSERT_ID' => 33, + 'MPOINTFROMTEXT' => 33, 'POLYGONFROMWKB' => 33, 'ST_GEOMFROMWKB' => 33, + 'ST_LINEFROMWKB' => 33, 'ST_POLYFROMWKB' => 33, 'UNIX_TIMESTAMP' => 33, + 'ASYMMETRIC_SIGN' => 33, 'GEOMCOLLFROMWKB' => 33, 'MASTER_POS_WAIT' => 33, + 'MULTILINESTRING' => 33, 'POLYGONFROMTEXT' => 33, 'ST_EXTERIORRING' => 33, + 'ST_GEOMETRYTYPE' => 33, 'ST_GEOMFROMTEXT' => 33, 'ST_INTERSECTION' => 33, + 'ST_LINEFROMTEXT' => 33, 'ST_POINTFROMWKB' => 33, 'ST_POLYFROMTEXT' => 33, + 'SUBSTRING_INDEX' => 33, + 'CHARACTER_LENGTH' => 33, 'GEOMCOLLFROMTEXT' => 33, 'GEOMETRYFROMTEXT' => 33, + 'NUMINTERIORRINGS' => 33, 'ST_INTERIORRINGN' => 33, 'ST_NUMGEOMETRIES' => 33, + 'ST_POINTFROMTEXT' => 33, 'ST_SYMDIFFERENCE' => 33, + 'ASYMMETRIC_DERIVE' => 33, 'ASYMMETRIC_VERIFY' => 33, 'LINESTRINGFROMWKB' => 33, + 'MULTIPOINTFROMWKB' => 33, 'ST_POLYGONFROMWKB' => 33, + 'ASYMMETRIC_DECRYPT' => 33, 'ASYMMETRIC_ENCRYPT' => 33, 'GEOMETRYCOLLECTION' => 33, + 'MULTIPOINTFROMTEXT' => 33, 'ST_GEOMCOLLFROMTXT' => 33, 'ST_GEOMCOLLFROMWKB' => 33, + 'ST_POLYGONFROMTEXT' => 33, + 'MULTIPOLYGONFROMWKB' => 33, 'ST_GEOMCOLLFROMTEXT' => 33, 'ST_GEOMETRYFROMTEXT' => 33, + 'ST_NUMINTERIORRINGS' => 33, 'UNCOMPRESSED_LENGTH' => 33, + 'CREATE_DH_PARAMETERS' => 33, 'MULTIPOLYGONFROMTEXT' => 33, + 'ST_LINESTRINGFROMWKB' => 33, + 'MULTILINESTRINGFROMWKB' => 33, + 'MULTILINESTRINGFROMTEXT' => 33, + 'CREATE_ASYMMETRIC_PUB_KEY' => 33, 'GEOMETRYCOLLECTIONFROMWKB' => 33, + 'CREATE_ASYMMETRIC_PRIV_KEY' => 33, 'GEOMETRYCOLLECTIONFROMTEXT' => 33, + 'VALIDATE_PASSWORD_STRENGTH' => 33, + 'SQL_THREAD_WAIT_AFTER_GTIDS' => 33, + 'ST_GEOMETRYCOLLECTIONFROMWKB' => 33, + 'ST_GEOMETRYCOLLECTIONFROMTEXT' => 33, + 'WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS' => 33, + + 'IF' => 35, 'IN' => 35, + 'MOD' => 35, + 'LEFT' => 35, + 'RIGHT' => 35, + 'INSERT' => 35, 'REPEAT' => 35, 'SCHEMA' => 35, 'VALUES' => 35, + 'CONVERT' => 35, 'DEFAULT' => 35, 'REPLACE' => 35, + 'DATABASE' => 35, 'UTC_DATE' => 35, 'UTC_TIME' => 35, + 'LOCALTIME' => 35, + 'CURRENT_DATE' => 35, 'CURRENT_TIME' => 35, 'CURRENT_USER' => 35, + 'UTC_TIMESTAMP' => 35, + 'LOCALTIMESTAMP' => 35, + 'CURRENT_TIMESTAMP' => 35, + + 'NOT IN' => 37, + 'PROCEDURE ANALYSE' => 37, + + 'DATE' => 41, 'TIME' => 41, 'YEAR' => 41, + 'TIMESTAMP' => 41, + + 'CHAR' => 43, + 'INTERVAL' => 43, + ); } diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50700.php b/libraries/sql-parser/src/Contexts/ContextMySql50700.php index 808de0df49..99dae9e02e 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50700.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50700.php @@ -34,95 +34,86 @@ class ContextMySql50700 extends Context public static $KEYWORDS = array( 'AT' => 1, 'DO' => 1, 'IO' => 1, 'NO' => 1, 'XA' => 1, - 'ANY' => 1, 'AVG' => 1, 'BIT' => 1, 'CPU' => 1, 'DAY' => 1, 'END' => 1, - 'IPC' => 1, 'NDB' => 1, 'NEW' => 1, 'ONE' => 1, 'ROW' => 1, 'XID' => 1, + 'ANY' => 1, 'BIT' => 1, 'CPU' => 1, 'END' => 1, 'IPC' => 1, 'NDB' => 1, + 'NEW' => 1, 'ONE' => 1, 'ROW' => 1, 'XID' => 1, 'BOOL' => 1, 'BYTE' => 1, 'CODE' => 1, 'CUBE' => 1, 'DATA' => 1, 'DISK' => 1, 'ENDS' => 1, 'FAST' => 1, 'FILE' => 1, 'FULL' => 1, 'HASH' => 1, 'HELP' => 1, - 'HOST' => 1, 'HOUR' => 1, 'LAST' => 1, 'LESS' => 1, 'LIST' => 1, 'LOGS' => 1, - 'MODE' => 1, 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'ONLY' => 1, 'OPEN' => 1, - 'PAGE' => 1, 'PORT' => 1, 'PREV' => 1, 'ROWS' => 1, 'SLOW' => 1, 'SOME' => 1, - 'STOP' => 1, 'THAN' => 1, 'TYPE' => 1, 'USER' => 1, 'VIEW' => 1, 'WAIT' => 1, - 'WEEK' => 1, 'WORK' => 1, 'X509' => 1, - 'AFTER' => 1, 'ASCII' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, - 'CACHE' => 1, 'CHAIN' => 1, 'CLOSE' => 1, 'ERROR' => 1, 'EVENT' => 1, - 'EVERY' => 1, 'FIRST' => 1, 'FIXED' => 1, 'FLUSH' => 1, 'FOUND' => 1, - 'HOSTS' => 1, 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, 'MERGE' => 1, - 'MONTH' => 1, 'MUTEX' => 1, 'NAMES' => 1, 'NCHAR' => 1, 'NEVER' => 1, - 'OWNER' => 1, 'PHASE' => 1, 'POINT' => 1, 'PROXY' => 1, 'QUERY' => 1, - 'QUICK' => 1, 'RELAY' => 1, 'RESET' => 1, 'RTREE' => 1, 'SHARE' => 1, - 'SLAVE' => 1, 'START' => 1, 'SUPER' => 1, 'SWAPS' => 1, 'TYPES' => 1, - 'UNTIL' => 1, 'VALUE' => 1, + 'HOST' => 1, 'LAST' => 1, 'LESS' => 1, 'LIST' => 1, 'LOGS' => 1, 'MODE' => 1, + 'NAME' => 1, 'NEXT' => 1, 'NONE' => 1, 'ONLY' => 1, 'OPEN' => 1, 'PAGE' => 1, + 'PORT' => 1, 'PREV' => 1, 'ROWS' => 1, 'SLOW' => 1, 'SOME' => 1, 'STOP' => 1, + 'THAN' => 1, 'TYPE' => 1, 'VIEW' => 1, 'WAIT' => 1, 'WORK' => 1, 'X509' => 1, + 'AFTER' => 1, 'BEGIN' => 1, 'BLOCK' => 1, 'BTREE' => 1, 'CACHE' => 1, + 'CHAIN' => 1, 'CLOSE' => 1, 'ERROR' => 1, 'EVENT' => 1, 'EVERY' => 1, + 'FIRST' => 1, 'FIXED' => 1, 'FLUSH' => 1, 'FOUND' => 1, 'HOSTS' => 1, + 'LEVEL' => 1, 'LOCAL' => 1, 'LOCKS' => 1, 'MERGE' => 1, 'MUTEX' => 1, + 'NAMES' => 1, 'NCHAR' => 1, 'NEVER' => 1, 'OWNER' => 1, 'PHASE' => 1, + 'PROXY' => 1, 'QUERY' => 1, 'QUICK' => 1, 'RELAY' => 1, 'RESET' => 1, + 'RTREE' => 1, 'SHARE' => 1, 'SLAVE' => 1, 'START' => 1, 'SUPER' => 1, + 'SWAPS' => 1, 'TYPES' => 1, 'UNTIL' => 1, 'VALUE' => 1, 'ACTION' => 1, 'ALWAYS' => 1, 'BACKUP' => 1, 'BINLOG' => 1, 'CIPHER' => 1, 'CLIENT' => 1, 'COMMIT' => 1, 'ENABLE' => 1, 'ENGINE' => 1, 'ERRORS' => 1, 'ESCAPE' => 1, 'EVENTS' => 1, 'EXPIRE' => 1, 'EXPORT' => 1, 'FAULTS' => 1, - 'FIELDS' => 1, 'FILTER' => 1, 'FORMAT' => 1, 'GLOBAL' => 1, 'GRANTS' => 1, - 'IMPORT' => 1, 'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1, 'MEDIUM' => 1, - 'MEMORY' => 1, 'MINUTE' => 1, 'MODIFY' => 1, 'NUMBER' => 1, 'OFFSET' => 1, - 'PARSER' => 1, 'PLUGIN' => 1, 'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, - 'RESUME' => 1, 'ROLLUP' => 1, 'SECOND' => 1, 'SERIAL' => 1, 'SERVER' => 1, - 'SIGNED' => 1, 'SIMPLE' => 1, 'SOCKET' => 1, 'SONAME' => 1, 'SOUNDS' => 1, - 'SOURCE' => 1, 'STARTS' => 1, 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1, + 'FIELDS' => 1, 'FILTER' => 1, 'GLOBAL' => 1, 'GRANTS' => 1, 'IMPORT' => 1, + 'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1, 'MEDIUM' => 1, 'MEMORY' => 1, + 'MODIFY' => 1, 'NUMBER' => 1, 'OFFSET' => 1, 'PARSER' => 1, 'PLUGIN' => 1, + 'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, 'RESUME' => 1, 'ROLLUP' => 1, + 'SERIAL' => 1, 'SERVER' => 1, 'SIGNED' => 1, 'SIMPLE' => 1, 'SOCKET' => 1, + 'SONAME' => 1, 'SOUNDS' => 1, 'SOURCE' => 1, 'STARTS' => 1, 'STATUS' => 1, + 'STRING' => 1, 'TABLES' => 1, 'ACCOUNT' => 1, 'AGAINST' => 1, 'ANALYSE' => 1, 'CHANGED' => 1, 'CHANNEL' => 1, - 'CHARSET' => 1, 'COLUMNS' => 1, 'COMMENT' => 1, 'COMPACT' => 1, 'CONTEXT' => 1, - 'CURRENT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1, 'DYNAMIC' => 1, - 'ENGINES' => 1, 'EXECUTE' => 1, 'FOLLOWS' => 1, 'GENERAL' => 1, 'HANDLER' => 1, - 'INDEXES' => 1, 'INSTALL' => 1, 'INVOKER' => 1, 'LOGFILE' => 1, 'MIGRATE' => 1, - 'NO_WAIT' => 1, 'OPTIONS' => 1, 'PARTIAL' => 1, 'PLUGINS' => 1, 'POLYGON' => 1, - 'PREPARE' => 1, 'PROFILE' => 1, 'QUARTER' => 1, 'REBUILD' => 1, 'RECOVER' => 1, - 'RESTORE' => 1, 'RETURNS' => 1, 'REVERSE' => 1, 'ROUTINE' => 1, 'SESSION' => 1, - 'STACKED' => 1, 'STORAGE' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1, 'UNICODE' => 1, - 'UNKNOWN' => 1, 'UPGRADE' => 1, 'USE_FRM' => 1, 'WITHOUT' => 1, 'WRAPPER' => 1, - 'CASCADED' => 1, 'CHECKSUM' => 1, 'COALESCE' => 1, 'CONTAINS' => 1, - 'DATAFILE' => 1, 'DUMPFILE' => 1, 'EXCHANGE' => 1, 'EXTENDED' => 1, - 'FUNCTION' => 1, 'GEOMETRY' => 1, 'LANGUAGE' => 1, 'MAX_ROWS' => 1, - 'MAX_SIZE' => 1, 'MIN_ROWS' => 1, 'NATIONAL' => 1, 'NVARCHAR' => 1, - 'PASSWORD' => 1, 'PRECEDES' => 1, 'PRESERVE' => 1, 'PROFILES' => 1, - 'REDOFILE' => 1, 'RELAYLOG' => 1, 'ROLLBACK' => 1, 'SCHEDULE' => 1, - 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1, 'SWITCHES' => 1, - 'TRIGGERS' => 1, 'TRUNCATE' => 1, 'UNDOFILE' => 1, 'WARNINGS' => 1, - 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COLLATION' => 1, 'COMMITTED' => 1, - 'DIRECTORY' => 1, 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, - 'ISOLATION' => 1, 'NODEGROUP' => 1, 'PACK_KEYS' => 1, 'READ_ONLY' => 1, - 'REDUNDANT' => 1, 'ROW_COUNT' => 1, 'SAVEPOINT' => 1, 'SQL_CACHE' => 1, - 'TEMPORARY' => 1, 'TEMPTABLE' => 1, 'UNDEFINED' => 1, 'UNINSTALL' => 1, - 'VARIABLES' => 1, + 'COLUMNS' => 1, 'COMMENT' => 1, 'COMPACT' => 1, 'CONTEXT' => 1, 'CURRENT' => 1, + 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1, 'DYNAMIC' => 1, 'ENGINES' => 1, + 'EXECUTE' => 1, 'FOLLOWS' => 1, 'GENERAL' => 1, 'HANDLER' => 1, 'INDEXES' => 1, + 'INSTALL' => 1, 'INVOKER' => 1, 'LOGFILE' => 1, 'MIGRATE' => 1, 'NO_WAIT' => 1, + 'OPTIONS' => 1, 'PARTIAL' => 1, 'PLUGINS' => 1, 'PREPARE' => 1, 'PROFILE' => 1, + 'REBUILD' => 1, 'RECOVER' => 1, 'RESTORE' => 1, 'RETURNS' => 1, 'ROUTINE' => 1, + 'SESSION' => 1, 'STACKED' => 1, 'STORAGE' => 1, 'SUBJECT' => 1, 'SUSPEND' => 1, + 'UNICODE' => 1, 'UNKNOWN' => 1, 'UPGRADE' => 1, 'USE_FRM' => 1, 'WITHOUT' => 1, + 'WRAPPER' => 1, + 'CASCADED' => 1, 'CHECKSUM' => 1, 'DATAFILE' => 1, 'DUMPFILE' => 1, + 'EXCHANGE' => 1, 'EXTENDED' => 1, 'FUNCTION' => 1, 'GEOMETRY' => 1, + 'LANGUAGE' => 1, 'MAX_ROWS' => 1, 'MAX_SIZE' => 1, 'MIN_ROWS' => 1, + 'NATIONAL' => 1, 'NVARCHAR' => 1, 'PRECEDES' => 1, 'PRESERVE' => 1, + 'PROFILES' => 1, 'REDOFILE' => 1, 'RELAYLOG' => 1, 'ROLLBACK' => 1, + 'SCHEDULE' => 1, 'SECURITY' => 1, 'SHUTDOWN' => 1, 'SNAPSHOT' => 1, + 'SWITCHES' => 1, 'TRIGGERS' => 1, 'UNDOFILE' => 1, 'WARNINGS' => 1, + 'AGGREGATE' => 1, 'ALGORITHM' => 1, 'COMMITTED' => 1, 'DIRECTORY' => 1, + 'DUPLICATE' => 1, 'EXPANSION' => 1, 'IO_THREAD' => 1, 'ISOLATION' => 1, + 'NODEGROUP' => 1, 'PACK_KEYS' => 1, 'READ_ONLY' => 1, 'REDUNDANT' => 1, + 'SAVEPOINT' => 1, 'SQL_CACHE' => 1, 'TEMPORARY' => 1, 'TEMPTABLE' => 1, + 'UNDEFINED' => 1, 'UNINSTALL' => 1, 'VARIABLES' => 1, 'COMPLETION' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1, - 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'GET_FORMAT' => 1, 'IDENTIFIED' => 1, - 'LINESTRING' => 1, 'MASTER_SSL' => 1, 'MULTIPOINT' => 1, 'NDBCLUSTER' => 1, - 'PARTITIONS' => 1, 'PLUGIN_DIR' => 1, 'PRIVILEGES' => 1, 'REORGANIZE' => 1, - 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, 'TABLESPACE' => 1, - 'TABLE_NAME' => 1, 'VALIDATION' => 1, + 'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'IDENTIFIED' => 1, 'MASTER_SSL' => 1, + 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PLUGIN_DIR' => 1, 'PRIVILEGES' => 1, + 'REORGANIZE' => 1, 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, + 'TABLESPACE' => 1, 'TABLE_NAME' => 1, 'VALIDATION' => 1, 'COLUMN_NAME' => 1, 'COMPRESSION' => 1, 'CURSOR_NAME' => 1, 'DIAGNOSTICS' => 1, 'EXTENT_SIZE' => 1, 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1, - 'MICROSECOND' => 1, 'MYSQL_ERRNO' => 1, 'NONBLOCKING' => 1, 'PROCESSLIST' => 1, - 'REPLICATION' => 1, 'SCHEMA_NAME' => 1, 'SQL_TSI_DAY' => 1, 'TRANSACTION' => 1, - 'UNCOMMITTED' => 1, + 'MYSQL_ERRNO' => 1, 'NONBLOCKING' => 1, 'PROCESSLIST' => 1, 'REPLICATION' => 1, + 'SCHEMA_NAME' => 1, 'SQL_TSI_DAY' => 1, 'TRANSACTION' => 1, 'UNCOMMITTED' => 1, 'CATALOG_NAME' => 1, 'CLASS_ORIGIN' => 1, 'DEFAULT_AUTH' => 1, 'DES_KEY_FILE' => 1, 'INITIAL_SIZE' => 1, 'MASTER_DELAY' => 1, - 'MESSAGE_TEXT' => 1, 'MULTIPOLYGON' => 1, 'OLD_PASSWORD' => 1, - 'PARTITIONING' => 1, 'RELAY_THREAD' => 1, 'SERIALIZABLE' => 1, - 'SQL_NO_CACHE' => 1, 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1, - 'SQL_TSI_YEAR' => 1, 'SUBPARTITION' => 1, 'TIMESTAMPADD' => 1, + 'MESSAGE_TEXT' => 1, 'PARTITIONING' => 1, 'RELAY_THREAD' => 1, + 'SERIALIZABLE' => 1, 'SQL_NO_CACHE' => 1, 'SQL_TSI_HOUR' => 1, + 'SQL_TSI_WEEK' => 1, 'SQL_TSI_YEAR' => 1, 'SUBPARTITION' => 1, 'COLUMN_FORMAT' => 1, 'INSERT_METHOD' => 1, 'MASTER_SSL_CA' => 1, 'RELAY_LOG_POS' => 1, 'SQL_TSI_MONTH' => 1, 'SUBPARTITIONS' => 1, - 'TIMESTAMPDIFF' => 1, 'WEIGHT_STRING' => 1, 'AUTO_INCREMENT' => 1, 'AVG_ROW_LENGTH' => 1, 'KEY_BLOCK_SIZE' => 1, 'MASTER_LOG_POS' => 1, 'MASTER_SSL_CRL' => 1, 'MASTER_SSL_KEY' => 1, 'RELAY_LOG_FILE' => 1, 'SQL_TSI_MINUTE' => 1, 'SQL_TSI_SECOND' => 1, 'TABLE_CHECKSUM' => 1, 'USER_RESOURCES' => 1, 'AUTOEXTEND_SIZE' => 1, 'CONSTRAINT_NAME' => 1, 'DELAY_KEY_WRITE' => 1, 'FILE_BLOCK_SIZE' => 1, 'MASTER_LOG_FILE' => 1, 'MASTER_PASSWORD' => 1, - 'MASTER_SSL_CERT' => 1, 'MULTILINESTRING' => 1, 'PARSE_GCOL_EXPR' => 1, - 'REPLICATE_DO_DB' => 1, 'SQL_AFTER_GTIDS' => 1, 'SQL_TSI_QUARTER' => 1, - 'SUBCLASS_ORIGIN' => 1, + 'MASTER_SSL_CERT' => 1, 'PARSE_GCOL_EXPR' => 1, 'REPLICATE_DO_DB' => 1, + 'SQL_AFTER_GTIDS' => 1, 'SQL_TSI_QUARTER' => 1, 'SUBCLASS_ORIGIN' => 1, 'MASTER_SERVER_ID' => 1, 'REDO_BUFFER_SIZE' => 1, 'SQL_BEFORE_GTIDS' => 1, 'STATS_PERSISTENT' => 1, 'UNDO_BUFFER_SIZE' => 1, 'CONSTRAINT_SCHEMA' => 1, 'GROUP_REPLICATION' => 1, 'IGNORE_SERVER_IDS' => 1, 'MASTER_SSL_CAPATH' => 1, 'MASTER_SSL_CIPHER' => 1, 'RETURNED_SQLSTATE' => 1, 'SQL_BUFFER_RESULT' => 1, 'STATS_AUTO_RECALC' => 1, - 'CONSTRAINT_CATALOG' => 1, 'GEOMETRYCOLLECTION' => 1, 'MASTER_RETRY_COUNT' => 1, - 'MASTER_SSL_CRLPATH' => 1, 'MAX_STATEMENT_TIME' => 1, 'REPLICATE_DO_TABLE' => 1, - 'SQL_AFTER_MTS_GAPS' => 1, 'STATS_SAMPLE_PAGES' => 1, + 'CONSTRAINT_CATALOG' => 1, 'MASTER_RETRY_COUNT' => 1, 'MASTER_SSL_CRLPATH' => 1, + 'MAX_STATEMENT_TIME' => 1, 'REPLICATE_DO_TABLE' => 1, 'SQL_AFTER_MTS_GAPS' => 1, + 'STATS_SAMPLE_PAGES' => 1, 'REPLICATE_IGNORE_DB' => 1, 'MASTER_AUTO_POSITION' => 1, 'MASTER_CONNECT_RETRY' => 1, 'MAX_QUERIES_PER_HOUR' => 1, 'MAX_UPDATES_PER_HOUR' => 1, @@ -132,55 +123,51 @@ class ContextMySql50700 extends Context 'MAX_CONNECTIONS_PER_HOUR' => 1, 'REPLICATE_WILD_IGNORE_TABLE' => 1, - 'AS' => 3, 'BY' => 3, 'IF' => 3, 'IN' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, - 'TO' => 3, + 'AS' => 3, 'BY' => 3, 'IS' => 3, 'ON' => 3, 'OR' => 3, 'TO' => 3, 'ADD' => 3, 'ALL' => 3, 'AND' => 3, 'ASC' => 3, 'DEC' => 3, 'DIV' => 3, - 'FOR' => 3, 'GET' => 3, 'MOD' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, - 'SSL' => 3, 'USE' => 3, 'XOR' => 3, + 'FOR' => 3, 'GET' => 3, 'NOT' => 3, 'OUT' => 3, 'SQL' => 3, 'SSL' => 3, + 'USE' => 3, 'XOR' => 3, 'BOTH' => 3, 'CALL' => 3, 'CASE' => 3, 'DESC' => 3, 'DROP' => 3, 'DUAL' => 3, 'EACH' => 3, 'ELSE' => 3, 'EXIT' => 3, 'FROM' => 3, 'INT1' => 3, 'INT2' => 3, 'INT3' => 3, 'INT4' => 3, 'INT8' => 3, 'INTO' => 3, 'JOIN' => 3, 'KEYS' => 3, - 'KILL' => 3, 'LEFT' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, - 'LOOP' => 3, 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, - 'UNDO' => 3, 'WHEN' => 3, 'WITH' => 3, + 'KILL' => 3, 'LIKE' => 3, 'LOAD' => 3, 'LOCK' => 3, 'LONG' => 3, 'LOOP' => 3, + 'NULL' => 3, 'READ' => 3, 'SHOW' => 3, 'THEN' => 3, 'TRUE' => 3, 'UNDO' => 3, + 'WHEN' => 3, 'WITH' => 3, 'ALTER' => 3, 'CHECK' => 3, 'CROSS' => 3, 'FALSE' => 3, 'FETCH' => 3, 'FORCE' => 3, 'GRANT' => 3, 'GROUP' => 3, 'INNER' => 3, 'INOUT' => 3, 'LEAVE' => 3, 'LIMIT' => 3, 'LINES' => 3, 'MATCH' => 3, 'ORDER' => 3, - 'OUTER' => 3, 'PURGE' => 3, 'RANGE' => 3, 'READS' => 3, 'RIGHT' => 3, - 'RLIKE' => 3, 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, - 'WHERE' => 3, 'WHILE' => 3, 'WRITE' => 3, + 'OUTER' => 3, 'PURGE' => 3, 'RANGE' => 3, 'READS' => 3, 'RLIKE' => 3, + 'TABLE' => 3, 'UNION' => 3, 'USAGE' => 3, 'USING' => 3, 'WHERE' => 3, + 'WHILE' => 3, 'WRITE' => 3, 'BEFORE' => 3, 'CHANGE' => 3, 'COLUMN' => 3, 'CREATE' => 3, 'CURSOR' => 3, 'DELETE' => 3, 'ELSEIF' => 3, 'EXISTS' => 3, 'FLOAT4' => 3, 'FLOAT8' => 3, - 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'INSERT' => 3, 'LINEAR' => 3, - 'OPTION' => 3, 'REGEXP' => 3, 'RENAME' => 3, 'REPEAT' => 3, 'RETURN' => 3, - 'REVOKE' => 3, 'SCHEMA' => 3, 'SELECT' => 3, 'SIGNAL' => 3, 'STORED' => 3, - 'UNLOCK' => 3, 'UPDATE' => 3, 'VALUES' => 3, - 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'CONVERT' => 3, - 'DECLARE' => 3, 'DEFAULT' => 3, 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, - 'FOREIGN' => 3, 'ITERATE' => 3, 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, - 'PRIMARY' => 3, 'RELEASE' => 3, 'REPLACE' => 3, 'REQUIRE' => 3, 'SCHEMAS' => 3, - 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3, 'VIRTUAL' => 3, - 'CONTINUE' => 3, 'DATABASE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, - 'DISTINCT' => 3, 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MAXVALUE' => 3, - 'MODIFIES' => 3, 'OPTIMIZE' => 3, 'RESIGNAL' => 3, 'RESTRICT' => 3, - 'SPECIFIC' => 3, 'SQLSTATE' => 3, 'STARTING' => 3, 'TRAILING' => 3, - 'UNSIGNED' => 3, 'UTC_DATE' => 3, 'UTC_TIME' => 3, 'ZEROFILL' => 3, - 'CONDITION' => 3, 'DATABASES' => 3, 'GENERATED' => 3, 'LOCALTIME' => 3, - 'MIDDLEINT' => 3, 'PARTITION' => 3, 'PRECISION' => 3, 'PROCEDURE' => 3, - 'SENSITIVE' => 3, 'SEPARATOR' => 3, + 'HAVING' => 3, 'IGNORE' => 3, 'INFILE' => 3, 'LINEAR' => 3, 'OPTION' => 3, + 'REGEXP' => 3, 'RENAME' => 3, 'RETURN' => 3, 'REVOKE' => 3, 'SELECT' => 3, + 'SIGNAL' => 3, 'STORED' => 3, 'UNLOCK' => 3, 'UPDATE' => 3, + 'ANALYZE' => 3, 'BETWEEN' => 3, 'CASCADE' => 3, 'COLLATE' => 3, 'DECLARE' => 3, + 'DELAYED' => 3, 'ESCAPED' => 3, 'EXPLAIN' => 3, 'FOREIGN' => 3, 'ITERATE' => 3, + 'LEADING' => 3, 'NATURAL' => 3, 'OUTFILE' => 3, 'PRIMARY' => 3, 'RELEASE' => 3, + 'REQUIRE' => 3, 'SCHEMAS' => 3, 'SPATIAL' => 3, 'TRIGGER' => 3, 'VARYING' => 3, + 'VIRTUAL' => 3, + 'CONTINUE' => 3, 'DAY_HOUR' => 3, 'DESCRIBE' => 3, 'DISTINCT' => 3, + 'ENCLOSED' => 3, 'FULLTEXT' => 3, 'MAXVALUE' => 3, 'MODIFIES' => 3, + 'OPTIMIZE' => 3, 'RESIGNAL' => 3, 'RESTRICT' => 3, 'SPECIFIC' => 3, + 'SQLSTATE' => 3, 'STARTING' => 3, 'TRAILING' => 3, 'UNSIGNED' => 3, + 'ZEROFILL' => 3, + 'CONDITION' => 3, 'DATABASES' => 3, 'GENERATED' => 3, 'MIDDLEINT' => 3, + 'PARTITION' => 3, 'PRECISION' => 3, 'PROCEDURE' => 3, 'SENSITIVE' => 3, + 'SEPARATOR' => 3, 'ACCESSIBLE' => 3, 'ASENSITIVE' => 3, 'CONSTRAINT' => 3, 'DAY_MINUTE' => 3, 'DAY_SECOND' => 3, 'OPTIONALLY' => 3, 'READ_WRITE' => 3, 'REFERENCES' => 3, 'SQLWARNING' => 3, 'TERMINATED' => 3, 'YEAR_MONTH' => 3, 'DISTINCTROW' => 3, 'HOUR_MINUTE' => 3, 'HOUR_SECOND' => 3, 'INSENSITIVE' => 3, 'MASTER_BIND' => 3, - 'CURRENT_DATE' => 3, 'CURRENT_TIME' => 3, 'CURRENT_USER' => 3, 'LOW_PRIORITY' => 3, 'SQLEXCEPTION' => 3, 'VARCHARACTER' => 3, 'DETERMINISTIC' => 3, 'HIGH_PRIORITY' => 3, 'MINUTE_SECOND' => 3, - 'STRAIGHT_JOIN' => 3, 'UTC_TIMESTAMP' => 3, - 'IO_AFTER_GTIDS' => 3, 'LOCALTIMESTAMP' => 3, 'SQL_BIG_RESULT' => 3, + 'STRAIGHT_JOIN' => 3, + 'IO_AFTER_GTIDS' => 3, 'SQL_BIG_RESULT' => 3, 'DAY_MICROSECOND' => 3, 'IO_BEFORE_GTIDS' => 3, 'OPTIMIZER_COSTS' => 3, 'HOUR_MICROSECOND' => 3, 'SQL_SMALL_RESULT' => 3, - 'CURRENT_TIMESTAMP' => 3, 'MINUTE_MICROSECOND' => 3, 'NO_WRITE_TO_BINLOG' => 3, 'SECOND_MICROSECOND' => 3, 'SQL_CALC_FOUND_ROWS' => 3, 'MASTER_SSL_VERIFY_SERVER_CERT' => 3, @@ -195,19 +182,18 @@ class ContextMySql50700 extends Context 'GROUP BY' => 7, 'ORDER BY' => 7, 'XML' => 9, - 'DATE' => 9, 'ENUM' => 9, 'TEXT' => 9, 'TIME' => 9, 'YEAR' => 9, + 'ENUM' => 9, 'TEXT' => 9, 'ARRAY' => 9, 'BOOLEAN' => 9, 'DATETIME' => 9, 'MULTISET' => 9, - 'TIMESTAMP' => 9, 'INT' => 11, 'SET' => 11, - 'BLOB' => 11, 'CHAR' => 11, 'REAL' => 11, + 'BLOB' => 11, 'REAL' => 11, 'FLOAT' => 11, 'BIGINT' => 11, 'BINARY' => 11, 'DOUBLE' => 11, 'DECIMAL' => 11, 'INTEGER' => 11, 'NUMERIC' => 11, 'TINYINT' => 11, 'VARCHAR' => 11, - 'INTERVAL' => 11, 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, - 'TINYBLOB' => 11, 'TINYTEXT' => 11, + 'LONGBLOB' => 11, 'LONGTEXT' => 11, 'SMALLINT' => 11, 'TINYBLOB' => 11, + 'TINYTEXT' => 11, 'CHARACTER' => 11, 'MEDIUMINT' => 11, 'VARBINARY' => 11, 'MEDIUMBLOB' => 11, 'MEDIUMTEXT' => 11, @@ -224,5 +210,130 @@ class ContextMySql50700 extends Context 'SPATIAL INDEX' => 21, 'FULLTEXT INDEX' => 21, + 'X' => 33, 'Y' => 33, + 'LN' => 33, 'PI' => 33, + 'ABS' => 33, 'AVG' => 33, 'BIN' => 33, 'COS' => 33, 'COT' => 33, 'DAY' => 33, + 'ELT' => 33, 'EXP' => 33, 'HEX' => 33, 'LOG' => 33, 'MAX' => 33, 'MD5' => 33, + 'MID' => 33, 'MIN' => 33, 'NOW' => 33, 'OCT' => 33, 'ORD' => 33, 'POW' => 33, + 'SHA' => 33, 'SIN' => 33, 'STD' => 33, 'SUM' => 33, 'TAN' => 33, + 'ACOS' => 33, 'AREA' => 33, 'ASIN' => 33, 'ATAN' => 33, 'CAST' => 33, 'CEIL' => 33, + 'CONV' => 33, 'HOUR' => 33, 'LOG2' => 33, 'LPAD' => 33, 'RAND' => 33, 'RPAD' => 33, + 'SHA1' => 33, 'SHA2' => 33, 'SIGN' => 33, 'SQRT' => 33, 'SRID' => 33, 'ST_X' => 33, + 'ST_Y' => 33, 'TRIM' => 33, 'USER' => 33, 'UUID' => 33, 'WEEK' => 33, + 'ASCII' => 33, 'ASWKB' => 33, 'ASWKT' => 33, 'ATAN2' => 33, 'COUNT' => 33, + 'CRC32' => 33, 'FIELD' => 33, 'FLOOR' => 33, 'INSTR' => 33, 'LCASE' => 33, + 'LEAST' => 33, 'LOG10' => 33, 'LOWER' => 33, 'LTRIM' => 33, 'MONTH' => 33, + 'POINT' => 33, 'POWER' => 33, 'QUOTE' => 33, 'ROUND' => 33, 'RTRIM' => 33, + 'SLEEP' => 33, 'SPACE' => 33, 'UCASE' => 33, 'UNHEX' => 33, 'UPPER' => 33, + 'ASTEXT' => 33, 'BIT_OR' => 33, 'BUFFER' => 33, 'CONCAT' => 33, 'DECODE' => 33, + 'ENCODE' => 33, 'EQUALS' => 33, 'FORMAT' => 33, 'IFNULL' => 33, 'ISNULL' => 33, + 'LENGTH' => 33, 'LOCATE' => 33, 'MINUTE' => 33, 'NULLIF' => 33, 'POINTN' => 33, + 'SECOND' => 33, 'STDDEV' => 33, 'STRCMP' => 33, 'SUBSTR' => 33, 'WITHIN' => 33, + 'ADDDATE' => 33, 'ADDTIME' => 33, 'BIT_AND' => 33, 'BIT_XOR' => 33, 'CEILING' => 33, + 'CHARSET' => 33, 'CROSSES' => 33, 'CURDATE' => 33, 'CURTIME' => 33, 'DAYNAME' => 33, + 'DEGREES' => 33, 'ENCRYPT' => 33, 'EXTRACT' => 33, 'GLENGTH' => 33, 'ISEMPTY' => 33, + 'IS_IPV4' => 33, 'IS_IPV6' => 33, 'POLYGON' => 33, 'QUARTER' => 33, 'RADIANS' => 33, + 'REVERSE' => 33, 'SOUNDEX' => 33, 'ST_AREA' => 33, 'ST_SRID' => 33, 'SUBDATE' => 33, + 'SUBTIME' => 33, 'SYSDATE' => 33, 'TOUCHES' => 33, 'TO_DAYS' => 33, 'VAR_POP' => 33, + 'VERSION' => 33, 'WEEKDAY' => 33, + 'ASBINARY' => 33, 'CENTROID' => 33, 'COALESCE' => 33, 'COMPRESS' => 33, + 'CONTAINS' => 33, 'DATEDIFF' => 33, 'DATE_ADD' => 33, 'DATE_SUB' => 33, + 'DISJOINT' => 33, 'DISTANCE' => 33, 'ENDPOINT' => 33, 'ENVELOPE' => 33, + 'GET_LOCK' => 33, 'GREATEST' => 33, 'ISCLOSED' => 33, 'ISSIMPLE' => 33, + 'MAKEDATE' => 33, 'MAKETIME' => 33, 'MAKE_SET' => 33, 'MBREQUAL' => 33, + 'OVERLAPS' => 33, 'PASSWORD' => 33, 'POSITION' => 33, 'ST_ASWKB' => 33, + 'ST_ASWKT' => 33, 'ST_UNION' => 33, 'TIMEDIFF' => 33, 'TRUNCATE' => 33, + 'VARIANCE' => 33, 'VAR_SAMP' => 33, 'YEARWEEK' => 33, + 'ANY_VALUE' => 33, 'BENCHMARK' => 33, 'BIT_COUNT' => 33, 'COLLATION' => 33, + 'CONCAT_WS' => 33, 'DAYOFWEEK' => 33, 'DAYOFYEAR' => 33, 'DIMENSION' => 33, + 'FROM_DAYS' => 33, 'GEOMETRYN' => 33, 'INET_ATON' => 33, 'INET_NTOA' => 33, + 'LOAD_FILE' => 33, 'MBRCOVERS' => 33, 'MBREQUALS' => 33, 'MBRWITHIN' => 33, + 'MONTHNAME' => 33, 'NUMPOINTS' => 33, 'ROW_COUNT' => 33, 'ST_ASTEXT' => 33, + 'ST_BUFFER' => 33, 'ST_EQUALS' => 33, 'ST_LENGTH' => 33, 'ST_POINTN' => 33, + 'ST_WITHIN' => 33, 'SUBSTRING' => 33, 'TO_BASE64' => 33, 'UPDATEXML' => 33, + 'BIT_LENGTH' => 33, 'CONVERT_TZ' => 33, 'CONVEXHULL' => 33, 'DAYOFMONTH' => 33, + 'EXPORT_SET' => 33, 'FOUND_ROWS' => 33, 'GET_FORMAT' => 33, 'INET6_ATON' => 33, + 'INET6_NTOA' => 33, 'INTERSECTS' => 33, 'LINESTRING' => 33, 'MBRTOUCHES' => 33, + 'MULTIPOINT' => 33, 'NAME_CONST' => 33, 'PERIOD_ADD' => 33, 'STARTPOINT' => 33, + 'STDDEV_POP' => 33, 'ST_CROSSES' => 33, 'ST_GEOHASH' => 33, 'ST_ISEMPTY' => 33, + 'ST_ISVALID' => 33, 'ST_TOUCHES' => 33, 'TO_SECONDS' => 33, 'UNCOMPRESS' => 33, + 'UUID_SHORT' => 33, 'WEEKOFYEAR' => 33, + 'AES_DECRYPT' => 33, 'AES_ENCRYPT' => 33, 'CHAR_LENGTH' => 33, 'DATE_FORMAT' => 33, + 'DES_DECRYPT' => 33, 'DES_ENCRYPT' => 33, 'FIND_IN_SET' => 33, 'FROM_BASE64' => 33, + 'GEOMFROMWKB' => 33, 'GTID_SUBSET' => 33, 'LINEFROMWKB' => 33, 'MBRCONTAINS' => 33, + 'MBRDISJOINT' => 33, 'MBROVERLAPS' => 33, 'MICROSECOND' => 33, 'PERIOD_DIFF' => 33, + 'POLYFROMWKB' => 33, 'SEC_TO_TIME' => 33, 'STDDEV_SAMP' => 33, 'STR_TO_DATE' => 33, + 'ST_ASBINARY' => 33, 'ST_CENTROID' => 33, 'ST_CONTAINS' => 33, 'ST_DISJOINT' => 33, + 'ST_DISTANCE' => 33, 'ST_ENDPOINT' => 33, 'ST_ENVELOPE' => 33, 'ST_ISCLOSED' => 33, + 'ST_ISSIMPLE' => 33, 'ST_OVERLAPS' => 33, 'ST_SIMPLIFY' => 33, 'ST_VALIDATE' => 33, + 'SYSTEM_USER' => 33, 'TIME_FORMAT' => 33, 'TIME_TO_SEC' => 33, + 'COERCIBILITY' => 33, 'EXTERIORRING' => 33, 'EXTRACTVALUE' => 33, + 'GEOMETRYTYPE' => 33, 'GEOMFROMTEXT' => 33, 'GROUP_CONCAT' => 33, + 'IS_FREE_LOCK' => 33, 'IS_USED_LOCK' => 33, 'LINEFROMTEXT' => 33, + 'MBRCOVEREDBY' => 33, 'MLINEFROMWKB' => 33, 'MPOLYFROMWKB' => 33, + 'MULTIPOLYGON' => 33, 'OCTET_LENGTH' => 33, 'OLD_PASSWORD' => 33, + 'POINTFROMWKB' => 33, 'POLYFROMTEXT' => 33, 'RANDOM_BYTES' => 33, + 'RELEASE_LOCK' => 33, 'SESSION_USER' => 33, 'ST_ASGEOJSON' => 33, + 'ST_DIMENSION' => 33, 'ST_GEOMETRYN' => 33, 'ST_NUMPOINTS' => 33, + 'TIMESTAMPADD' => 33, + 'CONNECTION_ID' => 33, 'FROM_UNIXTIME' => 33, 'GTID_SUBTRACT' => 33, + 'INTERIORRINGN' => 33, 'MBRINTERSECTS' => 33, 'MLINEFROMTEXT' => 33, + 'MPOINTFROMWKB' => 33, 'MPOLYFROMTEXT' => 33, 'NUMGEOMETRIES' => 33, + 'POINTFROMTEXT' => 33, 'ST_CONVEXHULL' => 33, 'ST_DIFFERENCE' => 33, + 'ST_INTERSECTS' => 33, 'ST_STARTPOINT' => 33, 'TIMESTAMPDIFF' => 33, + 'WEIGHT_STRING' => 33, + 'IS_IPV4_COMPAT' => 33, 'IS_IPV4_MAPPED' => 33, 'LAST_INSERT_ID' => 33, + 'MPOINTFROMTEXT' => 33, 'POLYGONFROMWKB' => 33, 'ST_GEOMFROMWKB' => 33, + 'ST_LINEFROMWKB' => 33, 'ST_POLYFROMWKB' => 33, 'UNIX_TIMESTAMP' => 33, + 'GEOMCOLLFROMWKB' => 33, 'MASTER_POS_WAIT' => 33, 'MULTILINESTRING' => 33, + 'POLYGONFROMTEXT' => 33, 'ST_EXTERIORRING' => 33, 'ST_GEOMETRYTYPE' => 33, + 'ST_GEOMFROMTEXT' => 33, 'ST_INTERSECTION' => 33, 'ST_LINEFROMTEXT' => 33, + 'ST_MAKEENVELOPE' => 33, 'ST_MLINEFROMWKB' => 33, 'ST_MPOLYFROMWKB' => 33, + 'ST_POINTFROMWKB' => 33, 'ST_POLYFROMTEXT' => 33, 'SUBSTRING_INDEX' => 33, + 'CHARACTER_LENGTH' => 33, 'GEOMCOLLFROMTEXT' => 33, 'GEOMETRYFROMTEXT' => 33, + 'NUMINTERIORRINGS' => 33, 'ST_INTERIORRINGN' => 33, 'ST_MLINEFROMTEXT' => 33, + 'ST_MPOINTFROMWKB' => 33, 'ST_MPOLYFROMTEXT' => 33, 'ST_NUMGEOMETRIES' => 33, + 'ST_POINTFROMTEXT' => 33, 'ST_SYMDIFFERENCE' => 33, + 'LINESTRINGFROMWKB' => 33, 'MULTIPOINTFROMWKB' => 33, 'RELEASE_ALL_LOCKS' => 33, + 'ST_LATFROMGEOHASH' => 33, 'ST_MPOINTFROMTEXT' => 33, 'ST_POLYGONFROMWKB' => 33, + 'GEOMETRYCOLLECTION' => 33, 'MULTIPOINTFROMTEXT' => 33, 'ST_BUFFER_STRATEGY' => 33, + 'ST_DISTANCE_SPHERE' => 33, 'ST_GEOMCOLLFROMTXT' => 33, 'ST_GEOMCOLLFROMWKB' => 33, + 'ST_GEOMFROMGEOJSON' => 33, 'ST_LONGFROMGEOHASH' => 33, 'ST_POLYGONFROMTEXT' => 33, + 'MULTIPOLYGONFROMWKB' => 33, 'ST_GEOMCOLLFROMTEXT' => 33, 'ST_GEOMETRYFROMTEXT' => 33, + 'ST_NUMINTERIORRINGS' => 33, 'ST_POINTFROMGEOHASH' => 33, 'UNCOMPRESSED_LENGTH' => 33, + 'MULTIPOLYGONFROMTEXT' => 33, 'ST_LINESTRINGFROMWKB' => 33, + 'ST_MULTIPOINTFROMWKB' => 33, + 'ST_MULTIPOINTFROMTEXT' => 33, + 'MULTILINESTRINGFROMWKB' => 33, 'ST_MULTIPOLYGONFROMWKB' => 33, + 'MULTILINESTRINGFROMTEXT' => 33, 'ST_MULTIPOLYGONFROMTEXT' => 33, + 'GEOMETRYCOLLECTIONFROMWKB' => 33, 'ST_MULTILINESTRINGFROMWKB' => 33, + 'GEOMETRYCOLLECTIONFROMTEXT' => 33, 'ST_MULTILINESTRINGFROMTEXT' => 33, + 'VALIDATE_PASSWORD_STRENGTH' => 33, 'WAIT_FOR_EXECUTED_GTID_SET' => 33, + 'ST_GEOMETRYCOLLECTIONFROMWKB' => 33, + 'ST_GEOMETRYCOLLECTIONFROMTEXT' => 33, + 'WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS' => 33, + + 'IF' => 35, 'IN' => 35, + 'MOD' => 35, + 'LEFT' => 35, + 'RIGHT' => 35, + 'INSERT' => 35, 'REPEAT' => 35, 'SCHEMA' => 35, 'VALUES' => 35, + 'CONVERT' => 35, 'DEFAULT' => 35, 'REPLACE' => 35, + 'DATABASE' => 35, 'UTC_DATE' => 35, 'UTC_TIME' => 35, + 'LOCALTIME' => 35, + 'CURRENT_DATE' => 35, 'CURRENT_TIME' => 35, 'CURRENT_USER' => 35, + 'UTC_TIMESTAMP' => 35, + 'LOCALTIMESTAMP' => 35, + 'CURRENT_TIMESTAMP' => 35, + + 'NOT IN' => 37, + 'PROCEDURE ANALYSE' => 37, + + 'DATE' => 41, 'TIME' => 41, 'YEAR' => 41, + 'TIMESTAMP' => 41, + + 'CHAR' => 43, + 'INTERVAL' => 43, + ); } diff --git a/libraries/sql-parser/src/Fragments/FieldFragment.php b/libraries/sql-parser/src/Fragments/FieldFragment.php index 4adbba5a73..a45c0fe482 100644 --- a/libraries/sql-parser/src/Fragments/FieldFragment.php +++ b/libraries/sql-parser/src/Fragments/FieldFragment.php @@ -54,6 +54,20 @@ class FieldFragment extends Fragment */ public $alias; + /** + * The name of the function. + * + * @var string + */ + public $function; + + /** + * The type of subquery. + * + * @var string + */ + public $subquery; + /** * @param Parser $parser The parser that serves as context. * @param TokensList $list The list of tokens that are being parsed. @@ -89,6 +103,16 @@ class FieldFragment extends Fragment */ $brackets = 0; + /** + * Keeps track of the previous token. + * Possible values: + * string, if function was previously found; + * true, if open bracket was previously found; + * null, in any other case. + * @var string|bool + */ + $prev = null; + for (; $list->idx < $list->count; ++$list->idx) { /** @@ -121,12 +145,26 @@ class FieldFragment extends Fragment continue; } break; + } else if ($prev === true) { + if ((empty($ret->subquery) && (!empty(Parser::$STATEMENT_PARSERS[$token->value])))) { + // A `(` was previously found and this keyword is the + // beginning of a statement, so this is a subquery. + $ret->subquery = $token->value; + } } } if ($token->type === Token::TYPE_OPERATOR) { if ($token->value === '(') { ++$brackets; + // We don't check to see if `$prev` is `true` (open bracke + // was found before) because the brackets count is one (the + // only bracket we found is this one). + if (($brackets === 1) && (empty($ret->function)) && ($prev !== null) && ($prev !== true)) { + // A function name was previously found and now an open + // bracket, so this is a function call. + $ret->function = $prev; + } $isExpr = true; } elseif ($token->value === ')') { --$brackets; @@ -150,15 +188,24 @@ class FieldFragment extends Fragment } if ($alias) { + // An alias is expected (the keyword `AS` was previously found). $ret->alias = $token->value; $alias = 0; } else { if (!$isExpr) { if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '.')) { + // Found a `.` which means we expect a column name and + // the column name we parsed is actually the table name + // and the table name is actually a database name. + if ((!empty($ret->database)) || ($period)) { + $parser->error('Unexpected dot.', $token); + } $ret->database = $ret->table; $ret->table = $ret->column; $period = true; } else { + // We found the name of a column (or table if column + // field should be skipped; used to parse table names). if (!empty($options['skipColumn'])) { $ret->table = $token->value; } else { @@ -167,6 +214,8 @@ class FieldFragment extends Fragment $period = false; } } else { + // Parsing aliases without `AS` keyword. + // Example: SELECT 'foo' `bar` if ($brackets === 0) { if (($token->type === Token::TYPE_NONE) || ($token->type === Token::TYPE_STRING) || (($token->type === Token::TYPE_SYMBOL) && ($token->flags & Token::FLAG_SYMBOL_BACKTICK)) @@ -178,12 +227,24 @@ class FieldFragment extends Fragment $ret->expr .= $token->token; } + + if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_FUNCTION)) { + $prev = strtoupper($token->value); + } else if (($token->type === Token::TYPE_OPERATOR) || ($token->value === '(')) { + $prev = true; + } else { + $prev = null; + } + } if ($alias === 2) { $parser->error('Alias was expected.'); } + // Whitespaces might be added at the end. + $ret->expr = trim($ret->expr); + if (empty($ret->expr)) { return null; } diff --git a/libraries/sql-parser/src/Fragments/IntoKeyword.php b/libraries/sql-parser/src/Fragments/IntoKeyword.php index 9cf634c427..f5c9592b06 100644 --- a/libraries/sql-parser/src/Fragments/IntoKeyword.php +++ b/libraries/sql-parser/src/Fragments/IntoKeyword.php @@ -20,11 +20,18 @@ class IntoKeyword extends Fragment { /** - * The name of the table. + * Type of target (OUTFILE or SYMBOL). * * @var string */ - public $table; + public $type; + + /** + * The name of the table or file. + * + * @var string + */ + public $name; /** * The name of the columns. @@ -49,11 +56,12 @@ class IntoKeyword extends Fragment * * Below are the states of the parser. * - * 0 ------------------------[ ( ]------------------------> 1 + * 0 -----------------------[ name ]----------------------> 1 + * 0 ---------------------[ OUTFILE ]---------------------> 2 * - * 1 --------------------[ field name ]-------------------> 2 + * 1 ------------------------[ ( ]------------------------> -1 * - * 2 ------------------------[ , ]------------------------> 1 + * 2 ---------------------[ filename ]--------------------> 1 * * @var int */ @@ -77,19 +85,31 @@ class IntoKeyword extends Fragment continue; } - // No keyword is expected. if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { + if (($state === 0) && ($token->value === 'OUTFILE')) { + $ret->type = 'OUTFILE'; + $state = 2; + continue; + } + + // No other keyword is expected. break; } - if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { - $ret->fields = ArrayFragment::parse($parser, $list)->values; + if ($state === 0) { + $ret->name = $token->value; + $state = 1; + } else if ($state === 1) { + if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { + $ret->fields = ArrayFragment::parse($parser, $list)->values; + ++$list->idx; + } + break; + } else if ($state === 2) { + $ret->name = $token->value; ++$list->idx; break; - } else { - $ret->table = $token->value; } - } --$list->idx; diff --git a/libraries/sql-parser/src/Fragments/KeyFragment.php b/libraries/sql-parser/src/Fragments/KeyFragment.php index 11f4caf015..e1ac67908d 100644 --- a/libraries/sql-parser/src/Fragments/KeyFragment.php +++ b/libraries/sql-parser/src/Fragments/KeyFragment.php @@ -54,6 +54,13 @@ class KeyFragment extends Fragment */ public $type; + /** + * The options of this key. + * + * @var OptionsFragment + */ + public $options; + /** * @param Parser $parser The parser that serves as context. * @param TokensList $list The list of tokens that are being parsed. diff --git a/libraries/sql-parser/src/Fragments/LimitKeyword.php b/libraries/sql-parser/src/Fragments/LimitKeyword.php index 6e12b444d0..1e4ae4f3ef 100644 --- a/libraries/sql-parser/src/Fragments/LimitKeyword.php +++ b/libraries/sql-parser/src/Fragments/LimitKeyword.php @@ -31,7 +31,7 @@ class LimitKeyword extends Fragment * * @var int */ - public $row_count; + public $rowCount; /** * @param Parser $parser The parser that serves as context. diff --git a/libraries/sql-parser/src/Fragments/OptionsFragment.php b/libraries/sql-parser/src/Fragments/OptionsFragment.php index dfb4fc98fb..dbd3676f4e 100644 --- a/libraries/sql-parser/src/Fragments/OptionsFragment.php +++ b/libraries/sql-parser/src/Fragments/OptionsFragment.php @@ -139,4 +139,21 @@ class OptionsFragment extends Fragment } return false; } + + /** + * Merges the specified options with these ones. Values with same ID will be + * replaced. + * + * @param array|OptionsFragment $options + * + * @return void + */ + public function merge($options) + { + if (is_array($options)) { + $this->options = array_merge_recursive($this->options, $options); + } else if ($options instanceof OptionsFragment) { + $this->options = array_merge_recursive($this->options, $options->options); + } + } } diff --git a/libraries/sql-parser/src/Parser.php b/libraries/sql-parser/src/Parser.php index a5fe233563..ba0a1440a0 100644 --- a/libraries/sql-parser/src/Parser.php +++ b/libraries/sql-parser/src/Parser.php @@ -23,11 +23,28 @@ class Parser */ public static $STATEMENT_PARSERS = array( + 'EXPLAIN' => 'SqlParser\\Statements\\ExplainStatement', + + // Table Maintenance Statements + // https://dev.mysql.com/doc/refman/5.7/en/table-maintenance-sql.html + 'ANALYZE' => 'SqlParser\\Statements\\AnalyzeStatement', + 'BACKUP' => 'SqlParser\\Statements\\BackupStatement', + 'CHECK' => 'SqlParser\\Statements\\CheckStatement', + 'CHECKSUM' => 'SqlParser\\Statements\\ChecsumStatement', + 'OPTIMIZE' => 'SqlParser\\Statements\\OptimizeStatement', + 'REPAIR' => 'SqlParser\\Statements\\RepairStatement', + 'RESTORE' => 'SqlParser\\Statements\\RestoreStatement', + + // Database Administration Statements + // https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-server-administration.html + 'SET' => '', + 'SHOW' => 'SqlParser\\Statements\\ShowStatement', + // Data Definition Statements. // https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-data-definition.html - 'ALTER' => '', + 'ALTER' => 'SqlParser\\Statements\\AlterStatement', 'CREATE' => 'SqlParser\\Statements\\CreateStatement', - 'DROP' => '', + 'DROP' => 'SqlParser\\Statements\\DropStatement', 'RENAME' => 'SqlParser\\Statements\\RenameStatement', 'TRUNCATE' => '', @@ -56,10 +73,26 @@ class Parser */ public static $KEYWORD_PARSERS = array( + 'ANALYZE' => array( + 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'field' => 'tables', + ), + 'BACKUP' => array( + 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'field' => 'tables', + ), 'CALL' => array( 'class' => 'SqlParser\\Fragments\\CallKeyword', 'field' => 'call', ), + 'CHECK' => array( + 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'field' => 'tables', + ), + 'CHECKSUM' => array( + 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'field' => 'tables', + ), 'FROM' => array( 'class' => 'SqlParser\\Fragments\\FromKeyword', 'field' => 'from', @@ -84,6 +117,10 @@ class Parser 'class' => 'SqlParser\\Fragments\\LimitKeyword', 'field' => 'limit', ), + 'OPTIMIZE' => array( + 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'field' => 'tables', + ), 'ORDER BY' => array( 'class' => 'SqlParser\\Fragments\\OrderKeyword', 'field' => 'order', @@ -92,10 +129,22 @@ class Parser 'class' => 'SqlParser\\Fragments\\ArrayFragment', 'field' => 'partition', ), + 'PROCEDURE' => array( + 'class' => 'SqlParser\\Fragments\\CallKeyword', + 'field' => 'procedure', + ), 'RENAME' => array( 'class' => 'SqlParser\\Fragments\\RenameKeyword', 'field' => 'renames', ), + 'REPAIR' => array( + 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'field' => 'tables', + ), + 'RESTORE' => array( + 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'field' => 'tables', + ), 'SET' => array( 'class' => 'SqlParser\\Fragments\\SetKeyword', 'field' => 'set', @@ -188,17 +237,15 @@ class Parser */ public function parse() { - $tokens = &$this->list->tokens; - $count = &$this->list->count; - $last = &$this->list->idx; + $list = &$this->list; - for (; $last < $count; ++$last) { + for (; $list->idx < $list->count; ++$list->idx) { /** * Token parsed at this moment. * @var Token */ - $token = $tokens[$last]; + $token = $list->tokens[$list->idx]; // Statements can start with keywords only. // Comments, whitespaces, etc. are ignored. @@ -212,7 +259,7 @@ class Parser 'Unrecognized statement type "' . $token->value . '".', $token ); - // TODO: Skip to first delimiter. + $list->getNextOfType(Token::TYPE_DELIMITER); continue; } diff --git a/libraries/sql-parser/src/Statement.php b/libraries/sql-parser/src/Statement.php index 0e57bfd45e..0fa1fc2668 100644 --- a/libraries/sql-parser/src/Statement.php +++ b/libraries/sql-parser/src/Statement.php @@ -5,15 +5,21 @@ namespace SqlParser; use SqlParser\Parser; use SqlParser\Statement; use SqlParser\Token; -use SqlParser\Fragments\CallKeyword; use SqlParser\Fragments\CreateDefFragment; use SqlParser\Fragments\DataTypeFragment; use SqlParser\Fragments\FieldDefFragment; -use SqlParser\Fragments\FromKeyword; use SqlParser\Fragments\OptionsFragment; use SqlParser\Fragments\ParamDefFragment; -use SqlParser\Fragments\RenameKeyword; -use SqlParser\Fragments\SelectKeyword; +use SqlParser\Statements\AlterStatement; +use SqlParser\Statements\BackupStatement; +use SqlParser\Statements\CheckStatement; +use SqlParser\Statements\ChecksumStatement; +use SqlParser\Statements\CreateStatement; +use SqlParser\Statements\ExplainStatement; +use SqlParser\Statements\RenameStatement; +use SqlParser\Statements\RepairStatement; +use SqlParser\Statements\RestoreStatement; +use SqlParser\Statements\ShowStatement; /** * Abstract statement definition. @@ -50,9 +56,8 @@ abstract class Statement */ public function parse(Parser $parser, TokensList $list) { - /** - * Whether otpions were parsed or not. + * Whether options were parsed or not. * For statements that do not have any options this is set to `true` by * default. * @var bool @@ -115,15 +120,15 @@ abstract class Statement continue; } - // Special cases. - if ($token->value === 'CREATE') { + // Special cases: before parsing this keyword. + if ($this instanceof CreateStatement) { ++$list->idx; $this->name = CreateDefFragment::parse($parser, $list); if ($this->options->has('TABLE')) { ++$list->idx; $this->fields = FieldDefFragment::parse($parser, $list); ++$list->idx; - $this->tableOptions = OptionsFragment::parse( + $this->entityOptions = OptionsFragment::parse( $parser, $list, CreateDefFragment::$TABLE_OPTIONS @@ -149,7 +154,7 @@ abstract class Statement } } ++$list->idx; - $this->funcOptions = OptionsFragment::parse( + $this->entityOptions = OptionsFragment::parse( $parser, $list, CreateDefFragment::$FUNC_OPTIONS @@ -167,14 +172,50 @@ abstract class Statement } $class = null; // The statement has been processed here. } - } else if ($token->value === 'RENAME') { + } else if ($this instanceof RenameStatement) { $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'TABLE'); } + // Parsing this keyword. if ($class !== null) { ++$list->idx; // Skipping keyword. $this->$field = $class::parse($parser, $list, array()); } + + // Special cases: after parsing this keyword. + if (($this instanceof BackupStatement) + || ($this instanceof CheckStatement) + || ($this instanceof ChecksumStatement) + || ($this instanceof RepairStatement) + || ($this instanceof RestoreStatement) + ) { + + // The statements mentioned above follow this template: + // `STMT` + // + // First of all, because static::$OPTIONS is set for all of the + // statements above, is going to be parsed first. + // + // There is a parser specified in `Parser::$KEYWORD_PARSERS` + // which parses . + // + // Finally, we pares here and that's all. + ++$list->idx; + $this->options->merge( + OptionsFragment::parse( + $parser, + $list, + static::$OPTIONS + ) + ); + } else if (($this instanceof AlterStatement) + || ($this instanceof ExplainStatement) + || ($this instanceof ShowStatement) + ) { + // TODO: Implement the statements above. + $list->getNextOfType(Token::TYPE_DELIMITER); + ++$list->idx; + } } $this->last = --$list->idx; // Go back to last used token. diff --git a/libraries/sql-parser/src/Statements/AlterStatement.php b/libraries/sql-parser/src/Statements/AlterStatement.php new file mode 100644 index 0000000000..47d34bba12 --- /dev/null +++ b/libraries/sql-parser/src/Statements/AlterStatement.php @@ -0,0 +1,48 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class AlterStatement extends Statement +{ + + /** + * Options of this statement. + * + * @var array + */ + public static $OPTIONS = array( + + 'DATABASE' => 1, + 'EVENT' => 1, + 'FUNCTION' => 1, + 'INDEX' => 1, + 'LOGFILE' => 1, + 'PROCEDURE' => 1, + 'SCHEMA' => 1, + 'SERVER' => 1, + 'TABLE' => 1, + 'TABLESPACE' => 1, + 'TRIGGER' => 1, + ); + + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; + +} diff --git a/libraries/sql-parser/src/Statements/AnalyzeStatement.php b/libraries/sql-parser/src/Statements/AnalyzeStatement.php new file mode 100644 index 0000000000..abe872c38d --- /dev/null +++ b/libraries/sql-parser/src/Statements/AnalyzeStatement.php @@ -0,0 +1,50 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class AnalyzeStatement extends Statement +{ + + /** + * Options of this statement. + * + * @var array + */ + public static $OPTIONS = array( + + 'TABLE' => 1, + + 'NO_WRITE_TO_BINLOG' => 2, + 'LOCAL' => 3, + ); + + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; + + /** + * Analyzed tables. + * + * @var FieldFragment[] + */ + public $tables; +} diff --git a/libraries/sql-parser/src/Statements/BackupStatement.php b/libraries/sql-parser/src/Statements/BackupStatement.php new file mode 100644 index 0000000000..bca4be7e8e --- /dev/null +++ b/libraries/sql-parser/src/Statements/BackupStatement.php @@ -0,0 +1,51 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class BackupStatement extends Statement +{ + + /** + * Options of this statement. + * + * @var array + */ + public static $OPTIONS = array( + + 'TABLE' => 1, + + 'NO_WRITE_TO_BINLOG' => 2, + 'LOCAL' => 3, + + 'TO' => array(4, 'var'), + ); + + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; + + /** + * Backup tables. + * + * @var FieldFragment[] + */ + public $tables; +} diff --git a/libraries/sql-parser/src/Statements/CheckStatement.php b/libraries/sql-parser/src/Statements/CheckStatement.php new file mode 100644 index 0000000000..fa54591e8f --- /dev/null +++ b/libraries/sql-parser/src/Statements/CheckStatement.php @@ -0,0 +1,53 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class CheckStatement extends Statement +{ + + /** + * Options of this statement. + * + * @var array + */ + public static $OPTIONS = array( + + 'TABLE' => 1, + + 'FOR UPGRADE' => 2, + 'QUICK' => 3, + 'FAST' => 4, + 'MEDIUM' => 5, + 'EXTENDED' => 6, + 'CHANGED' => 7, + ); + + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; + + /** + * Checked tables. + * + * @var FieldFragment[] + */ + public $tables; +} diff --git a/libraries/sql-parser/src/Statements/ChecsumStatement.php b/libraries/sql-parser/src/Statements/ChecsumStatement.php new file mode 100644 index 0000000000..ff879c224d --- /dev/null +++ b/libraries/sql-parser/src/Statements/ChecsumStatement.php @@ -0,0 +1,49 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class ChecksumStatement extends Statement +{ + + /** + * Options of this statement. + * + * @var array + */ + public static $OPTIONS = array( + + 'TABLE' => 1, + + 'QUICK' => 2, + 'EXTENDED' => 3, + ); + + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; + + /** + * Checked tables. + * + * @var FieldFragment[] + */ + public $tables; +} diff --git a/libraries/sql-parser/src/Statements/CreateStatement.php b/libraries/sql-parser/src/Statements/CreateStatement.php index edb87ea7fc..69e3f7f6fa 100644 --- a/libraries/sql-parser/src/Statements/CreateStatement.php +++ b/libraries/sql-parser/src/Statements/CreateStatement.php @@ -57,20 +57,14 @@ class CreateStatement extends Statement public $options; /** - * The parameters of this routine. - * - * @var ParamDefFragment[] - */ - public $parameters; - - /** - * The options of the table. + * The options of the entity (table, procedure, function, etc.). * * @var OptionsFragment * * @see CreateDefFragment::$TABLE_OPTIONS + * @see CreateDefFragment::$FUNC_OPTIONS */ - public $tableOptions; + public $entityOptions; /** * Field created by this statement. @@ -79,6 +73,20 @@ class CreateStatement extends Statement */ public $fields; + /** + * The return data type of this routine. + * + * @var DataTypeFragment + */ + public $return; + + /** + * The parameters of this routine. + * + * @var ParamDefFragment[] + */ + public $parameters; + /** * The body of this function or procedure. * diff --git a/libraries/sql-parser/src/Statements/DropStatement.php b/libraries/sql-parser/src/Statements/DropStatement.php new file mode 100644 index 0000000000..00d15912b7 --- /dev/null +++ b/libraries/sql-parser/src/Statements/DropStatement.php @@ -0,0 +1,57 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class DropStatement extends Statement +{ + + /** + * Options of this statement. + * + * @var array + */ + public static $OPTIONS = array( + + 'DATABASE' => 1, + 'EVENT' => 1, + 'FUNCTION' => 1, + 'INDEX' => 1, + 'LOGFILE' => 1, + 'PROCEDURE' => 1, + 'SCHEMA' => 1, + 'SERVER' => 1, + 'TABLE' => 1, + 'TABLESPACE' => 1, + 'TRIGGER' => 1, + + 'TEMPORARY' => 2, + 'IF EXISTS' => 3, + ); + + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; + + /** + * Dropped elements. + * + * @var FromKeyworrd[] + */ + public $name; +} diff --git a/libraries/sql-parser/src/Statements/ExplainStatement.php b/libraries/sql-parser/src/Statements/ExplainStatement.php new file mode 100644 index 0000000000..19834131bc --- /dev/null +++ b/libraries/sql-parser/src/Statements/ExplainStatement.php @@ -0,0 +1,19 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class ExplainStatement extends Statement +{ + +} diff --git a/libraries/sql-parser/src/Statements/OptimizeStatement.php b/libraries/sql-parser/src/Statements/OptimizeStatement.php new file mode 100644 index 0000000000..cb90f08293 --- /dev/null +++ b/libraries/sql-parser/src/Statements/OptimizeStatement.php @@ -0,0 +1,50 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class OptimizeStatement extends Statement +{ + + /** + * Options of this statement. + * + * @var array + */ + public static $OPTIONS = array( + + 'TABLE' => 1, + + 'NO_WRITE_TO_BINLOG' => 2, + 'LOCAL' => 3, + ); + + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; + + /** + * Optimized tables. + * + * @var FieldFragment[] + */ + public $tables; +} diff --git a/libraries/sql-parser/src/Statements/RepairStatement.php b/libraries/sql-parser/src/Statements/RepairStatement.php new file mode 100644 index 0000000000..a3f1afe833 --- /dev/null +++ b/libraries/sql-parser/src/Statements/RepairStatement.php @@ -0,0 +1,55 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class RepairStatement extends Statement +{ + + /** + * Options of this statement. + * + * @var array + */ + public static $OPTIONS = array( + + 'TABLE' => 1, + + 'NO_WRITE_TO_BINLOG' => 2, + 'LOCAL' => 3, + + 'QUICK' => 4, + 'EXTENDED' => 5, + 'USE_FRM' => 6, + ); + + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; + + /** + * Repaired tables. + * + * @var FieldFragment[] + */ + public $tables; +} diff --git a/libraries/sql-parser/src/Statements/RestoreStatement.php b/libraries/sql-parser/src/Statements/RestoreStatement.php new file mode 100644 index 0000000000..e8c46f8c5c --- /dev/null +++ b/libraries/sql-parser/src/Statements/RestoreStatement.php @@ -0,0 +1,48 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class RestoreStatement extends Statement +{ + + /** + * Options of this statement. + * + * @var array + */ + public static $OPTIONS = array( + + 'TABLE' => 1, + + 'FROM' => array(2, 'var'), + ); + + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; + + /** + * Restored tables. + * + * @var FieldFragment[] + */ + public $tables; +} diff --git a/libraries/sql-parser/src/Statements/SelectStatement.php b/libraries/sql-parser/src/Statements/SelectStatement.php index 50ce28148d..d8c9baaa5d 100644 --- a/libraries/sql-parser/src/Statements/SelectStatement.php +++ b/libraries/sql-parser/src/Statements/SelectStatement.php @@ -126,6 +126,20 @@ class SelectStatement extends Statement */ public $limit; + /** + * Procedure that should process the data in the result set. + * + * @var CallKeyword + */ + public $procedure; + + /** + * Destination of this result set. + * + * @var IntoKeyword + */ + public $into; + /** * Joins. * diff --git a/libraries/sql-parser/src/Statements/ShowStatement.php b/libraries/sql-parser/src/Statements/ShowStatement.php new file mode 100644 index 0000000000..962a7a3edd --- /dev/null +++ b/libraries/sql-parser/src/Statements/ShowStatement.php @@ -0,0 +1,76 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class ShowStatement extends Statement +{ + + /** + * Options of this statement. + * + * @var array + */ + public static $OPTIONS = array( + 'CREATE' => 1, + 'AUTHORS' => 2, + 'BINARY' => 2, + 'BINLOG' => 2, + 'CHARACTER' => 2, + 'CODE' => 2, + 'COLLATION' => 2, + 'COLUMNS' => 2, + 'CONTRIBUTORS' => 2, + 'DATABASE' => 2, + 'DATABASES' => 2, + 'ENGINE' => 2, + 'ENGINES' => 2, + 'ERRORS' => 2, + 'EVENT' => 2, + 'EVENTS' => 2, + 'FUNCTION' => 2, + 'GRANTS' => 2, + 'HOSTS' => 2, + 'INDEX' => 2, + 'INNODB' => 2, + 'LOGS' => 2, + 'MASTER' => 2, + 'OPEN' => 2, + 'PLUGINS' => 2, + 'PRIVILEGES' => 2, + 'PROCEDURE' => 2, + 'PROCESSLIST' => 2, + 'PROFILE' => 2, + 'PROFILES' => 2, + 'SCHEDULER' => 2, + 'SET' => 2, + 'SLAVE' => 2, + 'STATUS' => 2, + 'TABLE' => 2, + 'TABLES' => 2, + 'TRIGGER' => 2, + 'TRIGGERS' => 2, + 'VARIABLES' => 2, + 'VIEW' => 2, + 'WARNINGS' => 2, + ); + + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; +} diff --git a/libraries/sql-parser/src/Token.php b/libraries/sql-parser/src/Token.php index 867976c2bc..160efcda3d 100644 --- a/libraries/sql-parser/src/Token.php +++ b/libraries/sql-parser/src/Token.php @@ -120,6 +120,7 @@ class Token const FLAG_KEYWORD_COMPOSED = 4; const FLAG_KEYWORD_DATA_TYPE = 8; const FLAG_KEYWORD_KEY = 16; + const FLAG_KEYWORD_FUNCTION = 32; // Numbers related flags. const FLAG_NUMBER_HEX = 1; diff --git a/libraries/sql-parser/src/Utils/Misc.php b/libraries/sql-parser/src/Utils/Misc.php index 4332ae0642..55ae33b7c1 100644 --- a/libraries/sql-parser/src/Utils/Misc.php +++ b/libraries/sql-parser/src/Utils/Misc.php @@ -3,6 +3,7 @@ namespace SqlParser\Utils; use SqlParser\Statement; +use SqlParser\Statements\SelectStatement; /** * Miscellaneous utilities. @@ -19,12 +20,12 @@ class Misc /** * Gets a list of all aliases and their original names. * - * @param Statement $tree The tree that was generated after parsing. - * @param string $database The name of the database. + * @param SelectStatement $tree The tree that was generated after parsing. + * @param string $database The name of the database. * * @return array */ - public static function getAliases(Statement $tree, $database) + public static function getAliases($tree, $database) { if ((empty($tree->from)) || (empty($tree->expr))) { return array(); diff --git a/libraries/sql-parser/src/Utils/Query.php b/libraries/sql-parser/src/Utils/Query.php new file mode 100644 index 0000000000..0bd56d865c --- /dev/null +++ b/libraries/sql-parser/src/Utils/Query.php @@ -0,0 +1,131 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class Query +{ + + /** + * Functions that set the flag `is_func`. + * + * @var array + */ + public static $FUNCTIONS = array( + 'SUM','AVG','STD','STDDEV','MIN','MAX','BIT_OR','BIT_AND' + ); + + /** + * Gets an array with flags this statement has. + * + * @param Statement $statement + * + * @return array + */ + public static function getFlags($statement) + { + $flags = array(); + // TODO: 'union', 'join', 'offset' + + if (($statement instanceof AlterStatement) + || ($statement instanceof CreateStatement) + ) { + $flags['reload'] = true; + } else if ($statement instanceof AnalyzeStatement) { + $flags['is_maint'] = true; + $flags['is_analyze'] = true; + } else if ($statement instanceof CallStatement) { + $flags['is_procedure'] = true; + } else if (($statement instanceof CheckStatement) + || ($statement instanceof ChecksumStatement) + || ($statement instanceof OptimizeStatement) + || ($statement instanceof RepairStatement) + ) { + $flags['is_maint'] = true; + } else if ($statement instanceof DeleteStatement) { + $flags['is_delete'] = true; + $flags['is_affected'] = true; + } else if ($statement instanceof DropStatement) { + $flags['reload'] = true; + + if (($statement->options->has('DATABASE') + || ($statement->options->has('SCHEMA'))) + ) { + $flags['drop_database'] = true; + } + } else if ($statement instanceof ExplainStatement) { + $flags['is_explain'] = true; + } else if ($statement instanceof InsertStatement) { + $flags['is_affected'] = true; + $flags['is_insert'] = true; + } else if ($statement instanceof ReplaceStatement) { + $flags['is_affected'] = true; + $flags['is_replace'] = true; + } else if ($statement instanceof SelectStatement) { + + if (!empty($statement->from)) { + $flags['select_from'] = true; + } + + if ($statement->options->has('DISTINCT')) { + $flags['distinct'] = true; + } + + if ((!empty($statement->group)) || (!empty($statement->having))) { + $flags['is_group'] = true; + } + + if ((!empty($statement->into)) + && ($statement->into->type === 'OUTFILE') + ) { + $flags['is_export'] = true; + } + + foreach ($statement->expr as $expr) { + if (!empty($expr->function)) { + if ($expr->function === 'COUNT') { + $flags['is_count'] = true; + } else if (in_array($expr->function, static::$FUNCTIONS)) { + $flags['is_func'] = true; + } + } + if (!empty($expr->subquery)) { + $flags['is_subquery'] = true; + } + } + } else if ($statement instanceof ShowStatement) { + $flags['is_show'] = true; + } else if ($statement instanceof UpdateStatement) { + $flags['is_affected'] = true; + } + + return $flags; + } + +} diff --git a/libraries/sql-parser/src/Utils/Routine.php b/libraries/sql-parser/src/Utils/Routine.php index 740ace371a..76d3d71f28 100644 --- a/libraries/sql-parser/src/Utils/Routine.php +++ b/libraries/sql-parser/src/Utils/Routine.php @@ -7,6 +7,7 @@ use SqlParser\Parser; use SqlParser\Statement; use SqlParser\Fragments\DataTypeFragment; use SqlParser\Fragments\ParamDefFragment; +use SqlParser\Statements\CreateStatement; /** * Routine utilities. @@ -89,11 +90,11 @@ class Routine /** * Gets the parameters of a routine from the parse tree. * - * @param Statement $tree The tree that was generated after parsing. + * @param CreateStatement $tree The tree that was generated after parsing. * * @return array */ - public static function getParameters(Statement $tree) + public static function getParameters($tree) { $retval = array( 'num' => 0, diff --git a/libraries/sql-parser/src/Utils/Table.php b/libraries/sql-parser/src/Utils/Table.php index 7be3eac5b9..6bc83a501f 100644 --- a/libraries/sql-parser/src/Utils/Table.php +++ b/libraries/sql-parser/src/Utils/Table.php @@ -7,6 +7,7 @@ use SqlParser\Parser; use SqlParser\Statement; use SqlParser\Fragments\DataTypeFragment; use SqlParser\Fragments\ParamDefFragment; +use SqlParser\Statements\CreateStatement; /** * Table utilities. @@ -20,7 +21,14 @@ use SqlParser\Fragments\ParamDefFragment; class Table { - public static function getForeignKeys(Statement $tree) + /** + * Gets the foreign keys of the table. + * + * @param CreateStatement $tree + * + * @return array + */ + public static function getForeignKeys($tree) { if ((empty($tree->fields)) || (!$tree->options->has('TABLE'))) { return array(); @@ -63,7 +71,14 @@ class Table return $ret; } - public static function getFields(Statement $tree) + /** + * Gets fields of the table. + * + * @param CreateStatement $tree + * + * @return array + */ + public static function getFields($tree) { if ((empty($tree->fields)) || (!$tree->options->has('TABLE'))) { return array(); diff --git a/tbl_structure.php b/tbl_structure.php index 094356c355..99c59d558f 100644 --- a/tbl_structure.php +++ b/tbl_structure.php @@ -200,7 +200,13 @@ $show_create_table = $GLOBALS['dbi']->fetchValue( 0, 1 ); $parser = new SqlParser\Parser($show_create_table); -$create_table_fields = SqlParser\Utils\Table::getFields($parser->statements[0]); + +/** + * @var CreateStatement $stmt + */ +$stmt = $parser->statements[0]; + +$create_table_fields = SqlParser\Utils\Table::getFields($stmt); /** * prepare table infos From 9910f280a75dd00540c71c9e193e9d725a9d216d Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Fri, 26 Jun 2015 01:49:20 +0300 Subject: [PATCH 24/57] Started replacing parse_analyze.inc.php. Updated sql-parser library. Signed-off-by: Dan Ungureanu --- libraries/parse_analyze.inc.php | 160 +++++------------- libraries/sql-parser/autoload.php | 2 +- .../src/Contexts/ContextMySql50000.php | 1 - .../src/Contexts/ContextMySql50100.php | 1 - .../src/Contexts/ContextMySql50500.php | 1 - .../src/Contexts/ContextMySql50600.php | 1 - .../src/Contexts/ContextMySql50700.php | 1 - libraries/sql-parser/src/Utils/Query.php | 88 +++++++++- 8 files changed, 119 insertions(+), 136 deletions(-) diff --git a/libraries/parse_analyze.inc.php b/libraries/parse_analyze.inc.php index a9ce1d8a83..c4c3904002 100644 --- a/libraries/parse_analyze.inc.php +++ b/libraries/parse_analyze.inc.php @@ -9,136 +9,54 @@ if (! defined('PHPMYADMIN')) { exit; } -/** - * - */ $GLOBALS['unparsed_sql'] = $sql_query; -$parsed_sql = PMA_SQP_parse($sql_query); -$analyzed_sql = PMA_SQP_analyze($parsed_sql); -// for bug 780516: now that we use case insensitive preg_match -// or flags from the analyser, do not put back the reformatted query -// into $sql_query, to make this kind of query work without -// capitalizing keywords: -// -// CREATE TABLE SG_Persons ( -// id int(10) unsigned NOT NULL auto_increment, -// first varchar(64) NOT NULL default '', -// PRIMARY KEY (`id`) -// ) +// Get details about the SQL query. +$analyzed_sql_results = SqlParser\Utils\Query::getAll($sql_query); -// Fills some variables from the analysed SQL -// A table has to be created, renamed, dropped: -// the navigation panel should be reloaded -$reload = isset($analyzed_sql[0]['queryflags']['reload']); +// Adding data fetched from the old parser and analyzer. +// TODO: Finish replacing all calls to `PMA_SQP_*`. +$analyzed_sql_results['parsed_sql'] = PMA_SQP_parse($sql_query); +$analyzed_sql_results['analyzed_sql'] = PMA_SQP_analyze($analyzed_sql_results['parsed_sql']); -// check for drop database -$drop_database = isset($analyzed_sql[0]['queryflags']['drop_database']); +// TODO: Refactor this as well. +extract($analyzed_sql_results); -// for the presence of EXPLAIN -$is_explain = isset($analyzed_sql[0]['queryflags']['is_explain']); +// If the targeted table (and database) are different than the ones that is +// currently browsed, edit `$db` and `$table` to match them so other elements +// (page headers, links, navigation panel) can be updated properly. +if (!empty($analyzed_sql_results['tables'])) { -// for the presence of DELETE -$is_delete = isset($analyzed_sql[0]['queryflags']['is_delete']); + // Previous table and database name is stored to check if it changed. + $prevDb = $db; + $prevTable = $table; -// for the presence of UPDATE, DELETE or INSERT|LOAD DATA|REPLACE -$is_affected = isset($analyzed_sql[0]['queryflags']['is_affected']); + if (count($analyzed_sql_results['tables']) > 1) { -// for the presence of REPLACE -$is_replace = isset($analyzed_sql[0]['queryflags']['is_replace']); - -// for the presence of INSERT -$is_insert = isset($analyzed_sql[0]['queryflags']['is_insert']); - -// for the presence of CHECK|ANALYZE|REPAIR|OPTIMIZE|CHECKSUM TABLE -$is_maint = isset($analyzed_sql[0]['queryflags']['is_maint']); - -// for the presence of SHOW -$is_show = isset($analyzed_sql[0]['queryflags']['is_show']); - -// for the presence of PROCEDURE ANALYSE -$is_analyse = isset($analyzed_sql[0]['queryflags']['is_analyse']); - -// for the presence of INTO OUTFILE -$is_export = isset($analyzed_sql[0]['queryflags']['is_export']); - -// for the presence of GROUP BY|HAVING|SELECT DISTINCT -$is_group = isset($analyzed_sql[0]['queryflags']['is_group']); - -// for the presence of SUM|AVG|STD|STDDEV|MIN|MAX|BIT_OR|BIT_AND -$is_func = isset($analyzed_sql[0]['queryflags']['is_func']); - -// for the presence of SELECT COUNT -$is_count = isset($analyzed_sql[0]['queryflags']['is_count']); - -// check for a real SELECT ... FROM -$is_select = isset($analyzed_sql[0]['queryflags']['select_from']); - -// the query contains a subquery -$is_subquery = isset($analyzed_sql[0]['queryflags']['is_subquery']); - -// check for CALL -// Since multiple query execution is anyway handled, -// ignore the WHERE clause of the first sql statement -// which might contain a phrase like 'call ' -if (isset($analyzed_sql[0]['queryflags']['is_procedure']) - && empty($analyzed_sql[0]['where_clause']) -) { - $is_procedure = true; -} else { - $is_procedure = false; -} - -// aggregates all the results into one array -$analyzed_sql_results = array( - "parsed_sql" => $parsed_sql, - "analyzed_sql" => $analyzed_sql, - "reload" => $reload, - "drop_database" => $drop_database, - "is_explain" => $is_explain, - "is_delete" => $is_delete, - "is_affected" => $is_affected, - "is_replace" => $is_replace, - "is_insert" => $is_insert, - "is_maint" => $is_maint, - "is_show" => $is_show, - "is_analyse" => $is_analyse, - "is_export" => $is_export, - "is_group" => $is_group, - "is_func" => $is_func, - "is_count" => $is_count, - "is_select" => $is_select, - "is_procedure" => $is_procedure, - "is_subquery" => $is_subquery -); - - -// If the query is a Select, extract the db and table names and modify -// $db and $table, to have correct page headers, links and left frame. -// db and table name may be enclosed with backquotes, db is optional, -// query may contain aliases. - -/** - * @todo if there are more than one table name in the Select: - * - do not extract the first table name - * - do not show a table name in the page header - * - do not display the sub-pages links) - */ -if ($is_select) { - $prev_db = $db; - if (isset($analyzed_sql[0]['table_ref'][0]['table_true_name'])) { - $table = $analyzed_sql[0]['table_ref'][0]['table_true_name']; - } - if (isset($analyzed_sql[0]['table_ref'][0]['db']) - && /*overload*/mb_strlen($analyzed_sql[0]['table_ref'][0]['db']) - ) { - $db = $analyzed_sql[0]['table_ref'][0]['db']; + /** + * @todo if there are more than one table name in the Select: + * - do not extract the first table name + * - do not show a table name in the page header + * - do not display the sub-pages links) + */ + $table = ''; } else { - $db = $prev_db; + $table = $analyzed_sql_results['tables'][0][0]; + if (!empty($analyzed_sql_results['tables'][0][1])) { + $db = $analyzed_sql_results['tables'][0][1]; + } } - // Don't change reload, if we already decided to reload in import - if (empty($reload) && empty($GLOBALS['is_ajax_request'])) { - $reload = ($db == $prev_db) ? 0 : 1; + + // There is no point checking if a reload is required if we already decided + // to reload. Also, no reload is required for AJAX requests. + if ((empty($reload)) && (empty($GLOBALS['is_ajax_request']))) { + // NOTE: Tables are case-insensitive. + $reload = ((strcasecmp($db, $prevDb) == 0) + || (strcasecmp($table, $prevTable)) == 0) ? false : true; } + + // Updating the array as well. + $analyzed_sql_results['reload'] = $reload; } -?> + +return $analyzed_sql_results; diff --git a/libraries/sql-parser/autoload.php b/libraries/sql-parser/autoload.php index 882015deaf..e0718830ce 100644 --- a/libraries/sql-parser/autoload.php +++ b/libraries/sql-parser/autoload.php @@ -7,7 +7,7 @@ */ if (!class_exists('Composer\\Autoload\\ClassLoader')) { - include_once 'composer/ClassLoader.php'; + include_once './libraries/sql-parser/composer/ClassLoader.php'; } use Composer\Autoload\ClassLoader; diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50000.php b/libraries/sql-parser/src/Contexts/ContextMySql50000.php index d4b80e1f61..eedb59cb71 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50000.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50000.php @@ -258,7 +258,6 @@ class ContextMySql50000 extends Context 'CURRENT_TIMESTAMP' => 35, 'NOT IN' => 37, - 'PROCEDURE ANALYSE' => 37, 'DATE' => 41, 'TIME' => 41, 'YEAR' => 41, 'TIMESTAMP' => 41, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50100.php b/libraries/sql-parser/src/Contexts/ContextMySql50100.php index c6db3d5e8e..5f70976478 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50100.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50100.php @@ -280,7 +280,6 @@ class ContextMySql50100 extends Context 'CURRENT_TIMESTAMP' => 35, 'NOT IN' => 37, - 'PROCEDURE ANALYSE' => 37, 'DATE' => 41, 'TIME' => 41, 'YEAR' => 41, 'TIMESTAMP' => 41, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50500.php b/libraries/sql-parser/src/Contexts/ContextMySql50500.php index 26aa40e0bc..db53f5e841 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50500.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50500.php @@ -284,7 +284,6 @@ class ContextMySql50500 extends Context 'CURRENT_TIMESTAMP' => 35, 'NOT IN' => 37, - 'PROCEDURE ANALYSE' => 37, 'DATE' => 41, 'TIME' => 41, 'YEAR' => 41, 'TIMESTAMP' => 41, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50600.php b/libraries/sql-parser/src/Contexts/ContextMySql50600.php index 39521ef196..48fd6b2060 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50600.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50600.php @@ -315,7 +315,6 @@ class ContextMySql50600 extends Context 'CURRENT_TIMESTAMP' => 35, 'NOT IN' => 37, - 'PROCEDURE ANALYSE' => 37, 'DATE' => 41, 'TIME' => 41, 'YEAR' => 41, 'TIMESTAMP' => 41, diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50700.php b/libraries/sql-parser/src/Contexts/ContextMySql50700.php index 99dae9e02e..ac55a6c96a 100644 --- a/libraries/sql-parser/src/Contexts/ContextMySql50700.php +++ b/libraries/sql-parser/src/Contexts/ContextMySql50700.php @@ -327,7 +327,6 @@ class ContextMySql50700 extends Context 'CURRENT_TIMESTAMP' => 35, 'NOT IN' => 37, - 'PROCEDURE ANALYSE' => 37, 'DATE' => 41, 'TIME' => 41, 'YEAR' => 41, 'TIMESTAMP' => 41, diff --git a/libraries/sql-parser/src/Utils/Query.php b/libraries/sql-parser/src/Utils/Query.php index 0bd56d865c..c3083441ea 100644 --- a/libraries/sql-parser/src/Utils/Query.php +++ b/libraries/sql-parser/src/Utils/Query.php @@ -2,10 +2,11 @@ namespace SqlParser\Utils; +use SqlParser\Parser; use SqlParser\Statement; use SqlParser\Statements\AlterStatement; use SqlParser\Statements\AnalyzeStatement; -use SqlParser\Statement\CallStatement; +use SqlParser\Statements\CallStatement; use SqlParser\Statements\CheckStatement; use SqlParser\Statements\ChecksumStatement; use SqlParser\Statements\CreateStatement; @@ -45,29 +46,54 @@ class Query * Gets an array with flags this statement has. * * @param Statement $statement + * @param bool $all If `false`, false values will not be included. * * @return array */ - public static function getFlags($statement) + public static function getFlags($statement, $all = false) { $flags = array(); - // TODO: 'union', 'join', 'offset' + if ($all) { + $flags = array( + 'distinct' => false, + 'drop_database' => false, + 'is_affected' => false, + 'is_analyse' => false, + 'is_count' => false, + 'is_delete' => false, + 'is_explain' => false, + 'is_export' => false, + 'is_func' => false, + 'is_group' => false, + 'is_insert' => false, + 'is_maint' => false, + 'is_procedure' => false, + 'is_replace' => false, + 'is_select' => false, + 'is_show' => false, + 'is_subquery' => false, + 'join' => false, + 'offset' => false, + 'reload' => false, + 'select_from' => false, + 'union' => false + ); + } + // TODO: 'union', 'join', 'offset' if (($statement instanceof AlterStatement) || ($statement instanceof CreateStatement) ) { $flags['reload'] = true; - } else if ($statement instanceof AnalyzeStatement) { - $flags['is_maint'] = true; - $flags['is_analyze'] = true; - } else if ($statement instanceof CallStatement) { - $flags['is_procedure'] = true; - } else if (($statement instanceof CheckStatement) + } else if (($statement instanceof AnalyzeStatement) + || ($statement instanceof CheckStatement) || ($statement instanceof ChecksumStatement) || ($statement instanceof OptimizeStatement) || ($statement instanceof RepairStatement) ) { $flags['is_maint'] = true; + } else if ($statement instanceof CallStatement) { + $flags['is_procedure'] = true; } else if ($statement instanceof DeleteStatement) { $flags['is_delete'] = true; $flags['is_affected'] = true; @@ -88,6 +114,7 @@ class Query $flags['is_affected'] = true; $flags['is_replace'] = true; } else if ($statement instanceof SelectStatement) { + $flags['is_select'] = true; if (!empty($statement->from)) { $flags['select_from'] = true; @@ -119,6 +146,12 @@ class Query $flags['is_subquery'] = true; } } + + if ((!empty($statement->procedure)) + && ($statement->procedure->name === 'ANALYSE') + ) { + $flags['is_analyse'] = true; + } } else if ($statement instanceof ShowStatement) { $flags['is_show'] = true; } else if ($statement instanceof UpdateStatement) { @@ -128,4 +161,41 @@ class Query return $flags; } + /** + * Parses a query and gets all information about it. + * + * @param string $query + * + * @return array + */ + public static function getAll($query) + { + $parser = new Parser($query); + + if (!isset($parser->statements[0])) { + return array(); + } + + $statement = $parser->statements[0]; + + $ret = static::getFlags($statement, true); + + $ret['parser'] = $parser; + $ret['statement'] = $statement; + + if ($statement instanceof SelectStatement) { + $ret['tables'] = array(); + foreach ($statement->expr as $expr) { + if (!empty($expr->table)) { + $ret['tables'][] = array( + $expr->table, + !empty($expr->database) ? $expr->database : null + ); + } + } + } + + return $ret; + } + } From 3449e6810b5adb52621058d6901ce15532698355 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Fri, 26 Jun 2015 12:28:09 +0300 Subject: [PATCH 25/57] Updated sql-parser library. Signed-off-by: Dan Ungureanu --- .../src/Fragments/FieldFragment.php | 2 +- libraries/sql-parser/src/Statement.php | 143 +++++------------- .../src/Statements/AlterStatement.php | 13 +- .../src/Statements/AnalyzeStatement.php | 9 -- .../src/Statements/BackupStatement.php | 20 +-- .../src/Statements/CheckStatement.php | 13 +- .../src/Statements/ChecsumStatement.php | 13 +- .../src/Statements/CreateStatement.php | 79 ++++++++-- .../src/Statements/DeleteStatement.php | 9 -- .../src/Statements/DropStatement.php | 9 -- .../src/Statements/ExplainStatement.php | 4 +- .../src/Statements/InsertStatement.php | 9 -- .../src/Statements/MaintenanceStatement.php | 59 ++++++++ .../Statements/NotImplementedStatement.php | 38 +++++ .../src/Statements/OptimizeStatement.php | 9 -- .../src/Statements/RenameStatement.php | 20 +++ .../src/Statements/RepairStatement.php | 13 +- .../src/Statements/ReplaceStatement.php | 9 -- .../src/Statements/RestoreStatement.php | 13 +- .../src/Statements/SelectStatement.php | 9 -- .../src/Statements/ShowStatement.php | 13 +- .../src/Statements/UpdateStatement.php | 9 -- 22 files changed, 244 insertions(+), 271 deletions(-) create mode 100644 libraries/sql-parser/src/Statements/MaintenanceStatement.php create mode 100644 libraries/sql-parser/src/Statements/NotImplementedStatement.php diff --git a/libraries/sql-parser/src/Fragments/FieldFragment.php b/libraries/sql-parser/src/Fragments/FieldFragment.php index a45c0fe482..4a0c2cab07 100644 --- a/libraries/sql-parser/src/Fragments/FieldFragment.php +++ b/libraries/sql-parser/src/Fragments/FieldFragment.php @@ -57,7 +57,7 @@ class FieldFragment extends Fragment /** * The name of the function. * - * @var string + * @var mixed */ public $function; diff --git a/libraries/sql-parser/src/Statement.php b/libraries/sql-parser/src/Statement.php index 0fa1fc2668..1b7e590dce 100644 --- a/libraries/sql-parser/src/Statement.php +++ b/libraries/sql-parser/src/Statement.php @@ -5,21 +5,7 @@ namespace SqlParser; use SqlParser\Parser; use SqlParser\Statement; use SqlParser\Token; -use SqlParser\Fragments\CreateDefFragment; -use SqlParser\Fragments\DataTypeFragment; -use SqlParser\Fragments\FieldDefFragment; use SqlParser\Fragments\OptionsFragment; -use SqlParser\Fragments\ParamDefFragment; -use SqlParser\Statements\AlterStatement; -use SqlParser\Statements\BackupStatement; -use SqlParser\Statements\CheckStatement; -use SqlParser\Statements\ChecksumStatement; -use SqlParser\Statements\CreateStatement; -use SqlParser\Statements\ExplainStatement; -use SqlParser\Statements\RenameStatement; -use SqlParser\Statements\RepairStatement; -use SqlParser\Statements\RestoreStatement; -use SqlParser\Statements\ShowStatement; /** * Abstract statement definition. @@ -32,6 +18,15 @@ use SqlParser\Statements\ShowStatement; abstract class Statement { + /** + * The options of this query. + * + * @var OptionsFragment + * + * @see static::$OPTIONS + */ + public $options; + /** * The index of the first token used in this statement. * @@ -120,61 +115,7 @@ abstract class Statement continue; } - // Special cases: before parsing this keyword. - if ($this instanceof CreateStatement) { - ++$list->idx; - $this->name = CreateDefFragment::parse($parser, $list); - if ($this->options->has('TABLE')) { - ++$list->idx; - $this->fields = FieldDefFragment::parse($parser, $list); - ++$list->idx; - $this->entityOptions = OptionsFragment::parse( - $parser, - $list, - CreateDefFragment::$TABLE_OPTIONS - ); - } elseif (($this->options->has('PROCEDURE')) - || ($this->options->has('FUNCTION')) - ) { - ++$list->idx; - $this->parameters = ParamDefFragment::parse($parser, $list); - if ($this->options->has('FUNCTION')) { - $token = $list->getNextOfType(Token::TYPE_KEYWORD); - if ($token->value !== 'RETURNS') { - $parser->error( - '\'RETURNS\' keyword was expected.', - $token - ); - } else { - ++$list->idx; - $this->return = DataTypeFragment::parse( - $parser, - $list - ); - } - } - ++$list->idx; - $this->entityOptions = OptionsFragment::parse( - $parser, - $list, - CreateDefFragment::$FUNC_OPTIONS - ); - ++$list->idx; - $this->body = array(); - for (; $list->idx < $list->count; ++$list->idx) { - $token = $list->tokens[$list->idx]; - $this->body[] = $token; - if (($token->type === Token::TYPE_KEYWORD) - && ($token->value === 'END') - ) { - break; - } - } - $class = null; // The statement has been processed here. - } - } else if ($this instanceof RenameStatement) { - $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'TABLE'); - } + $this->before($parser, $list, $token); // Parsing this keyword. if ($class !== null) { @@ -182,42 +123,38 @@ abstract class Statement $this->$field = $class::parse($parser, $list, array()); } - // Special cases: after parsing this keyword. - if (($this instanceof BackupStatement) - || ($this instanceof CheckStatement) - || ($this instanceof ChecksumStatement) - || ($this instanceof RepairStatement) - || ($this instanceof RestoreStatement) - ) { - - // The statements mentioned above follow this template: - // `STMT` - // - // First of all, because static::$OPTIONS is set for all of the - // statements above, is going to be parsed first. - // - // There is a parser specified in `Parser::$KEYWORD_PARSERS` - // which parses . - // - // Finally, we pares here and that's all. - ++$list->idx; - $this->options->merge( - OptionsFragment::parse( - $parser, - $list, - static::$OPTIONS - ) - ); - } else if (($this instanceof AlterStatement) - || ($this instanceof ExplainStatement) - || ($this instanceof ShowStatement) - ) { - // TODO: Implement the statements above. - $list->getNextOfType(Token::TYPE_DELIMITER); - ++$list->idx; - } + $this->after($parser, $list, $token); } $this->last = --$list->idx; // Go back to last used token. } + + /** + * Function called before the token was processed. + * + * @param Parser $parser The instance that requests parsing. + * @param TokensList $list The list of tokens to be parsed. + * @param Token $token The token that is being parsed. + * + * @return void + */ + public function before(Parser $parser, TokensList $list, Token $token) + { + + } + + /** + * Function called after the token was processed. + * + * @param Parser $parser The instance that requests parsing. + * @param TokensList $list The list of tokens to be parsed. + * @param Token $token The token that is being parsed. + * + * @return + */ + public function after(Parser $parser, TokensList $list, Token $token) + { + + } + } diff --git a/libraries/sql-parser/src/Statements/AlterStatement.php b/libraries/sql-parser/src/Statements/AlterStatement.php index 47d34bba12..4cc29cdefa 100644 --- a/libraries/sql-parser/src/Statements/AlterStatement.php +++ b/libraries/sql-parser/src/Statements/AlterStatement.php @@ -2,7 +2,7 @@ namespace SqlParser\Statements; -use SqlParser\Statement; +use SqlParser\Statements\NotImplementedStatement; /** * `ALTER` statement. @@ -13,7 +13,7 @@ use SqlParser\Statement; * @author Dan Ungureanu * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ -class AlterStatement extends Statement +class AlterStatement extends NotImplementedStatement { /** @@ -36,13 +36,4 @@ class AlterStatement extends Statement 'TRIGGER' => 1, ); - /** - * The options of this query. - * - * @var OptionsFragment - * - * @see static::$OPTIONS - */ - public $options; - } diff --git a/libraries/sql-parser/src/Statements/AnalyzeStatement.php b/libraries/sql-parser/src/Statements/AnalyzeStatement.php index abe872c38d..78783f2a54 100644 --- a/libraries/sql-parser/src/Statements/AnalyzeStatement.php +++ b/libraries/sql-parser/src/Statements/AnalyzeStatement.php @@ -32,15 +32,6 @@ class AnalyzeStatement extends Statement 'LOCAL' => 3, ); - /** - * The options of this query. - * - * @var OptionsFragment - * - * @see static::$OPTIONS - */ - public $options; - /** * Analyzed tables. * diff --git a/libraries/sql-parser/src/Statements/BackupStatement.php b/libraries/sql-parser/src/Statements/BackupStatement.php index bca4be7e8e..cc2e07e256 100644 --- a/libraries/sql-parser/src/Statements/BackupStatement.php +++ b/libraries/sql-parser/src/Statements/BackupStatement.php @@ -2,7 +2,7 @@ namespace SqlParser\Statements; -use SqlParser\Statement; +use SqlParser\Statements\MaintenanceStatement; /** * `BACKUP` statement. @@ -15,7 +15,7 @@ use SqlParser\Statement; * @author Dan Ungureanu * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ -class BackupStatement extends Statement +class BackupStatement extends MaintenanceStatement { /** @@ -32,20 +32,4 @@ class BackupStatement extends Statement 'TO' => array(4, 'var'), ); - - /** - * The options of this query. - * - * @var OptionsFragment - * - * @see static::$OPTIONS - */ - public $options; - - /** - * Backup tables. - * - * @var FieldFragment[] - */ - public $tables; } diff --git a/libraries/sql-parser/src/Statements/CheckStatement.php b/libraries/sql-parser/src/Statements/CheckStatement.php index fa54591e8f..4619613c2f 100644 --- a/libraries/sql-parser/src/Statements/CheckStatement.php +++ b/libraries/sql-parser/src/Statements/CheckStatement.php @@ -2,7 +2,7 @@ namespace SqlParser\Statements; -use SqlParser\Statement; +use SqlParser\Statements\MaintenanceStatement; /** * `CHECK` statement. @@ -15,7 +15,7 @@ use SqlParser\Statement; * @author Dan Ungureanu * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ -class CheckStatement extends Statement +class CheckStatement extends MaintenanceStatement { /** @@ -35,15 +35,6 @@ class CheckStatement extends Statement 'CHANGED' => 7, ); - /** - * The options of this query. - * - * @var OptionsFragment - * - * @see static::$OPTIONS - */ - public $options; - /** * Checked tables. * diff --git a/libraries/sql-parser/src/Statements/ChecsumStatement.php b/libraries/sql-parser/src/Statements/ChecsumStatement.php index ff879c224d..36426d2afc 100644 --- a/libraries/sql-parser/src/Statements/ChecsumStatement.php +++ b/libraries/sql-parser/src/Statements/ChecsumStatement.php @@ -2,7 +2,7 @@ namespace SqlParser\Statements; -use SqlParser\Statement; +use SqlParser\Statements\MaintenanceStatement; /** * `CHECKSUM` statement. @@ -15,7 +15,7 @@ use SqlParser\Statement; * @author Dan Ungureanu * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ -class ChecksumStatement extends Statement +class ChecksumStatement extends MaintenanceStatement { /** @@ -31,15 +31,6 @@ class ChecksumStatement extends Statement 'EXTENDED' => 3, ); - /** - * The options of this query. - * - * @var OptionsFragment - * - * @see static::$OPTIONS - */ - public $options; - /** * Checked tables. * diff --git a/libraries/sql-parser/src/Statements/CreateStatement.php b/libraries/sql-parser/src/Statements/CreateStatement.php index 69e3f7f6fa..b5d56fef3f 100644 --- a/libraries/sql-parser/src/Statements/CreateStatement.php +++ b/libraries/sql-parser/src/Statements/CreateStatement.php @@ -2,7 +2,15 @@ namespace SqlParser\Statements; +use SqlParser\Parser; use SqlParser\Statement; +use sqlParser\Token; +use SqlParser\TokensList; +use SqlParser\Fragments\CreateDefFragment; +use SqlParser\Fragments\DataTypeFragment; +use SqlParser\Fragments\FieldDefFragment; +use SqlParser\Fragments\OptionsFragment; +use SqlParser\Fragments\ParamDefFragment; /** * `CREATE` statement. @@ -47,15 +55,6 @@ class CreateStatement extends Statement */ public $name; - /** - * The options of this query. - * - * @var OptionsFragment - * - * @see static::$OPTIONS - */ - public $options; - /** * The options of the entity (table, procedure, function, etc.). * @@ -93,4 +92,66 @@ class CreateStatement extends Statement * @var Token[] */ public $body; + + /** + * Parsing the `CREATE` statement. + * + * @param Parser $parser The instance that requests parsing. + * @param TokensList $list The list of tokens to be parsed. + * @param Token $token The token that is being parsed. + * + * @return void + */ + public function before(Parser $parser, TokensList $list, Token $token) + { + ++$list->idx; + $this->name = CreateDefFragment::parse($parser, $list); + if ($this->options->has('TABLE')) { + ++$list->idx; + $this->fields = FieldDefFragment::parse($parser, $list); + ++$list->idx; + $this->entityOptions = OptionsFragment::parse( + $parser, + $list, + CreateDefFragment::$TABLE_OPTIONS + ); + } elseif (($this->options->has('PROCEDURE')) + || ($this->options->has('FUNCTION')) + ) { + ++$list->idx; + $this->parameters = ParamDefFragment::parse($parser, $list); + if ($this->options->has('FUNCTION')) { + $token = $list->getNextOfType(Token::TYPE_KEYWORD); + if ($token->value !== 'RETURNS') { + $parser->error( + '\'RETURNS\' keyword was expected.', + $token + ); + } else { + ++$list->idx; + $this->return = DataTypeFragment::parse( + $parser, + $list + ); + } + } + ++$list->idx; + $this->entityOptions = OptionsFragment::parse( + $parser, + $list, + CreateDefFragment::$FUNC_OPTIONS + ); + ++$list->idx; + $this->body = array(); + for (; $list->idx < $list->count; ++$list->idx) { + $token = $list->tokens[$list->idx]; + $this->body[] = $token; + if (($token->type === Token::TYPE_KEYWORD) + && ($token->value === 'END') + ) { + break; + } + } + } + } } diff --git a/libraries/sql-parser/src/Statements/DeleteStatement.php b/libraries/sql-parser/src/Statements/DeleteStatement.php index 0e88fedefb..e7f3a69f75 100644 --- a/libraries/sql-parser/src/Statements/DeleteStatement.php +++ b/libraries/sql-parser/src/Statements/DeleteStatement.php @@ -33,15 +33,6 @@ class DeleteStatement extends Statement 'IGNORE' => 3, ); - /** - * The options of this query. - * - * @var OptionsFragment - * - * @see static::$OPTIONS - */ - public $options; - /** * Tables used as sources for this statement. * diff --git a/libraries/sql-parser/src/Statements/DropStatement.php b/libraries/sql-parser/src/Statements/DropStatement.php index 00d15912b7..de96de728b 100644 --- a/libraries/sql-parser/src/Statements/DropStatement.php +++ b/libraries/sql-parser/src/Statements/DropStatement.php @@ -39,15 +39,6 @@ class DropStatement extends Statement 'IF EXISTS' => 3, ); - /** - * The options of this query. - * - * @var OptionsFragment - * - * @see static::$OPTIONS - */ - public $options; - /** * Dropped elements. * diff --git a/libraries/sql-parser/src/Statements/ExplainStatement.php b/libraries/sql-parser/src/Statements/ExplainStatement.php index 19834131bc..8670b08c1f 100644 --- a/libraries/sql-parser/src/Statements/ExplainStatement.php +++ b/libraries/sql-parser/src/Statements/ExplainStatement.php @@ -2,7 +2,7 @@ namespace SqlParser\Statements; -use SqlParser\Statement; +use SqlParser\Statements\NotImplementedStatement; /** * `EXPLAIN` statement. @@ -13,7 +13,7 @@ use SqlParser\Statement; * @author Dan Ungureanu * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ -class ExplainStatement extends Statement +class ExplainStatement extends NotImplementedStatement { } diff --git a/libraries/sql-parser/src/Statements/InsertStatement.php b/libraries/sql-parser/src/Statements/InsertStatement.php index db88b42beb..c80e194966 100644 --- a/libraries/sql-parser/src/Statements/InsertStatement.php +++ b/libraries/sql-parser/src/Statements/InsertStatement.php @@ -58,15 +58,6 @@ class InsertStatement extends Statement 'IGNORE' => 4, ); - /** - * The options of this query. - * - * @var OptionsFragment - * - * @see static::$OPTIONS - */ - public $options; - /** * Tables used as target for this statement. * diff --git a/libraries/sql-parser/src/Statements/MaintenanceStatement.php b/libraries/sql-parser/src/Statements/MaintenanceStatement.php new file mode 100644 index 0000000000..b26e1c0509 --- /dev/null +++ b/libraries/sql-parser/src/Statements/MaintenanceStatement.php @@ -0,0 +1,59 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class MaintenanceStatement extends Statement +{ + + /** + * Tables maintained. + * + * @var FieldFragment[] + */ + public $tables; + + /** + * Parses the additional options fragment at the end. + * + * @param Parser $parser The instance that requests parsing. + * @param TokensList $list The list of tokens to be parsed. + * @param Token $token The token that is being parsed. + * + * @return + */ + public function after(Parser $parser, TokensList $list, Token $token) + { + // [some options] is going to be parsed first. + // + // There is a parser specified in `Parser::$KEYWORD_PARSERS` + // which parses the name of the tables. + // + // Finally, we parse here [some more options] and that's all. + ++$list->idx; + $this->options->merge( + OptionsFragment::parse( + $parser, + $list, + static::$OPTIONS + ) + ); + } +} diff --git a/libraries/sql-parser/src/Statements/NotImplementedStatement.php b/libraries/sql-parser/src/Statements/NotImplementedStatement.php new file mode 100644 index 0000000000..9f9f61cd09 --- /dev/null +++ b/libraries/sql-parser/src/Statements/NotImplementedStatement.php @@ -0,0 +1,38 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class NotImplementedStatement extends Statement +{ + + /** + * Jump to the end of the delimiter. + * + * @param Parser $parser The instance that requests parsing. + * @param TokensList $list The list of tokens to be parsed. + * @param Token $token The token that is being parsed. + * + * @return + */ + public function before(Parser $parser, TokensList $list, Token $token) + { + $list->getNextOfType(Token::TYPE_DELIMITER); + --$list->idx; + } +} diff --git a/libraries/sql-parser/src/Statements/OptimizeStatement.php b/libraries/sql-parser/src/Statements/OptimizeStatement.php index cb90f08293..0b7b38aa3d 100644 --- a/libraries/sql-parser/src/Statements/OptimizeStatement.php +++ b/libraries/sql-parser/src/Statements/OptimizeStatement.php @@ -32,15 +32,6 @@ class OptimizeStatement extends Statement 'LOCAL' => 3, ); - /** - * The options of this query. - * - * @var OptionsFragment - * - * @see static::$OPTIONS - */ - public $options; - /** * Optimized tables. * diff --git a/libraries/sql-parser/src/Statements/RenameStatement.php b/libraries/sql-parser/src/Statements/RenameStatement.php index 88607ea713..0f5a1c7f8d 100644 --- a/libraries/sql-parser/src/Statements/RenameStatement.php +++ b/libraries/sql-parser/src/Statements/RenameStatement.php @@ -2,7 +2,10 @@ namespace SqlParser\Statements; +use SqlParser\Parser; use SqlParser\Statement; +use sqlParser\Token; +use SqlParser\TokensList; /** * `RENAME` statement. @@ -25,4 +28,21 @@ class RenameStatement extends Statement * @var RenameKeyword[] */ public $renames; + + /** + * Skips the `TABLE` keyword after `RENAME`. + * + * @param Parser $parser The instance that requests parsing. + * @param TokensList $list The list of tokens to be parsed. + * @param Token $token The token that is being parsed. + * + * @return void + */ + public function before(Parser $parser, TokensList $list, Token $token) + { + if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'RENAME')) { + // Checking if it is the beginning of the query. + $list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'TABLE'); + } + } } diff --git a/libraries/sql-parser/src/Statements/RepairStatement.php b/libraries/sql-parser/src/Statements/RepairStatement.php index a3f1afe833..d4053ee375 100644 --- a/libraries/sql-parser/src/Statements/RepairStatement.php +++ b/libraries/sql-parser/src/Statements/RepairStatement.php @@ -2,7 +2,7 @@ namespace SqlParser\Statements; -use SqlParser\Statement; +use SqlParser\Statements\MaintenanceStatement; /** * `REPAIR` statement. @@ -17,7 +17,7 @@ use SqlParser\Statement; * @author Dan Ungureanu * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ -class RepairStatement extends Statement +class RepairStatement extends MaintenanceStatement { /** @@ -37,15 +37,6 @@ class RepairStatement extends Statement 'USE_FRM' => 6, ); - /** - * The options of this query. - * - * @var OptionsFragment - * - * @see static::$OPTIONS - */ - public $options; - /** * Repaired tables. * diff --git a/libraries/sql-parser/src/Statements/ReplaceStatement.php b/libraries/sql-parser/src/Statements/ReplaceStatement.php index 577f72c4fd..0411f45807 100644 --- a/libraries/sql-parser/src/Statements/ReplaceStatement.php +++ b/libraries/sql-parser/src/Statements/ReplaceStatement.php @@ -36,15 +36,6 @@ class ReplaceStatement extends Statement 'DELAYED' => 1, ); - /** - * The options of this query. - * - * @var OptionsFragment - * - * @see static::$OPTIONS - */ - public $options; - /** * Tables used as target for this statement. * diff --git a/libraries/sql-parser/src/Statements/RestoreStatement.php b/libraries/sql-parser/src/Statements/RestoreStatement.php index e8c46f8c5c..89e2ed5222 100644 --- a/libraries/sql-parser/src/Statements/RestoreStatement.php +++ b/libraries/sql-parser/src/Statements/RestoreStatement.php @@ -2,7 +2,7 @@ namespace SqlParser\Statements; -use SqlParser\Statement; +use SqlParser\Statements\MaintenanceStatement; /** * `RESTORE` statement. @@ -15,7 +15,7 @@ use SqlParser\Statement; * @author Dan Ungureanu * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ -class RestoreStatement extends Statement +class RestoreStatement extends MaintenanceStatement { /** @@ -30,15 +30,6 @@ class RestoreStatement extends Statement 'FROM' => array(2, 'var'), ); - /** - * The options of this query. - * - * @var OptionsFragment - * - * @see static::$OPTIONS - */ - public $options; - /** * Restored tables. * diff --git a/libraries/sql-parser/src/Statements/SelectStatement.php b/libraries/sql-parser/src/Statements/SelectStatement.php index d8c9baaa5d..4b9584f58d 100644 --- a/libraries/sql-parser/src/Statements/SelectStatement.php +++ b/libraries/sql-parser/src/Statements/SelectStatement.php @@ -61,15 +61,6 @@ class SelectStatement extends Statement 'SQL_CALC_FOUND_ROWS' => 9, ); - /** - * The options of this query. - * - * @var OptionsFragment - * - * @see static::$OPTIONS - */ - public $options; - /** * Expressions that are being selected by this statement. * diff --git a/libraries/sql-parser/src/Statements/ShowStatement.php b/libraries/sql-parser/src/Statements/ShowStatement.php index 962a7a3edd..57a411055d 100644 --- a/libraries/sql-parser/src/Statements/ShowStatement.php +++ b/libraries/sql-parser/src/Statements/ShowStatement.php @@ -2,7 +2,7 @@ namespace SqlParser\Statements; -use SqlParser\Statement; +use SqlParser\Statements\NotImplementedStatement; /** * `SHOW` statement. @@ -13,7 +13,7 @@ use SqlParser\Statement; * @author Dan Ungureanu * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ -class ShowStatement extends Statement +class ShowStatement extends NotImplementedStatement { /** @@ -64,13 +64,4 @@ class ShowStatement extends Statement 'VIEW' => 2, 'WARNINGS' => 2, ); - - /** - * The options of this query. - * - * @var OptionsFragment - * - * @see static::$OPTIONS - */ - public $options; } diff --git a/libraries/sql-parser/src/Statements/UpdateStatement.php b/libraries/sql-parser/src/Statements/UpdateStatement.php index 8dcc6f090c..39a0f1c227 100644 --- a/libraries/sql-parser/src/Statements/UpdateStatement.php +++ b/libraries/sql-parser/src/Statements/UpdateStatement.php @@ -38,15 +38,6 @@ class UpdateStatement extends Statement 'IGNORE' => 2, ); - /** - * The options of this query. - * - * @var OptionsFragment - * - * @see static::$OPTIONS - */ - public $options; - /** * Tables used as sources for this statement. * From 707ffe666d267613811a463cd344fa6432b9e9f0 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Fri, 26 Jun 2015 14:25:53 +0300 Subject: [PATCH 26/57] Updated sql-parser library. Signed-off-by: Dan Ungureanu --- libraries/sql-parser/src/Context.php | 10 +++++- .../src/Contexts/ContextMySql50000.php | 5 +-- .../src/Contexts/ContextMySql50100.php | 5 +-- .../src/Contexts/ContextMySql50500.php | 5 +-- .../src/Contexts/ContextMySql50600.php | 5 +-- .../src/Contexts/ContextMySql50700.php | 5 +-- .../src/Exceptions/LexerException.php | 6 ++++ .../src/Exceptions/ParserException.php | 6 ++++ libraries/sql-parser/src/Fragment.php | 9 ++++++ .../src/Fragments/ArrayFragment.php | 6 ++++ .../sql-parser/src/Fragments/CallKeyword.php | 6 ++++ .../src/Fragments/CreateDefFragment.php | 6 ++++ .../src/Fragments/DataTypeFragment.php | 6 ++++ .../src/Fragments/FieldDefFragment.php | 8 +++++ .../src/Fragments/FieldFragment.php | 6 ++++ .../sql-parser/src/Fragments/FromKeyword.php | 6 ++++ .../sql-parser/src/Fragments/IntoKeyword.php | 6 ++++ .../sql-parser/src/Fragments/JoinKeyword.php | 6 ++++ .../sql-parser/src/Fragments/KeyFragment.php | 6 ++++ .../sql-parser/src/Fragments/LimitKeyword.php | 6 ++++ .../src/Fragments/OptionsFragment.php | 10 ++++-- .../sql-parser/src/Fragments/OrderKeyword.php | 6 ++++ .../src/Fragments/ParamDefFragment.php | 6 ++++ .../src/Fragments/ReferencesKeyword.php | 6 ++++ .../src/Fragments/RenameKeyword.php | 6 ++++ .../src/Fragments/SelectKeyword.php | 6 ++++ .../sql-parser/src/Fragments/SetKeyword.php | 6 ++++ .../src/Fragments/ValuesKeyword.php | 6 ++++ .../sql-parser/src/Fragments/WhereKeyword.php | 6 ++++ libraries/sql-parser/src/Lexer.php | 9 ++++++ libraries/sql-parser/src/Parser.php | 9 ++++++ libraries/sql-parser/src/Statement.php | 22 +++++++++---- .../src/Statements/AlterStatement.php | 6 ++++ .../src/Statements/AnalyzeStatement.php | 6 ++++ .../src/Statements/BackupStatement.php | 6 ++++ .../src/Statements/CallStatement.php | 6 ++++ .../src/Statements/CheckStatement.php | 6 ++++ .../src/Statements/ChecsumStatement.php | 6 ++++ .../src/Statements/CreateStatement.php | 14 +++++--- .../src/Statements/DeleteStatement.php | 6 ++++ .../src/Statements/DropStatement.php | 6 ++++ .../src/Statements/ExplainStatement.php | 6 ++++ .../src/Statements/InsertStatement.php | 6 ++++ .../src/Statements/MaintenanceStatement.php | 18 +++++++---- .../Statements/NotImplementedStatement.php | 16 +++++++--- .../src/Statements/OptimizeStatement.php | 6 ++++ .../src/Statements/RenameStatement.php | 14 +++++--- .../src/Statements/RepairStatement.php | 6 ++++ .../src/Statements/ReplaceStatement.php | 6 ++++ .../src/Statements/RestoreStatement.php | 6 ++++ .../src/Statements/SelectStatement.php | 6 ++++ .../src/Statements/ShowStatement.php | 6 ++++ .../src/Statements/UpdateStatement.php | 6 ++++ libraries/sql-parser/src/Token.php | 7 ++++ libraries/sql-parser/src/TokensList.php | 5 +++ libraries/sql-parser/src/UtfString.php | 12 +++++++ libraries/sql-parser/src/Utils/Misc.php | 32 +++++++++++-------- libraries/sql-parser/src/Utils/Query.php | 12 +++++-- libraries/sql-parser/src/Utils/Routine.php | 14 +++++--- libraries/sql-parser/src/Utils/Table.php | 22 ++++++++----- 60 files changed, 423 insertions(+), 67 deletions(-) diff --git a/libraries/sql-parser/src/Context.php b/libraries/sql-parser/src/Context.php index cbe666df57..699d800b87 100644 --- a/libraries/sql-parser/src/Context.php +++ b/libraries/sql-parser/src/Context.php @@ -1,9 +1,17 @@ from)) || (empty($tree->expr))) { + if ((empty($statement->from)) || (empty($statement->expr))) { return array(); } @@ -35,28 +41,28 @@ class Misc $tables = array(); - if ((!empty($tree->join->expr->table)) - && (!empty($tree->join->expr->alias)) + if ((!empty($statement->join->expr->table)) + && (!empty($statement->join->expr->alias)) ) { - $thisDb = empty($tree->join->expr->database) ? - $database : $tree->join->expr->database; + $thisDb = empty($statement->join->expr->database) ? + $database : $statement->join->expr->database; $retval = array( $thisDb => array( 'alias' => null, 'tables' => array( - $tree->join->expr->table => array( - 'alias' => $tree->join->expr->alias, + $statement->join->expr->table => array( + 'alias' => $statement->join->expr->alias, 'columns' => array(), ), ), ), ); - $tables[$thisDb][$tree->join->expr->alias] = $tree->join->expr->table; + $tables[$thisDb][$statement->join->expr->alias] = $statement->join->expr->table; } - foreach ($tree->from as $expr) { + foreach ($statement->from as $expr) { if (empty($expr->table)) { continue; } @@ -83,7 +89,7 @@ class Misc $tables[$thisDb][$expr->alias] = $expr->table; } - foreach ($tree->expr as $expr) { + foreach ($statement->expr as $expr) { if ((empty($expr->column)) || (empty($expr->alias))) { continue; } diff --git a/libraries/sql-parser/src/Utils/Query.php b/libraries/sql-parser/src/Utils/Query.php index c3083441ea..b1a95b155c 100644 --- a/libraries/sql-parser/src/Utils/Query.php +++ b/libraries/sql-parser/src/Utils/Query.php @@ -1,5 +1,11 @@ 0, @@ -106,9 +112,9 @@ class Routine 'opts' => array(), ); - if (!empty($tree->parameters)) { + if (!empty($statement->parameters)) { $idx = 0; - foreach ($tree->parameters as $param) { + foreach ($statement->parameters as $param) { $retval['dir'][$idx] = $param->inOut; $retval['name'][$idx] = $param->name; $retval['type'][$idx] = $param->type->name; diff --git a/libraries/sql-parser/src/Utils/Table.php b/libraries/sql-parser/src/Utils/Table.php index 6bc83a501f..95b685001c 100644 --- a/libraries/sql-parser/src/Utils/Table.php +++ b/libraries/sql-parser/src/Utils/Table.php @@ -1,5 +1,11 @@ fields)) || (!$tree->options->has('TABLE'))) { + if ((empty($statement->fields)) || (!$statement->options->has('TABLE'))) { return array(); } $ret = array(); - foreach ($tree->fields as $field) { + foreach ($statement->fields as $field) { if ((empty($field->key)) || ($field->key->type !== 'FOREIGN KEY')) { continue; @@ -74,19 +80,19 @@ class Table /** * Gets fields of the table. * - * @param CreateStatement $tree + * @param CreateStatement $statement The statement to be processed. * * @return array */ - public static function getFields($tree) + public static function getFields($statement) { - if ((empty($tree->fields)) || (!$tree->options->has('TABLE'))) { + if ((empty($statement->fields)) || (!$statement->options->has('TABLE'))) { return array(); } $ret = array(); - foreach ($tree->fields as $field) { + foreach ($statement->fields as $field) { // Skipping keys. if (empty($field->type)) { From c1399cd58ad1fd4d0f7263229e4fd5fbfd1889fe Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Fri, 26 Jun 2015 15:06:31 +0300 Subject: [PATCH 27/57] Removed leftovers from old sql-parser version. Signed-off-by: Dan Ungureanu --- .../src/Contexts/Context_MySQL50000.php | 172 --------------- .../src/Contexts/Context_MySQL50100.php | 186 ---------------- .../src/Contexts/Context_MySQL50500.php | 190 ---------------- .../src/Contexts/Context_MySQL50600.php | 199 ----------------- .../src/Contexts/Context_MySQL50700.php | 208 ------------------ 5 files changed, 955 deletions(-) delete mode 100644 libraries/sql-parser/src/Contexts/Context_MySQL50000.php delete mode 100644 libraries/sql-parser/src/Contexts/Context_MySQL50100.php delete mode 100644 libraries/sql-parser/src/Contexts/Context_MySQL50500.php delete mode 100644 libraries/sql-parser/src/Contexts/Context_MySQL50600.php delete mode 100644 libraries/sql-parser/src/Contexts/Context_MySQL50700.php diff --git a/libraries/sql-parser/src/Contexts/Context_MySQL50000.php b/libraries/sql-parser/src/Contexts/Context_MySQL50000.php deleted file mode 100644 index 830399e719..0000000000 --- a/libraries/sql-parser/src/Contexts/Context_MySQL50000.php +++ /dev/null @@ -1,172 +0,0 @@ - - * @license http://opensource.org/licenses/GPL-2.0 GNU Public License - */ -class Context_MySQL50000 extends Context -{ - - public static $KEYWORDS = array( - - 'AS' => 1, 'BY' => 1, 'IF' => 1, 'IN' => 1, 'IS' => 1, - 'ON' => 1, 'OR' => 1, 'TO' => 1, - 'ADD' => 1, 'ALL' => 1, 'AND' => 1, 'ASC' => 1, 'DEC' => 1, - 'DIV' => 1, 'FOR' => 1, 'INT' => 1, 'KEY' => 1, 'MOD' => 1, - 'NOT' => 1, 'OUT' => 1, 'SET' => 1, 'SQL' => 1, 'SSL' => 1, - 'USE' => 1, 'XOR' => 1, - 'BLOB' => 1, 'BOTH' => 1, 'CALL' => 1, 'CASE' => 1, - 'CHAR' => 1, 'DESC' => 1, 'DROP' => 1, 'DUAL' => 1, - 'EACH' => 1, 'ELSE' => 1, 'EXIT' => 1, 'FROM' => 1, - 'INT1' => 1, 'INT2' => 1, 'INT3' => 1, 'INT4' => 1, - 'INT8' => 1, 'INTO' => 1, 'JOIN' => 1, 'KEYS' => 1, - 'KILL' => 1, 'LEFT' => 1, 'LIKE' => 1, 'LOAD' => 1, - 'LOCK' => 1, 'LONG' => 1, 'LOOP' => 1, 'NULL' => 1, - 'READ' => 1, 'REAL' => 1, 'SHOW' => 1, 'THEN' => 1, - 'TRUE' => 1, 'UNDO' => 1, 'WHEN' => 1, 'WITH' => 1, - 'ALTER' => 1, 'CHECK' => 1, 'CROSS' => 1, 'FALSE' => 1, - 'FETCH' => 1, 'FLOAT' => 1, 'FORCE' => 1, 'GRANT' => 1, - 'GROUP' => 1, 'INDEX' => 1, 'INNER' => 1, 'INOUT' => 1, - 'LEAVE' => 1, 'LIMIT' => 1, 'LINES' => 1, 'MATCH' => 1, - 'ORDER' => 1, 'OUTER' => 1, 'PURGE' => 1, 'READS' => 1, - 'RIGHT' => 1, 'RLIKE' => 1, 'TABLE' => 1, 'UNION' => 1, - 'USAGE' => 1, 'USING' => 1, 'WHERE' => 1, 'WHILE' => 1, - 'WRITE' => 1, - 'BEFORE' => 1, 'BIGINT' => 1, 'BINARY' => 1, 'CHANGE' => 1, - 'COLUMN' => 1, 'CREATE' => 1, 'CURSOR' => 1, 'DELETE' => 1, - 'DOUBLE' => 1, 'ELSEIF' => 1, 'EXISTS' => 1, 'FLOAT4' => 1, - 'FLOAT8' => 1, 'HAVING' => 1, 'IGNORE' => 1, 'INFILE' => 1, - 'INSERT' => 1, 'OPTION' => 1, 'REGEXP' => 1, 'RENAME' => 1, - 'REPEAT' => 1, 'RETURN' => 1, 'REVOKE' => 1, 'SCHEMA' => 1, - 'SELECT' => 1, 'SONAME' => 1, 'UNIQUE' => 1, 'UNLOCK' => 1, - 'UPDATE' => 1, 'VALUES' => 1, - 'ANALYZE' => 1, 'BETWEEN' => 1, 'CASCADE' => 1, 'COLLATE' => 1, - 'CONVERT' => 1, 'DECIMAL' => 1, 'DECLARE' => 1, 'DEFAULT' => 1, - 'DELAYED' => 1, 'ESCAPED' => 1, 'EXPLAIN' => 1, 'FOREIGN' => 1, - 'INTEGER' => 1, 'ITERATE' => 1, 'LEADING' => 1, 'NATURAL' => 1, - 'NUMERIC' => 1, 'OUTFILE' => 1, 'PRIMARY' => 1, 'RELEASE' => 1, - 'REPLACE' => 1, 'REQUIRE' => 1, 'SCHEMAS' => 1, 'SPATIAL' => 1, - 'TINYINT' => 1, 'TRIGGER' => 1, 'VARCHAR' => 1, 'VARYING' => 1, - 'CONTINUE' => 1, 'DATABASE' => 1, 'DAY_HOUR' => 1, - 'DESCRIBE' => 1, 'DISTINCT' => 1, 'ENCLOSED' => 1, - 'FULLTEXT' => 1, 'INTERVAL' => 1, 'LONGBLOB' => 1, - 'LONGTEXT' => 1, 'MODIFIES' => 1, 'OPTIMIZE' => 1, - 'RESTRICT' => 1, 'SMALLINT' => 1, 'SPECIFIC' => 1, - 'SQLSTATE' => 1, 'STARTING' => 1, 'TINYBLOB' => 1, - 'TINYTEXT' => 1, 'TRAILING' => 1, 'UNSIGNED' => 1, - 'UTC_DATE' => 1, 'UTC_TIME' => 1, 'ZEROFILL' => 1, - 'CHARACTER' => 1, 'CONDITION' => 1, 'DATABASES' => 1, - 'LOCALTIME' => 1, 'MEDIUMINT' => 1, 'MIDDLEINT' => 1, - 'PRECISION' => 1, 'PROCEDURE' => 1, 'SENSITIVE' => 1, - 'SEPARATOR' => 1, 'VARBINARY' => 1, - 'ASENSITIVE' => 1, 'CONSTRAINT' => 1, 'DAY_MINUTE' => 1, - 'DAY_SECOND' => 1, 'MEDIUMBLOB' => 1, 'MEDIUMTEXT' => 1, - 'OPTIONALLY' => 1, 'REFERENCES' => 1, 'SQLWARNING' => 1, - 'TERMINATED' => 1, 'YEAR_MONTH' => 1, - 'DISTINCTROW' => 1, 'HOUR_MINUTE' => 1, 'HOUR_SECOND' => 1, - 'INSENSITIVE' => 1, - 'CURRENT_DATE' => 1, 'CURRENT_TIME' => 1, 'CURRENT_USER' => 1, - 'LOW_PRIORITY' => 1, 'SQLEXCEPTION' => 1, 'VARCHARACTER' => 1, - 'DETERMINISTIC' => 1, 'HIGH_PRIORITY' => 1, 'MINUTE_SECOND' => 1, - 'STRAIGHT_JOIN' => 1, 'UTC_TIMESTAMP' => 1, - 'LOCALTIMESTAMP' => 1, 'SQL_BIG_RESULT' => 1, - 'DAY_MICROSECOND' => 1, - 'HOUR_MICROSECOND' => 1, 'SQL_SMALL_RESULT' => 1, - 'CURRENT_TIMESTAMP' => 1, - 'MINUTE_MICROSECOND' => 1, 'NO_WRITE_TO_BINLOG' => 1, - 'SECOND_MICROSECOND' => 1, - 'SQL_CALC_FOUND_ROWS' => 1, - - 'DO' => 2, 'IO' => 2, 'NO' => 2, 'XA' => 2, - 'ANY' => 2, 'AVG' => 2, 'BDB' => 2, 'BIT' => 2, 'CPU' => 2, 'DAY' => 2, - 'END' => 2, 'IPC' => 2, 'NDB' => 2, 'NEW' => 2, 'ONE' => 2, 'ROW' => 2, - 'BOOL' => 2, 'BYTE' => 2, 'CODE' => 2, 'CUBE' => 2, 'DATA' => 2, 'DATE' => 2, - 'ENUM' => 2, 'FAST' => 2, 'FILE' => 2, 'FULL' => 2, 'HASH' => 2, 'HELP' => 2, - 'HOUR' => 2, 'LAST' => 2, 'LOGS' => 2, 'MODE' => 2, 'NAME' => 2, 'NEXT' => 2, - 'NONE' => 2, 'OPEN' => 2, 'PAGE' => 2, 'PREV' => 2, 'ROWS' => 2, 'SOME' => 2, - 'STOP' => 2, 'TEXT' => 2, 'TIME' => 2, 'TYPE' => 2, 'USER' => 2, 'VIEW' => 2, - 'WEEK' => 2, 'WORK' => 2, 'X509' => 2, 'YEAR' => 2, - 'AFTER' => 2, 'ASCII' => 2, 'BEGIN' => 2, 'BLOCK' => 2, 'BTREE' => 2, - 'CACHE' => 2, 'CHAIN' => 2, 'CLOSE' => 2, 'FIRST' => 2, 'FIXED' => 2, - 'FLUSH' => 2, 'FOUND' => 2, 'HOSTS' => 2, 'LEVEL' => 2, 'LOCAL' => 2, - 'LOCKS' => 2, 'MERGE' => 2, 'MONTH' => 2, 'MUTEX' => 2, 'NAMES' => 2, - 'NCHAR' => 2, 'PHASE' => 2, 'POINT' => 2, 'QUERY' => 2, 'QUICK' => 2, - 'RAID0' => 2, 'RESET' => 2, 'RTREE' => 2, 'SHARE' => 2, 'SLAVE' => 2, - 'START' => 2, 'SUPER' => 2, 'SWAPS' => 2, 'TYPES' => 2, 'UNTIL' => 2, - 'VALUE' => 2, - 'ACTION' => 2, 'BACKUP' => 2, 'BINLOG' => 2, 'CIPHER' => 2, 'CLIENT' => 2, - 'COMMIT' => 2, 'ENABLE' => 2, 'ENGINE' => 2, 'ERRORS' => 2, 'ESCAPE' => 2, - 'EVENTS' => 2, 'FAULTS' => 2, 'FIELDS' => 2, 'GLOBAL' => 2, 'GRANTS' => 2, - 'IMPORT' => 2, 'INNODB' => 2, 'ISSUER' => 2, 'LEAVES' => 2, 'MASTER' => 2, - 'MEDIUM' => 2, 'MEMORY' => 2, 'MINUTE' => 2, 'MODIFY' => 2, 'OFFSET' => 2, - 'RELOAD' => 2, 'REPAIR' => 2, 'RESUME' => 2, 'ROLLUP' => 2, 'SECOND' => 2, - 'SERIAL' => 2, 'SIGNED' => 2, 'SIMPLE' => 2, 'SOUNDS' => 2, 'SOURCE' => 2, - 'STATUS' => 2, 'STRING' => 2, 'TABLES' => 2, - 'AGAINST' => 2, 'BOOLEAN' => 2, 'CHANGED' => 2, 'CHARSET' => 2, 'COLUMNS' => 2, - 'COMMENT' => 2, 'COMPACT' => 2, 'CONTEXT' => 2, 'DEFINER' => 2, 'DISABLE' => 2, - 'DISCARD' => 2, 'DYNAMIC' => 2, 'ENGINES' => 2, 'EXECUTE' => 2, 'HANDLER' => 2, - 'INDEXES' => 2, 'INVOKER' => 2, 'MIGRATE' => 2, 'PARTIAL' => 2, 'POLYGON' => 2, - 'PREPARE' => 2, 'PROFILE' => 2, 'QUARTER' => 2, 'RECOVER' => 2, 'RESTORE' => 2, - 'RETURNS' => 2, 'ROUTINE' => 2, 'SESSION' => 2, 'STORAGE' => 2, 'STRIPED' => 2, - 'SUBJECT' => 2, 'SUSPEND' => 2, 'UNICODE' => 2, 'UNKNOWN' => 2, 'UPGRADE' => 2, - 'USE_FRM' => 2, - 'CASCADED' => 2, 'CHECKSUM' => 2, 'CONTAINS' => 2, 'DATETIME' => 2, - 'DUMPFILE' => 2, 'EXTENDED' => 2, 'FUNCTION' => 2, 'GEOMETRY' => 2, - 'INNOBASE' => 2, 'LANGUAGE' => 2, 'MAX_ROWS' => 2, 'MIN_ROWS' => 2, - 'NATIONAL' => 2, 'NVARCHAR' => 2, 'ONE_SHOT' => 2, 'PASSWORD' => 2, - 'PROFILES' => 2, 'ROLLBACK' => 2, 'SECURITY' => 2, 'SHUTDOWN' => 2, - 'SNAPSHOT' => 2, 'SWITCHES' => 2, 'TRIGGERS' => 2, 'TRUNCATE' => 2, - 'WARNINGS' => 2, - 'AGGREGATE' => 2, 'ALGORITHM' => 2, 'COLLATION' => 2, 'COMMITTED' => 2, - 'DIRECTORY' => 2, 'DUPLICATE' => 2, 'EXPANSION' => 2, 'IO_THREAD' => 2, - 'ISOLATION' => 2, 'PACK_KEYS' => 2, 'RAID_TYPE' => 2, 'REDUNDANT' => 2, - 'SAVEPOINT' => 2, 'SQL_CACHE' => 2, 'TEMPORARY' => 2, 'TEMPTABLE' => 2, - 'TIMESTAMP' => 2, 'UNDEFINED' => 2, 'VARIABLES' => 2, - 'BERKELEYDB' => 2, 'COMPRESSED' => 2, 'CONCURRENT' => 2, 'CONNECTION' => 2, - 'CONSISTENT' => 2, 'DEALLOCATE' => 2, 'GET_FORMAT' => 2, 'IDENTIFIED' => 2, - 'LINESTRING' => 2, 'MASTER_SSL' => 2, 'MULTIPOINT' => 2, 'NDBCLUSTER' => 2, - 'PRIVILEGES' => 2, 'REPEATABLE' => 2, 'ROW_FORMAT' => 2, 'SQL_THREAD' => 2, - 'TABLESPACE' => 2, - 'FRAC_SECOND' => 2, 'MASTER_HOST' => 2, 'MASTER_PORT' => 2, 'MASTER_USER' => 2, - 'MICROSECOND' => 2, 'PROCESSLIST' => 2, 'RAID_CHUNKS' => 2, 'REPLICATION' => 2, - 'SQL_TSI_DAY' => 2, 'TRANSACTION' => 2, 'UNCOMMITTED' => 2, - 'DES_KEY_FILE' => 2, 'MULTIPOLYGON' => 2, 'OLD_PASSWORD' => 2, - 'RELAY_THREAD' => 2, 'SERIALIZABLE' => 2, 'SQL_NO_CACHE' => 2, - 'SQL_TSI_HOUR' => 2, 'SQL_TSI_WEEK' => 2, 'SQL_TSI_YEAR' => 2, - 'TIMESTAMPADD' => 2, - 'INSERT_METHOD' => 2, 'MASTER_SSL_CA' => 2, 'RELAY_LOG_POS' => 2, - 'SQL_TSI_MONTH' => 2, 'TIMESTAMPDIFF' => 2, - 'AUTO_INCREMENT' => 2, 'AVG_ROW_LENGTH' => 2, 'MASTER_LOG_POS' => 2, - 'MASTER_SSL_KEY' => 2, 'RAID_CHUNKSIZE' => 2, 'RELAY_LOG_FILE' => 2, - 'SQL_TSI_MINUTE' => 2, 'SQL_TSI_SECOND' => 2, 'USER_RESOURCES' => 2, - 'DELAY_KEY_WRITE' => 2, 'MASTER_LOG_FILE' => 2, 'MASTER_PASSWORD' => 2, - 'MASTER_SSL_CERT' => 2, 'MULTILINESTRING' => 2, 'SQL_TSI_QUARTER' => 2, - 'MASTER_SERVER_ID' => 2, - 'MASTER_SSL_CAPATH' => 2, 'MASTER_SSL_CIPHER' => 2, 'SQL_BUFFER_RESULT' => 2, - 'GEOMETRYCOLLECTION' => 2, - 'SQL_TSI_FRAC_SECOND' => 2, - 'MASTER_CONNECT_RETRY' => 2, 'MAX_QUERIES_PER_HOUR' => 2, - 'MAX_UPDATES_PER_HOUR' => 2, 'MAX_USER_CONNECTIONS' => 2, - 'MAX_CONNECTIONS_PER_HOUR' => 2, - - 'NOT NULL' => 4, - 'INDEX KEY' => 4, - 'UNIQUE KEY' => 4, - 'FOREIGN KEY' => 4, 'PRIMARY KEY' => 4, 'PRIMARY KEY' => 4, 'SPATIAL KEY' => 4, - 'FULLTEXT KEY' => 4, 'UNIQUE INDEX' => 4, - 'CHARACTER SET' => 4, 'IF NOT EXISTS' => 4, 'SPATIAL INDEX' => 4, - 'DATA DIRECTORY' => 4, 'FULLTEXT INDEX' => 4, - 'DEFAULT COLLATE' => 4, 'INDEX DIRECTORY' => 4, - 'DEFAULT CHARACTER SET' => 4, - - ); -} diff --git a/libraries/sql-parser/src/Contexts/Context_MySQL50100.php b/libraries/sql-parser/src/Contexts/Context_MySQL50100.php deleted file mode 100644 index f70ecef978..0000000000 --- a/libraries/sql-parser/src/Contexts/Context_MySQL50100.php +++ /dev/null @@ -1,186 +0,0 @@ - - * @license http://opensource.org/licenses/GPL-2.0 GNU Public License - */ -class Context_MySQL50100 extends Context -{ - - public static $KEYWORDS = array( - - 'AS' => 1, 'BY' => 1, 'IF' => 1, 'IN' => 1, 'IS' => 1, - 'ON' => 1, 'OR' => 1, 'TO' => 1, - 'ADD' => 1, 'ALL' => 1, 'AND' => 1, 'ASC' => 1, 'DEC' => 1, - 'DIV' => 1, 'FOR' => 1, 'INT' => 1, 'KEY' => 1, 'MOD' => 1, - 'NOT' => 1, 'OUT' => 1, 'SET' => 1, 'SQL' => 1, 'SSL' => 1, - 'USE' => 1, 'XOR' => 1, - 'BLOB' => 1, 'BOTH' => 1, 'CALL' => 1, 'CASE' => 1, - 'CHAR' => 1, 'DESC' => 1, 'DROP' => 1, 'DUAL' => 1, - 'EACH' => 1, 'ELSE' => 1, 'EXIT' => 1, 'FROM' => 1, - 'INT1' => 1, 'INT2' => 1, 'INT3' => 1, 'INT4' => 1, - 'INT8' => 1, 'INTO' => 1, 'JOIN' => 1, 'KEYS' => 1, - 'KILL' => 1, 'LEFT' => 1, 'LIKE' => 1, 'LOAD' => 1, - 'LOCK' => 1, 'LONG' => 1, 'LOOP' => 1, 'NULL' => 1, - 'READ' => 1, 'REAL' => 1, 'SHOW' => 1, 'THEN' => 1, - 'TRUE' => 1, 'UNDO' => 1, 'WHEN' => 1, 'WITH' => 1, - 'ALTER' => 1, 'CHECK' => 1, 'CROSS' => 1, 'FALSE' => 1, - 'FETCH' => 1, 'FLOAT' => 1, 'FORCE' => 1, 'GRANT' => 1, - 'GROUP' => 1, 'INDEX' => 1, 'INNER' => 1, 'INOUT' => 1, - 'LEAVE' => 1, 'LIMIT' => 1, 'LINES' => 1, 'MATCH' => 1, - 'ORDER' => 1, 'OUTER' => 1, 'PURGE' => 1, 'RANGE' => 1, - 'READS' => 1, 'RIGHT' => 1, 'RLIKE' => 1, 'TABLE' => 1, - 'UNION' => 1, 'USAGE' => 1, 'USING' => 1, 'WHERE' => 1, - 'WHILE' => 1, 'WRITE' => 1, - 'BEFORE' => 1, 'BIGINT' => 1, 'BINARY' => 1, 'CHANGE' => 1, - 'COLUMN' => 1, 'CREATE' => 1, 'CURSOR' => 1, 'DELETE' => 1, - 'DOUBLE' => 1, 'ELSEIF' => 1, 'EXISTS' => 1, 'FLOAT4' => 1, - 'FLOAT8' => 1, 'HAVING' => 1, 'IGNORE' => 1, 'INFILE' => 1, - 'INSERT' => 1, 'LINEAR' => 1, 'OPTION' => 1, 'REGEXP' => 1, - 'RENAME' => 1, 'REPEAT' => 1, 'RETURN' => 1, 'REVOKE' => 1, - 'SCHEMA' => 1, 'SELECT' => 1, 'UNIQUE' => 1, 'UNLOCK' => 1, - 'UPDATE' => 1, 'VALUES' => 1, - 'ANALYZE' => 1, 'BETWEEN' => 1, 'CASCADE' => 1, 'COLLATE' => 1, - 'CONVERT' => 1, 'DECIMAL' => 1, 'DECLARE' => 1, 'DEFAULT' => 1, - 'DELAYED' => 1, 'ESCAPED' => 1, 'EXPLAIN' => 1, 'FOREIGN' => 1, - 'INTEGER' => 1, 'ITERATE' => 1, 'LEADING' => 1, 'NATURAL' => 1, - 'NUMERIC' => 1, 'OUTFILE' => 1, 'PRIMARY' => 1, 'RELEASE' => 1, - 'REPLACE' => 1, 'REQUIRE' => 1, 'SCHEMAS' => 1, 'SPATIAL' => 1, - 'TINYINT' => 1, 'TRIGGER' => 1, 'VARCHAR' => 1, 'VARYING' => 1, - 'CONTINUE' => 1, 'DATABASE' => 1, 'DAY_HOUR' => 1, - 'DESCRIBE' => 1, 'DISTINCT' => 1, 'ENCLOSED' => 1, - 'FULLTEXT' => 1, 'INTERVAL' => 1, 'LONGBLOB' => 1, - 'LONGTEXT' => 1, 'MODIFIES' => 1, 'OPTIMIZE' => 1, - 'RESTRICT' => 1, 'SMALLINT' => 1, 'SPECIFIC' => 1, - 'SQLSTATE' => 1, 'STARTING' => 1, 'TINYBLOB' => 1, - 'TINYTEXT' => 1, 'TRAILING' => 1, 'UNSIGNED' => 1, - 'UTC_DATE' => 1, 'UTC_TIME' => 1, 'ZEROFILL' => 1, - 'CHARACTER' => 1, 'CONDITION' => 1, 'DATABASES' => 1, - 'LOCALTIME' => 1, 'MEDIUMINT' => 1, 'MIDDLEINT' => 1, - 'PRECISION' => 1, 'PROCEDURE' => 1, 'SENSITIVE' => 1, - 'SEPARATOR' => 1, 'VARBINARY' => 1, - 'ACCESSIBLE' => 1, 'ASENSITIVE' => 1, 'CONSTRAINT' => 1, - 'DAY_MINUTE' => 1, 'DAY_SECOND' => 1, 'MEDIUMBLOB' => 1, - 'MEDIUMTEXT' => 1, 'OPTIONALLY' => 1, 'READ_WRITE' => 1, - 'REFERENCES' => 1, 'SQLWARNING' => 1, 'TERMINATED' => 1, - 'YEAR_MONTH' => 1, - 'DISTINCTROW' => 1, 'HOUR_MINUTE' => 1, 'HOUR_SECOND' => 1, - 'INSENSITIVE' => 1, - 'CURRENT_DATE' => 1, 'CURRENT_TIME' => 1, 'CURRENT_USER' => 1, - 'LOW_PRIORITY' => 1, 'SQLEXCEPTION' => 1, 'VARCHARACTER' => 1, - 'DETERMINISTIC' => 1, 'HIGH_PRIORITY' => 1, 'MINUTE_SECOND' => 1, - 'STRAIGHT_JOIN' => 1, 'UTC_TIMESTAMP' => 1, - 'LOCALTIMESTAMP' => 1, 'SQL_BIG_RESULT' => 1, - 'DAY_MICROSECOND' => 1, - 'HOUR_MICROSECOND' => 1, 'SQL_SMALL_RESULT' => 1, - 'CURRENT_TIMESTAMP' => 1, - 'MINUTE_MICROSECOND' => 1, 'NO_WRITE_TO_BINLOG' => 1, - 'SECOND_MICROSECOND' => 1, - 'SQL_CALC_FOUND_ROWS' => 1, - 'MASTER_SSL_VERIFY_SERVER_CERT' => 1, - - 'AT' => 2, 'DO' => 2, 'IO' => 2, 'NO' => 2, 'XA' => 2, - 'ANY' => 2, 'AVG' => 2, 'BDB' => 2, 'BIT' => 2, 'CPU' => 2, 'DAY' => 2, - 'END' => 2, 'IPC' => 2, 'NDB' => 2, 'NEW' => 2, 'ONE' => 2, 'ROW' => 2, - 'BOOL' => 2, 'BYTE' => 2, 'CODE' => 2, 'CUBE' => 2, 'DATA' => 2, 'DATE' => 2, - 'DISK' => 2, 'ENDS' => 2, 'ENUM' => 2, 'FAST' => 2, 'FILE' => 2, 'FULL' => 2, - 'GOTO' => 2, 'HASH' => 2, 'HELP' => 2, 'HOST' => 2, 'HOUR' => 2, 'LAST' => 2, - 'LESS' => 2, 'LIST' => 2, 'LOGS' => 2, 'MODE' => 2, 'NAME' => 2, 'NEXT' => 2, - 'NONE' => 2, 'OPEN' => 2, 'PAGE' => 2, 'PORT' => 2, 'PREV' => 2, 'ROWS' => 2, - 'SOME' => 2, 'STOP' => 2, 'TEXT' => 2, 'THAN' => 2, 'TIME' => 2, 'TYPE' => 2, - 'USER' => 2, 'VIEW' => 2, 'WAIT' => 2, 'WEEK' => 2, 'WORK' => 2, 'X509' => 2, - 'YEAR' => 2, - 'AFTER' => 2, 'ASCII' => 2, 'BEGIN' => 2, 'BLOCK' => 2, 'BTREE' => 2, - 'CACHE' => 2, 'CHAIN' => 2, 'CLOSE' => 2, 'EVENT' => 2, 'EVERY' => 2, - 'FIRST' => 2, 'FIXED' => 2, 'FLUSH' => 2, 'FOUND' => 2, 'HOSTS' => 2, - 'LABEL' => 2, 'LEVEL' => 2, 'LOCAL' => 2, 'LOCKS' => 2, 'MERGE' => 2, - 'MONTH' => 2, 'MUTEX' => 2, 'NAMES' => 2, 'NCHAR' => 2, 'OWNER' => 2, - 'PHASE' => 2, 'POINT' => 2, 'QUERY' => 2, 'QUICK' => 2, 'RAID0' => 2, - 'RESET' => 2, 'RTREE' => 2, 'SHARE' => 2, 'SLAVE' => 2, 'START' => 2, - 'SUPER' => 2, 'SWAPS' => 2, 'TYPES' => 2, 'UNTIL' => 2, 'VALUE' => 2, - 'ACTION' => 2, 'BACKUP' => 2, 'BINLOG' => 2, 'CIPHER' => 2, 'CLIENT' => 2, - 'COMMIT' => 2, 'ENABLE' => 2, 'ENGINE' => 2, 'ERRORS' => 2, 'ESCAPE' => 2, - 'EVENTS' => 2, 'FAULTS' => 2, 'FIELDS' => 2, 'GLOBAL' => 2, 'GRANTS' => 2, - 'IMPORT' => 2, 'INNODB' => 2, 'ISSUER' => 2, 'LEAVES' => 2, 'MASTER' => 2, - 'MEDIUM' => 2, 'MEMORY' => 2, 'MINUTE' => 2, 'MODIFY' => 2, 'OFFSET' => 2, - 'PARSER' => 2, 'PLUGIN' => 2, 'RELOAD' => 2, 'REMOVE' => 2, 'REPAIR' => 2, - 'RESUME' => 2, 'ROLLUP' => 2, 'SECOND' => 2, 'SERIAL' => 2, 'SERVER' => 2, - 'SIGNED' => 2, 'SIMPLE' => 2, 'SOCKET' => 2, 'SONAME' => 2, 'SOUNDS' => 2, - 'SOURCE' => 2, 'STARTS' => 2, 'STATUS' => 2, 'STRING' => 2, 'TABLES' => 2, - 'AGAINST' => 2, 'AUTHORS' => 2, 'BOOLEAN' => 2, 'CHANGED' => 2, 'CHARSET' => 2, - 'COLUMNS' => 2, 'COMMENT' => 2, 'COMPACT' => 2, 'CONTEXT' => 2, 'DEFINER' => 2, - 'DISABLE' => 2, 'DISCARD' => 2, 'DYNAMIC' => 2, 'ENGINES' => 2, 'EXECUTE' => 2, - 'HANDLER' => 2, 'INDEXES' => 2, 'INSTALL' => 2, 'INVOKER' => 2, 'LOGFILE' => 2, - 'MIGRATE' => 2, 'NO_WAIT' => 2, 'OPTIONS' => 2, 'PARTIAL' => 2, 'PLUGINS' => 2, - 'POLYGON' => 2, 'PREPARE' => 2, 'PROFILE' => 2, 'QUARTER' => 2, 'REBUILD' => 2, - 'RECOVER' => 2, 'RESTORE' => 2, 'RETURNS' => 2, 'ROUTINE' => 2, 'SESSION' => 2, - 'STORAGE' => 2, 'STRIPED' => 2, 'SUBJECT' => 2, 'SUSPEND' => 2, 'UNICODE' => 2, - 'UNKNOWN' => 2, 'UPGRADE' => 2, 'USE_FRM' => 2, 'WRAPPER' => 2, - 'CASCADED' => 2, 'CHECKSUM' => 2, 'COALESCE' => 2, 'CONTAINS' => 2, - 'DATAFILE' => 2, 'DATETIME' => 2, 'DUMPFILE' => 2, 'EXTENDED' => 2, - 'FUNCTION' => 2, 'GEOMETRY' => 2, 'INNOBASE' => 2, 'LANGUAGE' => 2, - 'MAXVALUE' => 2, 'MAX_ROWS' => 2, 'MAX_SIZE' => 2, 'MIN_ROWS' => 2, - 'NATIONAL' => 2, 'NVARCHAR' => 2, 'ONE_SHOT' => 2, 'PASSWORD' => 2, - 'PRESERVE' => 2, 'PROFILES' => 2, 'REDOFILE' => 2, 'ROLLBACK' => 2, - 'SCHEDULE' => 2, 'SECURITY' => 2, 'SHUTDOWN' => 2, 'SNAPSHOT' => 2, - 'SWITCHES' => 2, 'TRIGGERS' => 2, 'TRUNCATE' => 2, 'UNDOFILE' => 2, - 'WARNINGS' => 2, - 'AGGREGATE' => 2, 'ALGORITHM' => 2, 'COLLATION' => 2, 'COMMITTED' => 2, - 'DIRECTORY' => 2, 'DUPLICATE' => 2, 'EXPANSION' => 2, 'IO_THREAD' => 2, - 'ISOLATION' => 2, 'NODEGROUP' => 2, 'PACK_KEYS' => 2, 'PARTITION' => 2, - 'RAID_TYPE' => 2, 'READ_ONLY' => 2, 'REDUNDANT' => 2, 'SAVEPOINT' => 2, - 'SCHEDULER' => 2, 'SQL_CACHE' => 2, 'TEMPORARY' => 2, 'TEMPTABLE' => 2, - 'TIMESTAMP' => 2, 'UNDEFINED' => 2, 'UNINSTALL' => 2, 'VARIABLES' => 2, - 'BERKELEYDB' => 2, 'COMPLETION' => 2, 'COMPRESSED' => 2, 'CONCURRENT' => 2, - 'CONNECTION' => 2, 'CONSISTENT' => 2, 'DEALLOCATE' => 2, 'GET_FORMAT' => 2, - 'IDENTIFIED' => 2, 'LINESTRING' => 2, 'MASTER_SSL' => 2, 'MULTIPOINT' => 2, - 'NDBCLUSTER' => 2, 'PARTITIONS' => 2, 'PRIVILEGES' => 2, 'REORGANISE' => 2, - 'REORGANIZE' => 2, 'REPEATABLE' => 2, 'ROW_FORMAT' => 2, 'SQL_THREAD' => 2, - 'TABLESPACE' => 2, - 'EXTENT_SIZE' => 2, 'FRAC_SECOND' => 2, 'MASTER_HOST' => 2, 'MASTER_PORT' => 2, - 'MASTER_USER' => 2, 'MICROSECOND' => 2, 'PROCESSLIST' => 2, 'RAID_CHUNKS' => 2, - 'REPLICATION' => 2, 'SQL_TSI_DAY' => 2, 'TRANSACTION' => 2, 'UNCOMMITTED' => 2, - 'CONTRIBUTORS' => 2, 'DES_KEY_FILE' => 2, 'INITIAL_SIZE' => 2, - 'MULTIPOLYGON' => 2, 'OLD_PASSWORD' => 2, 'PARTITIONING' => 2, - 'RELAY_THREAD' => 2, 'SERIALIZABLE' => 2, 'SQL_NO_CACHE' => 2, - 'SQL_TSI_HOUR' => 2, 'SQL_TSI_WEEK' => 2, 'SQL_TSI_YEAR' => 2, - 'SUBPARTITION' => 2, 'TIMESTAMPADD' => 2, - 'INSERT_METHOD' => 2, 'MASTER_SSL_CA' => 2, 'PAGE_CHECKSUM' => 2, - 'RELAY_LOG_POS' => 2, 'SQL_TSI_MONTH' => 2, 'SUBPARTITIONS' => 2, - 'TIMESTAMPDIFF' => 2, 'TRANSACTIONAL' => 2, - 'AUTO_INCREMENT' => 2, 'AVG_ROW_LENGTH' => 2, 'KEY_BLOCK_SIZE' => 2, - 'MASTER_LOG_POS' => 2, 'MASTER_SSL_KEY' => 2, 'RAID_CHUNKSIZE' => 2, - 'RELAY_LOG_FILE' => 2, 'SQL_TSI_MINUTE' => 2, 'SQL_TSI_SECOND' => 2, - 'TABLE_CHECKSUM' => 2, 'USER_RESOURCES' => 2, - 'AUTOEXTEND_SIZE' => 2, 'DELAY_KEY_WRITE' => 2, 'MASTER_LOG_FILE' => 2, - 'MASTER_PASSWORD' => 2, 'MASTER_SSL_CERT' => 2, 'MULTILINESTRING' => 2, - 'SQL_TSI_QUARTER' => 2, - 'MASTER_SERVER_ID' => 2, 'REDO_BUFFER_SIZE' => 2, 'UNDO_BUFFER_SIZE' => 2, - 'MASTER_SSL_CAPATH' => 2, 'MASTER_SSL_CIPHER' => 2, 'SQL_BUFFER_RESULT' => 2, - 'GEOMETRYCOLLECTION' => 2, - 'SQL_TSI_FRAC_SECOND' => 2, - 'MASTER_CONNECT_RETRY' => 2, 'MAX_QUERIES_PER_HOUR' => 2, - 'MAX_UPDATES_PER_HOUR' => 2, 'MAX_USER_CONNECTIONS' => 2, - 'MAX_CONNECTIONS_PER_HOUR' => 2, - - 'NOT NULL' => 4, - 'INDEX KEY' => 4, - 'UNIQUE KEY' => 4, - 'FOREIGN KEY' => 4, 'PRIMARY KEY' => 4, 'PRIMARY KEY' => 4, 'SPATIAL KEY' => 4, - 'FULLTEXT KEY' => 4, 'UNIQUE INDEX' => 4, - 'CHARACTER SET' => 4, 'IF NOT EXISTS' => 4, 'SPATIAL INDEX' => 4, - 'DATA DIRECTORY' => 4, 'FULLTEXT INDEX' => 4, - 'DEFAULT COLLATE' => 4, 'INDEX DIRECTORY' => 4, - 'DEFAULT CHARACTER SET' => 4, - - ); -} diff --git a/libraries/sql-parser/src/Contexts/Context_MySQL50500.php b/libraries/sql-parser/src/Contexts/Context_MySQL50500.php deleted file mode 100644 index 6febe72e3c..0000000000 --- a/libraries/sql-parser/src/Contexts/Context_MySQL50500.php +++ /dev/null @@ -1,190 +0,0 @@ - - * @license http://opensource.org/licenses/GPL-2.0 GNU Public License - */ -class Context_MySQL50500 extends Context -{ - - public static $KEYWORDS = array( - - 'AS' => 1, 'BY' => 1, 'IF' => 1, 'IN' => 1, 'IS' => 1, - 'ON' => 1, 'OR' => 1, 'TO' => 1, - 'ADD' => 1, 'ALL' => 1, 'AND' => 1, 'ASC' => 1, 'DEC' => 1, - 'DIV' => 1, 'FOR' => 1, 'INT' => 1, 'KEY' => 1, 'MOD' => 1, - 'NOT' => 1, 'OUT' => 1, 'SET' => 1, 'SQL' => 1, 'SSL' => 1, - 'USE' => 1, 'XOR' => 1, - 'BLOB' => 1, 'BOTH' => 1, 'CALL' => 1, 'CASE' => 1, - 'CHAR' => 1, 'DESC' => 1, 'DROP' => 1, 'DUAL' => 1, - 'EACH' => 1, 'ELSE' => 1, 'EXIT' => 1, 'FROM' => 1, - 'INT1' => 1, 'INT2' => 1, 'INT3' => 1, 'INT4' => 1, - 'INT8' => 1, 'INTO' => 1, 'JOIN' => 1, 'KEYS' => 1, - 'KILL' => 1, 'LEFT' => 1, 'LIKE' => 1, 'LOAD' => 1, - 'LOCK' => 1, 'LONG' => 1, 'LOOP' => 1, 'NULL' => 1, - 'READ' => 1, 'REAL' => 1, 'SHOW' => 1, 'THEN' => 1, - 'TRUE' => 1, 'UNDO' => 1, 'WHEN' => 1, 'WITH' => 1, - 'ALTER' => 1, 'CHECK' => 1, 'CROSS' => 1, 'FALSE' => 1, - 'FETCH' => 1, 'FLOAT' => 1, 'FORCE' => 1, 'GRANT' => 1, - 'GROUP' => 1, 'INDEX' => 1, 'INNER' => 1, 'INOUT' => 1, - 'LEAVE' => 1, 'LIMIT' => 1, 'LINES' => 1, 'MATCH' => 1, - 'ORDER' => 1, 'OUTER' => 1, 'PURGE' => 1, 'RANGE' => 1, - 'READS' => 1, 'RIGHT' => 1, 'RLIKE' => 1, 'TABLE' => 1, - 'UNION' => 1, 'USAGE' => 1, 'USING' => 1, 'WHERE' => 1, - 'WHILE' => 1, 'WRITE' => 1, - 'BEFORE' => 1, 'BIGINT' => 1, 'BINARY' => 1, 'CHANGE' => 1, - 'COLUMN' => 1, 'CREATE' => 1, 'CURSOR' => 1, 'DELETE' => 1, - 'DOUBLE' => 1, 'ELSEIF' => 1, 'EXISTS' => 1, 'FLOAT4' => 1, - 'FLOAT8' => 1, 'HAVING' => 1, 'IGNORE' => 1, 'INFILE' => 1, - 'INSERT' => 1, 'LINEAR' => 1, 'OPTION' => 1, 'REGEXP' => 1, - 'RENAME' => 1, 'REPEAT' => 1, 'RETURN' => 1, 'REVOKE' => 1, - 'SCHEMA' => 1, 'SELECT' => 1, 'SIGNAL' => 1, 'UNIQUE' => 1, - 'UNLOCK' => 1, 'UPDATE' => 1, 'VALUES' => 1, - 'ANALYZE' => 1, 'BETWEEN' => 1, 'CASCADE' => 1, 'COLLATE' => 1, - 'CONVERT' => 1, 'DECIMAL' => 1, 'DECLARE' => 1, 'DEFAULT' => 1, - 'DELAYED' => 1, 'ESCAPED' => 1, 'EXPLAIN' => 1, 'FOREIGN' => 1, - 'INTEGER' => 1, 'ITERATE' => 1, 'LEADING' => 1, 'NATURAL' => 1, - 'NUMERIC' => 1, 'OUTFILE' => 1, 'PRIMARY' => 1, 'RELEASE' => 1, - 'REPLACE' => 1, 'REQUIRE' => 1, 'SCHEMAS' => 1, 'SPATIAL' => 1, - 'TINYINT' => 1, 'TRIGGER' => 1, 'VARCHAR' => 1, 'VARYING' => 1, - 'CONTINUE' => 1, 'DATABASE' => 1, 'DAY_HOUR' => 1, - 'DESCRIBE' => 1, 'DISTINCT' => 1, 'ENCLOSED' => 1, - 'FULLTEXT' => 1, 'INTERVAL' => 1, 'LONGBLOB' => 1, - 'LONGTEXT' => 1, 'MAXVALUE' => 1, 'MODIFIES' => 1, - 'OPTIMIZE' => 1, 'RESIGNAL' => 1, 'RESTRICT' => 1, - 'SMALLINT' => 1, 'SPECIFIC' => 1, 'SQLSTATE' => 1, - 'STARTING' => 1, 'TINYBLOB' => 1, 'TINYTEXT' => 1, - 'TRAILING' => 1, 'UNSIGNED' => 1, 'UTC_DATE' => 1, - 'UTC_TIME' => 1, 'ZEROFILL' => 1, - 'CHARACTER' => 1, 'CONDITION' => 1, 'DATABASES' => 1, - 'LOCALTIME' => 1, 'MEDIUMINT' => 1, 'MIDDLEINT' => 1, - 'PRECISION' => 1, 'PROCEDURE' => 1, 'SENSITIVE' => 1, - 'SEPARATOR' => 1, 'VARBINARY' => 1, - 'ACCESSIBLE' => 1, 'ASENSITIVE' => 1, 'CONSTRAINT' => 1, - 'DAY_MINUTE' => 1, 'DAY_SECOND' => 1, 'MEDIUMBLOB' => 1, - 'MEDIUMTEXT' => 1, 'OPTIONALLY' => 1, 'READ_WRITE' => 1, - 'REFERENCES' => 1, 'SQLWARNING' => 1, 'TERMINATED' => 1, - 'YEAR_MONTH' => 1, - 'DISTINCTROW' => 1, 'HOUR_MINUTE' => 1, 'HOUR_SECOND' => 1, - 'INSENSITIVE' => 1, - 'CURRENT_DATE' => 1, 'CURRENT_TIME' => 1, 'CURRENT_USER' => 1, - 'LOW_PRIORITY' => 1, 'SQLEXCEPTION' => 1, 'VARCHARACTER' => 1, - 'DETERMINISTIC' => 1, 'HIGH_PRIORITY' => 1, 'MINUTE_SECOND' => 1, - 'STRAIGHT_JOIN' => 1, 'UTC_TIMESTAMP' => 1, - 'LOCALTIMESTAMP' => 1, 'SQL_BIG_RESULT' => 1, - 'DAY_MICROSECOND' => 1, - 'HOUR_MICROSECOND' => 1, 'SQL_SMALL_RESULT' => 1, - 'CURRENT_TIMESTAMP' => 1, - 'MINUTE_MICROSECOND' => 1, 'NO_WRITE_TO_BINLOG' => 1, - 'SECOND_MICROSECOND' => 1, - 'SQL_CALC_FOUND_ROWS' => 1, - 'MASTER_SSL_VERIFY_SERVER_CERT' => 1, - - 'AT' => 2, 'DO' => 2, 'IO' => 2, 'NO' => 2, 'XA' => 2, - 'ANY' => 2, 'AVG' => 2, 'BIT' => 2, 'CPU' => 2, 'DAY' => 2, 'END' => 2, - 'IPC' => 2, 'NDB' => 2, 'NEW' => 2, 'ONE' => 2, 'ROW' => 2, 'XML' => 2, - 'BOOL' => 2, 'BYTE' => 2, 'CODE' => 2, 'CUBE' => 2, 'DATA' => 2, 'DATE' => 2, - 'DISK' => 2, 'ENDS' => 2, 'ENUM' => 2, 'FAST' => 2, 'FILE' => 2, 'FULL' => 2, - 'HASH' => 2, 'HELP' => 2, 'HOST' => 2, 'HOUR' => 2, 'LAST' => 2, 'LESS' => 2, - 'LIST' => 2, 'LOGS' => 2, 'MODE' => 2, 'NAME' => 2, 'NEXT' => 2, 'NONE' => 2, - 'OPEN' => 2, 'PAGE' => 2, 'PORT' => 2, 'PREV' => 2, 'ROWS' => 2, 'SLOW' => 2, - 'SOME' => 2, 'STOP' => 2, 'TEXT' => 2, 'THAN' => 2, 'TIME' => 2, 'TYPE' => 2, - 'USER' => 2, 'VIEW' => 2, 'WAIT' => 2, 'WEEK' => 2, 'WORK' => 2, 'X509' => 2, - 'YEAR' => 2, - 'AFTER' => 2, 'ASCII' => 2, 'BEGIN' => 2, 'BLOCK' => 2, 'BTREE' => 2, - 'CACHE' => 2, 'CHAIN' => 2, 'CLOSE' => 2, 'ERROR' => 2, 'EVENT' => 2, - 'EVERY' => 2, 'FIRST' => 2, 'FIXED' => 2, 'FLUSH' => 2, 'FOUND' => 2, - 'HOSTS' => 2, 'LEVEL' => 2, 'LOCAL' => 2, 'LOCKS' => 2, 'MERGE' => 2, - 'MONTH' => 2, 'MUTEX' => 2, 'NAMES' => 2, 'NCHAR' => 2, 'OWNER' => 2, - 'PHASE' => 2, 'POINT' => 2, 'PROXY' => 2, 'QUERY' => 2, 'QUICK' => 2, - 'RELAY' => 2, 'RESET' => 2, 'RTREE' => 2, 'SHARE' => 2, 'SLAVE' => 2, - 'START' => 2, 'SUPER' => 2, 'SWAPS' => 2, 'TYPES' => 2, 'UNTIL' => 2, - 'VALUE' => 2, - 'ACTION' => 2, 'BACKUP' => 2, 'BINLOG' => 2, 'CIPHER' => 2, 'CLIENT' => 2, - 'COMMIT' => 2, 'ENABLE' => 2, 'ENGINE' => 2, 'ERRORS' => 2, 'ESCAPE' => 2, - 'EVENTS' => 2, 'FAULTS' => 2, 'FIELDS' => 2, 'GLOBAL' => 2, 'GRANTS' => 2, - 'IMPORT' => 2, 'INNODB' => 2, 'ISSUER' => 2, 'LEAVES' => 2, 'MASTER' => 2, - 'MEDIUM' => 2, 'MEMORY' => 2, 'MINUTE' => 2, 'MODIFY' => 2, 'OFFSET' => 2, - 'PARSER' => 2, 'PLUGIN' => 2, 'RELOAD' => 2, 'REMOVE' => 2, 'REPAIR' => 2, - 'RESUME' => 2, 'ROLLUP' => 2, 'SECOND' => 2, 'SERIAL' => 2, 'SERVER' => 2, - 'SIGNED' => 2, 'SIMPLE' => 2, 'SOCKET' => 2, 'SONAME' => 2, 'SOUNDS' => 2, - 'SOURCE' => 2, 'STARTS' => 2, 'STATUS' => 2, 'STRING' => 2, 'TABLES' => 2, - 'AGAINST' => 2, 'AUTHORS' => 2, 'BOOLEAN' => 2, 'CHANGED' => 2, 'CHARSET' => 2, - 'COLUMNS' => 2, 'COMMENT' => 2, 'COMPACT' => 2, 'CONTEXT' => 2, 'DEFINER' => 2, - 'DISABLE' => 2, 'DISCARD' => 2, 'DYNAMIC' => 2, 'ENGINES' => 2, 'EXECUTE' => 2, - 'GENERAL' => 2, 'HANDLER' => 2, 'INDEXES' => 2, 'INSTALL' => 2, 'INVOKER' => 2, - 'LOGFILE' => 2, 'MIGRATE' => 2, 'NO_WAIT' => 2, 'OPTIONS' => 2, 'PARTIAL' => 2, - 'PLUGINS' => 2, 'POLYGON' => 2, 'PREPARE' => 2, 'PROFILE' => 2, 'QUARTER' => 2, - 'REBUILD' => 2, 'RECOVER' => 2, 'RESTORE' => 2, 'RETURNS' => 2, 'ROUTINE' => 2, - 'SESSION' => 2, 'STORAGE' => 2, 'SUBJECT' => 2, 'SUSPEND' => 2, 'UNICODE' => 2, - 'UNKNOWN' => 2, 'UPGRADE' => 2, 'USE_FRM' => 2, 'WRAPPER' => 2, - 'CASCADED' => 2, 'CHECKSUM' => 2, 'COALESCE' => 2, 'CONTAINS' => 2, - 'DATAFILE' => 2, 'DATETIME' => 2, 'DUMPFILE' => 2, 'EXTENDED' => 2, - 'FUNCTION' => 2, 'GEOMETRY' => 2, 'INNOBASE' => 2, 'LANGUAGE' => 2, - 'MAX_ROWS' => 2, 'MAX_SIZE' => 2, 'MIN_ROWS' => 2, 'NATIONAL' => 2, - 'NVARCHAR' => 2, 'ONE_SHOT' => 2, 'PASSWORD' => 2, 'PRESERVE' => 2, - 'PROFILES' => 2, 'REDOFILE' => 2, 'RELAYLOG' => 2, 'ROLLBACK' => 2, - 'SCHEDULE' => 2, 'SECURITY' => 2, 'SHUTDOWN' => 2, 'SNAPSHOT' => 2, - 'SWITCHES' => 2, 'TRIGGERS' => 2, 'TRUNCATE' => 2, 'UNDOFILE' => 2, - 'WARNINGS' => 2, - 'AGGREGATE' => 2, 'ALGORITHM' => 2, 'COLLATION' => 2, 'COMMITTED' => 2, - 'DIRECTORY' => 2, 'DUPLICATE' => 2, 'EXPANSION' => 2, 'IO_THREAD' => 2, - 'ISOLATION' => 2, 'NODEGROUP' => 2, 'PACK_KEYS' => 2, 'PARTITION' => 2, - 'READ_ONLY' => 2, 'REDUNDANT' => 2, 'SAVEPOINT' => 2, 'SQL_CACHE' => 2, - 'TEMPORARY' => 2, 'TEMPTABLE' => 2, 'TIMESTAMP' => 2, 'UNDEFINED' => 2, - 'UNINSTALL' => 2, 'VARIABLES' => 2, - 'COMPLETION' => 2, 'COMPRESSED' => 2, 'CONCURRENT' => 2, 'CONNECTION' => 2, - 'CONSISTENT' => 2, 'DEALLOCATE' => 2, 'GET_FORMAT' => 2, 'IDENTIFIED' => 2, - 'LINESTRING' => 2, 'MASTER_SSL' => 2, 'MULTIPOINT' => 2, 'NDBCLUSTER' => 2, - 'PARTITIONS' => 2, 'PRIVILEGES' => 2, 'REORGANIZE' => 2, 'REPEATABLE' => 2, - 'ROW_FORMAT' => 2, 'SQL_THREAD' => 2, 'TABLESPACE' => 2, 'TABLE_NAME' => 2, - 'COLUMN_NAME' => 2, 'CURSOR_NAME' => 2, 'EXTENT_SIZE' => 2, 'FRAC_SECOND' => 2, - 'MASTER_HOST' => 2, 'MASTER_PORT' => 2, 'MASTER_USER' => 2, 'MICROSECOND' => 2, - 'MYSQL_ERRNO' => 2, 'PROCESSLIST' => 2, 'REPLICATION' => 2, 'SCHEMA_NAME' => 2, - 'SQL_TSI_DAY' => 2, 'TRANSACTION' => 2, 'UNCOMMITTED' => 2, - 'CATALOG_NAME' => 2, 'CLASS_ORIGIN' => 2, 'CONTRIBUTORS' => 2, - 'DES_KEY_FILE' => 2, 'INITIAL_SIZE' => 2, 'MESSAGE_TEXT' => 2, - 'MULTIPOLYGON' => 2, 'OLD_PASSWORD' => 2, 'PARTITIONING' => 2, - 'RELAY_THREAD' => 2, 'SERIALIZABLE' => 2, 'SQL_NO_CACHE' => 2, - 'SQL_TSI_HOUR' => 2, 'SQL_TSI_WEEK' => 2, 'SQL_TSI_YEAR' => 2, - 'SUBPARTITION' => 2, 'TIMESTAMPADD' => 2, - 'INSERT_METHOD' => 2, 'MASTER_SSL_CA' => 2, 'RELAY_LOG_POS' => 2, - 'SQL_TSI_MONTH' => 2, 'SUBPARTITIONS' => 2, 'TIMESTAMPDIFF' => 2, - 'AUTO_INCREMENT' => 2, 'AVG_ROW_LENGTH' => 2, 'KEY_BLOCK_SIZE' => 2, - 'MASTER_LOG_POS' => 2, 'MASTER_SSL_KEY' => 2, 'RELAY_LOG_FILE' => 2, - 'SQL_TSI_MINUTE' => 2, 'SQL_TSI_SECOND' => 2, 'TABLE_CHECKSUM' => 2, - 'USER_RESOURCES' => 2, - 'AUTOEXTEND_SIZE' => 2, 'CONSTRAINT_NAME' => 2, 'DELAY_KEY_WRITE' => 2, - 'MASTER_LOG_FILE' => 2, 'MASTER_PASSWORD' => 2, 'MASTER_SSL_CERT' => 2, - 'MULTILINESTRING' => 2, 'SQL_TSI_QUARTER' => 2, 'SUBCLASS_ORIGIN' => 2, - 'MASTER_SERVER_ID' => 2, 'REDO_BUFFER_SIZE' => 2, 'UNDO_BUFFER_SIZE' => 2, - 'CONSTRAINT_SCHEMA' => 2, 'IGNORE_SERVER_IDS' => 2, 'MASTER_SSL_CAPATH' => 2, - 'MASTER_SSL_CIPHER' => 2, 'SQL_BUFFER_RESULT' => 2, - 'CONSTRAINT_CATALOG' => 2, 'GEOMETRYCOLLECTION' => 2, - 'SQL_TSI_FRAC_SECOND' => 2, - 'MASTER_CONNECT_RETRY' => 2, 'MAX_QUERIES_PER_HOUR' => 2, - 'MAX_UPDATES_PER_HOUR' => 2, 'MAX_USER_CONNECTIONS' => 2, - 'MASTER_HEARTBEAT_PERIOD' => 2, - 'MAX_CONNECTIONS_PER_HOUR' => 2, - - 'NOT NULL' => 4, - 'INDEX KEY' => 4, - 'UNIQUE KEY' => 4, - 'FOREIGN KEY' => 4, 'PRIMARY KEY' => 4, 'PRIMARY KEY' => 4, 'SPATIAL KEY' => 4, - 'FULLTEXT KEY' => 4, 'UNIQUE INDEX' => 4, - 'CHARACTER SET' => 4, 'IF NOT EXISTS' => 4, 'SPATIAL INDEX' => 4, - 'DATA DIRECTORY' => 4, 'FULLTEXT INDEX' => 4, - 'DEFAULT COLLATE' => 4, 'INDEX DIRECTORY' => 4, - 'DEFAULT CHARACTER SET' => 4, - - ); -} diff --git a/libraries/sql-parser/src/Contexts/Context_MySQL50600.php b/libraries/sql-parser/src/Contexts/Context_MySQL50600.php deleted file mode 100644 index dfd114ace1..0000000000 --- a/libraries/sql-parser/src/Contexts/Context_MySQL50600.php +++ /dev/null @@ -1,199 +0,0 @@ - - * @license http://opensource.org/licenses/GPL-2.0 GNU Public License - */ -class Context_MySQL50600 extends Context -{ - - public static $KEYWORDS = array( - - 'AS' => 1, 'BY' => 1, 'IF' => 1, 'IN' => 1, 'IS' => 1, - 'ON' => 1, 'OR' => 1, 'TO' => 1, - 'ADD' => 1, 'ALL' => 1, 'AND' => 1, 'ASC' => 1, 'DEC' => 1, - 'DIV' => 1, 'FOR' => 1, 'GET' => 1, 'INT' => 1, 'KEY' => 1, - 'MOD' => 1, 'NOT' => 1, 'OUT' => 1, 'SET' => 1, 'SQL' => 1, - 'SSL' => 1, 'USE' => 1, 'XOR' => 1, - 'BLOB' => 1, 'BOTH' => 1, 'CALL' => 1, 'CASE' => 1, - 'CHAR' => 1, 'DESC' => 1, 'DROP' => 1, 'DUAL' => 1, - 'EACH' => 1, 'ELSE' => 1, 'EXIT' => 1, 'FROM' => 1, - 'INT1' => 1, 'INT2' => 1, 'INT3' => 1, 'INT4' => 1, - 'INT8' => 1, 'INTO' => 1, 'JOIN' => 1, 'KEYS' => 1, - 'KILL' => 1, 'LEFT' => 1, 'LIKE' => 1, 'LOAD' => 1, - 'LOCK' => 1, 'LONG' => 1, 'LOOP' => 1, 'NULL' => 1, - 'READ' => 1, 'REAL' => 1, 'SHOW' => 1, 'THEN' => 1, - 'TRUE' => 1, 'UNDO' => 1, 'WHEN' => 1, 'WITH' => 1, - 'ALTER' => 1, 'CHECK' => 1, 'CROSS' => 1, 'FALSE' => 1, - 'FETCH' => 1, 'FLOAT' => 1, 'FORCE' => 1, 'GRANT' => 1, - 'GROUP' => 1, 'INDEX' => 1, 'INNER' => 1, 'INOUT' => 1, - 'LEAVE' => 1, 'LIMIT' => 1, 'LINES' => 1, 'MATCH' => 1, - 'ORDER' => 1, 'OUTER' => 1, 'PURGE' => 1, 'RANGE' => 1, - 'READS' => 1, 'RIGHT' => 1, 'RLIKE' => 1, 'TABLE' => 1, - 'UNION' => 1, 'USAGE' => 1, 'USING' => 1, 'WHERE' => 1, - 'WHILE' => 1, 'WRITE' => 1, - 'BEFORE' => 1, 'BIGINT' => 1, 'BINARY' => 1, 'CHANGE' => 1, - 'COLUMN' => 1, 'CREATE' => 1, 'CURSOR' => 1, 'DELETE' => 1, - 'DOUBLE' => 1, 'ELSEIF' => 1, 'EXISTS' => 1, 'FLOAT4' => 1, - 'FLOAT8' => 1, 'HAVING' => 1, 'IGNORE' => 1, 'INFILE' => 1, - 'INSERT' => 1, 'LINEAR' => 1, 'OPTION' => 1, 'REGEXP' => 1, - 'RENAME' => 1, 'REPEAT' => 1, 'RETURN' => 1, 'REVOKE' => 1, - 'SCHEMA' => 1, 'SELECT' => 1, 'SIGNAL' => 1, 'UNIQUE' => 1, - 'UNLOCK' => 1, 'UPDATE' => 1, 'VALUES' => 1, - 'ANALYZE' => 1, 'BETWEEN' => 1, 'CASCADE' => 1, 'COLLATE' => 1, - 'CONVERT' => 1, 'DECIMAL' => 1, 'DECLARE' => 1, 'DEFAULT' => 1, - 'DELAYED' => 1, 'ESCAPED' => 1, 'EXPLAIN' => 1, 'FOREIGN' => 1, - 'INTEGER' => 1, 'ITERATE' => 1, 'LEADING' => 1, 'NATURAL' => 1, - 'NUMERIC' => 1, 'OUTFILE' => 1, 'PRIMARY' => 1, 'RELEASE' => 1, - 'REPLACE' => 1, 'REQUIRE' => 1, 'SCHEMAS' => 1, 'SPATIAL' => 1, - 'TINYINT' => 1, 'TRIGGER' => 1, 'VARCHAR' => 1, 'VARYING' => 1, - 'CONTINUE' => 1, 'DATABASE' => 1, 'DAY_HOUR' => 1, - 'DESCRIBE' => 1, 'DISTINCT' => 1, 'ENCLOSED' => 1, - 'FULLTEXT' => 1, 'INTERVAL' => 1, 'LONGBLOB' => 1, - 'LONGTEXT' => 1, 'MAXVALUE' => 1, 'MODIFIES' => 1, - 'OPTIMIZE' => 1, 'RESIGNAL' => 1, 'RESTRICT' => 1, - 'SMALLINT' => 1, 'SPECIFIC' => 1, 'SQLSTATE' => 1, - 'STARTING' => 1, 'TINYBLOB' => 1, 'TINYTEXT' => 1, - 'TRAILING' => 1, 'UNSIGNED' => 1, 'UTC_DATE' => 1, - 'UTC_TIME' => 1, 'ZEROFILL' => 1, - 'CHARACTER' => 1, 'CONDITION' => 1, 'DATABASES' => 1, - 'LOCALTIME' => 1, 'MEDIUMINT' => 1, 'MIDDLEINT' => 1, - 'PARTITION' => 1, 'PRECISION' => 1, 'PROCEDURE' => 1, - 'SENSITIVE' => 1, 'SEPARATOR' => 1, 'VARBINARY' => 1, - 'ACCESSIBLE' => 1, 'ASENSITIVE' => 1, 'CONSTRAINT' => 1, - 'DAY_MINUTE' => 1, 'DAY_SECOND' => 1, 'MEDIUMBLOB' => 1, - 'MEDIUMTEXT' => 1, 'OPTIONALLY' => 1, 'READ_WRITE' => 1, - 'REFERENCES' => 1, 'SQLWARNING' => 1, 'TERMINATED' => 1, - 'YEAR_MONTH' => 1, - 'DISTINCTROW' => 1, 'HOUR_MINUTE' => 1, 'HOUR_SECOND' => 1, - 'INSENSITIVE' => 1, 'MASTER_BIND' => 1, - 'CURRENT_DATE' => 1, 'CURRENT_TIME' => 1, 'CURRENT_USER' => 1, - 'LOW_PRIORITY' => 1, 'SQLEXCEPTION' => 1, 'VARCHARACTER' => 1, - 'DETERMINISTIC' => 1, 'HIGH_PRIORITY' => 1, 'MINUTE_SECOND' => 1, - 'STRAIGHT_JOIN' => 1, 'UTC_TIMESTAMP' => 1, - 'IO_AFTER_GTIDS' => 1, 'LOCALTIMESTAMP' => 1, 'SQL_BIG_RESULT' => 1, - 'DAY_MICROSECOND' => 1, 'IO_BEFORE_GTIDS' => 1, - 'HOUR_MICROSECOND' => 1, 'SQL_SMALL_RESULT' => 1, - 'CURRENT_TIMESTAMP' => 1, - 'MINUTE_MICROSECOND' => 1, 'NO_WRITE_TO_BINLOG' => 1, - 'SECOND_MICROSECOND' => 1, - 'SQL_CALC_FOUND_ROWS' => 1, - 'MASTER_SSL_VERIFY_SERVER_CERT' => 1, - - 'AT' => 2, 'DO' => 2, 'IO' => 2, 'NO' => 2, 'XA' => 2, - 'ANY' => 2, 'AVG' => 2, 'BIT' => 2, 'CPU' => 2, 'DAY' => 2, 'END' => 2, - 'IPC' => 2, 'NDB' => 2, 'NEW' => 2, 'ONE' => 2, 'ROW' => 2, 'XML' => 2, - 'BOOL' => 2, 'BYTE' => 2, 'CODE' => 2, 'CUBE' => 2, 'DATA' => 2, 'DATE' => 2, - 'DISK' => 2, 'ENDS' => 2, 'ENUM' => 2, 'FAST' => 2, 'FILE' => 2, 'FULL' => 2, - 'HASH' => 2, 'HELP' => 2, 'HOST' => 2, 'HOUR' => 2, 'LAST' => 2, 'LESS' => 2, - 'LIST' => 2, 'LOGS' => 2, 'MODE' => 2, 'NAME' => 2, 'NEXT' => 2, 'NONE' => 2, - 'ONLY' => 2, 'OPEN' => 2, 'PAGE' => 2, 'PORT' => 2, 'PREV' => 2, 'ROWS' => 2, - 'SLOW' => 2, 'SOME' => 2, 'STOP' => 2, 'TEXT' => 2, 'THAN' => 2, 'TIME' => 2, - 'TYPE' => 2, 'USER' => 2, 'VIEW' => 2, 'WAIT' => 2, 'WEEK' => 2, 'WORK' => 2, - 'X509' => 2, 'YEAR' => 2, - 'AFTER' => 2, 'ASCII' => 2, 'BEGIN' => 2, 'BLOCK' => 2, 'BTREE' => 2, - 'CACHE' => 2, 'CHAIN' => 2, 'CLOSE' => 2, 'ERROR' => 2, 'EVENT' => 2, - 'EVERY' => 2, 'FIRST' => 2, 'FIXED' => 2, 'FLUSH' => 2, 'FOUND' => 2, - 'HOSTS' => 2, 'LEVEL' => 2, 'LOCAL' => 2, 'LOCKS' => 2, 'MERGE' => 2, - 'MONTH' => 2, 'MUTEX' => 2, 'NAMES' => 2, 'NCHAR' => 2, 'OWNER' => 2, - 'PHASE' => 2, 'POINT' => 2, 'PROXY' => 2, 'QUERY' => 2, 'QUICK' => 2, - 'RELAY' => 2, 'RESET' => 2, 'RTREE' => 2, 'SHARE' => 2, 'SLAVE' => 2, - 'START' => 2, 'SUPER' => 2, 'SWAPS' => 2, 'TYPES' => 2, 'UNTIL' => 2, - 'VALUE' => 2, - 'ACTION' => 2, 'BACKUP' => 2, 'BINLOG' => 2, 'CIPHER' => 2, 'CLIENT' => 2, - 'COMMIT' => 2, 'ENABLE' => 2, 'ENGINE' => 2, 'ERRORS' => 2, 'ESCAPE' => 2, - 'EVENTS' => 2, 'EXPIRE' => 2, 'EXPORT' => 2, 'FAULTS' => 2, 'FIELDS' => 2, - 'FORMAT' => 2, 'GLOBAL' => 2, 'GRANTS' => 2, 'IMPORT' => 2, 'ISSUER' => 2, - 'LEAVES' => 2, 'MASTER' => 2, 'MEDIUM' => 2, 'MEMORY' => 2, 'MINUTE' => 2, - 'MODIFY' => 2, 'NUMBER' => 2, 'OFFSET' => 2, 'PARSER' => 2, 'PLUGIN' => 2, - 'RELOAD' => 2, 'REMOVE' => 2, 'REPAIR' => 2, 'RESUME' => 2, 'ROLLUP' => 2, - 'SECOND' => 2, 'SERIAL' => 2, 'SERVER' => 2, 'SIGNED' => 2, 'SIMPLE' => 2, - 'SOCKET' => 2, 'SONAME' => 2, 'SOUNDS' => 2, 'SOURCE' => 2, 'STARTS' => 2, - 'STATUS' => 2, 'STRING' => 2, 'TABLES' => 2, - 'AGAINST' => 2, 'ANALYSE' => 2, 'AUTHORS' => 2, 'BOOLEAN' => 2, 'CHANGED' => 2, - 'CHARSET' => 2, 'COLUMNS' => 2, 'COMMENT' => 2, 'COMPACT' => 2, 'CONTEXT' => 2, - 'CURRENT' => 2, 'DEFINER' => 2, 'DISABLE' => 2, 'DISCARD' => 2, 'DYNAMIC' => 2, - 'ENGINES' => 2, 'EXECUTE' => 2, 'GENERAL' => 2, 'HANDLER' => 2, 'INDEXES' => 2, - 'INSTALL' => 2, 'INVOKER' => 2, 'LOGFILE' => 2, 'MIGRATE' => 2, 'NO_WAIT' => 2, - 'OPTIONS' => 2, 'PARTIAL' => 2, 'PLUGINS' => 2, 'POLYGON' => 2, 'PREPARE' => 2, - 'PROFILE' => 2, 'QUARTER' => 2, 'REBUILD' => 2, 'RECOVER' => 2, 'RESTORE' => 2, - 'RETURNS' => 2, 'REVERSE' => 2, 'ROUTINE' => 2, 'SESSION' => 2, 'STORAGE' => 2, - 'SUBJECT' => 2, 'SUSPEND' => 2, 'UNICODE' => 2, 'UNKNOWN' => 2, 'UPGRADE' => 2, - 'USE_FRM' => 2, 'WRAPPER' => 2, - 'CASCADED' => 2, 'CHECKSUM' => 2, 'COALESCE' => 2, 'CONTAINS' => 2, - 'DATAFILE' => 2, 'DATETIME' => 2, 'DUMPFILE' => 2, 'EXCHANGE' => 2, - 'EXTENDED' => 2, 'FUNCTION' => 2, 'GEOMETRY' => 2, 'LANGUAGE' => 2, - 'MAX_ROWS' => 2, 'MAX_SIZE' => 2, 'MIN_ROWS' => 2, 'NATIONAL' => 2, - 'NVARCHAR' => 2, 'ONE_SHOT' => 2, 'PASSWORD' => 2, 'PRESERVE' => 2, - 'PROFILES' => 2, 'REDOFILE' => 2, 'RELAYLOG' => 2, 'ROLLBACK' => 2, - 'SCHEDULE' => 2, 'SECURITY' => 2, 'SHUTDOWN' => 2, 'SNAPSHOT' => 2, - 'SWITCHES' => 2, 'TRIGGERS' => 2, 'TRUNCATE' => 2, 'UNDOFILE' => 2, - 'WARNINGS' => 2, - 'AGGREGATE' => 2, 'ALGORITHM' => 2, 'COLLATION' => 2, 'COMMITTED' => 2, - 'DIRECTORY' => 2, 'DUPLICATE' => 2, 'EXPANSION' => 2, 'IO_THREAD' => 2, - 'ISOLATION' => 2, 'NODEGROUP' => 2, 'PACK_KEYS' => 2, 'READ_ONLY' => 2, - 'REDUNDANT' => 2, 'ROW_COUNT' => 2, 'SAVEPOINT' => 2, 'SQL_CACHE' => 2, - 'TEMPORARY' => 2, 'TEMPTABLE' => 2, 'TIMESTAMP' => 2, 'UNDEFINED' => 2, - 'UNINSTALL' => 2, 'VARIABLES' => 2, - 'COMPLETION' => 2, 'COMPRESSED' => 2, 'CONCURRENT' => 2, 'CONNECTION' => 2, - 'CONSISTENT' => 2, 'DEALLOCATE' => 2, 'GET_FORMAT' => 2, 'IDENTIFIED' => 2, - 'LINESTRING' => 2, 'MASTER_SSL' => 2, 'MULTIPOINT' => 2, 'NDBCLUSTER' => 2, - 'PARTITIONS' => 2, 'PLUGIN_DIR' => 2, 'PRIVILEGES' => 2, 'REORGANIZE' => 2, - 'REPEATABLE' => 2, 'ROW_FORMAT' => 2, 'SQL_THREAD' => 2, 'TABLESPACE' => 2, - 'TABLE_NAME' => 2, - 'COLUMN_NAME' => 2, 'CURSOR_NAME' => 2, 'DIAGNOSTICS' => 2, 'EXTENT_SIZE' => 2, - 'MASTER_HOST' => 2, 'MASTER_PORT' => 2, 'MASTER_USER' => 2, 'MICROSECOND' => 2, - 'MYSQL_ERRNO' => 2, 'PROCESSLIST' => 2, 'REPLICATION' => 2, 'SCHEMA_NAME' => 2, - 'SQL_TSI_DAY' => 2, 'TRANSACTION' => 2, 'UNCOMMITTED' => 2, - 'CATALOG_NAME' => 2, 'CLASS_ORIGIN' => 2, 'CONTRIBUTORS' => 2, - 'DEFAULT_AUTH' => 2, 'DES_KEY_FILE' => 2, 'INITIAL_SIZE' => 2, - 'MASTER_DELAY' => 2, 'MESSAGE_TEXT' => 2, 'MULTIPOLYGON' => 2, - 'OLD_PASSWORD' => 2, 'PARTITIONING' => 2, 'RELAY_THREAD' => 2, - 'SERIALIZABLE' => 2, 'SQL_NO_CACHE' => 2, 'SQL_TSI_HOUR' => 2, - 'SQL_TSI_WEEK' => 2, 'SQL_TSI_YEAR' => 2, 'SUBPARTITION' => 2, - 'TIMESTAMPADD' => 2, - 'COLUMN_FORMAT' => 2, 'INSERT_METHOD' => 2, 'MASTER_SSL_CA' => 2, - 'RELAY_LOG_POS' => 2, 'SQL_TSI_MONTH' => 2, 'SUBPARTITIONS' => 2, - 'TIMESTAMPDIFF' => 2, 'WEIGHT_STRING' => 2, - 'AUTO_INCREMENT' => 2, 'AVG_ROW_LENGTH' => 2, 'KEY_BLOCK_SIZE' => 2, - 'MASTER_LOG_POS' => 2, 'MASTER_SSL_CRL' => 2, 'MASTER_SSL_KEY' => 2, - 'RELAY_LOG_FILE' => 2, 'SQL_TSI_MINUTE' => 2, 'SQL_TSI_SECOND' => 2, - 'TABLE_CHECKSUM' => 2, 'USER_RESOURCES' => 2, - 'AUTOEXTEND_SIZE' => 2, 'CONSTRAINT_NAME' => 2, 'DELAY_KEY_WRITE' => 2, - 'MASTER_LOG_FILE' => 2, 'MASTER_PASSWORD' => 2, 'MASTER_SSL_CERT' => 2, - 'MULTILINESTRING' => 2, 'SQL_AFTER_GTIDS' => 2, 'SQL_TSI_QUARTER' => 2, - 'SUBCLASS_ORIGIN' => 2, - 'MASTER_SERVER_ID' => 2, 'REDO_BUFFER_SIZE' => 2, 'SQL_BEFORE_GTIDS' => 2, - 'STATS_PERSISTENT' => 2, 'UNDO_BUFFER_SIZE' => 2, - 'CONSTRAINT_SCHEMA' => 2, 'IGNORE_SERVER_IDS' => 2, 'MASTER_SSL_CAPATH' => 2, - 'MASTER_SSL_CIPHER' => 2, 'RETURNED_SQLSTATE' => 2, 'SQL_BUFFER_RESULT' => 2, - 'STATS_AUTO_RECALC' => 2, - 'CONSTRAINT_CATALOG' => 2, 'GEOMETRYCOLLECTION' => 2, 'MASTER_RETRY_COUNT' => 2, - 'MASTER_SSL_CRLPATH' => 2, 'SQL_AFTER_MTS_GAPS' => 2, 'STATS_SAMPLE_PAGES' => 2, - 'MASTER_AUTO_POSITION' => 2, 'MASTER_CONNECT_RETRY' => 2, - 'MAX_QUERIES_PER_HOUR' => 2, 'MAX_UPDATES_PER_HOUR' => 2, - 'MAX_USER_CONNECTIONS' => 2, - 'MASTER_HEARTBEAT_PERIOD' => 2, - 'MAX_CONNECTIONS_PER_HOUR' => 2, - - 'NOT NULL' => 4, - 'INDEX KEY' => 4, - 'UNIQUE KEY' => 4, - 'FOREIGN KEY' => 4, 'PRIMARY KEY' => 4, 'PRIMARY KEY' => 4, 'SPATIAL KEY' => 4, - 'FULLTEXT KEY' => 4, 'UNIQUE INDEX' => 4, - 'CHARACTER SET' => 4, 'IF NOT EXISTS' => 4, 'SPATIAL INDEX' => 4, - 'DATA DIRECTORY' => 4, 'FULLTEXT INDEX' => 4, - 'DEFAULT COLLATE' => 4, 'INDEX DIRECTORY' => 4, - 'DEFAULT CHARACTER SET' => 4, - - ); -} diff --git a/libraries/sql-parser/src/Contexts/Context_MySQL50700.php b/libraries/sql-parser/src/Contexts/Context_MySQL50700.php deleted file mode 100644 index b795b2d6e7..0000000000 --- a/libraries/sql-parser/src/Contexts/Context_MySQL50700.php +++ /dev/null @@ -1,208 +0,0 @@ - - * @license http://opensource.org/licenses/GPL-2.0 GNU Public License - */ -class Context_MySQL50700 extends Context -{ - - public static $KEYWORDS = array( - - 'AS' => 1, 'BY' => 1, 'IF' => 1, 'IN' => 1, 'IS' => 1, - 'ON' => 1, 'OR' => 1, 'TO' => 1, - 'ADD' => 1, 'ALL' => 1, 'AND' => 1, 'ASC' => 1, 'DEC' => 1, - 'DIV' => 1, 'FOR' => 1, 'GET' => 1, 'INT' => 1, 'KEY' => 1, - 'MOD' => 1, 'NOT' => 1, 'OUT' => 1, 'SET' => 1, 'SQL' => 1, - 'SSL' => 1, 'USE' => 1, 'XOR' => 1, - 'BLOB' => 1, 'BOTH' => 1, 'CALL' => 1, 'CASE' => 1, - 'CHAR' => 1, 'DESC' => 1, 'DROP' => 1, 'DUAL' => 1, - 'EACH' => 1, 'ELSE' => 1, 'EXIT' => 1, 'FROM' => 1, - 'INT1' => 1, 'INT2' => 1, 'INT3' => 1, 'INT4' => 1, - 'INT8' => 1, 'INTO' => 1, 'JOIN' => 1, 'KEYS' => 1, - 'KILL' => 1, 'LEFT' => 1, 'LIKE' => 1, 'LOAD' => 1, - 'LOCK' => 1, 'LONG' => 1, 'LOOP' => 1, 'NULL' => 1, - 'READ' => 1, 'REAL' => 1, 'SHOW' => 1, 'THEN' => 1, - 'TRUE' => 1, 'UNDO' => 1, 'WHEN' => 1, 'WITH' => 1, - 'ALTER' => 1, 'CHECK' => 1, 'CROSS' => 1, 'FALSE' => 1, - 'FETCH' => 1, 'FLOAT' => 1, 'FORCE' => 1, 'GRANT' => 1, - 'GROUP' => 1, 'INDEX' => 1, 'INNER' => 1, 'INOUT' => 1, - 'LEAVE' => 1, 'LIMIT' => 1, 'LINES' => 1, 'MATCH' => 1, - 'ORDER' => 1, 'OUTER' => 1, 'PURGE' => 1, 'RANGE' => 1, - 'READS' => 1, 'RIGHT' => 1, 'RLIKE' => 1, 'TABLE' => 1, - 'UNION' => 1, 'USAGE' => 1, 'USING' => 1, 'WHERE' => 1, - 'WHILE' => 1, 'WRITE' => 1, - 'BEFORE' => 1, 'BIGINT' => 1, 'BINARY' => 1, 'CHANGE' => 1, - 'COLUMN' => 1, 'CREATE' => 1, 'CURSOR' => 1, 'DELETE' => 1, - 'DOUBLE' => 1, 'ELSEIF' => 1, 'EXISTS' => 1, 'FLOAT4' => 1, - 'FLOAT8' => 1, 'HAVING' => 1, 'IGNORE' => 1, 'INFILE' => 1, - 'INSERT' => 1, 'LINEAR' => 1, 'OPTION' => 1, 'REGEXP' => 1, - 'RENAME' => 1, 'REPEAT' => 1, 'RETURN' => 1, 'REVOKE' => 1, - 'SCHEMA' => 1, 'SELECT' => 1, 'SIGNAL' => 1, 'STORED' => 1, - 'UNIQUE' => 1, 'UNLOCK' => 1, 'UPDATE' => 1, 'VALUES' => 1, - 'ANALYZE' => 1, 'BETWEEN' => 1, 'CASCADE' => 1, 'COLLATE' => 1, - 'CONVERT' => 1, 'DECIMAL' => 1, 'DECLARE' => 1, 'DEFAULT' => 1, - 'DELAYED' => 1, 'ESCAPED' => 1, 'EXPLAIN' => 1, 'FOREIGN' => 1, - 'INTEGER' => 1, 'ITERATE' => 1, 'LEADING' => 1, 'NATURAL' => 1, - 'NUMERIC' => 1, 'OUTFILE' => 1, 'PRIMARY' => 1, 'RELEASE' => 1, - 'REPLACE' => 1, 'REQUIRE' => 1, 'SCHEMAS' => 1, 'SPATIAL' => 1, - 'TINYINT' => 1, 'TRIGGER' => 1, 'VARCHAR' => 1, 'VARYING' => 1, - 'VIRTUAL' => 1, - 'CONTINUE' => 1, 'DATABASE' => 1, 'DAY_HOUR' => 1, - 'DESCRIBE' => 1, 'DISTINCT' => 1, 'ENCLOSED' => 1, - 'FULLTEXT' => 1, 'INTERVAL' => 1, 'LONGBLOB' => 1, - 'LONGTEXT' => 1, 'MAXVALUE' => 1, 'MODIFIES' => 1, - 'OPTIMIZE' => 1, 'RESIGNAL' => 1, 'RESTRICT' => 1, - 'SMALLINT' => 1, 'SPECIFIC' => 1, 'SQLSTATE' => 1, - 'STARTING' => 1, 'TINYBLOB' => 1, 'TINYTEXT' => 1, - 'TRAILING' => 1, 'UNSIGNED' => 1, 'UTC_DATE' => 1, - 'UTC_TIME' => 1, 'ZEROFILL' => 1, - 'CHARACTER' => 1, 'CONDITION' => 1, 'DATABASES' => 1, - 'GENERATED' => 1, 'LOCALTIME' => 1, 'MEDIUMINT' => 1, - 'MIDDLEINT' => 1, 'PARTITION' => 1, 'PRECISION' => 1, - 'PROCEDURE' => 1, 'SENSITIVE' => 1, 'SEPARATOR' => 1, - 'VARBINARY' => 1, - 'ACCESSIBLE' => 1, 'ASENSITIVE' => 1, 'CONSTRAINT' => 1, - 'DAY_MINUTE' => 1, 'DAY_SECOND' => 1, 'MEDIUMBLOB' => 1, - 'MEDIUMTEXT' => 1, 'OPTIONALLY' => 1, 'READ_WRITE' => 1, - 'REFERENCES' => 1, 'SQLWARNING' => 1, 'TERMINATED' => 1, - 'YEAR_MONTH' => 1, - 'DISTINCTROW' => 1, 'HOUR_MINUTE' => 1, 'HOUR_SECOND' => 1, - 'INSENSITIVE' => 1, 'MASTER_BIND' => 1, - 'CURRENT_DATE' => 1, 'CURRENT_TIME' => 1, 'CURRENT_USER' => 1, - 'LOW_PRIORITY' => 1, 'SQLEXCEPTION' => 1, 'VARCHARACTER' => 1, - 'DETERMINISTIC' => 1, 'HIGH_PRIORITY' => 1, 'MINUTE_SECOND' => 1, - 'STRAIGHT_JOIN' => 1, 'UTC_TIMESTAMP' => 1, - 'IO_AFTER_GTIDS' => 1, 'LOCALTIMESTAMP' => 1, 'SQL_BIG_RESULT' => 1, - 'DAY_MICROSECOND' => 1, 'IO_BEFORE_GTIDS' => 1, 'OPTIMIZER_COSTS' => 1, - 'HOUR_MICROSECOND' => 1, 'SQL_SMALL_RESULT' => 1, - 'CURRENT_TIMESTAMP' => 1, - 'MINUTE_MICROSECOND' => 1, 'NO_WRITE_TO_BINLOG' => 1, - 'SECOND_MICROSECOND' => 1, - 'SQL_CALC_FOUND_ROWS' => 1, - 'MASTER_SSL_VERIFY_SERVER_CERT' => 1, - - 'AT' => 2, 'DO' => 2, 'IO' => 2, 'NO' => 2, 'XA' => 2, - 'ANY' => 2, 'AVG' => 2, 'BIT' => 2, 'CPU' => 2, 'DAY' => 2, 'END' => 2, - 'IPC' => 2, 'NDB' => 2, 'NEW' => 2, 'ONE' => 2, 'ROW' => 2, 'XID' => 2, - 'XML' => 2, - 'BOOL' => 2, 'BYTE' => 2, 'CODE' => 2, 'CUBE' => 2, 'DATA' => 2, 'DATE' => 2, - 'DISK' => 2, 'ENDS' => 2, 'ENUM' => 2, 'FAST' => 2, 'FILE' => 2, 'FULL' => 2, - 'HASH' => 2, 'HELP' => 2, 'HOST' => 2, 'HOUR' => 2, 'LAST' => 2, 'LESS' => 2, - 'LIST' => 2, 'LOGS' => 2, 'MODE' => 2, 'NAME' => 2, 'NEXT' => 2, 'NONE' => 2, - 'ONLY' => 2, 'OPEN' => 2, 'PAGE' => 2, 'PORT' => 2, 'PREV' => 2, 'ROWS' => 2, - 'SLOW' => 2, 'SOME' => 2, 'STOP' => 2, 'TEXT' => 2, 'THAN' => 2, 'TIME' => 2, - 'TYPE' => 2, 'USER' => 2, 'VIEW' => 2, 'WAIT' => 2, 'WEEK' => 2, 'WORK' => 2, - 'X509' => 2, 'YEAR' => 2, - 'AFTER' => 2, 'ASCII' => 2, 'BEGIN' => 2, 'BLOCK' => 2, 'BTREE' => 2, - 'CACHE' => 2, 'CHAIN' => 2, 'CLOSE' => 2, 'ERROR' => 2, 'EVENT' => 2, - 'EVERY' => 2, 'FIRST' => 2, 'FIXED' => 2, 'FLUSH' => 2, 'FOUND' => 2, - 'HOSTS' => 2, 'LEVEL' => 2, 'LOCAL' => 2, 'LOCKS' => 2, 'MERGE' => 2, - 'MONTH' => 2, 'MUTEX' => 2, 'NAMES' => 2, 'NCHAR' => 2, 'NEVER' => 2, - 'OWNER' => 2, 'PHASE' => 2, 'POINT' => 2, 'PROXY' => 2, 'QUERY' => 2, - 'QUICK' => 2, 'RELAY' => 2, 'RESET' => 2, 'RTREE' => 2, 'SHARE' => 2, - 'SLAVE' => 2, 'START' => 2, 'SUPER' => 2, 'SWAPS' => 2, 'TYPES' => 2, - 'UNTIL' => 2, 'VALUE' => 2, - 'ACTION' => 2, 'ALWAYS' => 2, 'BACKUP' => 2, 'BINLOG' => 2, 'CIPHER' => 2, - 'CLIENT' => 2, 'COMMIT' => 2, 'ENABLE' => 2, 'ENGINE' => 2, 'ERRORS' => 2, - 'ESCAPE' => 2, 'EVENTS' => 2, 'EXPIRE' => 2, 'EXPORT' => 2, 'FAULTS' => 2, - 'FIELDS' => 2, 'FILTER' => 2, 'FORMAT' => 2, 'GLOBAL' => 2, 'GRANTS' => 2, - 'IMPORT' => 2, 'ISSUER' => 2, 'LEAVES' => 2, 'MASTER' => 2, 'MEDIUM' => 2, - 'MEMORY' => 2, 'MINUTE' => 2, 'MODIFY' => 2, 'NUMBER' => 2, 'OFFSET' => 2, - 'PARSER' => 2, 'PLUGIN' => 2, 'RELOAD' => 2, 'REMOVE' => 2, 'REPAIR' => 2, - 'RESUME' => 2, 'ROLLUP' => 2, 'SECOND' => 2, 'SERIAL' => 2, 'SERVER' => 2, - 'SIGNED' => 2, 'SIMPLE' => 2, 'SOCKET' => 2, 'SONAME' => 2, 'SOUNDS' => 2, - 'SOURCE' => 2, 'STARTS' => 2, 'STATUS' => 2, 'STRING' => 2, 'TABLES' => 2, - 'ACCOUNT' => 2, 'AGAINST' => 2, 'ANALYSE' => 2, 'BOOLEAN' => 2, 'CHANGED' => 2, - 'CHANNEL' => 2, 'CHARSET' => 2, 'COLUMNS' => 2, 'COMMENT' => 2, 'COMPACT' => 2, - 'CONTEXT' => 2, 'CURRENT' => 2, 'DEFINER' => 2, 'DISABLE' => 2, 'DISCARD' => 2, - 'DYNAMIC' => 2, 'ENGINES' => 2, 'EXECUTE' => 2, 'FOLLOWS' => 2, 'GENERAL' => 2, - 'HANDLER' => 2, 'INDEXES' => 2, 'INSTALL' => 2, 'INVOKER' => 2, 'LOGFILE' => 2, - 'MIGRATE' => 2, 'NO_WAIT' => 2, 'OPTIONS' => 2, 'PARTIAL' => 2, 'PLUGINS' => 2, - 'POLYGON' => 2, 'PREPARE' => 2, 'PROFILE' => 2, 'QUARTER' => 2, 'REBUILD' => 2, - 'RECOVER' => 2, 'RESTORE' => 2, 'RETURNS' => 2, 'REVERSE' => 2, 'ROUTINE' => 2, - 'SESSION' => 2, 'STACKED' => 2, 'STORAGE' => 2, 'SUBJECT' => 2, 'SUSPEND' => 2, - 'UNICODE' => 2, 'UNKNOWN' => 2, 'UPGRADE' => 2, 'USE_FRM' => 2, 'WITHOUT' => 2, - 'WRAPPER' => 2, - 'CASCADED' => 2, 'CHECKSUM' => 2, 'COALESCE' => 2, 'CONTAINS' => 2, - 'DATAFILE' => 2, 'DATETIME' => 2, 'DUMPFILE' => 2, 'EXCHANGE' => 2, - 'EXTENDED' => 2, 'FUNCTION' => 2, 'GEOMETRY' => 2, 'LANGUAGE' => 2, - 'MAX_ROWS' => 2, 'MAX_SIZE' => 2, 'MIN_ROWS' => 2, 'NATIONAL' => 2, - 'NVARCHAR' => 2, 'PASSWORD' => 2, 'PRECEDES' => 2, 'PRESERVE' => 2, - 'PROFILES' => 2, 'REDOFILE' => 2, 'RELAYLOG' => 2, 'ROLLBACK' => 2, - 'SCHEDULE' => 2, 'SECURITY' => 2, 'SHUTDOWN' => 2, 'SNAPSHOT' => 2, - 'SWITCHES' => 2, 'TRIGGERS' => 2, 'TRUNCATE' => 2, 'UNDOFILE' => 2, - 'WARNINGS' => 2, - 'AGGREGATE' => 2, 'ALGORITHM' => 2, 'COLLATION' => 2, 'COMMITTED' => 2, - 'DIRECTORY' => 2, 'DUPLICATE' => 2, 'EXPANSION' => 2, 'IO_THREAD' => 2, - 'ISOLATION' => 2, 'NODEGROUP' => 2, 'PACK_KEYS' => 2, 'READ_ONLY' => 2, - 'REDUNDANT' => 2, 'ROW_COUNT' => 2, 'SAVEPOINT' => 2, 'SQL_CACHE' => 2, - 'TEMPORARY' => 2, 'TEMPTABLE' => 2, 'TIMESTAMP' => 2, 'UNDEFINED' => 2, - 'UNINSTALL' => 2, 'VARIABLES' => 2, - 'COMPLETION' => 2, 'COMPRESSED' => 2, 'CONCURRENT' => 2, 'CONNECTION' => 2, - 'CONSISTENT' => 2, 'DEALLOCATE' => 2, 'GET_FORMAT' => 2, 'IDENTIFIED' => 2, - 'LINESTRING' => 2, 'MASTER_SSL' => 2, 'MULTIPOINT' => 2, 'NDBCLUSTER' => 2, - 'PARTITIONS' => 2, 'PLUGIN_DIR' => 2, 'PRIVILEGES' => 2, 'REORGANIZE' => 2, - 'REPEATABLE' => 2, 'ROW_FORMAT' => 2, 'SQL_THREAD' => 2, 'TABLESPACE' => 2, - 'TABLE_NAME' => 2, 'VALIDATION' => 2, - 'COLUMN_NAME' => 2, 'COMPRESSION' => 2, 'CURSOR_NAME' => 2, 'DIAGNOSTICS' => 2, - 'EXTENT_SIZE' => 2, 'MASTER_HOST' => 2, 'MASTER_PORT' => 2, 'MASTER_USER' => 2, - 'MICROSECOND' => 2, 'MYSQL_ERRNO' => 2, 'NONBLOCKING' => 2, 'PROCESSLIST' => 2, - 'REPLICATION' => 2, 'SCHEMA_NAME' => 2, 'SQL_TSI_DAY' => 2, 'TRANSACTION' => 2, - 'UNCOMMITTED' => 2, - 'CATALOG_NAME' => 2, 'CLASS_ORIGIN' => 2, 'DEFAULT_AUTH' => 2, - 'DES_KEY_FILE' => 2, 'INITIAL_SIZE' => 2, 'MASTER_DELAY' => 2, - 'MESSAGE_TEXT' => 2, 'MULTIPOLYGON' => 2, 'OLD_PASSWORD' => 2, - 'PARTITIONING' => 2, 'RELAY_THREAD' => 2, 'SERIALIZABLE' => 2, - 'SQL_NO_CACHE' => 2, 'SQL_TSI_HOUR' => 2, 'SQL_TSI_WEEK' => 2, - 'SQL_TSI_YEAR' => 2, 'SUBPARTITION' => 2, 'TIMESTAMPADD' => 2, - 'COLUMN_FORMAT' => 2, 'INSERT_METHOD' => 2, 'MASTER_SSL_CA' => 2, - 'RELAY_LOG_POS' => 2, 'SQL_TSI_MONTH' => 2, 'SUBPARTITIONS' => 2, - 'TIMESTAMPDIFF' => 2, 'WEIGHT_STRING' => 2, - 'AUTO_INCREMENT' => 2, 'AVG_ROW_LENGTH' => 2, 'KEY_BLOCK_SIZE' => 2, - 'MASTER_LOG_POS' => 2, 'MASTER_SSL_CRL' => 2, 'MASTER_SSL_KEY' => 2, - 'RELAY_LOG_FILE' => 2, 'SQL_TSI_MINUTE' => 2, 'SQL_TSI_SECOND' => 2, - 'TABLE_CHECKSUM' => 2, 'USER_RESOURCES' => 2, - 'AUTOEXTEND_SIZE' => 2, 'CONSTRAINT_NAME' => 2, 'DELAY_KEY_WRITE' => 2, - 'FILE_BLOCK_SIZE' => 2, 'MASTER_LOG_FILE' => 2, 'MASTER_PASSWORD' => 2, - 'MASTER_SSL_CERT' => 2, 'MULTILINESTRING' => 2, 'PARSE_GCOL_EXPR' => 2, - 'REPLICATE_DO_DB' => 2, 'SQL_AFTER_GTIDS' => 2, 'SQL_TSI_QUARTER' => 2, - 'SUBCLASS_ORIGIN' => 2, - 'MASTER_SERVER_ID' => 2, 'REDO_BUFFER_SIZE' => 2, 'SQL_BEFORE_GTIDS' => 2, - 'STATS_PERSISTENT' => 2, 'UNDO_BUFFER_SIZE' => 2, - 'CONSTRAINT_SCHEMA' => 2, 'GROUP_REPLICATION' => 2, 'IGNORE_SERVER_IDS' => 2, - 'MASTER_SSL_CAPATH' => 2, 'MASTER_SSL_CIPHER' => 2, 'RETURNED_SQLSTATE' => 2, - 'SQL_BUFFER_RESULT' => 2, 'STATS_AUTO_RECALC' => 2, - 'CONSTRAINT_CATALOG' => 2, 'GEOMETRYCOLLECTION' => 2, 'MASTER_RETRY_COUNT' => 2, - 'MASTER_SSL_CRLPATH' => 2, 'MAX_STATEMENT_TIME' => 2, 'REPLICATE_DO_TABLE' => 2, - 'SQL_AFTER_MTS_GAPS' => 2, 'STATS_SAMPLE_PAGES' => 2, - 'REPLICATE_IGNORE_DB' => 2, - 'MASTER_AUTO_POSITION' => 2, 'MASTER_CONNECT_RETRY' => 2, - 'MAX_QUERIES_PER_HOUR' => 2, 'MAX_UPDATES_PER_HOUR' => 2, - 'MAX_USER_CONNECTIONS' => 2, 'REPLICATE_REWRITE_DB' => 2, - 'REPLICATE_IGNORE_TABLE' => 2, - 'MASTER_HEARTBEAT_PERIOD' => 2, 'REPLICATE_WILD_DO_TABLE' => 2, - 'MAX_CONNECTIONS_PER_HOUR' => 2, - 'REPLICATE_WILD_IGNORE_TABLE' => 2, - - 'NOT NULL' => 4, - 'INDEX KEY' => 4, - 'UNIQUE KEY' => 4, - 'FOREIGN KEY' => 4, 'PRIMARY KEY' => 4, 'PRIMARY KEY' => 4, 'SPATIAL KEY' => 4, - 'FULLTEXT KEY' => 4, 'UNIQUE INDEX' => 4, - 'CHARACTER SET' => 4, 'IF NOT EXISTS' => 4, 'SPATIAL INDEX' => 4, - 'DATA DIRECTORY' => 4, 'FULLTEXT INDEX' => 4, - 'DEFAULT COLLATE' => 4, 'INDEX DIRECTORY' => 4, - 'DEFAULT CHARACTER SET' => 4, - - ); -} From ec750bec1caafe01bbab46da46a3ebd8490b940a Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Fri, 26 Jun 2015 15:20:48 +0300 Subject: [PATCH 28/57] Refactoring. Improved documentation. Signed-off-by: Dan Ungureanu --- libraries/sql-parser/ClassLoader.php | 250 +++++++++++ libraries/sql-parser/autoload.php | 26 +- libraries/sql-parser/composer/ClassLoader.php | 419 ------------------ 3 files changed, 267 insertions(+), 428 deletions(-) create mode 100644 libraries/sql-parser/ClassLoader.php delete mode 100644 libraries/sql-parser/composer/ClassLoader.php diff --git a/libraries/sql-parser/ClassLoader.php b/libraries/sql-parser/ClassLoader.php new file mode 100644 index 0000000000..3ff2f69de3 --- /dev/null +++ b/libraries/sql-parser/ClassLoader.php @@ -0,0 +1,250 @@ + + * Jordi Boggiano + * + * @package SqlParser + * @subpackage Autoload + */ +namespace SqlParser\Autoload; + +/** + * ClassLoader implements a PSR-4 class loader, + * + * This class is loosely based on the Symfony UniversalClassLoader. + * This class is a stripped version of Composer's ClassLoader. + * + * @package SqlParser + * @subpackage Autoload + * @author Fabien Potencier + * @author Jordi Boggiano + */ +class ClassLoader +{ + public $prefixLengths = array(); + public $prefixDirs = array(); + public $fallbackDirs = array(); + + public $classMap = array(); + + public $classMapAuthoritative = false; + + /** + * @param array $classMap Class to filename map + * + * @return void + */ + public function addClassMap(array $classMap) + { + if (!empty($this->classMap)) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-0 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirs = array_merge( + (array) $paths, + $this->fallbackDirs + ); + } else { + $this->fallbackDirs = array_merge( + $this->fallbackDirs, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirs[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengths[$prefix[0]][$prefix] = $length; + $this->prefixDirs[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirs[$prefix] = array_merge( + (array) $paths, + $this->prefixDirs[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirs[$prefix] = array_merge( + $this->prefixDirs[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirs = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengths[$prefix[0]][$prefix] = $length; + $this->prefixDirs[$prefix] = (array) $paths; + } + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + * + * @return void + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 + if ('\\' == $class[0]) { + $class = substr($class, 1); + } + + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative) { + return false; + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if ($file === null && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if ($file === null) { + // Remember that this class does not exist. + return $this->classMap[$class] = false; + } + + return $file; + } + + /** + * Finds a file that defines the specified class and has the specified + * extension. + * + * @param string $class The name of the class + * @param string $ext The extension of the file + * + * @return string|false The path if found, false otherwise + */ + public function findFileWithExtension($class, $ext) + { + $logicalPath = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengths[$first])) { + foreach ($this->prefixLengths[$first] as $prefix => $length) { + if (0 === strpos($class, $prefix)) { + foreach ($this->prefixDirs[$prefix] as $dir) { + if (is_file($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPath, $length))) { + return $file; + } + } + } + } + } + + foreach ($this->fallbackDirs as $dir) { + if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPath)) { + return $file; + } + } + + return false; + } +} + +if (!function_exists('SqlParser\\Autoload\\includeFile')) { + + /** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + * + * @param string $file The name of the file + * + * @return void + */ + function includeFile($file) + { + include $file; + } +} diff --git a/libraries/sql-parser/autoload.php b/libraries/sql-parser/autoload.php index e0718830ce..85f0d6c986 100644 --- a/libraries/sql-parser/autoload.php +++ b/libraries/sql-parser/autoload.php @@ -4,20 +4,28 @@ * The autoloader used for loading sql-parser's components. * * This file is based on Composer's autoloader. + * + * (c) Nils Adermann + * Jordi Boggiano + * + * @package SqlParser + * @subpackage Autoload */ +namespace SqlParser\Autoload; -if (!class_exists('Composer\\Autoload\\ClassLoader')) { - include_once './libraries/sql-parser/composer/ClassLoader.php'; +if (!class_exists('SqlParser\\Autoload\\ClassLoader')) { + include_once './libraries/sql-parser/ClassLoader.php'; } -use Composer\Autoload\ClassLoader; +use SqlParser\Autoload\ClassLoader; /** - * Initializes Composer's autoloader. + * Initializes the autoloader. * - * @package SqlParser + * @package SqlParser + * @subpackage Autoload */ -class ComposerAutoloaderInit +class AutoloaderInit { /** @@ -43,7 +51,7 @@ class ComposerAutoloaderInit self::$loader = $loader = new ClassLoader(); foreach ($map as $namespace => $path) { - $loader->setPsr4($namespace, $path); + $loader->set($namespace, $path); } $loader->register(true); @@ -52,8 +60,8 @@ class ComposerAutoloaderInit } } -// Initializing Composer's autoloader -return ComposerAutoloaderInit::getLoader( +// Initializing the autoloader. +return AutoloaderInit::getLoader( array( 'SqlParser\\' => array(dirname(__FILE__) . '/src'), ) diff --git a/libraries/sql-parser/composer/ClassLoader.php b/libraries/sql-parser/composer/ClassLoader.php deleted file mode 100644 index d2fd53f82d..0000000000 --- a/libraries/sql-parser/composer/ClassLoader.php +++ /dev/null @@ -1,419 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Autoload; - -/** - * ClassLoader implements a PSR-0 class loader - * - * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md - * - * $loader = new \Composer\Autoload\ClassLoader(); - * - * // register classes with namespaces - * $loader->add('Symfony\Component', __DIR__.'/component'); - * $loader->add('Symfony', __DIR__.'/framework'); - * - * // activate the autoloader - * $loader->register(); - * - * // to enable searching the include path (eg. for PEAR packages) - * $loader->setUseIncludePath(true); - * - * In this example, if you try to use a class in the Symfony\Component - * namespace or one of its children (Symfony\Component\Console for instance), - * the autoloader will first look for the class under the component/ - * directory, and it will then fallback to the framework/ directory if not - * found before giving up. - * - * This class is loosely based on the Symfony UniversalClassLoader. - * - * @author Fabien Potencier - * @author Jordi Boggiano - */ -class ClassLoader -{ - // PSR-4 - public $prefixLengthsPsr4 = array(); - public $prefixDirsPsr4 = array(); - public $fallbackDirsPsr4 = array(); - - // PSR-0 - public $prefixesPsr0 = array(); - public $fallbackDirsPsr0 = array(); - - public $useIncludePath = false; - public $classMap = array(); - - public $classMapAuthoritative = false; - - /** - * @param array $classMap Class to filename map - * - * @return void - */ - public function addClassMap(array $classMap) - { - if (!empty($this->classMap)) { - $this->classMap = array_merge($this->classMap, $classMap); - } else { - $this->classMap = $classMap; - } - } - - /** - * Registers a set of PSR-0 directories for a given prefix, either - * appending or prepending to the ones previously set for this prefix. - * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories - * - * @return void - */ - public function add($prefix, $paths, $prepend = false) - { - if (!$prefix) { - if ($prepend) { - $this->fallbackDirsPsr0 = array_merge( - (array) $paths, - $this->fallbackDirsPsr0 - ); - } else { - $this->fallbackDirsPsr0 = array_merge( - $this->fallbackDirsPsr0, - (array) $paths - ); - } - - return; - } - - $first = $prefix[0]; - if (!isset($this->prefixesPsr0[$first][$prefix])) { - $this->prefixesPsr0[$first][$prefix] = (array) $paths; - - return; - } - if ($prepend) { - $this->prefixesPsr0[$first][$prefix] = array_merge( - (array) $paths, - $this->prefixesPsr0[$first][$prefix] - ); - } else { - $this->prefixesPsr0[$first][$prefix] = array_merge( - $this->prefixesPsr0[$first][$prefix], - (array) $paths - ); - } - } - - /** - * Registers a set of PSR-4 directories for a given namespace, either - * appending or prepending to the ones previously set for this namespace. - * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-0 base directories - * @param bool $prepend Whether to prepend the directories - * - * @throws \InvalidArgumentException - * - * @return void - */ - public function addPsr4($prefix, $paths, $prepend = false) - { - if (!$prefix) { - // Register directories for the root namespace. - if ($prepend) { - $this->fallbackDirsPsr4 = array_merge( - (array) $paths, - $this->fallbackDirsPsr4 - ); - } else { - $this->fallbackDirsPsr4 = array_merge( - $this->fallbackDirsPsr4, - (array) $paths - ); - } - } elseif (!isset($this->prefixDirsPsr4[$prefix])) { - // Register directories for a new namespace. - $length = strlen($prefix); - if ('\\' !== $prefix[$length - 1]) { - throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); - } - $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; - } elseif ($prepend) { - // Prepend directories for an already registered namespace. - $this->prefixDirsPsr4[$prefix] = array_merge( - (array) $paths, - $this->prefixDirsPsr4[$prefix] - ); - } else { - // Append directories for an already registered namespace. - $this->prefixDirsPsr4[$prefix] = array_merge( - $this->prefixDirsPsr4[$prefix], - (array) $paths - ); - } - } - - /** - * Registers a set of PSR-0 directories for a given prefix, - * replacing any others previously set for this prefix. - * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 base directories - * - * @return void - */ - public function set($prefix, $paths) - { - if (!$prefix) { - $this->fallbackDirsPsr0 = (array) $paths; - } else { - $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; - } - } - - /** - * Registers a set of PSR-4 directories for a given namespace, - * replacing any others previously set for this namespace. - * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories - * - * @throws \InvalidArgumentException - * - * @return void - */ - public function setPsr4($prefix, $paths) - { - if (!$prefix) { - $this->fallbackDirsPsr4 = (array) $paths; - } else { - $length = strlen($prefix); - if ('\\' !== $prefix[$length - 1]) { - throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); - } - $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; - } - } - - /** - * Turns on searching the include path for class files. - * - * @param bool $useIncludePath - * - * @return void - */ - public function setUseIncludePath($useIncludePath) - { - $this->useIncludePath = $useIncludePath; - } - - /** - * Can be used to check if the autoloader uses the include path to check - * for classes. - * - * @return bool - */ - public function getUseIncludePath() - { - return $this->useIncludePath; - } - - /** - * Turns off searching the prefix and fallback directories for classes - * that have not been registered with the class map. - * - * @param bool $classMapAuthoritative - * - * @return void - */ - public function setClassMapAuthoritative($classMapAuthoritative) - { - $this->classMapAuthoritative = $classMapAuthoritative; - } - - /** - * Should class lookup fail if not found in the current class map? - * - * @return bool - */ - public function isClassMapAuthoritative() - { - return $this->classMapAuthoritative; - } - - /** - * Registers this instance as an autoloader. - * - * @param bool $prepend Whether to prepend the autoloader or not - * - * @return void - */ - public function register($prepend = false) - { - spl_autoload_register(array($this, 'loadClass'), true, $prepend); - } - - /** - * Unregisters this instance as an autoloader. - * - * @return void - */ - public function unregister() - { - spl_autoload_unregister(array($this, 'loadClass')); - } - - /** - * Loads the given class or interface. - * - * @param string $class The name of the class - * - * @return bool|null True if loaded, null otherwise - */ - public function loadClass($class) - { - if ($file = $this->findFile($class)) { - includeFile($file); - - return true; - } - } - - /** - * Finds the path to the file where the class is defined. - * - * @param string $class The name of the class - * - * @return string|false The path if found, false otherwise - */ - public function findFile($class) - { - // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 - if ('\\' == $class[0]) { - $class = substr($class, 1); - } - - // class map lookup - if (isset($this->classMap[$class])) { - return $this->classMap[$class]; - } - if ($this->classMapAuthoritative) { - return false; - } - - $file = $this->findFileWithExtension($class, '.php'); - - // Search for Hack files if we are running on HHVM - if ($file === null && defined('HHVM_VERSION')) { - $file = $this->findFileWithExtension($class, '.hh'); - } - - if ($file === null) { - // Remember that this class does not exist. - return $this->classMap[$class] = false; - } - - return $file; - } - - /** - * Finds a file that defines the specified class and has the specified - * extension. - * - * @param string $class - * @param string $ext - * - * @return string - */ - public function findFileWithExtension($class, $ext) - { - // PSR-4 lookup - $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; - - $first = $class[0]; - if (isset($this->prefixLengthsPsr4[$first])) { - foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { - if (0 === strpos($class, $prefix)) { - foreach ($this->prefixDirsPsr4[$prefix] as $dir) { - if (is_file($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { - return $file; - } - } - } - } - } - - // PSR-4 fallback dirs - foreach ($this->fallbackDirsPsr4 as $dir) { - if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { - return $file; - } - } - - // PSR-0 lookup - if (false !== $pos = strrpos($class, '\\')) { - // namespaced class name - $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) - . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); - } else { - // PEAR-like class name - $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; - } - - if (isset($this->prefixesPsr0[$first])) { - foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { - if (0 === strpos($class, $prefix)) { - foreach ($dirs as $dir) { - if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { - return $file; - } - } - } - } - } - - // PSR-0 fallback dirs - foreach ($this->fallbackDirsPsr0 as $dir) { - if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { - return $file; - } - } - - // PSR-0 include paths. - if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { - return $file; - } - } -} - -if (!function_exists('Composer\Autoload\includeFile')) { - - /** - * Scope isolated include. - * - * Prevents access to $this/self from included files. - * - * @param string $file - * - * @return void - */ - function includeFile($file) - { - include $file; - } -} From f7689d5c7ea50a06705441bbf520770e723b4ed5 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Sat, 27 Jun 2015 22:07:40 +0300 Subject: [PATCH 29/57] Replaced more of the old parser. Updated sql-parser library. Signed-off-by: Dan Ungureanu --- db_qbe.php | 23 +- import.php | 22 +- libraries/mult_submits.inc.php | 22 +- libraries/sql-parser/src/Lexer.php | 14 +- libraries/sql-parser/src/Parser.php | 2 +- libraries/sql-parser/src/Statement.php | 4 +- .../src/Statements/SelectStatement.php | 14 + libraries/sql-parser/src/Utils/Query.php | 320 +++++++++++++++++- libraries/sql-parser/src/Utils/Routine.php | 4 +- libraries/sql.lib.php | 256 ++++++-------- libraries/structure.lib.php | 21 +- sql.php | 37 +- tbl_row_action.php | 21 +- tbl_select.php | 22 +- 14 files changed, 571 insertions(+), 211 deletions(-) diff --git a/db_qbe.php b/db_qbe.php index 2d6b499106..b57fd31027 100644 --- a/db_qbe.php +++ b/db_qbe.php @@ -80,15 +80,30 @@ if (isset($_REQUEST['submit_sql']) && ! empty($sql_query)) { if (! preg_match('@^SELECT@i', $sql_query)) { $message_to_display = true; } else { - $goto = 'db_sql.php'; + $goto = 'db_sql.php'; // Parse and analyze the query include_once 'libraries/parse_analyze.inc.php'; PMA_executeQueryAndSendQueryResponse( - $analyzed_sql_results, false, $_REQUEST['db'], null, false, null, null, - false, null, null, null, $goto, $pmaThemeImage, null, null, null, - $sql_query, null, null + $analyzed_sql_results, // analyzed_sql_results + false, // is_gotofile + $_REQUEST['db'], // db + null, // table + false, // find_real_end + null, // sql_query_for_bookmark + null, // extra_data + null, // message_to_show + null, // message + null, // sql_data + $goto, // goto + $pmaThemeImage, // pmaThemeImage + null, // disp_query + null, // disp_message + null, // query_type + $sql_query, // sql_query + null, // selectedTables + null // complete_query ); } } diff --git a/import.php b/import.php index 0576cc8626..38d0d5c48d 100644 --- a/import.php +++ b/import.php @@ -745,10 +745,24 @@ if ($go_sql) { include 'libraries/parse_analyze.inc.php'; $html_output .= PMA_executeQueryAndGetQueryResponse( - $analyzed_sql_results, false, $db, $table, null, - $sql_query, null, $analyzed_sql_results['is_affected'], - null, null, null, $goto, $pmaThemeImage, - null, null, null, $sql_query, null, null + $analyzed_sql_results, // analyzed_sql_results + false, // is_gotofile + $db, // db + $table, // table + null, // find_real_end + $sql_query, // sql_query_for_bookmark + null, // extra_data + null, // message_to_show + null, // message + null, // sql_data + $goto, // goto + $pmaThemeImage, // pmaThemeImage + null, // disp_query + null, // disp_message + null, // query_type + $sql_query, // sql_query + null, // selectedTables + null // complete_query ); } diff --git a/libraries/mult_submits.inc.php b/libraries/mult_submits.inc.php index 6020c83b76..6500e0221c 100644 --- a/libraries/mult_submits.inc.php +++ b/libraries/mult_submits.inc.php @@ -244,15 +244,31 @@ if (!empty($submit_mult) && !empty($what)) { } if ($use_sql) { + /** * Parse and analyze the query */ include_once 'libraries/parse_analyze.inc.php'; PMA_executeQueryAndSendQueryResponse( - $analyzed_sql_results, false, $db, $table, null, null, null, - false, null, null, null, $goto, $pmaThemeImage, null, null, - $query_type, $sql_query, $selected, null + $analyzed_sql_results, // analyzed_sql_results + false, // is_gotofile + $db, // db + $table, // table + null, // find_real_end + null, // sql_query_for_bookmark + null, // extra_data + null, // message_to_show + null, // message + null, // sql_data + $goto, // goto + $pmaThemeImage, // pmaThemeImage + null, // disp_query + null, // disp_message + $query_type, // query_type + $sql_query, // sql_query + $selected, // selectedTables + null // complete_query ); } elseif (!$run_parts) { $GLOBALS['dbi']->selectDb($db); diff --git a/libraries/sql-parser/src/Lexer.php b/libraries/sql-parser/src/Lexer.php index d6814259d5..b91db8bf2a 100644 --- a/libraries/sql-parser/src/Lexer.php +++ b/libraries/sql-parser/src/Lexer.php @@ -100,7 +100,7 @@ class Lexer * * @var TokensList */ - public $tokens; + public $list; /** * Statements delimiter. @@ -164,7 +164,7 @@ class Lexer // context and compare again with `false`. // Another example is `parseComment`. - $tokens = new TokensList(); + $list = new TokensList(); $lastToken = null; for ($this->last = 0, $lastIdx = 0; $this->last < $this->len; $lastIdx = ++$this->last) { @@ -203,7 +203,7 @@ class Lexer } $token->position = $lastIdx; - $tokens->tokens[$tokens->count++] = $token; + $list->tokens[$list->count++] = $token; // Handling delimiters. if (($token->type === Token::TYPE_NONE) && ($token->value === 'DELIMITER')) { @@ -217,7 +217,7 @@ class Lexer $pos = ++$this->last; if (($token = $this->parseWhitespace()) !== null) { $token->position = $pos; - $tokens->tokens[$tokens->count++] = $token; + $list->tokens[$list->count++] = $token; } // Preparing the token that holds the new delimiter. @@ -238,17 +238,17 @@ class Lexer $this->delimiterLen = strlen($this->delimiter); $token = new Token($this->delimiter, Token::TYPE_DELIMITER); $token->position = $pos; - $tokens->tokens[$tokens->count++] = $token; + $list->tokens[$list->count++] = $token; } $lastToken = $token; } // Adding a final delimite at the end to mark the ending. - $tokens->tokens[$tokens->count++] = new Token(null, Token::TYPE_DELIMITER); + $list->tokens[$list->count++] = new Token(null, Token::TYPE_DELIMITER); // Saving the tokens list. - $this->tokens = $tokens; + $this->list = $list; } /** diff --git a/libraries/sql-parser/src/Parser.php b/libraries/sql-parser/src/Parser.php index a2f7ef768d..0a876b7ab1 100644 --- a/libraries/sql-parser/src/Parser.php +++ b/libraries/sql-parser/src/Parser.php @@ -225,7 +225,7 @@ class Parser { if ((is_string($list)) || ($list instanceof UtfString)) { $lexer = new Lexer($list, $strict); - $this->list = $lexer->tokens; + $this->list = $lexer->list; } elseif ($list instanceof TokensList) { $this->list = $list; } diff --git a/libraries/sql-parser/src/Statement.php b/libraries/sql-parser/src/Statement.php index a813fff2db..74b2cc3a6a 100644 --- a/libraries/sql-parser/src/Statement.php +++ b/libraries/sql-parser/src/Statement.php @@ -59,6 +59,8 @@ abstract class Statement */ public function parse(Parser $parser, TokensList $list) { + $this->first = $list->idx; + /** * Whether options were parsed or not. * For statements that do not have any options this is set to `true` by @@ -134,7 +136,7 @@ abstract class Statement $this->after($parser, $list, $token); } - $this->last = --$list->idx; // Go back to last used token. + $this->last = $list->idx--; // Go back to last used token. } /** diff --git a/libraries/sql-parser/src/Statements/SelectStatement.php b/libraries/sql-parser/src/Statements/SelectStatement.php index 8cdee820e5..0c4c354f19 100644 --- a/libraries/sql-parser/src/Statements/SelectStatement.php +++ b/libraries/sql-parser/src/Statements/SelectStatement.php @@ -67,6 +67,20 @@ class SelectStatement extends Statement 'SQL_CALC_FOUND_ROWS' => 9, ); + /** + * The sections of this statement, in order. + * + * Used by the query builder to arrange the clauses. + * + * @var array + */ + public static $SECTIONS = array( + 'SELECT' => 0, '%OPTIONS' => 1,'FROM' => 2, 'PARTITION' => 3, + 'WHERE' => 4, 'GROUP BY' => 5, 'HAVING' => 6, 'ORDER BY' => 7, + 'LIMIT' => 8, 'PROCEDURE' => 9, 'INTO' => 10, 'UNION' => 11, + 'JOIN' => 12, '%OPTIONS' => 13 + ); + /** * Expressions that are being selected by this statement. * diff --git a/libraries/sql-parser/src/Utils/Query.php b/libraries/sql-parser/src/Utils/Query.php index b1a95b155c..8cb9dfd4fd 100644 --- a/libraries/sql-parser/src/Utils/Query.php +++ b/libraries/sql-parser/src/Utils/Query.php @@ -10,6 +10,7 @@ namespace SqlParser\Utils; use SqlParser\Parser; use SqlParser\Statement; +use SqlParser\Token; use SqlParser\Statements\AlterStatement; use SqlParser\Statements\AnalyzeStatement; use SqlParser\Statements\CallStatement; @@ -61,49 +62,193 @@ class Query $flags = array(); if ($all) { $flags = array( + + /** + * select ... DISTINCT ... + */ 'distinct' => false, + + /** + * drop ... DATABASE ... + */ 'drop_database' => false, + + /** + * ... GROUP BY ... + */ + 'group' => false, + + /** + * ... HAVING ... + */ + 'having' => false, + + /** + * INSERT ... + * or + * REPLACE ... + * or + * DELETE ... + */ 'is_affected' => false, + + /** + * select ... PROCEDURE ANALYSE( ... ) ... + */ 'is_analyse' => false, + + /** + * select COUNT( ... ) ... + */ 'is_count' => false, - 'is_delete' => false, - 'is_explain' => false, + + /** + * DELETE ... + */ + 'is_delete' => false, // @deprecated; use `querytype` + + /** + * EXPLAIN ... + */ + 'is_explain' => false, // @deprecated; use `querytype` + + /** + * select ... INTO OUTFILE ... + */ 'is_export' => false, + + /** + * select FUNC( ... ) ... + */ 'is_func' => false, + + /** + * select ... GROUP BY ... + * or + * select ... HAVING ... + */ 'is_group' => false, + + /** + * INSERT ... + * or + * REPLACE ... + * or + * TODO: LOAD DATA ... + */ 'is_insert' => false, + + /** + * ANALYZE ... + * or + * CHECK ... + * or + * CHECKSUM ... + * or + * OPTIMIZE ... + * or + * REPAIR ... + */ 'is_maint' => false, + + /** + * CALL ... + */ 'is_procedure' => false, - 'is_replace' => false, - 'is_select' => false, - 'is_show' => false, + + /** + * REPLACE ... + */ + 'is_replace' => false, // @deprecated; use `querytype` + + /** + * SELECT ... + */ + 'is_select' => false, // @deprecated; use `querytype` + + /** + * SHOW ... + */ + 'is_show' => false, // @deprecated; use `querytype` + + /** + * Contains a subquery. + */ 'is_subquery' => false, + + /** + * ... JOIN ... + */ 'join' => false, + + /** + * ... LIMIT ... + */ + 'limit' => false, + + /** + * TODO + */ 'offset' => false, + + /** + * ... ORDER ... + */ + 'order' => false, + + /** + * The type of the query (which is usually the first keyword of + * the statement). + */ + 'querytype' => false, + + /** + * Whether a page reload is required. + */ 'reload' => false, + + /** + * SELECT ... FROM ... + */ 'select_from' => false, + + /** + * ... UNION ... + */ 'union' => false ); } - // TODO: 'union', 'join', 'offset' - if (($statement instanceof AlterStatement) - || ($statement instanceof CreateStatement) - ) { + if ($statement instanceof AlterStatement) { + $flags['querytype'] = 'ALTER'; $flags['reload'] = true; - } else if (($statement instanceof AnalyzeStatement) - || ($statement instanceof CheckStatement) - || ($statement instanceof ChecksumStatement) - || ($statement instanceof OptimizeStatement) - || ($statement instanceof RepairStatement) - ) { + } else if ($statement instanceof CreateStatement) { + $flags['querytype'] = 'CREATE'; + $flags['reload'] = true; + } else if ($statement instanceof AnalyzeStatement) { + $flags['querytype'] = 'ANALYZE'; + $flags['is_maint'] = true; + } else if ($statement instanceof CheckStatement) { + $flags['querytype'] = 'CHECK'; + $flags['is_maint'] = true; + } else if ($statement instanceof ChecksumStatement) { + $flags['querytype'] = 'CHECKSUM'; + $flags['is_maint'] = true; + } else if ($statement instanceof OptimizeStatement) { + $flags['querytype'] = 'OPTIMIZE'; + $flags['is_maint'] = true; + } else if ($statement instanceof RepairStatement) { + $flags['querytype'] = 'REPAIR'; $flags['is_maint'] = true; } else if ($statement instanceof CallStatement) { + $flags['querytype'] = 'CALL'; $flags['is_procedure'] = true; } else if ($statement instanceof DeleteStatement) { + $flags['querytype'] = 'DELETE'; $flags['is_delete'] = true; $flags['is_affected'] = true; } else if ($statement instanceof DropStatement) { + $flags['querytype'] = 'DROP'; $flags['reload'] = true; if (($statement->options->has('DATABASE') @@ -112,14 +257,19 @@ class Query $flags['drop_database'] = true; } } else if ($statement instanceof ExplainStatement) { + $flags['querytype'] = 'EXPLAIN'; $flags['is_explain'] = true; } else if ($statement instanceof InsertStatement) { + $flags['querytype'] = 'INSERT'; $flags['is_affected'] = true; $flags['is_insert'] = true; } else if ($statement instanceof ReplaceStatement) { + $flags['querytype'] = 'REPLACE'; $flags['is_affected'] = true; $flags['is_replace'] = true; + $flags['is_insert'] = true; } else if ($statement instanceof SelectStatement) { + $flags['querytype'] = 'SELECT'; $flags['is_select'] = true; if (!empty($statement->from)) { @@ -158,12 +308,43 @@ class Query ) { $flags['is_analyse'] = true; } + + if (!empty($statement->group)) { + $flags['group'] = true; + } + + if (!empty($statement->having)) { + $flags['having'] = true; + } + + if (!empty($statement->union)) { + $flags['union'] = true; + } + + if (!empty($statement->join)) { + $flags['join'] = true; + } + } else if ($statement instanceof ShowStatement) { + $flags['querytype'] = 'SHOW'; $flags['is_show'] = true; } else if ($statement instanceof UpdateStatement) { + $flags['querytype'] = 'UPDATE'; $flags['is_affected'] = true; } + if (($statement instanceof SelectStatement) + || ($statement instanceof UpdateStatement) + || ($statement instanceof DeleteStatement) + ) { + if (!empty($statement->limit)) { + $flags['limit'] = true; + } + if (!empty($statement->order)) { + $flags['order'] = true; + } + } + return $flags; } @@ -190,13 +371,16 @@ class Query $ret['statement'] = $statement; if ($statement instanceof SelectStatement) { - $ret['tables'] = array(); + $ret['select_tables'] = array(); + $ret['select_expr'] = array(); foreach ($statement->expr as $expr) { if (!empty($expr->table)) { - $ret['tables'][] = array( + $ret['select_tables'][] = array( $expr->table, !empty($expr->database) ? $expr->database : null ); + } else { + $ret['select_expr'][] = $expr->expr; } } } @@ -204,4 +388,106 @@ class Query return $ret; } + public static function getClauseType($clause) + { + $type = ''; + for ($i = 0, $len = strlen($clause); $i < $len; ++$i) { + if ((empty($type)) && (ctype_space($type))) { + // Skipping whitespaces if we haven't started determining the + // type. + continue; + } + if (!ctype_alnum($clause[$i])) { + // The type contains only alphanumeric characters. + break; + } + // Adding character. + $type .= $clause[$i]; + } + return $type; + } + + /** + * Replaces the clause in the query. If the clause does not exist, it is + * inserted. + * + * It is a very basic version of a query builder. + * + * @param Statement $statement The parsed query that has to be modified. + * @param TokensList $list The list of tokens. + * @param string $clause The clause to be replaced. + * + * @return string + */ + public static function replaceClause($statement, $list, $clause) + { + + /** + * Current location. + * @var int + */ + $currIdx = 0; + + /** + * The count of brackets. + * We keep track of them so we won't insert the clause in a subquery. + * @var int + */ + $brackets = 0; + + /** + * The sections before the clause + * @var string + */ + $before = ''; + + /** + * The sections after the clause. + * @var string + */ + $after = ''; + + /** + * The place where the clause should be added. + * @var int + */ + $clauseIdx = $statement::$SECTIONS[static::getClauseType($clause)]; + + for ($i = $statement->first; $i <= $statement->last; ++$i) { + + $token = $list->tokens[$i]; + + if ($token->type === Token::TYPE_DELIMITER) { + break; + } + + if ($token->type === Token::TYPE_OPERATOR) { + if ($token->value === '(') { + ++$brackets; + } elseif ($token->value === ')') { + --$brackets; + } + } + + if ($brackets == 0) { + // Checking if we changed sections. + if ($token->type === Token::TYPE_KEYWORD) { + if (isset($statement::$SECTIONS[$token->value])) { + if ($statement::$SECTIONS[$token->value] > $currIdx) { + $currIdx = $statement::$SECTIONS[$token->value]; + } + } + } + } + + if ($currIdx < $clauseIdx) { + $before .= $token->token; + } elseif ($currIdx > $clauseIdx) { + $after .= $token->value; + } + } + + return $before . ' ' . $clause . ' ' . $after; + } + } diff --git a/libraries/sql-parser/src/Utils/Routine.php b/libraries/sql-parser/src/Utils/Routine.php index 4b9b21daef..8298d8d73f 100644 --- a/libraries/sql-parser/src/Utils/Routine.php +++ b/libraries/sql-parser/src/Utils/Routine.php @@ -39,7 +39,7 @@ class Routine $lexer = new Lexer($param); // A dummy parser is used for error reporting. - $type = DataTypeFragment::parse(new Parser(), $lexer->tokens); + $type = DataTypeFragment::parse(new Parser(), $lexer->list); if ($type === null) { return array('', '', '', '', ''); @@ -71,7 +71,7 @@ class Routine $lexer = new Lexer('(' . $param . ')'); // A dummy parser is used for error reporting. - $param = ParamDefFragment::parse(new Parser(), $lexer->tokens); + $param = ParamDefFragment::parse(new Parser(), $lexer->list); if (empty($param[0])) { return array('', '', '', '', ''); diff --git a/libraries/sql.lib.php b/libraries/sql.lib.php index f8959946b0..206da97d60 100644 --- a/libraries/sql.lib.php +++ b/libraries/sql.lib.php @@ -60,7 +60,6 @@ function PMA_getTableNameBySQL($sql, $tables) return trim($table); } - /** * Handle remembered sorting order, only for single table query * @@ -75,31 +74,29 @@ function PMA_handleSortOrder( $db, $table, &$analyzed_sql_results, &$full_sql_query ) { $pmatable = new PMA_Table($table, $db); - if (empty($analyzed_sql_results['analyzed_sql'][0]['order_by_clause'])) { - $sorted_col = $pmatable->getUiProp(PMA_Table::PROP_SORTED_COLUMN); - if ($sorted_col) { - //remove the tablename from retrieved preference - //to get just the column name and the sort order - $sorted_col = str_replace( - PMA_Util::backquote($table) . '.', '', $sorted_col - ); - // retrieve the remembered sorting order for current table - $sql_order_to_append = ' ORDER BY ' . $sorted_col . ' '; - $full_sql_query - = $analyzed_sql_results['analyzed_sql'][0]['section_before_limit'] - . $sql_order_to_append - . $analyzed_sql_results['analyzed_sql'][0]['limit_clause'] - . ' ' - . $analyzed_sql_results['analyzed_sql'][0]['section_after_limit']; - // update the $analyzed_sql - $analyzed_sql_results['analyzed_sql'][0]['section_before_limit'] - .= $sql_order_to_append; - $analyzed_sql_results['analyzed_sql'][0]['order_by_clause'] - = $sorted_col; + if (empty($analyzed_sql_results['order'])) { + + // Retrieving the name of the column we should sort after. + $sortCol = $pmatable->getUiProp(PMA_Table::PROP_SORTED_COLUMN); + if (empty($sortCol)) { + return; } + + // Remove the name of the the table from the retrieved field name. + $sortCol = str_replace(PMA_Util::backquote($table) . '.', '', $sortCol); + + // Create the new query. + $full_sql_query = SqlParser\Utils\Query::replaceClause( + $analyzed_sql_results['statement'], + $analyzed_sql_results['parser']->list, + 'ORDER BY ' . $sortCol + ); + + // TODO: Avoid reparsing the query. + $analyzed_sql_results = SqlParser\Utils\Query::getAll($full_sql_query); } else { - // store the remembered table into session + // Store the remembered table into session. $pmatable->setUiProp( PMA_Table::PROP_SORTED_COLUMN, $analyzed_sql_results['analyzed_sql'][0]['order_by_clause'] @@ -110,16 +107,18 @@ function PMA_handleSortOrder( /** * Append limit clause to SQL query * - * @param array $analyzed_sql the analyzed query - * @param string $sql_limit_to_append clause to append + * @param array &$analyzed_sql_results the analyzed query results * * @return string limit clause appended SQL query */ -function PMA_getSqlWithLimitClause($analyzed_sql, - $sql_limit_to_append -) { - return $analyzed_sql[0]['section_before_limit'] . "\n" - . $sql_limit_to_append . $analyzed_sql[0]['section_after_limit']; +function PMA_getSqlWithLimitClause(&$analyzed_sql_results) +{ + return SqlParser\Utils\Query::replaceClause( + $analyzed_sql_results['statement'], + $analyzed_sql_results['parser']->list, + 'LIMIT ' . $_SESSION['tmpval']['pos'] . ', ' + . $_SESSION['tmpval']['max_rows'] + ); } @@ -617,23 +616,15 @@ function PMA_getHtmlForBookmark($displayParts, $cfgBookmark, $sql_query, $db, */ function PMA_isRememberSortingOrder($analyzed_sql_results) { - $select_from = isset( - $analyzed_sql_results['analyzed_sql'][0]['queryflags']['select_from'] - ); - if ($GLOBALS['cfg']['RememberSorting'] + return $GLOBALS['cfg']['RememberSorting'] && ! ($analyzed_sql_results['is_count'] - || $analyzed_sql_results['is_export'] - || $analyzed_sql_results['is_func'] - || $analyzed_sql_results['is_analyse']) - && isset($analyzed_sql_results['analyzed_sql'][0]['select_expr']) - && (count($analyzed_sql_results['analyzed_sql'][0]['select_expr']) == 0) - && $select_from - && count($analyzed_sql_results['analyzed_sql'][0]['table_ref']) == 1 - ) { - return true; - } else { - return false; - } + || $analyzed_sql_results['is_export'] + || $analyzed_sql_results['is_func'] + || $analyzed_sql_results['is_analyse']) + && $analyzed_sql_results['select_from'] + && empty($analyzed_sql_results['select_expr']) + && count($analyzed_sql_results['analyzed_sql']['select_expr']) == 0 + && count($analyzed_sql_results['analyzed_sql']['select_tables']) == 1; } /** @@ -646,20 +637,12 @@ function PMA_isRememberSortingOrder($analyzed_sql_results) */ function PMA_isAppendLimitClause($analyzed_sql_results) { - $select_from = isset( - $analyzed_sql_results['analyzed_sql'][0]['queryflags']['select_from'] - ); - if (($_SESSION['tmpval']['max_rows'] != 'all') + return ($_SESSION['tmpval']['max_rows'] != 'all') && ! ($analyzed_sql_results['is_export'] || $analyzed_sql_results['is_analyse']) - && ($select_from || $analyzed_sql_results['is_subquery']) - && ! isset($analyzed_sql_results['analyzed_sql'][0]['queryflags']['offset']) - && empty($analyzed_sql_results['analyzed_sql'][0]['limit_clause']) - ) { - return true; - } else { - return false; - } + && ($analyzed_sql_results['select_from'] + || $analyzed_sql_results['is_subquery']) + && empty($analyzed_sql_results['limit']); } /** @@ -673,29 +656,18 @@ function PMA_isAppendLimitClause($analyzed_sql_results) */ function PMA_isJustBrowsing($analyzed_sql_results, $find_real_end) { - $distinct = isset( - $analyzed_sql_results['analyzed_sql'][0]['queryflags']['distinct'] - ); - - $table_name = isset( - $analyzed_sql_results['analyzed_sql'][0]['table_ref'][1]['table_name'] - ); - if (! $analyzed_sql_results['is_group'] + return ! $analyzed_sql_results['is_group'] && ! $analyzed_sql_results['is_func'] - && ! isset($analyzed_sql_results['analyzed_sql'][0]['queryflags']['union']) - && ! $distinct - && ! $table_name - && (empty($analyzed_sql_results['analyzed_sql'][0]['where_clause']) - || $analyzed_sql_results['analyzed_sql'][0]['where_clause'] == '1 ') - && empty($analyzed_sql_results['analyzed_sql'][0]['group_by_clause']) + && empty($analyzed_sql_results['union']) + && empty($analyzed_sql_results['distinct']) + && count($analyzed_sql_results['select_tables'] <= 1) + && (empty($analyzed_sql_results['statement']->where) + || (count($analyzed_sql_results['statement']->where) == 1 + && $analyzed_sql_results['statement']->where->expr ==='1')) + && empty($analyzed_sql_results['group']) && ! isset($find_real_end) - && !$analyzed_sql_results['is_subquery'] - && empty($analyzed_sql_results['analyzed_sql'][0]['having_clause']) - ) { - return true; - } else { - return false; - } + && ! $analyzed_sql_results['is_subquery'] + && empty($analyzed_sql_results['having']); } /** @@ -708,14 +680,9 @@ function PMA_isJustBrowsing($analyzed_sql_results, $find_real_end) */ function PMA_isDeleteTransformationInfo($analyzed_sql_results) { - if (!empty($analyzed_sql_results['analyzed_sql'][0]['querytype']) - && (($analyzed_sql_results['analyzed_sql'][0]['querytype'] == 'ALTER') - || ($analyzed_sql_results['analyzed_sql'][0]['querytype'] == 'DROP')) - ) { - return true; - } else { - return false; - } + return !empty($analyzed_sql_results['querytype']) + && (($analyzed_sql_results['querytype'] == 'ALTER') + || ($analyzed_sql_results['querytype'] == 'DROP')); } /** @@ -1099,18 +1066,13 @@ function PMA_getNumberOfRowsAffectedOrChanged($is_affected, $result) */ function PMA_hasCurrentDbChanged($db) { - // Checks if the current database has changed - // This could happen if the user sends a query like "USE `database`;" - $reload = 0; if (/*overload*/mb_strlen($db)) { $current_db = $GLOBALS['dbi']->fetchValue('SELECT DATABASE()'); // $current_db is false, except when a USE statement was sent - if ($current_db != false && $db !== $current_db) { - $reload = 1; - } + return ($current_db != false) && ($db !== $current_db); } - return $reload; + return false; } /** @@ -1154,26 +1116,25 @@ function PMA_cleanupRelations($db, $table, $dropped_column, $purge, $extra_data) * the 'LIMIT' clause that may have been programatically added * * @param int $num_rows number of rows affected/changed by the query - * @param bool $is_select whether the query is SELECT or not * @param bool $justBrowsing whether just browsing or not * @param string $db the current database * @param string $table the current table - * @param array $parsed_sql parsed sql * @param array $analyzed_sql_results the analyzed query and other variables set * after analyzing the query * * @return int $unlim_num_rows unlimited number of rows */ function PMA_countQueryResults( - $num_rows, $is_select, $justBrowsing, - $db, $table, $parsed_sql, $analyzed_sql_results + $num_rows, $justBrowsing, $db, $table, $analyzed_sql_results ) { if (!PMA_isAppendLimitClause($analyzed_sql_results)) { // if we did not append a limit, set this to get a correct // "Showing rows..." message // $_SESSION['tmpval']['max_rows'] = 'all'; $unlim_num_rows = $num_rows; - } elseif ($is_select || $analyzed_sql_results['is_subquery']) { + } elseif ($analyzed_sql_results['querytype'] == 'SELECT' + || $analyzed_sql_results['is_subquery'] + ) { // c o u n t q u e r y // If we are "just browsing", there is only one table, @@ -1219,10 +1180,12 @@ function PMA_countQueryResults( // SELECT // (SELECT + // TODO: Replace PMA_SQP_ + $analyzed_sql = $analyzed_sql_results['analyzed_sql']; $count_query = PMA_SQP_format( - $parsed_sql, + $analyzed_sql_results['parsed_sql'], 'query_only', 0, $analyzed_sql[0]['position_of_first_select'] + 1 @@ -1230,7 +1193,7 @@ function PMA_countQueryResults( $count_query .= ' SQL_CALC_FOUND_ROWS '; // add everything that was after the first SELECT $count_query .= PMA_SQP_format( - $parsed_sql, + $analyzed_sql_results['parsed_sql'], 'query_only', $analyzed_sql[0]['position_of_first_select'] + 1 ); @@ -1341,8 +1304,7 @@ function PMA_executeTheQuery($analyzed_sql_results, $full_sql_query, $is_gotofil ); $unlim_num_rows = PMA_countQueryResults( - $num_rows, $analyzed_sql_results['is_select'], $justBrowsing, $db, - $table, $analyzed_sql_results['parsed_sql'], $analyzed_sql_results + $num_rows, $justBrowsing, $db, $table, $analyzed_sql_results ); $extra_data = PMA_cleanupRelations( @@ -1365,23 +1327,23 @@ function PMA_executeTheQuery($analyzed_sql_results, $full_sql_query, $is_gotofil /** * Delete related tranformatioinformationn information * - * @param String $db current database - * @param String $table current table - * @param array $analyzed_sql analyzed sql query + * @param String $db current database + * @param String $table current table + * @param array $analyzed_sql_results analyzed sql results * * @return void */ -function PMA_deleteTransformationInfo($db, $table, $analyzed_sql) +function PMA_deleteTransformationInfo($db, $table, $analyzed_sql_results) { include_once 'libraries/transformations.lib.php'; - if ($analyzed_sql[0]['querytype'] == 'ALTER') { + if ($analyzed_sql_results['querytype'] == 'ALTER') { $posDrop = /*overload*/mb_stripos( - $analyzed_sql[0]['unsorted_query'], + $analyzed_sql_results['analyzed_sql'][0]['unsorted_query'], 'DROP' ); if ($posDrop !== false) { $drop_column = PMA_getColumnNameInColumnDropSql( - $analyzed_sql[0]['unsorted_query'] + $analyzed_sql_results['analyzed_sql'][0]['unsorted_query'] ); if ($drop_column != '') { @@ -1389,7 +1351,7 @@ function PMA_deleteTransformationInfo($db, $table, $analyzed_sql) } } - } else if (($analyzed_sql[0]['querytype'] == 'DROP') && ($table != '')) { + } else if (($analyzed_sql_results['querytype'] == 'DROP') && ($table != '')) { PMA_clearTransformations($db, $table); } } @@ -1403,14 +1365,14 @@ function PMA_deleteTransformationInfo($db, $table, $analyzed_sql) * * @return string $message */ -function PMA_getMessageForNoRowsReturned($message_to_show, $analyzed_sql_results, - $num_rows +function PMA_getMessageForNoRowsReturned($message_to_show, + $analyzed_sql_results, $num_rows ) { - if ($analyzed_sql_results['is_delete']) { + if ($analyzed_sql_results['querytype'] == 'DELETE"') { $message = PMA_Message::getMessageForDeletedRows($num_rows); } elseif ($analyzed_sql_results['is_insert']) { - if ($analyzed_sql_results['is_replace']) { - // For replace we get DELETED + INSERTED row count, + if ($analyzed_sql_results['querytype'] == 'REPLACE') { + // For REPLACE we get DELETED + INSERTED row count, // so we have to call it affected $message = PMA_Message::getMessageForAffectedRows($num_rows); } else { @@ -1438,7 +1400,9 @@ function PMA_getMessageForNoRowsReturned($message_to_show, $analyzed_sql_results // fact that $message_to_show is sent for every case. // The $message_to_show containing a success message and sent with // the form should not have priority over errors - } elseif (! empty($message_to_show) && ! $analyzed_sql_results['is_select']) { + } elseif (! empty($message_to_show) + && $analyzed_sql_results['querytype'] != 'SELECT' + ) { $message = PMA_Message::rawSuccess(htmlspecialchars($message_to_show)); } elseif (! empty($GLOBALS['show_as_php'])) { $message = PMA_Message::success(__('Showing as PHP code')); @@ -1492,14 +1456,12 @@ function PMA_getQueryResponseForNoResultsReturned($analyzed_sql_results, $db, $table, $message_to_show, $num_rows, $displayResultsObject, $extra_data ) { if (PMA_isDeleteTransformationInfo($analyzed_sql_results)) { - PMA_deleteTransformationInfo( - $db, $table, $analyzed_sql_results['analyzed_sql'] - ); + PMA_deleteTransformationInfo($db, $table, $analyzed_sql_results); } $message = PMA_getMessageForNoRowsReturned( - isset($message_to_show) ? $message_to_show : null, $analyzed_sql_results, - $num_rows + isset($message_to_show) ? $message_to_show : null, + $analyzed_sql_results, $num_rows ); $html_output = ''; @@ -1526,8 +1488,7 @@ function PMA_getQueryResponseForNoResultsReturned($analyzed_sql_results, $db, $response = PMA_Response::getInstance(); $response->addJSON(isset($extra_data) ? $extra_data : array()); - $query_type = PMA_DisplayResults::QUERY_TYPE_SELECT; - if ($analyzed_sql_results['analyzed_sql'][0]['querytype'] == $query_type) { + if (!empty($analyzed_sql_results['is_select'])) { $html_output .= $displayResultsObject->getCreateViewQueryResultOp( $analyzed_sql_results['analyzed_sql'] ); @@ -2029,7 +1990,6 @@ function PMA_getQueryResponseForResultsReturned($result, * @param bool|null $find_real_end whether to find real end or not * @param string $sql_query_for_bookmark the sql query to be stored as bookmark * @param array|null $extra_data extra data - * @param bool $is_affected whether affected or not * @param string $message_to_show message to show * @param string $message message * @param array|null $sql_data sql data @@ -2049,16 +2009,29 @@ function PMA_getQueryResponseForResultsReturned($result, */ function PMA_executeQueryAndSendQueryResponse($analyzed_sql_results, $is_gotofile, $db, $table, $find_real_end, $sql_query_for_bookmark, - $extra_data, $is_affected, $message_to_show, $message, - $sql_data, $goto, $pmaThemeImage, $disp_query, $disp_message, - $query_type, $sql_query, $selectedTables, $complete_query + $extra_data, $message_to_show, $message, $sql_data, $goto, $pmaThemeImage, + $disp_query, $disp_message, $query_type, $sql_query, $selectedTables, + $complete_query ) { $html_output = PMA_executeQueryAndGetQueryResponse( - $analyzed_sql_results, $is_gotofile, $db, $table, - $find_real_end, $sql_query_for_bookmark, - $extra_data, $is_affected, $message_to_show, $message, - $sql_data, $goto, $pmaThemeImage, $disp_query, $disp_message, - $query_type, $sql_query, $selectedTables, $complete_query + $analyzed_sql_results, // analyzed_sql_results + $is_gotofile, // is_gotofile + $db, // db + $table, // table + $find_real_end, // find_real_end + $sql_query_for_bookmark, // sql_query_for_bookmark + $extra_data, // extra_data + $message_to_show, // message_to_show + $message, // message + $sql_data, // sql_data + $goto, // goto + $pmaThemeImage, // pmaThemeImage + $disp_query, // disp_query + $disp_message, // disp_message + $query_type, // query_type + $sql_query, // sql_query + $selectedTables, // selectedTables + $complete_query // complete_query ); $response = PMA_Response::getInstance(); @@ -2075,7 +2048,6 @@ function PMA_executeQueryAndSendQueryResponse($analyzed_sql_results, * @param bool|null $find_real_end whether to find real end or not * @param string $sql_query_for_bookmark the sql query to be stored as bookmark * @param array|null $extra_data extra data - * @param bool $is_affected whether affected or not * @param string $message_to_show message to show * @param string $message message * @param array|null $sql_data sql data @@ -2095,9 +2067,9 @@ function PMA_executeQueryAndSendQueryResponse($analyzed_sql_results, */ function PMA_executeQueryAndGetQueryResponse($analyzed_sql_results, $is_gotofile, $db, $table, $find_real_end, $sql_query_for_bookmark, - $extra_data, $is_affected, $message_to_show, $message, - $sql_data, $goto, $pmaThemeImage, $disp_query, $disp_message, - $query_type, $sql_query, $selectedTables, $complete_query + $extra_data, $message_to_show, $message, $sql_data, $goto, $pmaThemeImage, + $disp_query, $disp_message, $query_type, $sql_query, $selectedTables, + $complete_query ) { // Include PMA_Index class for use in PMA_DisplayResults class include_once './libraries/Index.class.php'; @@ -2111,7 +2083,7 @@ function PMA_executeQueryAndGetQueryResponse($analyzed_sql_results, // Handling is not required when it's a union query // (the parser never sets the 'union' key to 0) if (PMA_isRememberSortingOrder($analyzed_sql_results) - && ! isset($analyzed_sql_results['analyzed_sql'][0]['queryflags']['union']) + && empty($analyzed_sql_results['union']) ) { if (! isset($_SESSION['sql_from_query_box'])) { PMA_handleSortOrder($db, $table, $analyzed_sql_results, $sql_query); @@ -2131,11 +2103,7 @@ function PMA_executeQueryAndGetQueryResponse($analyzed_sql_results, // Do append a "LIMIT" clause? if (PMA_isAppendLimitClause($analyzed_sql_results)) { - $full_sql_query = PMA_getSqlWithLimitClause( - $analyzed_sql_results['analyzed_sql'], - ' LIMIT ' . $_SESSION['tmpval']['pos'] - . ', ' . $_SESSION['tmpval']['max_rows'] . " " - ); + $full_sql_query = PMA_getSqlWithLimitClause($analyzed_sql_results); } $GLOBALS['reload'] = PMA_hasCurrentDbChanged($db); @@ -2155,7 +2123,7 @@ function PMA_executeQueryAndGetQueryResponse($analyzed_sql_results, ); // No rows returned -> move back to the calling page - if ((0 == $num_rows && 0 == $unlim_num_rows) || $is_affected) { + if ((0 == $num_rows && 0 == $unlim_num_rows) || $analyzed_sql_results['is_affected']) { $html_output = PMA_getQueryResponseForNoResultsReturned( $analyzed_sql_results, $db, $table, isset($message_to_show) ? $message_to_show : null, diff --git a/libraries/structure.lib.php b/libraries/structure.lib.php index 1e896e3755..982b0b79a9 100644 --- a/libraries/structure.lib.php +++ b/libraries/structure.lib.php @@ -3004,9 +3004,24 @@ function PMA_displayTableBrowseForSelectedColumns($db, $table, $goto, include_once 'libraries/sql.lib.php'; PMA_executeQueryAndSendQueryResponse( - $analyzed_sql_results, false, $db, $table, null, null, null, false, - null, null, null, $goto, $pmaThemeImage, null, null, - null, $sql_query, null, null + $analyzed_sql_results, // analyzed_sql_results + false, // is_gotofile + $db, // db + $table, // table + null, // find_real_end + null, // sql_query_for_bookmark + null, // extra_data + null, // message_to_show + null, // message + null, // sql_data + $goto, // goto + $pmaThemeImage, // pmaThemeImage + null, // disp_query + null, // disp_message + null, // query_type + $sql_query, // sql_query + null, // selectedTables + null // complete_query ); } diff --git a/sql.php b/sql.php index 0e68804f91..5ba7e194c2 100644 --- a/sql.php +++ b/sql.php @@ -197,23 +197,22 @@ if ($goto == 'sql.php') { } // end if PMA_executeQueryAndSendQueryResponse( - $analyzed_sql_results, - $is_gotofile, - $db, - $table, - isset($find_real_end) ? $find_real_end : null, - isset($import_text) ? $import_text : null, - isset($extra_data) ? $extra_data : null, - $is_affected, - isset($message_to_show) ? $message_to_show : null, - isset($message) ? $message : null, - isset($sql_data) ? $sql_data : null, - $goto, - $pmaThemeImage, - isset($disp_query) ? $display_query : null, - isset($disp_message) ? $disp_message : null, - isset($query_type) ? $query_type : null, - $sql_query, - isset($selected) ? $selected : null, - isset($complete_query) ? $complete_query : null + $analyzed_sql_results, // analyzed_sql_results + $is_gotofile, // is_gotofile + $db, // db + $table, // table + isset($find_real_end) ? $find_real_end : null, // find_real_end + isset($import_text) ? $import_text : null, // sql_query_for_bookmark + isset($extra_data) ? $extra_data : null, // extra_data + isset($message_to_show) ? $message_to_show : null, // message_to_show + isset($message) ? $message : null, // message + isset($sql_data) ? $sql_data : null, // sql_data + $goto, // goto + $pmaThemeImage, // pmaThemeImage + isset($disp_query) ? $display_query : null, // disp_query + isset($disp_message) ? $disp_message : null, // disp_message + isset($query_type) ? $query_type : null, // query_type + $sql_query, // sql_query + isset($selected) ? $selected : null, // selectedTables + isset($complete_query) ? $complete_query : null // complete_query ); diff --git a/tbl_row_action.php b/tbl_row_action.php index 70423e141e..38ccef9b74 100644 --- a/tbl_row_action.php +++ b/tbl_row_action.php @@ -145,9 +145,24 @@ if (!empty($submit_mult)) { include_once 'libraries/parse_analyze.inc.php'; PMA_executeQueryAndSendQueryResponse( - $analyzed_sql_results, false, $db, $table, null, null, null, false, null, - null, null, $goto, $pmaThemeImage, null, null, null, $sql_query, - null, null + $analyzed_sql_results, // analyzed_sql_results + false, // is_gotofile + $db, // db + $table, // table + null, // find_real_end + null, // sql_query_for_bookmark + null, // extra_data + null, // message_to_show + null, // message + null, // sql_data + $goto, // goto + $pmaThemeImage, // pmaThemeImage + null, // disp_query + null, // disp_message + null, // query_type + $sql_query, // sql_query + null, // selectedTables + null // complete_query ); } } diff --git a/tbl_select.php b/tbl_select.php index 914b547157..84d82784b1 100644 --- a/tbl_select.php +++ b/tbl_select.php @@ -64,6 +64,7 @@ if (! isset($_POST['columnsToDisplay']) && ! isset($_POST['displayAllColumns'])) $response->addHTML($table_search->getSelectionForm($goto)); } else { + /** * Selection criteria have been submitted -> do the work */ @@ -75,8 +76,23 @@ if (! isset($_POST['columnsToDisplay']) && ! isset($_POST['displayAllColumns'])) include_once 'libraries/parse_analyze.inc.php'; PMA_executeQueryAndSendQueryResponse( - $analyzed_sql_results, false, $db, $table, null, null, null, false, - null, null, null, $GLOBALS['goto'], $pmaThemeImage, null, - null, null, $sql_query, null, null + $analyzed_sql_results, // analyzed_sql_results + false, // is_gotofile + $db, // db + $table, // table + null, // find_real_end + null, // sql_query_for_bookmark + null, // extra_data + null, // message_to_show + null, // message + null, // sql_data + $GLOBALS['goto'], // goto + $pmaThemeImage, // pmaThemeImage + null, // disp_query + null, // disp_message + null, // query_type + $sql_query, // sql_query + null, // selectedTables + null // complete_query ); } From 46e44ed0d59868213db8956c8adb17b5398425a1 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Sun, 28 Jun 2015 23:57:33 +0300 Subject: [PATCH 30/57] Replaced more of the old parser (2). Updated sql-parser library. Signed-off-by: Dan Ungureanu --- libraries/DisplayResults.class.php | 58 ++++----- libraries/parse_analyze.inc.php | 10 +- .../sql-parser/src/Fragments/LimitKeyword.php | 4 + libraries/sql-parser/src/Parser.php | 10 +- libraries/sql-parser/src/Statement.php | 11 +- .../src/Statements/AlterStatement.php | 105 ++++++++++++++-- .../src/Statements/DropStatement.php | 4 +- .../Statements/NotImplementedStatement.php | 4 +- libraries/sql-parser/src/Utils/Query.php | 99 +++++++++++---- libraries/sql.lib.php | 116 +++++++----------- 10 files changed, 274 insertions(+), 147 deletions(-) diff --git a/libraries/DisplayResults.class.php b/libraries/DisplayResults.class.php index 3ee40f21d3..c793cc0d74 100644 --- a/libraries/DisplayResults.class.php +++ b/libraries/DisplayResults.class.php @@ -4201,11 +4201,11 @@ class PMA_DisplayResults /** * Prepare a table of results returned by a SQL query. * - * @param integer &$dt_result the link id associated to the query - * which results have to be displayed - * @param array &$displayParts the parts to display - * @param array $analyzed_sql the analyzed query - * @param boolean $is_limited_display With limited operations or not + * @param integer &$dt_result the link id associated to the query + * which results have to be displayed + * @param array &$displayParts the parts to display + * @param array $analyzed_sql_results analyzed sql results + * @param boolean $is_limited_display With limited operations or not * * @return string $table_html Generated HTML content for resulted table * @@ -4214,10 +4214,13 @@ class PMA_DisplayResults * @see sql.php file */ public function getTable( - &$dt_result, &$displayParts, $analyzed_sql, + &$dt_result, &$displayParts, $analyzed_sql_results, $is_limited_display = false ) { + // TODO: Remove. + $analyzed_sql = $analyzed_sql_results['analyzed_sql']; + $table_html = ''; // Following variable are needed for use in isset/empty or // use with array indexes/safe use in foreach @@ -4236,10 +4239,8 @@ class PMA_DisplayResults && $showtable['Type'] == self::TABLE_TYPE_INNO_DB); if ($is_innodb - && ! isset($analyzed_sql[0]['queryflags']['union']) - && ! isset($analyzed_sql[0]['table_ref'][1]['table_name']) - && (empty($analyzed_sql[0]['where_clause']) - || ($analyzed_sql[0]['where_clause'] == '1 ')) + && PMA_isJustBrowsing($analyzed_sql_results, true) + ) { // "j u s t b r o w s i n g" $pre_count = '~'; @@ -4310,9 +4311,7 @@ class PMA_DisplayResults // 2.3 Prepare the navigation bars if (!/*overload*/mb_strlen($this->__get('table'))) { - if (isset($analyzed_sql[0]['query_type']) - && ($analyzed_sql[0]['query_type'] == self::QUERY_TYPE_SELECT) - ) { + if ($analyzed_sql_results['querytype'] == 'SELECT') { // table does not always contain a real table name, // for example in MySQL 5.0.x, the query SHOW STATUS // returns STATUS as a table name @@ -4416,7 +4415,7 @@ class PMA_DisplayResults // 6. ----- Prepare "Query results operations" if ((! isset($printview) || ($printview != '1')) && ! $is_limited_display) { $table_html .= $this->_getResultsOperations( - $displayParts, $analyzed_sql + $displayParts, $analyzed_sql_results ); } @@ -4946,8 +4945,8 @@ class PMA_DisplayResults /** * Generates HTML to display the Create view in span tag * - * @param array $analyzed_sql the analyzed Query - * @param string $url_query String with URL Parameters + * @param array $analyzed_sql_results analyzed sql results + * @param string $url_query String with URL Parameters * * @return string * @@ -4955,10 +4954,10 @@ class PMA_DisplayResults * * @see _getResultsOperations() */ - private function _getLinkForCreateView($analyzed_sql, $url_query) + private function _getLinkForCreateView($analyzed_sql_results, $url_query) { $results_operations_html = ''; - if (!PMA_DRIZZLE && !isset($analyzed_sql[0]['queryflags']['procedure'])) { + if (!PMA_DRIZZLE && empty($analyzed_sql_results['procedure'])) { $ajax_class = ' ajax'; @@ -4979,14 +4978,14 @@ class PMA_DisplayResults /** * Calls the _getResultsOperations with $only_view as true * - * @param array $analyzed_sql the analyzed Query + * @param array $analyzed_sql_results analyzed sql results * * @return string * * @access public * */ - public function getCreateViewQueryResultOp($analyzed_sql) + public function getCreateViewQueryResultOp($analyzed_sql_results) { $results_operations_html = ''; @@ -4994,7 +4993,7 @@ class PMA_DisplayResults //and setting only_view parameter to be true to generate just view $results_operations_html .= $this->_getResultsOperations( array(), - $analyzed_sql, + $analyzed_sql_results, true ); return $results_operations_html; @@ -5027,7 +5026,7 @@ class PMA_DisplayResults * Get operations that are available on results. * * @param array $displayParts the parts to display - * @param array $analyzed_sql the analyzed query + * @param array $analyzed_sql_results analyzed sql results * @param boolean $only_view Whether to show only view * * @return string $results_operations_html html content @@ -5037,7 +5036,7 @@ class PMA_DisplayResults * @see getTable() */ private function _getResultsOperations( - $displayParts, $analyzed_sql, $only_view = false + $displayParts, $analyzed_sql_results, $only_view = false ) { global $printview; @@ -5063,7 +5062,7 @@ class PMA_DisplayResults // show only view and not other options if ($only_view == true) { $results_operations_html .= $this->_getLinkForCreateView( - $analyzed_sql, $url_query + $analyzed_sql_results, $url_query ); if ($header_shown) { @@ -5084,15 +5083,12 @@ class PMA_DisplayResults // If the parser found a PROCEDURE clause // (most probably PROCEDURE ANALYSE()) it makes no sense to // display the Export link). - if (isset($analyzed_sql[0]) - && ($analyzed_sql[0]['querytype'] == self::QUERY_TYPE_SELECT) + if (($analyzed_sql_results['querytype'] == self::QUERY_TYPE_SELECT) && ! isset($printview) - && ! isset($analyzed_sql[0]['queryflags']['procedure']) + && empty($analyzed_sql_results['procedure']) ) { - if (isset($analyzed_sql[0]['table_ref'][0]['table_true_name']) - && ! isset($analyzed_sql[0]['table_ref'][1]['table_true_name']) - ) { + if (count($analyzed_sql_results['select_tables']) == 1) { $_url_params['single_table'] = 'true'; } @@ -5185,7 +5181,7 @@ class PMA_DisplayResults } $results_operations_html .= $this->_getLinkForCreateView( - $analyzed_sql, $url_query + $analyzed_sql_results, $url_query ); if ($header_shown) { diff --git a/libraries/parse_analyze.inc.php b/libraries/parse_analyze.inc.php index c4c3904002..f2cee87efc 100644 --- a/libraries/parse_analyze.inc.php +++ b/libraries/parse_analyze.inc.php @@ -25,13 +25,13 @@ extract($analyzed_sql_results); // If the targeted table (and database) are different than the ones that is // currently browsed, edit `$db` and `$table` to match them so other elements // (page headers, links, navigation panel) can be updated properly. -if (!empty($analyzed_sql_results['tables'])) { +if (!empty($analyzed_sql_results['select_tables'])) { // Previous table and database name is stored to check if it changed. $prevDb = $db; $prevTable = $table; - if (count($analyzed_sql_results['tables']) > 1) { + if (count($analyzed_sql_results['select_tables']) > 1) { /** * @todo if there are more than one table name in the Select: @@ -41,9 +41,9 @@ if (!empty($analyzed_sql_results['tables'])) { */ $table = ''; } else { - $table = $analyzed_sql_results['tables'][0][0]; - if (!empty($analyzed_sql_results['tables'][0][1])) { - $db = $analyzed_sql_results['tables'][0][1]; + $table = $analyzed_sql_results['select_tables'][0][0]; + if (!empty($analyzed_sql_results['select_tables'][0][1])) { + $db = $analyzed_sql_results['select_tables'][0][1]; } } diff --git a/libraries/sql-parser/src/Fragments/LimitKeyword.php b/libraries/sql-parser/src/Fragments/LimitKeyword.php index 261ef3e721..a23eb4c73e 100644 --- a/libraries/sql-parser/src/Fragments/LimitKeyword.php +++ b/libraries/sql-parser/src/Fragments/LimitKeyword.php @@ -70,6 +70,10 @@ class LimitKeyword extends Fragment continue; } + if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { + break; + } + if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'OFFSET')) { if ($offset) { $parser->error('An offset was expected.'); diff --git a/libraries/sql-parser/src/Parser.php b/libraries/sql-parser/src/Parser.php index 0a876b7ab1..2a9bd47c47 100644 --- a/libraries/sql-parser/src/Parser.php +++ b/libraries/sql-parser/src/Parser.php @@ -79,7 +79,11 @@ class Parser * @var array */ public static $KEYWORD_PARSERS = array( - + 'ALTER' => array( + 'class' => 'SqlParser\\Fragments\\FieldFragment', + 'field' => 'table', + 'options' => array('skipColumn' => true), + ), 'ANALYZE' => array( 'class' => 'SqlParser\\Fragments\\FromKeyword', 'field' => 'tables', @@ -100,6 +104,10 @@ class Parser 'class' => 'SqlParser\\Fragments\\FromKeyword', 'field' => 'tables', ), + 'DROP' => array( + 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'field' => 'fields' + ), 'FROM' => array( 'class' => 'SqlParser\\Fragments\\FromKeyword', 'field' => 'from', diff --git a/libraries/sql-parser/src/Statement.php b/libraries/sql-parser/src/Statement.php index 74b2cc3a6a..f10b5eed7f 100644 --- a/libraries/sql-parser/src/Statement.php +++ b/libraries/sql-parser/src/Statement.php @@ -100,9 +100,18 @@ abstract class Statement */ $field = null; + /** + * Parser's options. + * @var array + */ + $options = array(); + if (!empty(Parser::$KEYWORD_PARSERS[$token->value])) { $class = Parser::$KEYWORD_PARSERS[$token->value]['class']; $field = Parser::$KEYWORD_PARSERS[$token->value]['field']; + if (!empty(Parser::$KEYWORD_PARSERS[$token->value]['options'])) { + $options = Parser::$KEYWORD_PARSERS[$token->value]['options']; + } } if (!empty(Parser::$STATEMENT_PARSERS[$token->value])) { @@ -130,7 +139,7 @@ abstract class Statement // Parsing this keyword. if ($class !== null) { ++$list->idx; // Skipping keyword. - $this->$field = $class::parse($parser, $list, array()); + $this->$field = $class::parse($parser, $list, $options); } $this->after($parser, $list, $token); diff --git a/libraries/sql-parser/src/Statements/AlterStatement.php b/libraries/sql-parser/src/Statements/AlterStatement.php index 1d6b44ca96..b6c18edf3c 100644 --- a/libraries/sql-parser/src/Statements/AlterStatement.php +++ b/libraries/sql-parser/src/Statements/AlterStatement.php @@ -8,6 +8,11 @@ */ namespace SqlParser\Statements; +use SqlParser\Parser; +use SqlParser\Token; +use SqlParser\TokensList; +use SqlParser\Fragments\FieldFragment; +use SqlParser\Fragments\OptionsFragment; use SqlParser\Statements\NotImplementedStatement; /** @@ -22,6 +27,20 @@ use SqlParser\Statements\NotImplementedStatement; class AlterStatement extends NotImplementedStatement { + /** + * Table affected. + * + * @var FieldFragment + */ + public $table; + + /** + * Column affected by this statement. + * + * @var FieldFragment + */ + public $altered; + /** * Options of this statement. * @@ -29,17 +48,81 @@ class AlterStatement extends NotImplementedStatement */ public static $OPTIONS = array( - 'DATABASE' => 1, - 'EVENT' => 1, - 'FUNCTION' => 1, - 'INDEX' => 1, - 'LOGFILE' => 1, - 'PROCEDURE' => 1, - 'SCHEMA' => 1, - 'SERVER' => 1, - 'TABLE' => 1, - 'TABLESPACE' => 1, - 'TRIGGER' => 1, + 'ONLINE' => 1, + 'OFFLINE' => 1, + + 'IGNORE' => 2, + + 'TABLE' => 3, + + 'ADD' => 4, + 'ALTER' => 4, + 'ANALYZE' => 4, + 'CHANGE' => 4, + 'CHECK' => 4, + 'COALESCE' => 4, + 'CONVERT' => 4, + 'DISABLE' => 4, + 'DISCARD' => 4, + 'DROP' => 4, + 'ENABLE' => 4, + 'IMPORT' => 4, + 'MODIFY' => 4, + 'OPTIMIZE' => 4, + 'ORDER' => 4, + 'PARTITION' => 4, + 'REBUILD' => 4, + 'REMOVE' => 4, + 'RENAME' => 4, + 'REORGANIZE' => 4, + 'REPAIR' => 4, + + 'COLUMN' => 5, + 'CONSTRAINT' => 5, + 'DEFAULT' => 5, + 'TO' => 5, + 'BY' => 5, + 'FOREIGN' => 5, + 'FULLTEXT' => 5, + 'KEYS' => 5, + 'PARTITIONING' => 5, + 'PRIMARY KEY' => 5, + 'SPATIAL' => 5, + 'TABLESPACE' => 5, + 'INDEX' => 5, + + 'DEFAULT CHARACTER SET' => array(6, 'var'), + + 'COLLATE' => array(7, 'var'), ); + /** + * Extracts the name of affected column. + * + * @param Parser $parser The instance that requests parsing. + * @param TokensList $list The list of tokens to be parsed. + * @param Token $token The token that is being parsed. + * + * @return void + */ + public function after(Parser $parser, TokensList $list, Token $token) + { + // Parsing operation. + ++$list->idx; + $this->options->merge( + OptionsFragment::parse( + $parser, + $list, + static::$OPTIONS + ) + ); + + // Parsing affected field. + ++$list->idx; + $this->altered = FieldFragment::parse($parser, $list); + + // + parent::after($parser, $list, $token); + } + } diff --git a/libraries/sql-parser/src/Statements/DropStatement.php b/libraries/sql-parser/src/Statements/DropStatement.php index 716ca54f84..babf18ac58 100644 --- a/libraries/sql-parser/src/Statements/DropStatement.php +++ b/libraries/sql-parser/src/Statements/DropStatement.php @@ -48,7 +48,7 @@ class DropStatement extends Statement /** * Dropped elements. * - * @var FromKeyworrd[] + * @var FieldFragment[] */ - public $name; + public $fields; } diff --git a/libraries/sql-parser/src/Statements/NotImplementedStatement.php b/libraries/sql-parser/src/Statements/NotImplementedStatement.php index 1ad5cc50ef..1689df22ee 100644 --- a/libraries/sql-parser/src/Statements/NotImplementedStatement.php +++ b/libraries/sql-parser/src/Statements/NotImplementedStatement.php @@ -16,7 +16,7 @@ use SqlParser\TokensList; /** * Not implemented (yet) statements. * - * The `before` function makes the parser jump straight to the first delimiter. + * The `after` function makes the parser jump straight to the first delimiter. * * @category Statements * @package SqlParser @@ -36,7 +36,7 @@ class NotImplementedStatement extends Statement * * @return void */ - public function before(Parser $parser, TokensList $list, Token $token) + public function after(Parser $parser, TokensList $list, Token $token) { $list->getNextOfType(Token::TYPE_DELIMITER); --$list->idx; diff --git a/libraries/sql-parser/src/Utils/Query.php b/libraries/sql-parser/src/Utils/Query.php index 8cb9dfd4fd..dde33042d2 100644 --- a/libraries/sql-parser/src/Utils/Query.php +++ b/libraries/sql-parser/src/Utils/Query.php @@ -373,6 +373,10 @@ class Query if ($statement instanceof SelectStatement) { $ret['select_tables'] = array(); $ret['select_expr'] = array(); + + // Trying to find selected tables only from the select expression. + // Sometimes, this is not possible because the tables aren't defined + // explicitly (e.g. SELECT * FROM film, SELECT film_id FROM film). foreach ($statement->expr as $expr) { if (!empty($expr->table)) { $ret['select_tables'][] = array( @@ -383,16 +387,37 @@ class Query $ret['select_expr'][] = $expr->expr; } } + + // If no tables names were found in the SELECT clause or if there + // are expressions like * or COUNT(*), etc. tables names should be + // extracted from the FROM clause as well. + if ((empty($ret['select_tables'])) || (!$ret['select_expr'])) { + foreach ($statement->from as $expr) { + if (!empty($expr->table)) { + $ret['select_tables'][] = array( + $expr->table, + !empty($expr->database) ? $expr->database : null + ); + } + } + } } return $ret; } + /** + * Gets the type of clause. + * + * @param string $clause The clause. + * + * @return string + */ public static function getClauseType($clause) { $type = ''; for ($i = 0, $len = strlen($clause); $i < $len; ++$i) { - if ((empty($type)) && (ctype_space($type))) { + if ((empty($type)) && (ctype_space($clause[$i]))) { // Skipping whitespaces if we haven't started determining the // type. continue; @@ -408,18 +433,20 @@ class Query } /** - * Replaces the clause in the query. If the clause does not exist, it is - * inserted. - * - * It is a very basic version of a query builder. + * Gets a specific clause. * * @param Statement $statement The parsed query that has to be modified. * @param TokensList $list The list of tokens. - * @param string $clause The clause to be replaced. + * @param string $clause The clause to be returned. + * @param int $type The type of the search. + * -1 for everything that was before + * 0 only for the clause + * 1 for everything after + * @param bool $skipFirst Whether to skip the first keyword in clause. * * @return string */ - public static function replaceClause($statement, $list, $clause) + public static function getClause($statement, $list, $clause, $type = 0, $skipFirst = true) { /** @@ -436,16 +463,10 @@ class Query $brackets = 0; /** - * The sections before the clause + * The string to be returned. * @var string */ - $before = ''; - - /** - * The sections after the clause. - * @var string - */ - $after = ''; + $ret = ''; /** * The place where the clause should be added. @@ -473,21 +494,57 @@ class Query // Checking if we changed sections. if ($token->type === Token::TYPE_KEYWORD) { if (isset($statement::$SECTIONS[$token->value])) { - if ($statement::$SECTIONS[$token->value] > $currIdx) { + if ($statement::$SECTIONS[$token->value] >= $currIdx) { $currIdx = $statement::$SECTIONS[$token->value]; + if (($skipFirst) && ($currIdx == $clauseIdx)) { + // This token is skipped (not added to the old + // clause) because it will be replaced. + continue; + } } } } } - if ($currIdx < $clauseIdx) { - $before .= $token->token; - } elseif ($currIdx > $clauseIdx) { - $after .= $token->value; + if ((($type === -1) && ($currIdx < $clauseIdx)) + || (($type === 0) && ($currIdx === $clauseIdx)) + || (($type === 1) && ($currIdx > $clauseIdx)) + ) { + $ret .= $token->token; } } - return $before . ' ' . $clause . ' ' . $after; + return trim($ret); + } + + /** + * Builds a query by rebuilding the statement from the tokens list supplied + * and replaces a clause. + * + * It is a very basic version of a query builder. + * + * @param Statement $statement The parsed query that has to be modified. + * @param TokensList $list The list of tokens. + * @param string $clause The clause to be replaced. + * @param bool $onlyType Whether only the type of the clause should + * be replaced or the entire clause. + * + * @return string + */ + public static function replaceClause($statement, $list, $clause, $onlyType = false) + { + // TODO: Update the tokens list and the statement. + + if ($onlyType) { + return static::getClause($statement, $list, $clause, -1, false) . ' ' . + $clause . ' ' . + static::getCLause($statement, $list, $clause, 0) . ' ' . + static::getClause($statement, $list, $clause, 1, false); + } + + return static::getClause($statement, $list, $clause, -1, false) . ' ' . + $clause . ' ' . + static::getClause($statement, $list, $clause, 1, false); } } diff --git a/libraries/sql.lib.php b/libraries/sql.lib.php index 206da97d60..3abe192229 100644 --- a/libraries/sql.lib.php +++ b/libraries/sql.lib.php @@ -99,7 +99,11 @@ function PMA_handleSortOrder( // Store the remembered table into session. $pmatable->setUiProp( PMA_Table::PROP_SORTED_COLUMN, - $analyzed_sql_results['analyzed_sql'][0]['order_by_clause'] + Query::getClause( + $analyzed_sql_results['statement'], + $analyzed_sql_results['parser']->list, + 'ORDER' + ) ); } } @@ -623,8 +627,8 @@ function PMA_isRememberSortingOrder($analyzed_sql_results) || $analyzed_sql_results['is_analyse']) && $analyzed_sql_results['select_from'] && empty($analyzed_sql_results['select_expr']) - && count($analyzed_sql_results['analyzed_sql']['select_expr']) == 0 - && count($analyzed_sql_results['analyzed_sql']['select_tables']) == 1; + && count($analyzed_sql_results['select_expr']) == 0 + && count($analyzed_sql_results['select_tables']) == 1; } /** @@ -1127,11 +1131,12 @@ function PMA_cleanupRelations($db, $table, $dropped_column, $purge, $extra_data) function PMA_countQueryResults( $num_rows, $justBrowsing, $db, $table, $analyzed_sql_results ) { + if (!PMA_isAppendLimitClause($analyzed_sql_results)) { // if we did not append a limit, set this to get a correct // "Showing rows..." message // $_SESSION['tmpval']['max_rows'] = 'all'; - $unlim_num_rows = $num_rows; + $unlim_num_rows = $num_rows; } elseif ($analyzed_sql_results['querytype'] == 'SELECT' || $analyzed_sql_results['is_subquery'] ) { @@ -1171,64 +1176,31 @@ function PMA_countQueryResults( } } else { - // add select expression after the SQL_CALC_FOUND_ROWS - // for UNION, just adding SQL_CALC_FOUND_ROWS - // after the first SELECT works. + // The SQL_CALC_FOUND_ROWS option of the SELECT statement is used. - // take the left part, could be: - // SELECT - // (SELECT + // For UNION statements, only a SQL_CALC_FOUND_ROWS is required + // after the first SELECT. - // TODO: Replace PMA_SQP_ - - $analyzed_sql = $analyzed_sql_results['analyzed_sql']; - - $count_query = PMA_SQP_format( - $analyzed_sql_results['parsed_sql'], - 'query_only', - 0, - $analyzed_sql[0]['position_of_first_select'] + 1 + $count_query = SqlParser\Utils\Query::replaceClause( + $analyzed_sql_results['statement'], + $analyzed_sql_results['parser']->list, + 'SELECT SQL_CALC_FOUND_ROWS', + true ); - $count_query .= ' SQL_CALC_FOUND_ROWS '; - // add everything that was after the first SELECT - $count_query .= PMA_SQP_format( - $analyzed_sql_results['parsed_sql'], - 'query_only', - $analyzed_sql[0]['position_of_first_select'] + 1 - ); - // ensure there is no semicolon at the end of the - // count query because we'll probably add - // a LIMIT 1 clause after it - $count_query = rtrim($count_query); - $count_query = rtrim($count_query, ';'); - // if using SQL_CALC_FOUND_ROWS, add a LIMIT to avoid - // long delays. Returned count will be complete anyway. - // (but a LIMIT would disrupt results in an UNION) + // Another LIMIT clause is added to avoid long delays. + // A complete result will be returned anyway, but the LIMIT would + // stop the query as soon as the result that is required has been + // computed. - if (! isset($analyzed_sql[0]['queryflags']['union'])) { + if (empty($analyzed_sql_results['queryflags']['union'])) { $count_query .= ' LIMIT 1'; } - // run the count query - + // Running the count query. $GLOBALS['dbi']->tryQuery($count_query); - // if (mysql_error()) { - // void. - // I tried the case - // (SELECT `User`, `Host`, `Db`, `Select_priv` FROM `db`) - // UNION (SELECT `User`, `Host`, "%" AS "Db", - // `Select_priv` - // FROM `user`) ORDER BY `User`, `Host`, `Db`; - // and although the generated count_query is wrong - // the SELECT FOUND_ROWS() work! (maybe it gets the - // count from the latest query that worked) - // - // another case where the count_query is wrong: - // SELECT COUNT(*), f1 from t1 group by f1 - // and you click to sort on count(*) - // } + $unlim_num_rows = $GLOBALS['dbi']->fetchValue('SELECT FOUND_ROWS()'); } // end else "just browsing" } else {// not $is_select @@ -1336,22 +1308,14 @@ function PMA_executeTheQuery($analyzed_sql_results, $full_sql_query, $is_gotofil function PMA_deleteTransformationInfo($db, $table, $analyzed_sql_results) { include_once 'libraries/transformations.lib.php'; - if ($analyzed_sql_results['querytype'] == 'ALTER') { - $posDrop = /*overload*/mb_stripos( - $analyzed_sql_results['analyzed_sql'][0]['unsorted_query'], - 'DROP' - ); - if ($posDrop !== false) { - $drop_column = PMA_getColumnNameInColumnDropSql( - $analyzed_sql_results['analyzed_sql'][0]['unsorted_query'] - ); - - if ($drop_column != '') { - PMA_clearTransformations($db, $table, $drop_column); + $statement = $analyzed_sql_results['statement']; + if ($statement instanceof SqlParser\Statements\AlterStatement) { + if ($statement->options->has('DROP')) { + if (!empty($statement->altered->column)) { + PMA_clearTransformations($db, $table, $statement->altered->column); } } - - } else if (($analyzed_sql_results['querytype'] == 'DROP') && ($table != '')) { + } elseif ($statement instanceof SqlParser\Statements\DropStatement) { PMA_clearTransformations($db, $table); } } @@ -1490,7 +1454,7 @@ function PMA_getQueryResponseForNoResultsReturned($analyzed_sql_results, $db, if (!empty($analyzed_sql_results['is_select'])) { $html_output .= $displayResultsObject->getCreateViewQueryResultOp( - $analyzed_sql_results['analyzed_sql'] + $analyzed_sql_results ); } } @@ -1649,7 +1613,7 @@ function PMA_getHtmlForSqlQueryResultsTable($displayResultsObject, $table_html .= $displayResultsObject->getTable( $result, $displayParts, - $analyzed_sql_results['analyzed_sql'] + $analyzed_sql_results ); } @@ -1675,7 +1639,7 @@ function PMA_getHtmlForSqlQueryResultsTable($displayResultsObject, ); $table_html .= $displayResultsObject->getTable( - $result, $displayParts, $analyzed_sql_results['analyzed_sql'] + $result, $displayParts, $analyzed_sql_results ); $GLOBALS['dbi']->freeResult($result); } @@ -1847,10 +1811,16 @@ function PMA_getQueryResponseForResultsReturned($result, // - if the result set does not contain all the columns of a unique key // (unless this is an updatable view) - $sele_exp_cls = $analyzed_sql_results['analyzed_sql'][0]['select_expr_clause']; - $updatableView - = trim($sele_exp_cls) == '*' - && PMA_Table::isUpdatableView($db, $table); + $updatableView = false; + + $statement = $analyzed_sql_results['statement']; + if ($statement instanceof SqlParser\Statements\SelectStatement) { + if (!empty($statement->expr)) { + if ($statement->expr[0]->expr === '*') { + $updatableView = PMA_Table::isUpdatableView($db, $table); + } + } + } $has_unique = PMA_resultSetContainsUniqueKey( $db, $table, $fields_meta From d2b54985656d25befd5abd225caa701cfcfbee4f Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Tue, 30 Jun 2015 01:06:44 +0300 Subject: [PATCH 31/57] Fix failing tests. Updated sql-parser library. Signed-off-by: Dan Ungureanu --- libraries/parse_analyze.inc.php | 8 +- libraries/sql-parser/src/Builder.php | 84 +++++++++++++++ libraries/sql-parser/src/Fragment.php | 11 ++ .../src/Fragments/ArrayFragment.php | 37 ++++++- .../sql-parser/src/Fragments/CallKeyword.php | 33 +++++- .../src/Fragments/CreateDefFragment.php | 1 - .../src/Fragments/DataTypeFragment.php | 1 - .../src/Fragments/FieldDefFragment.php | 3 +- .../src/Fragments/FieldFragment.php | 73 ++++++++++++- ...electKeyword.php => FieldListFragment.php} | 18 +++- .../sql-parser/src/Fragments/FromKeyword.php | 83 -------------- .../sql-parser/src/Fragments/IntoKeyword.php | 5 +- .../sql-parser/src/Fragments/JoinKeyword.php | 1 - .../sql-parser/src/Fragments/KeyFragment.php | 1 - .../sql-parser/src/Fragments/LimitKeyword.php | 27 ++++- .../src/Fragments/OptionsFragment.php | 32 +++++- .../sql-parser/src/Fragments/OrderKeyword.php | 3 +- .../src/Fragments/ParamDefFragment.php | 1 - .../src/Fragments/ReferencesKeyword.php | 5 +- .../src/Fragments/RenameKeyword.php | 1 - .../sql-parser/src/Fragments/SetKeyword.php | 1 - .../src/Fragments/ValuesKeyword.php | 1 - .../sql-parser/src/Fragments/WhereKeyword.php | 51 ++++++--- libraries/sql-parser/src/Lexer.php | 1 - libraries/sql-parser/src/Parser.php | 101 +++++++++++++++--- libraries/sql-parser/src/Statement.php | 30 ++++-- .../src/Statements/AlterStatement.php | 3 +- ...sumStatement.php => ChecksumStatement.php} | 0 .../src/Statements/CreateStatement.php | 2 + .../src/Statements/MaintenanceStatement.php | 2 + .../Statements/NotImplementedStatement.php | 2 + .../src/Statements/RenameStatement.php | 2 + .../src/Statements/SelectStatement.php | 43 +++++--- libraries/sql-parser/src/Token.php | 86 +++++++-------- libraries/sql-parser/src/Utils/Query.php | 58 +++++----- libraries/sql-parser/src/Utils/Table.php | 3 - 36 files changed, 566 insertions(+), 248 deletions(-) create mode 100644 libraries/sql-parser/src/Builder.php rename libraries/sql-parser/src/Fragments/{SelectKeyword.php => FieldListFragment.php} (81%) delete mode 100644 libraries/sql-parser/src/Fragments/FromKeyword.php rename libraries/sql-parser/src/Statements/{ChecsumStatement.php => ChecksumStatement.php} (100%) diff --git a/libraries/parse_analyze.inc.php b/libraries/parse_analyze.inc.php index f2cee87efc..785a36faf8 100644 --- a/libraries/parse_analyze.inc.php +++ b/libraries/parse_analyze.inc.php @@ -28,8 +28,7 @@ extract($analyzed_sql_results); if (!empty($analyzed_sql_results['select_tables'])) { // Previous table and database name is stored to check if it changed. - $prevDb = $db; - $prevTable = $table; + $prev_db = $db; if (count($analyzed_sql_results['select_tables']) > 1) { @@ -50,9 +49,8 @@ if (!empty($analyzed_sql_results['select_tables'])) { // There is no point checking if a reload is required if we already decided // to reload. Also, no reload is required for AJAX requests. if ((empty($reload)) && (empty($GLOBALS['is_ajax_request']))) { - // NOTE: Tables are case-insensitive. - $reload = ((strcasecmp($db, $prevDb) == 0) - || (strcasecmp($table, $prevTable)) == 0) ? false : true; + // NOTE: Database names are case-insensitive. + $reload = strcasecmp($db, $prev_db) != 0; } // Updating the array as well. diff --git a/libraries/sql-parser/src/Builder.php b/libraries/sql-parser/src/Builder.php new file mode 100644 index 0000000000..b4559e9aa0 --- /dev/null +++ b/libraries/sql-parser/src/Builder.php @@ -0,0 +1,84 @@ + + * @license http://opensource.org/licenses/GPL-2.0 GNU Public License + */ +class Builder +{ + + /** + * Statement to be build. + * + * @var Statement + */ + public $statement; + + /** + * Built query. + * + * @var string + */ + public $query; + + /** + * Constructor. + * + * @param Statement $statement + */ + public function __construct($statement = null) + { + $this->statement = $statement; + + if ($this->statement != null) { + $this->build(); + } + } + + /** + * Builds the statement. + * + * @return void + */ + public function build() + { + $statement = $this->statement; + foreach ($statement::$CLAUSES as $clause) { + $name = $clause[0]; + $type = $clause[1]; + + if (empty(Parser::$KEYWORD_PARSERS[$name])) { + continue; + } + + $class = Parser::$KEYWORD_PARSERS[$name]['class']; + $field = Parser::$KEYWORD_PARSERS[$name]['field']; + + if (empty($statement->$field)) { + continue; + } + + if ($type & 2) { + $this->query .= $name . ' '; + } + + if ($type & 1) { + $this->query .= $class::build($statement->$field) . ' '; + } + } + } +} diff --git a/libraries/sql-parser/src/Fragment.php b/libraries/sql-parser/src/Fragment.php index a9a349ac23..6ae85da486 100644 --- a/libraries/sql-parser/src/Fragment.php +++ b/libraries/sql-parser/src/Fragment.php @@ -38,4 +38,15 @@ abstract class Fragment return null; } + /** + * Builds the string representation of a fragment of this type. + * + * @param Fragment $fragment The fragment to be built. + * + * @return string + */ + public static function build(Fragment $fragment) + { + return null; + } } diff --git a/libraries/sql-parser/src/Fragments/ArrayFragment.php b/libraries/sql-parser/src/Fragments/ArrayFragment.php index 7ed22ad9c0..db12622493 100644 --- a/libraries/sql-parser/src/Fragments/ArrayFragment.php +++ b/libraries/sql-parser/src/Fragments/ArrayFragment.php @@ -25,6 +25,13 @@ use SqlParser\TokensList; class ArrayFragment extends Fragment { + /** + * The array that contains the unprocessed value of each token. + * + * @var array + */ + public $raw = array(); + /** * The array that contains the processed value of each token. * @@ -33,11 +40,16 @@ class ArrayFragment extends Fragment public $values = array(); /** - * The array that contains the unprocessed value of each token. + * Constructor. * - * @var array + * @param array $raw The unprocessed values. + * @param array $values The processed values. */ - public $raw = array(); + public function __construct(array $raw = array(), array $values = array()) + { + $this->raw = $raw; + $this->values = $values; + } /** * @param Parser $parser The parser that serves as context. @@ -67,7 +79,6 @@ class ArrayFragment extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token @@ -114,4 +125,22 @@ class ArrayFragment extends Fragment return $ret; } + + /** + * @param ArrayFragment $fragment The fragment to be built. + * + * @return string + */ + public static function build(ArrayFragment $fragment) + { + $values = array(); + if (!empty($fragment->raw)) { + $values = $fragment->raw; + } else { + foreach ($fragment->values as $value) { + $values[] = $value; + } + } + return '(' . implode(', ', $values) . ')'; + } } diff --git a/libraries/sql-parser/src/Fragments/CallKeyword.php b/libraries/sql-parser/src/Fragments/CallKeyword.php index ae3c467f6a..3b8cc80b5a 100644 --- a/libraries/sql-parser/src/Fragments/CallKeyword.php +++ b/libraries/sql-parser/src/Fragments/CallKeyword.php @@ -35,9 +35,25 @@ class CallKeyword extends Fragment /** * The list of parameters * - * @var array + * @var ArrayFragment */ - public $parameters = array(); + public $parameters; + + /** + * Constructor. + * + * @param string $name The name of the function to be called. + * @param array|ArrayFragment $parameters The parameters of this function. + */ + public function __construct($name = null, $parameters = null) + { + $this->name = $name; + if (is_array($parameters)) { + $this->parameters = new ArrayFragment($parameters); + } elseif ($parameters instanceof ArrayFragment) { + $this->parameters = $parameters; + } + } /** * @param Parser $parser The parser that serves as context. @@ -64,7 +80,6 @@ class CallKeyword extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token @@ -86,7 +101,7 @@ class CallKeyword extends Fragment $state = 1; } elseif ($state === 1) { if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { - $ret->parameters = ArrayFragment::parse($parser, $list)->values; + $ret->parameters = ArrayFragment::parse($parser, $list); } break; } @@ -95,4 +110,14 @@ class CallKeyword extends Fragment return $ret; } + + /** + * @param CallKeyword $fragment The fragment to be built. + * + * @return string + */ + public static function build(CallKeyword $fragment) + { + return $fragment->name . ArrayFragment::build($fragment->parameters); + } } diff --git a/libraries/sql-parser/src/Fragments/CreateDefFragment.php b/libraries/sql-parser/src/Fragments/CreateDefFragment.php index 403426c109..933ea5ef5e 100644 --- a/libraries/sql-parser/src/Fragments/CreateDefFragment.php +++ b/libraries/sql-parser/src/Fragments/CreateDefFragment.php @@ -92,7 +92,6 @@ class CreateDefFragment extends Fragment $ret = new CreateDefFragment(); for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token diff --git a/libraries/sql-parser/src/Fragments/DataTypeFragment.php b/libraries/sql-parser/src/Fragments/DataTypeFragment.php index 2ad700a676..0b9e1a81b2 100644 --- a/libraries/sql-parser/src/Fragments/DataTypeFragment.php +++ b/libraries/sql-parser/src/Fragments/DataTypeFragment.php @@ -94,7 +94,6 @@ class DataTypeFragment extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token diff --git a/libraries/sql-parser/src/Fragments/FieldDefFragment.php b/libraries/sql-parser/src/Fragments/FieldDefFragment.php index d38eeda7c8..6c5771e95a 100644 --- a/libraries/sql-parser/src/Fragments/FieldDefFragment.php +++ b/libraries/sql-parser/src/Fragments/FieldDefFragment.php @@ -129,7 +129,6 @@ class FieldDefFragment extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token @@ -176,7 +175,7 @@ class FieldDefFragment extends Fragment --$list->idx; } $state = 5; - } else if ($state === 5) { + } elseif ($state === 5) { if ((!empty($expr->type)) || (!empty($expr->key))) { $ret[] = $expr; } diff --git a/libraries/sql-parser/src/Fragments/FieldFragment.php b/libraries/sql-parser/src/Fragments/FieldFragment.php index 51403248cb..8b0f0ef125 100644 --- a/libraries/sql-parser/src/Fragments/FieldFragment.php +++ b/libraries/sql-parser/src/Fragments/FieldFragment.php @@ -74,6 +74,38 @@ class FieldFragment extends Fragment */ public $subquery; + /** + * Constructor. + * + * Syntax: + * new FieldFragment('expr') + * new FieldFragment('expr', 'alias') + * new FieldFragment('database', 'table', 'column') + * new FieldFragment('database', 'table', 'column', 'alias') + * + * If the database, table or column name is not required, pass an empty + * string. + * + * @param string $database The name of the database or the the expression. + * the the expression. + * @param string $table The name of the table or the alias of the expression. + * the alias of the expression. + * @param string $column The name of the column. + * @param string $alias The name of the alias. + */ + public function __construct($database = null, $table = null, $column = null, $alias = null) + { + if (($column === null) && ($alias === null)) { + $this->expr = $database; // case 1 + $this->alias = $table; // case 2 + } else { + $this->database = $database; // case 3 + $this->table = $table; // case 3 + $this->column = $column; // case 3 + $this->alias = $alias; // case 4 + } + } + /** * @param Parser $parser The parser that serves as context. * @param TokensList $list The list of tokens that are being parsed. @@ -120,7 +152,6 @@ class FieldFragment extends Fragment $prev = null; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token @@ -150,8 +181,10 @@ class FieldFragment extends Fragment $alias = 2; continue; } - break; - } else if ($prev === true) { + if (!($token->flags & Token::FLAG_KEYWORD_FUNCTION)) { + break; + } + } elseif ($prev === true) { if ((empty($ret->subquery) && (!empty(Parser::$STATEMENT_PARSERS[$token->value])))) { // A `(` was previously found and this keyword is the // beginning of a statement, so this is a subquery. @@ -236,7 +269,7 @@ class FieldFragment extends Fragment if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_FUNCTION)) { $prev = strtoupper($token->value); - } else if (($token->type === Token::TYPE_OPERATOR) || ($token->value === '(')) { + } elseif (($token->type === Token::TYPE_OPERATOR) || ($token->value === '(')) { $prev = true; } else { $prev = null; @@ -258,4 +291,36 @@ class FieldFragment extends Fragment --$list->idx; return $ret; } + + /** + * @param FieldFragment $fragment The fragment to be built. + * + * @return string + */ + public static function build($fragment) + { + $ret = ''; + + if (!empty($fragment->expr)) { + $ret = $fragment->expr; + } else { + $fields = array(); + if (!empty($fragment->database)) { + $fields[] = $fragment->database; + } + if (!empty($fragment->table)) { + $fields[] = $fragment->table; + } + if (!empty($fragment->column)) { + $fields[] = $fragment->column; + } + $ret = implode('.', $fields); + } + + if (!empty($fragment->alias)) { + $ret .= ' AS ' . $fragment->alias; + } + + return $ret; + } } diff --git a/libraries/sql-parser/src/Fragments/SelectKeyword.php b/libraries/sql-parser/src/Fragments/FieldListFragment.php similarity index 81% rename from libraries/sql-parser/src/Fragments/SelectKeyword.php rename to libraries/sql-parser/src/Fragments/FieldListFragment.php index 5cf47199e3..cc769e00e8 100644 --- a/libraries/sql-parser/src/Fragments/SelectKeyword.php +++ b/libraries/sql-parser/src/Fragments/FieldListFragment.php @@ -1,7 +1,7 @@ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License */ -class SelectKeyword extends Fragment +class FieldListFragment extends Fragment { /** @@ -39,7 +39,6 @@ class SelectKeyword extends Fragment $expr = null; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token @@ -64,7 +63,7 @@ class SelectKeyword extends Fragment if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) { $ret[] = $expr; } else { - $expr = FieldFragment::parse($parser, $list); + $expr = FieldFragment::parse($parser, $list, $options); if ($expr === null) { break; } @@ -80,4 +79,13 @@ class SelectKeyword extends Fragment --$list->idx; return $ret; } + + public static function build($fragment) + { + $ret = array(); + foreach ($fragment as $frag) { + $ret[] = $frag::build($frag); + } + return implode($ret, ', '); + } } diff --git a/libraries/sql-parser/src/Fragments/FromKeyword.php b/libraries/sql-parser/src/Fragments/FromKeyword.php deleted file mode 100644 index 6fbf0ba365..0000000000 --- a/libraries/sql-parser/src/Fragments/FromKeyword.php +++ /dev/null @@ -1,83 +0,0 @@ - - * @license http://opensource.org/licenses/GPL-2.0 GNU Public License - */ -class FromKeyword extends Fragment -{ - - /** - * @param Parser $parser The parser that serves as context. - * @param TokensList $list The list of tokens that are being parsed. - * @param array $options Parameters for parsing. - * - * @return FieldFragment[] - */ - public static function parse(Parser $parser, TokensList $list, array $options = array()) - { - $ret = array(); - - $expr = new FieldFragment(); - - for (; $list->idx < $list->count; ++$list->idx) { - - /** - * Token parsed at this moment. - * @var Token - */ - $token = $list->tokens[$list->idx]; - - // End of statement. - if ($token->type === Token::TYPE_DELIMITER) { - break; - } - - // Skipping whitespaces and comments. - if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { - continue; - } - - // No keyword is expected. - if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { - break; - } - - if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) { - $ret[] = $expr; - } else { - $expr = FieldFragment::parse($parser, $list, array('skipColumn' => true)); - if ($expr === null) { - break; - } - } - - } - - // Last iteration was not saved. - if ($expr !== null) { - $ret[] = $expr; - } - - --$list->idx; - return $ret; - } -} diff --git a/libraries/sql-parser/src/Fragments/IntoKeyword.php b/libraries/sql-parser/src/Fragments/IntoKeyword.php index 558b3e64c6..0b515319e3 100644 --- a/libraries/sql-parser/src/Fragments/IntoKeyword.php +++ b/libraries/sql-parser/src/Fragments/IntoKeyword.php @@ -74,7 +74,6 @@ class IntoKeyword extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token @@ -105,13 +104,13 @@ class IntoKeyword extends Fragment if ($state === 0) { $ret->name = $token->value; $state = 1; - } else if ($state === 1) { + } elseif ($state === 1) { if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) { $ret->fields = ArrayFragment::parse($parser, $list)->values; ++$list->idx; } break; - } else if ($state === 2) { + } elseif ($state === 2) { $ret->name = $token->value; ++$list->idx; break; diff --git a/libraries/sql-parser/src/Fragments/JoinKeyword.php b/libraries/sql-parser/src/Fragments/JoinKeyword.php index 011bd4d80d..f8e1a57963 100644 --- a/libraries/sql-parser/src/Fragments/JoinKeyword.php +++ b/libraries/sql-parser/src/Fragments/JoinKeyword.php @@ -66,7 +66,6 @@ class JoinKeyword extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token diff --git a/libraries/sql-parser/src/Fragments/KeyFragment.php b/libraries/sql-parser/src/Fragments/KeyFragment.php index 4a71857c90..d84c9f6565 100644 --- a/libraries/sql-parser/src/Fragments/KeyFragment.php +++ b/libraries/sql-parser/src/Fragments/KeyFragment.php @@ -95,7 +95,6 @@ class KeyFragment extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token diff --git a/libraries/sql-parser/src/Fragments/LimitKeyword.php b/libraries/sql-parser/src/Fragments/LimitKeyword.php index a23eb4c73e..af8d92dbd8 100644 --- a/libraries/sql-parser/src/Fragments/LimitKeyword.php +++ b/libraries/sql-parser/src/Fragments/LimitKeyword.php @@ -39,6 +39,18 @@ class LimitKeyword extends Fragment */ public $rowCount; + /** + * Constructor. + * + * @param int $rowCount The row count. + * @param int $offset The offset. + */ + public function __construct($rowCount = null, $offset = null) + { + $this->rowCount = $rowCount; + $this->offset = $offset; + } + /** * @param Parser $parser The parser that serves as context. * @param TokensList $list The list of tokens that are being parsed. @@ -53,7 +65,6 @@ class LimitKeyword extends Fragment $offset = false; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token @@ -103,4 +114,18 @@ class LimitKeyword extends Fragment --$list->idx; return $ret; } + + /** + * @param LimitKeyword $fragment The fragment to be built. + * + * @return string + */ + public static function build($fragment) + { + if (empty($fragment->offset)) { + return $fragment->rowCount; + } else { + return $fragment->offset . ', ' . $fragment->rowCount; + } + } } diff --git a/libraries/sql-parser/src/Fragments/OptionsFragment.php b/libraries/sql-parser/src/Fragments/OptionsFragment.php index 54d4857d2f..16459cc5ba 100644 --- a/libraries/sql-parser/src/Fragments/OptionsFragment.php +++ b/libraries/sql-parser/src/Fragments/OptionsFragment.php @@ -32,6 +32,17 @@ class OptionsFragment extends Fragment */ public $options = array(); + /** + * Constructor. + * + * @param array $options The array of options. Options that have a value + * must be an array with two keys 'name' and 'value'. + */ + public function __construct(array $options = array()) + { + $this->options = $options; + } + /** * @param Parser $parser The parser that serves as context. * @param TokensList $list The list of tokens that are being parsed. @@ -59,7 +70,6 @@ class OptionsFragment extends Fragment $brackets = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token @@ -127,6 +137,24 @@ class OptionsFragment extends Fragment return $ret; } + /** + * @param OptionsFragment $fragment The fragment to be built. + * + * @return string + */ + public static function build(OptionsFragment $fragment) + { + $options = array(); + foreach ($fragment->options as $option) { + if (is_array($option)) { + $options[] = $option['name'] . '=' . $option['value']; + } else { + $options[] = $option; + } + } + return implode(' ', $options); + } + /** * Checks if it has the specified option and returns it value or true. * @@ -158,7 +186,7 @@ class OptionsFragment extends Fragment { if (is_array($options)) { $this->options = array_merge_recursive($this->options, $options); - } else if ($options instanceof OptionsFragment) { + } elseif ($options instanceof OptionsFragment) { $this->options = array_merge_recursive($this->options, $options->options); } } diff --git a/libraries/sql-parser/src/Fragments/OrderKeyword.php b/libraries/sql-parser/src/Fragments/OrderKeyword.php index 51942083fc..7a760841c1 100644 --- a/libraries/sql-parser/src/Fragments/OrderKeyword.php +++ b/libraries/sql-parser/src/Fragments/OrderKeyword.php @@ -67,7 +67,6 @@ class OrderKeyword extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token @@ -90,7 +89,7 @@ class OrderKeyword extends Fragment } elseif ($state === 1) { if (($token->type === Token::TYPE_KEYWORD) && (($token->value === 'ASC') || ($token->value === 'DESC'))) { $expr->type = $token->value; - } else if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) { + } elseif (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) { if (!empty($expr->field)) { $ret[] = $expr; } diff --git a/libraries/sql-parser/src/Fragments/ParamDefFragment.php b/libraries/sql-parser/src/Fragments/ParamDefFragment.php index a51259658d..583c3abbcd 100644 --- a/libraries/sql-parser/src/Fragments/ParamDefFragment.php +++ b/libraries/sql-parser/src/Fragments/ParamDefFragment.php @@ -80,7 +80,6 @@ class ParamDefFragment extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token diff --git a/libraries/sql-parser/src/Fragments/ReferencesKeyword.php b/libraries/sql-parser/src/Fragments/ReferencesKeyword.php index d4afd0194f..8de0233a71 100644 --- a/libraries/sql-parser/src/Fragments/ReferencesKeyword.php +++ b/libraries/sql-parser/src/Fragments/ReferencesKeyword.php @@ -84,7 +84,6 @@ class ReferencesKeyword extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token @@ -104,10 +103,10 @@ class ReferencesKeyword extends Fragment if ($state === 0) { $ret->table = $token->value; $state = 1; - } else if ($state === 1) { + } elseif ($state === 1) { $ret->columns = ArrayFragment::parse($parser, $list)->values; $state = 2; - } else if ($state === 2) { + } elseif ($state === 2) { $ret->options = OptionsFragment::parse($parser, $list, static::$REFERENCES_OPTIONS); ++$list->idx; break; diff --git a/libraries/sql-parser/src/Fragments/RenameKeyword.php b/libraries/sql-parser/src/Fragments/RenameKeyword.php index 980ad7b022..077982aafb 100644 --- a/libraries/sql-parser/src/Fragments/RenameKeyword.php +++ b/libraries/sql-parser/src/Fragments/RenameKeyword.php @@ -71,7 +71,6 @@ class RenameKeyword extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token diff --git a/libraries/sql-parser/src/Fragments/SetKeyword.php b/libraries/sql-parser/src/Fragments/SetKeyword.php index 547768cb37..bced45fb43 100644 --- a/libraries/sql-parser/src/Fragments/SetKeyword.php +++ b/libraries/sql-parser/src/Fragments/SetKeyword.php @@ -67,7 +67,6 @@ class SetKeyword extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token diff --git a/libraries/sql-parser/src/Fragments/ValuesKeyword.php b/libraries/sql-parser/src/Fragments/ValuesKeyword.php index 6977f6811a..c867551599 100644 --- a/libraries/sql-parser/src/Fragments/ValuesKeyword.php +++ b/libraries/sql-parser/src/Fragments/ValuesKeyword.php @@ -65,7 +65,6 @@ class ValuesKeyword extends Fragment $state = 0; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token diff --git a/libraries/sql-parser/src/Fragments/WhereKeyword.php b/libraries/sql-parser/src/Fragments/WhereKeyword.php index 1b36cc8a73..d2143f3589 100644 --- a/libraries/sql-parser/src/Fragments/WhereKeyword.php +++ b/libraries/sql-parser/src/Fragments/WhereKeyword.php @@ -46,6 +46,16 @@ class WhereKeyword extends Fragment */ public $condition; + /** + * Constructor. + * + * @param string $condition The condition or the operator. + */ + public function __construct($condition = null) + { + $this->condition = trim($condition); + } + /** * @param Parser $parser The parser that serves as context. * @param TokensList $list The list of tokens that are being parsed. @@ -57,10 +67,13 @@ class WhereKeyword extends Fragment { $ret = array(); - $expr = new WhereKeyword(); + /** + * The condition that was parsed so far. + * @var string + */ + $condition = ''; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token @@ -73,23 +86,23 @@ class WhereKeyword extends Fragment } // Skipping whitespaces and comments. - if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) { + if ($token->type === Token::TYPE_COMMENT) { continue; } // Conditions are delimited by logical operators. if (in_array($token->value, static::$OPERATORS, true)) { - if (!empty($expr->condition)) { - $ret[] = $expr; + if (!empty(trim($condition))) { + // Adding the condition that is delimited by this operator. + $ret[] = new WhereKeyword($condition); + $condition = ''; } - $expr = new WhereKeyword(); + // Adding the operator. + $expr = new WhereKeyword($token->value); $expr->isOperator = true; - $expr->condition = $token->value; $ret[] = $expr; - $expr = new WhereKeyword(); - continue; } @@ -98,16 +111,30 @@ class WhereKeyword extends Fragment break; } - $expr->condition .= $token->token; + $condition .= $token->token; } // Last iteration was not processed. - if (!empty($expr->condition)) { - $ret[] = $expr; + if (!empty(trim($condition))) { + $ret[] = new WhereKeyword($condition); } --$list->idx; return $ret; } + + /** + * @param WhereKeyword $fragment The fragment to be built. + * + * @return string + */ + public static function build($fragment) + { + $conditions = array(); + foreach ($fragment as $f) { + $conditions[] = $f->condition; + } + return implode(' ', $conditions); + } } diff --git a/libraries/sql-parser/src/Lexer.php b/libraries/sql-parser/src/Lexer.php index b91db8bf2a..0d0862d908 100644 --- a/libraries/sql-parser/src/Lexer.php +++ b/libraries/sql-parser/src/Lexer.php @@ -168,7 +168,6 @@ class Lexer $lastToken = null; for ($this->last = 0, $lastIdx = 0; $this->last < $this->len; $lastIdx = ++$this->last) { - /** * The new token. * @var Token diff --git a/libraries/sql-parser/src/Parser.php b/libraries/sql-parser/src/Parser.php index 2a9bd47c47..29e67017f5 100644 --- a/libraries/sql-parser/src/Parser.php +++ b/libraries/sql-parser/src/Parser.php @@ -9,6 +9,7 @@ */ namespace SqlParser; +use SqlParser\Statements\SelectStatement; use SqlParser\Exceptions\ParserException; /** @@ -37,7 +38,7 @@ class Parser 'ANALYZE' => 'SqlParser\\Statements\\AnalyzeStatement', 'BACKUP' => 'SqlParser\\Statements\\BackupStatement', 'CHECK' => 'SqlParser\\Statements\\CheckStatement', - 'CHECKSUM' => 'SqlParser\\Statements\\ChecsumStatement', + 'CHECKSUM' => 'SqlParser\\Statements\\ChecksumStatement', 'OPTIMIZE' => 'SqlParser\\Statements\\OptimizeStatement', 'REPAIR' => 'SqlParser\\Statements\\RepairStatement', 'RESTORE' => 'SqlParser\\Statements\\RestoreStatement', @@ -79,38 +80,51 @@ class Parser * @var array */ public static $KEYWORD_PARSERS = array( + + // This is not a proper keyword and was added here to help the builder. + '_OPTIONS' => array( + 'class' => 'SqlParser\\Fragments\\OptionsFragment', + 'field' => 'options', + ), + 'ALTER' => array( 'class' => 'SqlParser\\Fragments\\FieldFragment', 'field' => 'table', 'options' => array('skipColumn' => true), ), 'ANALYZE' => array( - 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'class' => 'SqlParser\\Fragments\\FieldListFragment', 'field' => 'tables', + 'options' => array('skipColumn' => true), ), 'BACKUP' => array( - 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'class' => 'SqlParser\\Fragments\\FieldListFragment', 'field' => 'tables', + 'options' => array('skipColumn' => true), ), 'CALL' => array( 'class' => 'SqlParser\\Fragments\\CallKeyword', 'field' => 'call', ), 'CHECK' => array( - 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'class' => 'SqlParser\\Fragments\\FieldListFragment', 'field' => 'tables', + 'options' => array('skipColumn' => true), ), 'CHECKSUM' => array( - 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'class' => 'SqlParser\\Fragments\\FieldListFragment', 'field' => 'tables', + 'options' => array('skipColumn' => true), ), 'DROP' => array( - 'class' => 'SqlParser\\Fragments\\FromKeyword', - 'field' => 'fields' + 'class' => 'SqlParser\\Fragments\\FieldListFragment', + 'field' => 'fields', + 'options' => array('skipColumn' => true), ), 'FROM' => array( - 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'class' => 'SqlParser\\Fragments\\FieldListFragment', 'field' => 'from', + 'options' => array('skipColumn' => true), ), 'GROUP BY' => array( 'class' => 'SqlParser\\Fragments\\OrderKeyword', @@ -133,8 +147,9 @@ class Parser 'field' => 'limit', ), 'OPTIMIZE' => array( - 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'class' => 'SqlParser\\Fragments\\FieldListFragment', 'field' => 'tables', + 'options' => array('skipColumn' => true), ), 'ORDER BY' => array( 'class' => 'SqlParser\\Fragments\\OrderKeyword', @@ -153,24 +168,27 @@ class Parser 'field' => 'renames', ), 'REPAIR' => array( - 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'class' => 'SqlParser\\Fragments\\FieldListFragment', 'field' => 'tables', + 'options' => array('skipColumn' => true), ), 'RESTORE' => array( - 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'class' => 'SqlParser\\Fragments\\FieldListFragment', 'field' => 'tables', + 'options' => array('skipColumn' => true), ), 'SET' => array( 'class' => 'SqlParser\\Fragments\\SetKeyword', 'field' => 'set', ), 'SELECT' => array( - 'class' => 'SqlParser\\Fragments\\SelectKeyword', + 'class' => 'SqlParser\\Fragments\\FieldListFragment', 'field' => 'expr', ), 'UPDATE' => array( - 'class' => 'SqlParser\\Fragments\\FromKeyword', + 'class' => 'SqlParser\\Fragments\\FieldListFragment', 'field' => 'from', + 'options' => array('skipColumn' => true), ), 'VALUE' => array( 'class' => 'SqlParser\\Fragments\\ValuesKeyword', @@ -252,6 +270,29 @@ class Parser */ public function parse() { + + /** + * Last parsed statement. + * @var Statement + */ + $lastStatement = null; + + /** + * Whether a union is parsed or not. + * @var bool + */ + $inUnion = true; + + /** + * The index of the last token from the last statement. + * @var int + */ + $prevLastIdx = -1; + + /** + * The list of tokens. + * @var TokensList + */ $list = &$this->list; for (; $list->idx < $list->count; ++$list->idx) { @@ -268,13 +309,21 @@ class Parser continue; } + if ($token->value === 'UNION') { + $inUnion = true; + continue; + } + // Checking if it is a known statement that can be parsed. if (empty(static::$STATEMENT_PARSERS[$token->value])) { $this->error( 'Unrecognized statement type "' . $token->value . '".', $token ); + // Skipping to the end of this statement. $list->getNextOfType(Token::TYPE_DELIMITER); + // + $prevLastIdx = $list->idx; continue; } @@ -290,8 +339,32 @@ class Parser */ $stmt = new $class(); + // The first token that is a part of this token is the next token + // unprocessed by the previous statement. + // There might be brackets around statements and this shouldn't + // affect the parser + $stmt->first = $prevLastIdx + 1; + + // Parsing the actual statement. $stmt->parse($this, $this->list); - $this->statements[] = $stmt; + + // Storing the index of the last token parsed and updating the old + // index. + $stmt->last = $list->idx; + $prevLastIdx = $list->idx; + + // Finally, storing the statement. + if (($inUnion) + && ($lastStatement instanceof SelectStatement) + && ($stmt instanceof SelectStatement) + ) { + $lastStatement->union[] = $stmt; + $inUnion = false; + } else { + $this->statements[] = $stmt; + $lastStatement = $stmt; + } + } } diff --git a/libraries/sql-parser/src/Statement.php b/libraries/sql-parser/src/Statement.php index f10b5eed7f..0cb362cdc0 100644 --- a/libraries/sql-parser/src/Statement.php +++ b/libraries/sql-parser/src/Statement.php @@ -26,6 +26,20 @@ use SqlParser\Fragments\OptionsFragment; abstract class Statement { + /** + * The clauses of this statement, in order. + * + * The value attributed to each clause is used by the builder and it may + * have one of the following values: + * + * - 1 = 01 - add the clause only + * - 2 = 10 - add the keyword + * - 3 = 11 - add both the keyword and the clause + * + * @var array + */ + public static $CLAUSES; + /** * The options of this query. * @@ -59,8 +73,6 @@ abstract class Statement */ public function parse(Parser $parser, TokensList $list) { - $this->first = $list->idx; - /** * Whether options were parsed or not. * For statements that do not have any options this is set to `true` by @@ -70,7 +82,6 @@ abstract class Statement $parsedOptions = isset(static::$OPTIONS) ? false : true; for (; $list->idx < $list->count; ++$list->idx) { - /** * Token parsed at this moment. * @var Token @@ -88,6 +99,12 @@ abstract class Statement continue; } + // Unions are parsed by the parser because they represent more than + // one statement. + if ($token->value === 'UNION') { + break; + } + /** * The name of the class that is used for parsing. * @var string @@ -124,7 +141,7 @@ abstract class Statement ); $parsedOptions = true; } - } else if ($class === null) { + } elseif ($class === null) { // There is no parser for this keyword and isn't the beggining // of a statement (so no options) either. $parser->error( @@ -145,11 +162,11 @@ abstract class Statement $this->after($parser, $list, $token); } - $this->last = $list->idx--; // Go back to last used token. + --$list->idx; // Go back to last used token. } /** - * Function called before the token was processed. + * Function called before the token is processed. * * @param Parser $parser The instance that requests parsing. * @param TokensList $list The list of tokens to be parsed. @@ -175,5 +192,4 @@ abstract class Statement { } - } diff --git a/libraries/sql-parser/src/Statements/AlterStatement.php b/libraries/sql-parser/src/Statements/AlterStatement.php index b6c18edf3c..81bca056f9 100644 --- a/libraries/sql-parser/src/Statements/AlterStatement.php +++ b/libraries/sql-parser/src/Statements/AlterStatement.php @@ -97,6 +97,8 @@ class AlterStatement extends NotImplementedStatement ); /** + * Function called after the token was processed. + * * Extracts the name of affected column. * * @param Parser $parser The instance that requests parsing. @@ -124,5 +126,4 @@ class AlterStatement extends NotImplementedStatement // parent::after($parser, $list, $token); } - } diff --git a/libraries/sql-parser/src/Statements/ChecsumStatement.php b/libraries/sql-parser/src/Statements/ChecksumStatement.php similarity index 100% rename from libraries/sql-parser/src/Statements/ChecsumStatement.php rename to libraries/sql-parser/src/Statements/ChecksumStatement.php diff --git a/libraries/sql-parser/src/Statements/CreateStatement.php b/libraries/sql-parser/src/Statements/CreateStatement.php index ef11537d99..f13866a965 100644 --- a/libraries/sql-parser/src/Statements/CreateStatement.php +++ b/libraries/sql-parser/src/Statements/CreateStatement.php @@ -100,6 +100,8 @@ class CreateStatement extends Statement public $body; /** + * Function called before the token is processed. + * * Parsing the `CREATE` statement. * * @param Parser $parser The instance that requests parsing. diff --git a/libraries/sql-parser/src/Statements/MaintenanceStatement.php b/libraries/sql-parser/src/Statements/MaintenanceStatement.php index a0df6343df..97c87b94b1 100644 --- a/libraries/sql-parser/src/Statements/MaintenanceStatement.php +++ b/libraries/sql-parser/src/Statements/MaintenanceStatement.php @@ -37,6 +37,8 @@ class MaintenanceStatement extends Statement public $tables; /** + * Function called after the token was processed. + * * Parses the additional options fragment at the end. * * @param Parser $parser The instance that requests parsing. diff --git a/libraries/sql-parser/src/Statements/NotImplementedStatement.php b/libraries/sql-parser/src/Statements/NotImplementedStatement.php index 1689df22ee..b96c5583fd 100644 --- a/libraries/sql-parser/src/Statements/NotImplementedStatement.php +++ b/libraries/sql-parser/src/Statements/NotImplementedStatement.php @@ -28,6 +28,8 @@ class NotImplementedStatement extends Statement { /** + * Function called after the token was processed. + * * Jump to the end of the delimiter. * * @param Parser $parser The instance that requests parsing. diff --git a/libraries/sql-parser/src/Statements/RenameStatement.php b/libraries/sql-parser/src/Statements/RenameStatement.php index 5ebd2faac4..473efe0ad2 100644 --- a/libraries/sql-parser/src/Statements/RenameStatement.php +++ b/libraries/sql-parser/src/Statements/RenameStatement.php @@ -36,6 +36,8 @@ class RenameStatement extends Statement public $renames; /** + * Function called before the token is processed. + * * Skips the `TABLE` keyword after `RENAME`. * * @param Parser $parser The instance that requests parsing. diff --git a/libraries/sql-parser/src/Statements/SelectStatement.php b/libraries/sql-parser/src/Statements/SelectStatement.php index 0c4c354f19..7704e263fe 100644 --- a/libraries/sql-parser/src/Statements/SelectStatement.php +++ b/libraries/sql-parser/src/Statements/SelectStatement.php @@ -68,17 +68,29 @@ class SelectStatement extends Statement ); /** - * The sections of this statement, in order. + * The clauses of this statement, in order. * - * Used by the query builder to arrange the clauses. + * @see Statement::$CLAUSES * * @var array */ - public static $SECTIONS = array( - 'SELECT' => 0, '%OPTIONS' => 1,'FROM' => 2, 'PARTITION' => 3, - 'WHERE' => 4, 'GROUP BY' => 5, 'HAVING' => 6, 'ORDER BY' => 7, - 'LIMIT' => 8, 'PROCEDURE' => 9, 'INTO' => 10, 'UNION' => 11, - 'JOIN' => 12, '%OPTIONS' => 13 + public static $CLAUSES = array( + 'SELECT' => array('SELECT', 2), + // Used for options. + '_OPTIONS' => array('_OPTIONS', 1), + // Used for select expressions. + '_SELECT' => array('SELECT', 1), + 'FROM' => array('FROM', 3), + 'PARTITION' => array('PARTITION', 3), + 'WHERE' => array('WHERE', 3), + 'GROUP BY' => array('GROUP BY', 3), + 'HAVING' => array('HAVING', 3), + 'ORDER BY' => array('ORDER BY', 3), + 'LIMIT' => array('LIMIT', 3), + 'PROCEDURE' => array('PROCEDURE', 3), + 'INTO' => array('INTO', 3), + 'UNION' => array('UNION', 3), + 'JOIN' => array('JOIN', 3), ); /** @@ -86,33 +98,33 @@ class SelectStatement extends Statement * * @var FieldFragment[] */ - public $expr; + public $expr = array(); /** * Tables used as sources for this statement. * * @var FieldFragment[] */ - public $from; + public $from = array(); /** * Partitions used as source for this statement. * - * @var ArrayFragment[] + * @var ArrayFragment */ public $partition; /** * Conditions used for filtering each row of the result set. * - * @var WhereKeyword + * @var WhereKeyword[] */ public $where; /** * Conditions used for grouping the result set. * - * @var GroupKeyword + * @var OrderKeyword[] */ public $group; @@ -157,4 +169,11 @@ class SelectStatement extends Statement * @var JoinKeyword */ public $join; + + /** + * Unions. + * + * @var SelectStatement[] + */ + public $union = array(); } diff --git a/libraries/sql-parser/src/Token.php b/libraries/sql-parser/src/Token.php index fa23d2870f..1db0d1d037 100644 --- a/libraries/sql-parser/src/Token.php +++ b/libraries/sql-parser/src/Token.php @@ -217,52 +217,52 @@ class Token public function extract() { switch ($this->type) { - case Token::TYPE_KEYWORD: - if (!($this->flags & Token::FLAG_KEYWORD_RESERVED)) { - // Unreserved keywords should stay the way they are because they - // might represent field names. - return $this->token; - } - return strtoupper($this->token); - case Token::TYPE_WHITESPACE: - return ' '; - case Token::TYPE_BOOL: - return strtoupper($this->token) === 'TRUE'; - case Token::TYPE_NUMBER: - $ret = str_replace('--', '', $this->token); // e.g. ---42 === -42 - if ($this->flags & Token::FLAG_NUMBER_HEX) { - if ($this->flags & Token::FLAG_NUMBER_NEGATIVE) { - $ret = str_replace('-', '', $this->token); - sscanf($ret, "%x", $ret); - $ret = -$ret; - } else { - sscanf($ret, "%x", $ret); + case Token::TYPE_KEYWORD: + if (!($this->flags & Token::FLAG_KEYWORD_RESERVED)) { + // Unreserved keywords should stay the way they are because they + // might represent field names. + return $this->token; } - } elseif (($this->flags & Token::FLAG_NUMBER_APPROXIMATE) + return strtoupper($this->token); + case Token::TYPE_WHITESPACE: + return ' '; + case Token::TYPE_BOOL: + return strtoupper($this->token) === 'TRUE'; + case Token::TYPE_NUMBER: + $ret = str_replace('--', '', $this->token); // e.g. ---42 === -42 + if ($this->flags & Token::FLAG_NUMBER_HEX) { + if ($this->flags & Token::FLAG_NUMBER_NEGATIVE) { + $ret = str_replace('-', '', $this->token); + sscanf($ret, "%x", $ret); + $ret = -$ret; + } else { + sscanf($ret, "%x", $ret); + } + } elseif (($this->flags & Token::FLAG_NUMBER_APPROXIMATE) || ($this->flags & Token::FLAG_NUMBER_FLOAT) - ) { - sscanf($ret, "%f", $ret); - } else { - sscanf($ret, "%d", $ret); - } - return $ret; - case Token::TYPE_STRING: - $quote = $this->token[0]; - $str = str_replace($quote . $quote, $quote, $this->token); - return mb_substr($str, 1, -1); // trims quotes - case Token::TYPE_SYMBOL: - $str = $this->token; - if ((isset($str[0])) && ($str[0] === '@')) { - $str = mb_substr($str, 1); - } - if ((isset($str[0])) && (($str[0] === '`') + ) { + sscanf($ret, "%f", $ret); + } else { + sscanf($ret, "%d", $ret); + } + return $ret; + case Token::TYPE_STRING: + $quote = $this->token[0]; + $str = str_replace($quote . $quote, $quote, $this->token); + return mb_substr($str, 1, -1); // trims quotes + case Token::TYPE_SYMBOL: + $str = $this->token; + if ((isset($str[0])) && ($str[0] === '@')) { + $str = mb_substr($str, 1); + } + if ((isset($str[0])) && (($str[0] === '`') || ($str[0] === '"') || ($str[0] === '\'')) - ) { - $quote = $str[0]; - $str = str_replace($quote . $quote, $quote, $str); - $str = mb_substr($str, 1, -1); - } - return $str; + ) { + $quote = $str[0]; + $str = str_replace($quote . $quote, $quote, $str); + $str = mb_substr($str, 1, -1); + } + return $str; } return $this->token; } diff --git a/libraries/sql-parser/src/Utils/Query.php b/libraries/sql-parser/src/Utils/Query.php index dde33042d2..f97374404a 100644 --- a/libraries/sql-parser/src/Utils/Query.php +++ b/libraries/sql-parser/src/Utils/Query.php @@ -222,32 +222,32 @@ class Query if ($statement instanceof AlterStatement) { $flags['querytype'] = 'ALTER'; $flags['reload'] = true; - } else if ($statement instanceof CreateStatement) { + } elseif ($statement instanceof CreateStatement) { $flags['querytype'] = 'CREATE'; $flags['reload'] = true; - } else if ($statement instanceof AnalyzeStatement) { + } elseif ($statement instanceof AnalyzeStatement) { $flags['querytype'] = 'ANALYZE'; $flags['is_maint'] = true; - } else if ($statement instanceof CheckStatement) { + } elseif ($statement instanceof CheckStatement) { $flags['querytype'] = 'CHECK'; $flags['is_maint'] = true; - } else if ($statement instanceof ChecksumStatement) { + } elseif ($statement instanceof ChecksumStatement) { $flags['querytype'] = 'CHECKSUM'; $flags['is_maint'] = true; - } else if ($statement instanceof OptimizeStatement) { + } elseif ($statement instanceof OptimizeStatement) { $flags['querytype'] = 'OPTIMIZE'; $flags['is_maint'] = true; - } else if ($statement instanceof RepairStatement) { + } elseif ($statement instanceof RepairStatement) { $flags['querytype'] = 'REPAIR'; $flags['is_maint'] = true; - } else if ($statement instanceof CallStatement) { + } elseif ($statement instanceof CallStatement) { $flags['querytype'] = 'CALL'; $flags['is_procedure'] = true; - } else if ($statement instanceof DeleteStatement) { + } elseif ($statement instanceof DeleteStatement) { $flags['querytype'] = 'DELETE'; $flags['is_delete'] = true; $flags['is_affected'] = true; - } else if ($statement instanceof DropStatement) { + } elseif ($statement instanceof DropStatement) { $flags['querytype'] = 'DROP'; $flags['reload'] = true; @@ -256,19 +256,19 @@ class Query ) { $flags['drop_database'] = true; } - } else if ($statement instanceof ExplainStatement) { + } elseif ($statement instanceof ExplainStatement) { $flags['querytype'] = 'EXPLAIN'; $flags['is_explain'] = true; - } else if ($statement instanceof InsertStatement) { + } elseif ($statement instanceof InsertStatement) { $flags['querytype'] = 'INSERT'; $flags['is_affected'] = true; $flags['is_insert'] = true; - } else if ($statement instanceof ReplaceStatement) { + } elseif ($statement instanceof ReplaceStatement) { $flags['querytype'] = 'REPLACE'; $flags['is_affected'] = true; $flags['is_replace'] = true; $flags['is_insert'] = true; - } else if ($statement instanceof SelectStatement) { + } elseif ($statement instanceof SelectStatement) { $flags['querytype'] = 'SELECT'; $flags['is_select'] = true; @@ -294,7 +294,7 @@ class Query if (!empty($expr->function)) { if ($expr->function === 'COUNT') { $flags['is_count'] = true; - } else if (in_array($expr->function, static::$FUNCTIONS)) { + } elseif (in_array($expr->function, static::$FUNCTIONS)) { $flags['is_func'] = true; } } @@ -325,10 +325,10 @@ class Query $flags['join'] = true; } - } else if ($statement instanceof ShowStatement) { + } elseif ($statement instanceof ShowStatement) { $flags['querytype'] = 'SHOW'; $flags['is_show'] = true; - } else if ($statement instanceof UpdateStatement) { + } elseif ($statement instanceof UpdateStatement) { $flags['querytype'] = 'UPDATE'; $flags['is_affected'] = true; } @@ -409,7 +409,7 @@ class Query /** * Gets the type of clause. * - * @param string $clause The clause. + * @param string $clause The clause. * * @return string */ @@ -450,7 +450,7 @@ class Query { /** - * Current location. + * The index of the current clause. * @var int */ $currIdx = 0; @@ -469,19 +469,20 @@ class Query $ret = ''; /** - * The place where the clause should be added. + * The clauses of this type of statement and their index. + * @var array + */ + $clauses = array_flip(array_keys($statement::$CLAUSES)); + + /** + * The index of this clause. * @var int */ - $clauseIdx = $statement::$SECTIONS[static::getClauseType($clause)]; + $clauseIdx = $clauses[static::getClauseType($clause)]; for ($i = $statement->first; $i <= $statement->last; ++$i) { - $token = $list->tokens[$i]; - if ($token->type === Token::TYPE_DELIMITER) { - break; - } - if ($token->type === Token::TYPE_OPERATOR) { if ($token->value === '(') { ++$brackets; @@ -493,9 +494,9 @@ class Query if ($brackets == 0) { // Checking if we changed sections. if ($token->type === Token::TYPE_KEYWORD) { - if (isset($statement::$SECTIONS[$token->value])) { - if ($statement::$SECTIONS[$token->value] >= $currIdx) { - $currIdx = $statement::$SECTIONS[$token->value]; + if (isset($clauses[$token->value])) { + if ($clauses[$token->value] >= $currIdx) { + $currIdx = $clauses[$token->value]; if (($skipFirst) && ($currIdx == $clauseIdx)) { // This token is skipped (not added to the old // clause) because it will be replaced. @@ -546,5 +547,4 @@ class Query $clause . ' ' . static::getClause($statement, $list, $clause, 1, false); } - } diff --git a/libraries/sql-parser/src/Utils/Table.php b/libraries/sql-parser/src/Utils/Table.php index 95b685001c..86ccbfb4d1 100644 --- a/libraries/sql-parser/src/Utils/Table.php +++ b/libraries/sql-parser/src/Utils/Table.php @@ -43,7 +43,6 @@ class Table $ret = array(); foreach ($statement->fields as $field) { - if ((empty($field->key)) || ($field->key->type !== 'FOREIGN KEY')) { continue; } @@ -93,7 +92,6 @@ class Table $ret = array(); foreach ($statement->fields as $field) { - // Skipping keys. if (empty($field->type)) { continue; @@ -105,7 +103,6 @@ class Table ); if ($field->options) { - if ($field->type->name === 'TIMESTAMP') { if ($field->options->has('NOT NULL')) { $ret[$field->name]['timestamp_not_null'] = true; From 825cfbdc11436e9c125b680aa1df98868dd657a7 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Tue, 30 Jun 2015 01:26:47 +0300 Subject: [PATCH 32/57] Fixed coding style. Signed-off-by: Dan Ungureanu --- libraries/DisplayResults.class.php | 5 +- .../src/Fragments/FieldFragment.php | 2 - .../sql-parser/src/Fragments/WhereKeyword.php | 2 +- .../src/Statements/SelectStatement.php | 2 +- libraries/sql-parser/src/Token.php | 86 +++++++++---------- 5 files changed, 47 insertions(+), 50 deletions(-) diff --git a/libraries/DisplayResults.class.php b/libraries/DisplayResults.class.php index c793cc0d74..5d8fcdccd2 100644 --- a/libraries/DisplayResults.class.php +++ b/libraries/DisplayResults.class.php @@ -4240,7 +4240,6 @@ class PMA_DisplayResults if ($is_innodb && PMA_isJustBrowsing($analyzed_sql_results, true) - ) { // "j u s t b r o w s i n g" $pre_count = '~'; @@ -5025,9 +5024,9 @@ class PMA_DisplayResults /** * Get operations that are available on results. * - * @param array $displayParts the parts to display + * @param array $displayParts the parts to display * @param array $analyzed_sql_results analyzed sql results - * @param boolean $only_view Whether to show only view + * @param boolean $only_view Whether to show only view * * @return string $results_operations_html html content * diff --git a/libraries/sql-parser/src/Fragments/FieldFragment.php b/libraries/sql-parser/src/Fragments/FieldFragment.php index 8b0f0ef125..a6c5777e08 100644 --- a/libraries/sql-parser/src/Fragments/FieldFragment.php +++ b/libraries/sql-parser/src/Fragments/FieldFragment.php @@ -299,8 +299,6 @@ class FieldFragment extends Fragment */ public static function build($fragment) { - $ret = ''; - if (!empty($fragment->expr)) { $ret = $fragment->expr; } else { diff --git a/libraries/sql-parser/src/Fragments/WhereKeyword.php b/libraries/sql-parser/src/Fragments/WhereKeyword.php index d2143f3589..8bc3018d2b 100644 --- a/libraries/sql-parser/src/Fragments/WhereKeyword.php +++ b/libraries/sql-parser/src/Fragments/WhereKeyword.php @@ -125,7 +125,7 @@ class WhereKeyword extends Fragment } /** - * @param WhereKeyword $fragment The fragment to be built. + * @param WhereKeyword[] $fragment The fragment to be built. * * @return string */ diff --git a/libraries/sql-parser/src/Statements/SelectStatement.php b/libraries/sql-parser/src/Statements/SelectStatement.php index 7704e263fe..84ec5a29f3 100644 --- a/libraries/sql-parser/src/Statements/SelectStatement.php +++ b/libraries/sql-parser/src/Statements/SelectStatement.php @@ -70,7 +70,7 @@ class SelectStatement extends Statement /** * The clauses of this statement, in order. * - * @see Statement::$CLAUSES + * @see Statement::$CLAUSES * * @var array */ diff --git a/libraries/sql-parser/src/Token.php b/libraries/sql-parser/src/Token.php index 1db0d1d037..fa23d2870f 100644 --- a/libraries/sql-parser/src/Token.php +++ b/libraries/sql-parser/src/Token.php @@ -217,52 +217,52 @@ class Token public function extract() { switch ($this->type) { - case Token::TYPE_KEYWORD: - if (!($this->flags & Token::FLAG_KEYWORD_RESERVED)) { - // Unreserved keywords should stay the way they are because they - // might represent field names. - return $this->token; - } - return strtoupper($this->token); - case Token::TYPE_WHITESPACE: - return ' '; - case Token::TYPE_BOOL: - return strtoupper($this->token) === 'TRUE'; - case Token::TYPE_NUMBER: - $ret = str_replace('--', '', $this->token); // e.g. ---42 === -42 - if ($this->flags & Token::FLAG_NUMBER_HEX) { - if ($this->flags & Token::FLAG_NUMBER_NEGATIVE) { - $ret = str_replace('-', '', $this->token); - sscanf($ret, "%x", $ret); - $ret = -$ret; - } else { - sscanf($ret, "%x", $ret); - } - } elseif (($this->flags & Token::FLAG_NUMBER_APPROXIMATE) - || ($this->flags & Token::FLAG_NUMBER_FLOAT) - ) { - sscanf($ret, "%f", $ret); + case Token::TYPE_KEYWORD: + if (!($this->flags & Token::FLAG_KEYWORD_RESERVED)) { + // Unreserved keywords should stay the way they are because they + // might represent field names. + return $this->token; + } + return strtoupper($this->token); + case Token::TYPE_WHITESPACE: + return ' '; + case Token::TYPE_BOOL: + return strtoupper($this->token) === 'TRUE'; + case Token::TYPE_NUMBER: + $ret = str_replace('--', '', $this->token); // e.g. ---42 === -42 + if ($this->flags & Token::FLAG_NUMBER_HEX) { + if ($this->flags & Token::FLAG_NUMBER_NEGATIVE) { + $ret = str_replace('-', '', $this->token); + sscanf($ret, "%x", $ret); + $ret = -$ret; } else { - sscanf($ret, "%d", $ret); + sscanf($ret, "%x", $ret); } - return $ret; - case Token::TYPE_STRING: - $quote = $this->token[0]; - $str = str_replace($quote . $quote, $quote, $this->token); - return mb_substr($str, 1, -1); // trims quotes - case Token::TYPE_SYMBOL: - $str = $this->token; - if ((isset($str[0])) && ($str[0] === '@')) { - $str = mb_substr($str, 1); - } - if ((isset($str[0])) && (($str[0] === '`') + } elseif (($this->flags & Token::FLAG_NUMBER_APPROXIMATE) + || ($this->flags & Token::FLAG_NUMBER_FLOAT) + ) { + sscanf($ret, "%f", $ret); + } else { + sscanf($ret, "%d", $ret); + } + return $ret; + case Token::TYPE_STRING: + $quote = $this->token[0]; + $str = str_replace($quote . $quote, $quote, $this->token); + return mb_substr($str, 1, -1); // trims quotes + case Token::TYPE_SYMBOL: + $str = $this->token; + if ((isset($str[0])) && ($str[0] === '@')) { + $str = mb_substr($str, 1); + } + if ((isset($str[0])) && (($str[0] === '`') || ($str[0] === '"') || ($str[0] === '\'')) - ) { - $quote = $str[0]; - $str = str_replace($quote . $quote, $quote, $str); - $str = mb_substr($str, 1, -1); - } - return $str; + ) { + $quote = $str[0]; + $str = str_replace($quote . $quote, $quote, $str); + $str = mb_substr($str, 1, -1); + } + return $str; } return $this->token; } From 2826b6b328dea467bb8a368d3a5fa96523ef173f Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Tue, 30 Jun 2015 22:14:58 +0300 Subject: [PATCH 33/57] More refactoring. Signed-off-by: Dan Ungureanu --- libraries/DisplayResults.class.php | 317 ++++++++---------- libraries/Util.class.php | 32 -- libraries/parse_analyze.inc.php | 4 +- libraries/sql-parser/src/Fragment.php | 7 +- .../src/Fragments/ArrayFragment.php | 2 +- .../sql-parser/src/Fragments/CallKeyword.php | 2 +- .../sql-parser/src/Fragments/LimitKeyword.php | 2 +- .../src/Fragments/OptionsFragment.php | 2 +- .../sql-parser/src/Fragments/WhereKeyword.php | 29 +- libraries/sql.lib.php | 44 ++- test/classes/PMA_DisplayResults_test.php | 84 ++--- test/classes/PMA_Util_test.php | 36 -- 12 files changed, 213 insertions(+), 348 deletions(-) diff --git a/libraries/DisplayResults.class.php b/libraries/DisplayResults.class.php index 5d8fcdccd2..19288f1f2b 100644 --- a/libraries/DisplayResults.class.php +++ b/libraries/DisplayResults.class.php @@ -660,7 +660,7 @@ class PMA_DisplayResults * Return true if we are executing a query in the form of * "SELECT * FROM ..." * - * @param array $analyzed_sql the analyzed query + * @param array $analyzed_sql_results analyzed sql results * * @return boolean * @@ -668,17 +668,16 @@ class PMA_DisplayResults * * @see _getTableHeaders(), _getColumnParams() */ - private function _isSelect($analyzed_sql) + private function _isSelect($analyzed_sql_results) { - if (!isset($analyzed_sql[0]['select_expr'])) { - $analyzed_sql[0]['select_expr'] = 0; - } - - return ! ($this->__get('is_count') || $this->__get('is_export') - || $this->__get('is_func') || $this->__get('is_analyse')) - && (count($analyzed_sql[0]['select_expr']) == 0) - && isset($analyzed_sql[0]['queryflags']['select_from']) - && (count($analyzed_sql[0]['table_ref']) == 1); + return ! ($this->__get('is_count') + || $this->__get('is_export') + || $this->__get('is_func') + || $this->__get('is_analyse')) + && !empty($analyzed_sql_results['queryflags']['select_from']) + && !empty($analyzed_sql_results['statement']->from) + && (count($analyzed_sql_results['statement']->from) == 1) + && !empty($analyzed_sql_results['statement']->from[0]->table) == 1; } @@ -1139,7 +1138,7 @@ class PMA_DisplayResults * Get the headers of the results table, for all of the columns * * @param array $displayParts which elements to display - * @param array $analyzed_sql the analyzed query + * @param array $analyzed_sql_results analyzed sql results * @param array $sort_expression sort expression * @param string $sort_expression_nodirection sort expression * without direction @@ -1155,9 +1154,9 @@ class PMA_DisplayResults * @see getTableHeaders() */ private function _getTableHeadersForColumns( - $displayParts, $analyzed_sql, - $sort_expression, $sort_expression_nodirection, - $sort_direction, $is_limited_display, $unsorted_sql_query + $displayParts, $analyzed_sql_results, $sort_expression, + $sort_expression_nodirection, $sort_direction, $is_limited_display, + $unsorted_sql_query ) { $html = ''; @@ -1175,9 +1174,9 @@ class PMA_DisplayResults // Prepare Display column comments if enabled // ($GLOBALS['cfg']['ShowBrowseComments']). - $comments_map = $this->_getTableCommentsArray($analyzed_sql); + $comments_map = $this->_getTableCommentsArray($analyzed_sql_results); - list($col_order, $col_visib) = $this->_getColumnParams($analyzed_sql); + list($col_order, $col_visib) = $this->_getColumnParams($analyzed_sql_results); // optimize: avoid calling a method on each iteration $number_of_columns = $this->__get('fields_cnt'); @@ -1245,7 +1244,7 @@ class PMA_DisplayResults * Get the headers of the results table * * @param array &$displayParts which elements to display - * @param array $analyzed_sql the analyzed query + * @param array $analyzed_sql_results analyzed sql results * @param array $sort_expression sort expression * @param string $sort_expression_nodirection sort expression * without direction @@ -1260,9 +1259,9 @@ class PMA_DisplayResults * @see getTable() */ private function _getTableHeaders( - &$displayParts, $analyzed_sql, - $sort_expression = array(), $sort_expression_nodirection = '', - $sort_direction = '', $is_limited_display = false + &$displayParts, $analyzed_sql_results, $sort_expression = array(), + $sort_expression_nodirection = '', $sort_direction = '', + $is_limited_display = false ) { $table_headers_html = ''; @@ -1271,8 +1270,8 @@ class PMA_DisplayResults $printview = $this->__get('printview'); $display_params = $this->__get('display_params'); - if ($analyzed_sql == '') { - $analyzed_sql = array(); + if ($analyzed_sql_results['analyzed_sql'] == '') { + $analyzed_sql_results['analyzed_sql'] = array(); } // can the result be sorted? @@ -1284,7 +1283,7 @@ class PMA_DisplayResults // "Sort by key" drop-down list($unsorted_sql_query, $drop_down_html) = $this->_getUnsortedSqlAndSortByKeyDropDown( - $analyzed_sql, $sort_expression[0] + $analyzed_sql_results, $sort_expression[0] ); $table_headers_html .= $drop_down_html; @@ -1303,7 +1302,7 @@ class PMA_DisplayResults . ''; // Output data needed for column reordering and show/hide column - if ($this->_isSelect($analyzed_sql)) { + if ($this->_isSelect($analyzed_sql_results)) { $table_headers_html .= $this->_getDataForResettingColumnOrder(); } @@ -1343,11 +1342,11 @@ class PMA_DisplayResults // See if we have to highlight any header fields of a WHERE query. // Uses SQL-Parser results. - $this->_setHighlightedColumnGlobalField($analyzed_sql); + $this->_setHighlightedColumnGlobalField($analyzed_sql_results); // Get the headers for all of the columns $table_headers_html .= $this->_getTableHeadersForColumns( - $displayParts, $analyzed_sql, $sort_expression, + $displayParts, $analyzed_sql_results, $sort_expression, $sort_expression_nodirection, $sort_direction, $is_limited_display, $unsorted_sql_query ); @@ -1368,8 +1367,8 @@ class PMA_DisplayResults /** * Prepare unsorted sql query and sort by key drop down * - * @param array $analyzed_sql the analyzed query - * @param string $sort_expression sort expression + * @param array $analyzed_sql_results analyzed sql results + * @param string $sort_expression sort expression * * @return array two element array - $unsorted_sql_query, $drop_down_html * @@ -1378,9 +1377,9 @@ class PMA_DisplayResults * @see _getTableHeaders() */ private function _getUnsortedSqlAndSortByKeyDropDown( - $analyzed_sql, $sort_expression + $analyzed_sql_results, $sort_expression ) { - + $analyzed_sql = $analyzed_sql_results['analyzed_sql']; $drop_down_html = ''; // Just as fallback @@ -1598,7 +1597,7 @@ class PMA_DisplayResults /** * Get table comments as array * - * @param array $analyzed_sql the analyzed query + * @param array $analyzed_sql_results analyzed sql results * * @return array $comments_map table comments when condition true * null when condition falls @@ -1607,8 +1606,9 @@ class PMA_DisplayResults * * @see _getTableHeaders() */ - private function _getTableCommentsArray($analyzed_sql) + private function _getTableCommentsArray($analyzed_sql_results) { + $analyzed_sql = $analyzed_sql_results['analyzed_sql']; $comments_map = array(); @@ -1633,7 +1633,7 @@ class PMA_DisplayResults /** * Set global array for store highlighted header fields * - * @param array $analyzed_sql the analyzed query + * @param array $analyzed_sql_results analyzed sql results * * @return void * @@ -1641,9 +1641,9 @@ class PMA_DisplayResults * * @see _getTableHeaders() */ - private function _setHighlightedColumnGlobalField($analyzed_sql) + private function _setHighlightedColumnGlobalField($analyzed_sql_results) { - + $analyzed_sql = $analyzed_sql_results['analyzed_sql']; $highlight_columns = array(); if (isset($analyzed_sql) && isset($analyzed_sql[0]) && isset($analyzed_sql[0]['where_clause_identifiers']) @@ -2667,12 +2667,12 @@ class PMA_DisplayResults /** * Prepare the body of the results table * - * @param integer &$dt_result the link id associated to the query + * @param integer &$dt_result the link id associated to the query which results have to be displayed * which results have to be displayed - * @param array &$displayParts which elements to display - * @param array $map the list of relations - * @param array $analyzed_sql the analyzed query - * @param boolean $is_limited_display with limited operations or not + * @param array &$displayParts which elements to display + * @param array $map the list of relations + * @param array $analyzed_sql_results analyzed sql results + * @param boolean $is_limited_display with limited operations or not * * @return string $table_body_html html content * @@ -2683,7 +2683,8 @@ class PMA_DisplayResults * @see getTable() */ private function _getTableBody( - &$dt_result, &$displayParts, $map, $analyzed_sql, $is_limited_display = false + &$dt_result, &$displayParts, $map, $analyzed_sql_results, + $is_limited_display = false ) { global $row; // mostly because of browser transformations, @@ -2693,7 +2694,7 @@ class PMA_DisplayResults // query without conditions to shorten URLs when needed, 200 is just // guess, it should depend on remaining URL length - $url_sql_query = $this->_getUrlSqlQuery($analyzed_sql); + $url_sql_query = $this->_getUrlSqlQuery($analyzed_sql_results); $display_params = $this->__get('display_params'); @@ -2701,7 +2702,7 @@ class PMA_DisplayResults $map = array(); } - $row_no = 0; + $row_no = 0; $display_params['edit'] = array(); $display_params['copy'] = array(); $display_params['delete'] = array(); @@ -2731,7 +2732,7 @@ class PMA_DisplayResults } // prepare to get the column order, if available - list($col_order, $col_visib) = $this->_getColumnParams($analyzed_sql); + list($col_order, $col_visib) = $this->_getColumnParams($analyzed_sql_results); // Correction University of Virginia 19991216 in the while below // Previous code assumed that all tables have keys, specifically that @@ -2854,9 +2855,15 @@ class PMA_DisplayResults $this->_setMimeMap(); } $table_body_html .= $this->_getRowValues( - $dt_result, $row, $row_no, $col_order, $map, - $grid_edit_class, $col_visib, - $url_sql_query, $analyzed_sql + $dt_result, + $row, + $row_no, + $col_order, + $map, + $grid_edit_class, + $col_visib, + $url_sql_query, + $analyzed_sql_results ); // 3. Displays the modify/delete links on the right if required @@ -2959,18 +2966,18 @@ class PMA_DisplayResults /** * Get the values for one data row * - * @param integer &$dt_result the link id associated to the query + * @param integer &$dt_result the link id associated to the query which results have to be displayed * which results have to be displayed - * @param array $row current row data - * @param integer $row_no the index of current row - * @param array $col_order the column order + * @param array $row current row data + * @param integer $row_no the index of current row + * @param array $col_order the column order false when a property not found * false when a property not found - * @param array $map the list of relations - * @param string $grid_edit_class the class for all editable columns - * @param boolean $col_visib column is visible(false) + * @param array $map the list of relations + * @param string $grid_edit_class the class for all editable columns + * @param boolean $col_visib column is visible(false) array column isn't visible(string array) * array column isn't visible(string array) - * @param string $url_sql_query the analyzed sql query - * @param array $analyzed_sql the analyzed query + * @param string $url_sql_query the analyzed sql query + * @param array $analyzed_sql_results analyzed sql results * * @return string $row_values_html html content * @@ -2981,9 +2988,9 @@ class PMA_DisplayResults private function _getRowValues( &$dt_result, $row, $row_no, $col_order, $map, $grid_edit_class, $col_visib, - $url_sql_query, $analyzed_sql + $url_sql_query, $analyzed_sql_results ) { - + $analyzed_sql = $analyzed_sql_results['analyzed_sql']; $row_values_html = ''; // Following variable are needed for use in isset/empty or @@ -3314,7 +3321,7 @@ class PMA_DisplayResults /** * Get url sql query without conditions to shorten URLs * - * @param array $analyzed_sql analyzed query + * @param array $analyzed_sql_results analyzed sql results * * @return string $url_sql analyzed sql query * @@ -3322,9 +3329,9 @@ class PMA_DisplayResults * * @see _getTableBody() */ - private function _getUrlSqlQuery($analyzed_sql) + private function _getUrlSqlQuery($analyzed_sql_results) { - + $analyzed_sql = $analyzed_sql_results['analyzed_sql']; if (isset($analyzed_sql) && isset($analyzed_sql[0]) && isset($analyzed_sql[0]['querytype']) @@ -3353,7 +3360,7 @@ class PMA_DisplayResults /** * Get column order and column visibility * - * @param array $analyzed_sql the analyzed query + * @param array $analyzed_sql_results analyzed sql results * * @return array 2 element array - $col_order, $col_visib * @@ -3361,9 +3368,9 @@ class PMA_DisplayResults * * @see _getTableBody() */ - private function _getColumnParams($analyzed_sql) + private function _getColumnParams($analyzed_sql_results) { - if ($this->_isSelect($analyzed_sql)) { + if ($this->_isSelect($analyzed_sql_results)) { $pmatable = new PMA_Table($this->__get('table'), $this->__get('db')); $col_order = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_ORDER); $col_visib = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_VISIB); @@ -4197,7 +4204,6 @@ class PMA_DisplayResults = $query['repeat_cells']; } - /** * Prepare a table of results returned by a SQL query. * @@ -4218,8 +4224,11 @@ class PMA_DisplayResults $is_limited_display = false ) { - // TODO: Remove. - $analyzed_sql = $analyzed_sql_results['analyzed_sql']; + /** + * The statement this table is built for. + * @var SelectStatement + */ + $statement = $analyzed_sql_results['statement']; $table_html = ''; // Following variable are needed for use in isset/empty or @@ -4264,19 +4273,28 @@ class PMA_DisplayResults if ($displayParts['nav_bar'] == '1') { list($pos_next, $pos_prev) = $this->_getOffsets(); } // end if - if (!isset($analyzed_sql[0]['order_by_clause'])) { - $analyzed_sql[0]['order_by_clause'] = ""; + + // 1.3 Extract sorting expressions. + // we need $sort_expression and $sort_expression_nodirection + // even if there are many table references + $sort_expression = array(); + $sort_expression_nodirection = array(); + $sort_direction = array(); + + if (!empty($statement->order)) { + foreach ($statement->order as $o) { + $sort_expression[] = $o->field->expr . ' ' . $o->type; + $sort_expression_nodirection[] = $o->field->expr; + $sort_direction[] = $o->type; + } + } else { + $sort_expression[] = ''; + $sort_expression_nodirection[] = ''; + $sort_direction[] = ''; } - // 1.3 Find the sort expression - // we need $sort_expression and $sort_expression_nodirection - // even if there are many table references - list( - $sort_expression, $sort_expression_nodirection, - $sort_direction - ) = $this->_getSortParams($analyzed_sql[0]['order_by_clause']); - $number_of_columns = count($sort_expression_nodirection); + // 1.4 Prepares display of first and last value of the sorted column $sorted_column_message = ''; for ( $i = 0; $i < $number_of_columns; $i++ ) { @@ -4291,8 +4309,12 @@ class PMA_DisplayResults if (($displayParts['nav_bar'] == '1') && isset($pos_next)) { $message = $this->_setMessageInformation( - $sorted_column_message, $analyzed_sql[0]['limit_clause'], - $total, $pos_next, $pre_count, $after_count + $sorted_column_message, + $analyzed_sql_results, + $total, + $pos_next, + $pre_count, + $after_count ); $table_html .= PMA_Util::getMessage( @@ -4321,15 +4343,11 @@ class PMA_DisplayResults } - if (($displayParts['nav_bar'] == '1') - && empty($analyzed_sql[0]['limit_clause']) - ) { - + if (($displayParts['nav_bar'] == '1') && (empty($statemet->limit))) { $table_html .= $this->_getPlacedTableNavigations( $pos_next, $pos_prev, self::PLACE_TOP_DIRECTION_DROPDOWN, $is_innodb ); - } elseif (! isset($printview) || ($printview != '1')) { $table_html .= "\n" . '

' . "\n"; } @@ -4340,18 +4358,13 @@ class PMA_DisplayResults // initialize map $map = array(); - // find tables $target = array(); - if (isset($analyzed_sql[0]['table_ref']) - && is_array($analyzed_sql[0]['table_ref']) - ) { - - foreach ($analyzed_sql[0]['table_ref'] - as $table_ref_position => $table_ref) { - $target[] = $analyzed_sql[0]['table_ref'] - [$table_ref_position]['table_true_name']; + if (!empty($statement->from)) { + foreach ($statement->from as $field) { + if (!empty($field->table)) { + $target[] = $field->table; + } } - } if (/*overload*/mb_strlen($this->__get('table'))) { @@ -4373,19 +4386,27 @@ class PMA_DisplayResults // 3. ----- Prepare the results table ----- $table_html .= $this->_getTableHeaders( - $displayParts, $analyzed_sql, $sort_expression, - $sort_expression_nodirection, $sort_direction, $is_limited_display - ) - . '' . "\n"; + $displayParts, + $analyzed_sql_results, + $sort_expression, + $sort_expression_nodirection, + $sort_direction, + $is_limited_display + ); + + $table_html .= '' . "\n"; $table_html .= $this->_getTableBody( - $dt_result, $displayParts, $map, $analyzed_sql, $is_limited_display + $dt_result, + $displayParts, + $map, + $analyzed_sql_results, + $is_limited_display ); $this->__set('display_params', null); - $table_html .= '' . "\n" - . ''; + $table_html .= '' . "\n" . ''; // 4. ----- Prepares the link for multi-fields edit and delete @@ -4394,15 +4415,15 @@ class PMA_DisplayResults ) { $table_html .= $this->_getMultiRowOperationLinks( - $dt_result, $analyzed_sql, $displayParts['del_lnk'] + $dt_result, + $analyzed_sql_results, + $displayParts['del_lnk'] ); } // 5. ----- Get the navigation bar at the bottom if required ----- - if (($displayParts['nav_bar'] == '1') - && empty($analyzed_sql[0]['limit_clause']) - ) { + if (($displayParts['nav_bar'] == '1') && empty($statement->limit)) { $table_html .= $this->_getPlacedTableNavigations( $pos_next, $pos_prev, self::PLACE_BOTTOM_DIRECTION_DROPDOWN, $is_innodb @@ -4456,61 +4477,6 @@ class PMA_DisplayResults } // end of the '_getOffsets()' function - /** - * Get sort parameters - * - * @param string $order_by_clause the order by clause of the sql query - * - * @return array 3 element array: $sort_expression, - * $sort_expression_nodirection, $sort_direction - * - * @access private - * - * @see getTable() - */ - private function _getSortParams($order_by_clause) - { - - $sort_expression = array(); - $sort_expression_nodirection = array(); - $sort_direction = array(); - if (! empty($order_by_clause)) { - // Each order by clause is assumed to be delimited by a comma - // A typical order by clause would be order by column1 asc, column2 desc - // The following line counts the number of columns in order by clause - $matches = explode(',', $order_by_clause); - // Iterate over each column in order by clause - foreach ($matches as $index=>$order_by_clause2) { - - $sort_expression[$index] = trim( - str_replace(' ', ' ', $order_by_clause2) - ); - /** - * Get rid of ASC|DESC - */ - preg_match( - '@(.*)([[:space:]]*(ASC|DESC))@si', - $sort_expression[$index], $matches - ); - - $sort_expression_nodirection[$index] = isset($matches[1]) - ? trim($matches[1]) - : $sort_expression[$index]; - $sort_direction[$index] - = isset($matches[2]) ? trim($matches[2]) : ''; - } - } else { - $sort_expression[0] = $sort_expression_nodirection[0] - = $sort_direction[0] = ''; - } - - return array($sort_expression, $sort_expression_nodirection, - $sort_direction - ); - - } // end of the '_getSortParams()' function - - /** * Prepare sorted column message * @@ -4633,7 +4599,7 @@ class PMA_DisplayResults * Set the content that needs to be shown in message * * @param string $sorted_column_message the message for sorted column - * @param string $limit_clause the limit clause of analyzed query + * @param array $analyzed_sql_results the analyzed query * @param integer $total the total number of rows returned by * the SQL query without any * programmatically appended LIMIT clause @@ -4648,22 +4614,21 @@ class PMA_DisplayResults * @see getTable() */ private function _setMessageInformation( - $sorted_column_message, $limit_clause, $total, + $sorted_column_message, $analyzed_sql_results, $total, $pos_next, $pre_count, $after_count ) { $unlim_num_rows = $this->__get('unlim_num_rows'); // To use in isset() - if (! empty($limit_clause)) { + if (!empty($analyzed_sql_results['statement']->limit)) { - $limit_data - = PMA_Util::analyzeLimitClause($limit_clause); - $first_shown_rec = $limit_data['start']; + $first_shown_rec = $analyzed_sql_results['statement']->limit->offset; + $row_count = $analyzed_sql_results['statement']->limit->rowCount; - if ($limit_data['length'] < $total) { - $last_shown_rec = $limit_data['start'] + $limit_data['length'] - 1; + if ($row_count < $total) { + $last_shown_rec = $first_shown_rec + $row_count - 1; } else { - $last_shown_rec = $limit_data['start'] + $total - 1; + $last_shown_rec = $first_shown_rec + $total - 1; } } elseif (($_SESSION['tmpval']['max_rows'] == self::ALL_ROWS) @@ -4811,10 +4776,10 @@ class PMA_DisplayResults /** * Prepare multi field edit/delete links * - * @param integer &$dt_result the link id associated to the query + * @param integer &$dt_result the link id associated to the query which results have to be displayed * which results have to be displayed - * @param array $analyzed_sql the analyzed query - * @param string $del_link the display element - 'del_link' + * @param array $analyzed_sql_results analyzed sql results + * @param string $del_link the display element - 'del_link' * * @return string $links_html html content * @@ -4823,7 +4788,7 @@ class PMA_DisplayResults * @see getTable() */ private function _getMultiRowOperationLinks( - &$dt_result, $analyzed_sql, $del_link + &$dt_result, $analyzed_sql_results, $del_link ) { $links_html = '