From d91def3d8433570eb58a1c3c5bfb7198d8bf74ac Mon Sep 17 00:00:00 2001 From: shreesh arora Date: Mon, 3 May 2021 01:06:30 +0530 Subject: [PATCH 1/2] update parser_sql --- tools/parser_sql/LICENSE | 62 +-- tools/parser_sql/Options.php | 57 +++ tools/parser_sql/PHPSQLCreator.php | 115 +++--- tools/parser_sql/PHPSQLParser.php | 77 +++- tools/parser_sql/builders/AliasBuilder.php | 10 +- .../builders/AliasReferenceBuilder.php | 63 +++ tools/parser_sql/builders/AlterBuilder.php | 35 ++ .../builders/AlterStatementBuilder.php | 24 ++ .../builders/BracketStatementBuilder.php | 78 ++++ tools/parser_sql/builders/Builder.php | 63 +++ .../builders/CharacterSetBuilder.php | 15 +- tools/parser_sql/builders/CheckBuilder.php | 14 +- .../parser_sql/builders/CollationBuilder.php | 14 +- .../builders/ColumnDefinitionBuilder.php | 14 +- .../parser_sql/builders/ColumnListBuilder.php | 29 +- .../builders/ColumnReferenceBuilder.php | 18 +- .../ColumnTypeBracketExpressionBuilder.php | 11 +- .../parser_sql/builders/ColumnTypeBuilder.php | 31 +- tools/parser_sql/builders/ConstantBuilder.php | 10 +- .../parser_sql/builders/ConstraintBuilder.php | 14 +- tools/parser_sql/builders/CreateBuilder.php | 24 +- .../builders/CreateIndexBuilder.php | 80 ++++ .../builders/CreateIndexOptionsBuilder.php | 109 +++++ .../builders/CreateIndexTableBuilder.php | 72 ++++ .../builders/CreateIndexTypeBuilder.php | 62 +++ .../builders/CreateStatementBuilder.php | 12 +- .../builders/CreateTableBuilder.php | 17 +- .../builders/CreateTableDefinitionBuilder.php | 8 +- .../builders/CreateTableOptionsBuilder.php | 20 +- .../CreateTableSelectOptionBuilder.php | 8 +- tools/parser_sql/builders/DataTypeBuilder.php | 9 +- tools/parser_sql/builders/DatabaseBuilder.php | 9 +- .../builders/DefaultValueBuilder.php | 62 +++ tools/parser_sql/builders/DeleteBuilder.php | 28 +- .../builders/DeleteStatementBuilder.php | 18 +- .../parser_sql/builders/DirectionBuilder.php | 8 +- tools/parser_sql/builders/DropBuilder.php | 100 +++++ .../builders/DropExpressionBuilder.php | 103 +++++ .../parser_sql/builders/DropIndexBuilder.php | 63 +++ .../builders/DropIndexTableBuilder.php | 67 +++ .../builders/DropStatementBuilder.php | 63 +++ tools/parser_sql/builders/EngineBuilder.php | 9 +- .../parser_sql/builders/ForeignKeyBuilder.php | 15 +- .../parser_sql/builders/ForeignRefBuilder.php | 14 +- tools/parser_sql/builders/FromBuilder.php | 57 ++- tools/parser_sql/builders/FunctionBuilder.php | 43 +- .../builders/GroupByAliasBuilder.php | 62 +++ tools/parser_sql/builders/GroupByBuilder.php | 30 +- .../builders/GroupByExpressionBuilder.php | 89 ++++ .../HavingBracketExpressionBuilder.php | 90 ++++ tools/parser_sql/builders/HavingBuilder.php | 97 +++++ .../builders/HavingExpressionBuilder.php | 94 +++++ tools/parser_sql/builders/InListBuilder.php | 10 +- .../builders/IndexAlgorithmBuilder.php | 91 ++++ .../builders/IndexColumnBuilder.php | 13 +- .../builders/IndexCommentBuilder.php | 85 ++++ .../builders/IndexHintListBuilder.php | 70 ++++ tools/parser_sql/builders/IndexKeyBuilder.php | 97 +++++ .../parser_sql/builders/IndexLockBuilder.php | 91 ++++ .../builders/IndexParserBuilder.php | 15 +- .../parser_sql/builders/IndexSizeBuilder.php | 15 +- .../parser_sql/builders/IndexTypeBuilder.php | 15 +- tools/parser_sql/builders/InsertBuilder.php | 64 +-- .../builders/InsertColumnListBuilder.php | 80 ++++ .../builders/InsertStatementBuilder.php | 34 +- tools/parser_sql/builders/JoinBuilder.php | 9 +- tools/parser_sql/builders/LikeBuilder.php | 14 +- .../builders/LikeExpressionBuilder.php | 12 +- tools/parser_sql/builders/LimitBuilder.php | 11 +- tools/parser_sql/builders/OperatorBuilder.php | 9 +- .../builders/OrderByAliasBuilder.php | 10 +- .../OrderByBracketExpressionBuilder.php | 69 ++++ tools/parser_sql/builders/OrderByBuilder.php | 46 ++- .../OrderByColumnReferenceBuilder.php | 69 ++++ .../builders/OrderByExpressionBuilder.php | 69 ++++ .../builders/OrderByFunctionBuilder.php | 69 ++++ .../builders/OrderByReservedBuilder.php | 69 ++++ tools/parser_sql/builders/PositionBuilder.php | 9 +- .../parser_sql/builders/PrimaryKeyBuilder.php | 23 +- .../parser_sql/builders/ProcedureBuilder.php | 9 +- tools/parser_sql/builders/QueryBuilder.php | 97 +++++ tools/parser_sql/builders/RecordBuilder.php | 26 +- .../parser_sql/builders/RefClauseBuilder.php | 58 ++- tools/parser_sql/builders/RefTypeBuilder.php | 5 +- .../builders/RenameStatementBuilder.php | 86 ++++ tools/parser_sql/builders/ReplaceBuilder.php | 100 +++++ .../builders/ReplaceColumnListBuilder.php | 80 ++++ .../builders/ReplaceStatementBuilder.php | 89 ++++ tools/parser_sql/builders/ReservedBuilder.php | 13 +- tools/parser_sql/builders/SchemaBuilder.php | 62 +++ .../SelectBracketExpressionBuilder.php | 21 +- tools/parser_sql/builders/SelectBuilder.php | 17 +- .../builders/SelectExpressionBuilder.php | 11 +- .../builders/SelectStatementBuilder.php | 42 +- tools/parser_sql/builders/SetBuilder.php | 10 +- .../builders/SetExpressionBuilder.php | 42 +- tools/parser_sql/builders/ShowBuilder.php | 32 +- .../builders/ShowStatementBuilder.php | 13 +- tools/parser_sql/builders/SignBuilder.php | 62 +++ tools/parser_sql/builders/SubQueryBuilder.php | 23 +- tools/parser_sql/builders/SubTreeBuilder.php | 57 ++- .../TableBracketExpressionBuilder.php | 25 +- tools/parser_sql/builders/TableBuilder.php | 35 +- .../builders/TableExpressionBuilder.php | 26 +- .../parser_sql/builders/TempTableBuilder.php | 91 ++++ tools/parser_sql/builders/TruncateBuilder.php | 71 ++++ .../builders/TruncateStatementBuilder.php | 72 ++++ .../builders/UnionAllStatementBuilder.php | 33 ++ .../builders/UnionStatementBuilder.php | 31 ++ tools/parser_sql/builders/UpdateBuilder.php | 27 +- .../builders/UpdateStatementBuilder.php | 10 +- .../builders/UserVariableBuilder.php | 9 +- tools/parser_sql/builders/ValuesBuilder.php | 21 +- tools/parser_sql/builders/ViewBuilder.php | 62 +++ .../WhereBracketExpressionBuilder.php | 42 +- tools/parser_sql/builders/WhereBuilder.php | 35 +- .../builders/WhereExpressionBuilder.php | 58 +-- .../exceptions/InvalidParameterException.php | 59 +-- .../UnableToCalculatePositionException.php | 57 ++- .../exceptions/UnableToCreateSQLException.php | 59 +-- .../UnsupportedFeatureException.php | 56 ++- tools/parser_sql/lexer/LexerSplitter.php | 83 ++-- tools/parser_sql/lexer/PHPSQLLexer.php | 203 ++++++--- .../positions/PositionCalculator.php | 178 +++++--- .../processors/AbstractProcessor.php | 229 +++++++--- .../processors/BracketProcessor.php | 100 +++++ .../processors/ColumnDefinitionProcessor.php | 133 +++--- .../processors/ColumnListProcessor.php | 4 +- .../processors/CreateDefinitionProcessor.php | 183 ++++---- .../parser_sql/processors/CreateProcessor.php | 89 ++-- .../processors/DefaultProcessor.php | 93 +++-- .../parser_sql/processors/DeleteProcessor.php | 82 ++-- tools/parser_sql/processors/DescProcessor.php | 4 +- .../processors/DescribeProcessor.php | 62 +-- tools/parser_sql/processors/DropProcessor.php | 148 ++++--- .../processors/DuplicateProcessor.php | 12 +- .../processors/ExplainProcessor.php | 66 +-- .../processors/ExpressionListProcessor.php | 162 +++++--- tools/parser_sql/processors/FromProcessor.php | 222 +++++++--- .../processors/GroupByProcessor.php | 4 +- .../parser_sql/processors/HavingProcessor.php | 90 ++-- .../processors/IndexColumnListProcessor.php | 4 +- .../parser_sql/processors/IndexProcessor.php | 306 ++++++++++++++ .../parser_sql/processors/InsertProcessor.php | 187 ++++++--- tools/parser_sql/processors/IntoProcessor.php | 4 +- .../parser_sql/processors/LimitProcessor.php | 74 ++-- .../processors/OptionsProcessor.php | 77 ++++ .../processors/OrderByProcessor.php | 78 ++-- .../PartitionDefinitionProcessor.php | 390 ++++++++++++++++++ .../processors/PartitionOptionsProcessor.php | 361 ++++++++++++++++ .../parser_sql/processors/RecordProcessor.php | 75 ++-- .../ReferenceDefinitionProcessor.php | 7 +- .../parser_sql/processors/RenameProcessor.php | 68 +-- .../processors/ReplaceProcessor.php | 63 +-- .../processors/SQLChunkProcessor.php | 166 ++++---- tools/parser_sql/processors/SQLProcessor.php | 231 +++++++---- .../processors/SelectExpressionProcessor.php | 53 ++- .../parser_sql/processors/SelectProcessor.php | 4 +- tools/parser_sql/processors/SetProcessor.php | 35 +- tools/parser_sql/processors/ShowProcessor.php | 26 +- .../SubpartitionDefinitionProcessor.php | 273 ++++++++++++ .../parser_sql/processors/TableProcessor.php | 153 ++++--- .../parser_sql/processors/UnionProcessor.php | 134 ++++-- .../parser_sql/processors/UpdateProcessor.php | 59 +-- .../parser_sql/processors/UsingProcessor.php | 59 +-- .../parser_sql/processors/ValuesProcessor.php | 156 +++++-- .../parser_sql/processors/WhereProcessor.php | 59 +-- tools/parser_sql/processors/WithProcessor.php | 119 ++++++ tools/parser_sql/utils/ExpressionToken.php | 40 +- tools/parser_sql/utils/ExpressionType.php | 143 ++++--- .../utils/PHPSQLParserConstants.php | 315 +++++++------- tools/parser_sql/utils/PHPSQLParserUtils.php | 150 ------- 172 files changed, 8743 insertions(+), 2571 deletions(-) create mode 100644 tools/parser_sql/Options.php create mode 100644 tools/parser_sql/builders/AliasReferenceBuilder.php create mode 100644 tools/parser_sql/builders/AlterBuilder.php create mode 100644 tools/parser_sql/builders/AlterStatementBuilder.php create mode 100644 tools/parser_sql/builders/BracketStatementBuilder.php create mode 100644 tools/parser_sql/builders/Builder.php create mode 100644 tools/parser_sql/builders/CreateIndexBuilder.php create mode 100644 tools/parser_sql/builders/CreateIndexOptionsBuilder.php create mode 100644 tools/parser_sql/builders/CreateIndexTableBuilder.php create mode 100644 tools/parser_sql/builders/CreateIndexTypeBuilder.php create mode 100644 tools/parser_sql/builders/DefaultValueBuilder.php create mode 100644 tools/parser_sql/builders/DropBuilder.php create mode 100644 tools/parser_sql/builders/DropExpressionBuilder.php create mode 100644 tools/parser_sql/builders/DropIndexBuilder.php create mode 100644 tools/parser_sql/builders/DropIndexTableBuilder.php create mode 100644 tools/parser_sql/builders/DropStatementBuilder.php create mode 100644 tools/parser_sql/builders/GroupByAliasBuilder.php create mode 100644 tools/parser_sql/builders/GroupByExpressionBuilder.php create mode 100644 tools/parser_sql/builders/HavingBracketExpressionBuilder.php create mode 100644 tools/parser_sql/builders/HavingBuilder.php create mode 100644 tools/parser_sql/builders/HavingExpressionBuilder.php create mode 100644 tools/parser_sql/builders/IndexAlgorithmBuilder.php create mode 100644 tools/parser_sql/builders/IndexCommentBuilder.php create mode 100644 tools/parser_sql/builders/IndexHintListBuilder.php create mode 100644 tools/parser_sql/builders/IndexKeyBuilder.php create mode 100644 tools/parser_sql/builders/IndexLockBuilder.php create mode 100644 tools/parser_sql/builders/InsertColumnListBuilder.php create mode 100644 tools/parser_sql/builders/OrderByBracketExpressionBuilder.php create mode 100644 tools/parser_sql/builders/OrderByColumnReferenceBuilder.php create mode 100644 tools/parser_sql/builders/OrderByExpressionBuilder.php create mode 100644 tools/parser_sql/builders/OrderByFunctionBuilder.php create mode 100644 tools/parser_sql/builders/OrderByReservedBuilder.php create mode 100644 tools/parser_sql/builders/QueryBuilder.php create mode 100644 tools/parser_sql/builders/RenameStatementBuilder.php create mode 100644 tools/parser_sql/builders/ReplaceBuilder.php create mode 100644 tools/parser_sql/builders/ReplaceColumnListBuilder.php create mode 100644 tools/parser_sql/builders/ReplaceStatementBuilder.php create mode 100644 tools/parser_sql/builders/SchemaBuilder.php create mode 100644 tools/parser_sql/builders/SignBuilder.php create mode 100644 tools/parser_sql/builders/TempTableBuilder.php create mode 100644 tools/parser_sql/builders/TruncateBuilder.php create mode 100644 tools/parser_sql/builders/TruncateStatementBuilder.php create mode 100644 tools/parser_sql/builders/UnionAllStatementBuilder.php create mode 100644 tools/parser_sql/builders/UnionStatementBuilder.php create mode 100644 tools/parser_sql/builders/ViewBuilder.php create mode 100644 tools/parser_sql/processors/BracketProcessor.php create mode 100644 tools/parser_sql/processors/IndexProcessor.php create mode 100644 tools/parser_sql/processors/OptionsProcessor.php create mode 100644 tools/parser_sql/processors/PartitionDefinitionProcessor.php create mode 100644 tools/parser_sql/processors/PartitionOptionsProcessor.php create mode 100644 tools/parser_sql/processors/SubpartitionDefinitionProcessor.php create mode 100644 tools/parser_sql/processors/WithProcessor.php delete mode 100644 tools/parser_sql/utils/PHPSQLParserUtils.php diff --git a/tools/parser_sql/LICENSE b/tools/parser_sql/LICENSE index 2229911c3..fede684d5 100644 --- a/tools/parser_sql/LICENSE +++ b/tools/parser_sql/LICENSE @@ -1,49 +1,27 @@ -Copyright (c) 2010-2014 André Rothe +Copyright (c) 2014, Justin Swanhart and André Rothe All rights reserved. Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products -derived from this software without specific prior written permission. +modification, are permitted provided that the following conditions are met: -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. -Copyright (c) 2010-2014 Justin Swanhart and André Rothe -All rights reserved. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products -derived from this software without specific prior written permission. +* Neither the name of the {organization} nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/tools/parser_sql/Options.php b/tools/parser_sql/Options.php new file mode 100644 index 000000000..460745220 --- /dev/null +++ b/tools/parser_sql/Options.php @@ -0,0 +1,57 @@ +options = $options; + } + + /** + * @return bool + */ + public function getConsistentSubtrees() + { + return (isset($this->options[self::CONSISTENT_SUB_TREES]) && $this->options[self::CONSISTENT_SUB_TREES]); + } + + /** + * @return bool + */ + public function getANSIQuotes() + { + return (isset($this->options[self::ANSI_QUOTES]) && $this->options[self::ANSI_QUOTES]); + } +} diff --git a/tools/parser_sql/PHPSQLCreator.php b/tools/parser_sql/PHPSQLCreator.php index 7507da140..409ab00db 100644 --- a/tools/parser_sql/PHPSQLCreator.php +++ b/tools/parser_sql/PHPSQLCreator.php @@ -35,17 +35,26 @@ * @author André Rothe * @copyright 2010-2014 André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: PHPSQLCreator.php 790 2013-12-17 12:16:48Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/exceptions/UnsupportedFeatureException.php'; -require_once dirname(__FILE__) . '/builders/SelectStatementBuilder.php'; -require_once dirname(__FILE__) . '/builders/DeleteStatementBuilder.php'; -require_once dirname(__FILE__) . '/builders/UpdateStatementBuilder.php'; -require_once dirname(__FILE__) . '/builders/InsertStatementBuilder.php'; -require_once dirname(__FILE__) . '/builders/CreateStatementBuilder.php'; -require_once dirname(__FILE__) . '/builders/ShowStatementBuilder.php'; +namespace PHPSQLParser; +use PHPSQLParser\exceptions\UnsupportedFeatureException; +use PHPSQLParser\builders\SelectStatementBuilder; +use PHPSQLParser\builders\DeleteStatementBuilder; +use PHPSQLParser\builders\TruncateStatementBuilder; +use PHPSQLParser\builders\UpdateStatementBuilder; +use PHPSQLParser\builders\InsertStatementBuilder; +use PHPSQLParser\builders\CreateStatementBuilder; +use PHPSQLParser\builders\DropStatementBuilder; +use PHPSQLParser\builders\RenameStatementBuilder; +use PHPSQLParser\builders\ReplaceStatementBuilder; +use PHPSQLParser\builders\ShowStatementBuilder; +use PHPSQLParser\builders\BracketStatementBuilder; +use PHPSQLParser\builders\UnionStatementBuilder; +use PHPSQLParser\builders\UnionAllStatementBuilder; +use PHPSQLParser\builders\AlterStatementBuilder; /** * This class generates SQL from the output of the PHPSQLParser. @@ -66,35 +75,60 @@ class PHPSQLCreator { $k = key($parsed); switch ($k) { - case "UNION": - case "UNION ALL": - throw new UnsupportedFeatureException($k); - break; - case "SELECT": - $builder = new SelectStatementBuilder($parsed); + case 'UNION': + $builder = new UnionStatementBuilder(); + $this->created = $builder->build($parsed); + break; + case 'UNION ALL': + $builder = new UnionAllStatementBuilder(); $this->created = $builder->build($parsed); break; - case "INSERT": - $builder = new InsertStatementBuilder($parsed); + case 'SELECT': + $builder = new SelectStatementBuilder(); $this->created = $builder->build($parsed); break; - case "DELETE": - $builder = new DeleteStatementBuilder($parsed); + case 'INSERT': + $builder = new InsertStatementBuilder(); $this->created = $builder->build($parsed); break; - case "UPDATE": - $builder = new UpdateStatementBuilder($parsed); + case 'REPLACE': + $builder = new ReplaceStatementBuilder(); $this->created = $builder->build($parsed); break; - case "RENAME": - $this->created = $this->processRenameTableStatement($parsed); - break; - case "SHOW": - $builder = new ShowStatementBuilder($parsed); + case 'DELETE': + $builder = new DeleteStatementBuilder(); $this->created = $builder->build($parsed); break; - case "CREATE": - $builder = new CreateStatementBuilder($parsed); + case 'TRUNCATE': + $builder = new TruncateStatementBuilder(); + $this->created = $builder->build($parsed); + break; + case 'UPDATE': + $builder = new UpdateStatementBuilder(); + $this->created = $builder->build($parsed); + break; + case 'RENAME': + $builder = new RenameStatementBuilder(); + $this->created = $builder->build($parsed); + break; + case 'SHOW': + $builder = new ShowStatementBuilder(); + $this->created = $builder->build($parsed); + break; + case 'CREATE': + $builder = new CreateStatementBuilder(); + $this->created = $builder->build($parsed); + break; + case 'BRACKET': + $builder = new BracketStatementBuilder(); + $this->created = $builder->build($parsed); + break; + case 'DROP': + $builder = new DropStatementBuilder(); + $this->created = $builder->build($parsed); + break; + case 'ALTER': + $builder = new AlterStatementBuilder(); $this->created = $builder->build($parsed); break; default: @@ -103,31 +137,6 @@ class PHPSQLCreator { } return $this->created; } - - // TODO: we should change that, there are multiple "rename objects" as - // table, user, database - protected function processRenameTableStatement($parsed) { - $rename = $parsed['RENAME']; - $sql = ""; - foreach ($rename as $k => $v) { - $len = strlen($sql); - $sql .= $this->processSourceAndDestTable($v); - - if ($len == strlen($sql)) { - throw new UnableToCreateSQLException('RENAME', $k, $v, 'expr_type'); - } - - $sql .= ","; - } - $sql = substr($sql, 0, -1); - return "RENAME TABLE " . $sql; - } - - protected function processSourceAndDestTable($v) { - if (!isset($v['source']) || !isset($v['destination'])) { - return ""; - } - return $v['source']['base_expr'] . " TO " . $v['destination']['base_expr']; - } } + ?> diff --git a/tools/parser_sql/PHPSQLParser.php b/tools/parser_sql/PHPSQLParser.php index d402bb43a..03b5d833b 100644 --- a/tools/parser_sql/PHPSQLParser.php +++ b/tools/parser_sql/PHPSQLParser.php @@ -1,7 +1,7 @@ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: PHPSQLParser.php 757 2013-12-16 09:54:05Z phosco@gmx.de $ + * @version SVN: $Id$ */ -require_once dirname(__FILE__) . '/positions/PositionCalculator.php'; -require_once dirname(__FILE__) . '/processors/DefaultProcessor.php'; +namespace PHPSQLParser; +use PHPSQLParser\positions\PositionCalculator; +use PHPSQLParser\processors\DefaultProcessor; +use PHPSQLParser\utils\PHPSQLParserConstants; /** * This class implements the parser functionality. @@ -54,34 +56,42 @@ class PHPSQLParser { public $parsed; /** - * Constructor. It simply calls the parse() function. - * Use the public variable $parsed to get the output. - * - * @param String $sql The SQL statement. - * @param boolean $calcPositions True, if the output should contain [position], false otherwise. + * @var Options */ - public function __construct($sql = false, $calcPositions = false) { + private $options; + + /** + * Constructor. It simply calls the parse() function. + * Use the public variable $parsed to get the output. + * + * @param String|bool $sql The SQL statement. + * @param bool $calcPositions True, if the output should contain [position], false otherwise. + * @param array $options + */ + public function __construct($sql = false, $calcPositions = false, array $options = array()) { + $this->options = new Options($options); + if ($sql) { $this->parse($sql, $calcPositions); } } /** - * It parses the given SQL statement and generates a detailled - * output array for every part of the statement. The method can - * also generate [position] fields within the output, which hold - * the character position for every statement part. The calculation + * It parses the given SQL statement and generates a detailled + * output array for every part of the statement. The method can + * also generate [position] fields within the output, which hold + * the character position for every statement part. The calculation * of the positions needs some time, if you don't need positions in * your application, set the parameter to false. - * + * * @param String $sql The SQL statement. * @param boolean $calcPositions True, if the output should contain [position], false otherwise. - * + * * @return array An associative array with all meta information about the SQL statement. */ public function parse($sql, $calcPositions = false) { - $processor = new DefaultProcessor(); + $processor = new DefaultProcessor($this->options); $queries = $processor->process($sql); // calc the positions of some important tokens @@ -94,5 +104,36 @@ class PHPSQLParser { $this->parsed = $queries; return $this->parsed; } + + /** + * Add a custom function to the parser. no return value + * + * @param String $token The name of the function to add + * + * @return null + */ + public function addCustomFunction($token) { + PHPSQLParserConstants::getInstance()->addCustomFunction($token); + } + + /** + * Remove a custom function from the parser. no return value + * + * @param String $token The name of the function to remove + * + * @return null + */ + public function removeCustomFunction($token) { + PHPSQLParserConstants::getInstance()->removeCustomFunction($token); + } + + /** + * Returns the list of custom functions + * + * @return array Returns an array of all custom functions + */ + public function getCustomFunctions() { + return PHPSQLParserConstants::getInstance()->getCustomFunctions(); + } } ?> diff --git a/tools/parser_sql/builders/AliasBuilder.php b/tools/parser_sql/builders/AliasBuilder.php index 9eb6db7d6..ab0068f8f 100644 --- a/tools/parser_sql/builders/AliasBuilder.php +++ b/tools/parser_sql/builders/AliasBuilder.php @@ -35,10 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: AliasBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ +namespace PHPSQLParser\builders; + /** * This class implements the builder for aliases. * You can overwrite all functions to achieve another handling. @@ -47,19 +49,19 @@ * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class AliasBuilder { +class AliasBuilder implements Builder { public function hasAlias($parsed) { return isset($parsed['alias']); } - public function build($parsed) { + public function build(array $parsed) { if (!isset($parsed['alias']) || $parsed['alias'] === false) { return ""; } $sql = ""; if ($parsed['alias']['as']) { - $sql .= " as"; + $sql .= " AS"; } $sql .= " " . $parsed['alias']['name']; return $sql; diff --git a/tools/parser_sql/builders/AliasReferenceBuilder.php b/tools/parser_sql/builders/AliasReferenceBuilder.php new file mode 100644 index 000000000..9d85c5c8c --- /dev/null +++ b/tools/parser_sql/builders/AliasReferenceBuilder.php @@ -0,0 +1,63 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for alias references. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class AliasReferenceBuilder implements Builder { + + public function build(array $parsed) { + if ($parsed['expr_type'] !== ExpressionType::ALIAS) { + return ""; + } + $sql = $parsed['base_expr']; + return $sql; + } +} +?> diff --git a/tools/parser_sql/builders/AlterBuilder.php b/tools/parser_sql/builders/AlterBuilder.php new file mode 100644 index 000000000..b3df74f58 --- /dev/null +++ b/tools/parser_sql/builders/AlterBuilder.php @@ -0,0 +1,35 @@ + + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class AlterBuilder implements Builder +{ + public function build(array $parsed) + { + $sql = ''; + + foreach ($parsed as $term) { + if ($term === ' ') { + continue; + } + + if (substr($term, 0, 1) === '(' || + strpos($term, "\n") !== false) { + $sql = rtrim($sql); + } + + $sql .= $term . ' '; + } + + $sql = rtrim($sql); + + return $sql; + } +} diff --git a/tools/parser_sql/builders/AlterStatementBuilder.php b/tools/parser_sql/builders/AlterStatementBuilder.php new file mode 100644 index 000000000..823cc801a --- /dev/null +++ b/tools/parser_sql/builders/AlterStatementBuilder.php @@ -0,0 +1,24 @@ +build($parsed); + } + + private function buildAlter($parsed) + { + $builder = new AlterBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) + { + $alter = $parsed['ALTER']; + $sql = $this->buildAlter($alter); + + return $sql; + } +} diff --git a/tools/parser_sql/builders/BracketStatementBuilder.php b/tools/parser_sql/builders/BracketStatementBuilder.php new file mode 100644 index 000000000..2f308d587 --- /dev/null +++ b/tools/parser_sql/builders/BracketStatementBuilder.php @@ -0,0 +1,78 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; + +/** + * This class implements the builder for the parentheses around a statement. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class BracketStatementBuilder implements Builder { + + protected function buildSelectBracketExpression($parsed) { + $builder = new SelectBracketExpressionBuilder(); + return $builder->build($parsed, " "); + } + + protected function buildSelectStatement($parsed) { + $builder = new SelectStatementBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + $sql = ""; + foreach ($parsed['BRACKET'] as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildSelectBracketExpression($v); + + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('BRACKET', $k, $v, 'expr_type'); + } + } + return trim($sql . " " . trim($this->buildSelectStatement($parsed))); + } +} +?> diff --git a/tools/parser_sql/builders/Builder.php b/tools/parser_sql/builders/Builder.php new file mode 100644 index 000000000..c3cc91d7e --- /dev/null +++ b/tools/parser_sql/builders/Builder.php @@ -0,0 +1,63 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; + +/** + * A builder can create a part of an SQL statement. The necessary information + * are provided by the function parameter as array. This array is a subtree + * of the PHPSQLParser output. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + */ +interface Builder { + /** + * Builds a part of an SQL statement. + * + * @param array $parsed a subtree of the PHPSQLParser output array + * + * @return A string, which contains a part of an SQL statement. + */ + public function build(array $parsed); +} + +?> diff --git a/tools/parser_sql/builders/CharacterSetBuilder.php b/tools/parser_sql/builders/CharacterSetBuilder.php index a2dcc2f46..8873aacc8 100644 --- a/tools/parser_sql/builders/CharacterSetBuilder.php +++ b/tools/parser_sql/builders/CharacterSetBuilder.php @@ -35,16 +35,13 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: CharacterSetBuilder.php 914 2014-01-08 11:33:25Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ColumnListBuilder.php'; -require_once dirname(__FILE__) . '/ConstraintBuilder.php'; -require_once dirname(__FILE__) . '/ReservedBuilder.php'; -require_once dirname(__FILE__) . '/IndexTypeBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for the CHARACTER SET statement part of CREATE TABLE. @@ -54,7 +51,7 @@ require_once dirname(__FILE__) . '/IndexTypeBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class CharacterSetBuilder { +class CharacterSetBuilder implements Builder { protected function buildConstant($parsed) { $builder = new ConstantBuilder(); @@ -71,7 +68,7 @@ class CharacterSetBuilder { return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::CHARSET) { return ""; } diff --git a/tools/parser_sql/builders/CheckBuilder.php b/tools/parser_sql/builders/CheckBuilder.php index 616a1e102..60d3c1323 100644 --- a/tools/parser_sql/builders/CheckBuilder.php +++ b/tools/parser_sql/builders/CheckBuilder.php @@ -35,14 +35,14 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: CheckBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ReservedBuilder.php'; -require_once dirname(__FILE__) . '/SelectBracketExpressionBuilder.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + /** * This class implements the builder for the CHECK statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. @@ -51,7 +51,7 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class CheckBuilder { +class CheckBuilder implements Builder { protected function buildSelectBracketExpression($parsed) { $builder = new SelectBracketExpressionBuilder(); @@ -63,7 +63,7 @@ class CheckBuilder { return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::CHECK) { return ""; } diff --git a/tools/parser_sql/builders/CollationBuilder.php b/tools/parser_sql/builders/CollationBuilder.php index 5705da298..ca58c77f7 100644 --- a/tools/parser_sql/builders/CollationBuilder.php +++ b/tools/parser_sql/builders/CollationBuilder.php @@ -35,15 +35,13 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: CollationBuilder.php 922 2014-01-08 12:19:35Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ConstantBuilder.php'; -require_once dirname(__FILE__) . '/OperatorBuilder.php'; -require_once dirname(__FILE__) . '/ReservedBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for the collation statement part of CREATE TABLE. @@ -53,7 +51,7 @@ require_once dirname(__FILE__) . '/ReservedBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class CollationBuilder { +class CollationBuilder implements Builder { protected function buildOperator($parsed) { $builder = new OperatorBuilder(); @@ -70,7 +68,7 @@ class CollationBuilder { return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::COLLATE) { return ""; } diff --git a/tools/parser_sql/builders/ColumnDefinitionBuilder.php b/tools/parser_sql/builders/ColumnDefinitionBuilder.php index 7553b1951..99a559f38 100644 --- a/tools/parser_sql/builders/ColumnDefinitionBuilder.php +++ b/tools/parser_sql/builders/ColumnDefinitionBuilder.php @@ -35,14 +35,14 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: ColumnDefinitionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; -require_once dirname(__FILE__) . '/ColumnTypeBuilder.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + /** * This class implements the builder for the columndefinition statement part * of CREATE TABLE. You can overwrite all functions to achieve another handling. @@ -51,7 +51,7 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class ColumnDefinitionBuilder { +class ColumnDefinitionBuilder implements Builder { protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); @@ -63,7 +63,7 @@ class ColumnDefinitionBuilder { return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::COLDEF) { return ""; } diff --git a/tools/parser_sql/builders/ColumnListBuilder.php b/tools/parser_sql/builders/ColumnListBuilder.php index b9cb0b20c..0ed8516ac 100644 --- a/tools/parser_sql/builders/ColumnListBuilder.php +++ b/tools/parser_sql/builders/ColumnListBuilder.php @@ -35,13 +35,14 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: ColumnListBuilder.php 894 2013-12-31 00:27:03Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/IndexColumnBuilder.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + /** * This class implements the builder for column-list parts of CREATE TABLE. * You can overwrite all functions to achieve another handling. @@ -50,29 +51,35 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class ColumnListBuilder { +class ColumnListBuilder implements Builder { protected function buildIndexColumn($parsed) { $builder = new IndexColumnBuilder(); return $builder->build($parsed); } - public function build($parsed) { + protected function buildColumnReference($parsed) { + $builder = new ColumnReferenceBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed, $delim = ', ') { if ($parsed['expr_type'] !== ExpressionType::COLUMN_LIST) { - return ""; + return ''; } - $sql = ""; + $sql = ''; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildIndexColumn($v); + $sql .= $this->buildColumnReference($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE column-list subtree', $k, $v, 'expr_type'); } - $sql .= " "; - } - return "(" . substr($sql, 0, -1) . ")"; + $sql .= $delim; + } + return '(' . substr($sql, 0, -strlen($delim)) . ')'; } } diff --git a/tools/parser_sql/builders/ColumnReferenceBuilder.php b/tools/parser_sql/builders/ColumnReferenceBuilder.php index aa3d7c310..ef04757cc 100644 --- a/tools/parser_sql/builders/ColumnReferenceBuilder.php +++ b/tools/parser_sql/builders/ColumnReferenceBuilder.php @@ -35,13 +35,13 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: ColumnReferenceBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/AliasBuilder.php'; -require_once dirname(__FILE__) . '/DirectionBuilder.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; + /** * This class implements the builder for column references. * You can overwrite all functions to achieve another handling. @@ -50,25 +50,19 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class ColumnReferenceBuilder { - - protected function buildDirection($parsed) { - $builder = new DirectionBuilder(); - return $builder->build($parsed); - } +class ColumnReferenceBuilder implements Builder { protected function buildAlias($parsed) { $builder = new AliasBuilder(); return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::COLREF) { return ""; } $sql = $parsed['base_expr']; $sql .= $this->buildAlias($parsed); - $sql .= $this->buildDirection($parsed); return $sql; } } diff --git a/tools/parser_sql/builders/ColumnTypeBracketExpressionBuilder.php b/tools/parser_sql/builders/ColumnTypeBracketExpressionBuilder.php index b2a81e196..8b29bfd56 100644 --- a/tools/parser_sql/builders/ColumnTypeBracketExpressionBuilder.php +++ b/tools/parser_sql/builders/ColumnTypeBracketExpressionBuilder.php @@ -35,12 +35,13 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: ColumnTypeBracketExpressionBuilder.php 934 2014-01-08 13:57:16Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/SubTreeBuilder.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; + /** * This class implements the builder for bracket expressions within a column type. * You can overwrite all functions to achieve another handling. @@ -49,14 +50,14 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class ColumnTypeBracketExpressionBuilder { +class ColumnTypeBracketExpressionBuilder implements Builder { protected function buildSubTree($parsed, $delim) { $builder = new SubTreeBuilder(); return $builder->build($parsed, $delim); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::BRACKET_EXPRESSION) { return ""; } diff --git a/tools/parser_sql/builders/ColumnTypeBuilder.php b/tools/parser_sql/builders/ColumnTypeBuilder.php index 5f31548ff..1550b2e47 100644 --- a/tools/parser_sql/builders/ColumnTypeBuilder.php +++ b/tools/parser_sql/builders/ColumnTypeBuilder.php @@ -35,15 +35,14 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: ColumnTypeBuilder.php 935 2014-01-08 13:58:11Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ReservedBuilder.php'; -require_once dirname(__FILE__) . '/ColumnTypeBracketExpressionBuilder.php'; -require_once dirname(__FILE__) . '/DataTypeBuilder.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + /** * This class implements the builder for the column type statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. @@ -52,7 +51,7 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class ColumnTypeBuilder { +class ColumnTypeBuilder implements Builder { protected function buildColumnTypeBracketExpression($parsed) { $builder = new ColumnTypeBracketExpressionBuilder(); @@ -69,7 +68,19 @@ class ColumnTypeBuilder { return $builder->build($parsed); } - public function build($parsed) { + protected function buildDefaultValue($parsed) { + $builder = new DefaultValueBuilder(); + return $builder->build($parsed); + } + + protected function buildCharacterSet($parsed) { + if ($parsed['expr_type'] !== ExpressionType::CHARSET) { + return ""; + } + return $parsed['base_expr']; + } + + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::COLUMN_TYPE) { return ""; } @@ -79,7 +90,9 @@ class ColumnTypeBuilder { $sql .= $this->buildDataType($v); $sql .= $this->buildColumnTypeBracketExpression($v); $sql .= $this->buildReserved($v); - + $sql .= $this->buildDefaultValue($v); + $sql .= $this->buildCharacterSet($v); + if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE column-type subtree', $k, $v, 'expr_type'); } diff --git a/tools/parser_sql/builders/ConstantBuilder.php b/tools/parser_sql/builders/ConstantBuilder.php index 840a8cb40..19dc6ae99 100644 --- a/tools/parser_sql/builders/ConstantBuilder.php +++ b/tools/parser_sql/builders/ConstantBuilder.php @@ -35,12 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: ConstantBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/AliasBuilder.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for constants. @@ -50,14 +50,14 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class ConstantBuilder { +class ConstantBuilder implements Builder { protected function buildAlias($parsed) { $builder = new AliasBuilder(); return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::CONSTANT) { return ""; } diff --git a/tools/parser_sql/builders/ConstraintBuilder.php b/tools/parser_sql/builders/ConstraintBuilder.php index b5537e1fc..955b93158 100644 --- a/tools/parser_sql/builders/ConstraintBuilder.php +++ b/tools/parser_sql/builders/ConstraintBuilder.php @@ -35,12 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: ConstraintBuilder.php 891 2013-12-31 00:20:19Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/ConstantBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for the constraint statement part of CREATE TABLE. @@ -50,18 +50,18 @@ require_once dirname(__FILE__) . '/ConstantBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class ConstraintBuilder { +class ConstraintBuilder implements Builder { protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::CONSTRAINT) { - return ""; + return ''; } - $sql = $this->buildConstant($parsed['sub_tree']); + $sql = $parsed['sub_tree'] === false ? '' : $this->buildConstant($parsed['sub_tree']); return "CONSTRAINT" . (empty($sql) ? '' : (' ' . $sql)); } diff --git a/tools/parser_sql/builders/CreateBuilder.php b/tools/parser_sql/builders/CreateBuilder.php index 4dd3dd35c..d5e45afbf 100644 --- a/tools/parser_sql/builders/CreateBuilder.php +++ b/tools/parser_sql/builders/CreateBuilder.php @@ -35,13 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: CreateBuilder.php 833 2013-12-18 10:13:59Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/CreateTableBuilder.php'; -require_once dirname(__FILE__) . '/SubTreeBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for the [CREATE] part. You can overwrite @@ -51,27 +50,36 @@ require_once dirname(__FILE__) . '/SubTreeBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class CreateBuilder { +class CreateBuilder implements Builder { protected function buildCreateTable($parsed) { $builder = new CreateTableBuilder(); return $builder->build($parsed); } + protected function buildCreateIndex($parsed) { + $builder = new CreateIndexBuilder(); + return $builder->build($parsed); + } + protected function buildSubTree($parsed) { $builder = new SubTreeBuilder(); return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { $create = $parsed['CREATE']; $sql = $this->buildSubTree($create); if (($create['expr_type'] === ExpressionType::TABLE) || ($create['expr_type'] === ExpressionType::TEMPORARY_TABLE)) { - $sql .= " " . $this->buildCreateTable($parsed['TABLE']); + $sql .= ' ' . $this->buildCreateTable($parsed['TABLE']); } - // TODO: add more expr_types here (like VIEW), if available + if ($create['expr_type'] === ExpressionType::INDEX) { + $sql .= ' ' . $this->buildCreateIndex($parsed['INDEX']); + } + + // TODO: add more expr_types here (like VIEW), if available in parser output return "CREATE " . $sql; } diff --git a/tools/parser_sql/builders/CreateIndexBuilder.php b/tools/parser_sql/builders/CreateIndexBuilder.php new file mode 100644 index 000000000..e443d6b59 --- /dev/null +++ b/tools/parser_sql/builders/CreateIndexBuilder.php @@ -0,0 +1,80 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; + +/** + * This class implements the builder for the CREATE INDEX statement. You can overwrite + * all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class CreateIndexBuilder implements Builder { + + protected function buildIndexType($parsed) { + $builder = new CreateIndexTypeBuilder(); + return $builder->build($parsed); + } + + protected function buildIndexTable($parsed) { + $builder = new CreateIndexTableBuilder(); + return $builder->build($parsed); + } + + protected function buildIndexOptions($parsed) { + $builder = new CreateIndexOptionsBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + $sql = $parsed['name']; + $sql .= ' ' . $this->buildIndexType($parsed); + $sql = trim($sql); + $sql .= ' ' . $this->buildIndexTable($parsed); + $sql = trim($sql); + $sql .= $this->buildIndexOptions($parsed); + return trim($sql); + } + +} +?> diff --git a/tools/parser_sql/builders/CreateIndexOptionsBuilder.php b/tools/parser_sql/builders/CreateIndexOptionsBuilder.php new file mode 100644 index 000000000..487bf2832 --- /dev/null +++ b/tools/parser_sql/builders/CreateIndexOptionsBuilder.php @@ -0,0 +1,109 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; + +/** + * This class implements the builder for the index options of a CREATE INDEX + * statement. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class CreateIndexOptionsBuilder implements Builder { + + protected function buildIndexParser($parsed) { + $builder = new IndexParserBuilder(); + return $builder->build($parsed); + } + + protected function buildIndexSize($parsed) { + $builder = new IndexSizeBuilder(); + return $builder->build($parsed); + } + + protected function buildIndexType($parsed) { + $builder = new IndexTypeBuilder(); + return $builder->build($parsed); + } + + protected function buildIndexComment($parsed) { + $builder = new IndexCommentBuilder(); + return $builder->build($parsed); + } + + protected function buildIndexAlgorithm($parsed) { + $builder = new IndexAlgorithmBuilder(); + return $builder->build($parsed); + } + + protected function buildIndexLock($parsed) { + $builder = new IndexLockBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + if ($parsed['options'] === false) { + return ''; + } + $sql = ''; + foreach ($parsed['options'] as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildIndexAlgorithm($v); + $sql .= $this->buildIndexLock($v); + $sql .= $this->buildIndexComment($v); + $sql .= $this->buildIndexParser($v); + $sql .= $this->buildIndexSize($v); + $sql .= $this->buildIndexType($v); + + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('CREATE INDEX options', $k, $v, 'expr_type'); + } + + $sql .= ' '; + } + return ' ' . substr($sql, 0, -1); + } +} +?> diff --git a/tools/parser_sql/builders/CreateIndexTableBuilder.php b/tools/parser_sql/builders/CreateIndexTableBuilder.php new file mode 100644 index 000000000..e3b9fcff4 --- /dev/null +++ b/tools/parser_sql/builders/CreateIndexTableBuilder.php @@ -0,0 +1,72 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for the table part of a CREATE INDEX statement. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class CreateIndexTableBuilder implements Builder { + + protected function buildColumnList($parsed) { + $builder = new ColumnListBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + if (!isset($parsed['on']) || $parsed['on'] === false) { + return ''; + } + $table = $parsed['on']; + if ($table['expr_type'] !== ExpressionType::TABLE) { + return ''; + } + return 'ON ' . $table['name'] . ' ' . $this->buildColumnList($table['sub_tree']); + } + +} +?> diff --git a/tools/parser_sql/builders/CreateIndexTypeBuilder.php b/tools/parser_sql/builders/CreateIndexTypeBuilder.php new file mode 100644 index 000000000..0b26e8e54 --- /dev/null +++ b/tools/parser_sql/builders/CreateIndexTypeBuilder.php @@ -0,0 +1,62 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; + +/** + * This class implements the builder for the index type of a CREATE INDEX + * statement. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class CreateIndexTypeBuilder extends IndexTypeBuilder { + + public function build(array $parsed) { + if (!isset($parsed['index-type']) || $parsed['index-type'] === false) { + return ''; + } + return parent::build($parsed['index-type']); + } +} +?> diff --git a/tools/parser_sql/builders/CreateStatementBuilder.php b/tools/parser_sql/builders/CreateStatementBuilder.php index bee99e067..d27a0d8bb 100644 --- a/tools/parser_sql/builders/CreateStatementBuilder.php +++ b/tools/parser_sql/builders/CreateStatementBuilder.php @@ -35,13 +35,11 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: CreateStatementBuilder.php 930 2014-01-08 13:07:55Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/LikeBuilder.php'; -require_once dirname(__FILE__) . '/SelectStatementBuilder.php'; -require_once dirname(__FILE__) . '/CreateBuilder.php'; +namespace PHPSQLParser\builders; /** * This class implements the builder for the whole Create statement. You can overwrite @@ -51,7 +49,7 @@ require_once dirname(__FILE__) . '/CreateBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class CreateStatementBuilder { +class CreateStatementBuilder implements Builder { protected function buildLIKE($parsed) { $builder = new LikeBuilder(); @@ -67,8 +65,8 @@ class CreateStatementBuilder { $builder = new CreateBuilder(); return $builder->build($parsed); } - - public function build($parsed) { + + public function build(array $parsed) { $sql = $this->buildCREATE($parsed); if (isset($parsed['LIKE'])) { $sql .= " " . $this->buildLIKE($parsed['LIKE']); diff --git a/tools/parser_sql/builders/CreateTableBuilder.php b/tools/parser_sql/builders/CreateTableBuilder.php index 1453262b6..7ffef9c4b 100644 --- a/tools/parser_sql/builders/CreateTableBuilder.php +++ b/tools/parser_sql/builders/CreateTableBuilder.php @@ -35,14 +35,11 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: CreateTableBuilder.php 892 2013-12-31 00:21:33Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/CreateTableDefinitionBuilder.php'; -require_once dirname(__FILE__) . '/CreateTableSelectOptionBuilder.php'; -require_once dirname(__FILE__) . '/CreateTableOptionsBuilder.php'; +namespace PHPSQLParser\builders; /** * This class implements the builder for the CREATE TABLE statement. You can overwrite @@ -52,7 +49,7 @@ require_once dirname(__FILE__) . '/CreateTableOptionsBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class CreateTableBuilder { +class CreateTableBuilder implements Builder { protected function buildCreateTableDefinition($parsed) { $builder = new CreateTableDefinitionBuilder(); @@ -63,19 +60,19 @@ class CreateTableBuilder { $builder = new CreateTableOptionsBuilder(); return $builder->build($parsed); } - + protected function buildCreateTableSelectOption($parsed) { $builder = new CreateTableSelectOptionBuilder(); return $builder->build($parsed); } - - public function build($parsed) { + + public function build(array $parsed) { $sql = $parsed['name']; $sql .= $this->buildCreateTableDefinition($parsed); $sql .= $this->buildCreateTableOptions($parsed); $sql .= $this->buildCreateTableSelectOption($parsed); return $sql; } - + } ?> diff --git a/tools/parser_sql/builders/CreateTableDefinitionBuilder.php b/tools/parser_sql/builders/CreateTableDefinitionBuilder.php index 3b7896f4f..e73150131 100644 --- a/tools/parser_sql/builders/CreateTableDefinitionBuilder.php +++ b/tools/parser_sql/builders/CreateTableDefinitionBuilder.php @@ -35,11 +35,11 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: CreateTableDefinitionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/TableBracketExpressionBuilder.php'; +namespace PHPSQLParser\builders; /** * This class implements the builder for the create definitions of CREATE TABLE. @@ -49,14 +49,14 @@ require_once dirname(__FILE__) . '/TableBracketExpressionBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class CreateTableDefinitionBuilder { +class CreateTableDefinitionBuilder implements Builder { protected function buildTableBracketExpression($parsed) { $builder = new TableBracketExpressionBuilder(); return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { if (!isset($parsed) || $parsed['create-def'] === false) { return ""; } diff --git a/tools/parser_sql/builders/CreateTableOptionsBuilder.php b/tools/parser_sql/builders/CreateTableOptionsBuilder.php index a23cb7333..1995460a2 100644 --- a/tools/parser_sql/builders/CreateTableOptionsBuilder.php +++ b/tools/parser_sql/builders/CreateTableOptionsBuilder.php @@ -35,14 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: CreateTableOptionsBuilder.php 923 2014-01-08 12:20:30Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/SelectExpressionBuilder.php'; -require_once dirname(__FILE__) . '/CharacterSetBuilder.php'; -require_once dirname(__FILE__) . '/CollationBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; /** * This class implements the builder for the table-options statement part of CREATE TABLE. @@ -52,23 +50,23 @@ require_once dirname(__FILE__) . '/CollationBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class CreateTableOptionsBuilder { +class CreateTableOptionsBuilder implements Builder { protected function buildExpression($parsed) { $builder = new SelectExpressionBuilder(); return $builder->build($parsed); } - + protected function buildCharacterSet($parsed) { $builder = new CharacterSetBuilder(); return $builder->build($parsed); } - + protected function buildCollation($parsed) { $builder = new CollationBuilder(); return $builder->build($parsed); } - + /** * Returns a well-formatted delimiter string. If you don't need nice SQL, * you could simply return $parsed['delim']. @@ -79,8 +77,8 @@ class CreateTableOptionsBuilder { protected function getDelimiter($parsed) { return ($parsed['delim'] === false ? '' : (trim($parsed['delim']) . ' ')); } - - public function build($parsed) { + + public function build(array $parsed) { if (!isset($parsed['options']) || $parsed['options'] === false) { return ""; } diff --git a/tools/parser_sql/builders/CreateTableSelectOptionBuilder.php b/tools/parser_sql/builders/CreateTableSelectOptionBuilder.php index 898917742..8aef6bf5b 100644 --- a/tools/parser_sql/builders/CreateTableSelectOptionBuilder.php +++ b/tools/parser_sql/builders/CreateTableSelectOptionBuilder.php @@ -35,10 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: CreateTableSelectOptionBuilder.php 932 2014-01-08 13:15:26Z phosco@gmx.de $ + * @version SVN: $Id$ * */ +namespace PHPSQLParser\builders; + /** * This class implements the builder for the select-options statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. @@ -47,9 +49,9 @@ * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class CreateTableSelectOptionBuilder { +class CreateTableSelectOptionBuilder implements Builder { - public function build($parsed) { + public function build(array $parsed) { if (!isset($parsed['select-option']) || $parsed['select-option'] === false) { return ""; } diff --git a/tools/parser_sql/builders/DataTypeBuilder.php b/tools/parser_sql/builders/DataTypeBuilder.php index cd4573285..248ff5a83 100644 --- a/tools/parser_sql/builders/DataTypeBuilder.php +++ b/tools/parser_sql/builders/DataTypeBuilder.php @@ -35,11 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: DataTypeBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for the data-type statement part of CREATE TABLE. @@ -49,9 +50,9 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class DataTypeBuilder { +class DataTypeBuilder implements Builder { - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::DATA_TYPE) { return ""; } diff --git a/tools/parser_sql/builders/DatabaseBuilder.php b/tools/parser_sql/builders/DatabaseBuilder.php index 5b33e3f5b..be3b32c0e 100644 --- a/tools/parser_sql/builders/DatabaseBuilder.php +++ b/tools/parser_sql/builders/DatabaseBuilder.php @@ -35,11 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: DatabaseBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for a database within SHOW statement. @@ -49,9 +50,9 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class DatabaseBuilder { +class DatabaseBuilder implements Builder { - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::DATABASE) { return ""; } diff --git a/tools/parser_sql/builders/DefaultValueBuilder.php b/tools/parser_sql/builders/DefaultValueBuilder.php new file mode 100644 index 000000000..af45a0417 --- /dev/null +++ b/tools/parser_sql/builders/DefaultValueBuilder.php @@ -0,0 +1,62 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for the default value statement part of CREATE TABLE. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class DefaultValueBuilder implements Builder { + + public function build(array $parsed) { + if ($parsed['expr_type'] !== ExpressionType::DEF_VALUE) { + return ""; + } + return $parsed['base_expr']; + } +} +?> diff --git a/tools/parser_sql/builders/DeleteBuilder.php b/tools/parser_sql/builders/DeleteBuilder.php index 369c02aa4..ff2d51d35 100644 --- a/tools/parser_sql/builders/DeleteBuilder.php +++ b/tools/parser_sql/builders/DeleteBuilder.php @@ -35,10 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: DeleteBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ +namespace PHPSQLParser\builders; + /** * This class implements the builder for the [DELETE] part. You can overwrite * all functions to achieve another handling. @@ -47,14 +49,26 @@ * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class DeleteBuilder { +class DeleteBuilder implements Builder { - public function build($parsed) { - $sql = "DELETE"; - foreach ($parsed['TABLES'] as $k => $v) { - $sql .= $v . ","; + public function build(array $parsed) { + $sql = "DELETE "; + $right = -1; + + if ($parsed['options'] !== false) { + foreach ($parsed['options'] as $k => $v) { + $sql .= $v . " "; + } } - return substr($sql, 0, -1); + + if ($parsed['tables'] !== false) { + foreach ($parsed['tables'] as $k => $v) { + $sql .= $v . ", "; + $right = -2; + } + } + + return substr($sql, 0, $right); } } ?> diff --git a/tools/parser_sql/builders/DeleteStatementBuilder.php b/tools/parser_sql/builders/DeleteStatementBuilder.php index 0aa88239a..26978c161 100644 --- a/tools/parser_sql/builders/DeleteStatementBuilder.php +++ b/tools/parser_sql/builders/DeleteStatementBuilder.php @@ -35,13 +35,11 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: DeleteStatementBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/WhereBuilder.php'; -require_once dirname(__FILE__) . '/FromBuilder.php'; -require_once dirname(__FILE__) . '/DeleteBuilder.php'; +namespace PHPSQLParser\builders; /** * This class implements the builder for the whole Delete statement. You can overwrite @@ -51,7 +49,7 @@ require_once dirname(__FILE__) . '/DeleteBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class DeleteStatementBuilder { +class DeleteStatementBuilder implements Builder { protected function buildWHERE($parsed) { $builder = new WhereBuilder(); @@ -67,14 +65,14 @@ class DeleteStatementBuilder { $builder = new DeleteBuilder(); return $builder->build($parsed); } - - public function processDeleteStatement($parsed) { - $sql = $this->buildDELETE($parsed['DELETE']) . " " . $this->processFROM($parsed['FROM']); + + public function build(array $parsed) { + $sql = $this->buildDELETE($parsed['DELETE']) . " " . $this->buildFROM($parsed['FROM']); if (isset($parsed['WHERE'])) { - $sql .= " " . $this->processWHERE($parsed['WHERE']); + $sql .= " " . $this->buildWHERE($parsed['WHERE']); } return $sql; } - + } ?> diff --git a/tools/parser_sql/builders/DirectionBuilder.php b/tools/parser_sql/builders/DirectionBuilder.php index d20f11474..3474f0336 100644 --- a/tools/parser_sql/builders/DirectionBuilder.php +++ b/tools/parser_sql/builders/DirectionBuilder.php @@ -35,10 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: DirectionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ +namespace PHPSQLParser\builders; + /** * This class implements the builder for directions (e.g. of the order-by clause). * You can overwrite all functions to achieve another handling. @@ -47,9 +49,9 @@ * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class DirectionBuilder { +class DirectionBuilder implements Builder { - public function build($parsed) { + public function build(array $parsed) { if (!isset($parsed['direction']) || $parsed['direction'] === false) { return ""; } diff --git a/tools/parser_sql/builders/DropBuilder.php b/tools/parser_sql/builders/DropBuilder.php new file mode 100644 index 000000000..e7465030a --- /dev/null +++ b/tools/parser_sql/builders/DropBuilder.php @@ -0,0 +1,100 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for the [DROP] part. You can overwrite + * all functions to achieve another handling. + */ +class DropBuilder implements Builder { + + protected function buildDropIndex( $parsed ) { + $builder = new DropIndexBuilder(); + + return $builder->build( $parsed ); + } + + protected function buildReserved( $parsed ) { + $builder = new ReservedBuilder(); + + return $builder->build( $parsed ); + } + + protected function buildExpression( $parsed ) { + $builder = new DropExpressionBuilder(); + + return $builder->build( $parsed ); + } + + protected function buildSubTree( $parsed ) { + $sql = ''; + foreach ( $parsed['sub_tree'] as $k => $v ) { + $len = strlen( $sql ); + $sql .= $this->buildReserved( $v ); + $sql .= $this->buildExpression( $v ); + + if ( $len == strlen( $sql ) ) { + throw new UnableToCreateSQLException( 'DROP subtree', $k, $v, 'expr_type' ); + } + + $sql .= ' '; + } + + return $sql; + } + + public function build( array $parsed ) { + $drop = $parsed['DROP']; + $sql = $this->buildSubTree( $drop ); + + if ( $drop['expr_type'] === ExpressionType::INDEX ) { + $sql .= '' . $this->buildDropIndex( $parsed['INDEX'] ) . ' '; + } + + return 'DROP ' . substr( $sql, 0, -1 ); + } + +} + +?> diff --git a/tools/parser_sql/builders/DropExpressionBuilder.php b/tools/parser_sql/builders/DropExpressionBuilder.php new file mode 100644 index 000000000..5bec36781 --- /dev/null +++ b/tools/parser_sql/builders/DropExpressionBuilder.php @@ -0,0 +1,103 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for the object list of a DROP statement. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class DropExpressionBuilder implements Builder { + + protected function buildTable($parsed, $index) { + $builder = new TableBuilder(); + return $builder->build($parsed, $index); + } + + protected function buildDatabase($parsed) { + $builder = new DatabaseBuilder(); + return $builder->build($parsed); + } + + protected function buildSchema($parsed) { + $builder = new SchemaBuilder(); + return $builder->build($parsed); + } + + protected function buildTemporaryTable($parsed) { + $builder = new TempTableBuilder(); + return $builder->build($parsed); + } + + protected function buildView($parsed) { + $builder = new ViewBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + if ($parsed['expr_type'] !== ExpressionType::EXPRESSION) { + return ""; + } + $sql = ''; + foreach ($parsed['sub_tree'] as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildTable($v, 0); + $sql .= $this->buildView($v); + $sql .= $this->buildSchema($v); + $sql .= $this->buildDatabase($v); + $sql .= $this->buildTemporaryTable($v, 0); + + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('DROP object-list subtree', $k, $v, 'expr_type'); + } + + $sql .= ', '; + } + return substr($sql, 0, -2); + } +} +?> diff --git a/tools/parser_sql/builders/DropIndexBuilder.php b/tools/parser_sql/builders/DropIndexBuilder.php new file mode 100644 index 000000000..c94b6f8cb --- /dev/null +++ b/tools/parser_sql/builders/DropIndexBuilder.php @@ -0,0 +1,63 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; + +/** + * This class implements the builder for the DROP INDEX statement. You can overwrite + * all functions to achieve another handling. + */ +class DropIndexBuilder implements Builder { + + protected function buildIndexTable($parsed) { + $builder = new DropIndexTableBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + $sql = $parsed['name']; + $sql = trim($sql); + $sql .= ' ' . $this->buildIndexTable($parsed); + return trim($sql); + } + +} +?> diff --git a/tools/parser_sql/builders/DropIndexTableBuilder.php b/tools/parser_sql/builders/DropIndexTableBuilder.php new file mode 100644 index 000000000..e46a84328 --- /dev/null +++ b/tools/parser_sql/builders/DropIndexTableBuilder.php @@ -0,0 +1,67 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for the table part of a DROP INDEX statement. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class DropIndexTableBuilder implements Builder { + + public function build(array $parsed) { + if (!isset($parsed['on']) || $parsed['on'] === false) { + return ''; + } + $table = $parsed['on']; + if ($table['expr_type'] !== ExpressionType::TABLE) { + return ''; + } + return 'ON ' . $table['name']; + } + +} +?> diff --git a/tools/parser_sql/builders/DropStatementBuilder.php b/tools/parser_sql/builders/DropStatementBuilder.php new file mode 100644 index 000000000..03af3ca70 --- /dev/null +++ b/tools/parser_sql/builders/DropStatementBuilder.php @@ -0,0 +1,63 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; + +/** + * This class implements the builder for the whole DROP TABLE statement. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class DropStatementBuilder implements Builder { + + protected function buildDROP( $parsed ) { + $builder = new DropBuilder(); + return $builder->build( $parsed ); + } + + public function build( array $parsed ) { + return $this->buildDROP( $parsed ); + } +} +?> diff --git a/tools/parser_sql/builders/EngineBuilder.php b/tools/parser_sql/builders/EngineBuilder.php index e10eac9d4..748b2e5a3 100644 --- a/tools/parser_sql/builders/EngineBuilder.php +++ b/tools/parser_sql/builders/EngineBuilder.php @@ -35,11 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: EngineBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for a database within SHOW statement. @@ -49,9 +50,9 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class EngineBuilder { +class EngineBuilder implements Builder { - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::ENGINE) { return ""; } diff --git a/tools/parser_sql/builders/ForeignKeyBuilder.php b/tools/parser_sql/builders/ForeignKeyBuilder.php index 2b634fc27..8d3082b9f 100644 --- a/tools/parser_sql/builders/ForeignKeyBuilder.php +++ b/tools/parser_sql/builders/ForeignKeyBuilder.php @@ -35,16 +35,13 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: ForeignKeyBuilder.php 927 2014-01-08 13:01:17Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ConstantBuilder.php'; -require_once dirname(__FILE__) . '/ReservedBuilder.php'; -require_once dirname(__FILE__) . '/ColumnListBuilder.php'; -require_once dirname(__FILE__) . '/ForeignRefBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for the FOREIGN KEY statement part of CREATE TABLE. @@ -54,7 +51,7 @@ require_once dirname(__FILE__) . '/ForeignRefBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class ForeignKeyBuilder { +class ForeignKeyBuilder implements Builder { protected function buildConstant($parsed) { $builder = new ConstantBuilder(); @@ -76,7 +73,7 @@ class ForeignKeyBuilder { return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::FOREIGN_KEY) { return ""; } diff --git a/tools/parser_sql/builders/ForeignRefBuilder.php b/tools/parser_sql/builders/ForeignRefBuilder.php index a7b47a2f2..9e3e6d485 100644 --- a/tools/parser_sql/builders/ForeignRefBuilder.php +++ b/tools/parser_sql/builders/ForeignRefBuilder.php @@ -35,15 +35,13 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: ForeignRefBuilder.php 927 2014-01-08 13:01:17Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/TableBuilder.php'; -require_once dirname(__FILE__) . '/ReservedBuilder.php'; -require_once dirname(__FILE__) . '/ColumnListBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for the FOREIGN KEY REFERENCES statement @@ -54,7 +52,7 @@ require_once dirname(__FILE__) . '/ColumnListBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class ForeignRefBuilder { +class ForeignRefBuilder implements Builder { protected function buildTable($parsed) { $builder = new TableBuilder(); @@ -71,7 +69,7 @@ class ForeignRefBuilder { return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::REFERENCE) { return ""; } diff --git a/tools/parser_sql/builders/FromBuilder.php b/tools/parser_sql/builders/FromBuilder.php index dcbdafc9b..1679ac975 100644 --- a/tools/parser_sql/builders/FromBuilder.php +++ b/tools/parser_sql/builders/FromBuilder.php @@ -31,18 +31,16 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: FromBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ - * + * @version SVN: $Id$ + * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/TableBuilder.php'; -require_once dirname(__FILE__) . '/TableExpressionBuilder.php'; -require_once dirname(__FILE__) . '/SubQueryBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; /** * This class implements the builder for the [FROM] part. You can overwrite @@ -50,9 +48,9 @@ require_once dirname(__FILE__) . '/SubQueryBuilder.php'; * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * + * */ -class FromBuilder { +class FromBuilder implements Builder { protected function buildTable($parsed, $key) { $builder = new TableBuilder(); @@ -69,16 +67,41 @@ class FromBuilder { return $builder->build($parsed, $key); } - public function build($parsed) { + public function build(array $parsed) { $sql = ""; - foreach ($parsed as $k => $v) { - $len = strlen($sql); - $sql .= $this->buildTable($v, $k); - $sql .= $this->buildTableExpression($v, $k); - $sql .= $this->buildSubquery($v, $k); + if (array_key_exists("UNION ALL", $parsed) || array_key_exists("UNION", $parsed)) { + foreach ($parsed as $union_type => $outer_v) { + $first = true; - if ($len == strlen($sql)) { - throw new UnableToCreateSQLException('FROM', $k, $v, 'expr_type'); + foreach ($outer_v as $item) { + if (!$first) { + $sql .= " $union_type "; + } + else { + $first = false; + } + + $select_builder = new SelectStatementBuilder(); + + $len = strlen($sql); + $sql .= $select_builder->build($item); + + if ($len === strlen($sql)) { + throw new UnableToCreateSQLException('FROM', $union_type, $outer_v, 'expr_type'); + } + } + } + } + else { + foreach ($parsed as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildTable($v, $k); + $sql .= $this->buildTableExpression($v, $k); + $sql .= $this->buildSubquery($v, $k); + + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('FROM', $k, $v, 'expr_type'); + } } } return "FROM " . $sql; diff --git a/tools/parser_sql/builders/FunctionBuilder.php b/tools/parser_sql/builders/FunctionBuilder.php index 5e2a768df..157204104 100644 --- a/tools/parser_sql/builders/FunctionBuilder.php +++ b/tools/parser_sql/builders/FunctionBuilder.php @@ -7,7 +7,7 @@ * PHP version 5 * * LICENSE: - * Copyright (c) 2010-2014 Justin Swanhart and André Rothe + * Copyright (c) 2010-2015 Justin Swanhart and André Rothe * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,22 +33,15 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @author André Rothe - * @copyright 2010-2014 Justin Swanhart and André Rothe + * @copyright 2010-2015 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: FunctionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/AliasBuilder.php'; -require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; -require_once dirname(__FILE__) . '/ConstantBuilder.php'; -require_once dirname(__FILE__) . '/FunctionBuilder.php'; -require_once dirname(__FILE__) . '/ReservedBuilder.php'; -require_once dirname(__FILE__) . '/SelectExpressionBuilder.php'; -require_once dirname(__FILE__) . '/SelectBracketExpressionBuilder.php'; -require_once dirname(__FILE__) . '/DirectionBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for function calls. @@ -58,13 +51,8 @@ require_once dirname(__FILE__) . '/DirectionBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class FunctionBuilder { +class FunctionBuilder implements Builder { - protected function buildDirection($parsed) { - $builder = new DirectionBuilder(); - return $builder->build($parsed); - } - protected function buildAlias($parsed) { $builder = new AliasBuilder(); return $builder->build($parsed); @@ -99,15 +87,21 @@ class FunctionBuilder { $builder = new SelectBracketExpressionBuilder(); return $builder->build($parsed); } - - public function build($parsed) { + + protected function buildSubQuery($parsed) { + $builder = new SubQueryBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { if (($parsed['expr_type'] !== ExpressionType::AGGREGATE_FUNCTION) - && ($parsed['expr_type'] !== ExpressionType::SIMPLE_FUNCTION)) { + && ($parsed['expr_type'] !== ExpressionType::SIMPLE_FUNCTION) + && ($parsed['expr_type'] !== ExpressionType::CUSTOM_FUNCTION)) { return ""; } if ($parsed['sub_tree'] === false) { - return $parsed['base_expr'] . "()"; + return $parsed['base_expr'] . "()" . $this->buildAlias($parsed); } $sql = ""; @@ -115,6 +109,7 @@ class FunctionBuilder { $len = strlen($sql); $sql .= $this->build($v); $sql .= $this->buildConstant($v); + $sql .= $this->buildSubQuery($v); $sql .= $this->buildColRef($v); $sql .= $this->buildReserved($v); $sql .= $this->buildSelectBracketExpression($v); @@ -126,7 +121,7 @@ class FunctionBuilder { $sql .= ($this->isReserved($v) ? " " : ","); } - return $parsed['base_expr'] . "(" . substr($sql, 0, -1) . ")" . $this->buildAlias($parsed) . $this->buildDirection($parsed); + return $parsed['base_expr'] . "(" . substr($sql, 0, -1) . ")" . $this->buildAlias($parsed); } } diff --git a/tools/parser_sql/builders/GroupByAliasBuilder.php b/tools/parser_sql/builders/GroupByAliasBuilder.php new file mode 100644 index 000000000..b9bc9784f --- /dev/null +++ b/tools/parser_sql/builders/GroupByAliasBuilder.php @@ -0,0 +1,62 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for an alias within the GROUP-BY clause. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class GroupByAliasBuilder implements Builder { + + public function build(array $parsed) { + if ($parsed['expr_type'] !== ExpressionType::ALIAS) { + return ""; + } + return $parsed['base_expr']; + } +} +?> diff --git a/tools/parser_sql/builders/GroupByBuilder.php b/tools/parser_sql/builders/GroupByBuilder.php index b63edaba8..d905118fd 100644 --- a/tools/parser_sql/builders/GroupByBuilder.php +++ b/tools/parser_sql/builders/GroupByBuilder.php @@ -35,14 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: GroupByBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/PositionBuilder.php'; -require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; -require_once dirname(__FILE__) . '/FunctionBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; /** * This class implements the builder for the GROUP-BY clause. @@ -52,7 +50,7 @@ require_once dirname(__FILE__) . '/FunctionBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class GroupByBuilder { +class GroupByBuilder implements Builder { protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); @@ -68,15 +66,27 @@ class GroupByBuilder { $builder = new FunctionBuilder(); return $builder->build($parsed); } - - public function build($parsed) { + + protected function buildGroupByAlias($parsed) { + $builder = new GroupByAliasBuilder(); + return $builder->build($parsed); + } + + protected function buildGroupByExpression($parsed) { + $builder = new GroupByExpressionBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { $sql = ""; foreach ($parsed as $k => $v) { $len = strlen($sql); $sql .= $this->buildColRef($v); $sql .= $this->buildPosition($v); $sql .= $this->buildFunction($v); - + $sql .= $this->buildGroupByExpression($v); + $sql .= $this->buildGroupByAlias($v); + if ($len == strlen($sql)) { throw new UnableToCreateSQLException('GROUP', $k, $v, 'expr_type'); } @@ -86,6 +96,6 @@ class GroupByBuilder { $sql = substr($sql, 0, -2); return "GROUP BY " . $sql; } - + } ?> diff --git a/tools/parser_sql/builders/GroupByExpressionBuilder.php b/tools/parser_sql/builders/GroupByExpressionBuilder.php new file mode 100644 index 000000000..8aef4e407 --- /dev/null +++ b/tools/parser_sql/builders/GroupByExpressionBuilder.php @@ -0,0 +1,89 @@ + + * @copyright 2010-2016 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * @example group by id desc + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for an alias within the GROUP-BY clause. + * You can overwrite all functions to achieve another handling. + * + * @author oohook + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class GroupByExpressionBuilder implements Builder { + + protected function buildColRef($parsed) { + $builder = new ColumnReferenceBuilder(); + return $builder->build($parsed); + } + + protected function buildReserved($parsed) { + $builder = new ReservedBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + if ($parsed['expr_type'] !== ExpressionType::EXPRESSION) { + return ""; + } + + $sql = ""; + foreach ($parsed['sub_tree'] as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildColRef($v); + $sql .= $this->buildReserved($v); + + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('GROUP expression subtree', $k, $v, 'expr_type'); + } + + $sql .= " "; + } + + $sql = substr($sql, 0, -1); + return $sql; + } +} +?> diff --git a/tools/parser_sql/builders/HavingBracketExpressionBuilder.php b/tools/parser_sql/builders/HavingBracketExpressionBuilder.php new file mode 100644 index 000000000..bee5c0df5 --- /dev/null +++ b/tools/parser_sql/builders/HavingBracketExpressionBuilder.php @@ -0,0 +1,90 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for bracket expressions within the HAVING part. + * You can overwrite all functions to achieve another handling. + * + * @author Ian Barker + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class HavingBracketExpressionBuilder extends WhereBracketExpressionBuilder { + + protected function buildHavingExpression($parsed) { + $builder = new HavingExpressionBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + if ($parsed['expr_type'] !== ExpressionType::BRACKET_EXPRESSION) { + return ""; + } + $sql = ""; + foreach ($parsed['sub_tree'] as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildColRef($v); + $sql .= $this->buildConstant($v); + $sql .= $this->buildOperator($v); + $sql .= $this->buildInList($v); + $sql .= $this->buildFunction($v); + $sql .= $this->buildHavingExpression($v); + $sql .= $this->build($v); + $sql .= $this->buildUserVariable($v); + + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('HAVING expression subtree', $k, $v, 'expr_type'); + } + + $sql .= " "; + } + + $sql = "(" . substr($sql, 0, -1) . ")"; + return $sql; + } + +} +?> diff --git a/tools/parser_sql/builders/HavingBuilder.php b/tools/parser_sql/builders/HavingBuilder.php new file mode 100644 index 000000000..04da357c9 --- /dev/null +++ b/tools/parser_sql/builders/HavingBuilder.php @@ -0,0 +1,97 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; + +/** + * This class implements the builder for the HAVING part. + * You can overwrite all functions to achieve another handling. + * + * @author Ian Barker + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class HavingBuilder extends WhereBuilder { + + protected function buildAliasReference($parsed) { + $builder = new AliasReferenceBuilder(); + return $builder->build($parsed); + } + + protected function buildHavingExpression($parsed) { + $builder = new HavingExpressionBuilder(); + return $builder->build($parsed); + } + + protected function buildHavingBracketExpression($parsed) { + $builder = new HavingBracketExpressionBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + $sql = "HAVING "; + foreach ($parsed as $k => $v) { + $len = strlen($sql); + + $sql .= $this->buildAliasReference($v); + $sql .= $this->buildOperator($v); + $sql .= $this->buildConstant($v); + $sql .= $this->buildColRef($v); + $sql .= $this->buildSubQuery($v); + $sql .= $this->buildInList($v); + $sql .= $this->buildFunction($v); + $sql .= $this->buildHavingExpression($v); + $sql .= $this->buildHavingBracketExpression($v); + $sql .= $this->buildUserVariable($v); + + if (strlen($sql) == $len) { + throw new UnableToCreateSQLException('HAVING', $k, $v, 'expr_type'); + } + + $sql .= " "; + } + return substr($sql, 0, -1); + } + +} +?> diff --git a/tools/parser_sql/builders/HavingExpressionBuilder.php b/tools/parser_sql/builders/HavingExpressionBuilder.php new file mode 100644 index 000000000..93dd76d4e --- /dev/null +++ b/tools/parser_sql/builders/HavingExpressionBuilder.php @@ -0,0 +1,94 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for expressions within the HAVING part. + * You can overwrite all functions to achieve another handling. + * + * @author Ian Barker + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class HavingExpressionBuilder extends WhereExpressionBuilder { + + protected function buildHavingExpression($parsed) { + return $this->build($parsed); + } + + protected function buildHavingBracketExpression($parsed) { + $builder = new HavingBracketExpressionBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + if ($parsed['expr_type'] !== ExpressionType::EXPRESSION) { + return ""; + } + $sql = ""; + foreach ($parsed['sub_tree'] as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildColRef($v); + $sql .= $this->buildConstant($v); + $sql .= $this->buildOperator($v); + $sql .= $this->buildInList($v); + $sql .= $this->buildFunction($v); + $sql .= $this->buildHavingExpression($v); + $sql .= $this->buildHavingBracketExpression($v); + $sql .= $this->buildUserVariable($v); + + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('HAVING expression subtree', $k, $v, 'expr_type'); + } + + $sql .= " "; + } + + $sql = substr($sql, 0, -1); + return $sql; + } + +} +?> diff --git a/tools/parser_sql/builders/InListBuilder.php b/tools/parser_sql/builders/InListBuilder.php index d8eb235b5..c516f6b91 100644 --- a/tools/parser_sql/builders/InListBuilder.php +++ b/tools/parser_sql/builders/InListBuilder.php @@ -35,12 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: InListBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/SubTreeBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder list of values for the IN statement. @@ -50,14 +50,14 @@ require_once dirname(__FILE__) . '/SubTreeBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class InListBuilder { +class InListBuilder implements Builder { protected function buildSubTree($parsed, $delim) { $builder = new SubTreeBuilder(); return $builder->build($parsed, $delim); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::IN_LIST) { return ""; } diff --git a/tools/parser_sql/builders/IndexAlgorithmBuilder.php b/tools/parser_sql/builders/IndexAlgorithmBuilder.php new file mode 100644 index 000000000..5d95deb9a --- /dev/null +++ b/tools/parser_sql/builders/IndexAlgorithmBuilder.php @@ -0,0 +1,91 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for the index algorithm of CREATE INDEX statement. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class IndexAlgorithmBuilder implements Builder { + + protected function buildReserved($parsed) { + $builder = new ReservedBuilder(); + return $builder->build($parsed); + } + + protected function buildConstant($parsed) { + $builder = new ConstantBuilder(); + return $builder->build($parsed); + } + + protected function buildOperator($parsed) { + $builder = new OperatorBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + if ($parsed['expr_type'] !== ExpressionType::INDEX_ALGORITHM) { + return ''; + } + $sql = ''; + foreach ($parsed['sub_tree'] as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildReserved($v); + $sql .= $this->buildConstant($v); + $sql .= $this->buildOperator($v); + + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('CREATE INDEX algorithm subtree', $k, $v, 'expr_type'); + } + + $sql .= ' '; + } + return substr($sql, 0, -1); + } +} +?> diff --git a/tools/parser_sql/builders/IndexColumnBuilder.php b/tools/parser_sql/builders/IndexColumnBuilder.php index 3a66a35c9..82a63abb1 100644 --- a/tools/parser_sql/builders/IndexColumnBuilder.php +++ b/tools/parser_sql/builders/IndexColumnBuilder.php @@ -35,12 +35,13 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: IndexColumnBuilder.php 917 2014-01-08 11:47:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnsupportedFeatureException.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; + /** * This class implements the builder for index column entries of the column-list * parts of CREATE TABLE. @@ -50,7 +51,7 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class IndexColumnBuilder { +class IndexColumnBuilder implements Builder { protected function buildLength($parsed) { return ($parsed === false ? '' : ('(' . $parsed . ')')); @@ -59,8 +60,8 @@ class IndexColumnBuilder { protected function buildDirection($parsed) { return ($parsed === false ? '' : (' ' . $parsed)); } - - public function build($parsed) { + + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::INDEX_COLUMN) { return ""; } diff --git a/tools/parser_sql/builders/IndexCommentBuilder.php b/tools/parser_sql/builders/IndexCommentBuilder.php new file mode 100644 index 000000000..33cc6ab52 --- /dev/null +++ b/tools/parser_sql/builders/IndexCommentBuilder.php @@ -0,0 +1,85 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for the index comment of CREATE INDEX statement. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class IndexCommentBuilder implements Builder { + + protected function buildReserved($parsed) { + $builder = new ReservedBuilder(); + return $builder->build($parsed); + } + + protected function buildConstant($parsed) { + $builder = new ConstantBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + if ($parsed['expr_type'] !== ExpressionType::COMMENT) { + return ''; + } + $sql = ''; + foreach ($parsed['sub_tree'] as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildReserved($v); + $sql .= $this->buildConstant($v); + + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('CREATE INDEX comment subtree', $k, $v, 'expr_type'); + } + + $sql .= ' '; + } + return substr($sql, 0, -1); + } +} +?> diff --git a/tools/parser_sql/builders/IndexHintListBuilder.php b/tools/parser_sql/builders/IndexHintListBuilder.php new file mode 100644 index 000000000..2f80b88eb --- /dev/null +++ b/tools/parser_sql/builders/IndexHintListBuilder.php @@ -0,0 +1,70 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; + +/** + * This class implements the builder for index hint lists. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class IndexHintListBuilder implements Builder { + + public function hasHint($parsed) { + return isset($parsed['hints']); + } + + // TODO: the hint list should be enhanced to get base_expr fro position calculation + public function build(array $parsed) { + if (!isset($parsed['hints']) || $parsed['hints'] === false) { + return ""; + } + $sql = ""; + foreach ($parsed['hints'] as $k => $v) { + $sql .= $v['hint_type'] . " " . $v['hint_list'] . " "; + } + return " " . substr($sql, 0, -1); + } +} +?> diff --git a/tools/parser_sql/builders/IndexKeyBuilder.php b/tools/parser_sql/builders/IndexKeyBuilder.php new file mode 100644 index 000000000..f195b615b --- /dev/null +++ b/tools/parser_sql/builders/IndexKeyBuilder.php @@ -0,0 +1,97 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for the index key part of a CREATE TABLE statement. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class IndexKeyBuilder implements Builder { + + protected function buildReserved($parsed) { + $builder = new ReservedBuilder(); + return $builder->build($parsed); + } + + protected function buildConstant($parsed) { + $builder = new ConstantBuilder(); + return $builder->build($parsed); + } + + protected function buildIndexType($parsed) { + $builder = new IndexTypeBuilder(); + return $builder->build($parsed); + } + + protected function buildColumnList($parsed) { + $builder = new ColumnListBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + if ($parsed['expr_type'] !== ExpressionType::INDEX) { + return ""; + } + $sql = ""; + foreach ($parsed['sub_tree'] as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildReserved($v); + $sql .= $this->buildColumnList($v); + $sql .= $this->buildConstant($v); + $sql .= $this->buildIndexType($v); + + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('CREATE TABLE index key subtree', $k, $v, 'expr_type'); + } + + $sql .= " "; + } + return substr($sql, 0, -1); + } +} +?> diff --git a/tools/parser_sql/builders/IndexLockBuilder.php b/tools/parser_sql/builders/IndexLockBuilder.php new file mode 100644 index 000000000..1b13d32d2 --- /dev/null +++ b/tools/parser_sql/builders/IndexLockBuilder.php @@ -0,0 +1,91 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for the index lock of CREATE INDEX statement. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class IndexLockBuilder implements Builder { + + protected function buildReserved($parsed) { + $builder = new ReservedBuilder(); + return $builder->build($parsed); + } + + protected function buildConstant($parsed) { + $builder = new ConstantBuilder(); + return $builder->build($parsed); + } + + protected function buildOperator($parsed) { + $builder = new OperatorBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + if ($parsed['expr_type'] !== ExpressionType::INDEX_LOCK) { + return ""; + } + $sql = ""; + foreach ($parsed['sub_tree'] as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildReserved($v); + $sql .= $this->buildConstant($v); + $sql .= $this->buildOperator($v); + + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('CREATE INDEX lock subtree', $k, $v, 'expr_type'); + } + + $sql .= ' '; + } + return substr($sql, 0, -1); + } +} +?> diff --git a/tools/parser_sql/builders/IndexParserBuilder.php b/tools/parser_sql/builders/IndexParserBuilder.php index ed609713f..00aa8a99d 100644 --- a/tools/parser_sql/builders/IndexParserBuilder.php +++ b/tools/parser_sql/builders/IndexParserBuilder.php @@ -35,16 +35,13 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: IndexParserBuilder.php 918 2014-01-08 11:48:30Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ColumnListBuilder.php'; -require_once dirname(__FILE__) . '/ConstraintBuilder.php'; -require_once dirname(__FILE__) . '/ReservedBuilder.php'; -require_once dirname(__FILE__) . '/IndexTypeBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for the index parser of a PRIMARY KEY @@ -55,7 +52,7 @@ require_once dirname(__FILE__) . '/IndexTypeBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class IndexParserBuilder { +class IndexParserBuilder implements Builder { protected function buildReserved($parsed) { $builder = new ReservedBuilder(); @@ -67,7 +64,7 @@ class IndexParserBuilder { return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::INDEX_PARSER) { return ""; } diff --git a/tools/parser_sql/builders/IndexSizeBuilder.php b/tools/parser_sql/builders/IndexSizeBuilder.php index c8321e7f0..272a49e15 100644 --- a/tools/parser_sql/builders/IndexSizeBuilder.php +++ b/tools/parser_sql/builders/IndexSizeBuilder.php @@ -35,16 +35,13 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: IndexSizeBuilder.php 918 2014-01-08 11:48:30Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ColumnListBuilder.php'; -require_once dirname(__FILE__) . '/ConstraintBuilder.php'; -require_once dirname(__FILE__) . '/ReservedBuilder.php'; -require_once dirname(__FILE__) . '/IndexTypeBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for the index size of a PRIMARY KEY @@ -55,7 +52,7 @@ require_once dirname(__FILE__) . '/IndexTypeBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class IndexSizeBuilder { +class IndexSizeBuilder implements Builder { protected function buildReserved($parsed) { $builder = new ReservedBuilder(); @@ -67,7 +64,7 @@ class IndexSizeBuilder { return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::INDEX_SIZE) { return ""; } diff --git a/tools/parser_sql/builders/IndexTypeBuilder.php b/tools/parser_sql/builders/IndexTypeBuilder.php index e58310294..6a197550f 100644 --- a/tools/parser_sql/builders/IndexTypeBuilder.php +++ b/tools/parser_sql/builders/IndexTypeBuilder.php @@ -35,16 +35,13 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: IndexTypeBuilder.php 910 2014-01-08 10:46:12Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ColumnListBuilder.php'; -require_once dirname(__FILE__) . '/ConstraintBuilder.php'; -require_once dirname(__FILE__) . '/ReservedBuilder.php'; -require_once dirname(__FILE__) . '/IndexTypeBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for the index type of a PRIMARY KEY @@ -55,14 +52,14 @@ require_once dirname(__FILE__) . '/IndexTypeBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class IndexTypeBuilder { +class IndexTypeBuilder implements Builder { protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::INDEX_TYPE) { return ""; } diff --git a/tools/parser_sql/builders/InsertBuilder.php b/tools/parser_sql/builders/InsertBuilder.php index c47384f15..929fb56ce 100644 --- a/tools/parser_sql/builders/InsertBuilder.php +++ b/tools/parser_sql/builders/InsertBuilder.php @@ -35,12 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: InsertBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; /** * This class implements the builder for the [INSERT] statement parts. @@ -50,39 +50,51 @@ require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class InsertBuilder { +class InsertBuilder implements Builder { - protected function buildColRef($parsed) { - $builder = new ColumnReferenceBuilder(); + protected function buildTable($parsed) { + $builder = new TableBuilder(); + return $builder->build($parsed, 0); + } + + protected function buildSubQuery($parsed) { + $builder = new SubQueryBuilder(); + return $builder->build($parsed, 0); + } + + protected function buildReserved($parsed) { + $builder = new ReservedBuilder(); return $builder->build($parsed); } - public function build($parsed) { - $sql = "INSERT INTO " . $parsed['table']; + protected function buildBracketExpression($parsed) { + $builder = new SelectBracketExpressionBuilder(); + return $builder->build($parsed); + } - if ($parsed['columns'] === false) { - return $sql; - } + protected function buildColumnList($parsed) { + $builder = new InsertColumnListBuilder(); + return $builder->build($parsed, 0); + } - $columns = ""; - foreach ($parsed['columns'] as $k => $v) { - $len = strlen($columns); - $columns .= $this->buildColRef($v); + public function build(array $parsed) { + $sql = ''; + foreach ($parsed as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildTable($v); + $sql .= $this->buildSubQuery($v); + $sql .= $this->buildColumnList($v); + $sql .= $this->buildReserved($v); + $sql .= $this->buildBracketExpression($v); - if ($len == strlen($columns)) { - throw new UnableToCreateSQLException('INSERT[columns]', $k, $v, 'expr_type'); + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('INSERT', $k, $v, 'expr_type'); } - $columns .= ","; + $sql .= " "; } - - if ($columns !== "") { - $columns = " (" . substr($columns, 0, -1) . ")"; - } - - $sql .= $columns; - return $sql; + return 'INSERT ' . substr($sql, 0, -1); } - + } ?> diff --git a/tools/parser_sql/builders/InsertColumnListBuilder.php b/tools/parser_sql/builders/InsertColumnListBuilder.php new file mode 100644 index 000000000..3a8cbf5cb --- /dev/null +++ b/tools/parser_sql/builders/InsertColumnListBuilder.php @@ -0,0 +1,80 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for column-list parts of INSERT statements. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class InsertColumnListBuilder implements Builder { + + protected function buildColumn($parsed) { + $builder = new ColumnReferenceBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + if ($parsed['expr_type'] !== ExpressionType::COLUMN_LIST) { + return ""; + } + $sql = ""; + foreach ($parsed['sub_tree'] as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildColumn($v); + + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('INSERT column-list subtree', $k, $v, 'expr_type'); + } + + $sql .= ", "; + } + return "(" . substr($sql, 0, -2) . ")"; + } + +} +?> diff --git a/tools/parser_sql/builders/InsertStatementBuilder.php b/tools/parser_sql/builders/InsertStatementBuilder.php index aab37c0ce..fb0cdb8e7 100644 --- a/tools/parser_sql/builders/InsertStatementBuilder.php +++ b/tools/parser_sql/builders/InsertStatementBuilder.php @@ -35,12 +35,11 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: InsertStatementBuilder.php 834 2013-12-18 10:14:26Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/InsertBuilder.php'; -require_once dirname(__FILE__) . '/ValuesBuilder.php'; +namespace PHPSQLParser\builders; /** * This class implements the builder for the whole Insert statement. You can overwrite @@ -50,7 +49,7 @@ require_once dirname(__FILE__) . '/ValuesBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class InsertStatementBuilder { +class InsertStatementBuilder implements Builder { protected function buildVALUES($parsed) { $builder = new ValuesBuilder(); @@ -58,14 +57,33 @@ class InsertStatementBuilder { } protected function buildINSERT($parsed) { - $builder = new InsertBuilder($parsed); + $builder = new InsertBuilder(); return $builder->build($parsed); } - public function build($parsed) { + protected function buildSELECT($parsed) { + $builder = new SelectStatementBuilder(); + return $builder->build($parsed); + } + + protected function buildSET($parsed) { + $builder = new SetBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { // TODO: are there more than one tables possible (like [INSERT][1]) - return $this->buildINSERT($parsed['INSERT'][0]) . " " . $this->buildVALUES($parsed['VALUES']); - // TODO: subquery? + $sql = $this->buildINSERT($parsed['INSERT']); + if (isset($parsed['VALUES'])) { + $sql .= ' ' . $this->buildVALUES($parsed['VALUES']); + } + if (isset($parsed['SET'])) { + $sql .= ' ' . $this->buildSET($parsed['SET']); + } + if (isset($parsed['SELECT'])) { + $sql .= ' ' . $this->buildSELECT($parsed); + } + return $sql; } } ?> diff --git a/tools/parser_sql/builders/JoinBuilder.php b/tools/parser_sql/builders/JoinBuilder.php index eeab8a3ae..1b324551e 100644 --- a/tools/parser_sql/builders/JoinBuilder.php +++ b/tools/parser_sql/builders/JoinBuilder.php @@ -33,19 +33,21 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @author André Rothe + * @author George Schneeloch * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: JoinBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnsupportedFeatureException.php'; +namespace PHPSQLParser\builders; /** * This class implements the builder for the JOIN statement parts (within FROM). * You can overwrite all functions to achieve another handling. * * @author André Rothe + * @author George Schneeloch * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ @@ -64,6 +66,9 @@ class JoinBuilder { if ($parsed === 'RIGHT') { return " RIGHT JOIN "; } + if ($parsed === 'STRAIGHT_JOIN') { + return " STRAIGHT_JOIN "; + } // TODO: add more throw new UnsupportedFeatureException($parsed); } diff --git a/tools/parser_sql/builders/LikeBuilder.php b/tools/parser_sql/builders/LikeBuilder.php index 021a5d81f..a95243d57 100644 --- a/tools/parser_sql/builders/LikeBuilder.php +++ b/tools/parser_sql/builders/LikeBuilder.php @@ -35,12 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: LikeBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/TableBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; /** * This class implements the builder for the LIKE statement part of CREATE TABLE. @@ -50,17 +50,17 @@ require_once dirname(__FILE__) . '/TableBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class LikeBuilder { +class LikeBuilder implements Builder { protected function buildTable($parsed, $index) { $builder = new TableBuilder(); return $builder->build($parsed, $index); } - - public function build($parsed) { + + public function build(array $parsed) { $sql = $this->buildTable($parsed, 0); if (strlen($sql) === 0) { - throw new UnableToCreateSQLException('LIKE', "", $like, 'table'); + throw new UnableToCreateSQLException('LIKE', "", $parsed, 'table'); } return "LIKE " . $sql; } diff --git a/tools/parser_sql/builders/LikeExpressionBuilder.php b/tools/parser_sql/builders/LikeExpressionBuilder.php index 4d50bb3fa..ece45192c 100644 --- a/tools/parser_sql/builders/LikeExpressionBuilder.php +++ b/tools/parser_sql/builders/LikeExpressionBuilder.php @@ -35,13 +35,13 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: LikeExpressionBuilder.php 906 2014-01-07 14:38:08Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/TableBuilder.php'; -require_once dirname(__FILE__) . '/ReservedBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for the (LIKE) keyword within a @@ -53,7 +53,7 @@ require_once dirname(__FILE__) . '/ReservedBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class LikeExpressionBuilder { +class LikeExpressionBuilder implements Builder { protected function buildTable($parsed, $index) { $builder = new TableBuilder(); @@ -65,7 +65,7 @@ class LikeExpressionBuilder { return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::LIKE) { return ""; } diff --git a/tools/parser_sql/builders/LimitBuilder.php b/tools/parser_sql/builders/LimitBuilder.php index d35b82166..3578b0475 100644 --- a/tools/parser_sql/builders/LimitBuilder.php +++ b/tools/parser_sql/builders/LimitBuilder.php @@ -35,11 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: LimitBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; /** * This class implements the builder LIMIT statement. @@ -49,10 +50,10 @@ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php' * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class LimitBuilder { +class LimitBuilder implements Builder { - public function build($parsed) { - $sql = ($parsed['offset'] ? $parsed['offset'] . ", " : "") . $parsed['rowcount']; + public function build(array $parsed) { + $sql = ($parsed['rowcount']) . ($parsed['offset'] ? " OFFSET " . $parsed['offset'] : ""); if ($sql === "") { throw new UnableToCreateSQLException('LIMIT', 'rowcount', $parsed, 'rowcount'); } diff --git a/tools/parser_sql/builders/OperatorBuilder.php b/tools/parser_sql/builders/OperatorBuilder.php index d82d3013f..9cc906b9c 100644 --- a/tools/parser_sql/builders/OperatorBuilder.php +++ b/tools/parser_sql/builders/OperatorBuilder.php @@ -35,11 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: OperatorBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for operators. @@ -49,9 +50,9 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class OperatorBuilder { +class OperatorBuilder implements Builder { - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::OPERATOR) { return ""; } diff --git a/tools/parser_sql/builders/OrderByAliasBuilder.php b/tools/parser_sql/builders/OrderByAliasBuilder.php index e57962b3c..85bf4f2e8 100644 --- a/tools/parser_sql/builders/OrderByAliasBuilder.php +++ b/tools/parser_sql/builders/OrderByAliasBuilder.php @@ -35,12 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: OrderByAliasBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/DirectionBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for an alias within the ORDER-BY clause. @@ -50,14 +50,14 @@ require_once dirname(__FILE__) . '/DirectionBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class OrderByAliasBuilder { +class OrderByAliasBuilder implements Builder { protected function buildDirection($parsed) { $builder = new DirectionBuilder(); return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::ALIAS) { return ""; } diff --git a/tools/parser_sql/builders/OrderByBracketExpressionBuilder.php b/tools/parser_sql/builders/OrderByBracketExpressionBuilder.php new file mode 100644 index 000000000..a28ee6165 --- /dev/null +++ b/tools/parser_sql/builders/OrderByBracketExpressionBuilder.php @@ -0,0 +1,69 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; + +/** + * This class implements the builder for bracket-expressions within the ORDER-BY part. + * It must contain the direction. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class OrderByBracketExpressionBuilder extends WhereBracketExpressionBuilder { + + protected function buildDirection($parsed) { + $builder = new DirectionBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + $sql = parent::build($parsed); + if ($sql !== '') { + $sql .= $this->buildDirection($parsed); + } + return $sql; + } + +} +?> diff --git a/tools/parser_sql/builders/OrderByBuilder.php b/tools/parser_sql/builders/OrderByBuilder.php index 4743573c8..e088ad95e 100644 --- a/tools/parser_sql/builders/OrderByBuilder.php +++ b/tools/parser_sql/builders/OrderByBuilder.php @@ -35,13 +35,13 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: OrderByBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/OrderByAliasBuilder.php'; -require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for the ORDER-BY clause. @@ -51,31 +51,55 @@ require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class OrderByBuilder { +class OrderByBuilder implements Builder { protected function buildFunction($parsed) { - $builder = new FunctionBuilder(); + $builder = new OrderByFunctionBuilder(); + return $builder->build($parsed); + } + + protected function buildReserved($parsed) { + $builder = new OrderByReservedBuilder(); return $builder->build($parsed); } protected function buildColRef($parsed) { - $builder = new ColumnReferenceBuilder(); + $builder = new OrderByColumnReferenceBuilder(); return $builder->build($parsed); } - protected function buildOrderByAlias($parsed) { + protected function buildAlias($parsed) { $builder = new OrderByAliasBuilder(); return $builder->build($parsed); } - public function build($parsed) { + protected function buildExpression($parsed) { + $builder = new OrderByExpressionBuilder(); + return $builder->build($parsed); + } + + protected function buildBracketExpression($parsed) { + $builder = new OrderByBracketExpressionBuilder(); + return $builder->build($parsed); + } + + protected function buildPosition($parsed) { + $builder = new PositionBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { $sql = ""; foreach ($parsed as $k => $v) { $len = strlen($sql); - $sql .= $this->buildOrderByAlias($v); + $sql .= $this->buildAlias($v); $sql .= $this->buildColRef($v); $sql .= $this->buildFunction($v); - + $sql .= $this->buildExpression($v); + $sql .= $this->buildBracketExpression($v); + $sql .= $this->buildReserved($v); + $sql .= $this->buildPosition($v); + if ($len == strlen($sql)) { throw new UnableToCreateSQLException('ORDER', $k, $v, 'expr_type'); } diff --git a/tools/parser_sql/builders/OrderByColumnReferenceBuilder.php b/tools/parser_sql/builders/OrderByColumnReferenceBuilder.php new file mode 100644 index 000000000..fd11629f3 --- /dev/null +++ b/tools/parser_sql/builders/OrderByColumnReferenceBuilder.php @@ -0,0 +1,69 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; + +/** + * This class implements the builder for column references within the ORDER-BY part. + * It must contain the direction. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class OrderByColumnReferenceBuilder extends ColumnReferenceBuilder { + + protected function buildDirection($parsed) { + $builder = new DirectionBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + $sql = parent::build($parsed); + if ($sql !== '') { + $sql .= $this->buildDirection($parsed); + } + return $sql; + } + +} +?> diff --git a/tools/parser_sql/builders/OrderByExpressionBuilder.php b/tools/parser_sql/builders/OrderByExpressionBuilder.php new file mode 100644 index 000000000..7a1116b3d --- /dev/null +++ b/tools/parser_sql/builders/OrderByExpressionBuilder.php @@ -0,0 +1,69 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; + +/** + * This class implements the builder for expressions within the ORDER-BY part. + * It must contain the direction. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class OrderByExpressionBuilder extends WhereExpressionBuilder { + + protected function buildDirection($parsed) { + $builder = new DirectionBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + $sql = parent::build($parsed); + if ($sql !== '') { + $sql .= $this->buildDirection($parsed); + } + return $sql; + } + +} +?> diff --git a/tools/parser_sql/builders/OrderByFunctionBuilder.php b/tools/parser_sql/builders/OrderByFunctionBuilder.php new file mode 100644 index 000000000..d2514835d --- /dev/null +++ b/tools/parser_sql/builders/OrderByFunctionBuilder.php @@ -0,0 +1,69 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; + +/** + * This class implements the builder for functions within the ORDER-BY part. + * It must contain the direction. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class OrderByFunctionBuilder extends FunctionBuilder { + + protected function buildDirection($parsed) { + $builder = new DirectionBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + $sql = parent::build($parsed); + if ($sql !== '') { + $sql .= $this->buildDirection($parsed); + } + return $sql; + } + +} +?> diff --git a/tools/parser_sql/builders/OrderByReservedBuilder.php b/tools/parser_sql/builders/OrderByReservedBuilder.php new file mode 100644 index 000000000..798da0d98 --- /dev/null +++ b/tools/parser_sql/builders/OrderByReservedBuilder.php @@ -0,0 +1,69 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; + +/** + * This class implements the builder for reserved keywords within the ORDER-BY part. + * It must contain the direction. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class OrderByReservedBuilder extends ReservedBuilder { + + protected function buildDirection($parsed) { + $builder = new DirectionBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + $sql = parent::build($parsed); + if ($sql !== '') { + $sql .= $this->buildDirection($parsed); + } + return $sql; + } + +} +?> diff --git a/tools/parser_sql/builders/PositionBuilder.php b/tools/parser_sql/builders/PositionBuilder.php index 9a12d36e2..0237660a4 100644 --- a/tools/parser_sql/builders/PositionBuilder.php +++ b/tools/parser_sql/builders/PositionBuilder.php @@ -35,11 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: PositionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for positions of the GROUP-BY clause. @@ -49,9 +50,9 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class PositionBuilder { +class PositionBuilder implements Builder { - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::POSITION) { return ""; } diff --git a/tools/parser_sql/builders/PrimaryKeyBuilder.php b/tools/parser_sql/builders/PrimaryKeyBuilder.php index 5bc7a7624..49c8097ad 100644 --- a/tools/parser_sql/builders/PrimaryKeyBuilder.php +++ b/tools/parser_sql/builders/PrimaryKeyBuilder.php @@ -35,18 +35,13 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: PrimaryKeyBuilder.php 919 2014-01-08 11:49:02Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ColumnListBuilder.php'; -require_once dirname(__FILE__) . '/ConstraintBuilder.php'; -require_once dirname(__FILE__) . '/ReservedBuilder.php'; -require_once dirname(__FILE__) . '/IndexTypeBuilder.php'; -require_once dirname(__FILE__) . '/IndexSizeBuilder.php'; -require_once dirname(__FILE__) . '/IndexParserBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for the PRIMARY KEY statement part of CREATE TABLE. @@ -56,7 +51,7 @@ require_once dirname(__FILE__) . '/IndexParserBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class PrimaryKeyBuilder { +class PrimaryKeyBuilder implements Builder { protected function buildColumnList($parsed) { $builder = new ColumnListBuilder(); @@ -77,18 +72,18 @@ class PrimaryKeyBuilder { $builder = new IndexTypeBuilder(); return $builder->build($parsed); } - + protected function buildIndexSize($parsed) { $builder = new IndexSizeBuilder(); return $builder->build($parsed); } - + protected function buildIndexParser($parsed) { $builder = new IndexParserBuilder(); return $builder->build($parsed); } - - public function build($parsed) { + + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::PRIMARY_KEY) { return ""; } diff --git a/tools/parser_sql/builders/ProcedureBuilder.php b/tools/parser_sql/builders/ProcedureBuilder.php index 9017f6a07..283959304 100644 --- a/tools/parser_sql/builders/ProcedureBuilder.php +++ b/tools/parser_sql/builders/ProcedureBuilder.php @@ -35,11 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: ProcedureBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for a procedure within SHOW statement. @@ -49,9 +50,9 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class ProcedureBuilder { +class ProcedureBuilder implements Builder { - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::PROCEDURE) { return ""; } diff --git a/tools/parser_sql/builders/QueryBuilder.php b/tools/parser_sql/builders/QueryBuilder.php new file mode 100644 index 000000000..948e751fb --- /dev/null +++ b/tools/parser_sql/builders/QueryBuilder.php @@ -0,0 +1,97 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for queries within parentheses (no subqueries). + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class QueryBuilder implements Builder { + + protected function buildRefClause($parsed) { + $builder = new RefClauseBuilder(); + return $builder->build($parsed); + } + + protected function buildRefType($parsed) { + $builder = new RefTypeBuilder(); + return $builder->build($parsed); + } + + protected function buildJoin($parsed) { + $builder = new JoinBuilder(); + return $builder->build($parsed); + } + + protected function buildAlias($parsed) { + $builder = new AliasBuilder(); + return $builder->build($parsed); + } + + protected function buildSelectStatement($parsed) { + $builder = new SelectStatementBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed, $index = 0) { + if ($parsed['expr_type'] !== ExpressionType::QUERY) { + return ''; + } + + // TODO: should we add a numeric level (0) between sub_tree and SELECT? + $sql = $this->buildSelectStatement($parsed['sub_tree']); + $sql .= $this->buildAlias($parsed); + + if ($index !== 0) { + $sql = $this->buildJoin($parsed['join_type']) . $sql; + $sql .= $this->buildRefType($parsed['ref_type']); + $sql .= $parsed['ref_clause'] === false ? '' : $this->buildRefClause($parsed['ref_clause']); + } + return $sql; + } +} +?> diff --git a/tools/parser_sql/builders/RecordBuilder.php b/tools/parser_sql/builders/RecordBuilder.php index 0595c978b..d96487e68 100644 --- a/tools/parser_sql/builders/RecordBuilder.php +++ b/tools/parser_sql/builders/RecordBuilder.php @@ -35,15 +35,13 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: RecordBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/OperatorBuilder.php'; -require_once dirname(__FILE__) . '/ConstantBuilder.php'; -require_once dirname(__FILE__) . '/FunctionBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for the records within INSERT statement. @@ -53,7 +51,7 @@ require_once dirname(__FILE__) . '/FunctionBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class RecordBuilder { +class RecordBuilder implements Builder { protected function buildOperator($parsed) { $builder = new OperatorBuilder(); @@ -70,9 +68,14 @@ class RecordBuilder { return $builder->build($parsed); } - public function build($parsed) { + protected function buildColRef($parsed) { + $builder = new ColumnReferenceBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::RECORD) { - return ""; + return isset($parsed['base_expr']) ? $parsed['base_expr'] : ''; } $sql = ""; foreach ($parsed['data'] as $k => $v) { @@ -80,14 +83,15 @@ class RecordBuilder { $sql .= $this->buildConstant($v); $sql .= $this->buildFunction($v); $sql .= $this->buildOperator($v); + $sql .= $this->buildColRef($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException(ExpressionType::RECORD, $k, $v, 'expr_type'); } - $sql .= ","; + $sql .= ", "; } - $sql = substr($sql, 0, -1); + $sql = substr($sql, 0, -2); return "(" . $sql . ")"; } diff --git a/tools/parser_sql/builders/RefClauseBuilder.php b/tools/parser_sql/builders/RefClauseBuilder.php index 377f05a8c..a79654236 100644 --- a/tools/parser_sql/builders/RefClauseBuilder.php +++ b/tools/parser_sql/builders/RefClauseBuilder.php @@ -31,28 +31,31 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: RefClauseBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ - * + * @version SVN: $Id$ + * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; -require_once dirname(__FILE__) . '/OperatorBuilder.php'; -require_once dirname(__FILE__) . '/ConstantBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; /** - * This class implements the references clause within a JOIN. + * This class implements the references clause within a JOIN. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * + * */ -class RefClauseBuilder { +class RefClauseBuilder implements Builder { + + protected function buildInList($parsed) { + $builder = new InListBuilder(); + return $builder->build($parsed); + } protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); @@ -64,29 +67,54 @@ class RefClauseBuilder { return $builder->build($parsed); } + protected function buildFunction($parsed) { + $builder = new FunctionBuilder(); + return $builder->build($parsed); + } + protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } - public function build($parsed) { + protected function buildBracketExpression($parsed) { + $builder = new SelectBracketExpressionBuilder(); + return $builder->build($parsed); + } + + protected function buildColumnList($parsed) { + $builder = new ColumnListBuilder(); + return $builder->build($parsed); + } + + protected function buildSubQuery($parsed) { + $builder = new SubQueryBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { if ($parsed === false) { - return ""; + return ''; } - $sql = ""; + $sql = ''; foreach ($parsed as $k => $v) { $len = strlen($sql); $sql .= $this->buildColRef($v); $sql .= $this->buildOperator($v); $sql .= $this->buildConstant($v); + $sql .= $this->buildFunction($v); + $sql .= $this->buildBracketExpression($v); + $sql .= $this->buildInList($v); + $sql .= $this->buildColumnList($v); + $sql .= $this->buildSubQuery($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('expression ref_clause', $k, $v, 'expr_type'); } - $sql .= " "; + $sql .= ' '; } - return "(" . substr($sql, 0, -1) . ")"; + return substr($sql, 0, -1); } } ?> diff --git a/tools/parser_sql/builders/RefTypeBuilder.php b/tools/parser_sql/builders/RefTypeBuilder.php index b86575f48..cee0ab9c0 100644 --- a/tools/parser_sql/builders/RefTypeBuilder.php +++ b/tools/parser_sql/builders/RefTypeBuilder.php @@ -35,11 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: RefTypeBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnsupportedFeatureException.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnsupportedFeatureException; /** * This class implements the references type within a JOIN. diff --git a/tools/parser_sql/builders/RenameStatementBuilder.php b/tools/parser_sql/builders/RenameStatementBuilder.php new file mode 100644 index 000000000..2f1358c86 --- /dev/null +++ b/tools/parser_sql/builders/RenameStatementBuilder.php @@ -0,0 +1,86 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; + +/** + * This class implements the builder for the RENAME statement. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class RenameStatementBuilder implements Builder { + + protected function buildReserved($parsed) { + $builder = new ReservedBuilder(); + return $builder->build($parsed); + } + + protected function processSourceAndDestTable($v) { + if (!isset($v['source']) || !isset($v['destination'])) { + return ''; + } + return $v['source']['base_expr'] . ' TO ' . $v['destination']['base_expr'] . ','; + } + + public function build(array $parsed) { + $rename = $parsed['RENAME']; + $sql = ''; + foreach ($rename['sub_tree'] as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildReserved($v); + $sql .= $this->processSourceAndDestTable($v); + + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('RENAME subtree', $k, $v, 'expr_type'); + } + + $sql .= ' '; + } + $sql = trim('RENAME ' . $sql); + return (substr($sql, -1) === ',' ? substr($sql, 0, -1) : $sql); + } +} + +?> diff --git a/tools/parser_sql/builders/ReplaceBuilder.php b/tools/parser_sql/builders/ReplaceBuilder.php new file mode 100644 index 000000000..b4e7caffc --- /dev/null +++ b/tools/parser_sql/builders/ReplaceBuilder.php @@ -0,0 +1,100 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; + +/** + * This class implements the builder for the [REPLACE] statement parts. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class ReplaceBuilder implements Builder { + + protected function buildTable($parsed) { + $builder = new TableBuilder(); + return $builder->build($parsed, 0); + } + + protected function buildSubQuery($parsed) { + $builder = new SubQueryBuilder(); + return $builder->build($parsed, 0); + } + + protected function buildReserved($parsed) { + $builder = new ReservedBuilder(); + return $builder->build($parsed); + } + + protected function buildBracketExpression($parsed) { + $builder = new SelectBracketExpressionBuilder(); + return $builder->build($parsed); + } + + protected function buildColumnList($parsed) { + $builder = new ReplaceColumnListBuilder(); + return $builder->build($parsed, 0); + } + + public function build(array $parsed) { + $sql = ''; + foreach ($parsed as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildTable($v); + $sql .= $this->buildSubQuery($v); + $sql .= $this->buildColumnList($v); + $sql .= $this->buildReserved($v); + $sql .= $this->buildBracketExpression($v); + + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('REPLACE', $k, $v, 'expr_type'); + } + + $sql .= " "; + } + return 'REPLACE ' . substr($sql, 0, -1); + } + +} +?> diff --git a/tools/parser_sql/builders/ReplaceColumnListBuilder.php b/tools/parser_sql/builders/ReplaceColumnListBuilder.php new file mode 100644 index 000000000..45066964a --- /dev/null +++ b/tools/parser_sql/builders/ReplaceColumnListBuilder.php @@ -0,0 +1,80 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for column-list parts of REPLACE statements. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class ReplaceColumnListBuilder implements Builder { + + protected function buildColumn($parsed) { + $builder = new ColumnReferenceBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + if ($parsed['expr_type'] !== ExpressionType::COLUMN_LIST) { + return ""; + } + $sql = ""; + foreach ($parsed['sub_tree'] as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildColumn($v); + + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('REPLACE column-list subtree', $k, $v, 'expr_type'); + } + + $sql .= ", "; + } + return "(" . substr($sql, 0, -2) . ")"; + } + +} +?> diff --git a/tools/parser_sql/builders/ReplaceStatementBuilder.php b/tools/parser_sql/builders/ReplaceStatementBuilder.php new file mode 100644 index 000000000..5a30e05cb --- /dev/null +++ b/tools/parser_sql/builders/ReplaceStatementBuilder.php @@ -0,0 +1,89 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; + +/** + * This class implements the builder for the whole Replace statement. You can overwrite + * all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class ReplaceStatementBuilder implements Builder { + + protected function buildVALUES($parsed) { + $builder = new ValuesBuilder(); + return $builder->build($parsed); + } + + protected function buildREPLACE($parsed) { + $builder = new ReplaceBuilder(); + return $builder->build($parsed); + } + + protected function buildSELECT($parsed) { + $builder = new SelectStatementBuilder(); + return $builder->build($parsed); + } + + protected function buildSET($parsed) { + $builder = new SetBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + // TODO: are there more than one tables possible (like [REPLACE][1]) + $sql = $this->buildREPLACE($parsed['REPLACE']); + if (isset($parsed['VALUES'])) { + $sql .= ' ' . $this->buildVALUES($parsed['VALUES']); + } + if (isset($parsed['SET'])) { + $sql .= ' ' . $this->buildSET($parsed['SET']); + } + if (isset($parsed['SELECT'])) { + $sql .= ' ' . $this->buildSELECT($parsed); + } + return $sql; + } +} +?> diff --git a/tools/parser_sql/builders/ReservedBuilder.php b/tools/parser_sql/builders/ReservedBuilder.php index edf2fffaf..a670814c1 100644 --- a/tools/parser_sql/builders/ReservedBuilder.php +++ b/tools/parser_sql/builders/ReservedBuilder.php @@ -35,11 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: ReservedBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for reserved keywords. @@ -49,13 +50,13 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class ReservedBuilder { +class ReservedBuilder implements Builder { public function isReserved($parsed) { - return ($parsed['expr_type'] === ExpressionType::RESERVED); + return (isset($parsed['expr_type']) && $parsed['expr_type'] === ExpressionType::RESERVED); } - - public function build($parsed) { + + public function build(array $parsed) { if (!$this->isReserved($parsed)) { return ""; } diff --git a/tools/parser_sql/builders/SchemaBuilder.php b/tools/parser_sql/builders/SchemaBuilder.php new file mode 100644 index 000000000..1f076556f --- /dev/null +++ b/tools/parser_sql/builders/SchemaBuilder.php @@ -0,0 +1,62 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for a schema within DROP statement. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class SchemaBuilder implements Builder { + + public function build(array $parsed) { + if ($parsed['expr_type'] !== ExpressionType::SCHEMA) { + return ""; + } + return $parsed['base_expr']; + } +} +?> diff --git a/tools/parser_sql/builders/SelectBracketExpressionBuilder.php b/tools/parser_sql/builders/SelectBracketExpressionBuilder.php index fb1b1d72f..5050b38c1 100644 --- a/tools/parser_sql/builders/SelectBracketExpressionBuilder.php +++ b/tools/parser_sql/builders/SelectBracketExpressionBuilder.php @@ -35,12 +35,13 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: SelectBracketExpressionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/SubTreeBuilder.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; + /** * This class implements the builder for bracket expressions within a SELECT statement. * You can overwrite all functions to achieve another handling. @@ -49,20 +50,24 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class SelectBracketExpressionBuilder { +class SelectBracketExpressionBuilder implements Builder { protected function buildSubTree($parsed, $delim) { $builder = new SubTreeBuilder(); return $builder->build($parsed, $delim); } - public function build($parsed) { + protected function buildAlias($parsed) { + $builder = new AliasBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::BRACKET_EXPRESSION) { return ""; } - $sql = $this->buildSubTree($parsed, " "); - $sql = "(" . $sql . ")"; - return $sql; + return '(' . $this->buildSubTree($parsed, ' ') . ')' + . $this->buildAlias($parsed); } } ?> diff --git a/tools/parser_sql/builders/SelectBuilder.php b/tools/parser_sql/builders/SelectBuilder.php index e616d4fd0..970d66aec 100644 --- a/tools/parser_sql/builders/SelectBuilder.php +++ b/tools/parser_sql/builders/SelectBuilder.php @@ -35,15 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: SelectBuilder.php 903 2014-01-06 11:29:19Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ConstantBuilder.php'; -require_once dirname(__FILE__) . '/FunctionBuilder.php'; -require_once dirname(__FILE__) . '/SelectExpressionBuilder.php'; -require_once dirname(__FILE__) . '/SelectBracketExpressionBuilder.php'; -require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; + +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; /** * This class implements the builder for the [SELECT] field. You can overwrite @@ -53,7 +50,7 @@ require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class SelectBuilder { +class SelectBuilder implements Builder { protected function buildConstant($parsed) { $builder = new ConstantBuilder(); @@ -92,10 +89,10 @@ class SelectBuilder { * @return a string, which is added right after the expression */ protected function getDelimiter($parsed) { - return ($parsed['delim'] === false ? '' : (trim($parsed['delim']) . ' ')); + return (!isset($parsed['delim']) || $parsed['delim'] === false ? '' : (trim($parsed['delim']) . ' ')); } - public function build($parsed) { + public function build(array $parsed) { $sql = ""; foreach ($parsed as $k => $v) { $len = strlen($sql); diff --git a/tools/parser_sql/builders/SelectExpressionBuilder.php b/tools/parser_sql/builders/SelectExpressionBuilder.php index 1034a3ce6..5150eaaf9 100644 --- a/tools/parser_sql/builders/SelectExpressionBuilder.php +++ b/tools/parser_sql/builders/SelectExpressionBuilder.php @@ -35,13 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: SelectExpressionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/SubTreeBuilder.php'; -require_once dirname(__FILE__) . '/AliasBuilder.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for simple expressions within a SELECT statement. @@ -51,7 +50,7 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class SelectExpressionBuilder { +class SelectExpressionBuilder implements Builder { protected function buildSubTree($parsed, $delim) { $builder = new SubTreeBuilder(); @@ -63,7 +62,7 @@ class SelectExpressionBuilder { return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::EXPRESSION) { return ""; } diff --git a/tools/parser_sql/builders/SelectStatementBuilder.php b/tools/parser_sql/builders/SelectStatementBuilder.php index 1ca227186..5fc8b125c 100644 --- a/tools/parser_sql/builders/SelectStatementBuilder.php +++ b/tools/parser_sql/builders/SelectStatementBuilder.php @@ -35,16 +35,11 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: SelectStatementBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/LimitBuilder.php'; -require_once dirname(__FILE__) . '/SelectBuilder.php'; -require_once dirname(__FILE__) . '/FromBuilder.php'; -require_once dirname(__FILE__) . '/WhereBuilder.php'; -require_once dirname(__FILE__) . '/GroupByBuilder.php'; -require_once dirname(__FILE__) . '/OrderByBuilder.php'; +namespace PHPSQLParser\builders; /** * This class implements the builder for the whole Select statement. You can overwrite @@ -54,7 +49,7 @@ require_once dirname(__FILE__) . '/OrderByBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class SelectStatementBuilder { +class SelectStatementBuilder implements Builder { protected function buildSELECT($parsed) { $builder = new SelectBuilder(); @@ -76,6 +71,11 @@ class SelectStatementBuilder { return $builder->build($parsed); } + protected function buildHAVING($parsed) { + $builder = new HavingBuilder(); + return $builder->build($parsed); + } + protected function buildORDER($parsed) { $builder = new OrderByBuilder(); return $builder->build($parsed); @@ -85,9 +85,22 @@ class SelectStatementBuilder { $builder = new LimitBuilder(); return $builder->build($parsed); } + + protected function buildUNION($parsed) { + $builder = new UnionStatementBuilder(); + return $builder->build($parsed); + } + + protected function buildUNIONALL($parsed) { + $builder = new UnionAllStatementBuilder(); + return $builder->build($parsed); + } - public function build($parsed) { - $sql = $this->buildSELECT($parsed['SELECT']); + public function build(array $parsed) { + $sql = ""; + if (isset($parsed['SELECT'])) { + $sql .= $this->buildSELECT($parsed['SELECT']); + } if (isset($parsed['FROM'])) { $sql .= " " . $this->buildFROM($parsed['FROM']); } @@ -97,11 +110,20 @@ class SelectStatementBuilder { if (isset($parsed['GROUP'])) { $sql .= " " . $this->buildGROUP($parsed['GROUP']); } + if (isset($parsed['HAVING'])) { + $sql .= " " . $this->buildHAVING($parsed['HAVING']); + } if (isset($parsed['ORDER'])) { $sql .= " " . $this->buildORDER($parsed['ORDER']); } if (isset($parsed['LIMIT'])) { $sql .= " " . $this->buildLIMIT($parsed['LIMIT']); + } + if (isset($parsed['UNION'])) { + $sql .= " " . $this->buildUNION($parsed); + } + if (isset($parsed['UNION ALL'])) { + $sql .= " " . $this->buildUNIONALL($parsed); } return $sql; } diff --git a/tools/parser_sql/builders/SetBuilder.php b/tools/parser_sql/builders/SetBuilder.php index 9919eb968..aa5b4e877 100644 --- a/tools/parser_sql/builders/SetBuilder.php +++ b/tools/parser_sql/builders/SetBuilder.php @@ -35,12 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: SetBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/SetExpressionBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; /** * This class implements the builder for the SET part of INSERT statement. @@ -50,14 +50,14 @@ require_once dirname(__FILE__) . '/SetExpressionBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class SetBuilder { +class SetBuilder implements Builder { protected function buildSetExpression($parsed) { $builder = new SetExpressionBuilder(); return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { $sql = ""; foreach ($parsed as $k => $v) { $len = strlen($sql); diff --git a/tools/parser_sql/builders/SetExpressionBuilder.php b/tools/parser_sql/builders/SetExpressionBuilder.php index 07228aef3..652e61c6e 100644 --- a/tools/parser_sql/builders/SetExpressionBuilder.php +++ b/tools/parser_sql/builders/SetExpressionBuilder.php @@ -35,16 +35,13 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: SetExpressionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; -require_once dirname(__FILE__) . '/ConstantBuilder.php'; -require_once dirname(__FILE__) . '/OperatorBuilder.php'; -require_once dirname(__FILE__) . '/FunctionBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for the SET part of INSERT statement. @@ -54,7 +51,7 @@ require_once dirname(__FILE__) . '/FunctionBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class SetExpressionBuilder { +class SetExpressionBuilder implements Builder { protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); @@ -76,23 +73,42 @@ class SetExpressionBuilder { return $builder->build($parsed); } - public function build($parsed) { + protected function buildBracketExpression($parsed) { + $builder = new SelectBracketExpressionBuilder(); + return $builder->build($parsed); + } + + protected function buildSign($parsed) { + $builder = new SignBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::EXPRESSION) { - return ""; + return ''; } - $sql = ""; + $sql = ''; foreach ($parsed['sub_tree'] as $k => $v) { + $delim = ' '; $len = strlen($sql); $sql .= $this->buildColRef($v); $sql .= $this->buildConstant($v); $sql .= $this->buildOperator($v); $sql .= $this->buildFunction($v); - + $sql .= $this->buildBracketExpression($v); + + // we don't need whitespace between the sign and + // the following part + if ($this->buildSign($v) !== '') { + $delim = ''; + } + $sql .= $this->buildSign($v); + if ($len == strlen($sql)) { throw new UnableToCreateSQLException('SET expression subtree', $k, $v, 'expr_type'); } - $sql .= " "; + $sql .= $delim; } $sql = substr($sql, 0, -1); return $sql; diff --git a/tools/parser_sql/builders/ShowBuilder.php b/tools/parser_sql/builders/ShowBuilder.php index 6dea90570..ac34339c4 100644 --- a/tools/parser_sql/builders/ShowBuilder.php +++ b/tools/parser_sql/builders/ShowBuilder.php @@ -35,18 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: ShowBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ReservedBuilder.php'; -require_once dirname(__FILE__) . '/ConstantBuilder.php'; -require_once dirname(__FILE__) . '/EngineBuilder.php'; -require_once dirname(__FILE__) . '/FunctionBuilder.php'; -require_once dirname(__FILE__) . '/ProcedureBuilder.php'; -require_once dirname(__FILE__) . '/DatabaseBuilder.php'; -require_once dirname(__FILE__) . '/TableBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; /** * This class implements the builder for the SHOW statement. @@ -56,44 +50,44 @@ require_once dirname(__FILE__) . '/TableBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class ShowBuilder { +class ShowBuilder implements Builder { protected function buildTable($parsed, $delim) { $builder = new TableBuilder(); return $builder->build($parsed, $delim); } - + protected function buildFunction($parsed) { $builder = new FunctionBuilder(); return $builder->build($parsed); } - + protected function buildProcedure($parsed) { $builder = new ProcedureBuilder(); return $builder->build($parsed); } - + protected function buildDatabase($parsed) { $builder = new DatabaseBuilder(); return $builder->build($parsed); } - + protected function buildEngine($parsed) { $builder = new EngineBuilder(); return $builder->build($parsed); } - + protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } - + protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } - - public function build($parsed) { + + public function build(array $parsed) { $show = $parsed['SHOW']; $sql = ""; foreach ($show as $k => $v) { @@ -115,6 +109,6 @@ class ShowBuilder { $sql = substr($sql, 0, -1); return "SHOW " . $sql; - } + } } ?> diff --git a/tools/parser_sql/builders/ShowStatementBuilder.php b/tools/parser_sql/builders/ShowStatementBuilder.php index 9d152b8b8..f48fd9967 100644 --- a/tools/parser_sql/builders/ShowStatementBuilder.php +++ b/tools/parser_sql/builders/ShowStatementBuilder.php @@ -35,12 +35,11 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: ShowStatementBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/ShowBuilder.php'; -require_once dirname(__FILE__) . '/WhereBuilder.php'; +namespace PHPSQLParser\builders; /** * This class implements the builder for the SHOW statement. @@ -50,19 +49,19 @@ require_once dirname(__FILE__) . '/WhereBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class ShowStatementBuilder { +class ShowStatementBuilder implements Builder { protected function buildWHERE($parsed) { $builder = new WhereBuilder(); return $builder->build($parsed); } - + protected function buildSHOW($parsed) { $builder = new ShowBuilder(); return $builder->build($parsed); } - - public function build($parsed) { + + public function build(array $parsed) { $sql = $this->buildSHOW($parsed); if (isset($parsed['WHERE'])) { $sql .= " " . $this->buildWHERE($parsed['WHERE']); diff --git a/tools/parser_sql/builders/SignBuilder.php b/tools/parser_sql/builders/SignBuilder.php new file mode 100644 index 000000000..16b335c2d --- /dev/null +++ b/tools/parser_sql/builders/SignBuilder.php @@ -0,0 +1,62 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for unary operators. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class SignBuilder implements Builder { + + public function build(array $parsed) { + if ($parsed['expr_type'] !== ExpressionType::SIGN) { + return ""; + } + return $parsed['base_expr']; + } +} +?> diff --git a/tools/parser_sql/builders/SubQueryBuilder.php b/tools/parser_sql/builders/SubQueryBuilder.php index 363bb2df0..6c7fe757c 100644 --- a/tools/parser_sql/builders/SubQueryBuilder.php +++ b/tools/parser_sql/builders/SubQueryBuilder.php @@ -35,16 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: SubQueryBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/RefClauseBuilder.php'; -require_once dirname(__FILE__) . '/RefTypeBuilder.php'; -require_once dirname(__FILE__) . '/JoinBuilder.php'; -require_once dirname(__FILE__) . '/AliasBuilder.php'; -require_once dirname(__FILE__) . '/AliasBuilder.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for sub-queries. @@ -54,7 +50,7 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class SubQueryBuilder { +class SubQueryBuilder implements Builder { protected function buildRefClause($parsed) { $builder = new RefClauseBuilder(); @@ -81,19 +77,20 @@ class SubQueryBuilder { return $builder->build($parsed); } - public function build($parsed, $index = 0) { + public function build(array $parsed, $index = 0) { if ($parsed['expr_type'] !== ExpressionType::SUBQUERY) { - return ""; + return ''; } + // TODO: should we add a numeric level (0) between sub_tree and SELECT? $sql = $this->buildSelectStatement($parsed['sub_tree']); - $sql = "(" . $sql . ")"; + $sql = '(' . $sql . ')'; $sql .= $this->buildAlias($parsed); if ($index !== 0) { $sql = $this->buildJoin($parsed['join_type']) . $sql; - $sql .= $this - buildRefType($parsed['ref_type']); - $sql .= $this->buildRefClause($parsed['ref_clause']); + $sql .= $this->buildRefType($parsed['ref_type']); + $sql .= $parsed['ref_clause'] === false ? '' : $this->buildRefClause($parsed['ref_clause']); } return $sql; } diff --git a/tools/parser_sql/builders/SubTreeBuilder.php b/tools/parser_sql/builders/SubTreeBuilder.php index 51129884a..51e1c33d3 100644 --- a/tools/parser_sql/builders/SubTreeBuilder.php +++ b/tools/parser_sql/builders/SubTreeBuilder.php @@ -31,33 +31,26 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: SubTreeBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ - * + * @version SVN: $Id$ + * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ReservedBuilder.php'; -require_once dirname(__FILE__) . '/SelectBracketExpressionBuilder.php'; -require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; -require_once dirname(__FILE__) . '/FunctionBuilder.php'; -require_once dirname(__FILE__) . '/OperatorBuilder.php'; -require_once dirname(__FILE__) . '/ConstantBuilder.php'; -require_once dirname(__FILE__) . '/SubQueryBuilder.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; /** - * This class implements the builder for [sub_tree] fields. + * This class implements the builder for [sub_tree] fields. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * + * */ -class SubTreeBuilder { +class SubTreeBuilder implements Builder { protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); @@ -79,6 +72,11 @@ class SubTreeBuilder { return $builder->build($parsed); } + protected function buildInList($parsed) { + $builder = new InListBuilder(); + return $builder->build($parsed); + } + protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); @@ -89,13 +87,28 @@ class SubTreeBuilder { return $builder->build($parsed); } + protected function buildQuery($parsed) { + $builder = new QueryBuilder(); + return $builder->build($parsed); + } + protected function buildSelectBracketExpression($parsed) { $builder = new SelectBracketExpressionBuilder(); return $builder->build($parsed); } - public function build($parsed, $delim = " ") { - if ($parsed['sub_tree'] === '') { + protected function buildUserVariable($parsed) { + $builder = new UserVariableBuilder(); + return $builder->build($parsed); + } + + protected function buildSign($parsed) { + $builder = new SignBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed, $delim = " ") { + if ($parsed['sub_tree'] === '' || $parsed['sub_tree'] === false) { return ""; } $sql = ""; @@ -105,15 +118,23 @@ class SubTreeBuilder { $sql .= $this->buildFunction($v); $sql .= $this->buildOperator($v); $sql .= $this->buildConstant($v); + $sql .= $this->buildInList($v); $sql .= $this->buildSubQuery($v); $sql .= $this->buildSelectBracketExpression($v); $sql .= $this->buildReserved($v); + $sql .= $this->buildQuery($v); + $sql .= $this->buildUserVariable($v); + $sign = $this->buildSign($v); + $sql .= $sign; if ($len == strlen($sql)) { throw new UnableToCreateSQLException('expression subtree', $k, $v, 'expr_type'); } - $sql .= $delim; + // We don't need whitespace between a sign and the following part. + if ($sign === '') { + $sql .= $delim; + } } return substr($sql, 0, -strlen($delim)); } diff --git a/tools/parser_sql/builders/TableBracketExpressionBuilder.php b/tools/parser_sql/builders/TableBracketExpressionBuilder.php index 4ead5da1e..41eb3875a 100644 --- a/tools/parser_sql/builders/TableBracketExpressionBuilder.php +++ b/tools/parser_sql/builders/TableBracketExpressionBuilder.php @@ -35,17 +35,14 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: TableBracketExpressionBuilder.php 928 2014-01-08 13:01:57Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ColumnDefinitionBuilder.php'; -require_once dirname(__FILE__) . '/PrimaryKeyBuilder.php'; -require_once dirname(__FILE__) . '/ForeignKeyBuilder.php'; -require_once dirname(__FILE__) . '/CheckBuilder.php'; -require_once dirname(__FILE__) . '/LikeExpressionBuilder.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + /** * This class implements the builder for the table expressions * within the create definitions of CREATE TABLE. @@ -55,7 +52,7 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class TableBracketExpressionBuilder { +class TableBracketExpressionBuilder implements Builder { protected function buildColDef($parsed) { $builder = new ColumnDefinitionBuilder(); @@ -82,7 +79,12 @@ class TableBracketExpressionBuilder { return $builder->build($parsed); } - public function build($parsed) { + protected function buildIndexKey($parsed) { + $builder = new IndexKeyBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::BRACKET_EXPRESSION) { return ""; } @@ -94,7 +96,8 @@ class TableBracketExpressionBuilder { $sql .= $this->buildCheck($v); $sql .= $this->buildLikeExpression($v); $sql .= $this->buildForeignKey($v); - + $sql .= $this->buildIndexKey($v); + if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE create-def expression subtree', $k, $v, 'expr_type'); } diff --git a/tools/parser_sql/builders/TableBuilder.php b/tools/parser_sql/builders/TableBuilder.php index 9a97184b0..e92823434 100644 --- a/tools/parser_sql/builders/TableBuilder.php +++ b/tools/parser_sql/builders/TableBuilder.php @@ -31,62 +31,65 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: TableBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ - * + * @version SVN: $Id$ + * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/AliasBuilder.php'; -require_once dirname(__FILE__) . '/JoinBuilder.php'; -require_once dirname(__FILE__) . '/RefTypeBuilder.php'; -require_once dirname(__FILE__) . '/RefClauseBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** - * This class implements the builder for the table name and join options. + * This class implements the builder for the table name and join options. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * + * */ -class TableBuilder { +class TableBuilder implements Builder { protected function buildAlias($parsed) { $builder = new AliasBuilder(); return $builder->build($parsed); } + protected function buildIndexHintList($parsed) { + $builder = new IndexHintListBuilder(); + return $builder->build($parsed); + } + protected function buildJoin($parsed) { $builder = new JoinBuilder(); return $builder->build($parsed); } - + protected function buildRefType($parsed) { $builder = new RefTypeBuilder(); return $builder->build($parsed); } - + protected function buildRefClause($parsed) { $builder = new RefClauseBuilder(); return $builder->build($parsed); } - public function build($parsed, $index) { + public function build(array $parsed, $index = 0) { if ($parsed['expr_type'] !== ExpressionType::TABLE) { - return ""; + return ''; } $sql = $parsed['table']; $sql .= $this->buildAlias($parsed); + $sql .= $this->buildIndexHintList($parsed); if ($index !== 0) { $sql = $this->buildJoin($parsed['join_type']) . $sql; $sql .= $this->buildRefType($parsed['ref_type']); - $sql .= $this->buildRefClause($parsed['ref_clause']); + $sql .= $parsed['ref_clause'] === false ? '' : $this->buildRefClause($parsed['ref_clause']); } return $sql; } diff --git a/tools/parser_sql/builders/TableExpressionBuilder.php b/tools/parser_sql/builders/TableExpressionBuilder.php index 69badcade..e13f2d3ea 100644 --- a/tools/parser_sql/builders/TableExpressionBuilder.php +++ b/tools/parser_sql/builders/TableExpressionBuilder.php @@ -35,16 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: TableExpressionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/AliasBuilder.php'; -require_once dirname(__FILE__) . '/JoinBuilder.php'; -require_once dirname(__FILE__) . '/RefTypeBuilder.php'; -require_once dirname(__FILE__) . '/RefClauseBuilder.php'; -require_once dirname(__FILE__) . '/FromBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for the table name and join options. @@ -54,13 +50,13 @@ require_once dirname(__FILE__) . '/FromBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class TableExpressionBuilder { +class TableExpressionBuilder implements Builder { protected function buildFROM($parsed) { $builder = new FromBuilder(); return $builder->build($parsed); } - + protected function buildAlias($parsed) { $builder = new AliasBuilder(); return $builder->build($parsed); @@ -70,29 +66,29 @@ class TableExpressionBuilder { $builder = new JoinBuilder(); return $builder->build($parsed); } - + protected function buildRefType($parsed) { $builder = new RefTypeBuilder(); return $builder->build($parsed); } - + protected function buildRefClause($parsed) { $builder = new RefClauseBuilder(); return $builder->build($parsed); } - public function build($parsed, $index) { + public function build(array $parsed, $index = 0) { if ($parsed['expr_type'] !== ExpressionType::TABLE_EXPRESSION) { - return ""; + return ''; } $sql = substr($this->buildFROM($parsed['sub_tree']), 5); // remove FROM keyword - $sql = "(" . $sql . ")"; + $sql = '(' . $sql . ')'; $sql .= $this->buildAlias($parsed); if ($index !== 0) { $sql = $this->buildJoin($parsed['join_type']) . $sql; $sql .= $this->buildRefType($parsed['ref_type']); - $sql .= $this->buildRefClause($parsed['ref_clause']); + $sql .= $parsed['ref_clause'] === false ? '' : $this->buildRefClause($parsed['ref_clause']); } return $sql; } diff --git a/tools/parser_sql/builders/TempTableBuilder.php b/tools/parser_sql/builders/TempTableBuilder.php new file mode 100644 index 000000000..0dbbd5108 --- /dev/null +++ b/tools/parser_sql/builders/TempTableBuilder.php @@ -0,0 +1,91 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for the temporary table name and join options. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class TempTableBuilder implements Builder { + + protected function buildAlias($parsed) { + $builder = new AliasBuilder(); + return $builder->build($parsed); + } + + protected function buildJoin($parsed) { + $builder = new JoinBuilder(); + return $builder->build($parsed); + } + + protected function buildRefType($parsed) { + $builder = new RefTypeBuilder(); + return $builder->build($parsed); + } + + protected function buildRefClause($parsed) { + $builder = new RefClauseBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed, $index = 0) { + if ($parsed['expr_type'] !== ExpressionType::TEMPORARY_TABLE) { + return ''; + } + + $sql = $parsed['table']; + $sql .= $this->buildAlias($parsed); + + if ($index !== 0) { + $sql = $this->buildJoin($parsed['join_type']) . $sql; + $sql .= $this->buildRefType($parsed['ref_type']); + $sql .= $parsed['ref_clause'] === false ? '' : $this->buildRefClause($parsed['ref_clause']); + } + return $sql; + } +} +?> diff --git a/tools/parser_sql/builders/TruncateBuilder.php b/tools/parser_sql/builders/TruncateBuilder.php new file mode 100644 index 000000000..1caffea98 --- /dev/null +++ b/tools/parser_sql/builders/TruncateBuilder.php @@ -0,0 +1,71 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; + +/** + * This class implements the builder for the [TRUNCATE] part. You can overwrite + * all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class TruncateBuilder implements Builder { + + public function build(array $parsed) { + $sql = "TRUNCATE TABLE "; + $right = -1; + + // works for one table only + $parsed['tables'] = array($parsed['TABLE']['base_expr']); + + if ($parsed['tables'] !== false) { + foreach ($parsed['tables'] as $k => $v) { + $sql .= $v . ", "; + $right = -2; + } + } + + return substr($sql, 0, $right); + } +} +?> diff --git a/tools/parser_sql/builders/TruncateStatementBuilder.php b/tools/parser_sql/builders/TruncateStatementBuilder.php new file mode 100644 index 000000000..1fcea20c1 --- /dev/null +++ b/tools/parser_sql/builders/TruncateStatementBuilder.php @@ -0,0 +1,72 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; + +/** + * This class implements the builder for the whole Truncate statement. You can overwrite + * all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class TruncateStatementBuilder implements Builder { + + protected function buildTRUNCATE($parsed) { + $builder = new TruncateBuilder(); + return $builder->build($parsed); + } + + protected function buildFROM($parsed) { + $builder = new FromBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { + $sql = $this->buildTRUNCATE($parsed); + // $sql .= " " . $this->buildTRUNCATE($parsed) // Uncomment when parser fills in expr_type=table + + return $sql; + } + +} +?> diff --git a/tools/parser_sql/builders/UnionAllStatementBuilder.php b/tools/parser_sql/builders/UnionAllStatementBuilder.php new file mode 100644 index 000000000..1cfa2e8e7 --- /dev/null +++ b/tools/parser_sql/builders/UnionAllStatementBuilder.php @@ -0,0 +1,33 @@ + + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class UnionAllStatementBuilder implements Builder { + + + + public function build(array $parsed) + { + $sql = ''; + $select_builder = new SelectStatementBuilder(); + $first = true; + foreach ($parsed['UNION ALL'] as $clause) { + if (!$first) { + $sql .= " UNION ALL "; + } + else { + $first = false; + } + + $sql .= $select_builder->build($clause); + } + return $sql; + } +} \ No newline at end of file diff --git a/tools/parser_sql/builders/UnionStatementBuilder.php b/tools/parser_sql/builders/UnionStatementBuilder.php new file mode 100644 index 000000000..7572a22be --- /dev/null +++ b/tools/parser_sql/builders/UnionStatementBuilder.php @@ -0,0 +1,31 @@ + + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class UnionStatementBuilder implements Builder { + + public function build(array $parsed) + { + $sql = ''; + $select_builder = new SelectStatementBuilder(); + $first = true; + foreach ($parsed['UNION'] as $clause) { + if (!$first) { + $sql .= " UNION "; + } + else { + $first = false; + } + + $sql .= $select_builder->build($clause); + } + return $sql; + } +} \ No newline at end of file diff --git a/tools/parser_sql/builders/UpdateBuilder.php b/tools/parser_sql/builders/UpdateBuilder.php index 4369ff708..a4c66f878 100644 --- a/tools/parser_sql/builders/UpdateBuilder.php +++ b/tools/parser_sql/builders/UpdateBuilder.php @@ -35,10 +35,14 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: UpdateBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; + /** * This class implements the builder for the UPDATE statement parts. * You can overwrite all functions to achieve another handling. @@ -47,10 +51,25 @@ * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class UpdateBuilder { +class UpdateBuilder implements Builder { - public function build($parsed) { - return "UPDATE " . $parsed[0]['table']; + protected function buildTable($parsed, $idx) { + $builder = new TableBuilder(); + return $builder->build($parsed, $idx); + } + + public function build(array $parsed) { + $sql = ''; + + foreach ($parsed as $k => $v) { + $len = strlen($sql); + $sql .= $this->buildTable($v, $k); + + if ($len == strlen($sql)) { + throw new UnableToCreateSQLException('UPDATE table list', $k, $v, 'expr_type'); + } + } + return 'UPDATE ' . $sql; } } ?> diff --git a/tools/parser_sql/builders/UpdateStatementBuilder.php b/tools/parser_sql/builders/UpdateStatementBuilder.php index cbacb052d..fcefdd8e1 100644 --- a/tools/parser_sql/builders/UpdateStatementBuilder.php +++ b/tools/parser_sql/builders/UpdateStatementBuilder.php @@ -35,13 +35,11 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: UpdateStatementBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/WhereBuilder.php'; -require_once dirname(__FILE__) . '/SetBuilder.php'; -require_once dirname(__FILE__) . '/UpdateBuilder.php'; +namespace PHPSQLParser\builders; /** * This class implements the builder for the whole Update statement. You can overwrite @@ -51,7 +49,7 @@ require_once dirname(__FILE__) . '/UpdateBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class UpdateStatementBuilder { +class UpdateStatementBuilder implements Builder { protected function buildWHERE($parsed) { $builder = new WhereBuilder(); @@ -68,7 +66,7 @@ class UpdateStatementBuilder { return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { $sql = $this->buildUPDATE($parsed['UPDATE']) . " " . $this->buildSET($parsed['SET']); if (isset($parsed['WHERE'])) { $sql .= " " . $this->buildWHERE($parsed['WHERE']); diff --git a/tools/parser_sql/builders/UserVariableBuilder.php b/tools/parser_sql/builders/UserVariableBuilder.php index 9a3db2d8e..349a031f2 100644 --- a/tools/parser_sql/builders/UserVariableBuilder.php +++ b/tools/parser_sql/builders/UserVariableBuilder.php @@ -35,11 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: UserVariableBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; /** * This class implements the builder for an user variable. @@ -49,9 +50,9 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class UserVariableBuilder { +class UserVariableBuilder implements Builder { - public function build($parsed) { + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::USER_VARIABLE) { return ""; } diff --git a/tools/parser_sql/builders/ValuesBuilder.php b/tools/parser_sql/builders/ValuesBuilder.php index dfa781369..9053d4675 100644 --- a/tools/parser_sql/builders/ValuesBuilder.php +++ b/tools/parser_sql/builders/ValuesBuilder.php @@ -35,12 +35,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: ValuesBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ + * @version SVN: $Id$ * */ -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/RecordBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; /** * This class implements the builder for the VALUES part of INSERT statement. @@ -50,14 +50,14 @@ require_once dirname(__FILE__) . '/RecordBuilder.php'; * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ -class ValuesBuilder { +class ValuesBuilder implements Builder { protected function buildRecord($parsed) { $builder = new RecordBuilder(); return $builder->build($parsed); } - public function build($parsed) { + public function build(array $parsed) { $sql = ""; foreach ($parsed as $k => $v) { $len = strlen($sql); @@ -67,10 +67,13 @@ class ValuesBuilder { throw new UnableToCreateSQLException('VALUES', $k, $v, 'expr_type'); } - $sql .= ","; + $sql .= $this->getRecordDelimiter($v); } - $sql = substr($sql, 0, -1); - return "VALUES " . $sql; - } + return "VALUES " . trim($sql); + } + + protected function getRecordDelimiter($parsed) { + return empty($parsed['delim']) ? ' ' : $parsed['delim'] . ' '; + } } ?> diff --git a/tools/parser_sql/builders/ViewBuilder.php b/tools/parser_sql/builders/ViewBuilder.php new file mode 100644 index 000000000..060f24c88 --- /dev/null +++ b/tools/parser_sql/builders/ViewBuilder.php @@ -0,0 +1,62 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\builders; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class implements the builder for a view within DROP statement. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class ViewBuilder implements Builder { + + public function build(array $parsed) { + if ($parsed['expr_type'] !== ExpressionType::VIEW) { + return ""; + } + return $parsed['base_expr']; + } +} +?> diff --git a/tools/parser_sql/builders/WhereBracketExpressionBuilder.php b/tools/parser_sql/builders/WhereBracketExpressionBuilder.php index c3d333f65..8a65914b5 100644 --- a/tools/parser_sql/builders/WhereBracketExpressionBuilder.php +++ b/tools/parser_sql/builders/WhereBracketExpressionBuilder.php @@ -31,34 +31,27 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: WhereBracketExpressionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ - * + * @version SVN: $Id$ + * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; -require_once dirname(__FILE__) . '/ConstantBuilder.php'; -require_once dirname(__FILE__) . '/OperatorBuilder.php'; -require_once dirname(__FILE__) . '/FunctionBuilder.php'; -require_once dirname(__FILE__) . '/InListBuilder.php'; -require_once dirname(__FILE__) . '/WhereExpressionBuilder.php'; -require_once dirname(__FILE__) . '/WhereBracketExpressionBuilder.php'; -require_once dirname(__FILE__) . '/UserVariableBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; /** - * This class implements the builder for bracket expressions within the WHERE part. + * This class implements the builder for bracket expressions within the WHERE part. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * + * */ -class WhereBracketExpressionBuilder { +class WhereBracketExpressionBuilder implements Builder { protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); @@ -95,7 +88,17 @@ class WhereBracketExpressionBuilder { return $builder->build($parsed); } - public function build($parsed) { + protected function buildSubQuery($parsed) { + $builder = new SubQueryBuilder(); + return $builder->build($parsed); + } + + protected function buildReserved($parsed) { + $builder = new ReservedBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::BRACKET_EXPRESSION) { return ""; } @@ -110,7 +113,10 @@ class WhereBracketExpressionBuilder { $sql .= $this->buildWhereExpression($v); $sql .= $this->build($v); $sql .= $this->buildUserVariable($v); - + // $sql .= $this->buildSubQuery($v); + $sql .= $this->buildReserved($v); + $sql .= $this->buildSubQuery($v); + if ($len == strlen($sql)) { throw new UnableToCreateSQLException('WHERE expression subtree', $k, $v, 'expr_type'); } diff --git a/tools/parser_sql/builders/WhereBuilder.php b/tools/parser_sql/builders/WhereBuilder.php index 3be2b80aa..507b437bf 100644 --- a/tools/parser_sql/builders/WhereBuilder.php +++ b/tools/parser_sql/builders/WhereBuilder.php @@ -31,35 +31,26 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: WhereBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ - * + * @version SVN: $Id$ + * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; -require_once dirname(__FILE__) . '/ConstantBuilder.php'; -require_once dirname(__FILE__) . '/OperatorBuilder.php'; -require_once dirname(__FILE__) . '/FunctionBuilder.php'; -require_once dirname(__FILE__) . '/InListBuilder.php'; -require_once dirname(__FILE__) . '/WhereExpressionBuilder.php'; -require_once dirname(__FILE__) . '/WhereBracketExpressionBuilder.php'; -require_once dirname(__FILE__) . '/UserVariableBuilder.php'; -require_once dirname(__FILE__) . '/SubQueryBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; /** - * This class implements the builder for the WHERE part. + * This class implements the builder for the WHERE part. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * + * */ -class WhereBuilder { +class WhereBuilder implements Builder { protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); @@ -106,7 +97,12 @@ class WhereBuilder { return $builder->build($parsed); } - public function build($parsed) { + protected function buildReserved($parsed) { + $builder = new ReservedBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { $sql = "WHERE "; foreach ($parsed as $k => $v) { $len = strlen($sql); @@ -120,7 +116,8 @@ class WhereBuilder { $sql .= $this->buildWhereExpression($v); $sql .= $this->buildWhereBracketExpression($v); $sql .= $this->buildUserVariable($v); - + $sql .= $this->buildReserved($v); + if (strlen($sql) == $len) { throw new UnableToCreateSQLException('WHERE', $k, $v, 'expr_type'); } diff --git a/tools/parser_sql/builders/WhereExpressionBuilder.php b/tools/parser_sql/builders/WhereExpressionBuilder.php index 659c1db1e..bf5b8868b 100644 --- a/tools/parser_sql/builders/WhereExpressionBuilder.php +++ b/tools/parser_sql/builders/WhereExpressionBuilder.php @@ -31,34 +31,27 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: WhereExpressionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ - * + * @version SVN: $Id$ + * */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; -require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; -require_once dirname(__FILE__) . '/ConstantBuilder.php'; -require_once dirname(__FILE__) . '/OperatorBuilder.php'; -require_once dirname(__FILE__) . '/FunctionBuilder.php'; -require_once dirname(__FILE__) . '/InListBuilder.php'; -require_once dirname(__FILE__) . '/WhereExpressionBuilder.php'; -require_once dirname(__FILE__) . '/WhereBracketExpressionBuilder.php'; -require_once dirname(__FILE__) . '/UserVariableBuilder.php'; +namespace PHPSQLParser\builders; +use PHPSQLParser\exceptions\UnableToCreateSQLException; +use PHPSQLParser\utils\ExpressionType; /** - * This class implements the builder for expressions within the WHERE part. + * This class implements the builder for expressions within the WHERE part. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * + * */ -class WhereExpressionBuilder { +class WhereExpressionBuilder implements Builder { protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); @@ -69,38 +62,47 @@ class WhereExpressionBuilder { $builder = new ConstantBuilder(); return $builder->build($parsed); } - + protected function buildOperator($parsed) { $builder = new OperatorBuilder(); return $builder->build($parsed); } - + protected function buildFunction($parsed) { $builder = new FunctionBuilder(); return $builder->build($parsed); } - + protected function buildInList($parsed) { $builder = new InListBuilder(); return $builder->build($parsed); } - + protected function buildWhereExpression($parsed) { - $builder = new WhereExpressionBuilder(); - return $builder->build($parsed); + return $this->build($parsed); } - + protected function buildWhereBracketExpression($parsed) { $builder = new WhereBracketExpressionBuilder(); return $builder->build($parsed); } - + protected function buildUserVariable($parsed) { $builder = new UserVariableBuilder(); return $builder->build($parsed); } - - public function build($parsed) { + + protected function buildSubQuery($parsed) { + $builder = new SubQueryBuilder(); + return $builder->build($parsed); + } + + protected function buildReserved($parsed) { + $builder = new ReservedBuilder(); + return $builder->build($parsed); + } + + public function build(array $parsed) { if ($parsed['expr_type'] !== ExpressionType::EXPRESSION) { return ""; } @@ -115,6 +117,8 @@ class WhereExpressionBuilder { $sql .= $this->buildWhereExpression($v); $sql .= $this->buildWhereBracketExpression($v); $sql .= $this->buildUserVariable($v); + $sql .= $this->buildSubQuery($v); + $sql .= $this->buildReserved($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('WHERE expression subtree', $k, $v, 'expr_type'); @@ -126,6 +130,6 @@ class WhereExpressionBuilder { $sql = substr($sql, 0, -1); return $sql; } - + } ?> diff --git a/tools/parser_sql/exceptions/InvalidParameterException.php b/tools/parser_sql/exceptions/InvalidParameterException.php index cfe80aab0..116747826 100644 --- a/tools/parser_sql/exceptions/InvalidParameterException.php +++ b/tools/parser_sql/exceptions/InvalidParameterException.php @@ -4,39 +4,52 @@ * * This file implements the InvalidParameterException class which is used within the * PHPSQLParser package. + * + * PHP version 5 * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe - * + * LICENSE: + * Copyright (c) 2010-2014 André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * */ +namespace PHPSQLParser\exceptions; +use InvalidArgumentException; + /** * This exception will occur in the parser, if the given SQL statement * is not a String type. - * - * @author arothe * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class InvalidParameterException extends InvalidArgumentException { diff --git a/tools/parser_sql/exceptions/UnableToCalculatePositionException.php b/tools/parser_sql/exceptions/UnableToCalculatePositionException.php index 2cc54c965..0d68e7a81 100644 --- a/tools/parser_sql/exceptions/UnableToCalculatePositionException.php +++ b/tools/parser_sql/exceptions/UnableToCalculatePositionException.php @@ -5,39 +5,52 @@ * This file implements the UnableToCalculatePositionException class which is used within the * PHPSQLParser package. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * */ +namespace PHPSQLParser\exceptions; +use Exception; + /** * This exception will occur, if the PositionCalculator can not find the token * defined by a base_expr field within the original SQL statement. Please create * an issue in such a case, it is an application error. - * - * @author arothe * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class UnableToCalculatePositionException extends Exception { diff --git a/tools/parser_sql/exceptions/UnableToCreateSQLException.php b/tools/parser_sql/exceptions/UnableToCreateSQLException.php index e9d38340a..c9b04d218 100644 --- a/tools/parser_sql/exceptions/UnableToCreateSQLException.php +++ b/tools/parser_sql/exceptions/UnableToCreateSQLException.php @@ -5,40 +5,52 @@ * This file implements the UnableToCreateSQLException class which is used within the * PHPSQLParser package. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * */ +namespace PHPSQLParser\exceptions; +use Exception; /** * This exception will occur within the PHPSQLCreator, if the creator can not find a * method, which can handle the current expr_type field. It could be an error within the parser * output or a special case has not been modelled within the creator. Please create an issue * in such a case. - * - * @author arothe * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class UnableToCreateSQLException extends Exception { @@ -52,7 +64,8 @@ class UnableToCreateSQLException extends Exception { $this->partkey = $partkey; $this->entry = $entry; $this->entrykey = $entrykey; - parent::__construct("unknown [" . $entrykey . "] = " .$entry[$entrykey] . " in \"" . $part . "\" [" . $partkey . "] ", 15); + parent::__construct( + "unknown [" . $entrykey . "] = " . $entry[$entrykey] . " in \"" . $part . "\" [" . $partkey . "] ", 15); } public function getEntry() { diff --git a/tools/parser_sql/exceptions/UnsupportedFeatureException.php b/tools/parser_sql/exceptions/UnsupportedFeatureException.php index e169e2461..bc5d2849a 100644 --- a/tools/parser_sql/exceptions/UnsupportedFeatureException.php +++ b/tools/parser_sql/exceptions/UnsupportedFeatureException.php @@ -5,40 +5,52 @@ * This file implements the UnsupportedFeatureException class which is used within the * PHPSQLParser package. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * */ +namespace PHPSQLParser\exceptions; +use Exception; /** * This exception will occur in the PHPSQLCreator, if the creator finds * a field name, which is unknown. The developers have created some * additional output of the parser, but the creator class has not been * enhanced. Please open an issue in such a case. - * - * @author arothe * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class UnsupportedFeatureException extends Exception { diff --git a/tools/parser_sql/lexer/LexerSplitter.php b/tools/parser_sql/lexer/LexerSplitter.php index 8c801817b..365f5c569 100644 --- a/tools/parser_sql/lexer/LexerSplitter.php +++ b/tools/parser_sql/lexer/LexerSplitter.php @@ -36,10 +36,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: LexerSplitter.php 842 2013-12-30 08:57:53Z phosco@gmx.de $ + * @version SVN: $Id$ * */ +namespace PHPSQLParser\lexer; + /** * This class holds a sorted array of characters, which are used as stop token. * On every part of the array the given SQL string will be split into single tokens. @@ -54,8 +56,11 @@ class LexerSplitter { protected static $splitters = array("<=>", "\r\n", "!=", ">=", "<=", "<>", "<<", ">>", ":=", "\\", "&&", "||", ":=", "/*", "*/", "--", ">", "<", "|", "=", "^", "(", ")", "\t", "\n", "'", "\"", "`", ",", "@", " ", "+", "-", "*", "/", ";"); - protected $tokenSize; - protected $hashSet; + + /** + * @var string Regex string pattern of splitters. + */ + protected $splitterPattern; /** * Constructor. @@ -63,32 +68,60 @@ class LexerSplitter { * It initializes some fields. */ public function __construct() { - $this->tokenSize = strlen(self::$splitters[0]); // should be the largest one - $this->hashSet = array_flip(self::$splitters); + $this->splitterPattern = $this->convertSplittersToRegexPattern( self::$splitters ); } - /** - * Get the maximum length of a split token. - * - * The largest element must be on position 0 of the internal $_splitters array, - * so the function returns the length of that token. It must be > 0. - * - * @return int The number of characters for the largest split token. - */ - public function getMaxLengthOfSplitter() { - return $this->tokenSize; + /** + * Get the regex pattern string of all the splitters + * + * @return string + */ + public function getSplittersRegexPattern () { + return $this->splitterPattern; } - /** - * Looks into the internal split token array and compares the given token with - * the array content. It returns true, if the token will be found, false otherwise. - * - * @param String $token a string, which could be a split token. - * - * @return boolean true, if the given string will be a split token, false otherwise - */ - public function isSplitter($token) { - return isset($this->hashSet[$token]); + /** + * Convert an array of splitter tokens to a regex pattern string. + * + * @param array $splitters + * + * @return string + */ + public function convertSplittersToRegexPattern( $splitters ) { + $regex_parts = array(); + foreach ( $splitters as $part ) { + $part = preg_quote( $part ); + + switch ( $part ) { + case "\r\n": + $part = '\r\n'; + break; + case "\t": + $part = '\t'; + break; + case "\n": + $part = '\n'; + break; + case " ": + $part = '\s'; + break; + case "/": + $part = "\/"; + break; + case "/\*": + $part = "\/\*"; + break; + case "\*/": + $part = "\*\/"; + break; + } + + $regex_parts[] = $part; + } + + $pattern = implode( '|', $regex_parts ); + + return '/(' . $pattern . ')/'; } } diff --git a/tools/parser_sql/lexer/PHPSQLLexer.php b/tools/parser_sql/lexer/PHPSQLLexer.php index d9c5cfe68..4ef0e1267 100644 --- a/tools/parser_sql/lexer/PHPSQLLexer.php +++ b/tools/parser_sql/lexer/PHPSQLLexer.php @@ -2,9 +2,9 @@ /** * PHPSQLLexer.php * - * This file contains the lexer, which splits and recombines parts of the + * This file contains the lexer, which splits and recombines parts of the * SQL statement just before parsing. - * + * * PHP version 5 * * LICENSE: @@ -32,21 +32,21 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: PHPSQLLexer.php 842 2013-12-30 08:57:53Z phosco@gmx.de $ - * + * @version SVN: $Id$ + * */ -require_once dirname(__FILE__) . '/LexerSplitter.php'; -require_once dirname(__FILE__) . '/../exceptions/InvalidParameterException.php'; +namespace PHPSQLParser\lexer; +use PHPSQLParser\exceptions\InvalidParameterException; /** * This class splits the SQL string into little parts, which the parser can * use to build the result array. - * + * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @@ -56,8 +56,8 @@ class PHPSQLLexer { protected $splitters; /** - * Constructor. - * + * Constructor. + * * It initializes some fields. */ public function __construct() { @@ -66,10 +66,10 @@ class PHPSQLLexer { /** * Ends the given string $haystack with the string $needle? - * + * * @param string $haystack * @param string $needle - * + * * @return boolean true, if the parameter $haystack ends with the character sequences $needle, false otherwise */ protected function endsWith($haystack, $needle) { @@ -84,50 +84,96 @@ class PHPSQLLexer { if (!is_string($sql)) { throw new InvalidParameterException($sql); } - - $tokens = array(); - $token = ""; - - $splitLen = $this->splitters->getMaxLengthOfSplitter(); - $found = false; - $len = strlen($sql); - $pos = 0; - - while ($pos < $len) { - - for ($i = $splitLen; $i > 0; $i--) { - $substr = substr($sql, $pos, $i); - if ($this->splitters->isSplitter($substr)) { - - if ($token !== "") { - $tokens[] = $token; - } - - $tokens[] = $substr; - $pos += $i; - $token = ""; - - continue 2; - } - } - - $token .= $sql[$pos]; - $pos++; - } - - if ($token !== "") { - $tokens[] = $token; - } - + $tokens = preg_split($this->splitters->getSplittersRegexPattern(), $sql, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + $tokens = $this->concatComments($tokens); $tokens = $this->concatEscapeSequences($tokens); $tokens = $this->balanceBackticks($tokens); $tokens = $this->concatColReferences($tokens); $tokens = $this->balanceParenthesis($tokens); - $tokens = $this->concatComments($tokens); $tokens = $this->concatUserDefinedVariables($tokens); + $tokens = $this->concatScientificNotations($tokens); + $tokens = $this->concatNegativeNumbers($tokens); return $tokens; } + protected function concatNegativeNumbers($tokens) { + + $i = 0; + $cnt = count($tokens); + $possibleSign = true; + + while ($i < $cnt) { + + if (!isset($tokens[$i])) { + $i++; + continue; + } + + $token = $tokens[$i]; + + // a sign is also possible on the first position of the tokenlist + if ($possibleSign === true) { + if ($token === '-' || $token === '+') { + if (is_numeric($tokens[$i + 1])) { + $tokens[$i + 1] = $token . $tokens[$i + 1]; + unset($tokens[$i]); + } + } + $possibleSign = false; + continue; + } + + // TODO: we can have sign of a number after "(" and ",", are others possible? + if (substr($token, -1, 1) === "," || substr($token, -1, 1) === "(") { + $possibleSign = true; + } + + $i++; + } + + return array_values($tokens); + } + + protected function concatScientificNotations($tokens) { + + $i = 0; + $cnt = count($tokens); + $scientific = false; + + while ($i < $cnt) { + + if (!isset($tokens[$i])) { + $i++; + continue; + } + + $token = $tokens[$i]; + + if ($scientific === true) { + if ($token === '-' || $token === '+') { + $tokens[$i - 1] .= $tokens[$i]; + $tokens[$i - 1] .= $tokens[$i + 1]; + unset($tokens[$i]); + unset($tokens[$i + 1]); + + } elseif (is_numeric($token)) { + $tokens[$i - 1] .= $tokens[$i]; + unset($tokens[$i]); + } + $scientific = false; + continue; + } + + if (strtoupper(substr($token, -1, 1)) === 'E') { + $scientific = is_numeric(substr($token, 0, -1)); + } + + $i++; + } + + return array_values($tokens); + } + protected function concatUserDefinedVariables($tokens) { $i = 0; $cnt = count($tokens); @@ -165,6 +211,9 @@ class PHPSQLLexer { $i = 0; $cnt = count($tokens); $comment = false; + $backTicks = []; + $in_string = false; + $inline = false; while ($i < $cnt) { @@ -175,26 +224,52 @@ class PHPSQLLexer { $token = $tokens[$i]; - if ($comment !== false) { - if ($inline === true && ($token === "\n" || $token === "\r\n")) { - $comment = false; + /* + * Check to see if we're inside a value (i.e. back ticks). + * If so inline comments are not valid. + */ + if ($comment === false && $this->isBacktick($token)) { + if (!empty($backTicks)) { + $lastBacktick = array_pop($backTicks); + if ($lastBacktick != $token) { + $backTicks[] = $lastBacktick; // Re-add last back tick + $backTicks[] = $token; + } } else { - unset($tokens[$i]); - $tokens[$comment] .= $token; - } - if ($inline === false && ($token === "*/")) { - $comment = false; + $backTicks[] = $token; } } - if (($comment === false) && ($token === "--")) { - $comment = $i; - $inline = true; + if($comment === false && ($token == "\"" || $token == "'")) { + $in_string = !$in_string; } + if(!$in_string) { + if ($comment !== false) { + if ($inline === true && ($token === "\n" || $token === "\r\n")) { + $comment = false; + } else { + unset($tokens[$i]); + $tokens[$comment] .= $token; + } + if ($inline === false && ($token === "*/")) { + $comment = false; + } + } - if (($comment === false) && ($token === "/*")) { - $comment = $i; - $inline = false; + if (($comment === false) && ($token === "--") && empty($backTicks)) { + $comment = $i; + $inline = true; + } + + if (($comment === false) && (substr($token, 0, 1) === "#") && empty($backTicks)) { + $comment = $i; + $inline = true; + } + + if (($comment === false) && ($token === "/*")) { + $comment = $i; + $inline = false; + } } $i++; @@ -258,9 +333,9 @@ class PHPSQLLexer { /** * This function concats some tokens to a column reference. * There are two different cases: - * + * * 1. If the current token ends with a dot, we will add the next token - * 2. If the next token starts with a dot, we will add it to the previous token + * 2. If the next token starts with a dot, we will add it to the previous token * */ protected function concatColReferences($tokens) { diff --git a/tools/parser_sql/positions/PositionCalculator.php b/tools/parser_sql/positions/PositionCalculator.php index 731f21ee6..53eb57f6c 100644 --- a/tools/parser_sql/positions/PositionCalculator.php +++ b/tools/parser_sql/positions/PositionCalculator.php @@ -1,54 +1,109 @@ + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2015 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * */ -require_once dirname(__FILE__) . '/../utils/PHPSQLParserConstants.php'; -require_once dirname(__FILE__) . '/../exceptions/UnableToCalculatePositionException.php'; +namespace PHPSQLParser\positions; +use PHPSQLParser\utils\PHPSQLParserConstants; +use PHPSQLParser\exceptions\UnableToCalculatePositionException; +use PHPSQLParser\utils\ExpressionType; /** - * This class calculates the positions - * of base_expr within the original SQL statement. - * - * @author arothe - * + * This class implements the calculator for the string positions of the + * base_expr elements within the output of the PHPSQLParser. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class PositionCalculator { - private static $_allowedOnOperator = array("\t", "\n", "\r", " ", ",", "(", ")", "_", "'", "\""); - private static $_allowedOnOther = array("\t", "\n", "\r", " ", ",", "(", ")", "<", ">", "*", "+", "-", "/", "|", - "&", "=", "!", ";"); + protected static $allowedOnOperator = array("\t", "\n", "\r", " ", ",", "(", ")", "_", "'", "\"", "?", "@", "0", + "1", "2", "3", "4", "5", "6", "7", "8", "9"); + protected static $allowedOnOther = array("\t", "\n", "\r", " ", ",", "(", ")", "<", ">", "*", "+", "-", "/", "|", + "&", "=", "!", ";"); - private function _printPos($text, $sql, $charPos, $key, $parsed, $backtracking) { - if (!isset($_ENV['DEBUG'])) { + protected $flippedBacktrackingTypes; + protected static $backtrackingTypes = array(ExpressionType::EXPRESSION, ExpressionType::SUBQUERY, + ExpressionType::BRACKET_EXPRESSION, ExpressionType::TABLE_EXPRESSION, + ExpressionType::RECORD, ExpressionType::IN_LIST, + ExpressionType::MATCH_ARGUMENTS, ExpressionType::TABLE, + ExpressionType::TEMPORARY_TABLE, ExpressionType::COLUMN_TYPE, + ExpressionType::COLDEF, ExpressionType::PRIMARY_KEY, + ExpressionType::CONSTRAINT, ExpressionType::COLUMN_LIST, + ExpressionType::CHECK, ExpressionType::COLLATE, ExpressionType::LIKE, + ExpressionType::INDEX, ExpressionType::INDEX_TYPE, + ExpressionType::INDEX_SIZE, ExpressionType::INDEX_PARSER, + ExpressionType::FOREIGN_KEY, ExpressionType::REFERENCE, + ExpressionType::PARTITION, ExpressionType::PARTITION_HASH, + ExpressionType::PARTITION_COUNT, ExpressionType::PARTITION_KEY, + ExpressionType::PARTITION_KEY_ALGORITHM, + ExpressionType::PARTITION_RANGE, ExpressionType::PARTITION_LIST, + ExpressionType::PARTITION_DEF, ExpressionType::PARTITION_VALUES, + ExpressionType::SUBPARTITION_DEF, ExpressionType::PARTITION_DATA_DIR, + ExpressionType::PARTITION_INDEX_DIR, ExpressionType::PARTITION_COMMENT, + ExpressionType::PARTITION_MAX_ROWS, ExpressionType::PARTITION_MIN_ROWS, + ExpressionType::SUBPARTITION_COMMENT, + ExpressionType::SUBPARTITION_DATA_DIR, + ExpressionType::SUBPARTITION_INDEX_DIR, + ExpressionType::SUBPARTITION_KEY, + ExpressionType::SUBPARTITION_KEY_ALGORITHM, + ExpressionType::SUBPARTITION_MAX_ROWS, + ExpressionType::SUBPARTITION_MIN_ROWS, ExpressionType::SUBPARTITION, + ExpressionType::SUBPARTITION_HASH, ExpressionType::SUBPARTITION_COUNT, + ExpressionType::CHARSET, ExpressionType::ENGINE, ExpressionType::QUERY, + ExpressionType::INDEX_ALGORITHM, ExpressionType::INDEX_LOCK, + ExpressionType::SUBQUERY_FACTORING, ExpressionType::CUSTOM_FUNCTION + ); + + /** + * Constructor. + * + * It initializes some fields. + */ + public function __construct() { + $this->flippedBacktrackingTypes = array_flip(self::$backtrackingTypes); + } + + protected function printPos($text, $sql, $charPos, $key, $parsed, $backtracking) { + if (!isset($_SERVER['DEBUG'])) { return; } @@ -71,13 +126,15 @@ class PositionCalculator { return $parsed; } - private function findPositionWithinString($sql, $value, $expr_type) { + protected function findPositionWithinString($sql, $value, $expr_type) { $offset = 0; $ok = false; while (true) { $pos = strpos($sql, $value, $offset); + // error_log("pos:$pos value:$value sql:$sql"); + if ($pos === false) { break; } @@ -87,6 +144,9 @@ class PositionCalculator { $before = $sql[$pos - 1]; } + // if we have a quoted string, we every character is allowed after it + // see issue 137 + $quoted = ($sql[$pos + strlen($value) - 1] === '`'); $after = ""; if (isset($sql[$pos + strlen($value)])) { $after = $sql[$pos + strlen($value)]; @@ -96,14 +156,13 @@ class PositionCalculator { // whitespace, comma, parenthesis, digit or letter, end_of_string // an operator should not be surrounded by another operator - if ($expr_type === 'operator') { + if (in_array($expr_type,array('operator','column-list'),true)) { - $ok = ($before === "" || in_array($before, self::$_allowedOnOperator, true)) - || (strtolower($before) >= 'a' && strtolower($before) <= 'z') || ($before >= '0' && $before <= '9'); + $ok = ($before === "" || in_array($before, self::$allowedOnOperator, true)) + || (strtolower($before) >= 'a' && strtolower($before) <= 'z'); $ok = $ok - && ($after === "" || in_array($after, self::$_allowedOnOperator, true) - || (strtolower($after) >= 'a' && strtolower($after) <= 'z') || ($after >= '0' && $after <= '9') - || ($after === '?') || ($after === '@')); + && ($after === "" || in_array($after, self::$allowedOnOperator, true) + || (strtolower($after) >= 'a' && strtolower($after) <= 'z')); if (!$ok) { $offset = $pos + 1; @@ -116,8 +175,10 @@ class PositionCalculator { // in all other cases we accept // whitespace, comma, operators, parenthesis and end_of_string - $ok = ($before === "" || in_array($before, self::$_allowedOnOther, true)); - $ok = $ok && ($after === "" || in_array($after, self::$_allowedOnOther, true)); + $ok = ($before === "" || in_array($before, self::$allowedOnOther, true)); + $ok = $ok + && ($after === "" || in_array($after, self::$allowedOnOther, true) + || ($quoted && (strtolower($after) >= 'a' && strtolower($after) <= 'z'))); if ($ok) { break; @@ -129,27 +190,10 @@ class PositionCalculator { return $pos; } - private function lookForBaseExpression($sql, &$charPos, &$parsed, $key, &$backtracking) { + protected function lookForBaseExpression($sql, &$charPos, &$parsed, $key, &$backtracking) { if (!is_numeric($key)) { if (($key === 'UNION' || $key === 'UNION ALL') - || ($key === 'expr_type' && $parsed === ExpressionType::EXPRESSION) - || ($key === 'expr_type' && $parsed === ExpressionType::SUBQUERY) - || ($key === 'expr_type' && $parsed === ExpressionType::BRACKET_EXPRESSION) - || ($key === 'expr_type' && $parsed === ExpressionType::TABLE_EXPRESSION) - || ($key === 'expr_type' && $parsed === ExpressionType::RECORD) - || ($key === 'expr_type' && $parsed === ExpressionType::IN_LIST) - || ($key === 'expr_type' && $parsed === ExpressionType::MATCH_ARGUMENTS) - || ($key === 'expr_type' && $parsed === ExpressionType::TABLE) - || ($key === 'expr_type' && $parsed === ExpressionType::TEMPORARY_TABLE) - || ($key === 'expr_type' && $parsed === ExpressionType::COLUMN_TYPE) - || ($key === 'expr_type' && $parsed === ExpressionType::COLDEF) - || ($key === 'expr_type' && $parsed === ExpressionType::PRIMARY_KEY) - || ($key === 'expr_type' && $parsed === ExpressionType::CONSTRAINT) - || ($key === 'expr_type' && $parsed === ExpressionType::COLUMN_LIST) - || ($key === 'expr_type' && $parsed === ExpressionType::CHECK) - || ($key === 'expr_type' && $parsed === ExpressionType::COLLATE) - || ($key === 'expr_type' && $parsed === ExpressionType::LIKE) - || ($key === 'expr_type' && $parsed === ExpressionType::INDEX) + || ($key === 'expr_type' && isset($this->flippedBacktrackingTypes[$parsed])) || ($key === 'select-option' && $parsed !== false) || ($key === 'alias' && $parsed !== false)) { // we hold the current position and come back after the next base_expr // we do this, because the next base_expr contains the complete expression/subquery/record @@ -176,7 +220,7 @@ class PositionCalculator { } else { // move the current pos after the keyword // SELECT, WHERE, INSERT etc. - if (PHPSQLParserConstants::isReserved($key)) { + if (PHPSQLParserConstants::getInstance()->isReserved($key)) { $charPos = stripos($sql, $key, $charPos); $charPos += strlen($key); } @@ -190,7 +234,7 @@ class PositionCalculator { foreach ($parsed as $key => $value) { if ($key === 'base_expr') { - //$this->_printPos("0", $sql, $charPos, $key, $value, $backtracking); + //$this->printPos("0", $sql, $charPos, $key, $value, $backtracking); $subject = substr($sql, $charPos); $pos = $this->findPositionWithinString($subject, $value, @@ -202,14 +246,14 @@ class PositionCalculator { $parsed['position'] = $charPos + $pos; $charPos += $pos + strlen($value); - //$this->_printPos("1", $sql, $charPos, $key, $value, $backtracking); + //$this->printPos("1", $sql, $charPos, $key, $value, $backtracking); $oldPos = array_pop($backtracking); if (isset($oldPos) && $oldPos !== false) { $charPos = $oldPos; } - //$this->_printPos("2", $sql, $charPos, $key, $value, $backtracking); + //$this->printPos("2", $sql, $charPos, $key, $value, $backtracking); } else { $this->lookForBaseExpression($sql, $charPos, $parsed[$key], $key, $backtracking); diff --git a/tools/parser_sql/processors/AbstractProcessor.php b/tools/parser_sql/processors/AbstractProcessor.php index 0af0396a0..b172399d2 100644 --- a/tools/parser_sql/processors/AbstractProcessor.php +++ b/tools/parser_sql/processors/AbstractProcessor.php @@ -4,49 +4,76 @@ * * This file implements an abstract processor, which implements some helper functions. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; -require_once dirname(__FILE__) . '/../lexer/PHPSQLLexer.php'; +namespace PHPSQLParser\processors; + +use PHPSQLParser\lexer\PHPSQLLexer; +use PHPSQLParser\Options; +use PHPSQLParser\utils\ExpressionType; /** - * - * This class processes contains some general functions for a processor. - * - * @author arothe - * + * This class contains some general functions for a processor. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ abstract class AbstractProcessor { + /** + * @var Options + */ + protected $options; + + /** + * AbstractProcessor constructor. + * + * @param Options $options + */ + public function __construct(Options $options = null) + { + $this->options = $options; + } + /** * This function implements the main functionality of a processor class. * Always use default valuses for additional parameters within overridden functions. */ - abstract public function process($tokens); + public abstract function process($tokens); /** * this function splits up a SQL statement into easy to "parse" @@ -59,26 +86,83 @@ abstract class AbstractProcessor { /** * Revokes the quoting characters from an expression + * Possibibilies: + * `a` + * 'a' + * "a" + * `a`.`b` + * `a.b` + * a.`b` + * `a`.b + * It is also possible to have escaped quoting characters + * within an expression part: + * `a``b` => a`b + * And you can use whitespace between the parts: + * a . `b` => [a,b] */ protected function revokeQuotation($sql) { - $result = trim($sql); + $tmp = trim($sql); + $result = array(); - if (($result[0] === '`') && ($result[strlen($result) - 1] === '`')) { - $result = substr($result, 1, -1); - return trim(str_replace('``', '`', $result)); + $quote = false; + $start = 0; + $i = 0; + $len = strlen($tmp); + + while ($i < $len) { + + $char = $tmp[$i]; + switch ($char) { + case '`': + case '\'': + case '"': + if ($quote === false) { + // start + $quote = $char; + $start = $i + 1; + break; + } + if ($quote !== $char) { + break; + } + if (isset($tmp[$i + 1]) && ($quote === $tmp[$i + 1])) { + // escaped + $i++; + break; + } + // end + $char = substr($tmp, $start, $i - $start); + $result[] = str_replace($quote . $quote, $quote, $char); + $start = $i + 1; + $quote = false; + break; + + case '.': + if ($quote === false) { + // we have found a separator + $char = trim(substr($tmp, $start, $i - $start)); + if ($char !== '') { + $result[] = $char; + } + $start = $i + 1; + } + break; + + default: + // ignore + break; + } + $i++; } - if (($result[0] === "'") && ($result[strlen($result) - 1] === "'")) { - $result = substr($result, 1, -1); - return trim(str_replace("''", "'", $result)); + if ($quote === false && ($start < $len)) { + $char = trim(substr($tmp, $start, $i - $start)); + if ($char !== '') { + $result[] = $char; + } } - if (($result[0] === "\"") && ($result[strlen($result) - 1] === "\"")) { - $result = substr($result, 1, -1); - return trim(str_replace("\"\"", "\"", $result)); - } - - return $sql; + return array('delim' => (count($result) === 1 ? false : '.'), 'parts' => $result); } /** @@ -89,33 +173,47 @@ abstract class AbstractProcessor { $parenthesisRemoved = 0; $trim = trim($token); - if ($trim !== "" && $trim[0] === "(") { // remove only one parenthesis pair now! + if ($trim !== '' && $trim[0] === '(') { // remove only one parenthesis pair now! $parenthesisRemoved++; - $trim[0] = " "; + $trim[0] = ' '; $trim = trim($trim); } $parenthesis = $parenthesisRemoved; $i = 0; $string = 0; + // Whether a string was opened or not, and with which character it was open (' or ") + $stringOpened = ''; while ($i < strlen($trim)) { if ($trim[$i] === "\\") { - $i += 2; # an escape character, the next character is irrelevant + $i += 2; // an escape character, the next character is irrelevant continue; } - if ($trim[$i] === "'" || $trim[$i] === '"') { - $string++; + if ($trim[$i] === "'") { + if ($stringOpened === '') { + $stringOpened = "'"; + } elseif ($stringOpened === "'") { + $stringOpened = ''; + } } - if (($string % 2 === 0) && ($trim[$i] === "(")) { + if ($trim[$i] === '"') { + if ($stringOpened === '') { + $stringOpened = '"'; + } elseif ($stringOpened === '"') { + $stringOpened = ''; + } + } + + if (($stringOpened === '') && ($trim[$i] === '(')) { $parenthesis++; } - if (($string % 2 === 0) && ($trim[$i] === ")")) { + if (($stringOpened === '') && ($trim[$i] === ')')) { if ($parenthesis == $parenthesisRemoved) { - $trim[$i] = " "; + $trim[$i] = ' '; $parenthesisRemoved--; } $parenthesis--; @@ -127,11 +225,11 @@ abstract class AbstractProcessor { protected function getVariableType($expression) { // $expression must contain only upper-case characters - if ($expression[1] !== "@") { + if ($expression[1] !== '@') { return ExpressionType::USER_VARIABLE; } - $type = substr($expression, 2, strpos($expression, ".", 2)); + $type = substr($expression, 2, strpos($expression, '.', 2)); switch ($type) { case 'GLOBAL': @@ -149,16 +247,16 @@ abstract class AbstractProcessor { } protected function isCommaToken($token) { - return (trim($token) === ","); + return (trim($token) === ','); } protected function isWhitespaceToken($token) { - return (trim($token) === ""); + return (trim($token) === ''); } protected function isCommentToken($token) { return isset($token[0]) && isset($token[1]) - && (($token[0] === '-' && $token[1] === '-') || ($token[0] === '/' && $token[1] === '*')); + && (($token[0] === '-' && $token[1] === '-') || ($token[0] === '/' && $token[1] === '*')); } protected function isColumnReference($out) { @@ -177,6 +275,10 @@ abstract class AbstractProcessor { return (isset($out['expr_type']) && $out['expr_type'] === ExpressionType::AGGREGATE_FUNCTION); } + protected function isCustomFunction($out) { + return (isset($out['expr_type']) && $out['expr_type'] === ExpressionType::CUSTOM_FUNCTION); + } + protected function isFunction($out) { return (isset($out['expr_type']) && $out['expr_type'] === ExpressionType::SIMPLE_FUNCTION); } @@ -193,21 +295,36 @@ abstract class AbstractProcessor { return (isset($out['expr_type']) && $out['expr_type'] === ExpressionType::SUBQUERY); } + protected function isComment($out) { + return (isset($out['expr_type']) && $out['expr_type'] === ExpressionType::COMMENT); + } + + public function processComment($expression) { + $result = array(); + $result['expr_type'] = ExpressionType::COMMENT; + $result['value'] = $expression; + return $result; + } + /** * translates an array of objects into an associative array */ public function toArray($tokenList) { $expr = array(); foreach ($tokenList as $token) { - $expr[] = $token->toArray(); + if ($token instanceof \PHPSQLParser\utils\ExpressionToken) { + $expr[] = $token->toArray(); + } else { + $expr[] = $token; + } } - return (empty($expr) ? false : $expr); + return $expr; } protected function array_insert_after($array, $key, $entry) { $idx = array_search($key, array_keys($array)); $array = array_slice($array, 0, $idx + 1, true) + $entry - + array_slice($array, $idx + 1, count($array) - 1, true); + + array_slice($array, $idx + 1, count($array) - 1, true); return $array; } } diff --git a/tools/parser_sql/processors/BracketProcessor.php b/tools/parser_sql/processors/BracketProcessor.php new file mode 100644 index 000000000..eb0922528 --- /dev/null +++ b/tools/parser_sql/processors/BracketProcessor.php @@ -0,0 +1,100 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class processes the parentheses around the statement. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class BracketProcessor extends AbstractProcessor { + + protected function processTopLevel($sql) { + $processor = new DefaultProcessor($this->options); + return $processor->process($sql); + } + + public function process($tokens) { + $token = $this->removeParenthesisFromStart($tokens[0]); + $subtree = $this->processTopLevel($token); + + $remainingExpressions = $this->getRemainingNotBracketExpression($subtree); + + if (isset($subtree['BRACKET'])) { + $subtree = $subtree['BRACKET']; + } + + if (isset($subtree['SELECT'])) { + $subtree = array( + array('expr_type' => ExpressionType::QUERY, 'base_expr' => $token, 'sub_tree' => $subtree)); + } + + return array( + array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => trim($tokens[0]), + 'sub_tree' => $subtree, 'remaining_expressions' => $remainingExpressions)); + } + + private function getRemainingNotBracketExpression($subtree) + { + // https://github.com/greenlion/PHP-SQL-Parser/issues/279 + // https://github.com/sinri/PHP-SQL-Parser/commit/eac592a0e19f1df6f420af3777a6d5504837faa7 + // as there is no pull request for 279 by the user. His solution works and tested. + if (empty($subtree)) $subtree = array();// as a fix by Sinri 20180528 + $remainingExpressions = array(); + $ignoredKeys = array('BRACKET', 'SELECT', 'FROM'); + $subtreeKeys = array_keys($subtree); + + foreach($subtreeKeys as $key) { + if(!in_array($key, $ignoredKeys)) { + $remainingExpressions[$key] = $subtree[$key]; + } + } + + return $remainingExpressions; + } + +} + +?> diff --git a/tools/parser_sql/processors/ColumnDefinitionProcessor.php b/tools/parser_sql/processors/ColumnDefinitionProcessor.php index d20e68d29..4cd162aef 100644 --- a/tools/parser_sql/processors/ColumnDefinitionProcessor.php +++ b/tools/parser_sql/processors/ColumnDefinitionProcessor.php @@ -30,10 +30,8 @@ * DAMAGE. */ -require_once dirname(__FILE__) . '/AbstractProcessor.php'; -require_once dirname(__FILE__) . '/ReferenceDefinitionProcessor.php'; -require_once dirname(__FILE__) . '/ExpressionListProcessor.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; /** * @@ -45,17 +43,20 @@ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; class ColumnDefinitionProcessor extends AbstractProcessor { protected function processExpressionList($parsed) { - $processor = new ExpressionListProcessor(); - return $processor->process($parsed); + $processor = new ExpressionListProcessor($this->options); + $expr = $this->removeParenthesisFromStart($parsed); + $expr = $this->splitSQLIntoTokens($expr); + $expr = $this->removeComma($expr); + return $processor->process($expr); } - + protected function processReferenceDefinition($parsed) { - $processor = new ReferenceDefinitionProcessor(); + $processor = new ReferenceDefinitionProcessor($this->options); return $processor->process($parsed); } - + protected function removeComma($tokens) { - $res = array(); + $res = array(); foreach ($tokens as $token) { if (trim($token) !== ',') { $res[] = $token; @@ -63,7 +64,7 @@ class ColumnDefinitionProcessor extends AbstractProcessor { } return $res; } - + protected function buildColDef($expr, $base_expr, $options, $refs, $key) { $expr = array('expr_type' => ExpressionType::COLUMN_TYPE, 'base_expr' => $base_expr, 'sub_tree' => $expr); @@ -134,24 +135,32 @@ class ColumnDefinitionProcessor extends AbstractProcessor { continue 2; case 'UNSIGNED': - $last = array_pop($expr); - $last['unsigned'] = true; - $expr[] = $last; + foreach (array_reverse(array_keys($expr)) as $i) { + if (isset($expr[$i]['expr_type']) && (ExpressionType::DATA_TYPE === $expr[$i]['expr_type'])) { + $expr[$i]['unsigned'] = true; + break; + } + } + $options['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); continue 2; case 'ZEROFILL': $last = array_pop($expr); $last['zerofill'] = true; $expr[] = $last; + $options['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); continue 2; case 'BIT': case 'TINYBIT': + case 'TINYINT': case 'SMALLINT': case 'MEDIUMINT': case 'INT': case 'INTEGER': case 'BIGINT': + case 'BOOL': + case 'BOOLEAN': $expr[] = array('expr_type' => ExpressionType::DATA_TYPE, 'base_expr' => $trim, 'unsigned' => false, 'zerofill' => false, 'length' => false); $currCategory = 'SINGLE_PARAM_PARENTHESIS'; @@ -194,11 +203,16 @@ class ColumnDefinitionProcessor extends AbstractProcessor { $prevCategory = $upper; continue 2; + case 'YEAR': + $expr[] = array('expr_type' => ExpressionType::DATA_TYPE, 'base_expr' => $trim, 'length' => false); + $currCategory = 'SINGLE_PARAM_PARENTHESIS'; + $prevCategory = $upper; + continue 2; + case 'DATE': case 'TIME': case 'TIMESTAMP': case 'DATETIME': - case 'YEAR': case 'TINYBLOB': case 'BLOB': case 'MEDIUMBLOB': @@ -217,7 +231,6 @@ class ColumnDefinitionProcessor extends AbstractProcessor { continue 2; case 'ENUM': - case 'SET': $currCategory = 'MULTIPLE_PARAM_PARENTHESIS'; $prevCategory = 'TEXT'; $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim, 'sub_tree' => false); @@ -238,40 +251,24 @@ class ColumnDefinitionProcessor extends AbstractProcessor { continue 2; case 'CHARACTER': - if ($prevCategory === 'TEXT') { - $parsed = array('expr_type' => ExpressionType::DATA_TYPE, 'base_expr' => $trim); - $expr[] = array('expr_type' => ExpressionType::CHARSET, 'base_expr' => substr($base_expr, 0, -1), - 'sub_tree' => $parsed); - $base_expr = $token; - $currCategory = 'CHARSET'; - continue 2; - } - // else ? - break; + $currCategory = 'CHARSET'; + $options['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); + continue 2; case 'SET': - if ($currCategory === 'CHARSET') { - // TODO: is it necessary to set special properties like the name or collation? - $parsed = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); - $last = array_pop($expr); - $last['sub_tree'][] = $parsed; - $expr[] = $last; - continue 2; - } - // else ? - break; + if ($currCategory == 'CHARSET') { + $options['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); + } else { + $currCategory = 'MULTIPLE_PARAM_PARENTHESIS'; + $prevCategory = 'TEXT'; + $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim, 'sub_tree' => false); + } + continue 2; case 'COLLATE': - if ($prevCategory === 'TEXT') { - $parsed = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); - $expr[] = array('expr_type' => ExpressionType::COLLATE, 'base_expr' => substr($base_expr, 0, -1), - 'sub_tree' => $parsed); - $base_expr = $token; - $currCategory = 'COLLATION'; - continue 2; - } - // else ? - break; + $currCategory = $upper; + $options['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); + continue 2; case 'NOT': case 'NULL': @@ -361,32 +358,24 @@ class ColumnDefinitionProcessor extends AbstractProcessor { case 'COLLATE': // this is the collation name - $parsed = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $trim); - $last = array_pop($expr); - $last['sub_tree'][] = $parsed; - $t = $base_expr; - $base_expr = $last['base_expr'] . $base_expr; - $last['base_expr'] = $t; + $options['sub_tree'][] = array('expr_type' => ExpressionType::COLLATE, 'base_expr' => $trim); + $options['collate'] = $trim; $currCategory = $prevCategory; break; case 'CHARSET': // this is the character set name - $parsed = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $trim); - $last = array_pop($expr); - $last['sub_tree'][] = $parsed; - $t = $base_expr; - $base_expr = $last['base_expr'] . $base_expr; - $last['base_expr'] = $t; + $options['sub_tree'][] = array('expr_type' => ExpressionType::CHARSET, 'base_expr' => $trim); + $options['charset'] = $trim; $currCategory = $prevCategory; - break; + break; case 'SINGLE_PARAM_PARENTHESIS': $parsed = $this->removeParenthesisFromStart($trim); $parsed = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => trim($parsed)); $last = array_pop($expr); $last['length'] = $parsed['base_expr']; - + $expr[] = $last; $expr[] = array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $trim, 'sub_tree' => array($parsed)); @@ -395,17 +384,12 @@ class ColumnDefinitionProcessor extends AbstractProcessor { case 'TWO_PARAM_PARENTHESIS': // maximum of two parameters - $parsed = $this->removeParenthesisFromStart($trim); - $parsed = $this->splitSQLIntoTokens($parsed); - $parsed = $this->removeComma($parsed); - $parsed = $this->processExpressionList($parsed); - - // TODO: check that + $parsed = $this->processExpressionList($trim); $last = array_pop($expr); $last['length'] = $parsed[0]['base_expr']; $last['decimals'] = isset($parsed[1]) ? $parsed[1]['base_expr'] : false; - + $expr[] = $last; $expr[] = array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $trim, 'sub_tree' => $parsed); @@ -414,14 +398,17 @@ class ColumnDefinitionProcessor extends AbstractProcessor { case 'MULTIPLE_PARAM_PARENTHESIS': // some parameters - $parsed = $this->removeParenthesisFromStart($trim); - $parsed = $this->splitSQLIntoTokens($parsed); - $parsed = $this->removeComma($parsed); - $this->processExpressionList($parsed); + $parsed = $this->processExpressionList($trim); $last = array_pop($expr); - $last['sub_tree'] = array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $trim, - 'sub_tree' => $parsed); + $subTree = array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $trim, + 'sub_tree' => $parsed); + + if ($this->options->getConsistentSubtrees()) { + $subTree = array($subTree); + } + + $last['sub_tree'] = $subTree; $expr[] = $last; $currCategory = $prevCategory; break; diff --git a/tools/parser_sql/processors/ColumnListProcessor.php b/tools/parser_sql/processors/ColumnListProcessor.php index 9b316c380..07859a9a8 100644 --- a/tools/parser_sql/processors/ColumnListProcessor.php +++ b/tools/parser_sql/processors/ColumnListProcessor.php @@ -30,8 +30,8 @@ * DAMAGE. */ -require_once dirname(__FILE__) . '/AbstractProcessor.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; /** * diff --git a/tools/parser_sql/processors/CreateDefinitionProcessor.php b/tools/parser_sql/processors/CreateDefinitionProcessor.php index b98660048..3ffa0b053 100644 --- a/tools/parser_sql/processors/CreateDefinitionProcessor.php +++ b/tools/parser_sql/processors/CreateDefinitionProcessor.php @@ -4,54 +4,80 @@ * * This file implements the processor for the create definition within the TABLE statements. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once dirname(__FILE__) . '/AbstractProcessor.php'; -require_once dirname(__FILE__) . '/ColumnDefinitionProcessor.php'; -require_once dirname(__FILE__) . '/IndexColumnListProcessor.php'; -require_once dirname(__FILE__) . '/ReferenceDefinitionProcessor.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; /** - * * This class processes the create definition of the TABLE statements. * - * @author arothe + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class CreateDefinitionProcessor extends AbstractProcessor { + protected function processExpressionList($parsed) { + $processor = new ExpressionListProcessor($this->options); + return $processor->process($parsed); + } + + protected function processIndexColumnList($parsed) { + $processor = new IndexColumnListProcessor($this->options); + return $processor->process($parsed); + } + + protected function processColumnDefinition($parsed) { + $processor = new ColumnDefinitionProcessor($this->options); + return $processor->process($parsed); + } + + protected function processReferenceDefinition($parsed) { + $processor = new ReferenceDefinitionProcessor($this->options); + return $processor->process($parsed); + } + protected function correctExpressionType(&$expr) { $type = ExpressionType::EXPRESSION; if (!isset($expr[0]) || !isset($expr[0]['expr_type'])) { return $type; } - # replace the constraint type with a more descriptive one + // replace the constraint type with a more descriptive one switch ($expr[0]['expr_type']) { case ExpressionType::CONSTRAINT: @@ -74,9 +100,9 @@ class CreateDefinitionProcessor extends AbstractProcessor { public function process($tokens) { - $base_expr = ""; - $prevCategory = ""; - $currCategory = ""; + $base_expr = ''; + $prevCategory = ''; + $currCategory = ''; $expr = array(); $result = array(); $skip = 0; @@ -91,7 +117,7 @@ class CreateDefinitionProcessor extends AbstractProcessor { continue; } - if ($trim === "") { + if ($trim === '') { continue; } @@ -110,36 +136,36 @@ class CreateDefinitionProcessor extends AbstractProcessor { continue 2; case 'FOREIGN': - if ($prevCategory === "" || $prevCategory === "CONSTRAINT") { + if ($prevCategory === '' || $prevCategory === 'CONSTRAINT') { $expr[] = array('expr_type' => ExpressionType::FOREIGN_KEY, 'base_expr' => $trim); $currCategory = $upper; continue 2; } - # else ? + // else ? break; case 'PRIMARY': - if ($prevCategory === "" || $prevCategory === "CONSTRAINT") { - # next one is KEY + if ($prevCategory === '' || $prevCategory === 'CONSTRAINT') { + // next one is KEY $expr[] = array('expr_type' => ExpressionType::PRIMARY_KEY, 'base_expr' => $trim); $currCategory = $upper; continue 2; } - # else ? + // else ? break; case 'UNIQUE': - if ($prevCategory === "" || $prevCategory === "CONSTRAINT") { - # next one is KEY + if ($prevCategory === '' || $prevCategory === 'CONSTRAINT' || $prevCategory === 'INDEX_COL_LIST') { + // next one is KEY $expr[] = array('expr_type' => ExpressionType::UNIQUE_IDX, 'base_expr' => $trim); $currCategory = $upper; continue 2; } - # else ? + // else ? break; case 'KEY': - # the next one is an index name + // the next one is an index name if ($currCategory === 'PRIMARY' || $currCategory === 'FOREIGN' || $currCategory === 'UNIQUE') { $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); continue 2; @@ -173,7 +199,7 @@ class CreateDefinitionProcessor extends AbstractProcessor { continue 2; case 'WITH': - # starts an index option + // starts an index option if ($currCategory === 'INDEX_COL_LIST') { $option = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr[] = array('expr_type' => ExpressionType::INDEX_PARSER, @@ -186,7 +212,7 @@ class CreateDefinitionProcessor extends AbstractProcessor { break; case 'KEY_BLOCK_SIZE': - # starts an index option + // starts an index option if ($currCategory === 'INDEX_COL_LIST') { $option = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr[] = array('expr_type' => ExpressionType::INDEX_SIZE, @@ -199,7 +225,7 @@ class CreateDefinitionProcessor extends AbstractProcessor { break; case 'USING': - # starts an index option + // starts an index option if ($currCategory === 'INDEX_COL_LIST' || $currCategory === 'PRIMARY') { $option = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr[] = array('base_expr' => substr($base_expr, 0, -strlen($token)), 'trim' => $trim, @@ -208,18 +234,18 @@ class CreateDefinitionProcessor extends AbstractProcessor { $currCategory = 'INDEX_TYPE'; continue 2; } - # else ? + // else ? break; case 'REFERENCES': if ($currCategory === 'INDEX_COL_LIST' && $prevCategory === 'FOREIGN') { - $processor = new ReferenceDefinitionProcessor(); - $refs = $processor->process(array_slice($tokens, $k - 1, null, true)); + $refs = $this->processReferenceDefinition(array_slice($tokens, $k - 1, null, true)); $skip = $refs['till'] - $k; unset($refs['till']); $expr[] = $refs; $currCategory = $upper; } + // else ? break; case 'BTREE': @@ -231,16 +257,16 @@ class CreateDefinitionProcessor extends AbstractProcessor { 'sub_tree' => $last['sub_tree']); $base_expr = $last['base_expr'] . $base_expr; - # FIXME: it could be wrong for index_type within index_option + // FIXME: it could be wrong for index_type within index_option $currCategory = $last['category']; continue 2; } - #else + // else ? break; case '=': if ($currCategory === 'INDEX_SIZE') { - # the optional character between KEY_BLOCK_SIZE and the numeric constant + // the optional character between KEY_BLOCK_SIZE and the numeric constant $last = array_pop($expr); $last['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr[] = $last; @@ -255,16 +281,16 @@ class CreateDefinitionProcessor extends AbstractProcessor { $expr[] = $last; continue 2; } - # else? + // else ? break; case ',': - # this starts the next definition + // this starts the next definition $type = $this->correctExpressionType($expr); $result['create-def'][] = array('expr_type' => $type, 'base_expr' => trim(substr($base_expr, 0, -strlen($token))), 'sub_tree' => $expr); - $base_expr = ""; + $base_expr = ''; $expr = array(); break; @@ -272,36 +298,34 @@ class CreateDefinitionProcessor extends AbstractProcessor { switch ($currCategory) { case 'LIKE': - # this is the tablename after LIKE + // this is the tablename after LIKE $expr[] = array('expr_type' => ExpressionType::TABLE, 'table' => $trim, 'base_expr' => $trim, 'no_quotes' => $this->revokeQuotation($trim)); break; case 'PRIMARY': if ($upper[0] === '(' && substr($upper, -1) === ')') { - # the column list - $processor = new IndexColumnListProcessor(); - $cols = $processor->process($this->removeParenthesisFromStart($trim)); + // the column list + $cols = $this->processIndexColumnList($this->removeParenthesisFromStart($trim)); $expr[] = array('expr_type' => ExpressionType::COLUMN_LIST, 'base_expr' => $trim, 'sub_tree' => $cols); $prevCategory = $currCategory; - $currCategory = "INDEX_COL_LIST"; + $currCategory = 'INDEX_COL_LIST'; continue 3; } - # else? + // else? break; case 'FOREIGN': if ($upper[0] === '(' && substr($upper, -1) === ')') { - $processor = new IndexColumnListProcessor(); - $cols = $processor->process($this->removeParenthesisFromStart($trim)); + $cols = $this->processIndexColumnList($this->removeParenthesisFromStart($trim)); $expr[] = array('expr_type' => ExpressionType::COLUMN_LIST, 'base_expr' => $trim, 'sub_tree' => $cols); $prevCategory = $currCategory; - $currCategory = "INDEX_COL_LIST"; + $currCategory = 'INDEX_COL_LIST'; continue 3; } - # index name + // index name $expr[] = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $trim); continue 3; @@ -309,20 +333,19 @@ class CreateDefinitionProcessor extends AbstractProcessor { case 'UNIQUE': case 'INDEX': if ($upper[0] === '(' && substr($upper, -1) === ')') { - $processor = new IndexColumnListProcessor(); - $cols = $processor->process($this->removeParenthesisFromStart($trim)); + $cols = $this->processIndexColumnList($this->removeParenthesisFromStart($trim)); $expr[] = array('expr_type' => ExpressionType::COLUMN_LIST, 'base_expr' => $trim, 'sub_tree' => $cols); $prevCategory = $currCategory; - $currCategory = "INDEX_COL_LIST"; + $currCategory = 'INDEX_COL_LIST'; continue 3; } - # index name + // index name $expr[] = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $trim); continue 3; case 'CONSTRAINT': - # constraint name + // constraint name $last = array_pop($expr); $last['base_expr'] = $base_expr; $last['sub_tree'] = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $trim); @@ -330,7 +353,7 @@ class CreateDefinitionProcessor extends AbstractProcessor { continue 3; case 'INDEX_PARSER': - # index parser name + // index parser name $last = array_pop($expr); $last['sub_tree'][] = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $trim); $expr[] = array('expr_type' => ExpressionType::INDEX_PARSER, 'base_expr' => $base_expr, @@ -340,7 +363,7 @@ class CreateDefinitionProcessor extends AbstractProcessor { continue 3; case 'INDEX_SIZE': - # index key block size numeric constant + // index key block size numeric constant $last = array_pop($expr); $last['sub_tree'][] = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $trim); $expr[] = array('expr_type' => ExpressionType::INDEX_SIZE, 'base_expr' => $base_expr, @@ -351,28 +374,26 @@ class CreateDefinitionProcessor extends AbstractProcessor { case 'CHECK': if ($upper[0] === '(' && substr($upper, -1) === ')') { - $processor = new ExpressionListProcessor(); - $unparsed = $this->splitSQLIntoTokens($this->removeParenthesisFromStart($trim)); - $parsed = $processor->process($unparsed); + $parsed = $this->splitSQLIntoTokens($this->removeParenthesisFromStart($trim)); + $parsed = $this->processExpressionList($parsed); $expr[] = array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $trim, 'sub_tree' => $parsed); } - # else? + // else? break; case '': - # if the currCategory is empty, we have an unknown token, - # which is a column reference + // if the currCategory is empty, we have an unknown token, + // which is a column reference $expr[] = array('expr_type' => ExpressionType::COLREF, 'base_expr' => $trim, 'no_quotes' => $this->revokeQuotation($trim)); $currCategory = 'COLUMN_NAME'; continue 3; case 'COLUMN_NAME': - # the column-definition - # it stops on a comma or on a parenthesis - $processor = new ColumnDefinitionProcessor(); - $parsed = $processor->process(array_slice($tokens, $k, null, true), $expr); + // the column-definition + // it stops on a comma or on a parenthesis + $parsed = $this->processColumnDefinition(array_slice($tokens, $k, null, true)); $skip = $parsed['till'] - $k; unset($parsed['till']); $expr[] = $parsed; @@ -380,7 +401,7 @@ class CreateDefinitionProcessor extends AbstractProcessor { break; default: - # ? + // ? break; } break; @@ -394,4 +415,4 @@ class CreateDefinitionProcessor extends AbstractProcessor { return $result; } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/CreateProcessor.php b/tools/parser_sql/processors/CreateProcessor.php index f2f5edbf5..ebdb7ee8d 100644 --- a/tools/parser_sql/processors/CreateProcessor.php +++ b/tools/parser_sql/processors/CreateProcessor.php @@ -2,81 +2,112 @@ /** * CreateProcessor.php * - * This file implements the processor for the CREATE TABLE statements. + * This file implements the processor for the CREATE statements. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once dirname(__FILE__) . '/AbstractProcessor.php'; -require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; /** - * * This class processes the CREATE statements. - * - * @author arothe - * + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class CreateProcessor extends AbstractProcessor { public function process($tokens) { - $result = array(); + $result = $expr = array(); $base_expr = ""; foreach ($tokens as $token) { - $trim = strtoupper(trim($token)); + + $trim = trim($token); $base_expr .= $token; if ($trim === "") { continue; } - switch ($trim) { + $upper = strtoupper($trim); + switch ($upper) { case 'TEMPORARY': + // CREATE TEMPORARY TABLE $result['expr_type'] = ExpressionType::TEMPORARY_TABLE; $result['not-exists'] = false; $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); break; case 'TABLE': + // CREATE TABLE $result['expr_type'] = ExpressionType::TABLE; $result['not-exists'] = false; $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); break; + case 'INDEX': + // CREATE INDEX + $result['expr_type'] = ExpressionType::INDEX; + $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); + break; + + case 'UNIQUE': + case 'FULLTEXT': + case 'SPATIAL': + // options of CREATE INDEX + $result['base_expr'] = $result['expr_type'] = false; + $result['constraint'] = $upper; + $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); + break; + case 'IF': + // option of CREATE TABLE $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); break; case 'NOT': + // option of CREATE TABLE $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); break; case 'EXISTS': + // option of CREATE TABLE $result['not-exists'] = true; $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); break; diff --git a/tools/parser_sql/processors/DefaultProcessor.php b/tools/parser_sql/processors/DefaultProcessor.php index 163f966a0..b90ea9a0e 100644 --- a/tools/parser_sql/processors/DefaultProcessor.php +++ b/tools/parser_sql/processors/DefaultProcessor.php @@ -4,62 +4,85 @@ * * This file implements the processor the unparsed sql string given by the user. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); -require_once(dirname(__FILE__) . '/UnionProcessor.php'); -require_once(dirname(__FILE__) . '/SQLProcessor.php'); +namespace PHPSQLParser\processors; /** - * * This class processes the incoming sql string. - * - * @author arothe - * + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class DefaultProcessor extends AbstractProcessor { + protected function isUnion($tokens) { + return UnionProcessor::isUnion($tokens); + } + + protected function processUnion($tokens) { + // this is the highest level lexical analysis. This is the part of the + // code which finds UNION and UNION ALL query parts + $processor = new UnionProcessor($this->options); + return $processor->process($tokens); + } + + protected function processSQL($tokens) { + $processor = new SQLProcessor($this->options); + return $processor->process($tokens); + } + public function process($sql) { $inputArray = $this->splitSQLIntoTokens($sql); - - // this is the highest level lexical analysis. This is the part of the - // code which finds UNION and UNION ALL query parts - $processor = new UnionProcessor(); - $queries = $processor->process($inputArray); + $queries = $this->processUnion($inputArray); // If there was no UNION or UNION ALL in the query, then the query is // stored at $queries[0]. - if (!$processor->isUnion($queries)) { - $processor = new SQLProcessor(); - $queries = $processor->process($queries[0]); + if (!empty($queries) && !$this->isUnion($queries)) { + $queries = $this->processSQL($queries[0]); } return $queries; } + + public function revokeQuotation($sql) { + return parent::revokeQuotation($sql); + } } -?> \ No newline at end of file + +?> diff --git a/tools/parser_sql/processors/DeleteProcessor.php b/tools/parser_sql/processors/DeleteProcessor.php index 6484b3720..652c3e181 100644 --- a/tools/parser_sql/processors/DeleteProcessor.php +++ b/tools/parser_sql/processors/DeleteProcessor.php @@ -2,42 +2,52 @@ /** * DeleteProcessor.php * - * This file implements the processor for the DELETE statements. + * Processes the DELETE statement parts and splits multi-table deletes. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); +namespace PHPSQLParser\processors; /** - * * This class processes the DELETE statements. - * - * @author arothe - * + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class DeleteProcessor extends AbstractProcessor { @@ -46,19 +56,29 @@ class DeleteProcessor extends AbstractProcessor { $del = $tokens['DELETE']; foreach ($tokens['DELETE'] as $expression) { - if ($expression !== 'DELETE' && trim($expression, ' .*') !== "" && !$this->isCommaToken($expression)) { - $tables[] = trim($expression, '.* '); + if (strtoupper($expression) !== 'DELETE' && trim($expression, " \t\n\r\0\x0B.*") !== "" + && !$this->isCommaToken($expression)) { + $tables[] = trim($expression, " \t\n\r\0\x0B.*"); } } - if (empty($tables)) { + if (empty($tables) && isset($tokens['USING'])) { foreach ($tokens['FROM'] as $table) { - $tables[] = $table['table']; + $tables[] = trim($table['table'], " \t\n\r\0\x0B.*"); } + $tokens['FROM'] = $tokens['USING']; + unset($tokens['USING']); } - $tokens['DELETE'] = array('TABLES' => $tables); + $options = array(); + if (isset($tokens['OPTIONS'])) { + $options = $tokens['OPTIONS']; + unset($tokens['OPTIONS']); + } + + $tokens['DELETE'] = array('options' => (empty($options) ? false : $options), + 'tables' => (empty($tables) ? false : $tables)); return $tokens; } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/DescProcessor.php b/tools/parser_sql/processors/DescProcessor.php index 1f89ccf70..776c5e3f3 100644 --- a/tools/parser_sql/processors/DescProcessor.php +++ b/tools/parser_sql/processors/DescProcessor.php @@ -30,7 +30,7 @@ * DAMAGE. */ -require_once(dirname(__FILE__) . '/ExplainProcessor.php'); +namespace PHPSQLParser\processors; /** * @@ -45,4 +45,4 @@ class DescProcessor extends ExplainProcessor { return parent::isStatement($keys, $needle); } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/DescribeProcessor.php b/tools/parser_sql/processors/DescribeProcessor.php index f162fbc5b..c7cf217d0 100644 --- a/tools/parser_sql/processors/DescribeProcessor.php +++ b/tools/parser_sql/processors/DescribeProcessor.php @@ -1,43 +1,52 @@ + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/ExplainProcessor.php'); +namespace PHPSQLParser\processors; /** - * * This class processes the DESCRIBE statements. - * - * @author arothe - * + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class DescribeProcessor extends ExplainProcessor { @@ -45,4 +54,5 @@ class DescribeProcessor extends ExplainProcessor { return parent::isStatement($keys, $needle); } } -?> \ No newline at end of file + +?> diff --git a/tools/parser_sql/processors/DropProcessor.php b/tools/parser_sql/processors/DropProcessor.php index 9720f69ea..131404c4a 100644 --- a/tools/parser_sql/processors/DropProcessor.php +++ b/tools/parser_sql/processors/DropProcessor.php @@ -4,105 +4,139 @@ * * This file implements the processor for the DROP statements. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/../utils/ExpressionToken.php'); -require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; /** - * * This class processes the DROP statements. - * - * @author arothe - * + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class DropProcessor extends AbstractProcessor { - // TODO: we should enhance it to get the positions for the IF EXISTS keywords - // look into the CreateProcessor to get an idea. public function process($tokenList) { - $skip = 0; - $warning = true; - $base_expr = ""; - $expr_type = false; + $exists = false; + $base_expr = ''; + $objectType = ''; + $subTree = array(); $option = false; - $resultList = array(); - foreach ($tokenList as $k => $v) { - $token = new ExpressionToken($k, $v); + foreach ($tokenList as $token) { + $base_expr .= $token; + $trim = trim($token); - if ($token->isWhitespaceToken()) { + if ($trim === '') { continue; } - if ($skip > 0) { - $skip --; - continue; - } - - switch ($token->getUpper()) { + $upper = strtoupper($trim); + switch ($upper) { case 'VIEW': case 'SCHEMA': case 'DATABASE': case 'TABLE': - $expr_type = strtolower($token->getTrim()); + if ($objectType === '') { + $objectType = constant('PHPSQLParser\utils\ExpressionType::' . $upper); + } + $base_expr = ''; break; - + case 'INDEX': + if ( $objectType === '' ) { + $objectType = constant( 'PHPSQLParser\utils\ExpressionType::' . $upper ); + } + $base_expr = ''; + break; case 'IF': - $warning = false; - $skip = 1; + case 'EXISTS': + $exists = true; + $base_expr = ''; break; case 'TEMPORARY': - $expr_type = ExpressionType::TEMPORARY_TABLE; - $skip = 1; + $objectType = ExpressionType::TEMPORARY_TABLE; + $base_expr = ''; break; case 'RESTRICT': case 'CASCADE': - $option = $token->getUpper(); + $option = $upper; + if (!empty($objectList)) { + $subTree[] = array('expr_type' => ExpressionType::EXPRESSION, + 'base_expr' => trim(substr($base_expr, 0, -strlen($token))), + 'sub_tree' => $objectList); + $objectList = array(); + } + $base_expr = ''; break; case ',': - $resultList[] = array('expr_type' => $expr_type, 'base_expr' => $base_expr); - $base_expr = ""; - break; + $last = array_pop($objectList); + $last['delim'] = $trim; + $objectList[] = $last; + continue 2; default: - $base_expr .= $token->getToken(); + $object = array(); + $object['expr_type'] = $objectType; + if ($objectType === ExpressionType::TABLE || $objectType === ExpressionType::TEMPORARY_TABLE) { + $object['table'] = $trim; + $object['no_quotes'] = false; + $object['alias'] = false; + } + $object['base_expr'] = $trim; + $object['no_quotes'] = $this->revokeQuotation($trim); + $object['delim'] = false; + + $objectList[] = $object; + continue 2; } + + $subTree[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); } - if ($base_expr !== "") { - $resultList[] = array('expr_type' => $expr_type, 'base_expr' => $base_expr); + if (!empty($objectList)) { + $subTree[] = array('expr_type' => ExpressionType::EXPRESSION, 'base_expr' => trim($base_expr), + 'sub_tree' => $objectList); } - return array('option' => $option, 'warning' => $warning, 'object_list' => $resultList); + return array('expr_type' => $objectType, 'option' => $option, 'if-exists' => $exists, 'sub_tree' => $subTree); } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/DuplicateProcessor.php b/tools/parser_sql/processors/DuplicateProcessor.php index b4876ba25..f3578da6c 100644 --- a/tools/parser_sql/processors/DuplicateProcessor.php +++ b/tools/parser_sql/processors/DuplicateProcessor.php @@ -30,20 +30,20 @@ * DAMAGE. */ -require_once(dirname(__FILE__) . '/SetProcessor.php'); +namespace PHPSQLParser\processors; /** - * + * * This class processes the DUPLICATE statements. - * + * * @author arothe - * + * */ class DuplicateProcessor extends SetProcessor { public function process($tokens, $isUpdate = false) { - return parent::process($tokens, false); + return parent::process($tokens, $isUpdate); } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/ExplainProcessor.php b/tools/parser_sql/processors/ExplainProcessor.php index 59fcb526a..bc9d7f53f 100644 --- a/tools/parser_sql/processors/ExplainProcessor.php +++ b/tools/parser_sql/processors/ExplainProcessor.php @@ -4,41 +4,50 @@ * * This file implements the processor for the EXPLAIN statements. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); -require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; /** - * * This class processes the EXPLAIN statements. - * - * @author arothe - * + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class ExplainProcessor extends AbstractProcessor { @@ -121,12 +130,14 @@ class ExplainProcessor extends AbstractProcessor { case 'TABLENAME': $currCategory = 'WILD'; - $expr[] = array('expr_type' => ExpressionType::COLREF, 'base_expr' => $trim); + $expr[] = array('expr_type' => ExpressionType::COLREF, 'base_expr' => $trim, + 'no_quotes' => $this->revokeQuotation($trim)); break; case '': $currCategory = 'TABLENAME'; - $expr[] = array('expr_type' => ExpressionType::TABLE, 'base_expr' => $trim); + $expr[] = array('expr_type' => ExpressionType::TABLE, 'table' => $trim, + 'no_quotes' => $this->revokeQuotation($trim), 'alias' => false, 'base_expr' => $trim); break; default: @@ -136,4 +147,5 @@ class ExplainProcessor extends AbstractProcessor { return empty($expr) ? null : $expr; } } + ?> diff --git a/tools/parser_sql/processors/ExpressionListProcessor.php b/tools/parser_sql/processors/ExpressionListProcessor.php index 7f4defa64..b0353f76e 100644 --- a/tools/parser_sql/processors/ExpressionListProcessor.php +++ b/tools/parser_sql/processors/ExpressionListProcessor.php @@ -4,43 +4,52 @@ * * This file implements the processor for expression lists. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); -require_once(dirname(__FILE__) . '/DefaultProcessor.php'); -require_once(dirname(__FILE__) . '/../utils/ExpressionToken.php'); -require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; +use PHPSQLParser\utils\ExpressionToken; +use PHPSQLParser\utils\PHPSQLParserConstants; /** - * * This class processes expression lists. - * - * @author arothe - * + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class ExpressionListProcessor extends AbstractProcessor { @@ -51,6 +60,12 @@ class ExpressionListProcessor extends AbstractProcessor { foreach ($tokens as $k => $v) { + + if ($this->isCommentToken($v)) { + $resultList[] = parent::processComment($v); + continue; + } + $curr = new ExpressionToken($k, $v); if ($curr->isWhitespaceToken()) { @@ -66,7 +81,7 @@ class ExpressionListProcessor extends AbstractProcessor { /* is it a subquery? */ if ($curr->isSubQueryToken()) { - $processor = new DefaultProcessor(); + $processor = new DefaultProcessor($this->options); $curr->setSubTree($processor->process($this->removeParenthesisFromStart($curr->getTrim()))); $curr->setTokenType(ExpressionType::SUBQUERY); @@ -121,7 +136,8 @@ class ExpressionListProcessor extends AbstractProcessor { $curr->setTokenType(ExpressionType::MATCH_ARGUMENTS); $prev->setTokenType(ExpressionType::SIMPLE_FUNCTION); - } elseif ($prev->isColumnReference() || $prev->isFunction() || $prev->isAggregateFunction()) { + } elseif ($prev->isColumnReference() || $prev->isFunction() || $prev->isAggregateFunction() + || $prev->isCustomFunction()) { // if we have a colref followed by a parenthesis pair, // it isn't a colref, it is a user-function @@ -152,7 +168,9 @@ class ExpressionListProcessor extends AbstractProcessor { } if (!$curr->getSubTree()) { - $curr->setSubTree($localExprList); + if (!empty($localExprList)) { + $curr->setSubTree($localExprList); + } } else { $tmpExprList = $curr->getSubTree(); $curr->setSubTree(array_merge($tmpExprList, $localExprList)); @@ -175,7 +193,9 @@ class ExpressionListProcessor extends AbstractProcessor { } if (!$curr->getSubTree()) { - $curr->setSubTree($localExprList); + if (!empty($localExprList)) { + $curr->setSubTree($localExprList); + } } else { $tmpExprList = $curr->getSubTree(); $curr->setSubTree(array_merge($tmpExprList, $localExprList)); @@ -183,8 +203,12 @@ class ExpressionListProcessor extends AbstractProcessor { $prev->setSubTree($curr->getSubTree()); if ($prev->isColumnReference()) { - $prev->setTokenType(ExpressionType::SIMPLE_FUNCTION); - $prev->setNoQuotes(null); + if (PHPSQLParserConstants::getInstance()->isCustomFunction($prev->getUpper())) { + $prev->setTokenType(ExpressionType::CUSTOM_FUNCTION); + } else { + $prev->setTokenType(ExpressionType::SIMPLE_FUNCTION); + } + $prev->setNoQuotes(null, null, $this->options); } array_pop($resultList); @@ -193,14 +217,20 @@ class ExpressionListProcessor extends AbstractProcessor { // we have parenthesis, but it seems to be an expression if ($curr->isUnspecified()) { + $tmpExprList = array_values($localTokenList); + $localExprList = $this->process($tmpExprList); - // TODO: the localTokenList could contain commas and further expressions, - // we must handle that like function parameters (see above)! - // this should solve issue 51 - - $curr->setSubTree($this->process($localTokenList)); $curr->setTokenType(ExpressionType::BRACKET_EXPRESSION); + if (!$curr->getSubTree()) { + if (!empty($localExprList)) { + $curr->setSubTree($localExprList); + } + } else { + $tmpExprList = $curr->getSubTree(); + $curr->setSubTree(array_merge($tmpExprList, $localExprList)); + } } + } elseif ($curr->isVariableToken()) { # a variable @@ -208,7 +238,7 @@ class ExpressionListProcessor extends AbstractProcessor { $curr->setTokenType($this->getVariableType($curr->getUpper())); $curr->setSubTree(false); - $curr->setNoQuotes(trim(trim($curr->getToken()), '@'), "`'\""); + $curr->setNoQuotes(trim(trim($curr->getToken()), '@'), "`'\"", $this->options); } else { /* it is either an operator, a colref or a constant */ @@ -227,7 +257,7 @@ class ExpressionListProcessor extends AbstractProcessor { // then * is an operator // but if the previous colref ends with a dot, the * is the all-columns-alias if (!$prev->isColumnReference() && !$prev->isConstant() && !$prev->isExpression() - && !$prev->isBracketExpression() && !$prev->isAggregateFunction() && !$prev->isVariable()) { + && !$prev->isBracketExpression() && !$prev->isAggregateFunction() && !$prev->isVariable()) { $curr->setTokenType(ExpressionType::COLREF); break; } @@ -244,7 +274,6 @@ class ExpressionListProcessor extends AbstractProcessor { case 'AND': case '&&': case 'BETWEEN': - case 'AND': case 'BINARY': case '&': case '~': @@ -289,8 +318,8 @@ class ExpressionListProcessor extends AbstractProcessor { $curr->setSubTree(false); if ($prev->isColumnReference() || $prev->isFunction() || $prev->isAggregateFunction() - || $prev->isConstant() || $prev->isSubQuery() || $prev->isExpression() - || $prev->isBracketExpression() || $prev->isVariable()) { + || $prev->isConstant() || $prev->isSubQuery() || $prev->isExpression() + || $prev->isBracketExpression() || $prev->isVariable() || $prev->isCustomFunction()) { $curr->setTokenType(ExpressionType::OPERATOR); } else { $curr->setTokenType(ExpressionType::SIGN); @@ -302,14 +331,20 @@ class ExpressionListProcessor extends AbstractProcessor { switch ($curr->getToken(0)) { case "'": - case '"': // it is a string literal $curr->setTokenType(ExpressionType::CONSTANT); break; + case '"': + if (!$this->options->getANSIQuotes()) { + // If we're not using ANSI quotes, this is a string literal. + $curr->setTokenType(ExpressionType::CONSTANT); + break; + } + // Otherwise continue to the next case case '`': // it is an escaped colum name $curr->setTokenType(ExpressionType::COLREF); - $curr->setNoQuotes($curr->getToken()); + $curr->setNoQuotes($curr->getToken(), null, $this->options); break; default: @@ -325,7 +360,7 @@ class ExpressionListProcessor extends AbstractProcessor { } } else { $curr->setTokenType(ExpressionType::COLREF); - $curr->setNoQuotes($curr->getToken()); + $curr->setNoQuotes($curr->getToken(), null, $this->options); } break; } @@ -334,48 +369,57 @@ class ExpressionListProcessor extends AbstractProcessor { /* is a reserved word? */ if (!$curr->isOperator() && !$curr->isInList() && !$curr->isFunction() && !$curr->isAggregateFunction() - && PHPSQLParserConstants::isReserved($curr->getUpper())) { + && !$curr->isCustomFunction() && PHPSQLParserConstants::getInstance()->isReserved($curr->getUpper())) { - if (PHPSQLParserConstants::isAggregateFunction($curr->getUpper())) { + $next = isset( $tokens[ $k + 1 ] ) ? new ExpressionToken( $k + 1, $tokens[ $k + 1 ] ) : new ExpressionToken(); + $isEnclosedWithinParenthesis = $next->isEnclosedWithinParenthesis(); + if ($isEnclosedWithinParenthesis && PHPSQLParserConstants::getInstance()->isCustomFunction($curr->getUpper())) { + $curr->setTokenType(ExpressionType::CUSTOM_FUNCTION); + $curr->setNoQuotes(null, null, $this->options); + + } elseif ($isEnclosedWithinParenthesis && PHPSQLParserConstants::getInstance()->isAggregateFunction($curr->getUpper())) { $curr->setTokenType(ExpressionType::AGGREGATE_FUNCTION); - $curr->setNoQuotes(null); + $curr->setNoQuotes(null, null, $this->options); } elseif ($curr->getUpper() === 'NULL') { // it is a reserved word, but we would like to set it as constant $curr->setTokenType(ExpressionType::CONSTANT); } else { - if (PHPSQLParserConstants::isParameterizedFunction($curr->getUpper())) { + if ($isEnclosedWithinParenthesis && PHPSQLParserConstants::getInstance()->isParameterizedFunction($curr->getUpper())) { // issue 60: check functions with parameters // -> colref (we check parameters later) // -> if there is no parameter, we leave the colref $curr->setTokenType(ExpressionType::COLREF); - } elseif (PHPSQLParserConstants::isFunction($curr->getUpper())) { + } elseif ($isEnclosedWithinParenthesis && PHPSQLParserConstants::getInstance()->isFunction($curr->getUpper())) { $curr->setTokenType(ExpressionType::SIMPLE_FUNCTION); - $curr->setNoQuotes(null); + $curr->setNoQuotes(null, null, $this->options); + } elseif (!$isEnclosedWithinParenthesis && PHPSQLParserConstants::getInstance()->isFunction($curr->getUpper())) { + // Colname using function name. + $curr->setTokenType(ExpressionType::COLREF); } else { $curr->setTokenType(ExpressionType::RESERVED); - $curr->setNoQuotes(null); + $curr->setNoQuotes(null, null, $this->options); } } } // issue 94, INTERVAL 1 MONTH - if ($curr->isConstant() && PHPSQLParserConstants::isParameterizedFunction($prev->getUpper())) { + if ($curr->isConstant() && PHPSQLParserConstants::getInstance()->isParameterizedFunction($prev->getUpper())) { $prev->setTokenType(ExpressionType::RESERVED); - $prev->setNoQuotes(null); + $prev->setNoQuotes(null, null, $this->options); } - if ($prev->isConstant() && PHPSQLParserConstants::isParameterizedFunction($curr->getUpper())) { + if ($prev->isConstant() && PHPSQLParserConstants::getInstance()->isParameterizedFunction($curr->getUpper())) { $curr->setTokenType(ExpressionType::RESERVED); - $curr->setNoQuotes(null); + $curr->setNoQuotes(null, null, $this->options); } if ($curr->isUnspecified()) { $curr->setTokenType(ExpressionType::EXPRESSION); - $curr->setNoQuotes(null); + $curr->setNoQuotes(null, null, $this->options); $curr->setSubTree($this->process($this->splitSQLIntoTokens($curr->getTrim()))); } @@ -386,4 +430,4 @@ class ExpressionListProcessor extends AbstractProcessor { return $this->toArray($resultList); } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/FromProcessor.php b/tools/parser_sql/processors/FromProcessor.php index d8cf0ab28..3ab97b99a 100644 --- a/tools/parser_sql/processors/FromProcessor.php +++ b/tools/parser_sql/processors/FromProcessor.php @@ -2,48 +2,73 @@ /** * FromProcessor.php * - * This file implements the processor for the FROM statements. + * This file implements the processor for the FROM statement. * - * Copyright (c) 2010-2013, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @author George Schneeloch + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); -require_once(dirname(__FILE__) . '/ExpressionListProcessor.php'); -require_once(dirname(__FILE__) . '/DefaultProcessor.php'); -require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; /** - * - * This class processes the FROM statements. - * - * @author arothe - * + * This class processes the FROM statement. + * + * @author André Rothe + * @author Marco Th. + * @author George Schneeloch + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class FromProcessor extends AbstractProcessor { + protected function processExpressionList($unparsed) { + $processor = new ExpressionListProcessor($this->options); + return $processor->process($unparsed); + } + + protected function processColumnList($unparsed) { + $processor = new ColumnListProcessor($this->options); + return $processor->process($unparsed); + } + + protected function processSQLDefault($unparsed) { + $processor = new DefaultProcessor($this->options); + return $processor->process($unparsed); + } + protected function initParseInfo($parseInfo = false) { // first init if ($parseInfo === false) { @@ -51,9 +76,9 @@ class FromProcessor extends AbstractProcessor { } // loop init return array('expression' => "", 'token_count' => 0, 'table' => "", 'no_quotes' => "", 'alias' => false, - 'join_type' => "", 'next_join_type' => "", 'saved_join_type' => $parseInfo['saved_join_type'], - 'ref_type' => false, 'ref_expr' => false, 'base_expr' => false, 'sub_tree' => false, - 'subquery' => ""); + 'hints' => false, 'join_type' => "", 'next_join_type' => "", + 'saved_join_type' => $parseInfo['saved_join_type'], 'ref_type' => false, 'ref_expr' => false, + 'base_expr' => false, 'sub_tree' => false, 'subquery' => ""); } protected function processFromExpression(&$parseInfo) { @@ -65,7 +90,7 @@ class FromProcessor extends AbstractProcessor { // we have a reg_expr, so we have to parse it if ($parseInfo['ref_expr'] !== false) { - $unparsed = $this->splitSQLIntoTokens($this->removeParenthesisFromStart($parseInfo['ref_expr'])); + $unparsed = $this->splitSQLIntoTokens($parseInfo['ref_expr']); // here we can get a comma separated list foreach ($unparsed as $k => $v) { @@ -73,21 +98,37 @@ class FromProcessor extends AbstractProcessor { $unparsed[$k] = ""; } } - $processor = new ExpressionListProcessor(); - $parseInfo['ref_expr'] = $processor->process($unparsed); + if ($parseInfo['ref_type'] === 'USING') { + // unparsed has only one entry, the column list + $ref = $this->processColumnList($this->removeParenthesisFromStart($unparsed[0])); + $ref = array(array('expr_type' => ExpressionType::COLUMN_LIST, 'base_expr' => $unparsed[0], 'sub_tree' => $ref)); + } else { + $ref = $this->processExpressionList($unparsed); + } + $parseInfo['ref_expr'] = (empty($ref) ? false : $ref); } // there is an expression, we have to parse it if (substr(trim($parseInfo['table']), 0, 1) == '(') { $parseInfo['expression'] = $this->removeParenthesisFromStart($parseInfo['table']); - if (preg_match("/^\\s*select/i", $parseInfo['expression'])) { - $processor = new DefaultProcessor(); - $parseInfo['sub_tree'] = $processor->process($parseInfo['expression']); + if (preg_match("/^\\s*(-- [\\w\\s]+\\n)?\\s*SELECT/i", $parseInfo['expression'])) { + $parseInfo['sub_tree'] = $this->processSQLDefault($parseInfo['expression']); $res['expr_type'] = ExpressionType::SUBQUERY; } else { $tmp = $this->splitSQLIntoTokens($parseInfo['expression']); - $parseInfo['sub_tree'] = $this->process($tmp); + $unionProcessor = new UnionProcessor($this->options); + $unionQueries = $unionProcessor->process($tmp); + + // If there was no UNION or UNION ALL in the query, then the query is + // stored at $queries[0]. + if (!empty($unionQueries) && !UnionProcessor::isUnion($unionQueries)) { + $sub_tree = $this->process($unionQueries[0]); + } + else { + $sub_tree = $unionQueries; + } + $parseInfo['sub_tree'] = $sub_tree; $res['expr_type'] = ExpressionType::TABLE_EXPRESSION; } } else { @@ -97,6 +138,7 @@ class FromProcessor extends AbstractProcessor { } $res['alias'] = $parseInfo['alias']; + $res['hints'] = $parseInfo['hints']; $res['join_type'] = $parseInfo['join_type']; $res['ref_type'] = $parseInfo['ref_type']; $res['ref_clause'] = $parseInfo['ref_expr']; @@ -108,6 +150,8 @@ class FromProcessor extends AbstractProcessor { public function process($tokens) { $parseInfo = $this->initParseInfo(); $expr = array(); + $token_category = ''; + $prevToken = ''; $skip_next = false; $i = 0; @@ -125,18 +169,48 @@ class FromProcessor extends AbstractProcessor { } } + if ($this->isCommentToken($token)) { + $expr[] = parent::processComment($token); + continue; + } + switch ($upper) { + case 'CROSS': + case ',': + case 'INNER': + case 'STRAIGHT_JOIN': + break; + case 'OUTER': + case 'JOIN': + if ($token_category === 'LEFT' || $token_category === 'RIGHT' || $token_category === 'NATURAL') { + $token_category = ''; + $parseInfo['next_join_type'] = strtoupper(trim($prevToken)); // it seems to be a join + } + break; + case 'LEFT': case 'RIGHT': case 'NATURAL': - case 'CROSS': - case ',': - case 'JOIN': - case 'INNER': - break; + $token_category = $upper; + $prevToken = $token; + $i++; + continue 2; default: + if ($token_category === 'LEFT' || $token_category === 'RIGHT') { + if ($upper === '') { + $prevToken .= $token; + break; + } else { + $token_category = ''; // it seems to be a function + $parseInfo['expression'] .= $prevToken; + if ($parseInfo['ref_type'] !== false) { // all after ON / USING + $parseInfo['ref_expr'] .= $prevToken; + } + $prevToken = ''; + } + } $parseInfo['expression'] .= $token; if ($parseInfo['ref_type'] !== false) { // all after ON / USING $parseInfo['ref_expr'] .= $token; @@ -144,13 +218,18 @@ class FromProcessor extends AbstractProcessor { break; } + if ($upper === '') { + $i++; + continue; + } + switch ($upper) { case 'AS': $parseInfo['alias'] = array('as' => true, 'name' => "", 'base_expr' => $token); $parseInfo['token_count']++; $n = 1; $str = ""; - while ($str == "") { + while ($str === "" && isset($tokens[$i + $n])) { $parseInfo['alias']['base_expr'] .= ($tokens[$i + $n] === "" ? " " : $tokens[$i + $n]); $str = trim($tokens[$i + $n]); ++$n; @@ -158,14 +237,26 @@ class FromProcessor extends AbstractProcessor { $parseInfo['alias']['name'] = $str; $parseInfo['alias']['no_quotes'] = $this->revokeQuotation($str); $parseInfo['alias']['base_expr'] = trim($parseInfo['alias']['base_expr']); - continue; + break; + case 'IGNORE': + case 'USE': + case 'FORCE': + $token_category = 'IDX_HINT'; + $parseInfo['hints'][]['hint_type'] = $upper; + continue 2; + + case 'KEY': case 'INDEX': - if ($token_category == 'CREATE') { - $token_category = $upper; + if ($token_category === 'CREATE') { + $token_category = $upper; // TODO: what is it for a statement? + continue 2; + } + if ($token_category === 'IDX_HINT') { + $cur_hint = (count($parseInfo['hints']) - 1); + $parseInfo['hints'][$cur_hint]['hint_type'] .= " " . $upper; continue 2; } - break; case 'USING': @@ -174,25 +265,26 @@ class FromProcessor extends AbstractProcessor { $parseInfo['ref_expr'] = ""; case 'CROSS': - case 'USE': - case 'FORCE': - case 'IGNORE': case 'INNER': case 'OUTER': + case 'NATURAL': $parseInfo['token_count']++; - continue; break; case 'FOR': $parseInfo['token_count']++; $skip_next = true; - continue; break; - case 'LEFT': - case 'RIGHT': case 'STRAIGHT_JOIN': - $parseInfo['next_join_type'] = $upper; + $parseInfo['next_join_type'] = "STRAIGHT_JOIN"; + if ($parseInfo['subquery']) { + $parseInfo['sub_tree'] = $this->parse($this->removeParenthesisFromStart($parseInfo['subquery'])); + $parseInfo['expression'] = $parseInfo['subquery']; + } + + $expr[] = $this->processFromExpression($parseInfo); + $parseInfo = $this->initParseInfo($parseInfo); break; case ',': @@ -209,8 +301,13 @@ class FromProcessor extends AbstractProcessor { break; default: - if ($upper === "") { - continue; // ends the switch statement! + // TODO: enhance it, so we can have base_expr to calculate the position of the keywords + // build a subtree under "hints" + if ($token_category === 'IDX_HINT') { + $token_category = ''; + $cur_hint = (count($parseInfo['hints']) - 1); + $parseInfo['hints'][$cur_hint]['hint_list'] = $token; + break; } if ($parseInfo['token_count'] === 0) { @@ -218,7 +315,7 @@ class FromProcessor extends AbstractProcessor { $parseInfo['table'] = $token; $parseInfo['no_quotes'] = $this->revokeQuotation($token); } - } elseif ($parseInfo['token_count'] === 1) { + } else if ($parseInfo['token_count'] === 1) { $parseInfo['alias'] = array('as' => false, 'name' => trim($token), 'no_quotes' => $this->revokeQuotation($token), 'base_expr' => trim($token)); @@ -226,7 +323,7 @@ class FromProcessor extends AbstractProcessor { $parseInfo['token_count']++; break; } - ++$i; + $i++; } $expr[] = $this->processFromExpression($parseInfo); @@ -234,4 +331,5 @@ class FromProcessor extends AbstractProcessor { } } -?> \ No newline at end of file + +?> diff --git a/tools/parser_sql/processors/GroupByProcessor.php b/tools/parser_sql/processors/GroupByProcessor.php index 1c39fb76a..8b4ad1cb1 100644 --- a/tools/parser_sql/processors/GroupByProcessor.php +++ b/tools/parser_sql/processors/GroupByProcessor.php @@ -30,7 +30,7 @@ * DAMAGE. */ -require_once(dirname(__FILE__) . '/OrderByProcessor.php'); +namespace PHPSQLParser\processors; /** * @@ -71,4 +71,4 @@ class GroupByProcessor extends OrderByProcessor { return $out; } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/HavingProcessor.php b/tools/parser_sql/processors/HavingProcessor.php index 8c6a959d8..1d86552b7 100644 --- a/tools/parser_sql/processors/HavingProcessor.php +++ b/tools/parser_sql/processors/HavingProcessor.php @@ -2,44 +2,78 @@ /** * HavingProcessor.php * - * This file implements the processor for the HAVING statements. + * Parses the HAVING statements. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * */ -require_once(dirname(__FILE__) . '/ExpressionListProcessor.php'); +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; /** - * - * This class processes the HAVING statements. - * - * @author arothe - * + * This class implements the processor for the HAVING statement. + * You can overwrite all functions to achieve another handling. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class HavingProcessor extends ExpressionListProcessor { + + public function process($tokens, $select = array()) { + $parsed = parent::process($tokens); + foreach ($parsed as $k => $v) { + if ($v['expr_type'] === ExpressionType::COLREF) { + foreach ($select as $clause) { + if (!isset($clause['alias'])) { + continue; + } + if (!$clause['alias']) { + continue; + } + if ($clause['alias']['no_quotes'] === $v['no_quotes']) { + $parsed[$k]['expr_type'] = ExpressionType::ALIAS; + break; + } + } + } + } + + return $parsed; + } } -?> \ No newline at end of file + +?> diff --git a/tools/parser_sql/processors/IndexColumnListProcessor.php b/tools/parser_sql/processors/IndexColumnListProcessor.php index 425fee94d..c7be39bae 100644 --- a/tools/parser_sql/processors/IndexColumnListProcessor.php +++ b/tools/parser_sql/processors/IndexColumnListProcessor.php @@ -30,8 +30,8 @@ * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); -require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; /** * diff --git a/tools/parser_sql/processors/IndexProcessor.php b/tools/parser_sql/processors/IndexProcessor.php new file mode 100644 index 000000000..50ef717d7 --- /dev/null +++ b/tools/parser_sql/processors/IndexProcessor.php @@ -0,0 +1,306 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class processes the INDEX statements. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class IndexProcessor extends AbstractProcessor { + + protected function getReservedType($token) { + return array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $token); + } + + protected function getConstantType($token) { + return array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $token); + } + + protected function getOperatorType($token) { + return array('expr_type' => ExpressionType::OPERATOR, 'base_expr' => $token); + } + + protected function processIndexColumnList($parsed) { + $processor = new IndexColumnListProcessor($this->options); + return $processor->process($parsed); + } + + public function process($tokens) { + + $currCategory = 'INDEX_NAME'; + $result = array('base_expr' => false, 'name' => false, 'no_quotes' => false, 'index-type' => false, 'on' => false, + 'options' => false); + $expr = array(); + $base_expr = ''; + $skip = 0; + + foreach ($tokens as $tokenKey => $token) { + $trim = trim($token); + $base_expr .= $token; + + if ($skip > 0) { + $skip--; + continue; + } + + if ($skip < 0) { + break; + } + + if ($trim === '') { + continue; + } + + $upper = strtoupper($trim); + switch ($upper) { + + case 'USING': + if ($prevCategory === 'CREATE_DEF') { + $expr[] = $this->getReservedType($trim); + $currCategory = 'TYPE_OPTION'; + continue 2; + } + if ($prevCategory === 'TYPE_DEF') { + $expr[] = $this->getReservedType($trim); + $currCategory = 'INDEX_TYPE'; + continue 2; + } + // else ? + break; + + case 'KEY_BLOCK_SIZE': + if ($prevCategory === 'CREATE_DEF') { + $expr[] = $this->getReservedType($trim); + $currCategory = 'INDEX_OPTION'; + continue 2; + } + // else ? + break; + + case 'WITH': + if ($prevCategory === 'CREATE_DEF') { + $expr[] = $this->getReservedType($trim); + $currCategory = 'INDEX_PARSER'; + continue 2; + } + // else ? + break; + + case 'PARSER': + if ($currCategory === 'INDEX_PARSER') { + $expr[] = $this->getReservedType($trim); + continue 2; + } + // else ? + break; + + case 'COMMENT': + if ($prevCategory === 'CREATE_DEF') { + $expr[] = $this->getReservedType($trim); + $currCategory = 'INDEX_COMMENT'; + continue 2; + } + // else ? + break; + + case 'ALGORITHM': + case 'LOCK': + if ($prevCategory === 'CREATE_DEF') { + $expr[] = $this->getReservedType($trim); + $currCategory = $upper . '_OPTION'; + continue 2; + } + // else ? + break; + + case '=': + // the optional operator + if (substr($currCategory, -7, 7) === '_OPTION') { + $expr[] = $this->getOperatorType($trim); + continue 2; // don't change the category + } + // else ? + break; + + case 'ON': + if ($prevCategory === 'CREATE_DEF' || $prevCategory === 'TYPE_DEF') { + $expr[] = $this->getReservedType($trim); + $currCategory = 'TABLE_DEF'; + continue 2; + } + // else ? + break; + + default: + switch ($currCategory) { + + case 'COLUMN_DEF': + if ($upper[0] === '(' && substr($upper, -1) === ')') { + $cols = $this->processIndexColumnList($this->removeParenthesisFromStart($trim)); + $result['on']['base_expr'] .= $base_expr; + $result['on']['sub_tree'] = array('expr_type' => ExpressionType::COLUMN_LIST, + 'base_expr' => $trim, 'sub_tree' => $cols); + } + + $expr = array(); + $base_expr = ''; + $currCategory = 'CREATE_DEF'; + break; + + case 'TABLE_DEF': + // the table name + $expr[] = $this->getConstantType($trim); + // TODO: the base_expr should contain the column-def too + $result['on'] = array('expr_type' => ExpressionType::TABLE, 'base_expr' => $base_expr, + 'name' => $trim, 'no_quotes' => $this->revokeQuotation($trim), + 'sub_tree' => false); + $expr = array(); + $base_expr = ''; + $currCategory = 'COLUMN_DEF'; + continue 3; + + case 'INDEX_NAME': + $result['base_expr'] = $result['name'] = $trim; + $result['no_quotes'] = $this->revokeQuotation($trim); + + $expr = array(); + $base_expr = ''; + $currCategory = 'TYPE_DEF'; + break; + + case 'INDEX_PARSER': + // the parser name + $expr[] = $this->getConstantType($trim); + $result['options'][] = array('expr_type' => ExpressionType::INDEX_PARSER, + 'base_expr' => trim($base_expr), 'sub_tree' => $expr); + $expr = array(); + $base_expr = ''; + $currCategory = 'CREATE_DEF'; + + break; + + case 'INDEX_COMMENT': + // the index comment + $expr[] = $this->getConstantType($trim); + $result['options'][] = array('expr_type' => ExpressionType::COMMENT, + 'base_expr' => trim($base_expr), 'sub_tree' => $expr); + $expr = array(); + $base_expr = ''; + $currCategory = 'CREATE_DEF'; + + break; + + case 'INDEX_OPTION': + // the key_block_size + $expr[] = $this->getConstantType($trim); + $result['options'][] = array('expr_type' => ExpressionType::INDEX_SIZE, + 'base_expr' => trim($base_expr), 'size' => $upper, + 'sub_tree' => $expr); + $expr = array(); + $base_expr = ''; + $currCategory = 'CREATE_DEF'; + + break; + + case 'INDEX_TYPE': + case 'TYPE_OPTION': + // BTREE or HASH + $expr[] = $this->getReservedType($trim); + if ($currCategory === 'INDEX_TYPE') { + $result['index-type'] = array('expr_type' => ExpressionType::INDEX_TYPE, + 'base_expr' => trim($base_expr), 'using' => $upper, + 'sub_tree' => $expr); + } else { + $result['options'][] = array('expr_type' => ExpressionType::INDEX_TYPE, + 'base_expr' => trim($base_expr), 'using' => $upper, + 'sub_tree' => $expr); + } + + $expr = array(); + $base_expr = ''; + $currCategory = 'CREATE_DEF'; + break; + + case 'LOCK_OPTION': + // DEFAULT|NONE|SHARED|EXCLUSIVE + $expr[] = $this->getReservedType($trim); + $result['options'][] = array('expr_type' => ExpressionType::INDEX_LOCK, + 'base_expr' => trim($base_expr), 'lock' => $upper, + 'sub_tree' => $expr); + + $expr = array(); + $base_expr = ''; + $currCategory = 'CREATE_DEF'; + break; + + case 'ALGORITHM_OPTION': + // DEFAULT|INPLACE|COPY + $expr[] = $this->getReservedType($trim); + $result['options'][] = array('expr_type' => ExpressionType::INDEX_ALGORITHM, + 'base_expr' => trim($base_expr), 'algorithm' => $upper, + 'sub_tree' => $expr); + + $expr = array(); + $base_expr = ''; + $currCategory = 'CREATE_DEF'; + + break; + + default: + break; + } + + break; + } + + $prevCategory = $currCategory; + $currCategory = ''; + } + + return $result; + } +} +?> diff --git a/tools/parser_sql/processors/InsertProcessor.php b/tools/parser_sql/processors/InsertProcessor.php index 460e4a45c..2d8ce9235 100644 --- a/tools/parser_sql/processors/InsertProcessor.php +++ b/tools/parser_sql/processors/InsertProcessor.php @@ -4,72 +4,167 @@ * * This file implements the processor for the INSERT statements. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); -require_once(dirname(__FILE__) . '/ColumnListProcessor.php'); -require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; /** - * * This class processes the INSERT statements. - * - * @author arothe - * + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class InsertProcessor extends AbstractProcessor { - public function process($tokenList, $token_category = 'INSERT') { - $table = ""; - $cols = array(); + protected function processOptions($tokenList) { + if (!isset($tokenList['OPTIONS'])) { + return array(); + } + $result = array(); + foreach ($tokenList['OPTIONS'] as $token) { + $result[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => trim($token)); + } + return $result; + } - $into = $tokenList['INTO']; - foreach ($into as $token) { - if ($this->isWhitespaceToken($token)) + protected function processKeyword($keyword, $tokenList) { + if (!isset($tokenList[$keyword])) { + return array('', false, array()); + } + + $table = ''; + $cols = false; + $result = array(); + + foreach ($tokenList[$keyword] as $token) { + $trim = trim($token); + + if ($trim === '') { continue; - if ($table === "") { - $table = $token; - } elseif (empty($cols)) { - $cols[] = $token; + } + + $upper = strtoupper($trim); + switch ($upper) { + case 'INTO': + $result[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); + break; + + case 'INSERT': + case 'REPLACE': + break; + + default: + if ($table === '') { + $table = $trim; + break; + } + + if ($cols === false) { + $cols = $trim; + } + break; + } + } + return array($table, $cols, $result); + } + + protected function processColumns($cols) { + if ($cols === false) { + return $cols; + } + if ($cols[0] === '(' && substr($cols, -1) === ')') { + $parsed = array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $cols, + 'sub_tree' => false); + } + $cols = $this->removeParenthesisFromStart($cols); + if (stripos($cols, 'SELECT') === 0) { + $processor = new DefaultProcessor($this->options); + $parsed['sub_tree'] = array( + array('expr_type' => ExpressionType::QUERY, 'base_expr' => $cols, + 'sub_tree' => $processor->process($cols))); + } else { + $processor = new ColumnListProcessor($this->options); + $parsed['sub_tree'] = $processor->process($cols); + $parsed['expr_type'] = ExpressionType::COLUMN_LIST; + } + return $parsed; + } + + public function process($tokenList, $token_category = 'INSERT') { + $table = ''; + $cols = false; + $comments = array(); + + foreach ($tokenList as $key => &$token) { + if ($key == 'VALUES') { + continue; + } + foreach ($token as &$value) { + if ($this->isCommentToken($value)) { + $comments[] = parent::processComment($value); + $value = ''; + } } } - if (empty($cols)) { - $cols = false; - } else { - $processor = new ColumnListProcessor(); - $cols = $processor->process($this->removeParenthesisFromStart($cols[0])); + $parsed = $this->processOptions($tokenList); + unset($tokenList['OPTIONS']); + + list($table, $cols, $key) = $this->processKeyword('INTO', $tokenList); + $parsed = array_merge($parsed, $key); + unset($tokenList['INTO']); + + if ($table === '' && in_array($token_category, array('INSERT', 'REPLACE'))) { + list($table, $cols, $key) = $this->processKeyword($token_category, $tokenList); } - unset($tokenList['INTO']); - $tokenList[$token_category][0] = array('table' => $table, 'columns' => $cols, 'base_expr' => $table, - 'no_quotes' => $this->revokeQuotation($table)); + $parsed[] = array('expr_type' => ExpressionType::TABLE, 'table' => $table, + 'no_quotes' => $this->revokeQuotation($table), 'alias' => false, 'base_expr' => $table); + + $cols = $this->processColumns($cols); + if ($cols !== false) { + $parsed[] = $cols; + } + + $parsed = array_merge($parsed, $comments); + + $tokenList[$token_category] = $parsed; return $tokenList; } - } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/IntoProcessor.php b/tools/parser_sql/processors/IntoProcessor.php index 25c7ada51..d12b95fcd 100644 --- a/tools/parser_sql/processors/IntoProcessor.php +++ b/tools/parser_sql/processors/IntoProcessor.php @@ -30,7 +30,7 @@ * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); +namespace PHPSQLParser\processors; /** * @@ -56,4 +56,4 @@ class IntoProcessor extends AbstractProcessor { return $tokenList; } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/LimitProcessor.php b/tools/parser_sql/processors/LimitProcessor.php index c0c3c8a10..1638748ce 100644 --- a/tools/parser_sql/processors/LimitProcessor.php +++ b/tools/parser_sql/processors/LimitProcessor.php @@ -4,39 +4,48 @@ * * This file implements the processor for the LIMIT statements. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); +namespace PHPSQLParser\processors; /** - * * This class processes the LIMIT statements. * - * @author arothe + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class LimitProcessor extends AbstractProcessor { @@ -47,9 +56,18 @@ class LimitProcessor extends AbstractProcessor { $comma = -1; $exchange = false; - + + $comments = array(); + + foreach ($tokens as &$token) { + if ($this->isCommentToken($token)) { + $comments[] = parent::processComment($token); + $token = ''; + } + } + for ($i = 0; $i < count($tokens); ++$i) { - $trim = trim($tokens[$i]); + $trim = strtoupper(trim($tokens[$i])); if ($trim === ",") { $comma = $i; break; @@ -77,7 +95,11 @@ class LimitProcessor extends AbstractProcessor { } } - return array('offset' => trim($offset), 'rowcount' => trim($rowcount)); + $return = array('offset' => trim($offset), 'rowcount' => trim($rowcount)); + if (count($comments)) { + $return['comments'] = $comments; + } + return $return; } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/OptionsProcessor.php b/tools/parser_sql/processors/OptionsProcessor.php new file mode 100644 index 000000000..a22605f58 --- /dev/null +++ b/tools/parser_sql/processors/OptionsProcessor.php @@ -0,0 +1,77 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class processes the statement options. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class OptionsProcessor extends AbstractProcessor { + + public function process($tokens) { + $resultList = array(); + + foreach ($tokens as $token) { + + $tokenList = $this->splitSQLIntoTokens($token); + $result = array(); + + foreach ($tokenList as $reserved) { + $trim = trim($reserved); + if ($trim === '') { + continue; + } + $result[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); + } + $resultList[] = array('expr_type' => ExpressionType::EXPRESSION, 'base_expr' => trim($token), + 'sub_tree' => $result); + } + + return $resultList; + } +} + +?> diff --git a/tools/parser_sql/processors/OrderByProcessor.php b/tools/parser_sql/processors/OrderByProcessor.php index 6752453cc..2f8b6576c 100644 --- a/tools/parser_sql/processors/OrderByProcessor.php +++ b/tools/parser_sql/processors/OrderByProcessor.php @@ -4,49 +4,56 @@ * * This file implements the processor for the ORDER-BY statements. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); -require_once(dirname(__FILE__) . '/SelectExpressionProcessor.php'); -require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; /** - * * This class processes the ORDER-BY statements. - * - * @author arothe - * + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class OrderByProcessor extends AbstractProcessor { - private $selectExpressionProcessor; - - public function __construct() { - $this->selectExpressionProcessor = new SelectExpressionProcessor(); + protected function processSelectExpression($unparsed) { + $processor = new SelectExpressionProcessor($this->options); + return $processor->process($unparsed); } protected function initParseInfo() { @@ -66,7 +73,7 @@ class OrderByProcessor extends AbstractProcessor { $parseInfo['no_quotes'] = $this->revokeQuotation($parseInfo['base_expr']); // search to see if the expression matches an alias foreach ($select as $clause) { - if (!$clause['alias']) { + if (empty($clause['alias'])) { continue; } @@ -78,7 +85,7 @@ class OrderByProcessor extends AbstractProcessor { } if ($parseInfo['expr_type'] === ExpressionType::EXPRESSION) { - $expr = $this->selectExpressionProcessor->process($parseInfo['base_expr']); + $expr = $this->processSelectExpression($parseInfo['base_expr']); $expr['direction'] = $parseInfo['dir']; unset($expr['alias']); return $expr; @@ -119,6 +126,11 @@ class OrderByProcessor extends AbstractProcessor { break; default: + if ($this->isCommentToken($token)) { + $out[] = parent::processComment($token); + break; + } + $parseInfo['base_expr'] .= $token; } } @@ -127,4 +139,4 @@ class OrderByProcessor extends AbstractProcessor { return $out; } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/PartitionDefinitionProcessor.php b/tools/parser_sql/processors/PartitionDefinitionProcessor.php new file mode 100644 index 000000000..41f3f2ac3 --- /dev/null +++ b/tools/parser_sql/processors/PartitionDefinitionProcessor.php @@ -0,0 +1,390 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class processes the PARTITION statements within CREATE TABLE. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class PartitionDefinitionProcessor extends AbstractProcessor { + + protected function processExpressionList($unparsed) { + $processor = new ExpressionListProcessor($this->options); + $expr = $this->removeParenthesisFromStart($unparsed); + $expr = $this->splitSQLIntoTokens($expr); + return $processor->process($expr); + } + + protected function processSubpartitionDefinition($unparsed) { + $processor = new SubpartitionDefinitionProcessor($this->options); + $expr = $this->removeParenthesisFromStart($unparsed); + $expr = $this->splitSQLIntoTokens($expr); + return $processor->process($expr); + } + + protected function getReservedType($token) { + return array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $token); + } + + protected function getConstantType($token) { + return array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $token); + } + + protected function getOperatorType($token) { + return array('expr_type' => ExpressionType::OPERATOR, 'base_expr' => $token); + } + + protected function getBracketExpressionType($token) { + return array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $token, 'sub_tree' => false); + } + + public function process($tokens) { + + $result = array(); + $prevCategory = ''; + $currCategory = ''; + $parsed = array(); + $expr = array(); + $base_expr = ''; + $skip = 0; + + foreach ($tokens as $tokenKey => $token) { + $trim = trim($token); + $base_expr .= $token; + + if ($skip > 0) { + $skip--; + continue; + } + + if ($skip < 0) { + break; + } + + if ($trim === '') { + continue; + } + + $upper = strtoupper($trim); + switch ($upper) { + + case 'PARTITION': + if ($currCategory === '') { + $expr[] = $this->getReservedType($trim); + $parsed = array('expr_type' => ExpressionType::PARTITION_DEF, 'base_expr' => trim($base_expr), + 'sub_tree' => false); + $currCategory = $upper; + continue 2; + } + // else ? + break; + + case 'VALUES': + if ($prevCategory === 'PARTITION') { + $expr[] = array('expr_type' => ExpressionType::PARTITION_VALUES, 'base_expr' => false, + 'sub_tree' => false, 'storage' => substr($base_expr, 0, -strlen($token))); + $parsed['sub_tree'] = $expr; + + $base_expr = $token; + $expr = array($this->getReservedType($trim)); + + $currCategory = $upper; + continue 2; + } + // else ? + break; + + case 'LESS': + if ($currCategory === 'VALUES') { + $expr[] = $this->getReservedType($trim); + continue 2; + } + // else ? + break; + + case 'THAN': + if ($currCategory === 'VALUES') { + // followed by parenthesis and (value-list or expr) + $expr[] = $this->getReservedType($trim); + continue 2; + } + // else ? + break; + + case 'MAXVALUE': + if ($currCategory === 'VALUES') { + $expr[] = $this->getConstantType($trim); + + $last = array_pop($parsed['sub_tree']); + $last['base_expr'] = $base_expr; + $last['sub_tree'] = $expr; + + $base_expr = $last['storage'] . $base_expr; + unset($last['storage']); + $parsed['sub_tree'][] = $last; + $parsed['base_expr'] = trim($base_expr); + + $expr = $parsed['sub_tree']; + unset($last); + $currCategory = $prevCategory; + } + // else ? + break; + + case 'IN': + if ($currCategory === 'VALUES') { + // followed by parenthesis and value-list + $expr[] = $this->getReservedType($trim); + continue 2; + } + break; + + case 'COMMENT': + if ($prevCategory === 'PARTITION') { + $expr[] = array('expr_type' => ExpressionType::PARTITION_COMMENT, 'base_expr' => false, + 'sub_tree' => false, 'storage' => substr($base_expr, 0, -strlen($token))); + + $parsed['sub_tree'] = $expr; + $base_expr = $token; + $expr = array($this->getReservedType($trim)); + + $currCategory = $upper; + continue 2; + } + // else ? + break; + + case 'STORAGE': + if ($prevCategory === 'PARTITION') { + // followed by ENGINE + $expr[] = array('expr_type' => ExpressionType::ENGINE, 'base_expr' => false, 'sub_tree' => false, + 'storage' => substr($base_expr, 0, -strlen($token))); + + $parsed['sub_tree'] = $expr; + $base_expr = $token; + $expr = array($this->getReservedType($trim)); + + $currCategory = $upper; + continue 2; + } + // else ? + break; + + case 'ENGINE': + if ($currCategory === 'STORAGE') { + $expr[] = $this->getReservedType($trim); + $currCategory = $upper; + continue 2; + } + if ($prevCategory === 'PARTITION') { + $expr[] = array('expr_type' => ExpressionType::ENGINE, 'base_expr' => false, 'sub_tree' => false, + 'storage' => substr($base_expr, 0, -strlen($token))); + + $parsed['sub_tree'] = $expr; + $base_expr = $token; + $expr = array($this->getReservedType($trim)); + + $currCategory = $upper; + continue 2; + } + // else ? + break; + + case '=': + if (in_array($currCategory, array('ENGINE', 'COMMENT', 'DIRECTORY', 'MAX_ROWS', 'MIN_ROWS'))) { + $expr[] = $this->getOperatorType($trim); + continue 2; + } + // else ? + break; + + case ',': + if ($prevCategory === 'PARTITION' && $currCategory === '') { + // it separates the partition-definitions + $result[] = $parsed; + $parsed = array(); + $base_expr = ''; + $expr = array(); + } + break; + + case 'DATA': + case 'INDEX': + if ($prevCategory === 'PARTITION') { + // followed by DIRECTORY + $expr[] = array('expr_type' => constant('PHPSQLParser\utils\ExpressionType::PARTITION_' . $upper . '_DIR'), + 'base_expr' => false, 'sub_tree' => false, + 'storage' => substr($base_expr, 0, -strlen($token))); + + $parsed['sub_tree'] = $expr; + $base_expr = $token; + $expr = array($this->getReservedType($trim)); + + $currCategory = $upper; + continue 2; + } + // else ? + break; + + case 'DIRECTORY': + if ($currCategory === 'DATA' || $currCategory === 'INDEX') { + $expr[] = $this->getReservedType($trim); + $currCategory = $upper; + continue 2; + } + // else ? + break; + + case 'MAX_ROWS': + case 'MIN_ROWS': + if ($prevCategory === 'PARTITION') { + $expr[] = array('expr_type' => constant('PHPSQLParser\utils\ExpressionType::PARTITION_' . $upper), + 'base_expr' => false, 'sub_tree' => false, + 'storage' => substr($base_expr, 0, -strlen($token))); + + $parsed['sub_tree'] = $expr; + $base_expr = $token; + $expr = array($this->getReservedType($trim)); + + $currCategory = $upper; + continue 2; + } + // else ? + break; + + default: + switch ($currCategory) { + + case 'MIN_ROWS': + case 'MAX_ROWS': + case 'ENGINE': + case 'DIRECTORY': + case 'COMMENT': + $expr[] = $this->getConstantType($trim); + + $last = array_pop($parsed['sub_tree']); + $last['sub_tree'] = $expr; + $last['base_expr'] = trim($base_expr); + $base_expr = $last['storage'] . $base_expr; + unset($last['storage']); + + $parsed['sub_tree'][] = $last; + $parsed['base_expr'] = trim($base_expr); + + $expr = $parsed['sub_tree']; + unset($last); + + $currCategory = $prevCategory; + break; + + case 'PARTITION': + // that is the partition name + $last = array_pop($expr); + $last['name'] = $trim; + $expr[] = $last; + $expr[] = $this->getConstantType($trim); + $parsed['sub_tree'] = $expr; + $parsed['base_expr'] = trim($base_expr); + break; + + case 'VALUES': + // we have parenthesis and have to process an expression/in-list + $last = $this->getBracketExpressionType($trim); + + $res = $this->processExpressionList($trim); + $last['sub_tree'] = (empty($res) ? false : $res); + $expr[] = $last; + + $last = array_pop($parsed['sub_tree']); + $last['base_expr'] = $base_expr; + $last['sub_tree'] = $expr; + + $base_expr = $last['storage'] . $base_expr; + unset($last['storage']); + $parsed['sub_tree'][] = $last; + $parsed['base_expr'] = trim($base_expr); + + $expr = $parsed['sub_tree']; + unset($last); + + $currCategory = $prevCategory; + break; + + case '': + if ($prevCategory === 'PARTITION') { + // last part to process, it is only one token! + if ($upper[0] === '(' && substr($upper, -1) === ')') { + $last = $this->getBracketExpressionType($trim); + $last['sub_tree'] = $this->processSubpartitionDefinition($trim); + $expr[] = $last; + unset($last); + + $parsed['base_expr'] = trim($base_expr); + $parsed['sub_tree'] = $expr; + + $currCategory = $prevCategory; + break; + } + } + // else ? + break; + + default: + break; + } + break; + } + + $prevCategory = $currCategory; + $currCategory = ''; + } + + $result[] = $parsed; + return $result; + } +} +?> diff --git a/tools/parser_sql/processors/PartitionOptionsProcessor.php b/tools/parser_sql/processors/PartitionOptionsProcessor.php new file mode 100644 index 000000000..a114abc33 --- /dev/null +++ b/tools/parser_sql/processors/PartitionOptionsProcessor.php @@ -0,0 +1,361 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class processes the PARTITION BY statements within CREATE TABLE. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class PartitionOptionsProcessor extends AbstractProcessor { + + protected function processExpressionList($unparsed) { + $processor = new ExpressionListProcessor($this->options); + $expr = $this->removeParenthesisFromStart($unparsed); + $expr = $this->splitSQLIntoTokens($expr); + return $processor->process($expr); + } + + protected function processColumnList($unparsed) { + $processor = new ColumnListProcessor($this->options); + $expr = $this->removeParenthesisFromStart($unparsed); + return $processor->process($expr); + } + + protected function processPartitionDefinition($unparsed) { + $processor = new PartitionDefinitionProcessor($this->options); + $expr = $this->removeParenthesisFromStart($unparsed); + $expr = $this->splitSQLIntoTokens($expr); + return $processor->process($expr); + } + + protected function getReservedType($token) { + return array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $token); + } + + protected function getConstantType($token) { + return array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $token); + } + + protected function getOperatorType($token) { + return array('expr_type' => ExpressionType::OPERATOR, 'base_expr' => $token); + } + + protected function getBracketExpressionType($token) { + return array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $token, 'sub_tree' => false); + } + + public function process($tokens) { + + $result = array('partition-options' => array(), 'last-parsed' => false); + + $prevCategory = ''; + $currCategory = ''; + $parsed = array(); + $expr = array(); + $base_expr = ''; + $skip = 0; + + foreach ($tokens as $tokenKey => $token) { + $trim = trim($token); + $base_expr .= $token; + + if ($skip > 0) { + $skip--; + continue; + } + + if ($skip < 0) { + break; + } + + if ($trim === '') { + continue; + } + + $upper = strtoupper($trim); + switch ($upper) { + + case 'PARTITION': + $currCategory = $upper; + $expr[] = $this->getReservedType($trim); + $parsed[] = array('expr_type' => ExpressionType::PARTITION, 'base_expr' => trim($base_expr), + 'sub_tree' => false); + break; + + case 'SUBPARTITION': + $currCategory = $upper; + $expr[] = $this->getReservedType($trim); + $parsed[] = array('expr_type' => ExpressionType::SUBPARTITION, 'base_expr' => trim($base_expr), + 'sub_tree' => false); + break; + + case 'BY': + if ($prevCategory === 'PARTITION' || $prevCategory === 'SUBPARTITION') { + $expr[] = $this->getReservedType($trim); + continue 2; + } + break; + + case 'PARTITIONS': + case 'SUBPARTITIONS': + $currCategory = 'PARTITION_NUM'; + $expr = array('expr_type' => constant('PHPSQLParser\utils\ExpressionType::' . substr($upper, 0, -1) . '_COUNT'), + 'base_expr' => false, 'sub_tree' => array($this->getReservedType($trim)), + 'storage' => substr($base_expr, 0, -strlen($token))); + $base_expr = $token; + continue 2; + + case 'LINEAR': + // followed by HASH or KEY + $currCategory = $upper; + $expr[] = $this->getReservedType($trim); + continue 2; + + case 'HASH': + case 'KEY': + $expr[] = array('expr_type' => constant('PHPSQLParser\utils\ExpressionType::' . $prevCategory . '_' . $upper), + 'base_expr' => false, 'linear' => ($currCategory === 'LINEAR'), 'sub_tree' => false, + 'storage' => substr($base_expr, 0, -strlen($token))); + + $last = array_pop($parsed); + $last['by'] = trim($currCategory . ' ' . $upper); // $currCategory will be empty or LINEAR! + $last['sub_tree'] = $expr; + $parsed[] = $last; + + $base_expr = $token; + $expr = array($this->getReservedType($trim)); + + $currCategory = $upper; + continue 2; + + case 'ALGORITHM': + if ($currCategory === 'KEY') { + $expr[] = array('expr_type' => constant('PHPSQLParser\utils\ExpressionType::' . $prevCategory . '_KEY_ALGORITHM'), + 'base_expr' => false, 'sub_tree' => false, + 'storage' => substr($base_expr, 0, -strlen($token))); + + $last = array_pop($parsed); + $subtree = array_pop($last['sub_tree']); + $subtree['sub_tree'] = $expr; + $last['sub_tree'][] = $subtree; + $parsed[] = $last; + unset($subtree); + unset($last); + + $base_expr = $token; + $expr = array($this->getReservedType($trim)); + $currCategory = $upper; + continue 2; + } + break; + + case 'RANGE': + case 'LIST': + $expr[] = array('expr_type' => constant('PHPSQLParser\utils\ExpressionType::PARTITION_' . $upper), 'base_expr' => false, + 'sub_tree' => false, 'storage' => substr($base_expr, 0, -strlen($token))); + + $last = array_pop($parsed); + $last['by'] = $upper; + $last['sub_tree'] = $expr; + $parsed[] = $last; + unset($last); + + $base_expr = $token; + $expr = array($this->getReservedType($trim)); + + $currCategory = $upper . '_EXPR'; + continue 2; + + case 'COLUMNS': + if ($currCategory === 'RANGE_EXPR' || $currCategory === 'LIST_EXPR') { + $expr[] = $this->getReservedType($trim); + $currCategory = substr($currCategory, 0, -4) . $upper; + continue 2; + } + break; + + case '=': + if ($currCategory === 'ALGORITHM') { + // between ALGORITHM and a constant + $expr[] = $this->getOperatorType($trim); + continue 2; + } + break; + + default: + switch ($currCategory) { + + case 'PARTITION_NUM': + // the number behind PARTITIONS or SUBPARTITIONS + $expr['base_expr'] = trim($base_expr); + $expr['sub_tree'][] = $this->getConstantType($trim); + $base_expr = $expr['storage'] . $base_expr; + unset($expr['storage']); + + $last = array_pop($parsed); + $last['count'] = $trim; + $last['sub_tree'][] = $expr; + $last['base_expr'] .= $base_expr; + $parsed[] = $last; + unset($last); + + $expr = array(); + $base_expr = ''; + $currCategory = $prevCategory; + break; + + case 'ALGORITHM': + // the number of the algorithm + $expr[] = $this->getConstantType($trim); + + $last = array_pop($parsed); + $subtree = array_pop($last['sub_tree']); + $key = array_pop($subtree['sub_tree']); + + $key['sub_tree'] = $expr; + $key['base_expr'] = trim($base_expr); + + $base_expr = $key['storage'] . $base_expr; + unset($key['storage']); + + $subtree['sub_tree'][] = $key; + unset($key); + + $expr = $subtree['sub_tree']; + $subtree['sub_tree'] = false; + $subtree['algorithm'] = $trim; + $last['sub_tree'][] = $subtree; + unset($subtree); + + $parsed[] = $last; + unset($last); + $currCategory = 'KEY'; + continue 3; + + case 'LIST_EXPR': + case 'RANGE_EXPR': + case 'HASH': + // parenthesis around an expression + $last = $this->getBracketExpressionType($trim); + $res = $this->processExpressionList($trim); + $last['sub_tree'] = (empty($res) ? false : $res); + $expr[] = $last; + + $last = array_pop($parsed); + $subtree = array_pop($last['sub_tree']); + $subtree['base_expr'] = $base_expr; + $subtree['sub_tree'] = $expr; + + $base_expr = $subtree['storage'] . $base_expr; + unset($subtree['storage']); + $last['sub_tree'][] = $subtree; + $last['base_expr'] = trim($base_expr); + $parsed[] = $last; + unset($last); + unset($subtree); + + $expr = array(); + $base_expr = ''; + $currCategory = $prevCategory; + break; + + case 'LIST_COLUMNS': + case 'RANGE_COLUMNS': + case 'KEY': + // the columnlist + $expr[] = array('expr_type' => ExpressionType::COLUMN_LIST, 'base_expr' => $trim, + 'sub_tree' => $this->processColumnList($trim)); + + $last = array_pop($parsed); + $subtree = array_pop($last['sub_tree']); + $subtree['base_expr'] = $base_expr; + $subtree['sub_tree'] = $expr; + + $base_expr = $subtree['storage'] . $base_expr; + unset($subtree['storage']); + $last['sub_tree'][] = $subtree; + $last['base_expr'] = trim($base_expr); + $parsed[] = $last; + unset($last); + unset($subtree); + + $expr = array(); + $base_expr = ''; + $currCategory = $prevCategory; + break; + + case '': + if ($prevCategory === 'PARTITION' || $prevCategory === 'SUBPARTITION') { + if ($upper[0] === '(' && substr($upper, -1) === ')') { + // last part to process, it is only one token! + $last = $this->getBracketExpressionType($trim); + $last['sub_tree'] = $this->processPartitionDefinition($trim); + $parsed[] = $last; + break; + } + } + // else ? + break; + + default: + break; + } + break; + } + + $prevCategory = $currCategory; + $currCategory = ''; + } + + $result['partition-options'] = $parsed; + if ($result['last-parsed'] === false) { + $result['last-parsed'] = $tokenKey; + } + return $result; + } +} +?> diff --git a/tools/parser_sql/processors/RecordProcessor.php b/tools/parser_sql/processors/RecordProcessor.php index 0e4b90442..9908325f3 100644 --- a/tools/parser_sql/processors/RecordProcessor.php +++ b/tools/parser_sql/processors/RecordProcessor.php @@ -2,50 +2,58 @@ /** * RecordProcessor.php * - * This file implements the processor for records. + * This file implements a processor, which processes records of data + * for an INSERT statement. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); -require_once(dirname(__FILE__) . '/ExpressionListProcessor.php'); +namespace PHPSQLParser\processors; /** - * - * This class processes records. - * - * @author arothe - * + * This class processes records of an INSERT statement. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class RecordProcessor extends AbstractProcessor { - private $expressionListProcessor; - - public function __construct() { - $this->expressionListProcessor = new ExpressionListProcessor(); + protected function processExpressionList($unparsed) { + $processor = new ExpressionListProcessor($this->options); + return $processor->process($unparsed); } public function process($unparsed) { @@ -57,8 +65,7 @@ class RecordProcessor extends AbstractProcessor { $values[$k] = ""; } } - return $this->expressionListProcessor->process($values); + return $this->processExpressionList($values); } - } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/ReferenceDefinitionProcessor.php b/tools/parser_sql/processors/ReferenceDefinitionProcessor.php index da2cf6a34..72df8567b 100644 --- a/tools/parser_sql/processors/ReferenceDefinitionProcessor.php +++ b/tools/parser_sql/processors/ReferenceDefinitionProcessor.php @@ -30,9 +30,8 @@ * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); -require_once(dirname(__FILE__) . '/IndexColumnListProcessor.php'); -require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; /** * @@ -155,7 +154,7 @@ class ReferenceDefinitionProcessor extends AbstractProcessor { case 'REFERENCES': if ($upper[0] === '(' && substr($upper, -1) === ')') { # index_col_name list - $processor = new IndexColumnListProcessor(); + $processor = new IndexColumnListProcessor($this->options); $cols = $processor->process($this->removeParenthesisFromStart($trim)); $expr['sub_tree'][] = array('expr_type' => ExpressionType::COLUMN_LIST, 'base_expr' => $trim, 'sub_tree' => $cols); diff --git a/tools/parser_sql/processors/RenameProcessor.php b/tools/parser_sql/processors/RenameProcessor.php index 3f9992d30..231406855 100644 --- a/tools/parser_sql/processors/RenameProcessor.php +++ b/tools/parser_sql/processors/RenameProcessor.php @@ -4,42 +4,51 @@ * * This file implements the processor for the RENAME statements. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); -require_once(dirname(__FILE__) . '/../utils/ExpressionToken.php'); -require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; +use PHPSQLParser\utils\ExpressionToken; /** - * * This class processes the RENAME statements. - * - * @author arothe - * + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class RenameProcessor extends AbstractProcessor { @@ -74,6 +83,11 @@ class RenameProcessor extends AbstractProcessor { $base_expr = ""; break; + case 'TABLE': + $objectType = ExpressionType::TABLE; + $resultList[] = array('expr_type'=>ExpressionType::RESERVED, 'base_expr'=>$token->getTrim()); + continue 2; + default: $base_expr .= $token->getToken(); break; @@ -87,7 +101,7 @@ class RenameProcessor extends AbstractProcessor { $resultList[] = $tablePair; } - return $resultList; + return array('expr_type' => $objectType, 'sub_tree'=>$resultList); } } diff --git a/tools/parser_sql/processors/ReplaceProcessor.php b/tools/parser_sql/processors/ReplaceProcessor.php index 741d5df32..92e302134 100644 --- a/tools/parser_sql/processors/ReplaceProcessor.php +++ b/tools/parser_sql/processors/ReplaceProcessor.php @@ -2,48 +2,57 @@ /** * ReplaceProcessor.php * - * This file implements the processor for the REPLACE statements. + * This file implements the processor for the REPLACE statements. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/InsertProcessor.php'); +namespace PHPSQLParser\processors; /** - * * This class processes the REPLACE statements. * - * @author arothe - * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class ReplaceProcessor extends InsertProcessor { - public function process($tokenList, $token_category = 'INSERT') { - return parent::process($tokenList, 'REPLACE'); + public function process($tokenList, $token_category = 'REPLACE') { + return parent::process($tokenList, $token_category); } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/SQLChunkProcessor.php b/tools/parser_sql/processors/SQLChunkProcessor.php index b99eea499..039cf4c8b 100644 --- a/tools/parser_sql/processors/SQLChunkProcessor.php +++ b/tools/parser_sql/processors/SQLChunkProcessor.php @@ -4,67 +4,49 @@ * * This file implements the processor for the SQL chunks. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); -require_once(dirname(__FILE__) . '/FromProcessor.php'); -require_once(dirname(__FILE__) . '/RecordProcessor.php'); -require_once(dirname(__FILE__) . '/UpdateProcessor.php'); -require_once(dirname(__FILE__) . '/DeleteProcessor.php'); -require_once(dirname(__FILE__) . '/GroupByProcessor.php'); -require_once(dirname(__FILE__) . '/RenameProcessor.php'); -require_once(dirname(__FILE__) . '/UsingProcessor.php'); -require_once(dirname(__FILE__) . '/DescribeProcessor.php'); -require_once(dirname(__FILE__) . '/DescProcessor.php'); -require_once(dirname(__FILE__) . '/HavingProcessor.php'); -require_once(dirname(__FILE__) . '/ReplaceProcessor.php'); -require_once(dirname(__FILE__) . '/ValuesProcessor.php'); -require_once(dirname(__FILE__) . '/DropProcessor.php'); -require_once(dirname(__FILE__) . '/InsertProcessor.php'); -require_once(dirname(__FILE__) . '/SelectExpressionProcessor.php'); -require_once(dirname(__FILE__) . '/WhereProcessor.php'); -require_once(dirname(__FILE__) . '/DuplicateProcessor.php'); -require_once(dirname(__FILE__) . '/IntoProcessor.php'); -require_once(dirname(__FILE__) . '/SelectProcessor.php'); -require_once(dirname(__FILE__) . '/ExplainProcessor.php'); -require_once(dirname(__FILE__) . '/LimitProcessor.php'); -require_once(dirname(__FILE__) . '/SetProcessor.php'); -require_once(dirname(__FILE__) . '/ExpressionListProcessor.php'); -require_once(dirname(__FILE__) . '/OrderByProcessor.php'); -require_once(dirname(__FILE__) . '/ShowProcessor.php'); -require_once(dirname(__FILE__) . '/CreateProcessor.php'); -require_once(dirname(__FILE__) . '/TableProcessor.php'); +namespace PHPSQLParser\processors; /** - * * This class processes the SQL chunks. - * - * @author arothe - * + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class SQLChunkProcessor extends AbstractProcessor { @@ -80,107 +62,137 @@ class SQLChunkProcessor extends AbstractProcessor { if (!$out) { return false; } + if (!empty($out['BRACKET'])) { + // TODO: this field should be a global STATEMENT field within the output + // we could add all other categories as sub_tree, it could also work with multipe UNIONs + $processor = new BracketProcessor($this->options); + $processedBracket = $processor->process($out['BRACKET']); + $remainingExpressions = $processedBracket[0]['remaining_expressions']; + + unset($processedBracket[0]['remaining_expressions']); + + if(!empty($remainingExpressions)) { + foreach($remainingExpressions as $key=>$expression) { + $processedBracket[][$key] = $expression; + } + } + + $out['BRACKET'] = $processedBracket; + } if (!empty($out['CREATE'])) { - $processor = new CreateProcessor(); + $processor = new CreateProcessor($this->options); $out['CREATE'] = $processor->process($out['CREATE']); } if (!empty($out['TABLE'])) { - $processor = new TableProcessor(); + $processor = new TableProcessor($this->options); $out['TABLE'] = $processor->process($out['TABLE']); $this->moveLIKE($out); } + if (!empty($out['INDEX'])) { + $processor = new IndexProcessor($this->options); + $out['INDEX'] = $processor->process($out['INDEX']); + } if (!empty($out['EXPLAIN'])) { - $processor = new ExplainProcessor(); + $processor = new ExplainProcessor($this->options); $out['EXPLAIN'] = $processor->process($out['EXPLAIN'], array_keys($out)); } if (!empty($out['DESCRIBE'])) { - $processor = new DescribeProcessor(); + $processor = new DescribeProcessor($this->options); $out['DESCRIBE'] = $processor->process($out['DESCRIBE'], array_keys($out)); } if (!empty($out['DESC'])) { - $processor = new DescProcessor(); + $processor = new DescProcessor($this->options); $out['DESC'] = $processor->process($out['DESC'], array_keys($out)); } if (!empty($out['SELECT'])) { - $processor = new SelectProcessor(); + $processor = new SelectProcessor($this->options); $out['SELECT'] = $processor->process($out['SELECT']); } if (!empty($out['FROM'])) { - $processor = new FromProcessor(); + $processor = new FromProcessor($this->options); $out['FROM'] = $processor->process($out['FROM']); } if (!empty($out['USING'])) { - $processor = new UsingProcessor(); + $processor = new UsingProcessor($this->options); $out['USING'] = $processor->process($out['USING']); } if (!empty($out['UPDATE'])) { - $processor = new UpdateProcessor(); + $processor = new UpdateProcessor($this->options); $out['UPDATE'] = $processor->process($out['UPDATE']); } if (!empty($out['GROUP'])) { // set empty array if we have partial SQL statement - $processor = new GroupByProcessor(); + $processor = new GroupByProcessor($this->options); $out['GROUP'] = $processor->process($out['GROUP'], isset($out['SELECT']) ? $out['SELECT'] : array()); } if (!empty($out['ORDER'])) { // set empty array if we have partial SQL statement - $processor = new OrderByProcessor(); + $processor = new OrderByProcessor($this->options); $out['ORDER'] = $processor->process($out['ORDER'], isset($out['SELECT']) ? $out['SELECT'] : array()); } if (!empty($out['LIMIT'])) { - $processor = new LimitProcessor(); + $processor = new LimitProcessor($this->options); $out['LIMIT'] = $processor->process($out['LIMIT']); } if (!empty($out['WHERE'])) { - $processor = new WhereProcessor(); + $processor = new WhereProcessor($this->options); $out['WHERE'] = $processor->process($out['WHERE']); } if (!empty($out['HAVING'])) { - $processor = new HavingProcessor(); - $out['HAVING'] = $processor->process($out['HAVING']); + $processor = new HavingProcessor($this->options); + $out['HAVING'] = $processor->process($out['HAVING'], isset($out['SELECT']) ? $out['SELECT'] : array()); } if (!empty($out['SET'])) { - $processor = new SetProcessor(); + $processor = new SetProcessor($this->options); $out['SET'] = $processor->process($out['SET'], isset($out['UPDATE'])); } if (!empty($out['DUPLICATE'])) { - $processor = new DuplicateProcessor(); + $processor = new DuplicateProcessor($this->options); $out['ON DUPLICATE KEY UPDATE'] = $processor->process($out['DUPLICATE']); unset($out['DUPLICATE']); } if (!empty($out['INSERT'])) { - $processor = new InsertProcessor(); + $processor = new InsertProcessor($this->options); $out = $processor->process($out); } if (!empty($out['REPLACE'])) { - $processor = new ReplaceProcessor(); + $processor = new ReplaceProcessor($this->options); $out = $processor->process($out); } if (!empty($out['DELETE'])) { - $processor = new DeleteProcessor(); + $processor = new DeleteProcessor($this->options); $out = $processor->process($out); } if (!empty($out['VALUES'])) { - $processor = new ValuesProcessor(); + $processor = new ValuesProcessor($this->options); $out = $processor->process($out); } if (!empty($out['INTO'])) { - $processor = new IntoProcessor(); + $processor = new IntoProcessor($this->options); $out = $processor->process($out); } if (!empty($out['DROP'])) { - $processor = new DropProcessor(); + $processor = new DropProcessor($this->options); $out['DROP'] = $processor->process($out['DROP']); } if (!empty($out['RENAME'])) { - $processor = new RenameProcessor(); + $processor = new RenameProcessor($this->options); $out['RENAME'] = $processor->process($out['RENAME']); } if (!empty($out['SHOW'])) { - $processor = new ShowProcessor(); + $processor = new ShowProcessor($this->options); $out['SHOW'] = $processor->process($out['SHOW']); } + if (!empty($out['OPTIONS'])) { + $processor = new OptionsProcessor($this->options); + $out['OPTIONS'] = $processor->process($out['OPTIONS']); + } + if (!empty($out['WITH'])) { + $processor = new WithProcessor($this->options); + $out['WITH'] = $processor->process($out['WITH']); + } + return $out; } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/SQLProcessor.php b/tools/parser_sql/processors/SQLProcessor.php index 19804894e..4c8ccfc35 100644 --- a/tools/parser_sql/processors/SQLProcessor.php +++ b/tools/parser_sql/processors/SQLProcessor.php @@ -4,47 +4,56 @@ * * This file implements the processor for the base SQL statements. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); -require_once(dirname(__FILE__) . '/SQLChunkProcessor.php'); +namespace PHPSQLParser\processors; /** - * * This class processes the base SQL statements. - * - * @author arothe - * + * + * @author André Rothe + * @author Marco Th. + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class SQLProcessor extends SQLChunkProcessor { - /* + /** * This function breaks up the SQL statement into logical sections. - * Some sections are then further handled by specialized processors. + * Some sections are delegated to specialized processors. */ public function process($tokens) { $prev_category = ""; @@ -52,15 +61,24 @@ class SQLProcessor extends SQLChunkProcessor { $skip_next = 0; $out = false; - $tokenCount = count($tokens); + // $tokens may come as a numeric indexed array starting with an index greater than 0 (or as a boolean) + $tokenCount = count($tokens); + if ( is_array($tokens) ){ + $tokens = array_values($tokens); + } for ($tokenNumber = 0; $tokenNumber < $tokenCount; ++$tokenNumber) { + // https://github.com/greenlion/PHP-SQL-Parser/issues/279 + // https://github.com/sinri/PHP-SQL-Parser/commit/eac592a0e19f1df6f420af3777a6d5504837faa7 + // as there is no pull request for 279 by the user. His solution works and tested. + if (!isset($tokens[$tokenNumber])) continue;// as a fix by Sinri 20180528 $token = $tokens[$tokenNumber]; $trim = trim($token); // this removes also \n and \t! // if it starts with an "(", it should follow a SELECT if ($trim !== "" && $trim[0] === "(" && $token_category === "") { - $token_category = 'SELECT'; + $token_category = 'BRACKET'; + $prev_category = $token_category; } /* @@ -68,12 +86,12 @@ class SQLProcessor extends SQLChunkProcessor { */ if ($skip_next > 0) { if ($trim === "") { - if ($token_category !== "") { # is this correct?? + if ($token_category !== "") { // is this correct?? $out[$token_category][] = $token; } continue; } - #to skip the token we replace it with whitespace + // to skip the token we replace it with whitespace $trim = ""; $token = ""; $skip_next--; @@ -88,7 +106,6 @@ class SQLProcessor extends SQLChunkProcessor { /* Tokens that get their own sections. These keywords have subclauses. */ case 'SELECT': case 'ORDER': - case 'DUPLICATE': case 'VALUES': case 'GROUP': case 'HAVING': @@ -110,6 +127,9 @@ class SQLProcessor extends SQLChunkProcessor { case 'PURGE': case 'EXECUTE': case 'PREPARE': + $token_category = $upper; + break; + case 'DEALLOCATE': if ($trim === 'DEALLOCATE') { $skip_next = 1; @@ -117,6 +137,12 @@ class SQLProcessor extends SQLChunkProcessor { $token_category = $upper; break; + case 'DUPLICATE': + if ($token_category !== 'VALUES') { + $token_category = $upper; + } + break; + case 'SET': if ($token_category !== 'TABLE') { $token_category = $upper; @@ -125,21 +151,21 @@ class SQLProcessor extends SQLChunkProcessor { case 'LIMIT': case 'PLUGIN': - # no separate section + // no separate section if ($token_category === 'SHOW') { - continue; + break; } $token_category = $upper; break; case 'FROM': - # this FROM is different from FROM in other DML (not join related) + // this FROM is different from FROM in other DML (not join related) if ($token_category === 'PREPARE') { continue 2; } - # no separate section + // no separate section if ($token_category === 'SHOW') { - continue; + break; } $token_category = $upper; break; @@ -149,7 +175,7 @@ class SQLProcessor extends SQLChunkProcessor { case 'SHOW': $token_category = $upper; break; - + case 'DESC': if ($token_category === '') { // short version of DESCRIBE @@ -159,18 +185,16 @@ class SQLProcessor extends SQLChunkProcessor { break; case 'RENAME': - // jump over TABLE keyword $token_category = $upper; - $skip_next = 1; - continue 2; + break; case 'DATABASE': case 'SCHEMA': if ($prev_category === 'DROP') { - continue; + break; } if ($prev_category === 'SHOW') { - continue; + break; } $token_category = $upper; break; @@ -192,10 +216,10 @@ class SQLProcessor extends SQLChunkProcessor { case 'INTO': // prevent wrong handling of CACHE within LOAD INDEX INTO CACHE... if ($prev_category === 'LOAD') { - $out[$prev_category][] = $upper; + $out[$prev_category][] = $trim; continue 2; } - $token_category = $upper; + $token_category = $prev_category = $upper; break; case 'USER': @@ -234,60 +258,74 @@ class SQLProcessor extends SQLChunkProcessor { case 'CHECKSUM': case 'REPAIR': case 'RESTORE': - case 'USE': case 'HELP': $token_category = $upper; // set the category in case these get subclauses in a future version of MySQL - $out[$upper][0] = $upper; + $out[$upper][0] = $trim; continue 2; case 'REPLACE': - if ($prev_category === 'TABLE') { - # part of the CREATE TABLE statement - $out[$prev_category][] = $upper; - continue 2; - } - // set the category in case these get subclauses in a future version of MySQL - $token_category = $upper; - $out[$upper][0] = $upper; + if ($prev_category === '') { + // set the category in case these get subclauses in a future version of MySQL + $token_category = $upper; + $out[$upper][0] = $trim; + continue 2; + } + // part of the CREATE TABLE statement or a function + $out[$prev_category][] = $trim; continue 2; case 'IGNORE': if ($prev_category === 'TABLE') { - # part of the CREATE TABLE statement - $out[$prev_category][] = $upper; + // part of the CREATE TABLE statement + $out[$prev_category][] = $trim; + continue 2; + } + if ($token_category === 'FROM') { + // part of the FROM statement (index hint) + $out[$token_category][] = $trim; continue 2; } $out['OPTIONS'][] = $upper; continue 2; - break; case 'CHECK': if ($prev_category === 'TABLE') { - $out[$prev_category][] = $upper; + $out[$prev_category][] = $trim; continue 2; } $token_category = $upper; - $out[$upper][0] = $upper; + $out[$upper][0] = $trim; continue 2; case 'CREATE': if ($prev_category === 'SHOW') { - continue; + break; } $token_category = $upper; break; + case 'INDEX': + if ( in_array( $prev_category, array( 'CREATE', 'DROP' ) ) ) { + $out[ $prev_category ][] = $trim; + $token_category = $upper; + } + break; + case 'TABLE': if ($prev_category === 'CREATE') { - $out[$prev_category][] = $upper; + $out[$prev_category][] = $trim; + $token_category = $upper; + } + if ($prev_category === 'TRUNCATE') { + $out[$prev_category][] = $trim; $token_category = $upper; } break; case 'TEMPORARY': if ($prev_category === 'CREATE') { - $out[$prev_category][] = $upper; + $out[$prev_category][] = $trim; $token_category = $prev_category; continue 2; } @@ -298,7 +336,7 @@ class SQLProcessor extends SQLChunkProcessor { $token_category = 'CREATE'; $out[$token_category] = array_merge($out[$token_category], $out[$prev_category]); $out[$prev_category] = array(); - $out[$token_category][] = $upper; + $out[$token_category][] = $trim; $prev_category = $token_category; continue 2; } @@ -307,14 +345,14 @@ class SQLProcessor extends SQLChunkProcessor { case 'NOT': if ($prev_category === 'CREATE') { $token_category = $prev_category; - $out[$prev_category][] = $upper; + $out[$prev_category][] = $trim; continue 2; } break; case 'EXISTS': if ($prev_category === 'CREATE') { - $out[$prev_category][] = $upper; + $out[$prev_category][] = $trim; $prev_category = $token_category = 'TABLE'; continue 2; } @@ -322,7 +360,7 @@ class SQLProcessor extends SQLChunkProcessor { case 'CACHE': if ($prev_category === "" || $prev_category === 'RESET' || $prev_category === 'FLUSH' - || $prev_category === 'LOAD') { + || $prev_category === 'LOAD') { $token_category = $upper; continue 2; } @@ -332,14 +370,15 @@ class SQLProcessor extends SQLChunkProcessor { case 'LOCK': if ($token_category === "") { $token_category = $upper; - $out[$upper][0] = $upper; + $out[$upper][0] = $trim; + } elseif ($token_category === 'INDEX') { + break; } else { $trim = 'LOCK IN SHARE MODE'; $skip_next = 3; $out['OPTIONS'][] = $trim; } continue 2; - break; case 'USING': /* USING in FROM clause is different from USING w/ prepared statement*/ if ($token_category === 'EXECUTE') { @@ -362,12 +401,11 @@ class SQLProcessor extends SQLChunkProcessor { case 'FOR': if ($prev_category === 'SHOW') { - continue; + break; } $skip_next = 1; - $out['OPTIONS'][] = 'FOR UPDATE'; + $out['OPTIONS'][] = 'FOR UPDATE'; // TODO: this could be generate problems within the position calculator continue 2; - break; case 'UPDATE': if ($token_category === "") { @@ -381,22 +419,30 @@ class SQLProcessor extends SQLChunkProcessor { case 'START': $trim = "BEGIN"; - $out[$upper][0] = $upper; + $out[$upper][0] = $upper; // TODO: this could be generate problems within the position calculator $skip_next = 1; break; - /* These tokens are ignored. */ + // This token is ignored, except within RENAME case 'TO': if ($token_category === 'RENAME') { break; } + continue 2; + + // This token is ignored, except within CREATE TABLE case 'BY': + if ($prev_category === 'TABLE') { + break; + } + continue 2; + + // These tokens are ignored. case 'ALL': case 'SHARE': case 'MODE': case ';': continue 2; - break; case 'KEY': if ($token_category === 'DUPLICATE') { @@ -404,21 +450,43 @@ class SQLProcessor extends SQLChunkProcessor { } break; - /* These tokens set particular options for the statement. They never stand alone. */ + /* These tokens set particular options for the statement. */ case 'LOW_PRIORITY': case 'DELAYED': - case 'FORCE': case 'QUICK': - $out['OPTIONS'][] = $upper; + case 'HIGH_PRIORITY': + $out['OPTIONS'][] = $trim; + continue 2; + + case 'USE': + if ($token_category === 'FROM') { + // index hint within FROM clause + $out[$token_category][] = $trim; + continue 2; + } + // set the category in case these get subclauses in a future version of MySQL + $token_category = $upper; + $out[$upper][0] = $trim; + continue 2; + + case 'FORCE': + if ($token_category === 'FROM') { + // index hint within FROM clause + $out[$token_category][] = $trim; + continue 2; + } + $out['OPTIONS'][] = $trim; continue 2; - break; case 'WITH': if ($token_category === 'GROUP') { $skip_next = 1; - $out['OPTIONS'][] = 'WITH ROLLUP'; + $out['OPTIONS'][] = 'WITH ROLLUP'; // TODO: this could be generate problems within the position calculator continue 2; } + if ($token_category === '') { + $token_category = $upper; + } break; case 'AS': @@ -426,7 +494,6 @@ class SQLProcessor extends SQLChunkProcessor { case '': case ',': - case ';': break; default: @@ -445,4 +512,4 @@ class SQLProcessor extends SQLChunkProcessor { return parent::process($out); } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/SelectExpressionProcessor.php b/tools/parser_sql/processors/SelectExpressionProcessor.php index 360dc0a3a..5d6f846a7 100644 --- a/tools/parser_sql/processors/SelectExpressionProcessor.php +++ b/tools/parser_sql/processors/SelectExpressionProcessor.php @@ -30,23 +30,21 @@ * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); -require_once(dirname(__FILE__) . '/ExpressionListProcessor.php'); -require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; /** - * + * * This class processes the SELECT expressions. - * + * * @author arothe - * + * */ class SelectExpressionProcessor extends AbstractProcessor { - private $expressionListProcessor; - - public function __construct() { - $this->expressionListProcessor = new ExpressionListProcessor(); + protected function processExpressionList($unparsed) { + $processor = new ExpressionListProcessor($this->options); + return $processor->process($unparsed); } /** @@ -62,8 +60,8 @@ class SelectExpressionProcessor extends AbstractProcessor { } /* - * Determine if there is an explicit alias after the AS clause. - * If AS is found, then the next non-whitespace token is captured as the alias. + * Determine if there is an explicit alias after the AS clause. + * If AS is found, then the next non-whitespace token is captured as the alias. * The tokens after (and including) the AS are removed. */ $base_expr = ""; @@ -102,7 +100,14 @@ class SelectExpressionProcessor extends AbstractProcessor { $base_expr .= $token; } - $stripped = $this->expressionListProcessor->process($stripped); + if ($alias) { + // remove quotation from the alias + $alias['no_quotes'] = $this->revokeQuotation($alias['name']); + $alias['name'] = trim($alias['name']); + $alias['base_expr'] = trim($alias['base_expr']); + } + + $stripped = $this->processExpressionList($stripped); // TODO: the last part can also be a comment, don't use array_pop @@ -118,34 +123,24 @@ class SelectExpressionProcessor extends AbstractProcessor { if ($this->isReserved($prev) || $this->isConstant($prev) || $this->isAggregateFunction($prev) || $this->isFunction($prev) || $this->isExpression($prev) || $this->isSubQuery($prev) - || $this->isColumnReference($prev) || $this->isBracketExpression($prev)) { + || $this->isColumnReference($prev) || $this->isBracketExpression($prev)|| $this->isCustomFunction($prev)) { $alias = array('as' => false, 'name' => trim($last['base_expr']), 'no_quotes' => $this->revokeQuotation($last['base_expr']), 'base_expr' => trim($last['base_expr'])); // remove the last token array_pop($tokens); - $base_expr = join("", $tokens); } } - if (!$alias) { - $base_expr = join("", $tokens); - } else { - /* remove escape from the alias */ - $alias['no_quotes'] = $this->revokeQuotation($alias['name']); - $alias['name'] = trim($alias['name']); - $alias['base_expr'] = trim($alias['base_expr']); - } + $base_expr = $expression; // TODO: this is always done with $stripped, how we do it twice? - $processed = $this->expressionListProcessor->process($tokens); + $processed = $this->processExpressionList($tokens); // if there is only one part, we copy the expr_type - // in all other cases we use "expression" as global type + // in all other cases we use "EXPRESSION" as global type $type = ExpressionType::EXPRESSION; - $no_quotes = $this->revokeQuotation(trim($base_expr)); - if (count($processed) === 1) { if (!$this->isSubQuery($processed[0])) { $type = $processed[0]['expr_type']; @@ -162,9 +157,9 @@ class SelectExpressionProcessor extends AbstractProcessor { if (!empty($no_quotes)) { $result['no_quotes'] = $no_quotes; } - $result['sub_tree'] = $processed; + $result['sub_tree'] = (empty($processed) ? false : $processed); return $result; } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/SelectProcessor.php b/tools/parser_sql/processors/SelectProcessor.php index 596a6069b..d5c6cb759 100644 --- a/tools/parser_sql/processors/SelectProcessor.php +++ b/tools/parser_sql/processors/SelectProcessor.php @@ -30,7 +30,7 @@ * DAMAGE. */ -require_once(dirname(__FILE__) . '/SelectExpressionProcessor.php'); +namespace PHPSQLParser\processors; /** * @@ -50,6 +50,8 @@ class SelectProcessor extends SelectExpressionProcessor { $expression['delim'] = ','; $expressionList[] = $expression; $expression = ""; + } else if ($this->isCommentToken($token)) { + $expressionList[] = parent::processComment($token); } else { switch (strtoupper($token)) { diff --git a/tools/parser_sql/processors/SetProcessor.php b/tools/parser_sql/processors/SetProcessor.php index 42b083ded..7fd1f7c6a 100644 --- a/tools/parser_sql/processors/SetProcessor.php +++ b/tools/parser_sql/processors/SetProcessor.php @@ -30,33 +30,34 @@ * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); -require_once(dirname(__FILE__) . '/ExpressionListProcessor.php'); -require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; /** - * + * * This class processes the SET statements. - * + * * @author arothe - * + * */ class SetProcessor extends AbstractProcessor { - private $expressionListProcessor; - - public function __construct() { - $this->expressionListProcessor = new ExpressionListProcessor(); + protected function processExpressionList($tokens) { + $processor = new ExpressionListProcessor($this->options); + return $processor->process($tokens); } /** * A SET list is simply a list of key = value expressions separated by comma (,). * This function produces a list of the key/value expressions. */ - protected function getAssignment($base_expr) { - $assignment = $this->expressionListProcessor->process($this->splitSQLIntoTokens($base_expr)); + protected function processAssignment($base_expr) { + $assignment = $this->processExpressionList($this->splitSQLIntoTokens($base_expr)); + + // TODO: if the left side of the assignment is a reserved keyword, it should be changed to colref + return array('expr_type' => ExpressionType::EXPRESSION, 'base_expr' => trim($base_expr), - 'sub_tree' => $assignment); + 'sub_tree' => (empty($assignment) ? false : $assignment)); } public function process($tokens, $isUpdate = false) { @@ -66,13 +67,15 @@ class SetProcessor extends AbstractProcessor { $varType = false; foreach ($tokens as $token) { - $upper = strtoupper(trim($token)); + $trim = trim($token); + $upper = strtoupper($trim); switch ($upper) { case 'LOCAL': case 'SESSION': case 'GLOBAL': if (!$isUpdate) { + $result[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $varType = $this->getVariableType("@@" . $upper . "."); $baseExpr = ""; continue 2; @@ -80,7 +83,7 @@ class SetProcessor extends AbstractProcessor { break; case ',': - $assignment = $this->getAssignment($baseExpr); + $assignment = $this->processAssignment($baseExpr); if (!$isUpdate && $varType !== false) { $assignment['sub_tree'][0]['expr_type'] = $varType; } @@ -95,7 +98,7 @@ class SetProcessor extends AbstractProcessor { } if (trim($baseExpr) !== "") { - $assignment = $this->getAssignment($baseExpr); + $assignment = $this->processAssignment($baseExpr); if (!$isUpdate && $varType !== false) { $assignment['sub_tree'][0]['expr_type'] = $varType; } diff --git a/tools/parser_sql/processors/ShowProcessor.php b/tools/parser_sql/processors/ShowProcessor.php index bc56f027e..1fc16bbbd 100644 --- a/tools/parser_sql/processors/ShowProcessor.php +++ b/tools/parser_sql/processors/ShowProcessor.php @@ -30,24 +30,25 @@ * DAMAGE. */ -require_once(dirname(__FILE__) . '/../utils/PHPSQLParserConstants.php'); -require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); -require_once(dirname(__FILE__) . '/LimitProcessor.php'); -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); +namespace PHPSQLParser\processors; +use PHPSQLParser\Options; +use PHPSQLParser\utils\ExpressionType; +use PHPSQLParser\utils\PHPSQLParserConstants; /** - * + * * This class processes the SHOW statements. - * + * * @author arothe - * + * */ class ShowProcessor extends AbstractProcessor { private $limitProcessor; - public function __construct() { - $this->limitProcessor = new LimitProcessor(); + public function __construct(Options $options) { + parent::__construct($options); + $this->limitProcessor = new LimitProcessor($options); } public function process($tokens) { @@ -67,13 +68,14 @@ class ShowProcessor extends AbstractProcessor { case 'FROM': $resultList[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => trim($token)); if ($prev === 'INDEX' || $prev === 'COLUMNS') { - continue; + break; } $category = $upper; break; case 'CREATE': case 'DATABASE': + case 'SCHEMA': case 'FUNCTION': case 'PROCEDURE': case 'ENGINE': @@ -99,6 +101,7 @@ class ShowProcessor extends AbstractProcessor { case 'TRIGGERS': case 'VARIABLES': case 'DATABASES': + case 'SCHEMAS': case 'ERRORS': case 'TABLES': case 'WARNINGS': @@ -120,6 +123,7 @@ class ShowProcessor extends AbstractProcessor { $resultList[] = $limit; break; case 'FROM': + case 'SCHEMA': case 'DATABASE': $resultList[] = array('expr_type' => ExpressionType::DATABASE, 'name' => $token, 'no_quotes' => $this->revokeQuotation($token), 'base_expr' => $token); @@ -136,7 +140,7 @@ class ShowProcessor extends AbstractProcessor { $category = "TABLENAME"; break; case 'FUNCTION': - if (PHPSQLParserConstants::isAggregateFunction($upper)) { + if (PHPSQLParserConstants::getInstance()->isAggregateFunction($upper)) { $expr_type = ExpressionType::AGGREGATE_FUNCTION; } else { $expr_type = ExpressionType::SIMPLE_FUNCTION; diff --git a/tools/parser_sql/processors/SubpartitionDefinitionProcessor.php b/tools/parser_sql/processors/SubpartitionDefinitionProcessor.php new file mode 100644 index 000000000..705ab0202 --- /dev/null +++ b/tools/parser_sql/processors/SubpartitionDefinitionProcessor.php @@ -0,0 +1,273 @@ + + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ + * + */ + +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; + +/** + * This class processes the SUBPARTITION statements within CREATE TABLE. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class SubpartitionDefinitionProcessor extends AbstractProcessor { + + protected function getReservedType($token) { + return array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $token); + } + + protected function getConstantType($token) { + return array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $token); + } + + protected function getOperatorType($token) { + return array('expr_type' => ExpressionType::OPERATOR, 'base_expr' => $token); + } + + protected function getBracketExpressionType($token) { + return array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $token, 'sub_tree' => false); + } + + public function process($tokens) { + + $result = array(); + $prevCategory = ''; + $currCategory = ''; + $parsed = array(); + $expr = array(); + $base_expr = ''; + $skip = 0; + + foreach ($tokens as $tokenKey => $token) { + $trim = trim($token); + $base_expr .= $token; + + if ($skip > 0) { + $skip--; + continue; + } + + if ($skip < 0) { + break; + } + + if ($trim === '') { + continue; + } + + $upper = strtoupper($trim); + switch ($upper) { + + case 'SUBPARTITION': + if ($currCategory === '') { + $expr[] = $this->getReservedType($trim); + $parsed = array('expr_type' => ExpressionType::SUBPARTITION_DEF, 'base_expr' => trim($base_expr), + 'sub_tree' => false); + $currCategory = $upper; + continue 2; + } + // else ? + break; + + case 'COMMENT': + if ($prevCategory === 'SUBPARTITION') { + $expr[] = array('expr_type' => ExpressionType::SUBPARTITION_COMMENT, 'base_expr' => false, + 'sub_tree' => false, 'storage' => substr($base_expr, 0, -strlen($token))); + + $parsed['sub_tree'] = $expr; + $base_expr = $token; + $expr = array($this->getReservedType($trim)); + + $currCategory = $upper; + continue 2; + } + // else ? + break; + + case 'STORAGE': + if ($prevCategory === 'SUBPARTITION') { + // followed by ENGINE + $expr[] = array('expr_type' => ExpressionType::ENGINE, 'base_expr' => false, 'sub_tree' => false, + 'storage' => substr($base_expr, 0, -strlen($token))); + + $parsed['sub_tree'] = $expr; + $base_expr = $token; + $expr = array($this->getReservedType($trim)); + + $currCategory = $upper; + continue 2; + } + // else ? + break; + + case 'ENGINE': + if ($currCategory === 'STORAGE') { + $expr[] = $this->getReservedType($trim); + $currCategory = $upper; + continue 2; + } + if ($prevCategory === 'SUBPARTITION') { + $expr[] = array('expr_type' => ExpressionType::ENGINE, 'base_expr' => false, 'sub_tree' => false, + 'storage' => substr($base_expr, 0, -strlen($token))); + + $parsed['sub_tree'] = $expr; + $base_expr = $token; + $expr = array($this->getReservedType($trim)); + + $currCategory = $upper; + continue 2; + } + // else ? + break; + + case '=': + if (in_array($currCategory, array('ENGINE', 'COMMENT', 'DIRECTORY', 'MAX_ROWS', 'MIN_ROWS'))) { + $expr[] = $this->getOperatorType($trim); + continue 2; + } + // else ? + break; + + case ',': + if ($prevCategory === 'SUBPARTITION' && $currCategory === '') { + // it separates the subpartition-definitions + $result[] = $parsed; + $parsed = array(); + $base_expr = ''; + $expr = array(); + } + break; + + case 'DATA': + case 'INDEX': + if ($prevCategory === 'SUBPARTITION') { + // followed by DIRECTORY + $expr[] = array('expr_type' => constant('PHPSQLParser\utils\ExpressionType::SUBPARTITION_' . $upper . '_DIR'), + 'base_expr' => false, 'sub_tree' => false, + 'storage' => substr($base_expr, 0, -strlen($token))); + + $parsed['sub_tree'] = $expr; + $base_expr = $token; + $expr = array($this->getReservedType($trim)); + + $currCategory = $upper; + continue 2; + } + // else ? + break; + + case 'DIRECTORY': + if ($currCategory === 'DATA' || $currCategory === 'INDEX') { + $expr[] = $this->getReservedType($trim); + $currCategory = $upper; + continue 2; + } + // else ? + break; + + case 'MAX_ROWS': + case 'MIN_ROWS': + if ($prevCategory === 'SUBPARTITION') { + $expr[] = array('expr_type' => constant('PHPSQLParser\utils\ExpressionType::SUBPARTITION_' . $upper), + 'base_expr' => false, 'sub_tree' => false, + 'storage' => substr($base_expr, 0, -strlen($token))); + + $parsed['sub_tree'] = $expr; + $base_expr = $token; + $expr = array($this->getReservedType($trim)); + + $currCategory = $upper; + continue 2; + } + // else ? + break; + + default: + switch ($currCategory) { + + case 'MIN_ROWS': + case 'MAX_ROWS': + case 'ENGINE': + case 'DIRECTORY': + case 'COMMENT': + $expr[] = $this->getConstantType($trim); + + $last = array_pop($parsed['sub_tree']); + $last['sub_tree'] = $expr; + $last['base_expr'] = trim($base_expr); + $base_expr = $last['storage'] . $base_expr; + unset($last['storage']); + + $parsed['sub_tree'][] = $last; + $parsed['base_expr'] = trim($base_expr); + $expr = $parsed['sub_tree']; + unset($last); + + $currCategory = $prevCategory; + break; + + case 'SUBPARTITION': + // that is the subpartition name + $last = array_pop($expr); + $last['name'] = $trim; + $expr[] = $last; + $expr[] = $this->getConstantType($trim); + $parsed['sub_tree'] = $expr; + $parsed['base_expr'] = trim($base_expr); + break; + + default: + break; + } + break; + } + + $prevCategory = $currCategory; + $currCategory = ''; + } + + $result[] = $parsed; + return $result; + } +} +?> diff --git a/tools/parser_sql/processors/TableProcessor.php b/tools/parser_sql/processors/TableProcessor.php index cb023457f..248fe3b4c 100644 --- a/tools/parser_sql/processors/TableProcessor.php +++ b/tools/parser_sql/processors/TableProcessor.php @@ -4,41 +4,49 @@ * * This file implements the processor for the TABLE statements. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); -require_once(dirname(__FILE__) . '/CreateDefinitionProcessor.php'); -require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; /** - * * This class processes the TABLE statements. * - * @author arothe + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class TableProcessor extends AbstractProcessor { @@ -55,6 +63,16 @@ class TableProcessor extends AbstractProcessor { return array('expr_type' => ExpressionType::OPERATOR, 'base_expr' => $token); } + protected function processPartitionOptions($tokens) { + $processor = new PartitionOptionsProcessor($this->options); + return $processor->process($tokens); + } + + protected function processCreateDefinition($tokens) { + $processor = new CreateDefinitionProcessor($this->options); + return $processor->process($tokens); + } + protected function clear(&$expr, &$base_expr, &$category) { $expr = array(); $base_expr = ''; @@ -63,14 +81,14 @@ class TableProcessor extends AbstractProcessor { public function process($tokens) { - $currCategory = "TABLE_NAME"; + $currCategory = 'TABLE_NAME'; $result = array('base_expr' => false, 'name' => false, 'no_quotes' => false, 'create-def' => false, 'options' => false, 'like' => false, 'select-option' => false); $expr = array(); $base_expr = ''; $skip = 0; - foreach ($tokens as $token) { + foreach ($tokens as $tokenKey => $token) { $trim = trim($token); $base_expr .= $token; @@ -83,7 +101,7 @@ class TableProcessor extends AbstractProcessor { break; } - if ($trim === "") { + if ($trim === '') { continue; } @@ -91,12 +109,12 @@ class TableProcessor extends AbstractProcessor { switch ($upper) { case ',': - # it is possible to separate the table options with comma! + // it is possible to separate the table options with comma! if ($prevCategory === 'CREATE_DEF') { $last = array_pop($result['options']); $last['delim'] = ','; $result['options'][] = $last; - $base_expr = ""; + $base_expr = ''; } continue 2; @@ -109,7 +127,7 @@ class TableProcessor extends AbstractProcessor { break; case 'LIKE': - # like without parenthesis + // like without parenthesis if ($prevCategory === 'TABLE_NAME') { $currCategory = $upper; continue 2; @@ -117,10 +135,10 @@ class TableProcessor extends AbstractProcessor { break; case '=': - # the optional operator + // the optional operator if ($prevCategory === 'TABLE_OPTION') { $expr[] = $this->getOperatorType($trim); - continue 2; # don't change the category + continue 2; // don't change the category } break; @@ -130,15 +148,16 @@ class TableProcessor extends AbstractProcessor { $currCategory = 'TABLE_OPTION'; } if ($prevCategory === 'TABLE_OPTION') { - # add it to the previous DEFAULT + // add it to the previous DEFAULT $expr[] = $this->getReservedType($trim); continue 2; } break; case 'SET': + case 'CHARSET': if ($prevCategory === 'TABLE_OPTION') { - # add it to a previous CHARACTER + // add it to a previous CHARACTER $expr[] = $this->getReservedType($trim); $currCategory = 'CHARSET'; continue 2; @@ -146,8 +165,8 @@ class TableProcessor extends AbstractProcessor { break; case 'COLLATE': - if ($prevCategory === 'TABLE_OPTION') { - # add it to the previous DEFAULT + if ($prevCategory === 'TABLE_OPTION' || $prevCategory === 'CREATE_DEF') { + // add it to the previous DEFAULT $expr[] = $this->getReservedType($trim); $currCategory = 'COLLATE'; continue 2; @@ -156,7 +175,7 @@ class TableProcessor extends AbstractProcessor { case 'DIRECTORY': if ($currCategory === 'INDEX_DIRECTORY' || $currCategory === 'DATA_DIRECTORY') { - # after INDEX or DATA + // after INDEX or DATA $expr[] = $this->getReservedType($trim); continue 2; } @@ -212,16 +231,15 @@ class TableProcessor extends AbstractProcessor { case 'LAST': case 'DEFAULT': if ($prevCategory === 'CREATE_DEF') { - # DEFAULT before CHARACTER SET and COLLATE + // DEFAULT before CHARACTER SET and COLLATE $expr[] = $this->getReservedType($trim); $currCategory = 'TABLE_OPTION'; } if ($prevCategory === 'TABLE_OPTION') { - # all assignments with the keywords + // all assignments with the keywords $expr[] = $this->getReservedType($trim); $result['options'][] = array('expr_type' => ExpressionType::EXPRESSION, - 'base_expr' => trim($base_expr), 'delim' => ' ', - 'sub_tree' => $expr); + 'base_expr' => trim($base_expr), 'delim' => ' ', 'sub_tree' => $expr); $this->clear($expr, $base_expr, $currCategory); } break; @@ -244,46 +262,47 @@ class TableProcessor extends AbstractProcessor { continue 2; case 'PARTITION': - # TODO: parse partition options - $skip = -1; + if ($prevCategory === 'CREATE_DEF') { + $part = $this->processPartitionOptions(array_slice($tokens, $tokenKey - 1, null, true)); + $skip = $part['last-parsed'] - $tokenKey; + $result['partition-options'] = $part['partition-options']; + continue 2; + } + // else break; default: switch ($currCategory) { case 'CHARSET': - # the charset name + // the charset name $expr[] = $this->getConstantType($trim); $result['options'][] = array('expr_type' => ExpressionType::CHARSET, - 'base_expr' => trim($base_expr), 'delim' => ' ', - 'sub_tree' => $expr); + 'base_expr' => trim($base_expr), 'delim' => ' ', 'sub_tree' => $expr); $this->clear($expr, $base_expr, $currCategory); break; case 'COLLATE': - # the collate name + // the collate name $expr[] = $this->getConstantType($trim); $result['options'][] = array('expr_type' => ExpressionType::COLLATE, - 'base_expr' => trim($base_expr), 'delim' => ' ', - 'sub_tree' => $expr); + 'base_expr' => trim($base_expr), 'delim' => ' ', 'sub_tree' => $expr); $this->clear($expr, $base_expr, $currCategory); break; case 'DATA_DIRECTORY': - # we have the directory name + // we have the directory name $expr[] = $this->getConstantType($trim); $result['options'][] = array('expr_type' => ExpressionType::DIRECTORY, 'kind' => 'DATA', - 'base_expr' => trim($base_expr), 'delim' => ' ', - 'sub_tree' => $expr); + 'base_expr' => trim($base_expr), 'delim' => ' ', 'sub_tree' => $expr); $this->clear($expr, $base_expr, $prevCategory); continue 3; case 'INDEX_DIRECTORY': - # we have the directory name + // we have the directory name $expr[] = $this->getConstantType($trim); $result['options'][] = array('expr_type' => ExpressionType::DIRECTORY, 'kind' => 'INDEX', - 'base_expr' => trim($base_expr), 'delim' => ' ', - 'sub_tree' => $expr); + 'base_expr' => trim($base_expr), 'delim' => ' ', 'sub_tree' => $expr); $this->clear($expr, $base_expr, $prevCategory); continue 3; @@ -294,17 +313,16 @@ class TableProcessor extends AbstractProcessor { break; case 'LIKE': - $result['like'] = array('expr_type' => ExpressionType::TABLE, 'table' => $trim, 'base_expr' => $trim, - 'no_quotes' => $this->revokeQuotation($trim)); + $result['like'] = array('expr_type' => ExpressionType::TABLE, 'table' => $trim, + 'base_expr' => $trim, 'no_quotes' => $this->revokeQuotation($trim)); $this->clear($expr, $base_expr, $currCategory); break; case '': - # after table name + // after table name if ($prevCategory === 'TABLE_NAME' && $upper[0] === '(' && substr($upper, -1) === ')') { $unparsed = $this->splitSQLIntoTokens($this->removeParenthesisFromStart($trim)); - $processor = new CreateDefinitionProcessor(); - $coldef = $processor->process($unparsed); + $coldef = $this->processCreateDefinition($unparsed); $result['create-def'] = array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $base_expr, 'sub_tree' => $coldef['create-def']); $expr = array(); @@ -314,10 +332,10 @@ class TableProcessor extends AbstractProcessor { break; case 'UNION': - # TODO: this token starts and ends with parenthesis - # and contains a list of table names (comma-separated) - # split the token and add the list as subtree - # we must change the DefaultProcessor + // TODO: this token starts and ends with parenthesis + // and contains a list of table names (comma-separated) + // split the token and add the list as subtree + // we must change the DefaultProcessor $unparsed = $this->splitSQLIntoTokens($this->removeParenthesisFromStart($trim)); $expr[] = array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $trim, @@ -328,11 +346,10 @@ class TableProcessor extends AbstractProcessor { break; default: - # strings and numeric constants + // strings and numeric constants $expr[] = $this->getConstantType($trim); $result['options'][] = array('expr_type' => ExpressionType::EXPRESSION, - 'base_expr' => trim($base_expr), 'delim' => ' ', - 'sub_tree' => $expr); + 'base_expr' => trim($base_expr), 'delim' => ' ', 'sub_tree' => $expr); $this->clear($expr, $base_expr, $currCategory); break; } @@ -340,7 +357,7 @@ class TableProcessor extends AbstractProcessor { } $prevCategory = $currCategory; - $currCategory = ""; + $currCategory = ''; } if ($result['like'] === false) { diff --git a/tools/parser_sql/processors/UnionProcessor.php b/tools/parser_sql/processors/UnionProcessor.php index 3e46a8527..2b37e537f 100644 --- a/tools/parser_sql/processors/UnionProcessor.php +++ b/tools/parser_sql/processors/UnionProcessor.php @@ -1,50 +1,66 @@ + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); -require_once(dirname(__FILE__) . '/SQLProcessor.php'); -require_once(dirname(__FILE__) . '/DefaultProcessor.php'); -require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); +namespace PHPSQLParser\processors; /** - * * This class processes the UNION statements. - * - * @author arothe - * + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class UnionProcessor extends AbstractProcessor { - public function isUnion($queries) { + protected function processDefault($token) { + $processor = new DefaultProcessor($this->options); + return $processor->process($token); + } + + protected function processSQL($token) { + $processor = new SQLProcessor($this->options); + return $processor->process($token); + } + + public static function isUnion($queries) { $unionTypes = array('UNION', 'UNION ALL'); foreach ($unionTypes as $unionType) { if (!empty($queries[$unionType])) { @@ -81,21 +97,66 @@ class UnionProcessor extends AbstractProcessor { // starts with "(select" if (preg_match("/^\\(\\s*select\\s*/i", $token)) { - $processor = new DefaultProcessor(); - $queries[$unionType][$key] = $processor->process($this->removeParenthesisFromStart($token)); + $queries[$unionType][$key] = $this->processDefault($this->removeParenthesisFromStart($token)); break; } - - $processor = new SQLProcessor(); - $queries[$unionType][$key] = $processor->process($queries[$unionType][$key]); + $queries[$unionType][$key] = $this->processSQL($queries[$unionType][$key]); break; } } } + // it can be parsed or not return $queries; } + /** + * Moves the final union query into a separate output, so the remainder (such as ORDER BY) can + * be processed separately. + */ + protected function splitUnionRemainder($queries, $unionType, $outputArray) + { + $finalQuery = []; + + //If this token contains a matching pair of brackets at the start and end, use it as the final query + $finalQueryFound = false; + if (count($outputArray) === 1) { + $tokenAsArray = str_split(trim($outputArray[0])); + if ($tokenAsArray[0] == '(' && $tokenAsArray[count($tokenAsArray)-1] == ')') { + $queries[$unionType][] = $outputArray; + $finalQueryFound = true; + } + } + + if (!$finalQueryFound) { + foreach ($outputArray as $key => $token) { + if (strtoupper($token) == 'ORDER') { + break; + } else { + $finalQuery[] = $token; + unset($outputArray[$key]); + } + } + } + + + $finalQueryString = trim(implode($finalQuery)); + + if (!empty($finalQuery) && $finalQueryString != '') { + $queries[$unionType][] = $finalQuery; + } + + $defaultProcessor = new DefaultProcessor($this->options); + $rePrepareSqlString = trim(implode($outputArray)); + + if (!empty($rePrepareSqlString)) { + $remainingQueries = $defaultProcessor->process($rePrepareSqlString); + $queries[] = $remainingQueries; + } + + return $queries; + } + public function process($inputArray) { $outputArray = array(); @@ -155,7 +216,7 @@ class UnionProcessor extends AbstractProcessor { // or we don't have an UNION/UNION ALL if (!empty($outputArray)) { if ($unionType) { - $queries[$unionType][] = $outputArray; + $queries = $this->splitUnionRemainder($queries, $unionType, $outputArray); } else { $queries[] = $outputArray; } @@ -163,6 +224,5 @@ class UnionProcessor extends AbstractProcessor { return $this->processMySQLUnion($queries); } - } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/UpdateProcessor.php b/tools/parser_sql/processors/UpdateProcessor.php index 8bee5290b..25a88185a 100644 --- a/tools/parser_sql/processors/UpdateProcessor.php +++ b/tools/parser_sql/processors/UpdateProcessor.php @@ -4,42 +4,51 @@ * * This file implements the processor for the UPDATE statements. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/FromProcessor.php'); +namespace PHPSQLParser\processors; /** - * * This class processes the UPDATE statements. - * - * @author arothe - * + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class UpdateProcessor extends FromProcessor { } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/UsingProcessor.php b/tools/parser_sql/processors/UsingProcessor.php index 79e6a52d8..20c10bb45 100644 --- a/tools/parser_sql/processors/UsingProcessor.php +++ b/tools/parser_sql/processors/UsingProcessor.php @@ -4,42 +4,51 @@ * * This file implements the processor for the USING statements. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/FromProcessor.php'); +namespace PHPSQLParser\processors; /** - * * This class processes the USING statements. - * - * @author arothe - * + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class UsingProcessor extends FromProcessor { } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/ValuesProcessor.php b/tools/parser_sql/processors/ValuesProcessor.php index 9c727a0d7..9f388da2b 100644 --- a/tools/parser_sql/processors/ValuesProcessor.php +++ b/tools/parser_sql/processors/ValuesProcessor.php @@ -4,76 +4,146 @@ * * This file implements the processor for the VALUES statements. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); -require_once(dirname(__FILE__) . '/RecordProcessor.php'); -require_once(dirname(__FILE__) . '/AbstractProcessor.php'); +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; /** - * * This class processes the VALUES statements. - * - * @author arothe - * + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class ValuesProcessor extends AbstractProcessor { - private $recordProcessor; + protected function processExpressionList($unparsed) { + $processor = new ExpressionListProcessor($this->options); + return $processor->process($unparsed); + } - public function __construct() { - $this->recordProcessor = new RecordProcessor(); + protected function processRecord($unparsed) { + $processor = new RecordProcessor($this->options); + return $processor->process($unparsed); } public function process($tokens) { - $unparsed = ""; + + $currCategory = ''; + $parsed = array(); + $base_expr = ''; + foreach ($tokens['VALUES'] as $k => $v) { + if ($this->isCommentToken($v)) { + $parsed[] = parent::processComment($v); + continue; + } + + $base_expr .= $v; + $trim = trim($v); + if ($this->isWhitespaceToken($v)) { continue; } - $unparsed .= $v; + + $upper = strtoupper($trim); + switch ($upper) { + + case 'ON': + if ($currCategory === '') { + + $base_expr = trim(substr($base_expr, 0, -strlen($v))); + $parsed[] = array('expr_type' => ExpressionType::RECORD, 'base_expr' => $base_expr, + 'data' => $this->processRecord($base_expr), 'delim' => false); + $base_expr = ''; + + $currCategory = 'DUPLICATE'; + $parsed[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); + } + // else ? + break; + + case 'DUPLICATE': + case 'KEY': + case 'UPDATE': + if ($currCategory === 'DUPLICATE') { + $parsed[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); + $base_expr = ''; + } + // else ? + break; + + case ',': + if ($currCategory === 'DUPLICATE') { + + $base_expr = trim(substr($base_expr, 0, -strlen($v))); + $res = $this->processExpressionList($this->splitSQLIntoTokens($base_expr)); + $parsed[] = array('expr_type' => ExpressionType::EXPRESSION, 'base_expr' => $base_expr, + 'sub_tree' => (empty($res) ? false : $res), 'delim' => $trim); + $base_expr = ''; + continue 2; + } + + $parsed[] = array('expr_type' => ExpressionType::RECORD, 'base_expr' => trim($base_expr), + 'data' => $this->processRecord(trim($base_expr)), 'delim' => $trim); + $base_expr = ''; + break; + + default: + break; + } + } - $values = $this->splitSQLIntoTokens($unparsed); - - $parsed = array(); - foreach ($values as $k => $v) { - if ($this->isCommaToken($v)) { - unset($values[$k]); - } else { - $processor = new RecordProcessor(); - $values[$k] = array('expr_type' => ExpressionType::RECORD, 'base_expr' => $v, - 'data' => $this->recordProcessor->process($v)); + if (trim($base_expr) !== '') { + if ($currCategory === '') { + $parsed[] = array('expr_type' => ExpressionType::RECORD, 'base_expr' => trim($base_expr), + 'data' => $this->processRecord(trim($base_expr)), 'delim' => false); + } + if ($currCategory === 'DUPLICATE') { + $res = $this->processExpressionList($this->splitSQLIntoTokens($base_expr)); + $parsed[] = array('expr_type' => ExpressionType::EXPRESSION, 'base_expr' => trim($base_expr), + 'sub_tree' => (empty($res) ? false : $res), 'delim' => false); } } - $tokens['VALUES'] = array_values($values); + $tokens['VALUES'] = $parsed; return $tokens; } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/WhereProcessor.php b/tools/parser_sql/processors/WhereProcessor.php index 051ea2fb0..2f13c8973 100644 --- a/tools/parser_sql/processors/WhereProcessor.php +++ b/tools/parser_sql/processors/WhereProcessor.php @@ -4,42 +4,51 @@ * * This file implements the processor for the WHERE statements. * - * Copyright (c) 2010-2012, Justin Swanhart - * with contributions by André Rothe + * PHP version 5 * + * LICENSE: + * Copyright (c) 2010-2014 Justin Swanhart and André Rothe * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author André Rothe + * @copyright 2010-2014 Justin Swanhart and André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version SVN: $Id$ * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. */ -require_once(dirname(__FILE__) . '/ExpressionListProcessor.php'); +namespace PHPSQLParser\processors; /** - * * This class processes the WHERE statements. - * - * @author arothe - * + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * */ class WhereProcessor extends ExpressionListProcessor { } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/processors/WithProcessor.php b/tools/parser_sql/processors/WithProcessor.php new file mode 100644 index 000000000..77cf84ca5 --- /dev/null +++ b/tools/parser_sql/processors/WithProcessor.php @@ -0,0 +1,119 @@ + + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + +namespace PHPSQLParser\processors; +use PHPSQLParser\utils\ExpressionType; + +/** + * + * This class processes Oracle's WITH statements. + * + * @author André Rothe + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * + */ +class WithProcessor extends AbstractProcessor { + + protected function processTopLevel($sql) { + $processor = new DefaultProcessor($this->options); + return $processor->process($sql); + } + + protected function buildTableName($token) { + return array('expr_type' => ExpressionType::TEMPORARY_TABLE, 'name'=>$token, 'base_expr' => $token, 'no_quotes' => $this->revokeQuotation($token)); + } + + public function process($tokens) { + $out = array(); + $resultList = array(); + $category = ''; + $base_expr = ''; + $prev = ''; + + foreach ($tokens as $token) { + $base_expr .= $token; + $upper = strtoupper(trim($token)); + + if ($this->isWhitespaceToken($token)) { + continue; + } + + $trim = trim($token); + switch ($upper) { + + case 'AS': + if ($prev !== 'TABLENAME') { + // error or tablename is AS + $resultList[] = $this->buildTableName($trim); + $category = 'TABLENAME'; + break; + } + + $resultList[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); + $category = $upper; + break; + + case ',': + // ignore + $base_expr = ''; + break; + + default: + switch ($prev) { + case 'AS': + // it follows a parentheses pair + $subtree = $this->processTopLevel($this->removeParenthesisFromStart($token)); + $resultList[] = array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $trim, 'sub_tree' => $subtree); + + $out[] = array('expr_type' => ExpressionType::SUBQUERY_FACTORING, 'base_expr' => trim($base_expr), 'sub_tree' => $resultList); + $resultList = array(); + $category = ''; + break; + + case '': + // we have the name of the table + $resultList[] = $this->buildTableName($trim); + $category = 'TABLENAME'; + break; + + default: + // ignore + break; + } + break; + } + $prev = $category; + } + return $out; + } +} +?> \ No newline at end of file diff --git a/tools/parser_sql/utils/ExpressionToken.php b/tools/parser_sql/utils/ExpressionToken.php index ef736220c..e58e36e1c 100644 --- a/tools/parser_sql/utils/ExpressionToken.php +++ b/tools/parser_sql/utils/ExpressionToken.php @@ -1,6 +1,9 @@ upper[0] === '(' && substr($this->upper, -1) === ')'); + return (!empty( $this->upper ) && $this->upper[0] === '(' && substr($this->upper, -1) === ')'); } public function setSubTree($tree) { @@ -53,10 +56,10 @@ class ExpressionToken { return $idx !== false ? $this->token[$idx] : $this->token; } - public function setNoQuotes($token, $qchars = '`') { - $this->noQuotes = ($token === null) ? null : $this->revokeQuotation($token, $qchars); + public function setNoQuotes($token, $qchars, Options $options) { + $this->noQuotes = ($token === null) ? null : $this->revokeQuotation($token, $options); } - + public function setTokenType($type) { $this->tokenType = $type; } @@ -84,7 +87,7 @@ class ExpressionToken { } public function isSubQueryToken() { - return preg_match("/^\\(\\s*SELECT/i", $this->trim); + return preg_match("/^\\(\\s*(-- [\\w\\s]+\\n)?\\s*SELECT/i", $this->trim); } public function isExpression() { @@ -114,11 +117,15 @@ class ExpressionToken { public function isVariable() { return $this->tokenType === ExpressionType::GLOBAL_VARIABLE || $this->tokenType === ExpressionType::LOCAL_VARIABLE || $this->tokenType === ExpressionType::USER_VARIABLE; } - + public function isAggregateFunction() { return $this->tokenType === ExpressionType::AGGREGATE_FUNCTION; } + public function isCustomFunction() { + return $this->tokenType === ExpressionType::CUSTOM_FUNCTION; + } + public function isColumnReference() { return $this->tokenType === ExpressionType::COLREF; } @@ -135,28 +142,21 @@ class ExpressionToken { return $this->tokenType === ExpressionType::SUBQUERY; } - private function revokeQuotation($token, $qchars = '`') { - $result = trim($token); - for ($i = 0; $i < strlen($qchars); $i++) { - $quote = $qchars[$i]; - if (($result[0] === $quote) && ($result[strlen($result) - 1] === $quote)) { - $result = substr($result, 1, -1); - return trim(str_replace($quote.$quote, $quote, $result)); - } - } - return $token; + private function revokeQuotation($token, Options $options) { + $defProc = new DefaultProcessor($options); + return $defProc->revokeQuotation($token); } - + public function toArray() { $result = array(); $result['expr_type'] = $this->tokenType; $result['base_expr'] = $this->token; if (!empty($this->noQuotes)) { - $result['no_quotes'] = $this->noQuotes; + $result['no_quotes'] = $this->noQuotes; } $result['sub_tree'] = $this->subTree; return $result; } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/utils/ExpressionType.php b/tools/parser_sql/utils/ExpressionType.php index 45c6f6ebe..93ab80a05 100644 --- a/tools/parser_sql/utils/ExpressionType.php +++ b/tools/parser_sql/utils/ExpressionType.php @@ -36,10 +36,12 @@ * @author André Rothe * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) - * @version SVN: $Id: ExpressionType.php 836 2013-12-20 05:31:55Z phosco@gmx.de $ + * @version SVN: $Id$ * */ +namespace PHPSQLParser\utils; + /** * This class defines all values, which are possible for the [expr_type] field * within the parser output. @@ -50,67 +52,102 @@ */ class ExpressionType { - const USER_VARIABLE = "user_variable"; - const SESSION_VARIABLE = "session_variable"; - const GLOBAL_VARIABLE = "global_variable"; - const LOCAL_VARIABLE = "local_variable"; + const USER_VARIABLE = 'user_variable'; + const SESSION_VARIABLE = 'session_variable'; + const GLOBAL_VARIABLE = 'global_variable'; + const LOCAL_VARIABLE = 'local_variable'; - const COLDEF = "column-def"; - const COLREF = "colref"; - const RESERVED = "reserved"; - const CONSTANT = "const"; + const COLDEF = 'column-def'; + const COLREF = 'colref'; + const RESERVED = 'reserved'; + const CONSTANT = 'const'; - const AGGREGATE_FUNCTION = "aggregate_function"; - const SIMPLE_FUNCTION = "function"; + const AGGREGATE_FUNCTION = 'aggregate_function'; + const CUSTOM_FUNCTION = 'custom_function'; - const EXPRESSION = "expression"; - const BRACKET_EXPRESSION = "bracket_expression"; - const TABLE_EXPRESSION = "table_expression"; + const SIMPLE_FUNCTION = 'function'; - const SUBQUERY = "subquery"; - const IN_LIST = "in-list"; - const OPERATOR = "operator"; - const SIGN = "sign"; - const RECORD = "record"; + const EXPRESSION = 'expression'; + const BRACKET_EXPRESSION = 'bracket_expression'; + const TABLE_EXPRESSION = 'table_expression'; - const MATCH_ARGUMENTS = "match-arguments"; - const MATCH_MODE = "match-mode"; + const SUBQUERY = 'subquery'; + const IN_LIST = 'in-list'; + const OPERATOR = 'operator'; + const SIGN = 'sign'; + const RECORD = 'record'; - const ALIAS = "alias"; - const POSITION = "pos"; + const MATCH_ARGUMENTS = 'match-arguments'; + const MATCH_MODE = 'match-mode'; - const TEMPORARY_TABLE = "temporary-table"; - const TABLE = "table"; - const VIEW = "view"; - const DATABASE = "database"; - const SCHEMA = "schema"; + const ALIAS = 'alias'; + const POSITION = 'pos'; - const PROCEDURE = "procedure"; - const ENGINE = "engine"; - const USER = "user"; - const DIRECTORY = "directory"; - const UNION = "union"; - const CHARSET = "character-set"; - const COLLATE = "collation"; + const TEMPORARY_TABLE = 'temporary-table'; + const TABLE = 'table'; + const VIEW = 'view'; + const DATABASE = 'database'; + const SCHEMA = 'schema'; - const LIKE = "like"; - const CONSTRAINT = "constraint"; - const PRIMARY_KEY = "primary-key"; - const FOREIGN_KEY = "foreign-key"; - const UNIQUE_IDX = "unique-index"; - const INDEX = "index"; - const FULLTEXT_IDX = "fulltext-index"; - const SPATIAL_IDX = "spatial-index"; - const INDEX_TYPE = "index-type"; - const CHECK = "check"; - const COLUMN_LIST = "column-list"; - const INDEX_COLUMN = "index-column"; - const INDEX_SIZE = "index-size"; - const INDEX_PARSER = "index-parser"; - const REFERENCE = "foreign-ref"; + const PROCEDURE = 'procedure'; + const ENGINE = 'engine'; + const USER = 'user'; + const DIRECTORY = 'directory'; + const UNION = 'union'; + const CHARSET = 'character-set'; + const COLLATE = 'collation'; - const DATA_TYPE = "data-type"; - const COLUMN_TYPE = "column-type"; - const DEF_VALUE = "default-value"; + const LIKE = 'like'; + const CONSTRAINT = 'constraint'; + const PRIMARY_KEY = 'primary-key'; + const FOREIGN_KEY = 'foreign-key'; + const UNIQUE_IDX = 'unique-index'; + const INDEX = 'index'; + const FULLTEXT_IDX = 'fulltext-index'; + const SPATIAL_IDX = 'spatial-index'; + const INDEX_TYPE = 'index-type'; + const CHECK = 'check'; + const COLUMN_LIST = 'column-list'; + const INDEX_COLUMN = 'index-column'; + const INDEX_SIZE = 'index-size'; + const INDEX_PARSER = 'index-parser'; + const INDEX_ALGORITHM = 'index-algorithm'; + const INDEX_LOCK = 'index-lock'; + const REFERENCE = 'foreign-ref'; + + const DATA_TYPE = 'data-type'; + const COLUMN_TYPE = 'column-type'; + const DEF_VALUE = 'default-value'; + const COMMENT = 'comment'; + + const PARTITION = 'partition'; + const PARTITION_LIST = 'partition-list'; + const PARTITION_RANGE = 'partition-range'; + const PARTITION_HASH = 'partition-hash'; + const PARTITION_KEY = 'partition-key'; + const PARTITION_COUNT = 'partition-count'; + const PARTITION_DEF = 'partition-def'; + const PARTITION_VALUES = 'partition-values'; + const PARTITION_COMMENT = 'partition-comment'; + const PARTITION_INDEX_DIR = 'partition-index-dir'; + const PARTITION_DATA_DIR = 'partition-data-dir'; + const PARTITION_MAX_ROWS = 'partition-max-rows'; + const PARTITION_MIN_ROWS = 'partition-min-rows'; + const PARTITION_KEY_ALGORITHM = 'partition-key-algorithm'; + + const SUBPARTITION = 'sub-partition'; + const SUBPARTITION_DEF = 'sub-partition-def'; + const SUBPARTITION_HASH = 'sub-partition-hash'; + const SUBPARTITION_KEY = 'sub-partition-key'; + const SUBPARTITION_COUNT = 'sub-partition-count'; + const SUBPARTITION_COMMENT = 'sub-partition-comment'; + const SUBPARTITION_INDEX_DIR = 'sub-partition-index-dir'; + const SUBPARTITION_DATA_DIR = 'sub-partition-data-dir'; + const SUBPARTITION_MAX_ROWS = 'sub-partition-max-rows'; + const SUBPARTITION_MIN_ROWS = 'sub-partition-min-rows'; + const SUBPARTITION_KEY_ALGORITHM = 'sub-partition-key-algorithm'; + + const QUERY = 'query'; + const SUBQUERY_FACTORING = 'subquery-factoring'; } ?> diff --git a/tools/parser_sql/utils/PHPSQLParserConstants.php b/tools/parser_sql/utils/PHPSQLParserConstants.php index 2a2ba5417..fe634d01b 100644 --- a/tools/parser_sql/utils/PHPSQLParserConstants.php +++ b/tools/parser_sql/utils/PHPSQLParserConstants.php @@ -30,155 +30,190 @@ * DAMAGE. */ +namespace PHPSQLParser\utils; class PHPSQLParserConstants { - protected static $reserved = array('ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_ENCRYPT', 'AES_DECRYPT', 'AGAINST', - 'ASCII', 'ASIN', 'ATAN', 'AVG', 'BENCHMARK', 'BIN', 'BIT_AND', 'BIT_OR', - 'BITCOUNT', 'BITLENGTH', 'CAST', 'CEILING', 'CHAR', 'CHAR_LENGTH', - 'CHARACTER_LENGTH', 'CHARSET', 'COALESCE', 'COERCIBILITY', 'COLLATION', - 'COMPRESS', 'CONCAT', 'CONCAT_WS', 'CONNECTION_ID', 'CONV', 'CONVERT', - 'CONVERT_TZ', 'COS', 'COT', 'COUNT', 'CRC32', 'CURDATE', 'CURRENT_USER', - 'CURRVAL', 'CURTIME', 'DATABASE', 'DATETIME', 'DATE_ADD', 'DATE_DIFF', - 'DATE_FORMAT', 'DATE_SUB', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', - 'DAYOFYEAR', 'DECODE', 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', - 'ELT', 'ENCODE', 'ENCRYPT', 'EXISTS', 'EXP', 'EXPORT_SET', 'EXTRACT', 'FIELD', - 'FIND_IN_SET', 'FLOOR', 'FORMAT', 'FOUND_ROWS', 'FROM_DAYS', 'FROM_UNIXTIME', - 'GET_FORMAT', 'GET_LOCK', 'GROUP_CONCAT', 'GREATEST', 'HEX', 'HOUR', 'IF', - 'IFNULL', 'IN', 'INET_ATON', 'INET_NTOA', 'INSERT', 'INSTR', 'INTERVAL', - 'IS_FREE_LOCK', 'IS_USED_LOCK', 'LAST_DAY', 'LAST_INSERT_ID', 'LCASE', 'LEAST', - 'LEFT', 'LENGTH', 'LN', 'LOAD_FILE', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCATE', - 'LOG', 'LOG2', 'LOG10', 'LOWER', 'LPAD', 'LTRIM', 'MAKE_SET', 'MAKEDATE', - 'MAKETIME', 'MASTER_POS_WAIT', 'MATCH', 'MAX', 'MD5', 'MICROSECOND', 'MID', - 'MIN', 'MINUTE', 'MOD', 'MONTH', 'MONTHNAME', 'NEXTVAL', 'NOW', 'NULLIF', 'OCT', - 'OCTET_LENGTH', 'OLD_PASSWORD', 'ORD', 'PASSWORD', 'PERIOD_ADD', 'PERIOD_DIFF', - 'PI', 'POSITION', 'POW', 'POWER', 'QUARTER', 'QUOTE', 'RADIANS', 'RAND', - 'RELEASE_LOCK', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'ROW_COUNT', - 'RPAD', 'RTRIM', 'SEC_TO_TIME', 'SECOND', 'SESSION_USER', 'SHA', 'SHA1', 'SIGN', - 'SOUNDEX', 'SPACE', 'SQRT', 'STD', 'STDDEV', 'STDDEV_POP', 'STDDEV_SAMP', - 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTRING', 'SUBSTRING_INDEX', 'SUBTIME', - 'SUM', 'SYSDATE', 'SYSTEM_USER', 'TAN', 'TIME', 'TIMEDIFF', 'TIMESTAMP', - 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', 'TIME_TO_SEC', 'TO_DAYS', - 'TRIM', 'TRUNCATE', 'UCASE', 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', - 'UNIX_TIMESTAMP', 'UPPER', 'USER', 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP', - 'UUID', 'VAR_POP', 'VAR_SAMP', 'VARIANCE', 'VERSION', 'WEEK', 'WEEKDAY', - 'WEEKOFYEAR', 'YEAR', 'YEARWEEK', 'ADD', 'ALL', 'ALTER', 'ANALYZE', 'AND', 'AS', - 'ASC', 'ASENSITIVE', 'AUTO_INCREMENT', 'BDB', 'BEFORE', 'BERKELEYDB', 'BETWEEN', - 'BIGINT', 'BINARY', 'BLOB', 'BOTH', 'BY', 'CALL', 'CASCADE', 'CASE', 'CHANGE', - 'CHAR', 'CHARACTER', 'CHECK', 'COLLATE', 'COLUMN', 'COLUMNS', 'CONDITION', - 'CONNECTION', 'CONSTRAINT', 'CONTINUE', 'CREATE', 'CROSS', 'CURRENT_DATE', - 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURSOR', 'DATABASE', 'DATABASES', - 'DAY_HOUR', 'DAY_MICROSECOND', 'DAY_MINUTE', 'DAY_SECOND', 'DEC', 'DECIMAL', - 'DECLARE', 'DEFAULT', 'DELAYED', 'DELETE', 'DESC', 'DESCRIBE', 'DETERMINISTIC', - 'DISTINCT', 'DISTINCTROW', 'DIV', 'DOUBLE', 'DROP', 'ELSE', 'ELSEIF', 'END', - 'ENCLOSED', 'ESCAPED', 'EXISTS', 'EXIT', 'EXPLAIN', 'FALSE', 'FETCH', 'FIELDS', - 'FLOAT', 'FOR', 'FORCE', 'FOREIGN', 'FOUND', 'FRAC_SECOND', 'FROM', 'FULLTEXT', - 'GRANT', 'GROUP', 'HAVING', 'HIGH_PRIORITY', 'HOUR_MICROSECOND', 'HOUR_MINUTE', - 'HOUR_SECOND', 'IF', 'IGNORE', 'IN', 'INDEX', 'INFILE', 'INNER', 'INNODB', - 'INOUT', 'INSENSITIVE', 'INSERT', 'INT', 'INTEGER', 'INTERVAL', 'INTO', - 'IO_THREAD', 'IS', 'ITERATE', 'JOIN', 'KEY', 'KEYS', 'KILL', 'LEADING', 'LEAVE', - 'LEFT', 'LIKE', 'LIMIT', 'LINES', 'LOAD', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCK', - 'LONG', 'LONGBLOB', 'LONGTEXT', 'LOOP', 'LOW_PRIORITY', 'MASTER_SERVER_ID', - 'MATCH', 'MEDIUMBLOB', 'MEDIUMINT', 'MEDIUMTEXT', 'MIDDLEINT', - 'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MOD', 'NATURAL', 'NOT', - 'NO_WRITE_TO_BINLOG', 'NULL', 'NUMERIC', 'ON', 'OPTIMIZE', 'OPTION', - 'OPTIONALLY', 'OR', 'ORDER', 'OUT', 'OUTER', 'OUTFILE', 'PRECISION', 'PRIMARY', - 'PRIVILEGES', 'PROCEDURE', 'PURGE', 'READ', 'REAL', 'REFERENCES', 'REGEXP', - 'RENAME', 'REPEAT', 'REPLACE', 'REQUIRE', 'RESTRICT', 'RETURN', 'REVOKE', - 'RIGHT', 'RLIKE', 'SECOND_MICROSECOND', 'SELECT', 'SENSITIVE', 'SEPARATOR', - 'SET', 'SHOW', 'SMALLINT', 'SOME', 'SONAME', 'SPATIAL', 'SPECIFIC', 'SQL', - 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', 'SQL_BIG_RESULT', - 'SQL_CALC_FOUND_ROWS', 'SQL_SMALL_RESULT', 'SQL_TSI_DAY', 'SQL_TSI_FRAC_SECOND', - 'SQL_TSI_HOUR', 'SQL_TSI_MINUTE', 'SQL_TSI_MONTH', 'SQL_TSI_QUARTER', - 'SQL_TSI_SECOND', 'SQL_TSI_WEEK', 'SQL_TSI_YEAR', 'SSL', 'STARTING', - 'STRAIGHT_JOIN', 'STRIPED', 'TABLE', 'TABLES', 'TEMPORARY', 'TERMINATED', 'THEN', - 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TINYBLOB', 'TINYINT', 'TINYTEXT', 'TO', - 'TRAILING', 'TRUE', 'UNDO', 'UNION', 'UNIQUE', 'UNLOCK', 'UNSIGNED', 'UPDATE', - 'USAGE', 'USE', 'USER_RESOURCES', 'USING', 'UTC_DATE', 'UTC_TIME', - 'UTC_TIMESTAMP', 'VALUES', 'VARBINARY', 'VARCHAR', 'VARCHARACTER', 'VARYING', - 'WHEN', 'WHERE', 'WHILE', 'WITH', 'WRITE', 'XOR', 'YEAR_MONTH', 'ZEROFILL'); + private static $inst = null; - protected static $parameterizedFunctions = array('ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_ENCRYPT', 'AES_DECRYPT', - 'AGAINST', 'ASCII', 'ASIN', 'ATAN', 'AVG', 'BENCHMARK', 'BIN', - 'BIT_AND', 'BIT_OR', 'BITCOUNT', 'BITLENGTH', 'CAST', 'CEILING', - 'CHAR', 'CHAR_LENGTH', 'CHARACTER_LENGTH', 'CHARSET', 'COALESCE', - 'COERCIBILITY', 'COLLATION', 'COMPRESS', 'CONCAT', 'CONCAT_WS', - 'CONV', 'CONVERT', 'CONVERT_TZ', 'COS', 'COT', 'COUNT', 'CRC32', - 'CURRVAL', 'DATE_ADD', 'DATE_DIFF', 'DATE_FORMAT', 'DATE_SUB', - 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', 'DAYOFYEAR', - 'DECODE', 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', - 'ELT', 'ENCODE', 'ENCRYPT', 'EXP', 'EXPORT_SET', 'EXTRACT', - 'FIELD', 'FIND_IN_SET', 'FLOOR', 'FORMAT', 'FROM_DAYS', - 'FROM_UNIXTIME', 'GET_FORMAT', 'GET_LOCK', 'GROUP_CONCAT', - 'GREATEST', 'HEX', 'HOUR', 'IF', 'IFNULL', 'IN', 'INET_ATON', - 'INET_NTOA', 'INSERT', 'INSTR', 'INTERVAL', 'IS_FREE_LOCK', - 'IS_USED_LOCK', 'LAST_DAY', 'LCASE', 'LEAST', 'LEFT', 'LENGTH', - 'LN', 'LOAD_FILE', 'LOCATE', 'LOG', 'LOG2', 'LOG10', 'LOWER', - 'LPAD', 'LTRIM', 'MAKE_SET', 'MAKEDATE', 'MAKETIME', - 'MASTER_POS_WAIT', 'MATCH', 'MAX', 'MD5', 'MICROSECOND', 'MID', - 'MIN', 'MINUTE', 'MOD', 'MONTH', 'MONTHNAME', 'NEXTVAL', 'NULLIF', - 'OCT', 'OCTET_LENGTH', 'OLD_PASSWORD', 'ORD', 'PASSWORD', - 'PERIOD_ADD', 'PERIOD_DIFF', 'PI', 'POSITION', 'POW', 'POWER', - 'QUARTER', 'QUOTE', 'RADIANS', 'RELEASE_LOCK', 'REPEAT', - 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'RPAD', 'RTRIM', - 'SEC_TO_TIME', 'SECOND', 'SHA', 'SHA1', 'SIGN', 'SOUNDEX', - 'SPACE', 'SQRT', 'STD', 'STDDEV', 'STDDEV_POP', 'STDDEV_SAMP', - 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTRING', - 'SUBSTRING_INDEX', 'SUBTIME', 'SUM', 'TAN', 'TIME', 'TIMEDIFF', - 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', - 'TIME_TO_SEC', 'TO_DAYS', 'TRIM', 'TRUNCATE', 'UCASE', - 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UPPER', 'VAR_POP', - 'VAR_SAMP', 'VARIANCE', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'YEAR', - 'YEARWEEK'); + protected $customFunctions = array(); + protected $reserved = array('ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_ENCRYPT', 'AES_DECRYPT', 'AGAINST', 'ASCII', + 'ASIN', 'ATAN', 'AVG', 'BENCHMARK', 'BIN', 'BIT_AND', 'BIT_OR', 'BITCOUNT', + 'BITLENGTH', 'CAST', 'CEILING', 'CHAR', 'CHAR_LENGTH', 'CHARACTER_LENGTH', 'CHARSET', + 'COALESCE', 'COERCIBILITY', 'COLLATION', 'COMPRESS', 'CONCAT', 'CONCAT_WS', + 'CONNECTION_ID', 'CONV', 'CONVERT', 'CONVERT_TZ', 'COS', 'COT', 'COUNT', 'CRC32', + 'CURDATE', 'CURRENT_USER', 'CURRVAL', 'CURTIME', 'DATABASE', 'SCHEMA', 'DATETIME', 'DATE_ADD', + 'DATE_DIFF', 'DATE_FORMAT', 'DATE_SUB', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', + 'DAYOFYEAR', 'DECODE', 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', 'ELT', + 'ENCODE', 'ENCRYPT', 'EXISTS', 'EXP', 'EXPORT_SET', 'EXTRACT', 'FIELD', 'FIND_IN_SET', + 'FLOOR', 'FORMAT', 'FOUND_ROWS', 'FROM_DAYS', 'FROM_UNIXTIME', 'GET_FORMAT', + 'GET_LOCK', 'GROUP_CONCAT', 'GREATEST', 'HEX', 'HOUR', 'IF', 'IFNULL', 'IN', + 'INET_ATON', 'INET_NTOA', 'INSERT', 'INSTR', 'INTERVAL', 'IS_FREE_LOCK', + 'IS_USED_LOCK', 'LAST_DAY', 'LAST_INSERT_ID', 'LCASE', 'LEAST', 'LEFT', 'LENGTH', 'LN', + 'LOAD_FILE', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCATE', 'LOG', 'LOG2', 'LOG10', 'LOWER', + 'LPAD', 'LTRIM', 'MAKE_SET', 'MAKEDATE', 'MAKETIME', 'MASTER_POS_WAIT', 'MATCH', 'MAX', + 'MD5', 'MICROSECOND', 'MID', 'MIN', 'MINUTE', 'MOD', 'MONTH', 'MONTHNAME', 'NEXTVAL', + 'NOW', 'NULLIF', 'OCT', 'OCTET_LENGTH', 'OLD_PASSWORD', 'ORD', 'PASSWORD', + 'PERIOD_ADD', 'PERIOD_DIFF', 'PI', 'POSITION', 'POW', 'POWER', 'QUARTER', 'QUOTE', + 'RADIANS', 'RAND', 'RELEASE_LOCK', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', + 'ROW_COUNT', 'RPAD', 'RTRIM', 'SEC_TO_TIME', 'SECOND', 'SESSION_USER', 'SHA', 'SHA1', + 'SIGN', 'SOUNDEX', 'SPACE', 'SQRT', 'STD', 'STDDEV', 'STDDEV_POP', 'STDDEV_SAMP', + 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTRING', 'SUBSTRING_INDEX', 'SUBTIME', 'SUM', + 'SYSDATE', 'SYSTEM_USER', 'TAN', 'TIME', 'TIMEDIFF', 'TIMESTAMP', 'TIMESTAMPADD', + 'TIMESTAMPDIFF', 'TIME_FORMAT', 'TIME_TO_SEC', 'TO_DAYS', 'TRIM', 'TRUNCATE', 'UCASE', + 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UNIX_TIMESTAMP', 'UPPER', 'USER', + 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP', 'UUID', 'VAR_POP', 'VAR_SAMP', 'VARIANCE', + 'VERSION', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'YEAR', 'YEARWEEK', 'ADD', 'ALL', 'ALTER', + 'ANALYZE', 'AND', 'AS', 'ASC', 'ASENSITIVE', 'AUTO_INCREMENT', 'BDB', 'BEFORE', + 'BERKELEYDB', 'BETWEEN', 'BIGINT', 'BINARY', 'BLOB', 'BOTH', 'BY', 'CALL', 'CASCADE', + 'CASE', 'CHANGE', 'CHAR', 'CHARACTER', 'CHECK', 'COLLATE', 'COLUMN', 'COLUMNS', + 'CONDITION', 'CONNECTION', 'CONSTRAINT', 'CONTINUE', 'CREATE', 'CROSS', 'CURRENT_DATE', + 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURSOR', 'DATABASE', 'SCHEMA', 'DATABASES', 'SCHEMAS', 'DAY_HOUR', + 'DAY_MICROSECOND', 'DAY_MINUTE', 'DAY_SECOND', 'DEC', 'DECIMAL', 'DECLARE', 'DEFAULT', + 'DELAYED', 'DELETE', 'DESC', 'DESCRIBE', 'DETERMINISTIC', 'DISTINCT', 'DISTINCTROW', + 'DIV', 'DOUBLE', 'DROP', 'ELSE', 'ELSEIF', 'END', 'ENCLOSED', 'ESCAPED', 'EXISTS', + 'EXIT', 'EXPLAIN', 'FALSE', 'FETCH', 'FIELDS', 'FLOAT', 'FOR', 'FORCE', 'FOREIGN', + 'FOUND', 'FRAC_SECOND', 'FROM', 'FULLTEXT', 'GRANT', 'GROUP', 'HAVING', + 'HIGH_PRIORITY', 'HOUR_MICROSECOND', 'HOUR_MINUTE', 'HOUR_SECOND', 'IF', 'IGNORE', + 'IN', 'INDEX', 'INFILE', 'INNER', 'INNODB', 'INOUT', 'INSENSITIVE', 'INSERT', 'INT', + 'INTEGER', 'INTERVAL', 'INTO', 'IO_THREAD', 'IS', 'ITERATE', 'JOIN', 'KEY', 'KEYS', + 'KILL', 'LEADING', 'LEAVE', 'LEFT', 'LIKE', 'LIMIT', 'LINES', 'LOAD', 'LOCALTIME', + 'LOCALTIMESTAMP', 'LOCK', 'LONG', 'LONGBLOB', 'LONGTEXT', 'LOOP', 'LOW_PRIORITY', + 'MASTER_SERVER_ID', 'MATCH', 'MEDIUMBLOB', 'MEDIUMINT', 'MEDIUMTEXT', 'MIDDLEINT', + 'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MOD', 'NATURAL', 'NOT', 'NO_WRITE_TO_BINLOG', + 'NULL', 'NUMERIC', 'ON', 'OPTIMIZE', 'OPTION', 'OPTIONALLY', 'OR', 'ORDER', 'OUT', + 'OUTER', 'OUTFILE', 'PRECISION', 'PRIMARY', 'PRIVILEGES', 'PROCEDURE', 'PURGE', 'READ', + 'REAL', 'REFERENCES', 'REGEXP', 'RENAME', 'REPEAT', 'REPLACE', 'REQUIRE', 'RESTRICT', + 'RETURN', 'REVOKE', 'RIGHT', 'RLIKE', 'SECOND_MICROSECOND', 'SELECT', 'SENSITIVE', + 'SEPARATOR', 'SET', 'SHOW', 'SMALLINT', 'SOME', 'SONAME', 'SPATIAL', 'SPECIFIC', 'SQL', + 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', 'SQL_BIG_RESULT', 'SQL_CALC_FOUND_ROWS', + 'SQL_SMALL_RESULT', 'SQL_TSI_DAY', 'SQL_TSI_FRAC_SECOND', 'SQL_TSI_HOUR', + 'SQL_TSI_MINUTE', 'SQL_TSI_MONTH', 'SQL_TSI_QUARTER', 'SQL_TSI_SECOND', 'SQL_TSI_WEEK', + 'SQL_TSI_YEAR', 'SSL', 'STARTING', 'STRAIGHT_JOIN', 'STRIPED', 'TABLE', 'TABLES', + 'TEMPORARY', 'TERMINATED', 'THEN', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TINYBLOB', + 'TINYINT', 'TINYTEXT', 'TO', 'TRAILING', 'TRUE', 'UNDO', 'UNION', 'UNIQUE', 'UNLOCK', + 'UNSIGNED', 'UPDATE', 'USAGE', 'USE', 'USER_RESOURCES', 'USING', 'UTC_DATE', + 'UTC_TIME', 'UTC_TIMESTAMP', 'VALUES', 'VARBINARY', 'VARCHAR', 'VARCHARACTER', + 'VARYING', 'WHEN', 'WHERE', 'WHILE', 'WITH', 'WRITE', 'XOR', 'YEAR_MONTH', 'ZEROFILL'); - protected static $functions = array('ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_ENCRYPT', 'AES_DECRYPT', 'AGAINST', - 'ASCII', 'ASIN', 'ATAN', 'AVG', 'BENCHMARK', 'BIN', 'BIT_AND', 'BIT_OR', - 'BITCOUNT', 'BITLENGTH', 'CAST', 'CEILING', 'CHAR', 'CHAR_LENGTH', - 'CHARACTER_LENGTH', 'CHARSET', 'COALESCE', 'COERCIBILITY', 'COLLATION', - 'COMPRESS', 'CONCAT', 'CONCAT_WS', 'CONNECTION_ID', 'CONV', 'CONVERT', - 'CONVERT_TZ', 'COS', 'COT', 'COUNT', 'CRC32', 'CURDATE', 'CURRENT_USER', - 'CURRVAL', 'CURTIME', 'DATABASE', 'DATE_ADD', 'DATE_DIFF', 'DATE_FORMAT', - 'DATE_SUB', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', 'DAYOFYEAR', 'DECODE', - 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', 'ELT', 'ENCODE', 'ENCRYPT', - 'EXP', 'EXPORT_SET', 'EXTRACT', 'FIELD', 'FIND_IN_SET', 'FLOOR', 'FORMAT', - 'FOUND_ROWS', 'FROM_DAYS', 'FROM_UNIXTIME', 'GET_FORMAT', 'GET_LOCK', - 'GROUP_CONCAT', 'GREATEST', 'HEX', 'HOUR', 'IF', 'IFNULL', 'IN', 'INET_ATON', - 'INET_NTOA', 'INSERT', 'INSTR', 'INTERVAL', 'IS_FREE_LOCK', 'IS_USED_LOCK', - 'LAST_DAY', 'LAST_INSERT_ID', 'LCASE', 'LEAST', 'LEFT', 'LENGTH', 'LN', - 'LOAD_FILE', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCATE', 'LOG', 'LOG2', 'LOG10', - 'LOWER', 'LPAD', 'LTRIM', 'MAKE_SET', 'MAKEDATE', 'MAKETIME', - 'MASTER_POS_WAIT', 'MATCH', 'MAX', 'MD5', 'MICROSECOND', 'MID', 'MIN', - 'MINUTE', 'MOD', 'MONTH', 'MONTHNAME', 'NEXTVAL', 'NOW', 'NULLIF', 'OCT', - 'OCTET_LENGTH', 'OLD_PASSWORD', 'ORD', 'PASSWORD', 'PERIOD_ADD', 'PERIOD_DIFF', - 'PI', 'POSITION', 'POW', 'POWER', 'QUARTER', 'QUOTE', 'RADIANS', 'RAND', - 'RELEASE_LOCK', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'ROW_COUNT', - 'RPAD', 'RTRIM', 'SEC_TO_TIME', 'SECOND', 'SESSION_USER', 'SHA', 'SHA1', - 'SIGN', 'SOUNDEX', 'SPACE', 'SQRT', 'STD', 'STDDEV', 'STDDEV_POP', - 'STDDEV_SAMP', 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTRING', - 'SUBSTRING_INDEX', 'SUBTIME', 'SUM', 'SYSDATE', 'SYSTEM_USER', 'TAN', 'TIME', - 'TIMEDIFF', 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', - 'TIME_TO_SEC', 'TO_DAYS', 'TRIM', 'TRUNCATE', 'UCASE', 'UNCOMPRESS', - 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UNIX_TIMESTAMP', 'UPPER', 'USER', 'UTC_DATE', - 'UTC_TIME', 'UTC_TIMESTAMP', 'UUID', 'VAR_POP', 'VAR_SAMP', 'VARIANCE', - 'VERSION', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'YEAR', 'YEARWEEK'); + protected $parameterizedFunctions = array('ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_ENCRYPT', 'AES_DECRYPT', + 'AGAINST', 'ASCII', 'ASIN', 'ATAN', 'AVG', 'BENCHMARK', 'BIN', 'BIT_AND', + 'BIT_OR', 'BITCOUNT', 'BITLENGTH', 'CAST', 'CEILING', 'CHAR', + 'CHAR_LENGTH', 'CHARACTER_LENGTH', 'CHARSET', 'COALESCE', 'COERCIBILITY', + 'COLLATION', 'COMPRESS', 'CONCAT', 'CONCAT_WS', 'CONV', 'CONVERT', + 'CONVERT_TZ', 'COS', 'COT', 'COUNT', 'CRC32', 'CURRVAL', 'DATE_ADD', + 'DATE_DIFF', 'DATE_FORMAT', 'DATE_SUB', 'DAY', 'DAYNAME', 'DAYOFMONTH', + 'DAYOFWEEK', 'DAYOFYEAR', 'DECODE', 'DEFAULT', 'DEGREES', 'DES_DECRYPT', + 'DES_ENCRYPT', 'ELT', 'ENCODE', 'ENCRYPT', 'EXP', 'EXPORT_SET', + 'EXTRACT', 'FIELD', 'FIND_IN_SET', 'FLOOR', 'FORMAT', 'FROM_DAYS', + 'FROM_UNIXTIME', 'GET_FORMAT', 'GET_LOCK', 'GROUP_CONCAT', 'GREATEST', + 'HEX', 'HOUR', 'IF', 'IFNULL', 'IN', 'INET_ATON', 'INET_NTOA', 'INSERT', + 'INSTR', 'INTERVAL', 'IS_FREE_LOCK', 'IS_USED_LOCK', 'LAST_DAY', 'LCASE', + 'LEAST', 'LEFT', 'LENGTH', 'LN', 'LOAD_FILE', 'LOCATE', 'LOG', 'LOG2', + 'LOG10', 'LOWER', 'LPAD', 'LTRIM', 'MAKE_SET', 'MAKEDATE', 'MAKETIME', + 'MASTER_POS_WAIT', 'MATCH', 'MAX', 'MD5', 'MICROSECOND', 'MID', 'MIN', + 'MINUTE', 'MOD', 'MONTH', 'MONTHNAME', 'NEXTVAL', 'NULLIF', 'OCT', + 'OCTET_LENGTH', 'OLD_PASSWORD', 'ORD', 'PASSWORD', 'PERIOD_ADD', + 'PERIOD_DIFF', 'PI', 'POSITION', 'POW', 'POWER', 'QUARTER', 'QUOTE', + 'RADIANS', 'RELEASE_LOCK', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', + 'ROUND', 'RPAD', 'RTRIM', 'SEC_TO_TIME', 'SECOND', 'SHA', 'SHA1', 'SIGN', + 'SOUNDEX', 'SPACE', 'SQRT', 'STD', 'STDDEV', 'STDDEV_POP', 'STDDEV_SAMP', + 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTRING', 'SUBSTRING_INDEX', + 'SUBTIME', 'SUM', 'TAN', 'TIME', 'TIMEDIFF', 'TIMESTAMP', 'TIMESTAMPADD', + 'TIMESTAMPDIFF', 'TIME_FORMAT', 'TIME_TO_SEC', 'TO_DAYS', 'TRIM', + 'TRUNCATE', 'UCASE', 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', + 'UPPER', 'VAR_POP', 'VAR_SAMP', 'VARIANCE', 'WEEK', 'WEEKDAY', + 'WEEKOFYEAR', 'YEAR', 'YEARWEEK'); - protected static $aggregateFunctions = array('AVG', 'SUM', 'COUNT', 'MIN', 'MAX', 'STDDEV', 'STDDEV_SAMP', - 'STDDEV_POP', 'VARIANCE', 'VAR_SAMP', 'VAR_POP', 'GROUP_CONCAT', - 'BIT_AND', 'BIT_OR', 'BIT_XOR'); + protected $functions = array('ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_ENCRYPT', 'AES_DECRYPT', 'AGAINST', 'ASCII', + 'ASIN', 'ATAN', 'AVG', 'BENCHMARK', 'BIN', 'BIT_AND', 'BIT_OR', 'BITCOUNT', + 'BITLENGTH', 'CAST', 'CEILING', 'CHAR', 'CHAR_LENGTH', 'CHARACTER_LENGTH', 'CHARSET', + 'COALESCE', 'COERCIBILITY', 'COLLATION', 'COMPRESS', 'CONCAT', 'CONCAT_WS', + 'CONNECTION_ID', 'CONV', 'CONVERT', 'CONVERT_TZ', 'COS', 'COT', 'COUNT', 'CRC32', + 'CURDATE', 'CURRENT_USER', 'CURRVAL', 'CURTIME', 'DATABASE', 'SCHEMA', 'DATE_ADD', 'DATE_DIFF', + 'DATE_FORMAT', 'DATE_SUB', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', 'DAYOFYEAR', + 'DECODE', 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', 'ELT', 'ENCODE', + 'ENCRYPT', 'EXP', 'EXPORT_SET', 'EXTRACT', 'FIELD', 'FIND_IN_SET', 'FLOOR', 'FORMAT', + 'FOUND_ROWS', 'FROM_DAYS', 'FROM_UNIXTIME', 'GET_FORMAT', 'GET_LOCK', 'GROUP_CONCAT', + 'GREATEST', 'HEX', 'HOUR', 'IF', 'IFNULL', 'IN', 'INET_ATON', 'INET_NTOA', 'INSERT', + 'INSTR', 'INTERVAL', 'IS_FREE_LOCK', 'IS_USED_LOCK', 'LAST_DAY', 'LAST_INSERT_ID', + 'LCASE', 'LEAST', 'LEFT', 'LENGTH', 'LN', 'LOAD_FILE', 'LOCALTIME', 'LOCALTIMESTAMP', + 'LOCATE', 'LOG', 'LOG2', 'LOG10', 'LOWER', 'LPAD', 'LTRIM', 'MAKE_SET', 'MAKEDATE', + 'MAKETIME', 'MASTER_POS_WAIT', 'MATCH', 'MAX', 'MD5', 'MICROSECOND', 'MID', 'MIN', + 'MINUTE', 'MOD', 'MONTH', 'MONTHNAME', 'NEXTVAL', 'NOW', 'NULLIF', 'OCT', + 'OCTET_LENGTH', 'OLD_PASSWORD', 'ORD', 'PASSWORD', 'PERIOD_ADD', 'PERIOD_DIFF', 'PI', + 'POSITION', 'POW', 'POWER', 'QUARTER', 'QUOTE', 'RADIANS', 'RAND', 'RELEASE_LOCK', + 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'ROW_COUNT', 'RPAD', 'RTRIM', + 'SEC_TO_TIME', 'SECOND', 'SESSION_USER', 'SHA', 'SHA1', 'SIGN', 'SOUNDEX', 'SPACE', + 'SQRT', 'STD', 'STDDEV', 'STDDEV_POP', 'STDDEV_SAMP', 'STRCMP', 'STR_TO_DATE', + 'SUBDATE', 'SUBSTRING', 'SUBSTRING_INDEX', 'SUBTIME', 'SUM', 'SYSDATE', 'SYSTEM_USER', + 'TAN', 'TIME', 'TIMEDIFF', 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', + 'TIME_FORMAT', 'TIME_TO_SEC', 'TO_DAYS', 'TRIM', 'TRUNCATE', 'UCASE', 'UNCOMPRESS', + 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UNIX_TIMESTAMP', 'UPPER', 'USER', 'UTC_DATE', + 'UTC_TIME', 'UTC_TIMESTAMP', 'UUID', 'VAR_POP', 'VAR_SAMP', 'VARIANCE', 'VERSION', + 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'YEAR', 'YEARWEEK'); - public static function isAggregateFunction($token) { - return in_array($token, PHPSQLParserConstants::$aggregateFunctions); + protected $aggregateFunctions = array('AVG', 'SUM', 'COUNT', 'MIN', 'MAX', 'STD', 'STDDEV', 'STDDEV_SAMP', + 'STDDEV_POP', 'VARIANCE', 'VAR_SAMP', 'VAR_POP', 'GROUP_CONCAT', 'BIT_AND', + 'BIT_OR', 'BIT_XOR'); + + /** + * Call this method to get singleton + * + * @return PHPSQLParserConstants + */ + public static function getInstance() { + if (!isset(self::$inst)) { + self::$inst = new PHPSQLParserConstants(); + } + return self::$inst; } - public static function isReserved($token) { - return in_array($token, PHPSQLParserConstants::$reserved); + /** + * Private ctor so nobody else can instance it + * + */ + private function __construct() { + $this->reserved = array_flip($this->reserved); + $this->aggregateFunctions = array_flip($this->aggregateFunctions); + $this->functions = array_flip($this->functions); + $this->parameterizedFunctions = array_flip($this->parameterizedFunctions); } - - public static function isFunction($token) { - return in_array($token, PHPSQLParserConstants::$functions); + + private function __clone() { } - - public static function isParameterizedFunction($token) { - return in_array($token, PHPSQLParserConstants::$parameterizedFunctions); + + public function isAggregateFunction($token) { + return isset($this->aggregateFunctions[$token]); + } + + public function isReserved($token) { + return isset($this->reserved[$token]); + } + + public function isFunction($token) { + return isset($this->functions[$token]); + } + + public function isParameterizedFunction($token) { + return isset($this->parameterizedFunctions[$token]); + } + + public function isCustomFunction($token) { + return isset($this->customFunctions[$token]); + } + + public function addCustomFunction($token) { + $token = strtoupper(trim($token)); + $this->customFunctions[$token] = true; + } + + public function removeCustomFunction($token) { + $token = strtoupper(trim($token)); + unset($this->customFunctions[$token]); + } + + public function getCustomFunctions() { + return array_keys($this->customFunctions); } } -?> \ No newline at end of file +?> diff --git a/tools/parser_sql/utils/PHPSQLParserUtils.php b/tools/parser_sql/utils/PHPSQLParserUtils.php deleted file mode 100644 index ffe9a6984..000000000 --- a/tools/parser_sql/utils/PHPSQLParserUtils.php +++ /dev/null @@ -1,150 +0,0 @@ - - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - */ - -/** - * This class implements some helper functions. - * - * @author arothe - * @deprecated - */ -class PHPSQLParserUtils { - - /** - * Prints an array only if debug mode is on. - * - * @param array $s - * @param boolean $return, if true, the formatted array is returned via return parameter - */ - protected function preprint($arr, $return = false) { - $x = "
";
-        $x .= print_r($arr, 1);
-        $x .= "
"; - if ($return) { - return $x; - } else { - if (isset($_ENV['DEBUG'])) { - print $x . "\n"; - } - } - } - - /** - * Ends the given string $haystack with the string $needle? - * - * @param string $haystack - * @param string $needle - */ - protected function endsWith($haystack, $needle) { - $length = strlen($needle); - if ($length == 0) { - return true; - } - return (substr($haystack, -$length) === $needle); - } - - /** - * Revokes the quoting characters from an expression - */ - protected function revokeQuotation($sql) { - $result = trim($sql); - if (($result[0] === '`') && ($result[strlen($result) - 1] === '`')) { - $result = substr($result, 1, -1); - return trim(str_replace('``', '`', $result)); - } - return $sql; - } - - /** - * This method removes parenthesis from start of the given string. - * It removes also the associated closing parenthesis. - */ - protected function removeParenthesisFromStart($token) { - - $parenthesisRemoved = 0; - - $trim = trim($token); - if ($trim !== "" && $trim[0] === "(") { // remove only one parenthesis pair now! - $parenthesisRemoved++; - $trim[0] = " "; - $trim = trim($trim); - } - - $parenthesis = $parenthesisRemoved; - $i = 0; - $string = 0; - while ($i < strlen($trim)) { - - if ($trim[$i] === "\\") { - $i += 2; # an escape character, the next character is irrelevant - continue; - } - - if ($trim[$i] === "'" || $trim[$i] === '"') { - $string++; - } - - if (($string % 2 === 0) && ($trim[$i] === "(")) { - $parenthesis++; - } - - if (($string % 2 === 0) && ($trim[$i] === ")")) { - if ($parenthesis == $parenthesisRemoved) { - $trim[$i] = " "; - $parenthesisRemoved--; - } - $parenthesis--; - } - $i++; - } - return trim($trim); - } - - public function getLastOf($array) { - // $array is a copy of the original array, so we can change it without sideeffects - if (!is_array($array)) { - return false; - } - return array_pop($array); - } - - /** - * translates an array of objects into an associative array - */ - public function toArray($tokenList) { - $expr = array(); - foreach ($tokenList as $token) { - $expr[] = $token->toArray(); - } - return (empty($expr) ? false : $expr); - } -} -?> From 0dc2cdc7f45f6ea41915076bf3b1c968d9529407 Mon Sep 17 00:00:00 2001 From: shreesh arora Date: Tue, 4 May 2021 14:55:15 +0530 Subject: [PATCH 2/2] added parser_autoload | updated --- classes/Tools.php | 4 +- tools/parser_sql/builders/index.php | 38 +++++++--------- tools/parser_sql/exceptions/index.php | 38 +++++++--------- tools/parser_sql/index.php | 44 ++++++++---------- tools/parser_sql/lexer/index.php | 38 +++++++--------- tools/parser_sql/php_sql_parser_autoload.php | 47 ++++++++++++++++++++ tools/parser_sql/positions/index.php | 38 +++++++--------- tools/parser_sql/processors/index.php | 38 +++++++--------- tools/parser_sql/utils/index.php | 38 +++++++--------- 9 files changed, 164 insertions(+), 159 deletions(-) create mode 100644 tools/parser_sql/php_sql_parser_autoload.php diff --git a/classes/Tools.php b/classes/Tools.php index 22ddaf612..17ac7a88d 100644 --- a/classes/Tools.php +++ b/classes/Tools.php @@ -2222,8 +2222,8 @@ class ToolsCore public static function parserSQL($sql) { if (strlen($sql) > 0) { - require_once(_PS_TOOL_DIR_.'parser_sql/PHPSQLParser.php'); - $parser = new PHPSQLParser($sql); + require_once _PS_TOOL_DIR_.'parser_sql/php_sql_parser_autoload.php'; + $parser = new PHPSQLParser\PHPSQLParser($sql); return $parser->parsed; } return false; diff --git a/tools/parser_sql/builders/index.php b/tools/parser_sql/builders/index.php index 9a99a8662..051e0122d 100644 --- a/tools/parser_sql/builders/index.php +++ b/tools/parser_sql/builders/index.php @@ -1,35 +1,29 @@ -* @copyright 2007-2017 PrestaShop SA -* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) -* International Registered Trademark & Property of PrestaShop SA +* @author Webkul IN +* @copyright 2010-2021 Webkul IN +* @license https://store.webkul.com/license.html */ -header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); -header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); +header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); +header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); -header("Cache-Control: no-store, no-cache, must-revalidate"); -header("Cache-Control: post-check=0, pre-check=0", false); -header("Pragma: no-cache"); +header('Cache-Control: no-store, no-cache, must-revalidate'); +header('Cache-Control: post-check=0, pre-check=0', false); +header('Pragma: no-cache'); -header("Location: ../"); +header('Location: ../../../'); exit; diff --git a/tools/parser_sql/exceptions/index.php b/tools/parser_sql/exceptions/index.php index 9a99a8662..051e0122d 100644 --- a/tools/parser_sql/exceptions/index.php +++ b/tools/parser_sql/exceptions/index.php @@ -1,35 +1,29 @@ -* @copyright 2007-2017 PrestaShop SA -* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) -* International Registered Trademark & Property of PrestaShop SA +* @author Webkul IN +* @copyright 2010-2021 Webkul IN +* @license https://store.webkul.com/license.html */ -header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); -header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); +header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); +header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); -header("Cache-Control: no-store, no-cache, must-revalidate"); -header("Cache-Control: post-check=0, pre-check=0", false); -header("Pragma: no-cache"); +header('Cache-Control: no-store, no-cache, must-revalidate'); +header('Cache-Control: post-check=0, pre-check=0', false); +header('Pragma: no-cache'); -header("Location: ../"); +header('Location: ../../../'); exit; diff --git a/tools/parser_sql/index.php b/tools/parser_sql/index.php index df55e1000..051e0122d 100644 --- a/tools/parser_sql/index.php +++ b/tools/parser_sql/index.php @@ -1,35 +1,29 @@ -* @copyright 2007-2017 PrestaShop SA -* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) -* International Registered Trademark & Property of PrestaShop SA +* @author Webkul IN +* @copyright 2010-2021 Webkul IN +* @license https://store.webkul.com/license.html */ - -header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); -header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); - -header("Cache-Control: no-store, no-cache, must-revalidate"); -header("Cache-Control: post-check=0, pre-check=0", false); -header("Pragma: no-cache"); - -header("Location: ../"); + +header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); +header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); + +header('Cache-Control: no-store, no-cache, must-revalidate'); +header('Cache-Control: post-check=0, pre-check=0', false); +header('Pragma: no-cache'); + +header('Location: ../../../'); exit; diff --git a/tools/parser_sql/lexer/index.php b/tools/parser_sql/lexer/index.php index 9a99a8662..051e0122d 100644 --- a/tools/parser_sql/lexer/index.php +++ b/tools/parser_sql/lexer/index.php @@ -1,35 +1,29 @@ -* @copyright 2007-2017 PrestaShop SA -* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) -* International Registered Trademark & Property of PrestaShop SA +* @author Webkul IN +* @copyright 2010-2021 Webkul IN +* @license https://store.webkul.com/license.html */ -header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); -header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); +header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); +header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); -header("Cache-Control: no-store, no-cache, must-revalidate"); -header("Cache-Control: post-check=0, pre-check=0", false); -header("Pragma: no-cache"); +header('Cache-Control: no-store, no-cache, must-revalidate'); +header('Cache-Control: post-check=0, pre-check=0', false); +header('Pragma: no-cache'); -header("Location: ../"); +header('Location: ../../../'); exit; diff --git a/tools/parser_sql/php_sql_parser_autoload.php b/tools/parser_sql/php_sql_parser_autoload.php new file mode 100644 index 000000000..093d61b52 --- /dev/null +++ b/tools/parser_sql/php_sql_parser_autoload.php @@ -0,0 +1,47 @@ + +* @copyright 2010-2021 Webkul IN +* @license https://store.webkul.com/license.html +*/ + +require_once __DIR__.'/PHPSQLParser.php'; + +function classAutoLoader($class) +{ + // check if php sql parser file is called + if(0 !== strpos($class, 'PHPSQLParser')) { + return; + } + + $className = end(explode('\\', $class)); + if(class_exists($className)) { + return; + } + + $class = str_replace('PHPSQLParser\\', '', $class); + + // create path for required file + $classFile = __DIR__.'/'.str_replace('\\', '/', $class).'.php'; + + if (!file_exists($classFile) || !is_file($classFile)) { + return; + } + + require $classFile; +} + +spl_autoload_register('classAutoLoader'); \ No newline at end of file diff --git a/tools/parser_sql/positions/index.php b/tools/parser_sql/positions/index.php index 9a99a8662..051e0122d 100644 --- a/tools/parser_sql/positions/index.php +++ b/tools/parser_sql/positions/index.php @@ -1,35 +1,29 @@ -* @copyright 2007-2017 PrestaShop SA -* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) -* International Registered Trademark & Property of PrestaShop SA +* @author Webkul IN +* @copyright 2010-2021 Webkul IN +* @license https://store.webkul.com/license.html */ -header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); -header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); +header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); +header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); -header("Cache-Control: no-store, no-cache, must-revalidate"); -header("Cache-Control: post-check=0, pre-check=0", false); -header("Pragma: no-cache"); +header('Cache-Control: no-store, no-cache, must-revalidate'); +header('Cache-Control: post-check=0, pre-check=0', false); +header('Pragma: no-cache'); -header("Location: ../"); +header('Location: ../../../'); exit; diff --git a/tools/parser_sql/processors/index.php b/tools/parser_sql/processors/index.php index 9a99a8662..051e0122d 100644 --- a/tools/parser_sql/processors/index.php +++ b/tools/parser_sql/processors/index.php @@ -1,35 +1,29 @@ -* @copyright 2007-2017 PrestaShop SA -* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) -* International Registered Trademark & Property of PrestaShop SA +* @author Webkul IN +* @copyright 2010-2021 Webkul IN +* @license https://store.webkul.com/license.html */ -header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); -header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); +header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); +header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); -header("Cache-Control: no-store, no-cache, must-revalidate"); -header("Cache-Control: post-check=0, pre-check=0", false); -header("Pragma: no-cache"); +header('Cache-Control: no-store, no-cache, must-revalidate'); +header('Cache-Control: post-check=0, pre-check=0', false); +header('Pragma: no-cache'); -header("Location: ../"); +header('Location: ../../../'); exit; diff --git a/tools/parser_sql/utils/index.php b/tools/parser_sql/utils/index.php index 9a99a8662..051e0122d 100644 --- a/tools/parser_sql/utils/index.php +++ b/tools/parser_sql/utils/index.php @@ -1,35 +1,29 @@ -* @copyright 2007-2017 PrestaShop SA -* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) -* International Registered Trademark & Property of PrestaShop SA +* @author Webkul IN +* @copyright 2010-2021 Webkul IN +* @license https://store.webkul.com/license.html */ -header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); -header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); +header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); +header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); -header("Cache-Control: no-store, no-cache, must-revalidate"); -header("Cache-Control: post-check=0, pre-check=0", false); -header("Pragma: no-cache"); +header('Cache-Control: no-store, no-cache, must-revalidate'); +header('Cache-Control: post-check=0, pre-check=0', false); +header('Pragma: no-cache'); -header("Location: ../"); +header('Location: ../../../'); exit;