Merged branch QueryCache to trunk
authorXavier Perseguers <typo3@perseguers.ch>
Mon, 20 Sep 2010 20:12:59 +0000 (20:12 +0000)
committerXavier Perseguers <typo3@perseguers.ch>
Mon, 20 Sep 2010 20:12:59 +0000 (20:12 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Extensions/dbal/trunk@38370 735d13b6-9817-0410-8766-e36946ffe9aa

typo3/sysext/dbal/ChangeLog
typo3/sysext/dbal/class.ux_t3lib_db.php
typo3/sysext/dbal/doc/manual.sxw
typo3/sysext/dbal/ext_autoload.php
typo3/sysext/dbal/lib/class.tx_dbal_querycache.php [new file with mode: 0644]
typo3/sysext/dbal/lib/class.tx_dbal_sqlengine.php

index 5d45e43..d02459f 100644 (file)
@@ -1,11 +1,18 @@
 2010-09-20  Xavier Perseguers  <typo3@perseguers.ch>
 
+       * Merged branch QueryCache to trunk
+       * Updated documentation to describe how to use Memcached to cache prepared queries
        * Fixed bug #15751: dbal does not parse setDBinit correctly (thanks to Tamer Erdogan)
 
 2010-08-30  Xavier Perseguers  <typo3@perseguers.ch>
 
        * Fixed bug #15582: Call to deprecated function template::middle()
 
+2010-08-24  Xavier Perseguers  <typo3@perseguers.ch>
+
+       * Fixed caching with Memcached
+       * Synchronized code from trunk
+
 2010-08-23  Xavier Perseguers  <typo3@perseguers.ch>
 
        * Fixed bug #15535: Error: No pages are found on the rootlevel! in Frontend when using Oracle
@@ -14,6 +21,8 @@
 
 2010-08-19  Xavier Perseguers  <typo3@perseguers.ch>
 
+       * Updated caching mechanism to cache prepared queries
+       * Synchronized code from trunk
        * Added unit test for feature #15457
        * Added feature #15457: Add support for prepared queries
 
 
        * Added feature #13508: Use exec_TRUNCATEquery() instead of DELETE FROM throughout the core
 
+2010-04-06  Xavier Perseguers  <typo3@perseguers.ch>
+
+       * Added skeleton of a cache for generated queries
+
 2010-03-07  Xavier Perseguers  <typo3@perseguers.ch>
 
        * Fixed bug #4640: Backend login impossible with MSSQL via ODBC (thanks to Felix Eckhofer)
index 66802bb..378aea9 100644 (file)
  *
  *
  *
- *  123: class ux_t3lib_DB extends t3lib_DB
- *  169:     function ux_t3lib_DB()
- *  184:     function initInternalVariables()
+ *  161: class ux_t3lib_DB extends t3lib_DB
+ *  229:     public function __construct()
+ *  260:     protected function initInternalVariables()
+ *  283:     public function clearCachedFieldInfo()
+ *  294:     public function cacheFieldInfo()
+ *  342:     protected function analyzeFields($parsedExtSQL)
+ *  375:     protected function mapCachedFieldInfo($fieldInfo)
  *
  *              SECTION: Query Building (Overriding parent methods)
- *  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 = '')
+ *  438:     public function exec_INSERTquery($table, $fields_values, $no_quote_fields = '')
+ *  575:     public function exec_INSERTmultipleRows($table, array $fields, array $rows, $no_quote_fields = FALSE)
+ *  600:     public function exec_UPDATEquery($table,$where,$fields_values,$no_quote_fields = '')
+ *  692:     public function exec_DELETEquery($table, $where)
+ *  759:     public function exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '')
+ *  856:     public function exec_TRUNCATEquery($table)
+ *  914:     protected function exec_query(array $queryParts)
  *
