Main Page | Directories | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages | Examples

class.t3lib_sqlparser.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 2004 Kasper Skaarhoj (kasperYYYY@typo3.com)
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00106 class t3lib_sqlparser {
00107 
00108       // Parser:
00109    var $parse_error = '';                 // Parsing error string
00110    var $lastStopKeyWord = '';             // Last stop keyword used.
00111 
00112 
00113 
00114 
00115    /*************************************
00116     *
00117     * SQL Parsing, full queries
00118     *
00119     **************************************/
00120 
00128    function parseSQL($parseString)  {
00129 
00130          // Prepare variables:
00131       $parseString = $this->trimSQL($parseString);
00132       $this->parse_error = '';
00133       $result = array();
00134 
00135          // Finding starting keyword of string:
00136       $_parseString = $parseString; // Protecting original string...
00137       $keyword = $this->nextPart($_parseString, '^(SELECT|UPDATE|INSERT[[:space:]]+INTO|DELETE[[:space:]]+FROM|EXPLAIN|DROP[[:space:]]+TABLE|CREATE[[:space:]]+TABLE|ALTER[[:space:]]+TABLE)[[:space:]]+');
00138       $keyword = strtoupper(ereg_replace('[[:space:]]*','',$keyword));
00139 
00140       switch($keyword)  {
00141          case 'SELECT':
00142                // Parsing SELECT query:
00143             $result = $this->parseSELECT($parseString);
00144          break;
00145          case 'UPDATE':
00146                // Parsing UPDATE query:
00147             $result = $this->parseUPDATE($parseString);
00148          break;
00149          case 'INSERTINTO':
00150                // Parsing INSERT query:
00151             $result = $this->parseINSERT($parseString);
00152          break;
00153          case 'DELETEFROM':
00154                // Parsing DELETE query:
00155             $result = $this->parseDELETE($parseString);
00156          break;
00157          case 'EXPLAIN':
00158                // Parsing EXPLAIN SELECT query:
00159             $result = $this->parseEXPLAIN($parseString);
00160          break;
00161          case 'DROPTABLE':
00162                // Parsing DROP TABLE query:
00163             $result = $this->parseDROPTABLE($parseString);
00164          break;
00165          case 'ALTERTABLE':
00166                // Parsing ALTER TABLE query:
00167             $result = $this->parseALTERTABLE($parseString);
00168          break;
00169          case 'CREATETABLE':
00170                // Parsing CREATE TABLE query:
00171             $result = $this->parseCREATETABLE($parseString);
00172          break;
00173          default:
00174             return $this->parseError('"'.$keyword.'" is not a keyword',$parseString);
00175          break;
00176       }
00177 
00178       return $result;
00179    }
00180 
00188    function parseSELECT($parseString)  {
00189 
00190          // Removing SELECT:
00191       $parseString = $this->trimSQL($parseString);
00192       $parseString = eregi_replace('^SELECT[[:space:]]+','',$parseString);
00193 
00194          // Init output variable:
00195       $result = array();
00196       $result['type'] = 'SELECT';
00197 
00198          // Looking for STRAIGHT_JOIN keyword:
00199       $result['STRAIGHT_JOIN'] = $this->nextPart($parseString, '^(STRAIGHT_JOIN)[[:space:]]+');
00200 
00201          // Select fields:
00202       $result['SELECT'] = $this->parseFieldList($parseString, '^(FROM)[[:space:]]+');
00203       if ($this->parse_error) { return $this->parse_error; }
00204 
00205          // Continue if string is not ended:
00206       if ($parseString) {
00207 
00208             // Get table list:
00209          $result['FROM'] = $this->parseFromTables($parseString, '^(WHERE)[[:space:]]+');
00210          if ($this->parse_error) { return $this->parse_error; }
00211 
00212             // If there are more than just the tables (a WHERE clause that would be...)
00213          if ($parseString) {
00214 
00215                // Get WHERE clause:
00216             $result['WHERE'] = $this->parseWhereClause($parseString, '^(GROUP[[:space:]]+BY|ORDER[[:space:]]+BY|LIMIT)[[:space:]]+');
00217             if ($this->parse_error) { return $this->parse_error; }
00218 
00219                // If the WHERE clause parsing was stopped by GROUP BY, ORDER BY or LIMIT, then proceed with parsing:
00220             if ($this->lastStopKeyWord)   {
00221 
00222                   // GROUP BY parsing:
00223                if ($this->lastStopKeyWord == 'GROUPBY')  {
00224                   $result['GROUPBY'] = $this->parseFieldList($parseString, '^(ORDER[[:space:]]+BY|LIMIT)[[:space:]]+');
00225                   if ($this->parse_error) { return $this->parse_error; }
00226                }
00227 
00228                   // ORDER BY parsing:
00229                if ($this->lastStopKeyWord == 'ORDERBY')  {
00230                   $result['ORDERBY'] = $this->parseFieldList($parseString, '^(LIMIT)[[:space:]]+');
00231                   if ($this->parse_error) { return $this->parse_error; }
00232                }
00233 
00234                   // LIMIT parsing:
00235                if ($this->lastStopKeyWord == 'LIMIT') {
00236                   if (ereg('^([0-9]+|[0-9]+[[:space:]]*,[[:space:]]*[0-9]+)$',trim($parseString))) {
00237                      $result['LIMIT'] = $parseString;
00238                   } else {
00239                      return $this->parseError('No value for limit!',$parseString);
00240                   }
00241                }
00242             }
00243          }
00244       } else return $this->parseError('No table to select from!',$parseString);
00245 
00246          // Return result:
00247       return $result;
00248    }
00249 
00257    function parseUPDATE($parseString)  {
00258 
00259          // Removing UPDATE
00260       $parseString = $this->trimSQL($parseString);
00261       $parseString = eregi_replace('^UPDATE[[:space:]]+','',$parseString);
00262 
00263          // Init output variable:
00264       $result = array();
00265       $result['type'] = 'UPDATE';
00266 
00267          // Get table:
00268       $result['TABLE'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+');
00269 
00270          // Continue if string is not ended:
00271       if ($result['TABLE'])   {
00272          if ($parseString && $this->nextPart($parseString, '^(SET)[[:space:]]+'))   {
00273 
00274             $comma = TRUE;
00275 
00276                // Get field/value pairs:
00277             while($comma)  {
00278                if ($fieldName = $this->nextPart($parseString,'^([[:alnum:]_]+)[[:space:]]*='))  {
00279                   $this->nextPart($parseString,'^(=)');  // Strip of "=" sign.
00280                   $value = $this->getValue($parseString);
00281                   $result['FIELDS'][$fieldName] = $value;
00282                } else return $this->parseError('No fieldname found',$parseString);
00283 
00284                $comma = $this->nextPart($parseString,'^(,)');
00285             }
00286 
00287                // WHERE
00288             if ($this->nextPart($parseString,'^(WHERE)'))   {
00289                $result['WHERE'] = $this->parseWhereClause($parseString);
00290                if ($this->parse_error) { return $this->parse_error; }
00291             }
00292          } else return $this->parseError('Query missing SET...',$parseString);
00293       } else return $this->parseError('No table found!',$parseString);
00294 
00295          // Should be no more content now:
00296       if ($parseString) {
00297          return $this->parseError('Still content in clause after parsing!',$parseString);
00298       }
00299 
00300          // Return result:
00301       return $result;
00302    }
00303 
00311    function parseINSERT($parseString)  {
00312 
00313          // Removing INSERT
00314       $parseString = $this->trimSQL($parseString);
00315       $parseString = eregi_replace('^INSERT[[:space:]]+INTO[[:space:]]+','',$parseString);
00316 
00317          // Init output variable:
00318       $result = array();
00319       $result['type'] = 'INSERT';
00320 
00321          // Get table:
00322       $result['TABLE'] = $this->nextPart($parseString, '^([[:alnum:]_]+)([[:space:]]+|\()');
00323 
00324       if ($result['TABLE'])   {
00325 
00326          if ($this->nextPart($parseString,'^(VALUES)[[:space:]]+'))  {  // In this case there are no field names mentioned in the SQL!
00327                // Get values/fieldnames (depending...)
00328             $result['VALUES_ONLY'] = $this->getValue($parseString,'IN');
00329             if ($this->parse_error) { return $this->parse_error; }
00330          } else { // There are apparently fieldnames listed:
00331             $fieldNames = $this->getValue($parseString,'_LIST');
00332             if ($this->parse_error) { return $this->parse_error; }
00333 
00334             if ($this->nextPart($parseString,'^(VALUES)[[:space:]]+'))  {  // "VALUES" keyword binds the fieldnames to values:
00335 
00336                $values = $this->getValue($parseString,'IN');   // Using the "getValue" function to get the field list...
00337                if ($this->parse_error) { return $this->parse_error; }
00338 
00339                foreach($fieldNames as $k => $fN)   {
00340                   if (ereg('^[[:alnum:]_]+$',$fN)) {
00341                      if (isset($values[$k])) {
00342                         if (!isset($result['FIELDS'][$fN])) {
00343                            $result['FIELDS'][$fN] = $values[$k];
00344                         } else return $this->parseError('Fieldname ("'.$fN.'") already found in list!',$parseString);
00345                      } else return $this->parseError('No value set!',$parseString);
00346                   } else return $this->parseError('Invalid fieldname ("'.$fN.'")',$parseString);
00347                }
00348                if (isset($values[$k+1]))  {
00349                   return $this->parseError('Too many values in list!',$parseString);
00350                }
00351             } else return $this->parseError('VALUES keyword expected',$parseString);
00352          }
00353       }  else return $this->parseError('No table found!',$parseString);
00354 
00355          // Should be no more content now:
00356       if ($parseString) {
00357          return $this->parseError('Still content after parsing!',$parseString);
00358       }
00359 
00360          // Return result
00361       return $result;
00362    }
00363 
00371    function parseDELETE($parseString)  {
00372 
00373          // Removing DELETE
00374       $parseString = $this->trimSQL($parseString);
00375       $parseString = eregi_replace('^DELETE[[:space:]]+FROM[[:space:]]+','',$parseString);
00376 
00377          // Init output variable:
00378       $result = array();
00379       $result['type'] = 'DELETE';
00380 
00381          // Get table:
00382       $result['TABLE'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+');
00383 
00384       if ($result['TABLE'])   {
00385 
00386             // WHERE
00387          if ($this->nextPart($parseString,'^(WHERE)'))   {
00388             $result['WHERE'] = $this->parseWhereClause($parseString);
00389             if ($this->parse_error) { return $this->parse_error; }
00390          }
00391       } else return $this->parseError('No table found!',$parseString);
00392 
00393          // Should be no more content now:
00394       if ($parseString) {
00395          return $this->parseError('Still content in clause after parsing!',$parseString);
00396       }
00397 
00398          // Return result:
00399       return $result;
00400    }
00401 
00409    function parseEXPLAIN($parseString) {
00410 
00411          // Removing EXPLAIN
00412       $parseString = $this->trimSQL($parseString);
00413       $parseString = eregi_replace('^EXPLAIN[[:space:]]+','',$parseString);
00414 
00415          // Init output variable:
00416       $result = $this->parseSELECT($parseString);
00417       if (is_array($result))  {
00418          $result['type'] = 'EXPLAIN';
00419       }
00420 
00421       return $result;
00422    }
00423 
00431    function parseCREATETABLE($parseString)   {
00432 
00433          // Removing CREATE TABLE
00434       $parseString = $this->trimSQL($parseString);
00435       $parseString = eregi_replace('^CREATE[[:space:]]+TABLE[[:space:]]+','',$parseString);
00436 
00437          // Init output variable:
00438       $result = array();
00439       $result['type'] = 'CREATETABLE';
00440 
00441          // Get table:
00442       $result['TABLE'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]*\(',TRUE);
00443 
00444       if ($result['TABLE'])   {
00445 
00446             // While the parseString is not yet empty:
00447          while(strlen($parseString)>0) {
00448             if ($key = $this->nextPart($parseString, '^(KEY|PRIMARY KEY)([[:space:]]+|\()')) {  // Getting key
00449                $key = strtoupper(ereg_replace('[[:space:]]','',$key));
00450 
00451                switch($key)   {
00452                   case 'PRIMARYKEY':
00453                      $result['KEYS'][$key] = $this->getValue($parseString,'_LIST');
00454                      if ($this->parse_error) { return $this->parse_error; }
00455                   break;
00456                   case 'KEY':
00457                      if ($keyName = $this->nextPart($parseString, '^([[:alnum:]_]+)([[:space:]]+|\()'))  {
00458                         $result['KEYS'][$keyName] = $this->getValue($parseString,'_LIST');
00459                         if ($this->parse_error) { return $this->parse_error; }
00460                      } else return $this->parseError('No keyname found',$parseString);
00461                   break;
00462                }
00463             } elseif ($fieldName = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+'))  {  // Getting field:
00464                $result['FIELDS'][$fieldName]['definition'] = $this->parseFieldDef($parseString);
00465                if ($this->parse_error) { return $this->parse_error; }
00466             }
00467 
00468                // Finding delimiter:
00469             $delim = $this->nextPart($parseString, '^(,|\))');
00470             if (!$delim)   {
00471                return $this->parseError('No delimiter found',$parseString);
00472             } elseif ($delim==')')  {
00473                break;
00474             }
00475          }
00476 
00477             // Finding what is after the table definition - table type in MySQL
00478          if ($delim==')')  {
00479             if ($this->nextPart($parseString, '^(TYPE[[:space:]]*=)'))  {
00480                $result['tableType'] = $parseString;
00481                $parseString = '';
00482             }
00483          } else return $this->parseError('No fieldname found!',$parseString);
00484 
00485             // Getting table type
00486       } else return $this->parseError('No table found!',$parseString);
00487 
00488          // Should be no more content now:
00489       if ($parseString) {
00490          return $this->parseError('Still content in clause after parsing!',$parseString);
00491       }
00492 
00493       return $result;
00494    }
00495 
00503    function parseALTERTABLE($parseString) {
00504 
00505          // Removing ALTER TABLE
00506       $parseString = $this->trimSQL($parseString);
00507       $parseString = eregi_replace('^ALTER[[:space:]]+TABLE[[:space:]]+','',$parseString);
00508 
00509          // Init output variable:
00510       $result = array();
00511       $result['type'] = 'ALTERTABLE';
00512 
00513          // Get table:
00514       $result['TABLE'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+');
00515 
00516       if ($result['TABLE'])   {
00517          if ($result['action'] = $this->nextPart($parseString, '^(CHANGE|DROP[[:space:]]+KEY|DROP[[:space:]]+PRIMARY[[:space:]]+KEY|ADD[[:space:]]+KEY|ADD[[:space:]]+PRIMARY[[:space:]]+KEY|DROP|ADD|RENAME)([[:space:]]+|\()'))   {
00518             $actionKey = strtoupper(ereg_replace('[[:space:]]','',$result['action']));
00519 
00520                // Getting field:
00521             if (t3lib_div::inList('ADDPRIMARYKEY,DROPPRIMARYKEY',$actionKey) || $fieldKey = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+'))  {
00522 
00523                switch($actionKey)   {
00524                   case 'ADD':
00525                      $result['FIELD'] = $fieldKey;
00526                      $result['definition'] = $this->parseFieldDef($parseString);
00527                      if ($this->parse_error) { return $this->parse_error; }
00528                   break;
00529                   case 'DROP':
00530                   case 'RENAME':
00531                      $result['FIELD'] = $fieldKey;
00532                   break;
00533                   case 'CHANGE':
00534                      $result['FIELD'] = $fieldKey;
00535                      if ($result['newField'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+'))  {
00536                         $result['definition'] = $this->parseFieldDef($parseString);
00537                         if ($this->parse_error) { return $this->parse_error; }
00538                      } else return $this->parseError('No NEW field name found',$parseString);
00539                   break;
00540 
00541                   case 'ADDKEY':
00542                   case 'ADDPRIMARYKEY':
00543                      $result['KEY'] = $fieldKey;
00544                      $result['fields'] = $this->getValue($parseString,'_LIST');
00545                      if ($this->parse_error) { return $this->parse_error; }
00546                   break;
00547                   case 'DROPKEY':
00548                      $result['KEY'] = $fieldKey;
00549                   break;
00550                   case 'DROPPRIMARYKEY':
00551                      // ??? todo!
00552                   break;
00553                }
00554             } else return $this->parseError('No field name found',$parseString);
00555          } else return $this->parseError('No action CHANGE, DROP or ADD found!',$parseString);
00556       } else return $this->parseError('No table found!',$parseString);
00557 
00558          // Should be no more content now:
00559       if ($parseString) {
00560          return $this->parseError('Still content in clause after parsing!',$parseString);
00561       }
00562 
00563       return $result;
00564    }
00565 
00572    function parseDROPTABLE($parseString)  {
00573 
00574          // Removing DROP TABLE
00575       $parseString = $this->trimSQL($parseString);
00576       $parseString = eregi_replace('^DROP[[:space:]]+TABLE[[:space:]]+','',$parseString);
00577 
00578          // Init output variable:
00579       $result = array();
00580       $result['type'] = 'DROPTABLE';
00581 
00582          // IF EXISTS
00583       $result['ifExists']  = $this->nextPart($parseString, '^(IF[[:space:]]+EXISTS[[:space:]]+)');
00584 
00585          // Get table:
00586       $result['TABLE'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+');
00587 
00588       if ($result['TABLE'])   {
00589 
00590             // Should be no more content now:
00591          if ($parseString) {
00592             return $this->parseError('Still content in clause after parsing!',$parseString);
00593          }
00594 
00595          return $result;
00596       } else return $this->parseError('No table found!',$parseString);
00597    }
00598 
00599 
00600 
00601 
00602 
00603 
00604 
00605 
00606 
00607 
00608 
00609 
00610 
00611 
00612 
00613 
00614 
00615    /**************************************
00616     *
00617     * SQL Parsing, helper functions for parts of queries
00618     *
00619     **************************************/
00620 
00631    function parseFieldList(&$parseString, $stopRegex='') {
00632 
00633          // Prepare variables:
00634       $parseString = $this->trimSQL($parseString);
00635       $this->lastStopKeyWord = '';
00636       $this->parse_error = '';
00637 
00638 
00639       $stack = array(); // Contains the parsed content
00640       $pnt = 0;         // Pointer to positions in $stack
00641       $level = 0;       // Indicates the parenthesis level we are at.
00642       $loopExit = 0;    // Recursivity brake.
00643 
00644          // $parseString is continously shortend by the process and we keep parsing it till it is zero:
00645       while (strlen($parseString)) {
00646 
00647             // Checking if we are inside / outside parenthesis (in case of a function like count(), max(), min() etc...):
00648          if ($level>0)  {  // Inside parenthesis here (does NOT detect if values in quotes are used, the only token is ")" or "("):
00649 
00650                // Accumulate function content until next () parenthesis:
00651             $funcContent = $this->nextPart($parseString,'^([^()]*.)');
00652             $stack[$pnt]['func_content.'][] = array(
00653                'level' => $level,
00654                'func_content' => substr($funcContent,0,-1)
00655             );
00656             $stack[$pnt]['func_content'].= $funcContent;
00657 
00658                // Detecting ( or )
00659             switch(substr($stack[$pnt]['func_content'],-1)) {
00660                case '(':
00661                   $level++;
00662                break;
00663                case ')':
00664                   $level--;
00665                   if (!$level)   {  // If this was the last parenthesis:
00666                      $stack[$pnt]['func_content'] = substr($stack[$pnt]['func_content'],0,-1);
00667                      $parseString = ltrim($parseString); // Remove any whitespace after the parenthesis.
00668                   }
00669                break;
00670             }
00671          } else { // Outside parenthesis, looking for next field:
00672 
00673                // Looking for a known function (only known functions supported)
00674             $func = $this->nextPart($parseString,'^(count|max|min|floor|sum|avg)[[:space:]]*\(');
00675             if ($func)  {
00676                $parseString = trim(substr($parseString,1)); // Strip of "("
00677                $stack[$pnt]['type'] = 'function';
00678                $stack[$pnt]['function'] = $func;
00679                $level++;   // increse parenthesis level counter.
00680             } else {
00681                   // Otherwise, look for regular fieldname:
00682                if ($fieldName = $this->nextPart($parseString,'^([[:alnum:]\*._]+)(,|[[:space:]]+)'))  {
00683                   $stack[$pnt]['type'] = 'field';
00684 
00685                      // Explode fieldname into field and table:
00686                   $tableField = explode('.',$fieldName,2);
00687                   if (count($tableField)==2) {
00688                      $stack[$pnt]['table'] = $tableField[0];
00689                      $stack[$pnt]['field'] = $tableField[1];
00690                   } else {
00691                      $stack[$pnt]['table'] = '';
00692                      $stack[$pnt]['field'] = $tableField[0];
00693                   }
00694                } else {
00695                   return $this->parseError('No field name found as expected',$parseString);
00696                }
00697             }
00698          }
00699 
00700             // After a function or field we look for "AS" alias and a comma to separate to the next field in the list:
00701          if (!$level)   {
00702 
00703                // Looking for "AS" alias:
00704             if ($as = $this->nextPart($parseString,'^(AS)[[:space:]]+'))   {
00705                $stack[$pnt]['as'] = $this->nextPart($parseString,'^([[:alnum:]_]+)(,|[[:space:]]+)');
00706                $stack[$pnt]['as_keyword'] = $as;
00707             }
00708 
00709                // Looking for "ASC" or "DESC" keywords (for ORDER BY)
00710             if ($sDir = $this->nextPart($parseString,'^(ASC|DESC)([[:space:]]+|,)'))   {
00711                $stack[$pnt]['sortDir'] = $sDir;
00712             }
00713 
00714                // Looking for stop-keywords:
00715             if ($stopRegex && $this->lastStopKeyWord = $this->nextPart($parseString, $stopRegex))  {
00716                $this->lastStopKeyWord = strtoupper(ereg_replace('[[:space:]]*','',$this->lastStopKeyWord));
00717                return $stack;
00718             }
00719 
00720                // Looking for comma (since the stop-keyword did not trigger a return...)
00721             if (strlen($parseString) && !$this->nextPart($parseString,'^(,)'))   {
00722                return $this->parseError('No comma found as expected',$parseString);
00723             }
00724 
00725                // Increasing pointer:
00726             $pnt++;
00727          }
00728 
00729             // Check recursivity brake:
00730          $loopExit++;
00731          if ($loopExit>500)   {
00732             return $this->parseError('More than 500 loops, exiting prematurely...',$parseString);
00733          }
00734       }
00735 
00736          // Return result array:
00737       return $stack;
00738    }
00739 
00749    function parseFromTables(&$parseString, $stopRegex='')   {
00750 
00751          // Prepare variables:
00752       $parseString = $this->trimSQL($parseString);
00753       $this->lastStopKeyWord = '';
00754       $this->parse_error = '';
00755 
00756       $stack = array(); // Contains the parsed content
00757       $pnt = 0;         // Pointer to positions in $stack
00758       $loopExit = 0;    // Recursivity brake.
00759 
00760          // $parseString is continously shortend by the process and we keep parsing it till it is zero:
00761       while (strlen($parseString)) {
00762 
00763             // Looking for the table:
00764          if ($stack[$pnt]['table'] = $this->nextPart($parseString,'^([[:alnum:]_]+)(,|[[:space:]]+)'))   {
00765             if ($as = $this->nextPart($parseString,'^(AS)[[:space:]]+'))   {
00766                $stack[$pnt]['as'] = $this->nextPart($parseString,'^([[:alnum:]_]+)(,|[[:space:]]+)');
00767                $stack[$pnt]['as_keyword'] = $as;
00768             }
00769          } else return $this->parseError('No table name found as expected!',$parseString);
00770 
00771             // Looking for JOIN
00772          if ($join = $this->nextPart($parseString,'^(JOIN|LEFT[[:space:]]+JOIN)[[:space:]]+'))  {
00773             $stack[$pnt]['JOIN']['type'] = $join;
00774             if ($stack[$pnt]['JOIN']['withTable'] = $this->nextPart($parseString,'^([[:alnum:]_]+)[[:space:]]+ON[[:space:]]+',1))   {
00775                $field1 = $this->nextPart($parseString,'^([[:alnum:]_.]+)[[:space:]]*=[[:space:]]*',1);
00776                $field2 = $this->nextPart($parseString,'^([[:alnum:]_.]+)[[:space:]]+');
00777                if ($field1 && $field2) {
00778                   $stack[$pnt]['JOIN']['ON'] = array($field1,$field2);
00779                } else return $this->parseError('No join fields found!',$parseString);
00780             } else  return $this->parseError('No join table found!',$parseString);
00781          }
00782 
00783             // Looking for stop-keywords:
00784          if ($stopRegex && $this->lastStopKeyWord = $this->nextPart($parseString, $stopRegex))  {
00785             $this->lastStopKeyWord = strtoupper(ereg_replace('[[:space:]]*','',$this->lastStopKeyWord));
00786             return $stack;
00787          }
00788 
00789             // Looking for comma:
00790          if (strlen($parseString) && !$this->nextPart($parseString,'^(,)'))   {
00791             return $this->parseError('No comma found as expected',$parseString);
00792          }
00793 
00794             // Increasing pointer:
00795          $pnt++;
00796 
00797             // Check recursivity brake:
00798          $loopExit++;
00799          if ($loopExit>500)   {
00800             return $this->parseError('More than 500 loops, exiting prematurely...',$parseString);
00801          }
00802       }
00803 
00804          // Return result array:
00805       return $stack;
00806    }
00807 
00816    function parseWhereClause(&$parseString, $stopRegex='')  {
00817 
00818          // Prepare variables:
00819       $parseString = $this->trimSQL($parseString);
00820       $this->lastStopKeyWord = '';
00821       $this->parse_error = '';
00822 
00823       $stack = array(0 => array()); // Contains the parsed content
00824       $pnt = array(0 => 0);         // Pointer to positions in $stack
00825       $level = 0;                // Determines parenthesis level
00826       $loopExit = 0;             // Recursivity brake.
00827 
00828          // $parseString is continously shortend by the process and we keep parsing it till it is zero:
00829       while (strlen($parseString)) {
00830 
00831             // Look for next parenthesis level:
00832          $newLevel = $this->nextPart($parseString,'^([(])');
00833          if ($newLevel=='(')  {        // If new level is started, manage stack/pointers:
00834             $level++;               // Increase level
00835             $pnt[$level] = 0;       // Reset pointer for this level
00836             $stack[$level] = array();  // Reset stack for this level
00837          } else { // If no new level is started, just parse the current level:
00838 
00839                // Find "modifyer", eg. "NOT or !"
00840             $stack[$level][$pnt[$level]]['modifier'] = trim($this->nextPart($parseString,'^(!|NOT[[:space:]]+)'));
00841 
00842                // Fieldname:
00843             if ($fieldName = $this->nextPart($parseString,'^([[:alnum:]._]+)([[:space:]]+|&|<=|>=|<|>|=|!=|IS)')) {
00844 
00845                   // Parse field name into field and table:
00846                $tableField = explode('.',$fieldName,2);
00847                if (count($tableField)==2) {
00848                   $stack[$level][$pnt[$level]]['table'] = $tableField[0];
00849                   $stack[$level][$pnt[$level]]['field'] = $tableField[1];
00850                } else {
00851                   $stack[$level][$pnt[$level]]['table'] = '';
00852                   $stack[$level][$pnt[$level]]['field'] = $tableField[0];
00853                }
00854             } else {
00855                return $this->parseError('No field name found as expected',$parseString);
00856             }
00857 
00858                // See if the value is calculated. Support only for "&" (boolean AND) at the moment:
00859             $stack[$level][$pnt[$level]]['calc'] = $this->nextPart($parseString,'^(&)');
00860             if (strlen($stack[$level][$pnt[$level]]['calc']))  {
00861                   // Finding value for calculation:
00862                $stack[$level][$pnt[$level]]['calc_value'] = $this->getValue($parseString);
00863             }
00864 
00865                // Find "comparator":
00866             $stack[$level][$pnt[$level]]['comparator'] = $this->nextPart($parseString,'^(<=|>=|<|>|=|!=|NOT[[:space:]]+IN|IN|NOT[[:space:]]+LIKE|LIKE|IS)');
00867             if (strlen($stack[$level][$pnt[$level]]['comparator']))  {
00868                   // Finding value for comparator:
00869                $stack[$level][$pnt[$level]]['value'] = $this->getValue($parseString,$stack[$level][$pnt[$level]]['comparator']);
00870                if ($this->parse_error) { return $this->parse_error; }
00871             }
00872 
00873                // Finished, increase pointer:
00874             $pnt[$level]++;
00875 
00876                // Checking if the current level is ended, in that case do stack management:
00877             while ($this->nextPart($parseString,'^([)])'))  {
00878                $level--;      // Decrease level:
00879                $stack[$level][$pnt[$level]]['sub'] = $stack[$level+1];     // Copy stack
00880                $pnt[$level]++;   // Increase pointer of the new level
00881 
00882                   // Make recursivity check:
00883                $loopExit++;
00884                if ($loopExit>500)   {
00885                   return $this->parseError('More than 500 loops (in search for exit parenthesis), exiting prematurely...',$parseString);
00886                }
00887             }
00888 
00889                // Detecting the operator for the next level; support for AND, OR and &&):
00890             $op = $this->nextPart($parseString,'^(AND|OR|AND[[:space:]]+NOT)(\(|[[:space:]]+)');
00891             if ($op) {
00892                $stack[$level][$pnt[$level]]['operator'] = $op;
00893             } elseif (strlen($parseString))  {
00894 
00895                   // Looking for stop-keywords:
00896                if ($stopRegex && $this->lastStopKeyWord = $this->nextPart($parseString, $stopRegex))  {
00897                   $this->lastStopKeyWord = strtoupper(ereg_replace('[[:space:]]*','',$this->lastStopKeyWord));
00898                   return $stack[0];
00899                } else {
00900                   return $this->parseError('No operator, but parsing not finished.',$parseString);
00901                }
00902             }
00903          }
00904 
00905             // Make recursivity check:
00906          $loopExit++;
00907          if ($loopExit>500)   {
00908             return $this->parseError('More than 500 loops, exiting prematurely...',$parseString);
00909          }
00910       }
00911 
00912          // Return the stacks lowest level:
00913       return $stack[0];
00914    }
00915 
00924    function parseFieldDef(&$parseString, $stopRegex='')  {
00925          // Prepare variables:
00926       $parseString = $this->trimSQL($parseString);
00927       $this->lastStopKeyWord = '';
00928       $this->parse_error = '';
00929 
00930       $result = array();
00931 
00932          // Field type:
00933       if ($result['fieldType'] =  $this->nextPart($parseString,'^(int|smallint|tinyint|mediumint|double|varchar|char|text|tinytext|mediumtext|blob|tinyblob|mediumblob|longblob)([[:space:]]+|\()'))  {
00934 
00935             // Looking for value:
00936          if (substr($parseString,0,1)=='(')  {
00937             $parseString = substr($parseString,1);
00938             if ($result['value'] =  $this->nextPart($parseString,'^([^)]*)')) {
00939                $parseString = ltrim(substr($parseString,1));
00940             } else return $this->parseError('No end-parenthesis for value found!',$parseString);
00941          }
00942 
00943             // Looking for keywords
00944          while($keyword = $this->nextPart($parseString,'^(DEFAULT|NOT[[:space:]]+NULL|AUTO_INCREMENT|UNSIGNED)([[:space:]]+|,|\))'))   {
00945             $keywordCmp = strtoupper(ereg_replace('[[:space:]]*','',$keyword));
00946 
00947             $result['featureIndex'][$keywordCmp]['keyword'] = $keyword;
00948 
00949             switch($keywordCmp)  {
00950                case 'DEFAULT':
00951                   $result['featureIndex'][$keywordCmp]['value'] = $this->getValue($parseString);
00952                break;
00953             }
00954          }
00955       } else return $this->parseError('Field type unknown!',$parseString);
00956 
00957       return $result;
00958    }
00959 
00960 
00961 
00962 
00963 
00964 
00965 
00966 
00967 
00968 
00969 
00970    /************************************
00971     *
00972     * Parsing: Helper functions
00973     *
00974     ************************************/
00975 
00985    function nextPart(&$parseString,$regex,$trimAll=FALSE)   {
00986       if (eregi($regex,$parseString.' ', $reg)) {  // Adding space char because [[:space:]]+ is often a requirement in regex's
00987          $parseString = ltrim(substr($parseString,strlen($reg[$trimAll?0:1])));
00988          return $reg[1];
00989       }
00990    }
00991 
00999    function getValue(&$parseString,$comparator='') {
01000       if (t3lib_div::inList('NOTIN,IN,_LIST',strtoupper(ereg_replace('[[:space:]]','',$comparator)))) {  // List of values:
01001          if ($this->nextPart($parseString,'^([(])'))  {
01002             $listValues = array();
01003             $comma=',';
01004 
01005             while($comma==',')   {
01006                $listValues[] = $this->getValue($parseString);
01007                $comma = $this->nextPart($parseString,'^([,])');
01008             }
01009 
01010             $out = $this->nextPart($parseString,'^([)])');
01011             if ($out)   {
01012                if ($comparator=='_LIST')  {
01013                   $kVals = array();
01014                   foreach ($listValues as $vArr)   {
01015                      $kVals[] = $vArr[0];
01016                   }
01017                   return $kVals;
01018                } else {
01019                   return $listValues;
01020                }
01021             } else return array($this->parseError('No ) parenthesis in list',$parseString));
01022          } else return array($this->parseError('No ( parenthesis starting the list',$parseString));
01023 
01024       } else { // Just plain string value, in quotes or not:
01025 
01026             // Quote?
01027          $firstChar = substr($parseString,0,1);
01028 
01029          switch($firstChar)   {
01030             case '"':
01031                return array($this->getValueInQuotes($parseString,'"'),'"');
01032             break;
01033             case "'":
01034                return array($this->getValueInQuotes($parseString,"'"),"'");
01035             break;
01036             default:
01037                if (eregi('^([[:alnum:]._-]+)',$parseString, $reg))   {
01038                   $parseString = ltrim(substr($parseString,strlen($reg[0])));
01039                   return array($reg[1]);
01040                }
01041             break;
01042          }
01043       }
01044    }
01045 
01054    function getValueInQuotes(&$parseString,$quote) {
01055 
01056       $parts = explode($quote,substr($parseString,1));
01057       $buffer = '';
01058       foreach($parts as $k => $v)   {
01059          $buffer.=$v;
01060 
01061          unset($reg);
01062          ereg('[\]*$',$v,$reg);
01063          if (strlen($reg[0])%2)  {
01064             $buffer.=$quote;
01065          } else {
01066             $parseString = ltrim(substr($parseString,strlen($buffer)+2));
01067             return $this->parseStripslashes($buffer);
01068          }
01069       }
01070    }
01071 
01079    function parseStripslashes($str) {
01080       $search = array('\\\\', '\\\'', '\\"', '\0', '\n', '\r', '\Z');
01081       $replace = array('\\', '\'', '"', "\x00", "\x0a", "\x0d", "\x1a");
01082 
01083       return str_replace($search, $replace, $str);
01084    }
01085 
01093    function compileAddslashes($str) {
01094       $search = array('\\', '\'', '"', "\x00", "\x0a", "\x0d", "\x1a");
01095       $replace = array('\\\\', '\\\'', '\\"', '\0', '\n', '\r', '\Z');
01096 
01097       return str_replace($search, $replace, $str);
01098    }
01099 
01107    function parseError($msg,$restQuery)   {
01108       $this->parse_error = 'SQL engine parse ERROR: '.$msg.': near "'.substr($restQuery,0,50).'"';
01109       return $this->parse_error;
01110    }
01111 
01121    function trimSQL($str)  {
01122       return trim(ereg_replace('[[:space:];]*$','',$str)).' ';
01123    }
01124 
01125 
01126 
01127 
01128 
01129 
01130 
01131 
01132 
01133 
01134 
01135 
01136    /*************************
01137     *
01138     * Compiling queries
01139     *
01140     *************************/
01141 
01149    function compileSQL($components) {
01150       switch($components['type'])   {
01151          case 'SELECT':
01152             $query = $this->compileSELECT($components);
01153          break;
01154          case 'UPDATE':
01155             $query = $this->compileUPDATE($components);
01156          break;
01157          case 'INSERT':
01158             $query = $this->compileINSERT($components);
01159          break;
01160          case 'DELETE':
01161             $query = $this->compileDELETE($components);
01162          break;
01163          case 'EXPLAIN':
01164             $query = 'EXPLAIN '.$this->compileSELECT($components);
01165          break;
01166          case 'DROPTABLE':
01167             $query = 'DROP TABLE'.($components['ifExists']?' IF EXISTS':'').' '.$components['TABLE'];
01168          break;
01169          case 'CREATETABLE':
01170             $query = $this->compileCREATETABLE($components);
01171          break;
01172          case 'ALTERTABLE':
01173             $query = $this->compileALTERTABLE($components);
01174          break;
01175       }
01176 
01177       return $query;
01178    }
01179 
01187    function compileSELECT($components) {
01188 
01189          // Initialize:
01190       $where = $this->compileWhereClause($components['WHERE']);
01191       $groupBy = $this->compileFieldList($components['GROUPBY']);
01192       $orderBy = $this->compileFieldList($components['ORDERBY']);
01193       $limit = $components['LIMIT'];
01194 
01195          // Make query:
01196       $query = 'SELECT '.($components['STRAIGHT_JOIN'] ? $components['STRAIGHT_JOIN'].'' : '').'
01197             '.$this->compileFieldList($components['SELECT']).'
01198             FROM '.$this->compileFromTables($components['FROM']).
01199                (strlen($where)?'
01200             WHERE '.$where : '').
01201                (strlen($groupBy)?'
01202             GROUP BY '.$groupBy : '').
01203                (strlen($orderBy)?'
01204             ORDER BY '.$orderBy : '').
01205                (strlen($limit)?'
01206             LIMIT '.$limit : '');
01207 
01208       return $query;
01209    }
01210 
01218    function compileUPDATE($components) {
01219 
01220          // Where clause:
01221       $where = $this->compileWhereClause($components['WHERE']);
01222 
01223          // Fields
01224       $fields = array();
01225       foreach($components['FIELDS'] as $fN => $fV) {
01226          $fields[]=$fN.'='.$fV[1].$this->compileAddslashes($fV[0]).$fV[1];
01227       }
01228 
01229          // Make query:
01230       $query = 'UPDATE '.$components['TABLE'].' SET
01231             '.implode(',
01232             ',$fields).'
01233             '.(strlen($where)?'
01234             WHERE '.$where : '');
01235 
01236       return $query;
01237    }
01238 
01246    function compileINSERT($components) {
01247 
01248       if ($components['VALUES_ONLY'])  {
01249             // Initialize:
01250          $fields = array();
01251          foreach($components['VALUES_ONLY'] as $fV)   {
01252             $fields[]=$fV[1].$this->compileAddslashes($fV[0]).$fV[1];
01253          }
01254 
01255             // Make query:
01256          $query = 'INSERT INTO '.$components['TABLE'].'
01257                VALUES
01258                ('.implode(',
01259                ',$fields).')';
01260       } else {
01261             // Initialize:
01262          $fields = array();
01263          foreach($components['FIELDS'] as $fN => $fV) {
01264             $fields[$fN]=$fV[1].$this->compileAddslashes($fV[0]).$fV[1];
01265          }
01266 
01267             // Make query:
01268          $query = 'INSERT INTO '.$components['TABLE'].'
01269                ('.implode(',
01270                ',array_keys($fields)).')
01271                VALUES
01272                ('.implode(',
01273                ',$fields).')';
01274       }
01275 
01276       return $query;
01277    }
01278 
01286    function compileDELETE($components) {
01287 
01288          // Where clause:
01289       $where = $this->compileWhereClause($components['WHERE']);
01290 
01291          // Make query:
01292       $query = 'DELETE FROM '.$components['TABLE'].
01293             (strlen($where)?'
01294             WHERE '.$where : '');
01295 
01296       return $query;
01297    }
01298 
01306    function compileCREATETABLE($components)  {
01307 
01308          // Create fields and keys:
01309       $fieldsKeys = array();
01310       foreach($components['FIELDS'] as $fN => $fCfg)  {
01311          $fieldsKeys[]=$fN.' '.$this->compileFieldCfg($fCfg['definition']);
01312       }
01313       foreach($components['KEYS'] as $kN => $kCfg) {
01314          if ($kN == 'PRIMARYKEY')   {
01315             $fieldsKeys[]='PRIMARY KEY ('.implode(',', $kCfg).')';
01316          } else {
01317             $fieldsKeys[]='KEY '.$kN.' ('.implode(',', $kCfg).')';
01318          }
01319       }
01320 
01321          // Make query:
01322       $query = 'CREATE TABLE '.$components['TABLE'].' (
01323          '.implode(',
01324          ', $fieldsKeys).'
01325          )'.($components['tableType'] ? ' TYPE='.$components['tableType'] : '');
01326 
01327       return $query;
01328    }
01329 
01337    function compileALTERTABLE($components)   {
01338 
01339          // Make query:
01340       $query = 'ALTER TABLE '.$components['TABLE'].' '.$components['action'].' '.($components['FIELD']?$components['FIELD']:$components['KEY']);
01341 
01342          // Based on action, add the final part:
01343       switch(strtoupper(ereg_replace('[[:space:]]','',$components['action'])))   {
01344          case 'ADD':
01345             $query.=' '.$this->compileFieldCfg($components['definition']);
01346          break;
01347          case 'CHANGE':
01348             $query.=' '.$components['newField'].' '.$this->compileFieldCfg($components['definition']);
01349          break;
01350          case 'DROP':
01351          case 'DROPKEY':
01352          break;
01353          case 'ADDKEY':
01354          case 'ADDPRIMARYKEY':
01355             $query.=' ('.implode(',',$components['fields']).')';
01356          break;
01357       }
01358 
01359          // Return query
01360       return $query;
01361    }
01362 
01363 
01364 
01365 
01366 
01367 
01368 
01369 
01370 
01371 
01372 
01373 
01374 
01375 
01376    /**************************************
01377     *
01378     * Compiling queries, helper functions for parts of queries
01379     *
01380     **************************************/
01381 
01390    function compileFieldList($selectFields)  {
01391 
01392          // Prepare buffer variable:
01393       $outputParts = array();
01394 
01395          // Traverse the selectFields if any:
01396       if (is_array($selectFields))  {
01397          foreach($selectFields as $k => $v)  {
01398 
01399                // Detecting type:
01400             switch($v['type'])   {
01401                case 'function':
01402                   $outputParts[$k] = $v['function'].'('.$v['func_content'].')';
01403                break;
01404                case 'field':
01405                   $outputParts[$k] = ($v['table']?$v['table'].'.':'').$v['field'];
01406                break;
01407             }
01408 
01409                // Alias:
01410             if ($v['as'])  {
01411                $outputParts[$k].= ' '.$v['as_keyword'].' '.$v['as'];
01412             }
01413 
01414                // Specifically for ORDER BY and GROUP BY field lists:
01415             if ($v['sortDir'])   {
01416                $outputParts[$k].= ' '.$v['sortDir'];
01417             }
01418          }
01419       }
01420 
01421          // Return imploded buffer:
01422       return implode(', ',$outputParts);
01423    }
01424 
01432    function compileFromTables($tablesArray)  {
01433 
01434          // Prepare buffer variable:
01435       $outputParts = array();
01436 
01437          // Traverse the table names:
01438       if (is_array($tablesArray))   {
01439          foreach($tablesArray as $k => $v)   {
01440 
01441                // Set table name:
01442             $outputParts[$k] = $v['table'];
01443 
01444                // Add alias AS if there:
01445             if ($v['as'])  {
01446                $outputParts[$k].= ' '.$v['as_keyword'].' '.$v['as'];
01447             }
01448 
01449             if (is_array($v['JOIN']))  {
01450                $outputParts[$k].= ' '.$v['JOIN']['type'].' '.$v['JOIN']['withTable'].' ON '.implode('=',$v['JOIN']['ON']);
01451             }
01452 
01453          }
01454       }
01455 
01456          // Return imploded buffer:
01457       return implode(', ',$outputParts);
01458    }
01459 
01468    function compileWhereClause($clauseArray) {
01469 
01470          // Prepare buffer variable:
01471       $output='';
01472 
01473          // Traverse clause array:
01474       if (is_array($clauseArray))   {
01475          foreach($clauseArray as $k => $v)   {
01476 
01477                // Set operator:
01478             $output.=$v['operator'] ? ' '.$v['operator'] : '';
01479 
01480                // Look for sublevel:
01481             if (is_array($v['sub']))   {
01482                $output.=' ('.trim($this->compileWhereClause($v['sub'])).')';
01483             } else {
01484 
01485                   // Set field/table with modifying prefix if any:
01486                $output.=' '.trim($v['modifier'].' '.($v['table']?$v['table'].'.':'').$v['field']);
01487 
01488                   // Set calculation, if any:
01489                if ($v['calc'])   {
01490                   $output.=$v['calc'].$v['calc_value'][1].$this->compileAddslashes($v['calc_value'][0]).$v['calc_value'][1];
01491                }
01492 
01493                   // Set comparator:
01494                if ($v['comparator'])   {
01495                   $output.=' '.$v['comparator'];
01496 
01497                      // Detecting value type; list or plain:
01498                   if (t3lib_div::inList('NOTIN,IN',strtoupper(ereg_replace('[[:space:]]','',$v['comparator']))))  {
01499                      $valueBuffer = array();
01500                      foreach($v['value'] as $realValue)  {
01501                         $valueBuffer[]=$realValue[1].$this->compileAddslashes($realValue[0]).$realValue[1];
01502                      }
01503                      $output.=' ('.trim(implode(',',$valueBuffer)).')';
01504                   } else {
01505                      $output.=' '.$v['value'][1].$this->compileAddslashes($v['value'][0]).$v['value'][1];
01506                   }
01507                }
01508             }
01509          }
01510       }
01511 
01512          // Return output buffer:
01513       return $output;
01514    }
01515 
01522    function compileFieldCfg($fieldCfg) {
01523 
01524          // Set type:
01525       $cfg = $fieldCfg['fieldType'];
01526 
01527          // Add value, if any:
01528       if (strlen($fieldCfg['value']))  {
01529          $cfg.='('.$fieldCfg['value'].')';
01530       }
01531 
01532          // Add additional features:
01533       if (is_array($fieldCfg['featureIndex']))  {
01534          foreach($fieldCfg['featureIndex'] as $featureDef)  {
01535             $cfg.=' '.$featureDef['keyword'];
01536 
01537                // Add value if found:
01538             if (is_array($featureDef['value'])) {
01539                $cfg.=' '.$featureDef['value'][1].$this->compileAddslashes($featureDef['value'][0]).$featureDef['value'][1];
01540             }
01541          }
01542       }
01543 
01544          // Return field definition string:
01545       return $cfg;
01546    }
01547 
01548 
01549 
01550 
01551 
01552 
01553 
01554 
01555 
01556 
01557 
01558    /*************************
01559     *
01560     * Debugging
01561     *
01562     *************************/
01563 
01571    function debug_parseSQLpart($part,$str)   {
01572       switch($part)  {
01573          case 'SELECT':
01574             return $this->debug_parseSQLpartCompare($str,$this->compileFieldList($this->parseFieldList($str)));
01575          break;
01576          case 'FROM':
01577             return $this->debug_parseSQLpartCompare($str,$this->compileFromTables($this->parseFromTables($str)));
01578          break;
01579          case 'WHERE':
01580             return $this->debug_parseSQLpartCompare($str,$this->compileWhereClause($this->parseWhereClause($str)));
01581          break;
01582       }
01583    }
01584 
01593    function debug_parseSQLpartCompare($str,$newStr,$caseInsensitive=FALSE) {
01594       if ($caseInsensitive)   {
01595          $str1 = strtoupper($str);
01596          $str2 = strtoupper($newStr);
01597       } else {
01598          $str1 = $str;
01599          $str2 = $newStr;
01600       }
01601 
01602          // Fixing escaped chars:
01603       $search = array('\0', '\n', '\r', '\Z');
01604       $replace = array("\x00", "\x0a", "\x0d", "\x1a");
01605       $str1 = str_replace($search, $replace, $str1);
01606       $str2 = str_replace($search, $replace, $str2);
01607 
01608          # Normally, commented out since they are needed only in tricky cases...
01609 #     $str1 = stripslashes($str1);
01610 #     $str2 = stripslashes($str2);
01611 
01612       if (strcmp(ereg_replace('[[:space:]]','',$this->trimSQL($str1)),ereg_replace('[[:space:]]','',$this->trimSQL($str2))))  {
01613          return array(
01614                ereg_replace('[[:space:]]+',' ',$str),
01615                ereg_replace('[[:space:]]+',' ',$newStr),
01616             );
01617       }
01618    }
01619 
01626    function debug_testSQL($SQLquery)   {
01627 #     return $SQLquery;
01628 #debug(array($SQLquery));
01629 
01630          // Getting result array:
01631       $parseResult = $this->parseSQL($SQLquery);
01632 
01633          // If result array was returned, proceed. Otherwise show error and exit.
01634       if (is_array($parseResult))   {
01635 
01636             // Re-compile query:
01637          $newQuery = $this->compileSQL($parseResult);
01638 
01639             // TEST the new query:
01640          $testResult = $this->debug_parseSQLpartCompare($SQLquery, $newQuery);
01641 
01642             // Return new query if OK, otherwise show error and exit:
01643          if (!is_array($testResult))   {
01644             return $newQuery;
01645          } else {
01646             debug(array('ERROR MESSAGE'=>'Input query did not match the parsed and recompiled query exactly (not observing whitespace)', 'TEST result' => $testResult),'SQL parsing failed:');
01647             exit;
01648          }
01649       } else {
01650          debug(array('query' => $SQLquery, 'ERROR MESSAGE'=>$parseResult),'SQL parsing failed:');
01651          exit;
01652       }
01653    }
01654 }
01655 
01656 
01657 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_sqlparser.php'])  {
01658    include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_sqlparser.php']);
01659 }
01660 ?>

Generated on Sun Oct 3 01:05:49 2004 for TYPO3core 3.7.0 dev by  doxygen 1.3.8-20040913