* Support php 5.3 for sql parser lib.
This commit is contained in:
@@ -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
@@ -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;
|
||||
|
||||
+15
-19
@@ -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]
|
||||
);
|
||||
}
|
||||
|
||||
+103
-140
@@ -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' ? ' ' : ' ';
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
+52
-55
@@ -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;
|
||||
|
||||
+25
-20
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user