summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Builder.php84
-rw-r--r--src/Fragment.php11
-rw-r--r--src/Fragments/ArrayFragment.php37
-rw-r--r--src/Fragments/CallKeyword.php33
-rw-r--r--src/Fragments/CreateDefFragment.php1
-rw-r--r--src/Fragments/DataTypeFragment.php1
-rw-r--r--src/Fragments/FieldDefFragment.php3
-rw-r--r--src/Fragments/FieldFragment.php73
-rw-r--r--src/Fragments/FieldListFragment.php (renamed from src/Fragments/SelectKeyword.php)18
-rw-r--r--src/Fragments/FromKeyword.php83
-rw-r--r--src/Fragments/IntoKeyword.php5
-rw-r--r--src/Fragments/JoinKeyword.php1
-rw-r--r--src/Fragments/KeyFragment.php1
-rw-r--r--src/Fragments/LimitKeyword.php27
-rw-r--r--src/Fragments/OptionsFragment.php32
-rw-r--r--src/Fragments/OrderKeyword.php3
-rw-r--r--src/Fragments/ParamDefFragment.php1
-rw-r--r--src/Fragments/ReferencesKeyword.php5
-rw-r--r--src/Fragments/RenameKeyword.php1
-rw-r--r--src/Fragments/SetKeyword.php1
-rw-r--r--src/Fragments/ValuesKeyword.php1
-rw-r--r--src/Fragments/WhereKeyword.php51
-rw-r--r--src/Lexer.php1
-rw-r--r--src/Parser.php101
-rw-r--r--src/Statement.php30
-rw-r--r--src/Statements/AlterStatement.php3
-rw-r--r--src/Statements/ChecksumStatement.php (renamed from src/Statements/ChecsumStatement.php)0
-rw-r--r--src/Statements/CreateStatement.php2
-rw-r--r--src/Statements/MaintenanceStatement.php2
-rw-r--r--src/Statements/NotImplementedStatement.php2
-rw-r--r--src/Statements/RenameStatement.php2
-rw-r--r--src/Statements/SelectStatement.php43
-rw-r--r--src/Token.php86
-rw-r--r--src/Utils/Query.php58
-rw-r--r--src/Utils/Table.php3
35 files changed, 563 insertions, 243 deletions
diff --git a/src/Builder.php b/src/Builder.php
new file mode 100644
index 0000000..b4559e9
--- /dev/null
+++ b/src/Builder.php
@@ -0,0 +1,84 @@
+<?php
+
+/**
+ * This is one of the most important components, along with the lexer and the
+ * parser.
+ *
+ * @package SqlParser
+ */
+namespace SqlParser;
+
+use SqlParser\Exceptions\ParserException;
+
+/**
+ * Builds the string representation of a Statement.
+ *
+ * @category Parser
+ * @package SqlParser
+ * @author Dan Ungureanu <udan1107@gmail.com>
+ * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
+ */
+class Builder
+{
+
+ /**
+ * Statement to be build.
+ *
+ * @var Statement
+ */
+ public $statement;
+
+ /**
+ * Built query.
+ *
+ * @var string
+ */
+ public $query;
+
+ /**
+ * Constructor.
+ *
+ * @param Statement $statement
+ */
+ public function __construct($statement = null)
+ {
+ $this->statement = $statement;
+
+ if ($this->statement != null) {
+ $this->build();
+ }
+ }
+
+ /**
+ * Builds the statement.
+ *
+ * @return void
+ */
+ public function build()
+ {
+ $statement = $this->statement;
+ foreach ($statement::$CLAUSES as $clause) {
+ $name = $clause[0];
+ $type = $clause[1];
+
+ if (empty(Parser::$KEYWORD_PARSERS[$name])) {
+ continue;
+ }
+
+ $class = Parser::$KEYWORD_PARSERS[$name]['class'];
+ $field = Parser::$KEYWORD_PARSERS[$name]['field'];
+
+ if (empty($statement->$field)) {
+ continue;
+ }
+
+ if ($type & 2) {
+ $this->query .= $name . ' ';
+ }
+
+ if ($type & 1) {
+ $this->query .= $class::build($statement->$field) . ' ';
+ }
+ }
+ }
+}
diff --git a/src/Fragment.php b/src/Fragment.php
index a9a349a..6ae85da 100644
--- a/src/Fragment.php
+++ b/src/Fragment.php
@@ -38,4 +38,15 @@ abstract class Fragment
return null;
}
+ /**
+ * Builds the string representation of a fragment of this type.
+ *
+ * @param Fragment $fragment The fragment to be built.
+ *
+ * @return string
+ */
+ public static function build(Fragment $fragment)
+ {
+ return null;
+ }
}
diff --git a/src/Fragments/ArrayFragment.php b/src/Fragments/ArrayFragment.php
index 7ed22ad..db12622 100644
--- a/src/Fragments/ArrayFragment.php
+++ b/src/Fragments/ArrayFragment.php
@@ -26,6 +26,13 @@ class ArrayFragment extends Fragment
{
/**
+ * The array that contains the unprocessed value of each token.
+ *
+ * @var array
+ */
+ public $raw = array();
+
+ /**
* The array that contains the processed value of each token.
*
* @var array
@@ -33,11 +40,16 @@ class ArrayFragment extends Fragment
public $values = array();
/**
- * The array that contains the unprocessed value of each token.
+ * Constructor.
*
- * @var array
+ * @param array $raw The unprocessed values.
+ * @param array $values The processed values.
*/
- public $raw = array();
+ public function __construct(array $raw = array(), array $values = array())
+ {
+ $this->raw = $raw;
+ $this->values = $values;
+ }
/**
* @param Parser $parser The parser that serves as context.
@@ -67,7 +79,6 @@ class ArrayFragment extends Fragment
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
@@ -114,4 +125,22 @@ class ArrayFragment extends Fragment
return $ret;
}
+
+ /**
+ * @param ArrayFragment $fragment The fragment to be built.
+ *
+ * @return string
+ */
+ public static function build(ArrayFragment $fragment)
+ {
+ $values = array();
+ if (!empty($fragment->raw)) {
+ $values = $fragment->raw;
+ } else {
+ foreach ($fragment->values as $value) {
+ $values[] = $value;
+ }
+ }
+ return '(' . implode(', ', $values) . ')';
+ }
}
diff --git a/src/Fragments/CallKeyword.php b/src/Fragments/CallKeyword.php
index ae3c467..3b8cc80 100644
--- a/src/Fragments/CallKeyword.php
+++ b/src/Fragments/CallKeyword.php
@@ -35,9 +35,25 @@ class CallKeyword extends Fragment
/**
* The list of parameters
*
- * @var array
+ * @var ArrayFragment
*/
- public $parameters = array();
+ public $parameters;
+
+ /**
+ * Constructor.
+ *
+ * @param string $name The name of the function to be called.
+ * @param array|ArrayFragment $parameters The parameters of this function.
+ */
+ public function __construct($name = null, $parameters = null)
+ {
+ $this->name = $name;
+ if (is_array($parameters)) {
+ $this->parameters = new ArrayFragment($parameters);
+ } elseif ($parameters instanceof ArrayFragment) {
+ $this->parameters = $parameters;
+ }
+ }
/**
* @param Parser $parser The parser that serves as context.
@@ -64,7 +80,6 @@ class CallKeyword extends Fragment
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
@@ -86,7 +101,7 @@ class CallKeyword extends Fragment
$state = 1;
} elseif ($state === 1) {
if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
- $ret->parameters = ArrayFragment::parse($parser, $list)->values;
+ $ret->parameters = ArrayFragment::parse($parser, $list);
}
break;
}
@@ -95,4 +110,14 @@ class CallKeyword extends Fragment
return $ret;
}
+
+ /**
+ * @param CallKeyword $fragment The fragment to be built.
+ *
+ * @return string
+ */
+ public static function build(CallKeyword $fragment)
+ {
+ return $fragment->name . ArrayFragment::build($fragment->parameters);
+ }
}
diff --git a/src/Fragments/CreateDefFragment.php b/src/Fragments/CreateDefFragment.php
index 403426c..933ea5e 100644
--- a/src/Fragments/CreateDefFragment.php
+++ b/src/Fragments/CreateDefFragment.php
@@ -92,7 +92,6 @@ class CreateDefFragment extends Fragment
$ret = new CreateDefFragment();
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
diff --git a/src/Fragments/DataTypeFragment.php b/src/Fragments/DataTypeFragment.php
index 2ad700a..0b9e1a8 100644
--- a/src/Fragments/DataTypeFragment.php
+++ b/src/Fragments/DataTypeFragment.php
@@ -94,7 +94,6 @@ class DataTypeFragment extends Fragment
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
diff --git a/src/Fragments/FieldDefFragment.php b/src/Fragments/FieldDefFragment.php
index d38eeda..6c5771e 100644
--- a/src/Fragments/FieldDefFragment.php
+++ b/src/Fragments/FieldDefFragment.php
@@ -129,7 +129,6 @@ class FieldDefFragment extends Fragment
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
@@ -176,7 +175,7 @@ class FieldDefFragment extends Fragment
--$list->idx;
}
$state = 5;
- } else if ($state === 5) {
+ } elseif ($state === 5) {
if ((!empty($expr->type)) || (!empty($expr->key))) {
$ret[] = $expr;
}
diff --git a/src/Fragments/FieldFragment.php b/src/Fragments/FieldFragment.php
index 5140324..8b0f0ef 100644
--- a/src/Fragments/FieldFragment.php
+++ b/src/Fragments/FieldFragment.php
@@ -75,6 +75,38 @@ class FieldFragment extends Fragment
public $subquery;
/**
+ * Constructor.
+ *
+ * Syntax:
+ * new FieldFragment('expr')
+ * new FieldFragment('expr', 'alias')
+ * new FieldFragment('database', 'table', 'column')
+ * new FieldFragment('database', 'table', 'column', 'alias')
+ *
+ * If the database, table or column name is not required, pass an empty
+ * string.
+ *
+ * @param string $database The name of the database or the the expression.
+ * the the expression.
+ * @param string $table The name of the table or the alias of the expression.
+ * the alias of the expression.
+ * @param string $column The name of the column.
+ * @param string $alias The name of the alias.
+ */
+ public function __construct($database = null, $table = null, $column = null, $alias = null)
+ {
+ if (($column === null) && ($alias === null)) {
+ $this->expr = $database; // case 1
+ $this->alias = $table; // case 2
+ } else {
+ $this->database = $database; // case 3
+ $this->table = $table; // case 3
+ $this->column = $column; // case 3
+ $this->alias = $alias; // case 4
+ }
+ }
+
+ /**
* @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.
@@ -120,7 +152,6 @@ class FieldFragment extends Fragment
$prev = null;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
@@ -150,8 +181,10 @@ class FieldFragment extends Fragment
$alias = 2;
continue;
}
- break;
- } else if ($prev === true) {
+ if (!($token->flags & Token::FLAG_KEYWORD_FUNCTION)) {
+ break;
+ }
+ } elseif ($prev === true) {
if ((empty($ret->subquery) && (!empty(Parser::$STATEMENT_PARSERS[$token->value])))) {
// A `(` was previously found and this keyword is the
// beginning of a statement, so this is a subquery.
@@ -236,7 +269,7 @@ class FieldFragment extends Fragment
if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_FUNCTION)) {
$prev = strtoupper($token->value);
- } else if (($token->type === Token::TYPE_OPERATOR) || ($token->value === '(')) {
+ } elseif (($token->type === Token::TYPE_OPERATOR) || ($token->value === '(')) {
$prev = true;
} else {
$prev = null;
@@ -258,4 +291,36 @@ class FieldFragment extends Fragment
--$list->idx;
return $ret;
}
+
+ /**
+ * @param FieldFragment $fragment The fragment to be built.
+ *
+ * @return string
+ */
+ public static function build($fragment)
+ {
+ $ret = '';
+
+ if (!empty($fragment->expr)) {
+ $ret = $fragment->expr;
+ } else {
+ $fields = array();
+ if (!empty($fragment->database)) {
+ $fields[] = $fragment->database;
+ }
+ if (!empty($fragment->table)) {
+ $fields[] = $fragment->table;
+ }
+ if (!empty($fragment->column)) {
+ $fields[] = $fragment->column;
+ }
+ $ret = implode('.', $fields);
+ }
+
+ if (!empty($fragment->alias)) {
+ $ret .= ' AS ' . $fragment->alias;
+ }
+
+ return $ret;
+ }
}
diff --git a/src/Fragments/SelectKeyword.php b/src/Fragments/FieldListFragment.php
index 5cf4719..cc769e0 100644
--- a/src/Fragments/SelectKeyword.php
+++ b/src/Fragments/FieldListFragment.php
@@ -1,7 +1,7 @@
<?php
/**
- * `SELECT` keyword parser.
+ * Parses a a list of fields delimited by a single comma.
*
* @package SqlParser
* @subpackage Fragments
@@ -14,7 +14,7 @@ use SqlParser\Token;
use SqlParser\TokensList;
/**
- * `SELECT` keyword parser.
+ * Parses a a list of fields delimited by a single comma.
*
* @category Keywords
* @package SqlParser
@@ -22,7 +22,7 @@ use SqlParser\TokensList;
* @author Dan Ungureanu <udan1107@gmail.com>
* @license http://opensource.org/licenses/GPL-2.0 GNU Public License
*/
-class SelectKeyword extends Fragment
+class FieldListFragment extends Fragment
{
/**
@@ -39,7 +39,6 @@ class SelectKeyword extends Fragment
$expr = null;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
@@ -64,7 +63,7 @@ class SelectKeyword extends Fragment
if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) {
$ret[] = $expr;
} else {
- $expr = FieldFragment::parse($parser, $list);
+ $expr = FieldFragment::parse($parser, $list, $options);
if ($expr === null) {
break;
}
@@ -80,4 +79,13 @@ class SelectKeyword extends Fragment
--$list->idx;
return $ret;
}
+
+ public static function build($fragment)
+ {
+ $ret = array();
+ foreach ($fragment as $frag) {
+ $ret[] = $frag::build($frag);
+ }
+ return implode($ret, ', ');
+ }
}
diff --git a/src/Fragments/FromKeyword.php b/src/Fragments/FromKeyword.php
deleted file mode 100644
index 6fbf0ba..0000000
--- a/src/Fragments/FromKeyword.php
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-
-/**
- * `FROM` keyword parser.
- *
- * @package SqlParser
- * @subpackage Fragments
- */
-namespace SqlParser\Fragments;
-
-use SqlParser\Fragment;
-use SqlParser\Parser;
-use SqlParser\Token;
-use SqlParser\TokensList;
-
-/**
- * `FROM` keyword parser.
- *
- * @category Keywords
- * @package SqlParser
- * @subpackage Fragments
- * @author Dan Ungureanu <udan1107@gmail.com>
- * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
- */
-class FromKeyword extends Fragment
-{
-
- /**
- * @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 FieldFragment[]
- */
- public static function parse(Parser $parser, TokensList $list, array $options = array())
- {
- $ret = array();
-
- $expr = new FieldFragment();
-
- for (; $list->idx < $list->count; ++$list->idx) {
-
- /**
- * Token parsed at this moment.
- * @var 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;
- }
-
- // No keyword is expected.
- if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) {
- break;
- }
-
- if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) {
- $ret[] = $expr;
- } else {
- $expr = FieldFragment::parse($parser, $list, array('skipColumn' => true));
- if ($expr === null) {
- break;
- }
- }
-
- }
-
- // Last iteration was not saved.
- if ($expr !== null) {
- $ret[] = $expr;
- }
-
- --$list->idx;
- return $ret;
- }
-}
diff --git a/src/Fragments/IntoKeyword.php b/src/Fragments/IntoKeyword.php
index 558b3e6..0b51531 100644
--- a/src/Fragments/IntoKeyword.php
+++ b/src/Fragments/IntoKeyword.php
@@ -74,7 +74,6 @@ class IntoKeyword extends Fragment
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
@@ -105,13 +104,13 @@ class IntoKeyword extends Fragment
if ($state === 0) {
$ret->name = $token->value;
$state = 1;
- } else if ($state === 1) {
+ } elseif ($state === 1) {
if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
$ret->fields = ArrayFragment::parse($parser, $list)->values;
++$list->idx;
}
break;
- } else if ($state === 2) {
+ } elseif ($state === 2) {
$ret->name = $token->value;
++$list->idx;
break;
diff --git a/src/Fragments/JoinKeyword.php b/src/Fragments/JoinKeyword.php
index 011bd4d..f8e1a57 100644
--- a/src/Fragments/JoinKeyword.php
+++ b/src/Fragments/JoinKeyword.php
@@ -66,7 +66,6 @@ class JoinKeyword extends Fragment
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
diff --git a/src/Fragments/KeyFragment.php b/src/Fragments/KeyFragment.php
index 4a71857..d84c9f6 100644
--- a/src/Fragments/KeyFragment.php
+++ b/src/Fragments/KeyFragment.php
@@ -95,7 +95,6 @@ class KeyFragment extends Fragment
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
diff --git a/src/Fragments/LimitKeyword.php b/src/Fragments/LimitKeyword.php
index a23eb4c..af8d92d 100644
--- a/src/Fragments/LimitKeyword.php
+++ b/src/Fragments/LimitKeyword.php
@@ -40,6 +40,18 @@ class LimitKeyword extends Fragment
public $rowCount;
/**
+ * Constructor.
+ *
+ * @param int $rowCount The row count.
+ * @param int $offset The offset.
+ */
+ public function __construct($rowCount = null, $offset = null)
+ {
+ $this->rowCount = $rowCount;
+ $this->offset = $offset;
+ }
+
+ /**
* @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.
@@ -53,7 +65,6 @@ class LimitKeyword extends Fragment
$offset = false;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
@@ -103,4 +114,18 @@ class LimitKeyword extends Fragment
--$list->idx;
return $ret;
}
+
+ /**
+ * @param LimitKeyword $fragment The fragment to be built.
+ *
+ * @return string
+ */
+ public static function build($fragment)
+ {
+ if (empty($fragment->offset)) {
+ return $fragment->rowCount;
+ } else {
+ return $fragment->offset . ', ' . $fragment->rowCount;
+ }
+ }
}
diff --git a/src/Fragments/OptionsFragment.php b/src/Fragments/OptionsFragment.php
index 54d4857..16459cc 100644
--- a/src/Fragments/OptionsFragment.php
+++ b/src/Fragments/OptionsFragment.php
@@ -33,6 +33,17 @@ class OptionsFragment extends Fragment
public $options = array();
/**
+ * Constructor.
+ *
+ * @param array $options The array of options. Options that have a value
+ * must be an array with two keys 'name' and 'value'.
+ */
+ public function __construct(array $options = array())
+ {
+ $this->options = $options;
+ }
+
+ /**
* @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.
@@ -59,7 +70,6 @@ class OptionsFragment extends Fragment
$brackets = 0;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
@@ -128,6 +138,24 @@ class OptionsFragment extends Fragment
}
/**
+ * @param OptionsFragment $fragment The fragment to be built.
+ *
+ * @return string
+ */
+ public static function build(OptionsFragment $fragment)
+ {
+ $options = array();
+ foreach ($fragment->options as $option) {
+ if (is_array($option)) {
+ $options[] = $option['name'] . '=' . $option['value'];
+ } else {
+ $options[] = $option;
+ }
+ }
+ return implode(' ', $options);
+ }
+
+ /**
* Checks if it has the specified option and returns it value or true.
*
* @param string $key The key to be checked.
@@ -158,7 +186,7 @@ class OptionsFragment extends Fragment
{
if (is_array($options)) {
$this->options = array_merge_recursive($this->options, $options);
- } else if ($options instanceof OptionsFragment) {
+ } elseif ($options instanceof OptionsFragment) {
$this->options = array_merge_recursive($this->options, $options->options);
}
}
diff --git a/src/Fragments/OrderKeyword.php b/src/Fragments/OrderKeyword.php
index 5194208..7a76084 100644
--- a/src/Fragments/OrderKeyword.php
+++ b/src/Fragments/OrderKeyword.php
@@ -67,7 +67,6 @@ class OrderKeyword extends Fragment
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
@@ -90,7 +89,7 @@ class OrderKeyword extends Fragment
} elseif ($state === 1) {
if (($token->type === Token::TYPE_KEYWORD) && (($token->value === 'ASC') || ($token->value === 'DESC'))) {
$expr->type = $token->value;
- } else if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) {
+ } elseif (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) {
if (!empty($expr->field)) {
$ret[] = $expr;
}
diff --git a/src/Fragments/ParamDefFragment.php b/src/Fragments/ParamDefFragment.php
index a512596..583c3ab 100644
--- a/src/Fragments/ParamDefFragment.php
+++ b/src/Fragments/ParamDefFragment.php
@@ -80,7 +80,6 @@ class ParamDefFragment extends Fragment
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
diff --git a/src/Fragments/ReferencesKeyword.php b/src/Fragments/ReferencesKeyword.php
index d4afd01..8de0233 100644
--- a/src/Fragments/ReferencesKeyword.php
+++ b/src/Fragments/ReferencesKeyword.php
@@ -84,7 +84,6 @@ class ReferencesKeyword extends Fragment
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
@@ -104,10 +103,10 @@ class ReferencesKeyword extends Fragment
if ($state === 0) {
$ret->table = $token->value;
$state = 1;
- } else if ($state === 1) {
+ } elseif ($state === 1) {
$ret->columns = ArrayFragment::parse($parser, $list)->values;
$state = 2;
- } else if ($state === 2) {
+ } elseif ($state === 2) {
$ret->options = OptionsFragment::parse($parser, $list, static::$REFERENCES_OPTIONS);
++$list->idx;
break;
diff --git a/src/Fragments/RenameKeyword.php b/src/Fragments/RenameKeyword.php
index 980ad7b..077982a 100644
--- a/src/Fragments/RenameKeyword.php
+++ b/src/Fragments/RenameKeyword.php
@@ -71,7 +71,6 @@ class RenameKeyword extends Fragment
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
diff --git a/src/Fragments/SetKeyword.php b/src/Fragments/SetKeyword.php
index 547768c..bced45f 100644
--- a/src/Fragments/SetKeyword.php
+++ b/src/Fragments/SetKeyword.php
@@ -67,7 +67,6 @@ class SetKeyword extends Fragment
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
diff --git a/src/Fragments/ValuesKeyword.php b/src/Fragments/ValuesKeyword.php
index 6977f68..c867551 100644
--- a/src/Fragments/ValuesKeyword.php
+++ b/src/Fragments/ValuesKeyword.php
@@ -65,7 +65,6 @@ class ValuesKeyword extends Fragment
$state = 0;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
diff --git a/src/Fragments/WhereKeyword.php b/src/Fragments/WhereKeyword.php
index 1b36cc8..d2143f3 100644
--- a/src/Fragments/WhereKeyword.php
+++ b/src/Fragments/WhereKeyword.php
@@ -47,6 +47,16 @@ class WhereKeyword extends Fragment
public $condition;
/**
+ * Constructor.
+ *
+ * @param string $condition The condition or the operator.
+ */
+ public function __construct($condition = null)
+ {
+ $this->condition = trim($condition);
+ }
+
+ /**
* @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.
@@ -57,10 +67,13 @@ class WhereKeyword extends Fragment
{
$ret = array();
- $expr = new WhereKeyword();
+ /**
+ * The condition that was parsed so far.
+ * @var string
+ */
+ $condition = '';
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
@@ -73,23 +86,23 @@ class WhereKeyword extends Fragment
}
// Skipping whitespaces and comments.
- if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
+ if ($token->type === Token::TYPE_COMMENT) {
continue;
}
// Conditions are delimited by logical operators.
if (in_array($token->value, static::$OPERATORS, true)) {
- if (!empty($expr->condition)) {
- $ret[] = $expr;
+ if (!empty(trim($condition))) {
+ // Adding the condition that is delimited by this operator.
+ $ret[] = new WhereKeyword($condition);
+ $condition = '';
}
- $expr = new WhereKeyword();
+ // Adding the operator.
+ $expr = new WhereKeyword($token->value);
$expr->isOperator = true;
- $expr->condition = $token->value;
$ret[] = $expr;
- $expr = new WhereKeyword();
-
continue;
}
@@ -98,16 +111,30 @@ class WhereKeyword extends Fragment
break;
}
- $expr->condition .= $token->token;
+ $condition .= $token->token;
}
// Last iteration was not processed.
- if (!empty($expr->condition)) {
- $ret[] = $expr;
+ if (!empty(trim($condition))) {
+ $ret[] = new WhereKeyword($condition);
}
--$list->idx;
return $ret;
}
+
+ /**
+ * @param WhereKeyword $fragment The fragment to be built.
+ *
+ * @return string
+ */
+ public static function build($fragment)
+ {
+ $conditions = array();
+ foreach ($fragment as $f) {
+ $conditions[] = $f->condition;
+ }
+ return implode(' ', $conditions);
+ }
}
diff --git a/src/Lexer.php b/src/Lexer.php
index b91db8b..0d0862d 100644
--- a/src/Lexer.php
+++ b/src/Lexer.php
@@ -168,7 +168,6 @@ class Lexer
$lastToken = null;
for ($this->last = 0, $lastIdx = 0; $this->last < $this->len; $lastIdx = ++$this->last) {
-
/**
* The new token.
* @var Token
diff --git a/src/Parser.php b/src/Parser.php
index 2a9bd47..29e6701 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -9,6 +9,7 @@
*/
namespace SqlParser;
+use SqlParser\Statements\SelectStatement;
use SqlParser\Exceptions\ParserException;
/**
@@ -37,7 +38,7 @@ class Parser
'ANALYZE' => 'SqlParser\\Statements\\AnalyzeStatement',
'BACKUP' => 'SqlParser\\Statements\\BackupStatement',
'CHECK' => 'SqlParser\\Statements\\CheckStatement',
- 'CHECKSUM' => 'SqlParser\\Statements\\ChecsumStatement',
+ 'CHECKSUM' => 'SqlParser\\Statements\\ChecksumStatement',
'OPTIMIZE' => 'SqlParser\\Statements\\OptimizeStatement',
'REPAIR' => 'SqlParser\\Statements\\RepairStatement',
'RESTORE' => 'SqlParser\\Statements\\RestoreStatement',
@@ -79,38 +80,51 @@ class Parser
* @var array
*/
public static $KEYWORD_PARSERS = array(
+
+ // This is not a proper keyword and was added here to help the builder.
+ '_OPTIONS' => array(
+ 'class' => 'SqlParser\\Fragments\\OptionsFragment',
+ 'field' => 'options',
+ ),
+
'ALTER' => array(
'class' => 'SqlParser\\Fragments\\FieldFragment',
'field' => 'table',
'options' => array('skipColumn' => true),
),
'ANALYZE' => array(
- 'class' => 'SqlParser\\Fragments\\FromKeyword',
+ 'class' => 'SqlParser\\Fragments\\FieldListFragment',
'field' => 'tables',
+ 'options' => array('skipColumn' => true),
),
'BACKUP' => array(
- 'class' => 'SqlParser\\Fragments\\FromKeyword',
+ 'class' => 'SqlParser\\Fragments\\FieldListFragment',
'field' => 'tables',
+ 'options' => array('skipColumn' => true),
),
'CALL' => array(
'class' => 'SqlParser\\Fragments\\CallKeyword',
'field' => 'call',
),
'CHECK' => array(
- 'class' => 'SqlParser\\Fragments\\FromKeyword',
+ 'class' => 'SqlParser\\Fragments\\FieldListFragment',
'field' => 'tables',
+ 'options' => array('skipColumn' => true),
),
'CHECKSUM' => array(
- 'class' => 'SqlParser\\Fragments\\FromKeyword',
+ 'class' => 'SqlParser\\Fragments\\FieldListFragment',
'field' => 'tables',
+ 'options' => array('skipColumn' => true),
),
'DROP' => array(
- 'class' => 'SqlParser\\Fragments\\FromKeyword',
- 'field' => 'fields'
+ 'class' => 'SqlParser\\Fragments\\FieldListFragment',
+ 'field' => 'fields',
+ 'options' => array('skipColumn' => true),
),
'FROM' => array(
- 'class' => 'SqlParser\\Fragments\\FromKeyword',
+ 'class' => 'SqlParser\\Fragments\\FieldListFragment',
'field' => 'from',
+ 'options' => array('skipColumn' => true),
),
'GROUP BY' => array(
'class' => 'SqlParser\\Fragments\\OrderKeyword',
@@ -133,8 +147,9 @@ class Parser
'field' => 'limit',
),
'OPTIMIZE' => array(
- 'class' => 'SqlParser\\Fragments\\FromKeyword',
+ 'class' => 'SqlParser\\Fragments\\FieldListFragment',
'field' => 'tables',
+ 'options' => array('skipColumn' => true),
),
'ORDER BY' => array(
'class' => 'SqlParser\\Fragments\\OrderKeyword',
@@ -153,24 +168,27 @@ class Parser
'field' => 'renames',
),
'REPAIR' => array(
- 'class' => 'SqlParser\\Fragments\\FromKeyword',
+ 'class' => 'SqlParser\\Fragments\\FieldListFragment',
'field' => 'tables',
+ 'options' => array('skipColumn' => true),
),
'RESTORE' => array(
- 'class' => 'SqlParser\\Fragments\\FromKeyword',
+ 'class' => 'SqlParser\\Fragments\\FieldListFragment',
'field' => 'tables',
+ 'options' => array('skipColumn' => true),
),
'SET' => array(
'class' => 'SqlParser\\Fragments\\SetKeyword',
'field' => 'set',
),
'SELECT' => array(
- 'class' => 'SqlParser\\Fragments\\SelectKeyword',
+ 'class' => 'SqlParser\\Fragments\\FieldListFragment',
'field' => 'expr',
),
'UPDATE' => array(
- 'class' => 'SqlParser\\Fragments\\FromKeyword',
+ 'class' => 'SqlParser\\Fragments\\FieldListFragment',
'field' => 'from',
+ 'options' => array('skipColumn' => true),
),
'VALUE' => array(
'class' => 'SqlParser\\Fragments\\ValuesKeyword',
@@ -252,6 +270,29 @@ class Parser
*/
public function parse()
{
+
+ /**
+ * Last parsed statement.
+ * @var Statement
+ */
+ $lastStatement = null;
+
+ /**
+ * Whether a union is parsed or not.
+ * @var bool
+ */
+ $inUnion = true;
+
+ /**
+ * The index of the last token from the last statement.
+ * @var int
+ */
+ $prevLastIdx = -1;
+
+ /**
+ * The list of tokens.
+ * @var TokensList
+ */
$list = &$this->list;
for (; $list->idx < $list->count; ++$list->idx) {
@@ -268,13 +309,21 @@ class Parser
continue;
}
+ if ($token->value === 'UNION') {
+ $inUnion = true;
+ continue;
+ }
+
// Checking if it is a known statement that can be parsed.
if (empty(static::$STATEMENT_PARSERS[$token->value])) {
$this->error(
'Unrecognized statement type "' . $token->value . '".',
$token
);
+ // Skipping to the end of this statement.
$list->getNextOfType(Token::TYPE_DELIMITER);
+ //
+ $prevLastIdx = $list->idx;
continue;
}
@@ -290,8 +339,32 @@ class Parser
*/
$stmt = new $class();
+ // The first token that is a part of this token is the next token
+ // unprocessed by the previous statement.
+ // There might be brackets around statements and this shouldn't
+ // affect the parser
+ $stmt->first = $prevLastIdx + 1;
+
+ // Parsing the actual statement.
$stmt->parse($this, $this->list);
- $this->statements[] = $stmt;
+
+ // Storing the index of the last token parsed and updating the old
+ // index.
+ $stmt->last = $list->idx;
+ $prevLastIdx = $list->idx;
+
+ // Finally, storing the statement.
+ if (($inUnion)
+ && ($lastStatement instanceof SelectStatement)
+ && ($stmt instanceof SelectStatement)
+ ) {
+ $lastStatement->union[] = $stmt;
+ $inUnion = false;
+ } else {
+ $this->statements[] = $stmt;
+ $lastStatement = $stmt;
+ }
+
}
}
diff --git a/src/Statement.php b/src/Statement.php
index f10b5ee..0cb362c 100644
--- a/src/Statement.php
+++ b/src/Statement.php
@@ -27,6 +27,20 @@ abstract class Statement
{
/**
+ * The clauses of this statement, in order.
+ *
+ * The value attributed to each clause is used by the builder and it may
+ * have one of the following values:
+ *
+ * - 1 = 01 - add the clause only
+ * - 2 = 10 - add the keyword
+ * - 3 = 11 - add both the keyword and the clause
+ *
+ * @var array
+ */
+ public static $CLAUSES;
+
+ /**
* The options of this query.
*
* @var OptionsFragment
@@ -59,8 +73,6 @@ abstract class Statement
*/
public function parse(Parser $parser, TokensList $list)
{
- $this->first = $list->idx;
-
/**
* Whether options were parsed or not.
* For statements that do not have any options this is set to `true` by
@@ -70,7 +82,6 @@ abstract class Statement
$parsedOptions = isset(static::$OPTIONS) ? false : true;
for (; $list->idx < $list->count; ++$list->idx) {
-
/**
* Token parsed at this moment.
* @var Token
@@ -88,6 +99,12 @@ abstract class Statement
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
@@ -124,7 +141,7 @@ abstract class Statement
);
$parsedOptions = true;
}
- } else if ($class === null) {
+ } elseif ($class === null) {
// There is no parser for this keyword and isn't the beggining
// of a statement (so no options) either.
$parser->error(
@@ -145,11 +162,11 @@ abstract class Statement
$this->after($parser, $list, $token);
}
- $this->last = $list->idx--; // Go back to last used token.
+ --$list->idx; // Go back to last used token.
}
/**
- * Function called before the token was processed.
+ * Function called before the token is processed.
*
* @param Parser $parser The instance that requests parsing.
* @param TokensList $list The list of tokens to be parsed.
@@ -175,5 +192,4 @@ abstract class Statement
{
}
-
}
diff --git a/src/Statements/AlterStatement.php b/src/Statements/AlterStatement.php
index b6c18ed..81bca05 100644
--- a/src/Statements/AlterStatement.php
+++ b/src/Statements/AlterStatement.php
@@ -97,6 +97,8 @@ class AlterStatement extends NotImplementedStatement
);
/**
+ * Function called after the token was processed.
+ *
* Extracts the name of affected column.
*
* @param Parser $parser The instance that requests parsing.
@@ -124,5 +126,4 @@ class AlterStatement extends NotImplementedStatement
//
parent::after($parser, $list, $token);
}
-
}
diff --git a/src/Statements/ChecsumStatement.php b/src/Statements/ChecksumStatement.php
index e2c6371..e2c6371 100644
--- a/src/Statements/ChecsumStatement.php
+++ b/src/Statements/ChecksumStatement.php
diff --git a/src/Statements/CreateStatement.php b/src/Statements/CreateStatement.php
index ef11537..f13866a 100644
--- a/src/Statements/CreateStatement.php
+++ b/src/Statements/CreateStatement.php
@@ -100,6 +100,8 @@ class CreateStatement extends Statement
public $body;
/**
+ * Function called before the token is processed.
+ *
* Parsing the `CREATE` statement.
*
* @param Parser $parser The instance that requests parsing.
diff --git a/src/Statements/MaintenanceStatement.php b/src/Statements/MaintenanceStatement.php
index a0df634..97c87b9 100644
--- a/src/Statements/MaintenanceStatement.php
+++ b/src/Statements/MaintenanceStatement.php
@@ -37,6 +37,8 @@ class MaintenanceStatement extends Statement
public $tables;
/**
+ * Function called after the token was processed.
+ *
* Parses the additional options fragment at the end.
*
* @param Parser $parser The instance that requests parsing.
diff --git a/src/Statements/NotImplementedStatement.php b/src/Statements/NotImplementedStatement.php
index 1689df2..b96c558 100644
--- a/src/Statements/NotImplementedStatement.php
+++ b/src/Statements/NotImplementedStatement.php
@@ -28,6 +28,8 @@ class NotImplementedStatement extends Statement
{
/**
+ * Function called after the token was processed.
+ *
* Jump to the end of the delimiter.
*
* @param Parser $parser The instance that requests parsing.
diff --git a/src/Statements/RenameStatement.php b/src/Statements/RenameStatement.php
index 5ebd2fa..473efe0 100644
--- a/src/Statements/RenameStatement.php
+++ b/src/Statements/RenameStatement.php
@@ -36,6 +36,8 @@ class RenameStatement extends Statement
public $renames;
/**
+ * Function called before the token is processed.
+ *
* Skips the `TABLE` keyword after `RENAME`.
*
* @param Parser $parser The instance that requests parsing.
diff --git a/src/Statements/SelectStatement.php b/src/Statements/SelectStatement.php
index 0c4c354..7704e26 100644
--- a/src/Statements/SelectStatement.php
+++ b/src/Statements/SelectStatement.php
@@ -68,17 +68,29 @@ class SelectStatement extends Statement
);
/**
- * The sections of this statement, in order.
+ * The clauses of this statement, in order.
*
- * Used by the query builder to arrange the clauses.
+ * @see Statement::$CLAUSES
*
* @var array
*/
- public static $SECTIONS = array(
- 'SELECT' => 0, '%OPTIONS' => 1,'FROM' => 2, 'PARTITION' => 3,
- 'WHERE' => 4, 'GROUP BY' => 5, 'HAVING' => 6, 'ORDER BY' => 7,
- 'LIMIT' => 8, 'PROCEDURE' => 9, 'INTO' => 10, 'UNION' => 11,
- 'JOIN' => 12, '%OPTIONS' => 13
+ public static $CLAUSES = array(
+ 'SELECT' => array('SELECT', 2),
+ // Used for options.
+ '_OPTIONS' => array('_OPTIONS', 1),
+ // Used for select expressions.
+ '_SELECT' => array('SELECT', 1),
+ 'FROM' => array('FROM', 3),
+ 'PARTITION' => array('PARTITION', 3),
+ 'WHERE' => array('WHERE', 3),
+ 'GROUP BY' => array('GROUP BY', 3),
+ 'HAVING' => array('HAVING', 3),
+ 'ORDER BY' => array('ORDER BY', 3),
+ 'LIMIT' => array('LIMIT', 3),
+ 'PROCEDURE' => array('PROCEDURE', 3),
+ 'INTO' => array('INTO', 3),
+ 'UNION' => array('UNION', 3),
+ 'JOIN' => array('JOIN', 3),
);
/**
@@ -86,33 +98,33 @@ class SelectStatement extends Statement
*
* @var FieldFragment[]
*/
- public $expr;
+ public $expr = array();
/**
* Tables used as sources for this statement.
*
* @var FieldFragment[]
*/
- public $from;
+ public $from = array();
/**
* Partitions used as source for this statement.
*
- * @var ArrayFragment[]
+ * @var ArrayFragment
*/
public $partition;
/**
* Conditions used for filtering each row of the result set.
*
- * @var WhereKeyword
+ * @var WhereKeyword[]
*/
public $where;
/**
* Conditions used for grouping the result set.
*
- * @var GroupKeyword
+ * @var OrderKeyword[]
*/
public $group;
@@ -157,4 +169,11 @@ class SelectStatement extends Statement
* @var JoinKeyword
*/
public $join;
+
+ /**
+ * Unions.
+ *
+ * @var SelectStatement[]
+ */
+ public $union = array();
}
diff --git a/src/Token.php b/src/Token.php
index fa23d28..1db0d1d 100644
--- a/src/Token.php
+++ b/src/Token.php
@@ -217,52 +217,52 @@ class Token
public function extract()
{
switch ($this->type) {
- case Token::TYPE_KEYWORD:
- if (!($this->flags & Token::FLAG_KEYWORD_RESERVED)) {
- // Unreserved keywords should stay the way they are because they
- // might represent field names.
- return $this->token;
- }
- return strtoupper($this->token);
- case Token::TYPE_WHITESPACE:
- return ' ';
- case Token::TYPE_BOOL:
- return strtoupper($this->token) === 'TRUE';
- case Token::TYPE_NUMBER:
- $ret = str_replace('--', '', $this->token); // e.g. ---42 === -42
- if ($this->flags & Token::FLAG_NUMBER_HEX) {
- if ($this->flags & Token::FLAG_NUMBER_NEGATIVE) {
- $ret = str_replace('-', '', $this->token);
- sscanf($ret, "%x", $ret);
- $ret = -$ret;
- } else {
- sscanf($ret, "%x", $ret);
+ case Token::TYPE_KEYWORD:
+ if (!($this->flags & Token::FLAG_KEYWORD_RESERVED)) {
+ // Unreserved keywords should stay the way they are because they
+ // might represent field names.
+ return $this->token;
}
- } elseif (($this->flags & Token::FLAG_NUMBER_APPROXIMATE)
+ return strtoupper($this->token);
+ case Token::TYPE_WHITESPACE:
+ return ' ';
+ case Token::TYPE_BOOL:
+ return strtoupper($this->token) === 'TRUE';
+ case Token::TYPE_NUMBER:
+ $ret = str_replace('--', '', $this->token); // e.g. ---42 === -42
+ if ($this->flags & Token::FLAG_NUMBER_HEX) {
+ if ($this->flags & Token::FLAG_NUMBER_NEGATIVE) {
+ $ret = str_replace('-', '', $this->token);
+ sscanf($ret, "%x", $ret);
+ $ret = -$ret;
+ } else {
+ sscanf($ret, "%x", $ret);
+ }
+ } elseif (($this->flags & Token::FLAG_NUMBER_APPROXIMATE)
|| ($this->flags & Token::FLAG_NUMBER_FLOAT)
- ) {
- sscanf($ret, "%f", $ret);
- } else {
- sscanf($ret, "%d", $ret);
- }
- return $ret;
- case Token::TYPE_STRING:
- $quote = $this->token[0];
- $str = str_replace($quote . $quote, $quote, $this->token);
- return mb_substr($str, 1, -1); // trims quotes
- case Token::TYPE_SYMBOL:
- $str = $this->token;
- if ((isset($str[0])) && ($str[0] === '@')) {
- $str = mb_substr($str, 1);
- }
- if ((isset($str[0])) && (($str[0] === '`')
+ ) {
+ sscanf($ret, "%f", $ret);
+ } else {
+ sscanf($ret, "%d", $ret);
+ }
+ return $ret;
+ case Token::TYPE_STRING:
+ $quote = $this->token[0];
+ $str = str_replace($quote . $quote, $quote, $this->token);
+ return mb_substr($str, 1, -1); // trims quotes
+ case Token::TYPE_SYMBOL:
+ $str = $this->token;
+ if ((isset($str[0])) && ($str[0] === '@')) {
+ $str = mb_substr($str, 1);
+ }
+ if ((isset($str[0])) && (($str[0] === '`')
|| ($str[0] === '"') || ($str[0] === '\''))
- ) {
- $quote = $str[0];
- $str = str_replace($quote . $quote, $quote, $str);
- $str = mb_substr($str, 1, -1);
- }
- return $str;
+ ) {
+ $quote = $str[0];
+ $str = str_replace($quote . $quote, $quote, $str);
+ $str = mb_substr($str, 1, -1);
+ }
+ return $str;
}
return $this->token;
}
diff --git a/src/Utils/Query.php b/src/Utils/Query.php
index dde3304..f973744 100644
--- a/src/Utils/Query.php
+++ b/src/Utils/Query.php
@@ -222,32 +222,32 @@ class Query
if ($statement instanceof AlterStatement) {
$flags['querytype'] = 'ALTER';
$flags['reload'] = true;
- } else if ($statement instanceof CreateStatement) {
+ } elseif ($statement instanceof CreateStatement) {
$flags['querytype'] = 'CREATE';
$flags['reload'] = true;
- } else if ($statement instanceof AnalyzeStatement) {
+ } elseif ($statement instanceof AnalyzeStatement) {
$flags['querytype'] = 'ANALYZE';
$flags['is_maint'] = true;
- } else if ($statement instanceof CheckStatement) {
+ } elseif ($statement instanceof CheckStatement) {
$flags['querytype'] = 'CHECK';
$flags['is_maint'] = true;
- } else if ($statement instanceof ChecksumStatement) {
+ } elseif ($statement instanceof ChecksumStatement) {
$flags['querytype'] = 'CHECKSUM';
$flags['is_maint'] = true;
- } else if ($statement instanceof OptimizeStatement) {
+ } elseif ($statement instanceof OptimizeStatement) {
$flags['querytype'] = 'OPTIMIZE';
$flags['is_maint'] = true;
- } else if ($statement instanceof RepairStatement) {
+ } elseif ($statement instanceof RepairStatement) {
$flags['querytype'] = 'REPAIR';
$flags['is_maint'] = true;
- } else if ($statement instanceof CallStatement) {
+ } elseif ($statement instanceof CallStatement) {
$flags['querytype'] = 'CALL';
$flags['is_procedure'] = true;
- } else if ($statement instanceof DeleteStatement) {
+ } elseif ($statement instanceof DeleteStatement) {
$flags['querytype'] = 'DELETE';
$flags['is_delete'] = true;
$flags['is_affected'] = true;
- } else if ($statement instanceof DropStatement) {
+ } elseif ($statement instanceof DropStatement) {
$flags['querytype'] = 'DROP';
$flags['reload'] = true;
@@ -256,19 +256,19 @@ class Query
) {
$flags['drop_database'] = true;
}
- } else if ($statement instanceof ExplainStatement) {
+ } elseif ($statement instanceof ExplainStatement) {
$flags['querytype'] = 'EXPLAIN';
$flags['is_explain'] = true;
- } else if ($statement instanceof InsertStatement) {
+ } elseif ($statement instanceof InsertStatement) {
$flags['querytype'] = 'INSERT';
$flags['is_affected'] = true;
$flags['is_insert'] = true;
- } else if ($statement instanceof ReplaceStatement) {
+ } elseif ($statement instanceof ReplaceStatement) {
$flags['querytype'] = 'REPLACE';
$flags['is_affected'] = true;
$flags['is_replace'] = true;
$flags['is_insert'] = true;
- } else if ($statement instanceof SelectStatement) {
+ } elseif ($statement instanceof SelectStatement) {
$flags['querytype'] = 'SELECT';
$flags['is_select'] = true;
@@ -294,7 +294,7 @@ class Query
if (!empty($expr->function)) {
if ($expr->function === 'COUNT') {
$flags['is_count'] = true;
- } else if (in_array($expr->function, static::$FUNCTIONS)) {
+ } elseif (in_array($expr->function, static::$FUNCTIONS)) {
$flags['is_func'] = true;
}
}
@@ -325,10 +325,10 @@ class Query
$flags['join'] = true;
}
- } else if ($statement instanceof ShowStatement) {
+ } elseif ($statement instanceof ShowStatement) {
$flags['querytype'] = 'SHOW';
$flags['is_show'] = true;
- } else if ($statement instanceof UpdateStatement) {
+ } elseif ($statement instanceof UpdateStatement) {
$flags['querytype'] = 'UPDATE';
$flags['is_affected'] = true;
}
@@ -409,7 +409,7 @@ class Query
/**
* Gets the type of clause.
*
- * @param string $clause The clause.
+ * @param string $clause The clause.
*
* @return string
*/
@@ -450,7 +450,7 @@ class Query
{
/**
- * Current location.
+ * The index of the current clause.
* @var int
*/
$currIdx = 0;
@@ -469,19 +469,20 @@ class Query
$ret = '';
/**
- * The place where the clause should be added.
+ * The clauses of this type of statement and their index.
+ * @var array
+ */
+ $clauses = array_flip(array_keys($statement::$CLAUSES));
+
+ /**
+ * The index of this clause.
* @var int
*/
- $clauseIdx = $statement::$SECTIONS[static::getClauseType($clause)];
+ $clauseIdx = $clauses[static::getClauseType($clause)];
for ($i = $statement->first; $i <= $statement->last; ++$i) {
-
$token = $list->tokens[$i];
- if ($token->type === Token::TYPE_DELIMITER) {
- break;
- }
-
if ($token->type === Token::TYPE_OPERATOR) {
if ($token->value === '(') {
++$brackets;
@@ -493,9 +494,9 @@ class Query
if ($brackets == 0) {
// Checking if we changed sections.
if ($token->type === Token::TYPE_KEYWORD) {
- if (isset($statement::$SECTIONS[$token->value])) {
- if ($statement::$SECTIONS[$token->value] >= $currIdx) {
- $currIdx = $statement::$SECTIONS[$token->value];
+ if (isset($clauses[$token->value])) {
+ if ($clauses[$token->value] >= $currIdx) {
+ $currIdx = $clauses[$token->value];
if (($skipFirst) && ($currIdx == $clauseIdx)) {
// This token is skipped (not added to the old
// clause) because it will be replaced.
@@ -546,5 +547,4 @@ class Query
$clause . ' ' .
static::getClause($statement, $list, $clause, 1, false);
}
-
}
diff --git a/src/Utils/Table.php b/src/Utils/Table.php
index 95b6850..86ccbfb 100644
--- a/src/Utils/Table.php
+++ b/src/Utils/Table.php
@@ -43,7 +43,6 @@ class Table
$ret = array();
foreach ($statement->fields as $field) {
-
if ((empty($field->key)) || ($field->key->type !== 'FOREIGN KEY')) {
continue;
}
@@ -93,7 +92,6 @@ class Table
$ret = array();
foreach ($statement->fields as $field) {
-
// Skipping keys.
if (empty($field->type)) {
continue;
@@ -105,7 +103,6 @@ class Table
);
if ($field->options) {
-
if ($field->type->name === 'TIMESTAMP') {
if ($field->options->has('NOT NULL')) {
$ret[$field->name]['timestamp_not_null'] = true;