* Support php 5.3 for sql parser lib.

This commit is contained in:
qixinzhi
2023-02-10 11:24:24 +08:00
parent 7c2e937eda
commit 7c122a0b29
648 changed files with 13815 additions and 279048 deletions
+65 -86
View File
@@ -1,4 +1,5 @@
<?php
/**
* Defines a context class that is later extended to define other contexts.
*
@@ -6,26 +7,16 @@
* parsing.
*/
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser;
use PhpMyAdmin\SqlParser\Exceptions\LoaderException;
use function class_exists;
use function constant;
use function explode;
use function intval;
use function is_array;
use function is_numeric;
use function str_replace;
use function strlen;
use function strncmp;
use function strtoupper;
use function substr;
/**
* Holds the configuration of the context that is currently used.
*
* @category Contexts
*
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
*/
abstract class Context
{
@@ -33,23 +24,29 @@ abstract class Context
* The maximum length of a keyword.
*
* @see static::$TOKEN_KEYWORD
*
* @var int
*/
public const KEYWORD_MAX_LENGTH = 30;
const KEYWORD_MAX_LENGTH = 30;
/**
* The maximum length of a label.
*
* @see static::$TOKEN_LABEL
* Ref: https://dev.mysql.com/doc/refman/5.7/en/statement-labels.html
*
* @var int
*/
public const LABEL_MAX_LENGTH = 16;
const LABEL_MAX_LENGTH = 16;
/**
* The maximum length of an operator.
*
* @see static::$TOKEN_OPERATOR
*
* @var int
*/
public const OPERATOR_MAX_LENGTH = 4;
const OPERATOR_MAX_LENGTH = 4;
/**
* The name of the default content.
@@ -89,14 +86,14 @@ abstract class Context
*
* @var array
*/
public static $KEYWORDS = [];
public static $KEYWORDS = array();
/**
* List of operators and their flags.
*
* @var array
*/
public static $OPERATORS = [
public static $OPERATORS = array(
// Some operators (*, =) may have ambiguous flags, because they depend on
// the context they are being used in.
// For example: 1. SELECT * FROM table; # SQL specific (wildcard)
@@ -140,8 +137,8 @@ abstract class Context
')' => 16,
'.' => 16,
',' => 16,
';' => 16,
];
';' => 16
);
/**
* The mode of the MySQL server that will be used in lexing, parsing and
@@ -158,77 +155,77 @@ abstract class Context
// Compatibility mode for Microsoft's SQL server.
// This is the equivalent of ANSI_QUOTES.
public const SQL_MODE_COMPAT_MYSQL = 2;
const SQL_MODE_COMPAT_MYSQL = 2;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_allow_invalid_dates
public const SQL_MODE_ALLOW_INVALID_DATES = 1;
const SQL_MODE_ALLOW_INVALID_DATES = 1;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_ansi_quotes
public const SQL_MODE_ANSI_QUOTES = 2;
const SQL_MODE_ANSI_QUOTES = 2;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_error_for_division_by_zero
public const SQL_MODE_ERROR_FOR_DIVISION_BY_ZERO = 4;
const SQL_MODE_ERROR_FOR_DIVISION_BY_ZERO = 4;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_high_not_precedence
public const SQL_MODE_HIGH_NOT_PRECEDENCE = 8;
const SQL_MODE_HIGH_NOT_PRECEDENCE = 8;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_ignore_space
public const SQL_MODE_IGNORE_SPACE = 16;
const SQL_MODE_IGNORE_SPACE = 16;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_auto_create_user
public const SQL_MODE_NO_AUTO_CREATE_USER = 32;
const SQL_MODE_NO_AUTO_CREATE_USER = 32;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_auto_value_on_zero
public const SQL_MODE_NO_AUTO_VALUE_ON_ZERO = 64;
const SQL_MODE_NO_AUTO_VALUE_ON_ZERO = 64;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_backslash_escapes
public const SQL_MODE_NO_BACKSLASH_ESCAPES = 128;
const SQL_MODE_NO_BACKSLASH_ESCAPES = 128;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_dir_in_create
public const SQL_MODE_NO_DIR_IN_CREATE = 256;
const SQL_MODE_NO_DIR_IN_CREATE = 256;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_dir_in_create
public const SQL_MODE_NO_ENGINE_SUBSTITUTION = 512;
const SQL_MODE_NO_ENGINE_SUBSTITUTION = 512;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_field_options
public const SQL_MODE_NO_FIELD_OPTIONS = 1024;
const SQL_MODE_NO_FIELD_OPTIONS = 1024;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_key_options
public const SQL_MODE_NO_KEY_OPTIONS = 2048;
const SQL_MODE_NO_KEY_OPTIONS = 2048;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_table_options
public const SQL_MODE_NO_TABLE_OPTIONS = 4096;
const SQL_MODE_NO_TABLE_OPTIONS = 4096;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_unsigned_subtraction
public const SQL_MODE_NO_UNSIGNED_SUBTRACTION = 8192;
const SQL_MODE_NO_UNSIGNED_SUBTRACTION = 8192;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_zero_date
public const SQL_MODE_NO_ZERO_DATE = 16384;
const SQL_MODE_NO_ZERO_DATE = 16384;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_no_zero_in_date
public const SQL_MODE_NO_ZERO_IN_DATE = 32768;
const SQL_MODE_NO_ZERO_IN_DATE = 32768;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_only_full_group_by
public const SQL_MODE_ONLY_FULL_GROUP_BY = 65536;
const SQL_MODE_ONLY_FULL_GROUP_BY = 65536;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_pipes_as_concat
public const SQL_MODE_PIPES_AS_CONCAT = 131072;
const SQL_MODE_PIPES_AS_CONCAT = 131072;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_real_as_float
public const SQL_MODE_REAL_AS_FLOAT = 262144;
const SQL_MODE_REAL_AS_FLOAT = 262144;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_strict_all_tables
public const SQL_MODE_STRICT_ALL_TABLES = 524288;
const SQL_MODE_STRICT_ALL_TABLES = 524288;
// https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_strict_trans_tables
public const SQL_MODE_STRICT_TRANS_TABLES = 1048576;
const SQL_MODE_STRICT_TRANS_TABLES = 1048576;
// Custom modes.
// The table and column names and any other field that must be escaped will
// not be.
// Reserved keywords are being escaped regardless this mode is used or not.
public const SQL_MODE_NO_ENCLOSING_QUOTES = 1073741824;
const SQL_MODE_NO_ENCLOSING_QUOTES = 1073741824;
/*
* Combination SQL Modes
@@ -236,31 +233,31 @@ abstract class Context
*/
// REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE
public const SQL_MODE_ANSI = 393234;
const SQL_MODE_ANSI = 393234;
// PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS,
// NO_TABLE_OPTIONS, NO_FIELD_OPTIONS,
public const SQL_MODE_DB2 = 138258;
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
public const SQL_MODE_MAXDB = 138290;
const SQL_MODE_MAXDB = 138290;
// PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS,
// NO_TABLE_OPTIONS, NO_FIELD_OPTIONS
public const SQL_MODE_MSSQL = 138258;
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
public const SQL_MODE_ORACLE = 138290;
const SQL_MODE_ORACLE = 138290;
// PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS,
// NO_TABLE_OPTIONS, NO_FIELD_OPTIONS
public const SQL_MODE_POSTGRESQL = 138258;
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
public const SQL_MODE_TRADITIONAL = 1622052;
const SQL_MODE_TRADITIONAL = 1622052;
// -------------------------------------------------------------------------
// Keyword.
@@ -344,24 +341,22 @@ abstract class Context
if ($str[0] === '#') {
return Token::FLAG_COMMENT_BASH;
}
// If comment is opening C style (/*), warning, it could be a MySQL command (/*!)
if (($len > 1) && ($str[0] === '/') && ($str[1] === '*')) {
return ($len > 2) && ($str[2] === '!') ?
Token::FLAG_COMMENT_MYSQL_CMD : Token::FLAG_COMMENT_C;
}
// If comment is closing C style (*/), warning, it could conflicts with wildcard and a real opening C style.
// It would looks like the following valid SQL statement: "SELECT */* comment */ FROM...".
if (($len > 1) && ($str[0] === '*') && ($str[1] === '/')) {
return Token::FLAG_COMMENT_C;
}
// If comment is SQL style (--\s?):
if (($len > 2) && ($str[0] === '-') && ($str[1] === '-') && static::isWhitespace($str[2])) {
if (($len > 2) && ($str[0] === '-')
&& ($str[1] === '-') && static::isWhitespace($str[2])
) {
return Token::FLAG_COMMENT_SQL;
}
if (($len === 2) && $end && ($str[0] === '-') && ($str[1] === '-')) {
return Token::FLAG_COMMENT_SQL;
}
@@ -400,7 +395,7 @@ abstract class Context
*/
public static function isNumber($str)
{
return ($str >= '0') && ($str <= '9') || ($str === '.')
return (($str >= '0') && ($str <= '9')) || ($str === '.')
|| ($str === '-') || ($str === '+') || ($str === 'e') || ($str === 'E');
}
@@ -420,16 +415,11 @@ abstract class Context
if (strlen($str) === 0) {
return null;
}
if ($str[0] === '@') {
return Token::FLAG_SYMBOL_VARIABLE;
}
if ($str[0] === '`') {
} elseif ($str[0] === '`') {
return Token::FLAG_SYMBOL_BACKTICK;
}
if ($str[0] === ':' || $str[0] === '?') {
} elseif ($str[0] === ':' || $str[0] === '?') {
return Token::FLAG_SYMBOL_PARAMETER;
}
@@ -451,12 +441,9 @@ abstract class Context
if (strlen($str) === 0) {
return null;
}
if ($str[0] === '\'') {
return Token::FLAG_STRING_SINGLE_QUOTES;
}
if ($str[0] === '"') {
} elseif ($str[0] === '"') {
return Token::FLAG_STRING_DOUBLE_QUOTES;
}
@@ -493,23 +480,23 @@ abstract class Context
* @param string $context name of the context or full class name that
* defines the context
*
* @throws LoaderException if the specified context doesn't exist.
* @throws LoaderException if the specified context doesn't exist
*/
public static function load($context = '')
{
if (empty($context)) {
$context = self::$defaultContext;
}
if ($context[0] !== '\\') {
// Short context name (must be formatted into class name).
$context = self::$contextPrefix . $context;
}
if (! class_exists($context)) {
throw @new LoaderException('Specified context ("' . $context . '") does not exist.', $context);
throw @new LoaderException(
'Specified context ("' . $context . '") does not exist.',
$context
);
}
self::$loadedContext = $context;
self::$KEYWORDS = $context::$KEYWORDS;
}
@@ -534,7 +521,6 @@ abstract class Context
try {
/* Trying to load the new context */
static::load($context);
return $context;
} catch (LoaderException $e) {
/* Replace last two non zero digits by zeroes */
@@ -546,20 +532,15 @@ abstract class Context
break 2;
}
} while (intval($part) === 0 && $i > 0);
$context = substr($context, 0, $i) . '00' . substr($context, $i + 2);
}
}
/* Fallback to loading at least matching engine */
if (strncmp($context, 'MariaDb', 7) === 0) {
return static::loadClosest('MariaDb100300');
}
if (strncmp($context, 'MySql', 5) === 0) {
} elseif (strncmp($context, 'MySql', 5) === 0) {
return static::loadClosest('MySql50700');
}
return null;
}
@@ -574,7 +555,6 @@ abstract class Context
if (empty($mode)) {
return;
}
$mode = explode(',', $mode);
foreach ($mode as $m) {
static::$MODE |= constant('static::SQL_MODE_' . $m);
@@ -599,7 +579,9 @@ abstract class Context
return $str;
}
if ((static::$MODE & self::SQL_MODE_NO_ENCLOSING_QUOTES) && (! static::isKeyword($str, true))) {
if ((static::$MODE & self::SQL_MODE_NO_ENCLOSING_QUOTES)
&& (! static::isKeyword($str, true))
) {
return $str;
}
@@ -612,7 +594,6 @@ abstract class Context
/**
* Returns char used to quote identifiers based on currently set SQL Mode (ie. standard or ANSI_QUOTES)
*
* @return string either " (double quote, ansi_quotes mode) or ` (backtick, standard mode)
*/
public static function getIdentifierQuote()
@@ -623,16 +604,14 @@ abstract class Context
/**
* Function verifies that given SQL Mode constant is currently set
*
* @return boolean false on empty param, true/false on given constant/int value
* @param int $flag for example Context::SQL_MODE_ANSI_QUOTES
*
* @return bool false on empty param, true/false on given constant/int value
*/
public static function hasMode($flag = null)
{
if (empty($flag)) {
return false;
}
return (self::$MODE & $flag) === $flag;
}
}