summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Contexts/ContextMySql50000.php2
-rw-r--r--src/Contexts/ContextMySql50100.php2
-rw-r--r--src/Contexts/ContextMySql50500.php2
-rw-r--r--src/Contexts/ContextMySql50600.php2
-rw-r--r--src/Contexts/ContextMySql50700.php2
-rw-r--r--src/Fragments/AlterFragment.php2
-rw-r--r--src/Fragments/FieldDefFragment.php1
-rw-r--r--src/Fragments/IntoKeyword.php18
-rw-r--r--src/Fragments/ParamDefFragment.php21
-rw-r--r--src/Fragments/RenameKeyword.php28
-rw-r--r--src/Fragments/SetKeyword.php9
-rw-r--r--src/Parser.php9
-rw-r--r--src/Statements/CheckStatement.php7
-rw-r--r--src/Statements/ChecksumStatement.php7
-rw-r--r--src/Statements/CreateStatement.php126
-rw-r--r--src/Statements/DeleteStatement.php18
-rw-r--r--src/Statements/RepairStatement.php7
-rw-r--r--src/Statements/RestoreStatement.php7
-rw-r--r--src/Statements/SelectStatement.php2
-rw-r--r--src/Statements/TruncateStatement.php49
-rw-r--r--src/Statements/UpdateStatement.php21
-rw-r--r--src/TokensList.php7
-rw-r--r--src/Utils/Query.php51
23 files changed, 326 insertions, 74 deletions
diff --git a/src/Contexts/ContextMySql50000.php b/src/Contexts/ContextMySql50000.php
index dc2759a..7db5fc3 100644
--- a/src/Contexts/ContextMySql50000.php
+++ b/src/Contexts/ContextMySql50000.php
@@ -146,7 +146,7 @@ class ContextMySql50000 extends Context
'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
'IF EXISTS' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
'OR REPLACE' => 7,
- 'SQL SECURITY' => 7,
+ 'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
'DATA DIRECTORY' => 7,
'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
diff --git a/src/Contexts/ContextMySql50100.php b/src/Contexts/ContextMySql50100.php
index 82db684..a5c4bef 100644
--- a/src/Contexts/ContextMySql50100.php
+++ b/src/Contexts/ContextMySql50100.php
@@ -157,7 +157,7 @@ class ContextMySql50100 extends Context
'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
'IF EXISTS' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
'OR REPLACE' => 7,
- 'SQL SECURITY' => 7,
+ 'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
'DATA DIRECTORY' => 7,
'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
diff --git a/src/Contexts/ContextMySql50500.php b/src/Contexts/ContextMySql50500.php
index e338232..3faf785 100644
--- a/src/Contexts/ContextMySql50500.php
+++ b/src/Contexts/ContextMySql50500.php
@@ -162,7 +162,7 @@ class ContextMySql50500 extends Context
'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
'IF EXISTS' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
'OR REPLACE' => 7,
- 'SQL SECURITY' => 7,
+ 'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
'DATA DIRECTORY' => 7,
'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
diff --git a/src/Contexts/ContextMySql50600.php b/src/Contexts/ContextMySql50600.php
index 780ea52..6a1af74 100644
--- a/src/Contexts/ContextMySql50600.php
+++ b/src/Contexts/ContextMySql50600.php
@@ -168,7 +168,7 @@ class ContextMySql50600 extends Context
'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
'IF EXISTS' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
'OR REPLACE' => 7,
- 'SQL SECURITY' => 7,
+ 'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
'DATA DIRECTORY' => 7,
'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
diff --git a/src/Contexts/ContextMySql50700.php b/src/Contexts/ContextMySql50700.php
index 6a3cfd6..ac81e8a 100644
--- a/src/Contexts/ContextMySql50700.php
+++ b/src/Contexts/ContextMySql50700.php
@@ -176,7 +176,7 @@ class ContextMySql50700 extends Context
'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
'IF EXISTS' => 7, 'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
'OR REPLACE' => 7,
- 'SQL SECURITY' => 7,
+ 'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
'DATA DIRECTORY' => 7,
'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
diff --git a/src/Fragments/AlterFragment.php b/src/Fragments/AlterFragment.php
index 54338f9..b5c66e8 100644
--- a/src/Fragments/AlterFragment.php
+++ b/src/Fragments/AlterFragment.php
@@ -160,7 +160,7 @@ class AlterFragment extends Fragment
);
if ($ret->field === null) {
// No field was read. We go back one token so the next
- // iteration will parse the same on, but in state 2.
+ // iteration will parse the same token, but in state 2.
--$list->idx;
}
$state = 2;
diff --git a/src/Fragments/FieldDefFragment.php b/src/Fragments/FieldDefFragment.php
index 9f43fcc..a4c21d7 100644
--- a/src/Fragments/FieldDefFragment.php
+++ b/src/Fragments/FieldDefFragment.php
@@ -221,7 +221,6 @@ class FieldDefFragment extends Fragment
--$list->idx;
return $ret;
-
}
/**
diff --git a/src/Fragments/IntoKeyword.php b/src/Fragments/IntoKeyword.php
index 0b51531..cf65da6 100644
--- a/src/Fragments/IntoKeyword.php
+++ b/src/Fragments/IntoKeyword.php
@@ -33,11 +33,11 @@ class IntoKeyword extends Fragment
public $type;
/**
- * The name of the table or file.
+ * The destination, which can be a table or a file.
*
- * @var string
+ * @var string|FieldFragment
*/
- public $name;
+ public $dest;
/**
* The name of the columns.
@@ -102,7 +102,15 @@ class IntoKeyword extends Fragment
}
if ($state === 0) {
- $ret->name = $token->value;
+ $ret->dest = FieldFragment::parse(
+ $parser,
+ $list,
+ array(
+ 'noAlias' => true,
+ 'noBrackets' => true,
+ 'skipColumn' => true,
+ )
+ );
$state = 1;
} elseif ($state === 1) {
if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
@@ -111,7 +119,7 @@ class IntoKeyword extends Fragment
}
break;
} elseif ($state === 2) {
- $ret->name = $token->value;
+ $ret->dest = $token->value;
++$list->idx;
break;
}
diff --git a/src/Fragments/ParamDefFragment.php b/src/Fragments/ParamDefFragment.php
index 583c3ab..23b84e3 100644
--- a/src/Fragments/ParamDefFragment.php
+++ b/src/Fragments/ParamDefFragment.php
@@ -135,6 +135,27 @@ class ParamDefFragment extends Fragment
--$list->idx;
return $ret;
+ }
+ /**
+ * @param ParamDefFragment[] $fragment The fragment to be built.
+ *
+ * @return string
+ */
+ public static function build($fragment)
+ {
+ $ret = array();
+ foreach ($fragment as $f) {
+ $tmp = '';
+ if (!empty($f->inOut)) {
+ $tmp .= $f->inOut . ' ';
+ }
+
+ $ret[] = trim(
+ $tmp . Context::escape($f->name) . ' ' .
+ DataTypeFragment::build($f->type)
+ );
+ }
+ return '(' . implode(', ', $ret) . ')';
}
}
diff --git a/src/Fragments/RenameKeyword.php b/src/Fragments/RenameKeyword.php
index 077982a..de81848 100644
--- a/src/Fragments/RenameKeyword.php
+++ b/src/Fragments/RenameKeyword.php
@@ -26,16 +26,16 @@ class RenameKeyword extends Fragment
{
/**
- * The old name.
+ * The old table name.
*
- * @var string
+ * @var FieldFragment
*/
public $old;
/**
- * The new name.
+ * The new table name.
*
- * @var string
+ * @var FieldFragment
*/
public $new;
@@ -110,10 +110,26 @@ class RenameKeyword extends Fragment
}
if ($state == 0) {
- $expr->old = $token->value;
+ $expr->old = FieldFragment::parse(
+ $parser,
+ $list,
+ array(
+ 'noAlias' => true,
+ 'noBrackets' => true,
+ 'skipColumn' => true,
+ )
+ );
$state = 1;
} elseif ($state == 2) {
- $expr->new = $token->value;
+ $expr->new = FieldFragment::parse(
+ $parser,
+ $list,
+ array(
+ 'noBrackets' => true,
+ 'skipColumn' => true,
+ 'noAlias' => true,
+ )
+ );
$state = 3;
}
diff --git a/src/Fragments/SetKeyword.php b/src/Fragments/SetKeyword.php
index bced45f..713a179 100644
--- a/src/Fragments/SetKeyword.php
+++ b/src/Fragments/SetKeyword.php
@@ -90,24 +90,29 @@ class SetKeyword extends Fragment
if ($token->type === Token::TYPE_OPERATOR) {
if ($token->value === ',') {
+ $expr->column = trim($expr->column);
+ $expr->value = trim($expr->value);
$ret[] = $expr;
$expr = new SetKeyword();
$state = 0;
continue;
} elseif ($token->value === '=') {
$state = 1;
+ continue;
}
}
if ($state === 0) {
- $expr->column .= $token->value;
+ $expr->column .= $token->token;
} else { // } else if ($state === 1) {
- $expr->value = $token->value;
+ $expr->value .= $token->token;
}
}
// Last iteration was not saved.
if (!empty($expr->column)) {
+ $expr->column = trim($expr->column);
+ $expr->value = trim($expr->value);
$ret[] = $expr;
}
diff --git a/src/Parser.php b/src/Parser.php
index ff55f5f..3c57406 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -54,7 +54,7 @@ class Parser
'CREATE' => 'SqlParser\\Statements\\CreateStatement',
'DROP' => 'SqlParser\\Statements\\DropStatement',
'RENAME' => 'SqlParser\\Statements\\RenameStatement',
- 'TRUNCATE' => '',
+ 'TRUNCATE' => 'SqlParser\\Statements\\TruncateStatement',
// Data Manipulation Statements.
// https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-data-manipulation.html
@@ -185,9 +185,14 @@ class Parser
'class' => 'SqlParser\\Fragments\\FieldListFragment',
'field' => 'expr',
),
+ 'TRUNCATE' => array(
+ 'class' => 'SqlParser\\Fragments\\FieldFragment',
+ 'field' => 'table',
+ 'options' => array('skipColumn' => true),
+ ),
'UPDATE' => array(
'class' => 'SqlParser\\Fragments\\FieldListFragment',
- 'field' => 'from',
+ 'field' => 'tables',
'options' => array('skipColumn' => true),
),
'VALUE' => array(
diff --git a/src/Statements/CheckStatement.php b/src/Statements/CheckStatement.php
index 38764ff..2e0e5a3 100644
--- a/src/Statements/CheckStatement.php
+++ b/src/Statements/CheckStatement.php
@@ -40,11 +40,4 @@ class CheckStatement extends MaintenanceStatement
'EXTENDED' => 6,
'CHANGED' => 7,
);
-
- /**
- * Checked tables.
- *
- * @var FieldFragment[]
- */
- public $tables;
}
diff --git a/src/Statements/ChecksumStatement.php b/src/Statements/ChecksumStatement.php
index e2c6371..0495932 100644
--- a/src/Statements/ChecksumStatement.php
+++ b/src/Statements/ChecksumStatement.php
@@ -36,11 +36,4 @@ class ChecksumStatement extends MaintenanceStatement
'QUICK' => 2,
'EXTENDED' => 3,
);
-
- /**
- * Checked tables.
- *
- * @var FieldFragment[]
- */
- public $tables;
}
diff --git a/src/Statements/CreateStatement.php b/src/Statements/CreateStatement.php
index 306bfeb..71557c7 100644
--- a/src/Statements/CreateStatement.php
+++ b/src/Statements/CreateStatement.php
@@ -101,15 +101,28 @@ class CreateStatement extends Statement
* @var array
*/
public static $FUNC_OPTIONS = array(
- 'COMMENT' => array(1, 'var'),
- 'LANGUAGE SQL' => 2,
- 'DETERMINISTIC' => 3,
- 'NOT DETERMINISTIC' => 3,
- 'CONSTAINS SQL' => 4,
- 'NO SQL' => 4,
- 'READS SQL DATA' => 4,
- 'MODIFIES SQL DATA' => 4,
- 'SQL SEQURITY DEFINER' => array(5, 'var'),
+ 'COMMENT' => array(1, 'var'),
+ 'LANGUAGE SQL' => 2,
+ 'DETERMINISTIC' => 3,
+ 'NOT DETERMINISTIC' => 3,
+ 'CONSTAINS SQL' => 4,
+ 'NO SQL' => 4,
+ 'READS SQL DATA' => 4,
+ 'MODIFIES SQL DATA' => 4,
+ 'SQL SEQURITY DEFINER' => array(5, 'var'),
+ );
+
+ /**
+ * All trigger options.
+ *
+ * @var array
+ */
+ public static $TRIGGER_OPTIONS = array(
+ 'BEFORE' => 1,
+ 'AFTER' => 1,
+ 'INSERT' => 2,
+ 'UPDATE' => 2,
+ 'DELETE' => 2,
);
/**
@@ -130,6 +143,7 @@ class CreateStatement extends Statement
*
* @see static::$TABLE_OPTIONS
* @see static::$FUNC_OPTIONS
+ * @see static::$TRIGGER_OPTIONS
*/
public $entityOptions;
@@ -144,6 +158,15 @@ class CreateStatement extends Statement
public $fields;
/**
+ * If `CREATE TRIGGER` the name of the table.
+ *
+ * Used by `CREATE TRIGGER`.
+ *
+ * @var FieldFragment
+ */
+ public $table;
+
+ /**
* The return data type of this routine.
*
* Used by `CREATE FUNCTION`.
@@ -167,7 +190,7 @@ class CreateStatement extends Statement
*
* Used by `CREATE FUNCTION`, `CREATE PROCEDURE` and `CREATE VIEW`.
*
- * @var Token[]
+ * @var Token[]|string
*/
public $body = array();
@@ -176,20 +199,43 @@ class CreateStatement extends Statement
*/
public function build()
{
- $tmp = '';
if ($this->options->has('TABLE')) {
- $tmp = FieldDefFragment::build($this->fields);
+ return 'CREATE '
+ . OptionsFragment::build($this->options) . ' '
+ . FieldFragment::build($this->name) . ' '
+ . FieldDefFragment::build($this->fields) . ' '
+ . OptionsFragment::build($this->entityOptions);
} elseif ($this->options->has('VIEW')) {
+ $tmp = '';
if (!empty($this->fields)) {
- $tmp .= ArrayFragment::build($this->fields) . ' ';
+ $tmp = ArrayFragment::build($this->fields);
+ }
+ return 'CREATE '
+ . OptionsFragment::build($this->options) . ' '
+ . FieldFragment::build($this->name) . ' '
+ . $tmp . ' AS ' . TokensList::build($this->body) . ' '
+ . OptionsFragment::build($this->entityOptions);
+ } elseif ($this->options->has('TRIGGER')) {
+ return 'CREATE '
+ . OptionsFragment::build($this->options) . ' '
+ . FieldFragment::build($this->name) . ' '
+ . OptionsFragment::build($this->entityOptions) . ' '
+ . 'ON ' . FieldFragment::build($this->table) . ' '
+ . 'FOR EACH ROW ' . TokensList::build($this->body);
+ } elseif (($this->options->has('PROCEDURE'))
+ || ($this->options->has('FUNCTION'))
+ ) {
+ $tmp = '';
+ if ($this->options->has('FUNCTION')) {
+ $tmp = 'RETURNS ' . DataTypeFragment::build($this->return);
}
- $tmp .= 'AS ' . TokensList::build($this->body);
+ return 'CREATE '
+ . OptionsFragment::build($this->options) . ' '
+ . FieldFragment::build($this->name) . ' '
+ . ParamDefFragment::build($this->parameters) . ' '
+ . $tmp . ' ' . TokensList::build($this->body);
}
- return 'CREATE '
- . OptionsFragment::build($this->options) . ' '
- . FieldFragment::build($this->name) . ' '
- . $tmp . ' '
- . OptionsFragment::build($this->entityOptions);
+ return '';
}
/**
@@ -221,6 +267,7 @@ class CreateStatement extends Statement
if ($this->options->has('TABLE')) {
$this->fields = FieldDefFragment::parse($parser, $list);
++$list->idx;
+
$this->entityOptions = OptionsFragment::parse(
$parser,
$list,
@@ -246,13 +293,14 @@ class CreateStatement extends Statement
}
}
++$list->idx;
+
$this->entityOptions = OptionsFragment::parse(
$parser,
$list,
static::$FUNC_OPTIONS
);
++$list->idx;
- $this->body = array();
+
for (; $list->idx < $list->count; ++$list->idx) {
$token = $list->tokens[$list->idx];
$this->body[] = $token;
@@ -263,7 +311,7 @@ class CreateStatement extends Statement
}
}
} else if ($this->options->has('VIEW')) {
- $token = $list->getNext();
+ $token = $list->getNext(); // Skipping whitespaces and comments.
// Parsing columns list.
if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
@@ -281,6 +329,42 @@ class CreateStatement extends Statement
}
$this->body[] = $token;
}
+ } else if ($this->options->has('TRIGGER')) {
+ // Parsing the time and the event.
+ $this->entityOptions = OptionsFragment::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->fields = FieldFragment::parse(
+ $parser,
+ $list,
+ array(
+ 'skipColumn' => true,
+ 'noAlias' => true,
+ 'noBrackets' => 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;
+ if (($token->type === Token::TYPE_KEYWORD)
+ && ($token->value === 'END')
+ ) {
+ break;
+ }
+ }
}
}
}
diff --git a/src/Statements/DeleteStatement.php b/src/Statements/DeleteStatement.php
index 9016da3..04208fc 100644
--- a/src/Statements/DeleteStatement.php
+++ b/src/Statements/DeleteStatement.php
@@ -40,6 +40,24 @@ class DeleteStatement extends Statement
);
/**
+ * The clauses of this statement, in order.
+ *
+ * @see Statement::$CLAUSES
+ *
+ * @var array
+ */
+ 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),
+ );
+
+ /**
* Tables used as sources for this statement.
*
* @var FieldFragment[]
diff --git a/src/Statements/RepairStatement.php b/src/Statements/RepairStatement.php
index 933d2c0..e340dd1 100644
--- a/src/Statements/RepairStatement.php
+++ b/src/Statements/RepairStatement.php
@@ -42,11 +42,4 @@ class RepairStatement extends MaintenanceStatement
'EXTENDED' => 5,
'USE_FRM' => 6,
);
-
- /**
- * Repaired tables.
- *
- * @var FieldFragment[]
- */
- public $tables;
}
diff --git a/src/Statements/RestoreStatement.php b/src/Statements/RestoreStatement.php
index 996b41e..1c03e29 100644
--- a/src/Statements/RestoreStatement.php
+++ b/src/Statements/RestoreStatement.php
@@ -35,11 +35,4 @@ class RestoreStatement extends MaintenanceStatement
'FROM' => array(2, 'var'),
);
-
- /**
- * Restored tables.
- *
- * @var FieldFragment[]
- */
- public $tables;
}
diff --git a/src/Statements/SelectStatement.php b/src/Statements/SelectStatement.php
index e376b47..b5d0b0a 100644
--- a/src/Statements/SelectStatement.php
+++ b/src/Statements/SelectStatement.php
@@ -78,7 +78,7 @@ class SelectStatement extends Statement
'SELECT' => array('SELECT', 2),
// Used for options.
'_OPTIONS' => array('_OPTIONS', 1),
- // Used for select expressions.
+ // Used for selected expressions.
'_SELECT' => array('SELECT', 1),
'FROM' => array('FROM', 3),
'PARTITION' => array('PARTITION', 3),
diff --git a/src/Statements/TruncateStatement.php b/src/Statements/TruncateStatement.php
new file mode 100644
index 0000000..9313204
--- /dev/null
+++ b/src/Statements/TruncateStatement.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * `TRUNCATE` statement.
+ *
+ * @package SqlParser
+ * @subpackage Statements
+ */
+namespace SqlParser\Statements;
+
+use SqlParser\Parser;
+use SqlParser\Statement;
+use SqlParser\Token;
+use SqlParser\TokensList;
+use SqlParser\Fragments\ArrayFragment;
+use SqlParser\Fragments\DataTypeFragment;
+use SqlParser\Fragments\FieldDefFragment;
+use SqlParser\Fragments\FieldFragment;
+use SqlParser\Fragments\OptionsFragment;
+use SqlParser\Fragments\ParamDefFragment;
+
+/**
+ * `TRUNCATE` statement.
+ *
+ * @category Statements
+ * @package SqlParser
+ * @subpackage Statements
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class TruncateStatement extends Statement
+{
+
+ /**
+ * Options for `TRUNCATE` statements.
+ *
+ * @var array
+ */
+ public static $OPTIONS = array(
+ 'TABLE' => 1,
+ );
+
+ /**
+ * The name of the truncated table.
+ *
+ * @var FieldFragment
+ */
+ public $table;
+}
diff --git a/src/Statements/UpdateStatement.php b/src/Statements/UpdateStatement.php
index d100560..ab445dc 100644
--- a/src/Statements/UpdateStatement.php
+++ b/src/Statements/UpdateStatement.php
@@ -45,11 +45,30 @@ class UpdateStatement extends Statement
);
/**
+ * The clauses of this statement, in order.
+ *
+ * @see Statement::$CLAUSES
+ *
+ * @var array
+ */
+ public static $CLAUSES = array(
+ 'UPDATE' => array('UPDATE', 2),
+ // Used for options.
+ '_OPTIONS' => array('_OPTIONS', 1),
+ // Used for updated tables.
+ '_UPDATE' => array('UPDATE', 1),
+ 'SET' => array('SET', 3),
+ 'WHERE' => array('WHERE', 3),
+ 'ORDER BY' => array('ORDER BY', 3),
+ 'LIMIT' => array('LIMIT', 3),
+ );
+
+ /**
* Tables used as sources for this statement.
*
* @var FieldFragment[]
*/
- public $from;
+ public $tables;
/**
* The updated values.
diff --git a/src/TokensList.php b/src/TokensList.php
index 229bebc..be9124c 100644
--- a/src/TokensList.php
+++ b/src/TokensList.php
@@ -57,15 +57,20 @@ class TokensList implements \ArrayAccess
/**
* Builds an array of tokens by merging their raw value.
*
- * @param array $tokens
+ * @param string|array|TokensList $tokens
*
* @return string
*/
public static function build($list)
{
+ if (is_string($list)) {
+ return $list;
+ }
+
if ($list instanceof TokensList) {
$list = $list->tokens;
}
+
$ret = '';
if (is_array($list)) {
foreach ($list as $tok) {
diff --git a/src/Utils/Query.php b/src/Utils/Query.php
index 5c4553d..d4c01af 100644
--- a/src/Utils/Query.php
+++ b/src/Utils/Query.php
@@ -12,6 +12,7 @@ use SqlParser\Lexer;
use SqlParser\Parser;
use SqlParser\Statement;
use SqlParser\Token;
+use SqlParser\Fragments\FieldFragment;
use SqlParser\Statements\AlterStatement;
use SqlParser\Statements\AnalyzeStatement;
use SqlParser\Statements\CallStatement;
@@ -23,10 +24,12 @@ use SqlParser\Statements\DropStatement;
use SqlParser\Statements\ExplainStatement;
use SqlParser\Statements\InsertStatement;
use SqlParser\Statements\OptimizeStatement;
+use SqlParser\Statements\RenameStatement;
use SqlParser\Statements\RepairStatement;
use SqlParser\Statements\ReplaceStatement;
use SqlParser\Statements\SelectStatement;
use SqlParser\Statements\ShowStatement;
+use SqlParser\Statements\TruncateStatement;
use SqlParser\Statements\UpdateStatement;
/**
@@ -437,6 +440,54 @@ class Query
}
/**
+ * Gets a list of all tables used in this statement.
+ *
+ * @param Statement $statement Statement to be scanned.
+ *
+ * @return array
+ */
+ public static function getTables($statement)
+ {
+ $fields = array();
+
+ if (($statement instanceof InsertStatement)
+ || ($statement instanceof ReplaceStatement)
+ ) {
+ $fields = array($statement->into->dest);
+ } elseif ($statement instanceof UpdateStatement) {
+ $fields = $statement->tables;
+ } elseif (($statement instanceof SelectStatement)
+ || ($statement instanceof DeleteStatement)
+ ) {
+ $fields = $statement->from;
+ } elseif (($statement instanceof AlterStatement)
+ || ($statement instanceof TruncateStatement)
+ ) {
+ $fields = array($statement->table);
+ } elseif ($statement instanceof DropStatement) {
+ if (!$statement->options->has('TABLE')) {
+ // No tables are dropped.
+ return array();
+ }
+ $fields = $statement->fields;
+ } elseif ($statement instanceof RenameStatement) {
+ foreach ($statement->renames as $rename) {
+ $fields[] = $rename->old;
+ }
+ }
+
+ $ret = array();
+ foreach ($fields as $field) {
+ if (!empty($field->table)) {
+ $field->expr = null; // Force rebuild.
+ $field->alias = null; // Aliases are not required.
+ $ret[] = FieldFragment::build($field);
+ }
+ }
+ return $ret;
+ }
+
+ /**
* Gets a specific clause.
*
* @param Statement $statement The parsed query that has to be modified.