PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/typo3/sysext/dbal/lib/class.tx_dbal_sqlengine.php

https://github.com/andreaswolf/typo3-tceforms
PHP | 855 lines | 366 code | 126 blank | 363 comment | 62 complexity | 8736771bfd106c96b5290aa2d45c664d MD5 | raw file
Possible License(s): Apache-2.0, BSD-2-Clause, LGPL-3.0
  1. <?php
  2. /***************************************************************
  3. * Copyright notice
  4. *
  5. * (c) 2009-2010 Xavier Perseguers <typo3@perseguers.ch>
  6. * (c) 2004-2009 Kasper Skårhøj <kasperYYYY@typo3.com>
  7. * All rights reserved
  8. *
  9. * This script is part of the TYPO3 project. The TYPO3 project is
  10. * free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * The GNU General Public License can be found at
  16. * http://www.gnu.org/copyleft/gpl.html.
  17. * A copy is found in the textfile GPL.txt and important notices to the license
  18. * from the author is found in LICENSE.txt distributed with these scripts.
  19. *
  20. *
  21. * This script is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU General Public License for more details.
  25. *
  26. * This copyright notice MUST APPEAR in all copies of the script!
  27. ***************************************************************/
  28. /**
  29. * PHP SQL engine
  30. *
  31. * $Id: class.tx_dbal_sqlengine.php 40828 2010-12-05 14:55:53Z xperseguers $
  32. *
  33. * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  34. * @author Xavier Perseguers <typo3@perseguers.ch>
  35. */
  36. /**
  37. * [CLASS/FUNCTION INDEX of SCRIPT]
  38. *
  39. *
  40. *
  41. * 106: class tx_dbal_sqlengine extends ux_t3lib_sqlparser
  42. * 128: public function init($config, $pObj)
  43. * 136: public function resetStatusVars()
  44. * 152: private function processAccordingToConfig(&$value, $fInfo)
  45. *
  46. * SECTION: SQL queries
  47. * 207: public function exec_INSERTquery($table, $fields_values)
  48. * 275: public function exec_UPDATEquery($table, $where, $fields_values)
  49. * 334: public function exec_DELETEquery($table, $where)
  50. * 385: public function exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit)
  51. * 428: public function sql_query($query)
  52. * 439: public function sql_error()
  53. * 448: public function sql_insert_id()
  54. * 457: public function sql_affected_rows()
  55. * 467: public function quoteStr($str)
  56. *
  57. * SECTION: SQL admin functions
  58. * 493: public function admin_get_tables()
  59. * 504: public function admin_get_fields($tableName)
  60. * 515: public function admin_get_keys($tableName)
  61. * 526: public function admin_query($query)
  62. *
  63. * SECTION: Data Source I/O
  64. * 551: public function readDataSource($table)
  65. * 563: public function saveDataSource($table)
  66. *
  67. * SECTION: SQL engine functions (PHP simulation of SQL) - still experimental
  68. * 593: public function selectFromData($table, $where)
  69. * 631: public function select_evalSingle($table,$config,&$itemKeys)
  70. * 750: public function getResultSet($keys, $table, $fieldList)
  71. *
  72. * SECTION: Debugging
  73. * 793: public function debug_printResultSet($array)
  74. *
  75. *
  76. * 832: class tx_dbal_sqlengine_resultobj
  77. * 846: public function sql_num_rows()
  78. * 855: public function sql_fetch_assoc()
  79. * 866: public function sql_fetch_row()
  80. * 884: public function sql_data_seek($pointer)
  81. * 897: public function sql_field_type()
  82. *
  83. * TOTAL FUNCTIONS: 27
  84. * (This index is automatically created/updated by the extension "extdeveval")
  85. *
  86. */
  87. /**
  88. * PHP SQL engine / server
  89. * Basically this is trying to emulation SQL record selection by PHP, thus allowing SQL queries into alternative data storages managed by PHP.
  90. * EXPERIMENTAL!
  91. *
  92. * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  93. * @package TYPO3
  94. * @subpackage t3lib
  95. */
  96. class tx_dbal_sqlengine extends ux_t3lib_sqlparser {
  97. // array with data records: [table name][num.index] = records
  98. var $data = array(); // Data source storage
  99. // Internal, SQL Status vars:
  100. var $errorStatus = ''; // Set with error message of last operation
  101. var $lastInsertedId = 0; // Set with last inserted unique ID
  102. var $lastAffectedRows = 0; // Set with last number of affected rows.
  103. /**
  104. * Dummy function for initializing SQL handler. Create you own in derived classes.
  105. *
  106. * @param array Configuration array from handler
  107. * @param object Parent object
  108. * @return void
  109. */
  110. public function init($config, $pObj) {
  111. }
  112. /**
  113. * Reset SQL engine status variables (insert id, affected rows, error status)
  114. *
  115. * @return void
  116. */
  117. public function resetStatusVars() {
  118. $this->errorStatus = '';
  119. $this->lastInsertedId = 0;
  120. $this->lastAffectedRows = 0;
  121. }
  122. /**
  123. * Processing of update/insert values based on field type.
  124. *
  125. * The input value is typecast and trimmed/shortened according to the field
  126. * type and the configuration options from the $fInfo parameter.
  127. *
  128. * @param mixed $value The input value to process
  129. * @param array $fInfo Field configuration data
  130. * @return mixed The processed input value
  131. */
  132. private function processAccordingToConfig(&$value, $fInfo) {
  133. $options = $this->parseFieldDef($fInfo['Type']);
  134. switch (strtolower($options['fieldType'])) {
  135. case 'int':
  136. case 'smallint':
  137. case 'tinyint':
  138. case 'mediumint':
  139. $value = intval($value);
  140. if ($options['featureIndex']['UNSIGNED']) {
  141. $value = t3lib_div::intInRange($value, 0);
  142. }
  143. break;
  144. case 'double':
  145. $value = (double) $value;
  146. break;
  147. case 'varchar':
  148. case 'char':
  149. $value = substr($value, 0, trim($options['value']));
  150. break;
  151. case 'text':
  152. case 'blob':
  153. $value = substr($value, 0, 65536);
  154. break;
  155. case 'tinytext':
  156. case 'tinyblob':
  157. $value = substr($value, 0, 256);
  158. break;
  159. case 'mediumtext':
  160. case 'mediumblob':
  161. // ??
  162. break;
  163. }
  164. }
  165. /********************************
  166. *
  167. * SQL queries
  168. * This is the SQL access functions used when this class is instantiated as a SQL handler with DBAL. Override these in derived classes.
  169. *
  170. ********************************/
  171. /**
  172. * Execute an INSERT query
  173. *
  174. * @param string Table name
  175. * @param array Field values as key=>value pairs.
  176. * @return boolean TRUE on success and FALSE on failure (error is set internally)
  177. */
  178. public function exec_INSERTquery($table, $fields_values) {
  179. // Initialize
  180. $this->resetStatusVars();
  181. // Reading Data Source if not done already.
  182. $this->readDataSource($table);
  183. // If data source is set:
  184. if (is_array($this->data[$table])) {
  185. $fieldInformation = $this->admin_get_fields($table); // Should cache this...!
  186. // Looking for unique keys:
  187. $saveArray = array();
  188. foreach ($fieldInformation as $fInfo) {
  189. // Field name:
  190. $fN = $fInfo['Field'];
  191. // Set value:
  192. // FIXME $options not defined
  193. $saveArray[$fN] = isset($fields_values[$fN]) ? $fields_values[$fN] : $options['Default'];
  194. // Process value:
  195. $this->processAccordingToConfig($saveArray[$fN], $fInfo);
  196. // If an auto increment field is found, find the largest current uid:
  197. if ($fInfo['Extra'] == 'auto_increment') {
  198. // Get all UIDs:
  199. $uidArray = array();
  200. foreach ($this->data[$table] as $r) {
  201. $uidArray[] = $r[$fN];
  202. }
  203. // If current value is blank or already in array, we create a new:
  204. if (!$saveArray[$fN] || in_array(intval($saveArray[$fN]), $uidArray)) {
  205. if (count($uidArray)) {
  206. $saveArray[$fN] = max($uidArray) + 1;
  207. } else $saveArray[$fN] = 1;
  208. }
  209. // Update "last inserted id":
  210. $this->lastInsertedId = $saveArray[$fN];
  211. }
  212. }
  213. // Insert row in table:
  214. $this->data[$table][] = $saveArray;
  215. // Save data source
  216. $this->saveDataSource($table);
  217. return TRUE;
  218. } else $this->errorStatus = 'No data loaded.';
  219. return FALSE;
  220. }
  221. /**
  222. * Execute UPDATE query on table
  223. *
  224. * @param string Table name
  225. * @param string WHERE clause
  226. * @param array Field values as key=>value pairs.
  227. * @return boolean TRUE on success and FALSE on failure (error is set internally)
  228. */
  229. public function exec_UPDATEquery($table, $where, $fields_values) {
  230. // Initialize:
  231. $this->resetStatusVars();
  232. // Reading Data Source if not done already.
  233. $this->readDataSource($table);
  234. // If anything is there:
  235. if (is_array($this->data[$table])) {
  236. // Parse WHERE clause:
  237. $where = $this->parseWhereClause($where);
  238. if (is_array($where)) {
  239. // Field information
  240. $fieldInformation = $this->admin_get_fields($table); // Should cache this...!
  241. // Traverse fields to update:
  242. foreach ($fields_values as $fName => $fValue) {
  243. $this->processAccordingToConfig($fields_values[$fName], $fieldInformation[$fName]);
  244. }
  245. // Do query, returns array with keys to the data array of the result:
  246. $itemKeys = $this->selectFromData($table, $where);
  247. // Set "last affected rows":
  248. $this->lastAffectedRows = count($itemKeys);
  249. // Update rows:
  250. if ($this->lastAffectedRows) {
  251. // Traverse result set here:
  252. foreach ($itemKeys as $dataArrayKey) {
  253. // Traverse fields to update:
  254. foreach ($fields_values as $fName => $fValue) {
  255. $this->data[$table][$dataArrayKey][$fName] = $fValue;
  256. }
  257. }
  258. // Save data source
  259. $this->saveDataSource($table);
  260. }
  261. return TRUE;
  262. } else $this->errorStatus = 'WHERE clause contained errors: ' . $where;
  263. } else $this->errorStatus = 'No data loaded.';
  264. return FALSE;
  265. }
  266. /**
  267. * Execute DELETE query
  268. *
  269. * @param string Table to delete from
  270. * @param string WHERE clause
  271. * @return boolean TRUE on success and FALSE on failure (error is set internally)
  272. */
  273. public function exec_DELETEquery($table, $where) {
  274. // Initialize:
  275. $this->resetStatusVars();
  276. // Reading Data Source if not done already.
  277. $this->readDataSource($table);
  278. // If anything is there:
  279. if (is_array($this->data[$table])) {
  280. // Parse WHERE clause:
  281. $where = $this->parseWhereClause($where);
  282. if (is_array($where)) {
  283. // Do query, returns array with keys to the data array of the result:
  284. $itemKeys = $this->selectFromData($table, $where);
  285. // Set "last affected rows":
  286. $this->lastAffectedRows = count($itemKeys);
  287. // Remove rows:
  288. if ($this->lastAffectedRows) {
  289. // Traverse result set:
  290. foreach ($itemKeys as $dataArrayKey) {
  291. unset($this->data[$table][$dataArrayKey]);
  292. }
  293. // Saving data source
  294. $this->saveDataSource($table);
  295. }
  296. return TRUE;
  297. } else $this->errorStatus = 'WHERE clause contained errors: ' . $where;
  298. } else $this->errorStatus = 'No data loaded.';
  299. return FALSE;
  300. }
  301. /**
  302. * Execute SELECT query
  303. *
  304. * @param string List of fields to select from the table. This is what comes right after "SELECT ...". Required value.
  305. * @param string Table(s) from which to select. This is what comes right after "FROM ...". Required value.
  306. * @param string Optional additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself! DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
  307. * @param string Optional GROUP BY field(s), if none, supply blank string.
  308. * @param string Optional ORDER BY field(s), if none, supply blank string.
  309. * @param string Optional LIMIT value ([begin,]max), if none, supply blank string.
  310. * @return object Returns result object, but if errors, returns false
  311. */
  312. public function exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit) {
  313. // Initialize:
  314. $this->resetStatusVars();
  315. // Create result object
  316. $sqlObj = t3lib_div::makeInstance('tx_dbal_sqlengine_resultobj');
  317. $sqlObj->result = array(); // Empty result as a beginning
  318. // Get table list:
  319. $tableArray = $this->parseFromTables($from_table);
  320. $table = $tableArray[0]['table'];
  321. // Reading Data Source if not done already.
  322. $this->readDataSource($table);
  323. // If anything is there:
  324. if (is_array($this->data[$table])) {
  325. // Parse WHERE clause:
  326. $where = $this->parseWhereClause($where_clause);
  327. if (is_array($where)) {
  328. // Do query, returns array with keys to the data array of the result:
  329. $itemKeys = $this->selectFromData($table, $where);
  330. // Finally, read the result rows into this variable:
  331. $sqlObj->result = $this->getResultSet($itemKeys, $table, '*');
  332. // Reset and return result:
  333. reset($sqlObj->result);
  334. return $sqlObj;
  335. } else $this->errorStatus = 'WHERE clause contained errors: ' . $where;
  336. } else $this->errorStatus = 'No data loaded: ' . $this->errorStatus;
  337. return FALSE;
  338. }
  339. /**
  340. * Performs an SQL query on the "database"
  341. *
  342. * @param string Query to execute
  343. * @return object Result object or false if error
  344. */
  345. public function sql_query($query) {
  346. $res = t3lib_div::makeInstance('tx_dbal_sqlengine_resultobj');
  347. $res->result = array();
  348. return $res;
  349. }
  350. /**
  351. * Returns most recent error
  352. *
  353. * @return string Error message, if any
  354. */
  355. public function sql_error() {
  356. return $this->errorStatus;
  357. }
  358. /**
  359. * Returns most recently create unique ID (of INSERT queries)
  360. *
  361. * @return integer Last unique id created.
  362. */
  363. public function sql_insert_id() {
  364. return $this->lastInsertedId;
  365. }
  366. /**
  367. * Returns affected rows (of UPDATE and DELETE queries)
  368. *
  369. * @return integer Last amount of affected rows.
  370. */
  371. public function sql_affected_rows() {
  372. return $this->lastAffectedRows;
  373. }
  374. /**
  375. * Quoting strings for insertion in SQL queries
  376. *
  377. * @param string Input String
  378. * @return string String, with quotes escaped
  379. */
  380. public function quoteStr($str) {
  381. return addslashes($str);
  382. }
  383. /**************************************
  384. *
  385. * SQL admin functions
  386. * (For use in the Install Tool and Extension Manager)
  387. *
  388. **************************************/
  389. /**
  390. * (DUMMY) Returns the list of tables from the database
  391. *
  392. * @return array Tables in an array (tablename is in both key and value)
  393. * @todo Should return table details in value! see t3lib_db::admin_get_tables()
  394. */
  395. public function admin_get_tables() {
  396. $whichTables = array();
  397. return $whichTables;
  398. }
  399. /**
  400. * (DUMMY) Returns information about each field in the $table
  401. *
  402. * @param string Table name
  403. * @return array Field information in an associative array with fieldname => field row
  404. */
  405. public function admin_get_fields($tableName) {
  406. $output = array();
  407. return $output;
  408. }
  409. /**
  410. * (DUMMY) Returns information about each index key in the $table
  411. *
  412. * @param string Table name
  413. * @return array Key information in a numeric array
  414. */
  415. public function admin_get_keys($tableName) {
  416. $output = array();
  417. return $output;
  418. }
  419. /**
  420. * (DUMMY) mysql() wrapper function, used by the Install Tool and EM for all queries regarding management of the database!
  421. *
  422. * @param string Query to execute
  423. * @return pointer Result pointer
  424. */
  425. public function admin_query($query) {
  426. return $this->sql_query($query);
  427. }
  428. /********************************
  429. *
  430. * Data Source I/O
  431. *
  432. ********************************/
  433. /**
  434. * Dummy function for setting table data. Create your own.
  435. * NOTICE: Handler to "table-locking" needs to be made probably!
  436. *
  437. * @param string Table name
  438. * @return void
  439. * @todo Table locking tools?
  440. */
  441. public function readDataSource($table) {
  442. $this->data[$table] = array();
  443. }
  444. /**
  445. * Dummy function for setting table data. Create your own.
  446. * NOTICE: Handler to "table-locking" needs to be made probably!
  447. *
  448. * @param string Table name
  449. * @return void
  450. * @todo Table locking tools?
  451. */
  452. public function saveDataSource($table) {
  453. debug($this->data[$table]);
  454. }
  455. /********************************
  456. *
  457. * SQL engine functions (PHP simulation of SQL) - still experimental
  458. *
  459. ********************************/
  460. /**
  461. * PHP simulation of SQL "SELECT"
  462. * Yet EXPERIMENTAL!
  463. *
  464. * @param string Table name
  465. * @param array Where clause parsed into array
  466. * @return array Array of keys pointing to result rows in $this->data[$table]
  467. */
  468. public function selectFromData($table, $where) {
  469. $output = array();
  470. if (is_array($this->data[$table])) {
  471. // All keys:
  472. $OR_index = 0;
  473. foreach ($where as $config) {
  474. if (strtoupper($config['operator']) == 'OR') {
  475. $OR_index++;
  476. }
  477. // FIXME: unknown variable $itemKeys
  478. if (!isset($itemKeys[$OR_index])) $itemKeys[$OR_index] = array_keys($this->data[$table]);
  479. $this->select_evalSingle($table, $config, $itemKeys[$OR_index]);
  480. }
  481. foreach ($itemKeys as $uidKeys) {
  482. $output = array_merge($output, $uidKeys);
  483. }
  484. $output = array_unique($output);
  485. }
  486. return $output;
  487. }
  488. /**
  489. * Evalutaion of a WHERE-clause-array.
  490. * Yet EXPERIMENTAL
  491. *
  492. * @param string Tablename
  493. * @param array WHERE-configuration array
  494. * @param array Data array to work on.
  495. * @return void Data array passed by reference
  496. * @see selectFromData()
  497. */
  498. public function select_evalSingle($table, $config, &$itemKeys) {
  499. $neg = preg_match('/^AND[[:space:]]+NOT$/', trim($config['operator']));
  500. if (is_array($config['sub'])) {
  501. $subSelKeys = $this->selectFromData($table, $config['sub']);
  502. if ($neg) {
  503. foreach ($itemKeys as $kk => $vv) {
  504. if (in_array($vv, $subSelKeys)) {
  505. unset($itemKeys[$kk]);
  506. }
  507. }
  508. } else {
  509. $itemKeys = array_intersect($itemKeys, $subSelKeys);
  510. }
  511. } else {
  512. $comp = strtoupper(str_replace(array(' ', "\t", "\r", "\n"), '', $config['comparator']));
  513. $mod = strtoupper($config['modifier']);
  514. switch ($comp) {
  515. case 'NOTLIKE':
  516. case 'LIKE':
  517. $like_value = strtolower($config['value'][0]);
  518. if (substr($like_value, 0, 1) == '%') {
  519. $wildCard_begin = TRUE;
  520. $like_value = substr($like_value, 1);
  521. }
  522. if (substr($like_value, -1) == '%') {
  523. $wildCard_end = TRUE;
  524. $like_value = substr($like_value, 0, -1);
  525. }
  526. break;
  527. case 'NOTIN':
  528. case 'IN':
  529. $in_valueArray = array();
  530. foreach ($config['value'] as $vParts) {
  531. $in_valueArray[] = (string) $vParts[0];
  532. }
  533. break;
  534. }
  535. foreach ($itemKeys as $kk => $v) {
  536. $field_value = $this->data[$table][$v][$config['field']];
  537. // Calculate it:
  538. if ($config['calc'] == '&') {
  539. $field_value &= intval($config['calc_value']);
  540. }
  541. // Compare it:
  542. switch ($comp) {
  543. case '<=':
  544. $bool = $field_value <= $config['value'][0];
  545. break;
  546. case '>=':
  547. $bool = $field_value >= $config['value'][0];
  548. break;
  549. case '<':
  550. $bool = $field_value < $config['value'][0];
  551. break;
  552. case '>':
  553. $bool = $field_value > $config['value'][0];
  554. break;
  555. case '=':
  556. $bool = !strcmp($field_value, $config['value'][0]);
  557. break;
  558. case '!=':
  559. $bool = strcmp($field_value, $config['value'][0]);
  560. break;
  561. case 'NOTIN':
  562. case 'IN':
  563. $bool = in_array((string) $field_value, $in_valueArray);
  564. if ($comp == 'NOTIN') $bool = !$bool;
  565. break;
  566. case 'NOTLIKE':
  567. case 'LIKE':
  568. if (!strlen($like_value)) {
  569. $bool = TRUE;
  570. } elseif ($wildCard_begin && !$wildCard_end) {
  571. $bool = !strcmp(substr(strtolower($field_value), -strlen($like_value)), $like_value);
  572. } elseif (!$wildCard_begin && $wildCard_end) {
  573. $bool = !strcmp(substr(strtolower($field_value), 0, strlen($like_value)), $like_value);
  574. } elseif ($wildCard_begin && $wildCard_end) {
  575. $bool = strstr($field_value, $like_value);
  576. } else {
  577. $bool = !strcmp(strtolower($field_value), $like_value);
  578. }
  579. if ($comp == 'NOTLIKE') $bool = !$bool;
  580. break;
  581. default:
  582. $bool = $field_value ? TRUE : FALSE;
  583. break;
  584. }
  585. // General negation:
  586. if ($neg) $bool = !$bool;
  587. // Modify?
  588. switch ($mod) {
  589. case 'NOT':
  590. case '!':
  591. $bool = !$bool;
  592. break;
  593. }
  594. // Action:
  595. if (!$bool) {
  596. unset($itemKeys[$kk]);
  597. }
  598. }
  599. }
  600. }
  601. /**
  602. * Returning result set based on result keys, table and field list
  603. *
  604. * @param array Result keys
  605. * @param string Tablename
  606. * @param string Fieldlist (commaseparated)
  607. * @return array Result array with "rows"
  608. */
  609. public function getResultSet($keys, $table, $fieldList) {
  610. $fields = t3lib_div::trimExplode(',', $fieldList);
  611. $output = array();
  612. foreach ($keys as $kValue) {
  613. if ($fieldList == '*') {
  614. $output[$kValue] = $this->data[$table][$kValue];
  615. } else {
  616. foreach ($fields as $fieldName) {
  617. $output[$kValue][$fieldName] = $this->data[$table][$kValue][$fieldName];
  618. }
  619. }
  620. }
  621. return $output;
  622. }
  623. /*************************
  624. *
  625. * Debugging
  626. *
  627. *************************/
  628. /**
  629. * Returns the result set (in array) as HTML table. For debugging.
  630. *
  631. * @param array Result set array (array of rows)
  632. * @return string HTML table
  633. */
  634. public function debug_printResultSet($array) {
  635. if (count($array)) {
  636. $tRows = array();
  637. $fields = array_keys(current($array));
  638. $tCell[] = '
  639. <td>IDX</td>';
  640. foreach ($fields as $fieldName) {
  641. $tCell[] = '
  642. <td>' . htmlspecialchars($fieldName) . '</td>';
  643. }
  644. $tRows[] = '<tr>' . implode('', $tCell) . '</tr>';
  645. foreach ($array as $index => $rec) {
  646. $tCell = array();
  647. $tCell[] = '
  648. <td>' . htmlspecialchars($index) . '</td>';
  649. foreach ($fields as $fieldName) {
  650. $tCell[] = '
  651. <td>' . htmlspecialchars($rec[$fieldName]) . '</td>';
  652. }
  653. $tRows[] = '<tr>' . implode('', $tCell) . '</tr>';
  654. }
  655. return '<table border="1">' . implode('', $tRows) . '</table>';
  656. } else 'Empty resultset';
  657. }
  658. }
  659. /**
  660. * PHP SQL engine, result object
  661. *
  662. * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  663. * @package TYPO3
  664. * @subpackage dbal
  665. */
  666. class tx_dbal_sqlengine_resultobj {
  667. // Result array, must contain the fields in the order they were selected in the SQL statement (for sql_fetch_row())
  668. var $result = array();
  669. var $TYPO3_DBAL_handlerType = '';
  670. var $TYPO3_DBAL_tableList = '';
  671. /**
  672. * Counting number of rows
  673. *
  674. * @return integer
  675. */
  676. public function sql_num_rows() {
  677. return count($this->result);
  678. }
  679. /**
  680. * Fetching next row in result array
  681. *
  682. * @return array Associative array
  683. */
  684. public function sql_fetch_assoc() {
  685. $row = current($this->result);
  686. next($this->result);
  687. return $row;
  688. }
  689. /**
  690. * Fetching next row, numerical indices
  691. *
  692. * @return array Numerical array
  693. */
  694. public function sql_fetch_row() {
  695. $resultRow = $this->sql_fetch_assoc();
  696. if (is_array($resultRow)) {
  697. $numArray = array();
  698. foreach ($resultRow as $value) {
  699. $numArray[] = $value;
  700. }
  701. return $numArray;
  702. }
  703. }
  704. /**
  705. * Seeking position in result
  706. *
  707. * @param integer Position pointer.
  708. * @return boolean Returns true on success
  709. */
  710. public function sql_data_seek($pointer) {
  711. reset($this->result);
  712. for ($a = 0; $a < $pointer; $a++) {
  713. next($this->result);
  714. }
  715. return TRUE;
  716. }
  717. /**
  718. * Returning SQL field type
  719. *
  720. * @return string Blank string, not supported (it seems)
  721. */
  722. public function sql_field_type() {
  723. return '';
  724. }
  725. }
  726. if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/dbal/lib/class.tx_dbal_sqlengine.php'])) {
  727. include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/dbal/lib/class.tx_dbal_sqlengine.php']);
  728. }
  729. ?>