Fixed bug #6196: IFNULL operator cannot be parsed
[Packages/TYPO3.CMS.git] / typo3 / sysext / dbal / class.ux_t3lib_db.php
old mode 100755 (executable)
new mode 100644 (file)
index 2dfe9e6..2b112c6
@@ -2,7 +2,9 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2004 Kasper Skaarhoj (kasper@typo3.com)
+*  (c) 2004-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
+*  (c) 2004-2009 Karsten Dambekalns <karsten@typo3.org>
+*  (c) 2009-2010 Xavier Perseguers <typo3@perseguers.ch>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -31,6 +33,7 @@
  *
  * @author     Kasper Skaarhoj <kasper@typo3.com>
  * @author     Karsten Dambekalns <k.dambekalns@fishfarm.de>
+ * @author     Xavier Perseguers <typo3@perseguers.ch>
  */
 /**
  * [CLASS/FUNCTION INDEX of SCRIPT]
  *  217:     function exec_INSERTquery($table,$fields_values)
  *  275:     function exec_UPDATEquery($table,$where,$fields_values)
  *  334:     function exec_DELETEquery($table,$where)
- *  387:     function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='')
+ *  387:     function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy = '',$orderBy = '',$limit = '')
  *
  *              SECTION: Creates an INSERT SQL-statement for $table from the array with field/value pairs $fields_values.
- *  533:     function SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='')
+ *  533:     function SELECTquery($select_fields,$from_table,$where_clause,$groupBy = '',$orderBy = '',$limit = '')
  *  556:     function quoteSelectFields(&$select_fields)
  *  573:     function quoteFromTables(&$from_table)
  *  595:     function quoteWhereClause(&$where_clause)
@@ -86,8 +89,8 @@
  * 1379:     function handler_init($handlerKey)
  *
  *              SECTION: Table/Field mapping
- * 1488:     function map_needMapping($tableList,$fieldMappingOnly=FALSE)
- * 1524:     function map_assocArray($input,$tables,$rev=FALSE)
+ * 1488:     function map_needMapping($tableList,$fieldMappingOnly = FALSE)
+ * 1524:     function map_assocArray($input,$tables,$rev = FALSE)
  * 1573:     function map_remapSELECTQueryParts(&$select_fields,&$from_table,&$where_clause,&$groupBy,&$orderBy)
  * 1615:     function map_sqlParts(&$sqlPartArray, $defaultTable)
  * 1650:     function map_genericQueryParsed(&$parsedQuery)
  * (This index is automatically created/updated by the extension "extdeveval")
  *
  */
-
-
-
-
-
-
-
-
-
-
-require_once(PATH_t3lib.'class.t3lib_sqlengine.php');
-require_once(PATH_t3lib.'class.t3lib_install.php');
-//require_once(t3lib_extMgm::extPath('install').'mod/class.tx_install.php');
-
 /**
  * TYPO3 database abstraction layer
  *
@@ -126,468 +115,564 @@ require_once(PATH_t3lib.'class.t3lib_install.php');
  */
 class ux_t3lib_DB extends t3lib_DB {
 
-  // Internal, static:
-  var $printErrors = FALSE;                    // Enable output of SQL errors after query executions. Set through TYPO3_CONF_VARS, see init()
-  var $debug = FALSE;                                  // Enable debug mode. Set through TYPO3_CONF_VARS, see init()
-  var $conf = array();                         // Configuration array, copied from TYPO3_CONF_VARS in constructor.
-
-  var $mapping = array();                              // See manual.
-  var $table2handlerKeys = array();    // See manual.
-  var $handlerCfg = array (                    // See manual.
-  '_DEFAULT' => array (
-  'type' => 'native',
-  'config' => array(
-  'username' => '',            // Set by default (overridden)
-  'password' => '',            // Set by default (overridden)
-  'host' => '',                        // Set by default (overridden)
-  'database' => '',            // Set by default (overridden)
-  'driver' => '',                      // ONLY "adodb" type; eg. "mysql"
-  )
-  ),
-  );
-
-
-  // Internal, dynamic:
-  var $handlerInstance = array();                              // Contains instance of the handler objects as they are created. Exception is the native mySQL calls which are registered as an array with keys "handlerType" = "native" and "link" pointing to the link resource for the connection.
-  var $lastHandlerKey = '';                                    // Storage of the handler key of last ( SELECT) query - used for subsequent fetch-row calls etc.
-  var $lastQuery = '';                                         // Storage of last SELECT query
-  var $lastParsedAndMappedQueryArray=array();  // Query array, the last one parsed
-
-  var $resourceIdToTableNameMap = array();     // Mapping of resource ids to table names.
-
-  // Internal, caching:
-  var $cache_handlerKeyFromTableList = array();                        // Caching handlerKeys for table lists
-  var $cache_mappingFromTableList = array();                   // Caching mapping information for table lists
-  var $cache_autoIncFields = array(); // parsed SQL from standard DB dump file
-  var $cache_fieldType = array(); // field types for tables/fields
-  var $cache_primaryKeys = array(); // primary keys
-
+               // Internal, static:
+       var $printErrors = FALSE;       // Enable output of SQL errors after query executions. Set through TYPO3_CONF_VARS, see init()
+       var $debug = FALSE;                     // Enable debug mode. Set through TYPO3_CONF_VARS, see init()
+       var $conf = array();            // Configuration array, copied from TYPO3_CONF_VARS in constructor.
+
+       var $mapping = array();         // See manual.
+       var $table2handlerKeys = array();       // See manual.
+       var $handlerCfg = array(        // See manual.
+           '_DEFAULT' => array(
+                               'type' => 'native',
+                               'config' => array(
+                                   'username' => '',   // Set by default (overridden)
+                                   'password' => '',   // Set by default (overridden)
+                                   'host' => '',       // Set by default (overridden)
+                                   'database' => '',   // Set by default (overridden)
+                                   'driver' => '',     // ONLY "adodb" type; eg. "mysql"
+                                   'sequenceStart' => 1,       // ONLY "adodb", first number in sequences/serials/...
+                                   'useNameQuote' => 0 // ONLY "adodb", whether to use NameQuote() method from ADOdb to quote names
+                               )
+           ),
+       );
+
+
+               // Internal, dynamic:
+       var $handlerInstance = array();                         // Contains instance of the handler objects as they are created. Exception is the native mySQL calls which are registered as an array with keys "handlerType" = "native" and "link" pointing to the link resource for the connection.
+       var $lastHandlerKey = '';                                       // Storage of the handler key of last ( SELECT) query - used for subsequent fetch-row calls etc.
+       var $lastQuery = '';                                            // Storage of last SELECT query
+       var $lastParsedAndMappedQueryArray = array();   // Query array, the last one parsed
+
+       var $resourceIdToTableNameMap = array();        // Mapping of resource ids to table names.
+
+               // Internal, caching:
+       var $cache_handlerKeyFromTableList = array();                   // Caching handlerKeys for table lists
+       var $cache_mappingFromTableList = array();                      // Caching mapping information for table lists
+       var $cache_autoIncFields = array(); // parsed SQL from standard DB dump file
+       var $cache_fieldType = array(); // field types for tables/fields
+       var $cache_primaryKeys = array(); // primary keys
 
+       /**
+        * SQL parser
+        *
+        * @var tx_dbal_sqlengine
+        */
+       var $SQLparser;
 
+       /**
+        * Installer
+        *
+        * @var t3lib_install
+        */
+       var $Installer;
 
 
-  /**
+       /**
         * Constructor.
         * Creates SQL parser object and imports configuration from $TYPO3_CONF_VARS['EXTCONF']['dbal']
+        */
+       public function __construct() {
+                       // Set SQL parser object for internal use:
+               $this->SQLparser = t3lib_div::makeInstance('tx_dbal_sqlengine');
+               $this->Installer = t3lib_div::makeInstance('t3lib_install');
+
+                       // Set internal variables with configuration:
+               $this->conf = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['dbal'];
+               $this->initInternalVariables();
+       }
+
+       /**
+        * Setting internal variables from $this->conf.
         *
         * @return      void
         */
-  function ux_t3lib_DB()       {
+       protected function initInternalVariables() {
+                       // Set outside configuration:
+               if (isset($this->conf['mapping'])) {
+                       $this->mapping = $this->conf['mapping'];
+               }
+               if (isset($this->conf['table2handlerKeys'])) {
+                       $this->table2handlerKeys = $this->conf['table2handlerKeys'];
+               }
+               if (isset($this->conf['handlerCfg'])) {
+                       $this->handlerCfg = $this->conf['handlerCfg'];
+               }
 
-    // Set SQL parser object for internal use:
-    $this->SQLparser = t3lib_div::makeInstance('t3lib_sqlengine');
-    $this->Installer = t3lib_div::makeInstance('t3lib_install');
+               $this->cacheFieldInfo();
+                       // Debugging settings:
+               $this->printErrors = $this->conf['debugOptions']['printErrors'] ? TRUE : FALSE;
+               $this->debug = $this->conf['debugOptions']['enabled'] ? TRUE : FALSE;
+       }
 
-    // Set internal variables with configuration:
-    $this->conf = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['dbal'];
-    $this->initInternalVariables();
-  }
+       /**
+        * Clears the cached field information file.
+        * 
+        * @return void
+        */
+       public function clearCachedFieldInfo() {
+               if (file_exists(PATH_typo3conf . 'temp_fieldInfo.php')) {
+                       unlink(PATH_typo3conf . 'temp_fieldInfo.php');  
+               }
+       }
 
-  /**
-        * Setting internal variables from $this->conf
-        *
-        * @return      void
+       /**
+        * Caches the field information.
+        * 
+        * @return void
         */
-  function initInternalVariables()     {
-
-    // Set outside configuration:
-    if (isset($this->conf['mapping']))                         $this->mapping = $this->conf['mapping'];
-    if (isset($this->conf['table2handlerKeys']))       $this->table2handlerKeys = $this->conf['table2handlerKeys'];
-    if (isset($this->conf['handlerCfg']))                      $this->handlerCfg = $this->conf['handlerCfg'];
-
-    $this->cacheFieldInfo();
-    // Debugging settings:
-    $this->printErrors = $this->conf['debugOptions']['printErrors'] ? TRUE : FALSE;
-    $this->debug = $this->conf['debugOptions']['enabled'] ? TRUE : FALSE;
-  }
-
-  function clearCachedFieldInfo() {
-    if(file_exists(PATH_typo3conf.'temp_fieldInfo.php'))
-    unlink(PATH_typo3conf.'temp_fieldInfo.php');
-  }
-
-  function cacheFieldInfo() {
-    global $TYPO3_LOADED_EXT;
-    $extSQL = '';
-    $parsedExtSQL = array();
-
-    // try to fetch cached file first
-    // file is removed when admin_query() is called
-    if(file_exists(PATH_typo3conf.'temp_fieldInfo.php')) {
-      $fdata = unserialize(t3lib_div::getUrl(PATH_typo3conf.'temp_fieldInfo.php'));
-      $this->cache_autoIncFields = $fdata['incFields'];
-      $this->cache_fieldType = $fdata['fieldTypes'];
-      $this->cache_primaryKeys = $fdata['primaryKeys'];
-    }
-    else {
-      // handle stddb.sql
-      $extSQL = t3lib_div::getUrl(PATH_site.'t3lib/stddb/tables.sql');
-      $parsedExtSQL = $this->Installer->getFieldDefinitions_sqlContent($extSQL);
-
-      // extract auto_inc field (if any)
-      foreach($parsedExtSQL as $table => $tdef) {
-        foreach($tdef['fields'] as $field => $fdef) {
-          $fdef = $this->SQLparser->parseFieldDef($fdef);
-          $this->cache_fieldType[$table][$field]['type'] = $fdef['fieldType'];
-          $this->cache_fieldType[$table][$field]['metaType'] = $this->MySQLMetaType($fdef['fieldType']);
-          $this->cache_fieldType[$table][$field]['notnull'] = (isset($fdef['featureIndex']['NOTNULL']) && !$this->SQLparser->checkEmptyDefaultValue($fdef['featureIndex'])) ? 1 : 0;
-          if(isset($fdef['featureIndex']['AUTO_INCREMENT'])) {
-            // store in array
-            $this->cache_autoIncFields[$table] = $field;
-          }
-          if(isset($tdef['keys']['PRIMARY'])) {
-                                               $this->cache_primaryKeys[$table] = substr($tdef['keys']['PRIMARY'], 13, -1);
-          }
-        }
-      }
-
-      // loop over all installed extensions
-      foreach($TYPO3_LOADED_EXT as $ext => $v) {
-        if(!is_array($v) || !isset($v['ext_tables.sql']))
-        continue;
-
-        // fetch db dump (if any) and parse it
-        $extSQL = t3lib_div::getUrl($v['ext_tables.sql']);
-        $parsedExtSQL = $this->Installer->getFieldDefinitions_sqlContent($extSQL);
-
-        // extract auto_inc field (if any)
-        foreach($parsedExtSQL as $table => $tdef) {
-          foreach($tdef['fields'] as $field => $fdef) {
-            $fdef = $this->SQLparser->parseFieldDef($fdef);
-            $this->cache_fieldType[$table][$field]['type'] = $fdef['fieldType'];
-            $this->cache_fieldType[$table][$field]['metaType'] = $this->MySQLMetaType($fdef['fieldType']);
-            $this->cache_fieldType[$table][$field]['notnull'] = (isset($fdef['featureIndex']['NOTNULL']) && !$this->SQLparser->checkEmptyDefaultValue($fdef['featureIndex'])) ? 1 : 0;
-            if(isset($fdef['featureIndex']['AUTO_INCREMENT'])) {
-              $this->cache_autoIncFields[$table] = $field;
-            }
-            if(isset($tdef['keys']['PRIMARY'])) {
-                                                       $this->cache_primaryKeys[$table] = substr($tdef['keys']['PRIMARY'], 13, -1);
-            }
-          }
-        }
-      }
+       public function cacheFieldInfo() {
+               $extSQL = '';
+               $parsedExtSQL = array();
+
+                       // try to fetch cached file first
+                       // file is removed when admin_query() is called
+               if (file_exists(PATH_typo3conf . 'temp_fieldInfo.php')) {
+                       $fdata = unserialize(t3lib_div::getUrl(PATH_typo3conf . 'temp_fieldInfo.php'));
+                       $this->cache_autoIncFields = $fdata['incFields'];
+                       $this->cache_fieldType = $fdata['fieldTypes'];
+                       $this->cache_primaryKeys = $fdata['primaryKeys'];
+               } else {
+                               // handle stddb.sql, parse and analyze
+                       $extSQL = t3lib_div::getUrl(PATH_site . 't3lib/stddb/tables.sql');
+                       $parsedExtSQL = $this->Installer->getFieldDefinitions_fileContent($extSQL);
+                       $this->analyzeFields($parsedExtSQL);
+
+                               // loop over all installed extensions
+                       foreach ($GLOBALS['TYPO3_LOADED_EXT'] as $ext => $v) {
+                               if (!is_array($v) || !isset($v['ext_tables.sql'])) {
+                                       continue;
+                               }
+
+                                       // fetch db dump (if any) and parse it, then analyze
+                               $extSQL = t3lib_div::getUrl($v['ext_tables.sql']);
+                               $parsedExtSQL = $this->Installer->getFieldDefinitions_fileContent($extSQL);
+                               $this->analyzeFields($parsedExtSQL);
+                       }
 
                        $cachedFieldInfo = array('incFields' => $this->cache_autoIncFields, 'fieldTypes' => $this->cache_fieldType, 'primaryKeys' => $this->cache_primaryKeys);
                        $cachedFieldInfo = serialize($this->mapCachedFieldInfo($cachedFieldInfo));
 
-      // write serialized content to file
-                       t3lib_div::writeFile(PATH_typo3conf."temp_fieldInfo.php", $cachedFieldInfo);
+                               // write serialized content to file
+                       t3lib_div::writeFile(PATH_typo3conf . 'temp_fieldInfo.php', $cachedFieldInfo);
+
+                       if (strcmp(t3lib_div::getUrl(PATH_typo3conf . 'temp_fieldInfo.php'), $cachedFieldInfo)) {
+                               die('typo3temp/temp_incfields.php was NOT updated properly (written content didn\'t match file content) - maybe write access problem?');
+                       }
+               }
+       }
 
-                       if (strcmp(t3lib_div::getUrl(PATH_typo3conf."temp_fieldInfo.php"), $cachedFieldInfo))   {
-        die('typo3temp/temp_incfields.php was NOT updated properly (written content didn\'t match file content) - maybe write access problem?');
-      }
-    }
-  }
+       /**
+        * Analyzes fields and adds the extracted information to the field type, auto increment and primary key info caches.
+        *
+        * @param array $parsedExtSQL The output produced by t3lib_install::getFieldDefinitions_fileContent()
+        * @return void
+        * @see t3lib_install::getFieldDefinitions_fileContent()
+        */
+       protected function analyzeFields($parsedExtSQL) {
+               foreach ($parsedExtSQL as $table => $tdef) {
+                       if (is_array($tdef['fields'])) {
+                               foreach ($tdef['fields'] as $field => $fdef) {
+                                       $fdef = $this->SQLparser->parseFieldDef($fdef);
+                                       $this->cache_fieldType[$table][$field]['type'] = $fdef['fieldType'];
+                                       $this->cache_fieldType[$table][$field]['metaType'] = $this->MySQLMetaType($fdef['fieldType']);
+                                       $this->cache_fieldType[$table][$field]['notnull'] = (isset($fdef['featureIndex']['NOTNULL']) && !$this->SQLparser->checkEmptyDefaultValue($fdef['featureIndex'])) ? 1 : 0;
+                                       if (isset($fdef['featureIndex']['DEFAULT'])) {
+                                               $default = $fdef['featureIndex']['DEFAULT']['value'][0];
+                                               if (isset($fdef['featureIndex']['DEFAULT']['value'][1])) {
+                                                       $default = $fdef['featureIndex']['DEFAULT']['value'][1] . $default . $fdef['featureIndex']['DEFAULT']['value'][1];
+                                               }
+                                               $this->cache_fieldType[$table][$field]['default'] = $default;
+                                       }
+                                       if (isset($fdef['featureIndex']['AUTO_INCREMENT'])) {
+                                               $this->cache_autoIncFields[$table] = $field;
+                                       }
+                                       if (isset($tdef['keys']['PRIMARY'])) {
+                                               $this->cache_primaryKeys[$table] = substr($tdef['keys']['PRIMARY'], 13, -1);
+                                       }
+                               }
+                       }
+               }
+       }
 
        /**
        * This function builds all definitions for mapped tables and fields
        * @see cacheFieldInfo()
        */
-       function mapCachedFieldInfo($fieldInfo){
-               global $TYPO3_CONF_VARS;
+       protected function mapCachedFieldInfo($fieldInfo) {
+               if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['dbal']['mapping'])) {
+                       foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['dbal']['mapping'] as $mappedTable => $mappedConf) {
+                               if (array_key_exists($mappedTable, $fieldInfo['incFields'])) {
+                                       $mappedTableAlias = $mappedConf['mapTableName'];
+                                       if (isset($mappedConf['mapFieldNames'][$fieldInfo['incFields'][$mappedTable]])) {
+                                               $fieldInfo['incFields'][$mappedTableAlias] = $mappedConf['mapFieldNames'][$fieldInfo['incFields'][$mappedTable]];
+                                       } else {
+                                               $fieldInfo['incFields'][$mappedTableAlias] = $fieldInfo['incFields'][$mappedTable];     
+                                       }
+                               }
 
-               foreach($TYPO3_CONF_VARS['EXTCONF']['dbal']['mapping'] as $mappedTable => $mappedConf){
-                       if(array_key_exists($mappedTable, $fieldInfo['incFields'])) {
-                               $mappedTableAlias = $mappedConf['mapTableName'];
-                               $fieldInfo['incFields'][$mappedTableAlias] = isset($mappedConf['mapFieldNames'][$fieldInfo['incFields'][$mappedTable]]) ? $mappedConf['mapFieldNames'][$fieldInfo['incFields'][$mappedTable]] : $fieldInfo['incFields'][$mappedTable];
-                       }
+                               if (array_key_exists($mappedTable, $fieldInfo['fieldTypes'])) {
+                                       foreach ($fieldInfo['fieldTypes'][$mappedTable] as $field => $fieldConf) {
+                                               $tempMappedFieldConf[$mappedConf['mapFieldNames'][$field]] = $fieldConf;
+                                       }
 
-                       if(array_key_exists($mappedTable, $fieldInfo['fieldTypes'])) {
-                               foreach($fieldInfo['fieldTypes'][$mappedTable] as $field => $fieldConf){
-                                       $tempMappedFieldConf[$mappedConf['mapFieldNames'][$field]] = $fieldConf;
+                                       $fieldInfo['fieldTypes'][$mappedConf['mapTableName']] = $tempMappedFieldConf;
                                }
 
-                               $fieldInfo['fieldTypes'][$mappedConf['mapTableName']] = $tempMappedFieldConf;
-                       }
-
-                       if(array_key_exists($mappedTable, $fieldInfo['primaryKeys'])) {
-                               $mappedTableAlias = $mappedConf['mapTableName'];
-                               $fieldInfo['primaryKeys'][$mappedTableAlias] = isset($mappedConf['mapFieldNames'][$fieldInfo['primaryKeys'][$mappedTable]]) ? $mappedConf['mapFieldNames'][$fieldInfo['primaryKeys'][$mappedTable]] : $fieldInfo['primaryKeys'][$mappedTable];
+                               if (array_key_exists($mappedTable, $fieldInfo['primaryKeys'])) {
+                                       $mappedTableAlias = $mappedConf['mapTableName'];
+                                       if (isset($mappedConf['mapFieldNames'][$fieldInfo['primaryKeys'][$mappedTable]])) {
+                                               $fieldInfo['primaryKeys'][$mappedTableAlias] = $mappedConf['mapFieldNames'][$fieldInfo['primaryKeys'][$mappedTable]];
+                                       } else {
+                                               $fieldInfo['primaryKeys'][$mappedTableAlias] = $fieldInfo['primaryKeys'][$mappedTable]; 
+                                       }
+                               }
                        }
-
                }
 
                return $fieldInfo;
        }
 
 
-  /************************************
-  *
-  * Query Building (Overriding parent methods)
-  * These functions are extending counterparts in the parent class.
-  *
-  **************************************/
+       /************************************
+       *
+       * Query Building (Overriding parent methods)
+       * These functions are extending counterparts in the parent class.
+       *
+       **************************************/
 
-  /* From the ADOdb documentation, this is what we do (_Execute for SELECT, _query for the other actions)
+       /* From the ADOdb documentation, this is what we do (_Execute for SELECT, _query for the other actions)
 
-  Execute() is the default way to run queries. You can use the low-level functions _Execute() and _query() to reduce query overhead.
-  Both these functions share the same parameters as Execute().
+       Execute() is the default way to run queries. You can use the low-level functions _Execute() and _query() to reduce query overhead.
+       Both these functions share the same parameters as Execute().
 
-  If you do not have any bind parameters or your database supports binding (without emulation), then you can call _Execute() directly.
-  Calling this function bypasses bind emulation. Debugging is still supported in _Execute().
+       If you do not have any bind parameters or your database supports binding (without emulation), then you can call _Execute() directly.
+       Calling this function bypasses bind emulation. Debugging is still supported in _Execute().
 
-  If you do not require debugging facilities nor emulated binding, and do not require a recordset to be returned, then you can call _query.
-  This is great for inserts, updates and deletes. Calling this function bypasses emulated binding, debugging, and recordset handling. Either
-  the resultid, true or false are returned by _query().
-  */
+       If you do not require debugging facilities nor emulated binding, and do not require a recordset to be returned, then you can call _query.
+       This is great for inserts, updates and deletes. Calling this function bypasses emulated binding, debugging, and recordset handling. Either
+       the resultid, TRUE or FALSE are returned by _query().
+       */
 
-  /**
+       /**
         * Inserts a record for $table from the array with field/value pairs $fields_values.
         *
         * @param       string          Table name
         * @param       array           Field values as key=>value pairs. Values will be escaped internally. Typically you would fill an array like "$insertFields" with 'fieldname'=>'value' and pass it to this function as argument.
+        * @param mixed    List/array of keys NOT to quote (eg. SQL functions)
         * @return      mixed           Result from handler, usually TRUE when success and FALSE on failure
         */
-  function exec_INSERTquery($table,$fields_values)     {
-
-    if ($this->debug)  $pt = t3lib_div::milliseconds();
-
-    // Do field mapping if needed:
-    $ORIG_tableName = $table;
-    if ($tableArray = $this->map_needMapping($table))  {
-
-      // Field mapping of array:
-      $fields_values = $this->map_assocArray($fields_values,$tableArray);
-
-      // Table name:
-      if ($this->mapping[$table]['mapTableName'])      {
-        $table = $this->mapping[$table]['mapTableName'];
-      }
-    }
-    // Select API:
-    $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
-    switch((string)$this->handlerCfg[$this->lastHandlerKey]['type'])   {
-      case 'native':
-      $this->lastQuery = $this->INSERTquery($table,$fields_values);
-      if(is_string($this->lastQuery)) {
-        $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']);
-      }
-      else {
-        $sqlResult = mysql_query($this->lastQuery[0], $this->handlerInstance[$this->lastHandlerKey]['link']);
-        foreach($this->lastQuery[1] as $field => $content) {
-          mysql_query('UPDATE '.$this->quoteFromTables($table).' SET '.$this->quoteFromTables($field).'='.$this->fullQuoteStr($content,$table).' WHERE '.$this->quoteWhereClause($where), $this->handlerInstance[$this->lastHandlerKey]['link']);
-        }
-      }
-      break;
-      case 'adodb':
-      // auto generate ID for auto_increment fields if not present (static import needs this!)
-      // should we check the table name here (static_*)?
-      if(isset($this->cache_autoIncFields[$table])) {
-        if(isset($fields_values[$this->cache_autoIncFields[$table]])) {
-          $new_id = $fields_values[$this->cache_autoIncFields[$table]];
-          if($table !== 'tx_dbal_debuglog') {
-            $this->handlerInstance[$this->lastHandlerKey]->last_insert_id = $new_id;
-          }
-        }
-        else {
-          $new_id = $this->handlerInstance[$this->lastHandlerKey]->GenID($table.'_'.$this->cache_autoIncFields[$table]);
-          $fields_values[$this->cache_autoIncFields[$table]] = $new_id;
-          if($table !== 'tx_dbal_debuglog') {
-            $this->handlerInstance[$this->lastHandlerKey]->last_insert_id = $new_id;
-          }
-        }
-      }
-
-      $this->lastQuery = $this->INSERTquery($table,$fields_values);
-      if(is_string($this->lastQuery)) {
-        $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery,false);
-      }
-      else {
-       $this->handlerInstance[$this->lastHandlerKey]->StartTrans();
-        $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery[0],false);
-        foreach($this->lastQuery[1] as $field => $content) {
-          if(empty($content)) continue;
-
-          if(isset($this->cache_autoIncFields[$table]) && isset($new_id)) {
-            $this->handlerInstance[$this->lastHandlerKey]->UpdateBlob($this->quoteFromTables($table),$field,$content,$this->quoteWhereClause($this->cache_autoIncFields[$table].'='.$new_id));
-          }
-          elseif(isset($this->cache_primaryKeys[$table])) {
-            $pks = explode(',', $this->cache_primaryKeys[$table]);
-            foreach ($pks as $pk) {
-              if(isset($fields_values[$pk]))
-              $where .= $pk.'='.$this->fullQuoteStr($fields_values[$pk], $table).' AND ';
-            }
-            $where = $this->quoteWhereClause($where.'1=1');
-            $this->handlerInstance[$this->lastHandlerKey]->UpdateBlob($this->quoteFromTables($table),$field,$content,$where);
-          }
-          else {
-                       $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans(false);
-            die('Could not update BLOB >>>> no WHERE clause found!'); // should never ever happen
-          }
-        }
-               $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans();
-      }
-      break;
-      case 'userdefined':
-      $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_INSERTquery($table,$fields_values);
-      break;
-    }
-
-    // Print errors:
-    if ($this->printErrors && $this->sql_error())      { debug(array($this->sql_error()));     }
-
-    # DEBUG:
-    if ($this->debug)  {
-      $this->debugHandler(
-      'exec_INSERTquery',
-      t3lib_div::milliseconds()-$pt,
-      array(
-      'handlerType' => $hType,
-      'args' => array($table,$fields_values),
-      'ORIG_tablename' => $ORIG_tableName
-      )
-      );
-    }
-    // Return output:
-    return $sqlResult;
-  }
-
-  /**
+       public function exec_INSERTquery($table, $fields_values, $no_quote_fields = '') {
+
+               if ($this->debug) {
+                       $pt = t3lib_div::milliseconds();
+               }
+
+                       // Do field mapping if needed:
+               $ORIG_tableName = $table;
+               if ($tableArray = $this->map_needMapping($table)) {
+
+                               // Field mapping of array:
+                       $fields_values = $this->map_assocArray($fields_values, $tableArray);
+
+                               // Table name:
+                       if ($this->mapping[$table]['mapTableName']) {
+                               $table = $this->mapping[$table]['mapTableName'];
+                       }
+               }
+                       // Select API:
+               $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
+               switch ((string)$this->handlerCfg[$this->lastHandlerKey]['type']) {
+                       case 'native':
+                               $this->lastQuery = $this->INSERTquery($table,$fields_values,$no_quote_fields);
+                               if (is_string($this->lastQuery)) {
+                                       $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']);
+                               } else {
+                                       $sqlResult = mysql_query($this->lastQuery[0], $this->handlerInstance[$this->lastHandlerKey]['link']);
+                                       foreach ($this->lastQuery[1] as $field => $content) {
+                                               mysql_query('UPDATE ' . $this->quoteFromTables($table) . ' SET ' . $this->quoteFromTables($field) . '=' . $this->fullQuoteStr($content, $table) . ' WHERE ' . $this->quoteWhereClause($where), $this->handlerInstance[$this->lastHandlerKey]['link']);
+                                       }
+                               }
+                               break;
+                       case 'adodb':
+                                       // auto generate ID for auto_increment fields if not present (static import needs this!)
+                                       // should we check the table name here (static_*)?
+                               if (isset($this->cache_autoIncFields[$table])) {
+                                       if (isset($fields_values[$this->cache_autoIncFields[$table]])) {
+                                               $new_id = $fields_values[$this->cache_autoIncFields[$table]];
+                                               if ($table != 'tx_dbal_debuglog') {
+                                                       $this->handlerInstance[$this->lastHandlerKey]->last_insert_id = $new_id;
+                                               }
+                                       } else {
+                                               $new_id = $this->handlerInstance[$this->lastHandlerKey]->GenID($table.'_'.$this->cache_autoIncFields[$table], $this->handlerInstance[$this->lastHandlerKey]->sequenceStart);
+                                               $fields_values[$this->cache_autoIncFields[$table]] = $new_id;
+                                               if ($table != 'tx_dbal_debuglog') {
+                                                       $this->handlerInstance[$this->lastHandlerKey]->last_insert_id = $new_id;
+                                               }
+                                       }
+                               }
+
+                               $this->lastQuery = $this->INSERTquery($table,$fields_values,$no_quote_fields);
+                               if (is_string($this->lastQuery)) {
+                                       $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery,FALSE);
+                               } else {
+                                       $this->handlerInstance[$this->lastHandlerKey]->StartTrans();
+                                       if (strlen($this->lastQuery[0])) {
+                                               $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery[0],FALSE);
+                                       }
+                                       if (is_array($this->lastQuery[1])) {
+                                               foreach ($this->lastQuery[1] as $field => $content) {
+                                                       if (empty($content)) continue;
+
+                                                       if (isset($this->cache_autoIncFields[$table]) && isset($new_id)) {
+                                                               $this->handlerInstance[$this->lastHandlerKey]->UpdateBlob($this->quoteFromTables($table),$field,$content,$this->quoteWhereClause($this->cache_autoIncFields[$table].'='.$new_id));
+                                                       } elseif (isset($this->cache_primaryKeys[$table])) {
+                                                               $where = '';
+                                                               $pks = explode(',', $this->cache_primaryKeys[$table]);
+                                                               foreach ($pks as $pk) {
+                                                                       if (isset($fields_values[$pk]))
+                                                                       $where .= $pk.'='.$this->fullQuoteStr($fields_values[$pk], $table).' AND ';
+                                                               }
+                                                               $where = $this->quoteWhereClause($where.'1=1');
+                                                               $this->handlerInstance[$this->lastHandlerKey]->UpdateBlob($this->quoteFromTables($table),$field,$content,$where);
+                                                       } else {
+                                                               $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans(FALSE);
+                                                               die('Could not update BLOB >>>> no WHERE clause found!'); // should never ever happen
+                                                       }
+                                               }
+                                       }
+                                       if (is_array($this->lastQuery[2])) {
+                                               foreach ($this->lastQuery[2] as $field => $content) {
+                                                       if (empty($content)) continue;
+
+                                                       if (isset($this->cache_autoIncFields[$table]) && isset($new_id)) {
+                                                               $this->handlerInstance[$this->lastHandlerKey]->UpdateClob($this->quoteFromTables($table),$field,$content,$this->quoteWhereClause($this->cache_autoIncFields[$table].'='.$new_id));
+                                                       } elseif (isset($this->cache_primaryKeys[$table])) {
+                                                               $where = '';
+                                                               $pks = explode(',', $this->cache_primaryKeys[$table]);
+                                                               foreach ($pks as $pk) {
+                                                                       if (isset($fields_values[$pk]))
+                                                                       $where .= $pk.'='.$this->fullQuoteStr($fields_values[$pk], $table).' AND ';
+                                                               }
+                                                               $where = $this->quoteWhereClause($where.'1=1');
+                                                               $this->handlerInstance[$this->lastHandlerKey]->UpdateClob($this->quoteFromTables($table),$field,$content,$where);
+                                                       } else {
+                                                               $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans(FALSE);
+                                                               die('Could not update CLOB >>>> no WHERE clause found!'); // should never ever happen
+                                                       }
+                                               }
+                                       }
+                                       $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans();
+                               }
+                               break;
+                       case 'userdefined':
+                               $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_INSERTquery($table,$fields_values,$no_quote_fields);
+                               break;
+               }
+
+               if ($this->printErrors && $this->sql_error()) {
+                       debug(array($this->lastQuery, $this->sql_error()));
+               }
+
+               if ($this->debug) {
+                       $this->debugHandler(
+                               'exec_INSERTquery',
+                               t3lib_div::milliseconds()-$pt,
+                               array(
+                                       'handlerType' => $hType,
+                                       'args' => array($table,$fields_values),
+                                       'ORIG_tablename' => $ORIG_tableName
+                               )
+                       );
+               }
+                       // Return output:
+               return $sqlResult;
+       }
+
+       /**
+        * Creates and executes an INSERT SQL-statement for $table with multiple rows.
+        * This method uses exec_INSERTquery() and is just a syntax wrapper to it.
+        *
+        * @param       string          Table name
+        * @param       array           Field names
+        * @param       array           Table rows. Each row should be an array with field values mapping to $fields
+        * @param       string/array            See fullQuoteArray()
+        * @return      mixed           Result from last handler, usually TRUE when success and FALSE on failure
+        */
+       public function exec_INSERTmultipleRows($table, array $fields, array $rows, $no_quote_fields = FALSE) {
+               if ((string)$this->handlerCfg[$this->lastHandlerKey]['type'] === 'native') {
+                       return parent::exec_INSERTmultipleRows($table, $fields, $rows, $no_quote_fields);
+               }
+
+               foreach ($rows as $row) {
+                       $fields_values = array();
+                       foreach ($fields as $key => $value) {
+                               $fields_values[$value] = $row[$key];
+                       }
+                       $res = $this->exec_INSERTquery($table, $fields_values, $no_quote_fields);
+               }
+
+               return $res;
+       }
+
+       /**
         * Updates a record from $table
         *
         * @param       string          Database tablename
         * @param       string          WHERE clause, eg. "uid=1". NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
         * @param       array           Field values as key=>value pairs. Values will be escaped internally. Typically you would fill an array like "$updateFields" with 'fieldname'=>'value' and pass it to this function as argument.
+        * @param mixed    List/array of keys NOT to quote (eg. SQL functions)
         * @return      mixed           Result from handler, usually TRUE when success and FALSE on failure
         */
