Documentation TYPO3 par Ameos |
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 ***************************************************************/ 00115 require_once(PATH_t3lib.'class.t3lib_sqlengine.php'); 00116 require_once(PATH_t3lib.'class.t3lib_install.php'); 00117 00126 class ux_t3lib_DB extends t3lib_DB { 00127 00128 // Internal, static: 00129 var $printErrors = false; // Enable output of SQL errors after query executions. Set through TYPO3_CONF_VARS, see init() 00130 var $debug = false; // Enable debug mode. Set through TYPO3_CONF_VARS, see init() 00131 var $conf = array(); // Configuration array, copied from TYPO3_CONF_VARS in constructor. 00132 00133 var $mapping = array(); // See manual. 00134 var $table2handlerKeys = array(); // See manual. 00135 var $handlerCfg = array ( // See manual. 00136 '_DEFAULT' => array ( 00137 'type' => 'native', 00138 'config' => array( 00139 'username' => '', // Set by default (overridden) 00140 'password' => '', // Set by default (overridden) 00141 'host' => '', // Set by default (overridden) 00142 'database' => '', // Set by default (overridden) 00143 'driver' => '', // ONLY "adodb" type; eg. "mysql" 00144 'sequenceStart' => 1 // ONLY "adodb", first number in sequences/serials/... 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 00173 function ux_t3lib_DB() { 00174 00175 // Set SQL parser object for internal use: 00176 $this->SQLparser = t3lib_div::makeInstance('t3lib_sqlengine'); 00177 $this->Installer = t3lib_div::makeInstance('t3lib_install'); 00178 00179 // Set internal variables with configuration: 00180 $this->conf = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['dbal']; 00181 $this->initInternalVariables(); 00182 } 00183 00189 function initInternalVariables() { 00190 00191 // Set outside configuration: 00192 if (isset($this->conf['mapping'])) $this->mapping = $this->conf['mapping']; 00193 if (isset($this->conf['table2handlerKeys'])) $this->table2handlerKeys = $this->conf['table2handlerKeys']; 00194 if (isset($this->conf['handlerCfg'])) $this->handlerCfg = $this->conf['handlerCfg']; 00195 00196 $this->cacheFieldInfo(); 00197 // Debugging settings: 00198 $this->printErrors = $this->conf['debugOptions']['printErrors'] ? TRUE : FALSE; 00199 $this->debug = $this->conf['debugOptions']['enabled'] ? TRUE : FALSE; 00200 } 00201 00202 function clearCachedFieldInfo() { 00203 if(file_exists(PATH_typo3conf.'temp_fieldInfo.php')) 00204 unlink(PATH_typo3conf.'temp_fieldInfo.php'); 00205 } 00206 00207 function cacheFieldInfo() { 00208 global $TYPO3_LOADED_EXT; 00209 $extSQL = ''; 00210 $parsedExtSQL = array(); 00211 00212 // try to fetch cached file first 00213 // file is removed when admin_query() is called 00214 if(file_exists(PATH_typo3conf.'temp_fieldInfo.php')) { 00215 $fdata = unserialize(t3lib_div::getUrl(PATH_typo3conf.'temp_fieldInfo.php')); 00216 $this->cache_autoIncFields = $fdata['incFields']; 00217 $this->cache_fieldType = $fdata['fieldTypes']; 00218 $this->cache_primaryKeys = $fdata['primaryKeys']; 00219 } 00220 else { 00221 // handle stddb.sql, parse and analyze 00222 $extSQL = t3lib_div::getUrl(PATH_site.'t3lib/stddb/tables.sql'); 00223 $parsedExtSQL = $this->Installer->getFieldDefinitions_sqlContent($extSQL); 00224 $this->analyzeFields($parsedExtSQL); 00225 00226 // loop over all installed extensions 00227 foreach($TYPO3_LOADED_EXT as $ext => $v) { 00228 if(!is_array($v) || !isset($v['ext_tables.sql'])) 00229 continue; 00230 00231 // fetch db dump (if any) and parse it, then analyze 00232 $extSQL = t3lib_div::getUrl($v['ext_tables.sql']); 00233 $parsedExtSQL = $this->Installer->getFieldDefinitions_sqlContent($extSQL); 00234 $this->analyzeFields($parsedExtSQL); 00235 } 00236 00237 $cachedFieldInfo = array('incFields' => $this->cache_autoIncFields, 'fieldTypes' => $this->cache_fieldType, 'primaryKeys' => $this->cache_primaryKeys); 00238 $cachedFieldInfo = serialize($this->mapCachedFieldInfo($cachedFieldInfo)); 00239 00240 // write serialized content to file 00241 t3lib_div::writeFile(PATH_typo3conf."temp_fieldInfo.php", $cachedFieldInfo); 00242 00243 if (strcmp(t3lib_div::getUrl(PATH_typo3conf."temp_fieldInfo.php"), $cachedFieldInfo)) { 00244 die('typo3temp/temp_incfields.php was NOT updated properly (written content didn\'t match file content) - maybe write access problem?'); 00245 } 00246 } 00247 } 00248 00256 function analyzeFields($parsedExtSQL) { 00257 foreach($parsedExtSQL as $table => $tdef) { 00258 if (is_array($tdef['fields'])) { 00259 foreach($tdef['fields'] as $field => $fdef) { 00260 $fdef = $this->SQLparser->parseFieldDef($fdef); 00261 $this->cache_fieldType[$table][$field]['type'] = $fdef['fieldType']; 00262 $this->cache_fieldType[$table][$field]['metaType'] = $this->MySQLMetaType($fdef['fieldType']); 00263 $this->cache_fieldType[$table][$field]['notnull'] = (isset($fdef['featureIndex']['NOTNULL']) && !$this->SQLparser->checkEmptyDefaultValue($fdef['featureIndex'])) ? 1 : 0; 00264 if(isset($fdef['featureIndex']['AUTO_INCREMENT'])) { 00265 $this->cache_autoIncFields[$table] = $field; 00266 } 00267 if(isset($tdef['keys']['PRIMARY'])) { 00268 $this->cache_primaryKeys[$table] = substr($tdef['keys']['PRIMARY'], 13, -1); 00269 } 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], $this->handlerInstance[$this->lastHandlerKey]->sequenceStart); 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 if(strlen($this->lastQuery[0])) 00392 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery[0],false); 00393 foreach($this->lastQuery[1] as $field => $content) { 00394 if(empty($content)) continue; 00395 00396 if(isset($this->cache_autoIncFields[$table]) && isset($new_id)) { 00397 $this->handlerInstance[$this->lastHandlerKey]->UpdateBlob($this->quoteFromTables($table),$field,$content,$this->quoteWhereClause($this->cache_autoIncFields[$table].'='.$new_id)); 00398 } elseif(isset($this->cache_primaryKeys[$table])) { 00399 $pks = explode(',', $this->cache_primaryKeys[$table]); 00400 foreach ($pks as $pk) { 00401 if(isset($fields_values[$pk])) 00402 $where .= $pk.'='.$this->fullQuoteStr($fields_values[$pk], $table).' AND '; 00403 } 00404 $where = $this->quoteWhereClause($where.'1=1'); 00405 $this->handlerInstance[$this->lastHandlerKey]->UpdateBlob($this->quoteFromTables($table),$field,$content,$where); 00406 } else { 00407 $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans(false); 00408 die('Could not update BLOB >>>> no WHERE clause found!'); // should never ever happen 00409 } 00410 } 00411 $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans(); 00412 } 00413 break; 00414 case 'userdefined': 00415 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_INSERTquery($table,$fields_values,$no_quote_fields); 00416 break; 00417 } 00418 00419 if ($this->printErrors && $this->sql_error()) { 00420 debug(array($this->lastQuery, $this->sql_error())); 00421 } 00422 00423 if ($this->debug) { 00424 $this->debugHandler( 00425 'exec_INSERTquery', 00426 t3lib_div::milliseconds()-$pt, 00427 array( 00428 'handlerType' => $hType, 00429 'args' => array($table,$fields_values), 00430 'ORIG_tablename' => $ORIG_tableName 00431 ) 00432 ); 00433 } 00434 // Return output: 00435 return $sqlResult; 00436 } 00437 00447 function exec_UPDATEquery($table,$where,$fields_values,$no_quote_fields='') { 00448 00449 if ($this->debug) $pt = t3lib_div::milliseconds(); 00450 00451 // Do table/field mapping: 00452 $ORIG_tableName = $table; 00453 if ($tableArray = $this->map_needMapping($table)) { 00454 00455 // Field mapping of array: 00456 $fields_values = $this->map_assocArray($fields_values,$tableArray); 00457 00458 // Where clause table and field mapping: 00459 $whereParts = $this->SQLparser->parseWhereClause($where); 00460 $this->map_sqlParts($whereParts,$tableArray[0]['table']); 00461 $where = $this->SQLparser->compileWhereClause($whereParts); 00462 00463 // Table name: 00464 if ($this->mapping[$table]['mapTableName']) { 00465 $table = $this->mapping[$table]['mapTableName']; 00466 } 00467 } 00468 00469 // Select API 00470 $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName); 00471 switch((string)$this->handlerCfg[$this->lastHandlerKey]['type']) { 00472 case 'native': 00473 $this->lastQuery = $this->UPDATEquery($table,$where,$fields_values,$no_quote_fields); 00474 if(is_string($this->lastQuery)) { 00475 $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']); 00476 } 00477 else { 00478 $sqlResult = mysql_query($this->lastQuery[0], $this->handlerInstance[$this->lastHandlerKey]['link']); 00479 foreach($this->lastQuery[1] as $field => $content) { 00480 mysql_query('UPDATE '.$this->quoteFromTables($table).' SET '.$this->quoteFromTables($field).'='.$this->fullQuoteStr($content,$table).' WHERE '.$this->quoteWhereClause($where), $this->handlerInstance[$this->lastHandlerKey]['link']); 00481 } 00482 } 00483 break; 00484 case 'adodb': 00485 $this->lastQuery = $this->UPDATEquery($table,$where,$fields_values,$no_quote_fields); 00486 if(is_string($this->lastQuery)) { 00487 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery,false); 00488 } else { 00489 $this->handlerInstance[$this->lastHandlerKey]->StartTrans(); 00490 if(strlen($this->lastQuery[0])) 00491 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery[0],false); 00492 foreach($this->lastQuery[1] as $field => $content) { 00493 $this->handlerInstance[$this->lastHandlerKey]->UpdateBlob($this->quoteFromTables($table),$field,$content,$this->quoteWhereClause($where)); 00494 } 00495 $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans(); 00496 } 00497 break; 00498 case 'userdefined': 00499 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_UPDATEquery($table,$where,$fields_values,$no_quote_fields); 00500 break; 00501 } 00502 00503 if ($this->printErrors && $this->sql_error()) { 00504 debug(array($this->lastQuery, $this->sql_error())); 00505 } 00506 00507 if ($this->debug) { 00508 $this->debugHandler( 00509 'exec_UPDATEquery', 00510 t3lib_div::milliseconds()-$pt, 00511 array( 00512 'handlerType' => $hType, 00513 'args' => array($table,$where, $fields_values), 00514 'ORIG_from_table' => $ORIG_tableName 00515 ) 00516 ); 00517 } 00518 00519 // Return result: 00520 return $sqlResult; 00521 } 00522 00530 function exec_DELETEquery($table,$where) { 00531 00532 if ($this->debug) $pt = t3lib_div::milliseconds(); 00533 00534 // Do table/field mapping: 00535 $ORIG_tableName = $table; 00536 if ($tableArray = $this->map_needMapping($table)) { 00537 00538 // Where clause: 00539 $whereParts = $this->SQLparser->parseWhereClause($where); 00540 $this->map_sqlParts($whereParts,$tableArray[0]['table']); 00541 $where = $this->SQLparser->compileWhereClause($whereParts); 00542 00543 // Table name: 00544 if ($this->mapping[$table]['mapTableName']) { 00545 $table = $this->mapping[$table]['mapTableName']; 00546 } 00547 } 00548 00549 // Select API 00550 $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName); 00551 switch((string)$this->handlerCfg[$this->lastHandlerKey]['type']) { 00552 case 'native': 00553 $this->lastQuery = $this->DELETEquery($table,$where); 00554 $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']); 00555 break; 00556 case 'adodb': 00557 $this->lastQuery = $this->DELETEquery($table,$where); 00558 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery,false); 00559 break; 00560 case 'userdefined': 00561 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_DELETEquery($table,$where); 00562 break; 00563 } 00564 00565 if ($this->printErrors && $this->sql_error()) { 00566 debug(array($this->lastQuery, $this->sql_error())); 00567 } 00568 00569 if ($this->debug) { 00570 $this->debugHandler( 00571 'exec_DELETEquery', 00572 t3lib_div::milliseconds()-$pt, 00573 array( 00574 'handlerType' => $hType, 00575 'args' => array($table,$where), 00576 'ORIG_from_table' => $ORIG_tableName 00577 ) 00578 ); 00579 } 00580 00581 // Return result: 00582 return $sqlResult; 00583 } 00584 00596 function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='') { 00597 00598 if ($this->debug) $pt = t3lib_div::milliseconds(); 00599 00600 // Map table / field names if needed: 00601 $ORIG_tableName = $from_table; // Saving table names in $ORIG_from_table since $from_table is transformed beneath: 00602 if ($tableArray = $this->map_needMapping($ORIG_tableName)) { 00603 $this->map_remapSELECTQueryParts($select_fields,$from_table,$where_clause,$groupBy,$orderBy); // Variables passed by reference! 00604 } 00605 00606 // Get handler key and select API: 00607 $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName); 00608 $hType = (string)$this->handlerCfg[$this->lastHandlerKey]['type']; 00609 switch($hType) { 00610 case 'native': 00611 $this->lastQuery = $this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit); 00612 $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']); 00613 $this->resourceIdToTableNameMap[(string)$sqlResult] = $ORIG_tableName; 00614 break; 00615 case 'adodb': 00616 if ($limit!='') { 00617 $splitLimit = t3lib_div::intExplode(',',$limit); // Splitting the limit values: 00618 if ($splitLimit[1]) { // If there are two parameters, do mapping differently than otherwise: 00619 $numrows = $splitLimit[1]; 00620 $offset = $splitLimit[0]; 00621 } else { 00622 $numrows = $splitLimit[0]; 00623 $offset = 0; 00624 } 00625 00626 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->SelectLimit($this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy), $numrows, $offset); 00627 $this->lastQuery = $sqlResult->sql; 00628 } else { 00629 $this->lastQuery = $this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy); 00630 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_Execute($this->lastQuery); 00631 } 00632 $sqlResult->TYPO3_DBAL_handlerType = 'adodb'; // Setting handler type in result object (for later recognition!) 00633 $sqlResult->TYPO3_DBAL_tableList = $ORIG_tableName; 00634 break; 00635 case 'userdefined': 00636 $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit); 00637 if (is_object($sqlResult)) { 00638 $sqlResult->TYPO3_DBAL_handlerType = 'userdefined'; // Setting handler type in result object (for later recognition!) 00639 $sqlResult->TYPO3_DBAL_tableList = $ORIG_tableName; 00640 } 00641 break; 00642 } 00643 00644 if ($this->printErrors && $this->sql_error()) { 00645 debug(array($this->lastQuery, $this->sql_error())); 00646 } 00647 00648 if ($this->debug) { 00649 $this->debugHandler( 00650 'exec_SELECTquery', 00651 t3lib_div::milliseconds()-$pt, 00652 array( 00653 'handlerType' => $hType, 00654 'args' => array($from_table,$select_fields,$where_clause,$groupBy,$orderBy,$limit), 00655 'ORIG_from_table' => $ORIG_tableName 00656 ) 00657 ); 00658 } 00659 00660 // Return result handler. 00661 return $sqlResult; 00662 } 00663 00664 00665 00666 /************************************** 00667 * 00668 * Query building 00669 * 00670 **************************************/ 00671 00682 function INSERTquery($table,$fields_values,$no_quote_fields='') { 00683 // Table and fieldnames should be "SQL-injection-safe" when supplied to this function (contrary to values in the arrays which may be insecure). 00684 if (is_array($fields_values) && count($fields_values)) { 00685 00686 if (is_string($no_quote_fields)) { 00687 $no_quote_fields = explode(',',$no_quote_fields); 00688 } elseif (!is_array($no_quote_fields)) { 00689 $no_quote_fields = array(); 00690 } 00691 00692 $blobfields = array(); 00693 $nArr = array(); 00694 foreach($fields_values as $k => $v) { 00695 if(!$this->runningNative() && $this->sql_field_metatype($table,$k) == 'B') { 00696 // we skip the field in the regular INSERT statement, it is only in blobfields 00697 $blobfields[$this->quoteFieldNames($k)] = $v; 00698 } 00699 else { 00700 // Add slashes old-school: 00701 // cast numerical values 00702 $mt = $this->sql_field_metatype($table,$k); 00703 $v = (($mt{0}=='I')||($mt{0}=='F')) ? (int)$v : $v; 00704 00705 $nArr[$this->quoteFieldNames($k)] = (!in_array($k,$no_quote_fields)) ? $this->fullQuoteStr($v, $table) : $v; 00706 } 00707 } 00708 if(count($blobfields)) { 00709 if(count($nArr)) { 00710 $query[0] = 'INSERT INTO '.$this->quoteFromTables($table).' 00711 ( 00712 '.implode(', 00713 ',array_keys($nArr)).' 00714 ) VALUES ( 00715 '.implode(', 00716 ',$nArr).' 00717 )'; 00718 } 00719 $query[1] = $blobfields; 00720 if ($this->debugOutput || $this->store_lastBuiltQuery) $this->debug_lastBuiltQuery = $query[0]; 00721 } 00722 else { 00723 $query = 'INSERT INTO '.$this->quoteFromTables($table).' 00724 ( 00725 '.implode(', 00726 ',array_keys($nArr)).' 00727 ) VALUES ( 00728 '.implode(', 00729 ',$nArr).' 00730 )'; 00731 00732 if ($this->debugOutput || $this->store_lastBuiltQuery) $this->debug_lastBuiltQuery = $query; 00733 } 00734 00735 return $query; 00736 } 00737 } 00738 00750 function UPDATEquery($table,$where,$fields_values,$no_quote_fields='') { 00751 // Table and fieldnames should be "SQL-injection-safe" when supplied to this function (contrary to values in the arrays which may be insecure). 00752 if (is_string($where)) { 00753 if (is_array($fields_values) && count($fields_values)) { 00754 00755 if (is_string($no_quote_fields)) { 00756 $no_quote_fields = explode(',',$no_quote_fields); 00757 } elseif (!is_array($no_quote_fields)) { 00758 $no_quote_fields = array(); 00759 } 00760 00761 $blobfields = array(); 00762 $nArr = array(); 00763 foreach($fields_values as $k => $v) { 00764 if(!$this->runningNative() && $this->sql_field_metatype($table,$k) == 'B') { 00765 // we skip the field in the regular UPDATE statement, it is only in blobfields 00766 $blobfields[$this->quoteFieldNames($k)] = $v; 00767 } 00768 else { 00769 // Add slashes old-school: 00770 // cast numeric values 00771 $mt = $this->sql_field_metatype($table,$k); 00772 $v = (($mt{0}=='I')||($mt{0}=='F')) ? (int)$v : $v; 00773 $nArr[] = $this->quoteFieldNames($k).'='.((!in_array($k,$no_quote_fields)) ? $this->fullQuoteStr($v, $table) : $v); 00774 } 00775 } 00776 00777 if(count($blobfields)) { 00778 if(count($nArr)) { 00779 $query[0] = 'UPDATE '.$this->quoteFromTables($table).' 00780 SET 00781 '.implode(', 00782 ',$nArr). 00783 (strlen($where)>0 ? ' 00784 WHERE 00785 '.$this->quoteWhereClause($where) : ''); 00786 } 00787 $query[1] = $blobfields; 00788 if ($this->debugOutput || $this->store_lastBuiltQuery) $this->debug_lastBuiltQuery = $query[0]; 00789 } 00790 else { 00791 $query = 'UPDATE '.$this->quoteFromTables($table).' 00792 SET 00793 '.implode(', 00794 ',$nArr). 00795 (strlen($where)>0 ? ' 00796 WHERE 00797 '.$this->quoteWhereClause($where) : ''); 00798 00799 if ($this->debugOutput || $this->store_lastBuiltQuery) $this->debug_lastBuiltQuery = $query; 00800 } 00801 00802 return $query; 00803 } 00804 } 00805 else { 00806 die('<strong>TYPO3 Fatal Error:</strong> "Where" clause argument for UPDATE query was not a string in $this->UPDATEquery() !'); 00807 } 00808 } 00809 00819 function DELETEquery($table,$where) { 00820 if (is_string($where)) { 00821 $table = $this->quoteFromTables($table); 00822 $where = $this->quoteWhereClause($where); 00823 00824 $query = parent::DELETEquery($table, $where); 00825 00826 if ($this->debugOutput || $this->store_lastBuiltQuery) $this->debug_lastBuiltQuery = $query; 00827 return $query; 00828 } else { 00829 die('<strong>TYPO3 Fatal Error:</strong> "Where" clause argument for DELETE query was not a string in $this->DELETEquery() !'); 00830 } 00831 } 00832 00846 function SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='') { 00847 00848 $select_fields = $this->quoteFieldNames($select_fields); 00849 $from_table = $this->quoteFromTables($from_table); 00850 $where_clause = $this->quoteWhereClause($where_clause); 00851 $groupBy = $this->quoteGroupBy($groupBy); 00852 $orderBy = $this->quoteOrderBy($orderBy); 00853 00854 // call parent method to build actual query 00855 $query = parent::SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit); 00856 00857 if ($this->debugOutput || $this->store_lastBuiltQuery) $this->debug_lastBuiltQuery = $query; 00858 00859 return $query; 00860 } 00861 00862 00863 /************************************** 00864 * 00865 * Functions for quoting table/field names 00866 * 00867 **************************************/ 00868 00877 function quoteSelectFields($select_fields) { 00878 $this->quoteFieldNames($select_fields); 00879 } 00880 00887 function quoteFieldNames($select_fields) { 00888 if($select_fields == '') return ''; 00889 if($this->runningNative()) return $select_fields; 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 if($this->runningNative()) return $from_table; 00926 00927 $from_table = $this->SQLparser->parseFromTables($from_table); 00928 foreach($from_table as $k => $v) { 00929 $from_table[$k]['table'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00930 if($from_table[$k]['as'] != '') { 00931 $from_table[$k]['as'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['as'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00932 } 00933 if (is_array($v['JOIN'])) { 00934 $from_table[$k]['JOIN']['withTable'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['JOIN']['withTable'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00935 $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 : ''; 00936 $from_table[$k]['JOIN']['ON'][0]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['JOIN']['ON'][0]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00937 $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 : ''; 00938 $from_table[$k]['JOIN']['ON'][1]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$from_table[$k]['JOIN']['ON'][1]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00939 } 00940 } 00941 return $this->SQLparser->compileFromTables($from_table); 00942 } 00943 00950 function quoteWhereClause($where_clause) { 00951 if($where_clause == '') return ''; 00952 if($this->runningNative()) return $where_clause; 00953 00954 $where_clause = $this->SQLparser->parseWhereClause($where_clause); 00955 $where_clause = $this->_quoteWhereClause($where_clause); 00956 $where_clause = $this->SQLparser->compileWhereClause($where_clause); 00957 00958 return $where_clause; 00959 } 00960 00967 function _quoteWhereClause($where_clause) { 00968 foreach($where_clause as $k => $v) { 00969 // Look for sublevel: 00970 if (is_array($where_clause[$k]['sub'])) { 00971 $where_clause[$k]['sub'] = $this->_quoteWhereClause($where_clause[$k]['sub']); 00972 } else { 00973 if($where_clause[$k]['table'] != '') { 00974 $where_clause[$k]['table'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$where_clause[$k]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00975 } 00976 if(!is_numeric($where_clause[$k]['field'])) { 00977 $where_clause[$k]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$where_clause[$k]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 00978 } 00979 } 00980 if ($where_clause[$k]['comparator']) { 00981 // Detecting value type; list or plain: 00982 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'])))) { 00983 $where_clause[$k]['value'][0] = $this->quoteFieldNames($where_clause[$k]['value'][0]); 00984 } 00985 } 00986 } 00987 00988 return $where_clause; 00989 } 00990 00997 function quoteGroupBy($groupBy) { 00998 if($groupBy == '') return ''; 00999 if($this->runningNative()) return $groupBy; 01000 01001 $groupBy = $this->SQLparser->parseFieldList($groupBy); 01002 foreach($groupBy as $k => $v) { 01003 $groupBy[$k]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$groupBy[$k]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 01004 if($groupBy[$k]['table'] != '') { 01005 $groupBy[$k]['table'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$groupBy[$k]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 01006 } 01007 } 01008 return $this->SQLparser->compileFieldList($groupBy); 01009 } 01010 01017 function quoteOrderBy($orderBy) { 01018 if($orderBy == '') return ''; 01019 if($this->runningNative()) return $orderBy; 01020 01021 $orderBy = $this->SQLparser->parseFieldList($orderBy); 01022 foreach($orderBy as $k => $v) { 01023 $orderBy[$k]['field'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$orderBy[$k]['field'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 01024 if($orderBy[$k]['table'] != '') { 01025 $orderBy[$k]['table'] = $this->handlerInstance[$this->lastHandlerKey]->nameQuote.$orderBy[$k]['table'].$this->handlerInstance[$this->lastHandlerKey]->nameQuote; 01026 } 01027 } 01028 return $this->SQLparser->compileFieldList($orderBy); 01029 } 01030 01031 01032 01033 /************************************** 01034 * 01035 * Various helper functions 01036 * 01037 **************************************/ 01038 01047 function fullQuoteStr($str,$table) { 01048 return '\''.$this->quoteStr($str, $table).'\''; 01049 } 01050 01060 function quoteStr($str, $table) { 01061 $this->lastHandlerKey = $this->handler_getFromTableList($table); 01062 switch((string)$this->handlerCfg[$this->lastHandlerKey]['type']) { 01063 case 'native': 01064 $str = mysql_real_escape_string($str, $this->handlerInstance[$this->lastHandlerKey]['link']); 01065 break; 01066 case 'adodb': 01067 $str = substr($this->handlerInstance[$this->lastHandlerKey]->qstr($str),1,-1); 01068 break; 01069 case 'userdefined': 01070 $str = $this->handlerInstance[$this->lastHandlerKey]->quoteStr($str); 01071 break; 01072 default: 01073 die('No handler found!!!'); 01074 break; 01075 } 01076 01077 return $str; 01078 } 01079 01080 01088 function MetaType($type,$table,$max_length=-1) { 01089 $this->lastHandlerKey = $this->handler_getFromTableList($table); 01090 switch((string)$this->handlerCfg[$this->lastHandlerKey]['type']) { 01091 case 'native': 01092 $str = $type; 01093 break; 01094 case 'adodb': 01095 $rs = $this->handlerInstance[$this->lastHandlerKey]->SelectLimit('SELECT * FROM '.$this->quoteFromTables($table),1); 01096 $str = $rs->MetaType($type, $max_length); 01097 break; 01098 case 'userdefined': 01099 $str = $this->handlerInstance[$this->lastHandlerKey]->MetaType($str,$table,$max_length); 01100 break; 01101 default: 01102 die('No handler found!!!'); 01103 break; 01104 } 01105 01106 return $str; 01107 } 01108 01109 01116 function MySQLMetaType($t) { 01117 01118 switch (strtoupper($t)) { 01119 case 'STRING': 01120 case 'CHAR': 01121 case 'VARCHAR': 01122 case 'TINYBLOB': 01123 case 'TINYTEXT': 01124 case 'ENUM': 01125 case 'SET': return 'C'; 01126 01127 case 'TEXT': 01128 case 'LONGTEXT': 01129 case 'MEDIUMTEXT': return 'X'; 01130 01131 case 'IMAGE': 01132 case 'LONGBLOB': 01133 case 'BLOB': 01134 case 'MEDIUMBLOB': return 'B'; 01135 01136 case 'YEAR': 01137 case 'DATE': return 'D'; 01138 01139 case 'TIME': 01140 case 'DATETIME': 01141 case 'TIMESTAMP': return 'T'; 01142 01143 case 'FLOAT': 01144 case 'DOUBLE': return 'F'; 01145 01146 case 'INT': 01147 case 'INTEGER': 01148 case 'TINYINT': 01149 case 'SMALLINT': 01150 case 'MEDIUMINT': 01151 case 'BIGINT': return 'I8'; // we always return I8 to be on the safe side. Under some circumstances the fields are to small otherwise... 01152 01153 default: return 'N'; 01154 } 01155 } 01156 01163 function MySQLActualType($meta) { 01164 switch(strtoupper($meta)) { 01165 case 'C': return 'VARCHAR'; 01166 case 'XL': 01167 case 'X': return 'LONGTEXT'; 01168 01169 case 'C2': return 'VARCHAR'; 01170 case 'X2': return 'LONGTEXT'; 01171 01172 case 'B': return 'LONGBLOB'; 01173 01174 case 'D': return 'DATE'; 01175 case 'T': return 'DATETIME'; 01176 case 'L': return 'TINYINT'; 01177 01178 case 'I': 01179 case 'I1': 01180 case 'I2': 01181 case 'I4': 01182 case 'I8': return 'BIGINT'; // we only have I8 in DBAL, see MySQLMetaType() 01183 01184 case 'F': return 'DOUBLE'; 01185 case 'N': return 'NUMERIC'; 01186 01187 default: return $meta; 01188 } 01189 } 01190 01191 01192 01193 01194 /************************************** 01195 * 01196 * SQL wrapper functions (Overriding parent methods) 01197 * (For use in your applications) 01198 * 01199 **************************************/ 01200 01206 function sql_error() { 01207 01208 switch($this->handlerCfg[$this->lastHandlerKey]['type']) { 01209 case 'native': 01210 $output = mysql_error($this->handlerInstance[$this->lastHandlerKey]['link']); 01211 break; 01212 case 'adodb': 01213 $output = $this->handlerInstance[$this->lastHandlerKey]->ErrorMsg(); 01214 break; 01215 case 'userdefined': 01216 $output = $this->handlerInstance[$this->lastHandlerKey]->sql_error(); 01217 break; 01218 } 01219 return $output; 01220 } 01221 01228 function sql_num_rows(&$res) { 01229 if($res === false) return 0; 01230 01231 $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : 'native'; 01232 switch($handlerType) { 01233 case 'native': 01234 $output = mysql_num_rows($res); 01235 break; 01236 case 'adodb': 01237 $output = method_exists($res, 'RecordCount') ? $res->RecordCount() : 0; 01238 break; 01239 case 'userdefined': 01240 $output = $res->sql_num_rows(); 01241 break; 01242 } 01243 return $output; 01244 } 01245 01252 function sql_fetch_assoc(&$res) { 01253 $output = array(); 01254 01255 $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : (is_resource($res) ? 'native' : false); 01256 switch($handlerType) { 01257 case 'native': 01258 $output = mysql_fetch_assoc($res); 01259 $tableList = $this->resourceIdToTableNameMap[(string)$res]; // Reading list of tables from SELECT query: 01260 break; 01261 case 'adodb': 01262 // Check if method exists for the current $res object. 01263 // If a table exists in TCA but not in the db, a error 01264 // occured because $res is not a valid object. 01265 if(method_exists($res, 'FetchRow')) { 01266 $output = $res->FetchRow(); 01267 $tableList = $res->TYPO3_DBAL_tableList; // Reading list of tables from SELECT query: 01268 01269 // Removing all numeric/integer keys. 01270 // A workaround because in ADOdb we would need to know what we want before executing the query... 01271 if (is_array($output)) { 01272 foreach($output as $key => $value) { 01273 if (is_integer($key)) unset($output[$key]); 01274 elseif($value===' ' && $this->runningADOdbDriver('mssql')) $output[$key]=''; // MSSQL does not know such thing as an empty string. So it returns one space instead, which we must fix. 01275 } 01276 } 01277 } 01278 break; 01279 case 'userdefined': 01280 $output = $res->sql_fetch_assoc(); 01281 $tableList = $res->TYPO3_DBAL_tableList; // Reading list of tables from SELECT query: 01282 break; 01283 } 01284 01285 // Table/Fieldname mapping: 01286 if (is_array($output)) { 01287 if ($tables = $this->map_needMapping($tableList,TRUE)) { 01288 $output = $this->map_assocArray($output,$tables,1); 01289 } 01290 } 01291 01292 // Return result: 01293 return $output; 01294 } 01295 01303 function sql_fetch_row(&$res) { 01304 $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : 'native'; 01305 switch($handlerType) { 01306 case 'native': 01307 $output = mysql_fetch_row($res); 01308 break; 01309 case 'adodb': 01310 // Check if method exists for the current $res object. 01311 // If a table exists in TCA but not in the db, a error 01312 // occured because $res is not a valid object. 01313 if(method_exists($res, 'FetchRow')) { 01314 $output = $res->FetchRow(); 01315 01316 // Removing all assoc. keys. 01317 // A workaround because in ADOdb we would need to know what we want before executing the query... 01318 if (is_array($output)) { 01319 foreach($output as $key => $value) { 01320 if (!is_integer($key)) unset($output[$key]); 01321 elseif($value===' ' && $this->runningADOdbDriver('mssql')) $output[$key]=''; // MSSQL does not know such thing as an empty string. So it returns one space instead, which we must fix. 01322 } 01323 } 01324 } 01325 break; 01326 case 'userdefined': 01327 $output = $res->sql_fetch_row(); 01328 break; 01329 } 01330 return $output; 01331 } 01332 01339 function sql_free_result(&$res) { 01340 if($res===false) return false; 01341 01342 $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : 'native'; 01343 switch($handlerType) { 01344 case 'native': 01345 $output = mysql_free_result($res); 01346 break; 01347 case 'adodb': 01348 if(method_exists($res, 'Close')) { 01349 $res->Close(); 01350 unset($res); 01351 $output = true; 01352 } else { 01353 $output = false; 01354 } 01355 break; 01356 case 'userdefined': 01357 unset($res); 01358 break; 01359 } 01360 return $output; 01361 } 01362 01368 function sql_insert_id() { 01369 01370 switch($this->handlerCfg[$this->lastHandlerKey]['type']) { 01371 case 'native': 01372 $output = mysql_insert_id($this->handlerInstance[$this->lastHandlerKey]['link']); 01373 break; 01374 case 'adodb': 01375 $output = $this->handlerInstance[$this->lastHandlerKey]->last_insert_id; 01376 break; 01377 case 'userdefined': 01378 $output = $this->handlerInstance[$this->lastHandlerKey]->sql_insert_id(); 01379 break; 01380 } 01381 return $output; 01382 } 01383 01389 function sql_affected_rows() { 01390 01391 switch($this->handlerCfg[$this->lastHandlerKey]['type']) { 01392 case 'native': 01393 $output = mysql_affected_rows(); 01394 break; 01395 case 'adodb': 01396 $output = $this->handlerInstance[$this->lastHandlerKey]->Affected_Rows(); 01397 break; 01398 case 'userdefined': 01399 $output = $this->handlerInstance[$this->lastHandlerKey]->sql_affected_rows(); 01400 break; 01401 } 01402 return $output; 01403 } 01404 01412 function sql_data_seek(&$res,$seek) { 01413 01414 $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : 'native'; 01415 switch($handlerType) { 01416 case 'native': 01417 $output = mysql_data_seek($res,$seek); 01418 break; 01419 case 'adodb': 01420 $output = $res->Move($seek); 01421 break; 01422 case 'userdefined': 01423 $output = $res->sql_data_seek($seek); 01424 break; 01425 } 01426 return $output; 01427 } 01428 01438 function sql_field_metatype($table,$field) { 01439 return $this->cache_fieldType[$table][$field]['metaType']; 01440 } 01441 01451 function sql_field_type(&$res,$pointer) { 01452 if($res === null) { 01453 debug(array('no res in sql_field_type!')); 01454 return 'text'; 01455 } 01456 else if(is_string($res)){ 01457 if($res == 'tx_dbal_debuglog') return 'text'; 01458 $handlerType = 'adodb'; 01459 } 01460 else { 01461 $handlerType = is_object($res) ? $res->TYPO3_DBAL_handlerType : 'native'; 01462 } 01463 01464 switch($handlerType) { 01465 case 'native': 01466 $output = mysql_field_type($res,$pointer); 01467 break; 01468 case 'adodb': 01469 if(is_string($pointer)){ 01470 $output = $this->cache_fieldType[$res][$pointer]['type']; 01471 } 01472 01473 break; 01474 case 'userdefined': 01475 $output = $res->sql_field_type($pointer); 01476 break; 01477 } 01478 01479 return $output; 01480 } 01481 01482 01483 01484 01485 01486 01487 01488 01489 /********** 01490 * 01491 * Legacy functions, bound to _DEFAULT handler. (Overriding parent methods) 01492 * Deprecated. 01493 * 01494 **********/ 01495 01505 function sql($db,$query) { 01506 return $this->sql_query($query); 01507 } 01508 01519 function sql_query($query) { 01520 01521 switch($this->handlerCfg['_DEFAULT']['type']) { 01522 case 'native': 01523 $sqlResult = mysql_query($query, $this->handlerInstance['_DEFAULT']['link']); 01524 break; 01525 case 'adodb': 01526 $sqlResult = $this->handlerInstance['_DEFAULT']->Execute($query); 01527 $sqlResult->TYPO3_DBAL_handlerType = 'adodb'; 01528 break; 01529 case 'userdefined': 01530 $sqlResult = $this->handlerInstance['_DEFAULT']->sql_query($query); 01531 $sqlResult->TYPO3_DBAL_handlerType = 'userdefined'; 01532 break; 01533 } 01534 01535 if ($this->printErrors && $this->sql_error()) { 01536 debug(array($this->lastQuery, $this->sql_error())); 01537 } 01538 01539 return $sqlResult; 01540 } 01541 01554 function sql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password) { 01555 // Overriding the _DEFAULT handler configuration of username, password, localhost and database name: 01556 $this->handlerCfg['_DEFAULT']['config']['username'] = $TYPO3_db_username; 01557 $this->handlerCfg['_DEFAULT']['config']['password'] = $TYPO3_db_password; 01558 $this->handlerCfg['_DEFAULT']['config']['host'] = $TYPO3_db_host; 01559 $this->handlerCfg['_DEFAULT']['config']['database'] = TYPO3_db; 01560 01561 // Initializing and output value: 01562 $sqlResult = $this->handler_init('_DEFAULT'); 01563 return $sqlResult; 01564 } 01565 01573 function sql_select_db($TYPO3_db) { 01574 return TRUE; 01575 } 01576 01577 01578 01579 01580 01581 01582 01583 01584 01585 01586 01587 01588 01589 01590 01591 /************************************** 01592 * 01593 * SQL admin functions 01594 * (For use in the Install Tool and Extension Manager) 01595 * 01596 **************************************/ 01597 01605 function admin_get_dbs() { 01606 $dbArr = array(); 01607 switch($this->handlerCfg['_DEFAULT']['type']) { 01608 case 'native': 01609 $db_list = mysql_list_dbs($this->link); 01610 while ($row = mysql_fetch_object($db_list)) { 01611 if ($this->sql_select_db($row->Database)) { 01612 $dbArr[] = $row->Database; 01613 } 01614 } 01615 break; 01616 case 'adodb': 01617 // check needed for install tool - otherwise it will just die because the call to 01618 // MetaDatabases is done on a stdClass instance 01619 if(method_exists($this->handlerInstance['_DEFAULT'],'MetaDatabases')) { 01620 $sqlDBs = $this->handlerInstance['_DEFAULT']->MetaDatabases(); 01621 if(is_array($sqlDBs)) { 01622 foreach($sqlDBs as $k => $theDB) { 01623 $dbArr[] = $theDB; 01624 } 01625 } 01626 } 01627 break; 01628 case 'userdefined': 01629 $dbArr = $this->handlerInstance['_DEFAULT']->admin_get_tables(); 01630 break; 01631 } 01632 01633 return $dbArr; 01634 } 01635 01645 function admin_get_tables() { 01646 $whichTables = array(); 01647 01648 // Getting real list of tables: 01649 switch($this->handlerCfg['_DEFAULT']['type']) { 01650 case 'native': 01651 $tables_result = mysql_list_tables(TYPO3_db, $this->handlerInstance['_DEFAULT']['link']); 01652 if (!$this->sql_error()) { 01653 while ($theTable = $this->sql_fetch_assoc($tables_result)) { 01654 $whichTables[current($theTable)] = current($theTable); 01655 } 01656 } 01657 break; 01658 case 'adodb': 01659 $sqlTables = $this->handlerInstance['_DEFAULT']->MetaTables('TABLES'); 01660 while (list($k, $theTable) = each($sqlTables)) { 01661 if(preg_match('/BIN\$/', $theTable)) continue; // skip tables from the Oracle 10 Recycle Bin 01662 $whichTables[$theTable] = $theTable; 01663 } 01664 break; 01665 case 'userdefined': 01666 $whichTables = $this->handlerInstance['_DEFAULT']->admin_get_tables(); 01667 break; 01668 } 01669 01670 // Check mapping: 01671 if (is_array($this->mapping) && count($this->mapping)) { 01672 01673 // Mapping table names in reverse, first getting list of real table names: 01674 $tMap = array(); 01675 foreach($this->mapping as $tN => $tMapInfo) { 01676 if (isset($tMapInfo['mapTableName'])) $tMap[$tMapInfo['mapTableName']]=$tN; 01677 } 01678 01679 // Do mapping: 01680 $newList=array(); 01681 foreach($whichTables as $tN) { 01682 if (isset($tMap[$tN])) $tN = $tMap[$tN]; 01683 $newList[$tN] = $tN; 01684 } 01685 01686 $whichTables = $newList; 01687 } 01688 01689 // Adding tables configured to reside in other DBMS (handler by other handlers than the default): 01690 if (is_array($this->table2handlerKeys)) { 01691 foreach($this->table2handlerKeys as $key => $handlerKey) { 01692 $whichTables[$key] = $key; 01693 } 01694 } 01695 01696 return $whichTables; 01697 } 01698 01707 function admin_get_fields($tableName) { 01708 $output = array(); 01709 01710 // Do field mapping if needed: 01711 $ORIG_tableName = $tableName; 01712 if ($tableArray = $this->map_needMapping($tableName)) { 01713 01714 // Table name: 01715 if ($this->mapping[$tableName]['mapTableName']) { 01716 $tableName = $this->mapping[$tableName]['mapTableName']; 01717 } 01718 } 01719 01720 // Find columns 01721 $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName); 01722 switch((string)$this->handlerCfg[$this->lastHandlerKey]['type']) { 01723 case 'native': 01724 $columns_res = mysql_query('SHOW columns FROM '.$tableName, $this->handlerInstance[$this->lastHandlerKey]['link']); 01725 while($fieldRow = mysql_fetch_assoc($columns_res)) { 01726 $output[$fieldRow['Field']] = $fieldRow; 01727 } 01728 break; 01729 case 'adodb': 01730 $fieldRows = $this->handlerInstance[$this->lastHandlerKey]->MetaColumns($tableName, false); 01731 foreach($fieldRows as $k => $fieldRow) { 01732 settype($fieldRow, 'array'); 01733 $fieldRow['Field'] = $fieldRow['name']; 01734 $ntype = $this->MySQLActualType($this->MetaType($fieldRow['type'],$tableName)); 01735 $ntype .= (($fieldRow['max_length'] != -1) ? (($ntype == 'INT') ? '(11)' :'('.$fieldRow['max_length'].')') : ''); 01736 $fieldRow['Type'] = strtolower($ntype); 01737 $fieldRow['Null'] = ''; 01738 $fieldRow['Key'] = ''; 01739 $fieldRow['Default'] = $fieldRow['default_value']; 01740 $fieldRow['Extra'] = ''; 01741 $output[$fieldRow['name']] = $fieldRow; 01742 } 01743 break; 01744 case 'userdefined': 01745 $output = $this->handlerInstance[$this->lastHandlerKey]->admin_get_fields($tableName); 01746 break; 01747 } 01748 01749 // mapping should be done: 01750 if (is_array($tableArray) && is_array($this->mapping[$ORIG_tableName]['mapFieldNames'])) { 01751 $revFields = array_flip($this->mapping[$ORIG_tableName]['mapFieldNames']); 01752 01753 $newOutput = array(); 01754 foreach($output as $fN => $fInfo) { 01755 if (isset($revFields[$fN])) { 01756 $fN = $revFields[$fN]; 01757 $fInfo['Field'] = $fN; 01758 } 01759 $newOutput[$fN] = $fInfo; 01760 } 01761 $output = $newOutput; 01762 } 01763 01764 return $output; 01765 } 01766 01774 function admin_get_keys($tableName) { 01775 $output = array(); 01776 01777 // Do field mapping if needed: 01778 $ORIG_tableName = $tableName; 01779 if ($tableArray = $this->map_needMapping($tableName)) { 01780 01781 // Table name: 01782 if ($this->mapping[$tableName]['mapTableName']) { 01783 $tableName = $this->mapping[$tableName]['mapTableName']; 01784 } 01785 } 01786 01787 // Find columns 01788 $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName); 01789 switch((string)$this->handlerCfg[$this->lastHandlerKey]['type']) { 01790 case 'native': 01791 $keyRes = mysql_query('SHOW keys FROM '.$tableName, $this->handlerInstance[$this->lastHandlerKey]['link']); 01792 while($keyRow = mysql_fetch_assoc($keyRes)) { 01793 $output[] = $keyRow; 01794 } 01795 break; 01796 case 'adodb': 01797 $keyRows = $this->handlerInstance[$this->lastHandlerKey]->MetaIndexes($tableName); 01798 if($keyRows !== false) { 01799 while (list($k, $theKey) = each($keyRows)) { 01800 $theKey['Table'] = $tableName; 01801 $theKey['Non_unique'] = (int) !$theKey['unique']; 01802 $theKey['Key_name'] = str_replace($tableName.'_','',$k); 01803 01804 // the following are probably not needed anyway... 01805 $theKey['Collation'] = ''; 01806 $theKey['Cardinality'] = ''; 01807 $theKey['Sub_part'] = ''; 01808 $theKey['Packed'] = ''; 01809 $theKey['Null'] = ''; 01810 $theKey['Index_type'] = ''; 01811 $theKey['Comment'] = ''; 01812 01813 // now map multiple fields into multiple rows (we mimic MySQL, remember...) 01814 $keycols = $theKey['columns']; 01815 while (list($c, $theCol) = each($keycols)) { 01816 $theKey['Seq_in_index'] = $c+1; 01817 $theKey['Column_name'] = $theCol; 01818 $output[] = $theKey; 01819 } 01820 } 01821 } 01822 $priKeyRow = $this->handlerInstance[$this->lastHandlerKey]->MetaPrimaryKeys($tableName); 01823 $theKey = array(); 01824 $theKey['Table'] = $tableName; 01825 $theKey['Non_unique'] = 0; 01826 $theKey['Key_name'] = 'PRIMARY'; 01827 01828 // the following are probably not needed anyway... 01829 $theKey['Collation'] = ''; 01830 $theKey['Cardinality'] = ''; 01831 $theKey['Sub_part'] = ''; 01832 $theKey['Packed'] = ''; 01833 $theKey['Null'] = ''; 01834 $theKey['Index_type'] = ''; 01835 $theKey['Comment'] = ''; 01836 01837 // now map multiple fields into multiple rows (we mimic MySQL, remember...) 01838 if($priKeyRow !== false) { 01839 while (list($c, $theCol) = each($priKeyRow)) { 01840 $theKey['Seq_in_index'] = $c+1; 01841 $theKey['Column_name'] = $theCol; 01842 $output[] = $theKey; 01843 } 01844 } 01845 break; 01846 case 'userdefined': 01847 $output = $this->handlerInstance[$this->lastHandlerKey]->admin_get_keys($tableName); 01848 break; 01849 } 01850 01851 // mapping should be done: 01852 if (is_array($tableArray) && is_array($this->mapping[$ORIG_tableName]['mapFieldNames'])) { 01853 $revFields = array_flip($this->mapping[$ORIG_tableName]['mapFieldNames']); 01854 01855 $newOutput = array(); 01856 foreach($output as $kN => $kInfo) { 01857 // Table: 01858 $kInfo['Table'] = $ORIG_tableName; 01859 01860 // Column 01861 if (isset($revFields[$kInfo['Column_name']])) { 01862 $kInfo['Column_name'] = $revFields[$kInfo['Column_name']]; 01863 } 01864 01865 // Write it back: 01866 $newOutput[$kN] = $kInfo; 01867 } 01868 $output = $newOutput; 01869 } 01870 01871 return $output; 01872 } 01873 01880 function admin_query($query) { 01881 $parsedQuery = $this->SQLparser->parseSQL($query); 01882 $ORIG_table = $parsedQuery['TABLE']; 01883 01884 if (is_array($parsedQuery)) { 01885 01886 // Process query based on type: 01887 switch($parsedQuery['type']) { 01888 case 'CREATETABLE': 01889 case 'ALTERTABLE': 01890 case 'DROPTABLE': 01891 if(file_exists(PATH_typo3conf.'temp_fieldInfo.php')) unlink(PATH_typo3conf.'temp_fieldInfo.php'); 01892 $this->map_genericQueryParsed($parsedQuery); 01893 break; 01894 case 'INSERT': 01895 $this->map_genericQueryParsed($parsedQuery); 01896 break; 01897 case 'CREATEDATABASE': 01898 die('Creating a database with DBAL is not supported. Did you really read the manual?'); 01899 break; 01900 default: 01901 die('ERROR: Invalid Query type ('.$parsedQuery['type'].') for ->admin_query() function!: "'.htmlspecialchars($query).'"'); 01902 break; 01903 } 01904 01905 // Setting query array (for other applications to access if needed) 01906 $this->lastParsedAndMappedQueryArray = $parsedQuery; 01907 01908 // Execute query (based on handler derived from the TABLE name which we actually know for once!) 01909 $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_table); 01910 switch((string)$this->handlerCfg[$this->lastHandlerKey]['type']) { 01911 case 'native': 01912 // Compiling query: 01913 $compiledQuery = $this->SQLparser->compileSQL($this->lastParsedAndMappedQueryArray); 01914 01915 if($this->lastParsedAndMappedQueryArray['type']=='INSERT') { 01916 return mysql_query($compiledQuery, $this->link); 01917 } 01918 return mysql_query($compiledQuery[0], $this->link); 01919 break; 01920 case 'adodb': 01921 // Compiling query: 01922 $compiledQuery = $this->SQLparser->compileSQL($this->lastParsedAndMappedQueryArray); 01923 if($this->lastParsedAndMappedQueryArray['type']=='INSERT') { 01924 return $this->exec_INSERTquery($this->lastParsedAndMappedQueryArray['TABLE'],$compiledQuery); 01925 } 01926 return $this->handlerInstance[$this->lastHandlerKey]->DataDictionary->ExecuteSQLArray($compiledQuery); 01927 break; 01928 case 'userdefined': 01929 // Compiling query: 01930 $compiledQuery = $this->SQLparser->compileSQL($this->lastParsedAndMappedQueryArray); 01931 01932 return $this->handlerInstance[$this->lastHandlerKey]->admin_query($compiledQuery); 01933 break; 01934 } 01935 } else die('ERROR: Query could not be parsed: "'.htmlspecialchars($parsedQuery).'". Query: "'.htmlspecialchars($query).'"'); 01936 } 01937 01938 01939 01940 01941 01942 01943 01944 01945 01946 01947 /************************************ 01948 * 01949 * Handler management 01950 * 01951 **************************************/ 01952 01960 function handler_getFromTableList($tableList) { 01961 01962 $key = $tableList; 01963 01964 if (!isset($this->cache_handlerKeyFromTableList[$key])) { 01965 01966 // Get tables separated: 01967 $_tableList = $tableList; 01968 $tableArray = $this->SQLparser->parseFromTables($_tableList); 01969 01970 // If success, traverse the tables: 01971 if (is_array($tableArray) && count($tableArray)) { 01972 foreach($tableArray as $vArray) { 01973 01974 // Find handler key, select "_DEFAULT" if none is specifically configured: 01975 $handlerKey = $this->table2handlerKeys[$vArray['table']] ? $this->table2handlerKeys[$vArray['table']] : '_DEFAULT'; 01976 01977 // In case of separate handler keys for joined tables: 01978 if ($outputHandlerKey && $handlerKey != $outputHandlerKey) { 01979 die('DBAL fatal error: Tables in this list "'.$tableList.'" didn\'t use the same DB handler!'); 01980 } 01981 01982 $outputHandlerKey = $handlerKey; 01983 } 01984 01985 // Check initialized state; if handler is NOT initialized (connected) then we will connect it! 01986 if (!isset($this->handlerInstance[$outputHandlerKey])) { 01987 $this->handler_init($outputHandlerKey); 01988 } 01989 01990 // Return handler key: 01991 $this->cache_handlerKeyFromTableList[$key] = $outputHandlerKey; 01992 } else { 01993 die('DBAL fatal error: No handler found in handler_getFromTableList() for: "'.$tableList.'" ('.$tableArray.')'); 01994 } 01995 } 01996 01997 return $this->cache_handlerKeyFromTableList[$key]; 01998 } 01999 02007 function handler_init($handlerKey) { 02008 02009 // Find handler configuration: 02010 $cfgArray = $this->handlerCfg[$handlerKey]; 02011 $handlerType = (string)$cfgArray['type']; 02012 $output = FALSE; 02013 02014 if (is_array($cfgArray)) { 02015 switch($handlerType) { 02016 case 'native': 02017 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['no_pconnect']) { 02018 $link = mysql_connect($cfgArray['config']['host'].(isset($cfgArray['config']['port']) ? ':'.$cfgArray['config']['port'] : ''), $cfgArray['config']['username'], $cfgArray['config']['password'], true); 02019 } else { 02020 $link = mysql_pconnect($cfgArray['config']['host'].(isset($cfgArray['config']['port']) ? ':'.$cfgArray['config']['port'] : ''), $cfgArray['config']['username'], $cfgArray['config']['password']); 02021 } 02022 02023 // Set handler instance: 02024 $this->handlerInstance[$handlerKey] = array('handlerType' => 'native', 'link' => $link); 02025 02026 // If link succeeded: 02027 if ($link) { 02028 // For default, set ->link (see t3lib_DB) 02029 if ($handlerKey == '_DEFAULT') { 02030 $this->link = $link; 02031 } 02032 02033 // Select database as well: 02034 if (mysql_select_db($cfgArray['config']['database'], $link)) { 02035 $output = TRUE; 02036 } 02037 $setDBinit = t3lib_div::trimExplode(chr(10), $GLOBALS['TYPO3_CONF_VARS']['SYS']['setDBinit'], 1); 02038 foreach ($setDBinit as $v) { 02039 if (mysql_query($v, $this->link) === FALSE) { 02040 t3lib_div::sysLog('Could not initialize DB connection with query "'.$v.'".','Core',3); 02041 } 02042 } 02043 } else { 02044 t3lib_div::sysLog('Could not connect to MySQL server '.$cfgArray['config']['host'].' with user '.$cfgArray['config']['username'].'.','Core',4); 02045 } 02046 break; 02047 case 'adodb': 02048 $output = true; 02049 require_once(t3lib_extMgm::extPath('adodb').'adodb/adodb.inc.php'); 02050 if(!defined('ADODB_FORCE_NULLS')) define('ADODB_FORCE_NULLS', 1); 02051 $GLOBALS['ADODB_FORCE_TYPE'] = ADODB_FORCE_VALUE; 02052 $GLOBALS['ADODB_FETCH_MODE'] = ADODB_FETCH_BOTH; 02053 02054 $this->handlerInstance[$handlerKey] = &ADONewConnection($cfgArray['config']['driver']); 02055 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['no_pconnect']) { 02056 $this->handlerInstance[$handlerKey]->Connect($cfgArray['config']['host'].(isset($cfgArray['config']['port']) ? ':'.$cfgArray['config']['port'] : ''),$cfgArray['config']['username'],$cfgArray['config']['password'],$cfgArray['config']['database']); 02057 } else { 02058 $this->handlerInstance[$handlerKey]->PConnect($cfgArray['config']['host'].(isset($cfgArray['config']['port']) ? ':'.$cfgArray['config']['port'] : ''),$cfgArray['config']['username'],$cfgArray['config']['password'],$cfgArray['config']['database']); 02059 } 02060 if(!$this->handlerInstance[$handlerKey]->isConnected()) { 02061 $dsn = $cfgArray['config']['driver'].'://'.$cfgArray['config']['username']. 02062 (strlen($cfgArray['config']['password']) ? ':XXXX@' : ''). 02063 $cfgArray['config']['host'].(isset($cfgArray['config']['port']) ? ':'.$cfgArray['config']['port'] : '').'/'.$cfgArray['config']['database']. 02064 ($GLOBALS['TYPO3_CONF_VARS']['SYS']['no_pconnect'] ? '' : '?persistent=1'); 02065 t3lib_div::sysLog('Could not connect to DB server using ADOdb on '.$cfgArray['config']['host'].' with user '.$cfgArray['config']['username'].'.','Core',4); 02066 error_log('DBAL error: Connection to '.$dsn.' failed. Maybe PHP doesn\'t support the database?'); 02067 $output = false; 02068 } else { 02069 $this->handlerInstance[$handlerKey]->DataDictionary = NewDataDictionary($this->handlerInstance[$handlerKey]); 02070 $this->handlerInstance[$handlerKey]->last_insert_id = 0; 02071 if(isset($cfgArray['config']['sequenceStart'])) { 02072 $this->handlerInstance[$handlerKey]->sequenceStart = $cfgArray['config']['sequenceStart']; 02073 } else { 02074 $this->handlerInstance[$handlerKey]->sequenceStart = 1; 02075 } 02076 } 02077 break; 02078 case 'userdefined': 02079 // Find class file: 02080 $fileName = t3lib_div::getFileAbsFileName($cfgArray['config']['classFile']); 02081 if (@is_file($fileName)) { 02082 require_once($fileName); 02083 } else die('DBAL error: "'.$fileName.'" was not a file to include.'); 02084 02085 // Initialize: 02086 $this->handlerInstance[$handlerKey] = t3lib_div::makeInstance($cfgArray['config']['class']); 02087 $this->handlerInstance[$handlerKey]->init($cfgArray,$this); 02088 02089 if (is_object($this->handlerInstance[$handlerKey])) { 02090 $output = TRUE; 02091 } 02092 break; 02093 default: 02094 die('ERROR: Invalid handler type: "'.$cfgArray['type'].'"'); 02095 break; 02096 } 02097 02098 return $output; 02099 } else die('ERROR: No handler for key "'.$handlerKey.'"'); 02100 } 02101 02102 02108 function runningNative() { 02109 return ((string)$this->handlerCfg[$this->lastHandlerKey]['type']==='native'); 02110 } 02111 02112 02119 function runningADOdbDriver($driver) { 02120 return strstr($this->handlerCfg[$this->lastHandlerKey]['config']['driver'], $driver); 02121 } 02122 02123 02124 02125 02126 02127 02128 02129 02130 02131 02132 /************************************ 02133 * 02134 * Table/Field mapping 02135 * 02136 **************************************/ 02137 02145 function map_needMapping($tableList,$fieldMappingOnly=FALSE) { 02146 02147 $key = $tableList.'|'.$fieldMappingOnly; 02148 if (!isset($this->cache_mappingFromTableList[$key])) { 02149 $this->cache_mappingFromTableList[$key] = FALSE; // Default: 02150 02151 $tables = $this->SQLparser->parseFromTables($tableList); 02152 if (is_array($tables)) { 02153 foreach($tables as $tableCfg) { 02154 if ($fieldMappingOnly) { 02155 if (is_array($this->mapping[$tableCfg['table']]['mapFieldNames'])) { 02156 $this->cache_mappingFromTableList[$key] = $tables; 02157 } 02158 } else { 02159 if (is_array($this->mapping[$tableCfg['table']])) { 02160 $this->cache_mappingFromTableList[$key] = $tables; 02161 } 02162 } 02163 } 02164 } 02165 } 02166 02167 return $this->cache_mappingFromTableList[$key]; 02168 } 02169 02181 function map_assocArray($input,$tables,$rev=FALSE) { 02182 02183 // Traverse tables from query (hopefully only one table): 02184 foreach($tables as $tableCfg) { 02185 if (is_array($this->mapping[$tableCfg['table']]['mapFieldNames'])) { 02186 02187 // Get the map (reversed if needed): 02188 if ($rev) { 02189 $theMap = array_flip($this->mapping[$tableCfg['table']]['mapFieldNames']); 02190 } else { 02191 $theMap = $this->mapping[$tableCfg['table']]['mapFieldNames']; 02192 } 02193 02194 // Traverse selected record, map fieldnames: 02195 $output = array(); 02196 foreach($input as $fN => $value) { 02197 02198 // Set the field name, change it if found in mapping array: 02199 if ($theMap[$fN]) { 02200 $newKey = $theMap[$fN]; 02201 } else { 02202 $newKey = $fN; 02203 } 02204 02205 // Set value to fieldname: 02206 $output[$newKey] = $value; 02207 } 02208 02209 // When done, override the $input array with the result: 02210 $input = $output; 02211 } 02212 } 02213 02214 // Return input array (which might have been altered in the mean time) 02215 return $input; 02216 } 02217 02230 function map_remapSELECTQueryParts(&$select_fields,&$from_table,&$where_clause,&$groupBy,&$orderBy) { 02231 02232 // Tables: 02233 $tables = $this->SQLparser->parseFromTables($from_table); 02234 $defaultTable = $tables[0]['table']; 02235 foreach($tables as $k => $v) { 02236 if ($this->mapping[$v['table']]['mapTableName']) { 02237 $tables[$k]['table'] = $this->mapping[$v['table']]['mapTableName']; 02238 } 02239 } 02240 $from_table = $this->SQLparser->compileFromTables($tables); 02241 02242 // Where clause: 02243 $whereParts = $this->SQLparser->parseWhereClause($where_clause); 02244 $this->map_sqlParts($whereParts,$defaultTable); 02245 $where_clause = $this->SQLparser->compileWhereClause($whereParts); 02246 02247 // Select fields: 02248 $expFields = $this->SQLparser->parseFieldList($select_fields); 02249 $this->map_sqlParts($expFields,$defaultTable); 02250 $select_fields = $this->SQLparser->compileFieldList($expFields); 02251 02252 // Group By fields 02253 $expFields = $this->SQLparser->parseFieldList($groupBy); 02254 $this->map_sqlParts($expFields,$defaultTable); 02255 $groupBy = $this->SQLparser->compileFieldList($expFields); 02256 02257 // Order By fields 02258 $expFields = $this->SQLparser->parseFieldList($orderBy); 02259 $this->map_sqlParts($expFields,$defaultTable); 02260 $orderBy = $this->SQLparser->compileFieldList($expFields); 02261 } 02262 02272 function map_sqlParts(&$sqlPartArray, $defaultTable) { 02273 02274 // Traverse sql Part array: 02275 if (is_array($sqlPartArray)) { 02276 foreach($sqlPartArray as $k => $v) { 02277 02278 // Look for sublevel (WHERE parts only) 02279 if (is_array($sqlPartArray[$k]['sub'])) { 02280 $this->map_sqlParts($sqlPartArray[$k]['sub'], $defaultTable); // Call recursively! 02281 } else { 02282 // For the field, look for table mapping (generic): 02283 $t = $sqlPartArray[$k]['table'] ? $sqlPartArray[$k]['table'] : $defaultTable; 02284 02285 // Mapping field name, if set: 02286 if (is_array($this->mapping[$t]['mapFieldNames']) && $this->mapping[$t]['mapFieldNames'][$sqlPartArray[$k]['field']]) { 02287 $sqlPartArray[$k]['field'] = $this->mapping[$t]['mapFieldNames'][$sqlPartArray[$k]['field']]; 02288 } 02289 02290 // Map table? 02291 if ($sqlPartArray[$k]['table'] && $this->mapping[$sqlPartArray[$k]['table']]['mapTableName']) { 02292 $sqlPartArray[$k]['table'] = $this->mapping[$sqlPartArray[$k]['table']]['mapTableName']; 02293 } 02294 } 02295 } 02296 } 02297 } 02298 02307 function map_genericQueryParsed(&$parsedQuery) { 02308 02309 // Getting table - same for all: 02310 $table = $parsedQuery['TABLE']; 02311 if ($table) { 02312 // Do field mapping if needed: 02313 if ($tableArray = $this->map_needMapping($table)) { 02314 02315 // Table name: 02316 if ($this->mapping[$table]['mapTableName']) { 02317 $parsedQuery['TABLE'] = $this->mapping[$table]['mapTableName']; 02318 } 02319 02320 // Based on type, do additional changes: 02321 switch($parsedQuery['type']) { 02322 case 'ALTERTABLE': 02323 02324 // Changing field name: 02325 $newFieldName = $this->mapping[$table]['mapFieldNames'][$parsedQuery['FIELD']]; 02326 if ($newFieldName) { 02327 if ($parsedQuery['FIELD'] == $parsedQuery['newField']) { 02328 $parsedQuery['FIELD'] = $parsedQuery['newField'] = $newFieldName; 02329 } else $parsedQuery['FIELD'] = $newFieldName; 02330 } 02331 02332 // Changing key field names: 02333 if (is_array($parsedQuery['fields'])) { 02334 $this->map_fieldNamesInArray($table,$parsedQuery['fields']); 02335 } 02336 break; 02337 case 'CREATETABLE': 02338 // Remapping fields: 02339 if (is_array($parsedQuery['FIELDS'])) { 02340 $newFieldsArray = array(); 02341 foreach($parsedQuery['FIELDS'] as $fN => $fInfo) { 02342 if ($this->mapping[$table]['mapFieldNames'][$fN]) { 02343 $fN = $this->mapping[$table]['mapFieldNames'][$fN]; 02344 } 02345 $newFieldsArray[$fN] = $fInfo; 02346 } 02347 $parsedQuery['FIELDS'] = $newFieldsArray; 02348 } 02349 02350 // Remapping keys: 02351 if (is_array($parsedQuery['KEYS'])) { 02352 foreach($parsedQuery['KEYS'] as $kN => $kInfo) { 02353 $this->map_fieldNamesInArray($table,$parsedQuery['KEYS'][$kN]); 02354 } 02355 } 02356 break; 02357 02359 02360 } 02361 } 02362 } else die('ERROR, mapping: No table found in parsed Query array...'); 02363 } 02364 02372 function map_fieldNamesInArray($table,&$fieldArray) { 02373 if (is_array($this->mapping[$table]['mapFieldNames'])) { 02374 foreach($fieldArray as $k => $v) { 02375 if ($this->mapping[$table]['mapFieldNames'][$v]) { 02376 $fieldArray[$k] = $this->mapping[$table]['mapFieldNames'][$v]; 02377 } 02378 } 02379 } 02380 } 02381 02382 02383 02384 02385 02386 02387 02388 02389 02390 02391 02392 02393 02394 02395 02396 02397 02398 /************************************** 02399 * 02400 * Debugging 02401 * 02402 **************************************/ 02403 02413 function debugHandler($function,$execTime,$inData) { 02414 // we don't want to log our own log/debug SQL 02415 $script = substr(PATH_thisScript,strlen(PATH_site)); 02416 02417 if (substr($script,-strlen('dbal/mod1/index.php'))!='dbal/mod1/index.php' && 02418 !strstr($inData['args'][0], 'tx_dbal_debuglog')) { 02419 $data = array(); 02420 $errorFlag = 0; 02421 $joinTable = ''; 02422 02423 if ($this->sql_error()) { 02424 $data['sqlError'] = $this->sql_error(); 02425 $errorFlag|=1; 02426 } 02427 02428 // if lastQuery is empty (for whatever reason) at least log inData.args 02429 if(empty($this->lastQuery)) 02430 $query = implode(' ',$inData['args']); 02431 else 02432 $query = $this->lastQuery; 02433 02434 switch($function) { 02435 case 'exec_INSERTquery': 02436 case 'exec_UPDATEquery': 02437 case 'exec_DELETEquery': 02438 $this->debug_log($query,$execTime,$data,$joinTable,$errorFlag, $script); 02439 break; 02440 02441 case 'exec_SELECTquery': 02442 // Get explain data: 02443 if ($this->conf['debugOptions']['EXPLAIN'] && t3lib_div::inList('adodb,native',$inData['handlerType'])) { 02444 $data['EXPLAIN'] = $this->debug_explain($this->lastQuery); 02445 } 02446 02447 // Check parsing of Query: 02448 if ($this->conf['debugOptions']['parseQuery']) { 02449 $parseResults = array(); 02450 $parseResults['SELECT'] = $this->SQLparser->debug_parseSQLpart('SELECT',$inData['args'][1]); 02451 $parseResults['FROM'] = $this->SQLparser->debug_parseSQLpart('FROM',$inData['args'][0]); 02452 $parseResults['WHERE'] = $this->SQLparser->debug_parseSQLpart('WHERE',$inData['args'][2]); 02453 $parseResults['GROUPBY'] = $this->SQLparser->debug_parseSQLpart('SELECT',$inData['args'][3]); // Using select field list syntax 02454 $parseResults['ORDERBY'] = $this->SQLparser->debug_parseSQLpart('SELECT',$inData['args'][4]); // Using select field list syntax 02455 02456 foreach($parseResults as $k => $v) { 02457 if (!strlen($parseResults[$k])) unset($parseResults[$k]); 02458 } 02459 if (count($parseResults)) { 02460 $data['parseError'] = $parseResults; 02461 $errorFlag|=2; 02462 } 02463 } 02464 02465 // Checking joinTables: 02466 if ($this->conf['debugOptions']['joinTables']) { 02467 if (count(explode(',', $inData['ORIG_from_table']))>1) { 02468 $joinTable = $inData['args'][0]; 02469 } 02470 } 02471 02472 // Logging it: 02473 $this->debug_log($query,$execTime,$data,$joinTable,$errorFlag, $script); 02474 if(!empty($inData['args'][2])) 02475 $this->debug_WHERE($inData['args'][0], $inData['args'][2], $script); 02476 break; 02477 } 02478 } 02479 } 02480 02489 function debug_WHERE($table,$where, $script='') { 02490 $insertArray = array ( 02491 'tstamp' => $GLOBALS['EXEC_TIME'], 02492 'beuser_id' => intval($GLOBALS['BE_USER']->user['uid']), 02493 'script' => $script, 02494 'tablename' => $table, 02495 'whereclause' => $where 02496 ); 02497 02498 $this->exec_INSERTquery('tx_dbal_debuglog_where', $insertArray); 02499 } 02500 02512 function debug_log($query,$ms,$data,$join,$errorFlag, $script='') { 02513 $insertArray = array ( 02514 'tstamp' => $GLOBALS['EXEC_TIME'], 02515 'beuser_id' => intval($GLOBALS['BE_USER']->user['uid']), 02516 'script' => $script, 02517 'exec_time' => $ms, 02518 'table_join' => $join, 02519 'serdata' => serialize($data), 02520 'query' => (is_array($query) ? $query[0].' WITH '.count($query[1]).' BLOB FIELDS: '.implode(', ',array_keys($query[1])) : $query), 02521 'errorFlag' => $errorFlag 02522 ); 02523 02524 $this->exec_INSERTquery('tx_dbal_debuglog', $insertArray); 02525 } 02526 02534 function debug_explain($query) { 02535 $res = $this->sql_query('EXPLAIN '.$query); 02536 02537 $output = array(); 02538 while($row = $this->sql_fetch_assoc($res)) { 02539 $output[] = $row; 02540 } 02541 return $output; 02542 } 02543 } 02544 02545 02546 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dbal/class.ux_t3lib_db.php']) { 02547 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dbal/class.ux_t3lib_db.php']); 02548 } 02549 ?>