Project

General

Profile

Bug #22410 » 14050_cleaning_t3lib_sqlparser.patch

Administrator Admin, 2010-11-24 16:09

View differences:

t3lib/class.t3lib_sqlparser.php (revision )
<?php
/***************************************************************
* Copyright notice
*
* (c) 2004-2010 Kasper Sk?rh?j (kasperYYYY@typo3.com)
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the textfile GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
* Copyright notice
*
* (c) 2004-2010 Kasper Sk?rh?j (kasperYYYY@typo3.com)
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the textfile GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
* TYPO3 SQL parser
*
......
*
* 107: class t3lib_sqlparser
*
* SECTION: SQL Parsing, full queries
* SECTION: SQL Parsing, full queries
* 129: function parseSQL($parseString)
* 129: function parseSQL($parseString)
* 192: function parseSELECT($parseString)
* 192: function parseSELECT($parseString)
* 261: function parseUPDATE($parseString)
* 261: function parseUPDATE($parseString)
* 315: function parseINSERT($parseString)
* 315: function parseINSERT($parseString)
* 375: function parseDELETE($parseString)
* 375: function parseDELETE($parseString)
* 413: function parseEXPLAIN($parseString)
* 413: function parseEXPLAIN($parseString)
* 435: function parseCREATETABLE($parseString)
* 435: function parseCREATETABLE($parseString)
* 514: function parseALTERTABLE($parseString)
* 514: function parseALTERTABLE($parseString)
* 583: function parseDROPTABLE($parseString)
* 583: function parseDROPTABLE($parseString)
* 616: function parseCREATEDATABASE($parseString)
* 616: function parseCREATEDATABASE($parseString)
*
* SECTION: SQL Parsing, helper functions for parts of queries
* SECTION: SQL Parsing, helper functions for parts of queries
* 670: function parseFieldList(&$parseString, $stopRegex='')
* 670: function parseFieldList(&$parseString, $stopRegex='')
* 791: function parseFromTables(&$parseString, $stopRegex='')
* 791: function parseFromTables(&$parseString, $stopRegex='')
* 882: function parseWhereClause(&$parseString, $stopRegex='')
* 882: function parseWhereClause(&$parseString, $stopRegex='')
* 990: function parseFieldDef(&$parseString, $stopRegex='')
* 990: function parseFieldDef(&$parseString, $stopRegex='')
*
* SECTION: Parsing: Helper functions
* SECTION: Parsing: Helper functions
* 1053: function nextPart(&$parseString,$regex,$trimAll=FALSE)
* 1053: function nextPart(&$parseString,$regex,$trimAll=FALSE)
* 1068: function getValue(&$parseString,$comparator='')
* 1068: function getValue(&$parseString,$comparator='')
* 1127: function getValueInQuotes(&$parseString,$quote)
* 1127: function getValueInQuotes(&$parseString,$quote)
* 1153: function parseStripslashes($str)
* 1153: function parseStripslashes($str)
* 1167: function compileAddslashes($str)
* 1167: function compileAddslashes($str)
* 1182: function parseError($msg,$restQuery)
* 1182: function parseError($msg,$restQuery)
* 1196: function trimSQL($str)
* 1196: function trimSQL($str)
*
* SECTION: Compiling queries
* SECTION: Compiling queries
* 1225: function compileSQL($components)
* 1225: function compileSQL($components)
* 1263: function compileSELECT($components)
* 1263: function compileSELECT($components)
* 1294: function compileUPDATE($components)
* 1294: function compileUPDATE($components)
* 1322: function compileINSERT($components)
* 1322: function compileINSERT($components)
* 1362: function compileDELETE($components)
* 1362: function compileDELETE($components)
* 1382: function compileCREATETABLE($components)
* 1382: function compileCREATETABLE($components)
* 1415: function compileALTERTABLE($components)
* 1415: function compileALTERTABLE($components)
*
* SECTION: Compiling queries, helper functions for parts of queries
* SECTION: Compiling queries, helper functions for parts of queries
* 1468: function compileFieldList($selectFields)
* 1468: function compileFieldList($selectFields)
* 1510: function compileFromTables($tablesArray)
* 1510: function compileFromTables($tablesArray)
* 1551: function compileWhereClause($clauseArray)
* 1551: function compileWhereClause($clauseArray)
* 1605: function compileFieldCfg($fieldCfg)
* 1605: function compileFieldCfg($fieldCfg)
*
* SECTION: Debugging
* SECTION: Debugging
* 1654: function debug_parseSQLpart($part,$str)
* 1654: function debug_parseSQLpart($part,$str)
* 1679: function debug_parseSQLpartCompare($str,$newStr,$caseInsensitive=FALSE)
* 1679: function debug_parseSQLpartCompare($str,$newStr,$caseInsensitive=FALSE)
* 1712: function debug_testSQL($SQLquery)
* 1712: function debug_testSQL($SQLquery)
*
* TOTAL FUNCTIONS: 35
* (This index is automatically created/updated by the extension "extdeveval")
......
*/
/**
* TYPO3 SQL parser class.
*
......
class t3lib_sqlparser {
// Parser:
var $parse_error = ''; // Parsing error string
var $parse_error = ''; // Parsing error string
var $lastStopKeyWord = ''; // Last stop keyword used.
var $lastStopKeyWord = ''; // Last stop keyword used.
/*************************************
*
* SQL Parsing, full queries
......
$result = array();
// Finding starting keyword of string:
$_parseString = $parseString; // Protecting original string...
$_parseString = $parseString; // Protecting original string...
$keyword = $this->nextPart($_parseString, '^(SELECT|UPDATE|INSERT[[:space:]]+INTO|DELETE[[:space:]]+FROM|EXPLAIN|DROP[[:space:]]+TABLE|CREATE[[:space:]]+TABLE|CREATE[[:space:]]+DATABASE|ALTER[[:space:]]+TABLE|TRUNCATE[[:space:]]+TABLE)[[:space:]]+');
$keyword = strtoupper(str_replace(array(' ',TAB,CR,LF),'',$keyword));
$keyword = strtoupper(str_replace(array(' ', TAB, CR, LF), '', $keyword));
switch($keyword) {
switch ($keyword) {
case 'SELECT':
// Parsing SELECT query:
$result = $this->parseSELECT($parseString);
......
$result = $this->parseTRUNCATETABLE($parseString);
break;
default:
$result = $this->parseError('"'.$keyword.'" is not a keyword',$parseString);
$result = $this->parseError('"' . $keyword . '" is not a keyword', $parseString);
break;
}
......
// Removing SELECT:
$parseString = $this->trimSQL($parseString);
$parseString = ltrim(substr($parseString,6));
$parseString = ltrim(substr($parseString, 6));
// Init output variable:
$result = array();
......
// Select fields:
$result['SELECT'] = $this->parseFieldList($parseString, '^(FROM)[[:space:]]+');
if ($this->parse_error) { return $this->parse_error; }
if ($this->parse_error) {
return $this->parse_error;
}
// Continue if string is not ended:
if ($parseString) {
if ($parseString) {
// Get table list:
$result['FROM'] = $this->parseFromTables($parseString, '^(WHERE)[[:space:]]+');
if ($this->parse_error) { return $this->parse_error; }
if ($this->parse_error) {
return $this->parse_error;
}
// If there are more than just the tables (a WHERE clause that would be...)
if ($parseString) {
if ($parseString) {
// Get WHERE clause:
$result['WHERE'] = $this->parseWhereClause($parseString, '^(GROUP[[:space:]]+BY|ORDER[[:space:]]+BY|LIMIT)[[:space:]]+', $parameterReferences);
if ($this->parse_error) { return $this->parse_error; }
if ($this->parse_error) {
return $this->parse_error;
}
// If the WHERE clause parsing was stopped by GROUP BY, ORDER BY or LIMIT, then proceed with parsing:
if ($this->lastStopKeyWord) {
if ($this->lastStopKeyWord) {
// GROUP BY parsing:
if ($this->lastStopKeyWord == 'GROUPBY') {
if ($this->lastStopKeyWord == 'GROUPBY') {
$result['GROUPBY'] = $this->parseFieldList($parseString, '^(ORDER[[:space:]]+BY|LIMIT)[[:space:]]+');
if ($this->parse_error) { return $this->parse_error; }
if ($this->parse_error) {
return $this->parse_error;
}
}
}
// ORDER BY parsing:
if ($this->lastStopKeyWord == 'ORDERBY') {
if ($this->lastStopKeyWord == 'ORDERBY') {
$result['ORDERBY'] = $this->parseFieldList($parseString, '^(LIMIT)[[:space:]]+');
if ($this->parse_error) { return $this->parse_error; }
if ($this->parse_error) {
return $this->parse_error;
}
}
}
// LIMIT parsing:
if ($this->lastStopKeyWord == 'LIMIT') {
if ($this->lastStopKeyWord == 'LIMIT') {
if (preg_match('/^([0-9]+|[0-9]+[[:space:]]*,[[:space:]]*[0-9]+)$/',trim($parseString))) {
if (preg_match('/^([0-9]+|[0-9]+[[:space:]]*,[[:space:]]*[0-9]+)$/', trim($parseString))) {
$result['LIMIT'] = $parseString;
} else {
return $this->parseError('No value for limit!',$parseString);
return $this->parseError('No value for limit!', $parseString);
}
}
}
}
} else return $this->parseError('No table to select from!',$parseString);
} else {
return $this->parseError('No table to select from!', $parseString);
}
// Store current parseString in the result array for possible further processing (e.g., subquery support by DBAL)
$result['parseString'] = $parseString;
......
// Removing UPDATE
$parseString = $this->trimSQL($parseString);
$parseString = ltrim(substr($parseString,6));
$parseString = ltrim(substr($parseString, 6));
// Init output variable:
$result = array();
......
$result['TABLE'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+');
// Continue if string is not ended:
if ($result['TABLE']) {
if ($result['TABLE']) {
if ($parseString && $this->nextPart($parseString, '^(SET)[[:space:]]+')) {
if ($parseString && $this->nextPart($parseString, '^(SET)[[:space:]]+')) {
$comma = TRUE;
// Get field/value pairs:
while($comma) {
while ($comma) {
if ($fieldName = $this->nextPart($parseString,'^([[:alnum:]_]+)[[:space:]]*=')) {
if ($fieldName = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]*=')) {
$this->nextPart($parseString,'^(=)'); // Strip of "=" sign.
$this->nextPart($parseString, '^(=)'); // Strip of "=" sign.
$value = $this->getValue($parseString);
$result['FIELDS'][$fieldName] = $value;
} else return $this->parseError('No fieldname found',$parseString);
} else {
return $this->parseError('No fieldname found', $parseString);
}
$comma = $this->nextPart($parseString,'^(,)');
$comma = $this->nextPart($parseString, '^(,)');
}
// WHERE
if ($this->nextPart($parseString,'^(WHERE)')) {
if ($this->nextPart($parseString, '^(WHERE)')) {
$result['WHERE'] = $this->parseWhereClause($parseString);
if ($this->parse_error) { return $this->parse_error; }
if ($this->parse_error) {
return $this->parse_error;
}
}
} else return $this->parseError('Query missing SET...',$parseString);
} else return $this->parseError('No table found!',$parseString);
}
} else {
return $this->parseError('Query missing SET...', $parseString);
}
} else {
return $this->parseError('No table found!', $parseString);
}
// Should be no more content now:
if ($parseString) {
if ($parseString) {
return $this->parseError('Still content in clause after parsing!',$parseString);
return $this->parseError('Still content in clause after parsing!', $parseString);
}
// Return result:
......
// Removing INSERT
$parseString = $this->trimSQL($parseString);
$parseString = ltrim(substr(ltrim(substr($parseString,6)),4));
$parseString = ltrim(substr(ltrim(substr($parseString, 6)), 4));
// Init output variable:
$result = array();
......
// Get table:
$result['TABLE'] = $this->nextPart($parseString, '^([[:alnum:]_]+)([[:space:]]+|\()');
if ($result['TABLE']) {
if ($result['TABLE']) {
if ($this->nextPart($parseString,'^(VALUES)([[:space:]]+|\()')) { // In this case there are no field names mentioned in the SQL!
if ($this->nextPart($parseString, '^(VALUES)([[:space:]]+|\()')) { // In this case there are no field names mentioned in the SQL!
// Get values/fieldnames (depending...)
$result['VALUES_ONLY'] = $this->getValue($parseString,'IN');
$result['VALUES_ONLY'] = $this->getValue($parseString, 'IN');
if ($this->parse_error) {
if ($this->parse_error) {
return $this->parse_error;
}
if (preg_match('/^,/', $parseString)) {
......
$result['EXTENDED'] = '1';
while ($this->nextPart($parseString, '^(,)') === ',') {
$result['VALUES_ONLY'][] = $this->getValue($parseString, 'IN');
if ($this->parse_error) {
if ($this->parse_error) {
return $this->parse_error;
}
}
}
} else { // There are apparently fieldnames listed:
} else { // There are apparently fieldnames listed:
$fieldNames = $this->getValue($parseString,'_LIST');
$fieldNames = $this->getValue($parseString, '_LIST');
if ($this->parse_error) { return $this->parse_error; }
if ($this->parse_error) {
return $this->parse_error;
}
if ($this->nextPart($parseString,'^(VALUES)([[:space:]]+|\()')) { // "VALUES" keyword binds the fieldnames to values:
if ($this->nextPart($parseString, '^(VALUES)([[:space:]]+|\()')) { // "VALUES" keyword binds the fieldnames to values:
$result['FIELDS'] = array();
do {
$values = $this->getValue($parseString, 'IN'); // Using the "getValue" function to get the field list...
$values = $this->getValue($parseString, 'IN'); // Using the "getValue" function to get the field list...
if ($this->parse_error) {
if ($this->parse_error) {
return $this->parse_error;
}
$insertValues = array();
foreach ($fieldNames as $k => $fN) {
if (preg_match('/^[[:alnum:]_]+$/', $fN)) {
if (isset($values[$k])) {
if (isset($values[$k])) {
if (!isset($insertValues[$fN])) {
$insertValues[$fN] = $values[$k];
} else return $this->parseError('Fieldname ("' . $fN . '") already found in list!', $parseString);
} else return $this->parseError('No value set!', $parseString);
} else return $this->parseError('Invalid fieldname ("' . $fN . '")', $parseString);
} else {
return $this->parseError('Fieldname ("' . $fN . '") already found in list!', $parseString);
}
}
} else {
return $this->parseError('No value set!', $parseString);
}
} else {
return $this->parseError('Invalid fieldname ("' . $fN . '")', $parseString);
}
}
if (isset($values[$k + 1])) {
return $this->parseError('Too many values in list!', $parseString);
}
......
} else {
$result['EXTENDED'] = '1';
}
} else return $this->parseError('VALUES keyword expected',$parseString);
} else {
return $this->parseError('VALUES keyword expected', $parseString);
}
}
} else return $this->parseError('No table found!',$parseString);
}
} else {
return $this->parseError('No table found!', $parseString);
}
// Should be no more content now:
if ($parseString) {
if ($parseString) {
return $this->parseError('Still content after parsing!',$parseString);
return $this->parseError('Still content after parsing!', $parseString);
}
// Return result
......
// Removing DELETE
$parseString = $this->trimSQL($parseString);
$parseString = ltrim(substr(ltrim(substr($parseString,6)),4));
$parseString = ltrim(substr(ltrim(substr($parseString, 6)), 4));
// Init output variable:
$result = array();
......
// Get table:
$result['TABLE'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+');
if ($result['TABLE']) {
if ($result['TABLE']) {
// WHERE
if ($this->nextPart($parseString,'^(WHERE)')) {
if ($this->nextPart($parseString, '^(WHERE)')) {
$result['WHERE'] = $this->parseWhereClause($parseString);
if ($this->parse_error) { return $this->parse_error; }
if ($this->parse_error) {
return $this->parse_error;
}
}
} else return $this->parseError('No table found!',$parseString);
}
} else {
return $this->parseError('No table found!', $parseString);
}
// Should be no more content now:
if ($parseString) {
if ($parseString) {
return $this->parseError('Still content in clause after parsing!',$parseString);
return $this->parseError('Still content in clause after parsing!', $parseString);
}
// Return result:
......
// Removing EXPLAIN
$parseString = $this->trimSQL($parseString);
$parseString = ltrim(substr($parseString,6));
$parseString = ltrim(substr($parseString, 6));
// Init output variable:
$result = $this->parseSELECT($parseString);
if (is_array($result)) {
if (is_array($result)) {
$result['type'] = 'EXPLAIN';
}
......
// Removing CREATE TABLE
$parseString = $this->trimSQL($parseString);
$parseString = ltrim(substr(ltrim(substr($parseString,6)),5));
$parseString = ltrim(substr(ltrim(substr($parseString, 6)), 5));
// Init output variable:
$result = array();
$result['type'] = 'CREATETABLE';
// Get table:
$result['TABLE'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]*\(',TRUE);
$result['TABLE'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]*\(', TRUE);
if ($result['TABLE']) {
if ($result['TABLE']) {
// While the parseString is not yet empty:
while(strlen($parseString)>0) {
while (strlen($parseString) > 0) {
if ($key = $this->nextPart($parseString, '^(KEY|PRIMARY KEY|UNIQUE KEY|UNIQUE)([[:space:]]+|\()')) { // Getting key
if ($key = $this->nextPart($parseString, '^(KEY|PRIMARY KEY|UNIQUE KEY|UNIQUE)([[:space:]]+|\()')) { // Getting key
$key = strtoupper(str_replace(array(' ',TAB,CR,LF),'',$key));
$key = strtoupper(str_replace(array(' ', TAB, CR, LF), '', $key));
switch($key) {
switch ($key) {
case 'PRIMARYKEY':
$result['KEYS']['PRIMARYKEY'] = $this->getValue($parseString,'_LIST');
$result['KEYS']['PRIMARYKEY'] = $this->getValue($parseString, '_LIST');
if ($this->parse_error) { return $this->parse_error; }
if ($this->parse_error) {
return $this->parse_error;
}
break;
case 'UNIQUE':
case 'UNIQUEKEY':
if ($keyName = $this->nextPart($parseString, '^([[:alnum:]_]+)([[:space:]]+|\()')) {
if ($keyName = $this->nextPart($parseString, '^([[:alnum:]_]+)([[:space:]]+|\()')) {
$result['KEYS']['UNIQUE'] = array($keyName => $this->getValue($parseString,'_LIST'));
$result['KEYS']['UNIQUE'] = array($keyName => $this->getValue($parseString, '_LIST'));
if ($this->parse_error) { return $this->parse_error; }
} else return $this->parseError('No keyname found',$parseString);
if ($this->parse_error) {
return $this->parse_error;
}
} else {
return $this->parseError('No keyname found', $parseString);
}
break;
case 'KEY':
if ($keyName = $this->nextPart($parseString, '^([[:alnum:]_]+)([[:space:]]+|\()')) {
if ($keyName = $this->nextPart($parseString, '^([[:alnum:]_]+)([[:space:]]+|\()')) {
$result['KEYS'][$keyName] = $this->getValue($parseString, '_LIST', 'INDEX');
if ($this->parse_error) { return $this->parse_error; }
} else return $this->parseError('No keyname found',$parseString);
if ($this->parse_error) {
return $this->parse_error;
}
} else {
return $this->parseError('No keyname found', $parseString);
}
break;
}
} elseif ($fieldName = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+')) { // Getting field:
} elseif ($fieldName = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+')) { // Getting field:
$result['FIELDS'][$fieldName]['definition'] = $this->parseFieldDef($parseString);
if ($this->parse_error) { return $this->parse_error; }
if ($this->parse_error) {
return $this->parse_error;
}
}
}
// Finding delimiter:
$delim = $this->nextPart($parseString, '^(,|\))');
if (!$delim) {
if (!$delim) {
return $this->parseError('No delimiter found',$parseString);
return $this->parseError('No delimiter found', $parseString);
} elseif ($delim==')') {
} elseif ($delim == ')') {
break;
}
}
// Finding what is after the table definition - table type in MySQL
if ($delim==')') {
if ($delim == ')') {
if ($this->nextPart($parseString, '^((ENGINE|TYPE)[[:space:]]*=)')) {
if ($this->nextPart($parseString, '^((ENGINE|TYPE)[[:space:]]*=)')) {
$result['tableType'] = $parseString;
$parseString = '';
}
} else return $this->parseError('No fieldname found!',$parseString);
} else {
return $this->parseError('No fieldname found!', $parseString);
}
// Getting table type
// Getting table type
} else return $this->parseError('No table found!',$parseString);
} else {
return $this->parseError('No table found!', $parseString);
}
// Should be no more content now:
if ($parseString) {
if ($parseString) {
return $this->parseError('Still content in clause after parsing!',$parseString);
return $this->parseError('Still content in clause after parsing!', $parseString);
}
return $result;
......
// Removing ALTER TABLE
$parseString = $this->trimSQL($parseString);
$parseString = ltrim(substr(ltrim(substr($parseString,5)),5));
$parseString = ltrim(substr(ltrim(substr($parseString, 5)), 5));
// Init output variable:
$result = array();
......
return $this->parseError('No end backquote found!', $parseString);
}
if ($result['TABLE']) {
if ($result['TABLE']) {
if ($result['action'] = $this->nextPart($parseString, '^(CHANGE|DROP[[:space:]]+KEY|DROP[[:space:]]+PRIMARY[[:space:]]+KEY|ADD[[:space:]]+KEY|ADD[[:space:]]+PRIMARY[[:space:]]+KEY|ADD[[:space:]]+UNIQUE|DROP|ADD|RENAME|DEFAULT[[:space:]]+CHARACTER[[:space:]]+SET|ENGINE)([[:space:]]+|\(|=)')) {
if ($result['action'] = $this->nextPart($parseString, '^(CHANGE|DROP[[:space:]]+KEY|DROP[[:space:]]+PRIMARY[[:space:]]+KEY|ADD[[:space:]]+KEY|ADD[[:space:]]+PRIMARY[[:space:]]+KEY|ADD[[:space:]]+UNIQUE|DROP|ADD|RENAME|DEFAULT[[:space:]]+CHARACTER[[:space:]]+SET|ENGINE)([[:space:]]+|\(|=)')) {
$actionKey = strtoupper(str_replace(array(' ',TAB,CR,LF),'',$result['action']));
$actionKey = strtoupper(str_replace(array(' ', TAB, CR, LF), '', $result['action']));
// Getting field:
if (t3lib_div::inList('ADDPRIMARYKEY,DROPPRIMARYKEY,ENGINE', $actionKey) || $fieldKey = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+')) {
switch($actionKey) {
switch ($actionKey) {
case 'ADD':
$result['FIELD'] = $fieldKey;
$result['definition'] = $this->parseFieldDef($parseString);
if ($this->parse_error) { return $this->parse_error; }
if ($this->parse_error) {
return $this->parse_error;
}
break;
case 'DROP':
case 'RENAME':
......
break;
case 'CHANGE':
$result['FIELD'] = $fieldKey;
if ($result['newField'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+')) {
if ($result['newField'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+')) {
$result['definition'] = $this->parseFieldDef($parseString);
if ($this->parse_error) { return $this->parse_error; }
} else return $this->parseError('No NEW field name found',$parseString);
if ($this->parse_error) {
return $this->parse_error;
}
} else {
return $this->parseError('No NEW field name found', $parseString);
}
break;
case 'ADDKEY':
......
case 'ADDUNIQUE':
$result['KEY'] = $fieldKey;
$result['fields'] = $this->getValue($parseString, '_LIST', 'INDEX');
if ($this->parse_error) { return $this->parse_error; }
if ($this->parse_error) {
return $this->parse_error;
}
break;
case 'DROPKEY':
$result['KEY'] = $fieldKey;
break;
case 'DROPPRIMARYKEY':
// ??? todo!
// ??? todo!
break;
case 'DEFAULTCHARACTERSET':
$result['charset'] = $fieldKey;
......
$result['engine'] = $this->nextPart($parseString, '^=[[:space:]]*([[:alnum:]]+)[[:space:]]+', TRUE);
break;
}
} else return $this->parseError('No field name found',$parseString);
} else return $this->parseError('No action CHANGE, DROP or ADD found!',$parseString);
} else return $this->parseError('No table found!',$parseString);
} else {
return $this->parseError('No field name found', $parseString);
}
} else {
return $this->parseError('No action CHANGE, DROP or ADD found!', $parseString);
}
} else {
return $this->parseError('No table found!', $parseString);
}
// Should be no more content now:
if ($parseString) {
if ($parseString) {
return $this->parseError('Still content in clause after parsing!',$parseString);
return $this->parseError('Still content in clause after parsing!', $parseString);
}
return $result;
......
// Removing DROP TABLE
$parseString = $this->trimSQL($parseString);
$parseString = ltrim(substr(ltrim(substr($parseString,4)),5));
$parseString = ltrim(substr(ltrim(substr($parseString, 4)), 5));
// Init output variable:
$result = array();
$result['type'] = 'DROPTABLE';
// IF EXISTS
$result['ifExists'] = $this->nextPart($parseString, '^(IF[[:space:]]+EXISTS[[:space:]]+)');
$result['ifExists'] = $this->nextPart($parseString, '^(IF[[:space:]]+EXISTS[[:space:]]+)');
// Get table:
$result['TABLE'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+');
if ($result['TABLE']) {
if ($result['TABLE']) {
// Should be no more content now:
if ($parseString) {
if ($parseString) {
return $this->parseError('Still content in clause after parsing!',$parseString);
return $this->parseError('Still content in clause after parsing!', $parseString);
}
return $result;
} else return $this->parseError('No table found!',$parseString);
} else {
return $this->parseError('No table found!', $parseString);
}
}
}
/**
* Parsing CREATE DATABASE query
......
// Removing CREATE DATABASE
$parseString = $this->trimSQL($parseString);
$parseString = ltrim(substr(ltrim(substr($parseString,6)),8));
$parseString = ltrim(substr(ltrim(substr($parseString, 6)), 8));
// Init output variable:
$result = array();
......
// Get table:
$result['DATABASE'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+');
if ($result['DATABASE']) {
if ($result['DATABASE']) {
// Should be no more content now:
if ($parseString) {
if ($parseString) {
return $this->parseError('Still content in clause after parsing!',$parseString);
return $this->parseError('Still content in clause after parsing!', $parseString);
}
return $result;
} else return $this->parseError('No database found!',$parseString);
} else {
return $this->parseError('No database found!', $parseString);
}
}
}
/**
* Parsing TRUNCATE TABLE query
......
}
/**************************************
*
* SQL Parsing, helper functions for parts of queries
......
*/
public function parseFieldList(&$parseString, $stopRegex = '') {
$stack = array(); // Contains the parsed content
$stack = array(); // Contains the parsed content
if(strlen($parseString)==0) return $stack; // FIXME - should never happen, why does it?
if (strlen($parseString) == 0) {
return $stack;
} // FIXME - should never happen, why does it?
$pnt = 0; // Pointer to positions in $stack
$pnt = 0; // Pointer to positions in $stack
$level = 0; // Indicates the parenthesis level we are at.
$level = 0; // Indicates the parenthesis level we are at.
$loopExit = 0; // Recursivity brake.
$loopExit = 0; // Recursivity brake.
// Prepare variables:
$parseString = $this->trimSQL($parseString);
......
while (strlen($parseString)) {
// Checking if we are inside / outside parenthesis (in case of a function like count(), max(), min() etc...):
if ($level>0) { // Inside parenthesis here (does NOT detect if values in quotes are used, the only token is ")" or "("):
if ($level > 0) { // Inside parenthesis here (does NOT detect if values in quotes are used, the only token is ")" or "("):
// Accumulate function content until next () parenthesis:
$funcContent = $this->nextPart($parseString,'^([^()]*.)');
$funcContent = $this->nextPart($parseString, '^([^()]*.)');
$stack[$pnt]['func_content.'][] = array(
'level' => $level,
'func_content' => substr($funcContent,0,-1)
'func_content' => substr($funcContent, 0, -1)
);
$stack[$pnt]['func_content'].= $funcContent;
$stack[$pnt]['func_content'] .= $funcContent;
// Detecting ( or )
switch(substr($stack[$pnt]['func_content'],-1)) {
switch (substr($stack[$pnt]['func_content'], -1)) {
case '(':
$level++;
break;
case ')':
$level--;
if (!$level) { // If this was the last parenthesis:
if (!$level) { // If this was the last parenthesis:
$stack[$pnt]['func_content'] = substr($stack[$pnt]['func_content'],0,-1);
$stack[$pnt]['func_content'] = substr($stack[$pnt]['func_content'], 0, -1);
$parseString = ltrim($parseString); // Remove any whitespace after the parenthesis.
$parseString = ltrim($parseString); // Remove any whitespace after the parenthesis.
}
break;
}
} else { // Outside parenthesis, looking for next field:
} else { // Outside parenthesis, looking for next field:
// Looking for a flow-control construct (only known constructs supported)
if (preg_match('/^case([[:space:]][[:alnum:]\*._]+)?[[:space:]]when/i', $parseString)) {
......
}
} else {
// Looking for a known function (only known functions supported)
$func = $this->nextPart($parseString,'^(count|max|min|floor|sum|avg)[[:space:]]*\(');
$func = $this->nextPart($parseString, '^(count|max|min|floor|sum|avg)[[:space:]]*\(');
if ($func) {
if ($func) {
$parseString = trim(substr($parseString,1)); // Strip of "("
$parseString = trim(substr($parseString, 1)); // Strip of "("
$stack[$pnt]['type'] = 'function';
$stack[$pnt]['function'] = $func;
$level++; // increse parenthesis level counter.
$level++; // increse parenthesis level counter.
} else {
$stack[$pnt]['distinct'] = $this->nextPart($parseString,'^(distinct[[:space:]]+)');
$stack[$pnt]['distinct'] = $this->nextPart($parseString, '^(distinct[[:space:]]+)');
// Otherwise, look for regular fieldname:
if (($fieldName = $this->nextPart($parseString, '^([[:alnum:]\*._]+)(,|[[:space:]]+)')) !== '') {
$stack[$pnt]['type'] = 'field';
// Explode fieldname into field and table:
$tableField = explode('.',$fieldName,2);
$tableField = explode('.', $fieldName, 2);
if (count($tableField)==2) {
if (count($tableField) == 2) {
$stack[$pnt]['table'] = $tableField[0];
$stack[$pnt]['field'] = $tableField[1];
} else {
......
$stack[$pnt]['field'] = $tableField[0];
}
} else {
return $this->parseError('No field name found as expected in parseFieldList()',$parseString);
return $this->parseError('No field name found as expected in parseFieldList()', $parseString);
}
}
}
}
// After a function or field we look for "AS" alias and a comma to separate to the next field in the list:
if (!$level) {
if (!$level) {
// Looking for "AS" alias:
if ($as = $this->nextPart($parseString,'^(AS)[[:space:]]+')) {
if ($as = $this->nextPart($parseString, '^(AS)[[:space:]]+')) {
$stack[$pnt]['as'] = $this->nextPart($parseString,'^([[:alnum:]_]+)(,|[[:space:]]+)');
$stack[$pnt]['as'] = $this->nextPart($parseString, '^([[:alnum:]_]+)(,|[[:space:]]+)');
$stack[$pnt]['as_keyword'] = $as;
}
// Looking for "ASC" or "DESC" keywords (for ORDER BY)
if ($sDir = $this->nextPart($parseString,'^(ASC|DESC)([[:space:]]+|,)')) {
if ($sDir = $this->nextPart($parseString, '^(ASC|DESC)([[:space:]]+|,)')) {
$stack[$pnt]['sortDir'] = $sDir;
}
// Looking for stop-keywords:
if ($stopRegex && $this->lastStopKeyWord = $this->nextPart($parseString, $stopRegex)) {
if ($stopRegex && $this->lastStopKeyWord = $this->nextPart($parseString, $stopRegex)) {
$this->lastStopKeyWord = strtoupper(str_replace(array(' ',TAB,CR,LF),'',$this->lastStopKeyWord));
$this->lastStopKeyWord = strtoupper(str_replace(array(' ', TAB, CR, LF), '', $this->lastStopKeyWord));
return $stack;
}
// Looking for comma (since the stop-keyword did not trigger a return...)
if (strlen($parseString) && !$this->nextPart($parseString,'^(,)')) {
if (strlen($parseString) && !$this->nextPart($parseString, '^(,)')) {
return $this->parseError('No comma found as expected in parseFieldList()',$parseString);
return $this->parseError('No comma found as expected in parseFieldList()', $parseString);
}
// Increasing pointer:
......
// Check recursivity brake:
$loopExit++;
if ($loopExit>500) {
if ($loopExit > 500) {
return $this->parseError('More than 500 loops, exiting prematurely in parseFieldList()...',$parseString);
return $this->parseError('More than 500 loops, exiting prematurely in parseFieldList()...', $parseString);
}
}
......
$this->lastStopKeyWord = '';
$this->parse_error = '';
$stack = array(); // Contains the parsed content
$stack = array(); // Contains the parsed content
$pnt = 0; // Pointer to positions in $stack
$pnt = 0; // Pointer to positions in $stack
$loopExit = 0; // Recursivity brake.
$loopExit = 0; // Recursivity brake.
// $parseString is continously shortend by the process and we keep parsing it till it is zero:
while (strlen($parseString)) {
// Looking for the table:
if ($stack[$pnt]['table'] = $this->nextPart($parseString,'^([[:alnum:]_]+)(,|[[:space:]]+)')) {
if ($stack[$pnt]['table'] = $this->nextPart($parseString, '^([[:alnum:]_]+)(,|[[:space:]]+)')) {
// Looking for stop-keywords before fetching potential table alias:
if ($stopRegex && ($this->lastStopKeyWord = $this->nextPart($parseString, $stopRegex))) {
$this->lastStopKeyWord = strtoupper(str_replace(array(' ',TAB,CR,LF), '', $this->lastStopKeyWord));
$this->lastStopKeyWord = strtoupper(str_replace(array(' ', TAB, CR, LF), '', $this->lastStopKeyWord));
return $stack;
}
if (!preg_match('/^(LEFT|RIGHT|JOIN|INNER)[[:space:]]+/i', $parseString)) {
$stack[$pnt]['as_keyword'] = $this->nextPart($parseString,'^(AS[[:space:]]+)');
$stack[$pnt]['as_keyword'] = $this->nextPart($parseString, '^(AS[[:space:]]+)');
$stack[$pnt]['as'] = $this->nextPart($parseString,'^([[:alnum:]_]+)[[:space:]]*');
$stack[$pnt]['as'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]*');
}
} else return $this->parseError('No table name found as expected in parseFromTables()!', $parseString);
} else {
return $this->parseError('No table name found as expected in parseFromTables()!', $parseString);
}
// Looking for JOIN
$joinCnt = 0;
while ($join = $this->nextPart($parseString,'^(LEFT[[:space:]]+JOIN|LEFT[[:space:]]+OUTER[[:space:]]+JOIN|RIGHT[[:space:]]+JOIN|RIGHT[[:space:]]+OUTER[[:space:]]+JOIN|INNER[[:space:]]+JOIN|JOIN)[[:space:]]+')) {
while ($join = $this->nextPart($parseString, '^(LEFT[[:space:]]+JOIN|LEFT[[:space:]]+OUTER[[:space:]]+JOIN|RIGHT[[:space:]]+JOIN|RIGHT[[:space:]]+OUTER[[:space:]]+JOIN|INNER[[:space:]]+JOIN|JOIN)[[:space:]]+')) {
$stack[$pnt]['JOIN'][$joinCnt]['type'] = $join;
if ($stack[$pnt]['JOIN'][$joinCnt]['withTable'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+', 1)) {
if (!preg_match('/^ON[[:space:]]+/i', $parseString)) {
......
}
}
$joinCnt++;
} else return $this->parseError('No join table found in parseFromTables()!', $parseString);
} else {
return $this->parseError('No join table found in parseFromTables()!', $parseString);
}
}
}
// Looking for stop-keywords:
if ($stopRegex && $this->lastStopKeyWord = $this->nextPart($parseString, $stopRegex)) {
$this->lastStopKeyWord = strtoupper(str_replace(array(' ',TAB,CR,LF), '', $this->lastStopKeyWord));
$this->lastStopKeyWord = strtoupper(str_replace(array(' ', TAB, CR, LF), '', $this->lastStopKeyWord));
return $stack;
}
......
$this->lastStopKeyWord = '';
$this->parse_error = '';
$stack = array(0 => array()); // Contains the parsed content
$stack = array(0 => array()); // Contains the parsed content
$pnt = array(0 => 0); // Pointer to positions in $stack
$pnt = array(0 => 0); // Pointer to positions in $stack
$level = 0; // Determines parenthesis level
$level = 0; // Determines parenthesis level
$loopExit = 0; // Recursivity brake.
$loopExit = 0; // Recursivity brake.
// $parseString is continously shortend by the process and we keep parsing it till it is zero:
while (strlen($parseString)) {
// Look for next parenthesis level:
$newLevel = $this->nextPart($parseString,'^([(])');
$newLevel = $this->nextPart($parseString, '^([(])');
if ($newLevel == '(') { // If new level is started, manage stack/pointers:
if ($newLevel == '(') { // If new level is started, manage stack/pointers:
$level++; // Increase level
$level++; // Increase level
$pnt[$level] = 0; // Reset pointer for this level
$pnt[$level] = 0; // Reset pointer for this level
$stack[$level] = array(); // Reset stack for this level
$stack[$level] = array(); // Reset stack for this level
} else { // If no new level is started, just parse the current level:
} else { // If no new level is started, just parse the current level:
// Find "modifier", eg. "NOT or !"
$stack[$level][$pnt[$level]]['modifier'] = trim($this->nextPart($parseString, '^(!|NOT[[:space:]]+)'));
......
// See if condition is EXISTS with a subquery
if (preg_match('/^EXISTS[[:space:]]*[(]/i', $parseString)) {
$stack[$level][$pnt[$level]]['func']['type'] = $this->nextPart($parseString, '^(EXISTS)[[:space:]]*');
$parseString = trim(substr($parseString, 1)); // Strip of "("
$parseString = trim(substr($parseString, 1)); // Strip of "("
$stack[$level][$pnt[$level]]['func']['subquery'] = $this->parseSELECT($parseString, $parameterReferences);
// Seek to new position in parseString after parsing of the subquery
$parseString = $stack[$level][$pnt[$level]]['func']['subquery']['parseString'];
unset($stack[$level][$pnt[$level]]['func']['subquery']['parseString']);
if (!$this->nextPart($parseString, '^([)])')) {
return 'No ) parenthesis at end of subquery';
}
} else {
}
} else {
// See if LOCATE function is found
// See if LOCATE function is found
if (preg_match('/^LOCATE[[:space:]]*[(]/i', $parseString)) {
$stack[$level][$pnt[$level]]['func']['type'] = $this->nextPart($parseString, '^(LOCATE)[[:space:]]*');
$parseString = trim(substr($parseString, 1)); // Strip of "("
$parseString = trim(substr($parseString, 1)); // Strip of "("
$stack[$level][$pnt[$level]]['func']['substr'] = $this->getValue($parseString);
if (!$this->nextPart($parseString, '^(,)')) {
return $this->parseError('No comma found as expected in parseWhereClause()', $parseString);
......
$stack[$level][$pnt[$level]]['func']['table'] = '';
$stack[$level][$pnt[$level]]['func']['field'] = $tableField[0];
}
} else {
} else {
return $this->parseError('No field name found as expected in parseWhereClause()', $parseString);
}
}
if ($this->nextPart($parseString, '^(,)')) {
$stack[$level][$pnt[$level]]['func']['pos'] = $this->getValue($parseString);
}
if (!$this->nextPart($parseString, '^([)])')) {
return $this->parseError('No ) parenthesis at end of function', $parseString);
}
}
} elseif (preg_match('/^IFNULL[[:space:]]*[(]/i', $parseString)) {
$stack[$level][$pnt[$level]]['func']['type'] = $this->nextPart($parseString, '^(IFNULL)[[:space:]]*');
$parseString = trim(substr($parseString, 1)); // Strip of "("
$parseString = trim(substr($parseString, 1)); // Strip of "("
if ($fieldName = $this->nextPart($parseString, '^([[:alnum:]\*._]+)[[:space:]]*')) {
// Parse field name into field and table:
......
$stack[$level][$pnt[$level]]['func']['table'] = '';
$stack[$level][$pnt[$level]]['func']['field'] = $tableField[0];
}
} else {
} else {
return $this->parseError('No field name found as expected in parseWhereClause()', $parseString);
}
}
if ($this->nextPart($parseString, '^(,)')) {
$stack[$level][$pnt[$level]]['func']['default'] = $this->getValue($parseString);
}
if (!$this->nextPart($parseString, '^([)])')) {
return $this->parseError('No ) parenthesis at end of function', $parseString);
}
}
} elseif (preg_match('/^FIND_IN_SET[[:space:]]*[(]/i', $parseString)) {
$stack[$level][$pnt[$level]]['func']['type'] = $this->nextPart($parseString, '^(FIND_IN_SET)[[:space:]]*');
$parseString = trim(substr($parseString, 1)); // Strip of "("
$parseString = trim(substr($parseString, 1)); // Strip of "("
if ($str = $this->getValue($parseString)) {
$stack[$level][$pnt[$level]]['func']['str'] = $str;
if ($fieldName = $this->nextPart($parseString, '^,[[:space:]]*([[:alnum:]._]+)[[:space:]]*', TRUE)) {
......
}
if (!$this->nextPart($parseString, '^([)])')) {
return $this->parseError('No ) parenthesis at end of function', $parseString);
}
}
} else {
return $this->parseError('No item to look for found as expected in parseWhereClause()', $parseString);
}
} else {
} else {
// Support calculated value only for:
// Support calculated value only for:
// - "&" (boolean AND)
// - "+" (addition)
// - "-" (substraction)
......
// Parse field name into field and table:
$tableField = explode('.', $fieldName, 2);
if (count($tableField) == 2) {
if (count($tableField) == 2) {
$stack[$level][$pnt[$level]]['table'] = $tableField[0];
$stack[$level][$pnt[$level]]['field'] = $tableField[1];
} else {
} else {
$stack[$level][$pnt[$level]]['table'] = '';
$stack[$level][$pnt[$level]]['field'] = $tableField[0];
}
}
} else {
return $this->parseError('No field name found as expected in parseWhereClause()', $parseString);
}
}
// See if the value is calculated:
$stack[$level][$pnt[$level]]['calc'] = $this->nextPart($parseString, '^(' . $calcOperators . ')');
......
}
}
}
}
}
// Find "comparator":
$comparatorPatterns = array(
'<=', '>=', '<', '>', '=', '!=',
'NOT[[:space:]]+IN', 'IN',
'NOT[[:space:]]+LIKE[[:space:]]+BINARY', 'LIKE[[:space:]]+BINARY', 'NOT[[:space:]]+LIKE', 'LIKE',
'IS[[:space:]]+NOT', 'IS',
'BETWEEN', 'NOT[[:space]]+BETWEEN',
);
// Find "comparator":
$comparatorPatterns = array(
'<=', '>=', '<', '>', '=', '!=',
'NOT[[:space:]]+IN', 'IN',
'NOT[[:space:]]+LIKE[[:space:]]+BINARY', 'LIKE[[:space:]]+BINARY', 'NOT[[:space:]]+LIKE', 'LIKE',
'IS[[:space:]]+NOT', 'IS',
'BETWEEN', 'NOT[[:space]]+BETWEEN',
);
$stack[$level][$pnt[$level]]['comparator'] = $this->nextPart($parseString, '^(' . implode('|', $comparatorPatterns) . ')');
if (strlen($stack[$level][$pnt[$level]]['comparator'])) {
if (preg_match('/^CONCAT[[:space:]]*\(/', $parseString)) {
......
// Look for ending parenthesis:
$this->nextPart($parseString, '([)])');
$stack[$level][$pnt[$level]]['value'] = $values;
} else if (t3lib_div::inList('IN,NOT IN', $stack[$level][$pnt[$level]]['comparator']) && preg_match('/^[(][[:space:]]*SELECT[[:space:]]+/', $parseString)) {
} else {
if (t3lib_div::inList('IN,NOT IN', $stack[$level][$pnt[$level]]['comparator']) && preg_match('/^[(][[:space:]]*SELECT[[:space:]]+/', $parseString)) {
$this->nextPart($parseString, '^([(])');
$stack[$level][$pnt[$level]]['subquery'] = $this->parseSELECT($parseString, $parameterReferences);
// Seek to new position in parseString after parsing of the subquery
$parseString = $stack[$level][$pnt[$level]]['subquery']['parseString'];
unset($stack[$level][$pnt[$level]]['subquery']['parseString']);
if (!$this->nextPart($parseString, '^([)])')) {
return 'No ) parenthesis at end of subquery';
}
$this->nextPart($parseString, '^([(])');
$stack[$level][$pnt[$level]]['subquery'] = $this->parseSELECT($parseString, $parameterReferences);
// Seek to new position in parseString after parsing of the subquery
$parseString = $stack[$level][$pnt[$level]]['subquery']['parseString'];
unset($stack[$level][$pnt[$level]]['subquery']['parseString']);
if (!$this->nextPart($parseString, '^([)])')) {
return 'No ) parenthesis at end of subquery';
}
} else if (t3lib_div::inList('BETWEEN,NOT BETWEEN', $stack[$level][$pnt[$level]]['comparator'])) {
} else {
if (t3lib_div::inList('BETWEEN,NOT BETWEEN', $stack[$level][$pnt[$level]]['comparator'])) {
$stack[$level][$pnt[$level]]['values'] = array();
$stack[$level][$pnt[$level]]['values'][0] = $this->getValue($parseString);
if (!$this->nextPart($parseString, '^(AND)')) {
return $this->parseError('No AND operator found as expected in parseWhereClause()', $parseString);
}
$stack[$level][$pnt[$level]]['values'][1] = $this->getValue($parseString);
} else {
// Finding value for comparator:
$stack[$level][$pnt[$level]]['value'] = &$this->getValueOrParameter($parseString, $stack[$level][$pnt[$level]]['comparator'], '', $parameterReferences);
$stack[$level][$pnt[$level]]['values'] = array();
$stack[$level][$pnt[$level]]['values'][0] = $this->getValue($parseString);
if (!$this->nextPart($parseString, '^(AND)')) {
return $this->parseError('No AND operator found as expected in parseWhereClause()', $parseString);
}
$stack[$level][$pnt[$level]]['values'][1] = $this->getValue($parseString);
} else {
// Finding value for comparator:
$stack[$level][$pnt[$level]]['value'] = &$this->getValueOrParameter($parseString, $stack[$level][$pnt[$level]]['comparator'], '', $parameterReferences);
if ($this->parse_error) {
if ($this->parse_error) {
return $this->parse_error;
}
}
}
}
return $this->parse_error;
}
}
}
}
}
}
// Finished, increase pointer:
$pnt[$level]++;
......
}
// Checking if the current level is ended, in that case do stack management:
while ($this->nextPart($parseString,'^([)])')) {
while ($this->nextPart($parseString, '^([)])')) {
$level--; // Decrease level:
$level--; // Decrease level:
$stack[$level][$pnt[$level]]['sub'] = $stack[$level+1]; // Copy stack
$stack[$level][$pnt[$level]]['sub'] = $stack[$level + 1]; // Copy stack
$pnt[$level]++; // Increase pointer of the new level
$pnt[$level]++; // Increase pointer of the new level
// Make recursivity check:
$loopExit++;
......
// Looking for stop-keywords:
if ($stopRegex && $this->lastStopKeyWord = $this->nextPart($parseString, $stopRegex)) {
$this->lastStopKeyWord = strtoupper(str_replace(array(' ',TAB,CR,LF), '', $this->lastStopKeyWord));
$this->lastStopKeyWord = strtoupper(str_replace(array(' ', TAB, CR, LF), '', $this->lastStopKeyWord));
return $stack[0];
} else {
return $this->parseError('No operator, but parsing not finished in parseWhereClause().', $parseString);
......
$result = array();
// Field type:
if ($result['fieldType'] = $this->nextPart($parseString,'^(int|smallint|tinyint|mediumint|bigint|double|numeric|decimal|float|varchar|char|text|tinytext|mediumtext|longtext|blob|tinyblob|mediumblob|longblob)([[:space:],]+|\()')) {
if ($result['fieldType'] = $this->nextPart($parseString, '^(int|smallint|tinyint|mediumint|bigint|double|numeric|decimal|float|varchar|char|text|tinytext|mediumtext|longtext|blob|tinyblob|mediumblob|longblob)([[:space:],]+|\()')) {
// Looking for value:
if (substr($parseString,0,1)=='(') {
if (substr($parseString, 0, 1) == '(') {
$parseString = substr($parseString,1);
$parseString = substr($parseString, 1);
if ($result['value'] = $this->nextPart($parseString,'^([^)]*)')) {
if ($result['value'] = $this->nextPart($parseString, '^([^)]*)')) {
$parseString = ltrim(substr($parseString,1));
$parseString = ltrim(substr($parseString, 1));
} else return $this->parseError('No end-parenthesis for value found in parseFieldDef()!',$parseString);
} else {
return $this->parseError('No end-parenthesis for value found in parseFieldDef()!', $parseString);
}
}
}
// Looking for keywords
while($keyword = $this->nextPart($parseString,'^(DEFAULT|NOT[[:space:]]+NULL|AUTO_INCREMENT|UNSIGNED)([[:space:]]+|,|\))')) {
while ($keyword = $this->nextPart($parseString, '^(DEFAULT|NOT[[:space:]]+NULL|AUTO_INCREMENT|UNSIGNED)([[:space:]]+|,|\))')) {
$keywordCmp = strtoupper(str_replace(array(' ',TAB,CR,LF),'',$keyword));
$keywordCmp = strtoupper(str_replace(array(' ', TAB, CR, LF), '', $keyword));
$result['featureIndex'][$keywordCmp]['keyword'] = $keyword;
switch($keywordCmp) {
switch ($keywordCmp) {
case 'DEFAULT':
$result['featureIndex'][$keywordCmp]['value'] = $this->getValue($parseString);
break;
}
}
} else {
return $this->parseError('Field type unknown in parseFieldDef()!',$parseString);
return $this->parseError('Field type unknown in parseFieldDef()!', $parseString);
}
return $result;
}
/************************************
*
* Parsing: Helper functions
......
*/
protected function nextPart(&$parseString, $regex, $trimAll = FALSE) {
$reg = array();
if (preg_match('/'.$regex.'/i',$parseString.' ', $reg)) { // Adding space char because [[:space:]]+ is often a requirement in regex's
if (preg_match('/' . $regex . '/i', $parseString . ' ', $reg)) { // Adding space char because [[:space:]]+ is often a requirement in regex's
$parseString = ltrim(substr($parseString,strlen($reg[$trimAll?0:1])));
$parseString = ltrim(substr($parseString, strlen($reg[$trimAll ? 0 : 1])));
return $reg[1];
}
// No match found
......
}
$value = array('?');
$parameterReferences['?'][] = &$value;
} elseif ($parameter !== '') { // named parameter
} elseif ($parameter !== '') { // named parameter
if (isset($parameterReferences[$parameter])) {
// Use the same reference as last time we encountered this parameter
$value = &$parameterReferences[$parameter];
......
protected function getValue(&$parseString, $comparator = '', $mode = '') {
$value = '';
if (t3lib_div::inList('NOTIN,IN,_LIST',strtoupper(str_replace(array(' ',LF,CR,TAB),'',$comparator)))) { // List of values:
if (t3lib_div::inList('NOTIN,IN,_LIST', strtoupper(str_replace(array(' ', LF, CR, TAB), '', $comparator)))) { // List of values:
if ($this->nextPart($parseString,'^([(])')) {
if ($this->nextPart($parseString, '^([(])')) {
$listValues = array();
$comma=',';
$comma = ',';
while($comma==',') {
while ($comma == ',') {
$listValues[] = $this->getValue($parseString);
if ($mode === 'INDEX') {
// Remove any length restriction on INDEX definition
$this->nextPart($parseString, '^([(]\d+[)])');
}
$comma = $this->nextPart($parseString,'^([,])');
$comma = $this->nextPart($parseString, '^([,])');
}
$out = $this->nextPart($parseString,'^([)])');
$out = $this->nextPart($parseString, '^([)])');
if ($out) {
if ($out) {
if ($comparator=='_LIST') {
if ($comparator == '_LIST') {
$kVals = array();
foreach ($listValues as $vArr) {
foreach ($listValues as $vArr) {
$kVals[] = $vArr[0];
}
return $kVals;
} else {
return $listValues;
}
} else return array($this->parseError('No ) parenthesis in list',$parseString));
} else return array($this->parseError('No ( parenthesis starting the list',$parseString));
} else {
return array($this->parseError('No ) parenthesis in list', $parseString));
}
} else {
return array($this->parseError('No ( parenthesis starting the list', $parseString));
}
} else { // Just plain string value, in quotes or not:
} else { // Just plain string value, in quotes or not:
// Quote?
$firstChar = substr($parseString,0,1);
$firstChar = substr($parseString, 0, 1);
switch($firstChar) {
switch ($firstChar) {
case '"':
$value = array($this->getValueInQuotes($parseString,'"'),'"');
$value = array($this->getValueInQuotes($parseString, '"'), '"');
break;
case "'":
$value = array($this->getValueInQuotes($parseString,"'"),"'");
$value = array($this->getValueInQuotes($parseString, "'"), "'");
break;
default:
$reg = array();
if (preg_match('/^([[:alnum:]._-]+)/i',$parseString, $reg)) {
if (preg_match('/^([[:alnum:]._-]+)/i', $parseString, $reg)) {
$parseString = ltrim(substr($parseString,strlen($reg[0])));
$parseString = ltrim(substr($parseString, strlen($reg[0])));
$value = array($reg[1]);
}
break;
......
*/
protected function getValueInQuotes(&$parseString, $quote) {
$parts = explode($quote,substr($parseString,1));
$parts = explode($quote, substr($parseString, 1));
$buffer = '';
foreach($parts as $k => $v) {
foreach ($parts as $k => $v) {
$buffer.=$v;
$buffer .= $v;
$reg = array();
preg_match('/\\\\$/', $v, $reg);
if ($reg AND strlen($reg[0])%2) {
if ($reg AND strlen($reg[0]) % 2) {
$buffer.=$quote;
$buffer .= $quote;
} else {
$parseString = ltrim(substr($parseString,strlen($buffer)+2));
$parseString = ltrim(substr($parseString, strlen($buffer) + 2));
return $this->parseStripslashes($buffer);
}
}
......
* @return string Error message.
*/
protected function parseError($msg, $restQuery) {
$this->parse_error = 'SQL engine parse ERROR: '.$msg.': near "'.substr($restQuery,0,50).'"';
$this->parse_error = 'SQL engine parse ERROR: ' . $msg . ': near "' . substr($restQuery, 0, 50) . '"';
return $this->parse_error;
}
......
* @return string Output string
*/
protected function trimSQL($str) {
return trim(rtrim($str, "; \r\n\t")).' ';
return trim(rtrim($str, "; \r\n\t")) . ' ';
}
/*************************
*
* Compiling queries
......
* @see parseSQL()
*/
public function compileSQL($components) {
switch($components['type']) {
switch ($components['type']) {
case 'SELECT':
$query = $this->compileSELECT($components);
break;
......
$query = $this->compileDELETE($components);
break;
case 'EXPLAIN':
$query = 'EXPLAIN '.$this->compileSELECT($components);
$query = 'EXPLAIN ' . $this->compileSELECT($components);
break;
case 'DROPTABLE':
$query = 'DROP TABLE'.($components['ifExists']?' IF EXISTS':'').' '.$components['TABLE'];
$query = 'DROP TABLE' . ($components['ifExists'] ? ' IF EXISTS' : '') . ' ' . $components['TABLE'];
break;
case 'CREATETABLE':
$query = $this->compileCREATETABLE($components);
......
$limit = $components['LIMIT'];
... This diff was truncated because it exceeds the maximum size that can be displayed.
(55-55/93)