Fixed bug #10735: Wrong returnUrl with clipboard actions
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_sqlparser.php
old mode 100755 (executable)
new mode 100644 (file)
index 9035cb0..2a6425f
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2004 Kasper Skaarhoj (kasper@typo3.com)
+*  (c) 2004-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
  *
  * $Id$
  *
- * @author     Kasper Skaarhoj <kasper@typo3.com>
+ * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
  */
 /**
  * [CLASS/FUNCTION INDEX of SCRIPT]
  *
  *
  *
- *  106: class t3lib_sqlparser
+ *  107: class t3lib_sqlparser
  *
  *              SECTION: SQL Parsing, full queries
- *  128:     function parseSQL($parseString)
- *  188:     function parseSELECT($parseString)
- *  257:     function parseUPDATE($parseString)
- *  311:     function parseINSERT($parseString)
- *  371:     function parseDELETE($parseString)
- *  409:     function parseEXPLAIN($parseString)
- *  431:     function parseCREATETABLE($parseString)
- *  503:     function parseALTERTABLE($parseString)
- *  572:     function parseDROPTABLE($parseString)
+ *  129:     function parseSQL($parseString)
+ *  192:     function parseSELECT($parseString)
+ *  261:     function parseUPDATE($parseString)
+ *  315:     function parseINSERT($parseString)
+ *  375:     function parseDELETE($parseString)
+ *  413:     function parseEXPLAIN($parseString)
+ *  435:     function parseCREATETABLE($parseString)
+ *  514:     function parseALTERTABLE($parseString)
+ *  583:     function parseDROPTABLE($parseString)
+ *  616:     function parseCREATEDATABASE($parseString)
  *
  *              SECTION: SQL Parsing, helper functions for parts of queries
- *  631:     function parseFieldList(&$parseString, $stopRegex='')
- *  749:     function parseFromTables(&$parseString, $stopRegex='')
- *  816:     function parseWhereClause(&$parseString, $stopRegex='')
- *  924:     function parseFieldDef(&$parseString, $stopRegex='')
+ *  670:     function parseFieldList(&$parseString, $stopRegex='')
+ *  791:     function parseFromTables(&$parseString, $stopRegex='')
+ *  882:     function parseWhereClause(&$parseString, $stopRegex='')
+ *  990:     function parseFieldDef(&$parseString, $stopRegex='')
  *
  *              SECTION: Parsing: Helper functions
- *  985:     function nextPart(&$parseString,$regex,$trimAll=FALSE)
- *  999:     function getValue(&$parseString,$comparator='')
- * 1054:     function getValueInQuotes(&$parseString,$quote)
- * 1079:     function parseStripslashes($str)
- * 1093:     function compileAddslashes($str)
- * 1107:     function parseError($msg,$restQuery)
- * 1121:     function trimSQL($str)
+ * 1053:     function nextPart(&$parseString,$regex,$trimAll=FALSE)
+ * 1068:     function getValue(&$parseString,$comparator='')
+ * 1127:     function getValueInQuotes(&$parseString,$quote)
+ * 1153:     function parseStripslashes($str)
+ * 1167:     function compileAddslashes($str)
+ * 1182:     function parseError($msg,$restQuery)
+ * 1196:     function trimSQL($str)
  *
  *              SECTION: Compiling queries
- * 1149:     function compileSQL($components)
- * 1187:     function compileSELECT($components)
- * 1218:     function compileUPDATE($components)
- * 1246:     function compileINSERT($components)
- * 1286:     function compileDELETE($components)
- * 1306:     function compileCREATETABLE($components)
- * 1337:     function compileALTERTABLE($components)
+ * 1225:     function compileSQL($components)
+ * 1263:     function compileSELECT($components)
+ * 1294:     function compileUPDATE($components)
+ * 1322:     function compileINSERT($components)
+ * 1362:     function compileDELETE($components)
+ * 1382:     function compileCREATETABLE($components)
+ * 1415:     function compileALTERTABLE($components)
  *
  *              SECTION: Compiling queries, helper functions for parts of queries
- * 1390:     function compileFieldList($selectFields)
- * 1432:     function compileFromTables($tablesArray)
- * 1468:     function compileWhereClause($clauseArray)
- * 1522:     function compileFieldCfg($fieldCfg)
+ * 1468:     function compileFieldList($selectFields)
+ * 1510:     function compileFromTables($tablesArray)
+ * 1551:     function compileWhereClause($clauseArray)
+ * 1605:     function compileFieldCfg($fieldCfg)
  *
  *              SECTION: Debugging
- * 1571:     function debug_parseSQLpart($part,$str)
- * 1593:     function debug_parseSQLpartCompare($str,$newStr,$caseInsensitive=FALSE)
- * 1626:     function debug_testSQL($SQLquery)
+ * 1654:     function debug_parseSQLpart($part,$str)
+ * 1679:     function debug_parseSQLpartCompare($str,$newStr,$caseInsensitive=FALSE)
+ * 1712:     function debug_testSQL($SQLquery)
  *
- * TOTAL FUNCTIONS: 34
+ * TOTAL FUNCTIONS: 35
  * (This index is automatically created/updated by the extension "extdeveval")
  *
  */
