* 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
@@ -1,41 +1,39 @@
<?php
/**
* Buffered query utilities.
*/
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Utils;
use PhpMyAdmin\SqlParser\Context;
use function array_merge;
use function strlen;
use function substr;
use function trim;
/**
* Buffer query utilities.
*
* Implements a specialized lexer used to extract statements from large inputs
* that are being buffered. After each statement has been extracted, a lexer or
* a parser may be used.
*
* @category Lexer
*
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
*/
class BufferedQuery
{
// Constants that describe the current status of the parser.
// A string is being parsed.
public const STATUS_STRING = 16; // 0001 0000
public const STATUS_STRING_SINGLE_QUOTES = 17; // 0001 0001
public const STATUS_STRING_DOUBLE_QUOTES = 18; // 0001 0010
public const STATUS_STRING_BACKTICK = 20; // 0001 0100
const STATUS_STRING = 16; // 0001 0000
const STATUS_STRING_SINGLE_QUOTES = 17; // 0001 0001
const STATUS_STRING_DOUBLE_QUOTES = 18; // 0001 0010
const STATUS_STRING_BACKTICK = 20; // 0001 0100
// A comment is being parsed.
public const STATUS_COMMENT = 32; // 0010 0000
public const STATUS_COMMENT_BASH = 33; // 0010 0001
public const STATUS_COMMENT_C = 34; // 0010 0010
public const STATUS_COMMENT_SQL = 36; // 0010 0100
const STATUS_COMMENT = 32; // 0010 0000
const STATUS_COMMENT_BASH = 33; // 0010 0001
const STATUS_COMMENT_C = 34; // 0010 0010
const STATUS_COMMENT_SQL = 36; // 0010 0100
/**
* The query that is being processed.
@@ -51,7 +49,7 @@ class BufferedQuery
*
* @var array
*/
public $options = [];
public $options = array();
/**
* The last delimiter used.
@@ -82,14 +80,16 @@ class BufferedQuery
public $current = '';
/**
* Constructor.
*
* @param string $query the query to be parsed
* @param array $options the options of this parser
*/
public function __construct($query = '', array $options = [])
public function __construct($query = '', array $options = array())
{
// Merges specified options with defaults.
$this->options = array_merge(
[
array(
/*
* The starting delimiter.
*
@@ -111,7 +111,7 @@ class BufferedQuery
* @var bool
*/
'add_delimiter' => false,
],
),
$options
);
@@ -191,7 +191,7 @@ class BufferedQuery
* treated differently, because of the preceding backslash, it will
* be ignored.
*/
if ((($this->status & self::STATUS_COMMENT) === 0) && ($this->query[$i] === '\\')) {
if ((($this->status & static::STATUS_COMMENT) === 0) && ($this->query[$i] === '\\')) {
$this->current .= $this->query[$i] . ($i + 1 < $len ? $this->query[++$i] : '');
continue;
}
@@ -199,43 +199,40 @@ class BufferedQuery
/*
* Handling special parses statuses.
*/
if ($this->status === self::STATUS_STRING_SINGLE_QUOTES) {
if ($this->status === static::STATUS_STRING_SINGLE_QUOTES) {
// Single-quoted strings like 'foo'.
if ($this->query[$i] === '\'') {
$this->status = 0;
}
$this->current .= $this->query[$i];
continue;
} elseif ($this->status === self::STATUS_STRING_DOUBLE_QUOTES) {
} elseif ($this->status === static::STATUS_STRING_DOUBLE_QUOTES) {
// Double-quoted strings like "bar".
if ($this->query[$i] === '"') {
$this->status = 0;
}
$this->current .= $this->query[$i];
continue;
} elseif ($this->status === self::STATUS_STRING_BACKTICK) {
} elseif ($this->status === static::STATUS_STRING_BACKTICK) {
if ($this->query[$i] === '`') {
$this->status = 0;
}
$this->current .= $this->query[$i];
continue;
} elseif (($this->status === self::STATUS_COMMENT_BASH) || ($this->status === self::STATUS_COMMENT_SQL)) {
} elseif (($this->status === static::STATUS_COMMENT_BASH)
|| ($this->status === static::STATUS_COMMENT_SQL)
) {
// Bash-like (#) or SQL-like (-- ) comments end in new line.
if ($this->query[$i] === "\n") {
$this->status = 0;
}
$this->current .= $this->query[$i];
continue;
} elseif ($this->status === self::STATUS_COMMENT_C) {
} elseif ($this->status === static::STATUS_COMMENT_C) {
// C-like comments end in */.
if (($this->query[$i - 1] === '*') && ($this->query[$i] === '/')) {
$this->status = 0;
}
$this->current .= $this->query[$i];
continue;
}
@@ -244,19 +241,15 @@ class BufferedQuery
* Checking if a string started.
*/
if ($this->query[$i] === '\'') {
$this->status = self::STATUS_STRING_SINGLE_QUOTES;
$this->status = static::STATUS_STRING_SINGLE_QUOTES;
$this->current .= $this->query[$i];
continue;
}
if ($this->query[$i] === '"') {
$this->status = self::STATUS_STRING_DOUBLE_QUOTES;
} elseif ($this->query[$i] === '"') {
$this->status = static::STATUS_STRING_DOUBLE_QUOTES;
$this->current .= $this->query[$i];
continue;
}
if ($this->query[$i] === '`') {
$this->status = self::STATUS_STRING_BACKTICK;
} elseif ($this->query[$i] === '`') {
$this->status = static::STATUS_STRING_BACKTICK;
$this->current .= $this->query[$i];
continue;
}
@@ -265,24 +258,20 @@ class BufferedQuery
* Checking if a comment started.
*/
if ($this->query[$i] === '#') {
$this->status = self::STATUS_COMMENT_BASH;
$this->status = static::STATUS_COMMENT_BASH;
$this->current .= $this->query[$i];
continue;
}
if ($i + 2 < $len) {
if (
($this->query[$i] === '-')
&& ($this->query[$i + 1] === '-')
&& Context::isWhitespace($this->query[$i + 2])
) {
$this->status = self::STATUS_COMMENT_SQL;
} elseif ($i + 2 < $len) {
if (($this->query[$i] === '-')
&& ($this->query[$i + 1] === '-')
&& Context::isWhitespace($this->query[$i + 2])) {
$this->status = static::STATUS_COMMENT_SQL;
$this->current .= $this->query[$i];
continue;
}
if (($this->query[$i] === '/') && ($this->query[$i + 1] === '*') && ($this->query[$i + 2] !== '!')) {
$this->status = self::STATUS_COMMENT_C;
} elseif (($this->query[$i] === '/')
&& ($this->query[$i + 1] === '*')
&& ($this->query[$i + 2] !== '!')) {
$this->status = static::STATUS_COMMENT_C;
$this->current .= $this->query[$i];
continue;
}
@@ -300,8 +289,7 @@ class BufferedQuery
* it has a special meaning is when it is the beginning of a
* statement. This is the reason for the last condition.
*/
if (
($i + 9 < $len)
if (($i + 9 < $len)
&& (($this->query[$i] === 'D') || ($this->query[$i] === 'd'))
&& (($this->query[$i + 1] === 'E') || ($this->query[$i + 1] === 'e'))
&& (($this->query[$i + 2] === 'L') || ($this->query[$i + 2] === 'l'))
@@ -330,9 +318,8 @@ class BufferedQuery
}
// Checking if the delimiter definition ended.
if (
($delimiter !== '')
&& (($i < $len) && Context::isWhitespace($this->query[$i])
if (($delimiter !== '')
&& ((($i < $len) && Context::isWhitespace($this->query[$i]))
|| (($i === $len) && $end))
) {
// Saving the delimiter.
@@ -374,8 +361,7 @@ class BufferedQuery
* There is no point in checking if two strings match if not even
* the first letter matches.
*/
if (
($this->query[$i] === $this->delimiter[0])
if (($this->query[$i] === $this->delimiter[0])
&& (($this->delimiterLen === 1)
|| (substr($this->query, $i, $this->delimiterLen) === $this->delimiter))
) {
+40 -105
View File
@@ -1,92 +1,65 @@
<?php
/**
* CLI interface.
*/
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Utils;
use PhpMyAdmin\SqlParser\Context;
use PhpMyAdmin\SqlParser\Lexer;
use PhpMyAdmin\SqlParser\Parser;
use function count;
use function getopt;
use function implode;
use function in_array;
use function rtrim;
use function stream_get_contents;
use function stream_select;
use function var_export;
use const STDIN;
/**
* CLI interface.
*
* @category Exceptions
*
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
*/
class CLI
{
/**
* @param string[]|false[] $params
* @param string[] $longopts
*
* @return void
*/
public function mergeLongOpts(&$params, &$longopts)
{
foreach ($longopts as $value) {
$value = rtrim($value, ':');
if (! isset($params[$value])) {
continue;
if (isset($params[$value])) {
$params[$value[0]] = $params[$value];
}
$params[$value[0]] = $params[$value];
}
}
/**
* @return void
*/
public function usageHighlight()
{
echo "Usage: highlight-query --query SQL [--format html|cli|text] [--ansi]\n";
echo " cat file.sql | highlight-query\n";
}
/**
* @param string $opt
* @param array $long
*
* @return string[]|false[]|false
*/
public function getopt($opt, $long)
{
return getopt($opt, $long);
}
/**
* @return mixed|false
*/
public function parseHighlight()
{
$longopts = [
$longopts = array(
'help',
'query:',
'format:',
'ansi',
];
$params = $this->getopt('hq:f:a', $longopts);
'ansi'
);
$params = $this->getopt(
'hq:f:a',
$longopts
);
if ($params === false) {
return false;
}
$this->mergeLongOpts($params, $longopts);
if (! isset($params['f'])) {
$params['f'] = 'cli';
}
if (! in_array($params['f'], ['html', 'cli', 'text'])) {
if (! in_array($params['f'], array('html', 'cli', 'text'))) {
echo "ERROR: Invalid value for format!\n";
return false;
@@ -95,26 +68,19 @@ class CLI
return $params;
}
/**
* @return int
*/
public function runHighlight()
{
$params = $this->parseHighlight();
if ($params === false) {
return 1;
}
if (isset($params['h'])) {
$this->usageHighlight();
return 0;
}
if (! isset($params['q'])) {
$stdIn = $this->readStdin();
if ($stdIn) {
if (!isset($params['q'])) {
if ($stdIn = $this->readStdin()) {
$params['q'] = $stdIn;
}
}
@@ -122,77 +88,63 @@ class CLI
if (isset($params['a'])) {
Context::setMode('ANSI_QUOTES');
}
if (isset($params['q'])) {
echo Formatter::format(
$params['q'],
['type' => $params['f']]
array('type' => $params['f'])
);
echo "\n";
return 0;
}
echo "ERROR: Missing parameters!\n";
$this->usageHighlight();
return 1;
}
/**
* @return void
*/
public function usageLint()
{
echo "Usage: lint-query --query SQL [--ansi]\n";
echo " cat file.sql | lint-query\n";
}
/**
* @return mixed
*/
public function parseLint()
{
$longopts = [
$longopts = array(
'help',
'query:',
'context:',
'ansi',
];
$params = $this->getopt('hq:c:a', $longopts);
'ansi'
);
$params = $this->getopt(
'hq:c:a',
$longopts
);
$this->mergeLongOpts($params, $longopts);
return $params;
}
/**
* @return int
*/
public function runLint()
{
$params = $this->parseLint();
if ($params === false) {
return 1;
}
if (isset($params['h'])) {
$this->usageLint();
return 0;
}
if (isset($params['c'])) {
Context::load($params['c']);
}
if (! isset($params['q'])) {
$stdIn = $this->readStdin();
if ($stdIn) {
if (!isset($params['q'])) {
if ($stdIn = $this->readStdin()) {
$params['q'] = $stdIn;
}
}
if (isset($params['a'])) {
Context::setMode('ANSI_QUOTES');
}
@@ -200,69 +152,57 @@ class CLI
if (isset($params['q'])) {
$lexer = new Lexer($params['q'], false);
$parser = new Parser($lexer->list);
$errors = Error::get([$lexer, $parser]);
$errors = Error::get(array($lexer, $parser));
if (count($errors) === 0) {
return 0;
}
$output = Error::format($errors);
echo implode("\n", $output);
echo "\n";
return 10;
}
echo "ERROR: Missing parameters!\n";
$this->usageLint();
return 1;
}
/**
* @return void
*/
public function usageTokenize()
{
echo "Usage: tokenize-query --query SQL [--ansi]\n";
echo " cat file.sql | tokenize-query\n";
}
/**
* @return mixed
*/
public function parseTokenize()
{
$longopts = [
$longopts = array(
'help',
'query:',
'ansi',
];
$params = $this->getopt('hq:a', $longopts);
'ansi'
);
$params = $this->getopt(
'hq:a',
$longopts
);
$this->mergeLongOpts($params, $longopts);
return $params;
}
/**
* @return int
*/
public function runTokenize()
{
$params = $this->parseTokenize();
if ($params === false) {
return 1;
}
if (isset($params['h'])) {
$this->usageTokenize();
return 0;
}
if (! isset($params['q'])) {
$stdIn = $this->readStdin();
if ($stdIn) {
if (!isset($params['q'])) {
if ($stdIn = $this->readStdin()) {
$params['q'] = $stdIn;
}
}
@@ -270,7 +210,6 @@ class CLI
if (isset($params['a'])) {
Context::setMode('ANSI_QUOTES');
}
if (isset($params['q'])) {
$lexer = new Lexer($params['q'], false);
foreach ($lexer->list->tokens as $idx => $token) {
@@ -288,21 +227,17 @@ class CLI
return 0;
}
echo "ERROR: Missing parameters!\n";
$this->usageTokenize();
return 1;
}
/**
* @return string|false
*/
public function readStdin()
{
$read = [STDIN];
$write = [];
$except = [];
$read = array(STDIN);
$write = array();
$except = array();
// Assume there's nothing to be read from STDIN.
$stdin = null;
@@ -1,22 +1,20 @@
<?php
/**
* Error related utilities.
*/
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Utils;
use PhpMyAdmin\SqlParser\Exceptions\LexerException;
use PhpMyAdmin\SqlParser\Exceptions\ParserException;
use PhpMyAdmin\SqlParser\Lexer;
use PhpMyAdmin\SqlParser\Parser;
use function htmlspecialchars;
use function sprintf;
/**
* Error related utilities.
*
* @category Exceptions
*
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
*/
class Error
{
@@ -30,32 +28,30 @@ class Error
* `$err[1]` holds the error code.
* `$err[2]` holds the string that caused the issue.
* `$err[3]` holds the position of the string.
* (i.e. `[$msg, $code, $str, $pos]`)
* (i.e. `array($msg, $code, $str, $pos)`)
*/
public static function get($objs)
{
$ret = [];
$ret = array();
foreach ($objs as $obj) {
if ($obj instanceof Lexer) {
/** @var LexerException $err */
foreach ($obj->errors as $err) {
$ret[] = [
$ret[] = array(
$err->getMessage(),
$err->getCode(),
$err->ch,
$err->pos,
];
$err->pos
);
}
} elseif ($obj instanceof Parser) {
/** @var ParserException $err */
foreach ($obj->errors as $err) {
$ret[] = [
$ret[] = array(
$err->getMessage(),
$err->getCode(),
$err->token->token,
$err->token->position,
];
$err->token->position
);
}
}
}
@@ -81,7 +77,7 @@ class Error
$errors,
$format = '#%1$d: %2$s (near "%4$s" at position %5$d)'
) {
$ret = [];
$ret = array();
$i = 0;
foreach ($errors as $key => $err) {
@@ -90,7 +86,7 @@ class Error
++$i,
$err[0],
$err[1],
htmlspecialchars((string) $err[2]),
htmlspecialchars($err[2]),
$err[3]
);
}
@@ -1,10 +1,9 @@
<?php
/**
* Utilities that are used for formatting queries.
*/
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Utils;
use PhpMyAdmin\SqlParser\Components\JoinKeyword;
@@ -13,22 +12,12 @@ use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Token;
use PhpMyAdmin\SqlParser\TokensList;
use function array_merge;
use function array_pop;
use function end;
use function htmlspecialchars;
use function in_array;
use function mb_strlen;
use function str_repeat;
use function str_replace;
use function strpos;
use function strtoupper;
use const ENT_NOQUOTES;
use const PHP_SAPI;
/**
* Utilities that are used for formatting queries.
*
* @category Misc
*
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
*/
class Formatter
{
@@ -57,10 +46,10 @@ class Formatter
*
* @var array
*/
public static $SHORT_CLAUSES = [
public static $SHORT_CLAUSES = array(
'CREATE' => true,
'INSERT' => true,
];
'INSERT' => true
);
/**
* Clauses that must be inlined.
@@ -69,7 +58,7 @@ class Formatter
*
* @var array
*/
public static $INLINE_CLAUSES = [
public static $INLINE_CLAUSES = array(
'CREATE' => true,
'INTO' => true,
'LIMIT' => true,
@@ -77,13 +66,15 @@ class Formatter
'PARTITION' => true,
'PROCEDURE' => true,
'SUBPARTITION BY' => true,
'VALUES' => true,
];
'VALUES' => true
);
/**
* Constructor.
*
* @param array $options the formatting options
*/
public function __construct(array $options = [])
public function __construct(array $options = array())
{
$this->options = $this->getMergedOptions($options);
}
@@ -108,11 +99,11 @@ class Formatter
$options['formats'] = $this->getDefaultFormats();
}
if ($options['line_ending'] === null) {
if (is_null($options['line_ending'])) {
$options['line_ending'] = $options['type'] === 'html' ? '<br/>' : "\n";
}
if ($options['indentation'] === null) {
if (is_null($options['indentation'])) {
$options['indentation'] = $options['type'] === 'html' ? '&nbsp;&nbsp;&nbsp;&nbsp;' : ' ';
}
@@ -129,13 +120,13 @@ class Formatter
*/
protected function getDefaultOptions()
{
return [
return array(
/*
* The format of the result.
*
* @var string The type ('text', 'cli' or 'html')
*/
'type' => PHP_SAPI === 'cli' ? 'cli' : 'text',
'type' => php_sapi_name() === 'cli' ? 'cli' : 'text',
/*
* The line ending used.
@@ -179,129 +170,122 @@ class Formatter
*
* @var bool
*/
'indent_parts' => true,
];
'indent_parts' => true
);
}
/**
* The styles used for HTML formatting.
* [$type, $flags, $span, $callback].
* array($type, $flags, $span, $callback).
*
* @return array
*/
protected function getDefaultFormats()
{
return [
[
return array(
array(
'type' => Token::TYPE_KEYWORD,
'flags' => Token::FLAG_KEYWORD_RESERVED,
'html' => 'class="sql-reserved"',
'cli' => "\x1b[35m",
'function' => 'strtoupper',
],
[
),
array(
'type' => Token::TYPE_KEYWORD,
'flags' => 0,
'html' => 'class="sql-keyword"',
'cli' => "\x1b[95m",
'function' => 'strtoupper',
],
[
),
array(
'type' => Token::TYPE_COMMENT,
'flags' => 0,
'html' => 'class="sql-comment"',
'cli' => "\x1b[37m",
'function' => '',
],
[
),
array(
'type' => Token::TYPE_BOOL,
'flags' => 0,
'html' => 'class="sql-atom"',
'cli' => "\x1b[36m",
'function' => 'strtoupper',
],
[
),
array(
'type' => Token::TYPE_NUMBER,
'flags' => 0,
'html' => 'class="sql-number"',
'cli' => "\x1b[92m",
'function' => 'strtolower',
],
[
),
array(
'type' => Token::TYPE_STRING,
'flags' => 0,
'html' => 'class="sql-string"',
'cli' => "\x1b[91m",
'function' => '',
],
[
),
array(
'type' => Token::TYPE_SYMBOL,
'flags' => Token::FLAG_SYMBOL_PARAMETER,
'html' => 'class="sql-parameter"',
'cli' => "\x1b[31m",
'function' => '',
],
[
),
array(
'type' => Token::TYPE_SYMBOL,
'flags' => 0,
'html' => 'class="sql-variable"',
'cli' => "\x1b[36m",
'function' => '',
],
];
)
);
}
private static function mergeFormats(array $formats, array $newFormats): array
private static function mergeFormats(array $formats, array $newFormats)
{
$added = [];
$integers = [
$added = array();
$integers = array(
'flags',
'type',
];
$strings = [
'type'
);
$strings = array(
'html',
'cli',
'function',
];
'function'
);
/* Sanitize the array so that we do not have to care later */
foreach ($newFormats as $j => $new) {
foreach ($integers as $name) {
if (isset($new[$name])) {
continue;
if (! isset($new[$name])) {
$newFormats[$j][$name] = 0;
}
$newFormats[$j][$name] = 0;
}
foreach ($strings as $name) {
if (isset($new[$name])) {
continue;
if (! isset($new[$name])) {
$newFormats[$j][$name] = '';
}
$newFormats[$j][$name] = '';
}
}
/* Process changes to existing formats */
foreach ($formats as $i => $original) {
foreach ($newFormats as $j => $new) {
if ($new['type'] !== $original['type'] || $original['flags'] !== $new['flags']) {
continue;
if ($new['type'] === $original['type']
&& $original['flags'] === $new['flags']
) {
$formats[$i] = $new;
$added[] = $j;
}
$formats[$i] = $new;
$added[] = $j;
}
}
/* Add not already handled formats */
foreach ($newFormats as $j => $new) {
if (in_array($j, $added)) {
continue;
if (! in_array($j, $added)) {
$formats[] = $new;
}
$formats[] = $new;
}
return $formats;
@@ -357,7 +341,7 @@ class Formatter
*
* @var array
*/
$blocksIndentation = [];
$blocksIndentation = array();
/**
* A stack that keeps track of the line endings every time a new block
@@ -365,7 +349,7 @@ class Formatter
*
* @var array
*/
$blocksLineEndings = [];
$blocksLineEndings = array();
/**
* Whether clause's options were formatted.
@@ -400,15 +384,13 @@ class Formatter
if ($curr->type === Token::TYPE_WHITESPACE) {
// Keep linebreaks before and after comments
if (
strpos($curr->token, "\n") !== false && (
if (strpos($curr->token, "\n") !== false && (
($prev !== null && $prev->type === Token::TYPE_COMMENT) ||
($next !== null && $next->type === Token::TYPE_COMMENT)
)
) {
$lineEnded = true;
}
// Whitespaces are skipped because the formatter adds its own.
continue;
}
@@ -427,8 +409,7 @@ class Formatter
}
// The options of a clause should stay on the same line and everything that follows.
if (
$this->options['parts_newline']
if ($this->options['parts_newline']
&& ! $formattedOptions
&& empty(self::$INLINE_CLAUSES[$lastClause])
&& (
@@ -445,13 +426,8 @@ class Formatter
}
// Checking if this clause ended.
$isClause = static::isClause($curr);
if ($isClause) {
if (
($isClause === 2 || $this->options['clause_newline'])
&& empty(self::$SHORT_CLAUSES[$lastClause])
) {
if ($isClause = static::isClause($curr)) {
if (($isClause === 2 || $this->options['clause_newline']) && empty(self::$SHORT_CLAUSES[$lastClause])) {
$lineEnded = true;
if ($this->options['parts_newline'] && $indent > 0) {
--$indent;
@@ -460,10 +436,8 @@ class Formatter
}
// Inline JOINs
if (
($prev->type === Token::TYPE_KEYWORD && isset(JoinKeyword::$JOINS[$prev->value]))
|| (in_array($curr->value, ['ON', 'USING'], true)
&& isset(JoinKeyword::$JOINS[$list->tokens[$list->idx - 2]->value]))
if (($prev->type === Token::TYPE_KEYWORD && isset(JoinKeyword::$JOINS[$prev->value]))
|| (in_array($curr->value, array('ON', 'USING'), true) && isset(JoinKeyword::$JOINS[$list->tokens[$list->idx - 2]->value]))
|| isset($list->tokens[$list->idx - 4], JoinKeyword::$JOINS[$list->tokens[$list->idx - 4]->value])
|| isset($list->tokens[$list->idx - 6], JoinKeyword::$JOINS[$list->tokens[$list->idx - 6]->value])
) {
@@ -485,8 +459,7 @@ class Formatter
// Fragments delimited by a comma are broken into multiple
// pieces only if the clause is not inlined or this fragment
// is between brackets that are on new line.
if (
end($blocksLineEndings) === true
if (end($blocksLineEndings) === true
|| (
empty(self::$INLINE_CLAUSES[$lastClause])
&& ! $shortGroup
@@ -508,7 +481,6 @@ class Formatter
$lineEnded = true;
$shortGroup = false;
}
$blocksLineEndings[] = $lineEnded;
} elseif ($curr->type === Token::TYPE_OPERATOR && $curr->value === ')') {
$indent = array_pop($blocksIndentation);
@@ -522,23 +494,20 @@ class Formatter
// Finishing the line.
if ($lineEnded) {
$ret .= $this->options['line_ending']
. str_repeat($this->options['indentation'], (int) $indent);
. str_repeat($this->options['indentation'], $indent);
$lineEnded = false;
} else {
// If the line ended there is no point in adding whitespaces.
// Also, some tokens do not have spaces before or after them.
if (
// A space after delimiters that are longer than 2 characters.
if (// A space after delimiters that are longer than 2 characters.
$prev->keyword === 'DELIMITER'
|| ! (
($prev->type === Token::TYPE_OPERATOR && ($prev->value === '.' || $prev->value === '('))
// No space after . (
|| ($curr->type === Token::TYPE_OPERATOR
&& ($curr->value === '.' || $curr->value === ','
|| $curr->value === '(' || $curr->value === ')'))
|| ($curr->type === Token::TYPE_OPERATOR && ($curr->value === '.' || $curr->value === ',' || $curr->value === '(' || $curr->value === ')'))
// No space before . , ( )
|| $curr->type === Token::TYPE_DELIMITER && mb_strlen((string) $curr->value, 'UTF-8') < 2
|| $curr->type === Token::TYPE_DELIMITER && mb_strlen($curr->value, 'UTF-8') < 2
)
) {
$ret .= ' ';
@@ -557,10 +526,10 @@ class Formatter
return $ret;
}
public function escapeConsole(string $string): string
public function escapeConsole($string)
{
return str_replace(
[
array(
"\x00",
"\x01",
"\x02",
@@ -593,8 +562,8 @@ class Formatter
"\x1D",
"\x1E",
"\x1F",
],
[
),
array(
'\x00',
'\x01',
'\x02',
@@ -627,7 +596,7 @@ class Formatter
'\x1D',
'\x1E',
'\x1F',
],
),
$string
);
}
@@ -645,32 +614,30 @@ class Formatter
static $prev;
foreach ($this->options['formats'] as $format) {
if ($token->type !== $format['type'] || ! (($token->flags & $format['flags']) === $format['flags'])) {
continue;
}
// Running transformation function.
if (! empty($format['function'])) {
$func = $format['function'];
$text = $func($text);
}
// Formatting HTML.
if ($this->options['type'] === 'html') {
return '<span ' . $format['html'] . '>' . htmlspecialchars($text, ENT_NOQUOTES) . '</span>';
}
if ($this->options['type'] === 'cli') {
if ($prev !== $format['cli']) {
$prev = $format['cli'];
return $format['cli'] . $this->escapeConsole($text);
if ($token->type === $format['type']
&& ($token->flags & $format['flags']) === $format['flags']
) {
// Running transformation function.
if (! empty($format['function'])) {
$func = $format['function'];
$text = $func($text);
}
return $this->escapeConsole($text);
}
// Formatting HTML.
if ($this->options['type'] === 'html') {
return '<span ' . $format['html'] . '>' . htmlspecialchars($text, ENT_NOQUOTES) . '</span>';
} elseif ($this->options['type'] === 'cli') {
if ($prev !== $format['cli']) {
$prev = $format['cli'];
break;
return $format['cli'] . $this->escapeConsole($text);
}
return $this->escapeConsole($text);
}
break;
}
}
if ($this->options['type'] === 'cli') {
@@ -681,9 +648,7 @@ class Formatter
}
return $this->escapeConsole($text);
}
if ($this->options['type'] === 'html') {
} elseif ($this->options['type'] === 'html') {
return htmlspecialchars($text, ENT_NOQUOTES);
}
@@ -698,7 +663,7 @@ class Formatter
*
* @return string the formatted string
*/
public static function format($query, array $options = [])
public static function format($query, array $options = array())
{
$lexer = new Lexer($query);
$formatter = new self($options);
@@ -748,7 +713,7 @@ class Formatter
}
// Keeping track of this group's length.
$length += mb_strlen((string) $list->tokens[$idx]->value, 'UTF-8');
$length += mb_strlen($list->tokens[$idx]->value, 'UTF-8');
}
return $length;
@@ -763,14 +728,12 @@ class Formatter
*/
public static function isClause($token)
{
if (
($token->type === Token::TYPE_KEYWORD && isset(Parser::$STATEMENT_PARSERS[$token->keyword]))
if (($token->type === Token::TYPE_KEYWORD && isset(Parser::$STATEMENT_PARSERS[$token->keyword]))
|| ($token->type === Token::TYPE_NONE && strtoupper($token->token) === 'DELIMITER')
) {
return 2;
}
if ($token->type === Token::TYPE_KEYWORD && isset(Parser::$KEYWORD_PARSERS[$token->keyword])) {
} elseif ($token->type === Token::TYPE_KEYWORD && isset(Parser::$KEYWORD_PARSERS[$token->keyword])
) {
return 1;
}
+26 -19
View File
@@ -1,10 +1,9 @@
<?php
/**
* Miscellaneous utilities.
*/
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Utils;
use PhpMyAdmin\SqlParser\Components\Expression;
@@ -12,6 +11,10 @@ use PhpMyAdmin\SqlParser\Statements\SelectStatement;
/**
* Miscellaneous utilities.
*
* @category Misc
*
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
*/
class Misc
{
@@ -25,13 +28,16 @@ class Misc
*/
public static function getAliases($statement, $database)
{
if (! ($statement instanceof SelectStatement) || empty($statement->expr) || empty($statement->from)) {
return [];
if (! ($statement instanceof SelectStatement)
|| empty($statement->expr)
|| empty($statement->from)
) {
return array();
}
$retval = [];
$retval = array();
$tables = [];
$tables = array();
/**
* Expressions that may contain aliases.
@@ -53,41 +59,42 @@ class Misc
continue;
}
$thisDb = isset($expr->database) && ($expr->database !== '') ?
$thisDb = (isset($expr->database) && ($expr->database !== '')) ?
$expr->database : $database;
if (! isset($retval[$thisDb])) {
$retval[$thisDb] = [
$retval[$thisDb] = array(
'alias' => null,
'tables' => [],
];
'tables' => array()
);
}
if (! isset($retval[$thisDb]['tables'][$expr->table])) {
$retval[$thisDb]['tables'][$expr->table] = [
'alias' => isset($expr->alias) && ($expr->alias !== '') ?
$retval[$thisDb]['tables'][$expr->table] = array(
'alias' => (isset($expr->alias) && ($expr->alias !== '')) ?
$expr->alias : null,
'columns' => [],
];
'columns' => array()
);
}
if (! isset($tables[$thisDb])) {
$tables[$thisDb] = [];
$tables[$thisDb] = array();
}
$tables[$thisDb][$expr->alias] = $expr->table;
}
foreach ($statement->expr as $expr) {
if (! isset($expr->column, $expr->alias) || ($expr->column === '') || ($expr->alias === '')) {
if (! isset($expr->column, $expr->alias) || ($expr->column === '') || ($expr->alias === '')
) {
continue;
}
$thisDb = isset($expr->database) && ($expr->database !== '') ?
$thisDb = (isset($expr->database) && ($expr->database !== '')) ?
$expr->database : $database;
if (isset($expr->table) && ($expr->table !== '')) {
$thisTable = $tables[$thisDb][$expr->table] ?? $expr->table;
$thisTable = isset($tables[$thisDb][$expr->table]) ?
$tables[$thisDb][$expr->table] : $expr->table;
$retval[$thisDb]['tables'][$thisTable]['columns'][$expr->column] = $expr->alias;
} else {
foreach ($retval[$thisDb]['tables'] as &$table) {
+96 -106
View File
@@ -1,10 +1,9 @@
<?php
/**
* Statement utilities.
*/
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Utils;
use PhpMyAdmin\SqlParser\Components\Expression;
@@ -34,24 +33,21 @@ use PhpMyAdmin\SqlParser\Statements\UpdateStatement;
use PhpMyAdmin\SqlParser\Token;
use PhpMyAdmin\SqlParser\TokensList;
use function array_flip;
use function array_keys;
use function count;
use function in_array;
use function is_string;
use function trim;
/**
* Statement utilities.
*
* @category Statement
*
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
*/
class Query
{
/**
* Functions that set the flag `is_func`.
*
* @var string[]
* @var array
*/
public static $FUNCTIONS = [
public static $FUNCTIONS = array(
'SUM',
'AVG',
'STD',
@@ -59,11 +55,10 @@ class Query
'MIN',
'MAX',
'BIT_OR',
'BIT_AND',
];
'BIT_AND'
);
/** @var array<string,false> */
public static $ALLFLAGS = [
public static $ALLFLAGS = array(
/*
* select ... DISTINCT ...
*/
@@ -216,8 +211,8 @@ class Query
/*
* ... UNION ...
*/
'union' => false,
];
'union' => false
);
/**
* Gets an array with flags select statement has.
@@ -244,7 +239,9 @@ class Query
$flags['is_group'] = true;
}
if (! empty($statement->into) && ($statement->into->type === 'OUTFILE')) {
if (! empty($statement->into)
&& ($statement->into->type === 'OUTFILE')
) {
$flags['is_export'] = true;
}
@@ -263,15 +260,14 @@ class Query
$flags['is_func'] = true;
}
}
if (empty($expr->subquery)) {
continue;
if (! empty($expr->subquery)) {
$flags['is_subquery'] = true;
}
$flags['is_subquery'] = true;
}
if (! empty($statement->procedure) && ($statement->procedure->name === 'ANALYSE')) {
if (! empty($statement->procedure)
&& ($statement->procedure->name === 'ANALYSE')
) {
$flags['is_analyse'] = true;
}
@@ -304,7 +300,7 @@ class Query
*/
public static function getFlags($statement, $all = false)
{
$flags = ['querytype' => false];
$flags = array('querytype' => false);
if ($all) {
$flags = self::$ALLFLAGS;
}
@@ -341,7 +337,9 @@ class Query
$flags['querytype'] = 'DROP';
$flags['reload'] = true;
if ($statement->options->has('DATABASE') || $statement->options->has('SCHEMA')) {
if ($statement->options->has('DATABASE')
|| $statement->options->has('SCHEMA')
) {
$flags['drop_database'] = true;
}
} elseif ($statement instanceof ExplainStatement) {
@@ -372,15 +370,13 @@ class Query
$flags['querytype'] = 'SET';
}
if (
($statement instanceof SelectStatement)
if (($statement instanceof SelectStatement)
|| ($statement instanceof UpdateStatement)
|| ($statement instanceof DeleteStatement)
) {
if (! empty($statement->limit)) {
$flags['limit'] = true;
}
if (! empty($statement->order)) {
$flags['order'] = true;
}
@@ -420,20 +416,19 @@ class Query
$ret['statement'] = $statement;
if ($statement instanceof SelectStatement) {
$ret['select_tables'] = [];
$ret['select_expr'] = [];
$ret['select_tables'] = array();
$ret['select_expr'] = array();
// Finding tables' aliases and their associated real names.
$tableAliases = [];
$tableAliases = array();
foreach ($statement->from as $expr) {
if (! isset($expr->table, $expr->alias) || ($expr->table === '') || ($expr->alias === '')) {
continue;
if (isset($expr->table, $expr->alias) && ($expr->table !== '') && ($expr->alias !== '')
) {
$tableAliases[$expr->alias] = array(
$expr->table,
isset($expr->database) ? $expr->database : null
);
}
$tableAliases[$expr->alias] = [
$expr->table,
$expr->database ?? null,
];
}
// Trying to find selected tables only from the select expression.
@@ -444,13 +439,12 @@ class Query
if (isset($tableAliases[$expr->table])) {
$arr = $tableAliases[$expr->table];
} else {
$arr = [
$arr = array(
$expr->table,
isset($expr->database) && ($expr->database !== '') ?
$expr->database : null,
];
(isset($expr->database) && ($expr->database !== '')) ?
$expr->database : null
);
}
if (! in_array($arr, $ret['select_tables'])) {
$ret['select_tables'][] = $arr;
}
@@ -464,20 +458,16 @@ class Query
// extracted from the FROM clause.
if (empty($ret['select_tables'])) {
foreach ($statement->from as $expr) {
if (! isset($expr->table) || ($expr->table === '')) {
continue;
if (isset($expr->table) && ($expr->table !== '')) {
$arr = array(
$expr->table,
(isset($expr->database) && ($expr->database !== '')) ?
$expr->database : null
);
if (! in_array($arr, $ret['select_tables'])) {
$ret['select_tables'][] = $arr;
}
}
$arr = [
$expr->table,
isset($expr->database) && ($expr->database !== '') ?
$expr->database : null,
];
if (in_array($arr, $ret['select_tables'])) {
continue;
}
$ret['select_tables'][] = $arr;
}
}
}
@@ -494,22 +484,27 @@ class Query
*/
public static function getTables($statement)
{
$expressions = [];
$expressions = array();
if (($statement instanceof InsertStatement) || ($statement instanceof ReplaceStatement)) {
$expressions = [$statement->into->dest];
if (($statement instanceof InsertStatement)
|| ($statement instanceof ReplaceStatement)
) {
$expressions = array($statement->into->dest);
} elseif ($statement instanceof UpdateStatement) {
$expressions = $statement->tables;
} elseif (($statement instanceof SelectStatement) || ($statement instanceof DeleteStatement)) {
} elseif (($statement instanceof SelectStatement)
|| ($statement instanceof DeleteStatement)
) {
$expressions = $statement->from;
} elseif (($statement instanceof AlterStatement) || ($statement instanceof TruncateStatement)) {
$expressions = [$statement->table];
} elseif (($statement instanceof AlterStatement)
|| ($statement instanceof TruncateStatement)
) {
$expressions = array($statement->table);
} elseif ($statement instanceof DropStatement) {
if (! $statement->options->has('TABLE')) {
// No tables are dropped.
return [];
return array();
}
$expressions = $statement->fields;
} elseif ($statement instanceof RenameStatement) {
foreach ($statement->renames as $rename) {
@@ -517,15 +512,13 @@ class Query
}
}
$ret = [];
$ret = array();
foreach ($expressions as $expr) {
if (empty($expr->table)) {
continue;
if (! empty($expr->table)) {
$expr->expr = null; // Force rebuild.
$expr->alias = null; // Aliases are not required.
$ret[] = Expression::build($expr);
}
$expr->expr = null; // Force rebuild.
$expr->alias = null; // Aliases are not required.
$ret[] = Expression::build($expr);
}
return $ret;
@@ -598,7 +591,7 @@ class Query
*
* @var int
*/
$clauseIdx = $clauses[$clauseType] ?? -1;
$clauseIdx = isset($clauses[$clauseType]) ? $clauses[$clauseType] : -1;
$firstClauseIdx = $clauseIdx;
$lastClauseIdx = $clauseIdx;
@@ -642,8 +635,7 @@ class Query
if ($brackets === 0) {
// Checking if the section was changed.
if (
($token->type === Token::TYPE_KEYWORD)
if (($token->type === Token::TYPE_KEYWORD)
&& isset($clauses[$token->keyword])
&& ($clauses[$token->keyword] >= $currIdx)
) {
@@ -656,11 +648,9 @@ class Query
}
}
if (($firstClauseIdx > $currIdx) || ($currIdx > $lastClauseIdx)) {
continue;
if (($firstClauseIdx <= $currIdx) && ($currIdx <= $lastClauseIdx)) {
$ret .= $token->token;
}
$ret .= $token->token;
}
return trim($ret);
@@ -708,7 +698,7 @@ class Query
* @param Statement $statement the parsed query that has to be modified
* @param TokensList $list the list of tokens
* @param array $ops Clauses to be replaced. Contains multiple
* arrays having two values: [$old, $new].
* arrays having two values: array($old, $new).
* Clauses must be sorted.
*
* @return string
@@ -731,7 +721,12 @@ class Query
// If there is only one clause, `replaceClause()` should be used.
if ($count === 1) {
return static::replaceClause($statement, $list, $ops[0][0], $ops[0][1]);
return static::replaceClause(
$statement,
$list,
$ops[0][0],
$ops[0][1]
);
}
// Adding everything before first replacement.
@@ -742,15 +737,15 @@ class Query
$ret .= $clause[1] . ' ';
// Adding everything between this and next replacement.
if ($i + 1 === $count) {
continue;
if ($i + 1 !== $count) {
$ret .= static::getClause($statement, $list, $clause[0], $ops[$i + 1][0]) . ' ';
}
$ret .= static::getClause($statement, $list, $clause[0], $ops[$i + 1][0]) . ' ';
}
// Adding everything after the last replacement.
return $ret . static::getClause($statement, $list, $ops[$count - 1][0], 1);
$ret .= static::getClause($statement, $list, $ops[$count - 1][0], 1);
return $ret;
}
/**
@@ -801,11 +796,11 @@ class Query
// No statement was found so we return the entire query as being the
// remaining part.
if (! $fullStatement) {
return [
return array(
null,
$query,
$delimiter,
];
$delimiter
);
}
// At least one query was found so we have to build the rest of the
@@ -815,11 +810,11 @@ class Query
$query .= $list->tokens[$list->idx]->token;
}
return [
return array(
trim($statement),
$query,
$delimiter,
];
$delimiter
);
}
/**
@@ -863,20 +858,15 @@ class Query
}
}
if ($brackets !== 0) {
continue;
}
if (
($token->type === Token::TYPE_KEYWORD)
&& isset($clauses[$token->keyword])
&& ($clause === $token->keyword)
) {
return $i;
}
if ($token->keyword === 'UNION') {
return -1;
if ($brackets === 0) {
if (($token->type === Token::TYPE_KEYWORD)
&& isset($clauses[$token->keyword])
&& ($clause === $token->keyword)
) {
return $i;
} elseif ($token->keyword === 'UNION') {
return -1;
}
}
}
@@ -1,10 +1,9 @@
<?php
/**
* Routine utilities.
*/
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Utils;
use PhpMyAdmin\SqlParser\Components\DataType;
@@ -13,11 +12,12 @@ use PhpMyAdmin\SqlParser\Lexer;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Statements\CreateStatement;
use function implode;
use function is_string;
/**
* Routine utilities.
*
* @category Routines
*
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
*/
class Routine
{
@@ -36,27 +36,27 @@ class Routine
$type = DataType::parse(new Parser(), $lexer->list);
if ($type === null) {
return [
return array(
'',
'',
'',
'',
'',
];
''
);
}
$options = [];
$options = array();
foreach ($type->options->options as $opt) {
$options[] = is_string($opt) ? $opt : $opt['value'];
}
return [
return array(
'',
'',
$type->name,
implode(',', $type->parameters),
implode(' ', $options),
];
implode(' ', $options)
);
}
/**
@@ -74,29 +74,29 @@ class Routine
$param = ParameterDefinition::parse(new Parser(), $lexer->list);
if (empty($param[0])) {
return [
return array(
'',
'',
'',
'',
'',
];
''
);
}
$param = $param[0];
$options = [];
$options = array();
foreach ($param->type->options->options as $opt) {
$options[] = is_string($opt) ? $opt : $opt['value'];
}
return [
return array(
empty($param->inOut) ? '' : $param->inOut,
$param->name,
$param->type->name,
implode(',', $param->type->parameters),
implode(' ', $options),
];
implode(' ', $options)
);
}
/**
@@ -108,15 +108,15 @@ class Routine
*/
public static function getParameters($statement)
{
$retval = [
$retval = array(
'num' => 0,
'dir' => [],
'name' => [],
'type' => [],
'length' => [],
'length_arr' => [],
'opts' => [],
];
'dir' => array(),
'name' => array(),
'type' => array(),
'length' => array(),
'length_arr' => array(),
'opts' => array()
);
if (! empty($statement->parameters)) {
$idx = 0;
@@ -126,12 +126,11 @@ class Routine
$retval['type'][$idx] = $param->type->name;
$retval['length'][$idx] = implode(',', $param->type->parameters);
$retval['length_arr'][$idx] = $param->type->parameters;
$retval['opts'][$idx] = [];
$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;
}
@@ -1,19 +1,19 @@
<?php
/**
* Table utilities.
*/
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Utils;
use PhpMyAdmin\SqlParser\Statements\CreateStatement;
use function is_array;
use function str_replace;
/**
* Table utilities.
*
* @category Statement
*
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
*/
class Table
{
@@ -26,47 +26,49 @@ class Table
*/
public static function getForeignKeys($statement)
{
if (empty($statement->fields) || (! is_array($statement->fields)) || (! $statement->options->has('TABLE'))) {
return [];
if (empty($statement->fields)
|| (! is_array($statement->fields))
|| (! $statement->options->has('TABLE'))
) {
return array();
}
$ret = [];
$ret = array();
foreach ($statement->fields as $field) {
if (empty($field->key) || ($field->key->type !== 'FOREIGN KEY')) {
continue;
}
$columns = [];
$columns = array();
foreach ($field->key->columns as $column) {
if (! isset($column['name'])) {
continue;
}
$columns[] = $column['name'];
}
$tmp = [
$tmp = array(
'constraint' => $field->name,
'index_list' => $columns,
];
'index_list' => $columns
);
if (! empty($field->references)) {
$tmp['ref_db_name'] = $field->references->table->database;
$tmp['ref_table_name'] = $field->references->table->table;
$tmp['ref_index_list'] = $field->references->columns;
$opt = $field->references->options->has('ON UPDATE');
if ($opt) {
if ($opt = $field->references->options->has('ON UPDATE')) {
$tmp['on_update'] = str_replace(' ', '_', $opt);
}
$opt = $field->references->options->has('ON DELETE');
if ($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;
@@ -84,11 +86,14 @@ class Table
*/
public static function getFields($statement)
{
if (empty($statement->fields) || (! is_array($statement->fields)) || (! $statement->options->has('TABLE'))) {
return [];
if (empty($statement->fields)
|| (! is_array($statement->fields))
|| (! $statement->options->has('TABLE'))
) {
return array();
}
$ret = [];
$ret = array();
foreach ($statement->fields as $field) {
// Skipping keys.
@@ -96,44 +101,36 @@ class Table
continue;
}
$ret[$field->name] = [
$ret[$field->name] = array(
'type' => $field->type->name,
'timestamp_not_null' => false,
];
'timestamp_not_null' => false
);
if (! $field->options) {
continue;
}
if ($field->options) {
if ($field->type->name === 'TIMESTAMP') {
if ($field->options->has('NOT NULL')) {
$ret[$field->name]['timestamp_not_null'] = true;
}
}
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;
}
}
if ($option = $field->options->has('AS')) {
$ret[$field->name]['generated'] = true;
$ret[$field->name]['expr'] = $option;
}
}
$option = $field->options->has('DEFAULT');
if ($option) {
$ret[$field->name]['default_value'] = $option;
if ($option === 'CURRENT_TIMESTAMP') {
$ret[$field->name]['default_current_timestamp'] = true;
}
}
$option = $field->options->has('ON UPDATE');
if ($option === 'CURRENT_TIMESTAMP') {
$ret[$field->name]['on_update_current_timestamp'] = true;
}
$option = $field->options->has('AS');
if (! $option) {
continue;
}
$ret[$field->name]['generated'] = true;
$ret[$field->name]['expr'] = $option;
}
return $ret;
@@ -1,22 +1,21 @@
<?php
/**
* Token utilities.
*/
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Utils;
use PhpMyAdmin\SqlParser\Lexer;
use PhpMyAdmin\SqlParser\Token;
use PhpMyAdmin\SqlParser\TokensList;
use PhpMyAdmin\SqlParser\UtfString;
use function count;
use function strcasecmp;
/**
* Token utilities.
*
* @category Token
*
* @license https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
*/
class Tokens
{
@@ -31,36 +30,42 @@ class Tokens
public static function match(Token $token, array $pattern)
{
// Token.
if (isset($pattern['token']) && ($pattern['token'] !== $token->token)) {
if (isset($pattern['token'])
&& ($pattern['token'] !== $token->token)
) {
return false;
}
// Value.
if (isset($pattern['value']) && ($pattern['value'] !== $token->value)) {
if (isset($pattern['value'])
&& ($pattern['value'] !== $token->value)
) {
return false;
}
if (isset($pattern['value_str']) && strcasecmp($pattern['value_str'], (string) $token->value)) {
if (isset($pattern['value_str'])
&& strcasecmp($pattern['value_str'], $token->value)
) {
return false;
}
// Type.
if (isset($pattern['type']) && ($pattern['type'] !== $token->type)) {
if (isset($pattern['type'])
&& ($pattern['type'] !== $token->type)
) {
return false;
}
// Flags.
return ! isset($pattern['flags'])
|| (! (($pattern['flags'] & $token->flags) === 0));
if (isset($pattern['flags'])
&& (($pattern['flags'] & $token->flags) === 0)
) {
return false;
}
return true;
}
/**
* @param TokensList|string|UtfString $list
* @param array $find
* @param array $replace
*
* @return TokensList
*/
public static function replaceTokens($list, array $find, array $replace)
{
/**
@@ -80,7 +85,7 @@ class Tokens
*
* @var array
*/
$newList = [];
$newList = array();
/**
* The length of the find pattern is calculated only once.