public function testParseBetween() { $component = Condition::parse(new Parser(), $this->getTokensList('(id BETWEEN 10 AND 20) OR (id BETWEEN 30 AND 40)')); $this->assertEquals($component[0]->expr, '(id BETWEEN 10 AND 20)'); $this->assertEquals($component[1]->expr, 'OR'); $this->assertEquals($component[2]->expr, '(id BETWEEN 30 AND 40)'); }
/** * @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; }
/** * @param JoinKeyword[] $component The component to be built. * @param array $options Parameters for building. * * @return string */ public static function build($component, array $options = array()) { $ret = array(); foreach ($component as $c) { $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); }
/** * @param JoinKeyword[] $component The component to be built. * * @return string */ public static function build($component) { $ret = array(); foreach ($component as $c) { $ret[] = ($c->type === 'JOIN' ? 'JOIN ' : $c->type . ' JOIN ') . Expression::build($c->expr) . ' ON ' . Condition::build($c->on); } return implode(' ', $ret); }
/** * @param JoinKeyword[] $component The component to be built. * @param array $options Parameters for building. * * @return string */ public static function build($component, array $options = array()) { $ret = array(); foreach ($component as $c) { $ret[] = array_search($c->type, static::$JOINS) . ' ' . $c->expr . ' ON ' . Condition::build($c->on); } return implode(' ', $ret); }
/** * @param Expression $component The component to be built. * @param array $options Parameters for building. * * @return string */ public static function build($component, array $options = array()) { $ret = 'CASE '; if (isset($component->value)) { // Syntax type 0 $ret .= $component->value . ' '; for ($i = 0; $i < count($component->compare_values) && $i < count($component->results); ++$i) { $ret .= 'WHEN ' . $component->compare_values[$i] . ' '; $ret .= 'THEN ' . $component->results[$i] . ' '; } } else { // Syntax type 1 for ($i = 0; $i < count($component->conditions) && $i < count($component->results); ++$i) { $ret .= 'WHEN ' . Condition::build($component->conditions[$i]) . ' '; $ret .= 'THEN ' . $component->results[$i] . ' '; } } if (isset($component->else_result)) { $ret .= 'ELSE ' . $component->else_result . ' '; } $ret .= 'END'; return $ret; }