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

class.t3lib_sqlengine.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 2004 Kasper Skaarhoj (kasperYYYY@typo3.com)
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00091 require_once(PATH_t3lib.'class.t3lib_sqlparser.php');
00092 
00093 
00102 class t3lib_sqlengine extends t3lib_sqlparser {
00103 
00104       // array with data records: [table name][num.index] = records
00105    var $data = array();                // Data source storage
00106 
00107 
00108       // Internal, SQL Status vars:
00109    var $errorStatus = '';                 // Set with error message of last operation
00110    var $lastInsertedId = 0;               // Set with last inserted unique ID
00111    var $lastAffectedRows = 0;             // Set with last number of affected rows.
00112 
00113 
00114 
00115 
00116 
00124    function init($config, &$pObj)   {
00125    }
00126 
00132    function resetStatusVars() {
00133       $this->errorStatus = '';
00134       $this->lastInsertedId = 0;
00135       $this->lastAffectedRows = 0;
00136    }
00137 
00145    function processAccordingToConfig(&$value,$fInfo)  {
00146       $options = $this->parseFieldDef($fInfo['Type']);
00147 
00148       switch(strtolower($options['fieldType'])) {
00149          case 'int':
00150          case 'smallint':
00151          case 'tinyint':
00152          case 'mediumint':
00153             $value = intval($value);
00154             if ($options['featureIndex']['UNSIGNED']) {
00155                $value = t3lib_div::intInRange($value,0);
00156             }
00157          break;
00158          case 'double':
00159             $value = (double)$value;
00160          break;
00161          case 'varchar':
00162          case 'char':
00163             $value = substr($value,0,trim($options['value']));
00164          break;
00165          case 'text':
00166          case 'blob':
00167             $value = substr($value,0,65536);
00168          break;
00169          case 'tinytext':
00170          case 'tinyblob':
00171             $value = substr($value,0,256);
00172          break;
00173          case 'mediumtext':
00174          case 'mediumblob':
00175             // ??
00176          break;
00177       }
00178    }
00179 
00180 
00181 
00182 
00183 
00184 
00185 
00186    /********************************
00187     *
00188     * SQL queries
00189     * This is the SQL access functions used when this class is instantiated as a SQL handler with DBAL. Override these in derived classes.
00190     *
00191     ********************************/
00192 
00200    function exec_INSERTquery($table,$fields_values)   {
00201 
00202          // Initialize
00203       $this->resetStatusVars();
00204 
00205          // Reading Data Source if not done already.
00206       $this->readDataSource($table);
00207 
00208          // If data source is set:
00209       if (is_array($this->data[$table]))  {
00210 
00211          $fieldInformation = $this->admin_get_fields($table);     // Should cache this...!
00212 
00213             // Looking for unique keys:
00214          $saveArray = array();
00215          foreach($fieldInformation as $fInfo)   {
00216 
00217                // Field name:
00218             $fN = $fInfo['Field'];
00219 
00220                // Set value:
00221             $saveArray[$fN] = isset($fields_values[$fN]) ? $fields_values[$fN] : $options['Default'];
00222 
00223                // Process value:
00224             $this->processAccordingToConfig($saveArray[$fN], $fInfo);
00225 
00226                // If an auto increment field is found, find the largest current uid:
00227             if ($fInfo['Extra'] == 'auto_increment')  {
00228 
00229                   // Get all UIDs:
00230                $uidArray = array();
00231                foreach($this->data[$table] as $r)  {
00232                   $uidArray[] = $r[$fN];
00233                }
00234 
00235                   // If current value is blank or already in array, we create a new:
00236                if (!$saveArray[$fN] || in_array(intval($saveArray[$fN]), $uidArray))   {
00237                   if (count($uidArray))   {
00238                      $saveArray[$fN] = max($uidArray)+1;
00239                   } else $saveArray[$fN] = 1;
00240                }
00241 
00242                   // Update "last inserted id":
00243                $this->lastInsertedId = $saveArray[$fN];
00244             }
00245          }
00246 #debug(array($fields_values,$saveArray));
00247             // Insert row in table:
00248          $this->data[$table][] = $saveArray;
00249 
00250             // Save data source
00251          $this->saveDataSource($table);
00252 
00253          return TRUE;
00254       } else $this->errorStatus = 'No data loaded.';
00255 
00256       return FALSE;
00257    }
00258 
00267    function exec_UPDATEquery($table,$where,$fields_values)  {
00268 
00269          // Initialize:
00270       $this->resetStatusVars();
00271 
00272          // Reading Data Source if not done already.
00273       $this->readDataSource($table);
00274 
00275          // If anything is there:
00276       if (is_array($this->data[$table]))  {
00277 
00278             // Parse WHERE clause:
00279          $where = $this->parseWhereClause($where);
00280 
00281          if (is_array($where))   {
00282 
00283                // Field information
00284             $fieldInformation = $this->admin_get_fields($table);     // Should cache this...!
00285 
00286                // Traverse fields to update:
00287             foreach($fields_values as $fName => $fValue) {
00288                $this->processAccordingToConfig($fields_values[$fName],$fieldInformation[$fName]);
00289             }
00290 #debug($fields_values);
00291                // Do query, returns array with keys to the data array of the result:
00292             $itemKeys = $this->selectFromData($table,$where);
00293 
00294                // Set "last affected rows":
00295             $this->lastAffectedRows = count($itemKeys);
00296 
00297                // Update rows:
00298             if ($this->lastAffectedRows)  {
00299                   // Traverse result set here:
00300                foreach($itemKeys as $dataArrayKey) {
00301 
00302                      // Traverse fields to update:
00303                   foreach($fields_values as $fName => $fValue) {
00304                      $this->data[$table][$dataArrayKey][$fName] = $fValue;
00305                   }
00306                }
00307 
00308                // Save data source
00309                $this->saveDataSource($table);
00310             }
00311 
00312             return TRUE;
00313          } else $this->errorStatus = 'WHERE clause contained errors: '.$where;
00314       } else $this->errorStatus = 'No data loaded.';
00315 
00316       return FALSE;
00317    }
00318 
00326    function exec_DELETEquery($table,$where)  {
00327 
00328          // Initialize:
00329       $this->resetStatusVars();
00330 
00331          // Reading Data Source if not done already.
00332       $this->readDataSource($table);
00333 
00334          // If anything is there:
00335       if (is_array($this->data[$table]))  {
00336 
00337             // Parse WHERE clause:
00338          $where = $this->parseWhereClause($where);
00339 
00340          if (is_array($where))   {
00341 
00342                // Do query, returns array with keys to the data array of the result:
00343             $itemKeys = $this->selectFromData($table,$where);
00344 
00345                // Set "last affected rows":
00346             $this->lastAffectedRows = count($itemKeys);
00347 
00348                // Remove rows:
00349             if ($this->lastAffectedRows)  {
00350                   // Traverse result set:
00351                foreach($itemKeys as $dataArrayKey) {
00352                   unset($this->data[$table][$dataArrayKey]);
00353                }
00354 
00355                   // Saving data source
00356                $this->saveDataSource($table);
00357             }
00358 
00359             return TRUE;
00360          } else $this->errorStatus = 'WHERE clause contained errors: '.$where;
00361       } else $this->errorStatus = 'No data loaded.';
00362 
00363       return FALSE;
00364    }
00365 
00377    function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit) {
00378 
00379          // Initialize:
00380       $this->resetStatusVars();
00381 
00382          // Create result object
00383       $sqlObj = t3lib_div::makeInstance('t3lib_sqlengine_resultobj');
00384       $sqlObj->result = array(); // Empty result as a beginning
00385 
00386          // Get table list:
00387       $tableArray = $this->parseFromTables($from_table);
00388       $table = $tableArray[0]['table'];
00389 
00390          // Reading Data Source if not done already.
00391       $this->readDataSource($table);
00392 
00393          // If anything is there:
00394       if (is_array($this->data[$table]))  {
00395 
00396             // Parse WHERE clause:
00397          $where = $this->parseWhereClause($where_clause);
00398          if (is_array($where))   {
00399 
00400                // Do query, returns array with keys to the data array of the result:
00401             $itemKeys = $this->selectFromData($table,$where);
00402 
00403                // Finally, read the result rows into this variable:
00404             $sqlObj->result = $this->getResultSet($itemKeys,$table,'*');
00405                // Reset and return result:
00406             reset($sqlObj->result);
00407             return $sqlObj;
00408          } else $this->errorStatus = 'WHERE clause contained errors: '.$where;
00409       }  else $this->errorStatus = 'No data loaded: '.$this->errorStatus;
00410 
00411       return FALSE;
00412    }
00413 
00420    function sql_query($query) {
00421       $res = t3lib_div::makeInstance('t3lib_sqlengine_resultobj');
00422       $res->result = array();
00423       return $res;
00424    }
00425 
00431    function sql_error() {
00432       return $this->errorStatus;
00433    }
00434 
00440    function sql_insert_id() {
00441       return $this->lastInsertedId;
00442    }
00443 
00449    function sql_affected_rows() {
00450       return $this->lastAffectedRows;
00451    }
00452 
00459    function quoteStr($str) {
00460       return addslashes($str);
00461    }
00462 
00463 
00464 
00465 
00466 
00467 
00468 
00469 
00470 
00471 
00472    /**************************************
00473     *
00474     * SQL admin functions
00475     * (For use in the Install Tool and Extension Manager)
00476     *
00477     **************************************/
00478 
00484    function admin_get_tables()   {
00485       $whichTables = array();
00486       return $whichTables;
00487    }
00488 
00495    function admin_get_fields($tableName)  {
00496       $output = array();
00497       return $output;
00498    }
00499 
00506    function admin_get_keys($tableName) {
00507       $output = array();
00508       return $output;
00509    }
00510 
00517    function admin_query($query)  {
00518       return $this->sql_query($query);
00519    }
00520 
00521 
00522 
00523 
00524 
00525 
00526 
00527 
00528    /********************************
00529     *
00530     * Data Source I/O
00531     *
00532     ********************************/
00533 
00542    function readDataSource($table)  {
00543       $this->data[$table] = array();
00544    }
00545 
00554    function saveDataSource($table)  {
00555       debug($this->data[$table]);
00556    }
00557 
00558 
00559 
00560 
00561 
00562 
00563 
00564 
00565 
00566 
00567 
00568 
00569 
00570    /********************************
00571     *
00572     * SQL engine functions
00573     *
00574     ********************************/
00575 
00583    function selectFromData($table,$where) {
00584 
00585       $output = array();
00586       if (is_array($this->data[$table]))  {
00587 
00588             // All keys:
00589          $OR_index = 0;
00590 
00591          foreach($where as $config) {
00592 
00593             if (strtoupper($config['operator'])=='OR')   {
00594                $OR_index++;
00595             }
00596 
00597             if (!isset($itemKeys[$OR_index]))   $itemKeys[$OR_index] = array_keys($this->data[$table]);
00598 
00599             $this->select_evalSingle($table,$config,$itemKeys[$OR_index]);
00600          }
00601 
00602          foreach($itemKeys as $uidKeys)   {
00603             $output = array_merge($output, $uidKeys);
00604          }
00605          $output = array_unique($output);
00606       }
00607 
00608       return $output;
00609    }
00610 
00619    function select_evalSingle($table,$config,&$itemKeys) {
00620       $neg = ereg('^AND[[:space:]]+NOT$',trim($config['operator']));
00621 
00622       if (is_array($config['sub'])) {
00623          $subSelKeys = $this->selectFromData($table,$config['sub']);
00624          if ($neg)   {
00625             foreach($itemKeys as $kk => $vv) {
00626                if (in_array($vv,$subSelKeys))   {
00627                   unset($itemKeys[$kk]);
00628                }
00629             }
00630          } else {
00631             $itemKeys = array_intersect($itemKeys, $subSelKeys);
00632          }
00633       } else {
00634          $comp = strtoupper(ereg_replace('[[:space:]]','',$config['comparator']));
00635          $mod = strtoupper($config['modifier']);
00636          switch($comp)  {
00637             case 'NOTLIKE':
00638             case 'LIKE':
00639                $like_value = strtolower($config['value'][0]);
00640                if (substr($like_value,0,1)=='%')   {
00641                   $wildCard_begin = TRUE;
00642                   $like_value = substr($like_value,1);
00643                }
00644                if (substr($like_value,-1)=='%') {
00645                   $wildCard_end = TRUE;
00646                   $like_value = substr($like_value,0,-1);
00647                }
00648             break;
00649             case 'NOTIN':
00650             case 'IN':
00651                $in_valueArray = array();
00652                foreach($config['value'] as $vParts)   {
00653                   $in_valueArray[] = (string)$vParts[0];
00654                }
00655             break;
00656          }
00657 
00658          foreach($itemKeys as $kk => $v)  {
00659             $field_value = $this->data[$table][$v][$config['field']];
00660 
00661                // Calculate it:
00662             if ($config['calc']=='&')  {
00663                $field_value&=intval($config['calc_value']);
00664             }
00665 
00666                // Compare it:
00667             switch($comp)  {
00668                case '<=':
00669                   $bool = $field_value <= $config['value'][0];
00670                break;
00671                case '>=':
00672                   $bool = $field_value >= $config['value'][0];
00673                break;
00674                case '<':
00675                   $bool = $field_value < $config['value'][0];
00676                break;
00677                case '>':
00678                   $bool = $field_value > $config['value'][0];
00679                break;
00680                case '=':
00681                   $bool = !strcmp($field_value,$config['value'][0]);
00682                break;
00683                case '!=':
00684                   $bool = strcmp($field_value,$config['value'][0]);
00685                break;
00686                case 'NOTIN':
00687                case 'IN':
00688                   $bool = in_array((string)$field_value, $in_valueArray);
00689                   if ($comp=='NOTIN')  $bool = !$bool;
00690                break;
00691                case 'NOTLIKE':
00692                case 'LIKE':
00693                   if (!strlen($like_value))  {
00694                      $bool = TRUE;
00695                   } elseif ($wildCard_begin && !$wildCard_end) {
00696                      $bool = !strcmp(substr(strtolower($field_value),-strlen($like_value)),$like_value);
00697                   } elseif (!$wildCard_begin && $wildCard_end) {
00698                      $bool = !strcmp(substr(strtolower($field_value),0,strlen($like_value)),$like_value);
00699                   } elseif ($wildCard_begin && $wildCard_end)  {
00700                      $bool = strstr($field_value,$like_value);
00701                   } else {
00702                      $bool = !strcmp(strtolower($field_value),$like_value);
00703                   }
00704                   if ($comp=='NOTLIKE')   $bool = !$bool;
00705                break;
00706                default:
00707                   $bool = $field_value ? TRUE : FALSE;
00708                break;
00709             }
00710 
00711                // General negation:
00712             if ($neg)   $bool = !$bool;
00713 
00714                // Modify?
00715             switch($mod)   {
00716                case 'NOT':
00717                case '!':
00718                   $bool = !$bool;
00719                break;
00720             }
00721 
00722                // Action:
00723             if (!$bool) {
00724                unset($itemKeys[$kk]);
00725             }
00726          }
00727 
00728 #        echo $this->debug_printResultSet($this->getResultSet($itemKeys,$table,'uid,tstamp'));
00729       }
00730    }
00731 
00740    function getResultSet($keys, $table, $fieldList)   {
00741       $fields = t3lib_div::trimExplode(',',$fieldList);
00742 
00743       $output = array();
00744       foreach($keys as $kValue)  {
00745          if ($fieldList=='*') {
00746             $output[$kValue] = $this->data[$table][$kValue];
00747          } else {
00748             foreach($fields as $fieldName)   {
00749                $output[$kValue][$fieldName] = $this->data[$table][$kValue][$fieldName];
00750             }
00751          }
00752       }
00753 
00754       return $output;
00755    }
00756 
00757 
00758 
00759 
00760 
00761 
00762 
00763 
00764 
00765 
00766 
00767 
00768 
00769 
00770 
00771 
00772 
00773    /*************************
00774     *
00775     * Debugging
00776     *
00777     *************************/
00778 
00785    function debug_printResultSet($array)  {
00786 
00787       if (count($array))   {
00788          $tRows=array();
00789          $fields = array_keys(current($array));
00790                $tCell[]='
00791                      <td>IDX</td>';
00792             foreach($fields as $fieldName)   {
00793                $tCell[]='
00794                      <td>'.htmlspecialchars($fieldName).'</td>';
00795             }
00796             $tRows[]='<tr>'.implode('',$tCell).'</tr>';
00797 
00798 
00799          foreach($array as $index => $rec)   {
00800 
00801             $tCell=array();
00802             $tCell[]='
00803                   <td>'.htmlspecialchars($index).'</td>';
00804             foreach($fields as $fieldName)   {
00805                $tCell[]='
00806                      <td>'.htmlspecialchars($rec[$fieldName]).'</td>';
00807             }
00808             $tRows[]='<tr>'.implode('',$tCell).'</tr>';
00809          }
00810 
00811          return '<table border="1">'.implode('',$tRows).'</table>';
00812       } else 'Empty resultset';
00813    }
00814 }
00815 
00816 
00824 class t3lib_sqlengine_resultobj {
00825 
00826       // Result array, must contain the fields in the order they were selected in the SQL statement (for sql_fetch_row())
00827    var $result = array();
00828 
00829    var $TYPO3_DBAL_handlerType = '';
00830    var $TYPO3_DBAL_tableList = '';
00831 
00832 
00838    function sql_num_rows() {
00839       return count($this->result);
00840    }
00841 
00847    function sql_fetch_assoc() {
00848       $row = current($this->result);
00849       next($this->result);
00850       return $row;
00851    }
00852 
00858    function sql_fetch_row()   {
00859       $resultRow = $this->sql_fetch_assoc();
00860 
00861       if (is_array($resultRow))  {
00862          $numArray = array();
00863          foreach($resultRow as $value) {
00864             $numArray[]=$value;
00865          }
00866          return $numArray;
00867       }
00868    }
00869 
00876    function sql_data_seek($pointer) {
00877       reset($this->result);
00878       for ($a=0;$a<$pointer;$a++)   {
00879          next($this->result);
00880       }
00881       return TRUE;
00882    }
00883 
00889    function sql_field_type()  {
00890       return '';
00891    }
00892 }
00893 
00894 
00895 
00896 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_sqlengine.php'])  {
00897    include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_sqlengine.php']);
00898 }
00899 ?>

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