- *              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 = '')
- *  556:     function quoteSelectFields(&$select_fields)
- *  573:     function quoteFromTables(&$from_table)
- *  595:     function quoteWhereClause(&$where_clause)
- *  620:     function quoteGroupBy(&$groupBy)
- *  637:     function quoteOrderBy(&$orderBy)
+ *              SECTION: Query building
+ *  978:     public function INSERTquery($table, $fields_values, $no_quote_fields = '')
+ * 1052:     public function INSERTmultipleRows($table, array $fields, array $rows, $no_quote_fields = FALSE)
+ * 1085:     public function UPDATEquery($table, $where, $fields_values, $no_quote_fields = '')
+ * 1170:     public function DELETEquery($table, $where)
+ * 1196:     public function SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '')
+ * 1229:     protected function SELECTqueryFromArray(array $params)
+ * 1267:     protected function compileSelectParameters(array $params)
+ * 1283:     public function TRUNCATEquery($table)
+ *
+ *              SECTION: Prepared Query Support
+ * 1314:     public function prepare_SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '', array $input_parameters = array())
+ * 1416:     protected function getQueryComponents($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit)
+ * 1465:     protected function precompileSELECTquery(array $components)
+ * 1523:     public function exec_PREPAREDquery($query, array $precompiledParts)
+ *
+ *              SECTION: Functions for quoting table/field names
+ * 1619:     protected function quoteSELECTsubquery(array $components)
+ * 1634:     public function quoteSelectFields($select_fields)
+ * 1644:     public function quoteFieldNames($select_fields)
+ * 1664:     protected function _quoteFieldNames(array $select_fields)
+ * 1701:     public function quoteFromTables($from_table)
+ * 1717:     protected function _quoteFromTables(array $from_table)
+ * 1746:     public function quoteWhereClause($where_clause)
+ * 1767:     protected function _quoteWhereClause(array $where_clause)
+ * 1843:     protected function quoteGroupBy($groupBy)
+ * 1860:     protected function _quoteGroupBy(array $groupBy)
+ * 1877:     protected function quoteOrderBy($orderBy)
+ * 1894:     protected function _quoteOrderBy(array $orderBy)
  *
  *              SECTION: Various helper functions
- *  663:     function quoteStr($str, $table)
+ * 1919:     public function fullQuoteStr($str, $table)
+ * 1932:     public function quoteStr($str, $table)
+ * 1965:     public function quoteName($name, $handlerKey = NULL, $useBackticks = FALSE)
+ * 1984:     public function MetaType($type, $table, $max_length = -1)
+ * 2015:     public function MySQLMetaType($t)
+ * 2062:     public function MySQLActualType($meta)
  *
  *              SECTION: SQL wrapper functions (Overriding parent methods)
- *  707:     function sql_error()
- *  734:     function sql_num_rows(&$res)
- *  760:     function sql_fetch_assoc(&$res)
- *  808:     function sql_fetch_row(&$res)
- *  842:     function sql_free_result(&$res)
- *  868:     function sql_insert_id()
- *  893:     function sql_affected_rows()
- *  919:     function sql_data_seek(&$res,$seek)
- *  946:     function sql_field_type(&$res,$pointer)
+ * 2105:     public function sql_error()
+ * 2125:     public function sql_errno()
+ * 2146:     public function sql_num_rows(&$res)
+ * 2170:     public function sql_fetch_assoc(&$res)
+ * 2233:     public function sql_fetch_row(&$res)
+ * 2279:     public function sql_free_result(&$res)
+ * 2308:     public function sql_insert_id()
+ * 2328:     public function sql_affected_rows()
+ * 2350:     public function sql_data_seek(&$res, $seek)
+ * 2375:     public function sql_field_metatype($table, $field)
+ * 2405:     public function sql_field_type(&$res,$pointer)
  *
  *              SECTION: Legacy functions, bound to _DEFAULT handler. (Overriding parent methods)
