作者:TheBlackBloodyUnicor
项目:pico_wanderblo
/**
* Function called after the token was processed.
*
* Parses the additional options from the end.
*
* @param Parser $parser The instance that requests parsing.
* @param TokensList $list The list of tokens to be parsed.
* @param Token $token The token that is being parsed.
*
* @return void
*/
public function after(Parser $parser, TokensList $list, Token $token)
{
// [some options] is going to be parsed first.
//
// There is a parser specified in `Parser::$KEYWORD_PARSERS`
// which parses the name of the tables.
//
// Finally, we parse here [some more options] and that's all.
++$list->idx;
$this->options->merge(OptionsArray::parse($parser, $list, static::$OPTIONS));
}
作者:scriptpaza
项目:phpmyadmi
/**
* @return string
*/
public function build()
{
$ret = OptionsArray::build($this->options);
if ($this->type === TransactionStatement::TYPE_BEGIN) {
foreach ($this->statements as $statement) {
$ret .= ';' . $statement->build();
}
$ret .= ';' . $this->end->build();
}
return $ret;
}
作者:saisa
项目:phpmyadmi
/**
* @param FieldDefinition|FieldDefinition[] $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 {
$tmp = '';
if ($component->isConstraint) {
$tmp .= 'CONSTRAINT ';
}
if (!empty($component->name)) {
$tmp .= Context::escape($component->name) . ' ';
}
if (!empty($component->type)) {
$tmp .= DataType::build($component->type) . ' ';
}
if (!empty($component->key)) {
$tmp .= Key::build($component->key) . ' ';
}
if (!empty($component->references)) {
$tmp .= 'REFERENCES ' . Reference::build($component->references) . ' ';
}
$tmp .= OptionsArray::build($component->options);
return trim($tmp);
}
}
作者:WSDC-NITWaranga
项目:phpmyadmi
/**
* @param Key $component The component to be built.
*
* @return string
*/
public static function build($component)
{
$ret = $component->type . ' ';
if (!empty($component->name)) {
$ret .= Context::escape($component->name) . ' ';
}
$ret .= '(' . implode(',', Context::escape($component->columns)) . ')';
$ret .= OptionsArray::build($component->options);
return trim($ret);
}
作者:phpmyadmi
项目:sql-parse
/**
* @return string
*/
public function build()
{
return 'SET ' . OptionsArray::build($this->options) . ' ' . SetOperation::build($this->set);
}
作者:FuhrerMalkovic
项目:Blogpos
/**
* @param Parser $parser The instance that requests parsing.
* @param TokensList $list The list of tokens to be parsed.
*
* @return void
*/
public function parse(Parser $parser, TokensList $list)
{
++$list->idx;
// Skipping `CREATE`.
// Parsing options.
$this->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
++$list->idx;
// Skipping last option.
// Parsing the field name.
$this->name = Expression::parse($parser, $list, array('noAlias' => true, 'noBrackets' => true, 'skipColumn' => true));
if (!isset($this->name) || $this->name === '') {
$parser->error(__('The name of the entity was expected.'), $list->tokens[$list->idx]);
} else {
++$list->idx;
// Skipping field.
}
if ($this->options->has('DATABASE')) {
$this->entityOptions = OptionsArray::parse($parser, $list, static::$DB_OPTIONS);
} elseif ($this->options->has('TABLE')) {
$this->fields = CreateDefinition::parse($parser, $list);
if (empty($this->fields)) {
$parser->error(__('At least one column definition was expected.'), $list->tokens[$list->idx]);
}
++$list->idx;
$this->entityOptions = OptionsArray::parse($parser, $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) {
//.........这里部分代码省略.........
作者:scriptpaza
项目:phpmyadmi
/**
* Parses the statements defined by the tokens list.
*
* @param Parser $parser The instance that requests parsing.
* @param TokensList $list The list of tokens to be parsed.
*
* @return void
*/
public function parse(Parser $parser, TokensList $list)
{
/**
* Whether the beginning of this statement was previously parsed.
*
* This is used to delimit statements that don't use the usual
* delimiters.
*
* @var bool
*/
$parsedBeginning = false;
// This may be corrected by the parser.
$this->first = $list->idx;
/**
* 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];
// End of statement.
if ($token->type === Token::TYPE_DELIMITER) {
break;
}
// Only keywords are relevant here. Other parts of the query are
// processed in the functions below.
if ($token->type !== Token::TYPE_KEYWORD) {
if ($token->type !== TOKEN::TYPE_COMMENT && $token->type !== Token::TYPE_WHITESPACE) {
$parser->error(__('Unexpected token.'), $token);
}
continue;
}
// Unions are parsed by the parser because they represent more than
// one statement.
if ($token->value === 'UNION') {
break;
}
/**
* The name of the class that is used for parsing.
* @var string $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();
if (!empty(Parser::$KEYWORD_PARSERS[$token->value])) {
$class = Parser::$KEYWORD_PARSERS[$token->value]['class'];
$field = Parser::$KEYWORD_PARSERS[$token->value]['field'];
if (!empty(Parser::$KEYWORD_PARSERS[$token->value]['options'])) {
$options = Parser::$KEYWORD_PARSERS[$token->value]['options'];
}
}
if (!empty(Parser::$STATEMENT_PARSERS[$token->value])) {
if ($parsedBeginning) {
// New statement has started. We let the parser construct a
// new statement and parse that one
$parser->error(__('A new statement was found, but no delimiter between them.'), $token);
break;
}
$parsedBeginning = true;
if (!$parsedOptions) {
if (empty(static::$OPTIONS[$token->value])) {
// Skipping keyword because if it is not a option.
++$list->idx;
}
$this->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
$parsedOptions = true;
}
} elseif ($class === null) {
// There is no parser for this keyword and isn't the beginning
// of a statement (so no options) either.
$parser->error(__('Unrecognized keyword.'), $token);
continue;
}
$this->before($parser, $list, $token);
// Parsing this keyword.
if ($class !== null) {
++$list->idx;
// Skipping keyword or last option.
//.........这里部分代码省略.........
作者:elrossco2
项目:sql-parse
public function testBuild()
{
$component = new OptionsArray(array('ALL', 'SQL_CALC_FOUND_ROWS', array('name' => 'MAX_STATEMENT_TIME', 'value' => '42', 'equals' => true)));
$this->assertEquals(OptionsArray::build($component), 'ALL SQL_CALC_FOUND_ROWS MAX_STATEMENT_TIME=42');
}
作者:TheBlackBloodyUnicor
项目:pico_wanderblo
/**
* @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 Key[]
*/
public static function parse(Parser $parser, TokensList $list, array $options = array())
{
$ret = new Key();
/**
* Last parsed column.
*
* @var array
*/
$lastColumn = array();
/**
* The state of the parser.
*
* Below are the states of the parser.
*
* 0 ----------------------[ type ]-----------------------> 1
*
* 1 ----------------------[ name ]-----------------------> 1
* 1 ---------------------[ columns ]---------------------> 2
*
* 2 ---------------------[ options ]---------------------> 3
*
* @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->type = $token->value;
$state = 1;
} elseif ($state === 1) {
if ($token->type === Token::TYPE_OPERATOR && $token->value === '(') {
$state = 2;
} else {
$ret->name = $token->value;
}
} elseif ($state === 2) {
if ($token->type === Token::TYPE_OPERATOR) {
if ($token->value === '(') {
$state = 3;
} elseif ($token->value === ',' || $token->value === ')') {
$state = $token->value === ',' ? 2 : 4;
if (!empty($lastColumn)) {
$ret->columns[] = $lastColumn;
$lastColumn = array();
}
}
} else {
$lastColumn['name'] = $token->value;
}
} elseif ($state === 3) {
if ($token->type === Token::TYPE_OPERATOR && $token->value === ')') {
$state = 2;
} else {
$lastColumn['length'] = $token->value;
}
} elseif ($state === 4) {
$ret->options = OptionsArray::parse($parser, $list, static::$KEY_OPTIONS);
++$list->idx;
break;
}
}
--$list->idx;
return $ret;
}
作者:remicolle
项目:sql-parse
/**
* @param Parser $parser The instance that requests parsing.
* @param TokensList $list The list of tokens to be parsed.
*
* @return void
*/
public function parse(Parser $parser, TokensList $list)
{
++$list->idx;
// Skipping `INSERT`.
// parse any options if provided
$this->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
++$list->idx;
$token = $list->tokens[$list->idx];
/**
* The state of the parser.
*
* Below are the states of the parser.
*
* 0 ---------------------------------[ INTO ]----------------------------------> 1
*
* 1 -------------------------[ VALUES/VALUE/SET/SELECT ]-----------------------> 2
*
* 2 -------------------------[ ON DUPLICATE KEY UPDATE ]-----------------------> 3
*
* @var int $state
*/
$state = 0;
/**
* For keeping track of semi-states on encountering
* ON DUPLICATE KEY UPDATE ...
*
*/
$miniState = 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) {
if ($token->type === Token::TYPE_KEYWORD && $token->value !== 'INTO') {
$parser->error(__('Unexpected keyword.'), $token);
break;
} else {
++$list->idx;
$this->into = IntoKeyword::parse($parser, $list);
}
$state = 1;
} elseif ($state === 1) {
if ($token->type === Token::TYPE_KEYWORD) {
if ($token->value === 'VALUE' || $token->value === 'VALUES') {
++$list->idx;
// skip VALUES
$this->values = Array2d::parse($parser, $list);
} elseif ($token->value === 'SET') {
++$list->idx;
// skip SET
$this->set = SetOperation::parse($parser, $list);
} elseif ($token->value === 'SELECT') {
$this->select = new SelectStatement($parser, $list);
} else {
$parser->error(__('Unexpected keyword.'), $token);
break;
}
$state = 2;
$miniState = 1;
} else {
$parser->error(__('Unexpected token.'), $token);
break;
}
} elseif ($state == 2) {
$lastCount = $miniState;
if ($miniState === 1 && $token->value === 'ON') {
$miniState++;
} elseif ($miniState === 2 && $token->value === 'DUPLICATE') {
$miniState++;
} elseif ($miniState === 3 && $token->value === 'KEY') {
$miniState++;
} elseif ($miniState === 4 && $token->value === 'UPDATE') {
$miniState++;
}
if ($lastCount === $miniState) {
$parser->error(__('Unexpected token.'), $token);
break;
}
if ($miniState === 5) {
++$list->idx;
$this->onDuplicateSet = SetOperation::parse($parser, $list);
$state = 3;
}
//.........这里部分代码省略.........
作者:remicolle
项目:sql-parse
/**
* @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 AlterOperation
*/
public static function parse(Parser $parser, TokensList $list, array $options = array())
{
$ret = new AlterOperation();
/**
* Counts brackets.
*
* @var int $brackets
*/
$brackets = 0;
/**
* The state of the parser.
*
* Below are the states of the parser.
*
* 0 ---------------------[ options ]---------------------> 1
*
* 1 ----------------------[ field ]----------------------> 2
*
* 2 -------------------------[ , ]-----------------------> 0
*
* @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 comments.
if ($token->type === Token::TYPE_COMMENT) {
continue;
}
// Skipping whitespaces.
if ($token->type === Token::TYPE_WHITESPACE) {
if ($state === 2) {
// When parsing the unknown part, the whitespaces are
// included to not break anything.
$ret->unknown[] = $token;
}
continue;
}
if ($state === 0) {
$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($parser, $list, array('breakOnAlias' => true, 'parseField' => 'column'));
if ($ret->field === null) {
// No field was read. We go back one token so the next
// iteration will parse the same token, but in state 2.
--$list->idx;
}
$state = 2;
} elseif ($state === 2) {
if ($token->type === Token::TYPE_OPERATOR) {
if ($token->value === '(') {
++$brackets;
} elseif ($token->value === ')') {
--$brackets;
} elseif ($token->value === ',' && $brackets === 0) {
break;
}
} elseif (!empty(Parser::$STATEMENT_PARSERS[$token->value])) {
// We have reached the end of ALTER operation and suddenly found
// a start to new statement, but have not find a delimiter between them
if (!($token->value == 'SET' && $list->tokens[$list->idx - 1]->value == 'CHARACTER')) {
$parser->error(__('A new statement was found, but no delimiter between it and the previous one.'), $token);
break;
}
}
$ret->unknown[] = $token;
}
}
if ($ret->options->isEmpty()) {
$parser->error(__('Unrecognized alter operation.'), $list->tokens[$list->idx]);
}
--$list->idx;
return $ret;
}
作者:WSDC-NITWaranga
项目:phpmyadmi
/**
* @param DataType $component The component to be built.
*
* @return string
*/
public static function build($component)
{
$tmp = '';
if (!empty($component->parameters)) {
$tmp = '(' . implode(',', $component->parameters) . ')';
}
return trim(strtolower($component->name) . $tmp . ' ' . OptionsArray::build($component->options));
}
作者:phpmyadmi
项目:sql-parse
/**
* @param Parser $parser The instance that requests parsing.
* @param TokensList $list The list of tokens to be parsed.
*
* @return void
*/
public function parse(Parser $parser, TokensList $list)
{
++$list->idx;
// Skipping `REPLACE`.
// parse any options if provided
$this->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
++$list->idx;
$token = $list->tokens[$list->idx];
/**
* The state of the parser.
*
* Below are the states of the parser.
*
* 0 ---------------------------------[ INTO ]----------------------------------> 1
*
* 1 -------------------------[ VALUES/VALUE/SET/SELECT ]-----------------------> 2
*
* @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) {
if ($token->type === Token::TYPE_KEYWORD && $token->value !== 'INTO') {
$parser->error(__('Unexpected keyword.'), $token);
break;
} else {
++$list->idx;
$this->into = IntoKeyword::parse($parser, $list, array('fromReplace' => true));
}
$state = 1;
} elseif ($state === 1) {
if ($token->type === Token::TYPE_KEYWORD) {
if ($token->value === 'VALUE' || $token->value === 'VALUES') {
++$list->idx;
// skip VALUES
$this->values = Array2d::parse($parser, $list);
} elseif ($token->value === 'SET') {
++$list->idx;
// skip SET
$this->set = SetOperation::parse($parser, $list);
} elseif ($token->value === 'SELECT') {
$this->select = new SelectStatement($parser, $list);
} else {
$parser->error(__('Unexpected keyword.'), $token);
break;
}
$state = 2;
} else {
$parser->error(__('Unexpected token.'), $token);
break;
}
}
}
--$list->idx;
}
作者:WSDC-NITWaranga
项目:phpmyadmi
/**
* @param Reference $component The component to be built.
*
* @return string
*/
public static function build($component)
{
return trim(Context::escape($component->table) . ' (' . implode(', ', Context::escape($component->columns)) . ') ' . OptionsArray::build($component->options));
}
作者:phpmyadmi
项目:sql-parse
//.........这里部分代码省略.........
// Unions are parsed by the parser because they represent more than
// one statement.
if ($token->value === 'UNION' || $token->value === 'UNION ALL' || $token->value === 'UNION DISTINCT') {
break;
}
$lastIdx = $list->idx;
// ON DUPLICATE KEY UPDATE ...
// has to be parsed in parent statement (INSERT or REPLACE)
// so look for it and break
if (get_class($this) === 'SqlParser\\Statements\\SelectStatement' && $token->value === 'ON') {
++$list->idx;
// Skip ON
// look for ON DUPLICATE KEY UPDATE
$first = $list->getNextOfType(Token::TYPE_KEYWORD);
$second = $list->getNextOfType(Token::TYPE_KEYWORD);
$third = $list->getNextOfType(Token::TYPE_KEYWORD);
if ($first && $second && $third && $first->value === 'DUPLICATE' && $second->value === 'KEY' && $third->value === 'UPDATE') {
$list->idx = $lastIdx;
break;
}
}
$list->idx = $lastIdx;
/**
* 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();
// Looking for duplicated clauses.
if (!empty(Parser::$KEYWORD_PARSERS[$token->value]) || !empty(Parser::$STATEMENT_PARSERS[$token->value])) {
if (!empty($parsedClauses[$token->value])) {
$parser->error(__('This type of clause was previously parsed.'), $token);
break;
}
$parsedClauses[$token->value] = true;
}
// Checking if this is the beginning of a clause.
if (!empty(Parser::$KEYWORD_PARSERS[$token->value])) {
$class = Parser::$KEYWORD_PARSERS[$token->value]['class'];
$field = Parser::$KEYWORD_PARSERS[$token->value]['field'];
if (!empty(Parser::$KEYWORD_PARSERS[$token->value]['options'])) {
$options = Parser::$KEYWORD_PARSERS[$token->value]['options'];
}
}
// Checking if this is the beginning of the statement.
if (!empty(Parser::$STATEMENT_PARSERS[$token->value])) {
if (!empty(static::$CLAUSES) && empty(static::$CLAUSES[$token->value])) {
// Some keywords (e.g. `SET`) may be the beginning of a
// statement and a clause.
// If such keyword was found and it cannot be a clause of
// this statement it means it is a new statement, but no
// delimiter was found between them.
$parser->error(__('A new statement was found, but no delimiter between it and the previous one.'), $token);
break;
}
if (!$parsedOptions) {
if (empty(static::$OPTIONS[$token->value])) {
// Skipping keyword because if it is not a option.
++$list->idx;
}
$this->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
$parsedOptions = true;
}
} elseif ($class === null) {
// Handle special end options in Select statement
// See Statements\SelectStatement::$END_OPTIONS
if (get_class($this) === 'SqlParser\\Statements\\SelectStatement' && ($token->value === 'FOR UPDATE' || $token->value === 'LOCK IN SHARE MODE')) {
$this->end_options = OptionsArray::parse($parser, $list, static::$END_OPTIONS);
} else {
// There is no parser for this keyword and isn't the beginning
// of a statement (so no options) either.
$parser->error(__('Unrecognized keyword.'), $token);
continue;
}
}
$this->before($parser, $list, $token);
// Parsing this keyword.
if ($class !== null) {
++$list->idx;
// Skipping keyword or last option.
$this->{$field} = $class::parse($parser, $list, $options);
}
$this->after($parser, $list, $token);
}
// This may be corrected by the parser.
$this->last = --$list->idx;
// Go back to last used token.
}
作者:pjiaha
项目:phpmyadmi
/**
* @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 AlterOperation
*/
public static function parse(Parser $parser, TokensList $list, array $options = array())
{
$ret = new AlterOperation();
/**
* Counts brackets.
*
* @var int $brackets
*/
$brackets = 0;
/**
* The state of the parser.
*
* Below are the states of the parser.
*
* 0 ---------------------[ options ]---------------------> 1
*
* 1 ----------------------[ field ]----------------------> 2
*
* 2 -------------------------[ , ]-----------------------> 0
*
* @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 comments.
if ($token->type === Token::TYPE_COMMENT) {
continue;
}
// Skipping whitespaces.
if ($token->type === Token::TYPE_WHITESPACE) {
if ($state === 2) {
// When parsing the unknown part, the whitespaces are
// included to not break anything.
$ret->unknown[] = $token;
}
continue;
}
if ($state === 0) {
$ret->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
$state = 1;
} elseif ($state === 1) {
$ret->field = Expression::parse($parser, $list, array('noAlias' => true, 'noBrackets' => true));
if ($ret->field === null) {
// No field was read. We go back one token so the next
// iteration will parse the same token, but in state 2.
--$list->idx;
}
$state = 2;
} elseif ($state === 2) {
if ($token->type === Token::TYPE_OPERATOR) {
if ($token->value === '(') {
++$brackets;
} elseif ($token->value === ')') {
--$brackets;
} elseif ($token->value === ',' && $brackets === 0) {
break;
}
}
$ret->unknown[] = $token;
}
}
if ($ret->options->isEmpty()) {
$parser->error(__('Unrecognized alter operation.'), $list->tokens[$list->idx]);
}
--$list->idx;
return $ret;
}
作者:TheBlackBloodyUnicor
项目:pico_wanderblo
//.........这里部分代码省略.........
*
* @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];
// End of statement.
if ($token->type === Token::TYPE_DELIMITER) {
break;
}
// Only keywords are relevant here. Other parts of the query are
// processed in the functions below.
if ($token->type !== Token::TYPE_KEYWORD) {
if ($token->type !== TOKEN::TYPE_COMMENT && $token->type !== Token::TYPE_WHITESPACE) {
$parser->error(__('Unexpected token.'), $token);
}
continue;
}
// Unions are parsed by the parser because they represent more than
// one statement.
if ($token->value === 'UNION') {
break;
}
/**
* 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();
// Looking for duplicated clauses.
if (!empty(Parser::$KEYWORD_PARSERS[$token->value]) || !empty(Parser::$STATEMENT_PARSERS[$token->value])) {
if (!empty($parsedClauses[$token->value])) {
$parser->error(__('This type of clause was previously parsed.'), $token);
break;
}
$parsedClauses[$token->value] = true;
}
// Checking if this is the beginning of a clause.
if (!empty(Parser::$KEYWORD_PARSERS[$token->value])) {
$class = Parser::$KEYWORD_PARSERS[$token->value]['class'];
$field = Parser::$KEYWORD_PARSERS[$token->value]['field'];
if (!empty(Parser::$KEYWORD_PARSERS[$token->value]['options'])) {
$options = Parser::$KEYWORD_PARSERS[$token->value]['options'];
}
}
// Checking if this is the beginning of the statement.
if (!empty(Parser::$STATEMENT_PARSERS[$token->value])) {
if (!empty(static::$CLAUSES) && empty(static::$CLAUSES[$token->value])) {
// Some keywords (e.g. `SET`) may be the beginning of a
// statement and a clause.
// If such keyword was found and it cannot be a clause of
// this statement it means it is a new statement, but no
// delimiter was found between them.
$parser->error(__('A new statement was found, but no delimiter between it and the previous one.'), $token);
break;
}
if (!$parsedOptions) {
if (empty(static::$OPTIONS[$token->value])) {
// Skipping keyword because if it is not a option.
++$list->idx;
}
$this->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
$parsedOptions = true;
}
} elseif ($class === null) {
// There is no parser for this keyword and isn't the beginning
// of a statement (so no options) either.
$parser->error(__('Unrecognized keyword.'), $token);
continue;
}
$this->before($parser, $list, $token);
// Parsing this keyword.
if ($class !== null) {
++$list->idx;
// Skipping keyword or last option.
$this->{$field} = $class::parse($parser, $list, $options);
}
$this->after($parser, $list, $token);
}
// This may be corrected by the parser.
$this->last = --$list->idx;
// Go back to last used token.
}
作者:WSDC-NITWaranga
项目:phpmyadmi
/**
* @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;
}
作者:BrunoChauve
项目:phpmyadmi
/**
* @param Parser $parser The instance that requests parsing.
* @param TokensList $list The list of tokens to be parsed.
*
* @return void
*/
public function parse(Parser $parser, TokensList $list)
{
++$list->idx;
// Skipping `CREATE`.
// Parsing options.
$this->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
++$list->idx;
// Skipping last option.
// Parsing the field name.
$this->name = Expression::parse($parser, $list, array('noAlias' => true, 'noBrackets' => true, 'skipColumn' => true));
++$list->idx;
// Skipping field.
if ($this->options->has('DATABASE')) {
$this->entityOptions = OptionsArray::parse($parser, $list, static::$DB_OPTIONS);
} elseif ($this->options->has('TABLE')) {
$this->fields = FieldDefinition::parse($parser, $list);
++$list->idx;
$this->entityOptions = OptionsArray::parse($parser, $list, static::$TABLE_OPTIONS);
} elseif ($this->options->has('PROCEDURE') || $this->options->has('FUNCTION')) {
$this->parameters = ParameterDefinition::parse($parser, $list);
if ($this->options->has('FUNCTION')) {
$token = $list->getNextOfType(Token::TYPE_KEYWORD);
if ($token->value !== 'RETURNS') {
$parser->error('\'RETURNS\' keyword was expected.', $token);
} else {
++$list->idx;
$this->return = DataType::parse($parser, $list);
}
}
++$list->idx;
$this->entityOptions = OptionsArray::parse($parser, $list, static::$FUNC_OPTIONS);
++$list->idx;
for (; $list->idx < $list->count; ++$list->idx) {
$token = $list->tokens[$list->idx];
$this->body[] = $token;
}
} else {
if ($this->options->has('VIEW')) {
$token = $list->getNext();
// Skipping whitespaces and comments.
// Parsing columns list.
if ($token->type === Token::TYPE_OPERATOR && $token->value === '(') {
--$list->idx;
// getNext() also goes forward one field.
$this->fields = ArrayObj::parse($parser, $list);
++$list->idx;
// Skipping last token from the array.
$list->getNext();
}
// Parsing the `AS` keyword.
for (; $list->idx < $list->count; ++$list->idx) {
$token = $list->tokens[$list->idx];
if ($token->type === Token::TYPE_DELIMITER) {
break;
}
$this->body[] = $token;
}
} else {
if ($this->options->has('TRIGGER')) {
// Parsing the time and the event.
$this->entityOptions = OptionsArray::parse($parser, $list, static::$TRIGGER_OPTIONS);
++$list->idx;
$list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'ON');
++$list->idx;
// Skipping `ON`.
// Parsing the name of the table.
$this->table = Expression::parse($parser, $list, array('noAlias' => true, 'noBrackets' => true, 'skipColumn' => true));
++$list->idx;
$list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'FOR EACH ROW');
++$list->idx;
// Skipping `FOR EACH ROW`.
for (; $list->idx < $list->count; ++$list->idx) {
$token = $list->tokens[$list->idx];
$this->body[] = $token;
}
}
}
}
}
作者:BrunoChauve
项目:phpmyadmi
/**
* Parses the statements defined by the tokens list.
*
* @param Parser $parser The instance that requests parsing.
* @param TokensList $list The list of tokens to be parsed.
*
* @return void
*/
public function parse(Parser $parser, TokensList $list)
{
// This may be corrected by the parser.
$this->first = $list->idx;
/**
* 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) ? false : true;
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;
}
// Only keywords are relevant here. Other parts of the query are
// processed in the functions below.
if ($token->type !== Token::TYPE_KEYWORD) {
continue;
}
// Unions are parsed by the parser because they represent more than
// one statement.
if ($token->value === 'UNION') {
break;
}
/**
* The name of the class that is used for parsing.
* @var string $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();
if (!empty(Parser::$KEYWORD_PARSERS[$token->value])) {
$class = Parser::$KEYWORD_PARSERS[$token->value]['class'];
$field = Parser::$KEYWORD_PARSERS[$token->value]['field'];
if (!empty(Parser::$KEYWORD_PARSERS[$token->value]['options'])) {
$options = Parser::$KEYWORD_PARSERS[$token->value]['options'];
}
}
if (!empty(Parser::$STATEMENT_PARSERS[$token->value])) {
if (!$parsedOptions) {
++$list->idx;
// Skipping keyword.
$this->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
$parsedOptions = true;
}
} elseif ($class === null) {
// There is no parser for this keyword and isn't the beginning
// of a statement (so no options) either.
$parser->error('Unrecognized keyword "' . $token->value . '".', $token);
continue;
}
$this->before($parser, $list, $token);
// Parsing this keyword.
if ($class !== null) {
++$list->idx;
// Skipping keyword.
$this->{$field} = $class::parse($parser, $list, $options);
}
$this->after($parser, $list, $token);
}
// This may be corrected by the parser.
$this->last = --$list->idx;
// Go back to last used token.
}