commit
09837fade0
@ -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];
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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];
|
||||
|
||||
219
libraries/sql-parser/src/Components/PartitionDefinition.php
Normal file
219
libraries/sql-parser/src/Components/PartitionDefinition.php
Normal file
@ -0,0 +1,219 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Parses the create definition of a partition.
|
||||
*
|
||||
* Used for parsing `CREATE TABLE` statement.
|
||||
*
|
||||
* @package SqlParser
|
||||
* @subpackage Components
|
||||
*/
|
||||
namespace SqlParser\Components;
|
||||
|
||||
use SqlParser\Context;
|
||||
use SqlParser\Component;
|
||||
use SqlParser\Parser;
|
||||
use SqlParser\Token;
|
||||
use SqlParser\TokensList;
|
||||
|
||||
/**
|
||||
* Parses the create definition of a partition.
|
||||
*
|
||||
* Used for parsing `CREATE TABLE` statement.
|
||||
*
|
||||
* @category Components
|
||||
* @package SqlParser
|
||||
* @subpackage Components
|
||||
* @author Dan Ungureanu <udan1107@gmail.com>
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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];
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
|
||||
@ -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 = '';
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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'))
|
||||
) {
|
||||
|
||||
@ -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] === '\''))
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 "<br/>".
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
'line_ending' => $this->options['type'] == 'html' ? '<br/>' : "\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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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 = '';
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user