summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Components/Limit.php6
-rw-r--r--src/Statements/DeleteStatement.php262
2 files changed, 248 insertions, 20 deletions
diff --git a/src/Components/Limit.php b/src/Components/Limit.php
index da4f7f7..13a1127 100644
--- a/src/Components/Limit.php
+++ b/src/Components/Limit.php
@@ -126,10 +126,6 @@ class Limit extends Component
*/
public static function build($component, array $options = array())
{
- if (empty($component->offset)) {
- return (string) $component->rowCount;
- } else {
- return $component->offset . ', ' . $component->rowCount;
- }
+ return $component->offset . ', ' . $component->rowCount;
}
}
diff --git a/src/Statements/DeleteStatement.php b/src/Statements/DeleteStatement.php
index 0788ad2..394c0f4 100644
--- a/src/Statements/DeleteStatement.php
+++ b/src/Statements/DeleteStatement.php
@@ -9,11 +9,16 @@
namespace SqlParser\Statements;
use SqlParser\Statement;
+use SqlParser\Parser;
+use SqlParser\Token;
+use SqlParser\TokensList;
use SqlParser\Components\ArrayObj;
use SqlParser\Components\Expression;
+use SqlParser\Components\ExpressionArray;
use SqlParser\Components\Limit;
use SqlParser\Components\OrderKeyword;
use SqlParser\Components\Condition;
+use SqlParser\Components\OptionsArray;
/**
* `DELETE` statement.
@@ -24,6 +29,21 @@ use SqlParser\Components\Condition;
* [ORDER BY ...]
* [LIMIT row_count]
*
+ * Multi-table syntax
+ *
+ * DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
+ * tbl_name[.*] [, tbl_name[.*]] ...
+ * FROM table_references
+ * [WHERE where_condition]
+ *
+ * OR
+ *
+ * DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
+ * FROM tbl_name[.*] [, tbl_name[.*]] ...
+ * USING table_references
+ * [WHERE where_condition]
+ *
+ *
* @category Statements
* @package SqlParser
* @subpackage Statements
@@ -44,29 +64,25 @@ class DeleteStatement extends Statement
);
/**
- * The clauses of this statement, in order.
+ * Table(s) used as sources for this statement.
*
- * @see Statement::$CLAUSES
+ * @var Expression[]
+ */
+ public $from;
+
+ /**
+ * Tables used as sources for this statement
*
- * @var array
+ * @var Expression[]
*/
- public static $CLAUSES = array(
- 'DELETE' => array('DELETE', 2),
- // Used for options.
- '_OPTIONS' => array('_OPTIONS', 1),
- 'FROM' => array('FROM', 3),
- 'PARTITION' => array('PARTITION', 3),
- 'WHERE' => array('WHERE', 3),
- 'ORDER BY' => array('ORDER BY', 3),
- 'LIMIT' => array('LIMIT', 3),
- );
+ public $using;
/**
- * Tables used as sources for this statement.
+ * Columns used in this statement
*
* @var Expression[]
*/
- public $from;
+ public $columns;
/**
* Partitions used as source for this statement.
@@ -95,4 +111,220 @@ class DeleteStatement extends Statement
* @var Limit
*/
public $limit;
+
+
+ /**
+ * @return string
+ */
+ public function build()
+ {
+ $ret = 'DELETE ' . OptionsArray::build($this->options);
+
+ if ($this->columns != NULL && count($this->columns) > 0) {
+ $ret .= ' ' . ExpressionArray::build($this->columns);
+ }
+ if ($this->from != NULL && count($this->from) > 0) {
+ $ret .= ' FROM ' . ExpressionArray::build($this->from);
+ }
+ if ($this->using != NULL && count($this->using) > 0) {
+ $ret .= ' USING ' . ExpressionArray::build($this->using);
+ }
+ if ($this->where != NULL && count($this->where) > 0) {
+ $ret .= ' WHERE ' . Condition::build($this->where);
+ }
+ if ($this->order != NULL && count($this->order) > 0) {
+ $ret .= ' ORDER BY ' . ExpressionArray::build($this->order);
+ }
+ if ($this->limit != NULL && count($this->limit) > 0) {
+ $ret .= ' LIMIT ' . Limit::build($this->limit);
+ }
+
+ return $ret;
+
+ }
+
+
+ /**
+ * @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;
+ }
}