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