update parser_sql
This commit is contained in:
@@ -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 <arothe@phosco.info, phosco@gmx.de>
|
||||
* 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 <andre.rothe@phosco.info>
|
||||
* @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 <andre.rothe@phosco.info>
|
||||
* @author Marco Th. <marco64th@gmail.com>
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
?>
|
||||
?>
|
||||
|
||||
Reference in New Issue
Block a user