-  function exec_UPDATEquery($table,$where,$fields_values)      {
-
-    if ($this->debug)  $pt = t3lib_div::milliseconds();
-
-    // Do table/field mapping:
-    $ORIG_tableName = $table;
-    if ($tableArray = $this->map_needMapping($table))  {
-
-      // Field mapping of array:
-      $fields_values = $this->map_assocArray($fields_values,$tableArray);
-
-      // Where clause table and field mapping:
-      $whereParts = $this->SQLparser->parseWhereClause($where);
-      $this->map_sqlParts($whereParts,$tableArray[0]['table']);
-      $where = $this->SQLparser->compileWhereClause($whereParts);
-
-      // Table name:
-      if ($this->mapping[$table]['mapTableName'])      {
-        $table = $this->mapping[$table]['mapTableName'];
-      }
-    }
-
-    // Select API
-    $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
-    switch((string)$this->handlerCfg[$this->lastHandlerKey]['type'])   {
-      case 'native':
-      $this->lastQuery = $this->UPDATEquery($table,$where,$fields_values);
-      if(is_string($this->lastQuery)) {
-        $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']);
-      }
-      else {
-        $sqlResult = mysql_query($this->lastQuery[0], $this->handlerInstance[$this->lastHandlerKey]['link']);
-        foreach($this->lastQuery[1] as $field => $content) {
-          mysql_query('UPDATE '.$this->quoteFromTables($table).' SET '.$this->quoteFromTables($field).'='.$this->fullQuoteStr($content,$table).' WHERE '.$this->quoteWhereClause($where), $this->handlerInstance[$this->lastHandlerKey]['link']);
-        }
-      }
-      break;
-      case 'adodb':
-      $this->lastQuery = $this->UPDATEquery($table,$where,$fields_values);
-      if(is_string($this->lastQuery)) {
-             $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery,false);
-      } else {
-               $this->handlerInstance[$this->lastHandlerKey]->StartTrans();
-        $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery[0],false);
-        foreach($this->lastQuery[1] as $field => $content) {
-          $this->handlerInstance[$this->lastHandlerKey]->UpdateBlob($this->quoteFromTables($table),$field,$content,$this->quoteWhereClause($where));
-        }
-               $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans();
-      }
-      break;
-      case 'userdefined':
-      $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_UPDATEquery($table,$where,$fields_values);
-      break;
-    }
-
-    // Print errors:
-    if ($this->printErrors && $this->sql_error())      { debug(array($this->sql_error()));     }
-
-    # DEBUG:
-    if ($this->debug)  {
-      $this->debugHandler(
-      'exec_UPDATEquery',
-      t3lib_div::milliseconds()-$pt,
-      array(
-      'handlerType' => $hType,
-      'args' => array($table,$where, $fields_values),
-      'ORIG_from_table' => $ORIG_tableName
-      )
-      );
-    }
-
-    // Return result:
-    return $sqlResult;
-  }
-
-  /**
+       public function exec_UPDATEquery($table,$where,$fields_values,$no_quote_fields = '') {
+               if ($this->debug) {
+                       $pt = t3lib_div::milliseconds();
+               }
+
+                       // Do table/field mapping:
+               $ORIG_tableName = $table;
+               if ($tableArray = $this->map_needMapping($table)) {
+
+                               // Field mapping of array:
+                       $fields_values = $this->map_assocArray($fields_values,$tableArray);
+
+                               // Where clause table and field mapping:
+                       $whereParts = $this->SQLparser->parseWhereClause($where);
+                       $this->map_sqlParts($whereParts,$tableArray[0]['table']);
+                       $where = $this->SQLparser->compileWhereClause($whereParts, FALSE);
+
+                               // Table name:
+                       if ($this->mapping[$table]['mapTableName']) {
+                               $table = $this->mapping[$table]['mapTableName'];
+                       }
+               }
+
+                       // Select API
+               $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
+               switch ((string)$this->handlerCfg[$this->lastHandlerKey]['type']) {
+                       case 'native':
+                               $this->lastQuery = $this->UPDATEquery($table,$where,$fields_values,$no_quote_fields);
+                               if (is_string($this->lastQuery)) {
+                                       $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']);
+                               }
+                               else {
+                                       $sqlResult = mysql_query($this->lastQuery[0], $this->handlerInstance[$this->lastHandlerKey]['link']);
+                                       foreach ($this->lastQuery[1] as $field => $content) {
+                                               mysql_query('UPDATE '.$this->quoteFromTables($table).' SET '.$this->quoteFromTables($field).'='.$this->fullQuoteStr($content,$table).' WHERE '.$this->quoteWhereClause($where), $this->handlerInstance[$this->lastHandlerKey]['link']);
+                                       }
+                               }
+                       break;
+                       case 'adodb':
+                               $this->lastQuery = $this->UPDATEquery($table,$where,$fields_values,$no_quote_fields);
+                               if (is_string($this->lastQuery)) {
+                                       $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery,FALSE);
+                               } else {
+                                       $this->handlerInstance[$this->lastHandlerKey]->StartTrans();
+                                       if (strlen($this->lastQuery[0])) {
+                                               $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery[0],FALSE);
+                                       }
+                                       if (is_array($this->lastQuery[1])) {
+                                               foreach ($this->lastQuery[1] as $field => $content) {
+                                                       $this->handlerInstance[$this->lastHandlerKey]->UpdateBlob($this->quoteFromTables($table),$field,$content,$this->quoteWhereClause($where));
+                                               }
+                                       }
+                                       if (is_array($this->lastQuery[2])) {
+                                               foreach ($this->lastQuery[2] as $field => $content) {
+                                                       $this->handlerInstance[$this->lastHandlerKey]->UpdateClob($this->quoteFromTables($table),$field,$content,$this->quoteWhereClause($where));
+                                               }
+                                       }
+                                       $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans();
+                               }
+                               break;
+                       case 'userdefined':
+                               $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_UPDATEquery($table,$where,$fields_values,$no_quote_fields);
+                               break;
+               }
+
+               if ($this->printErrors && $this->sql_error()) {
+                       debug(array($this->lastQuery, $this->sql_error()));
+               }
+
+               if ($this->debug) {
+                       $this->debugHandler(
+                               'exec_UPDATEquery',
+                               t3lib_div::milliseconds()-$pt,
+                               array(
+                                       'handlerType' => $hType,
+                                       'args' => array($table,$where, $fields_values),
+                                       'ORIG_from_table' => $ORIG_tableName
+                               )
+                       );
+               }
+
+                       // Return result:
+               return $sqlResult;
+       }
+
+       /**
         * Deletes records from table
         *
         * @param       string          Database tablename
         * @param       string          WHERE clause, eg. "uid=1". NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
         * @return      mixed           Result from handler
         */
-  function exec_DELETEquery($table,$where)     {
-
-    if ($this->debug)  $pt = t3lib_div::milliseconds();
-
-    // Do table/field mapping:
-    $ORIG_tableName = $table;
-    if ($tableArray = $this->map_needMapping($table))  {
-
-      // Where clause:
-      $whereParts = $this->SQLparser->parseWhereClause($where);
-      $this->map_sqlParts($whereParts,$tableArray[0]['table']);
-      $where = $this->SQLparser->compileWhereClause($whereParts);
-
-      // Table name:
-      if ($this->mapping[$table]['mapTableName'])      {
-        $table = $this->mapping[$table]['mapTableName'];
-      }
-    }
-
-    // Select API
-    $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
-    switch((string)$this->handlerCfg[$this->lastHandlerKey]['type'])   {
-      case 'native':
-      $this->lastQuery = $this->DELETEquery($table,$where);
-      $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']);
-      break;
-      case 'adodb':
-      $this->lastQuery = $this->DELETEquery($table,$where);
-      $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery,false);
-      break;
-      case 'userdefined':
-      $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_DELETEquery($table,$where);
-      break;
-    }
-
-    // Print errors:
-    if ($this->printErrors && $this->sql_error())      { debug(array($this->sql_error()));     }
-
-    # DEBUG:
-    if ($this->debug)  {
-      $this->debugHandler(
-      'exec_DELETEquery',
-      t3lib_div::milliseconds()-$pt,
-      array(
-      'handlerType' => $hType,
-      'args' => array($table,$where),
-      'ORIG_from_table' => $ORIG_tableName
-      )
-      );
-    }
-
-    // Return result:
-    return $sqlResult;
-  }
-
-  /**
+       public function exec_DELETEquery($table, $where) {
+               if ($this->debug) {
+                       $pt = t3lib_div::milliseconds();
+               }
+
+                       // Do table/field mapping:
+               $ORIG_tableName = $table;
+               if ($tableArray = $this->map_needMapping($table)) {
+
+                               // Where clause:
+                       $whereParts = $this->SQLparser->parseWhereClause($where);
+                       $this->map_sqlParts($whereParts,$tableArray[0]['table']);
+                       $where = $this->SQLparser->compileWhereClause($whereParts, FALSE);
+
+                               // Table name:
+                       if ($this->mapping[$table]['mapTableName']) {
+                               $table = $this->mapping[$table]['mapTableName'];
+                       }
+               }
+
+                       // Select API
+               $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
+               switch ((string)$this->handlerCfg[$this->lastHandlerKey]['type']) {
+                       case 'native':
+                               $this->lastQuery = $this->DELETEquery($table,$where);
+                               $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']);
+                               break;
+                       case 'adodb':
+                               $this->lastQuery = $this->DELETEquery($table,$where);
+                               $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery,FALSE);
+                               break;
+                       case 'userdefined':
+                               $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_DELETEquery($table,$where);
+                               break;
+               }
+
+               if ($this->printErrors && $this->sql_error()) {
+                       debug(array($this->lastQuery, $this->sql_error()));
+               }
+
+               if ($this->debug) {
+                       $this->debugHandler(
+                               'exec_DELETEquery',
+                               t3lib_div::milliseconds()-$pt,
+                               array(
+                                       'handlerType' => $hType,
+                                       'args' => array($table,$where),
+                                       'ORIG_from_table' => $ORIG_tableName
+                               )
+                       );
+               }
+
+                       // Return result:
+               return $sqlResult;
+       }
+
+       /**
         * Selects records from Data Source
         *
         * @param       string $select_fields List of fields to select from the table. This is what comes right after "SELECT ...". Required value.
@@ -598,231 +683,399 @@ class ux_t3lib_DB extends t3lib_DB {
         * @param       string $limit Optional LIMIT value ([begin,]max), if none, supply blank string.
         * @return      mixed           Result from handler. Typically object from DBAL layers.
         */
