Documentation TYPO3 par Ameos |
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 2004 Kasper Skaarhoj (kasper@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 ***************************************************************/ 00115 require_once(PATH_t3lib.'class.t3lib_sqlengine.php'); 00116 require_once(PATH_t3lib.'class.t3lib_install.php'); 00117 //require_once(t3lib_extMgm::extPath('install').'mod/class.tx_install.php'); 00118 00127 class ux_t3lib_DB extends t3lib_DB { 00128 00129 // Internal, static: 00130 var $printErrors = FALSE; // Enable output of SQL errors after query executions. Set through TYPO3_CONF_VARS, see init() 00131 var $debug = FALSE; // Enable debug mode. Set through TYPO3_CONF_VARS, see init() 00132 var $conf = array(); // Configuration array, copied from TYPO3_CONF_VARS in constructor. 00133 00134 var $mapping = array(); // See manual. 00135 var $table2handlerKeys = array(); // See manual. 00136 var $handlerCfg = array ( // See manual. 00137 '_DEFAULT' => array ( 00138 'type' => 'native', 00139 'config' => array( 00140 'username' => '', // Set by default (overridden) 00141 'password' => '', // Set by default (overridden) 00142 'host' => '', // Set by default (overridden) 00143 'database' => '', // Set by default (overridden) 00144 'driver' => '', // ONLY "adodb" type; eg. "mysql" 00145 ) 00146 ), 00147 ); 00148 00149 00150 // Internal, dynamic: 00151 var $handlerInstance = array(); // Contains instance of the handler objects as they are created. Exception is the native mySQL calls which are registered as an array with keys "handlerType" = "native" and "link" pointing to the link resource for the connection. 00152 var $lastHandlerKey = ''; // Storage of the handler key of last ( SELECT) query - used for subsequent fetch-row calls etc. 00153 var $lastQuery = ''; // Storage of last SELECT query 00154 var $lastParsedAndMappedQueryArray=array(); // Query array, the last one parsed 00155 00156 var $resourceIdToTableNameMap = array(); // Mapping of resource ids to table names. 00157 00158 // Internal, caching: 00159 var $cache_handlerKeyFromTableList = array(); // Caching handlerKeys for table lists 00160 var $cache_mappingFromTableList = array(); // Caching mapping information for table lists 00161 var $cache_autoIncFields = array(); // parsed SQL from standard DB dump file 00162 var $cache_fieldType = array(); // field types for tables/fields 00163 var $cache_primaryKeys = array(); // primary keys 00164 00165 00166 00167 00168 00175 function ux_t3lib_DB() { 00176 00177 // Set SQL parser object for internal use: 00178 $this->SQLparser = t3lib_div::makeInstance('t3lib_sqlengine'); 00179 $this->Installer = t3lib_div::makeInstance('t3lib_install'); 00180 00181 // Set internal variables with configuration: 00182 $this->conf = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['dbal']; 00183 $this->initInternalVariables(); 00184 } 00185 00191 function initInternalVariables() { 00192 00193 // Set outside configuration: 00194 if (isset($this->conf['mapping'])) $this->mapping = $this->conf['mapping']; 00195 if (isset($this->conf['table2handlerKeys'])) $this->table2handlerKeys = $this->conf['table2handlerKeys']; 00196 if (isset($this->conf['handlerCfg'])) $this->handlerCfg = $this->conf['handlerCfg']; 00197 00198 $this->cacheFieldInfo(); 00199 // Debugging settings: 00200 $this->printErrors = $this->conf['debugOptions']['printErrors'] ? TRUE : FALSE; 00201 $this->debug = $this->conf['debugOptions']['enabled'] ? TRUE : FALSE; 00202 } 00203 00204 function clearCachedFieldInfo() { 00205 if(file_exists(PATH_typo3conf.'temp_fieldInfo.php')) 00206 unlink(PATH_typo3conf.'temp_fieldInfo.php'); 00207 } 00208 00209 function cacheFieldInfo() { 00210 global $TYPO3_LOADED_EXT; 00211 $extSQL = ''; 00212 $parsedExtSQL = array(); 00213 00214 // try to fetch cached file first 00215 // file is removed when admin_query() is called 00216 if(file_exists(PATH_typo3conf.'temp_fieldInfo.php')) { 00217 $fdata = unserialize(t3lib_div::getUrl(PATH_typo3conf.'temp_fieldInfo.php')); 00218 $this->cache_autoIncFields = $fdata['incFields']; 00219 $this->cache_fieldType = $fdata['fieldTypes']; 00220 $this->cache_primaryKeys = $fdata['primaryKeys']; 00221 } 00222 else { 00223 // handle stddb.sql, parse and analyze 00224 $extSQL = t3lib_div::getUrl(PATH_site.'t3lib/stddb/tables.sql'); 00225 $parsedExtSQL = $this->Installer->getFieldDefinitions_sqlContent($extSQL); 00226 $this->analyzeFields($parsedExtSQL); 00227 00228 // loop over all installed extensions 00229 foreach($TYPO3_LOADED_EXT as $ext => $v) { 00230 if(!is_array($v) || !isset($v['ext_tables.sql'])) 00231 continue; 00232 00233 // fetch db dump (if any) and parse it, then analyze 00234 $extSQL = t3lib_div::getUrl($v['ext_tables.sql']); 00235 $parsedExtSQL = $this->Installer->getFieldDefinitions_sqlContent($extSQL); 00236 $this->analyzeFields($parsedExtSQL); 00237 } 00238 00239 $cachedFieldInfo = array('incFields' => $this->cache_autoIncFields, 'fieldTypes' => $this->cache_fieldType, 'primaryKeys' => $this->cache_primaryKeys); 00240 $cachedFieldInfo = serialize($this->mapCachedFieldInfo($cachedFieldInfo)); 00241 00242 // write serialized content to file 00243 t3lib_div::writeFile(PATH_typo3conf."temp_fieldInfo.php", $cachedFieldInfo); 00244 00245 if (strcmp(t3lib_div::getUrl(PATH_typo3conf."temp_fieldInfo.php"), $cachedFieldInfo)) { 00246 die('typo3temp/temp_incfields.php was NOT updated properly (written content didn\'t match file content) - maybe write access problem?'); 00247 } 00248 } 00249 } 00250 00258 function analyzeFields($parsedExtSQL) { 00259 foreach($parsedExtSQL as $table => $tdef) { 00260 foreach($tdef['fields'] as $field => $fdef) { 00261 $fdef = $this->SQLparser->parseFieldDef($fdef); 00262 $this->cache_fieldType[$table][$field]['type'] = $fdef['fieldType']; 00263 $this->cache_fieldType[$table][$field]['metaType'] = $this->MySQLMetaType($fdef['fieldType']); 00264 $this->cache_fieldType[$table][$field]['notnull'] = (isset($fdef['featureIndex']['NOTNULL']) && !$this->SQLparser->checkEmptyDefaultValue($fdef['featureIndex'])) ? 1 : 0; 00265 if(isset($fdef['featureIndex']['AUTO_INCREMENT'])) { 00266 $this->cache_autoIncFields[$table] = $field; 00267 } 00268 if(isset($tdef['keys']['PRIMARY'])) { 00269 $this->cache_primaryKeys[$table] = substr($tdef['keys']['PRIMARY'], 13, -1); 00270 } 00271 } 00272 } 00273 } 00274 00279 function mapCachedFieldInfo($fieldInfo){ 00280 global $TYPO3_CONF_VARS; 00281 00282 if(is_array($TYPO3_CONF_VARS['EXTCONF']['dbal']['mapping'])) { 00283 foreach($TYPO3_CONF_VARS['EXTCONF']['dbal']['mapping'] as $mappedTable => $mappedConf){ 00284 if(array_key_exists($mappedTable, $fieldInfo['incFields'])) { 00285 $mappedTableAlias = $mappedConf['mapTableName']; 00286 $fieldInfo['incFields'][$mappedTableAlias] = isset($mappedConf['mapFieldNames'][$fieldInfo['incFields'][$mappedTable]]) ? $mappedConf['mapFieldNames'][$fieldInfo['incFields'][$mappedTable]] : $fieldInfo['incFields'][$mappedTable]; 00287 } 00288 00289 if(array_key_exists($mappedTable, $fieldInfo['fieldTypes'])) { 00290 foreach($fieldInfo['fieldTypes'][$mappedTable] as $field => $fieldConf){ 00291 $tempMappedFieldConf[$mappedConf['mapFieldNames'][$field]] = $fieldConf; 00292 } 00293 00294 $fieldInfo['fieldTypes'][$mappedConf['mapTableName']] = $tempMappedFieldConf; 00295 } 00296 00297 if(array_key_exists($mappedTable, $fieldInfo['primaryKeys'])) { 00298 $mappedTableAlias = $mappedConf['mapTableName']; 00299 $fieldInfo['primaryKeys'][$mappedTableAlias] = isset($mappedConf['mapFieldNames'][$fieldInfo['primaryKeys'][$mappedTable]]) ? $mappedConf['mapFieldNames'][$fieldInfo['primaryKeys'][$mappedTable]] : $fieldInfo['primaryKeys'][$mappedTable]; 00300 } 00301 00302 } 00303 } 00304 00305 return $fieldInfo; 00306 } 00307 00308 00309 /************************************ 00310 * 00311 * Query Building (Overriding parent methods) 00312 * These functions are extending counterparts in the parent class. 00313 * 00314 **************************************/ 00315 00316 /* From the ADOdb documentation, this is what we do (_Execute for SELECT, _query for the other actions) 00317 00318 Execute() is the default way to run queries. You can use the low-level functions _Execute() and _query() to reduce query overhead. 00319 Both these functions share the same parameters as Execute(). 00320 00321 If you do not have any bind parameters or your database supports binding (without emulation), then you can call _Execute() directly. 00322 Calling this function bypasses bind emulation. Debugging is still supported in _Execute(). 00323 00324 If you do not require debugging facilities nor emulated binding, and do not require a recordset to be returned, then you can call _query. 00325 This is great for inserts, updates and deletes. Calling this function bypasses emulated binding, debugging, and recordset handling. Either 00326 the resultid, true or false are returned by _query(). 00327 */ 00328 00337 function exec_INSERTquery($table,$fields_values,$no_quote_fields='') { 00338 00339 if ($this->debug) $pt = t3lib_div::milliseconds(); 00340 00341 // Do field mapping if needed: 00342 $ORIG_tableName = $table; 00343 if ($tableArray = $this->map_needMapping($table)) { 00344 00345 // Field mapping of array: 00346 $fields_values = $this->map_assocArray($fields_values,$tableArray); 00347 00348 // Table name: 00349 if ($this->mapping[$table]['mapTableName']) { 00350 $table = $this->mapping[$table]['mapTableName']; 00351 } 00352 } 00353 // Select API: 00354 $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName); 00355 switch((string)$this->handlerCfg[$this->lastHandlerKey]['type']) { 00356 case 'native': 00357 $this->lastQuery = $this->INSERTquery($table,$fields_values,$no_quote_fields); 00358 if(is_string($this->lastQuery)) { 00359 $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']); 00360 } 00361 else { 00362 $sqlResult = mysql_query($this->lastQuery[0], $this->handlerInstance[$this->lastHandlerKey]['link']); 00363 foreach($this->lastQuery[1] as $field => $content) { 00364 mysql_query('UPDATE '.$this->quoteFromTables($table).' SET '.$this->quoteFromTables($field).'='.$this->fullQuoteStr($content,$table).' WHERE '.$this->quoteWhereClause($where), $this->handlerInstance[$this->lastHandlerKey]['link']); 00365 } 00366 } 00367 break; 00368 case 'adodb': 00369 // auto generate ID for auto_increment fields if not present (static import needs this!) 00370 // should we check the table name here (static_*)? 00371 if(isset($this->cache_autoIncFields[$table])) { 00372 if(isset($fields_values[$this->cache_autoIncFields[$table]])) { 00373 $new_id = $fields_values[$this->cache_autoIncFields[$table]]; 00374 if($table !== 'tx_dbal_debuglog') { 00375 $this->handlerInstance[$this->lastHandlerKey]->last_insert_id = $new_id; 00376 } 00377 } else { 00378 $new_id = $this->handlerInstance[$this->lastHandlerKey]->GenID($table.'_'.$this->cache_autoIncFields[$table]); 00379 $fields_values[$this->cache_autoIncFields[$table]] = $new_id; 00380 if($table !== 'tx_dbal_debuglog') { 00381 $this->handlerInstance[$this->lastHandlerKey]->last_insert_id = $new_id; 00382 } 00383 } 00384 } 00385 00386 $this->lastQuery = $this->INSERTquery($table,$fields_values,$no_quote_fields); 00387 if(is_string($this->lastQuery)) { 00388 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery,false); 00389 } else { 00390 $this->handlerInstance[$this->lastHandlerKey]->StartTrans(); 00391 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery[0],false); 00392 foreach($this->lastQuery[1] as $field => $content) { 00393 if(empty($content)) continue; 00394 00395 if(isset($this->cache_autoIncFields[$table]) && isset($new_id)) { 00396 $this->handlerInstance[$this->lastHandlerKey]->UpdateBlob($this->quoteFromTables($table),$field,$content,$this->quoteWhereClause($this->cache_autoIncFields[$table].'='.$new_id)); 00397 } elseif(isset($this->cache_primaryKeys[$table])) { 00398 $pks = explode(',', $this->cache_primaryKeys[$table]); 00399 foreach ($pks as $pk) { 00400 if(isset($fields_values[$pk])) 00401 $where .= $pk.'='.$this->fullQuoteStr($fields_values[$pk], $table).' AND '; 00402 } 00403 $where = $this->quoteWhereClause($where.'1=1'); 00404 $this->handlerInstance[$this->lastHandlerKey]->UpdateBlob($this->quoteFromTables($table),$field,$content,$where); 00405 } else { 00406 $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans(false); 00407 die('Could not update BLOB >>>> no WHERE clause found!'); // should never ever happen 00408 } 00409 } 00410 $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans(); 00411 } 00412 break; 00413 case 'userdefined': 00414 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_INSERTquery($table,$fields_values,$no_quote_fields); 00415 break; 00416 } 00417 00418 if ($this->printErrors && $this->sql_error()) { 00419 debug(array($this->lastQuery, $this->sql_error())); 00420 } 00421 00422 if ($this->debug) { 00423 $this->debugHandler( 00424 'exec_INSERTquery', 00425 t3lib_div::milliseconds()-$pt, 00426 array( 00427 'handlerType' => $hType, 00428 'args' => array($table,$fields_values), 00429 'ORIG_tablename' => $ORIG_tableName 00430 ) 00431 ); 00432 } 00433 // Return output: 00434 return $sqlResult; 00435 } 00436 00446 function exec_UPDATEquery($table,$where,$fields_values,$no_quote_fields='') { 00447 00448 if ($this->debug) $pt = t3lib_div::milliseconds(); 00449 00450 // Do table/field mapping: 00451 $ORIG_tableName = $table; 00452 if ($tableArray = $this->map_needMapping($table)) { 00453 00454 // Field mapping of array: 00455 $fields_values = $this->map_assocArray($fields_values,$tableArray); 00456 00457 // Where clause table and field mapping: 00458 $whereParts = $this->SQLparser->parseWhereClause($where); 00459 $this->map_sqlParts($whereParts,$tableArray[0]['table']); 00460 $where = $this->SQLparser->compileWhereClause($whereParts); 00461 00462 // Table name: 00463 if ($this->mapping[$table]['mapTableName']) { 00464 $table = $this->mapping[$table]['mapTableName']; 00465 } 00466 } 00467 00468 // Select API 00469 $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName); 00470 switch((string)$this->handlerCfg[$this->lastHandlerKey]['type']) { 00471 case 'native': 00472 $this->lastQuery = $this->UPDATEquery($table,$where,$fields_values,$no_quote_fields); 00473 if(is_string($this->lastQuery)) { 00474 $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']); 00475 } 00476 else { 00477 $sqlResult = mysql_query($this->lastQuery[0], $this->handlerInstance[$this->lastHandlerKey]['link']); 00478 foreach($this->lastQuery[1] as $field => $content) { 00479 mysql_query('UPDATE '.$this->quoteFromTables($table).' SET '.$this->quoteFromTables($field).'='.$this->fullQuoteStr($content,$table).' WHERE '.$this->quoteWhereClause($where), $this->handlerInstance[$this->lastHandlerKey]['link']); 00480 } 00481 } 00482 break; 00483 case 'adodb': 00484 $this->lastQuery = $this->UPDATEquery($table,$where,$fields_values,$no_quote_fields); 00485 if(is_string($this->lastQuery)) { 00486 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery,false); 00487 } else { 00488 $this->handlerInstance[$this->lastHandlerKey]->StartTrans(); 00489 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery[0],false); 00490 foreach($this->lastQuery[1] as $field => $content) { 00491 $this->handlerInstance[$this->lastHandlerKey]->UpdateBlob($this->quoteFromTables($table),$field,$content,$this->quoteWhereClause($where)); 00492 } 00493 $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans(); 00494 } 00495 break; 00496 case 'userdefined': 00497 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_UPDATEquery($table,$where,$fields_values,$no_quote_fields); 00498 break; 00499 } 00500 00501 if ($this->printErrors && $this->sql_error()) { 00502 debug(array($this->lastQuery, $this->sql_error())); 00503 } 00504 00505 if ($this->debug) { 00506 $this->debugHandler( 00507 'exec_UPDATEquery', 00508 t3lib_div::milliseconds()-$pt, 00509 array( 00510 'handlerType' => $hType, 00511 'args' => array($table,$where, $fields_values), 00512 'ORIG_from_table' => $ORIG_tableName 00513 ) 00514 ); 00515 } 00516 00517 // Return result: 00518 return $sqlResult; 00519 } 00520 00528 function exec_DELETEquery($table,$where) { 00529 00530 if ($this->debug) $pt = t3lib_div::milliseconds(); 00531 00532 // Do table/field mapping: 00533 $ORIG_tableName = $table; 00534 if ($tableArray = $this->map_needMapping($table)) { 00535 00536 // Where clause: 00537 $whereParts = $this->SQLparser->parseWhereClause($where); 00538 $this->map_sqlParts($whereParts,$tableArray[0]['table']); 00539 $where = $this->SQLparser->compileWhereClause($whereParts); 00540 00541 // Table name: 00542 if ($this->mapping[$table]['mapTableName']) { 00543 $table = $this->mapping[$table]['mapTableName']; 00544 } 00545 } 00546 00547 // Select API 00548 $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName); 00549 switch((string)$this->handlerCfg[$this->lastHandlerKey]['type']) { 00550 case 'native': 00551 $this->lastQuery = $this->DELETEquery($table,$where); 00552 $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']); 00553 break; 00554 case 'adodb': 00555 $this->lastQuery = $this->DELETEquery($table,$where); 00556 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery,false); 00557 break; 00558 case 'userdefined': 00559 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_DELETEquery($table,$where); 00560 break; 00561 } 00562 00563 if ($this->printErrors && $this->sql_error()) { 00564 debug(array($this->lastQuery, $this->sql_error())); 00565 } 00566 00567 if ($this->debug) { 00568 $this->debugHandler( 00569 'exec_DELETEquery', 00570 t3lib_div::milliseconds()-$pt, 00571 array( 00572 'handlerType' => $hType, 00573 'args' => array($table,$where), 00574 'ORIG_from_table' => $ORIG_tableName 00575 ) 00576 ); 00577 } 00578 00579 // Return result: 00580 return $sqlResult; 00581 } 00582 00594 function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='') { 00595 00596 if ($this->debug) $pt = t3lib_div::milliseconds(); 00597 00598 // Map table / field names if needed: 00599 $ORIG_tableName = $from_table; // Saving table names in $ORIG_from_table since $from_table is transformed beneath: 00600 if ($tableArray = $this->map_needMapping($ORIG_tableName)) { 00601 $this->map_remapSELECTQueryParts($select_fields,$from_table,$where_clause,$groupBy,$orderBy); // Variables passed by reference! 00602 } 00603 00604 // Get handler key and select API: 00605 $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName); 00606 $hType = (string)$this->handlerCfg[$this->lastHandlerKey]['type']; 00607 switch($hType) { 00608 case 'native': 00609 $this->lastQuery = $this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit); 00610 $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']); 00611 $this->resourceIdToTableNameMap[(string)$sqlResult] = $ORIG_tableName; 00612 break; 00613 case 'adodb': 00614 if ($limit!='') { 00615 $splitLimit = t3lib_div::intExplode(',',$limit); // Splitting the limit values: 00616 if ($splitLimit[1]) { // If there are two parameters, do mapping differently than otherwise: 00617 $numrows = $splitLimit[1]; 00618 $offset = $splitLimit[0]; 00619 } else { 00620 $numrows = $splitLimit[0]; 00621 $offset = 0; 00622 } 00623 00624 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->SelectLimit($this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy), $numrows, $offset); 00625 $this->lastQuery = $sqlResult->sql; 00626 } else { 00627 $this->lastQuery = $this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy); 00628 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_Execute($this->lastQuery); 00629 } 00630 $sqlResult->TYPO3_DBAL_handlerType = 'adodb'; // Setting handler type in result object (for later recognition!) 00631 $sqlResult->TYPO3_DBAL_tableList = $ORIG_tableName; 00632 break; 00633 case 'userdefined': 00634 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit); 00635 if (is_object($sqlResult)) { 00636 $sqlResult->TYPO3_DBAL_handlerType = 'userdefined'; // Setting handler type in result object (for later recognition!) 00637 $sqlResult->TYPO3_DBAL_tableList = $ORIG_tableName; 00638 } 00639 break; 00640 } 00641 00642 if ($this->printErrors && $this->sql_error()) { 00643 debug(array($this->lastQuery, $this->sql_error())); 00644 } 00645 00646 if ($this->debug) { 00647 $this->debugHandler( 00648 'exec_SELECTquery', 00649 t3lib_div::milliseconds()-$pt, 00650 array( 00651 'handlerType' => $hType, 00652 'args' => array($from_table,$select_fields,$where_clause,$groupBy,$orderBy,$limit), 00653 'ORIG_from_table' => $ORIG_tableName 00654 ) 00655 ); 00656 } 00657 00658 // Return result handler. 00659 return $sqlResult; 00660 } 00661 00662 00663 00664 /************************************** 00665 * 00666 * Query building 00667 * 00668 **************************************/ 00669 00680 function INSERTquery($table,$fields_values,$no_quote_fields='') { 00681 // Table and fieldnames should be "SQL-injection-safe" when supplied to this function (contrary to values in the arrays which may be insecure). 00682 if (is_array($fields_values) && count($fields_values)) { 00683 00684 if (is_string($no_quote_fields)) { 00685 $no_quote_fields = explode(',',$no_quote_fields); 00686 } elseif (!is_array($no_quote_fields)) { 00687 $no_quote_fields = array(); 00688 } 00689 00690 $blobfields = array(); 00691 $nArr = array(); 00692 foreach($fields_values as $k => $v) { 00693 if($this->sql_field_metatype($table,$k) == 'B') { 00694 /* // is this really needed for Oracle? 00695 if($this->handlerInstance[$this->lastHandlerKey]->databaseType == 'oci8') 00696 $nArr[$this->quoteFieldNames($k)] = 'empty_blob()'; 00697 else 00698 $nArr[$this->quoteFieldNames($k)] = 'null'; 00699 */ 00700 $nArr[$this->quoteFieldNames($k)] = 'null'; 00701 $blobfields[$this->quoteFieldNames($k)] = $v; 00702 } 00703 else { 00704 // Add slashes old-school: 00705 // cast numerical values 00706 $mt = $this->sql_field_metatype($table,$k); 00707 $v = (($mt{0}=='I')||($mt{0}=='F')) ? (int)$v : $v; 00708 00709 $nArr[$this->quoteFieldNames($k)] = (!in_array($k,$no_quote_fields)) ? $this->fullQuoteStr($v, $table) : $v; 00710 } 00711 } 00712 if(((string)$this->handlerCfg[$this->lastHandlerKey]['type']!=='native') && count($blobfields)) { 00713 $query[0] = 'INSERT INTO '.$this->quoteFromTables($table).' 00714 ( 00715 '.implode(', 00716 ',array_keys($nArr)).' 00717 ) VALUES ( 00718 '.implode(', 00719 ',$nArr).' 00720 )'; 00721 $query[1] = $blobfields; 00722 if ($this->debugOutput) $this->debug_lastBuiltQuery = $query[0]; 00723 } 00724 else { 00725 $query = 'INSERT INTO '.$this->quoteFromTables($table).' 00726 ( 00727 '.implode(', 00728 ',array_keys($nArr)).' 00729 ) VALUES ( 00730 '.implode(', 00731 ',$nArr).' 00732 )'; 00733 00734 if ($this->debugOutput) $this->debug_lastBuiltQuery = $query; 00735 } 00736 00737 return $query; 00738 } 00739 } 00740 00752 function UPDATEquery($table,$where,$fields_values,$no_quote_fields='') { 00753 // Table and fieldnames should be "SQL-injection-safe" when supplied to this function (contrary to values in the arrays which may be insecure). 00754 if (is_string($where)) { 00755 if (is_array($fields_values) && count($fields_values)) { 00756 00757 if (is_string($no_quote_fields)) { 00758 $no_quote_fields = explode(',',$no_quote_fields); 00759 } elseif (!is_array($no_quote_fields)) { 00760 $no_quote_fields = array(); 00761 } 00762 00763 $blobfields = array(); 00764 $nArr = array(); 00765 foreach($fields_values as $k => $v) { 00766 if($this->sql_field_metatype($table,$k) == 'B') { 00767 // do we need empty_blob() for Oracle? see also INSERTquery() 00768 $nArr[] = $this->quoteFieldNames($k).'=NULL'; 00769 $blobfields[$this->quoteFieldNames($k)] = $v; 00770 } 00771 else { 00772 // Add slashes old-school: 00773 // cast numeric values 00774 $mt = $this->sql_field_metatype($table,$k); 00775 $v = (($mt{0}=='I')||($mt{0}=='F')) ? (int)$v : $v; 00776 $nArr[] = $this->quoteFieldNames($k).'='.((!in_array($k,$no_quote_fields)) ? $this->fullQuoteStr($v, $table) : $v); 00777 } 00778 } 00779 00780 if(count($blobfields)) { 00781 $query[0] = 'UPDATE '.$this->quoteFromTables($table).' 00782 SET 00783 '.implode(', 00784 ',$nArr). 00785 (strlen($where)>0 ? ' 00786 WHERE 00787 '.$this->quoteWhereClause($where) : ''); 00788 $query[1] = $blobfields; 00789 if ($this->debugOutput) $this->debug_lastBuiltQuery = $query[0]; 00790 } 00791 else { 00792 $query = 'UPDATE '.$this->quoteFromTables($table).' 00793 SET 00794 '.implode(', 00795 ',$nArr). 00796 (strlen($where)>0 ? ' 00797 WHERE 00798 '.$this->quoteWhereClause($where) : ''); 00799 00800 if ($this->debugOutput) $this->debug_lastBuiltQuery = $query; 00801 } 00802 00803 return $query; 00804 } 00805 } 00806 else { 00807 die('<strong>TYPO3 Fatal Error:</strong> "Where" clause argument for UPDATE query was not a string in $this->UPDATEquery() !'); 00808 } 00809 } 00810 00820 function DELETEquery($table,$where) { 00821 if (is_string($where)) { 00822 $table = $this->quoteFromTables($table); 00823 $where = $this->quoteWhereClause($where); 00824 00825 $query = parent::DELETEquery($table, $where); 00826 00827 if ($this->debugOutput) $this->debug_lastBuiltQuery = $query; 00828 return $query; 00829 } else { 00830 die('<strong>TYPO3 Fatal Error:</strong> "Where" clause argument for DELETE query was not a string in $this->DELETEquery() !'); 00831 } 00832 } 00833 00847 function SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='') { 00848 00849 $select_fields = $this->quoteFieldNames($select_fields); 00850 $from_table = $this->quoteFromTables($from_table); 00851 $where_clause = $this->quoteWhereClause($where_clause); 00852 $groupBy = $this->quoteGroupBy($groupBy); 00853 $orderBy = $this->quoteOrderBy($orderBy); 00854 00855 // call parent method to build actual query 00856 $query = parent::SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit); 00857 00858 if ($this->debugOutput) $this->debug_lastBuiltQuery = $query; 00859 00860 return $query; 00861 } 00862 00863 00864 /************************************** 00865 * 00866 * Functions for quoting table/field names 00867 * 00868 **************************************/ 00869 00878 function quoteSelectFields($select_fields) { 00879 $this->quoteFieldNames($select_fields); 00880 } 00881 00888 function quoteFieldNames($select_fields) { 00889 if($select_fields == '') return ''; 00890 00891 $select_fields = $this->SQLparser->parseFieldList($select_fields); 00892 foreach($select_fields as $k => $v) { 00893 if($select_fields[$k]['field'] != '' && $select_fields[$k]['field'] != '*') { 00894 $select_fields[$k]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$select_fields[$k]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00895 } 00896 if($select_fields[$k]['table'] != '') { 00897 $select_fields[$k]['table'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$select_fields[$k]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00898 } 00899 if($select_fields[$k]['as'] != '') { 00900 $select_fields[$k]['as'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$select_fields[$k]['as'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00901 } 00902 if(isset($select_fields[$k]['func_content.']) && $select_fields[$k]['func_content.'][0]['func_content'] != '*'){ 00903 if(strstr($select_fields[$k]['func_content.'][0]['func_content'],'.')) { 00904 $select_fields[$k]['func_content.'][0]['func_content'] = $this->quoteFieldNames($select_fields[$k]['func_content.'][0]['func_content']); 00905 $select_fields[$k]['func_content'] = $this->quoteFieldNames($select_fields[$k]['func_content']); 00906 } 00907 else { 00908 $select_fields[$k]['func_content.'][0]['func_content'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$select_fields[$k]['func_content.'][0]['func_content'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00909 $select_fields[$k]['func_content'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$select_fields[$k]['func_content'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00910 } 00911 } 00912 } 00913 00914 return $this->SQLparser->compileFieldList($select_fields); 00915 } 00916 00923 function quoteFromTables($from_table) { 00924 if($from_table == '') return ''; 00925 00926 $from_table = $this->SQLparser->parseFromTables($from_table); 00927 foreach($from_table as $k => $v) { 00928 $from_table[$k]['table'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00929 if($from_table[$k]['as'] != '') { 00930 $from_table[$k]['as'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['as'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00931 } 00932 if (is_array($v['JOIN'])) { 00933 $from_table[$k]['JOIN']['withTable'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['JOIN']['withTable'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00934 $from_table[$k]['JOIN']['ON'][0]['table'] = ($from_table[$k]['JOIN']['ON'][0]['table']) ? $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['JOIN']['ON'][0]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote : ''; 00935 $from_table[$k]['JOIN']['ON'][0]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['JOIN']['ON'][0]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00936 $from_table[$k]['JOIN']['ON'][1]['table'] = ($from_table[$k]['JOIN']['ON'][1]['table']) ? $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['JOIN']['ON'][1]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote : ''; 00937 $from_table[$k]['JOIN']['ON'][1]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['JOIN']['ON'][1]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00938 } 00939 } 00940 return $this->SQLparser->compileFromTables($from_table); 00941 } 00942 00949 function quoteWhereClause($where_clause) { 00950 if($where_clause == '') return ''; 00951 00952 $where_clause = $this->SQLparser->parseWhereClause($where_clause); 00953 $where_clause = $this->_quoteWhereClause($where_clause); 00954 $where_clause = $this->SQLparser->compileWhereClause($where_clause); 00955 00956 return $where_clause; 00957 } 00958 00965 function _quoteWhereClause($where_clause) { 00966 foreach($where_clause as $k => $v) { 00967 // Look for sublevel: 00968 if (is_array($where_clause[$k]['sub'])) { 00969 $where_clause[$k]['sub'] = $this->_quoteWhereClause($where_clause[$k]['sub']); 00970 } else { 00971 if($where_clause[$k]['table'] != '') { 00972 $where_clause[$k]['table'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$where_clause[$k]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00973 } 00974 if(!is_numeric($where_clause[$k]['field'])) { 00975 $where_clause[$k]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$where_clause[$k]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00976 } 00977 } 00978 if ($where_clause[$k]['comparator']) { 00979 // Detecting value type; list or plain: 00980 if ((!isset($where_clause[$k]['value'][1]) || $where_clause[$k]['value'][1] == '') && is_string($where_clause[$k]['value'][0]) && strstr($where_clause[$k]['value'][0], '.') && !t3lib_div::inList('NOTIN,IN',strtoupper(str_replace(array(" ","\n","\r","\t"),'',$where_clause[$k]['comparator'])))) { 00981 $where_clause[$k]['value'][0] = $this->quoteFieldNames($where_clause[$k]['value'][0]); 00982 } 00983 } 00984 } 00985 00986 return $where_clause; 00987 } 00988 00995 function quoteGroupBy($groupBy) { 00996 if($groupBy == '') return ''; 00997 00998 $groupBy = $this->SQLparser->parseFieldList($groupBy); 00999 foreach($groupBy as $k => $v) { 01000 $groupBy[$k]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$groupBy[$k]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 01001 if($groupBy[$k]['table'] != '') { 01002 $groupBy[$k]['table'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$groupBy[$k]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 01003 } 01004 } 01005 return $this->SQLparser->compileFieldList($groupBy); 01006 } 01007 01014 function quoteOrderBy($orderBy) { 01015 if($orderBy == '') return ''; 01016 01017 $orderBy = $this->SQLparser->parseFieldList($orderBy); 01018 foreach($orderBy as $k => $v) { 01019 $orderBy[$k]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$orderBy[$k]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 01020 if($orderBy[$k]['table'] != '') { 01021 $orderBy[$k]['table'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$orderBy[$k]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 01022 } 01023 } 01024 return $this->SQLparser->compileFieldList($orderBy); 01025 } 01026 01027 01028 01029 /************************************** 01030 * 01031 * Various helper functions 01032 * 01033 **************************************/ 01034 01043 function fullQuoteStr($str,$table) { 01044 return '\''.$this->quoteStr($str, $table).'\''; 01045 } 01046 01056 function quoteStr($str, $table) { 01057 $this->lastHandlerKey = $this->handler_getFromTableList($table); 01058 switch((string)$this->handlerCfg[$this->lastHandlerKey]['type']) { 01059 case 'native': 01060 $str = mysql_real_escape_string($str, $this->handlerInstance[$this->lastHandlerKey]['link']); 01061 break; 01062 case 'adodb': 01063 $str = substr($this->handlerInstance[$this->lastHandlerKey]->qstr($str),1,-1); 01064 break; 01065 case 'userdefined': 01066 $str = $this->handlerInstance[$this->lastHandlerKey]->quoteStr($str); 01067 break; 01068 default: 01069 die('No handler found!!!'); 01070 break; 01071 } 01072 01073 return $str; 01074 } 01075 01076 01084 function MetaType($type,$table,$max_length=-1) { 01085 $this->lastHandlerKey = $this->handler_getFromTableList($table); 01086 switch((string)$this->handlerCfg[$this->lastHandlerKey]['type']) { 01087 case 'adodb': 01088 $rs = $this->handlerInstance[$this->lastHandlerKey]->SelectLimit('SELECT * FROM '.$this->quoteFromTables($table),1); 01089 $str = $rs->MetaType($type, $max_length); 01090 break; 01091 default: 01092 die('No handler found!!!'); 01093 break; 01094 } 01095 01096 return $str; 01097 } 01098 01099 01106 function MySQLMetaType($t) { 01107 01108 switch (strtoupper($t)) { 01109 case 'STRING': 01110 case 'CHAR': 01111 case 'VARCHAR': 01112 case 'TINYBLOB': 01113 case 'TINYTEXT': 01114 case 'ENUM': 01115 case 'SET': 01116 return 'C'; 01117 01118 case 'TEXT': 01119 case 'LONGTEXT': 01120 case 'MEDIUMTEXT': 01121 return 'X'; 01122 01123 // php_mysql extension always returns 'blob' even if 'text' 01124 // so we have to check whether binary... 01125 case 'IMAGE': 01126 case 'LONGBLOB': 01127 case 'BLOB': 01128 case 'MEDIUMBLOB': 01129 return 'B'; 01130 01131 case 'YEAR': 01132 case 'DATE': return 'D'; 01133 01134 case 'TIME': 01135 case 'DATETIME': 01136 case 'TIMESTAMP': return 'T'; 01137 01138 case 'FLOAT': 01139 case 'DOUBLE': 01140 return 'F'; 01141 01142 case 'INT': 01143 case 'INTEGER': return 'I'; 01144 case 'TINYINT': // MS SQL Server allows only 0..255 for tinyint, so we do not map to I1 01145 case 'SMALLINT': return 'I2'; 01146 case 'MEDIUMINT': return 'I4'; 01147 case 'BIGINT': return 'I8'; 01148 01149 default: return 'N'; 01150 } 01151 } 01152 01159 function MySQLActualType($meta) { 01160 switch(strtoupper($meta)) { 01161 case 'C': return 'VARCHAR'; 01162 case 'XL': 01163 case 'X': return 'LONGTEXT'; 01164 01165 case 'C2': return 'VARCHAR'; 01166 case 'X2': return 'LONGTEXT'; 01167 01168 case 'B': return 'LONGBLOB'; 01169 01170 case 'D': return 'DATE'; 01171 case 'T': return 'DATETIME'; 01172 case 'L': return 'TINYINT'; 01173 01174 case 'I': return 'INT'; 01175 case 'I1': // MS SQL Server allows only 0..255 for tinyint, so we do not map to TINYINT 01176 case 'I2': return 'SMALLINT'; 01177 case 'I4': return 'MEDIUMINT'; 01178 case 'I8': return 'BIGINT'; 01179 01180 case 'F': return 'DOUBLE'; 01181 case 'N': return 'NUMERIC'; 01182 default: 01183 return $meta; 01184 } 01185 } 01186 01187 01188 01189 01190 /************************************** 01191 * 01192 * SQL wrapper functions (Overriding parent methods) 01193 * (For use in your applications) 01194 * 01195 **************************************/ 01196 01202 function sql_error() { 01203 01204 switch($this->handlerCfg[$this->lastHandlerKey]['type']) { 01205 case 'native': 01206 $output = mysql_error($this->handlerInstance[$this->lastHandlerKey]['link']); 01207 break; 01208 case 'adodb': 01209 $output = $this->handlerInstance[$this->lastHandlerKey]->ErrorMsg(); 01210 break; 01211 case 'userdefined': 01212 $output = $this->handlerInstance[$this->lastHandlerKey]->sql_error(); 01213 break; 01214 } 01215 return $output; 01216 } 01217 01224 function sql_num_rows(&$res) { 01225 01226 $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : 'native'; 01227 switch($handlerType) { 01228 case 'native': 01229 $output = mysql_num_rows($res); 01230 break; 01231 case 'adodb': 01232 $output = method_exists($res, 'RecordCount') ? $res->RecordCount() : 0; 01233 break; 01234 case 'userdefined': 01235 $output = $res->sql_num_rows(); 01236 break; 01237 } 01238 return $output; 01239 } 01240 01247 function sql_fetch_assoc(&$res) { 01248 $output = array(); 01249 01250 $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : (is_resource($res) ? 'native' : false); 01251 switch($handlerType) { 01252 case 'native': 01253 $output = mysql_fetch_assoc($res); 01254 $tableList = $this->resourceIdToTableNameMap[(string)$res]; // Reading list of tables from SELECT query: 01255 break; 01256 case 'adodb': 01257 // Check if method exists for the current $res object. 01258 // If a table exists in TCA but not in the db, a error 01259 // occured because $res is not a valid object. 01260 if(method_exists($res, 'FetchRow')) { 01261 $output = $res->FetchRow(); 01262 $tableList = $res->TYPO3_DBAL_tableList; // Reading list of tables from SELECT query: 01263 01264 // Removing all numeric/integer keys. 01265 // A workaround because in ADOdb we would need to know what we want before executing the query... 01266 if (is_array($output)) { 01267 foreach($output as $key => $value) { 01268 if (is_integer($key)) unset($output[$key]); 01269 elseif($value===' ' && strstr($GLOBALS['TYPO3_DB']->handlerCfg[$GLOBALS['TYPO3_DB']->lastHandlerKey]['config']['driver'],'mssql')) $output[$key]=''; // MSSQL does not know such thing as an empty string. So it returns one space instead, which we must fix. 01270 } 01271 } 01272 } 01273 break; 01274 case 'userdefined': 01275 $output = $res->sql_fetch_assoc(); 01276 $tableList = $res->TYPO3_DBAL_tableList; // Reading list of tables from SELECT query: 01277 break; 01278 } 01279 01280 // Table/Fieldname mapping: 01281 if (is_array($output)) { 01282 if ($tables = $this->map_needMapping($tableList,TRUE)) { 01283 $output = $this->map_assocArray($output,$tables,1); 01284 } 01285 } 01286 01287 // Return result: 01288 return $output; 01289 } 01290 01298 function sql_fetch_row(&$res) { 01299 $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : 'native'; 01300 switch($handlerType) { 01301 case 'native': 01302 $output = mysql_fetch_row($res); 01303 break; 01304 case 'adodb': 01305 // Check if method exists for the current $res object. 01306 // If a table exists in TCA but not in the db, a error 01307 // occured because $res is not a valid object. 01308 if(method_exists($res, 'FetchRow')) { 01309 $output = $res->FetchRow(); 01310 01311 // Removing all assoc. keys. 01312 // A workaround because in ADOdb we would need to know what we want before executing the query... 01313 if (is_array($output)) { 01314 foreach($output as $key => $value) { 01315 if (!is_integer($key)) unset($output[$key]); 01316 elseif($value===' ' && strstr($GLOBALS['TYPO3_DB']->handlerCfg[$GLOBALS['TYPO3_DB']->lastHandlerKey]['config']['driver'],'mssql')) $output[$key]=''; // MSSQL does not know such thing as an empty string. So it returns one space instead, which we must fix. 01317 } 01318 } 01319 } 01320 break; 01321 case 'userdefined': 01322 $output = $res->sql_fetch_row(); 01323 break; 01324 } 01325 return $output; 01326 } 01327 01334 function sql_free_result(&$res) { 01335 01336 $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : 'native'; 01337 switch($handlerType) { 01338 case 'native': 01339 $output = mysql_free_result($res); 01340 break; 01341 case 'adodb': 01342 if(method_exists($res, 'Close')) { 01343 $res->Close(); 01344 unset($res); 01345 $output = true; 01346 } else { 01347 $output = false; 01348 } 01349 break; 01350 case 'userdefined': 01351 unset($res); 01352 break; 01353 } 01354 return $output; 01355 } 01356 01362 function sql_insert_id() { 01363 01364 switch($this->handlerCfg[$this->lastHandlerKey]['type']) { 01365 case 'native': 01366 $output = mysql_insert_id($this->handlerInstance[$this->lastHandlerKey]['link']); 01367 break; 01368 case 'adodb': 01369 $output = $this->handlerInstance[$this->lastHandlerKey]->last_insert_id; 01370 break; 01371 case 'userdefined': 01372 $output = $this->handlerInstance[$this->lastHandlerKey]->sql_insert_id(); 01373 break; 01374 } 01375 return $output; 01376 } 01377 01383 function sql_affected_rows() { 01384 01385 switch($this->handlerCfg[$this->lastHandlerKey]['type']) { 01386 case 'native': 01387 $output = mysql_affected_rows(); 01388 break; 01389 case 'adodb': 01390 $output = $this->handlerInstance[$this->lastHandlerKey]->Affected_Rows(); 01391 break; 01392 case 'userdefined': 01393 $output = $this->handlerInstance[$this->lastHandlerKey]->sql_affected_rows(); 01394 break; 01395 } 01396 return $output; 01397 } 01398 01406 function sql_data_seek(&$res,$seek) { 01407 01408 $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : 'native'; 01409 switch($handlerType) { 01410 case 'native': 01411 $output = mysql_data_seek($res,$seek); 01412 break; 01413 case 'adodb': 01414 $output = $res->Move($seek); 01415 break; 01416 case 'userdefined': 01417 $output = $res->sql_data_seek($seek); 01418 break; 01419 } 01420 return $output; 01421 } 01422 01432 function sql_field_metatype($table,$field) { 01433 return $this->cache_fieldType[$table][$field]['metaType']; 01434 } 01435 01445 function sql_field_type(&$res,$pointer) { 01446 if($res === null) { 01447 debug(array('no res in sql_field_type!')); 01448 return 'text'; 01449 } 01450 else if(is_string($res)){ 01451 if($res == 'tx_dbal_debuglog') return 'text'; 01452 $handlerType = 'adodb'; 01453 } 01454 else { 01455 $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : 'native'; 01456 } 01457 01458 switch($handlerType) { 01459 case 'native': 01460 $output = mysql_field_type($res,$pointer); 01461 break; 01462 case 'adodb': 01463 if(is_string($pointer)){ 01464 $output = $this->cache_fieldType[$res][$pointer]['type']; 01465 } 01466 01467 break; 01468 case 'userdefined': 01469 $output = $res->sql_field_type($pointer); 01470 break; 01471 } 01472 01473 return $output; 01474 } 01475 01476 01477 01478 01479 01480 01481 01482 01483 /********** 01484 * 01485 * Legacy functions, bound to _DEFAULT handler. (Overriding parent methods) 01486 * Depreciated. 01487 * 01488 **********/ 01489 01499 function sql($db,$query) { 01500 return $this->sql_query($query); 01501 } 01502 01511 function sql_query($query) { 01512 01513 switch($this->handlerCfg['_DEFAULT']['type']) { 01514 case 'native': 01515 $sqlResult = mysql_query($query, $this->handlerInstance['_DEFAULT']['link']); 01516 break; 01517 case 'adodb': 01518 $sqlResult = $this->handlerInstance['_DEFAULT']->Execute($query); 01519 $sqlResult->TYPO3_DBAL_handlerType = 'adodb'; 01520 break; 01521 case 'userdefined': 01522 $sqlResult = $this->handlerInstance['_DEFAULT']->sql_query($query); 01523 $sqlResult->TYPO3_DBAL_handlerType = 'userdefined'; 01524 break; 01525 } 01526 01527 if ($this->printErrors && $this->sql_error()) { 01528 debug(array($this->lastQuery, $this->sql_error())); 01529 } 01530 01531 return $sqlResult; 01532 } 01533 01546 function sql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password) { 01547 // Overriding the _DEFAULT handler configuration of username, password, localhost and database name: 01548 $this->handlerCfg['_DEFAULT']['config']['username'] = $TYPO3_db_username; 01549 $this->handlerCfg['_DEFAULT']['config']['password'] = $TYPO3_db_password; 01550 $this->handlerCfg['_DEFAULT']['config']['host'] = $TYPO3_db_host; 01551 $this->handlerCfg['_DEFAULT']['config']['database'] = TYPO3_db; 01552 01553 // Initializing and output value: 01554 $sqlResult = $this->handler_init('_DEFAULT'); 01555 return $sqlResult; 01556 } 01557 01565 function sql_select_db($TYPO3_db) { 01566 return TRUE; 01567 } 01568 01569 01570 01571 01572 01573 01574 01575 01576 01577 01578 01579 01580 01581 01582 01583 /************************************** 01584 * 01585 * SQL admin functions 01586 * (For use in the Install Tool and Extension Manager) 01587 * 01588 **************************************/ 01589 01597 function admin_get_dbs() { 01598 $dbArr = array(); 01599 switch($this->handlerCfg['_DEFAULT']['type']) { 01600 case 'native': 01601 $db_list = mysql_list_dbs($this->link); 01602 while ($row = mysql_fetch_object($db_list)) { 01603 if ($this->sql_select_db($row->Database)) { 01604 $dbArr[] = $row->Database; 01605 } 01606 } 01607 break; 01608 case 'adodb': 01609 // check needed for install tool - otherwise it will just die because the call to 01610 // MetaDatabases is done on a stdClass instance 01611 if(method_exists($this->handlerInstance['_DEFAULT'],'MetaDatabases')) { 01612 $sqlDBs = $this->handlerInstance['_DEFAULT']->MetaDatabases(); 01613 if(is_array($sqlDBs)) { 01614 foreach($sqlDBs as $k => $theDB) { 01615 $dbArr[] = $theDB; 01616 } 01617 } 01618 } 01619 break; 01620 case 'userdefined': 01621 $dbArr = $this->handlerInstance['_DEFAULT']->admin_get_tables(); 01622 break; 01623 } 01624 01625 return $dbArr; 01626 } 01627 01634 function admin_get_tables() { 01635 $whichTables = array(); 01636 01637 // Getting real list of tables: 01638 switch($this->handlerCfg['_DEFAULT']['type']) { 01639 case 'native': 01640 $tables_result = mysql_list_tables(TYPO3_db, $this->handlerInstance['_DEFAULT']['link']); 01641 if (!$this->sql_error()) { 01642 while ($theTable = $this->sql_fetch_assoc($tables_result)) { 01643 $whichTables[current($theTable)] = current($theTable); 01644 } 01645 } 01646 break; 01647 case 'adodb': 01648 $sqlTables = $this->handlerInstance['_DEFAULT']->MetaTables('TABLES'); 01649 while (list($k, $theTable) = each($sqlTables)) { 01650 $whichTables[$theTable] = $theTable; 01651 } 01652 break; 01653 case 'userdefined': 01654 $whichTables = $this->handlerInstance['_DEFAULT']->admin_get_tables(); 01655 break; 01656 } 01657 01658 // Check mapping: 01659 if (is_array($this->mapping)) { 01660 01661 // Mapping table names in reverse, first getting list of real table names: 01662 $tMap = array(); 01663 foreach($this->mapping as $tN => $tMapInfo) { 01664 if (isset($tMapInfo['mapTableName'])) $tMap[$tMapInfo['mapTableName']]=$tN; 01665 } 01666 01667 // Do mapping: 01668 $newList=array(); 01669 foreach($whichTables as $tN) { 01670 if (isset($tMap[$tN])) $tN = $tMap[$tN]; 01671 $newList[$tN] = $tN; 01672 } 01673 01674 $whichTables = $newList; 01675 } 01676 01677 // Adding tables configured to reside in other DBMS (handler by other handlers than the default): 01678 if (is_array($this->table2handlerKeys)) { 01679 foreach($this->table2handlerKeys as $key => $handlerKey) { 01680 $whichTables[$key] = $key; 01681 } 01682 } 01683 01684 return $whichTables; 01685 } 01686 01695 function admin_get_fields($tableName) { 01696 $output = array(); 01697 01698 // Do field mapping if needed: 01699 $ORIG_tableName = $tableName; 01700 if ($tableArray = $this->map_needMapping($tableName)) { 01701 01702 // Table name: 01703 if ($this->mapping[$tableName]['mapTableName']) { 01704 $tableName = $this->mapping[$tableName]['mapTableName']; 01705 } 01706 } 01707 01708 // Find columns 01709 $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName); 01710 switch((string)$this->handlerCfg[$this->lastHandlerKey]['type']) { 01711 case 'native': 01712 $columns_res = mysql_query('SHOW columns FROM '.$tableName, $this->handlerInstance[$this->lastHandlerKey]['link']); 01713 while($fieldRow = mysql_fetch_assoc($columns_res)) { 01714 $output[$fieldRow['Field']] = $fieldRow; 01715 } 01716 break; 01717 case 'adodb': 01718 $fieldRows = $this->handlerInstance[$this->lastHandlerKey]->MetaColumns($tableName, false); 01719 foreach($fieldRows as $k => $fieldRow) { 01720 settype($fieldRow, 'array'); 01721 $fieldRow['Field'] = $fieldRow['name']; 01722 $ntype = $this->MySQLActualType($this->MetaType($fieldRow['type'],$tableName)); 01723 $ntype .= (($fieldRow['max_length'] != -1) ? (($ntype == 'INT') ? '(11)' :'('.$fieldRow['max_length'].')') : ''); 01724 $fieldRow['Type'] = strtolower($ntype); 01725 $fieldRow['Null'] = ''; 01726 $fieldRow['Key'] = ''; 01727 $fieldRow['Default'] = $fieldRow['default_value']; 01728 $fieldRow['Extra'] = ''; 01729 $output[$fieldRow['name']] = $fieldRow; 01730 } 01731 break; 01732 case 'userdefined': 01733 $output = $this->handlerInstance[$this->lastHandlerKey]->admin_get_fields($tableName); 01734 break; 01735 } 01736 01737 // mapping should be done: 01738 if (is_array($tableArray) && is_array($this->mapping[$ORIG_tableName]['mapFieldNames'])) { 01739 $revFields = array_flip($this->mapping[$ORIG_tableName]['mapFieldNames']); 01740 01741 $newOutput = array(); 01742 foreach($output as $fN => $fInfo) { 01743 if (isset($revFields[$fN])) { 01744 $fN = $revFields[$fN]; 01745 $fInfo['Field'] = $fN; 01746 } 01747 $newOutput[$fN] = $fInfo; 01748 } 01749 $output = $newOutput; 01750 } 01751 01752 return $output; 01753 } 01754 01762 function admin_get_keys($tableName) { 01763 $output = array(); 01764 01765 // Do field mapping if needed: 01766 $ORIG_tableName = $tableName; 01767 if ($tableArray = $this->map_needMapping($tableName)) { 01768 01769 // Table name: 01770 if ($this->mapping[$tableName]['mapTableName']) { 01771 $tableName = $this->mapping[$tableName]['mapTableName']; 01772 } 01773 } 01774 01775 // Find columns 01776 $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName); 01777 switch((string)$this->handlerCfg[$this->lastHandlerKey]['type']) { 01778 case 'native': 01779 $keyRes = mysql_query('SHOW keys FROM '.$tableName, $this->handlerInstance[$this->lastHandlerKey]['link']); 01780 while($keyRow = mysql_fetch_assoc($keyRes)) { 01781 $output[] = $keyRow; 01782 } 01783 break; 01784 case 'adodb': 01785 $keyRows = $this->handlerInstance[$this->lastHandlerKey]->MetaIndexes($tableName); 01786 if($keyRows !== false) { 01787 while (list($k, $theKey) = each($keyRows)) { 01788 $theKey['Table'] = $tableName; 01789 $theKey['Non_unique'] = (int) !$theKey['unique']; 01790 $theKey['Key_name'] = str_replace($tableName.'_','',$k); 01791 01792 // the following are probably not needed anyway... 01793 $theKey['Collation'] = ''; 01794 $theKey['Cardinality'] = ''; 01795 $theKey['Sub_part'] = ''; 01796 $theKey['Packed'] = ''; 01797 $theKey['Null'] = ''; 01798 $theKey['Index_type'] = ''; 01799 $theKey['Comment'] = ''; 01800 01801 // now map multiple fields into multiple rows (we mimic MySQL, remember...) 01802 $keycols = $theKey['columns']; 01803 while (list($c, $theCol) = each($keycols)) { 01804 $theKey['Seq_in_index'] = $c+1; 01805 $theKey['Column_name'] = $theCol; 01806 $output[] = $theKey; 01807 } 01808 } 01809 } 01810 $priKeyRow = $this->handlerInstance[$this->lastHandlerKey]->MetaPrimaryKeys($tableName); 01811 $theKey = array(); 01812 $theKey['Table'] = $tableName; 01813 $theKey['Non_unique'] = 0; 01814 $theKey['Key_name'] = 'PRIMARY'; 01815 01816 // the following are probably not needed anyway... 01817 $theKey['Collation'] = ''; 01818 $theKey['Cardinality'] = ''; 01819 $theKey['Sub_part'] = ''; 01820 $theKey['Packed'] = ''; 01821 $theKey['Null'] = ''; 01822 $theKey['Index_type'] = ''; 01823 $theKey['Comment'] = ''; 01824 01825 // now map multiple fields into multiple rows (we mimic MySQL, remember...) 01826 if($priKeyRow !== false) { 01827 while (list($c, $theCol) = each($priKeyRow)) { 01828 $theKey['Seq_in_index'] = $c+1; 01829 $theKey['Column_name'] = $theCol; 01830 $output[] = $theKey; 01831 } 01832 } 01833 break; 01834 case 'userdefined': 01835 $output = $this->handlerInstance[$this->lastHandlerKey]->admin_get_keys($tableName); 01836 break; 01837 } 01838 01839 // mapping should be done: 01840 if (is_array($tableArray) && is_array($this->mapping[$ORIG_tableName]['mapFieldNames'])) { 01841 $revFields = array_flip($this->mapping[$ORIG_tableName]['mapFieldNames']); 01842 01843 $newOutput = array(); 01844 foreach($output as $kN => $kInfo) { 01845 // Table: 01846 $kInfo['Table'] = $ORIG_tableName; 01847 01848 // Column 01849 if (isset($revFields[$kInfo['Column_name']])) { 01850 $kInfo['Column_name'] = $revFields[$kInfo['Column_name']]; 01851 } 01852 01853 // Write it back: 01854 $newOutput[$kN] = $kInfo; 01855 } 01856 $output = $newOutput; 01857 } 01858 01859 return $output; 01860 } 01861 01868 function admin_query($query) { 01869 $parsedQuery = $this->SQLparser->parseSQL($query); 01870 $ORIG_table = $parsedQuery['TABLE']; 01871 01872 if (is_array($parsedQuery)) { 01873 01874 // Process query based on type: 01875 switch($parsedQuery['type']) { 01876 case 'CREATETABLE': 01877 case 'ALTERTABLE': 01878 case 'DROPTABLE': 01879 if(file_exists(PATH_typo3conf.'temp_fieldInfo.php')) unlink(PATH_typo3conf.'temp_fieldInfo.php'); 01880 $this->map_genericQueryParsed($parsedQuery); 01881 break; 01882 case 'INSERT': 01883 $this->map_genericQueryParsed($parsedQuery); 01884 break; 01885 case 'CREATEDATABASE': 01886 die('Creating a database with DBAL is not supported. Did you really read the manual?'); 01887 break; 01888 default: 01889 die('ERROR: Invalid Query type ('.$parsedQuery['type'].') for ->admin_query() function!: "'.htmlspecialchars($query).'"'); 01890 break; 01891 } 01892 01893 // Setting query array (for other applications to access if needed) 01894 $this->lastParsedAndMappedQueryArray = $parsedQuery; 01895 01896 // Execute query (based on handler derived from the TABLE name which we actually know for once!) 01897 $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_table); 01898 switch((string)$this->handlerCfg[$this->lastHandlerKey]['type']) { 01899 case 'native': 01900 // Compiling query: 01901 $compiledQuery = $this->SQLparser->compileSQL($this->lastParsedAndMappedQueryArray); 01902 01903 return mysql_query($compiledQuery[0], $this->link); 01904 break; 01905 case 'adodb': 01906 // Compiling query: 01907 $compiledQuery = $this->SQLparser->compileSQL($this->lastParsedAndMappedQueryArray); 01908 if($this->lastParsedAndMappedQueryArray['type']=='INSERT') { 01909 return $this->exec_INSERTquery($this->lastParsedAndMappedQueryArray['TABLE'],$compiledQuery); 01910 } 01911 return $this->handlerInstance[$this->lastHandlerKey]->DataDictionary->ExecuteSQLArray($compiledQuery); 01912 break; 01913 case 'userdefined': 01914 // Compiling query: 01915 $compiledQuery = $this->SQLparser->compileSQL($this->lastParsedAndMappedQueryArray); 01916 01917 return $this->handlerInstance[$this->lastHandlerKey]->admin_query($compiledQuery); 01918 break; 01919 } 01920 } else die('ERROR: Query could not be parsed: "'.htmlspecialchars($parsedQuery).'". Query: "'.htmlspecialchars($query).'"'); 01921 } 01922 01923 01924 01925 01926 01927 01928 01929 01930 01931 01932 /************************************ 01933 * 01934 * Handler management 01935 * 01936 **************************************/ 01937 01945 function handler_getFromTableList($tableList) { 01946 01947 $key = $tableList; 01948 01949 if (!isset($this->cache_handlerKeyFromTableList[$key])) { 01950 01951 // Get tables separated: 01952 $_tableList = $tableList; 01953 $tableArray = $this->SQLparser->parseFromTables($_tableList); 01954 01955 // If success, traverse the tables: 01956 if (is_array($tableArray) && count($tableArray)) { 01957 foreach($tableArray as $vArray) { 01958 01959 // Find handler key, select "_DEFAULT" if none is specifically configured: 01960 $handlerKey = $this->table2handlerKeys[$vArray['table']] ? $this->table2handlerKeys[$vArray['table']] : '_DEFAULT'; 01961 01962 // In case of separate handler keys for joined tables: 01963 if ($outputHandlerKey && $handlerKey != $outputHandlerKey) { 01964 die('DBAL fatal error: Tables in this list "'.$tableList.'" didn\'t use the same DB handler!'); 01965 } 01966 01967 $outputHandlerKey = $handlerKey; 01968 } 01969 01970 // Check initialized state; if handler is NOT initialized (connected) then we will connect it! 01971 if (!isset($this->handlerInstance[$outputHandlerKey])) { 01972 $this->handler_init($outputHandlerKey); 01973 } 01974 01975 // Return handler key: 01976 $this->cache_handlerKeyFromTableList[$key] = $outputHandlerKey; 01977 } else { 01978 die('DBAL fatal error: No tables found: "'.$tableList.'"'); 01979 } 01980 } 01981 01982 return $this->cache_handlerKeyFromTableList[$key]; 01983 } 01984 01992 function handler_init($handlerKey) { 01993 01994 // Find handler configuration: 01995 $cfgArray = $this->handlerCfg[$handlerKey]; 01996 $handlerType = (string)$cfgArray['type']; 01997 $output = FALSE; 01998 01999 if (is_array($cfgArray)) { 02000 switch($handlerType) { 02001 case 'native': 02002 $link = mysql_pconnect($cfgArray['config']['host'].(isset($cfgArray['config']['port']) ? ':'.$cfgArray['config']['port'] : ''), $cfgArray['config']['username'], $cfgArray['config']['password']); 02003 02004 // Set handler instance: 02005 $this->handlerInstance[$handlerKey] = array('handlerType' => 'native', 'link' => $link); 02006 02007 // If link succeeded: 02008 if ($link) { 02009 // For default, set ->link (see t3lib_DB) 02010 if ($handlerKey == '_DEFAULT') { 02011 $this->link = $link; 02012 } 02013 02014 // Select database as well: 02015 if (mysql_select_db($cfgArray['config']['database'], $link)) { 02016 $output = TRUE; 02017 } 02018 $setDBinit = t3lib_div::trimExplode(chr(10), $GLOBALS['TYPO3_CONF_VARS']['SYS']['setDBinit']); 02019 foreach ($setDBinit as $v) { 02020 if (mysql_query($v, $this->link) === FALSE) { 02021 t3lib_div::sysLog('Could not initialize DB connection with query "'.$v.'".','Core',3); 02022 } 02023 } 02024 } 02025 break; 02026 case 'adodb': 02027 $output = true; 02028 require_once(t3lib_extMgm::extPath('adodb').'adodb/adodb.inc.php'); 02029 if(!defined('ADODB_FORCE_NULLS')) define('ADODB_FORCE_NULLS', 1); 02030 $GLOBALS['ADODB_FORCE_TYPE'] = ADODB_FORCE_VALUE; 02031 $GLOBALS['ADODB_FETCH_MODE'] = ADODB_FETCH_BOTH; 02032 02033 $this->handlerInstance[$handlerKey] = &ADONewConnection($cfgArray['config']['driver']); 02034 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['no_pconnect']) { 02035 $this->handlerInstance[$handlerKey]->Connect($cfgArray['config']['host'].(isset($cfgArray['config']['port']) ? ':'.$cfgArray['config']['port'] : ''),$cfgArray['config']['username'],$cfgArray['config']['password'],$cfgArray['config']['database']); 02036 } else { 02037 $this->handlerInstance[$handlerKey]->PConnect($cfgArray['config']['host'].(isset($cfgArray['config']['port']) ? ':'.$cfgArray['config']['port'] : ''),$cfgArray['config']['username'],$cfgArray['config']['password'],$cfgArray['config']['database']); 02038 } 02039 if(!$this->handlerInstance[$handlerKey]->isConnected()) { 02040 $dsn = $cfgArray['config']['driver'].'://'.$cfgArray['config']['username']. 02041 (strlen($cfgArray['config']['password']) ? ':XXXX@' : ''). 02042 $cfgArray['config']['host'].(isset($cfgArray['config']['port']) ? ':'.$cfgArray['config']['port'] : '').'/'.$cfgArray['config']['database']. 02043 ($GLOBALS['TYPO3_CONF_VARS']['SYS']['no_pconnect'] ? '' : '?persistent=1'); 02044 error_log('DBAL error: Connection to '.$dsn.' failed. Maybe PHP doesn\'t support the database?'); 02045 $output = false; 02046 } else { 02047 $this->handlerInstance[$handlerKey]->DataDictionary = NewDataDictionary($this->handlerInstance[$handlerKey]); 02048 $this->handlerInstance[$handlerKey]->last_insert_id = 0; 02049 } 02050 break; 02051 case 'userdefined': 02052 // Find class file: 02053 $fileName = t3lib_div::getFileAbsFileName($cfgArray['config']['classFile']); 02054 if (@is_file($fileName)) { 02055 require_once($fileName); 02056 } else die('DBAL error: "'.$fileName.'" was not a file to include.'); 02057 02058 // Initialize: 02059 $this->handlerInstance[$handlerKey] = t3lib_div::makeInstance($cfgArray['config']['class']); 02060 $this->handlerInstance[$handlerKey]->init($cfgArray,$this); 02061 02062 if (is_object($this->handlerInstance[$handlerKey])) { 02063 $output = TRUE; 02064 } 02065 break; 02066 default: 02067 die('ERROR: Invalid handler type: "'.$cfgArray['type'].'"'); 02068 break; 02069 } 02070 02071 return $output; 02072 } else die('ERROR: No handler for key "'.$handlerKey.'"'); 02073 } 02074 02075 02076 02077 02078 02079 02080 02081 02082 02083 02084 02085 02086 02087 02088 /************************************ 02089 * 02090 * Table/Field mapping 02091 * 02092 **************************************/ 02093 02101 function map_needMapping($tableList,$fieldMappingOnly=FALSE) { 02102 02103 $key = $tableList.'|'.$fieldMappingOnly; 02104 if (!isset($this->cache_mappingFromTableList[$key])) { 02105 $this->cache_mappingFromTableList[$key] = FALSE; // Default: 02106 02107 $tables = $this->SQLparser->parseFromTables($tableList); 02108 if (is_array($tables)) { 02109 foreach($tables as $tableCfg) { 02110 if ($fieldMappingOnly) { 02111 if (is_array($this->mapping[$tableCfg['table']]['mapFieldNames'])) { 02112 $this->cache_mappingFromTableList[$key] = $tables; 02113 } 02114 } else { 02115 if (is_array($this->mapping[$tableCfg['table']])) { 02116 $this->cache_mappingFromTableList[$key] = $tables; 02117 } 02118 } 02119 } 02120 } 02121 } 02122 02123 return $this->cache_mappingFromTableList[$key]; 02124 } 02125 02137 function map_assocArray($input,$tables,$rev=FALSE) { 02138 02139 // Traverse tables from query (hopefully only one table): 02140 foreach($tables as $tableCfg) { 02141 if (is_array($this->mapping[$tableCfg['table']]['mapFieldNames'])) { 02142 02143 // Get the map (reversed if needed): 02144 if ($rev) { 02145 $theMap = array_flip($this->mapping[$tableCfg['table']]['mapFieldNames']); 02146 } else { 02147 $theMap = $this->mapping[$tableCfg['table']]['mapFieldNames']; 02148 } 02149 02150 // Traverse selected record, map fieldnames: 02151 $output = array(); 02152 foreach($input as $fN => $value) { 02153 02154 // Set the field name, change it if found in mapping array: 02155 if ($theMap[$fN]) { 02156 $newKey = $theMap[$fN]; 02157 } else { 02158 $newKey = $fN; 02159 } 02160 02161 // Set value to fieldname: 02162 $output[$newKey] = $value; 02163 } 02164 02165 // When done, override the $input array with the result: 02166 $input = $output; 02167 } 02168 } 02169 02170 // Return input array (which might have been altered in the mean time) 02171 return $input; 02172 } 02173 02186 function map_remapSELECTQueryParts(&$select_fields,&$from_table,&$where_clause,&$groupBy,&$orderBy) { 02187 02188 // Tables: 02189 $tables = $this->SQLparser->parseFromTables($from_table); 02190 $defaultTable = $tables[0]['table']; 02191 foreach($tables as $k => $v) { 02192 if ($this->mapping[$v['table']]['mapTableName']) { 02193 $tables[$k]['table'] = $this->mapping[$v['table']]['mapTableName']; 02194 } 02195 } 02196 $from_table = $this->SQLparser->compileFromTables($tables); 02197 02198 // Where clause: 02199 $whereParts = $this->SQLparser->parseWhereClause($where_clause); 02200 $this->map_sqlParts($whereParts,$defaultTable); 02201 $where_clause = $this->SQLparser->compileWhereClause($whereParts); 02202 02203 // Select fields: 02204 $expFields = $this->SQLparser->parseFieldList($select_fields); 02205 $this->map_sqlParts($expFields,$defaultTable); 02206 $select_fields = $this->SQLparser->compileFieldList($expFields); 02207 02208 // Group By fields 02209 $expFields = $this->SQLparser->parseFieldList($groupBy); 02210 $this->map_sqlParts($expFields,$defaultTable); 02211 $groupBy = $this->SQLparser->compileFieldList($expFields); 02212 02213 // Order By fields 02214 $expFields = $this->SQLparser->parseFieldList($orderBy); 02215 $this->map_sqlParts($expFields,$defaultTable); 02216 $orderBy = $this->SQLparser->compileFieldList($expFields); 02217 } 02218 02228 function map_sqlParts(&$sqlPartArray, $defaultTable) { 02229 02230 // Traverse sql Part array: 02231 if (is_array($sqlPartArray)) { 02232 foreach($sqlPartArray as $k => $v) { 02233 02234 // Look for sublevel (WHERE parts only) 02235 if (is_array($sqlPartArray[$k]['sub'])) { 02236 $this->map_sqlParts($sqlPartArray[$k]['sub'], $defaultTable); // Call recursively! 02237 } else { 02238 // For the field, look for table mapping (generic): 02239 $t = $sqlPartArray[$k]['table'] ? $sqlPartArray[$k]['table'] : $defaultTable; 02240 02241 // Mapping field name, if set: 02242 if (is_array($this->mapping[$t]['mapFieldNames']) && $this->mapping[$t]['mapFieldNames'][$sqlPartArray[$k]['field']]) { 02243 $sqlPartArray[$k]['field'] = $this->mapping[$t]['mapFieldNames'][$sqlPartArray[$k]['field']]; 02244 } 02245 02246 // Map table? 02247 if ($sqlPartArray[$k]['table'] && $this->mapping[$sqlPartArray[$k]['table']]['mapTableName']) { 02248 $sqlPartArray[$k]['table'] = $this->mapping[$sqlPartArray[$k]['table']]['mapTableName']; 02249 } 02250 } 02251 } 02252 } 02253 } 02254 02263 function map_genericQueryParsed(&$parsedQuery) { 02264 02265 // Getting table - same for all: 02266 $table = $parsedQuery['TABLE']; 02267 if ($table) { 02268 // Do field mapping if needed: 02269 if ($tableArray = $this->map_needMapping($table)) { 02270 02271 // Table name: 02272 if ($this->mapping[$table]['mapTableName']) { 02273 $parsedQuery['TABLE'] = $this->mapping[$table]['mapTableName']; 02274 } 02275 02276 // Based on type, do additional changes: 02277 switch($parsedQuery['type']) { 02278 case 'ALTERTABLE': 02279 02280 // Changing field name: 02281 $newFieldName = $this->mapping[$table]['mapFieldNames'][$parsedQuery['FIELD']]; 02282 if ($newFieldName) { 02283 if ($parsedQuery['FIELD'] == $parsedQuery['newField']) { 02284 $parsedQuery['FIELD'] = $parsedQuery['newField'] = $newFieldName; 02285 } else $parsedQuery['FIELD'] = $newFieldName; 02286 } 02287 02288 // Changing key field names: 02289 if (is_array($parsedQuery['fields'])) { 02290 $this->map_fieldNamesInArray($table,$parsedQuery['fields']); 02291 } 02292 break; 02293 case 'CREATETABLE': 02294 // Remapping fields: 02295 if (is_array($parsedQuery['FIELDS'])) { 02296 $newFieldsArray = array(); 02297 foreach($parsedQuery['FIELDS'] as $fN => $fInfo) { 02298 if ($this->mapping[$table]['mapFieldNames'][$fN]) { 02299 $fN = $this->mapping[$table]['mapFieldNames'][$fN]; 02300 } 02301 $newFieldsArray[$fN] = $fInfo; 02302 } 02303 $parsedQuery['FIELDS'] = $newFieldsArray; 02304 } 02305 02306 // Remapping keys: 02307 if (is_array($parsedQuery['KEYS'])) { 02308 foreach($parsedQuery['KEYS'] as $kN => $kInfo) { 02309 $this->map_fieldNamesInArray($table,$parsedQuery['KEYS'][$kN]); 02310 } 02311 } 02312 break; 02313 02314 02316 02317 02318 } 02319 } 02320 } else die('ERROR, mapping: No table found in parsed Query array...'); 02321 } 02322 02330 function map_fieldNamesInArray($table,&$fieldArray) { 02331 if (is_array($this->mapping[$table]['mapFieldNames'])) { 02332 foreach($fieldArray as $k => $v) { 02333 if ($this->mapping[$table]['mapFieldNames'][$v]) { 02334 $fieldArray[$k] = $this->mapping[$table]['mapFieldNames'][$v]; 02335 } 02336 } 02337 } 02338 } 02339 02340 02341 02342 02343 02344 02345 02346 02347 02348 02349 02350 02351 02352 02353 02354 02355 02356 /************************************** 02357 * 02358 * Debugging 02359 * 02360 **************************************/ 02361 02371 function debugHandler($function,$execTime,$inData) { 02372 // we don't want to log our own log/debug SQL 02373 $script = substr(PATH_thisScript,strlen(PATH_site)); 02374 02375 if (substr($script,-strlen('dbal/mod1/index.php'))!='dbal/mod1/index.php' && 02376 !strstr($inData['args'][0], 'tx_dbal_debuglog')) { 02377 $data = array(); 02378 $errorFlag = 0; 02379 $joinTable = ''; 02380 02381 if ($this->sql_error()) { 02382 $data['sqlError'] = $this->sql_error(); 02383 $errorFlag|=1; 02384 } 02385 02386 // if lastQuery is empty (for whatever reason) at least log inData.args 02387 if(empty($this->lastQuery)) 02388 $query = implode(' ',$inData['args']); 02389 else 02390 $query = $this->lastQuery; 02391 02392 switch($function) { 02393 case 'exec_INSERTquery': 02394 case 'exec_UPDATEquery': 02395 case 'exec_DELETEquery': 02396 $this->debug_log($query,$execTime,$data,$joinTable,$errorFlag, $script); 02397 break; 02398 02399 case 'exec_SELECTquery': 02400 // Get explain data: 02401 if ($this->conf['debugOptions']['EXPLAIN'] && t3lib_div::inList('adodb,native',$inData['handlerType'])) { 02402 $data['EXPLAIN'] = $this->debug_explain($this->lastQuery); 02403 } 02404 02405 // Check parsing of Query: 02406 if ($this->conf['debugOptions']['parseQuery']) { 02407 $parseResults = array(); 02408 $parseResults['SELECT'] = $this->SQLparser->debug_parseSQLpart('SELECT',$inData['args'][1]); 02409 $parseResults['FROM'] = $this->SQLparser->debug_parseSQLpart('FROM',$inData['args'][0]); 02410 $parseResults['WHERE'] = $this->SQLparser->debug_parseSQLpart('WHERE',$inData['args'][2]); 02411 $parseResults['GROUPBY'] = $this->SQLparser->debug_parseSQLpart('SELECT',$inData['args'][3]); // Using select field list syntax 02412 $parseResults['ORDERBY'] = $this->SQLparser->debug_parseSQLpart('SELECT',$inData['args'][4]); // Using select field list syntax 02413 02414 foreach($parseResults as $k => $v) { 02415 if (!strlen($parseResults[$k])) unset($parseResults[$k]); 02416 } 02417 if (count($parseResults)) { 02418 $data['parseError'] = $parseResults; 02419 $errorFlag|=2; 02420 } 02421 } 02422 02423 // Checking joinTables: 02424 if ($this->conf['debugOptions']['joinTables']) { 02425 if (count(explode(',', $inData['ORIG_from_table']))>1) { 02426 $joinTable = $inData['args'][0]; 02427 } 02428 } 02429 02430 // Logging it: 02431 $this->debug_log($query,$execTime,$data,$joinTable,$errorFlag, $script); 02432 if(!empty($inData['args'][2])) 02433 $this->debug_WHERE($inData['args'][0], $inData['args'][2], $script); 02434 break; 02435 } 02436 } 02437 } 02438 02445 function debug_WHERE($table,$where, $script='') { 02446 $insertArray = array ( 02447 'tstamp' => $GLOBALS['EXEC_TIME'], 02448 'beuser_id' => intval($GLOBALS['BE_USER']->user['uid']), 02449 'script' => $script, 02450 'tablename' => $table, 02451 'whereclause' => $where 02452 ); 02453 02454 $this->exec_INSERTquery('tx_dbal_debuglog_where', $insertArray); 02455 } 02456 02467 function debug_log($query,$ms,$data,$join,$errorFlag, $script='') { 02468 $insertArray = array ( 02469 'tstamp' => $GLOBALS['EXEC_TIME'], 02470 'beuser_id' => intval($GLOBALS['BE_USER']->user['uid']), 02471 'script' => $script, 02472 'exec_time' => $ms, 02473 'table_join' => $join, 02474 'serdata' => serialize($data), 02475 'query' => (is_array($query) ? $query[0].' WITH '.count($query[1]).' BLOB FIELDS: '.implode(', ',array_keys($query[1])) : $query), 02476 'errorFlag' => $errorFlag 02477 ); 02478 02479 $this->exec_INSERTquery('tx_dbal_debuglog', $insertArray); 02480 } 02481 02489 function debug_explain($query) { 02490 $res = $this->sql_query('EXPLAIN '.$query); 02491 02492 $output = array(); 02493 while($row = $this->sql_fetch_assoc($res)) { 02494 $output[] = $row; 02495 } 02496 return $output; 02497 } 02498 } 02499 02500 02501 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dbal/class.ux_t3lib_db.php']) { 02502 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dbal/class.ux_t3lib_db.php']); 02503 } 02504 ?>