Disabling some or all controls in group field - controllable via pageTS
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_sqlengine.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2004-2008 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 */
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 ?>