Update website
This commit is contained in:
parent
4413528994
commit
1d90fbf296
6865 changed files with 1091082 additions and 0 deletions
857
admin/phpMyAdmin/vendor/phpmyadmin/sql-parser/src/Context.php
vendored
Normal file
857
admin/phpMyAdmin/vendor/phpmyadmin/sql-parser/src/Context.php
vendored
Normal file
|
@ -0,0 +1,857 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\SqlParser;
|
||||
|
||||
use PhpMyAdmin\SqlParser\Exceptions\LoaderException;
|
||||
|
||||
use function class_exists;
|
||||
use function explode;
|
||||
use function intval;
|
||||
use function is_array;
|
||||
use function is_int;
|
||||
use function is_numeric;
|
||||
use function str_replace;
|
||||
use function str_starts_with;
|
||||
use function strlen;
|
||||
use function strtoupper;
|
||||
use function substr;
|
||||
|
||||
/**
|
||||
* Defines a context class that is later extended to define other contexts.
|
||||
*
|
||||
* A context is a collection of keywords, operators and functions used for parsing.
|
||||
*
|
||||
* Holds the configuration of the context that is currently used.
|
||||
*/
|
||||
abstract class Context
|
||||
{
|
||||
/**
|
||||
* The maximum length of a keyword.
|
||||
*
|
||||
* @see static::$TOKEN_KEYWORD
|
||||
*/
|
||||
public 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
|
||||
*/
|
||||
public const LABEL_MAX_LENGTH = 16;
|
||||
|
||||
/**
|
||||
* The maximum length of an operator.
|
||||
*
|
||||
* @see static::$TOKEN_OPERATOR
|
||||
*/
|
||||
public const OPERATOR_MAX_LENGTH = 4;
|
||||
|
||||
/**
|
||||
* The name of the default content.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $defaultContext = '\\PhpMyAdmin\\SqlParser\\Contexts\\ContextMySql50700';
|
||||
|
||||
/**
|
||||
* The name of the loaded context.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $loadedContext = '\\PhpMyAdmin\\SqlParser\\Contexts\\ContextMySql50700';
|
||||
|
||||
/**
|
||||
* The prefix concatenated to the context name when an incomplete class name
|
||||
* is specified.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $contextPrefix = '\\PhpMyAdmin\\SqlParser\\Contexts\\Context';
|
||||
|
||||
/**
|
||||
* List of keywords.
|
||||
*
|
||||
* Because, PHP's associative arrays are basically hash tables, it is more
|
||||
* efficient to store keywords as keys instead of values.
|
||||
*
|
||||
* The value associated to each keyword represents its flags.
|
||||
*
|
||||
* @see Token::FLAG_KEYWORD_RESERVED Token::FLAG_KEYWORD_COMPOSED
|
||||
* Token::FLAG_KEYWORD_DATA_TYPE Token::FLAG_KEYWORD_KEY
|
||||
* Token::FLAG_KEYWORD_FUNCTION
|
||||
*
|
||||
* Elements are sorted by flags, length and keyword.
|
||||
*
|
||||
* @var array<string,int>
|
||||
* @phpstan-var non-empty-array<non-empty-string,Token::FLAG_KEYWORD_*|int>
|
||||
*/
|
||||
public static $KEYWORDS = [];
|
||||
|
||||
/**
|
||||
* List of operators and their flags.
|
||||
*
|
||||
* @var array<string, int>
|
||||
*/
|
||||
public static $OPERATORS = [
|
||||
// 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)
|
||||
// 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,
|
||||
';' => 16,
|
||||
];
|
||||
|
||||
/**
|
||||
* The mode of the MySQL server that will be used in lexing, parsing and building the statements.
|
||||
*
|
||||
* @internal use the {@see Context::getMode()} method instead.
|
||||
*
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html
|
||||
* @link https://mariadb.com/kb/en/sql-mode/
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public static $MODE = self::SQL_MODE_NONE;
|
||||
|
||||
public const SQL_MODE_NONE = 0;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_allow_invalid_dates
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#allow_invalid_dates
|
||||
*/
|
||||
public const SQL_MODE_ALLOW_INVALID_DATES = 1;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_ansi_quotes
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#ansi_quotes
|
||||
*/
|
||||
public const SQL_MODE_ANSI_QUOTES = 2;
|
||||
|
||||
/** Compatibility mode for Microsoft's SQL server. This is the equivalent of {@see SQL_MODE_ANSI_QUOTES}. */
|
||||
public const SQL_MODE_COMPAT_MYSQL = 2;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_error_for_division_by_zero
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#error_for_division_by_zero
|
||||
*/
|
||||
public const SQL_MODE_ERROR_FOR_DIVISION_BY_ZERO = 4;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_high_not_precedence
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#high_not_precedence
|
||||
*/
|
||||
public const SQL_MODE_HIGH_NOT_PRECEDENCE = 8;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_ignore_space
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#ignore_space
|
||||
*/
|
||||
public const SQL_MODE_IGNORE_SPACE = 16;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_auto_create_user
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#no_auto_create_user
|
||||
*/
|
||||
public const SQL_MODE_NO_AUTO_CREATE_USER = 32;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_no_auto_value_on_zero
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#no_auto_value_on_zero
|
||||
*/
|
||||
public const SQL_MODE_NO_AUTO_VALUE_ON_ZERO = 64;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_no_backslash_escapes
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#no_backslash_escapes
|
||||
*/
|
||||
public const SQL_MODE_NO_BACKSLASH_ESCAPES = 128;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_no_dir_in_create
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#no_dir_in_create
|
||||
*/
|
||||
public const SQL_MODE_NO_DIR_IN_CREATE = 256;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_no_engine_substitution
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#no_engine_substitution
|
||||
*/
|
||||
public const SQL_MODE_NO_ENGINE_SUBSTITUTION = 512;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_field_options
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#no_field_options
|
||||
*/
|
||||
public const SQL_MODE_NO_FIELD_OPTIONS = 1024;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_key_options
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#no_key_options
|
||||
*/
|
||||
public const SQL_MODE_NO_KEY_OPTIONS = 2048;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_table_options
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#no_table_options
|
||||
*/
|
||||
public const SQL_MODE_NO_TABLE_OPTIONS = 4096;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_no_unsigned_subtraction
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#no_unsigned_subtraction
|
||||
*/
|
||||
public const SQL_MODE_NO_UNSIGNED_SUBTRACTION = 8192;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_no_zero_date
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#no_zero_date
|
||||
*/
|
||||
public const SQL_MODE_NO_ZERO_DATE = 16384;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_no_zero_in_date
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#no_zero_in_date
|
||||
*/
|
||||
public const SQL_MODE_NO_ZERO_IN_DATE = 32768;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_only_full_group_by
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#only_full_group_by
|
||||
*/
|
||||
public const SQL_MODE_ONLY_FULL_GROUP_BY = 65536;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_pipes_as_concat
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#pipes_as_concat
|
||||
*/
|
||||
public const SQL_MODE_PIPES_AS_CONCAT = 131072;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_real_as_float
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#real_as_float
|
||||
*/
|
||||
public const SQL_MODE_REAL_AS_FLOAT = 262144;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_strict_all_tables
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#strict_all_tables
|
||||
*/
|
||||
public const SQL_MODE_STRICT_ALL_TABLES = 524288;
|
||||
|
||||
/**
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_strict_trans_tables
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#strict_trans_tables
|
||||
*/
|
||||
public const SQL_MODE_STRICT_TRANS_TABLES = 1048576;
|
||||
|
||||
/**
|
||||
* Custom mode.
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Equivalent to {@see SQL_MODE_REAL_AS_FLOAT}, {@see SQL_MODE_PIPES_AS_CONCAT}, {@see SQL_MODE_ANSI_QUOTES},
|
||||
* {@see SQL_MODE_IGNORE_SPACE}.
|
||||
*
|
||||
* @link https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_ansi
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#ansi
|
||||
*/
|
||||
public const SQL_MODE_ANSI = 393234;
|
||||
|
||||
/**
|
||||
* Equivalent to {@see SQL_MODE_PIPES_AS_CONCAT}, {@see SQL_MODE_ANSI_QUOTES}, {@see SQL_MODE_IGNORE_SPACE},
|
||||
* {@see SQL_MODE_NO_KEY_OPTIONS}, {@see SQL_MODE_NO_TABLE_OPTIONS}, {@see SQL_MODE_NO_FIELD_OPTIONS}.
|
||||
*
|
||||
* @link https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_db2
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#db2
|
||||
*/
|
||||
public const SQL_MODE_DB2 = 138258;
|
||||
|
||||
/**
|
||||
* Equivalent to {@see SQL_MODE_PIPES_AS_CONCAT}, {@see SQL_MODE_ANSI_QUOTES}, {@see SQL_MODE_IGNORE_SPACE},
|
||||
* {@see SQL_MODE_NO_KEY_OPTIONS}, {@see SQL_MODE_NO_TABLE_OPTIONS}, {@see SQL_MODE_NO_FIELD_OPTIONS},
|
||||
* {@see SQL_MODE_NO_AUTO_CREATE_USER}.
|
||||
*
|
||||
* @link https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_maxdb
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#maxdb
|
||||
*/
|
||||
public const SQL_MODE_MAXDB = 138290;
|
||||
|
||||
/**
|
||||
* Equivalent to {@see SQL_MODE_PIPES_AS_CONCAT}, {@see SQL_MODE_ANSI_QUOTES}, {@see SQL_MODE_IGNORE_SPACE},
|
||||
* {@see SQL_MODE_NO_KEY_OPTIONS}, {@see SQL_MODE_NO_TABLE_OPTIONS}, {@see SQL_MODE_NO_FIELD_OPTIONS}.
|
||||
*
|
||||
* @link https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_mssql
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#mssql
|
||||
*/
|
||||
public const SQL_MODE_MSSQL = 138258;
|
||||
|
||||
/**
|
||||
* Equivalent to {@see SQL_MODE_PIPES_AS_CONCAT}, {@see SQL_MODE_ANSI_QUOTES}, {@see SQL_MODE_IGNORE_SPACE},
|
||||
* {@see SQL_MODE_NO_KEY_OPTIONS}, {@see SQL_MODE_NO_TABLE_OPTIONS}, {@see SQL_MODE_NO_FIELD_OPTIONS},
|
||||
* {@see SQL_MODE_NO_AUTO_CREATE_USER}.
|
||||
*
|
||||
* @link https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_oracle
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#oracle
|
||||
*/
|
||||
public const SQL_MODE_ORACLE = 138290;
|
||||
|
||||
/**
|
||||
* Equivalent to {@see SQL_MODE_PIPES_AS_CONCAT}, {@see SQL_MODE_ANSI_QUOTES}, {@see SQL_MODE_IGNORE_SPACE},
|
||||
* {@see SQL_MODE_NO_KEY_OPTIONS}, {@see SQL_MODE_NO_TABLE_OPTIONS}, {@see SQL_MODE_NO_FIELD_OPTIONS}.
|
||||
*
|
||||
* @link https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_postgresql
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#postgresql
|
||||
*/
|
||||
public const SQL_MODE_POSTGRESQL = 138258;
|
||||
|
||||
/**
|
||||
* Equivalent to {@see SQL_MODE_STRICT_TRANS_TABLES}, {@see SQL_MODE_STRICT_ALL_TABLES},
|
||||
* {@see SQL_MODE_NO_ZERO_IN_DATE}, {@see SQL_MODE_NO_ZERO_DATE}, {@see SQL_MODE_ERROR_FOR_DIVISION_BY_ZERO},
|
||||
* {@see SQL_MODE_NO_AUTO_CREATE_USER}.
|
||||
*
|
||||
* @link https://dev.mysql.com/doc/refman/en/sql-mode.html#sqlmode_traditional
|
||||
* @link https://mariadb.com/kb/en/sql-mode/#traditional
|
||||
*/
|
||||
public const SQL_MODE_TRADITIONAL = 1622052;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Keyword.
|
||||
|
||||
/**
|
||||
* Checks if the given string is a keyword.
|
||||
*
|
||||
* @param string $str string to be checked
|
||||
* @param bool $isReserved checks if the keyword is reserved
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public static function isKeyword($str, $isReserved = false)
|
||||
{
|
||||
$str = strtoupper($str);
|
||||
|
||||
if (isset(static::$KEYWORDS[$str])) {
|
||||
if ($isReserved && ! (static::$KEYWORDS[$str] & Token::FLAG_KEYWORD_RESERVED)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return static::$KEYWORDS[$str];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Operator.
|
||||
|
||||
/**
|
||||
* Checks if the given string is an operator.
|
||||
*
|
||||
* @param string $str string to be checked
|
||||
*
|
||||
* @return int|null 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 $str string to be checked
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isWhitespace($str)
|
||||
{
|
||||
return ($str === ' ') || ($str === "\r") || ($str === "\n") || ($str === "\t");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Comment.
|
||||
|
||||
/**
|
||||
* Checks if the given string is the beginning of a whitespace.
|
||||
*
|
||||
* @param string $str string to be checked
|
||||
* @param mixed $end
|
||||
*
|
||||
* @return int|null the appropriate flag for the comment type
|
||||
*/
|
||||
public static function isComment($str, $end = false)
|
||||
{
|
||||
$len = strlen($str);
|
||||
if ($len === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If comment is Bash style (#):
|
||||
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])) {
|
||||
return Token::FLAG_COMMENT_SQL;
|
||||
}
|
||||
|
||||
if (($len === 2) && $end && ($str[0] === '-') && ($str[1] === '-')) {
|
||||
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 $str string to be checked
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isBool($str)
|
||||
{
|
||||
$str = strtoupper($str);
|
||||
|
||||
return ($str === 'TRUE') || ($str === 'FALSE');
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Number.
|
||||
|
||||
/**
|
||||
* Checks if the given character can be a part of a number.
|
||||
*
|
||||
* @param string $str string to be checked
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isNumber($str)
|
||||
{
|
||||
return ($str >= '0') && ($str <= '9') || ($str === '.')
|
||||
|| ($str === '-') || ($str === '+') || ($str === 'e') || ($str === '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 $str string to be checked
|
||||
*
|
||||
* @return int|null the appropriate flag for the symbol type
|
||||
*/
|
||||
public static function isSymbol($str)
|
||||
{
|
||||
if (strlen($str) === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($str[0] === '@') {
|
||||
return Token::FLAG_SYMBOL_VARIABLE;
|
||||
}
|
||||
|
||||
if ($str[0] === '`') {
|
||||
return Token::FLAG_SYMBOL_BACKTICK;
|
||||
}
|
||||
|
||||
if ($str[0] === ':' || $str[0] === '?') {
|
||||
return Token::FLAG_SYMBOL_PARAMETER;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// String.
|
||||
|
||||
/**
|
||||
* Checks if the given character is the beginning of a string.
|
||||
*
|
||||
* @param string $str string to be checked
|
||||
*
|
||||
* @return int|null the appropriate flag for the string type
|
||||
*/
|
||||
public static function isString($str)
|
||||
{
|
||||
if (strlen($str) === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($str[0] === '\'') {
|
||||
return Token::FLAG_STRING_SINGLE_QUOTES;
|
||||
}
|
||||
|
||||
if ($str[0] === '"') {
|
||||
return Token::FLAG_STRING_DOUBLE_QUOTES;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Delimiter.
|
||||
|
||||
/**
|
||||
* Checks if the given character can be a separator for two lexeme.
|
||||
*
|
||||
* @param string $str string to be checked
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isSeparator($str)
|
||||
{
|
||||
// NOTES: Only non alphanumeric ASCII characters may be separators.
|
||||
// `~` is the last printable ASCII character.
|
||||
return ($str <= '~')
|
||||
&& ($str !== '_')
|
||||
&& ($str !== '$')
|
||||
&& (($str < '0') || ($str > '9'))
|
||||
&& (($str < 'a') || ($str > 'z'))
|
||||
&& (($str < 'A') || ($str > 'Z'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the specified context.
|
||||
*
|
||||
* Contexts may be used by accessing the context directly.
|
||||
*
|
||||
* @param string $context name of the context or full class name that defines the context
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
self::$loadedContext = $context;
|
||||
self::$KEYWORDS = $context::$KEYWORDS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the context with the closest version to the one specified.
|
||||
*
|
||||
* The closest context is found by replacing last digits with zero until one
|
||||
* is loaded successfully.
|
||||
*
|
||||
* @see Context::load()
|
||||
*
|
||||
* @param string $context name of the context or full class name that
|
||||
* defines the context
|
||||
*
|
||||
* @return string|null The loaded context. `null` if no context was loaded.
|
||||
*/
|
||||
public static function loadClosest($context = '')
|
||||
{
|
||||
$length = strlen($context);
|
||||
for ($i = $length; $i > 0;) {
|
||||
try {
|
||||
/* Trying to load the new context */
|
||||
static::load($context);
|
||||
|
||||
return $context;
|
||||
} catch (LoaderException $e) {
|
||||
/* Replace last two non zero digits by zeroes */
|
||||
do {
|
||||
$i -= 2;
|
||||
$part = substr($context, $i, 2);
|
||||
/* No more numeric parts to strip */
|
||||
if (! is_numeric($part)) {
|
||||
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 (str_starts_with($context, 'MariaDb')) {
|
||||
return static::loadClosest('MariaDb100300');
|
||||
}
|
||||
|
||||
if (str_starts_with($context, 'MySql')) {
|
||||
return static::loadClosest('MySql50700');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SQL mode.
|
||||
*/
|
||||
public static function getMode(): int
|
||||
{
|
||||
return static::$MODE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SQL mode.
|
||||
*
|
||||
* @param int|string $mode
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function setMode($mode = self::SQL_MODE_NONE)
|
||||
{
|
||||
if (is_int($mode)) {
|
||||
static::$MODE = $mode;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static::$MODE = self::SQL_MODE_NONE;
|
||||
if ($mode === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$modes = explode(',', $mode);
|
||||
foreach ($modes as $sqlMode) {
|
||||
static::$MODE |= self::getModeFromString($sqlMode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress MixedReturnStatement, MixedInferredReturnType Is caused by the LSB of the constants
|
||||
*/
|
||||
private static function getModeFromString(string $mode): int
|
||||
{
|
||||
// phpcs:disable SlevomatCodingStandard.Classes.DisallowLateStaticBindingForConstants.DisallowedLateStaticBindingForConstant
|
||||
switch ($mode) {
|
||||
case 'ALLOW_INVALID_DATES':
|
||||
return static::SQL_MODE_ALLOW_INVALID_DATES;
|
||||
|
||||
case 'ANSI_QUOTES':
|
||||
return static::SQL_MODE_ANSI_QUOTES;
|
||||
|
||||
case 'COMPAT_MYSQL':
|
||||
return static::SQL_MODE_COMPAT_MYSQL;
|
||||
|
||||
case 'ERROR_FOR_DIVISION_BY_ZERO':
|
||||
return static::SQL_MODE_ERROR_FOR_DIVISION_BY_ZERO;
|
||||
|
||||
case 'HIGH_NOT_PRECEDENCE':
|
||||
return static::SQL_MODE_HIGH_NOT_PRECEDENCE;
|
||||
|
||||
case 'IGNORE_SPACE':
|
||||
return static::SQL_MODE_IGNORE_SPACE;
|
||||
|
||||
case 'NO_AUTO_CREATE_USER':
|
||||
return static::SQL_MODE_NO_AUTO_CREATE_USER;
|
||||
|
||||
case 'NO_AUTO_VALUE_ON_ZERO':
|
||||
return static::SQL_MODE_NO_AUTO_VALUE_ON_ZERO;
|
||||
|
||||
case 'NO_BACKSLASH_ESCAPES':
|
||||
return static::SQL_MODE_NO_BACKSLASH_ESCAPES;
|
||||
|
||||
case 'NO_DIR_IN_CREATE':
|
||||
return static::SQL_MODE_NO_DIR_IN_CREATE;
|
||||
|
||||
case 'NO_ENGINE_SUBSTITUTION':
|
||||
return static::SQL_MODE_NO_ENGINE_SUBSTITUTION;
|
||||
|
||||
case 'NO_FIELD_OPTIONS':
|
||||
return static::SQL_MODE_NO_FIELD_OPTIONS;
|
||||
|
||||
case 'NO_KEY_OPTIONS':
|
||||
return static::SQL_MODE_NO_KEY_OPTIONS;
|
||||
|
||||
case 'NO_TABLE_OPTIONS':
|
||||
return static::SQL_MODE_NO_TABLE_OPTIONS;
|
||||
|
||||
case 'NO_UNSIGNED_SUBTRACTION':
|
||||
return static::SQL_MODE_NO_UNSIGNED_SUBTRACTION;
|
||||
|
||||
case 'NO_ZERO_DATE':
|
||||
return static::SQL_MODE_NO_ZERO_DATE;
|
||||
|
||||
case 'NO_ZERO_IN_DATE':
|
||||
return static::SQL_MODE_NO_ZERO_IN_DATE;
|
||||
|
||||
case 'ONLY_FULL_GROUP_BY':
|
||||
return static::SQL_MODE_ONLY_FULL_GROUP_BY;
|
||||
|
||||
case 'PIPES_AS_CONCAT':
|
||||
return static::SQL_MODE_PIPES_AS_CONCAT;
|
||||
|
||||
case 'REAL_AS_FLOAT':
|
||||
return static::SQL_MODE_REAL_AS_FLOAT;
|
||||
|
||||
case 'STRICT_ALL_TABLES':
|
||||
return static::SQL_MODE_STRICT_ALL_TABLES;
|
||||
|
||||
case 'STRICT_TRANS_TABLES':
|
||||
return static::SQL_MODE_STRICT_TRANS_TABLES;
|
||||
|
||||
case 'NO_ENCLOSING_QUOTES':
|
||||
return static::SQL_MODE_NO_ENCLOSING_QUOTES;
|
||||
|
||||
case 'ANSI':
|
||||
return static::SQL_MODE_ANSI;
|
||||
|
||||
case 'DB2':
|
||||
return static::SQL_MODE_DB2;
|
||||
|
||||
case 'MAXDB':
|
||||
return static::SQL_MODE_MAXDB;
|
||||
|
||||
case 'MSSQL':
|
||||
return static::SQL_MODE_MSSQL;
|
||||
|
||||
case 'ORACLE':
|
||||
return static::SQL_MODE_ORACLE;
|
||||
|
||||
case 'POSTGRESQL':
|
||||
return static::SQL_MODE_POSTGRESQL;
|
||||
|
||||
case 'TRADITIONAL':
|
||||
return static::SQL_MODE_TRADITIONAL;
|
||||
|
||||
default:
|
||||
return self::SQL_MODE_NONE;
|
||||
}
|
||||
// phpcs:enable
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes the symbol by adding surrounding backticks.
|
||||
*
|
||||
* @param string[]|string $str the string to be escaped
|
||||
* @param string $quote quote to be used when escaping
|
||||
*
|
||||
* @return string|string[]
|
||||
*/
|
||||
public static function escape($str, $quote = '`')
|
||||
{
|
||||
if (is_array($str)) {
|
||||
foreach ($str as $key => $value) {
|
||||
$str[$key] = static::escape($value);
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
if ((static::$MODE & self::SQL_MODE_NO_ENCLOSING_QUOTES) && (! static::isKeyword($str, true))) {
|
||||
return $str;
|
||||
}
|
||||
|
||||
if (static::$MODE & self::SQL_MODE_ANSI_QUOTES) {
|
||||
$quote = '"';
|
||||
}
|
||||
|
||||
return $quote . str_replace($quote, $quote . $quote, $str) . $quote;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
{
|
||||
return self::hasMode(self::SQL_MODE_ANSI_QUOTES) ? '"' : '`';
|
||||
}
|
||||
|
||||
/**
|
||||
* Function verifies that given SQL Mode constant is currently set
|
||||
*
|
||||
* @param int $flag for example {@see 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;
|
||||
}
|
||||
}
|
||||
|
||||
// Initializing the default context.
|
||||
Context::load();
|
Loading…
Add table
Add a link
Reference in a new issue