"TYPO3 4.0.1: typo3_src-4.0.1/t3lib/class.t3lib_sqlengine.php Source File", "datetime" => "Sat Dec 2 19:22:18 2006", "date" => "2 Dec 2006", "doxygenversion" => "1.4.6", "projectname" => "TYPO3 4.0.1", "projectnumber" => "4.0.1" ); get_header($doxygen_vars); ?>

class.t3lib_sqlengine.php

00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 2004-2006 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 ***************************************************************/
00092 require_once(PATH_t3lib.'class.t3lib_sqlparser.php');
00093 
00094 
00104 class t3lib_sqlengine extends t3lib_sqlparser {
00105 
00106                 // array with data records: [table name][num.index] = records
00107         var $data = array();                                            // Data source storage
00108 
00109 
00110                 // Internal, SQL Status vars:
00111         var $errorStatus = '';                                          // Set with error message of last operation
00112         var $lastInsertedId = 0;                                        // Set with last inserted unique ID
00113         var $lastAffectedRows = 0;                                      // Set with last number of affected rows.
00114 
00115 
00116 
00117 
00118 
00126         function init($config, &$pObj)  {
00127         }
00128 
00134         function resetStatusVars()      {
00135                 $this->errorStatus = '';
00136                 $this->lastInsertedId = 0;
00137                 $this->lastAffectedRows = 0;
00138         }
00139 
00150         function processAccordingToConfig(&$value,$fInfo)       {
00151                 $options = $this->parseFieldDef($fInfo['Type']);
00152 
00153                 switch(strtolower($options['fieldType']))       {
00154                         case 'int':
00155                         case 'smallint':
00156                         case 'tinyint':
00157                         case 'mediumint':
00158                                 $value = intval($value);
00159                                 if ($options['featureIndex']['UNSIGNED'])       {
00160                                         $value = t3lib_div::intInRange($value,0);
00161                                 }
00162                         break;
00163                         case 'double':
00164                                 $value = (double)$value;
00165                         break;
00166                         case 'varchar':
00167                         case 'char':
00168                                 $value = substr($value,0,trim($options['value']));
00169                         break;
00170                         case 'text':
00171                         case 'blob':
00172                                 $value = substr($value,0,65536);
00173                         break;
00174                         case 'tinytext':
00175                         case 'tinyblob':
00176                                 $value = substr($value,0,256);
00177                         break;
00178                         case 'mediumtext':
00179                         case 'mediumblob':
00180                                 // ??
00181                         break;
00182                 }
00183         }
00184 
00185 
00186 
00187 
00188 
00189 
00190 
00191         /********************************
00192          *
00193          * SQL queries
00194          * This is the SQL access functions used when this class is instantiated as a SQL handler with DBAL. Override these in derived classes.
00195          *
00196          ********************************/
00197 
00205         function exec_INSERTquery($table,$fields_values)        {
00206 
00207                         // Initialize
00208                 $this->resetStatusVars();
00209 
00210                         // Reading Data Source if not done already.
00211                 $this->readDataSource($table);
00212 
00213                         // If data source is set:
00214                 if (is_array($this->data[$table]))      {
00215 
00216                         $fieldInformation = $this->admin_get_fields($table);            // Should cache this...!
00217 
00218                                 // Looking for unique keys:
00219                         $saveArray = array();
00220                         foreach($fieldInformation as $fInfo)    {
00221 
00222                                         // Field name:
00223                                 $fN = $fInfo['Field'];
00224 
00225                                         // Set value:
00226 // FIXME $options not defined
00227                                 $saveArray[$fN] = isset($fields_values[$fN]) ? $fields_values[$fN] : $options['Default'];
00228 
00229                                         // Process value:
00230                                 $this->processAccordingToConfig($saveArray[$fN], $fInfo);
00231 
00232                                         // If an auto increment field is found, find the largest current uid:
00233                                 if ($fInfo['Extra'] == 'auto_increment')        {
00234 
00235                                                 // Get all UIDs:
00236                                         $uidArray = array();
00237                                         foreach($this->data[$table] as $r)      {
00238                                                 $uidArray[] = $r[$fN];
00239                                         }
00240 
00241                                                 // If current value is blank or already in array, we create a new:
00242                                         if (!$saveArray[$fN] || in_array(intval($saveArray[$fN]), $uidArray))   {
00243                                                 if (count($uidArray))   {
00244                                                         $saveArray[$fN] = max($uidArray)+1;
00245                                                 } else $saveArray[$fN] = 1;
00246                                         }
00247 
00248                                                 // Update "last inserted id":
00249                                         $this->lastInsertedId = $saveArray[$fN];
00250                                 }
00251                         }
00252 
00253                                 // Insert row in table:
00254                         $this->data[$table][] = $saveArray;
00255 
00256                                 // Save data source
00257                         $this->saveDataSource($table);
00258 
00259                         return TRUE;
00260                 } else $this->errorStatus = 'No data loaded.';
00261 
00262                 return FALSE;
00263         }
00264 
00273         function exec_UPDATEquery($table,$where,$fields_values) {
00274 
00275                         // Initialize:
00276                 $this->resetStatusVars();
00277 
00278                         // Reading Data Source if not done already.
00279                 $this->readDataSource($table);
00280 
00281                         // If anything is there:
00282                 if (is_array($this->data[$table]))      {
00283 
00284                                 // Parse WHERE clause:
00285                         $where = $this->parseWhereClause($where);
00286 
00287                         if (is_array($where))   {
00288 
00289                                         // Field information
00290                                 $fieldInformation = $this->admin_get_fields($table);            // Should cache this...!
00291 
00292                                         // Traverse fields to update:
00293                                 foreach($fields_values as $fName => $fValue)    {
00294                                         $this->processAccordingToConfig($fields_values[$fName],$fieldInformation[$fName]);
00295                                 }
00296 
00297                                         // Do query, returns array with keys to the data array of the result:
00298                                 $itemKeys = $this->selectFromData($table,$where);
00299 
00300                                         // Set "last affected rows":
00301                                 $this->lastAffectedRows = count($itemKeys);
00302 
00303                                         // Update rows:
00304                                 if ($this->lastAffectedRows)    {
00305                                                 // Traverse result set here:
00306                                         foreach($itemKeys as $dataArrayKey)     {
00307 
00308                                                         // Traverse fields to update:
00309                                                 foreach($fields_values as $fName => $fValue)    {
00310                                                         $this->data[$table][$dataArrayKey][$fName] = $fValue;
00311                                                 }
00312                                         }
00313 
00314                                         // Save data source
00315                                         $this->saveDataSource($table);
00316                                 }
00317 
00318                                 return TRUE;
00319                         } else $this->errorStatus = 'WHERE clause contained errors: '.$where;
00320                 } else $this->errorStatus = 'No data loaded.';
00321 
00322                 return FALSE;
00323         }
00324 
00332         function exec_DELETEquery($table,$where)        {
00333 
00334                         // Initialize:
00335                 $this->resetStatusVars();
00336 
00337                         // Reading Data Source if not done already.
00338                 $this->readDataSource($table);
00339 
00340                         // If anything is there:
00341                 if (is_array($this->data[$table]))      {
00342 
00343                                 // Parse WHERE clause:
00344                         $where = $this->parseWhereClause($where);
00345 
00346                         if (is_array($where))   {
00347 
00348                                         // Do query, returns array with keys to the data array of the result:
00349                                 $itemKeys = $this->selectFromData($table,$where);
00350 
00351                                         // Set "last affected rows":
00352                                 $this->lastAffectedRows = count($itemKeys);
00353 
00354                                         // Remove rows:
00355                                 if ($this->lastAffectedRows)    {
00356                                                 // Traverse result set:
00357                                         foreach($itemKeys as $dataArrayKey)     {
00358                                                 unset($this->data[$table][$dataArrayKey]);
00359                                         }
00360 
00361                                                 // Saving data source
00362                                         $this->saveDataSource($table);
00363                                 }
00364 
00365                                 return TRUE;
00366                         } else $this->errorStatus = 'WHERE clause contained errors: '.$where;
00367                 } else $this->errorStatus = 'No data loaded.';
00368 
00369                 return FALSE;
00370         }
00371 
00383         function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit)    {
00384 
00385                         // Initialize:
00386                 $this->resetStatusVars();
00387 
00388                         // Create result object
00389                 $sqlObj = t3lib_div::makeInstance('t3lib_sqlengine_resultobj');
00390                 $sqlObj->result = array();      // Empty result as a beginning
00391 
00392                         // Get table list:
00393                 $tableArray = $this->parseFromTables($from_table);
00394                 $table = $tableArray[0]['table'];
00395 
00396                         // Reading Data Source if not done already.
00397                 $this->readDataSource($table);
00398 
00399                         // If anything is there:
00400                 if (is_array($this->data[$table]))      {
00401 
00402                                 // Parse WHERE clause:
00403                         $where = $this->parseWhereClause($where_clause);
00404                         if (is_array($where))   {
00405 
00406                                         // Do query, returns array with keys to the data array of the result:
00407                                 $itemKeys = $this->selectFromData($table,$where);
00408 
00409                                         // Finally, read the result rows into this variable:
00410                                 $sqlObj->result = $this->getResultSet($itemKeys,$table,'*');
00411                                         // Reset and return result:
00412                                 reset($sqlObj->result);
00413                                 return $sqlObj;
00414                         } else $this->errorStatus = 'WHERE clause contained errors: '.$where;
00415                 }  else $this->errorStatus = 'No data loaded: '.$this->errorStatus;
00416 
00417                 return FALSE;
00418         }
00419 
00426         function sql_query($query)      {
00427                 $res = t3lib_div::makeInstance('t3lib_sqlengine_resultobj');
00428                 $res->result = array();
00429                 return $res;
00430         }
00431 
00437         function sql_error()    {
00438                 return $this->errorStatus;
00439         }
00440 
00446         function sql_insert_id() {
00447                 return $this->lastInsertedId;
00448         }
00449 
00455         function sql_affected_rows() {
00456                 return $this->lastAffectedRows;
00457         }
00458 
00465         function quoteStr($str) {
00466                 return addslashes($str);
00467         }
00468 
00469 
00470 
00471 
00472 
00473 
00474 
00475 
00476 
00477 
00478         /**************************************
00479          *
00480          * SQL admin functions
00481          * (For use in the Install Tool and Extension Manager)
00482          *
00483          **************************************/
00484 
00490         function admin_get_tables()     {
00491                 $whichTables = array();
00492                 return $whichTables;
00493         }
00494 
00501         function admin_get_fields($tableName)   {
00502                 $output = array();
00503                 return $output;
00504         }
00505 
00512         function admin_get_keys($tableName)     {
00513                 $output = array();
00514                 return $output;
00515         }
00516 
00523         function admin_query($query)    {
00524                 return $this->sql_query($query);
00525         }
00526 
00527 
00528 
00529 
00530 
00531 
00532 
00533 
00534         /********************************
00535          *
00536          * Data Source I/O
00537          *
00538          ********************************/
00539 
00548         function readDataSource($table) {
00549                 $this->data[$table] = array();
00550         }
00551 
00560         function saveDataSource($table) {
00561                 debug($this->data[$table]);
00562         }
00563 
00564 
00565 
00566 
00567 
00568 
00569 
00570 
00571 
00572 
00573 
00574 
00575 
00576         /********************************
00577          *
00578          * SQL engine functions (PHP simulation of SQL) - still experimental
00579          *
00580          ********************************/
00581 
00590         function selectFromData($table,$where)  {
00591 
00592                 $output = array();
00593                 if (is_array($this->data[$table]))      {
00594 
00595                                 // All keys:
00596                         $OR_index = 0;
00597 
00598                         foreach($where as $config)      {
00599 
00600                                 if (strtoupper($config['operator'])=='OR')      {
00601                                         $OR_index++;
00602                                 }
00603 
00604                                 if (!isset($itemKeys[$OR_index]))       $itemKeys[$OR_index] = array_keys($this->data[$table]);
00605 
00606                                 $this->select_evalSingle($table,$config,$itemKeys[$OR_index]);
00607                         }
00608 
00609                         foreach($itemKeys as $uidKeys)  {
00610                                 $output = array_merge($output, $uidKeys);
00611                         }
00612                         $output = array_unique($output);
00613                 }
00614 
00615                 return $output;
00616         }
00617 
00628         function select_evalSingle($table,$config,&$itemKeys)   {
00629                 $neg = preg_match('/^AND[[:space:]]+NOT$/',trim($config['operator']));
00630 
00631                 if (is_array($config['sub']))   {
00632                         $subSelKeys = $this->selectFromData($table,$config['sub']);
00633                         if ($neg)       {
00634                                 foreach($itemKeys as $kk => $vv)        {
00635                                         if (in_array($vv,$subSelKeys))  {
00636                                                 unset($itemKeys[$kk]);
00637                                         }
00638                                 }
00639                         } else {
00640                                 $itemKeys = array_intersect($itemKeys, $subSelKeys);
00641                         }
00642                 } else {
00643                         $comp = strtoupper(str_replace(array(' ',"\t","\r","\n"),'',$config['comparator']));
00644                         $mod = strtoupper($config['modifier']);
00645                         switch($comp)   {
00646                                 case 'NOTLIKE':
00647                                 case 'LIKE':
00648                                         $like_value = strtolower($config['value'][0]);
00649                                         if (substr($like_value,0,1)=='%')       {
00650                                                 $wildCard_begin = TRUE;
00651                                                 $like_value = substr($like_value,1);
00652                                         }
00653                                         if (substr($like_value,-1)=='%')        {
00654                                                 $wildCard_end = TRUE;
00655                                                 $like_value = substr($like_value,0,-1);
00656                                         }
00657                                 break;
00658                                 case 'NOTIN':
00659                                 case 'IN':
00660                                         $in_valueArray = array();
00661                                         foreach($config['value'] as $vParts)    {
00662                                                 $in_valueArray[] = (string)$vParts[0];
00663                                         }
00664                                 break;
00665                         }
00666 
00667                         foreach($itemKeys as $kk => $v) {
00668                                 $field_value = $this->data[$table][$v][$config['field']];
00669 
00670                                         // Calculate it:
00671                                 if ($config['calc']=='&')       {
00672                                         $field_value&=intval($config['calc_value']);
00673                                 }
00674 
00675                                         // Compare it:
00676                                 switch($comp)   {
00677                                         case '<=':
00678                                                 $bool = $field_value <= $config['value'][0];
00679                                         break;
00680                                         case '>=':
00681                                                 $bool = $field_value >= $config['value'][0];
00682                                         break;
00683                                         case '<':
00684                                                 $bool = $field_value < $config['value'][0];
00685                                         break;
00686                                         case '>':
00687                                                 $bool = $field_value > $config['value'][0];
00688                                         break;
00689                                         case '=':
00690                                                 $bool = !strcmp($field_value,$config['value'][0]);
00691                                         break;
00692                                         case '!=':
00693                                                 $bool = strcmp($field_value,$config['value'][0]);
00694                                         break;
00695                                         case 'NOTIN':
00696                                         case 'IN':
00697                                                 $bool = in_array((string)$field_value, $in_valueArray);
00698                                                 if ($comp=='NOTIN')     $bool = !$bool;
00699                                         break;
00700                                         case 'NOTLIKE':
00701                                         case 'LIKE':
00702                                                 if (!strlen($like_value))       {
00703                                                         $bool = TRUE;
00704                                                 } elseif ($wildCard_begin && !$wildCard_end)    {
00705                                                         $bool = !strcmp(substr(strtolower($field_value),-strlen($like_value)),$like_value);
00706                                                 } elseif (!$wildCard_begin && $wildCard_end)    {
00707                                                         $bool = !strcmp(substr(strtolower($field_value),0,strlen($like_value)),$like_value);
00708                                                 } elseif ($wildCard_begin && $wildCard_end)     {
00709                                                         $bool = strstr($field_value,$like_value);
00710                                                 } else {
00711                                                         $bool = !strcmp(strtolower($field_value),$like_value);
00712                                                 }
00713                                                 if ($comp=='NOTLIKE')   $bool = !$bool;
00714                                         break;
00715                                         default:
00716                                                 $bool = $field_value ? TRUE : FALSE;
00717                                         break;
00718                                 }
00719 
00720                                         // General negation:
00721                                 if ($neg)       $bool = !$bool;
00722 
00723                                         // Modify?
00724                                 switch($mod)    {
00725                                         case 'NOT':
00726                                         case '!':
00727                                                 $bool = !$bool;
00728                                         break;
00729                                 }
00730 
00731                                         // Action:
00732                                 if (!$bool)     {
00733                                         unset($itemKeys[$kk]);
00734                                 }
00735                         }
00736                 }
00737         }
00738 
00747         function getResultSet($keys, $table, $fieldList)        {
00748                 $fields = t3lib_div::trimExplode(',',$fieldList);
00749 
00750                 $output = array();
00751                 foreach($keys as $kValue)       {
00752                         if ($fieldList=='*')    {
00753                                 $output[$kValue] = $this->data[$table][$kValue];
00754                         } else {
00755                                 foreach($fields as $fieldName)  {
00756                                         $output[$kValue][$fieldName] = $this->data[$table][$kValue][$fieldName];
00757                                 }
00758                         }
00759                 }
00760 
00761                 return $output;
00762         }
00763 
00764 
00765 
00766 
00767 
00768 
00769 
00770 
00771 
00772 
00773 
00774 
00775 
00776 
00777 
00778         /*************************
00779          *
00780          * Debugging
00781          *
00782          *************************/
00783 
00790         function debug_printResultSet($array)   {
00791 
00792                 if (count($array))      {
00793                         $tRows=array();
00794                         $fields = array_keys(current($array));
00795                                         $tCell[]='
00796                                                         <td>IDX</td>';
00797                                 foreach($fields as $fieldName)  {
00798                                         $tCell[]='
00799                                                         <td>'.htmlspecialchars($fieldName).'</td>';
00800                                 }
00801                                 $tRows[]='<tr>'.implode('',$tCell).'</tr>';
00802 
00803 
00804                         foreach($array as $index => $rec)       {
00805 
00806                                 $tCell=array();
00807                                 $tCell[]='
00808                                                 <td>'.htmlspecialchars($index).'</td>';
00809                                 foreach($fields as $fieldName)  {
00810                                         $tCell[]='
00811                                                         <td>'.htmlspecialchars($rec[$fieldName]).'</td>';
00812                                 }
00813                                 $tRows[]='<tr>'.implode('',$tCell).'</tr>';
00814                         }
00815 
00816                         return '<table border="1">'.implode('',$tRows).'</table>';
00817                 } else 'Empty resultset';
00818         }
00819 }
00820 
00821 
00829 class t3lib_sqlengine_resultobj {
00830 
00831                 // Result array, must contain the fields in the order they were selected in the SQL statement (for sql_fetch_row())
00832         var $result = array();
00833 
00834         var $TYPO3_DBAL_handlerType = '';
00835         var $TYPO3_DBAL_tableList = '';
00836 
00837 
00843         function sql_num_rows() {
00844                 return count($this->result);
00845         }
00846 
00852         function sql_fetch_assoc()      {
00853                 $row = current($this->result);
00854                 next($this->result);
00855                 return $row;
00856         }
00857 
00863         function sql_fetch_row()        {
00864                 $resultRow = $this->sql_fetch_assoc();
00865 
00866                 if (is_array($resultRow))       {
00867                         $numArray = array();
00868                         foreach($resultRow as $value)   {
00869                                 $numArray[]=$value;
00870                         }
00871                         return $numArray;
00872                 }
00873         }
00874 
00881         function sql_data_seek($pointer)        {
00882                 reset($this->result);
00883                 for ($a=0;$a<$pointer;$a++)     {
00884                         next($this->result);
00885                 }
00886                 return TRUE;
00887         }
00888 
00894         function sql_field_type()       {
00895                 return '';
00896         }
00897 }
00898 
00899 
00900 
00901 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_sqlengine.php']) {
00902         include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_sqlengine.php']);
00903 }
00904 ?>