TYPO3 API  SVNRelease
class.tx_dbal_sqlengine.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003  *  Copyright notice
00004  *
00005  *  (c) 2009-2010 Xavier Perseguers <typo3@perseguers.ch>
00006  *  (c) 2004-2009 Kasper Skårhøj <kasperYYYY@typo3.com>
00007  *  All rights reserved
00008  *
00009  *  This script is part of the TYPO3 project. The TYPO3 project is
00010  *  free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  The GNU General Public License can be found at
00016  *  http://www.gnu.org/copyleft/gpl.html.
00017  *  A copy is found in the textfile GPL.txt and important notices to the license
00018  *  from the author is found in LICENSE.txt distributed with these scripts.
00019  *
00020  *
00021  *  This script is distributed in the hope that it will be useful,
00022  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024  *  GNU General Public License for more details.
00025  *
00026  *  This copyright notice MUST APPEAR in all copies of the script!
00027  ***************************************************************/
00028 
00029 
00030 /**
00031  * PHP SQL engine
00032  *
00033  * $Id: class.tx_dbal_sqlengine.php 40828 2010-12-05 14:55:53Z xperseguers $
00034  *
00035  * @author Kasper Skårhøj <kasperYYYY@typo3.com>
00036  * @author Xavier Perseguers <typo3@perseguers.ch>
00037  */
00038 /**
00039  * [CLASS/FUNCTION INDEX of SCRIPT]
00040  *
00041  *
00042  *
00043  *  106: class tx_dbal_sqlengine extends ux_t3lib_sqlparser
00044  *  128:     public function init($config, $pObj)
00045  *  136:     public function resetStatusVars()
00046  *  152:     private function processAccordingToConfig(&$value, $fInfo)
00047  *
00048  *            SECTION: SQL queries
00049  *  207:     public function exec_INSERTquery($table, $fields_values)
00050  *  275:     public function exec_UPDATEquery($table, $where, $fields_values)
00051  *  334:     public function exec_DELETEquery($table, $where)
00052  *  385:     public function exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit)
00053  *  428:     public function sql_query($query)
00054  *  439:     public function sql_error()
00055  *  448:     public function sql_insert_id()
00056  *  457:     public function sql_affected_rows()
00057  *  467:     public function quoteStr($str)
00058  *
00059  *            SECTION: SQL admin functions
00060  *  493:     public function admin_get_tables()
00061  *  504:     public function admin_get_fields($tableName)
00062  *  515:     public function admin_get_keys($tableName)
00063  *  526:     public function admin_query($query)
00064  *
00065  *            SECTION: Data Source I/O
00066  *  551:     public function readDataSource($table)
00067  *  563:     public function saveDataSource($table)
00068  *
00069  *            SECTION: SQL engine functions (PHP simulation of SQL) - still experimental
00070  *  593:     public function selectFromData($table, $where)
00071  *  631:     public function select_evalSingle($table,$config,&$itemKeys)
00072  *  750:     public function getResultSet($keys, $table, $fieldList)
00073  *
00074  *            SECTION: Debugging
00075  *  793:     public function debug_printResultSet($array)
00076  *
00077  *
00078  *  832: class tx_dbal_sqlengine_resultobj
00079  *  846:     public function sql_num_rows()
00080  *  855:     public function sql_fetch_assoc()
00081  *  866:     public function sql_fetch_row()
00082  *  884:     public function sql_data_seek($pointer)
00083  *  897:     public function sql_field_type()
00084  *
00085  * TOTAL FUNCTIONS: 27
00086  * (This index is automatically created/updated by the extension "extdeveval")
00087  *
00088  */
00089 
00090 
00091 /**
00092  * PHP SQL engine / server
00093  * Basically this is trying to emulation SQL record selection by PHP, thus allowing SQL queries into alternative data storages managed by PHP.
00094  * EXPERIMENTAL!
00095  *
00096  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00097  * @package TYPO3
00098  * @subpackage t3lib
00099  */
00100 class tx_dbal_sqlengine extends ux_t3lib_sqlparser {
00101 
00102     // array with data records: [table name][num.index] = records
00103     var $data = array(); // Data source storage
00104 
00105 
00106     // Internal, SQL Status vars:
00107     var $errorStatus = ''; // Set with error message of last operation
00108     var $lastInsertedId = 0; // Set with last inserted unique ID
00109     var $lastAffectedRows = 0; // Set with last number of affected rows.
00110 
00111 
00112     /**
00113      * Dummy function for initializing SQL handler. Create you own in derived classes.
00114      *
00115      * @param   array       Configuration array from handler
00116      * @param   object      Parent object
00117      * @return  void
00118      */
00119     public function init($config, $pObj) {
00120     }
00121 
00122     /**
00123      * Reset SQL engine status variables (insert id, affected rows, error status)
00124      *
00125      * @return  void
00126      */
00127     public function resetStatusVars() {
00128         $this->errorStatus = '';
00129         $this->lastInsertedId = 0;
00130         $this->lastAffectedRows = 0;
00131     }
00132 
00133     /**
00134      * Processing of update/insert values based on field type.
00135      *
00136      * The input value is typecast and trimmed/shortened according to the field
00137      * type and the configuration options from the $fInfo parameter.
00138      *
00139      * @param   mixed       $value The input value to process
00140      * @param   array       $fInfo Field configuration data
00141      * @return  mixed       The processed input value
00142      */
00143     private function processAccordingToConfig(&$value, $fInfo) {
00144         $options = $this->parseFieldDef($fInfo['Type']);
00145 
00146         switch (strtolower($options['fieldType'])) {
00147             case 'int':
00148             case 'smallint':
00149             case 'tinyint':
00150             case 'mediumint':
00151                 $value = intval($value);
00152                 if ($options['featureIndex']['UNSIGNED']) {
00153                     $value = t3lib_div::intInRange($value, 0);
00154                 }
00155                 break;
00156             case 'double':
00157                 $value = (double) $value;
00158                 break;
00159             case 'varchar':
00160             case 'char':
00161                 $value = substr($value, 0, trim($options['value']));
00162                 break;
00163             case 'text':
00164             case 'blob':
00165                 $value = substr($value, 0, 65536);
00166                 break;
00167             case 'tinytext':
00168             case 'tinyblob':
00169                 $value = substr($value, 0, 256);
00170                 break;
00171             case 'mediumtext':
00172             case 'mediumblob':
00173                 // ??
00174                 break;
00175         }
00176     }
00177 
00178 
00179     /********************************
00180      *
00181      * SQL queries
00182      * This is the SQL access functions used when this class is instantiated as a SQL handler with DBAL. Override these in derived classes.
00183      *
00184      ********************************/
00185 
00186     /**
00187      * Execute an INSERT query
00188      *
00189      * @param   string      Table name
00190      * @param   array       Field values as key=>value pairs.
00191      * @return  boolean     TRUE on success and FALSE on failure (error is set internally)
00192      */
00193     public function exec_INSERTquery($table, $fields_values) {
00194 
00195         // Initialize
00196         $this->resetStatusVars();
00197 
00198         // Reading Data Source if not done already.
00199         $this->readDataSource($table);
00200 
00201         // If data source is set:
00202         if (is_array($this->data[$table])) {
00203 
00204             $fieldInformation = $this->admin_get_fields($table); // Should cache this...!
00205 
00206             // Looking for unique keys:
00207             $saveArray = array();
00208             foreach ($fieldInformation as $fInfo) {
00209 
00210                 // Field name:
00211                 $fN = $fInfo['Field'];
00212 
00213                 // Set value:
00214 // FIXME $options not defined
00215                 $saveArray[$fN] = isset($fields_values[$fN]) ? $fields_values[$fN] : $options['Default'];
00216 
00217                 // Process value:
00218                 $this->processAccordingToConfig($saveArray[$fN], $fInfo);
00219 
00220                 // If an auto increment field is found, find the largest current uid:
00221                 if ($fInfo['Extra'] == 'auto_increment') {
00222 
00223                     // Get all UIDs:
00224                     $uidArray = array();
00225                     foreach ($this->data[$table] as $r) {
00226                         $uidArray[] = $r[$fN];
00227                     }
00228 
00229                     // If current value is blank or already in array, we create a new:
00230                     if (!$saveArray[$fN] || in_array(intval($saveArray[$fN]), $uidArray)) {
00231                         if (count($uidArray)) {
00232                             $saveArray[$fN] = max($uidArray) + 1;
00233                         } else $saveArray[$fN] = 1;
00234                     }
00235 
00236                     // Update "last inserted id":
00237                     $this->lastInsertedId = $saveArray[$fN];
00238                 }
00239             }
00240 
00241             // Insert row in table:
00242             $this->data[$table][] = $saveArray;
00243 
00244             // Save data source
00245             $this->saveDataSource($table);
00246 
00247             return TRUE;
00248         } else $this->errorStatus = 'No data loaded.';
00249 
00250         return FALSE;
00251     }
00252 
00253     /**
00254      * Execute UPDATE query on table
00255      *
00256      * @param   string      Table name
00257      * @param   string      WHERE clause
00258      * @param   array       Field values as key=>value pairs.
00259      * @return  boolean     TRUE on success and FALSE on failure (error is set internally)
00260      */
00261     public function exec_UPDATEquery($table, $where, $fields_values) {
00262 
00263         // Initialize:
00264         $this->resetStatusVars();
00265 
00266         // Reading Data Source if not done already.
00267         $this->readDataSource($table);
00268 
00269         // If anything is there:
00270         if (is_array($this->data[$table])) {
00271 
00272             // Parse WHERE clause:
00273             $where = $this->parseWhereClause($where);
00274 
00275             if (is_array($where)) {
00276 
00277                 // Field information
00278                 $fieldInformation = $this->admin_get_fields($table); // Should cache this...!
00279 
00280                 // Traverse fields to update:
00281                 foreach ($fields_values as $fName => $fValue) {
00282                     $this->processAccordingToConfig($fields_values[$fName], $fieldInformation[$fName]);
00283                 }
00284 
00285                 // Do query, returns array with keys to the data array of the result:
00286                 $itemKeys = $this->selectFromData($table, $where);
00287 
00288                 // Set "last affected rows":
00289                 $this->lastAffectedRows = count($itemKeys);
00290 
00291                 // Update rows:
00292                 if ($this->lastAffectedRows) {
00293                     // Traverse result set here:
00294                     foreach ($itemKeys as $dataArrayKey) {
00295 
00296                         // Traverse fields to update:
00297                         foreach ($fields_values as $fName => $fValue) {
00298                             $this->data[$table][$dataArrayKey][$fName] = $fValue;
00299                         }
00300                     }
00301 
00302                     // Save data source
00303                     $this->saveDataSource($table);
00304                 }
00305 
00306                 return TRUE;
00307             } else $this->errorStatus = 'WHERE clause contained errors: ' . $where;
00308         } else $this->errorStatus = 'No data loaded.';
00309 
00310         return FALSE;
00311     }
00312 
00313     /**
00314      * Execute DELETE query
00315      *
00316      * @param   string      Table to delete from
00317      * @param   string      WHERE clause
00318      * @return  boolean     TRUE on success and FALSE on failure (error is set internally)
00319      */
00320     public function exec_DELETEquery($table, $where) {
00321 
00322         // Initialize:
00323         $this->resetStatusVars();
00324 
00325         // Reading Data Source if not done already.
00326         $this->readDataSource($table);
00327 
00328         // If anything is there:
00329         if (is_array($this->data[$table])) {
00330 
00331             // Parse WHERE clause:
00332             $where = $this->parseWhereClause($where);
00333 
00334             if (is_array($where)) {
00335 
00336                 // Do query, returns array with keys to the data array of the result:
00337                 $itemKeys = $this->selectFromData($table, $where);
00338 
00339                 // Set "last affected rows":
00340                 $this->lastAffectedRows = count($itemKeys);
00341 
00342                 // Remove rows:
00343                 if ($this->lastAffectedRows) {
00344                     // Traverse result set:
00345                     foreach ($itemKeys as $dataArrayKey) {
00346                         unset($this->data[$table][$dataArrayKey]);
00347                     }
00348 
00349                     // Saving data source
00350                     $this->saveDataSource($table);
00351                 }
00352 
00353                 return TRUE;
00354             } else $this->errorStatus = 'WHERE clause contained errors: ' . $where;
00355         } else $this->errorStatus = 'No data loaded.';
00356 
00357         return FALSE;
00358     }
00359 
00360     /**
00361      * Execute SELECT query
00362      *
00363      * @param   string      List of fields to select from the table. This is what comes right after "SELECT ...". Required value.
00364      * @param   string      Table(s) from which to select. This is what comes right after "FROM ...". Required value.
00365      * @param   string      Optional additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself! DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
00366      * @param   string      Optional GROUP BY field(s), if none, supply blank string.
00367      * @param   string      Optional ORDER BY field(s), if none, supply blank string.
00368      * @param   string      Optional LIMIT value ([begin,]max), if none, supply blank string.
00369      * @return  object      Returns result object, but if errors, returns false
00370      */
00371     public function exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit) {
00372 
00373         // Initialize:
00374         $this->resetStatusVars();
00375 
00376         // Create result object
00377         $sqlObj = t3lib_div::makeInstance('tx_dbal_sqlengine_resultobj');
00378         $sqlObj->result = array(); // Empty result as a beginning
00379 
00380         // Get table list:
00381         $tableArray = $this->parseFromTables($from_table);
00382         $table = $tableArray[0]['table'];
00383 
00384         // Reading Data Source if not done already.
00385         $this->readDataSource($table);
00386 
00387         // If anything is there:
00388         if (is_array($this->data[$table])) {
00389 
00390             // Parse WHERE clause:
00391             $where = $this->parseWhereClause($where_clause);
00392             if (is_array($where)) {
00393 
00394                 // Do query, returns array with keys to the data array of the result:
00395                 $itemKeys = $this->selectFromData($table, $where);
00396 
00397                 // Finally, read the result rows into this variable:
00398                 $sqlObj->result = $this->getResultSet($itemKeys, $table, '*');
00399                 // Reset and return result:
00400                 reset($sqlObj->result);
00401                 return $sqlObj;
00402             } else $this->errorStatus = 'WHERE clause contained errors: ' . $where;
00403         } else $this->errorStatus = 'No data loaded: ' . $this->errorStatus;
00404 
00405         return FALSE;
00406     }
00407 
00408     /**
00409      * Performs an SQL query on the "database"
00410      *
00411      * @param   string      Query to execute
00412      * @return  object      Result object or false if error
00413      */
00414     public function sql_query($query) {
00415         $res = t3lib_div::makeInstance('tx_dbal_sqlengine_resultobj');
00416         $res->result = array();
00417         return $res;
00418     }
00419 
00420     /**
00421      * Returns most recent error
00422      *
00423      * @return  string      Error message, if any
00424      */
00425     public function sql_error() {
00426         return $this->errorStatus;
00427     }
00428 
00429     /**
00430      * Returns most recently create unique ID (of INSERT queries)
00431      *
00432      * @return  integer     Last unique id created.
00433      */
00434     public function sql_insert_id() {
00435         return $this->lastInsertedId;
00436     }
00437 
00438     /**
00439      * Returns affected rows (of UPDATE and DELETE queries)
00440      *
00441      * @return  integer     Last amount of affected rows.
00442      */
00443     public function sql_affected_rows() {
00444         return $this->lastAffectedRows;
00445     }
00446 
00447     /**
00448      * Quoting strings for insertion in SQL queries
00449      *
00450      * @param   string      Input String
00451      * @return  string      String, with quotes escaped
00452      */
00453     public function quoteStr($str) {
00454         return addslashes($str);
00455     }
00456 
00457 
00458     /**************************************
00459      *
00460      * SQL admin functions
00461      * (For use in the Install Tool and Extension Manager)
00462      *
00463      **************************************/
00464 
00465     /**
00466      * (DUMMY) Returns the list of tables from the database
00467      *
00468      * @return  array       Tables in an array (tablename is in both key and value)
00469      * @todo    Should return table details in value! see t3lib_db::admin_get_tables()
00470      */
00471     public function admin_get_tables() {
00472         $whichTables = array();
00473         return $whichTables;
00474     }
00475 
00476     /**
00477      * (DUMMY) Returns information about each field in the $table
00478      *
00479      * @param   string      Table name
00480      * @return  array       Field information in an associative array with fieldname => field row
00481      */
00482     public function admin_get_fields($tableName) {
00483         $output = array();
00484         return $output;
00485     }
00486 
00487     /**
00488      * (DUMMY) Returns information about each index key in the $table
00489      *
00490      * @param   string      Table name
00491      * @return  array       Key information in a numeric array
00492      */
00493     public function admin_get_keys($tableName) {
00494         $output = array();
00495         return $output;
00496     }
00497 
00498     /**
00499      * (DUMMY) mysql() wrapper function, used by the Install Tool and EM for all queries regarding management of the database!
00500      *
00501      * @param   string      Query to execute
00502      * @return  pointer     Result pointer
00503      */
00504     public function admin_query($query) {
00505         return $this->sql_query($query);
00506     }
00507 
00508 
00509     /********************************
00510      *
00511      * Data Source I/O
00512      *
00513      ********************************/
00514 
00515     /**
00516      * Dummy function for setting table data. Create your own.
00517      * NOTICE: Handler to "table-locking" needs to be made probably!
00518      *
00519      * @param   string      Table name
00520      * @return  void
00521      * @todo    Table locking tools?
00522      */
00523     public function readDataSource($table) {
00524         $this->data[$table] = array();
00525     }
00526 
00527     /**
00528      * Dummy function for setting table data. Create your own.
00529      * NOTICE: Handler to "table-locking" needs to be made probably!
00530      *
00531      * @param   string      Table name
00532      * @return  void
00533      * @todo    Table locking tools?
00534      */
00535     public function saveDataSource($table) {
00536         debug($this->data[$table]);
00537     }
00538 
00539 
00540     /********************************
00541      *
00542      * SQL engine functions (PHP simulation of SQL) - still experimental
00543      *
00544      ********************************/
00545 
00546     /**
00547      * PHP simulation of SQL "SELECT"
00548      * Yet EXPERIMENTAL!
00549      *
00550      * @param   string      Table name
00551      * @param   array       Where clause parsed into array
00552      * @return  array       Array of keys pointing to result rows in $this->data[$table]
00553      */
00554     public function selectFromData($table, $where) {
00555 
00556         $output = array();
00557         if (is_array($this->data[$table])) {
00558 
00559             // All keys:
00560             $OR_index = 0;
00561 
00562             foreach ($where as $config) {
00563 
00564                 if (strtoupper($config['operator']) == 'OR') {
00565                     $OR_index++;
00566                 }
00567 // FIXME: unknown variable $itemKeys
00568                 if (!isset($itemKeys[$OR_index]))   $itemKeys[$OR_index] = array_keys($this->data[$table]);
00569 
00570                 $this->select_evalSingle($table, $config, $itemKeys[$OR_index]);
00571             }
00572 
00573             foreach ($itemKeys as $uidKeys) {
00574                 $output = array_merge($output, $uidKeys);
00575             }
00576             $output = array_unique($output);
00577         }
00578 
00579         return $output;
00580     }
00581 
00582     /**
00583      * Evalutaion of a WHERE-clause-array.
00584      * Yet EXPERIMENTAL
00585      *
00586      * @param   string      Tablename
00587      * @param   array       WHERE-configuration array
00588      * @param   array       Data array to work on.
00589      * @return  void        Data array passed by reference
00590      * @see selectFromData()
00591      */
00592     public function select_evalSingle($table, $config, &$itemKeys) {
00593         $neg = preg_match('/^AND[[:space:]]+NOT$/', trim($config['operator']));
00594 
00595         if (is_array($config['sub'])) {
00596             $subSelKeys = $this->selectFromData($table, $config['sub']);
00597             if ($neg) {
00598                 foreach ($itemKeys as $kk => $vv) {
00599                     if (in_array($vv, $subSelKeys)) {
00600                         unset($itemKeys[$kk]);
00601                     }
00602                 }
00603             } else {
00604                 $itemKeys = array_intersect($itemKeys, $subSelKeys);
00605             }
00606         } else {
00607             $comp = strtoupper(str_replace(array(' ', "\t", "\r", "\n"), '', $config['comparator']));
00608             $mod = strtoupper($config['modifier']);
00609             switch ($comp) {
00610                 case 'NOTLIKE':
00611                 case 'LIKE':
00612                     $like_value = strtolower($config['value'][0]);
00613                     if (substr($like_value, 0, 1) == '%') {
00614                         $wildCard_begin = TRUE;
00615                         $like_value = substr($like_value, 1);
00616                     }
00617                     if (substr($like_value, -1) == '%') {
00618                         $wildCard_end = TRUE;
00619                         $like_value = substr($like_value, 0, -1);
00620                     }
00621                     break;
00622                 case 'NOTIN':
00623                 case 'IN':
00624                     $in_valueArray = array();
00625                     foreach ($config['value'] as $vParts) {
00626                         $in_valueArray[] = (string) $vParts[0];
00627                     }
00628                     break;
00629             }
00630 
00631             foreach ($itemKeys as $kk => $v) {
00632                 $field_value = $this->data[$table][$v][$config['field']];
00633 
00634                 // Calculate it:
00635                 if ($config['calc'] == '&') {
00636                     $field_value &= intval($config['calc_value']);
00637                 }
00638 
00639                 // Compare it:
00640                 switch ($comp) {
00641                     case '<=':
00642                         $bool = $field_value <= $config['value'][0];
00643                         break;
00644                     case '>=':
00645                         $bool = $field_value >= $config['value'][0];
00646                         break;
00647                     case '<':
00648                         $bool = $field_value < $config['value'][0];
00649                         break;
00650                     case '>':
00651                         $bool = $field_value > $config['value'][0];
00652                         break;
00653                     case '=':
00654                         $bool = !strcmp($field_value, $config['value'][0]);
00655                         break;
00656                     case '!=':
00657                         $bool = strcmp($field_value, $config['value'][0]);
00658                         break;
00659                     case 'NOTIN':
00660                     case 'IN':
00661                         $bool = in_array((string) $field_value, $in_valueArray);
00662                         if ($comp == 'NOTIN')   $bool = !$bool;
00663                         break;
00664                     case 'NOTLIKE':
00665                     case 'LIKE':
00666                         if (!strlen($like_value)) {
00667                             $bool = TRUE;
00668                         } elseif ($wildCard_begin && !$wildCard_end) {
00669                             $bool = !strcmp(substr(strtolower($field_value), -strlen($like_value)), $like_value);
00670                         } elseif (!$wildCard_begin && $wildCard_end) {
00671                             $bool = !strcmp(substr(strtolower($field_value), 0, strlen($like_value)), $like_value);
00672                         } elseif ($wildCard_begin && $wildCard_end) {
00673                             $bool = strstr($field_value, $like_value);
00674                         } else {
00675                             $bool = !strcmp(strtolower($field_value), $like_value);
00676                         }
00677                         if ($comp == 'NOTLIKE') $bool = !$bool;
00678                         break;
00679                     default:
00680                         $bool = $field_value ? TRUE : FALSE;
00681                         break;
00682                 }
00683 
00684                 // General negation:
00685                 if ($neg)   $bool = !$bool;
00686 
00687                 // Modify?
00688                 switch ($mod) {
00689                     case 'NOT':
00690                     case '!':
00691                         $bool = !$bool;
00692                         break;
00693                 }
00694 
00695                 // Action:
00696                 if (!$bool) {
00697                     unset($itemKeys[$kk]);
00698                 }
00699             }
00700         }
00701     }
00702 
00703     /**
00704      * Returning result set based on result keys, table and field list
00705      *
00706      * @param   array       Result keys
00707      * @param   string      Tablename
00708      * @param   string      Fieldlist (commaseparated)
00709      * @return  array       Result array with "rows"
00710      */
00711     public function getResultSet($keys, $table, $fieldList) {
00712         $fields = t3lib_div::trimExplode(',', $fieldList);
00713 
00714         $output = array();
00715         foreach ($keys as $kValue) {
00716             if ($fieldList == '*') {
00717                 $output[$kValue] = $this->data[$table][$kValue];
00718             } else {
00719                 foreach ($fields as $fieldName) {
00720                     $output[$kValue][$fieldName] = $this->data[$table][$kValue][$fieldName];
00721                 }
00722             }
00723         }
00724 
00725         return $output;
00726     }
00727 
00728 
00729     /*************************
00730      *
00731      * Debugging
00732      *
00733      *************************/
00734 
00735     /**
00736      * Returns the result set (in array) as HTML table. For debugging.
00737      *
00738      * @param   array       Result set array (array of rows)
00739      * @return  string      HTML table
00740      */
00741     public function debug_printResultSet($array) {
00742 
00743         if (count($array)) {
00744             $tRows = array();
00745             $fields = array_keys(current($array));
00746             $tCell[] = '
00747                             <td>IDX</td>';
00748             foreach ($fields as $fieldName) {
00749                 $tCell[] = '
00750                             <td>' . htmlspecialchars($fieldName) . '</td>';
00751             }
00752             $tRows[] = '<tr>' . implode('', $tCell) . '</tr>';
00753 
00754 
00755             foreach ($array as $index => $rec) {
00756 
00757                 $tCell = array();
00758                 $tCell[] = '
00759                         <td>' . htmlspecialchars($index) . '</td>';
00760                 foreach ($fields as $fieldName) {
00761                     $tCell[] = '
00762                             <td>' . htmlspecialchars($rec[$fieldName]) . '</td>';
00763                 }
00764                 $tRows[] = '<tr>' . implode('', $tCell) . '</tr>';
00765             }
00766 
00767             return '<table border="1">' . implode('', $tRows) . '</table>';
00768         } else 'Empty resultset';
00769     }
00770 }
00771 
00772 
00773 /**
00774  * PHP SQL engine, result object
00775  *
00776  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00777  * @package TYPO3
00778  * @subpackage dbal
00779  */
00780 class tx_dbal_sqlengine_resultobj {
00781 
00782     // Result array, must contain the fields in the order they were selected in the SQL statement (for sql_fetch_row())
00783     var $result = array();
00784 
00785     var $TYPO3_DBAL_handlerType = '';
00786     var $TYPO3_DBAL_tableList = '';
00787 
00788 
00789     /**
00790      * Counting number of rows
00791      *
00792      * @return  integer
00793      */
00794     public function sql_num_rows() {
00795         return count($this->result);
00796     }
00797 
00798     /**
00799      * Fetching next row in result array
00800      *
00801      * @return  array       Associative array
00802      */
00803     public function sql_fetch_assoc() {
00804         $row = current($this->result);
00805         next($this->result);
00806         return $row;
00807     }
00808 
00809     /**
00810      * Fetching next row, numerical indices
00811      *
00812      * @return  array       Numerical array
00813      */
00814     public function sql_fetch_row() {
00815         $resultRow = $this->sql_fetch_assoc();
00816 
00817         if (is_array($resultRow)) {
00818             $numArray = array();
00819             foreach ($resultRow as $value) {
00820                 $numArray[] = $value;
00821             }
00822             return $numArray;
00823         }
00824     }
00825 
00826     /**
00827      * Seeking position in result
00828      *
00829      * @param   integer     Position pointer.
00830      * @return  boolean     Returns true on success
00831      */
00832     public function sql_data_seek($pointer) {
00833         reset($this->result);
00834         for ($a = 0; $a < $pointer; $a++) {
00835             next($this->result);
00836         }
00837         return TRUE;
00838     }
00839 
00840     /**
00841      * Returning SQL field type
00842      *
00843      * @return  string      Blank string, not supported (it seems)
00844      */
00845     public function sql_field_type() {
00846         return '';
00847     }
00848 }
00849 
00850 
00851 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/dbal/lib/class.tx_dbal_sqlengine.php'])) {
00852     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/dbal/lib/class.tx_dbal_sqlengine.php']);
00853 }
00854 
00855 ?>