- *  987:     function sql($db,$query)
- *  999:     function sql_query($query)
- * 1035:     function sql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password)
- * 1055:     function sql_select_db($TYPO3_db)
+ * 2459:     public function sql($db,$query)
+ * 2477:     public function sql_query($query)
+ * 2516:     public function sql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password)
+ * 2534:     public function sql_select_db($TYPO3_db)
  *
  *              SECTION: SQL admin functions
- * 1086:     function admin_get_tables()
- * 1149:     function admin_get_fields($tableName)
- * 1210:     function admin_get_keys($tableName)
- * 1270:     function admin_query($query)
+ * 2566:     public function admin_get_dbs()
+ * 2607:     public function admin_get_tables()
+ * 2673:     public function admin_get_fields($tableName)
+ * 2742:     public function admin_get_keys($tableName)
+ * 2847:     public function admin_get_charsets()
+ * 2857:     public function admin_query($query)
  *
  *              SECTION: Handler management
- * 1333:     function handler_getFromTableList($tableList)
- * 1379:     function handler_init($handlerKey)
+ * 2941:     public function handler_getFromTableList($tableList)
+ * 2989:     public function handler_init($handlerKey)
+ * 3107:     public function isConnected()
+ * 3127:     public function runningNative()
+ * 3138:     public function runningADOdbDriver($driver)
  *
  *              SECTION: Table/Field mapping
- * 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)
- * 1717:     function map_fieldNamesInArray($table,&$fieldArray)
+ * 3165:     protected function map_needMapping($tableList, $fieldMappingOnly = FALSE, array &$parsedTableList = array())
+ * 3215:     protected function map_assocArray($input, $tables, $rev = FALSE)
+ * 3263:     protected function map_remapSELECTQueryParts($select_fields, $from_table, $where_clause, $groupBy, $orderBy)
+ * 3357:     protected function getMappingKey($tableName)
+ * 3371:     protected function getFreeMappingKey($tableName)
+ * 3387:     protected function map_sqlParts(&$sqlPartArray, $defaultTable)
+ * 3549:     protected function map_subquery(&$parsedQuery)
+ * 3589:     protected function map_genericQueryParsed(&$parsedQuery)
+ * 3654:     protected function map_fieldNamesInArray($table,&$fieldArray)
  *
  *              SECTION: Debugging
- * 1758:     function debugHandler($function,$execTime,$inData)
- * 1823:     function debug_log($query,$ms,$data,$join,$errorFlag)
- * 1849:     function debug_explain($query)
+ * 3695:     public function debugHandler($function,$execTime,$inData)
+ * 3790:     public function debug_WHERE($table, $where, $script = '')
+ * 3813:     public function debug_log($query,$ms,$data,$join,$errorFlag, $script='')
+ * 3846:     public function debug_explain($query)
  *
- * TOTAL FUNCTIONS: 41
+ * TOTAL FUNCTIONS: 82
  * (This index is automatically created/updated by the extension "extdeveval")
  *
  */
