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