Commit version 24.12.13800

This commit is contained in:
2025-01-06 17:35:06 -05:00
parent b7f6a79c2c
commit 55d9218816
6133 changed files with 4239740 additions and 1374287 deletions

View File

@ -5,11 +5,12 @@ declare(strict_types=1);
namespace Doctrine\SqlFormatter;
use function sprintf;
use const PHP_EOL;
final class CliHighlighter implements Highlighter
{
const HIGHLIGHT_FUNCTIONS = 'functions';
public const HIGHLIGHT_FUNCTIONS = 'functions';
/** @var array<string, string> */
private $escapeSequences;
@ -33,9 +34,9 @@ final class CliHighlighter implements Highlighter
];
}
public function highlightToken(int $type, string $value) : string
public function highlightToken(int $type, string $value): string
{
if ($type === Token::TOKEN_TYPE_BOUNDARY && ($value==='(' || $value===')')) {
if ($type === Token::TOKEN_TYPE_BOUNDARY && ($value === '(' || $value === ')')) {
return $value;
}
@ -47,7 +48,7 @@ final class CliHighlighter implements Highlighter
return $prefix . $value . "\x1b[0m";
}
private function prefix(int $type)
private function prefix(int $type): ?string
{
if (! isset(self::TOKEN_TYPE_TO_HIGHLIGHT[$type])) {
return null;
@ -56,7 +57,7 @@ final class CliHighlighter implements Highlighter
return $this->escapeSequences[self::TOKEN_TYPE_TO_HIGHLIGHT[$type]];
}
public function highlightError(string $value) : string
public function highlightError(string $value): string
{
return sprintf(
'%s%s%s%s',
@ -67,12 +68,12 @@ final class CliHighlighter implements Highlighter
);
}
public function highlightErrorMessage(string $value) : string
public function highlightErrorMessage(string $value): string
{
return $this->highlightError($value);
}
public function output(string $string) : string
public function output(string $string): string
{
return $string . "\n";
}

View File

@ -20,7 +20,7 @@ final class Cursor
$this->tokens = $tokens;
}
public function next(int $exceptTokenType = null)
public function next(?int $exceptTokenType = null): ?Token
{
while ($token = $this->tokens[++$this->position] ?? null) {
if ($exceptTokenType !== null && $token->isOfType($exceptTokenType)) {
@ -33,7 +33,7 @@ final class Cursor
return null;
}
public function previous(int $exceptTokenType = null)
public function previous(?int $exceptTokenType = null): ?Token
{
while ($token = $this->tokens[--$this->position] ?? null) {
if ($exceptTokenType !== null && $token->isOfType($exceptTokenType)) {
@ -46,7 +46,7 @@ final class Cursor
return null;
}
public function subCursor() : self
public function subCursor(): self
{
$cursor = new self($this->tokens);
$cursor->position = $this->position;

View File

@ -6,7 +6,7 @@ namespace Doctrine\SqlFormatter;
interface Highlighter
{
const TOKEN_TYPE_TO_HIGHLIGHT = [
public const TOKEN_TYPE_TO_HIGHLIGHT = [
Token::TOKEN_TYPE_BOUNDARY => self::HIGHLIGHT_BOUNDARY,
Token::TOKEN_TYPE_WORD => self::HIGHLIGHT_WORD,
Token::TOKEN_TYPE_BACKTICK_QUOTE => self::HIGHLIGHT_BACKTICK_QUOTE,
@ -20,30 +20,30 @@ interface Highlighter
Token::TOKEN_TYPE_BLOCK_COMMENT => self::HIGHLIGHT_COMMENT,
];
const HIGHLIGHT_BOUNDARY = 'boundary';
const HIGHLIGHT_WORD = 'word';
const HIGHLIGHT_BACKTICK_QUOTE = 'backtickQuote';
const HIGHLIGHT_QUOTE = 'quote';
const HIGHLIGHT_RESERVED = 'reserved';
const HIGHLIGHT_NUMBER = 'number';
const HIGHLIGHT_VARIABLE = 'variable';
const HIGHLIGHT_COMMENT = 'comment';
const HIGHLIGHT_ERROR = 'error';
public const HIGHLIGHT_BOUNDARY = 'boundary';
public const HIGHLIGHT_WORD = 'word';
public const HIGHLIGHT_BACKTICK_QUOTE = 'backtickQuote';
public const HIGHLIGHT_QUOTE = 'quote';
public const HIGHLIGHT_RESERVED = 'reserved';
public const HIGHLIGHT_NUMBER = 'number';
public const HIGHLIGHT_VARIABLE = 'variable';
public const HIGHLIGHT_COMMENT = 'comment';
public const HIGHLIGHT_ERROR = 'error';
/**
* Highlights a token depending on its type.
*/
public function highlightToken(int $type, string $value) : string;
public function highlightToken(int $type, string $value): string;
/**
* Highlights a token which causes an issue
*/
public function highlightError(string $value) : string;
public function highlightError(string $value): string;
/**
* Highlights an error message
*/
public function highlightErrorMessage(string $value) : string;
public function highlightErrorMessage(string $value): string;
/**
* Helper function for building string output
@ -52,5 +52,5 @@ interface Highlighter
*
* @return string The quoted string
*/
public function output(string $string) : string;
public function output(string $string): string;
}

View File

@ -7,13 +7,14 @@ namespace Doctrine\SqlFormatter;
use function htmlentities;
use function sprintf;
use function trim;
use const ENT_COMPAT;
use const ENT_IGNORE;
use const PHP_EOL;
final class HtmlHighlighter implements Highlighter
{
const HIGHLIGHT_PRE = 'pre';
public const HIGHLIGHT_PRE = 'pre';
/**
* This flag tells us if queries need to be enclosed in <pre> tags
@ -45,11 +46,11 @@ final class HtmlHighlighter implements Highlighter
$this->usePre = $usePre;
}
public function highlightToken(int $type, string $value) : string
public function highlightToken(int $type, string $value): string
{
$value = htmlentities($value, ENT_COMPAT | ENT_IGNORE, 'UTF-8');
if ($type === Token::TOKEN_TYPE_BOUNDARY && ($value==='(' || $value===')')) {
if ($type === Token::TOKEN_TYPE_BOUNDARY && ($value === '(' || $value === ')')) {
return $value;
}
@ -61,7 +62,7 @@ final class HtmlHighlighter implements Highlighter
return '<span ' . $attributes . '>' . $value . '</span>';
}
public function attributes(int $type)
public function attributes(int $type): ?string
{
if (! isset(self::TOKEN_TYPE_TO_HIGHLIGHT[$type])) {
return null;
@ -70,7 +71,7 @@ final class HtmlHighlighter implements Highlighter
return $this->htmlAttributes[self::TOKEN_TYPE_TO_HIGHLIGHT[$type]];
}
public function highlightError(string $value) : string
public function highlightError(string $value): string
{
return sprintf(
'%s<span %s>%s</span>',
@ -80,16 +81,16 @@ final class HtmlHighlighter implements Highlighter
);
}
public function highlightErrorMessage(string $value) : string
public function highlightErrorMessage(string $value): string
{
return $this->highlightError($value);
}
public function output(string $string) : string
public function output(string $string): string
{
$string =trim($string);
$string = trim($string);
// This is derp truncate for long list
// Added by Observium Developers. IN list truncated for a long list
$string = preg_replace('!(IN</span>\s*)(\()([^\)]+)(\))!', '$1$2<div class="text-truncate" onclick="revealHiddenOverflow(this)">$3</div>$4', $string);
if (! $this->usePre) {

View File

@ -6,22 +6,22 @@ namespace Doctrine\SqlFormatter;
final class NullHighlighter implements Highlighter
{
public function highlightToken(int $type, string $value) : string
public function highlightToken(int $type, string $value): string
{
return $value;
}
public function highlightError(string $value) : string
public function highlightError(string $value): string
{
return $value;
}
public function highlightErrorMessage(string $value) : string
public function highlightErrorMessage(string $value): string
{
return ' ' . $value;
}
public function output(string $string) : string
public function output(string $string): string
{
return $string;
}

View File

@ -23,6 +23,7 @@ use function str_repeat;
use function str_replace;
use function strlen;
use function trim;
use const PHP_SAPI;
final class SqlFormatter
@ -33,7 +34,7 @@ final class SqlFormatter
/** @var Tokenizer */
private $tokenizer;
public function __construct(Highlighter $highlighter = null)
public function __construct(?Highlighter $highlighter = null)
{
$this->tokenizer = new Tokenizer();
$this->highlighter = $highlighter ?? (PHP_SAPI === 'cli' ? new CliHighlighter() : new HtmlHighlighter());
@ -46,7 +47,7 @@ final class SqlFormatter
*
* @return string The SQL string with HTML styles and formatting wrapped in a <pre> tag
*/
public function format(string $string, string $indentString = ' ') : string
public function format(string $string, string $indentString = ' '): string
{
// This variable will be populated with formatted html
$return = '';
@ -148,7 +149,7 @@ final class SqlFormatter
// Allow up to 3 non-whitespace tokens inside inline parentheses
$length = 0;
$subCursor = $cursor->subCursor();
for ($j=1; $j<=250; $j++) {
for ($j = 1; $j <= 250; $j++) {
// Reached end of string
$next = $subCursor->next(Token::TOKEN_TYPE_WHITESPACE);
if (! $next) {
@ -164,17 +165,19 @@ final class SqlFormatter
}
// Reached an invalid token for inline parentheses
if ($next->value()===';' || $next->value()==='(') {
if ($next->value() === ';' || $next->value() === '(') {
break;
}
// Reached an invalid token type for inline parentheses
if ($next->isOfType(
Token::TOKEN_TYPE_RESERVED_TOPLEVEL,
Token::TOKEN_TYPE_RESERVED_NEWLINE,
Token::TOKEN_TYPE_COMMENT,
Token::TOKEN_TYPE_BLOCK_COMMENT
)) {
if (
$next->isOfType(
Token::TOKEN_TYPE_RESERVED_TOPLEVEL,
Token::TOKEN_TYPE_RESERVED_NEWLINE,
Token::TOKEN_TYPE_COMMENT,
Token::TOKEN_TYPE_BLOCK_COMMENT
)
) {
break;
}
@ -206,8 +209,8 @@ final class SqlFormatter
$indentLevel--;
// Reset indent level
while ($j=array_shift($indentTypes)) {
if ($j!=='special') {
while ($j = array_shift($indentTypes)) {
if ($j !== 'special') {
break;
}
@ -232,7 +235,7 @@ final class SqlFormatter
// If the last indent type was 'special', decrease the special indent for this round
reset($indentTypes);
if (current($indentTypes)==='special') {
if (current($indentTypes) === 'special') {
$indentLevel--;
array_shift($indentTypes);
}
@ -256,9 +259,11 @@ final class SqlFormatter
if ($token->value() === 'LIMIT' && ! $inlineParentheses) {
$clauseLimit = true;
}
} elseif ($clauseLimit &&
} elseif (
$clauseLimit &&
$token->value() !== ',' &&
! $token->isOfType(Token::TOKEN_TYPE_NUMBER, Token::TOKEN_TYPE_WHITESPACE)) {
! $token->isOfType(Token::TOKEN_TYPE_NUMBER, Token::TOKEN_TYPE_WHITESPACE)
) {
// Checks if we are out of the limit clause
$clauseLimit = false;
} elseif ($token->value() === ',' && ! $inlineParentheses) {
@ -294,9 +299,11 @@ final class SqlFormatter
}
// If the token shouldn't have a space before it
if ($token->value() === '.' ||
if (
$token->value() === '.' ||
$token->value() === ',' ||
$token->value() === ';') {
$token->value() === ';'
) {
$return = rtrim($return, ' ');
}
@ -322,12 +329,14 @@ final class SqlFormatter
continue;
}
if ($prev->isOfType(
Token::TOKEN_TYPE_QUOTE,
Token::TOKEN_TYPE_BACKTICK_QUOTE,
Token::TOKEN_TYPE_WORD,
Token::TOKEN_TYPE_NUMBER
)) {
if (
$prev->isOfType(
Token::TOKEN_TYPE_QUOTE,
Token::TOKEN_TYPE_BACKTICK_QUOTE,
Token::TOKEN_TYPE_WORD,
Token::TOKEN_TYPE_NUMBER
)
) {
continue;
}
@ -355,7 +364,7 @@ final class SqlFormatter
*
* @return string The SQL string with HTML styles applied
*/
public function highlight(string $string) : string
public function highlight(string $string): string
{
$cursor = $this->tokenizer->tokenize($string);
@ -378,7 +387,7 @@ final class SqlFormatter
*
* @return string The SQL string without comments
*/
public function compress(string $string) : string
public function compress(string $string): string
{
$result = '';
$cursor = $this->tokenizer->tokenize($string);
@ -392,11 +401,13 @@ final class SqlFormatter
// Remove extra whitespace in reserved words (e.g "OUTER JOIN" becomes "OUTER JOIN")
if ($token->isOfType(
Token::TOKEN_TYPE_RESERVED,
Token::TOKEN_TYPE_RESERVED_NEWLINE,
Token::TOKEN_TYPE_RESERVED_TOPLEVEL
)) {
if (
$token->isOfType(
Token::TOKEN_TYPE_RESERVED,
Token::TOKEN_TYPE_RESERVED_NEWLINE,
Token::TOKEN_TYPE_RESERVED_TOPLEVEL
)
) {
$newValue = preg_replace('/\s+/', ' ', $token->value());
assert($newValue !== null);
$token = $token->withValue($newValue);

View File

@ -10,23 +10,23 @@ use function strpos;
final class Token
{
// Constants for token types
const TOKEN_TYPE_WHITESPACE = 0;
const TOKEN_TYPE_WORD = 1;
const TOKEN_TYPE_QUOTE = 2;
const TOKEN_TYPE_BACKTICK_QUOTE = 3;
const TOKEN_TYPE_RESERVED = 4;
const TOKEN_TYPE_RESERVED_TOPLEVEL = 5;
const TOKEN_TYPE_RESERVED_NEWLINE = 6;
const TOKEN_TYPE_BOUNDARY = 7;
const TOKEN_TYPE_COMMENT = 8;
const TOKEN_TYPE_BLOCK_COMMENT = 9;
const TOKEN_TYPE_NUMBER = 10;
const TOKEN_TYPE_ERROR = 11;
const TOKEN_TYPE_VARIABLE = 12;
public const TOKEN_TYPE_WHITESPACE = 0;
public const TOKEN_TYPE_WORD = 1;
public const TOKEN_TYPE_QUOTE = 2;
public const TOKEN_TYPE_BACKTICK_QUOTE = 3;
public const TOKEN_TYPE_RESERVED = 4;
public const TOKEN_TYPE_RESERVED_TOPLEVEL = 5;
public const TOKEN_TYPE_RESERVED_NEWLINE = 6;
public const TOKEN_TYPE_BOUNDARY = 7;
public const TOKEN_TYPE_COMMENT = 8;
public const TOKEN_TYPE_BLOCK_COMMENT = 9;
public const TOKEN_TYPE_NUMBER = 10;
public const TOKEN_TYPE_ERROR = 11;
public const TOKEN_TYPE_VARIABLE = 12;
// Constants for different components of a token
const TOKEN_TYPE = 0;
const TOKEN_VALUE = 1;
public const TOKEN_TYPE = 0;
public const TOKEN_VALUE = 1;
/** @var int */
private $type;
@ -40,29 +40,29 @@ final class Token
$this->value = $value;
}
public function value() : string
public function value(): string
{
return $this->value;
}
public function type() : int
public function type(): int
{
return $this->type;
}
public function isOfType(int ...$types) : bool
public function isOfType(int ...$types): bool
{
return in_array($this->type, $types, true);
}
public function hasExtraWhitespace() : bool
public function hasExtraWhitespace(): bool
{
return strpos($this->value(), ' ')!== false ||
return strpos($this->value(), ' ') !== false ||
strpos($this->value(), "\n") !== false ||
strpos($this->value(), "\t") !== false;
}
public function withValue(string $value) : self
public function withValue(string $value): self
{
return new self($this->type(), $value);
}

View File

@ -70,6 +70,7 @@ final class Tokenizer
'CONVERT',
'CREATE',
'CROSS',
'CURRENT ROW',
'CURRENT_TIMESTAMP',
'DATABASE',
'DATABASES',
@ -108,11 +109,13 @@ final class Tokenizer
'FAST',
'FIELDS',
'FILE',
'FILTER',
'FIRST',
'FIXED',
'FLUSH',
'FOR',
'FORCE',
'FOLLOWING',
'FOREIGN',
'FULL',
'FULLTEXT',
@ -120,7 +123,8 @@ final class Tokenizer
'GLOBAL',
'GRANT',
'GRANTS',
'GROUP_CONCAT',
'GROUP',
'GROUPS',
'HEAP',
'HIGH_PRIORITY',
'HOSTS',
@ -180,6 +184,7 @@ final class Tokenizer
'MYISAM',
'NAMES',
'NATURAL',
'NO OTHERS',
'NOT',
'NOW()',
'NULL',
@ -192,12 +197,14 @@ final class Tokenizer
'ON UPDATE',
'ON DELETE',
'OUTFILE',
'OVER',
'PACK_KEYS',
'PAGE',
'PARTIAL',
'PARTITION',
'PARTITIONS',
'PASSWORD',
'PRECEDING',
'PRIMARY',
'PRIVILEGES',
'PROCEDURE',
@ -213,6 +220,7 @@ final class Tokenizer
'READ',
'READ_ONLY',
'READ_WRITE',
'RECURSIVE',
'REFERENCES',
'REGEXP',
'RELOAD',
@ -277,6 +285,7 @@ final class Tokenizer
'TEMPORARY',
'TERMINATED',
'THEN',
'TIES',
'TO',
'TRAILING',
'TRANSACTIONAL',
@ -284,6 +293,7 @@ final class Tokenizer
'TRUNCATE',
'TYPE',
'TYPES',
'UNBOUNDED',
'UNCOMMITTED',
'UNIQUE',
'UNLOCK',
@ -307,6 +317,7 @@ final class Tokenizer
* @var string[]
*/
private $reservedToplevel = [
'WITH',
'SELECT',
'FROM',
'WHERE',
@ -327,6 +338,11 @@ final class Tokenizer
'UNION',
'EXCEPT',
'INTERSECT',
'PARTITION BY',
'ROWS',
'RANGE',
'GROUPS',
'WINDOW',
];
/** @var string[] */
@ -341,6 +357,7 @@ final class Tokenizer
'XOR',
'OR',
'AND',
'EXCLUDE',
];
/** @var string[] */
@ -351,6 +368,7 @@ final class Tokenizer
'ADDTIME',
'AES_DECRYPT',
'AES_ENCRYPT',
'APPROX_COUNT_DISTINCT',
'AREA',
'ASBINARY',
'ASCII',
@ -380,6 +398,7 @@ final class Tokenizer
'CHARACTER_LENGTH',
'CHARSET',
'CHAR_LENGTH',
'CHECKSUM_AGG',
'COALESCE',
'COERCIBILITY',
'COLLATION',
@ -395,8 +414,10 @@ final class Tokenizer
'COS',
'COT',
'COUNT',
'COUNT_BIG',
'CRC32',
'CROSSES',
'CUME_DIST',
'CURDATE',
'CURRENT_DATE',
'CURRENT_TIME',
@ -418,6 +439,7 @@ final class Tokenizer
'DECODE',
'DEFAULT',
'DEGREES',
'DENSE_RANK',
'DES_DECRYPT',
'DES_ENCRYPT',
'DIFFERENCE',
@ -437,6 +459,7 @@ final class Tokenizer
'EXTRACTVALUE',
'FIELD',
'FIND_IN_SET',
'FIRST_VALUE',
'FLOOR',
'FORMAT',
'FOUND_ROWS',
@ -457,6 +480,8 @@ final class Tokenizer
'GET_LOCK',
'GLENGTH',
'GREATEST',
'GROUPING',
'GROUPING_ID',
'GROUP_CONCAT',
'GROUP_UNIQUE_USERS',
'HEX',
@ -478,9 +503,12 @@ final class Tokenizer
'ISSIMPLE',
'IS_FREE_LOCK',
'IS_USED_LOCK',
'LAG',
'LAST_DAY',
'LAST_INSERT_ID',
'LAST_VALUE',
'LCASE',
'LEAD',
'LEAST',
'LEFT',
'LENGTH',
@ -489,6 +517,7 @@ final class Tokenizer
'LINESTRING',
'LINESTRINGFROMTEXT',
'LINESTRINGFROMWKB',
'LISTAGG',
'LN',
'LOAD_FILE',
'LOCALTIME',
@ -536,6 +565,8 @@ final class Tokenizer
'MULTIPOLYGONFROMTEXT',
'MULTIPOLYGONFROMWKB',
'NAME_CONST',
'NTH_VALUE',
'NTILE',
'NULLIF',
'NUMGEOMETRIES',
'NUMINTERIORRINGS',
@ -546,6 +577,9 @@ final class Tokenizer
'ORD',
'OVERLAPS',
'PASSWORD',
'PERCENT_RANK',
'PERCENTILE_CONT',
'PERCENTILE_DISC',
'PERIOD_ADD',
'PERIOD_DIFF',
'PI',
@ -566,6 +600,7 @@ final class Tokenizer
'QUOTE',
'RADIANS',
'RAND',
'RANK',
'RELATED',
'RELEASE_LOCK',
'REPEAT',
@ -574,6 +609,7 @@ final class Tokenizer
'RIGHT',
'ROUND',
'ROW_COUNT',
'ROW_NUMBER',
'RPAD',
'RTRIM',
'SCHEMA',
@ -591,9 +627,12 @@ final class Tokenizer
'SRID',
'STARTPOINT',
'STD',
'STDEV',
'STDEVP',
'STDDEV',
'STDDEV_POP',
'STDDEV_SAMP',
'STRING_AGG',
'STRCMP',
'STR_TO_DATE',
'SUBDATE',
@ -630,7 +669,9 @@ final class Tokenizer
'UTC_TIME',
'UTC_TIMESTAMP',
'UUID',
'VAR',
'VARIANCE',
'VARP',
'VAR_POP',
'VAR_SAMP',
'VERSION',
@ -669,6 +710,7 @@ final class Tokenizer
private $boundaries = [
',',
';',
'::', // PostgreSQL cast operator
':',
')',
'(',
@ -727,7 +769,7 @@ final class Tokenizer
*
* @param string $string The SQL string
*/
public function tokenize(string $string) : Cursor
public function tokenize(string $string): Cursor
{
$tokens = [];
@ -774,7 +816,7 @@ final class Tokenizer
*
* @return Token An associative array containing the type and value of the token.
*/
private function createNextToken(string $string, Token $previous = null) : Token
private function createNextToken(string $string, ?Token $previous = null): Token
{
$matches = [];
// Whitespace
@ -783,9 +825,11 @@ final class Tokenizer
}
// Comment
if ($string[0] === '#' ||
(isset($string[1]) && ($string[0]==='-' && $string[1]==='-') ||
(isset($string[1]) && $string[0]==='/' && $string[1]==='*'))) {
if (
$string[0] === '#' ||
(isset($string[1]) && (($string[0] === '-' && $string[1] === '-') ||
($string[0] === '/' && $string[1] === '*')))
) {
// Comment until end of line
if ($string[0] === '-' || $string[0] === '#') {
$last = strpos($string, "\n");
@ -805,9 +849,9 @@ final class Tokenizer
}
// Quoted String
if ($string[0]==='"' || $string[0]==='\'' || $string[0]==='`' || $string[0]==='[') {
if ($string[0] === '"' || $string[0] === '\'' || $string[0] === '`' || $string[0] === '[') {
return new Token(
($string[0]==='`' || $string[0]==='['
($string[0] === '`' || $string[0] === '['
? Token::TOKEN_TYPE_BACKTICK_QUOTE
: Token::TOKEN_TYPE_QUOTE),
$this->getQuotedString($string)
@ -820,7 +864,7 @@ final class Tokenizer
$type = Token::TOKEN_TYPE_VARIABLE;
// If the variable name is quoted
if ($string[1]==='"' || $string[1]==='\'' || $string[1]==='`') {
if ($string[1] === '"' || $string[1] === '\'' || $string[1] === '`') {
$value = $string[0] . $this->getQuotedString(substr($string, 1));
} else {
// Non-quoted variable name
@ -836,11 +880,13 @@ final class Tokenizer
}
// Number (decimal, binary, or hex)
if (preg_match(
'/^([0-9]+(\.[0-9]+)?|0x[0-9a-fA-F]+|0b[01]+)($|\s|"\'`|' . $this->regexBoundaries . ')/',
$string,
$matches
)) {
if (
preg_match(
'/^([0-9]+(\.[0-9]+)?|0x[0-9a-fA-F]+|0b[01]+)($|\s|"\'`|' . $this->regexBoundaries . ')/',
$string,
$matches
)
) {
return new Token(Token::TOKEN_TYPE_NUMBER, $matches[1]);
}
@ -854,38 +900,44 @@ final class Tokenizer
if (! $previous || $previous->value() !== '.') {
$upper = strtoupper($string);
// Top Level Reserved Word
if (preg_match(
'/^(' . $this->regexReservedToplevel . ')($|\s|' . $this->regexBoundaries . ')/',
$upper,
$matches
)) {
if (
preg_match(
'/^(' . $this->regexReservedToplevel . ')($|\s|' . $this->regexBoundaries . ')/',
$upper,
$matches
)
) {
return new Token(
Token::TOKEN_TYPE_RESERVED_TOPLEVEL,
substr($string, 0, strlen($matches[1]))
substr($upper, 0, strlen($matches[1]))
);
}
// Newline Reserved Word
if (preg_match(
'/^(' . $this->regexReservedNewline . ')($|\s|' . $this->regexBoundaries . ')/',
$upper,
$matches
)) {
if (
preg_match(
'/^(' . $this->regexReservedNewline . ')($|\s|' . $this->regexBoundaries . ')/',
$upper,
$matches
)
) {
return new Token(
Token::TOKEN_TYPE_RESERVED_NEWLINE,
substr($string, 0, strlen($matches[1]))
substr($upper, 0, strlen($matches[1]))
);
}
// Other Reserved Word
if (preg_match(
'/^(' . $this->regexReserved . ')($|\s|' . $this->regexBoundaries . ')/',
$upper,
$matches
)) {
if (
preg_match(
'/^(' . $this->regexReserved . ')($|\s|' . $this->regexBoundaries . ')/',
$upper,
$matches
)
) {
return new Token(
Token::TOKEN_TYPE_RESERVED,
substr($string, 0, strlen($matches[1]))
substr($upper, 0, strlen($matches[1]))
);
}
}
@ -897,7 +949,7 @@ final class Tokenizer
if (preg_match('/^(' . $this->regexFunction . '[(]|\s|[)])/', $upper, $matches)) {
return new Token(
Token::TOKEN_TYPE_RESERVED,
substr($string, 0, strlen($matches[1])-1)
substr($upper, 0, strlen($matches[1]) - 1)
);
}
@ -914,14 +966,14 @@ final class Tokenizer
*
* @return string[] The quoted strings
*/
private function quoteRegex(array $strings) : array
private function quoteRegex(array $strings): array
{
return array_map(static function (string $string) : string {
return array_map(static function (string $string): string {
return preg_quote($string, '/');
}, $strings);
}
private function getQuotedString(string $string) : string
private function getQuotedString(string $string): string
{
$ret = '';
@ -930,14 +982,16 @@ final class Tokenizer
// 2. square bracket quoted string (SQL Server) using ]] to escape
// 3. double quoted string using "" or \" to escape
// 4. single quoted string using '' or \' to escape
if (preg_match(
'/^(((`[^`]*($|`))+)|
if (
preg_match(
'/^(((`[^`]*($|`))+)|
((\[[^\]]*($|\]))(\][^\]]*($|\]))*)|
(("[^"\\\\]*(?:\\\\.[^"\\\\]*)*("|$))+)|
((\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*(\'|$))+))/sx',
$string,
$matches
)) {
$string,
$matches
)
) {
$ret = $matches[1];
}