@@ -167,6 +212,13 @@ class ux_t3lib_DB extends t3lib_DB {
         */
        var $Installer;
 
+       /**
+        * Cache for queries
+        *
+        * @var t3lib_cache_frontend_VariableFrontend
+        */
+       protected $queryCache;
+
 
        /**
         * Constructor.
@@ -177,6 +229,22 @@ class ux_t3lib_DB extends t3lib_DB {
                $this->SQLparser = t3lib_div::makeInstance('tx_dbal_sqlengine');
                $this->Installer = t3lib_div::makeInstance('t3lib_install');
 
+               if (TYPO3_UseCachingFramework) {
+                       tx_dbal_querycache::initializeCachingFramework();
+
+                       try {
+                               $this->queryCache = $GLOBALS['typo3CacheManager']->getCache(
+                                       'dbal'
+                               );
+                       } catch (t3lib_cache_exception_NoSuchCache $e) {
+                               tx_dbal_querycache::initDbalCache();
+
+                               $this->queryCache = $GLOBALS['typo3CacheManager']->getCache(
+                                       'dbal'
+                               );
+                       }
+               }
+
                        // Set internal variables with configuration:
                $this->conf = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['dbal'];
                $this->initInternalVariables();
@@ -1243,35 +1311,67 @@ class ux_t3lib_DB extends t3lib_DB {
                        $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:
-               $parsedFromTable = array();
-               $queryComponents = array();
-               if ($tableArray = $this->map_needMapping($ORIG_tableName, FALSE, $parsedFromTable)) {
-                       $from = $parsedFromTable ? $parsedFromTable : $from_table;
-                       $components = $this->map_remapSELECTQueryParts($select_fields, $from, $where_clause, $groupBy, $orderBy);
-                       $queryComponents['SELECT']     = $components[0];
-                       $queryComponents['FROM']       = $components[1];
-                       $queryComponents['WHERE']      = $components[2];
-                       $queryComponents['GROUPBY']    = $components[3];
-                       $queryComponents['ORDERBY']    = $components[4];
-                       $queryComponents['parameters'] = $components[5];
-               } else {
-                       $queryComponents = $this->getQueryComponents($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
-               }
+               $precompiledParts = array();
 
-               $queryComponents['ORIG_tableName'] = $ORIG_tableName;
+               if ($this->queryCache) {
+                       $cacheKey = 'prepare_SELECTquery-' . tx_dbal_querycache::getCacheKey(array(
+                               'selectFields' => $select_fields,
+                               'fromTable'    => $from_table,
+                               'whereClause'  => $where_clause,
+                               'groupBy'      => $groupBy,
+                               'orderBy'      => $orderBy,
+                               'limit'        => $limit,
+                       ));
+                       if ($this->queryCache->has($cacheKey)) {
+                               $precompiledParts = $this->queryCache->get($cacheKey);
+                               if ($this->debug) {
+                                       $data = array(
+                                               'args' => array($from_table, $select_fields, $where_clause, $groupBy, $orderBy, $limit, $input_parameters),
+                                               'precompiledParts' => $precompiledParts,
+                                       );
+                                       $this->debugHandler(
+                                               'prepare_SELECTquery (cache hit)',
+                                               t3lib_div::milliseconds() - $pt,
+                                               $data
+                                       );
+                               }
+                       }
+               }
+
+               if (count($precompiledParts) == 0) {
+                               // Map table / field names if needed:
+                       $ORIG_tableName = $from_table;  // Saving table names in $ORIG_from_table since $from_table is transformed beneath:
+                       $parsedFromTable = array();
+                       $queryComponents = array();
+                       if ($tableArray = $this->map_needMapping($ORIG_tableName, FALSE, $parsedFromTable)) {
+                               $from = $parsedFromTable ? $parsedFromTable : $from_table;
+                               $components = $this->map_remapSELECTQueryParts($select_fields, $from, $where_clause, $groupBy, $orderBy);
+                               $queryComponents['SELECT']     = $components[0];
+                               $queryComponents['FROM']       = $components[1];
+                               $queryComponents['WHERE']      = $components[2];
+                               $queryComponents['GROUPBY']    = $components[3];
+                               $queryComponents['ORDERBY']    = $components[4];
+                               $queryComponents['parameters'] = $components[5];
+                       } else {
+                               $queryComponents = $this->getQueryComponents($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
+                       }
 
-               if (!$this->runningNative()) {
-                               // Quotes all fields
-                       $queryComponents['SELECT']  = $this->_quoteFieldNames($queryComponents['SELECT']);
-                       $queryComponents['FROM']    = $this->_quoteFromTables($queryComponents['FROM']);
-                       $queryComponents['WHERE']   = $this->_quoteWhereClause($queryComponents['WHERE']);
-                       $queryComponents['GROUPBY'] = $this->_quoteGroupBy($queryComponents['GROUPBY']);
-                       $queryComponents['ORDERBY'] = $this->_quoteOrderBy($queryComponents['ORDERBY']);
-               }
+                       $queryComponents['ORIG_tableName'] = $ORIG_tableName;
 
-               $precompiledParts = $this->precompileSELECTquery($queryComponents);
+                       if (!$this->runningNative()) {
+                                       // Quotes all fields
+                               $queryComponents['SELECT']  = $this->_quoteFieldNames($queryComponents['SELECT']);
+                               $queryComponents['FROM']    = $this->_quoteFromTables($queryComponents['FROM']);
+                               $queryComponents['WHERE']   = $this->_quoteWhereClause($queryComponents['WHERE']);
+                               $queryComponents['GROUPBY'] = $this->_quoteGroupBy($queryComponents['GROUPBY']);
+                               $queryComponents['ORDERBY'] = $this->_quoteOrderBy($queryComponents['ORDERBY']);
+                       }
+
+                       $precompiledParts = $this->precompileSELECTquery($queryComponents);
+                       if ($this->queryCache) {
+                               $this->queryCache->set($cacheKey, $precompiledParts);
+                       }
+               }
 
                $preparedStatement = t3lib_div::makeInstance('t3lib_db_PreparedStatement', '', $from_table, $precompiledParts);
                /* @var $preparedStatement t3lib_db_PreparedStatement */
index fa2f4a8..60f94f6 100644 (file)
Binary files a/typo3/sysext/dbal/doc/manual.sxw and b/typo3/sysext/dbal/doc/manual.sxw differ
index 4e54f1b..263768b 100644 (file)
@@ -1,10 +1,11 @@
 <?php
 // DO NOT CHANGE THIS FILE! It is automatically generated by extdeveval::buildAutoloadRegistry.
-// This file was generated on 2009-10-26 22:04
+// This file was generated on 2010-04-06 21:47
 
 
 $extensionPath = t3lib_extMgm::extPath('dbal');
 return array(
+       'tx_dbal_querycache' => $extensionPath . 'lib/class.tx_dbal_querycache.php',
        'tx_dbal_sqlengine' => $extensionPath . 'lib/class.tx_dbal_sqlengine.php',
        'ux_t3lib_sqlparser' => $extensionPath . 'class.ux_t3lib_sqlparser.php',
 );
diff --git a/typo3/sysext/dbal/lib/class.tx_dbal_querycache.php b/typo3/sysext/dbal/lib/class.tx_dbal_querycache.php
new file mode 100644 (file)
index 0000000..ff5c142
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 Xavier Perseguers <typo3@perseguers.ch>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+
+/**
+ * Cache engine helper for generated queries.
+ *
+ * $Id$
+ *
+ * @author Xavier Perseguers <typo3@perseguers.ch>
+ * @package TYPO3
+ * @subpackage dbal
+ */
+class tx_dbal_querycache {
+
+       /**
+        * Initializes the caching framework by loading the cache manager and factory
+        * into the global context.
+        *
+        * @return      void
+        */
+       public static function initializeCachingFramework() {
+               t3lib_cache::initializeCachingFramework();
+       }
+
+       /**
+        * Initializes the DBAL cache.
+        *
+        * @return      void
+        */
+       public static function initDbalCache() {
+               try {
+                       if (is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['dbal'])) {
+                               $backend = $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['dbal']['backend'];
+                               $options = $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['dbal']['options'];
+                       } else {
+                                       // Transient storage, will be better than nothing
+                               $backend = 't3lib_cache_backend_TransientMemoryBackend';
+                               $options = array();
+                       }
+
+                       $GLOBALS['typo3CacheFactory']->create(
+                               'dbal',
+                               't3lib_cache_frontend_VariableFrontend',
+                               $backend,
+                               $options
+                       );
+               } catch (t3lib_cache_exception_DuplicateIdentifier $e) {
+                               // Do nothing, a DBAL cache already exists
+               }
+       }
+
+       /**
+        * Returns a proper cache key.
+        *
+        * @param       mixed           $config
+        * @return      void
+        */
+       public static function getCacheKey($config) {
+               if (is_array($config)) {
+                       return md5(serialize($config));
+               } else {
+                       return $config;
+               }
+       }
+}
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dbal/lib/class.tx_dbal_querycache.php']) {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dbal/lib/class.tx_dbal_querycache.php']);
+}
+
+?>
\ No newline at end of file
index 0c1f6d9..a940d9c 100644 (file)
  *
  *
  *