-  function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='')        {
-
-    if ($this->debug)  $pt = t3lib_div::milliseconds();
-
-    // Map table / field names if needed:
-    $ORIG_tableName = $from_table;     // Saving table names in $ORIG_from_table since $from_table is transformed beneath:
-    if ($tableArray = $this->map_needMapping($ORIG_tableName)) {
-      $this->map_remapSELECTQueryParts($select_fields,$from_table,$where_clause,$groupBy,$orderBy);    // Variables passed by reference!
-    }
-
-    // Get handler key and select API:
-    $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
-    $hType = (string)$this->handlerCfg[$this->lastHandlerKey]['type'];
-    switch($hType)     {
-      case 'native':
-      $this->lastQuery = $this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit);
-      $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']);
-      $this->resourceIdToTableNameMap[(string)$sqlResult] = $ORIG_tableName;
-      break;
-      case 'adodb':
-      if ($limit)      {
-        $splitLimit = t3lib_div::intExplode(',',$limit);               // Splitting the limit values:
-        if ($splitLimit[1])    {       // If there are two parameters, do mapping differently than otherwise:
-        $numrows = $splitLimit[1];
-        $offset = $splitLimit[0];
-        } else {
-          $numrows = $splitLimit[0];
-          $offset = 0;
-        }
-
-                               $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->SelectLimit($this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy), $numrows, $offset);
-        $this->lastQuery = $sqlResult->sql;
-      } else {
-        $this->lastQuery = $this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit);
-        $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_Execute($this->lastQuery);
-      }
-      $sqlResult->TYPO3_DBAL_handlerType = 'adodb';    // Setting handler type in result object (for later recognition!)
-      $sqlResult->TYPO3_DBAL_tableList = $ORIG_tableName;
-      break;
-      case 'userdefined':
-      $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit);
-      if (is_object($sqlResult))       {
-        $sqlResult->TYPO3_DBAL_handlerType = 'userdefined';    // Setting handler type in result object (for later recognition!)
-        $sqlResult->TYPO3_DBAL_tableList = $ORIG_tableName;
-      }
-      break;
-    }
-
-    // Print errors:
-    if ($this->printErrors && $this->sql_error())      { debug(array($this->sql_error()));     }
-
-    # DEBUG:
-    if ($this->debug)  {
-      $this->debugHandler(
-      'exec_SELECTquery',
-      t3lib_div::milliseconds()-$pt,
-      array(
-      'handlerType' => $hType,
-      'args' => array($from_table,$select_fields,$where_clause,$groupBy,$orderBy,$limit),
-      'ORIG_from_table' => $ORIG_tableName
-      )
-      );
-    }
-
-    // Return result handler.
-    return $sqlResult;
-  }
-
-
-
-  /**************************************
-  *
-  * Query building
-  *
-  **************************************/
-
-  /**
+       public function exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '') {
+               if ($this->debug) {
+                       $pt = t3lib_div::milliseconds();
+               }
+
+                       // Map table / field names if needed:
+               $ORIG_tableName = $from_table;  // Saving table names in $ORIG_from_table since $from_table is transformed beneath:
+               if ($tableArray = $this->map_needMapping($ORIG_tableName)) {
+                       $this->map_remapSELECTQueryParts($select_fields,$from_table,$where_clause,$groupBy,$orderBy);   // Variables passed by reference!
+               }
+
+                       // Get handler key and select API:
+               $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
+               $hType = (string)$this->handlerCfg[$this->lastHandlerKey]['type'];
+               switch ($hType) {
+                       case 'native':
+                               $this->lastQuery = $this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit);
+                               $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']);
+                               $this->resourceIdToTableNameMap[(string)$sqlResult] = $ORIG_tableName;
+                               break;
+                       case 'adodb':
+                               if ($limit != '') {
+                                       $splitLimit = t3lib_div::intExplode(',', $limit);               // Splitting the limit values:
+                                       if ($splitLimit[1]) {   // If there are two parameters, do mapping differently than otherwise:
+                                               $numrows = $splitLimit[1];
+                                               $offset = $splitLimit[0];
+                                       } else {
+                                               $numrows = $splitLimit[0];
+                                               $offset = 0;
+                                       }
+
+                                       $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->SelectLimit($this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy), $numrows, $offset);
+                                       $this->lastQuery = $sqlResult->sql;
+                               } else {
+                                       $this->lastQuery = $this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy);
+                                       $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_Execute($this->lastQuery);
+                               }
+
+                               $sqlResult->TYPO3_DBAL_handlerType = 'adodb';   // Setting handler type in result object (for later recognition!)
+                               $sqlResult->TYPO3_DBAL_tableList = $ORIG_tableName;
+                               break;
+                       case 'userdefined':
+                               $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit);
+                               if (is_object($sqlResult)) {
+                                       $sqlResult->TYPO3_DBAL_handlerType = 'userdefined';     // Setting handler type in result object (for later recognition!)
+                                       $sqlResult->TYPO3_DBAL_tableList = $ORIG_tableName;
+                               }
+                               break;
+               }
+
+               if ($this->printErrors && $this->sql_error()) {
+                       debug(array($this->lastQuery, $this->sql_error()));
+               }
+
+               if ($this->debug) {
+                       $this->debugHandler(
+                               'exec_SELECTquery',
+                               t3lib_div::milliseconds()-$pt,
+                               array(
+                                       'handlerType' => $hType,
+                                       'args' => array($from_table,$select_fields,$where_clause,$groupBy,$orderBy,$limit),
+                                       'ORIG_from_table' => $ORIG_tableName
+                               )
+                       );
+               }
+
+                       // Return result handler.
+               return $sqlResult;
+       }
+
+       /**
+        * Truncates a table.
+        * 
+        * @param       string          Database tablename
+        * @return      mixed           Result from handler
+        */
+       public function exec_TRUNCATEquery($table) {
+               if ($this->debug) {
+                       $pt = t3lib_div::milliseconds();
+               }
+
+                       // Do table/field mapping:
+               $ORIG_tableName = $table;
+               if ($tableArray = $this->map_needMapping($table)) {
+                               // Table name:
+                       if ($this->mapping[$table]['mapTableName']) {
+                               $table = $this->mapping[$table]['mapTableName'];
+                       }
+               }
+
+                       // Select API
+               $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
+               switch ((string)$this->handlerCfg[$this->lastHandlerKey]['type']) {
+                       case 'native':
+                               $this->lastQuery = $this->TRUNCATEquery($table);
+                               $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']);
+                               break;
+                       case 'adodb':
+                               $this->lastQuery = $this->TRUNCATEquery($table);
+                               $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery, FALSE);
+                               break;
+                       case 'userdefined':
+                               $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_TRUNCATEquery($table,$where);
+                               break;
+               }
+
+               if ($this->printErrors && $this->sql_error()) {
+                       debug(array($this->lastQuery, $this->sql_error()));
+               }
+
+               if ($this->debug) {
+                       $this->debugHandler(
+                               'exec_TRUNCATEquery',
+                               t3lib_div::milliseconds() - $pt,
+                               array(
+                                       'handlerType' => $hType,
+                                       'args' => array($table),
+                                       'ORIG_from_table' => $ORIG_tableName
+                               )
+                       );
+               }
+
+                       // Return result:
+               return $sqlResult;
+       }
+
+       /**
+        * Executes a query.
+        * EXPERIMENTAL since TYPO3 4.4.
+        * 
+        * @param array $queryParts SQL parsed by method parseSQL() of t3lib_sqlparser
+        * @return pointer Result pointer / DBAL object
+        * @see ux_t3lib_db::sql_query()
+        */
+       protected function exec_query(array $queryParts) {
+               switch ($queryParts['type']) {
+                       case 'SELECT':
+                               $selectFields = $this->SQLparser->compileFieldList($queryParts['SELECT']);
+                               $fromTables = $this->SQLparser->compileFromTables($queryParts['FROM']);
+                               $whereClause = isset($queryParts['WHERE']) ? $this->SQLparser->compileWhereClause($queryParts['WHERE']) : '1=1';
+                               $groupBy = isset($queryParts['GROUPBY']) ? $this->SQLparser->compileWhereClause($queryParts['GROUPBY']) : '';
+                               $orderBy = isset($queryParts['GROUPBY']) ? $this->SQLparser->compileWhereClause($queryParts['ORDERBY']) : '';
+                               $limit = isset($queryParts['LIMIT']) ? $this->SQLparser->compileWhereClause($queryParts['LIMIT']) : '';
+                               return $this->exec_SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy, $limit);
+
+                       case 'UPDATE':
+                               $table = $queryParts['TABLE'];
+                               $fields = array();
+                               foreach ($components['FIELDS'] as $fN => $fV) {
+                                       $fields[$fN] = $fV[0];
+                               }
+                               $whereClause = isset($queryParts['WHERE']) ? $this->SQLparser->compileWhereClause($queryParts['WHERE']) : '1=1';
+                               return $this->exec_UPDATEquery($table, $whereClause, $fields);
+
+                       case 'INSERT':
+                               $table = $queryParts['TABLE'];
+                               $values = array();
+                               if (isset($queryParts['VALUES_ONLY']) && is_array($queryParts['VALUES_ONLY'])) {
+                                       $fields = $GLOBALS['TYPO3_DB']->cache_fieldType[$table];
+                                       $fc = 0;
+                                       foreach ($fields as $fn => $fd) {
+                                               $values[$fn] = $queryParts['VALUES_ONLY'][$fc++][0];
+                                       }
+                               } else {
+                                       foreach ($queryParts['FIELDS'] as $fN => $fV) {
+                                               $values[$fN] = $fV[0];
+                                       }
+                               }
+                               return $this->exec_INSERTquery($table, $values);
+                               
+                       case 'DELETE':
+                               $table = $queryParts['TABLE'];
+                               $whereClause = isset($queryParts['WHERE']) ? $this->SQLparser->compileWhereClause($queryParts['WHERE']) : '1=1';
+                               return $this->exec_DELETEquery($table, $whereClause);
+
+                       case 'TRUNCATETABLE':
+                               $table = $queryParts['TABLE'];
+                               return $this->exec_TRUNCATEquery($table);
+               }
+       }
+
+
+
+       /**************************************
+       *
+       * Query building
+       *
+       **************************************/
+
+       /**
         * Creates an INSERT SQL-statement for $table from the array with field/value pairs $fields_values.
         * Usage count/core: 4
         *
         * @param       string          See exec_INSERTquery()
         * @param       array           See exec_INSERTquery()
-        * @return      string          Full SQL query for INSERT (unless $fields_values does not contain any elements in which case it will be false)
-        * @depreciated                 use exec_INSERTquery() instead if possible!
-        */
-  function INSERTquery($table,$fields_values)  {
-    // Table and fieldnames should be "SQL-injection-safe" when supplied to this function (contrary to values in the arrays which may be insecure).
-    if (is_array($fields_values) && count($fields_values))     {
-      $blobfields = array();
-      $nArr = array();
-      foreach($fields_values as $k => $v)      {
-        if($this->sql_field_metatype($table,$k) == 'B') {
-          /* // is this really needed for Oracle?
-          if($this->handlerInstance[$this->lastHandlerKey]->databaseType == 'oci8')
-                                       $nArr[$this->quoteFieldNames($k)] = 'empty_blob()';
-          else
-                                       $nArr[$this->quoteFieldNames($k)] = 'null';
-          */
-                                       $nArr[$this->quoteFieldNames($k)] = 'null';
+        * @param mixed         See exec_INSERTquery()
+        * @return      mixed           Full SQL query for INSERT as string or array (unless $fields_values does not contain any elements in which case it will be FALSE). If BLOB fields will be affected and one is not running the native type, an array will be returned, where 0 => plain SQL, 1 => fieldname/value pairs of BLOB fields
+        */
+       public function INSERTquery($table, $fields_values, $no_quote_fields = '') {
+                       // Table and fieldnames should be "SQL-injection-safe" when supplied to this function (contrary to values in the arrays which may be insecure).
+               if (is_array($fields_values) && count($fields_values)) {
+
+                       if (is_string($no_quote_fields)) {
+                               $no_quote_fields = explode(',', $no_quote_fields);
+                       } elseif (!is_array($no_quote_fields)) {
+                               $no_quote_fields = array();
+                       }
+
+                       $blobfields = array();
+                       $nArr = array();
+                       foreach ($fields_values as $k => $v) {
+                               if (!$this->runningNative() && $this->sql_field_metatype($table, $k) == 'B') {
+                                               // we skip the field in the regular INSERT statement, it is only in blobfields
                                        $blobfields[$this->quoteFieldNames($k)] = $v;
-        }
-        else {
-          // Add slashes old-school:
-          // cast numerical values
-          $mt = $this->sql_field_metatype($table,$k);
-          $v = (($mt{0}=='I')||($mt{0}=='F')) ? (int)$v : $v;
-
-                                       $nArr[$this->quoteFieldNames($k)] = $this->fullQuoteStr($v, $table);
-        }
-      }
-      if(((string)$this->handlerCfg[$this->lastHandlerKey]['type']!=='native') && count($blobfields)) {
-        $query[0] = 'INSERT INTO '.$this->quoteFromTables($table).'
-                               (
-                                       '.implode(',
-                                       ',array_keys($nArr)).'
-                               ) VALUES (
-                                       '.implode(',
-                                       ',$nArr).'
-                               )';
-        $query[1] = $blobfields;
-        if ($this->debugOutput) $this->debug_lastBuiltQuery = $query[0];
-      }
-      else {
-        $query = 'INSERT INTO '.$this->quoteFromTables($table).'
+                               } elseif (!$this->runningNative() && $this->sql_field_metatype($table, $k) == 'XL') {
+                                               // we skip the field in the regular INSERT statement, it is only in clobfields
+                                       $clobfields[$this->quoteFieldNames($k)] = $v;
+                               } else {
+                                               // Add slashes old-school:
+                                               // cast numerical values
+                                       $mt = $this->sql_field_metatype($table, $k);
+                                       if ($mt{0} == 'I') {
+                                               $v = (int)$v;
+                                       } else if ($mt{0} == 'F') {
+                                               $v = (double)$v;
+                                       }
+
+                                       $nArr[$this->quoteFieldNames($k)] = (!in_array($k,$no_quote_fields)) ? $this->fullQuoteStr($v, $table) : $v;
+                               }
+                       }
+
+                       if (count($blobfields) || count($clobfields)) {
+                               if (count($nArr)) {
+                                       $query[0] = 'INSERT INTO ' . $this->quoteFromTables($table) . '
+                                       (
+                                               ' . implode(',
+                                               ', array_keys($nArr)) . '
+                                       ) VALUES (
+                                               ' . implode(',
+                                               ', $nArr) . '
+                                       )';
+                               }
+                               if (count($blobfields)) $query[1] = $blobfields;
+                               if (count($clobfields)) $query[2] = $clobfields;
+                               if ($this->debugOutput || $this->store_lastBuiltQuery) $this->debug_lastBuiltQuery = $query[0];
+                       } else {
+                               $query = 'INSERT INTO '.$this->quoteFromTables($table).'
                                (
-                                       '.implode(',
-                                       ',array_keys($nArr)).'
+                                       ' . implode(',
+                                       ', array_keys($nArr)) . '
                                ) VALUES (
-                                       '.implode(',
-                                       ',$nArr).'
+                                       ' . implode(',
+                                       ', $nArr) . '
                                )';
 
-        if ($this->debugOutput) $this->debug_lastBuiltQuery = $query;
-      }
+                               if ($this->debugOutput || $this->store_lastBuiltQuery) $this->debug_lastBuiltQuery = $query;
+                       }
+
+                       return $query;
+               }
+       }
+
+       /**
+        * Creates an INSERT SQL-statement for $table with multiple rows.
+        * This method will create multiple INSERT queries concatenated with ';'
+        *
+        * @param       string          Table name
+        * @param       array           Field names
+        * @param       array           Table rows. Each row should be an array with field values mapping to $fields
+        * @param       string/array            See fullQuoteArray()
+        * @return      array           Full SQL query for INSERT as array of strings (unless $fields_values does not contain any elements in which case it will be FALSE). If BLOB fields will be affected and one is not running the native type, an array will be returned for each row, where 0 => plain SQL, 1 => fieldname/value pairs of BLOB fields.
+        */
+       public function INSERTmultipleRows($table, array $fields, array $rows, $no_quote_fields = FALSE) {
+               if ((string)$this->handlerCfg[$this->lastHandlerKey]['type'] === 'native') {
+                       return parent::INSERTmultipleRows($table, $fields, $rows, $no_quote_fields);
+               }
+
+               $result = array();
+
+               foreach ($rows as $row) {
+                       $fields_values = array();
+                       foreach ($fields as $key => $value) {
+                               $fields_values[$value] = $row[$key];
+                       }
+                       $rowQuery = $this->INSERTquery($table, $fields_values, $no_quote_fields);
+                       if (is_array($rowQuery)) {
+                               $result[] = $rowQuery;
+                       } else {
+                               $result[][0] = $rowQuery;
+                       }
+               }
 
-      return $query;
-    }
-  }
+               return $result;
+       }
 
-  /**
+       /**
         * Creates an UPDATE SQL-statement for $table where $where-clause (typ. 'uid=...') from the array with field/value pairs $fields_values.
         * Usage count/core: 6
         *
         * @param       string          See exec_UPDATEquery()
         * @param       string          See exec_UPDATEquery()
         * @param       array           See exec_UPDATEquery()
-        * @return      string          Full SQL query for UPDATE (unless $fields_values does not contain any elements in which case it will be false)
-        * @depreciated                 use exec_UPDATEquery() instead if possible!
-        */
-  function UPDATEquery($table,$where,$fields_values)   {
-    // Table and fieldnames should be "SQL-injection-safe" when supplied to this function (contrary to values in the arrays which may be insecure).
-    if (is_string($where))     {
-      if (is_array($fields_values) && count($fields_values))   {
-        $blobfields = array();
-        $nArr = array();
-        foreach($fields_values as $k => $v)    {
-          if($this->sql_field_metatype($table,$k) == 'B') {
-            // do we need empty_blob() for Oracle? see also INSERTquery()
-                                               $nArr[] = $this->quoteFieldNames($k).'=NULL';
+        * @param mixed         See exec_UPDATEquery()
+        * @return      mixed           Full SQL query for UPDATE as string or array (unless $fields_values does not contain any elements in which case it will be FALSE). If BLOB fields will be affected and one is not running the native type, an array will be returned, where 0 => plain SQL, 1 => fieldname/value pairs of BLOB fields
+        */
+       public function UPDATEquery($table, $where, $fields_values, $no_quote_fields = '') {
+                       // Table and fieldnames should be "SQL-injection-safe" when supplied to this function (contrary to values in the arrays which may be insecure).
+               if (is_string($where)) {
+                       if (is_array($fields_values) && count($fields_values)) {
+
+                               if (is_string($no_quote_fields)) {
+                                       $no_quote_fields = explode(',', $no_quote_fields);
+                               } elseif (!is_array($no_quote_fields)) {
+                                       $no_quote_fields = array();
+                               }
+
+                               $blobfields = array();
+                               $nArr = array();
+                               foreach ($fields_values as $k => $v) {
+                                       if (!$this->runningNative() && $this->sql_field_metatype($table, $k) == 'B') {
+                                                       // we skip the field in the regular UPDATE statement, it is only in blobfields
                                                $blobfields[$this->quoteFieldNames($k)] = $v;
-          }
-          else {
-            // Add slashes old-school:
-            // cast numeric values
-            $mt = $this->sql_field_metatype($table,$k);
-            $v = (($mt{0}=='I')||($mt{0}=='F')) ? (int)$v : $v;
-                                               $nArr[] = $this->quoteFieldNames($k).'='.$this->fullQuoteStr($v, $table);
-          }
-        }
-      }
-
-      if(count($blobfields)) {
-        $query[0] = 'UPDATE '.$this->quoteFromTables($table).'
-                                       SET
-                                               '.implode(',
-                                               ',$nArr).
-        (strlen($where)>0 ? '
-                                       WHERE
-                                               '.$this->quoteWhereClause($where) : '');
-        $query[1] = $blobfields;
-        if ($this->debugOutput) $this->debug_lastBuiltQuery = $query[0];
-      }
-      else {
-        $query = 'UPDATE '.$this->quoteFromTables($table).'
+                                       } elseif (!$this->runningNative() && $this->sql_field_metatype($table, $k) == 'XL') {
+                                                               // we skip the field in the regular UPDATE statement, it is only in clobfields
+                                                       $clobfields[$this->quoteFieldNames($k)] = $v;
+                                       } else {
+                                                       // Add slashes old-school:
+                                                       // cast numeric values
+                                               $mt = $this->sql_field_metatype($table, $k);
+                                               if ($mt{0} == 'I') {
+                                                       $v = (int)$v;
+                                               } else if ($mt{0} == 'F') {
+                                                       $v = (double)$v;
+                                               }
+                                               $nArr[] = $this->quoteFieldNames($k) . '=' . ((!in_array($k, $no_quote_fields)) ? $this->fullQuoteStr($v, $table) : $v);
+                                       }
+                               }
+
+                               if (count($blobfields) || count($clobfields)) {
+                                       if (count($nArr)) {
+                                               $query[0] = 'UPDATE '.$this->quoteFromTables($table).'
+                                               SET
+                                                       '.implode(',
+                                                       ',$nArr).
+                                                       (strlen($where)>0 ? '
+                                               WHERE
+                                                       '.$this->quoteWhereClause($where) : '');
+                                       }
+                                       if (count($blobfields)) $query[1] = $blobfields;
+                                       if (count($clobfields)) $query[2] = $clobfields;
+                                       if ($this->debugOutput || $this->store_lastBuiltQuery) $this->debug_lastBuiltQuery = $query[0];
+                               } else {
+                                       $query = 'UPDATE '.$this->quoteFromTables($table).'
                                        SET
                                                '.implode(',
                                                ',$nArr).
-        (strlen($where)>0 ? '
+                                               (strlen($where)>0 ? '
                                        WHERE
                                                '.$this->quoteWhereClause($where) : '');
 
-        if ($this->debugOutput) $this->debug_lastBuiltQuery = $query;
-      }
+                                               if ($this->debugOutput || $this->store_lastBuiltQuery) $this->debug_lastBuiltQuery = $query;
+                               }
 
-      return $query;
-    }
-    else {
-      die('<strong>TYPO3 Fatal Error:</strong> "Where" clause argument for UPDATE query was not a string in $this->UPDATEquery() !');
-    }
-  }
+                               return $query;
+                       }
+               } else {
+                       die('<strong>TYPO3 Fatal Error:</strong> "Where" clause argument for UPDATE query was not a string in $this->UPDATEquery() !');
+               }
+       }
 
-  /**
+       /**
         * Creates a DELETE SQL-statement for $table where $where-clause
         * Usage count/core: 3
         *
         * @param       string          See exec_DELETEquery()
         * @param       string          See exec_DELETEquery()
         * @return      string          Full SQL query for DELETE
-        * @depreciated                 use exec_DELETEquery() instead if possible!
         */
-  function DELETEquery($table,$where)  {
-    if (is_string($where))     {
-      $table = $this->quoteFromTables($table);
-      $where = $this->quoteWhereClause($where);
+       public function DELETEquery($table, $where) {
+               if (is_string($where)) {
+                       $table = $this->quoteFromTables($table);
+                       $where = $this->quoteWhereClause($where);
 
-      $query = parent::DELETEquery($table, $where);
+                       $query = parent::DELETEquery($table, $where);
 
-      if ($this->debugOutput) $this->debug_lastBuiltQuery = $query;
-      return $query;
-    } else {
-      die('<strong>TYPO3 Fatal Error:</strong> "Where" clause argument for DELETE query was not a string in $this->DELETEquery() !');
-    }
-  }
+                       if ($this->debugOutput || $this->store_lastBuiltQuery) $this->debug_lastBuiltQuery = $query;
+                       return $query;
+               } else {
+                       die('<strong>TYPO3 Fatal Error:</strong> "Where" clause argument for DELETE query was not a string in $this->DELETEquery() !');
+               }
+       }
 
-  /**
+       /**
         * Creates a SELECT SQL-statement
         * Usage count/core: 11
         *
@@ -833,40 +1086,70 @@ class ux_t3lib_DB extends t3lib_DB {
         * @param       string          See exec_SELECTquery()
         * @param       string          See exec_SELECTquery()
         * @return      string          Full SQL query for SELECT
-        * @depreciated                 use exec_SELECTquery() instead if possible!
         */
-  function SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='')     {
-
+       public function SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '') {
                $select_fields = $this->quoteFieldNames($select_fields);
-    $from_table = $this->quoteFromTables($from_table);
-    $where_clause = $this->quoteWhereClause($where_clause);
-    $groupBy = $this->quoteGroupBy($groupBy);
-    $orderBy = $this->quoteOrderBy($orderBy);
+               $from_table = $this->quoteFromTables($from_table);
+               $where_clause = $this->quoteWhereClause($where_clause);
+               $groupBy = $this->quoteGroupBy($groupBy);
+               $orderBy = $this->quoteOrderBy($orderBy);
 
-    // call parent method to build actual query
-    $query = parent::SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit);
+                       // Call parent method to build actual query
+               $query = parent::SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit);
 
-    if ($this->debugOutput) $this->debug_lastBuiltQuery = $query;
+               if ($this->debugOutput || $this->store_lastBuiltQuery) $this->debug_lastBuiltQuery = $query;
+
+               return $query;
+       }
+
+       /**
+        * Creates a TRUNCATE TABLE SQL-statement
+        * 
+        * @param       string          See exec_TRUNCATEquery()
+        * @return      string          Full SQL query for TRUNCATE TABLE
+        */
+       public function TRUNCATEquery($table) {
+               $table = $this->quoteFromTables($table);
+
+                       // Call parent method to build actual query
+               $query = parent::TRUNCATEquery($table);
+
+               if ($this->debugOutput || $this->store_lastBuiltQuery) {
+                       $this->debug_lastBuiltQuery = $query;
+               }
+
+               return $query;
+       }
 
-    return $query;
-  }
 
+       /**************************************
+       *
+       * Functions for quoting table/field names
+       *
+       **************************************/
 
-  /**************************************
-  *
-  * Functions for quoting table/field names
-  *
-  **************************************/
+       /**
+        * Quotes components of a SELECT subquery.
+        * 
+        * @param array $components     Array of SQL query components
+        * @return array
+        */
+       protected function quoteSELECTsubquery(array $components) {
+               $components['SELECT'] = $this->_quoteFieldNames($components['SELECT']);
+               $components['FROM'] = $this->_quoteFromTables($components['FROM']);
+               $components['WHERE'] = $this->_quoteWhereClause($components['WHERE']);
+               return $components;
+       }
 
-  /**
+       /**
         * Quotes field (and table) names with the quote character suitable for the DB being used
         * Use quoteFieldNames instead!
         *
         * @param       string          List of fields to be selected from DB
         * @return      string          Quoted list of fields to be selected from DB
-        * @deprecated
+        * @deprecated since TYPO3 4.0
         */
