PageRenderTime 68ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/typo3/sysext/dbal/class.ux_t3lib_db.php

https://bitbucket.org/linxpinx/mercurial
PHP | 3373 lines | 2068 code | 383 blank | 922 comment | 472 complexity | 5d57942da2ed45977e109034af05d4eb MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, Unlicense, LGPL-2.1, Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /***************************************************************
  3. * Copyright notice
  4. *
  5. * (c) 2004-2010 Kasper Skaarhoj (kasperYYYY@typo3.com)
  6. * (c) 2004-2010 Karsten Dambekalns <karsten@typo3.org>
  7. * (c) 2009-2010 Xavier Perseguers <typo3@perseguers.ch>
  8. * All rights reserved
  9. *
  10. * This script is part of the TYPO3 project. The TYPO3 project is
  11. * free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * The GNU General Public License can be found at
  17. * http://www.gnu.org/copyleft/gpl.html.
  18. * A copy is found in the textfile GPL.txt and important notices to the license
  19. * from the author is found in LICENSE.txt distributed with these scripts.
  20. *
  21. *
  22. * This script is distributed in the hope that it will be useful,
  23. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25. * GNU General Public License for more details.
  26. *
  27. * This copyright notice MUST APPEAR in all copies of the script!
  28. ***************************************************************/
  29. /**
  30. * Contains a database abstraction layer class for TYPO3
  31. *
  32. * $Id: class.ux_t3lib_db.php 29977 2010-02-13 13:18:32Z xperseguers $
  33. *
  34. * @author Kasper Skaarhoj <kasper@typo3.com>
  35. * @author Karsten Dambekalns <k.dambekalns@fishfarm.de>
  36. * @author Xavier Perseguers <typo3@perseguers.ch>
  37. */
  38. /**
  39. * [CLASS/FUNCTION INDEX of SCRIPT]
  40. *
  41. *
  42. *
  43. * 123: class ux_t3lib_DB extends t3lib_DB
  44. * 169: function ux_t3lib_DB()
  45. * 184: function initInternalVariables()
  46. *
  47. * SECTION: Query Building (Overriding parent methods)
  48. * 217: function exec_INSERTquery($table,$fields_values)
  49. * 275: function exec_UPDATEquery($table,$where,$fields_values)
  50. * 334: function exec_DELETEquery($table,$where)
  51. * 387: function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy = '',$orderBy = '',$limit = '')
  52. *
  53. * SECTION: Creates an INSERT SQL-statement for $table from the array with field/value pairs $fields_values.
  54. * 533: function SELECTquery($select_fields,$from_table,$where_clause,$groupBy = '',$orderBy = '',$limit = '')
  55. * 556: function quoteSelectFields(&$select_fields)
  56. * 573: function quoteFromTables(&$from_table)
  57. * 595: function quoteWhereClause(&$where_clause)
  58. * 620: function quoteGroupBy(&$groupBy)
  59. * 637: function quoteOrderBy(&$orderBy)
  60. *
  61. * SECTION: Various helper functions
  62. * 663: function quoteStr($str, $table)
  63. *
  64. * SECTION: SQL wrapper functions (Overriding parent methods)
  65. * 707: function sql_error()
  66. * 734: function sql_num_rows(&$res)
  67. * 760: function sql_fetch_assoc(&$res)
  68. * 808: function sql_fetch_row(&$res)
  69. * 842: function sql_free_result(&$res)
  70. * 868: function sql_insert_id()
  71. * 893: function sql_affected_rows()
  72. * 919: function sql_data_seek(&$res,$seek)
  73. * 946: function sql_field_type(&$res,$pointer)
  74. *
  75. * SECTION: Legacy functions, bound to _DEFAULT handler. (Overriding parent methods)
  76. * 987: function sql($db,$query)
  77. * 999: function sql_query($query)
  78. * 1035: function sql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password)
  79. * 1055: function sql_select_db($TYPO3_db)
  80. *
  81. * SECTION: SQL admin functions
  82. * 1086: function admin_get_tables()
  83. * 1149: function admin_get_fields($tableName)
  84. * 1210: function admin_get_keys($tableName)
  85. * 1270: function admin_query($query)
  86. *
  87. * SECTION: Handler management
  88. * 1333: function handler_getFromTableList($tableList)
  89. * 1379: function handler_init($handlerKey)
  90. *
  91. * SECTION: Table/Field mapping
  92. * 1488: function map_needMapping($tableList,$fieldMappingOnly = FALSE)
  93. * 1524: function map_assocArray($input,$tables,$rev = FALSE)
  94. * 1573: function map_remapSELECTQueryParts(&$select_fields,&$from_table,&$where_clause,&$groupBy,&$orderBy)
  95. * 1615: function map_sqlParts(&$sqlPartArray, $defaultTable)
  96. * 1650: function map_genericQueryParsed(&$parsedQuery)
  97. * 1717: function map_fieldNamesInArray($table,&$fieldArray)
  98. *
  99. * SECTION: Debugging
  100. * 1758: function debugHandler($function,$execTime,$inData)
  101. * 1823: function debug_log($query,$ms,$data,$join,$errorFlag)
  102. * 1849: function debug_explain($query)
  103. *
  104. * TOTAL FUNCTIONS: 41
  105. * (This index is automatically created/updated by the extension "extdeveval")
  106. *
  107. */
  108. /**
  109. * TYPO3 database abstraction layer
  110. *
  111. * @author Kasper Skaarhoj <kasper@typo3.com>
  112. * @author Karsten Dambekalns <k.dambekalns@fishfarm.de>
  113. * @package TYPO3
  114. * @subpackage tx_dbal
  115. */
  116. class ux_t3lib_DB extends t3lib_DB {
  117. // Internal, static:
  118. var $printErrors = FALSE; // Enable output of SQL errors after query executions. Set through TYPO3_CONF_VARS, see init()
  119. var $debug = FALSE; // Enable debug mode. Set through TYPO3_CONF_VARS, see init()
  120. var $conf = array(); // Configuration array, copied from TYPO3_CONF_VARS in constructor.
  121. var $mapping = array(); // See manual.
  122. var $table2handlerKeys = array(); // See manual.
  123. var $handlerCfg = array( // See manual.
  124. '_DEFAULT' => array(
  125. 'type' => 'native',
  126. 'config' => array(
  127. 'username' => '', // Set by default (overridden)
  128. 'password' => '', // Set by default (overridden)
  129. 'host' => '', // Set by default (overridden)
  130. 'database' => '', // Set by default (overridden)
  131. 'driver' => '', // ONLY "adodb" type; eg. "mysql"
  132. 'sequenceStart' => 1, // ONLY "adodb", first number in sequences/serials/...
  133. 'useNameQuote' => 0 // ONLY "adodb", whether to use NameQuote() method from ADOdb to quote names
  134. )
  135. ),
  136. );
  137. // Internal, dynamic:
  138. 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.
  139. var $lastHandlerKey = ''; // Storage of the handler key of last ( SELECT) query - used for subsequent fetch-row calls etc.
  140. var $lastQuery = ''; // Storage of last SELECT query
  141. var $lastParsedAndMappedQueryArray = array(); // Query array, the last one parsed
  142. var $resourceIdToTableNameMap = array(); // Mapping of resource ids to table names.
  143. // Internal, caching:
  144. var $cache_handlerKeyFromTableList = array(); // Caching handlerKeys for table lists
  145. var $cache_mappingFromTableList = array(); // Caching mapping information for table lists
  146. var $cache_autoIncFields = array(); // parsed SQL from standard DB dump file
  147. var $cache_fieldType = array(); // field types for tables/fields
  148. var $cache_primaryKeys = array(); // primary keys
  149. /**
  150. * SQL parser
  151. *
  152. * @var tx_dbal_sqlengine
  153. */
  154. var $SQLparser;
  155. /**
  156. * Installer
  157. *
  158. * @var t3lib_install
  159. */
  160. var $Installer;
  161. /**
  162. * Constructor.
  163. * Creates SQL parser object and imports configuration from $TYPO3_CONF_VARS['EXTCONF']['dbal']
  164. */
  165. public function __construct() {
  166. // Set SQL parser object for internal use:
  167. $this->SQLparser = t3lib_div::makeInstance('tx_dbal_sqlengine');
  168. $this->Installer = t3lib_div::makeInstance('t3lib_install');
  169. // Set internal variables with configuration:
  170. $this->conf = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['dbal'];
  171. $this->initInternalVariables();
  172. }
  173. /**
  174. * Setting internal variables from $this->conf.
  175. *
  176. * @return void
  177. */
  178. protected function initInternalVariables() {
  179. // Set outside configuration:
  180. if (isset($this->conf['mapping'])) {
  181. $this->mapping = $this->conf['mapping'];
  182. }
  183. if (isset($this->conf['table2handlerKeys'])) {
  184. $this->table2handlerKeys = $this->conf['table2handlerKeys'];
  185. }
  186. if (isset($this->conf['handlerCfg'])) {
  187. $this->handlerCfg = $this->conf['handlerCfg'];
  188. }
  189. $this->cacheFieldInfo();
  190. // Debugging settings:
  191. $this->printErrors = $this->conf['debugOptions']['printErrors'] ? TRUE : FALSE;
  192. $this->debug = $this->conf['debugOptions']['enabled'] ? TRUE : FALSE;
  193. }
  194. /**
  195. * Clears the cached field information file.
  196. *
  197. * @return void
  198. */
  199. public function clearCachedFieldInfo() {
  200. if (file_exists(PATH_typo3conf . 'temp_fieldInfo.php')) {
  201. unlink(PATH_typo3conf . 'temp_fieldInfo.php');
  202. }
  203. }
  204. /**
  205. * Caches the field information.
  206. *
  207. * @return void
  208. */
  209. public function cacheFieldInfo() {
  210. $extSQL = '';
  211. $parsedExtSQL = array();
  212. // try to fetch cached file first
  213. // file is removed when admin_query() is called
  214. if (file_exists(PATH_typo3conf . 'temp_fieldInfo.php')) {
  215. $fdata = unserialize(t3lib_div::getUrl(PATH_typo3conf . 'temp_fieldInfo.php'));
  216. $this->cache_autoIncFields = $fdata['incFields'];
  217. $this->cache_fieldType = $fdata['fieldTypes'];
  218. $this->cache_primaryKeys = $fdata['primaryKeys'];
  219. } else {
  220. // handle stddb.sql, parse and analyze
  221. $extSQL = t3lib_div::getUrl(PATH_site . 't3lib/stddb/tables.sql');
  222. $parsedExtSQL = $this->Installer->getFieldDefinitions_fileContent($extSQL);
  223. $this->analyzeFields($parsedExtSQL);
  224. // loop over all installed extensions
  225. foreach ($GLOBALS['TYPO3_LOADED_EXT'] as $ext => $v) {
  226. if (!is_array($v) || !isset($v['ext_tables.sql'])) {
  227. continue;
  228. }
  229. // fetch db dump (if any) and parse it, then analyze
  230. $extSQL = t3lib_div::getUrl($v['ext_tables.sql']);
  231. $parsedExtSQL = $this->Installer->getFieldDefinitions_fileContent($extSQL);
  232. $this->analyzeFields($parsedExtSQL);
  233. }
  234. $cachedFieldInfo = array('incFields' => $this->cache_autoIncFields, 'fieldTypes' => $this->cache_fieldType, 'primaryKeys' => $this->cache_primaryKeys);
  235. $cachedFieldInfo = serialize($this->mapCachedFieldInfo($cachedFieldInfo));
  236. // write serialized content to file
  237. t3lib_div::writeFile(PATH_typo3conf . 'temp_fieldInfo.php', $cachedFieldInfo);
  238. if (strcmp(t3lib_div::getUrl(PATH_typo3conf . 'temp_fieldInfo.php'), $cachedFieldInfo)) {
  239. die('typo3temp/temp_incfields.php was NOT updated properly (written content didn\'t match file content) - maybe write access problem?');
  240. }
  241. }
  242. }
  243. /**
  244. * Analyzes fields and adds the extracted information to the field type, auto increment and primary key info caches.
  245. *
  246. * @param array $parsedExtSQL The output produced by t3lib_install::getFieldDefinitions_fileContent()
  247. * @return void
  248. * @see t3lib_install::getFieldDefinitions_fileContent()
  249. */
  250. protected function analyzeFields($parsedExtSQL) {
  251. foreach ($parsedExtSQL as $table => $tdef) {
  252. if (is_array($tdef['fields'])) {
  253. foreach ($tdef['fields'] as $field => $fdef) {
  254. $fdef = $this->SQLparser->parseFieldDef($fdef);
  255. $this->cache_fieldType[$table][$field]['type'] = $fdef['fieldType'];
  256. $this->cache_fieldType[$table][$field]['metaType'] = $this->MySQLMetaType($fdef['fieldType']);
  257. $this->cache_fieldType[$table][$field]['notnull'] = (isset($fdef['featureIndex']['NOTNULL']) && !$this->SQLparser->checkEmptyDefaultValue($fdef['featureIndex'])) ? 1 : 0;
  258. if (isset($fdef['featureIndex']['DEFAULT'])) {
  259. $default = $fdef['featureIndex']['DEFAULT']['value'][0];
  260. if (isset($fdef['featureIndex']['DEFAULT']['value'][1])) {
  261. $default = $fdef['featureIndex']['DEFAULT']['value'][1] . $default . $fdef['featureIndex']['DEFAULT']['value'][1];
  262. }
  263. $this->cache_fieldType[$table][$field]['default'] = $default;
  264. }
  265. if (isset($fdef['featureIndex']['AUTO_INCREMENT'])) {
  266. $this->cache_autoIncFields[$table] = $field;
  267. }
  268. if (isset($tdef['keys']['PRIMARY'])) {
  269. $this->cache_primaryKeys[$table] = substr($tdef['keys']['PRIMARY'], 13, -1);
  270. }
  271. }
  272. }
  273. }
  274. }
  275. /**
  276. * This function builds all definitions for mapped tables and fields
  277. * @see cacheFieldInfo()
  278. */
  279. protected function mapCachedFieldInfo($fieldInfo) {
  280. if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['dbal']['mapping'])) {
  281. foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['dbal']['mapping'] as $mappedTable => $mappedConf) {
  282. if (array_key_exists($mappedTable, $fieldInfo['incFields'])) {
  283. $mappedTableAlias = $mappedConf['mapTableName'];
  284. if (isset($mappedConf['mapFieldNames'][$fieldInfo['incFields'][$mappedTable]])) {
  285. $fieldInfo['incFields'][$mappedTableAlias] = $mappedConf['mapFieldNames'][$fieldInfo['incFields'][$mappedTable]];
  286. } else {
  287. $fieldInfo['incFields'][$mappedTableAlias] = $fieldInfo['incFields'][$mappedTable];
  288. }
  289. }
  290. if (array_key_exists($mappedTable, $fieldInfo['fieldTypes'])) {
  291. foreach ($fieldInfo['fieldTypes'][$mappedTable] as $field => $fieldConf) {
  292. $tempMappedFieldConf[$mappedConf['mapFieldNames'][$field]] = $fieldConf;
  293. }
  294. $fieldInfo['fieldTypes'][$mappedConf['mapTableName']] = $tempMappedFieldConf;
  295. }
  296. if (array_key_exists($mappedTable, $fieldInfo['primaryKeys'])) {
  297. $mappedTableAlias = $mappedConf['mapTableName'];
  298. if (isset($mappedConf['mapFieldNames'][$fieldInfo['primaryKeys'][$mappedTable]])) {
  299. $fieldInfo['primaryKeys'][$mappedTableAlias] = $mappedConf['mapFieldNames'][$fieldInfo['primaryKeys'][$mappedTable]];
  300. } else {
  301. $fieldInfo['primaryKeys'][$mappedTableAlias] = $fieldInfo['primaryKeys'][$mappedTable];
  302. }
  303. }
  304. }
  305. }
  306. return $fieldInfo;
  307. }
  308. /************************************
  309. *
  310. * Query Building (Overriding parent methods)
  311. * These functions are extending counterparts in the parent class.
  312. *
  313. **************************************/
  314. /* From the ADOdb documentation, this is what we do (_Execute for SELECT, _query for the other actions)
  315. Execute() is the default way to run queries. You can use the low-level functions _Execute() and _query() to reduce query overhead.
  316. Both these functions share the same parameters as Execute().
  317. If you do not have any bind parameters or your database supports binding (without emulation), then you can call _Execute() directly.
  318. Calling this function bypasses bind emulation. Debugging is still supported in _Execute().
  319. If you do not require debugging facilities nor emulated binding, and do not require a recordset to be returned, then you can call _query.
  320. This is great for inserts, updates and deletes. Calling this function bypasses emulated binding, debugging, and recordset handling. Either
  321. the resultid, TRUE or FALSE are returned by _query().
  322. */
  323. /**
  324. * Inserts a record for $table from the array with field/value pairs $fields_values.
  325. *
  326. * @param string Table name
  327. * @param array Field values as key=>value pairs. Values will be escaped internally. Typically you would fill an array like "$insertFields" with 'fieldname'=>'value' and pass it to this function as argument.
  328. * @param mixed List/array of keys NOT to quote (eg. SQL functions)
  329. * @return mixed Result from handler, usually TRUE when success and FALSE on failure
  330. */
  331. public function exec_INSERTquery($table, $fields_values, $no_quote_fields = '') {
  332. if ($this->debug) {
  333. $pt = t3lib_div::milliseconds();
  334. }
  335. // Do field mapping if needed:
  336. $ORIG_tableName = $table;
  337. if ($tableArray = $this->map_needMapping($table)) {
  338. // Field mapping of array:
  339. $fields_values = $this->map_assocArray($fields_values, $tableArray);
  340. // Table name:
  341. if ($this->mapping[$table]['mapTableName']) {
  342. $table = $this->mapping[$table]['mapTableName'];
  343. }
  344. }
  345. // Select API:
  346. $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
  347. switch ((string)$this->handlerCfg[$this->lastHandlerKey]['type']) {
  348. case 'native':
  349. $this->lastQuery = $this->INSERTquery($table,$fields_values,$no_quote_fields);
  350. if (is_string($this->lastQuery)) {
  351. $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']);
  352. } else {
  353. $sqlResult = mysql_query($this->lastQuery[0], $this->handlerInstance[$this->lastHandlerKey]['link']);
  354. foreach ($this->lastQuery[1] as $field => $content) {
  355. mysql_query('UPDATE ' . $this->quoteFromTables($table) . ' SET ' . $this->quoteFromTables($field) . '=' . $this->fullQuoteStr($content, $table) . ' WHERE ' . $this->quoteWhereClause($where), $this->handlerInstance[$this->lastHandlerKey]['link']);
  356. }
  357. }
  358. break;
  359. case 'adodb':
  360. // auto generate ID for auto_increment fields if not present (static import needs this!)
  361. // should we check the table name here (static_*)?
  362. if (isset($this->cache_autoIncFields[$table])) {
  363. if (isset($fields_values[$this->cache_autoIncFields[$table]])) {
  364. $new_id = $fields_values[$this->cache_autoIncFields[$table]];
  365. if ($table != 'tx_dbal_debuglog') {
  366. $this->handlerInstance[$this->lastHandlerKey]->last_insert_id = $new_id;
  367. }
  368. } else {
  369. $new_id = $this->handlerInstance[$this->lastHandlerKey]->GenID($table.'_'.$this->cache_autoIncFields[$table], $this->handlerInstance[$this->lastHandlerKey]->sequenceStart);
  370. $fields_values[$this->cache_autoIncFields[$table]] = $new_id;
  371. if ($table != 'tx_dbal_debuglog') {
  372. $this->handlerInstance[$this->lastHandlerKey]->last_insert_id = $new_id;
  373. }
  374. }
  375. }
  376. $this->lastQuery = $this->INSERTquery($table,$fields_values,$no_quote_fields);
  377. if (is_string($this->lastQuery)) {
  378. $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery,FALSE);
  379. } else {
  380. $this->handlerInstance[$this->lastHandlerKey]->StartTrans();
  381. if (strlen($this->lastQuery[0])) {
  382. $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery[0],FALSE);
  383. }
  384. if (is_array($this->lastQuery[1])) {
  385. foreach ($this->lastQuery[1] as $field => $content) {
  386. if (empty($content)) continue;
  387. if (isset($this->cache_autoIncFields[$table]) && isset($new_id)) {
  388. $this->handlerInstance[$this->lastHandlerKey]->UpdateBlob($this->quoteFromTables($table),$field,$content,$this->quoteWhereClause($this->cache_autoIncFields[$table].'='.$new_id));
  389. } elseif (isset($this->cache_primaryKeys[$table])) {
  390. $where = '';
  391. $pks = explode(',', $this->cache_primaryKeys[$table]);
  392. foreach ($pks as $pk) {
  393. if (isset($fields_values[$pk]))
  394. $where .= $pk.'='.$this->fullQuoteStr($fields_values[$pk], $table).' AND ';
  395. }
  396. $where = $this->quoteWhereClause($where.'1=1');
  397. $this->handlerInstance[$this->lastHandlerKey]->UpdateBlob($this->quoteFromTables($table),$field,$content,$where);
  398. } else {
  399. $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans(FALSE);
  400. die('Could not update BLOB >>>> no WHERE clause found!'); // should never ever happen
  401. }
  402. }
  403. }
  404. if (is_array($this->lastQuery[2])) {
  405. foreach ($this->lastQuery[2] as $field => $content) {
  406. if (empty($content)) continue;
  407. if (isset($this->cache_autoIncFields[$table]) && isset($new_id)) {
  408. $this->handlerInstance[$this->lastHandlerKey]->UpdateClob($this->quoteFromTables($table),$field,$content,$this->quoteWhereClause($this->cache_autoIncFields[$table].'='.$new_id));
  409. } elseif (isset($this->cache_primaryKeys[$table])) {
  410. $where = '';
  411. $pks = explode(',', $this->cache_primaryKeys[$table]);
  412. foreach ($pks as $pk) {
  413. if (isset($fields_values[$pk]))
  414. $where .= $pk.'='.$this->fullQuoteStr($fields_values[$pk], $table).' AND ';
  415. }
  416. $where = $this->quoteWhereClause($where.'1=1');
  417. $this->handlerInstance[$this->lastHandlerKey]->UpdateClob($this->quoteFromTables($table),$field,$content,$where);
  418. } else {
  419. $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans(FALSE);
  420. die('Could not update CLOB >>>> no WHERE clause found!'); // should never ever happen
  421. }
  422. }
  423. }
  424. $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans();
  425. }
  426. break;
  427. case 'userdefined':
  428. $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_INSERTquery($table,$fields_values,$no_quote_fields);
  429. break;
  430. }
  431. if ($this->printErrors && $this->sql_error()) {
  432. debug(array($this->lastQuery, $this->sql_error()));
  433. }
  434. if ($this->debug) {
  435. $this->debugHandler(
  436. 'exec_INSERTquery',
  437. t3lib_div::milliseconds()-$pt,
  438. array(
  439. 'handlerType' => $hType,
  440. 'args' => array($table,$fields_values),
  441. 'ORIG_tablename' => $ORIG_tableName
  442. )
  443. );
  444. }
  445. // Return output:
  446. return $sqlResult;
  447. }
  448. /**
  449. * Creates and executes an INSERT SQL-statement for $table with multiple rows.
  450. * This method uses exec_INSERTquery() and is just a syntax wrapper to it.
  451. *
  452. * @param string Table name
  453. * @param array Field names
  454. * @param array Table rows. Each row should be an array with field values mapping to $fields
  455. * @param string/array See fullQuoteArray()
  456. * @return mixed Result from last handler, usually TRUE when success and FALSE on failure
  457. */
  458. public function exec_INSERTmultipleRows($table, array $fields, array $rows, $no_quote_fields = FALSE) {
  459. if ((string)$this->handlerCfg[$this->lastHandlerKey]['type'] === 'native') {
  460. return parent::exec_INSERTmultipleRows($table, $fields, $rows, $no_quote_fields);
  461. }
  462. foreach ($rows as $row) {
  463. $fields_values = array();
  464. foreach ($fields as $key => $value) {
  465. $fields_values[$value] = $row[$key];
  466. }
  467. $res = $this->exec_INSERTquery($table, $fields_values, $no_quote_fields);
  468. }
  469. return $res;
  470. }
  471. /**
  472. * Updates a record from $table
  473. *
  474. * @param string Database tablename
  475. * @param string WHERE clause, eg. "uid=1". NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
  476. * @param array Field values as key=>value pairs. Values will be escaped internally. Typically you would fill an array like "$updateFields" with 'fieldname'=>'value' and pass it to this function as argument.
  477. * @param mixed List/array of keys NOT to quote (eg. SQL functions)
  478. * @return mixed Result from handler, usually TRUE when success and FALSE on failure
  479. */
  480. public function exec_UPDATEquery($table,$where,$fields_values,$no_quote_fields = '') {
  481. if ($this->debug) {
  482. $pt = t3lib_div::milliseconds();
  483. }
  484. // Do table/field mapping:
  485. $ORIG_tableName = $table;
  486. if ($tableArray = $this->map_needMapping($table)) {
  487. // Field mapping of array:
  488. $fields_values = $this->map_assocArray($fields_values,$tableArray);
  489. // Where clause table and field mapping:
  490. $whereParts = $this->SQLparser->parseWhereClause($where);
  491. $this->map_sqlParts($whereParts,$tableArray[0]['table']);
  492. $where = $this->SQLparser->compileWhereClause($whereParts, FALSE);
  493. // Table name:
  494. if ($this->mapping[$table]['mapTableName']) {
  495. $table = $this->mapping[$table]['mapTableName'];
  496. }
  497. }
  498. // Select API
  499. $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
  500. switch ((string)$this->handlerCfg[$this->lastHandlerKey]['type']) {
  501. case 'native':
  502. $this->lastQuery = $this->UPDATEquery($table,$where,$fields_values,$no_quote_fields);
  503. if (is_string($this->lastQuery)) {
  504. $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']);
  505. }
  506. else {
  507. $sqlResult = mysql_query($this->lastQuery[0], $this->handlerInstance[$this->lastHandlerKey]['link']);
  508. foreach ($this->lastQuery[1] as $field => $content) {
  509. mysql_query('UPDATE '.$this->quoteFromTables($table).' SET '.$this->quoteFromTables($field).'='.$this->fullQuoteStr($content,$table).' WHERE '.$this->quoteWhereClause($where), $this->handlerInstance[$this->lastHandlerKey]['link']);
  510. }
  511. }
  512. break;
  513. case 'adodb':
  514. $this->lastQuery = $this->UPDATEquery($table,$where,$fields_values,$no_quote_fields);
  515. if (is_string($this->lastQuery)) {
  516. $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery,FALSE);
  517. } else {
  518. $this->handlerInstance[$this->lastHandlerKey]->StartTrans();
  519. if (strlen($this->lastQuery[0])) {
  520. $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery[0],FALSE);
  521. }
  522. if (is_array($this->lastQuery[1])) {
  523. foreach ($this->lastQuery[1] as $field => $content) {
  524. $this->handlerInstance[$this->lastHandlerKey]->UpdateBlob($this->quoteFromTables($table),$field,$content,$this->quoteWhereClause($where));
  525. }
  526. }
  527. if (is_array($this->lastQuery[2])) {
  528. foreach ($this->lastQuery[2] as $field => $content) {
  529. $this->handlerInstance[$this->lastHandlerKey]->UpdateClob($this->quoteFromTables($table),$field,$content,$this->quoteWhereClause($where));
  530. }
  531. }
  532. $this->handlerInstance[$this->lastHandlerKey]->CompleteTrans();
  533. }
  534. break;
  535. case 'userdefined':
  536. $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_UPDATEquery($table,$where,$fields_values,$no_quote_fields);
  537. break;
  538. }
  539. if ($this->printErrors && $this->sql_error()) {
  540. debug(array($this->lastQuery, $this->sql_error()));
  541. }
  542. if ($this->debug) {
  543. $this->debugHandler(
  544. 'exec_UPDATEquery',
  545. t3lib_div::milliseconds()-$pt,
  546. array(
  547. 'handlerType' => $hType,
  548. 'args' => array($table,$where, $fields_values),
  549. 'ORIG_from_table' => $ORIG_tableName
  550. )
  551. );
  552. }
  553. // Return result:
  554. return $sqlResult;
  555. }
  556. /**
  557. * Deletes records from table
  558. *
  559. * @param string Database tablename
  560. * @param string WHERE clause, eg. "uid=1". NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
  561. * @return mixed Result from handler
  562. */
  563. public function exec_DELETEquery($table, $where) {
  564. if ($this->debug) {
  565. $pt = t3lib_div::milliseconds();
  566. }
  567. // Do table/field mapping:
  568. $ORIG_tableName = $table;
  569. if ($tableArray = $this->map_needMapping($table)) {
  570. // Where clause:
  571. $whereParts = $this->SQLparser->parseWhereClause($where);
  572. $this->map_sqlParts($whereParts,$tableArray[0]['table']);
  573. $where = $this->SQLparser->compileWhereClause($whereParts, FALSE);
  574. // Table name:
  575. if ($this->mapping[$table]['mapTableName']) {
  576. $table = $this->mapping[$table]['mapTableName'];
  577. }
  578. }
  579. // Select API
  580. $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
  581. switch ((string)$this->handlerCfg[$this->lastHandlerKey]['type']) {
  582. case 'native':
  583. $this->lastQuery = $this->DELETEquery($table,$where);
  584. $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']);
  585. break;
  586. case 'adodb':
  587. $this->lastQuery = $this->DELETEquery($table,$where);
  588. $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery,FALSE);
  589. break;
  590. case 'userdefined':
  591. $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_DELETEquery($table,$where);
  592. break;
  593. }
  594. if ($this->printErrors && $this->sql_error()) {
  595. debug(array($this->lastQuery, $this->sql_error()));
  596. }
  597. if ($this->debug) {
  598. $this->debugHandler(
  599. 'exec_DELETEquery',
  600. t3lib_div::milliseconds()-$pt,
  601. array(
  602. 'handlerType' => $hType,
  603. 'args' => array($table,$where),
  604. 'ORIG_from_table' => $ORIG_tableName
  605. )
  606. );
  607. }
  608. // Return result:
  609. return $sqlResult;
  610. }
  611. /**
  612. * Selects records from Data Source
  613. *
  614. * @param string $select_fields List of fields to select from the table. This is what comes right after "SELECT ...". Required value.
  615. * @param string $from_table Table(s) from which to select. This is what comes right after "FROM ...". Required value.
  616. * @param string $where_clause Optional additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQquoteStr() yourself! DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
  617. * @param string $groupBy Optional GROUP BY field(s), if none, supply blank string.
  618. * @param string $orderBy Optional ORDER BY field(s), if none, supply blank string.
  619. * @param string $limit Optional LIMIT value ([begin,]max), if none, supply blank string.
  620. * @return mixed Result from handler. Typically object from DBAL layers.
  621. */
  622. public function exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '') {
  623. if ($this->debug) {
  624. $pt = t3lib_div::milliseconds();
  625. }
  626. // Map table / field names if needed:
  627. $ORIG_tableName = $from_table; // Saving table names in $ORIG_from_table since $from_table is transformed beneath:
  628. if ($tableArray = $this->map_needMapping($ORIG_tableName)) {
  629. $this->map_remapSELECTQueryParts($select_fields,$from_table,$where_clause,$groupBy,$orderBy); // Variables passed by reference!
  630. }
  631. // Get handler key and select API:
  632. $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
  633. $hType = (string)$this->handlerCfg[$this->lastHandlerKey]['type'];
  634. switch ($hType) {
  635. case 'native':
  636. $this->lastQuery = $this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit);
  637. $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']);
  638. $this->resourceIdToTableNameMap[(string)$sqlResult] = $ORIG_tableName;
  639. break;
  640. case 'adodb':
  641. if ($limit != '') {
  642. $splitLimit = t3lib_div::intExplode(',', $limit); // Splitting the limit values:
  643. if ($splitLimit[1]) { // If there are two parameters, do mapping differently than otherwise:
  644. $numrows = $splitLimit[1];
  645. $offset = $splitLimit[0];
  646. } else {
  647. $numrows = $splitLimit[0];
  648. $offset = 0;
  649. }
  650. $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->SelectLimit($this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy), $numrows, $offset);
  651. $this->lastQuery = $sqlResult->sql;
  652. } else {
  653. $this->lastQuery = $this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy);
  654. $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_Execute($this->lastQuery);
  655. }
  656. $sqlResult->TYPO3_DBAL_handlerType = 'adodb'; // Setting handler type in result object (for later recognition!)
  657. $sqlResult->TYPO3_DBAL_tableList = $ORIG_tableName;
  658. break;
  659. case 'userdefined':
  660. $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit);
  661. if (is_object($sqlResult)) {
  662. $sqlResult->TYPO3_DBAL_handlerType = 'userdefined'; // Setting handler type in result object (for later recognition!)
  663. $sqlResult->TYPO3_DBAL_tableList = $ORIG_tableName;
  664. }
  665. break;
  666. }
  667. if ($this->printErrors && $this->sql_error()) {
  668. debug(array($this->lastQuery, $this->sql_error()));
  669. }
  670. if ($this->debug) {
  671. $this->debugHandler(
  672. 'exec_SELECTquery',
  673. t3lib_div::milliseconds()-$pt,
  674. array(
  675. 'handlerType' => $hType,
  676. 'args' => array($from_table,$select_fields,$where_clause,$groupBy,$orderBy,$limit),
  677. 'ORIG_from_table' => $ORIG_tableName
  678. )
  679. );
  680. }
  681. // Return result handler.
  682. return $sqlResult;
  683. }
  684. /**
  685. * Truncates a table.
  686. *
  687. * @param string Database tablename
  688. * @return mixed Result from handler
  689. */
  690. public function exec_TRUNCATEquery($table) {
  691. if ($this->debug) {
  692. $pt = t3lib_div::milliseconds();
  693. }
  694. // Do table/field mapping:
  695. $ORIG_tableName = $table;
  696. if ($tableArray = $this->map_needMapping($table)) {
  697. // Table name:
  698. if ($this->mapping[$table]['mapTableName']) {
  699. $table = $this->mapping[$table]['mapTableName'];
  700. }
  701. }
  702. // Select API
  703. $this->lastHandlerKey = $this->handler_getFromTableList($ORIG_tableName);
  704. switch ((string)$this->handlerCfg[$this->lastHandlerKey]['type']) {
  705. case 'native':
  706. $this->lastQuery = $this->TRUNCATEquery($table);
  707. $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']);
  708. break;
  709. case 'adodb':
  710. $this->lastQuery = $this->TRUNCATEquery($table);
  711. $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_query($this->lastQuery, FALSE);
  712. break;
  713. case 'userdefined':
  714. $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_TRUNCATEquery($table,$where);
  715. break;
  716. }
  717. if ($this->printErrors && $this->sql_error()) {
  718. debug(array($this->lastQuery, $this->sql_error()));
  719. }
  720. if ($this->debug) {
  721. $this->debugHandler(
  722. 'exec_TRUNCATEquery',
  723. t3lib_div::milliseconds() - $pt,
  724. array(
  725. 'handlerType' => $hType,
  726. 'args' => array($table),
  727. 'ORIG_from_table' => $ORIG_tableName
  728. )
  729. );
  730. }
  731. // Return result:
  732. return $sqlResult;
  733. }
  734. /**
  735. * Executes a query.
  736. * EXPERIMENTAL since TYPO3 4.4.
  737. *
  738. * @param array $queryParts SQL parsed by method parseSQL() of t3lib_sqlparser
  739. * @return pointer Result pointer / DBAL object
  740. * @see ux_t3lib_db::sql_query()
  741. */
  742. protected function exec_query(array $queryParts) {
  743. switch ($queryParts['type']) {
  744. case 'SELECT':
  745. $selectFields = $this->SQLparser->compileFieldList($queryParts['SELECT']);
  746. $fromTables = $this->SQLparser->compileFromTables($queryParts['FROM']);
  747. $whereClause = isset($queryParts['WHERE']) ? $this->SQLparser->compileWhereClause($queryParts['WHERE']) : '1=1';
  748. $groupBy = isset($queryParts['GROUPBY']) ? $this->SQLparser->compileWhereClause($queryParts['GROUPBY']) : '';
  749. $orderBy = isset($queryParts['GROUPBY']) ? $this->SQLparser->compileWhereClause($queryParts['ORDERBY']) : '';
  750. $limit = isset($queryParts['LIMIT']) ? $this->SQLparser->compileWhereClause($queryParts['LIMIT']) : '';
  751. return $this->exec_SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy, $limit);
  752. case 'UPDATE':
  753. $table = $queryParts['TABLE'];
  754. $fields = array();
  755. foreach ($components['FIELDS'] as $fN => $fV) {
  756. $fields[$fN] = $fV[0];
  757. }
  758. $whereClause = isset($queryParts['WHERE']) ? $this->SQLparser->compileWhereClause($queryParts['WHERE']) : '1=1';
  759. return $this->exec_UPDATEquery($table, $whereClause, $fields);
  760. case 'INSERT':
  761. $table = $queryParts['TABLE'];
  762. $values = array();
  763. if (isset($queryParts['VALUES_ONLY']) && is_array($queryParts['VALUES_ONLY'])) {
  764. $fields = $GLOBALS['TYPO3_DB']->cache_fieldType[$table];
  765. $fc = 0;
  766. foreach ($fields as $fn => $fd) {
  767. $values[$fn] = $queryParts['VALUES_ONLY'][$fc++][0];
  768. }
  769. } else {
  770. foreach ($queryParts['FIELDS'] as $fN => $fV) {
  771. $values[$fN] = $fV[0];
  772. }
  773. }
  774. return $this->exec_INSERTquery($table, $values);
  775. case 'DELETE':
  776. $table = $queryParts['TABLE'];
  777. $whereClause = isset($queryParts['WHERE']) ? $this->SQLparser->compileWhereClause($queryParts['WHERE']) : '1=1';
  778. return $this->exec_DELETEquery($table, $whereClause);
  779. case 'TRUNCATETABLE':
  780. $table = $queryParts['TABLE'];
  781. return $this->exec_TRUNCATEquery($table);
  782. }
  783. }
  784. /**************************************
  785. *
  786. * Query building
  787. *
  788. **************************************/
  789. /**
  790. * Creates an INSERT SQL-statement for $table from the array with field/value pairs $fields_values.
  791. * Usage count/core: 4
  792. *
  793. * @param string See exec_INSERTquery()
  794. * @param array See exec_INSERTquery()
  795. * @param mixed See exec_INSERTquery()
  796. * @return mixed Full SQL query for INSERT as string or array (unless $fields_values does not contain any elements in which case it will be FALSE). If BLOB fields will be affected and one is not running the native type, an array will be returned, where 0 => plain SQL, 1 => fieldname/value pairs of BLOB fields
  797. */
  798. public function INSERTquery($table, $fields_values, $no_quote_fields = '') {
  799. // Table and fieldnames should be "SQL-injection-safe" when supplied to this function (contrary to values in the arrays which may be insecure).
  800. if (is_array($fields_values) && count($fields_values)) {
  801. if (is_string($no_quote_fields)) {
  802. $no_quote_fields = explode(',', $no_quote_fields);
  803. } elseif (!is_array($no_quote_fields)) {
  804. $no_quote_fields = array();
  805. }
  806. $blobfields = array();
  807. $nArr = array();
  808. foreach ($fields_values as $k => $v) {
  809. if (!$this->runningNative() && $this->sql_field_metatype($table, $k) == 'B') {
  810. // we skip the field in the regular INSERT statement, it is only in blobfields
  811. $blobfields[$this->quoteFieldNames($k)] = $v;
  812. } elseif (!$this->runningNative() && $this->sql_field_metatype($table, $k) == 'XL') {
  813. // we skip the field in the regular INSERT statement, it is only in clobfields
  814. $clobfields[$this->quoteFieldNames($k)] = $v;
  815. } else {
  816. // Add slashes old-school:
  817. // cast numerical values
  818. $mt = $this->sql_field_metatype($table, $k);
  819. if ($mt{0} == 'I') {
  820. $v = (int)$v;
  821. } else if ($mt{0} == 'F') {
  822. $v = (double)$v;
  823. }
  824. $nArr[$this->quoteFieldNames($k)] = (!in_array($k,$no_quote_fields)) ? $this->fullQuoteStr($v, $table) : $v;
  825. }
  826. }
  827. if (count($blobfields) || count($clobfields)) {
  828. if (count($nArr)) {
  829. $query[0] = 'INSERT INTO ' . $this->quoteFromTables($table) . '
  830. (
  831. ' . implode(',
  832. ', array_keys($nArr)) . '
  833. ) VALUES (
  834. ' . implode(',
  835. ', $nArr) . '
  836. )';
  837. }
  838. if (count($blobfields)) $query[1] = $blobfields;
  839. if (count($clobfields)) $query[2] = $clobfields;
  840. if ($this->debugOutput || $this->store_lastBuiltQuery) $this->debug_lastBuiltQuery = $query[0];
  841. } else {
  842. $query = 'INSERT INTO '.$this->quoteFromTables($table).'
  843. (
  844. ' . implode(',
  845. ', array_keys($nArr)) . '
  846. ) VALUES (
  847. ' . implode(',
  848. ', $nArr) . '
  849. )';
  850. if ($this->debugOutput || $this->store_lastBuiltQuery) $this->debug_lastBuiltQuery = $query;
  851. }
  852. return $query;
  853. }
  854. }
  855. /**
  856. * Creates an INSERT SQL-statement for $table with multiple rows.
  857. * This method will create multiple INSERT queries concatenated with ';'
  858. *
  859. * @param string Table name
  860. * @param array Field names
  861. * @param array Table rows. Each row should be an array with field values mapping to $fields
  862. * @param string/array See fullQuoteArray()
  863. * @return array Full SQL query for INSERT as array of strings (unless $fields_values does not contain any elements in which case it will be FALSE). If BLOB fields will be affected and one is not running the native type, an array will be returned for each row, where 0 => plain SQL, 1 => fieldname/value pairs of BLOB fields.
  864. */
  865. public function INSERTmultipleRows($table, array $fields, array $rows, $no_quote_fields = FALSE) {
  866. if ((string)$this->handlerCfg[$this->lastHandlerKey]['type'] === 'native') {
  867. return parent::INSERTmultipleRows($table, $fields, $rows, $no_quote_fields);
  868. }
  869. $result = array();
  870. foreach ($rows as $row) {
  871. $fields_values = array();
  872. foreach ($fields as $key => $value) {
  873. $fields_values[$value] = $row[$key];
  874. }
  875. $rowQuery = $this->INSERTquery($table, $fields_values, $no_quote_fields);
  876. if (is_array($rowQuery)) {
  877. $result[] = $rowQuery;
  878. } else {
  879. $result[][0] = $rowQuery;
  880. }
  881. }
  882. return $result;
  883. }
  884. /**
  885. * Creates an UPDATE SQL-statement for $table where $where-clause (typ. 'uid=...') from the array with field/value pairs $fields_values.
  886. * Usage count/core: 6
  887. *
  888. * @param string See exec_UPDATEquery()
  889. * @param string See exec_UPDATEquery()
  890. * @param array See exec_UPDATEquery()
  891. * @param mixed See exec_UPDATEquery()
  892. * @return mixed Full SQL query for UPDATE as string or array (unless $fields_values does not contain any elements in which case it will be FALSE). If BLOB fields will be affected and one is not running the native type, an array will be returned, where 0 => plain SQL, 1 => fieldname/value pairs of BLOB fields
  893. */
  894. public function UPDATEquery($table, $where, $fields_values, $no_quote_fields = '') {
  895. // Table and fieldnames should be "SQL-injection-safe" when supplied to this function (contrary to values in the arrays which may be insecure).
  896. if (is_string($where)) {
  897. $fields = array();
  898. $blobfields = array();
  899. $clobfields = array();
  900. if (is_array($fields_values) && count($fields_values)) {
  901. if (is_string($no_quote_fields)) {
  902. $no_quote_fields = explode(',', $no_quote_fields);
  903. } elseif (!is_array($no_quote_fields)) {
  904. $no_quote_fields = array();
  905. }
  906. $nArr = array();
  907. foreach ($fields_values as $k => $v) {
  908. if (!$this->runningNative() && $this->sql_field_metatype($table, $k) == 'B') {
  909. // we skip the field in the regular UPDATE statement, it is only in blobfields
  910. $blobfields[$this->quoteFieldNames($k)] = $v;
  911. } elseif (!$this->runningNative() && $this->sql_field_metatype($table, $k) == 'XL') {
  912. // we skip the field in the regular UPDATE statement, it is only in clobfields
  913. $clobfields[$this->quoteFieldNames($k)] = $v;
  914. } else {
  915. // Add slashes old-school:
  916. // cast numeric values
  917. $mt = $this->sql_field_metatype($table, $k);
  918. if ($mt{0} == 'I') {
  919. $v = (int)$v;
  920. } else if ($mt{0} == 'F') {
  921. $v = (double)$v;
  922. }
  923. $nArr[] = $this->quoteFieldNames($k) . '=' . ((!in_array($k, $no_quote_fields)) ? $this->fullQuoteStr($v, $table) : $v);
  924. }
  925. }
  926. }
  927. if (count($blobfields) || count($clobfields)) {
  928. if (count($nArr)) {
  929. $query[0] = 'UPDATE ' . $this->quoteFromTables($table) . '
  930. SET
  931. ' . implode(',
  932. ', $nArr) .
  933. (strlen($where) > 0 ? '
  934. WHERE
  935. ' . $this->quoteWhereClause($where) : '');
  936. }
  937. if (count($blobfields)) {
  938. $query[1] = $blobfields;
  939. }
  940. if (count($clobfields)) {
  941. $query[2] = $clobfields;
  942. }
  943. if ($this->debugOutput || $this->store_lastBuiltQuery) {
  944. $this->debug_lastBuiltQuery = $query[0];
  945. }
  946. } else {
  947. $query = 'UPDATE ' . $this->quoteFromTables($table) . '
  948. SET
  949. ' . implode(',
  950. ', $nArr) .
  951. (strlen($where) > 0 ? '
  952. WHERE
  953. ' . $this->quoteWhereClause($where) : '');
  954. if ($this->debugOutput || $this->store_lastBuiltQuery) {
  955. $this->debug_lastBuiltQuery = $query;
  956. }
  957. }
  958. return $query;
  959. } else {
  960. throw new InvalidArgumentException(
  961. 'TYPO3 Fatal Error: "Where" clause argument for UPDATE query was not a string in $this->UPDATEquery() !',
  962. 1270853880
  963. );
  964. }
  965. }
  966. /**
  967. * Creates a DELETE SQL-statement for $table where $where-clause
  968. * Usage count/core: 3
  969. *
  970. * @param string See exec_DELETEquery()
  971. * @param string See exec_DELETEquery()
  972. * @return string Full SQL query for DELETE
  973. */
  974. public function DELETEquery($table, $where) {
  975. if (is_string($where)) {
  976. $table = $this->quoteFromTables($table);
  977. $where = $this->quoteWhereClause($where);
  978. $query = parent::DELETEquery($table, $where);
  979. if ($this->debugOutput || $this->store_lastBuiltQuery) $this->debug_lastBuiltQuery = $query;
  980. return $query;
  981. } else {
  982. die('<strong>TYPO3 Fatal Error:</strong> "Where" clause argument for DELETE query was not a string in $this->DELETEquery() !');
  983. }
  984. }
  985. /**
  986. * Creates a SELECT SQL-statement
  987. * Usage count/core: 11
  988. *
  989. * @param string See exec_SELECTquery()
  990. * @param string See exec_SELECTquery()
  991. * @param string See exec_SELECTquery()
  992. * @param string See exec_SELECTquery()
  993. * @param string See exec_SELECTquery()
  994. * @param string See exec_SELECTquery()
  995. * @return string Full SQL query for SELECT
  996. */
  997. public function SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '') {
  998. $this->lastHandlerKey = $this->handler_getFromTableList($from_table);
  999. $hType = (string)$this->handlerCfg[$this->lastHandlerKey]['type'];
  1000. if ($hType === 'adodb' && $this->runningADOdbDriver('postgres')) {
  1001. // Possibly rewrite the LIMIT to be PostgreSQL-compatible
  1002. $splitLimit = t3lib_div::intExplode(',', $limit); // Splitting the limit values:
  1003. if ($splitLimit[1]) { // If there are two parameters, do mapping differently than otherwise:
  1004. $numrows = $splitLimit[1];
  1005. $offset = $splitLimit[0];
  1006. $limit = $numrows . ' OFFSET ' . $offset;
  1007. }
  1008. }
  1009. $select_fields = $this->quoteFieldNames($select_fields);
  1010. $from_table = $this->quoteFromTables($from_table);
  1011. $where_clause = $this->quoteWhereClause($where_clause);
  1012. $groupBy = $this->quoteGroupBy($groupBy);
  1013. $orderBy = $this->quoteOrderBy($orderBy);
  1014. // Call parent method to build actual query
  1015. $query = parent::SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit);
  1016. if ($this->debugOutput || $this->store_lastBuiltQuery) $this->debug_lastBuiltQuery = $query;
  1017. return $query;
  1018. }
  1019. /**
  1020. * Creates a TRUNCATE TABLE SQL-statement
  1021. *
  1022. * @param string See exec_TRUNCATEquery()
  1023. * @return string Full SQL query for TRUNCATE TABLE
  1024. */
  1025. public function TRUNCATEquery($table) {
  1026. $table = $this->quoteFromTables($table);
  1027. // Call parent method to build actual query
  1028. $query = parent::TRUNCATEquery($table);
  1029. if ($this->debugOutput || $this->store_lastBuiltQuery) {
  1030. $this->debug_lastBuiltQuery = $query;
  1031. }
  1032. return $query;
  1033. }
  1034. /**************************************
  1035. *
  1036. * Functions for quoting table/field names
  1037. *
  1038. **************************************/
  1039. /**
  1040. * Quotes components of a SELECT subquery.
  1041. *
  1042. * @param array $components Array of SQL query components
  1043. * @return array
  1044. */
  1045. protected function quoteSELECTsubquery(array $components) {
  1046. $components['SELECT'] = $this->_quoteFieldNames($components['SELECT']);
  1047. $components['FROM'] = $this->_quoteFromTables($components['FROM']);
  1048. $components['WHERE'] = $this->_quoteWhereClause($components['WHERE']);
  1049. return $components;
  1050. }
  1051. /**
  1052. * Quotes field (and table) names with the quote character suitable for the DB being used
  1053. * Use quoteFieldNames instead!
  1054. *
  1055. * @param string List of fields to be selected from DB
  1056. * @return string Quoted list of fields to be selected from DB
  1057. * @deprecated since TYPO3 4.0
  1058. */
  1059. public function quoteSelectFields($select_fields) {
  1060. $this->quoteFieldNames($select_fields);
  1061. }
  1062. /**
  1063. * Quotes field (and table) names with the quote character suitable for the DB being used
  1064. *
  1065. * @param string List of fields to be used in query to DB
  1066. * @return string Quoted list of fields to be in query to DB
  1067. */
  1068. public function quoteFieldNames($select_fields) {
  1069. if ($select_fields == '') return '';
  1070. if ($this->runningNative()) return $select_fields;
  1071. $select_fields = $this->SQLparser->parseFieldList($select_fields);
  1072. if ($this->SQLparser->parse_error) {
  1073. die($this->SQLparser->parse_error . ' in ' . __FILE__ . ' : ' . __LINE__);
  1074. }
  1075. $select_fields = $this->_quoteFieldNames($select_fields);
  1076. return $this->SQLparser->compileFieldList($select_fields);
  1077. }
  1078. /**
  1079. * Quotes field (and table) names in a SQL SELECT clause acccording to DB rules
  1080. *
  1081. * @param array $select_fields The parsed fields to quote
  1082. * @return array
  1083. * @see quoteFieldNames()
  1084. */
  1085. protected function _quoteFieldNames(array $select_fields) {
  1086. foreach ($select_fields as $k => $v) {
  1087. if ($select_fields[$k]['field'] != '' && $select_fields[$k]['field'] != '*' && !is_numeric($select_fields[$k]['field'])) {
  1088. $select_fields[$k]['field'] = $this->quoteName($select_fields[$k]['field']);
  1089. }
  1090. if ($select_fields[$k]['table'] != '' && !is_numeric($select_fields[$k]['table'])) {
  1091. $select_fields[$k]['table'] = $this->quoteName($select_fields[$k]['table']);
  1092. }
  1093. if ($select_fields[$k]['as'] != '') {
  1094. $select_fields[$k]['as'] = $this->quoteName($select_fields[$k]['as']);
  1095. }
  1096. if (isset($select_fields[$k]['func_content.']) && $select_fields[$k]['func_content.'][0]['func_content'] != '*'){
  1097. $select_fields[$k]['func_content.'][0]['func_content'] = $this->quoteFieldNames($select_fields[$k]['func_content.'][0]['func_content']);
  1098. $select_fields[$k]['func_content'] = $this->quoteFieldNames($select_fields[$k]['func_content']);
  1099. }
  1100. if (isset($select_fields[$k]['flow-control'])) {
  1101. // Quoting flow-control statements
  1102. if ($select_fields[$k]['flow-control']['type'] === 'CASE') {
  1103. if (isset($select_fields[$k]['flow-control']['case_field'])) {
  1104. $select_fields[$k]['flow-control']['case_field'] = $this->quoteFieldNames($select_fields[$k]['flow-control']['case_field']);
  1105. }
  1106. foreach ($select_fields[$k]['flow-control']['when'] as $key => $when) {
  1107. $select_fields[$k]['flow-control']['when'][$key]['when_value'] = $this->_quoteWhereClause($when['when_value']);
  1108. }
  1109. }
  1110. }
  1111. }
  1112. return $select_fields;
  1113. }
  1114. /**
  1115. * Quotes table names with the quote character suitable for the DB being used
  1116. *
  1117. * @param string List of tables to be selected from DB
  1118. * @return string Quoted list of tables to be selected from DB
  1119. */
  1120. public function quoteFromTables($from_table) {
  1121. if ($from_table == '') return '';
  1122. if ($this->runningNative()) return $from_table;
  1123. $from_table = $this->SQLparser->parseFromTables($from_table);
  1124. $from_table = $this->_quoteFromTables($from_table);
  1125. return $this->SQLparser->compileFromTables($from_table);
  1126. }
  1127. /**
  1128. * Quotes table names in a SQL FROM clause acccording to DB rules
  1129. *
  1130. * @param array $from_table The parsed FROM clause to quote
  1131. * @return array
  1132. * @see quoteFromTables()
  1133. */
  1134. protected function _quoteFromTables(array $from_table) {
  1135. foreach ($from_table as $k => $v) {
  1136. $from_table[$k]['table'] = $this->quoteName($from_table[$k]['table']);
  1137. if ($from_table[$k]['as'] != '') {
  1138. $from_table[$k]['as'] = $this->quoteName($from_table[$k]['as']);
  1139. }
  1140. if (is_array($v['JOIN'])) {
  1141. foreach ($v['JOIN'] as $joinCnt => $join) {
  1142. $from_table[$k]['JOIN'][$joinCnt]['withTable'] = $this->quoteName($join['withTable']);
  1143. $from_table[$k]['JOIN'][$joinCnt]['as'] = ($join['as']) ? $this->quoteName($join['as']) : '';
  1144. foreach ($from_table[$k]['JOIN'][$joinCnt]['ON'] as &$condition) {
  1145. $condition['left']['table'] = ($condition['left']['table']) ? $this->quoteName($condition['left']['table']) : '';
  1146. $condition['left']['field'] = $this->quoteName($condition['left']['field']);
  1147. $condition['right']['table'] = ($condition['right'

Large files files are truncated, but you can click here to view the full file