PageRenderTime 62ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

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

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

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