-  function quoteSelectFields($select_fields) {
+       public function quoteSelectFields($select_fields) {
                $this->quoteFieldNames($select_fields);
        }
 
@@ -876,152 +1159,234 @@ class ux_t3lib_DB extends t3lib_DB {
         * @param       string          List of fields to be used in query to DB
         * @return      string          Quoted list of fields to be in query to DB
         */
-       function quoteFieldNames($select_fields) {
-    if($select_fields == '') return '';
-
-    $select_fields = $this->SQLparser->parseFieldList($select_fields);
-    foreach($select_fields as $k => $v)        {
-      if($select_fields[$k]['field'] != '' && $select_fields[$k]['field'] != '*') {
-        $select_fields[$k]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$select_fields[$k]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote;
-      }
-      if($select_fields[$k]['table'] != '') {
-        $select_fields[$k]['table'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$select_fields[$k]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote;
-      }
-      if($select_fields[$k]['as'] != '') {
-        $select_fields[$k]['as'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$select_fields[$k]['as'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote;
-      }
-      if(isset($select_fields[$k]['func_content.']) && $select_fields[$k]['func_content.'][0]['func_content'] != '*'){
-        if(strstr($select_fields[$k]['func_content.'][0]['func_content'],'.')) {
-                                       $select_fields[$k]['func_content.'][0]['func_content'] = $this->quoteFieldNames($select_fields[$k]['func_content.'][0]['func_content']);
-                                       $select_fields[$k]['func_content'] = $this->quoteFieldNames($select_fields[$k]['func_content']);
-        }
-        else {
-          $select_fields[$k]['func_content.'][0]['func_content'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$select_fields[$k]['func_content.'][0]['func_content'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote;
-          $select_fields[$k]['func_content'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$select_fields[$k]['func_content'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote;
-        }
-      }
-    }
-
-    return $this->SQLparser->compileFieldList($select_fields);
-  }
-
-  /**
+       public function quoteFieldNames($select_fields) {
+               if ($select_fields == '') return '';
+               if ($this->runningNative()) return $select_fields;
+
+               $select_fields = $this->SQLparser->parseFieldList($select_fields);
+               if ($this->SQLparser->parse_error) {
+                       die($this->SQLparser->parse_error . ' in ' . __FILE__ . ' : ' . __LINE__);
+               }
+               $select_fields = $this->_quoteFieldNames($select_fields);
+
+               return $this->SQLparser->compileFieldList($select_fields);
+       }
+
+       /**
+        * Quotes field (and table) names in a SQL SELECT clause acccording to DB rules
+        *
+        * @param array $select_fields The parsed fields to quote
+        * @return array
+        * @see quoteFieldNames()
+        */
+       protected function _quoteFieldNames(array $select_fields) {
+               foreach ($select_fields as $k => $v) {
+                       if ($select_fields[$k]['field'] != '' && $select_fields[$k]['field'] != '*' && !is_numeric($select_fields[$k]['field'])) {
+                               $select_fields[$k]['field'] = $this->quoteName($select_fields[$k]['field']);
+                       }
+                       if ($select_fields[$k]['table'] != '' && !is_numeric($select_fields[$k]['table'])) {
+                               $select_fields[$k]['table'] = $this->quoteName($select_fields[$k]['table']);
+                       }
+                       if ($select_fields[$k]['as'] != '') {
+                               $select_fields[$k]['as'] = $this->quoteName($select_fields[$k]['as']);
+                       }
+                       if (isset($select_fields[$k]['func_content.']) && $select_fields[$k]['func_content.'][0]['func_content'] != '*'){
+                               $select_fields[$k]['func_content.'][0]['func_content'] = $this->quoteFieldNames($select_fields[$k]['func_content.'][0]['func_content']);
+                               $select_fields[$k]['func_content'] = $this->quoteFieldNames($select_fields[$k]['func_content']);
+                       }
+                       if (isset($select_fields[$k]['flow-control'])) {
+                                       // Quoting flow-control statements
+                               if ($select_fields[$k]['flow-control']['type'] === 'CASE') {
+                                       if (isset($select_fields[$k]['flow-control']['case_field'])) {
+                                               $select_fields[$k]['flow-control']['case_field'] = $this->quoteFieldNames($select_fields[$k]['flow-control']['case_field']);
+                                       }
+                                       foreach ($select_fields[$k]['flow-control']['when'] as $key => $when) {
+                                               $select_fields[$k]['flow-control']['when'][$key]['when_value'] = $this->_quoteWhereClause($when['when_value']);
+                                       } 
+                               }
+                       }
+               }
+
+               return $select_fields;
+       }
+
+       /**
         * Quotes table names with the quote character suitable for the DB being used
         *
         * @param       string          List of tables to be selected from DB
         * @return      string          Quoted list of tables to be selected from DB
         */
-  function quoteFromTables($from_table) {
-    if($from_table == '') return '';
-
-    $from_table = $this->SQLparser->parseFromTables($from_table);
-    foreach($from_table as $k => $v)   {
-      $from_table[$k]['table'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote;
-      if($from_table[$k]['as'] != '') {
-        $from_table[$k]['as'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['as'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote;
-      }
-      if (is_array($v['JOIN']))        {
-        $from_table[$k]['JOIN']['withTable'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['JOIN']['withTable'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote;
-        $from_table[$k]['JOIN']['ON'][0]['table'] = ($from_table[$k]['JOIN']['ON'][0]['table']) ? $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['JOIN']['ON'][0]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote : '';
-        $from_table[$k]['JOIN']['ON'][0]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['JOIN']['ON'][0]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote;
-        $from_table[$k]['JOIN']['ON'][1]['table'] = ($from_table[$k]['JOIN']['ON'][1]['table']) ? $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['JOIN']['ON'][1]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote : '';
-        $from_table[$k]['JOIN']['ON'][1]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['JOIN']['ON'][1]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote;
-      }
-    }
-    return $this->SQLparser->compileFromTables($from_table);
-  }
-
-  /**
+       public function quoteFromTables($from_table) {
+               if ($from_table == '') return '';
+               if ($this->runningNative()) return $from_table;
+
+               $from_table = $this->SQLparser->parseFromTables($from_table);
+               $from_table = $this->_quoteFromTables($from_table);
+               return $this->SQLparser->compileFromTables($from_table);
+       }
+
+       /**
+        * Quotes table names in a SQL FROM clause acccording to DB rules
+        *
+        * @param array $from_table The parsed FROM clause to quote
+        * @return array
+        * @see quoteFromTables()
+        */
+       protected function _quoteFromTables(array $from_table) {
+               foreach ($from_table as $k => $v) {
+                       $from_table[$k]['table'] = $this->quoteName($from_table[$k]['table']);
+                       if ($from_table[$k]['as'] != '') {
+                               $from_table[$k]['as'] = $this->quoteName($from_table[$k]['as']);
+                       }
+                       if (is_array($v['JOIN'])) {
+                               foreach ($v['JOIN'] as $joinCnt => $join) {
+                                       $from_table[$k]['JOIN'][$joinCnt]['withTable'] = $this->quoteName($join['withTable']);
+                                       $from_table[$k]['JOIN'][$joinCnt]['as'] = ($join['as']) ? $this->quoteName($join['as']) : '';
+                                       $from_table[$k]['JOIN'][$joinCnt]['ON'][0]['table'] = ($join['ON'][0]['table']) ? $this->quoteName($join['ON'][0]['table']) : '';
+                                       $from_table[$k]['JOIN'][$joinCnt]['ON'][0]['field'] = $this->quoteName($join['ON'][0]['field']);
+                                       $from_table[$k]['JOIN'][$joinCnt]['ON'][1]['table'] = ($join['ON'][1]['table']) ? $this->quoteName($join['ON'][1]['table']) : '';
+                                       $from_table[$k]['JOIN'][$joinCnt]['ON'][1]['field'] = $this->quoteName($join['ON'][1]['field']);
+                               }
+                       }
+               }
+
+               return $from_table;
+       }
+
+       /**
         * Quotes the field (and table) names within a where clause with the quote character suitable for the DB being used
         *
         * @param       string          A where clause that can e parsed by parseWhereClause
         * @return      string          Usable where clause with quoted field/table names
         */
-  function quoteWhereClause($where_clause) {
-    if($where_clause == '') return '';
-
-    $where_clause = $this->SQLparser->parseWhereClause($where_clause);
-    $where_clause = $this->_quoteWhereClause($where_clause);
-    $where_clause = $this->SQLparser->compileWhereClause($where_clause);
+       public function quoteWhereClause($where_clause) {
+               if ($where_clause === '' || $this->runningNative()) return $where_clause;
+
+               $where_clause = $this->SQLparser->parseWhereClause($where_clause);
+               if (is_array($where_clause)) {
+                       $where_clause = $this->_quoteWhereClause($where_clause);
+                       $where_clause = $this->SQLparser->compileWhereClause($where_clause);
+               } else {
+                       die('Could not parse where clause in ' . __FILE__ . ' : ' . __LINE__);
+               }
 
-    return $where_clause;
-  }
+               return $where_clause;
+       }
 
-  /**
-        * [Describe function...]
+       /**
+        * Quotes field names in a SQL WHERE clause acccording to DB rules
         *
-        * @param       [type]          $$groupBy: ...
-        * @return      [type]          ...
+        * @param       array           $where_clause The parsed WHERE clause to quote
+        * @return      array
+        * @see quoteWhereClause()
         */
-  function _quoteWhereClause($where_clause) {
-    foreach($where_clause as $k => $v) {
-      // Look for sublevel:
-      if (is_array($where_clause[$k]['sub']))  {
-        $where_clause[$k]['sub'] = $this->_quoteWhereClause($where_clause[$k]['sub']);
-      } else {
-        if($where_clause[$k]['table'] != '') {
-          $where_clause[$k]['table'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$where_clause[$k]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote;
-        }
-        if(!is_numeric($where_clause[$k]['field'])) {
-          $where_clause[$k]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$where_clause[$k]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote;
-        }
-      }
-      if ($where_clause[$k]['comparator'])     {
-        // Detecting value type; list or plain:
-        if ((!isset($where_clause[$k]['value'][1]) || $where_clause[$k]['value'][1] == '') && is_string($where_clause[$k]['value'][0]) && strstr($where_clause[$k]['value'][0], '.') && !t3lib_div::inList('NOTIN,IN',strtoupper(str_replace(array(" ","\n","\r","\t"),'',$where_clause[$k]['comparator']))))  {
-                                       $where_clause[$k]['value'][0] = $this->quoteFieldNames($where_clause[$k]['value'][0]);
-        }
-      }
-    }
-
-    return $where_clause;
-  }
-
-  /**
+       protected function _quoteWhereClause(array $where_clause) {
+               foreach ($where_clause as $k => $v) {
+                               // Look for sublevel:
+                       if (is_array($where_clause[$k]['sub'])) {
+                               $where_clause[$k]['sub'] = $this->_quoteWhereClause($where_clause[$k]['sub']);
+                       } elseif (isset($v['func'])) {
+                               switch ($where_clause[$k]['func']['type']) {
+                                       case 'EXISTS':
+                                               $where_clause[$k]['func']['subquery'] = $this->quoteSELECTsubquery($v['func']['subquery']);
+                                               break;
+                                       case 'IFNULL':
+                                       case 'LOCATE':
+                                               if ($where_clause[$k]['func']['table'] != '') {
+                                                       $where_clause[$k]['func']['table'] = $this->quoteName($v['func']['table']);
+                                               }
+                                               if ($where_clause[$k]['func']['field'] != '') {
+                                                       $where_clause[$k]['func']['field'] = $this->quoteName($v['func']['field']);
+                                               }
+                                       break;
+                               }
+                       } else {
+                               if ($where_clause[$k]['table'] != '') {
+                                       $where_clause[$k]['table'] = $this->quoteName($where_clause[$k]['table']);
+                               }
+                               if (!is_numeric($where_clause[$k]['field'])) {
+                                       $where_clause[$k]['field'] = $this->quoteName($where_clause[$k]['field']);
+                               }
+                               if (isset($where_clause[$k]['calc_table'])) {
+                                       if ($where_clause[$k]['calc_table'] != '') {
+                                               $where_clause[$k]['calc_table'] = $this->quoteName($where_clause[$k]['calc_table']);
+                                       }
+                                       if ($where_clause[$k]['calc_field'] != '') {
+                                               $where_clause[$k]['calc_field'] = $this->quoteName($where_clause[$k]['calc_field']);
+                                       }
+                               }
+                       }
+                       if ($where_clause[$k]['comparator']) {
+                               if (isset($v['value']['operator'])) {
+                                       foreach ($where_clause[$k]['value']['args'] as $argK => $fieldDef) {
+                                               $where_clause[$k]['value']['args'][$argK]['table'] = $this->quoteName($fieldDef['table']);
+                                               $where_clause[$k]['value']['args'][$argK]['field'] = $this->quoteName($fieldDef['field']);
+                                       }
+                               } else {
+                                               // Detecting value type; list or plain:
+                                       if (t3lib_div::inList('NOTIN,IN', strtoupper(str_replace(array(' ',"\n", "\r", "\t"), '', $where_clause[$k]['comparator'])))) {
+                                               if (isset($v['subquery'])) {
+                                                       $where_clause[$k]['subquery'] = $this->quoteSELECTsubquery($v['subquery']);
+                                               }
+                                       } else {
+                                               if ((!isset($where_clause[$k]['value'][1]) || $where_clause[$k]['value'][1] == '') && is_string($where_clause[$k]['value'][0]) && strstr($where_clause[$k]['value'][0], '.')) {
+                                                       $where_clause[$k]['value'][0] = $this->quoteFieldNames($where_clause[$k]['value'][0]);
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               return $where_clause;
+       }
+
+       /**
         * [Describe function...]
         *
         * @param       [type]          $$groupBy: ...
         * @return      [type]          ...
         */
-  function quoteGroupBy($groupBy) {
-    if($groupBy == '') return '';
-
-    $groupBy = $this->SQLparser->parseFieldList($groupBy);
-    foreach($groupBy as $k => $v)      {
-      $groupBy[$k]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$groupBy[$k]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote;
-      if($groupBy[$k]['table'] != '') {
-        $groupBy[$k]['table'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$groupBy[$k]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote;
-      }
-    }
-    return $this->SQLparser->compileFieldList($groupBy);
-  }
+       protected function quoteGroupBy($groupBy) {
+               if ($groupBy === '') return '';
+               if ($this->runningNative()) return $groupBy;
+
+               $groupBy = $this->SQLparser->parseFieldList($groupBy);
+               foreach ($groupBy as $k => $v) {
+                       $groupBy[$k]['field'] = $this->quoteName($groupBy[$k]['field']);
+                       if ($groupBy[$k]['table'] != '') {
+                               $groupBy[$k]['table'] = $this->quoteName($groupBy[$k]['table']);
+                       }
+               }
+               return $this->SQLparser->compileFieldList($groupBy);
+       }
 
-  /**
+       /**
         * [Describe function...]
         *
         * @param       [type]          $$orderBy: ...
         * @return      [type]          ...
         */
-  function quoteOrderBy($orderBy) {
-    if($orderBy == '') return '';
-
-    $orderBy = $this->SQLparser->parseFieldList($orderBy);
-    foreach($orderBy as $k => $v)      {
-      $orderBy[$k]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$orderBy[$k]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote;
-      if($orderBy[$k]['table'] != '') {
-        $orderBy[$k]['table'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$orderBy[$k]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote;
-      }
-    }
-    return $this->SQLparser->compileFieldList($orderBy);
-  }
+       protected function quoteOrderBy($orderBy) {
+               if ($orderBy === '') return '';
+               if ($this->runningNative()) return $orderBy;
+
+               $orderBy = $this->SQLparser->parseFieldList($orderBy);
+               foreach ($orderBy as $k => $v) {
+                       $orderBy[$k]['field'] = $this->quoteName($orderBy[$k]['field']);
+                       if ($orderBy[$k]['table'] != '') {
+                               $orderBy[$k]['table'] = $this->quoteName($orderBy[$k]['table']);
+                       }
+               }
+               return $this->SQLparser->compileFieldList($orderBy);
+       }
 
 
 
-  /**************************************
-  *
-  * Various helper functions
-  *
-  **************************************/
+       /**************************************
+       *
+       * Various helper functions
+       *
+       **************************************/
 
        /**
         * Escaping and quoting values for SQL statements.
@@ -1031,9 +1396,9 @@ class ux_t3lib_DB extends t3lib_DB {
         * @return      string          Output string; Wrapped in single quotes and quotes in the string (" / ') and \ will be backslashed (or otherwise based on DBAL handler)
         * @see quoteStr()
         */
-  function fullQuoteStr($str,$table) {
-       return '\''.$this->quoteStr($str, $table).'\'';
-  }
+       public function fullQuoteStr($str, $table) {
+               return '\'' . $this->quoteStr($str, $table) . '\'';
+       }
 
        /**
         * Substitution for PHP function "addslashes()"
@@ -1044,375 +1409,415 @@ class ux_t3lib_DB extends t3lib_DB {
         * @return      string          Output string; Quotes (" / ') and \ will be backslashed (or otherwise based on DBAL handler)
         * @see quoteStr()
         */
-  function quoteStr($str, $table)      {
-    $this->lastHandlerKey = $this->handler_getFromTableList($table);
-    switch((string)$this->handlerCfg[$this->lastHandlerKey]['type'])   {
-      case 'native':
-      $str = mysql_real_escape_string($str, $this->handlerInstance[$this->lastHandlerKey]['link']);
-      break;
-      case 'adodb':
-      $str = substr($this->handlerInstance[$this->lastHandlerKey]->qstr($str),1,-1);
-      break;
-      case 'userdefined':
-      $str = $this->handlerInstance[$this->lastHandlerKey]->quoteStr($str);
-      break;
-      default:
-      die('No handler found!!!');
-      break;
-    }
-
-    return $str;
-  }
-
-
-  /**
+       public function quoteStr($str, $table) {
+               $this->lastHandlerKey = $this->handler_getFromTableList($table);
+               switch ((string)$this->handlerCfg[$this->lastHandlerKey]['type']) {
+                       case 'native':
+                               $str = mysql_real_escape_string($str, $this->handlerInstance[$this->lastHandlerKey]['link']);
+                               break;
+                       case 'adodb':
+                               $str = substr($this->handlerInstance[$this->lastHandlerKey]->qstr($str), 1, -1);
+                               break;
+                       case 'userdefined':
+                               $str = $this->handlerInstance[$this->lastHandlerKey]->quoteStr($str);
+                               break;
+                       default:
+                               die('No handler found!!!');
+                               break;
+               }
+
+               return $str;
+       }
+
+       /**
+        * Quotes an object name (table name, field, ...)
+        *
+        * @param       string          Object's name
+        * @param       string          Handler key
+        * @param       boolean         If method NameQuote() is not used, whether to use backticks instead of driver-specific quotes
+        * @return      string          Properly-quoted object's name
+        */
+       public function quoteName($name, $handlerKey = NULL, $useBackticks = FALSE) {
+               $handlerKey = $handlerKey ? $handlerKey : $this->lastHandlerKey;
+               $useNameQuote = isset($this->handlerCfg[$handlerKey]['config']['useNameQuote']) ? $this->handlerCfg[$handlerKey]['config']['useNameQuote'] : FALSE;
+               if ($useNameQuote) {
+                       return $this->handlerInstance[$handlerKey]->DataDictionary->NameQuote($name);
+               } else {
+                       $quote = $useBackticks ? '`' : $this->handlerInstance[$handlerKey]->nameQuote;
+                       return $quote . $name . $quote;
+               }
+       }
+
+       /**
         * Return MetaType for native field type (ADOdb only!)
         *
         * @param       string          native type as reported by admin_get_fields()
         * @param       string          Table name for which query type string. Important for detection of DBMS handler of the query!
         * @return      string          Meta type (currenly ADOdb syntax only, http://phplens.com/lens/adodb/docs-adodb.htm#metatype)
         */
-  function MetaType($type,$table,$max_length=-1)       {
-    $this->lastHandlerKey = $this->handler_getFromTableList($table);
-    switch((string)$this->handlerCfg[$this->lastHandlerKey]['type'])   {
-      case 'adodb':
-      $rs = $this->handlerInstance[$this->lastHandlerKey]->SelectLimit('SELECT * FROM '.$this->quoteFromTables($table),1);
-      $str = $rs->MetaType($type, $max_length);
-      break;
-      default:
-      die('No handler found!!!');
-      break;
-    }
+       public function MetaType($type, $table, $max_length = -1) {
+               $this->lastHandlerKey = $this->handler_getFromTableList($table);
+               $str = '';
+               switch ((string)$this->handlerCfg[$this->lastHandlerKey]['type']) {
+                       case 'native':
+                               $str = $type;
+                               break;
+                       case 'adodb':
+                               if (in_array($table, $this->cache_fieldType)) {
+                                       $rs = $this->handlerInstance[$this->lastHandlerKey]->SelectLimit('SELECT * FROM ' . $this->quoteFromTables($table), 1);
+                                       $str = $rs->MetaType($type, $max_length);
+                               }
+                               break;
+                       case 'userdefined':
+                               $str = $this->handlerInstance[$this->lastHandlerKey]->MetaType($str,$table,$max_length);
+                               break;
+                       default:
+                               die('No handler found!!!');
+                               break;
+               }
 
-    return $str;
-  }
+               return $str;
+       }
 
 
-  /**
+       /**
         * Return MetaType for native MySQL field type
         *
         * @param       string          native type as reported as in mysqldump files
         * @return      string          Meta type (currenly ADOdb syntax only, http://phplens.com/lens/adodb/docs-adodb.htm#metatype)
         */
-  function MySQLMetaType($t) {
-
-    switch (strtoupper($t)) {
-      case 'STRING':
-      case 'CHAR':
-      case 'VARCHAR':
-      //               case 'TINYBLOB': // moved below, see there for the reason
-      //               case 'TINYTEXT': // moved below, see there for the reason
-      case 'ENUM':
-      case 'SET':
-      return 'C';
-
-      case 'TINYTEXT': // basically the same as with TINYBLOB
-      case 'TEXT':
-      case 'LONGTEXT':
-      case 'MEDIUMTEXT':
-      return 'X';
-
-      // php_mysql extension always returns 'blob' even if 'text'
-      // so we have to check whether binary...
-      case 'IMAGE':
-      case 'TINYBLOB': // this got moved here from above.
-      // otherwise tinyblob fields become varchar without length.
-      // this fails on Oracle and results in char(1) on PostgreSQL
-      case 'LONGBLOB':
-      case 'BLOB':
-      case 'MEDIUMBLOB':
-      return 'B';
-
-      case 'YEAR':
-      case 'DATE': return 'D';
-
-      case 'TIME':
-      case 'DATETIME':
-      case 'TIMESTAMP': return 'T';
-
-      case 'FLOAT':
-      case 'DOUBLE':
-      return 'F';
-
-      case 'INT':
-      case 'INTEGER': return 'I';
-      case 'TINYINT': return 'I1';
-      case 'SMALLINT': return 'I2';
-      case 'MEDIUMINT': return 'I4';
-      case 'BIGINT': return 'I8';
-
-      default: return 'N';
-    }
-  }
-
-  /**
+       public function MySQLMetaType($t) {
+
+               switch (strtoupper($t)) {
+                       case 'STRING':
+                       case 'CHAR':
+                       case 'VARCHAR':
+                       case 'TINYBLOB':
+                       case 'TINYTEXT':
+                       case 'ENUM':
+                       case 'SET': return 'C';
+
+                       case 'TEXT':
+                       case 'LONGTEXT':
+                       case 'MEDIUMTEXT': return 'XL';
+
+                       case 'IMAGE':
+                       case 'LONGBLOB':
+                       case 'BLOB':
+                       case 'MEDIUMBLOB': return 'B';
+
+                       case 'YEAR':
+                       case 'DATE': return 'D';
+
+                       case 'TIME':
+                       case 'DATETIME':
+                       case 'TIMESTAMP': return 'T';
+
+                       case 'FLOAT':
+                       case 'DOUBLE': return 'F';
+
+                       case 'INT':
+                       case 'INTEGER':
+                       case 'TINYINT':
+                       case 'SMALLINT':
+                       case 'MEDIUMINT':
+                       case 'BIGINT': return 'I8'; // we always return I8 to be on the safe side. Under some circumstances the fields are to small otherwise...
+
+                       default: return 'N';
+               }
+       }
+
+       /**
         * Return actual MySQL type for meta field type
         *
         * @param       string          Meta type (currenly ADOdb syntax only, http://phplens.com/lens/adodb/docs-adodb.htm#metatype)
         * @return      string          native type as reported as in mysqldump files, uppercase
         */
-  function MySQLActualType($meta) {
-    switch(strtoupper($meta)) {
-      case 'C': return 'VARCHAR';
-      case 'XL':
-      case 'X': return 'LONGTEXT';
+       public function MySQLActualType($meta) {
+               switch (strtoupper($meta)) {
+                       case 'C': return 'VARCHAR';
+                       case 'XL':
+                       case 'X': return 'LONGTEXT';
+
+                       case 'C2': return 'VARCHAR';
+                       case 'X2': return 'LONGTEXT';
 
-      case 'C2': return 'VARCHAR';
-      case 'X2': return 'LONGTEXT';
+                       case 'B': return 'LONGBLOB';
 
-      case 'B': return 'LONGBLOB';
+                       case 'D': return 'DATE';
+                       case 'T': return 'DATETIME';
+                       case 'L': return 'TINYINT';
 
-      case 'D': return 'DATE';
-      case 'T': return 'DATETIME';
-      case 'L': return 'TINYINT';
+                       case 'I':
+                       case 'I1':
+                       case 'I2':
+                       case 'I4':
+                       case 'I8': return 'BIGINT'; // we only have I8 in DBAL, see MySQLMetaType()
 
-      case 'I': return 'INT';
-      case 'I1': return 'TINYINT';
-      case 'I2': return 'SMALLINT';
-      case 'I4': return 'MEDIUMINT';
-      case 'I8': return 'BIGINT';
+                       case 'F': return 'DOUBLE';
+                       case 'N': return 'NUMERIC';
 
-      case 'F': return 'DOUBLE';
-      case 'N': return 'NUMERIC';
-      default:
-      return $meta;
-    }
-  }
+                       default: return $meta;
+               }
+       }
 
 
 
 
-  /**************************************
-  *
-  * SQL wrapper functions (Overriding parent methods)
-  * (For use in your applications)
-  *
-  **************************************/
+       /**************************************
+       *
+       * SQL wrapper functions (Overriding parent methods)
+       * (For use in your applications)
+       *
+       **************************************/
 
-  /**
+       /**
         * Returns the error status on the most recent sql() execution (based on $this->lastHandlerKey)
         *
         * @return      string          Handler error strings
         */
-  function sql_error() {
-
-    switch($this->handlerCfg[$this->lastHandlerKey]['type'])   {
-      case 'native':
-      $output = mysql_error($this->handlerInstance[$this->lastHandlerKey]['link']);
-      break;
-      case 'adodb':
-      $output = $this->handlerInstance[$this->lastHandlerKey]->ErrorMsg();
-      break;
-      case 'userdefined':
-      $output = $this->handlerInstance[$this->lastHandlerKey]->sql_error();
-      break;
-    }
-    return $output;
-  }
-
-  /**
+       public function sql_error() {
+               switch ($this->handlerCfg[$this->lastHandlerKey]['type']) {
+                       case 'native':
+                               $output = mysql_error($this->handlerInstance[$this->lastHandlerKey]['link']);
+                               break;
+                       case 'adodb':
+                               $output = $this->handlerInstance[$this->lastHandlerKey]->ErrorMsg();
+                               break;
+                       case 'userdefined':
+                               $output = $this->handlerInstance[$this->lastHandlerKey]->sql_error();
+                               break;
+               }
+               return $output;
+       }
+
+       /**
+        * Returns the error number on the most recent sql() execution (based on $this->lastHandlerKey)
+        *
+        * @return      int             Handler error number
+        */
+       public function sql_errno() {
+               switch ($this->handlerCfg[$this->lastHandlerKey]['type']) {
+                       case 'native':
+                               $output = mysql_errno($this->handlerInstance[$this->lastHandlerKey]['link']);
+                               break;
+                       case 'adodb':
+                               $output = $this->handlerInstance[$this->lastHandlerKey]->ErrorNo();
+                               break;
+                       case 'userdefined':
+                               $output = $this->handlerInstance[$this->lastHandlerKey]->sql_errno();
+                               break;
+               }
+               return $output;
+       }
+
+       /**
         * Returns the number of selected rows.
         *
         * @param       pointer         Result pointer / DBAL object
         * @return      integer         Number of resulting rows.
         */
-  function sql_num_rows(&$res) {
-
-    $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : 'native';
-    switch($handlerType)       {
-      case 'native':
-      $output = mysql_num_rows($res);
-      break;
-      case 'adodb':
-                       $output = method_exists($res, 'RecordCount') ? $res->RecordCount() : 0;
-      break;
-      case 'userdefined':
-      $output = $res->sql_num_rows();
-      break;
-    }
-    return $output;
-  }
-
-  /**
+       public function sql_num_rows(&$res) {
+               if ($res === FALSE) return 0;
+
+               $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : 'native';
+               switch ($handlerType) {
+                       case 'native':
+                               $output = mysql_num_rows($res);
+                               break;
+                       case 'adodb':
+                               $output = method_exists($res, 'RecordCount') ? $res->RecordCount() : 0;
+                               break;
+                       case 'userdefined':
+                               $output = $res->sql_num_rows();
+                               break;
+               }
+               return $output;
+       }
+
+       /**
         * Returns an associative array that corresponds to the fetched row, or FALSE if there are no more rows.
         *
         * @param       pointer         MySQL result pointer (of SELECT query) / DBAL object
         * @return      array           Associative array of result row.
         */
-  function sql_fetch_assoc(&$res)      {
-
-    $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType :  'native';
-    switch($handlerType)       {
-      case 'native':
-      $output = mysql_fetch_assoc($res);
-      $tableList = $this->resourceIdToTableNameMap[(string)$res];      // Reading list of tables from SELECT query:
-      break;
-      case 'adodb':
-                       // Check if method exists for the current $res object.
-                       // If a table exists in TCA but not in the db, a error
-                       // occured because $res is not a valid object.
-                       if(method_exists($res, 'FetchRow')) {
-      $output = $res->FetchRow();
-      $tableList = $res->TYPO3_DBAL_tableList; // Reading list of tables from SELECT query:
-
-      // Removing all numeric/integer keys.
-      // Just a temporary workaround till I know how to make ADOdb return this by default... Most likely this will not work with other databases than MySQL
-      if (is_array($output))   {
-        foreach($output as $key => $value)     {
-          if (is_integer($key))        unset($output[$key]);
-        }
-      }
+       public function sql_fetch_assoc(&$res) {
+               $output = array();
+
+               $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : (is_resource($res) ? 'native' : FALSE);
+               switch ($handlerType) {
+                       case 'native':
+                               $output = mysql_fetch_assoc($res);
+                               $tableList = $this->resourceIdToTableNameMap[(string)$res];     // Reading list of tables from SELECT query:
+                               break;
+                       case 'adodb':
+                                       // Check if method exists for the current $res object.
+                                       // If a table exists in TCA but not in the db, a error
+                                       // occured because $res is not a valid object.
+                               if (method_exists($res, 'FetchRow')) {
+                                       $output = $res->FetchRow();
+                                       $tableList = $res->TYPO3_DBAL_tableList;        // Reading list of tables from SELECT query:
+
+                                               // Removing all numeric/integer keys.
+                                               // A workaround because in ADOdb we would need to know what we want before executing the query...
+                                       if (is_array($output)) {
+                                               foreach ($output as $key => $value) {
+                                                       if (is_integer($key)) {
+                                                               unset($output[$key]);
+                                                       }
+                                                       elseif ($value === ' ' && $this->runningADOdbDriver('mssql')) $output[$key] = ''; // MSSQL does not know such thing as an empty string. So it returns one space instead, which we must fix.
+                                               }
+                                       }
+                               }
+                               break;
+                       case 'userdefined':
+                               $output = $res->sql_fetch_assoc();
+                               $tableList = $res->TYPO3_DBAL_tableList;        // Reading list of tables from SELECT query:
+                               break;
+               }
+
+                       // Table/Fieldname mapping:
+               if (is_array($output)) {
+                       if ($tables = $this->map_needMapping($tableList,TRUE)) {
+                               $output = $this->map_assocArray($output,$tables,1);
                        }
-      break;
-      case 'userdefined':
-      $output = $res->sql_fetch_assoc();
-      $tableList = $res->TYPO3_DBAL_tableList; // Reading list of tables from SELECT query:
-      break;
-    }
-
-    // Table/Fieldname mapping:
-    if (is_array($output))     {
-      if ($tables = $this->map_needMapping($tableList,TRUE))   {
-        $output = $this->map_assocArray($output,$tables,1);
-      }
-    }
-
-    // Return result:
-    return $output;
-  }
-
-  /**
+               }
+
+                       // Return result:
+               return $output;
+       }
+
+       /**
         * Returns an array that corresponds to the fetched row, or FALSE if there are no more rows.
         * The array contains the values in numerical indices.
         *
         * @param       pointer         MySQL result pointer (of SELECT query) / DBAL object
         * @return      array           Array with result rows.
         */
-  function sql_fetch_row(&$res)        {
-    $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType :  'native';
-    switch($handlerType)       {
-      case 'native':
-      $output = mysql_fetch_row($res);
-      break;
-      case 'adodb':
-                       // Check if method exists for the current $res object.
-                       // If a table exists in TCA but not in the db, a error
-                       // occured because $res is not a valid object.
-                       if(method_exists($res, 'FetchRow')) {
-      $output = $res->FetchRow();
-
-      // Removing all assoc. keys.
-      // Just a temporary workaround till I know how to make ADOdb return this by default... Most likely this will not work with other databases than MySQL
-      if (is_array($output))   {
-        foreach($output as $key => $value)     {
-          if (!is_integer($key))       unset($output[$key]);
-        }
-      }
-                       }
-      break;
-      case 'userdefined':
-      $output = $res->sql_fetch_row();
-      break;
-    }
-    return $output;
-  }
-
-  /**
+       public function sql_fetch_row(&$res) {
+               $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : 'native';
+               switch ($handlerType) {
+                       case 'native':
+                               $output = mysql_fetch_row($res);
+                               break;
+                       case 'adodb':
+                                       // Check if method exists for the current $res object.
+                                       // If a table exists in TCA but not in the db, a error
+                                       // occured because $res is not a valid object.
+                               if (method_exists($res, 'FetchRow')) {
+                                       $output = $res->FetchRow();
+
+                                               // Removing all assoc. keys.
+                                               // A workaround because in ADOdb we would need to know what we want before executing the query...
+                                       if (is_array($output)) {
+                                               foreach ($output as $key => $value) {
+                                                       if (!is_integer($key))  unset($output[$key]);
+                                                       elseif ($value === ' ' && $this->runningADOdbDriver('mssql')) $output[$key] = ''; // MSSQL does not know such thing as an empty string. So it returns one space instead, which we must fix.
+                                               }
+                                       }
+                               }
+                               break;
+                       case 'userdefined':
+                               $output = $res->sql_fetch_row();
+                               break;
+               }
+               return $output;
+       }
+
+       /**
         * Free result memory / unset result object
         *
         * @param       pointer         MySQL result pointer to free / DBAL object
         * @return      boolean         Returns TRUE on success or FALSE on failure.
         */
-  function sql_free_result(&$res)      {
-
-    $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType :  'native';
-    switch($handlerType)       {
-      case 'native':
-      $output = mysql_free_result($res);
-      break;
-      case 'adodb':
-                       if(method_exists($res, 'Close')) {
-      $res->Close();
-      unset($res);
-      $output = true;
-                       } else {
-                               $output = false;
-                       }
-      break;
-      case 'userdefined':
-      unset($res);
-      break;
-    }
-    return $output;
-  }
-
-  /**
+       public function sql_free_result(&$res) {
+               if ($res === FALSE) return FALSE;
+
+               $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : 'native';
+               switch ($handlerType) {
+                       case 'native':
+                               $output = mysql_free_result($res);
+                               break;
+                       case 'adodb':
+                               if (method_exists($res, 'Close')) {
+                                       $res->Close();
+                                       unset($res);
+                                       $output = TRUE;
+                               } else {
+                                       $output = FALSE;
+                               }
+                               break;
+                       case 'userdefined':
+                               unset($res);
+                               break;
+               }
+               return $output;
+       }
+
+       /**
         * Get the ID generated from the previous INSERT operation
         *
         * @return      integer         The uid of the last inserted record.
         */
-  function sql_insert_id()     {
-
-    switch($this->handlerCfg[$this->lastHandlerKey]['type'])   {
-      case 'native':
-      $output = mysql_insert_id($this->handlerInstance[$this->lastHandlerKey]['link']);
-      break;
-      case 'adodb':
-      $output = $this->handlerInstance[$this->lastHandlerKey]->last_insert_id;
-      break;
-      case 'userdefined':
-      $output = $this->handlerInstance[$this->lastHandlerKey]->sql_insert_id();
-      break;
-    }
-    return $output;
-  }
-
-  /**
+       public function sql_insert_id() {
+               switch ($this->handlerCfg[$this->lastHandlerKey]['type']) {
+                       case 'native':
+                               $output = mysql_insert_id($this->handlerInstance[$this->lastHandlerKey]['link']);
+                               break;
+                       case 'adodb':
+                               $output = $this->handlerInstance[$this->lastHandlerKey]->last_insert_id;
+                               break;
+                       case 'userdefined':
+                               $output = $this->handlerInstance[$this->lastHandlerKey]->sql_insert_id();
+                               break;
+               }
+               return $output;
+       }
+
+       /**
         * Returns the number of rows affected by the last INSERT, UPDATE or DELETE query
         *
         * @return      integer         Number of rows affected by last query
         */
-  function sql_affected_rows() {
-
-    switch($this->handlerCfg[$this->lastHandlerKey]['type'])   {
-      case 'native':
-      $output = mysql_affected_rows();
-      break;
-      case 'adodb':
-      $output = $this->handlerInstance[$this->lastHandlerKey]->Affected_Rows();
-      break;
-      case 'userdefined':
-      $output = $this->handlerInstance[$this->lastHandlerKey]->sql_affected_rows();
-      break;
-    }
-    return $output;
-  }
-
-  /**
+       public function sql_affected_rows() {
+               switch ($this->handlerCfg[$this->lastHandlerKey]['type']) {
+                       case 'native':
+                               $output = mysql_affected_rows();
+                               break;
+                       case 'adodb':
+                               $output = $this->handlerInstance[$this->lastHandlerKey]->Affected_Rows();
+                               break;
+                       case 'userdefined':
+                               $output = $this->handlerInstance[$this->lastHandlerKey]->sql_affected_rows();
+                               break;
+               }
+               return $output;
+       }
+
+       /**
         * Move internal result pointer
         *
         * @param       pointer         MySQL result pointer (of SELECT query) / DBAL object
         * @param       integer         Seek result number.
         * @return      boolean         Returns TRUE on success or FALSE on failure.
         */
-  function sql_data_seek(&$res,$seek)  {
-
-    $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType :  'native';
-    switch($handlerType)       {
-      case 'native':
-      $output = mysql_data_seek($res,$seek);
-      break;
-      case 'adodb':
-      $output = $res->Move($seek);
-      break;
-      case 'userdefined':
-      $output = $res->sql_data_seek($seek);
-      break;
-    }
-    return $output;
-  }
-
-  /**
+       public function sql_data_seek(&$res, $seek) {
+               $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : 'native';
+               switch ($handlerType) {
+                       case 'native':
+                               $output = mysql_data_seek($res,$seek);
+                               break;
+                       case 'adodb':
+                               $output = $res->Move($seek);
+                               break;
+                       case 'userdefined':
+                               $output = $res->sql_data_seek($seek);
+                               break;
+               }
+               return $output;
+       }
+
+       /**
         * Get the type of the specified field in a result
         *
         * If the first parameter is a string, it is used as table name for the lookup.
@@ -1421,11 +1826,28 @@ class ux_t3lib_DB extends t3lib_DB {
         * @param       integer         Field index. In case of ADOdb a string (field name!) FIXME
         * @return      string          Returns the type of the specified field index
         */
-  function sql_field_metatype($table,$field)   {
-    return $this->cache_fieldType[$table][$field]['metaType'];
-  }
+       public function sql_field_metatype($table, $field) {
+                       // If $table and/or $field are mapped, use the original names instead
+               foreach ($this->mapping as $tableName => $tableMapInfo) {
+                       if (isset($tableMapInfo['mapTableName']) && $tableMapInfo['mapTableName'] === $table) {
+                                       // Table name is mapped => use original name
+                               $table = $tableName;
+                       }
+
+                       if (isset($tableMapInfo['mapFieldNames'])) {
+                               foreach ($tableMapInfo['mapFieldNames'] as $fieldName => $fieldMapInfo) {
+                                       if ($fieldMapInfo === $field) {
+                                                       // Field name is mapped => use original name
+                                               $field = $fieldName;
+                                       }
+                               }
+                       }
+               }
+
+               return $this->cache_fieldType[$table][$field]['metaType'];
+       }
 
-  /**
+       /**
         * Get the type of the specified field in a result
         *
         * If the first parameter is a string, it is used as table name for the lookup.
@@ -1434,36 +1856,36 @@ class ux_t3lib_DB extends t3lib_DB {
         * @param       integer         Field index. In case of ADOdb a string (field name!) FIXME
         * @return      string          Returns the type of the specified field index
         */
-  function sql_field_type(&$res,$pointer)      {
-    if($res === null) {
-      debug(array('no res in sql_field_type!'));
-      return 'text';
-    }
-    else if(is_string($res)){
-      if($res == 'tx_dbal_debuglog') return 'text';
-      $handlerType = 'adodb';
-    }
-    else {
-      $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType :  'native';
-    }
-
-    switch($handlerType)       {
-      case 'native':
-      $output = mysql_field_type($res,$pointer);
-      break;
-      case 'adodb':
-                       if(is_string($pointer)){
-      $output = $this->cache_fieldType[$res][$pointer]['type'];
-                       }
+       public function sql_field_type(&$res,$pointer) {
+               if ($res === null) {
+                       debug(array('no res in sql_field_type!'));
+                       return 'text';
+               }
+               elseif (is_string($res)){
+                       if ($res === 'tx_dbal_debuglog') return 'text';
+                       $handlerType = 'adodb';
+               }
+               else {
+                       $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType :  'native';
+               }
 
-      break;
-      case 'userdefined':
-      $output = $res->sql_field_type($pointer);
-      break;
-    }
+               switch ($handlerType) {
+                       case 'native':
+                               $output = mysql_field_type($res,$pointer);
+                               break;
+                       case 'adodb':
+                               if (is_string($pointer)){
+                                       $output = $this->cache_fieldType[$res][$pointer]['type'];
+                               }
+
+                               break;
+                       case 'userdefined':
+                               $output = $res->sql_field_type($pointer);
+                               break;
+               }
 
-    return $output;
-  }
+               return $output;
+       }
 
 
 
@@ -1472,55 +1894,69 @@ class ux_t3lib_DB extends t3lib_DB {
 
 
 
-  /**********
-  *
-  * Legacy functions, bound to _DEFAULT handler. (Overriding parent methods)
-  * Depreciated.
-  *
-  **********/
+       /**********
+       *
+       * Legacy functions, bound to _DEFAULT handler. (Overriding parent methods)
+       * Deprecated or still experimental.
+       *
+       **********/
 
-  /**
+       /**
         * Executes query (on DEFAULT handler!)
-        * DEPRECIATED - use exec_* functions from this class instead!
+        * DEPRECATED - use exec_* functions from this class instead!
         *
         * @param       string          Database name
         * @param       string          Query to execute
         * @return      pointer         Result pointer
-        * @depreciated
+        * @deprecated since TYPO3 4.1
         */
-  function sql($db,$query)     {
-    return $this->sql_query($query);
-  }
+       public function sql($db,$query) {
+               return $this->sql_query($query);
+       }
 
-  /**
-        * Executes query (on DEFAULT handler!)
-        * DEPRECIATED - use exec_* functions from this class instead!
+       /**
+        * Executes a query
+        * EXPERIMENTAL - This method will make its best to handle the query correctly
+        * but if it cannot, it will simply pass the query to DEFAULT handler.
+        *
+        * You should use exec_* function from this class instead!
+        * If you don't, anything that does not use the _DEFAULT handler will probably break!
+        * 
+        * This method was deprecated in TYPO3 4.1 but is considered experimental since TYPO3 4.4
+        * as it tries to handle the query correctly anyway.
         *
         * @param       string          Query to execute
         * @return      pointer         Result pointer / DBAL object
-        * @depreciated
         */
-  function sql_query($query)   {
+       public function sql_query($query) {
+                       // This method is heavily used by Extbase, try to handle it with DBAL-native methods
+               $queryParts = $this->SQLparser->parseSQL($query);
+               if (is_array($queryParts) && t3lib_div::inList('SELECT,UPDATE,INSERT,DELETE', $queryParts['type'])) {
+                       return $this->exec_query($queryParts);
+               }
 
-    switch($this->handlerCfg['_DEFAULT']['type'])      {
-      case 'native':
-      $sqlResult = mysql_query($query, $this->handlerInstance['_DEFAULT']['link']);
-      break;
-      case 'adodb':
-      $sqlResult = $this->handlerInstance['_DEFAULT']->Execute($query);
-      break;
-      case 'userdefined':
-      $sqlResult = $this->handlerInstance['_DEFAULT']->sql_query($query);
-      break;
-    }
+               switch ($this->handlerCfg['_DEFAULT']['type']) {
+                       case 'native':
+                               $sqlResult = mysql_query($query, $this->handlerInstance['_DEFAULT']['link']);
+                               break;
+                       case 'adodb':
+                               $sqlResult = $this->handlerInstance['_DEFAULT']->Execute($query);
+                               $sqlResult->TYPO3_DBAL_handlerType = 'adodb';
+                               break;
+                       case 'userdefined':
+                               $sqlResult = $this->handlerInstance['_DEFAULT']->sql_query($query);
+                               $sqlResult->TYPO3_DBAL_handlerType = 'userdefined';
+                               break;
+               }
 
-    // Print errors:
-    if ($this->printErrors && $this->sql_error())      { debug(array($this->sql_error()));     }
+               if ($this->printErrors && $this->sql_error()) {
+                       debug(array($this->lastQuery, $this->sql_error()));
+               }
 
-    return $sqlResult;
-  }
+               return $sqlResult;
+       }
 
-  /**
+       /**
         * Opening the _DEFAULT connection handler to the database.
         * This is typically done by the scripts "init.php" in the backend or "index_ts.php" in the frontend (tslib_fe->connectToMySQL())
         * You wouldn't need to use this at any time - let TYPO3 core handle this.
@@ -1529,31 +1965,31 @@ class ux_t3lib_DB extends t3lib_DB {
         * @param       string          Username to connect with.
         * @param       string          Password to connect with.
         * @return      mixed           Returns handler connection value
-        * @depreciated
+        * @deprecated since TYPO3 4.1
         * @see handler_init()
         */
-  function sql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password)        {
-    // Overriding the _DEFAULT handler configuration of username, password, localhost and database name:
-    $this->handlerCfg['_DEFAULT']['config']['username'] = $TYPO3_db_username;
-    $this->handlerCfg['_DEFAULT']['config']['password'] = $TYPO3_db_password;
-    $this->handlerCfg['_DEFAULT']['config']['host'] = $TYPO3_db_host;
-    $this->handlerCfg['_DEFAULT']['config']['database'] = TYPO3_db;
-
-    // Initializing and output value:
-    $sqlResult = $this->handler_init('_DEFAULT');
-    return $sqlResult;
-  }
+       public function sql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password) {
+                       // Overriding the _DEFAULT handler configuration of username, password, localhost and database name:
+               $this->handlerCfg['_DEFAULT']['config']['username'] = $TYPO3_db_username;
+               $this->handlerCfg['_DEFAULT']['config']['password'] = $TYPO3_db_password;
+               $this->handlerCfg['_DEFAULT']['config']['host'] = $TYPO3_db_host;
+               $this->handlerCfg['_DEFAULT']['config']['database'] = TYPO3_db;
+
+                       // Initializing and output value:
+               $sqlResult = $this->handler_init('_DEFAULT');
+               return $sqlResult;
+       }
 
-  /**
+       /**
         * Select database for _DEFAULT handler.
         *
         * @param       string          Database to connect to.
-        * @return      boolean         Always returns true; function is obsolete, database selection is made in handler_init() function!
-        * @depreciated
+        * @return      boolean         Always returns TRUE; function is obsolete, database selection is made in handler_init() function!
+        * @deprecated since TYPO3 4.1
         */
-  function sql_select_db($TYPO3_db)    {
-    return TRUE;
-  }
+       public function sql_select_db($TYPO3_db) {
+               return TRUE;
+       }
 
 
 
@@ -1569,109 +2005,116 @@ class ux_t3lib_DB extends t3lib_DB {
 
 
 
-  /**************************************
-  *
-  * SQL admin functions
-  * (For use in the Install Tool and Extension Manager)
-  *
-  **************************************/
+       /**************************************
+       *
+       * SQL admin functions
+       * (For use in the Install Tool and Extension Manager)
+       *
+       **************************************/
 
-  /**
+       /**
         * Listing databases from current MySQL connection. NOTICE: It WILL try to select those databases and thus break selection of current database.
         * Use in Install Tool only!
         * Usage count/core: 1
         *
         * @return      array           Each entry represents a database name
         */
-  function admin_get_dbs()     {
-    $dbArr = array();
-    switch($this->handlerCfg['_DEFAULT']['type'])      {
-      case 'native':
-      $db_list = mysql_list_dbs($this->link);
-      while ($row = mysql_fetch_object($db_list)) {
-        if ($this->sql_select_db($row->Database))      {
-          $dbArr[] = $row->Database;
-        }
-      }
-      break;
-      case 'adodb':
-       // check needed for install tool - otherwise it will just die because the call to
-       // MetaDatabases is done on a stdClass instance
-      if(method_exists($this->handlerInstance['_DEFAULT'],'MetaDatabases')) {
-             $sqlDBs = $this->handlerInstance['_DEFAULT']->MetaDatabases();
-           foreach( $sqlDBs as $k => $theDB) {
-           $dbArr[] = $theDB;
-       }
-      }
-      break;
-      case 'userdefined':
-      $dbArr = $this->handlerInstance['_DEFAULT']->admin_get_tables();
-      break;
-    }
-
-    return $dbArr;
-  }
-
-  /**
+       public function admin_get_dbs() {
+               $dbArr = array();
+               switch ($this->handlerCfg['_DEFAULT']['type']) {
+                       case 'native':
+                               $db_list = mysql_list_dbs($this->link);
+                               while ($row = mysql_fetch_object($db_list)) {
+                                       if ($this->sql_select_db($row->Database)) {
+                                               $dbArr[] = $row->Database;
+                                       }
+                               }
+                               break;
+                       case 'adodb':
+                                       // check needed for install tool - otherwise it will just die because the call to
+                                       // MetaDatabases is done on a stdClass instance
+                               if (method_exists($this->handlerInstance['_DEFAULT'],'MetaDatabases')) {
+                                       $sqlDBs = $this->handlerInstance['_DEFAULT']->MetaDatabases();
+                                       if (is_array($sqlDBs)) {
+                                               foreach ($sqlDBs as $k => $theDB) {
+                                                       $dbArr[] = $theDB;
+                                               }
+                                       }
+                               }
+                               break;
+                       case 'userdefined':
+                               $dbArr = $this->handlerInstance['_DEFAULT']->admin_get_tables();
+                               break;
+               }
+
+               return $dbArr;
+       }
+
+       /**
         * Returns the list of tables from the system (quering the DBMSs)
         * It looks up all tables from the DBMS of the _DEFAULT handler and then add all tables *configured* to be managed by other handlers
         *
+        * When fetching the tables, it skips tables whose names begin with BIN$, as this is taken as a table coming from the "Recycle Bin" on Oracle.
+        *
         * @return      array           Tables in an array (tablename is in both key and value)
+        * @todo        Should the check for Oracle Recycle Bin stuff be moved elsewhere?
+        * @todo        Should return table details in value! see t3lib_db::admin_get_tables()
         */
-  function admin_get_tables()  {
-    $whichTables = array();
-
-    // Getting real list of tables:
-    switch($this->handlerCfg['_DEFAULT']['type'])      {
-      case 'native':
-      $tables_result = mysql_list_tables(TYPO3_db, $this->handlerInstance['_DEFAULT']['link']);
-      if (!$this->sql_error()) {
-        while ($theTable = $this->sql_fetch_assoc($tables_result)) {
-          $whichTables[current($theTable)] = current($theTable);
-        }
-      }
-      break;
-      case 'adodb':
-      $sqlTables = $this->handlerInstance['_DEFAULT']->MetaTables('TABLES');
-      while (list($k, $theTable) = each($sqlTables)) {
-        $whichTables[$theTable] = $theTable;
-      }
-      break;
-      case 'userdefined':
-      $whichTables = $this->handlerInstance['_DEFAULT']->admin_get_tables();
-      break;
-    }
-
-    // Check mapping:
-    if (is_array($this->mapping))      {
-
-      // Mapping table names in reverse, first getting list of real table names:
-      $tMap = array();
-      foreach($this->mapping as $tN => $tMapInfo)      {
-        if (isset($tMapInfo['mapTableName']))  $tMap[$tMapInfo['mapTableName']]=$tN;
-      }
-
-      // Do mapping:
-      $newList=array();
-      foreach($whichTables as $tN)     {
-        if (isset($tMap[$tN])) $tN = $tMap[$tN];
-        $newList[$tN] = $tN;
-      }
-
-      $whichTables = $newList;
-    }
-
-    // Adding tables configured to reside in other DBMS (handler by other handlers than the default):
-    if (is_array($this->table2handlerKeys))    {
-      foreach($this->table2handlerKeys as $key => $handlerKey) {
-        $whichTables[$key] = $key;
-      }
-    }
-
-    return $whichTables;
-  }
-
-  /**
+       public function admin_get_tables() {
+               $whichTables = array();
+
+                       // Getting real list of tables:
+               switch ($this->handlerCfg['_DEFAULT']['type']) {
+                       case 'native':
+                               $tables_result = mysql_query('SHOW TABLE STATUS FROM `' . TYPO3_db . '`', $this->handlerInstance['_DEFAULT']['link']);
+                               if (!$this->sql_error()) {
+                                       while ($theTable = $this->sql_fetch_assoc($tables_result)) {
+                                               $whichTables[current($theTable)] = current($theTable);
+                                       }
+                               }
+                               break;
+                       case 'adodb':
+                               $sqlTables = $this->handlerInstance['_DEFAULT']->MetaTables('TABLES');
+                               while (list($k, $theTable) = each($sqlTables)) {
+                                       if (preg_match('/BIN\$/', $theTable)) continue; // skip tables from the Oracle 10 Recycle Bin
+                                       $whichTables[$theTable] = $theTable;
+                               }
+                               break;
+                       case 'userdefined':
+                               $whichTables = $this->handlerInstance['_DEFAULT']->admin_get_tables();
+                               break;
+               }
+
+                       // Check mapping:
+               if (is_array($this->mapping) && count($this->mapping)) {
+
+                               // Mapping table names in reverse, first getting list of real table names:
+                       $tMap = array();
+                       foreach ($this->mapping as $tN => $tMapInfo) {
+                               if (isset($tMapInfo['mapTableName']))   $tMap[$tMapInfo['mapTableName']]=$tN;
+                       }
+
+                               // Do mapping:
+                       $newList=array();
+                       foreach ($whichTables as $tN) {
+                               if (isset($tMap[$tN]))  $tN = $tMap[$tN];
+                               $newList[$tN] = $tN;
+                       }
+
+                       $whichTables = $newList;
+               }
+
+                       // Adding tables configured to reside in other DBMS (handler by other handlers than the default):
+               if (is_array($this->table2handlerKeys)) {
+                       foreach ($this->table2handlerKeys as $key => $handlerKey) {
+                               $whichTables[$key] = $key;
+                       }
+               }
+
+               return $whichTables;
+       }
+
+       /**
         * Returns information about each field in the $table (quering the DBMS)
         * In a DBAL this should look up the right handler for the table and return compatible information
         * This function is important not only for the Install Tool but probably for DBALs as well since they might need to look up table specific information in order to construct correct queries. In such cases this information should probably be cached for quick delivery
@@ -1679,231 +2122,251 @@ class ux_t3lib_DB extends t3lib_DB {
         * @param       string          Table name
         * @return      array           Field information in an associative array with fieldname => field row
         */
-  function admin_get_fields($tableName)        {
-    $output = array();
-
-    // Do field mapping if needed:
-    $ORIG_tableName = $tableName;
-    if ($tableArray = $this->map_needMapping($tableName))      {
-
-      // Table name:
-      if ($this->mapping[$tableName]['mapTableName'])  {
-        $tableName = $this->mapping[$tableName]['mapTableName'];
-      }
-    }
-
-    // Find columns
-    $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
-    switch((string)$this->handlerCfg[$this->lastHandlerKey]['type'])   {
-      case 'native':
-      $columns_res = mysql_query('SHOW columns FROM '.$tableName, $this->handlerInstance[$this->lastHandlerKey]['link']);
-      while($fieldRow = mysql_fetch_assoc($columns_res))       {
-        $output[$fieldRow['Field']] = $fieldRow;
-      }
-      break;
-      case 'adodb':
-      $fieldRows = $this->handlerInstance[$this->lastHandlerKey]->MetaColumns($tableName, false);
-      foreach($fieldRows as $k => $fieldRow) {
-        settype($fieldRow, 'array');
-        $fieldRow['Field'] = $fieldRow['name'];
-        $ntype = $this->MySQLActualType($this->MetaType($fieldRow['type'],$tableName));
-        $ntype .= (($fieldRow['max_length'] != -1) ? (($ntype == 'INT') ? '(11)' :'('.$fieldRow['max_length'].')') : '');
-        $fieldRow['Type'] = strtolower($ntype);
-        $fieldRow['Null'] = '';
-        $fieldRow['Key'] = '';
-        $fieldRow['Default'] = $fieldRow['default_value'];
-        $fieldRow['Extra'] = '';
-        $output[$fieldRow['name']] = $fieldRow;
-      }
-      break;
-      case 'userdefined':
-      $output = $this->handlerInstance[$this->lastHandlerKey]->admin_get_fields($tableName);
-      break;
-    }
-
-    // mapping should be done:
-    if (is_array($tableArray) && is_array($this->mapping[$ORIG_tableName]['mapFieldNames']))   {
-      $revFields = array_flip($this->mapping[$ORIG_tableName]['mapFieldNames']);
-
-      $newOutput = array();
-      foreach($output as $fN => $fInfo)        {
-        if (isset($revFields[$fN]))    {
-          $fN = $revFields[$fN];
-          $fInfo['Field'] = $fN;
-        }
-        $newOutput[$fN] = $fInfo;
-      }
-      $output = $newOutput;
-    }
-
-    return $output;
-  }
-
-  /**
+       public function admin_get_fields($tableName) {
+               $output = array();
+
+                       // Do field mapping if needed:
+               $ORIG_tableName = $tableName;
+               if ($tableArray = $this->map_needMapping($tableName)) {
+
+                               // Table name:
+                       if ($this->mapping[$tableName]['mapTableName']) {
+                               $tableName = $this->mapping[$tableName]['mapTableName'];
+                       }
+               }
+
+                       // Find columns
+               $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
+               switch ((string)$this->handlerCfg[$this->lastHandlerKey]['type']) {
+                       case 'native':
+                               $columns_res = mysql_query('SHOW columns FROM '.$tableName, $this->handlerInstance[$this->lastHandlerKey]['link']);
+                               while($fieldRow = mysql_fetch_assoc($columns_res)) {
+                                       $output[$fieldRow['Field']] = $fieldRow;
+                               }
+                               break;
+                       case 'adodb':
+                               $fieldRows = $this->handlerInstance[$this->lastHandlerKey]->MetaColumns($tableName, FALSE);
+                               if (is_array($fieldRows)) {
+                                       foreach ($fieldRows as $k => $fieldRow) {
+                                               settype($fieldRow, 'array');
+                                               $fieldRow['Field'] = $fieldRow['name'];
+                                               $ntype = $this->MySQLActualType($this->MetaType($fieldRow['type'],$tableName));
+                                               $ntype .= (($fieldRow['max_length'] != -1) ? (($ntype == 'INT') ? '(11)' :'('.$fieldRow['max_length'].')') : '');
+                                               $fieldRow['Type'] = strtolower($ntype);
+                                               $fieldRow['Null'] = '';
+                                               $fieldRow['Key'] = '';
+                                               $fieldRow['Default'] = $fieldRow['default_value'];
+                                               $fieldRow['Extra'] = '';
+                                               $output[$fieldRow['name']] = $fieldRow;
+                                       }
+                               }
+                               break;
+                       case 'userdefined':
+                               $output = $this->handlerInstance[$this->lastHandlerKey]->admin_get_fields($tableName);
+                               break;
+               }
+
+                       // mapping should be done:
+               if (is_array($tableArray) && is_array($this->mapping[$ORIG_tableName]['mapFieldNames'])) {
+                       $revFields = array_flip($this->mapping[$ORIG_tableName]['mapFieldNames']);
+
+                       $newOutput = array();
+                       foreach ($output as $fN => $fInfo) {
+                               if (isset($revFields[$fN])) {
+                                       $fN = $revFields[$fN];
+                                       $fInfo['Field'] = $fN;
+                               }
+                               $newOutput[$fN] = $fInfo;
+                       }
+                       $output = $newOutput;
+               }
+
+               return $output;
+       }
+
+       /**
         * Returns information about each index key in the $table (quering the DBMS)
         * In a DBAL this should look up the right handler for the table and return compatible information
         *
         * @param       string          Table name
         * @return      array           Key information in a numeric array
         */
-  function admin_get_keys($tableName)  {
-    $output = array();
-
-    // Do field mapping if needed:
-    $ORIG_tableName = $tableName;
-    if ($tableArray = $this->map_needMapping($tableName))      {
-
-      // Table name:
-      if ($this->mapping[$tableName]['mapTableName'])  {
-        $tableName = $this->mapping[$tableName]['mapTableName'];
-      }
-    }
-
-    // Find columns
-    $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
-    switch((string)$this->handlerCfg[$this->lastHandlerKey]['type'])   {
-      case 'native':
-      $keyRes = mysql_query('SHOW keys FROM '.$tableName, $this->handlerInstance[$this->lastHandlerKey]['link']);
-      while($keyRow = mysql_fetch_assoc($keyRes))      {
-        $output[] = $keyRow;
-      }
-      break;
-      case 'adodb':
-      $keyRows = $this->handlerInstance[$this->lastHandlerKey]->MetaIndexes($tableName);
-      if($keyRows !== false) {
-        while (list($k, $theKey) = each($keyRows)) {
-          $theKey['Table'] = $tableName;
-          $theKey['Non_unique'] = (int) !$theKey['unique'];
-          $theKey['Key_name'] = str_replace($tableName.'_','',$k);
-
-          // the following are probably not needed anyway...
-          $theKey['Collation'] = '';
-          $theKey['Cardinality'] = '';
-          $theKey['Sub_part'] = '';
-          $theKey['Packed'] = '';
-          $theKey['Null'] = '';
-          $theKey['Index_type'] = '';
-          $theKey['Comment'] = '';
-
-          // now map multiple fields into multiple rows (we mimic MySQL, remember...)
-          $keycols = $theKey['columns'];
-          while (list($c, $theCol) = each($keycols)) {
-            $theKey['Seq_in_index'] = $c+1;
-            $theKey['Column_name'] = $theCol;
-            $output[] = $theKey;
-          }
-        }
-      }
-      $priKeyRow = $this->handlerInstance[$this->lastHandlerKey]->MetaPrimaryKeys($tableName);
-      $theKey = array();
-      $theKey['Table'] = $tableName;
-      $theKey['Non_unique'] = 0;
-      $theKey['Key_name'] = 'PRIMARY';
-
-      // the following are probably not needed anyway...
-      $theKey['Collation'] = '';
-      $theKey['Cardinality'] = '';
-      $theKey['Sub_part'] = '';
-      $theKey['Packed'] = '';
-      $theKey['Null'] = '';
-      $theKey['Index_type'] = '';
-      $theKey['Comment'] = '';
-
-      // now map multiple fields into multiple rows (we mimic MySQL, remember...)
-      if($priKeyRow !== false) {
-        while (list($c, $theCol) = each($priKeyRow)) {
-          $theKey['Seq_in_index'] = $c+1;
-          $theKey['Column_name'] = $theCol;
-          $output[] = $theKey;
-        }
-      }
-      break;
-      case 'userdefined':
-      $output = $this->handlerInstance[$this->lastHandlerKey]->admin_get_keys($tableName);
-      break;
-    }
-
-    // mapping should be done:
-    if (is_array($tableArray) && is_array($this->mapping[$ORIG_tableName]['mapFieldNames']))   {
-      $revFields = array_flip($this->mapping[$ORIG_tableName]['mapFieldNames']);
-
-      $newOutput = array();
-      foreach($output as $kN => $kInfo)        {
-        // Table:
-        $kInfo['Table'] = $ORIG_tableName;
-
-        // Column
-        if (isset($revFields[$kInfo['Column_name']]))  {
-          $kInfo['Column_name'] = $revFields[$kInfo['Column_name']];
-        }
-
-        // Write it back:
-        $newOutput[$kN] = $kInfo;
-      }
-      $output = $newOutput;
-    }
-
-    return $output;
-  }
-
-  /**
-        * mysql() wrapper function, used by the Install Tool and EM for all queries regarding management of the database!
-        *
-        * @param       string          Query to execute
-        * @return      pointer         Result pointer
-        */
-  function admin_query($query) {
-    $parsedQuery = $this->SQLparser->parseSQL($query);
-    $ORIG_table = $parsedQuery['TABLE'];
+       public function admin_get_keys($tableName) {
+               $output = array();
+
+                       // Do field mapping if needed:
+               $ORIG_tableName = $tableName;
+               if ($tableArray = $this->map_needMapping($tableName)) {
+
+                               // Table name:
+                       if ($this->mapping[$tableName]['mapTableName']) {
+                               $tableName = $this->mapping[$tableName]['mapTableName'];
+                       }
+               }
+
+                       // Find columns
+               $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
+               switch ((string)$this->handlerCfg[$this->lastHandlerKey]['type']) {
+                       case 'native':
+                               $keyRes = mysql_query('SHOW keys FROM '.$tableName, $this->handlerInstance[$this->lastHandlerKey]['link']);
+                               while($keyRow = mysql_fetch_assoc($keyRes)) {
+                                       $output[] = $keyRow;
+                               }
+                               break;
+                       case 'adodb':
+                               $keyRows = $this->handlerInstance[$this->lastHandlerKey]->MetaIndexes($tableName);
+                               if ($keyRows !== FALSE) {
+                                       while (list($k, $theKey) = each($keyRows)) {
+                                               $theKey['Table'] = $tableName;
+                                               $theKey['Non_unique'] = (int) !$theKey['unique'];
+                                               $theKey['Key_name'] = str_replace($tableName.'_','',$k);
+       
+                                                       // the following are probably not needed anyway...
+                                               $theKey['Collation'] = '';
+                                               $theKey['Cardinality'] = '';
+                                               $theKey['Sub_part'] = '';
+                                               $theKey['Packed'] = '';
+                                               $theKey['Null'] = '';
+                                               $theKey['Index_type'] = '';
+                                               $theKey['Comment'] = '';
+       
+                                                       // now map multiple fields into multiple rows (we mimic MySQL, remember...)
+                                               $keycols = $theKey['columns'];
+                                               while (list($c, $theCol) = each($keycols)) {
+                                                       $theKey['Seq_in_index'] = $c+1;
+                                                       $theKey['Column_name'] = $theCol;
+                                                       $output[] = $theKey;
+                                               }
+                                       }
+                               }
+                               $priKeyRow = $this->handlerInstance[$this->lastHandlerKey]->MetaPrimaryKeys($tableName);
+                               $theKey = array();
+                               $theKey['Table'] = $tableName;
+                               $theKey['Non_unique'] = 0;
+                               $theKey['Key_name'] = 'PRIMARY';
+       
+                                       // the following are probably not needed anyway...
+                               $theKey['Collation'] = '';
+                               $theKey['Cardinality'] = '';
+                               $theKey['Sub_part'] = '';
+                               $theKey['Packed'] = '';
+                               $theKey['Null'] = '';
+                               $theKey['Index_type'] = '';
+                               $theKey['Comment'] = '';
+       
+                                       // now map multiple fields into multiple rows (we mimic MySQL, remember...)
+                               if ($priKeyRow !== FALSE) {
+                                       while (list($c, $theCol) = each($priKeyRow)) {
+                                               $theKey['Seq_in_index'] = $c+1;
+                                               $theKey['Column_name'] = $theCol;
+                                               $output[] = $theKey;
+                                       }
+                               }
+                               break;
+                       case 'userdefined':
+                               $output = $this->handlerInstance[$this->lastHandlerKey]->admin_get_keys($tableName);
+                               break;
+               }
+
+                       // mapping should be done:
+               if (is_array($tableArray) && is_array($this->mapping[$ORIG_tableName]['mapFieldNames'])) {
+                       $revFields = array_flip($this->mapping[$ORIG_tableName]['mapFieldNames']);
 
-    if (is_array($parsedQuery))        {
+                       $newOutput = array();
+                       foreach ($output as $kN => $kInfo) {
+                                       // Table:
+                               $kInfo['Table'] = $ORIG_tableName;
 
-      // Process query based on type:
-      switch($parsedQuery['type'])     {
-        case 'CREATETABLE':
-        case 'ALTERTABLE':
-        case 'DROPTABLE':
-        if(file_exists(PATH_typo3conf.'temp_fieldInfo.php'))
-        unlink(PATH_typo3conf.'temp_fieldInfo.php');
-        $this->map_genericQueryParsed($parsedQuery);
-        break;
-        case 'INSERT':
-        $this->map_genericQueryParsed($parsedQuery);
-        break;
-        default:
-        die('ERROR: Invalid Query type ('.$parsedQuery['type'].') for ->admin_query() function!: "'.htmlspecialchars($query).'"');
-        break;
-      }
+                                       // Column
+                               if (isset($revFields[$kInfo['Column_name']])) {
+                                       $kInfo['Column_name'] = $revFields[$kInfo['Column_name']];
+                               }
+
+                                       // Write it back:
+                               $newOutput[$kN] = $kInfo;
+                       }
+                       $output = $newOutput;
+               }
 
-      // Setting query array (for other applications to access if needed)
-      $this->lastParsedAndMappedQueryArray = $parsedQuery;
+               return $output;
+       }
 
-      // Execute query (based on handler derived from the TABLE name which we actually know for once!)
-      $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_table);
-      switch((string)$this->handlerCfg[$this->lastHandlerKey]['type']) {
-        case 'native':
-        // Compiling query:
-        $compiledQuery =  $this->SQLparser->compileSQL($this->lastParsedAndMappedQueryArray);
+       /**
+        * mysql() wrapper function, used by the Install Tool.
+        *
+        * @return      array
+        */
+       public function admin_get_charsets() {
+               return array();
+       }
 
-        return mysql_query($compiledQuery[0], $this->link);
-        break;
-        case 'adodb':
-        // Compiling query:
-        $compiledQuery =  $this->SQLparser->compileSQL($this->lastParsedAndMappedQueryArray);
-        if($this->lastParsedAndMappedQueryArray['type']=='INSERT') {
-          return $this->exec_INSERTquery($this->lastParsedAndMappedQueryArray['TABLE'],$compiledQuery);
-        }
-        return $this->handlerInstance[$this->lastHandlerKey]->DataDictionary->ExecuteSQLArray($compiledQuery);
-        break;
-        case 'userdefined':
-        // Compiling query:
-        $compiledQuery =  $this->SQLparser->compileSQL($this->lastParsedAndMappedQueryArray);
+       /**
+        * mysql() wrapper function, used by the Install Tool and EM for all queries regarding management of the database!
+        *
+        * @param       string          Query to execute
+        * @return      pointer         Result pointer
+        */
+       public function admin_query($query) {
+               $parsedQuery = $this->SQLparser->parseSQL($query);
+               $ORIG_table = $parsedQuery['TABLE'];
+
+               if (is_array($parsedQuery)) {
+
+                               // Process query based on type:
+                       switch ($parsedQuery['type']) {
+                               case 'CREATETABLE':
+                               case 'ALTERTABLE':
+                               case 'DROPTABLE':
+                                       if (file_exists(PATH_typo3conf.'temp_fieldInfo.php')) unlink(PATH_typo3conf.'temp_fieldInfo.php');
+                                       $this->map_genericQueryParsed($parsedQuery);
+                                       break;
+                               case 'INSERT':
+                               case 'TRUNCATETABLE':
+                                       $this->map_genericQueryParsed($parsedQuery);
+                                       break;
+                               case 'CREATEDATABASE':
+                                       die('Creating a database with DBAL is not supported. Did you really read the manual?');
+                                       break;
+                               default:
+                                       die('ERROR: Invalid Query type ('.$parsedQuery['type'].') for ->admin_query() function!: "'.htmlspecialchars($query).'"');
+                                       break;
+                       }
 
-        return $this->handlerInstance[$this->lastHandlerKey]->admin_query($compiledQuery);
-        break;
-      }
-    } else die('ERROR: Query could not be parsed: "'.htmlspecialchars($parsedQuery).'". Query: "'.htmlspecialchars($query).'"');
-  }
+                               // Setting query array (for other applications to access if needed)
+                       $this->lastParsedAndMappedQueryArray = $parsedQuery;
+
+                               // Execute query (based on handler derived from the TABLE name which we actually know for once!)
+                       $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_table);
+                       switch ((string)$this->handlerCfg[$this->lastHandlerKey]['type']) {
+                               case 'native':
+                                               // Compiling query:
+                                       $compiledQuery =  $this->SQLparser->compileSQL($this->lastParsedAndMappedQueryArray);
+
+                                       if ($this->lastParsedAndMappedQueryArray['type']=='INSERT') {
+                                               return mysql_query($compiledQuery, $this->link);
+                                       }
+                                       return mysql_query($compiledQuery[0], $this->link);
+                                       break;
+                               case 'adodb':
+                                               // Compiling query:
+                                       $compiledQuery =  $this->SQLparser->compileSQL($this->lastParsedAndMappedQueryArray);
+                                       switch ($this->lastParsedAndMappedQueryArray['type']) {
+                                               case 'INSERT':
+                                                       return $this->exec_INSERTquery($this->lastParsedAndMappedQueryArray['TABLE'], $compiledQuery);
+                                               case 'TRUNCATETABLE':
+                                                       return $this->exec_TRUNCATEquery($this->lastParsedAndMappedQueryArray['TABLE']);
+                                       }
+                                       return $this->handlerInstance[$this->lastHandlerKey]->DataDictionary->ExecuteSQLArray($compiledQuery);
+                                       break;
+                               case 'userdefined':
+                                               // Compiling query:
+                                       $compiledQuery =  $this->SQLparser->compileSQL($this->lastParsedAndMappedQueryArray);
+
+                                       return $this->handlerInstance[$this->lastHandlerKey]->admin_query($compiledQuery);
+                                       break;
+                       }
+               } else die('ERROR: Query could not be parsed: "'.htmlspecialchars($parsedQuery).'". Query: "'.htmlspecialchars($query).'"');
+       }
 
 
 
@@ -1914,150 +2377,195 @@ class ux_t3lib_DB extends t3lib_DB {
 
 
 
-  /************************************
-  *
-  * Handler management
-  *
-  **************************************/
+       /************************************
+       *
+       * Handler management
+       *
+       **************************************/
 
-  /**
+       /**
         * Return the handler key pointing to an appropriate database handler as found in $this->handlerCfg array
         * Notice: TWO or more tables in the table list MUST use the SAME handler key - otherwise a fatal error is thrown! (Logically, no database can possibly join two tables from separate sources!)
         *
         * @param       string          Table list, eg. "pages" or "pages, tt_content" or "pages AS A, tt_content AS B"
         * @return      string          Handler key (see $this->handlerCfg array) for table
         */
-  function handler_getFromTableList($tableList)        {
+       public function handler_getFromTableList($tableList) {
 
-    $key = $tableList;
+               $key = $tableList;
 
-    if (!isset($this->cache_handlerKeyFromTableList[$key]))    {
+               if (!isset($this->cache_handlerKeyFromTableList[$key])) {
 
-      // Get tables separated:
-      $_tableList = $tableList;
-      $tableArray = $this->SQLparser->parseFromTables($_tableList);
+                               // Get tables separated:
+                       $_tableList = $tableList;
+                       $tableArray = $this->SQLparser->parseFromTables($_tableList);
 
-      // If success, traverse the tables:
-      if (is_array($tableArray) && count($tableArray)) {
-        foreach($tableArray as $vArray)        {
+                               // If success, traverse the tables:
+                       if (is_array($tableArray) && count($tableArray)) {
+                               $outputHandlerKey = '';
 
-          // Find handler key, select "_DEFAULT" if none is specifically configured:
-          $handlerKey = $this->table2handlerKeys[$vArray['table']] ? $this->table2handlerKeys[$vArray['table']] : '_DEFAULT';
+                               foreach ($tableArray as $vArray) {
+                                               // Find handler key, select "_DEFAULT" if none is specifically configured:
+                                       $handlerKey = $this->table2handlerKeys[$vArray['table']] ? $this->table2handlerKeys[$vArray['table']] : '_DEFAULT';
 
-          // In case of separate handler keys for joined tables:
-          if ($outputHandlerKey && $handlerKey != $outputHandlerKey)   {
-            die('DBAL fatal error: Tables in this list "'.$tableList.'" didn\'t use the same DB handler!');
-          }
+                                               // In case of separate handler keys for joined tables:
+                                       if ($outputHandlerKey && $handlerKey != $outputHandlerKey) {
+                                               die('DBAL fatal error: Tables in this list "'.$tableList.'" didn\'t use the same DB handler!');
+                                       }
 
-          $outputHandlerKey = $handlerKey;
-        }
+                                       $outputHandlerKey = $handlerKey;
+                               }
 
-        // Check initialized state; if handler is NOT initialized (connected) then we will connect it!
-        if (!isset($this->handlerInstance[$outputHandlerKey])) {
-          $this->handler_init($outputHandlerKey);
-        }
+                                       // Check initialized state; if handler is NOT initialized (connected) then we will connect it!
+                               if (!isset($this->handlerInstance[$outputHandlerKey])) {
+                                       $this->handler_init($outputHandlerKey);
+                               }
 
-        // Return handler key:
-        $this->cache_handlerKeyFromTableList[$key] = $outputHandlerKey;
-      } else {
-        die('DBAL fatal error: No tables found: "'.$tableList.'"');
-      }
-    }
+                                       // Return handler key:
+                               $this->cache_handlerKeyFromTableList[$key] = $outputHandlerKey;
+                       } else {
+                               die('DBAL fatal error: No handler found in handler_getFromTableList() for: "'.$tableList.'" ('.$tableArray.')');
+                       }
+               }
 
-    return $this->cache_handlerKeyFromTableList[$key];
-  }
+               return $this->cache_handlerKeyFromTableList[$key];
+       }
 
-  /**
+       /**
         * Initialize handler (connecting to database)
         *
         * @param       string          Handler key
-        * @return      boolean         If connection went well, return true
+        * @return      boolean         If connection went well, return TRUE
         * @see handler_getFromTableList()
         */
-  function handler_init($handlerKey)   {
-
-    // Find handler configuration:
-    $cfgArray = $this->handlerCfg[$handlerKey];
-    $handlerType = (string)$cfgArray['type'];
-    $output = FALSE;
-
-    if (is_array($cfgArray))   {
-      switch($handlerType)     {
-        case 'native':
-        $link = mysql_pconnect(
-        $cfgArray['config']['host'],
-        $cfgArray['config']['username'],
-        $cfgArray['config']['password']
-        );
-
-        // Set handler instance:
-        $this->handlerInstance[$handlerKey] = array(
-        'handlerType' => 'native',
-        'link' => $link
-        );
-
-        // If link succeeded:
-        if ($link)     {
-
-          // For default, set ->link (see t3lib_DB)
-          if ($handlerKey == '_DEFAULT') {
-            $this->link = $link;
-          }
-
-          // Select database as well:
-          if (mysql_select_db($cfgArray['config']['database'], $link)) {
-            $output = TRUE;
-          }
-        }
-        break;
-        case 'adodb':
-        $output = true;
-        require_once (t3lib_extMgm::extPath('adodb').'adodb/adodb.inc.php');
-        if(!defined('ADODB_FORCE_NULLS')) define('ADODB_FORCE_NULLS',1);
-        $ADODB_FORCE_TYPE = ADODB_FORCE_VALUE;
-
-        $dsn = $cfgArray['config']['driver'].'://'.
-        rawurlencode($cfgArray['config']['username']).':'.
-        rawurlencode($cfgArray['config']['password']).'@'.
-        rawurlencode($cfgArray['config']['host']).'/'.
-        rawurlencode($cfgArray['config']['database']).
-        '?persistent=1&fetchmode='.ADODB_FETCH_BOTH;
-        $this->handlerInstance[$handlerKey] = &ADONewConnection($dsn);
-        if($this->handlerInstance[$handlerKey] === false) {
-          error_log('DBAL error: Connection to '.$dsn.' failed. Maybe PHP doesn\'t support the database?');
-               $output = false;
-        }
-
-        $this->handlerInstance[$handlerKey]->DataDictionary  = NewDataDictionary($this->handlerInstance[$handlerKey]);
-        $this->handlerInstance[$handlerKey]->last_insert_id = 0;
-        break;
-        case 'userdefined':
-        // Find class file:
-        $fileName = t3lib_div::getFileAbsFileName($cfgArray['config']['classFile']);
-        if (@is_file($fileName))       {
-          require_once($fileName);
-        } else die('DBAL error: "'.$fileName.'" was not a file to include.');
-
-        // Initialize:
-        $this->handlerInstance[$handlerKey] = t3lib_div::makeInstance($cfgArray['config']['class']);
-        $this->handlerInstance[$handlerKey]->init($cfgArray,$this);
-
-        if (is_object($this->handlerInstance[$handlerKey]))            {
-          $output = TRUE;
-        }
-        break;
-        default:
-        die('ERROR: Invalid handler type: "'.$cfgArray['type'].'"');
-        break;
-      }
+       public function handler_init($handlerKey) {
+
+                       // Find handler configuration:
+               $cfgArray = $this->handlerCfg[$handlerKey];
+               $handlerType = (string)$cfgArray['type'];
+               $output = FALSE;
+
+               if (is_array($cfgArray)) {
+                       switch ($handlerType) {
+                               case 'native':
+                                       if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['no_pconnect']) {
+                                               $link = mysql_connect($cfgArray['config']['host'].(isset($cfgArray['config']['port']) ? ':'.$cfgArray['config']['port'] : ''), $cfgArray['config']['username'], $cfgArray['config']['password'], TRUE);
+                                       } else {
+                                               $link = mysql_pconnect($cfgArray['config']['host'].(isset($cfgArray['config']['port']) ? ':'.$cfgArray['config']['port'] : ''), $cfgArray['config']['username'], $cfgArray['config']['password']);
+                                       }
+
+                                               // Set handler instance:
+                                       $this->handlerInstance[$handlerKey] = array('handlerType' => 'native', 'link' => $link);
+
+                                               // If link succeeded:
+                                       if ($link) {
+                                                       // For default, set ->link (see t3lib_DB)
+                                               if ($handlerKey == '_DEFAULT') {
+                                                       $this->link = $link;
+                                               }
+
+                                                       // Select database as well:
+                                               if (mysql_select_db($cfgArray['config']['database'], $link)) {
+                                                       $output = TRUE;
+                                               }
+                                               $setDBinit = t3lib_div::trimExplode(chr(10), $GLOBALS['TYPO3_CONF_VARS']['SYS']['setDBinit'], 1);
+                                               foreach ($setDBinit as $v) {
+                                                       if (mysql_query($v, $this->link) === FALSE) {
+                                                               t3lib_div::sysLog('Could not initialize DB connection with query "'.$v.'".','Core',3);
+                                                       }
+                                               }
+                                       } else {
+                                               t3lib_div::sysLog('Could not connect to MySQL server '.$cfgArray['config']['host'].' with user '.$cfgArray['config']['username'].'.','Core',4);
+                                       }
+                                       break;
+                               case 'adodb':
+                                       $output = TRUE;
+                                       require_once(t3lib_extMgm::extPath('adodb').'adodb/adodb.inc.php');
+                                       if (!defined('ADODB_FORCE_NULLS')) define('ADODB_FORCE_NULLS', 1);
+                                       $GLOBALS['ADODB_FORCE_TYPE'] = ADODB_FORCE_VALUE;
+                                       $GLOBALS['ADODB_FETCH_MODE'] = ADODB_FETCH_BOTH;
+
+                                       $this->handlerInstance[$handlerKey] = &ADONewConnection($cfgArray['config']['driver']);
+
+                                               // Set driver-specific options
+                                       if (isset($cfgArray['config']['driverOptions'])) {
+                                               foreach ($cfgArray['config']['driverOptions'] as $optionName => $optionValue) {
+                                                       $optionSetterName = 'set' . ucfirst($optionName);
+                                                       if (method_exists($this->handlerInstance[$handlerKey], $optionSetterName)) {
+                                                               $this->handlerInstance[$handlerKey]->$optionSetterName($optionValue);
+                                                       } else {
+                                                               $this->handlerInstance[$handlerKey]->$optionName = $optionValue;
+                                                       }
+                                               }
+                                       }
+
+                                       if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['no_pconnect']) {
+                                               $this->handlerInstance[$handlerKey]->Connect($cfgArray['config']['host'].(isset($cfgArray['config']['port']) ? ':'.$cfgArray['config']['port'] : ''),$cfgArray['config']['username'],$cfgArray['config']['password'],$cfgArray['config']['database']);
+                                       } else {
+                                               $this->handlerInstance[$handlerKey]->PConnect($cfgArray['config']['host'].(isset($cfgArray['config']['port']) ? ':'.$cfgArray['config']['port'] : ''),$cfgArray['config']['username'],$cfgArray['config']['password'],$cfgArray['config']['database']);
+                                       }
+                                       if (!$this->handlerInstance[$handlerKey]->isConnected()) {
+                                               $dsn = $cfgArray['config']['driver'].'://'.$cfgArray['config']['username'].
+                                                       (strlen($cfgArray['config']['password']) ? ':XXXX@' : '').
+                                                       $cfgArray['config']['host'].(isset($cfgArray['config']['port']) ? ':'.$cfgArray['config']['port'] : '').'/'.$cfgArray['config']['database'].
+                                                       ($GLOBALS['TYPO3_CONF_VARS']['SYS']['no_pconnect'] ? '' : '?persistent=1');
+                                               t3lib_div::sysLog('Could not connect to DB server using ADOdb on '.$cfgArray['config']['host'].' with user '.$cfgArray['config']['username'].'.','Core',4);
+                                               error_log('DBAL error: Connection to '.$dsn.' failed. Maybe PHP doesn\'t support the database?');
+                                               $output = FALSE;
+                                       } else {
+                                               $this->handlerInstance[$handlerKey]->DataDictionary  = NewDataDictionary($this->handlerInstance[$handlerKey]);
+                                               $this->handlerInstance[$handlerKey]->last_insert_id = 0;
+                                               if (isset($cfgArray['config']['sequenceStart'])) {
+                                                       $this->handlerInstance[$handlerKey]->sequenceStart = $cfgArray['config']['sequenceStart'];
+                                               } else {
+                                                       $this->handlerInstance[$handlerKey]->sequenceStart = 1;
+                                               }
+                                       }
+                                       break;
+                               case 'userdefined':
+                                               // Find class file:
+                                       $fileName = t3lib_div::getFileAbsFileName($cfgArray['config']['classFile']);
+                                       if (@is_file($fileName)) {
+                                               require_once($fileName);
+                                       } else die('DBAL error: "'.$fileName.'" was not a file to include.');
+
+                                               // Initialize:
+                                       $this->handlerInstance[$handlerKey] = t3lib_div::makeInstance($cfgArray['config']['class']);
+                                       $this->handlerInstance[$handlerKey]->init($cfgArray,$this);
+
+                                       if (is_object($this->handlerInstance[$handlerKey])) {
+                                               $output = TRUE;
+                                       }
+                                       break;
+                               default:
+                                       die('ERROR: Invalid handler type: "'.$cfgArray['type'].'"');
+                                       break;
+                       }
 
-      return $output;
-    } else die('ERROR: No handler for key "'.$handlerKey.'"');
-  }
+                       return $output;
+               } else die('ERROR: No handler for key "'.$handlerKey.'"');
+       }
 
 
+       /**
+        * Checks whether the DBAL is currently inside an operation running on the "native" DB handler (i.e. MySQL)
+        *
+        * @return boolean      True if running on "native" DB handler (i.e. MySQL)
+        */
+       public function runningNative() {
+               return ((string)$this->handlerCfg[$this->lastHandlerKey]['type']==='native');
+       }
 
 
+       /**
+        * Checks whether the ADOdb handler is running with a driver that contains the argument
+        *
+        * @param string        $driver Driver name, matched with strstr().
+        * @return boolean      True if running with the given driver
+        */
+       public function runningADOdbDriver($driver) {
+               return strstr($this->handlerCfg[$this->lastHandlerKey]['config']['driver'], $driver);
+       }
 
 
 
@@ -2068,45 +2576,58 @@ class ux_t3lib_DB extends t3lib_DB {
 
 
 
-  /************************************
-  *
-  * Table/Field mapping
-  *
-  **************************************/
+       /************************************
+       *
+       * Table/Field mapping
+       *
+       **************************************/
 
-  /**
+       /**
         * Checks if mapping is needed for a table(list)
         *
         * @param       string          List of tables in query
-        * @param       boolean         If true, it will check only if FIELDs are configured and ignore the mapped table name if any.
-        * @return      mixed           Returns an array of table names (parsed version of input table) if mapping is needed, otherwise just false.
-        */
-  function map_needMapping($tableList,$fieldMappingOnly=FALSE) {
-
-    $key = $tableList.'|'.$fieldMappingOnly;
-    if (!isset($this->cache_mappingFromTableList[$key]))       {
-      $this->cache_mappingFromTableList[$key] = FALSE; // Default:
-
-      $tables = $this->SQLparser->parseFromTables($tableList);
-      if (is_array($tables))   {
-        foreach($tables as $tableCfg)  {
-          if ($fieldMappingOnly)       {
-            if (is_array($this->mapping[$tableCfg['table']]['mapFieldNames'])) {
-              $this->cache_mappingFromTableList[$key] = $tables;
-            }
-          } else {
-            if (is_array($this->mapping[$tableCfg['table']]))  {
-              $this->cache_mappingFromTableList[$key] = $tables;
-            }
-          }
-        }
-      }
-    }
-
-    return $this->cache_mappingFromTableList[$key];
-  }
-
-  /**
+        * @param       boolean         If TRUE, it will check only if FIELDs are configured and ignore the mapped table name if any.
+        * @return      mixed           Returns an array of table names (parsed version of input table) if mapping is needed, otherwise just FALSE.
+        */
+       protected function map_needMapping($tableList, $fieldMappingOnly = FALSE) {
+               $key = $tableList.'|'.$fieldMappingOnly;
+               if (!isset($this->cache_mappingFromTableList[$key])) {
+                       $this->cache_mappingFromTableList[$key] = FALSE;        // Default:
+
+                       $tables = $this->SQLparser->parseFromTables($tableList);
+                       if (is_array($tables)) {
+                               foreach ($tables as $tableCfg) {
+                                       if ($fieldMappingOnly) {
+                                               if (is_array($this->mapping[$tableCfg['table']]['mapFieldNames'])) {
+                                                       $this->cache_mappingFromTableList[$key] = $tables;
+                                               } elseif (is_array($tableCfg['JOIN'])) {
+                                                       foreach ($tableCfg['JOIN'] as $join) {
+                                                               if (is_array($this->mapping[$join['withTable']]['mapFieldNames'])) {
+                                                                       $this->cache_mappingFromTableList[$key] = $tables;
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+                                       } else {
+                                               if (is_array($this->mapping[$tableCfg['table']])) {
+                                                       $this->cache_mappingFromTableList[$key] = $tables;
+                                               } elseif (is_array($tableCfg['JOIN'])) {
+                                                       foreach ($tableCfg['JOIN'] as $join) {
+                                                               if (is_array($this->mapping[$join['withTable']])) {
+                                                                       $this->cache_mappingFromTableList[$key] = $tables;
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               return $this->cache_mappingFromTableList[$key];
+       }
+
+       /**
         * Takes an associated array with field => value pairs and remaps the field names if configured for this table in $this->mapping array.
         * Be careful not to map a field name to another existing fields name (although you can use this to swap fieldnames of course...:-)
         * Observe mapping problems with join-results (more than one table): Joined queries should always prefix the table name to avoid problems with this.
@@ -2114,47 +2635,46 @@ class ux_t3lib_DB extends t3lib_DB {
         *
         * @param       array           Input array, associative keys
         * @param       array           Array of tables from the query. Normally just one table; many tables in case of a join. NOTICE: for multiple tables (with joins) there MIGHT occur trouble with fields of the same name in the two tables: This function traverses the mapping information for BOTH tables and applies mapping without checking from which table the field really came!
-        * @param       boolean         If true, reverse direction. Default direction is to map an array going INTO the database (thus mapping TYPO3 fieldnames to PHYSICAL field names!)
+        * @param       boolean         If TRUE, reverse direction. Default direction is to map an array going INTO the database (thus mapping TYPO3 fieldnames to PHYSICAL field names!)
         * @return      array           Output array, with mapped associative keys.
         */
-  function map_assocArray($input,$tables,$rev=FALSE)   {
-
-    // Traverse tables from query (hopefully only one table):
-    foreach($tables as $tableCfg)      {
-      if (is_array($this->mapping[$tableCfg['table']]['mapFieldNames']))       {
-
-        // Get the map (reversed if needed):
-        if ($rev)      {
-          $theMap = array_flip($this->mapping[$tableCfg['table']]['mapFieldNames']);
-        } else {
-          $theMap = $this->mapping[$tableCfg['table']]['mapFieldNames'];
-        }
+       protected function map_assocArray($input, $tables, $rev = FALSE) {
+                       // Traverse tables from query (hopefully only one table):
+               foreach ($tables as $tableCfg) {
+                       if (is_array($this->mapping[$tableCfg['table']]['mapFieldNames'])) {
+
+                                       // Get the map (reversed if needed):
+                               if ($rev) {
+                                       $theMap = array_flip($this->mapping[$tableCfg['table']]['mapFieldNames']);
+                               } else {
+                                       $theMap = $this->mapping[$tableCfg['table']]['mapFieldNames'];
+                               }
 
-        // Traverse selected record, map fieldnames:
-        $output = array();
-        foreach($input as $fN => $value)       {
+                                       // Traverse selected record, map fieldnames:
+                               $output = array();
+                               foreach ($input as $fN => $value) {
 
-          // Set the field name, change it if found in mapping array:
-          if ($theMap[$fN])    {
-            $newKey = $theMap[$fN];
-          } else {
-            $newKey = $fN;
-          }
+                                               // Set the field name, change it if found in mapping array:
+                                       if ($theMap[$fN]) {
+                                               $newKey = $theMap[$fN];
+                                       } else {
+                                               $newKey = $fN;
+                                       }
 
-          // Set value to fieldname:
-          $output[$newKey] = $value;
-        }
+                                               // Set value to fieldname:
+                                       $output[$newKey] = $value;
+                               }
 
-        // When done, override the $input array with the result:
-        $input = $output;
-      }
-    }
+                                       // When done, override the $input array with the result:
+                               $input = $output;
+                       }
+               }
 
-    // Return input array (which might have been altered in the mean time)
-    return $input;
-  }
+                       // Return input array (which might have been altered in the mean time)
+               return $input;
+       }
 
-  /**
+       /**
         * Remaps table/field names in a SELECT query's parts
         * Notice: All arguments are passed by reference!
         *
@@ -2166,41 +2686,63 @@ class ux_t3lib_DB extends t3lib_DB {
         * @return      void
         * @see exec_SELECTquery()
         */
-  function map_remapSELECTQueryParts(&$select_fields,&$from_table,&$where_clause,&$groupBy,&$orderBy)  {
-
-    // Tables:
-    $tables = $this->SQLparser->parseFromTables($from_table);
-    $defaultTable = $tables[0]['table'];
-    foreach($tables as $k => $v)       {
-      if ($this->mapping[$v['table']]['mapTableName']) {
-        $tables[$k]['table'] = $this->mapping[$v['table']]['mapTableName'];
-      }
-    }
-    $from_table = $this->SQLparser->compileFromTables($tables);
-
-    // Where clause:
-    $whereParts = $this->SQLparser->parseWhereClause($where_clause);
-    $this->map_sqlParts($whereParts,$defaultTable);
-    $where_clause = $this->SQLparser->compileWhereClause($whereParts);
-
-    // Select fields:
-    $expFields = $this->SQLparser->parseFieldList($select_fields);
-    $this->map_sqlParts($expFields,$defaultTable);
-    $select_fields = $this->SQLparser->compileFieldList($expFields);
-
-    // Group By fields
-    $expFields = $this->SQLparser->parseFieldList($groupBy);
-    $this->map_sqlParts($expFields,$defaultTable);
-    $groupBy = $this->SQLparser->compileFieldList($expFields);
-
-    // Order By fields
-    $expFields = $this->SQLparser->parseFieldList($orderBy);
-    $this->map_sqlParts($expFields,$defaultTable);
-    $orderBy = $this->SQLparser->compileFieldList($expFields);
-  }
-
-  /**
-        * Generic mapping of table/field names arrays (as parsed by t3lib_sqlengine)
+       protected function map_remapSELECTQueryParts(&$select_fields, &$from_table, &$where_clause, &$groupBy, &$orderBy) {
+                       // Tables:
+               $tables = $this->SQLparser->parseFromTables($from_table);
+               $defaultTable = $tables[0]['table'];
+               foreach ($tables as $k => $v) {
+                       if ($this->mapping[$v['table']]['mapTableName']) {
+                               $tables[$k]['table'] = $this->mapping[$v['table']]['mapTableName'];
+                       }
+                               // Mapping JOINS
+                       if (is_array($v['JOIN'])) {
+                               foreach($v['JOIN'] as $joinCnt => $join) {
+                                               // Mapping withTable of the JOIN
+                                       if ($this->mapping[$join['withTable']]['mapTableName']) {
+                                               $tables[$k]['JOIN'][$joinCnt]['withTable'] = $this->mapping[$join['withTable']]['mapTableName'];                                        
+                                       }
+                                       $onPartsArray = array();
+                                               // Mapping ON parts of the JOIN
+                                       if (is_array($join['ON'])) {
+                                               foreach ($join['ON'] as $onParts) {
+                                                       if (isset($this->mapping[$onParts['table']]['mapFieldNames'][$onParts['field']])) {
+                                                               $onParts['field'] = $this->mapping[$onParts['table']]['mapFieldNames'][$onParts['field']];
+                                                       }
+                                                       if (isset($this->mapping[$onParts['table']]['mapTableName'])) {
+                                                               $onParts['table'] = $this->mapping[$onParts['table']]['mapTableName'];
+                                                       }
+                                                       $onPartsArray[] = $onParts;
+                                               }
+                                               $tables[$k]['JOIN'][$joinCnt]['ON'] = $onPartsArray;
+                                       }
+                               }
+                       }
+               }
+               $from_table = $this->SQLparser->compileFromTables($tables);
+
+                       // Where clause:
+               $whereParts = $this->SQLparser->parseWhereClause($where_clause);
+               $this->map_sqlParts($whereParts,$defaultTable);
+               $where_clause = $this->SQLparser->compileWhereClause($whereParts, FALSE);
+
+                       // Select fields:
+               $expFields = $this->SQLparser->parseFieldList($select_fields);
+               $this->map_sqlParts($expFields,$defaultTable);
+               $select_fields = $this->SQLparser->compileFieldList($expFields, FALSE, FALSE);
+
+                       // Group By fields
+               $expFields = $this->SQLparser->parseFieldList($groupBy);
+               $this->map_sqlParts($expFields,$defaultTable);
+               $groupBy = $this->SQLparser->compileFieldList($expFields);
+
+                       // Order By fields
+               $expFields = $this->SQLparser->parseFieldList($orderBy);
+               $this->map_sqlParts($expFields,$defaultTable);
+               $orderBy = $this->SQLparser->compileFieldList($expFields);
+       }
+
+       /**
+        * Generic mapping of table/field names arrays (as parsed by tx_dbal_sqlengine)
         *
         * @param       array           Array with parsed SQL parts; Takes both fields, tables, where-parts, group and order-by. Passed by reference.
         * @param       string          Default table name to assume if no table is found in $sqlPartArray
@@ -2208,117 +2750,241 @@ class ux_t3lib_DB extends t3lib_DB {
         * @access private
         * @see map_remapSELECTQueryParts()
         */
-  function map_sqlParts(&$sqlPartArray, $defaultTable) {
-
-    // Traverse sql Part array:
-    if (is_array($sqlPartArray))       {
-      foreach($sqlPartArray as $k => $v)       {
-
-        // Look for sublevel (WHERE parts only)
-        if (is_array($sqlPartArray[$k]['sub']))        {
-          $this->map_sqlParts($sqlPartArray[$k]['sub'], $defaultTable);        // Call recursively!
-        } else {
-          // For the field, look for table mapping (generic):
-          $t = $sqlPartArray[$k]['table'] ? $sqlPartArray[$k]['table'] : $defaultTable;
-
-          // Mapping field name, if set:
-          if (is_array($this->mapping[$t]['mapFieldNames']) && $this->mapping[$t]['mapFieldNames'][$sqlPartArray[$k]['field']])        {
-            $sqlPartArray[$k]['field'] = $this->mapping[$t]['mapFieldNames'][$sqlPartArray[$k]['field']];
-          }
-
-          // Map table?
-          if ($sqlPartArray[$k]['table'] && $this->mapping[$sqlPartArray[$k]['table']]['mapTableName'])        {
-            $sqlPartArray[$k]['table'] = $this->mapping[$sqlPartArray[$k]['table']]['mapTableName'];
-          }
-        }
-      }
-    }
-  }
-
-  /**
-        * Will do table/field mapping on a general t3lib_sqlengine-compliant SQL query
+       protected function map_sqlParts(&$sqlPartArray, $defaultTable) {
+                       // Traverse sql Part array:
+               if (is_array($sqlPartArray)) {
+                       foreach ($sqlPartArray as $k => $v) {
+
+                               if (isset($sqlPartArray[$k]['type'])) {
+                                       switch ($sqlPartArray[$k]['type']) {
+                                               case 'flow-control':
+                                                       $temp = array($sqlPartArray[$k]['flow-control']);
+                                                       $this->map_sqlParts($temp, $defaultTable);      // Call recursively!
+                                                       $sqlPartArray[$k]['flow-control'] = $temp[0];
+                                                       break;
+                                               case 'CASE':
+                                                       if (isset($sqlPartArray[$k]['case_field'])) {
+                                                               $fieldArray = explode('.', $sqlPartArray[$k]['case_field']);
+                                                               if (count($fieldArray) == 1 && is_array($this->mapping[$defaultTable]['mapFieldNames']) && isset($this->mapping[$defaultTable]['mapFieldNames'][$fieldArray[0]])) {
+                                                                       $sqlPartArray[$k]['case_field'] = $this->mapping[$defaultTable]['mapFieldNames'][$fieldArray[0]];
+                                                               }
+                                                               elseif (count($fieldArray) == 2) {
+                                                                               // Map the external table
+                                                                       $table = $fieldArray[0];
+                                                                       if (isset($this->mapping[$fieldArray[0]]['mapTableName'])) {
+                                                                               $table = $this->mapping[$fieldArray[0]]['mapTableName'];
+                                                                       }
+                                                                               // Map the field itself
+                                                                       $field = $fieldArray[1];
+                                                                       if (is_array($this->mapping[$fieldArray[0]]['mapFieldNames']) && isset($this->mapping[$fieldArray[0]]['mapFieldNames'][$fieldArray[1]])) {
+                                                                               $field = $this->mapping[$fieldArray[0]]['mapFieldNames'][$fieldArray[1]];
+                                                                       }
+                                                                       $sqlPartArray[$k]['case_field'] = $table . '.' . $field;
+                                                               }
+                                                       }
+                                                       foreach ($sqlPartArray[$k]['when'] as $key => $when) {
+                                                               $this->map_sqlParts($sqlPartArray[$k]['when'][$key]['when_value'], $defaultTable);
+                                                       }
+                                                       break;
+                                       }
+                               }
+
+                                       // Look for sublevel (WHERE parts only)
+                               if (is_array($sqlPartArray[$k]['sub'])) {
+                                       $this->map_sqlParts($sqlPartArray[$k]['sub'], $defaultTable);   // Call recursively!
+                               } elseif (isset($sqlPartArray[$k]['func'])) {
+                                       switch ($sqlPartArray[$k]['func']['type']) {
+                                               case 'EXISTS':
+                                                       $subqueryDefaultTable = $sqlPartArray[$k]['func']['subquery']['FROM'][0]['table'];
+                                                       $this->map_sqlParts($sqlPartArray[$k]['func']['subquery']['SELECT'], $subqueryDefaultTable);
+                                                       $this->map_sqlParts($sqlPartArray[$k]['func']['subquery']['FROM'], $subqueryDefaultTable);
+                                                       $this->map_sqlParts($sqlPartArray[$k]['func']['subquery']['WHERE'], $subqueryDefaultTable);
+                                                       break;
+                                               case 'IFNULL':
+                                               case 'LOCATE':
+                                                               // For the field, look for table mapping (generic):
+                                                       $t = $sqlPartArray[$k]['func']['table'] ? $sqlPartArray[$k]['func']['table'] : $defaultTable;
+                                                       if (is_array($this->mapping[$t]['mapFieldNames']) && $this->mapping[$t]['mapFieldNames'][$sqlPartArray[$k]['func']['field']]) {
+                                                               $sqlPartArray[$k]['func']['field'] = $this->mapping[$t]['mapFieldNames'][$sqlPartArray[$k]['func']['field']];
+                                                       }
+                                                       if ($this->mapping[$t]['mapTableName']) {
+                                                               $sqlPartArray[$k]['func']['table'] = $this->mapping[$t]['mapTableName'];
+                                                       }
+                                                       break;
+                                       }
+                               } else {
+                                               // For the field, look for table mapping (generic):
+                                       $t = $sqlPartArray[$k]['table'] ? $sqlPartArray[$k]['table'] : $defaultTable;
+
+                                               // Mapping field name, if set:
+                                       if (is_array($this->mapping[$t]['mapFieldNames']) && isset($this->mapping[$t]['mapFieldNames'][$sqlPartArray[$k]['field']])) {
+                                               $sqlPartArray[$k]['field'] = $this->mapping[$t]['mapFieldNames'][$sqlPartArray[$k]['field']];
+                                       }
+
+                                               // Mapping field name in SQL-functions like MIN(), MAX() or SUM()
+                                       if ($this->mapping[$t]['mapFieldNames']) {
+                                               $fieldArray = explode('.', $sqlPartArray[$k]['func_content']);
+                                               if (count($fieldArray) == 1 && is_array($this->mapping[$t]['mapFieldNames']) && isset($this->mapping[$t]['mapFieldNames'][$fieldArray[0]])) {
+                                                       $sqlPartArray[$k]['func_content.'][0]['func_content'] = $this->mapping[$t]['mapFieldNames'][$fieldArray[0]];
+                                                       $sqlPartArray[$k]['func_content'] = $this->mapping[$t]['mapFieldNames'][$fieldArray[0]];
+                                               }
+                                               elseif (count($fieldArray) == 2) {
+                                                               // Map the external table
+                                                       $table = $fieldArray[0];
+                                                       if (isset($this->mapping[$fieldArray[0]]['mapTableName'])) {
+                                                               $table = $this->mapping[$fieldArray[0]]['mapTableName'];
+                                                       }
+                                                               // Map the field itself
+                                                       $field = $fieldArray[1];
+                                                       if (is_array($this->mapping[$fieldArray[0]]['mapFieldNames']) && isset($this->mapping[$fieldArray[0]]['mapFieldNames'][$fieldArray[1]])) {
+                                                               $field = $this->mapping[$fieldArray[0]]['mapFieldNames'][$fieldArray[1]];
+                                                       }
+                                                       $sqlPartArray[$k]['func_content.'][0]['func_content'] = $table . '.' . $field;
+                                                       $sqlPartArray[$k]['func_content'] = $table . '.' . $field;
+                                               }
+
+                                                       // Mapping flow-control statements
+                                               if (isset($sqlPartArray[$k]['flow-control'])) {                                                 
+                                                       if (isset($sqlPartArray[$k]['flow-control']['type'])) {
+                                                               $temp = array($sqlPartArray[$k]['flow-control']);
+                                                               $this->map_sqlParts($temp, $t); // Call recursively!
+                                                               $sqlPartArray[$k]['flow-control'] = $temp[0];
+                                                       }
+                                               }
+                                       }
+
+                                               // Do we have a function (e.g., CONCAT)
+                                       if (isset($v['value']['operator'])) {
+                                               foreach ($sqlPartArray[$k]['value']['args'] as $argK => $fieldDef) {
+                                                       if (isset($this->mapping[$fieldDef['table']]['mapTableName'])) {
+                                                               $sqlPartArray[$k]['value']['args'][$argK]['table'] = $this->mapping[$fieldDef['table']]['mapTableName'];
+                                                       }
+                                                       if (is_array($this->mapping[$fieldDef['table']]['mapFieldNames']) && isset($this->mapping[$fieldDef['table']]['mapFieldNames'][$fieldDef['field']])) {
+                                                               $sqlPartArray[$k]['value']['args'][$argK]['field'] = $this->mapping[$fieldDef['table']]['mapFieldNames'][$fieldDef['field']];   
+                                                       }
+                                               }
+                                       }
+
+                                               // Do we have a subquery (WHERE parts only)?
+                                       if (isset($sqlPartArray[$k]['subquery'])) {
+                                               $subqueryDefaultTable = $sqlPartArray[$k]['subquery']['FROM'][0]['table'];
+                                               $this->map_sqlParts($sqlPartArray[$k]['subquery']['SELECT'], $subqueryDefaultTable);
+                                               $this->map_sqlParts($sqlPartArray[$k]['subquery']['FROM'], $subqueryDefaultTable);
+                                               $this->map_sqlParts($sqlPartArray[$k]['subquery']['WHERE'], $subqueryDefaultTable);
+                                       }
+
+                                               // do we have a field name in the value?
+                                               // this is a very simplistic check, beware
+                                       if (!is_numeric($sqlPartArray[$k]['value'][0]) && !isset($sqlPartArray[$k]['value'][1])) {
+                                               $fieldArray = explode('.', $sqlPartArray[$k]['value'][0]);
+                                               if (count($fieldArray) == 1 && is_array($this->mapping[$t]['mapFieldNames']) && isset($this->mapping[$t]['mapFieldNames'][$fieldArray[0]])) {
+                                                       $sqlPartArray[$k]['value'][0] = $this->mapping[$t]['mapFieldNames'][$fieldArray[0]];
+                                               } elseif (count($fieldArray) == 2) {
+                                                               // Map the external table
+                                                       $table = $fieldArray[0];
+                                                       if (isset($this->mapping[$fieldArray[0]]['mapTableName'])) {
+                                                               $table = $this->mapping[$fieldArray[0]]['mapTableName'];
+                                                       }
+                                                               // Map the field itself
+                                                       $field = $fieldArray[1];
+                                                       if (is_array($this->mapping[$fieldArray[0]]['mapFieldNames']) && isset($this->mapping[$fieldArray[0]]['mapFieldNames'][$fieldArray[1]])) {
+                                                               $field = $this->mapping[$fieldArray[0]]['mapFieldNames'][$fieldArray[1]];
+                                                       }
+                                                       $sqlPartArray[$k]['value'][0] = $table . '.' . $field;
+                                               }
+                                       }
+
+                                               // Map table?
+                                       if ($sqlPartArray[$k]['table'] && $this->mapping[$sqlPartArray[$k]['table']]['mapTableName']) {
+                                               $sqlPartArray[$k]['table'] = $this->mapping[$sqlPartArray[$k]['table']]['mapTableName'];
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Will do table/field mapping on a general tx_dbal_sqlengine-compliant SQL query
         * (May still not support all query types...)
         *
-        * @param       array           Parsed QUERY as from t3lib_sqlengine::parseSQL(). NOTICE: Passed by reference!
+        * @param       array           Parsed QUERY as from tx_dbal_sqlengine::parseSQL(). NOTICE: Passed by reference!
         * @return      void
-        * @see t3lib_sqlengine::parseSQL()
-        */
-  function map_genericQueryParsed(&$parsedQuery)       {
-
-    // Getting table - same for all:
-    $table = $parsedQuery['TABLE'];
-    if ($table)        {
-      // Do field mapping if needed:
-      if ($tableArray = $this->map_needMapping($table))        {
-
-        // Table name:
-        if ($this->mapping[$table]['mapTableName'])    {
-          $parsedQuery['TABLE'] = $this->mapping[$table]['mapTableName'];
-        }
-
-        // Based on type, do additional changes:
-        switch($parsedQuery['type'])   {
-          case 'ALTERTABLE':
-
-          // Changing field name:
-          $newFieldName = $this->mapping[$table]['mapFieldNames'][$parsedQuery['FIELD']];
-          if ($newFieldName)   {
-            if ($parsedQuery['FIELD'] == $parsedQuery['newField'])     {
-              $parsedQuery['FIELD'] = $parsedQuery['newField'] = $newFieldName;
-            } else $parsedQuery['FIELD'] = $newFieldName;
-          }
-
-          // Changing key field names:
-          if (is_array($parsedQuery['fields']))        {
-            $this->map_fieldNamesInArray($table,$parsedQuery['fields']);
-          }
-          break;
-          case 'CREATETABLE':
-          // Remapping fields:
-          if (is_array($parsedQuery['FIELDS']))        {
-            $newFieldsArray = array();
-            foreach($parsedQuery['FIELDS'] as $fN => $fInfo)   {
-              if ($this->mapping[$table]['mapFieldNames'][$fN])        {
-                $fN = $this->mapping[$table]['mapFieldNames'][$fN];
-              }
-              $newFieldsArray[$fN] = $fInfo;
-            }
-            $parsedQuery['FIELDS'] = $newFieldsArray;
-          }
-
-          // Remapping keys:
-          if (is_array($parsedQuery['KEYS']))  {
-            foreach($parsedQuery['KEYS'] as $kN => $kInfo)     {
-              $this->map_fieldNamesInArray($table,$parsedQuery['KEYS'][$kN]);
-            }
-          }
-          break;
-
-
-          /// ... and here support for all other query types should be!
-
-
-        }
-      }
-    } else die('ERROR, mapping: No table found in parsed Query array...');
-  }
-
-  /**
+        * @see tx_dbal_sqlengine::parseSQL()
+        */
+       protected function map_genericQueryParsed(&$parsedQuery) {
+
+                       // Getting table - same for all:
+               $table = $parsedQuery['TABLE'];
+               if ($table) {
+                               // Do field mapping if needed:
+                       if ($tableArray = $this->map_needMapping($table)) {
+
+                                       // Table name:
+                               if ($this->mapping[$table]['mapTableName']) {
+                                       $parsedQuery['TABLE'] = $this->mapping[$table]['mapTableName'];
+                               }
+
+                                       // Based on type, do additional changes:
+                               switch ($parsedQuery['type']) {
+                                       case 'ALTERTABLE':
+
+                                               // Changing field name:
+                                       $newFieldName = $this->mapping[$table]['mapFieldNames'][$parsedQuery['FIELD']];
+                                       if ($newFieldName) {
+                                               if ($parsedQuery['FIELD'] == $parsedQuery['newField']) {
+                                                       $parsedQuery['FIELD'] = $parsedQuery['newField'] = $newFieldName;
+                                               } else $parsedQuery['FIELD'] = $newFieldName;
+                                       }
+
+                                               // Changing key field names:
+                                       if (is_array($parsedQuery['fields'])) {
+                                               $this->map_fieldNamesInArray($table,$parsedQuery['fields']);
+                                       }
+                                       break;
+                                       case 'CREATETABLE':
+                                               // Remapping fields:
+                                       if (is_array($parsedQuery['FIELDS'])) {
+                                               $newFieldsArray = array();
+                                               foreach ($parsedQuery['FIELDS'] as $fN => $fInfo) {
+                                                       if ($this->mapping[$table]['mapFieldNames'][$fN]) {
+                                                               $fN = $this->mapping[$table]['mapFieldNames'][$fN];
+                                                       }
+                                                       $newFieldsArray[$fN] = $fInfo;
+                                               }
+                                               $parsedQuery['FIELDS'] = $newFieldsArray;
+                                       }
+
+                                               // Remapping keys:
+                                       if (is_array($parsedQuery['KEYS'])) {
+                                               foreach ($parsedQuery['KEYS'] as $kN => $kInfo) {
+                                                       $this->map_fieldNamesInArray($table,$parsedQuery['KEYS'][$kN]);
+                                               }
+                                       }
+                                       break;
+
+                                       /// ... and here support for all other query types should be!
+
+                               }
+                       }
+               } else die('ERROR, mapping: No table found in parsed Query array...');
+       }
+
+       /**
         * Re-mapping field names in array
         *
         * @param       string          (TYPO3) Table name for fields.
         * @param       array           Array of fieldnames to remap. Notice: Passed by reference!
         * @return      void
         */
-  function map_fieldNamesInArray($table,&$fieldArray)  {
-    if (is_array($this->mapping[$table]['mapFieldNames']))     {
-      foreach($fieldArray as $k => $v) {
-        if ($this->mapping[$table]['mapFieldNames'][$v])       {
-          $fieldArray[$k] = $this->mapping[$table]['mapFieldNames'][$v];
-        }
-      }
-    }
-  }
+       protected function map_fieldNamesInArray($table,&$fieldArray) {
+               if (is_array($this->mapping[$table]['mapFieldNames'])) {
+                       foreach ($fieldArray as $k => $v) {
+                               if ($this->mapping[$table]['mapFieldNames'][$v]) {
+                                       $fieldArray[$k] = $this->mapping[$table]['mapFieldNames'][$v];
+                               }
+                       }
+               }
+       }
 
 
 
@@ -2336,13 +3002,13 @@ class ux_t3lib_DB extends t3lib_DB {
 
 
 
-  /**************************************
-  *
-  * Debugging
-  *
-  **************************************/
+       /**************************************
+       *
+       * Debugging
+       *
+       **************************************/
 
-  /**
+       /**
         * Debug handler for query execution
         *
         * @param       string          Function name from which this function is called.
@@ -2351,136 +3017,176 @@ class ux_t3lib_DB extends t3lib_DB {
         * @return      void
         * @access private
         */
-  function debugHandler($function,$execTime,$inData)   {
-    // we don't want to log our own log/debug SQL
-    $script = substr(PATH_thisScript,strlen(PATH_site));
-    if (substr($script,-strlen('dbal/mod1/index.php'))!='dbal/mod1/index.php' &&
-    !strstr($inData['args'][0], 'tx_dbal_debuglog'))   {
-      $data = array();
-      $errorFlag = 0;
-      $joinTable = '';
-
-      if ($this->sql_error())  {
-        $data['sqlError'] = $this->sql_error();
-        $errorFlag|=1;
-      }
-
-      // if lastQuery is empty (for whatever reason) at least log inData.args
-      if(empty($this->lastQuery))
-      $query = implode(' ',$inData['args']);
-      else
-      $query = $this->lastQuery;
-
-      switch($function)        {
-        case 'exec_INSERTquery':
-        case 'exec_UPDATEquery':
-        case 'exec_DELETEquery':
-        $this->debug_log($query,$execTime,$data,$joinTable,$errorFlag, $script);
-        break;
-
-        case 'exec_SELECTquery':
-        // Get explain data:
-        if ($this->conf['debugOptions']['EXPLAIN'] && t3lib_div::inList('adodb,native',$inData['handlerType']))        {
-          $data['EXPLAIN'] = $this->debug_explain($this->lastQuery);
-        }
-
-        // Check parsing of Query:
-        if ($this->conf['debugOptions']['parseQuery']) {
-          $parseResults = array();
-          $parseResults['SELECT'] = $this->SQLparser->debug_parseSQLpart('SELECT',$inData['args'][1]);
-          $parseResults['FROM'] = $this->SQLparser->debug_parseSQLpart('FROM',$inData['args'][0]);
-          $parseResults['WHERE'] = $this->SQLparser->debug_parseSQLpart('WHERE',$inData['args'][2]);
-          $parseResults['GROUPBY'] = $this->SQLparser->debug_parseSQLpart('SELECT',$inData['args'][3]);        // Using select field list syntax
-          $parseResults['ORDERBY'] = $this->SQLparser->debug_parseSQLpart('SELECT',$inData['args'][4]);        // Using select field list syntax
-
-          foreach($parseResults as $k => $v)   {
-            if (!strlen($parseResults[$k]))    unset($parseResults[$k]);
-          }
-          if (count($parseResults))    {
-            $data['parseError'] = $parseResults;
-            $errorFlag|=2;
-          }
-        }
-
-        // Checking joinTables:
-        if ($this->conf['debugOptions']['joinTables']) {
-          if (count(explode(',', $inData['ORIG_from_table']))>1)               {
-            $joinTable = $inData['args'][0];
-          }
-        }
-
-        // Logging it:
-        $this->debug_log($query,$execTime,$data,$joinTable,$errorFlag, $script);
-        if(!empty($inData['args'][2]))
-        $this->debug_WHERE($inData['args'][0], $inData['args'][2], $script);
-        break;
-      }
-    }
-  }
-
-  /**
-   * Log the where clause for debugging purposes.
-   *
-   * @param string $table
-   * @param string $where
-   */
-  function debug_WHERE($table,$where, $script='')      {
-    $insertArray = array (
-    'tstamp' => $GLOBALS['EXEC_TIME'],
-    'beuser_id' => intval($GLOBALS['BE_USER']->user['uid']),
-    'script' => $script,
-    'tablename' => $table,
-    'whereclause' => $where
-    );
-
-    $this->exec_INSERTquery('tx_dbal_debuglog_where', $insertArray);
-  }
-
-  /**
-        * Insert row in the log table
+       public function debugHandler($function,$execTime,$inData) {
+                       // we don't want to log our own log/debug SQL
+               $script = substr(PATH_thisScript,strlen(PATH_site));
+
+               if (substr($script,-strlen('dbal/mod1/index.php'))!='dbal/mod1/index.php' && !strstr($inData['args'][0], 'tx_dbal_debuglog')) {
+                       $data = array();
+                       $errorFlag = 0;
+                       $joinTable = '';
+
+                       if ($this->sql_error()) {
+                               $data['sqlError'] = $this->sql_error();
+                               $errorFlag|=1;
+                       }
+
+                               // if lastQuery is empty (for whatever reason) at least log inData.args
+                       if (empty($this->lastQuery))
+                               $query = implode(' ',$inData['args']);
+                       else
+                               $query = $this->lastQuery;
+
+                       if ($this->conf['debugOptions']['backtrace']) {
+                               $backtrace = debug_backtrace();
+                               unset($backtrace[0]); // skip this very method :)
+                               $data['backtrace'] = array_slice($backtrace, 0, $this->conf['debugOptions']['backtrace']);
+                       }
+
+                       switch ($function) {
+                               case 'exec_INSERTquery':
+                               case 'exec_UPDATEquery':
+                               case 'exec_DELETEquery':
+                                       $this->debug_log($query,$execTime,$data,$joinTable,$errorFlag, $script);
+                                       break;
+
+                               case 'exec_SELECTquery':
+                                               // Get explain data:
+                                       if ($this->conf['debugOptions']['EXPLAIN'] && t3lib_div::inList('adodb,native',$inData['handlerType'])) {
+                                               $data['EXPLAIN'] = $this->debug_explain($this->lastQuery);
+                                       }
+
+                                               // Check parsing of Query:
+                                       if ($this->conf['debugOptions']['parseQuery']) {
+                                               $parseResults = array();
+                                               $parseResults['SELECT'] = $this->SQLparser->debug_parseSQLpart('SELECT',$inData['args'][1]);
+                                               $parseResults['FROM'] = $this->SQLparser->debug_parseSQLpart('FROM',$inData['args'][0]);
+                                               $parseResults['WHERE'] = $this->SQLparser->debug_parseSQLpart('WHERE',$inData['args'][2]);
+                                               $parseResults['GROUPBY'] = $this->SQLparser->debug_parseSQLpart('SELECT',$inData['args'][3]);   // Using select field list syntax
+                                               $parseResults['ORDERBY'] = $this->SQLparser->debug_parseSQLpart('SELECT',$inData['args'][4]);   // Using select field list syntax
+
+                                               foreach ($parseResults as $k => $v) {
+                                                       if (!strlen($parseResults[$k])) unset($parseResults[$k]);
+                                               }
+                                               if (count($parseResults)) {
+                                                       $data['parseError'] = $parseResults;
+                                                       $errorFlag|=2;
+                                               }
+                                       }
+
+                                               // Checking joinTables:
+                                       if ($this->conf['debugOptions']['joinTables']) {
+                                               if (count(explode(',', $inData['ORIG_from_table']))>1) {
+                                                       $joinTable = $inData['args'][0];
+                                               }
+                                       }
+
+                                               // Logging it:
+                                       $this->debug_log($query,$execTime,$data,$joinTable,$errorFlag, $script);
+                                       if (!empty($inData['args'][2]))
+                                               $this->debug_WHERE($inData['args'][0], $inData['args'][2], $script);
+                                       break;
+                       }
+               }
+       }
+
+       /**
+        * Logs the where clause for debugging purposes.
+        *
+        * @param string $table Table name(s) the query was targeted at
+        * @param string $where The WHERE clause to be logged
+        * @param string $script        The script calling the logging
+        * @return void
+        */
+       public function debug_WHERE($table, $where, $script = '') {
+               $insertArray = array (
+                       'tstamp' => $GLOBALS['EXEC_TIME'],
+                       'beuser_id' => intval($GLOBALS['BE_USER']->user['uid']),
+                       'script' => $script,
+                       'tablename' => $table,
+                       'whereclause' => $where
+               );
+
+               $this->exec_INSERTquery('tx_dbal_debuglog_where', $insertArray);
+       }
+
+       /**
+        * Inserts row in the log table
         *
         * @param       string          The current query
         * @param       integer         Execution time of query in milliseconds
         * @param       array           Data to be stored serialized.
         * @param       string          Join string if there IS a join.
         * @param       integer         Error status.
+        * @param string $script        The script calling the logging
         * @return      void
         */
-  function debug_log($query,$ms,$data,$join,$errorFlag, $script='')    {
-    $insertArray = array (
-    'tstamp' => $GLOBALS['EXEC_TIME'],
-    'beuser_id' => intval($GLOBALS['BE_USER']->user['uid']),
-    'script' => $script,
-    'exec_time' => $ms,
-    'table_join' => $join,
-    'serdata' => serialize($data),
-    'query' => (is_array($query) ? $query[0].' WITH '.count($query[1]).' BLOB FIELDS: '.implode(', ',array_keys($query[1])) : $query),
-    'errorFlag' => $errorFlag
-    );
-
-    $this->exec_INSERTquery('tx_dbal_debuglog', $insertArray);
-  }
-
-  /**
+       public function debug_log($query,$ms,$data,$join,$errorFlag, $script='') {
+               if (is_array($query)) {
+                       $queryToLog = $query[0].' --  ';
+                       if (count($query[1])) {
+                               $queryToLog .= count($query[1]).' BLOB FIELDS: '.implode(', ',array_keys($query[1]));
+                       }
+                       if (count($query[2])) {
+                               $queryToLog .= count($query[2]).' CLOB FIELDS: '.implode(', ',array_keys($query[2]));
+                       }
+               } else {
+                       $queryToLog = $query;
+               }
+               $insertArray = array (
+                       'tstamp' => $GLOBALS['EXEC_TIME'],
+                       'beuser_id' => intval($GLOBALS['BE_USER']->user['uid']),
+                       'script' => $script,
+                       'exec_time' => $ms,
+                       'table_join' => $join,
+                       'serdata' => serialize($data),
+                       'query' => $queryToLog,
+                       'errorFlag' => $errorFlag
+               );
+
+               $this->exec_INSERTquery('tx_dbal_debuglog', $insertArray);
+       }
+
+       /**
         * Perform EXPLAIN query on DEFAULT handler!
         *
         * @param       string          SELECT Query
         * @return      array           The Explain result rows in an array
         * @todo        Not supporting other than the default handler? And what about DBMS of other kinds than MySQL - support for EXPLAIN?
         */
-  function debug_explain($query)       {
-    $res = $this->sql_query('EXPLAIN '.$query);
+       public function debug_explain($query) {
+               $output = array();
+               $hType = (string)$this->handlerCfg[$this->lastHandlerKey]['type'];
+               switch ($hType) {
+                       case 'native':
+                               $res = $this->sql_query('EXPLAIN '.$query);
+                               while($row = $this->sql_fetch_assoc($res)) {
+                                       $output[] = $row;
+                               }
+                               break;
+                       case 'adodb':
+                               switch ($this->handlerCfg['_DEFAULT']['config']['driver']) {
+                                       case 'oci8':
+                                               $res = $this->sql_query('EXPLAIN PLAN '.$query);
+                                               $output[] = 'EXPLAIN PLAN data logged to default PLAN_TABLE';
+                                               break;
+                                       default:
+                                               $res = $this->sql_query('EXPLAIN '.$query);
+                                               while($row = $this->sql_fetch_assoc($res)) {
+                                                       $output[] = $row;
+                                               }
+                                               break;
+                               }
+                       break;
+               }
 
-    $output = array();
-    while($row = $this->sql_fetch_assoc($res)) {
-      $output[] = $row;
-    }
-    return $output;
-  }
+               return $output;
+       }
 }
 
 
-if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dbal/class.ux_t3lib_db.php']) {
-  include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dbal/class.ux_t3lib_db.php']);
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dbal/class.ux_t3lib_db.php']) {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dbal/class.ux_t3lib_db.php']);
 }
-?>
+
+?>
\ No newline at end of file