Merge commit '2b1a68cc4eb935ef3df5c7401d0d1338df09bc72' into MAINT_4_5_5
This commit is contained in:
commit
5fb33a7af4
@ -26,19 +26,31 @@ class AlterOperation extends Component
|
||||
{
|
||||
|
||||
/**
|
||||
* All alter operations.
|
||||
* All database options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $OPTIONS = array(
|
||||
public static $DB_OPTIONS = array(
|
||||
'CHARACTER SET' => array(1, 'var'),
|
||||
'CHARSET' => array(1, 'var'),
|
||||
'DEFAULT CHARACTER SET' => array(1, 'var'),
|
||||
'DEFAULT CHARSET' => array(1, 'var'),
|
||||
'UPGRADE' => array(1, 'var'),
|
||||
'COLLATE' => array(2, 'var'),
|
||||
'DEFAULT COLLATE' => array(2, 'var'),
|
||||
);
|
||||
|
||||
// table_options
|
||||
/**
|
||||
* All table options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $TABLE_OPTIONS = array(
|
||||
'ENGINE' => array(1, 'var='),
|
||||
'AUTO_INCREMENT' => array(1, 'var='),
|
||||
'AVG_ROW_LENGTH' => array(1, 'var'),
|
||||
'MAX_ROWS' => array(1, 'var'),
|
||||
'ROW_FORMAT' => array(1, 'var'),
|
||||
|
||||
'ADD' => 1,
|
||||
'ALTER' => 1,
|
||||
'ANALYZE' => 1,
|
||||
@ -60,6 +72,7 @@ class AlterOperation extends Component
|
||||
'RENAME' => 1,
|
||||
'REORGANIZE' => 1,
|
||||
'REPAIR' => 1,
|
||||
'UPGRADE' => 1,
|
||||
|
||||
'COLUMN' => 2,
|
||||
'CONSTRAINT' => 2,
|
||||
@ -75,11 +88,15 @@ class AlterOperation extends Component
|
||||
'SPATIAL' => 2,
|
||||
'TABLESPACE' => 2,
|
||||
'INDEX' => 2,
|
||||
);
|
||||
|
||||
'DEFAULT CHARACTER SET' => array(3, 'var'),
|
||||
'DEFAULT CHARSET' => array(3, 'var'),
|
||||
|
||||
'COLLATE' => array(4, 'var'),
|
||||
/**
|
||||
* All view options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $VIEW_OPTIONS = array(
|
||||
'AS' => 1,
|
||||
);
|
||||
|
||||
/**
|
||||
@ -165,7 +182,18 @@ class AlterOperation extends Component
|
||||
}
|
||||
|
||||
if ($state === 0) {
|
||||
$ret->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
|
||||
$ret->options = OptionsArray::parse($parser, $list, $options);
|
||||
|
||||
if ($ret->options->has('AS')) {
|
||||
for (; $list->idx < $list->count; ++$list->idx) {
|
||||
if ($list->tokens[$list->idx]->type === Token::TYPE_DELIMITER) {
|
||||
break;
|
||||
}
|
||||
$ret->unknown[] = $list->tokens[$list->idx];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$state = 1;
|
||||
} elseif ($state === 1) {
|
||||
$ret->field = Expression::parse(
|
||||
|
||||
@ -108,7 +108,7 @@ class ArrayObj extends Component
|
||||
|| ($token->type === Token::TYPE_COMMENT)
|
||||
) {
|
||||
$lastRaw .= $token->token;
|
||||
$lastValue = trim($lastValue) .' ';
|
||||
$lastValue = trim($lastValue) . ' ';
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@ -166,7 +166,10 @@ class Condition extends Component
|
||||
}
|
||||
}
|
||||
|
||||
if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) {
|
||||
if (($token->type === Token::TYPE_KEYWORD)
|
||||
&& ($token->flags & Token::FLAG_KEYWORD_RESERVED)
|
||||
&& !($token->flags & Token::FLAG_KEYWORD_FUNCTION)
|
||||
) {
|
||||
if ($token->value === 'BETWEEN') {
|
||||
$betweenBefore = true;
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ class CreateDefinition extends Component
|
||||
|
||||
'NOT NULL' => 1,
|
||||
'NULL' => 1,
|
||||
'DEFAULT' => array(2, 'expr'),
|
||||
'DEFAULT' => array(2, 'expr', array('breakOnAlias' => true)),
|
||||
'AUTO_INCREMENT' => 3,
|
||||
'PRIMARY' => 4,
|
||||
'PRIMARY KEY' => 4,
|
||||
|
||||
@ -243,9 +243,9 @@ class Expression extends Component
|
||||
if (!empty($options['breakOnAlias'])) {
|
||||
break;
|
||||
}
|
||||
if (!empty($ret->alias)) {
|
||||
if ($alias) {
|
||||
$parser->error(
|
||||
__('An alias was previously found.'),
|
||||
__('An alias was expected.'),
|
||||
$token
|
||||
);
|
||||
break;
|
||||
|
||||
@ -63,6 +63,13 @@ class JoinKeyword extends Component
|
||||
*/
|
||||
public $on;
|
||||
|
||||
/**
|
||||
* Columns in Using clause
|
||||
*
|
||||
* @var ArrayObj
|
||||
*/
|
||||
public $using;
|
||||
|
||||
/**
|
||||
* @param Parser $parser The parser that serves as context.
|
||||
* @param TokensList $list The list of tokens that are being parsed.
|
||||
@ -86,9 +93,12 @@ class JoinKeyword extends Component
|
||||
* 1 -----------------------[ expr ]----------------------> 2
|
||||
*
|
||||
* 2 ------------------------[ ON ]-----------------------> 3
|
||||
* 2 -----------------------[ USING ]---------------------> 4
|
||||
*
|
||||
* 3 --------------------[ conditions ]-------------------> 0
|
||||
*
|
||||
* 4 ----------------------[ columns ]--------------------> 0
|
||||
*
|
||||
* @var int $state
|
||||
*/
|
||||
$state = 0;
|
||||
@ -131,14 +141,23 @@ class JoinKeyword extends Component
|
||||
$expr->expr = Expression::parse($parser, $list, array('field' => 'table'));
|
||||
$state = 2;
|
||||
} elseif ($state === 2) {
|
||||
if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'ON')) {
|
||||
$state = 3;
|
||||
if ($token->type === Token::TYPE_KEYWORD) {
|
||||
if ($token->value === 'ON') {
|
||||
$state = 3;
|
||||
} elseif ($token->value === 'USING') {
|
||||
$state = 4;
|
||||
}
|
||||
}
|
||||
} elseif ($state === 3) {
|
||||
$expr->on = Condition::parse($parser, $list);
|
||||
$ret[] = $expr;
|
||||
$expr = new JoinKeyword();
|
||||
$state = 0;
|
||||
} elseif ($state === 4) {
|
||||
$expr->using = ArrayObj::parse($parser, $list);
|
||||
$ret[] = $expr;
|
||||
$expr = new JoinKeyword();
|
||||
$state = 0;
|
||||
}
|
||||
|
||||
}
|
||||
@ -161,8 +180,10 @@ class JoinKeyword extends Component
|
||||
{
|
||||
$ret = array();
|
||||
foreach ($component as $c) {
|
||||
$ret[] = array_search($c->type, static::$JOINS) . ' '
|
||||
. $c->expr . ' ON ' . Condition::build($c->on);
|
||||
$ret[] = array_search($c->type, static::$JOINS) . ' ' . $c->expr
|
||||
. (!empty($c->on)
|
||||
? ' ON ' . Condition::build($c->on)
|
||||
: ' USING ' . ArrayObj::build($c->using));
|
||||
}
|
||||
return implode(' ', $ret);
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ class Key extends Component
|
||||
* @param TokensList $list The list of tokens that are being parsed.
|
||||
* @param array $options Parameters for parsing.
|
||||
*
|
||||
* @return Key[]
|
||||
* @return Key
|
||||
*/
|
||||
public static function parse(Parser $parser, TokensList $list, array $options = array())
|
||||
{
|
||||
|
||||
@ -128,7 +128,7 @@ class Limit extends Component
|
||||
public static function build($component, array $options = array())
|
||||
{
|
||||
if (empty($component->offset)) {
|
||||
return $component->rowCount;
|
||||
return (string) $component->rowCount;
|
||||
} else {
|
||||
return $component->offset . ', ' . $component->rowCount;
|
||||
}
|
||||
|
||||
@ -287,10 +287,12 @@ class OptionsArray extends Component
|
||||
public function has($key, $getExpr = false)
|
||||
{
|
||||
foreach ($this->options as $option) {
|
||||
if ($key === $option) {
|
||||
if (is_array($option)) {
|
||||
if (!strcasecmp($key, $option['name'])) {
|
||||
return $getExpr ? $option['expr'] : $option['value'];
|
||||
}
|
||||
} elseif (!strcasecmp($key, $option)) {
|
||||
return true;
|
||||
} elseif ((is_array($option)) && ($key === $option['name'])) {
|
||||
return $getExpr ? $option['expr'] : $option['value'];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -306,9 +308,12 @@ class OptionsArray extends Component
|
||||
public function remove($key)
|
||||
{
|
||||
foreach ($this->options as $idx => $option) {
|
||||
if (($key === $option)
|
||||
|| ((is_array($option)) && ($key === $option['name']))
|
||||
) {
|
||||
if (is_array($option)) {
|
||||
if (!strcasecmp($key, $option['name'])) {
|
||||
unset($this->options[$idx]);
|
||||
return true;
|
||||
}
|
||||
} elseif (!strcasecmp($key, $option)) {
|
||||
unset($this->options[$idx]);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -100,9 +100,13 @@ class OrderKeyword extends Component
|
||||
$expr->expr = Expression::parse($parser, $list);
|
||||
$state = 1;
|
||||
} elseif ($state === 1) {
|
||||
if (($token->type === Token::TYPE_KEYWORD) && (($token->value === 'ASC') || ($token->value === 'DESC'))) {
|
||||
if (($token->type === Token::TYPE_KEYWORD)
|
||||
&& (($token->value === 'ASC') || ($token->value === 'DESC'))
|
||||
) {
|
||||
$expr->type = $token->value;
|
||||
} elseif (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) {
|
||||
} elseif (($token->type === Token::TYPE_OPERATOR)
|
||||
&& ($token->value === ',')
|
||||
) {
|
||||
if (!empty($expr->expr)) {
|
||||
$ret[] = $expr;
|
||||
}
|
||||
|
||||
@ -85,7 +85,10 @@ class SetOperation extends Component
|
||||
}
|
||||
|
||||
// No keyword is expected.
|
||||
if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED) && ($state == 0)) {
|
||||
if (($token->type === Token::TYPE_KEYWORD)
|
||||
&& ($token->flags & Token::FLAG_KEYWORD_RESERVED)
|
||||
&& ($state == 0)
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -104,7 +107,6 @@ class SetOperation extends Component
|
||||
)
|
||||
);
|
||||
if ($tmp == null) {
|
||||
$expr = null;
|
||||
break;
|
||||
}
|
||||
$expr->column = trim($expr->column);
|
||||
|
||||
@ -185,6 +185,11 @@ class Parser
|
||||
'class' => 'SqlParser\\Components\\JoinKeyword',
|
||||
'field' => 'join',
|
||||
),
|
||||
'ON' => array(
|
||||
'class' => 'SqlParser\\Components\\Expression',
|
||||
'field' => 'table',
|
||||
'options' => array('parseField' => 'table'),
|
||||
),
|
||||
'RIGHT JOIN' => array(
|
||||
'class' => 'SqlParser\\Components\\JoinKeyword',
|
||||
'field' => 'join',
|
||||
|
||||
@ -51,6 +51,15 @@ class AlterStatement extends Statement
|
||||
'ONLINE' => 1,
|
||||
'OFFLINE' => 1,
|
||||
'IGNORE' => 2,
|
||||
|
||||
'DATABASE' => 3,
|
||||
'EVENT' => 3,
|
||||
'FUNCTION' => 3,
|
||||
'PROCEDURE' => 3,
|
||||
'SERVER' => 3,
|
||||
'TABLE' => 3,
|
||||
'TABLESPACE' => 3,
|
||||
'VIEW' => 3,
|
||||
);
|
||||
|
||||
/**
|
||||
@ -67,16 +76,14 @@ class AlterStatement extends Statement
|
||||
$list,
|
||||
static::$OPTIONS
|
||||
);
|
||||
|
||||
// Skipping `TABLE`.
|
||||
$list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'TABLE');
|
||||
++$list->idx;
|
||||
|
||||
// Parsing affected table.
|
||||
$this->table = Expression::parse(
|
||||
$parser,
|
||||
$list,
|
||||
array(
|
||||
'parseField' => 'column',
|
||||
'parseField' => 'table',
|
||||
'breakOnAlias' => true,
|
||||
)
|
||||
);
|
||||
@ -114,7 +121,16 @@ class AlterStatement extends Statement
|
||||
}
|
||||
|
||||
if ($state === 0) {
|
||||
$this->altered[] = AlterOperation::parse($parser, $list);
|
||||
$options = array();
|
||||
if ($this->options->has('DATABASE')) {
|
||||
$options = AlterOperation::$DB_OPTIONS;
|
||||
} elseif ($this->options->has('TABLE')) {
|
||||
$options = AlterOperation::$TABLE_OPTIONS;
|
||||
} elseif ($this->options->has('VIEW')) {
|
||||
$options = AlterOperation::$VIEW_OPTIONS;
|
||||
}
|
||||
|
||||
$this->altered[] = AlterOperation::parse($parser, $list, $options);
|
||||
$state = 1;
|
||||
} elseif ($state === 1) {
|
||||
if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) {
|
||||
@ -135,7 +151,7 @@ class AlterStatement extends Statement
|
||||
}
|
||||
|
||||
return 'ALTER ' . OptionsArray::build($this->options)
|
||||
. ' TABLE ' . Expression::build($this->table)
|
||||
. ' ' . Expression::build($this->table)
|
||||
. ' ' . implode(', ', $tmp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,6 +53,9 @@ class CreateStatement extends Statement
|
||||
'EVENT' => 6,
|
||||
'FUNCTION' => 6,
|
||||
'INDEX' => 6,
|
||||
'UNIQUE INDEX' => 6,
|
||||
'FULLTEXT INDEX' => 6,
|
||||
'SPATIAL INDEX' => 6,
|
||||
'PROCEDURE' => 6,
|
||||
'SERVER' => 6,
|
||||
'TABLE' => 6,
|
||||
@ -314,13 +317,11 @@ class CreateStatement extends Statement
|
||||
. Expression::build($this->name) . ' '
|
||||
. ParameterDefinition::build($this->parameters) . ' '
|
||||
. $tmp . ' ' . TokensList::build($this->body);
|
||||
} else {
|
||||
return 'CREATE '
|
||||
. OptionsArray::build($this->options) . ' '
|
||||
. Expression::build($this->name) . ' '
|
||||
. TokensList::build($this->body);
|
||||
}
|
||||
return '';
|
||||
return 'CREATE '
|
||||
. OptionsArray::build($this->options) . ' '
|
||||
. Expression::build($this->name) . ' '
|
||||
. TokensList::build($this->body);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -59,6 +59,7 @@ class DropStatement extends Statement
|
||||
'_OPTIONS' => array('_OPTIONS', 1),
|
||||
// Used for select expressions.
|
||||
'DROP_' => array('DROP', 1),
|
||||
'ON' => array('ON', 3),
|
||||
);
|
||||
|
||||
/**
|
||||
@ -67,4 +68,11 @@ class DropStatement extends Statement
|
||||
* @var Expression[]
|
||||
*/
|
||||
public $fields;
|
||||
|
||||
/**
|
||||
* Table of the dropped index.
|
||||
*
|
||||
* @var Expression
|
||||
*/
|
||||
public $table;
|
||||
}
|
||||
|
||||
@ -235,17 +235,17 @@ class Token
|
||||
if ($this->flags & Token::FLAG_NUMBER_HEX) {
|
||||
if ($this->flags & Token::FLAG_NUMBER_NEGATIVE) {
|
||||
$ret = str_replace('-', '', $this->token);
|
||||
sscanf($ret, "%x", $ret);
|
||||
sscanf($ret, '%x', $ret);
|
||||
$ret = -$ret;
|
||||
} else {
|
||||
sscanf($ret, "%x", $ret);
|
||||
sscanf($ret, '%x', $ret);
|
||||
}
|
||||
} elseif (($this->flags & Token::FLAG_NUMBER_APPROXIMATE)
|
||||
|| ($this->flags & Token::FLAG_NUMBER_FLOAT)
|
||||
) {
|
||||
sscanf($ret, "%f", $ret);
|
||||
sscanf($ret, '%f', $ret);
|
||||
} else {
|
||||
sscanf($ret, "%d", $ret);
|
||||
sscanf($ret, '%d', $ret);
|
||||
}
|
||||
return $ret;
|
||||
case Token::TYPE_STRING:
|
||||
|
||||
@ -80,7 +80,7 @@ class Formatter
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
'indentation' => " ",
|
||||
'indentation' => ' ',
|
||||
|
||||
/**
|
||||
* Whether comments should be removed or not.
|
||||
@ -122,49 +122,49 @@ class Formatter
|
||||
'type' => Token::TYPE_KEYWORD,
|
||||
'flags' => Token::FLAG_KEYWORD_RESERVED,
|
||||
'html' => 'class="sql-reserved"',
|
||||
'cli' => "\e[35m",
|
||||
'cli' => "\e[35m",
|
||||
'function' => 'strtoupper',
|
||||
),
|
||||
array(
|
||||
'type' => Token::TYPE_KEYWORD,
|
||||
'flags' => 0,
|
||||
'html' => 'class="sql-keyword"',
|
||||
'cli' => "\e[95m",
|
||||
'cli' => "\e[95m",
|
||||
'function' => 'strtoupper',
|
||||
),
|
||||
array(
|
||||
'type' => Token::TYPE_COMMENT,
|
||||
'flags' => 0,
|
||||
'html' => 'class="sql-comment"',
|
||||
'cli' => "\e[37m",
|
||||
'cli' => "\e[37m",
|
||||
'function' => '',
|
||||
),
|
||||
array(
|
||||
'type' => Token::TYPE_BOOL,
|
||||
'flags' => 0,
|
||||
'html' => 'class="sql-atom"',
|
||||
'cli' => "\e[36m",
|
||||
'cli' => "\e[36m",
|
||||
'function' => 'strtoupper',
|
||||
),
|
||||
array(
|
||||
'type' => Token::TYPE_NUMBER,
|
||||
'flags' => 0,
|
||||
'html' => 'class="sql-number"',
|
||||
'cli' => "\e[92m",
|
||||
'cli' => "\e[92m",
|
||||
'function' => 'strtolower',
|
||||
),
|
||||
array(
|
||||
'type' => Token::TYPE_STRING,
|
||||
'flags' => 0,
|
||||
'html' => 'class="sql-string"',
|
||||
'cli' => "\e[91m",
|
||||
'cli' => "\e[91m",
|
||||
'function' => '',
|
||||
),
|
||||
array(
|
||||
'type' => Token::TYPE_SYMBOL,
|
||||
'flags' => 0,
|
||||
'html' => 'class="sql-variable"',
|
||||
'cli' => "\e[36m",
|
||||
'cli' => "\e[36m",
|
||||
'function' => '',
|
||||
),
|
||||
)
|
||||
@ -387,7 +387,8 @@ class Formatter
|
||||
// Also, some tokens do not have spaces before or after them.
|
||||
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 === ')')))
|
||||
|| (($curr->type === Token::TYPE_OPERATOR) && (($curr->value === '.') || ($curr->value === ',')
|
||||
|| ($curr->value === '(') || ($curr->value === ')')))
|
||||
// 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.
|
||||
|
||||
@ -57,8 +57,8 @@ class Query
|
||||
/**
|
||||
* Gets an array with flags this statement has.
|
||||
*
|
||||
* @param Statement $statement The statement to be processed.
|
||||
* @param bool $all If `false`, false values will not be included.
|
||||
* @param Statement|null $statement The statement to be processed.
|
||||
* @param bool $all If `false`, false values will not be included.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@ -380,7 +380,7 @@ class Query
|
||||
$parser = new Parser($query);
|
||||
|
||||
if (empty($parser->statements[0])) {
|
||||
return array();
|
||||
return static::getFlags(null, true);
|
||||
}
|
||||
|
||||
$statement = $parser->statements[0];
|
||||
|
||||
Loading…
Reference in New Issue
Block a user