- *  104: class tx_dbal_sqlengine extends ux_t3lib_sqlparser
- *  126:     function init($config, &$pObj)
- *  134:     function resetStatusVars()
- *  150:     function processAccordingToConfig(&$value,$fInfo)
+ *  106: class tx_dbal_sqlengine extends ux_t3lib_sqlparser
+ *  128:     public function init($config, $pObj)
+ *  136:     public function resetStatusVars()
+ *  152:     private function processAccordingToConfig(&$value, $fInfo)
  *
  *              SECTION: SQL queries
- *  205:     function exec_INSERTquery($table,$fields_values)
- *  273:     function exec_UPDATEquery($table,$where,$fields_values)
- *  332:     function exec_DELETEquery($table,$where)
- *  383:     function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit)
- *  426:     function sql_query($query)
- *  437:     function sql_error()
- *  446:     function sql_insert_id()
- *  455:     function sql_affected_rows()
- *  465:     function quoteStr($str)
+ *  207:     public function exec_INSERTquery($table, $fields_values)
+ *  275:     public function exec_UPDATEquery($table, $where, $fields_values)
+ *  334:     public function exec_DELETEquery($table, $where)
+ *  385:     public function exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit)
+ *  428:     public function sql_query($query)
+ *  439:     public function sql_error()
+ *  448:     public function sql_insert_id()
+ *  457:     public function sql_affected_rows()
+ *  467:     public function quoteStr($str)
  *
  *              SECTION: SQL admin functions
