/** * @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 `DELETE`. // parse any options if provided $this->options = OptionsArray::parse($parser, $list, static::$OPTIONS); ++$list->idx; /** * The state of the parser. * * Below are the states of the parser. * * 0 ---------------------------------[ FROM ]----------------------------------> 2 * 0 ------------------------------[ table[.*] ]--------------------------------> 1 * 1 ---------------------------------[ FROM ]----------------------------------> 2 * 2 --------------------------------[ USING ]----------------------------------> 3 * 2 --------------------------------[ WHERE ]----------------------------------> 4 * 2 --------------------------------[ ORDER ]----------------------------------> 5 * 2 --------------------------------[ LIMIT ]----------------------------------> 6 * * @var int $state */ $state = 0; /** * If the query is multi-table or not * * @var bool $multiTable */ $multiTable = false; 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; } if ($state === 0) { if ($token->type === Token::TYPE_KEYWORD && $token->value !== 'FROM') { $parser->error(__('Unexpected keyword.'), $token); break; } elseif ($token->type === Token::TYPE_KEYWORD && $token->value === 'FROM') { ++$list->idx; // Skip 'FROM' $this->from = ExpressionArray::parse($parser, $list); $state = 2; } else { $this->columns = ExpressionArray::parse($parser, $list); $state = 1; } } elseif ($state === 1) { if ($token->type === Token::TYPE_KEYWORD && $token->value !== 'FROM') { $parser->error(__('Unexpected keyword.'), $token); break; } elseif ($token->type === Token::TYPE_KEYWORD && $token->value === 'FROM') { ++$list->idx; // Skip 'FROM' $this->from = ExpressionArray::parse($parser, $list); $state = 2; } else { $parser->error(__('Unexpected token.'), $token); break; } } elseif ($state === 2) { if ($token->type === Token::TYPE_KEYWORD && $token->value === 'USING') { ++$list->idx; // Skip 'USING' $this->using = ExpressionArray::parse($parser, $list); $state = 3; $multiTable = true; } elseif ($token->type === Token::TYPE_KEYWORD && $token->value === 'WHERE') { ++$list->idx; // Skip 'WHERE' $this->where = Condition::parse($parser, $list); $state = 4; } elseif ($token->type === Token::TYPE_KEYWORD && $token->value === 'ORDER BY') { ++$list->idx; // Skip 'ORDER BY' $this->order = OrderKeyword::parse($parser, $list); $state = 5; } elseif ($token->type === Token::TYPE_KEYWORD && $token->value === 'LIMIT') { ++$list->idx; // Skip 'LIMIT' $this->limit = Limit::parse($parser, $list); $state = 6; } elseif ($token->type === Token::TYPE_KEYWORD) { $parser->error(__('Unexpected keyword.'), $token); break; } } elseif ($state === 3) { if ($token->type === Token::TYPE_KEYWORD && $token->value === 'WHERE') { ++$list->idx; // Skip 'WHERE' $this->where = Condition::parse($parser, $list); $state = 4; } elseif ($token->type === Token::TYPE_KEYWORD) { $parser->error(__('Unexpected keyword.'), $token); break; } else { $parser->error(__('Unexpected token.'), $token); break; } } elseif ($state === 4) { if ($multiTable === true && $token->type === Token::TYPE_KEYWORD) { $parser->error(__('This type of clause is not valid in Multi-table queries.'), $token); break; } if ($token->type === Token::TYPE_KEYWORD && $token->value === 'ORDER BY') { ++$list->idx; // Skip 'ORDER BY' $this->order = OrderKeyword::parse($parser, $list); $state = 5; } elseif ($token->type === Token::TYPE_KEYWORD && $token->value === 'LIMIT') { ++$list->idx; // Skip 'LIMIT' $this->limit = Limit::parse($parser, $list); $state = 6; } elseif ($token->type === Token::TYPE_KEYWORD) { $parser->error(__('Unexpected keyword.'), $token); break; } } elseif ($state === 5) { if ($token->type === Token::TYPE_KEYWORD && $token->value === 'LIMIT') { ++$list->idx; // Skip 'LIMIT' $this->limit = Limit::parse($parser, $list); $state = 6; } elseif ($token->type === Token::TYPE_KEYWORD) { $parser->error(__('Unexpected keyword.'), $token); break; } } } if ($state >= 2) { foreach ($this->from as $from_expr) { $from_expr->database = $from_expr->table; $from_expr->table = $from_expr->column; $from_expr->column = null; } } --$list->idx; }
public function testBuild() { $this->assertEquals(OrderKeyword::build(array(new OrderKeyword(new Expression('a'), 'ASC'), new OrderKeyword(new Expression('b'), 'DESC'))), 'a ASC, b DESC'); }