diff --git a/libraries/sql-parser/src/Components/AlterOperation.php b/libraries/sql-parser/src/Components/AlterOperation.php
index d704f25ba2..6b81a46235 100644
--- a/libraries/sql-parser/src/Components/AlterOperation.php
+++ b/libraries/sql-parser/src/Components/AlterOperation.php
@@ -108,6 +108,7 @@ class AlterOperation extends Component
/**
* Counts brackets.
+ *
* @var int $brackets
*/
$brackets = 0;
@@ -123,13 +124,15 @@ class AlterOperation extends Component
*
* 2 -------------------------[ , ]-----------------------> 0
*
- * @var int
+ * @var int $state
*/
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
diff --git a/libraries/sql-parser/src/Components/Array2d.php b/libraries/sql-parser/src/Components/Array2d.php
index c53c8be9e6..268dcea9b0 100644
--- a/libraries/sql-parser/src/Components/Array2d.php
+++ b/libraries/sql-parser/src/Components/Array2d.php
@@ -38,7 +38,8 @@ class Array2d extends Component
/**
* The number of values in each set.
- * @var int
+ *
+ * @var int $count
*/
$count = -1;
@@ -47,18 +48,20 @@ class Array2d extends Component
*
* Below are the states of the parser.
*
- * 0 ----------------------[ array ]---------------------> 1
+ * 0 ----------------------[ array ]----------------------> 1
*
* 1 ------------------------[ , ]------------------------> 0
- * 1 -----------------------[ else ]----------------------> -1
+ * 1 -----------------------[ else ]----------------------> (END)
*
- * @var int
+ * @var int $state
*/
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
@@ -118,4 +121,14 @@ class Array2d extends Component
--$list->idx;
return $ret;
}
+
+ /**
+ * @param ArrayObj[] $component The component to be built.
+ *
+ * @return string
+ */
+ public static function build($component)
+ {
+ return ArrayObj::build($component);
+ }
}
diff --git a/libraries/sql-parser/src/Components/ArrayObj.php b/libraries/sql-parser/src/Components/ArrayObj.php
index 8dde51857a..0e0b1830ed 100644
--- a/libraries/sql-parser/src/Components/ArrayObj.php
+++ b/libraries/sql-parser/src/Components/ArrayObj.php
@@ -56,11 +56,11 @@ class ArrayObj extends Component
* @param TokensList $list The list of tokens that are being parsed.
* @param array $options Parameters for parsing.
*
- * @return ArrayObj
+ * @return mixed
*/
public static function parse(Parser $parser, TokensList $list, array $options = array())
{
- $ret = new ArrayObj();
+ $ret = empty($options['type']) ? new ArrayObj() : array();
/**
* The state of the parser.
@@ -72,15 +72,17 @@ class ArrayObj extends Component
* 1 ------------------[ array element ]-----------------> 2
*
* 2 ------------------------[ , ]-----------------------> 1
- * 2 ------------------------[ ) ]-----------------------> -1
+ * 2 ------------------------[ ) ]-----------------------> (END)
*
- * @var int
+ * @var int $state
*/
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
@@ -109,8 +111,16 @@ class ArrayObj extends Component
// Empty array.
break;
}
- $ret->values[] = $token->value;
- $ret->raw[] = $token->token;
+ if (empty($options['type'])) {
+ $ret->values[] = $token->value;
+ $ret->raw[] = $token->token;
+ } else {
+ $ret[] = $options['type']::parse(
+ $parser,
+ $list,
+ empty($options['typeOptions']) ? array() : $options['typeOptions']
+ );
+ }
$state = 2;
} elseif ($state === 2) {
if (($token->type !== Token::TYPE_OPERATOR) || (($token->value !== ',') && ($token->value !== ')'))) {
@@ -133,20 +143,28 @@ class ArrayObj extends Component
}
/**
- * @param ArrayObj $component The component to be built.
+ * @param ArrayObj|ArrayObj[] $component The component to be built.
*
* @return string
*/
public static function build($component)
{
- $values = array();
- if (!empty($component->raw)) {
- $values = $component->raw;
- } else {
- foreach ($component->values as $value) {
- $values[] = $value;
+ if (is_array($component)) {
+ $values = array();
+ foreach ($component as $c) {
+ $values[] = static::build($c);
}
+ return implode(', ', $values);
+ } else {
+ $values = array();
+ if (!empty($component->raw)) {
+ $values = $component->raw;
+ } else {
+ foreach ($component->values as $value) {
+ $values[] = $value;
+ }
+ }
+ return '(' . implode(', ', $values) . ')';
}
- return '(' . implode(', ', $values) . ')';
}
}
diff --git a/libraries/sql-parser/src/Components/Condition.php b/libraries/sql-parser/src/Components/Condition.php
index 46cab2ad1a..1f515dcfd4 100644
--- a/libraries/sql-parser/src/Components/Condition.php
+++ b/libraries/sql-parser/src/Components/Condition.php
@@ -95,6 +95,7 @@ class Condition extends Component
/**
* Counts brackets.
+ *
* @var int $brackets
*/
$brackets = 0;
@@ -104,7 +105,8 @@ class Condition extends Component
* It is required to keep track of them because their structure contains
* the keyword `AND`, which is also an operator that delimits
* expressions.
- * @var bool
+ *
+ * @var bool $betweenBefore
*/
$betweenBefore = false;
@@ -112,6 +114,7 @@ class Condition extends Component
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
diff --git a/libraries/sql-parser/src/Components/CreateDefinition.php b/libraries/sql-parser/src/Components/CreateDefinition.php
index 4dfbb7ae11..5671801a35 100644
--- a/libraries/sql-parser/src/Components/CreateDefinition.php
+++ b/libraries/sql-parser/src/Components/CreateDefinition.php
@@ -173,13 +173,15 @@ class CreateDefinition extends Component
* 5 ------------------------[ , ]-----------------------> 1
* 5 ------------------------[ ) ]-----------------------> 6 (-1)
*
- * @var int
+ * @var int $state
*/
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
diff --git a/libraries/sql-parser/src/Components/DataType.php b/libraries/sql-parser/src/Components/DataType.php
index 99c3918ebe..48ce5b702b 100644
--- a/libraries/sql-parser/src/Components/DataType.php
+++ b/libraries/sql-parser/src/Components/DataType.php
@@ -103,13 +103,15 @@ class DataType extends Component
*
* 1 ----------------[ size and options ]----------------> 2
*
- * @var int
+ * @var int $state
*/
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
diff --git a/libraries/sql-parser/src/Components/Expression.php b/libraries/sql-parser/src/Components/Expression.php
index 60f85544ba..11e713217e 100644
--- a/libraries/sql-parser/src/Components/Expression.php
+++ b/libraries/sql-parser/src/Components/Expression.php
@@ -122,24 +122,28 @@ class Expression extends Component
/**
* Whether current tokens make an expression or a table reference.
+ *
* @var bool $isExpr
*/
$isExpr = false;
/**
* Whether a period was previously found.
+ *
* @var bool $dot
*/
$dot = false;
/**
* Whether an alias is expected. Is 2 if `AS` keyword was found.
+ *
* @var int $alias
*/
$alias = 0;
/**
* Counts brackets.
+ *
* @var int $brackets
*/
$brackets = 0;
@@ -150,13 +154,16 @@ class Expression extends Component
* string, if function was previously found;
* true, if opening bracket was previously found;
* null, in any other case.
+ *
* @var string|bool $prev
*/
$prev = null;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
diff --git a/libraries/sql-parser/src/Components/ExpressionArray.php b/libraries/sql-parser/src/Components/ExpressionArray.php
index 309972a2c4..82e67c9ffc 100644
--- a/libraries/sql-parser/src/Components/ExpressionArray.php
+++ b/libraries/sql-parser/src/Components/ExpressionArray.php
@@ -44,15 +44,17 @@ class ExpressionArray extends Component
* 0 ----------------------[ array ]---------------------> 1
*
* 1 ------------------------[ , ]------------------------> 0
- * 1 -----------------------[ else ]----------------------> -1
+ * 1 -----------------------[ else ]----------------------> (END)
*
- * @var int
+ * @var int $state
*/
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
diff --git a/libraries/sql-parser/src/Components/FunctionCall.php b/libraries/sql-parser/src/Components/FunctionCall.php
index b86eeb8513..43eb082ea9 100644
--- a/libraries/sql-parser/src/Components/FunctionCall.php
+++ b/libraries/sql-parser/src/Components/FunctionCall.php
@@ -73,15 +73,17 @@ class FunctionCall extends Component
*
* 0 ----------------------[ name ]-----------------------> 1
*
- * 1 --------------------[ parameters ]-------------------> -1
+ * 1 --------------------[ parameters ]-------------------> (END)
*
- * @var int
+ * @var int $state
*/
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
diff --git a/libraries/sql-parser/src/Components/IntoKeyword.php b/libraries/sql-parser/src/Components/IntoKeyword.php
index cb2548110c..7a91064b31 100644
--- a/libraries/sql-parser/src/Components/IntoKeyword.php
+++ b/libraries/sql-parser/src/Components/IntoKeyword.php
@@ -65,17 +65,19 @@ class IntoKeyword extends Component
* 0 -----------------------[ name ]----------------------> 1
* 0 ---------------------[ OUTFILE ]---------------------> 2
*
- * 1 ------------------------[ ( ]------------------------> -1
+ * 1 ------------------------[ ( ]------------------------> (END)
*
* 2 ---------------------[ filename ]--------------------> 1
*
- * @var int
+ * @var int $state
*/
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
@@ -128,4 +130,20 @@ class IntoKeyword extends Component
--$list->idx;
return $ret;
}
+
+ /**
+ * @param IntoKeyword $component The component to be built.
+ *
+ * @return string
+ */
+ public static function build($component)
+ {
+ if ($component->type === 'OUTFILE') {
+ return 'OUTFILE "' . $component->dest . '"';
+ } else {
+ $columns = !empty($component->columns) ?
+ '(' . implode(', ', $component->columns) . ')' : '';
+ return Expression::build($component->dest) . $columns;
+ }
+ }
}
diff --git a/libraries/sql-parser/src/Components/JoinKeyword.php b/libraries/sql-parser/src/Components/JoinKeyword.php
index 171ad98db3..237022a16c 100644
--- a/libraries/sql-parser/src/Components/JoinKeyword.php
+++ b/libraries/sql-parser/src/Components/JoinKeyword.php
@@ -86,7 +86,7 @@ class JoinKeyword extends Component
*
* 3 --------------------[ conditions ]-------------------> 0
*
- * @var int
+ * @var int $state
*/
$state = 0;
@@ -98,8 +98,10 @@ class JoinKeyword extends Component
}
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
diff --git a/libraries/sql-parser/src/Components/Key.php b/libraries/sql-parser/src/Components/Key.php
index bb8bbf02ed..1364a8ceef 100644
--- a/libraries/sql-parser/src/Components/Key.php
+++ b/libraries/sql-parser/src/Components/Key.php
@@ -107,13 +107,15 @@ class Key extends Component
*
* 2 ---------------------[ options ]---------------------> 3
*
- * @var int
+ * @var int $state
*/
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
diff --git a/libraries/sql-parser/src/Components/Limit.php b/libraries/sql-parser/src/Components/Limit.php
index a821b9fe79..8622c96d9e 100644
--- a/libraries/sql-parser/src/Components/Limit.php
+++ b/libraries/sql-parser/src/Components/Limit.php
@@ -65,8 +65,10 @@ class Limit extends Component
$offset = false;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
diff --git a/libraries/sql-parser/src/Components/OptionsArray.php b/libraries/sql-parser/src/Components/OptionsArray.php
index da2ec8dbee..6b43844c24 100644
--- a/libraries/sql-parser/src/Components/OptionsArray.php
+++ b/libraries/sql-parser/src/Components/OptionsArray.php
@@ -57,24 +57,28 @@ class OptionsArray extends Component
/**
* The ID that will be assigned to duplicate options.
+ *
* @var int $lastAssignedId
*/
$lastAssignedId = count($options) + 1;
/**
* The option that was processed last time.
+ *
* @var array $lastOption
*/
$lastOption = null;
/**
* The index of the option that was processed last time.
+ *
* @var int $lastOptionId
*/
$lastOptionId = 0;
/**
* Counts brackets.
+ *
* @var int $brackets
*/
$brackets = 0;
@@ -90,13 +94,15 @@ class OptionsArray extends Component
*
* 2 ----------------------[ value ]----------------------> 0
*
- * @var int
+ * @var int $state
*/
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
diff --git a/libraries/sql-parser/src/Components/OrderKeyword.php b/libraries/sql-parser/src/Components/OrderKeyword.php
index b8b05c15b6..81bff2f7a2 100644
--- a/libraries/sql-parser/src/Components/OrderKeyword.php
+++ b/libraries/sql-parser/src/Components/OrderKeyword.php
@@ -74,13 +74,15 @@ class OrderKeyword extends Component
* 1 ------------------------[ , ]------------------------> 0
* 1 -------------------[ ASC / DESC ]--------------------> 1
*
- * @var int
+ * @var int $state
*/
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
diff --git a/libraries/sql-parser/src/Components/ParameterDefinition.php b/libraries/sql-parser/src/Components/ParameterDefinition.php
index d10a460f38..79b4845e22 100644
--- a/libraries/sql-parser/src/Components/ParameterDefinition.php
+++ b/libraries/sql-parser/src/Components/ParameterDefinition.php
@@ -73,15 +73,17 @@ class ParameterDefinition extends Component
* 2 -------------------[ data type ]--------------------> 3
*
* 3 ------------------------[ , ]-----------------------> 1
- * 3 ------------------------[ ) ]-----------------------> -1
+ * 3 ------------------------[ ) ]-----------------------> (END)
*
- * @var int
+ * @var int $state
*/
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
diff --git a/libraries/sql-parser/src/Components/PartitionDefinition.php b/libraries/sql-parser/src/Components/PartitionDefinition.php
new file mode 100644
index 0000000000..c46252d9fd
--- /dev/null
+++ b/libraries/sql-parser/src/Components/PartitionDefinition.php
@@ -0,0 +1,219 @@
+
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class PartitionDefinition extends Component
+{
+
+ /**
+ * All field options.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+ 'STORAGE' => array(1, 'var'),
+ 'STORAGE ENGINE' => array(1, 'var'),
+ 'COMMENT' => array(2, 'var'),
+ 'DATA DIRECTORY' => array(3, 'var'),
+ 'INDEX DIRECTORY' => array(4, 'var'),
+ 'MAX_ROWS' => array(5, 'var'),
+ 'MIN_ROWS' => array(6, 'var'),
+ 'TABLESPACE' => array(7, 'var'),
+ 'NODEGROUP' => array(8, 'var'),
+ );
+
+ /**
+ * Whether this entry is a subpartition or a partition.
+ *
+ * @var bool
+ */
+ public $isSubpartition;
+
+ /**
+ * The name of this partition.
+ *
+ * @var string
+ */
+ public $name;
+
+ /**
+ * The type of this partition (what follows the `VALUES` keyword).
+ *
+ * @var string
+ */
+ public $type;
+
+ /**
+ * The expression used to defined this partition.
+ *
+ * @var Expression
+ */
+ public $expr;
+
+ /**
+ * The subpartitions of this partition.
+ *
+ * @var PartitionDefinition[]
+ */
+ public $subpartitions;
+
+ /**
+ * The options of this field.
+ *
+ * @var OptionsArray
+ */
+ public $options;
+
+ /**
+ * @param Parser $parser The parser that serves as context.
+ * @param TokensList $list The list of tokens that are being parsed.
+ * @param array $options Parameters for parsing.
+ *
+ * @return PartitionDefinition
+ */
+ public static function parse(Parser $parser, TokensList $list, array $options = array())
+ {
+ $ret = new PartitionDefinition();
+
+ /**
+ * The state of the parser.
+ *
+ * Below are the states of the parser.
+ *
+ * 0 -------------[ PARTITION | SUBPARTITION ]------------> 1
+ *
+ * 1 -----------------------[ name ]----------------------> 2
+ *
+ * 2 ----------------------[ VALUES ]---------------------> 3
+ *
+ * 3 ---------------------[ LESS THAN ]-------------------> 4
+ * 3 ------------------------[ IN ]-----------------------> 4
+ *
+ * 4 -----------------------[ expr ]----------------------> 5
+ *
+ * 5 ----------------------[ options ]--------------------> 6
+ *
+ * 6 ------------------[ subpartitions ]------------------> (END)
+ *
+ * @var int $state
+ */
+ $state = 0;
+
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping whitespaces and comments.
+ if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ continue;
+ }
+
+ if ($state === 0) {
+ $ret->isSubpartition = ($token->type === Token::TYPE_KEYWORD) && ($token->value === 'SUBPARTITION');
+ $state = 1;
+ } elseif ($state === 1) {
+ $ret->name = $token->value;
+ $state = $ret->isSubpartition ? 5 : 2;
+ } elseif ($state === 2) {
+ $state = 3;
+ } elseif ($state === 3) {
+ $ret->type = $token->value;
+ $state = 4;
+ } elseif ($state === 4) {
+ if ($token->value === 'MAXVALUE') {
+ $ret->expr = $token->value;
+ } else {
+ $ret->expr = Expression::parse(
+ $parser,
+ $list,
+ array(
+ 'bracketsDelimited' => true,
+ 'noAlias' => true,
+ )
+ );
+ }
+ $state = 5;
+ } elseif ($state === 5) {
+ $ret->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
+ $state = 6;
+ } elseif ($state === 6) {
+ if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
+ $ret->subpartitions = ArrayObj::parse(
+ $parser,
+ $list,
+ array(
+ 'type' => 'SqlParser\\Components\\PartitionDefinition'
+ )
+ );
+ ++$list->idx;
+ }
+ break;
+ }
+ }
+
+ --$list->idx;
+ return $ret;
+ }
+
+ /**
+ * @param PartitionDefinition|PartitionDefinition[] $component The component to be built.
+ *
+ * @return string
+ */
+ public static function build($component)
+ {
+ if (is_array($component)) {
+ $ret = array();
+ foreach ($component as $c) {
+ $ret[] = static::build($c);
+ }
+ return "(\n" . implode(",\n", $ret) . "\n)";
+ } else {
+ if ($component->isSubpartition) {
+ return 'SUBPARTITION ' . $component->name;
+ } else {
+ $subpartitions = empty($component->subpartitions)
+ ? '' : ' ' . PartitionDefinition::build($component->subpartitions);
+ return 'PARTITION ' . $component->name
+ . ' VALUES ' . $component->type . ' ' . $component->expr
+ . $subpartitions;
+ }
+
+ }
+ }
+}
diff --git a/libraries/sql-parser/src/Components/Reference.php b/libraries/sql-parser/src/Components/Reference.php
index fa468875ac..36d3971477 100644
--- a/libraries/sql-parser/src/Components/Reference.php
+++ b/libraries/sql-parser/src/Components/Reference.php
@@ -92,15 +92,17 @@ class Reference extends Component
*
* 1 ---------------------[ columns ]--------------------> 2
*
- * 2 ---------------------[ options ]--------------------> -1
+ * 2 ---------------------[ options ]--------------------> (END)
*
- * @var int
+ * @var int $state
*/
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
diff --git a/libraries/sql-parser/src/Components/RenameOperation.php b/libraries/sql-parser/src/Components/RenameOperation.php
index 7d115fb330..34c62bb415 100644
--- a/libraries/sql-parser/src/Components/RenameOperation.php
+++ b/libraries/sql-parser/src/Components/RenameOperation.php
@@ -44,7 +44,7 @@ class RenameOperation extends Component
* @param TokensList $list The list of tokens that are being parsed.
* @param array $options Parameters for parsing.
*
- * @return RenameOperation
+ * @return RenameOperation[]
*/
public static function parse(Parser $parser, TokensList $list, array $options = array())
{
@@ -64,15 +64,17 @@ class RenameOperation extends Component
* 2 ---------------------[ old name ]--------------------> 3
*
* 3 ------------------------[ , ]------------------------> 0
- * 3 -----------------------[ else ]----------------------> -1
+ * 3 -----------------------[ else ]----------------------> (END)
*
- * @var int
+ * @var int $state
*/
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
@@ -157,4 +159,23 @@ class RenameOperation extends Component
--$list->idx;
return $ret;
}
+
+ /**
+ * @param RenameOperation $component The component to be built.
+ *
+ * @return string
+ */
+ public static function build($component)
+ {
+ if (is_array($component)) {
+ $values = array();
+ foreach ($component as $c) {
+ $values[] = static::build($c);
+ }
+ return implode(', ', $values);
+ } else {
+ return Expression::build($component->old) . ' TO '
+ . Expression::build($component->new);
+ }
+ }
}
diff --git a/libraries/sql-parser/src/Components/SetOperation.php b/libraries/sql-parser/src/Components/SetOperation.php
index 25bb9e4231..8b6af87458 100644
--- a/libraries/sql-parser/src/Components/SetOperation.php
+++ b/libraries/sql-parser/src/Components/SetOperation.php
@@ -62,13 +62,15 @@ class SetOperation extends Component
* 1 ------------------------[ , ]------------------------> 0
* 1 ----------------------[ value ]----------------------> 1
*
- * @var int
+ * @var int $state
*/
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
diff --git a/libraries/sql-parser/src/Context.php b/libraries/sql-parser/src/Context.php
index c355534978..d6602ce29d 100644
--- a/libraries/sql-parser/src/Context.php
+++ b/libraries/sql-parser/src/Context.php
@@ -450,6 +450,7 @@ abstract class Context
/**
* The number of replaces done by `preg_replace`.
* This actually represents whether a new context was generated or not.
+ *
* @var int $count
*/
$count = 0;
diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50000.php b/libraries/sql-parser/src/Contexts/ContextMySql50000.php
index ed86320ac4..42366983fe 100644
--- a/libraries/sql-parser/src/Contexts/ContextMySql50000.php
+++ b/libraries/sql-parser/src/Contexts/ContextMySql50000.php
@@ -54,9 +54,8 @@ class ContextMySql50000 extends Context
'EVENTS' => 1, 'FAULTS' => 1, 'FIELDS' => 1, 'GLOBAL' => 1, 'GRANTS' => 1,
'IMPORT' => 1, 'INNODB' => 1, 'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1,
'MEDIUM' => 1, 'MEMORY' => 1, 'MODIFY' => 1, 'OFFSET' => 1, 'RELOAD' => 1,
- 'REPAIR' => 1, 'RESUME' => 1, 'ROLLUP' => 1, 'SERIAL' => 1, 'SIGNED' => 1,
- 'SIMPLE' => 1, 'SOUNDS' => 1, 'SOURCE' => 1, 'STATUS' => 1, 'STRING' => 1,
- 'TABLES' => 1,
+ 'REPAIR' => 1, 'RESUME' => 1, 'ROLLUP' => 1, 'SIGNED' => 1, 'SIMPLE' => 1,
+ 'SOUNDS' => 1, 'SOURCE' => 1, 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1,
'AGAINST' => 1, 'CHANGED' => 1, 'COLUMNS' => 1, 'COMMENT' => 1, 'COMPACT' => 1,
'CONTEXT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1, 'DYNAMIC' => 1,
'ENGINES' => 1, 'EXECUTE' => 1, 'HANDLER' => 1, 'INDEXES' => 1, 'INVOKER' => 1,
@@ -77,8 +76,8 @@ class ContextMySql50000 extends Context
'VARIABLES' => 1,
'BERKELEYDB' => 1, 'COMPRESSED' => 1, 'CONCURRENT' => 1, 'CONNECTION' => 1,
'CONSISTENT' => 1, 'DEALLOCATE' => 1, 'IDENTIFIED' => 1, 'MASTER_SSL' => 1,
- 'NDBCLUSTER' => 1, 'PERSISTENT' => 1, 'PRIVILEGES' => 1, 'REPEATABLE' => 1,
- 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, 'TABLESPACE' => 1,
+ 'NDBCLUSTER' => 1, 'PARTITIONS' => 1, 'PERSISTENT' => 1, 'PRIVILEGES' => 1,
+ 'REPEATABLE' => 1, 'ROW_FORMAT' => 1, 'SQL_THREAD' => 1, 'TABLESPACE' => 1,
'FRAC_SECOND' => 1, 'MASTER_HOST' => 1, 'MASTER_PORT' => 1, 'MASTER_USER' => 1,
'PROCESSLIST' => 1, 'RAID_CHUNKS' => 1, 'REPLICATION' => 1, 'SQL_TSI_DAY' => 1,
'TRANSACTION' => 1, 'UNCOMMITTED' => 1,
@@ -86,7 +85,7 @@ class ContextMySql50000 extends Context
'SQL_NO_CACHE' => 1, 'SQL_TSI_HOUR' => 1, 'SQL_TSI_WEEK' => 1,
'SQL_TSI_YEAR' => 1,
'INSERT_METHOD' => 1, 'MASTER_SSL_CA' => 1, 'RELAY_LOG_POS' => 1,
- 'SQL_TSI_MONTH' => 1,
+ 'SQL_TSI_MONTH' => 1, 'SUBPARTITIONS' => 1,
'AUTO_INCREMENT' => 1, 'AVG_ROW_LENGTH' => 1, 'MASTER_LOG_POS' => 1,
'MASTER_SSL_KEY' => 1, 'RAID_CHUNKSIZE' => 1, 'RELAY_LOG_FILE' => 1,
'SQL_TSI_MINUTE' => 1, 'SQL_TSI_SECOND' => 1, 'USER_RESOURCES' => 1,
@@ -145,12 +144,16 @@ class ContextMySql50000 extends Context
'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7,
- 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
- 'INNER JOIN' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7, 'RIGHT JOIN' => 7,
- 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
+ 'LESS THAN' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
+ 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7,
+ 'RIGHT JOIN' => 7,
+ 'LINEAR HASH' => 7,
+ 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7,
+ 'SQL SECURITY' => 7,
'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
'DATA DIRECTORY' => 7,
'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
+ 'SUBPARTITION BY' => 7,
'GENERATED ALWAYS' => 7,
'START TRANSACTION' => 7,
'SELECT TRANSACTION' => 7,
@@ -160,6 +163,7 @@ class ContextMySql50000 extends Context
'XML' => 9,
'ENUM' => 9, 'TEXT' => 9,
'ARRAY' => 9,
+ 'SERIAL' => 9,
'BOOLEAN' => 9,
'DATETIME' => 9, 'MULTISET' => 9,
diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50100.php b/libraries/sql-parser/src/Contexts/ContextMySql50100.php
index c71ff6cc22..8da3d06152 100644
--- a/libraries/sql-parser/src/Contexts/ContextMySql50100.php
+++ b/libraries/sql-parser/src/Contexts/ContextMySql50100.php
@@ -57,9 +57,9 @@ class ContextMySql50100 extends Context
'IMPORT' => 1, 'INNODB' => 1, 'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1,
'MEDIUM' => 1, 'MEMORY' => 1, 'MODIFY' => 1, 'OFFSET' => 1, 'PARSER' => 1,
'PLUGIN' => 1, 'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, 'RESUME' => 1,
- 'ROLLUP' => 1, 'SERIAL' => 1, 'SERVER' => 1, 'SIGNED' => 1, 'SIMPLE' => 1,
- 'SOCKET' => 1, 'SONAME' => 1, 'SOUNDS' => 1, 'SOURCE' => 1, 'STARTS' => 1,
- 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1,
+ 'ROLLUP' => 1, 'SERVER' => 1, 'SIGNED' => 1, 'SIMPLE' => 1, 'SOCKET' => 1,
+ 'SONAME' => 1, 'SOUNDS' => 1, 'SOURCE' => 1, 'STARTS' => 1, 'STATUS' => 1,
+ 'STRING' => 1, 'TABLES' => 1,
'AGAINST' => 1, 'AUTHORS' => 1, 'CHANGED' => 1, 'COLUMNS' => 1, 'COMMENT' => 1,
'COMPACT' => 1, 'CONTEXT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1,
'DYNAMIC' => 1, 'ENGINES' => 1, 'EXECUTE' => 1, 'HANDLER' => 1, 'INDEXES' => 1,
@@ -157,12 +157,16 @@ class ContextMySql50100 extends Context
'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7,
- 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
- 'INNER JOIN' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7, 'RIGHT JOIN' => 7,
- 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
+ 'LESS THAN' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
+ 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7,
+ 'RIGHT JOIN' => 7,
+ 'LINEAR HASH' => 7,
+ 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7,
+ 'SQL SECURITY' => 7,
'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
'DATA DIRECTORY' => 7,
'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
+ 'SUBPARTITION BY' => 7,
'GENERATED ALWAYS' => 7,
'START TRANSACTION' => 7,
'SELECT TRANSACTION' => 7,
@@ -172,6 +176,7 @@ class ContextMySql50100 extends Context
'XML' => 9,
'ENUM' => 9, 'TEXT' => 9,
'ARRAY' => 9,
+ 'SERIAL' => 9,
'BOOLEAN' => 9,
'DATETIME' => 9, 'MULTISET' => 9,
diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50500.php b/libraries/sql-parser/src/Contexts/ContextMySql50500.php
index 6f6bb66af6..16207dcb15 100644
--- a/libraries/sql-parser/src/Contexts/ContextMySql50500.php
+++ b/libraries/sql-parser/src/Contexts/ContextMySql50500.php
@@ -57,9 +57,9 @@ class ContextMySql50500 extends Context
'IMPORT' => 1, 'INNODB' => 1, 'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1,
'MEDIUM' => 1, 'MEMORY' => 1, 'MODIFY' => 1, 'OFFSET' => 1, 'PARSER' => 1,
'PLUGIN' => 1, 'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, 'RESUME' => 1,
- 'ROLLUP' => 1, 'SERIAL' => 1, 'SERVER' => 1, 'SIGNED' => 1, 'SIMPLE' => 1,
- 'SOCKET' => 1, 'SONAME' => 1, 'SOUNDS' => 1, 'SOURCE' => 1, 'STARTS' => 1,
- 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1,
+ 'ROLLUP' => 1, 'SERVER' => 1, 'SIGNED' => 1, 'SIMPLE' => 1, 'SOCKET' => 1,
+ 'SONAME' => 1, 'SOUNDS' => 1, 'SOURCE' => 1, 'STARTS' => 1, 'STATUS' => 1,
+ 'STRING' => 1, 'TABLES' => 1,
'AGAINST' => 1, 'AUTHORS' => 1, 'CHANGED' => 1, 'COLUMNS' => 1, 'COMMENT' => 1,
'COMPACT' => 1, 'CONTEXT' => 1, 'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1,
'DYNAMIC' => 1, 'ENGINES' => 1, 'EXECUTE' => 1, 'GENERAL' => 1, 'HANDLER' => 1,
@@ -162,12 +162,16 @@ class ContextMySql50500 extends Context
'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7,
- 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
- 'INNER JOIN' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7, 'RIGHT JOIN' => 7,
- 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
+ 'LESS THAN' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
+ 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7,
+ 'RIGHT JOIN' => 7,
+ 'LINEAR HASH' => 7,
+ 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7,
+ 'SQL SECURITY' => 7,
'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
'DATA DIRECTORY' => 7,
'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
+ 'SUBPARTITION BY' => 7,
'GENERATED ALWAYS' => 7,
'START TRANSACTION' => 7,
'SELECT TRANSACTION' => 7,
@@ -177,6 +181,7 @@ class ContextMySql50500 extends Context
'XML' => 9,
'ENUM' => 9, 'TEXT' => 9,
'ARRAY' => 9,
+ 'SERIAL' => 9,
'BOOLEAN' => 9,
'DATETIME' => 9, 'MULTISET' => 9,
diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50600.php b/libraries/sql-parser/src/Contexts/ContextMySql50600.php
index 62b75abae1..4165140516 100644
--- a/libraries/sql-parser/src/Contexts/ContextMySql50600.php
+++ b/libraries/sql-parser/src/Contexts/ContextMySql50600.php
@@ -57,9 +57,9 @@ class ContextMySql50600 extends Context
'GLOBAL' => 1, 'GRANTS' => 1, 'IMPORT' => 1, 'ISSUER' => 1, 'LEAVES' => 1,
'MASTER' => 1, 'MEDIUM' => 1, 'MEMORY' => 1, 'MODIFY' => 1, 'NUMBER' => 1,
'OFFSET' => 1, 'PARSER' => 1, 'PLUGIN' => 1, 'RELOAD' => 1, 'REMOVE' => 1,
- 'REPAIR' => 1, 'RESUME' => 1, 'ROLLUP' => 1, 'SERIAL' => 1, 'SERVER' => 1,
- 'SIGNED' => 1, 'SIMPLE' => 1, 'SOCKET' => 1, 'SONAME' => 1, 'SOUNDS' => 1,
- 'SOURCE' => 1, 'STARTS' => 1, 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1,
+ 'REPAIR' => 1, 'RESUME' => 1, 'ROLLUP' => 1, 'SERVER' => 1, 'SIGNED' => 1,
+ 'SIMPLE' => 1, 'SOCKET' => 1, 'SONAME' => 1, 'SOUNDS' => 1, 'SOURCE' => 1,
+ 'STARTS' => 1, 'STATUS' => 1, 'STRING' => 1, 'TABLES' => 1,
'AGAINST' => 1, 'ANALYSE' => 1, 'AUTHORS' => 1, 'CHANGED' => 1, 'COLUMNS' => 1,
'COMMENT' => 1, 'COMPACT' => 1, 'CONTEXT' => 1, 'CURRENT' => 1, 'DEFINER' => 1,
'DISABLE' => 1, 'DISCARD' => 1, 'DYNAMIC' => 1, 'ENGINES' => 1, 'EXECUTE' => 1,
@@ -167,12 +167,16 @@ class ContextMySql50600 extends Context
'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7,
- 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
- 'INNER JOIN' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7, 'RIGHT JOIN' => 7,
- 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
+ 'LESS THAN' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
+ 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7,
+ 'RIGHT JOIN' => 7,
+ 'LINEAR HASH' => 7,
+ 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7,
+ 'SQL SECURITY' => 7,
'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
'DATA DIRECTORY' => 7,
'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
+ 'SUBPARTITION BY' => 7,
'GENERATED ALWAYS' => 7,
'START TRANSACTION' => 7,
'SELECT TRANSACTION' => 7,
@@ -182,6 +186,7 @@ class ContextMySql50600 extends Context
'XML' => 9,
'ENUM' => 9, 'TEXT' => 9,
'ARRAY' => 9,
+ 'SERIAL' => 9,
'BOOLEAN' => 9,
'DATETIME' => 9, 'MULTISET' => 9,
diff --git a/libraries/sql-parser/src/Contexts/ContextMySql50700.php b/libraries/sql-parser/src/Contexts/ContextMySql50700.php
index 8b0568b0cd..7d75a728a0 100644
--- a/libraries/sql-parser/src/Contexts/ContextMySql50700.php
+++ b/libraries/sql-parser/src/Contexts/ContextMySql50700.php
@@ -58,9 +58,9 @@ class ContextMySql50700 extends Context
'ISSUER' => 1, 'LEAVES' => 1, 'MASTER' => 1, 'MEDIUM' => 1, 'MEMORY' => 1,
'MODIFY' => 1, 'NUMBER' => 1, 'OFFSET' => 1, 'PARSER' => 1, 'PLUGIN' => 1,
'RELOAD' => 1, 'REMOVE' => 1, 'REPAIR' => 1, 'RESUME' => 1, 'ROLLUP' => 1,
- 'SERIAL' => 1, 'SERVER' => 1, 'SIGNED' => 1, 'SIMPLE' => 1, 'SOCKET' => 1,
- 'SONAME' => 1, 'SOUNDS' => 1, 'SOURCE' => 1, 'STARTS' => 1, 'STATUS' => 1,
- 'STRING' => 1, 'TABLES' => 1,
+ 'SERVER' => 1, 'SIGNED' => 1, 'SIMPLE' => 1, 'SOCKET' => 1, 'SONAME' => 1,
+ 'SOUNDS' => 1, 'SOURCE' => 1, 'STARTS' => 1, 'STATUS' => 1, 'STRING' => 1,
+ 'TABLES' => 1,
'ACCOUNT' => 1, 'AGAINST' => 1, 'ANALYSE' => 1, 'CHANGED' => 1, 'CHANNEL' => 1,
'COLUMNS' => 1, 'COMMENT' => 1, 'COMPACT' => 1, 'CONTEXT' => 1, 'CURRENT' => 1,
'DEFINER' => 1, 'DISABLE' => 1, 'DISCARD' => 1, 'DYNAMIC' => 1, 'ENGINES' => 1,
@@ -175,12 +175,16 @@ class ContextMySql50700 extends Context
'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7,
- 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
- 'INNER JOIN' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7, 'RIGHT JOIN' => 7,
- 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
+ 'LESS THAN' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
+ 'INNER JOIN' => 7, 'LINEAR KEY' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7,
+ 'RIGHT JOIN' => 7,
+ 'LINEAR HASH' => 7,
+ 'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'PARTITION BY' => 7,
+ 'SQL SECURITY' => 7,
'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
'DATA DIRECTORY' => 7,
'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
+ 'SUBPARTITION BY' => 7,
'GENERATED ALWAYS' => 7,
'START TRANSACTION' => 7,
'SELECT TRANSACTION' => 7,
@@ -190,6 +194,7 @@ class ContextMySql50700 extends Context
'XML' => 9,
'ENUM' => 9, 'TEXT' => 9,
'ARRAY' => 9,
+ 'SERIAL' => 9,
'BOOLEAN' => 9,
'DATETIME' => 9, 'MULTISET' => 9,
diff --git a/libraries/sql-parser/src/Lexer.php b/libraries/sql-parser/src/Lexer.php
index b969a1959a..1d1839957e 100644
--- a/libraries/sql-parser/src/Lexer.php
+++ b/libraries/sql-parser/src/Lexer.php
@@ -42,6 +42,7 @@ namespace SqlParser {
/**
* Forces usage of `UtfString` if the string is multibyte.
* `UtfString` may be slower, but it gives better results.
+ *
* @var bool
*/
define('USE_UTF_STRINGS', true);
@@ -242,13 +243,16 @@ namespace SqlParser {
/**
* Last processed token.
+ *
* @var Token $lastToken
*/
$lastToken = null;
for ($this->last = 0, $lastIdx = 0; $this->last < $this->len; $lastIdx = ++$this->last) {
+
/**
* The new token.
+ *
* @var Token $token
*/
$token = null;
@@ -392,23 +396,27 @@ namespace SqlParser {
/**
* Value to be returned.
+ *
* @var Token $ret
*/
$ret = null;
/**
* The value of `$this->last` where `$token` ends in `$this->str`.
+ *
* @var int $iEnd
*/
$iEnd = $this->last;
/**
* Whether last parsed character is a whitespace.
+ *
* @var bool $lastSpace
*/
$lastSpace = false;
for ($j = 1; $j < Context::KEYWORD_MAX_LENGTH && $this->last < $this->len; ++$j, ++$this->last) {
+
// Composed keywords shouldn't have more than one whitespace between
// keywords.
if (Context::isWhitespace($this->str[$this->last])) {
@@ -426,6 +434,7 @@ namespace SqlParser {
if (($flags = Context::isKeyword($token))) {
$ret = new Token($token, Token::TYPE_KEYWORD, $flags);
$iEnd = $this->last;
+
// We don't break so we find longest keyword.
// For example, `OR` and `ORDER` have a common prefix `OR`.
// If we stopped at `OR`, the parsing would be invalid.
@@ -448,12 +457,14 @@ namespace SqlParser {
/**
* Value to be returned.
+ *
* @var Token $ret
*/
$ret = null;
/**
* The value of `$this->last` where `$token` ends in `$this->str`.
+ *
* @var int $iEnd
*/
$iEnd = $this->last;
@@ -799,7 +810,11 @@ namespace SqlParser {
}
if ($flags & Token::FLAG_SYMBOL_VARIABLE) {
- ++$this->last;
+ if ($this->str[++$this->last] === '@') {
+ // This is a system variable (e.g. `@@hostname`).
+ $token .= $this->str[$this->last++];
+ $flags |= Token::FLAG_SYMBOL_SYSTEM;
+ }
} else {
$token = '';
}
diff --git a/libraries/sql-parser/src/Parser.php b/libraries/sql-parser/src/Parser.php
index d6d391bd7c..5b74f33982 100644
--- a/libraries/sql-parser/src/Parser.php
+++ b/libraries/sql-parser/src/Parser.php
@@ -113,153 +113,158 @@ namespace SqlParser {
*/
public static $KEYWORD_PARSERS = array(
- // This is not a proper keyword and was added here to help the builder.
- '_OPTIONS' => array(
- 'class' => 'SqlParser\\Components\\OptionsArray',
- 'field' => 'options',
+ // This is not a proper keyword and was added here to help the
+ // formatter.
+ 'PARTITION BY' => array(),
+ 'SUBPARTITION BY' => array(),
+
+ // This is not a proper keyword and was added here to help the
+ // builder.
+ '_OPTIONS' => array(
+ 'class' => 'SqlParser\\Components\\OptionsArray',
+ 'field' => 'options',
+ ),
+ 'UNION' => array(
+ 'class' => 'SqlParser\\Components\\UnionKeyword',
+ 'field' => 'union',
),
- // This is used only for building.
- 'UNION' => array(
- 'class' => 'SqlParser\\Components\\UnionKeyword',
- 'field' => 'union',
+ // Actual clause parsers.
+ 'ALTER' => array(
+ 'class' => 'SqlParser\\Components\\Expression',
+ 'field' => 'table',
+ 'options' => array('skipColumn' => true),
),
-
- 'ALTER' => array(
- 'class' => 'SqlParser\\Components\\Expression',
- 'field' => 'table',
- 'options' => array('skipColumn' => true),
+ 'ANALYZE' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('skipColumn' => true),
),
- 'ANALYZE' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'tables',
- 'options' => array('skipColumn' => true),
+ 'BACKUP' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('skipColumn' => true),
),
- 'BACKUP' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'tables',
- 'options' => array('skipColumn' => true),
+ 'CALL' => array(
+ 'class' => 'SqlParser\\Components\\FunctionCall',
+ 'field' => 'call',
),
- 'CALL' => array(
- 'class' => 'SqlParser\\Components\\FunctionCall',
- 'field' => 'call',
+ 'CHECK' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('skipColumn' => true),
),
- 'CHECK' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'tables',
- 'options' => array('skipColumn' => true),
+ 'CHECKSUM' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('skipColumn' => true),
),
- 'CHECKSUM' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'tables',
- 'options' => array('skipColumn' => true),
+ 'DROP' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'fields',
+ 'options' => array('skipColumn' => true),
),
- 'DROP' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'fields',
- 'options' => array('skipColumn' => true),
+ 'FROM' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'from',
+ 'options' => array('skipColumn' => true),
),
- 'FROM' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'from',
- 'options' => array('skipColumn' => true),
+ 'GROUP BY' => array(
+ 'class' => 'SqlParser\\Components\\OrderKeyword',
+ 'field' => 'group',
),
- 'GROUP BY' => array(
- 'class' => 'SqlParser\\Components\\OrderKeyword',
- 'field' => 'group',
+ 'HAVING' => array(
+ 'class' => 'SqlParser\\Components\\Condition',
+ 'field' => 'having',
),
- 'HAVING' => array(
- 'class' => 'SqlParser\\Components\\Condition',
- 'field' => 'having',
+ 'INTO' => array(
+ 'class' => 'SqlParser\\Components\\IntoKeyword',
+ 'field' => 'into',
),
- 'INTO' => array(
- 'class' => 'SqlParser\\Components\\IntoKeyword',
- 'field' => 'into',
+ 'JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
),
- 'JOIN' => array(
- 'class' => 'SqlParser\\Components\\JoinKeyword',
- 'field' => 'join',
+ 'LEFT JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
),
- 'LEFT JOIN' => array(
- 'class' => 'SqlParser\\Components\\JoinKeyword',
- 'field' => 'join',
+ 'RIGHT JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
),
- 'RIGHT JOIN' => array(
- 'class' => 'SqlParser\\Components\\JoinKeyword',
- 'field' => 'join',
+ 'INNER JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
),
- 'INNER JOIN' => array(
- 'class' => 'SqlParser\\Components\\JoinKeyword',
- 'field' => 'join',
+ 'FULL JOIN' => array(
+ 'class' => 'SqlParser\\Components\\JoinKeyword',
+ 'field' => 'join',
),
- 'FULL JOIN' => array(
- 'class' => 'SqlParser\\Components\\JoinKeyword',
- 'field' => 'join',
+ 'LIMIT' => array(
+ 'class' => 'SqlParser\\Components\\Limit',
+ 'field' => 'limit',
),
- 'LIMIT' => array(
- 'class' => 'SqlParser\\Components\\Limit',
- 'field' => 'limit',
+ 'OPTIMIZE' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('skipColumn' => true),
),
- 'OPTIMIZE' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'tables',
- 'options' => array('skipColumn' => true),
+ 'ORDER BY' => array(
+ 'class' => 'SqlParser\\Components\\OrderKeyword',
+ 'field' => 'order',
),
- 'ORDER BY' => array(
- 'class' => 'SqlParser\\Components\\OrderKeyword',
- 'field' => 'order',
+ 'PARTITION' => array(
+ 'class' => 'SqlParser\\Components\\ArrayObj',
+ 'field' => 'partition',
),
- 'PARTITION' => array(
- 'class' => 'SqlParser\\Components\\ArrayObj',
- 'field' => 'partition',
+ 'PROCEDURE' => array(
+ 'class' => 'SqlParser\\Components\\FunctionCall',
+ 'field' => 'procedure',
),
- 'PROCEDURE' => array(
- 'class' => 'SqlParser\\Components\\FunctionCall',
- 'field' => 'procedure',
+ 'RENAME' => array(
+ 'class' => 'SqlParser\\Components\\RenameOperation',
+ 'field' => 'renames',
),
- 'RENAME' => array(
- 'class' => 'SqlParser\\Components\\RenameOperation',
- 'field' => 'renames',
+ 'REPAIR' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('skipColumn' => true),
),
- 'REPAIR' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'tables',
- 'options' => array('skipColumn' => true),
+ 'RESTORE' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('skipColumn' => true),
),
- 'RESTORE' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'tables',
- 'options' => array('skipColumn' => true),
+ 'SET' => array(
+ 'class' => 'SqlParser\\Components\\SetOperation',
+ 'field' => 'set',
),
- 'SET' => array(
- 'class' => 'SqlParser\\Components\\SetOperation',
- 'field' => 'set',
+ 'SELECT' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'expr',
),
- 'SELECT' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'expr',
+ 'TRUNCATE' => array(
+ 'class' => 'SqlParser\\Components\\Expression',
+ 'field' => 'table',
+ 'options' => array('skipColumn' => true),
),
- 'TRUNCATE' => array(
- 'class' => 'SqlParser\\Components\\Expression',
- 'field' => 'table',
- 'options' => array('skipColumn' => true),
+ 'UPDATE' => array(
+ 'class' => 'SqlParser\\Components\\ExpressionArray',
+ 'field' => 'tables',
+ 'options' => array('skipColumn' => true),
),
- 'UPDATE' => array(
- 'class' => 'SqlParser\\Components\\ExpressionArray',
- 'field' => 'tables',
- 'options' => array('skipColumn' => true),
+ 'VALUE' => array(
+ 'class' => 'SqlParser\\Components\\Array2d',
+ 'field' => 'values',
),
- 'VALUE' => array(
- 'class' => 'SqlParser\\Components\\Array2d',
- 'field' => 'values',
+ 'VALUES' => array(
+ 'class' => 'SqlParser\\Components\\Array2d',
+ 'field' => 'values',
),
- 'VALUES' => array(
- 'class' => 'SqlParser\\Components\\Array2d',
- 'field' => 'values',
- ),
- 'WHERE' => array(
- 'class' => 'SqlParser\\Components\\Condition',
- 'field' => 'where',
+ 'WHERE' => array(
+ 'class' => 'SqlParser\\Components\\Condition',
+ 'field' => 'where',
),
);
@@ -304,7 +309,7 @@ namespace SqlParser {
* Constructor.
*
* @param string|UtfString|TokensList $list The list of tokens to be parsed.
- * @param bool $strict Whether strict mode should be enabled or not.
+ * @param bool $strict Whether strict mode should be enabled or not.
*/
public function __construct($list = null, $strict = false)
{
@@ -332,30 +337,35 @@ namespace SqlParser {
/**
* Last transaction.
+ *
* @var TransactionStatement $lastTransaction
*/
$lastTransaction = null;
/**
* Last parsed statement.
+ *
* @var Statement $lastStatement
*/
$lastStatement = null;
/**
* Whether a union is parsed or not.
+ *
* @var bool $inUnion
*/
$inUnion = false;
/**
* The index of the last token from the last statement.
+ *
* @var int $prevLastIdx
*/
$prevLastIdx = -1;
/**
* The list of tokens.
+ *
* @var TokensList $list
*/
$list = &$this->list;
@@ -364,6 +374,7 @@ namespace SqlParser {
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
@@ -419,12 +430,14 @@ namespace SqlParser {
/**
* The name of the class that is used for parsing.
+ *
* @var string $class
*/
$class = static::$STATEMENT_PARSERS[$token->value];
/**
* Processed statement.
+ *
* @var Statement $statement
*/
$statement = new $class($this, $this->list);
@@ -445,13 +458,16 @@ namespace SqlParser {
&& ($lastStatement instanceof SelectStatement)
&& ($statement instanceof SelectStatement)
) {
+
/**
* This SELECT statement.
+ *
* @var SelectStatement $statement
*/
/**
* Last SELECT statement.
+ *
* @var SelectStatement $lastStatement
*/
$lastStatement->union[] = $statement;
diff --git a/libraries/sql-parser/src/Statement.php b/libraries/sql-parser/src/Statement.php
index 8bf3d24ef2..0568d93773 100644
--- a/libraries/sql-parser/src/Statement.php
+++ b/libraries/sql-parser/src/Statement.php
@@ -103,6 +103,7 @@ abstract class Statement
{
/**
* Query to be returned.
+ *
* @var string $query
*/
$query = '';
@@ -111,12 +112,14 @@ abstract class Statement
/**
* The name of the clause.
+ *
* @var string $name
*/
$name = $clause[0];
/**
* The type of the clause.
+ *
* @see self::$CLAUSES
* @var int $type
*/
@@ -124,6 +127,7 @@ abstract class Statement
/**
* The builder (parser) of this clause.
+ *
* @var Component $class
*/
$class = Parser::$KEYWORD_PARSERS[$name]['class'];
@@ -131,6 +135,7 @@ abstract class Statement
/**
* The name of the field that is used as source for the builder.
* Same field is used to store the result of parsing.
+ *
* @var string $field
*/
$field = Parser::$KEYWORD_PARSERS[$name]['field'];
@@ -167,7 +172,8 @@ abstract class Statement
/**
* Array containing all list of clauses parsed.
* This is used to check for duplicates.
- * @var array
+ *
+ * @var array $parsedClauses
*/
$parsedClauses = array();
@@ -178,13 +184,16 @@ abstract class Statement
* Whether options were parsed or not.
* For statements that do not have any options this is set to `true` by
* default.
+ *
* @var bool $parsedOptions
*/
$parsedOptions = empty(static::$OPTIONS);
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
@@ -213,18 +222,21 @@ abstract class Statement
/**
* The name of the class that is used for parsing.
+ *
* @var Component $class
*/
$class = null;
/**
* The name of the field where the result of the parsing is stored.
+ *
* @var string $field
*/
$field = null;
/**
* Parser's options.
+ *
* @var array $options
*/
$options = array();
diff --git a/libraries/sql-parser/src/Statements/AlterStatement.php b/libraries/sql-parser/src/Statements/AlterStatement.php
index 2c48181152..31bbcb4540 100644
--- a/libraries/sql-parser/src/Statements/AlterStatement.php
+++ b/libraries/sql-parser/src/Statements/AlterStatement.php
@@ -89,13 +89,15 @@ class AlterStatement extends Statement
*
* 1 -------------------------[ , ]-----------------------> 0
*
- * @var int
+ * @var int $state
*/
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
+
/**
* Token parsed at this moment.
+ *
* @var Token $token
*/
$token = $list->tokens[$list->idx];
diff --git a/libraries/sql-parser/src/Statements/CreateStatement.php b/libraries/sql-parser/src/Statements/CreateStatement.php
index 4c0d985d47..bc7cf7355f 100644
--- a/libraries/sql-parser/src/Statements/CreateStatement.php
+++ b/libraries/sql-parser/src/Statements/CreateStatement.php
@@ -15,6 +15,7 @@ use SqlParser\TokensList;
use SqlParser\Components\ArrayObj;
use SqlParser\Components\DataType;
use SqlParser\Components\CreateDefinition;
+use SqlParser\Components\PartitionDefinition;
use SqlParser\Components\Expression;
use SqlParser\Components\OptionsArray;
use SqlParser\Components\ParameterDefinition;
@@ -173,6 +174,41 @@ class CreateStatement extends Statement
*/
public $fields;
+ /**
+ * Expression used for partitioning.
+ *
+ * @var string
+ */
+ public $partitionBy;
+
+ /**
+ * The number of partitions.
+ *
+ * @var int
+ */
+ public $partitionsNum;
+
+ /**
+ * Expression used for subpartitioning.
+ *
+ * @var string
+ */
+ public $subpartitionBy;
+
+ /**
+ * The number of subpartitions.
+ *
+ * @var int
+ */
+ public $subpartitionsNum;
+
+ /**
+ * The partition of the new table.
+ *
+ * @var PartitionDefinition[]
+ */
+ public $partitions;
+
/**
* If `CREATE TRIGGER` the name of the table.
*
@@ -229,11 +265,30 @@ class CreateStatement extends Statement
. Expression::build($this->name) . ' '
. OptionsArray::build($this->entityOptions);
} elseif ($this->options->has('TABLE')) {
+ $partition = '';
+
+ if (!empty($this->partitionBy)) {
+ $partition .= "\nPARTITION BY " . $this->partitionBy;
+ }
+ if (!empty($this->partitionsNum)) {
+ $partition .= "\nPARTITIONS " . $this->partitionsNum;
+ }
+ if (!empty($this->subpartitionBy)) {
+ $partition .= "\nSUBPARTITION BY " . $this->subpartitionBy;
+ }
+ if (!empty($this->subpartitionsNum)) {
+ $partition .= "\nSUBPARTITIONS " . $this->subpartitionsNum;
+ }
+ if (!empty($this->partitions)) {
+ $partition .= "\n" . PartitionDefinition::build($this->partitions);
+ }
+
return 'CREATE '
. OptionsArray::build($this->options) . ' '
. Expression::build($this->name) . ' '
. $fields
- . OptionsArray::build($this->entityOptions);
+ . OptionsArray::build($this->entityOptions)
+ . $partition;
} elseif ($this->options->has('VIEW')) {
return 'CREATE '
. OptionsArray::build($this->options) . ' '
@@ -318,6 +373,100 @@ class CreateStatement extends Statement
$list,
static::$TABLE_OPTIONS
);
+
+ /**
+ * The field that is being filled (`partitionBy` or
+ * `subpartitionBy`).
+ *
+ * @var string $field
+ */
+ $field = null;
+
+ /**
+ * The number of brackets. `false` means no bracket was found
+ * previously. At least one bracket is required to validate the
+ * expression.
+ *
+ * @var int|bool $brackets
+ */
+ $brackets = false;
+
+ /*
+ * Handles partitions.
+ */
+ for (; $list->idx < $list->count; ++$list->idx) {
+
+ /**
+ * Token parsed at this moment.
+ *
+ * @var Token $token
+ */
+ $token = $list->tokens[$list->idx];
+
+ // End of statement.
+ if ($token->type === Token::TYPE_DELIMITER) {
+ break;
+ }
+
+ // Skipping comments.
+ if ($token->type === Token::TYPE_COMMENT) {
+ continue;
+ }
+
+ if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'PARTITION BY')) {
+ $field = 'partitionBy';
+ $brackets = false;
+ } elseif (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'SUBPARTITION BY')) {
+ $field = 'subpartitionBy';
+ $brackets = false;
+ } elseif (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'PARTITIONS')) {
+ $token = $list->getNextOfType(Token::TYPE_NUMBER);
+ --$list->idx; // `getNextOfType` also advances one position.
+ $this->partitionsNum = $token->value;
+ } elseif (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'SUBPARTITIONS')) {
+ $token = $list->getNextOfType(Token::TYPE_NUMBER);
+ --$list->idx; // `getNextOfType` also advances one position.
+ $this->subpartitionsNum = $token->value;
+ } elseif (!empty($field)) {
+
+ /*
+ * Handling the content of `PARTITION BY` and `SUBPARTITION BY`.
+ */
+
+ // Counting brackets.
+ if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
+ // This is used instead of `++$brackets` because,
+ // initially, `$brackets` is `false` cannot be
+ // incremented.
+ $brackets = $brackets + 1;
+ } elseif (($token->type === Token::TYPE_OPERATOR) && ($token->value === ')')) {
+ --$brackets;
+ }
+
+ // Building the expression used for partitioning.
+ $this->$field .= ($token->type === Token::TYPE_WHITESPACE) ? ' ' : $token->token;
+
+ // Last bracket was read, the expression ended.
+ // Comparing with `0` and not `false`, because `false` means
+ // that no bracket was found and at least one must is
+ // required.
+ if ($brackets === 0) {
+ $this->$field = trim($this->$field);
+ $field = null;
+ }
+ } elseif (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
+ if (!empty($this->partitionBy)) {
+ $this->partitions = ArrayObj::parse(
+ $parser,
+ $list,
+ array(
+ 'type' => 'SqlParser\\Components\\PartitionDefinition'
+ )
+ );
+ }
+ break;
+ }
+ }
} elseif (($this->options->has('PROCEDURE'))
|| ($this->options->has('FUNCTION'))
) {
diff --git a/libraries/sql-parser/src/Token.php b/libraries/sql-parser/src/Token.php
index 3c36d1c375..d5343212cb 100644
--- a/libraries/sql-parser/src/Token.php
+++ b/libraries/sql-parser/src/Token.php
@@ -157,6 +157,7 @@ class Token
const FLAG_SYMBOL_VARIABLE = 1;
const FLAG_SYMBOL_BACKTICK = 2;
const FLAG_SYMBOL_USER = 4;
+ const FLAG_SYMBOL_SYSTEM = 8;
/**
* The token it its raw string representation.
@@ -256,7 +257,12 @@ class Token
if ((isset($str[0])) && ($str[0] === '@')) {
// `mb_strlen($str)` must be used instead of `null` because
// in PHP 5.3- the `null` parameter isn't handled correctly.
- $str = mb_substr($str, 1, mb_strlen($str), 'UTF-8');
+ $str = mb_substr(
+ $str,
+ ((!empty($str[1])) && ($str[1] === '@')) ? 2 : 1,
+ mb_strlen($str),
+ 'UTF-8'
+ );
}
if ((isset($str[0])) && (($str[0] === '`')
|| ($str[0] === '"') || ($str[0] === '\''))
diff --git a/libraries/sql-parser/src/Utils/BufferedQuery.php b/libraries/sql-parser/src/Utils/BufferedQuery.php
index e308fb2248..e58165ab27 100644
--- a/libraries/sql-parser/src/Utils/BufferedQuery.php
+++ b/libraries/sql-parser/src/Utils/BufferedQuery.php
@@ -91,14 +91,17 @@ class BufferedQuery
// Merges specified options with defaults.
$this->options = array_merge(
array(
+
/**
* The starting delimiter.
+ *
* @var string
*/
'delimiter' => ';',
/**
* Whether `DELIMITER` statements should be parsed.
+ *
* @var bool
*/
'parse_delimiter' => false,
@@ -106,6 +109,7 @@ class BufferedQuery
/**
* Whether a delimiter should be added at the end of the
* statement.
+ *
* @var bool
*/
'add_delimiter' => false,
@@ -156,6 +160,7 @@ class BufferedQuery
/**
* The length of the buffer.
+ *
* @var int $len
*/
$len = strlen($this->query);
diff --git a/libraries/sql-parser/src/Utils/Formatter.php b/libraries/sql-parser/src/Utils/Formatter.php
index dc8c3af31f..998d94b2b6 100644
--- a/libraries/sql-parser/src/Utils/Formatter.php
+++ b/libraries/sql-parser/src/Utils/Formatter.php
@@ -41,8 +41,12 @@ class Formatter
*/
public static $INLINE_CLAUSES = array(
'CREATE' => true,
- 'PROCEDURE' => true,
'LIMIT' => true,
+ 'PARTITION BY' => true,
+ 'PARTITION' => true,
+ 'PROCEDURE' => true,
+ 'SUBPARTITION BY' => true,
+ 'VALUES' => true,
);
/**
@@ -58,6 +62,7 @@ class Formatter
/**
* The format of the result.
+ *
* @var string The type ('text', 'cli' or 'html')
*/
'type' => php_sapi_name() == 'cli' ? 'cli' : 'text',
@@ -65,24 +70,28 @@ class Formatter
/**
* The line ending used.
* By default, for text this is "\n" and for HTML this is "
".
+ *
* @var string
*/
'line_ending' => $this->options['type'] == 'html' ? '
' : "\n",
/**
* The string used for indentation.
+ *
* @var string
*/
'indentation' => " ",
/**
* Whether comments should be removed or not.
+ *
* @var bool
*/
'remove_comments' => false,
/**
* Whether each clause should be on a new line.
+ *
* @var bool
*/
'clause_newline' => true,
@@ -90,12 +99,14 @@ class Formatter
/**
* Whether each part should be on a new line.
* Parts are delimited by brackets and commas.
+ *
* @var bool
*/
'parts_newline' => true,
/**
* Whether each part of each clause should be indented.
+ *
* @var bool
*/
'indent_parts' => true,
@@ -103,6 +114,7 @@ class Formatter
/**
* The styles used for HTML formatting.
* array($type, $flags, $span, $callback)
+ *
* @var array[]
*/
'formats' => array(
@@ -176,24 +188,28 @@ class Formatter
/**
* The query to be returned.
+ *
* @var string $ret
*/
$ret = '';
/**
* The indentation level.
+ *
* @var int $indent
*/
$indent = 0;
/**
* Whether the line ended.
+ *
* @var bool $lineEnded
*/
$lineEnded = false;
/**
* The name of the last clause.
+ *
* @var string $lastClause
*/
$lastClause = '';
@@ -201,6 +217,7 @@ class Formatter
/**
* A stack that keeps track of the indentation level every time a new
* block is found.
+ *
* @var array $blocksIndentation
*/
$blocksIndentation = array();
@@ -208,18 +225,21 @@ class Formatter
/**
* A stack that keeps track of the line endings every time a new block
* is found.
+ *
* @var array $blocksLineEndings
*/
$blocksLineEndings = array();
/**
* Whether clause's options were formatted.
+ *
* @var bool $formattedOptions
*/
$formattedOptions = false;
/**
* Previously parsed token.
+ *
* @var Token $prev
*/
$prev = null;
@@ -227,6 +247,7 @@ class Formatter
/**
* Comments are being formatted separately to maintain the whitespaces
* before and after them.
+ *
* @var string $comment
*/
$comment = '';
@@ -239,6 +260,7 @@ class Formatter
/**
* Token parsed at this moment.
+ *
* @var Token $curr
*/
$curr = $list->tokens[$list->idx];
@@ -368,7 +390,7 @@ class Formatter
if (!((($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 === ')')))
- // No space before . , )
+ // No space before . , ( )
|| (($curr->type === Token::TYPE_DELIMITER)) && (mb_strlen($curr->value, 'UTF-8') < 2))
// A space after delimiters that are longer than 2 characters.
|| ($prev->value === 'DELIMITER')
@@ -461,13 +483,15 @@ class Formatter
* This counter starts at one because by the time this function called,
* the list already advanced one position and the opening bracket was
* already parsed.
- * @var int
+ *
+ * @var int $count
*/
$count = 1;
/**
* The length of this group.
- * @var int
+ *
+ * @var int $length
*/
$length = 0;
diff --git a/libraries/sql-parser/src/Utils/Misc.php b/libraries/sql-parser/src/Utils/Misc.php
index 2107172317..1597648500 100644
--- a/libraries/sql-parser/src/Utils/Misc.php
+++ b/libraries/sql-parser/src/Utils/Misc.php
@@ -47,7 +47,8 @@ class Misc
/**
* Expressions that may contain aliases.
* These are extracted from `FROM` and `JOIN` keywords.
- * @var Expression[]
+ *
+ * @var Expression[] $expressions
*/
$expressions = $statement->from;
diff --git a/libraries/sql-parser/src/Utils/Query.php b/libraries/sql-parser/src/Utils/Query.php
index 6aff11de1d..5723ec6363 100644
--- a/libraries/sql-parser/src/Utils/Query.php
+++ b/libraries/sql-parser/src/Utils/Query.php
@@ -510,6 +510,7 @@ class Query
/**
* The index of the current clause.
+ *
* @var int $currIdx
*/
$currIdx = 0;
@@ -517,18 +518,21 @@ class Query
/**
* The count of brackets.
* We keep track of them so we won't insert the clause in a subquery.
+ *
* @var int $brackets
*/
$brackets = 0;
/**
* The string to be returned.
+ *
* @var string $ret
*/
$ret = '';
/**
* The clauses of this type of statement and their index.
+ *
* @var array $clauses
*/
$clauses = array_flip(array_keys($statement::$CLAUSES));
@@ -543,18 +547,21 @@ class Query
/**
* Lexer used for lexing the clause.
+ *
* @var Lexer $lexer
*/
$lexer = new Lexer($clause);
/**
* The type of this clause.
+ *
* @var string $clauseType
*/
$clauseType = $lexer->list->getNextOfType(Token::TYPE_KEYWORD)->value;
/**
* The index of this clause.
+ *
* @var int $clauseIdx
*/
$clauseIdx = $clauses[$clauseType];
@@ -680,6 +687,7 @@ class Query
/**
* Value to be returned.
+ *
* @var string $ret
*/
$ret = '';
@@ -730,13 +738,15 @@ class Query
/**
* Whether a full statement was found.
- * @var bool
+ *
+ * @var bool $fullStatement
*/
$fullStatement = false;
/**
* The first full statement.
- * @var string
+ *
+ * @var string $statement
*/
$statement = '';