- *  490:     function admin_get_tables()
- *  501:     function admin_get_fields($tableName)
- *  512:     function admin_get_keys($tableName)
- *  523:     function admin_query($query)
+ *  493:     public function admin_get_tables()
+ *  504:     public function admin_get_fields($tableName)
+ *  515:     public function admin_get_keys($tableName)
+ *  526:     public function admin_query($query)
  *
  *              SECTION: Data Source I/O
- *  548:     function readDataSource($table)
- *  560:     function saveDataSource($table)
+ *  551:     public function readDataSource($table)
+ *  563:     public function saveDataSource($table)
  *
  *              SECTION: SQL engine functions (PHP simulation of SQL) - still experimental
- *  590:     function selectFromData($table,$where)
- *  628:     function select_evalSingle($table,$config,&$itemKeys)
- *  747:     function getResultSet($keys, $table, $fieldList)
+ *  593:     public function selectFromData($table, $where)
+ *  631:     public function select_evalSingle($table,$config,&$itemKeys)
+ *  750:     public function getResultSet($keys, $table, $fieldList)
  *
  *              SECTION: Debugging
- *  790:     function debug_printResultSet($array)
+ *  793:     public function debug_printResultSet($array)
  *
  *
- *  829: class tx_dbal_sqlengine_resultobj
- *  843:     function sql_num_rows()
- *  852:     function sql_fetch_assoc()
- *  863:     function sql_fetch_row()
- *  881:     function sql_data_seek($pointer)
- *  894:     function sql_field_type()
+ *  832: class tx_dbal_sqlengine_resultobj
+ *  846:     public function sql_num_rows()
+ *  855:     public function sql_fetch_assoc()
+ *  866:     public function sql_fetch_row()
+ *  884:     public function sql_data_seek($pointer)
+ *  897:     public function sql_field_type()
  *
  * TOTAL FUNCTIONS: 27
  * (This index is automatically created/updated by the extension "extdeveval")