@@ -97,9 +98,9 @@
 
 
 /**
- * TYPO3 SQL parser
+ * TYPO3 SQL parser class.
  *
- * @author     Kasper Skaarhoj <kasper@typo3.com>
+ * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
  * @package TYPO3
  * @subpackage t3lib
  */
@@ -126,7 +127,6 @@ class t3lib_sqlparser {
         * @see compileSQL(), debug_testSQL()
         */
        function parseSQL($parseString) {
-
                        // Prepare variables:
                $parseString = $this->trimSQL($parseString);
                $this->parse_error = '';
@@ -134,8 +134,8 @@ class t3lib_sqlparser {
 
                        // Finding starting keyword of 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|ALTER[[:space:]]+TABLE)[[:space:]]+');
-               $keyword = strtoupper(ereg_replace('[[:space:]]*','',$keyword));
+               $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)[[:space:]]+');
+               $keyword = strtoupper(str_replace(array(' ',"\t","\r","\n"),'',$keyword));
 
                switch($keyword)        {
                        case 'SELECT':
@@ -170,8 +170,12 @@ class t3lib_sqlparser {
                                        // Parsing CREATE TABLE query:
                                $result = $this->parseCREATETABLE($parseString);
                        break;
+                       case 'CREATEDATABASE':
+                                       // Parsing CREATE DATABASE query:
+                               $result = $this->parseCREATEDATABASE($parseString);
+                       break;
                        default:
-                               return $this->parseError('"'.$keyword.'" is not a keyword',$parseString);
+                               $result = $this->parseError('"'.$keyword.'" is not a keyword',$parseString);
                        break;
                }
 
@@ -189,7 +193,7 @@ class t3lib_sqlparser {
 
                        // Removing SELECT:
                $parseString = $this->trimSQL($parseString);
-               $parseString = eregi_replace('^SELECT[[:space:]]+','',$parseString);
+               $parseString = ltrim(substr($parseString,6)); // REMOVE eregi_replace('^SELECT[[:space:]]+','',$parseString);
 
                        // Init output variable:
                $result = array();
@@ -233,7 +237,7 @@ class t3lib_sqlparser {
 
                                                // LIMIT parsing:
                                        if ($this->lastStopKeyWord == 'LIMIT')  {
-                                               if (ereg('^([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);
@@ -258,7 +262,7 @@ class t3lib_sqlparser {
 
                        // Removing UPDATE
                $parseString = $this->trimSQL($parseString);
-               $parseString = eregi_replace('^UPDATE[[:space:]]+','',$parseString);
+               $parseString = ltrim(substr($parseString,6)); // REMOVE eregi_replace('^UPDATE[[:space:]]+','',$parseString);
 
                        // Init output variable:
                $result = array();
@@ -312,7 +316,7 @@ class t3lib_sqlparser {
 
                        // Removing INSERT
                $parseString = $this->trimSQL($parseString);
-               $parseString = eregi_replace('^INSERT[[:space:]]+INTO[[:space:]]+','',$parseString);
+               $parseString = ltrim(substr(ltrim(substr($parseString,6)),4)); // REMOVE eregi_replace('^INSERT[[:space:]]+INTO[[:space:]]+','',$parseString);
 
                        // Init output variable:
                $result = array();
@@ -337,7 +341,7 @@ class t3lib_sqlparser {
                                        if ($this->parse_error) { return $this->parse_error; }
 
                                        foreach($fieldNames as $k => $fN)       {
-                                               if (ereg('^[[:alnum:]_]+$',$fN))        {
+                                               if (preg_match('/^[[:alnum:]_]+$/',$fN))        {
                                                        if (isset($values[$k])) {
                                                                if (!isset($result['FIELDS'][$fN]))     {
                                                                        $result['FIELDS'][$fN] = $values[$k];
@@ -372,7 +376,7 @@ class t3lib_sqlparser {
 
                        // Removing DELETE
                $parseString = $this->trimSQL($parseString);
-               $parseString = eregi_replace('^DELETE[[:space:]]+FROM[[:space:]]+','',$parseString);
+               $parseString = ltrim(substr(ltrim(substr($parseString,6)),4)); // REMOVE eregi_replace('^DELETE[[:space:]]+FROM[[:space:]]+','',$parseString);
 
                        // Init output variable:
                $result = array();
@@ -410,7 +414,7 @@ class t3lib_sqlparser {
 
                        // Removing EXPLAIN
                $parseString = $this->trimSQL($parseString);
-               $parseString = eregi_replace('^EXPLAIN[[:space:]]+','',$parseString);
+               $parseString = ltrim(substr($parseString,6)); // REMOVE eregi_replace('^EXPLAIN[[:space:]]+','',$parseString);
 
                        // Init output variable:
                $result = $this->parseSELECT($parseString);
@@ -432,7 +436,7 @@ class t3lib_sqlparser {
 
                        // Removing CREATE TABLE
                $parseString = $this->trimSQL($parseString);
-               $parseString = eregi_replace('^CREATE[[:space:]]+TABLE[[:space:]]+','',$parseString);
+               $parseString = ltrim(substr(ltrim(substr($parseString,6)),5)); // REMOVE eregi_replace('^CREATE[[:space:]]+TABLE[[:space:]]+','',$parseString);
 
                        // Init output variable:
                $result = array();
@@ -445,14 +449,21 @@ class t3lib_sqlparser {
 
                                // While the parseString is not yet empty:
                        while(strlen($parseString)>0)   {
-                               if ($key = $this->nextPart($parseString, '^(KEY|PRIMARY KEY)([[:space:]]+|\()'))        {       // Getting key
-                                       $key = strtoupper(ereg_replace('[[:space:]]','',$key));
+                               if ($key = $this->nextPart($parseString, '^(KEY|PRIMARY KEY|UNIQUE KEY|UNIQUE)([[:space:]]+|\()'))      {       // Getting key
+                                       $key = strtoupper(str_replace(array(' ',"\t","\r","\n"),'',$key));
 
                                        switch($key)    {
                                                case 'PRIMARYKEY':
-                                                       $result['KEYS'][$key] = $this->getValue($parseString,'_LIST');
+                                                       $result['KEYS']['PRIMARYKEY'] = $this->getValue($parseString,'_LIST');
                                                        if ($this->parse_error) { return $this->parse_error; }
                                                break;
+                                               case 'UNIQUE':
+                                               case 'UNIQUEKEY':
+                                                       if ($keyName = $this->nextPart($parseString, '^([[:alnum:]_]+)([[:space:]]+|\()'))      {
+                                                               $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);
+                                               break;
                                                case 'KEY':
                                                        if ($keyName = $this->nextPart($parseString, '^([[:alnum:]_]+)([[:space:]]+|\()'))      {
                                                                $result['KEYS'][$keyName] = $this->getValue($parseString,'_LIST');
@@ -504,7 +515,7 @@ class t3lib_sqlparser {
 
                        // Removing ALTER TABLE
                $parseString = $this->trimSQL($parseString);
-               $parseString = eregi_replace('^ALTER[[:space:]]+TABLE[[:space:]]+','',$parseString);
+               $parseString = ltrim(substr(ltrim(substr($parseString,5)),5)); // REMOVE eregi_replace('^ALTER[[:space:]]+TABLE[[:space:]]+','',$parseString);
 
                        // Init output variable:
                $result = array();
@@ -515,7 +526,7 @@ class t3lib_sqlparser {
 
                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|DROP|ADD|RENAME)([[:space:]]+|\()'))        {
-                               $actionKey = strtoupper(ereg_replace('[[:space:]]','',$result['action']));
+                               $actionKey = strtoupper(str_replace(array(' ',"\t","\r","\n"),'',$result['action']));
 
                                        // Getting field:
                                if (t3lib_div::inList('ADDPRIMARYKEY,DROPPRIMARYKEY',$actionKey) || $fieldKey = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+'))  {
@@ -573,7 +584,7 @@ class t3lib_sqlparser {
 
                        // Removing DROP TABLE
                $parseString = $this->trimSQL($parseString);
-               $parseString = eregi_replace('^DROP[[:space:]]+TABLE[[:space:]]+','',$parseString);
+               $parseString = ltrim(substr(ltrim(substr($parseString,4)),5)); // eregi_replace('^DROP[[:space:]]+TABLE[[:space:]]+','',$parseString);
 
                        // Init output variable:
                $result = array();
@@ -596,7 +607,35 @@ class t3lib_sqlparser {
                } else return $this->parseError('No table found!',$parseString);
        }
 
+       /**
+        * Parsing CREATE DATABASE query
+        *
+        * @param       string          SQL string starting with CREATE DATABASE
+        * @return      mixed           Returns array with components of CREATE DATABASE query on success, otherwise an error message string.
+        */
+       function parseCREATEDATABASE($parseString)      {
 
+                       // Removing CREATE DATABASE
+               $parseString = $this->trimSQL($parseString);
+               $parseString = ltrim(substr(ltrim(substr($parseString,6)),8)); // eregi_replace('^CREATE[[:space:]]+DATABASE[[:space:]]+','',$parseString);
+
+                       // Init output variable:
+               $result = array();
+               $result['type'] = 'CREATEDATABASE';
+
+                       // Get table:
+               $result['DATABASE'] = $this->nextPart($parseString, '^([[:alnum:]_]+)[[:space:]]+');
+
+               if ($result['DATABASE'])        {
+
+                               // Should be no more content now:
+                       if ($parseString)       {
+                               return $this->parseError('Still content in clause after parsing!',$parseString);
+                       }
+
+                       return $result;
+               } else return $this->parseError('No database found!',$parseString);
+       }
 
 
 
@@ -630,17 +669,19 @@ class t3lib_sqlparser {
         */
        function parseFieldList(&$parseString, $stopRegex='')   {
 
-                       // Prepare variables:
-               $parseString = $this->trimSQL($parseString);
-               $this->lastStopKeyWord = '';
-               $this->parse_error = '';
+               $stack = array();       // Contains the parsed content
 
+               if(strlen($parseString)==0) return $stack;  // FIXME - should never happen, why does it?
 
-               $stack = array();       // Contains the parsed content
                $pnt = 0;                       // Pointer to positions in $stack
                $level = 0;                     // Indicates the parenthesis level we are at.
                $loopExit = 0;          // Recursivity brake.
 
+                       // Prepare variables:
+               $parseString = $this->trimSQL($parseString);
+               $this->lastStopKeyWord = '';
+               $this->parse_error = '';
+
                        // $parseString is continously shortend by the process and we keep parsing it till it is zero:
                while (strlen($parseString)) {
 
@@ -678,6 +719,7 @@ class t3lib_sqlparser {
                                        $stack[$pnt]['function'] = $func;
                                        $level++;       // increse parenthesis level counter.
                                } else {
+                                       $stack[$pnt]['distinct'] = $this->nextPart($parseString,'^(distinct[[:space:]]+)');
                                                // Otherwise, look for regular fieldname:
                                        if ($fieldName = $this->nextPart($parseString,'^([[:alnum:]\*._]+)(,|[[:space:]]+)'))   {
                                                $stack[$pnt]['type'] = 'field';
@@ -692,7 +734,7 @@ class t3lib_sqlparser {
                                                        $stack[$pnt]['field'] = $tableField[0];
                                                }
                                        } else {
-                                               return $this->parseError('No field name found as expected',$parseString);
+                                               return $this->parseError('No field name found as expected in parseFieldList()',$parseString);
                                        }
                                }
                        }
@@ -713,13 +755,13 @@ class t3lib_sqlparser {
 
                                        // Looking for stop-keywords:
                                if ($stopRegex && $this->lastStopKeyWord = $this->nextPart($parseString, $stopRegex))   {
-                                       $this->lastStopKeyWord = strtoupper(ereg_replace('[[:space:]]*','',$this->lastStopKeyWord));
+                                       $this->lastStopKeyWord = strtoupper(str_replace(array(' ',"\t","\r","\n"),'',$this->lastStopKeyWord));
                                        return $stack;
                                }
 
                                        // Looking for comma (since the stop-keyword did not trigger a return...)
                                if (strlen($parseString) && !$this->nextPart($parseString,'^(,)'))      {
-                                       return $this->parseError('No comma found as expected',$parseString);
+                                       return $this->parseError('No comma found as expected in parseFieldList()',$parseString);
                                }
 
                                        // Increasing pointer:
@@ -729,7 +771,7 @@ class t3lib_sqlparser {
                                // Check recursivity brake:
                        $loopExit++;
                        if ($loopExit>500)      {
-                               return $this->parseError('More than 500 loops, exiting prematurely...',$parseString);
+                               return $this->parseError('More than 500 loops, exiting prematurely in parseFieldList()...',$parseString);
                        }
                }
 
@@ -759,36 +801,60 @@ class t3lib_sqlparser {
 
                        // $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 ($as = $this->nextPart($parseString,'^(AS)[[:space:]]+'))    {
-                                       $stack[$pnt]['as'] = $this->nextPart($parseString,'^([[:alnum:]_]+)(,|[[:space:]]+)');
-                                       $stack[$pnt]['as_keyword'] = $as;
+                                       // Looking for stop-keywords before fetching potential table alias:
+                               if ($stopRegex && ($this->lastStopKeyWord = $this->nextPart($parseString, $stopRegex))) {
+                                       $this->lastStopKeyWord = strtoupper(str_replace(array(' ',"\t","\r","\n"),'',$this->lastStopKeyWord));
+                                       return $stack;
                                }
-                       } else return $this->parseError('No table name found as expected!',$parseString);
+                               if(!preg_match('/^(LEFT|JOIN)[[:space:]]+/i',$parseString)) {
+                                       $stack[$pnt]['as_keyword'] = $this->nextPart($parseString,'^(AS[[:space:]]+)');
+                                       $stack[$pnt]['as'] = $this->nextPart($parseString,'^([[:alnum:]_]+)[[:space:]]*');
+                               }
+                       } else return $this->parseError('No table name found as expected in parseFromTables()!',$parseString);
 
                                // Looking for JOIN
-                       if ($join = $this->nextPart($parseString,'^(JOIN|LEFT[[:space:]]+JOIN)[[:space:]]+'))   {
+                       if ($join = $this->nextPart($parseString,'^(LEFT[[:space:]]+JOIN|LEFT[[:space:]]+OUTER[[:space:]]+JOIN|JOIN)[[:space:]]+'))     {
                                $stack[$pnt]['JOIN']['type'] = $join;
                                if ($stack[$pnt]['JOIN']['withTable'] = $this->nextPart($parseString,'^([[:alnum:]_]+)[[:space:]]+ON[[:space:]]+',1))   {
                                        $field1 = $this->nextPart($parseString,'^([[:alnum:]_.]+)[[:space:]]*=[[:space:]]*',1);
                                        $field2 = $this->nextPart($parseString,'^([[:alnum:]_.]+)[[:space:]]+');
                                        if ($field1 && $field2) {
+
+                                               // Explode fields into field and table:
+                                               $tableField = explode('.',$field1,2);
+                                               $field1 = array();
+                                               if (count($tableField)!=2)      {
+                                                       $field1['table'] = '';
+                                                       $field1['field'] = $tableField[0];
+                                               } else {
+                                                       $field1['table'] = $tableField[0];
+                                                       $field1['field'] = $tableField[1];
+                                               }
+                                               $tableField = explode('.',$field2,2);
+                                               $field2 = array();
+                                               if (count($tableField)!=2)      {
+                                                       $field2['table'] = '';
+                                                       $field2['field'] = $tableField[0];
+                                               } else {
+                                                       $field2['table'] = $tableField[0];
+                                                       $field2['field'] = $tableField[1];
+                                               }
                                                $stack[$pnt]['JOIN']['ON'] = array($field1,$field2);
-                                       } else return $this->parseError('No join fields found!',$parseString);
-                               } else  return $this->parseError('No join table found!',$parseString);
+                                       } else return $this->parseError('No join fields 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(ereg_replace('[[:space:]]*','',$this->lastStopKeyWord));
+                               $this->lastStopKeyWord = strtoupper(str_replace(array(' ',"\t","\r","\n"),'',$this->lastStopKeyWord));
                                return $stack;
                        }
 
                                // Looking for comma:
                        if (strlen($parseString) && !$this->nextPart($parseString,'^(,)'))      {
-                               return $this->parseError('No comma found as expected',$parseString);
+                               return $this->parseError('No comma found as expected in parseFromTables()',$parseString);
                        }
 
                                // Increasing pointer:
@@ -797,7 +863,7 @@ class t3lib_sqlparser {
                                // Check recursivity brake:
                        $loopExit++;
                        if ($loopExit>500)      {
-                               return $this->parseError('More than 500 loops, exiting prematurely...',$parseString);
+                               return $this->parseError('More than 500 loops, exiting prematurely in parseFromTables()...',$parseString);
                        }
                }
 
@@ -852,7 +918,7 @@ class t3lib_sqlparser {
                                                $stack[$level][$pnt[$level]]['field'] = $tableField[0];
                                        }
                                } else {
-                                       return $this->parseError('No field name found as expected',$parseString);
+                                       return $this->parseError('No field name found as expected in parseWhereClause()',$parseString);
                                }
 
                                        // See if the value is calculated. Support only for "&" (boolean AND) at the moment:
@@ -863,7 +929,7 @@ class t3lib_sqlparser {
                                }
 
                                        // Find "comparator":
-                               $stack[$level][$pnt[$level]]['comparator'] = $this->nextPart($parseString,'^(<=|>=|<|>|=|!=|NOT[[:space:]]+IN|IN|NOT[[:space:]]+LIKE|LIKE|IS)');
+                               $stack[$level][$pnt[$level]]['comparator'] = $this->nextPart($parseString,'^(<=|>=|<|>|=|!=|NOT[[:space:]]+IN|IN|NOT[[:space:]]+LIKE|LIKE|IS[[:space:]]+NOT|IS)');
                                if (strlen($stack[$level][$pnt[$level]]['comparator'])) {
                                                // Finding value for comparator:
                                        $stack[$level][$pnt[$level]]['value'] = $this->getValue($parseString,$stack[$level][$pnt[$level]]['comparator']);
@@ -882,22 +948,22 @@ class t3lib_sqlparser {
                                                // Make recursivity check:
                                        $loopExit++;
                                        if ($loopExit>500)      {
-                                               return $this->parseError('More than 500 loops (in search for exit parenthesis), exiting prematurely...',$parseString);
+                                               return $this->parseError('More than 500 loops (in search for exit parenthesis), exiting prematurely in parseWhereClause()...',$parseString);
                                        }
                                }
 
-                                       // Detecting the operator for the next level; support for AND, OR and &&):
-                               $op = $this->nextPart($parseString,'^(AND|OR|AND[[:space:]]+NOT)(\(|[[:space:]]+)');
+                                       // Detecting the operator for the next level:
+                               $op = $this->nextPart($parseString,'^(AND[[:space:]]+NOT|OR[[:space:]]+NOT|AND|OR)(\(|[[:space:]]+)');
                                if ($op)        {
                                        $stack[$level][$pnt[$level]]['operator'] = $op;
                                } elseif (strlen($parseString)) {
 
                                                // Looking for stop-keywords:
                                        if ($stopRegex && $this->lastStopKeyWord = $this->nextPart($parseString, $stopRegex))   {
-                                               $this->lastStopKeyWord = strtoupper(ereg_replace('[[:space:]]*','',$this->lastStopKeyWord));
+                                               $this->lastStopKeyWord = strtoupper(str_replace(array(' ',"\t","\r","\n"),'',$this->lastStopKeyWord));
                                                return $stack[0];
                                        } else {
-                                               return $this->parseError('No operator, but parsing not finished.',$parseString);
+                                               return $this->parseError('No operator, but parsing not finished in parseWhereClause().',$parseString);
                                        }
                                }
                        }
@@ -905,7 +971,7 @@ class t3lib_sqlparser {
                                // Make recursivity check:
                        $loopExit++;
                        if ($loopExit>500)      {
-                               return $this->parseError('More than 500 loops, exiting prematurely...',$parseString);
+                               return $this->parseError('More than 500 loops, exiting prematurely in parseWhereClause()...',$parseString);
                        }
                }
 
@@ -930,19 +996,19 @@ class t3lib_sqlparser {
                $result = array();
 
                        // Field type:
-               if ($result['fieldType'] =  $this->nextPart($parseString,'^(int|smallint|tinyint|mediumint|double|varchar|char|text|tinytext|mediumtext|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)=='(')      {
                                $parseString = substr($parseString,1);
                                if ($result['value'] =  $this->nextPart($parseString,'^([^)]*)'))       {
                                        $parseString = ltrim(substr($parseString,1));
-                               } else return $this->parseError('No end-parenthesis for value found!',$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:]]+|,|\))'))     {
-                               $keywordCmp = strtoupper(ereg_replace('[[:space:]]*','',$keyword));
+                               $keywordCmp = strtoupper(str_replace(array(' ',"\t","\r","\n"),'',$keyword));
 
                                $result['featureIndex'][$keywordCmp]['keyword'] = $keyword;
 
@@ -952,7 +1018,9 @@ class t3lib_sqlparser {
                                        break;
                                }
                        }
-               } else return $this->parseError('Field type unknown!',$parseString);
+               } else {
+                       return $this->parseError('Field type unknown in parseFieldDef()!',$parseString);
+               }
 
                return $result;
        }
@@ -974,7 +1042,7 @@ class t3lib_sqlparser {
         ************************************/
 
        /**
-        * Strips of a part of the parseString and returns the matching part.
+        * Strips off a part of the parseString and returns the matching part.
         * Helper function for the parsing methods.
         *
         * @param       string          Parse string; if $regex finds anything the value of the first () level will be stripped of the string in the beginning. Further $parseString is left-trimmed (on success). Notice; parsestring is passed by reference.
@@ -983,7 +1051,8 @@ class t3lib_sqlparser {
         * @return      string          The value of the first parenthesis level of the REGEX.
         */
        function nextPart(&$parseString,$regex,$trimAll=FALSE)  {
-               if (eregi($regex,$parseString.' ', $reg))       {       // Adding space char because [[:space:]]+ is often a requirement in regex's
+               $reg = array();
+               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])));
                        return $reg[1];
                }
@@ -994,10 +1063,12 @@ class t3lib_sqlparser {
         *
         * @param       string          The parseString, eg. "(0,1,2,3) ..." or "('asdf','qwer') ..." or "1234 ..." or "'My string value here' ..."
         * @param       string          The comparator used before. If "NOT IN" or "IN" then the value is expected to be a list of values. Otherwise just an integer (un-quoted) or string (quoted)
-        * @return      string          The value (string/integer). Otherwise an array with error message in first key (0)
+        * @return      mixed           The value (string/integer). Otherwise an array with error message in first key (0)
         */
        function getValue(&$parseString,$comparator='') {
-               if (t3lib_div::inList('NOTIN,IN,_LIST',strtoupper(ereg_replace('[[:space:]]','',$comparator)))) {       // List of values:
+               $value = '';
+
+               if (t3lib_div::inList('NOTIN,IN,_LIST',strtoupper(str_replace(array(' ',"\n","\r","\t"),'',$comparator))))      {       // List of values:
                        if ($this->nextPart($parseString,'^([(])'))     {
                                $listValues = array();
                                $comma=',';
@@ -1025,22 +1096,23 @@ class t3lib_sqlparser {
 
                                // Quote?
                        $firstChar = substr($parseString,0,1);
-
                        switch($firstChar)      {
                                case '"':
-                                       return array($this->getValueInQuotes($parseString,'"'),'"');
+                                       $value = array($this->getValueInQuotes($parseString,'"'),'"');
                                break;
                                case "'":
-                                       return array($this->getValueInQuotes($parseString,"'"),"'");
+                                       $value = array($this->getValueInQuotes($parseString,"'"),"'");
                                break;
                                default:
-                                       if (eregi('^([[:alnum:]._-]+)',$parseString, $reg))     {
+                                       $reg = array();
+                                       if (preg_match('/^([[:alnum:]._-]+)/i',$parseString, $reg))     {
                                                $parseString = ltrim(substr($parseString,strlen($reg[0])));
-                                               return array($reg[1]);
+                                               $value = array($reg[1]);
                                        }
                                break;
                        }
                }
+               return $value;
        }
 
        /**
@@ -1058,9 +1130,10 @@ class t3lib_sqlparser {
                foreach($parts as $k => $v)     {
                        $buffer.=$v;
 
-                       unset($reg);
+                       $reg = array();
+                       //preg_match('/[\]*$/',$v,$reg); // does not work. what is the *exact* meaning of the next line?
                        ereg('[\]*$',$v,$reg);
-                       if (strlen($reg[0])%2)  {
+                       if ($reg AND strlen($reg[0])%2) {
                                $buffer.=$quote;
                        } else {
                                $parseString = ltrim(substr($parseString,strlen($buffer)+2));
@@ -1091,6 +1164,7 @@ class t3lib_sqlparser {
         * @return      string          Output string
         */
        function compileAddslashes($str)        {
+return $str;
                $search = array('\\', '\'', '"', "\x00", "\x0a", "\x0d", "\x1a");
                $replace = array('\\\\', '\\\'', '\\"', '\0', '\n', '\r', '\Z');
 
@@ -1119,7 +1193,8 @@ class t3lib_sqlparser {
         * @return      string          Output string
         */
        function trimSQL($str)  {
-               return trim(ereg_replace('[[:space:];]*$','',$str)).' ';
+               return trim(rtrim($str, "; \r\n\t")).' ';
+               //return trim(ereg_replace('[[:space:];]*$','',$str)).' ';
        }
 
 
@@ -1313,6 +1388,8 @@ class t3lib_sqlparser {
                foreach($components['KEYS'] as $kN => $kCfg)    {
                        if ($kN == 'PRIMARYKEY')        {
                                $fieldsKeys[]='PRIMARY KEY ('.implode(',', $kCfg).')';
+                       } elseif ($kN == 'UNIQUE')      {
+                               $fieldsKeys[]='UNIQUE '.$kN.' ('.implode(',', $kCfg).')';
                        } else {
                                $fieldsKeys[]='KEY '.$kN.' ('.implode(',', $kCfg).')';
                        }
@@ -1340,7 +1417,7 @@ class t3lib_sqlparser {
                $query = 'ALTER TABLE '.$components['TABLE'].' '.$components['action'].' '.($components['FIELD']?$components['FIELD']:$components['KEY']);
 
                        // Based on action, add the final part:
-               switch(strtoupper(ereg_replace('[[:space:]]','',$components['action'])))        {
+               switch(strtoupper(str_replace(array(' ',"\t","\r","\n"),'',$components['action'])))     {
                        case 'ADD':
                                $query.=' '.$this->compileFieldCfg($components['definition']);
                        break;
@@ -1402,7 +1479,7 @@ class t3lib_sqlparser {
                                                $outputParts[$k] = $v['function'].'('.$v['func_content'].')';
                                        break;
                                        case 'field':
-                                               $outputParts[$k] = ($v['table']?$v['table'].'.':'').$v['field'];
+                                               $outputParts[$k] = ($v['distinct']?$v['distinct']:'').($v['table']?$v['table'].'.':'').$v['field'];
                                        break;
                                }
 
@@ -1447,9 +1524,13 @@ class t3lib_sqlparser {
                                }
 
                                if (is_array($v['JOIN']))       {
-                                       $outputParts[$k].= ' '.$v['JOIN']['type'].' '.$v['JOIN']['withTable'].' ON '.implode('=',$v['JOIN']['ON']);
+                                       $outputParts[$k] .= ' '.$v['JOIN']['type'].' '.$v['JOIN']['withTable'].' ON ';
+                                       $outputParts[$k] .= ($v['JOIN']['ON'][0]['table']) ? $v['JOIN']['ON'][0]['table'].'.' : '';
+                                       $outputParts[$k] .= $v['JOIN']['ON'][0]['field'];
+                                       $outputParts[$k] .= '=';
+                                       $outputParts[$k] .= ($v['JOIN']['ON'][1]['table']) ? $v['JOIN']['ON'][1]['table'].'.' : '';
+                                       $outputParts[$k] .= $v['JOIN']['ON'][1]['field'];
                                }
-
                        }
                }
 
@@ -1460,6 +1541,7 @@ class t3lib_sqlparser {
        /**
         * Implodes an array of WHERE clause configuration into a WHERE clause.
         * NOTICE: MIGHT BY A TEMPORARY FUNCTION. Use for debugging only!
+        * BUT IT IS NEEDED FOR DBAL - MAKE IT PERMANENT?!?!
         *
         * @param       array           WHERE clause configuration
         * @return      string          WHERE clause as string.
@@ -1495,7 +1577,7 @@ class t3lib_sqlparser {
                                                $output.=' '.$v['comparator'];
 
                                                        // Detecting value type; list or plain:
-                                               if (t3lib_div::inList('NOTIN,IN',strtoupper(ereg_replace('[[:space:]]','',$v['comparator']))))  {
+                                               if (t3lib_div::inList('NOTIN,IN',strtoupper(str_replace(array(' ',"\t","\r","\n"),'',$v['comparator']))))       {
                                                        $valueBuffer = array();
                                                        foreach($v['value'] as $realValue)      {
                                                                $valueBuffer[]=$realValue[1].$this->compileAddslashes($realValue[0]).$realValue[1];
@@ -1569,17 +1651,20 @@ class t3lib_sqlparser {
         * @return      mixed           Returns array with string 1 and 2 if error, otherwise false
         */
        function debug_parseSQLpart($part,$str) {
+               $retVal = false;
+
                switch($part)   {
                        case 'SELECT':
-                               return $this->debug_parseSQLpartCompare($str,$this->compileFieldList($this->parseFieldList($str)));
+                               $retVal = $this->debug_parseSQLpartCompare($str,$this->compileFieldList($this->parseFieldList($str)));
                        break;
                        case 'FROM':
-                               return $this->debug_parseSQLpartCompare($str,$this->compileFromTables($this->parseFromTables($str)));
+                               $retVal = $this->debug_parseSQLpartCompare($str,$this->compileFromTables($this->parseFromTables($str)));
                        break;
                        case 'WHERE':
-                               return $this->debug_parseSQLpartCompare($str,$this->compileWhereClause($this->parseWhereClause($str)));
+                               $retVal = $this->debug_parseSQLpartCompare($str,$this->compileWhereClause($this->parseWhereClause($str)));
                        break;
                }
+               return $retVal;
        }
 
        /**
@@ -1609,10 +1694,10 @@ class t3lib_sqlparser {
 #              $str1 = stripslashes($str1);
 #              $str2 = stripslashes($str2);
 
-               if (strcmp(ereg_replace('[[:space:]]','',$this->trimSQL($str1)),ereg_replace('[[:space:]]','',$this->trimSQL($str2))))  {
+               if (strcmp(str_replace(array(' ',"\t","\r","\n"),'',$this->trimSQL($str1)),str_replace(array(' ',"\t","\r","\n"),'',$this->trimSQL($str2))))    {
                        return array(
-                                       ereg_replace('[[:space:]]+',' ',$str),
-                                       ereg_replace('[[:space:]]+',' ',$newStr),
+                                       str_replace(array(' ',"\t","\r","\n"),' ',$str),
+                                       str_replace(array(' ',"\t","\r","\n"),' ',$newStr),
                                );
                }
        }
@@ -1624,8 +1709,6 @@ class t3lib_sqlparser {
         * @return      string          Query if all is well, otherwise exit.
         */
        function debug_testSQL($SQLquery)       {
-#              return $SQLquery;
-#debug(array($SQLquery));
 
                        // Getting result array:
                $parseResult = $this->parseSQL($SQLquery);
@@ -1657,4 +1740,5 @@ class t3lib_sqlparser {
 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_sqlparser.php'])        {
        include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_sqlparser.php']);
 }
-?>
+
+?>
\ No newline at end of file