|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 2004-2009 Kasper Skårhøj (kasperYYYY@typo3.com) 00006 * (c) 2004-2009 Karsten Dambekalns <karsten@typo3.org> 00007 * (c) 2009-2010 Xavier Perseguers <typo3@perseguers.ch> 00008 * All rights reserved 00009 * 00010 * This script is part of the TYPO3 project. The TYPO3 project is 00011 * free software; you can redistribute it and/or modify 00012 * it under the terms of the GNU General Public License as published by 00013 * the Free Software Foundation; either version 2 of the License, or 00014 * (at your option) any later version. 00015 * 00016 * The GNU General Public License can be found at 00017 * http://www.gnu.org/copyleft/gpl.html. 00018 * A copy is found in the textfile GPL.txt and important notices to the license 00019 * from the author is found in LICENSE.txt distributed with these scripts. 00020 * 00021 * 00022 * This script is distributed in the hope that it will be useful, 00023 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00025 * GNU General Public License for more details. 00026 * 00027 * This copyright notice MUST APPEAR in all copies of the script! 00028 ***************************************************************/ 00029 /** 00030 * PHP SQL engine 00031 * 00032 * $Id: class.ux_t3lib_sqlparser.php 42538 2011-01-24 15:04:19Z xperseguers $ 00033 * 00034 * @author Kasper Skårhøj <kasperYYYY@typo3.com> 00035 * @author Karsten Dambekalns <k.dambekalns@fishfarm.de> 00036 * @author Xavier Perseguers <typo3@perseguers.ch> 00037 */ 00038 00039 00040 /** 00041 * PHP SQL engine / server 00042 * 00043 * @author Kasper Skårhøj <kasper@typo3.com> 00044 * @package TYPO3 00045 * @subpackage t3lib 00046 */ 00047 class ux_t3lib_sqlparser extends t3lib_sqlparser { 00048 00049 /** 00050 * Compiles a "SELECT [output] FROM..:" field list based on input array (made with ->parseFieldList()) 00051 * Can also compile field lists for ORDER BY and GROUP BY. 00052 * 00053 * @param array Array of select fields, (made with ->parseFieldList()) 00054 * @param boolean Whether comments should be compiled 00055 * @param boolean Whether function mapping should take place 00056 * @return string Select field string 00057 * @see parseFieldList() 00058 */ 00059 public function compileFieldList($selectFields, $compileComments = TRUE, $functionMapping = TRUE) { 00060 switch ((string) $GLOBALS['TYPO3_DB']->handlerCfg[$GLOBALS['TYPO3_DB']->lastHandlerKey]['type']) { 00061 case 'native': 00062 $output = parent::compileFieldList($selectFields, $compileComments); 00063 break; 00064 case 'adodb': 00065 $output = ''; 00066 // Traverse the selectFields if any: 00067 if (is_array($selectFields)) { 00068 $outputParts = array(); 00069 foreach ($selectFields as $k => $v) { 00070 00071 // Detecting type: 00072 switch ($v['type']) { 00073 case 'function': 00074 $outputParts[$k] = $v['function'] . '(' . $v['func_content'] . ')'; 00075 break; 00076 case 'flow-control': 00077 if ($v['flow-control']['type'] === 'CASE') { 00078 $outputParts[$k] = $this->compileCaseStatement($v['flow-control'], $functionMapping); 00079 } 00080 break; 00081 case 'field': 00082 $outputParts[$k] = ($v['distinct'] ? $v['distinct'] : '') . ($v['table'] ? $v['table'] . '.' : '') . $v['field']; 00083 break; 00084 } 00085 00086 // Alias: 00087 if ($v['as']) { 00088 $outputParts[$k] .= ' ' . $v['as_keyword'] . ' ' . $v['as']; 00089 } 00090 00091 // Specifically for ORDER BY and GROUP BY field lists: 00092 if ($v['sortDir']) { 00093 $outputParts[$k] .= ' ' . $v['sortDir']; 00094 } 00095 } 00096 // TODO: Handle SQL hints in comments according to current DBMS 00097 if ( /* $compileComments */ 00098 FALSE && $selectFields[0]['comments']) { 00099 $output = $selectFields[0]['comments'] . ' '; 00100 } 00101 $output .= implode(', ', $outputParts); 00102 } 00103 break; 00104 } 00105 return $output; 00106 } 00107 00108 /** 00109 * Compiles a CASE ... WHEN flow-control construct based on input array (made with ->parseCaseStatement()) 00110 * 00111 * @param array Array of case components, (made with ->parseCaseStatement()) 00112 * @param boolean Whether function mapping should take place 00113 * @return string case when string 00114 * @see parseCaseStatement() 00115 */ 00116 protected function compileCaseStatement(array $components, $functionMapping = TRUE) { 00117 switch ((string) $GLOBALS['TYPO3_DB']->handlerCfg[$GLOBALS['TYPO3_DB']->lastHandlerKey]['type']) { 00118 case 'native': 00119 $output = parent::compileCaseStatement($components); 00120 break; 00121 case 'adodb': 00122 $statement = 'CASE'; 00123 if (isset($components['case_field'])) { 00124 $statement .= ' ' . $components['case_field']; 00125 } elseif (isset($components['case_value'])) { 00126 $statement .= ' ' . $components['case_value'][1] . $components['case_value'][0] . $components['case_value'][1]; 00127 } 00128 foreach ($components['when'] as $when) { 00129 $statement .= ' WHEN '; 00130 $statement .= $this->compileWhereClause($when['when_value'], $functionMapping); 00131 $statement .= ' THEN '; 00132 $statement .= $when['then_value'][1] . $when['then_value'][0] . $when['then_value'][1]; 00133 } 00134 if (isset($components['else'])) { 00135 $statement .= ' ELSE '; 00136 $statement .= $components['else'][1] . $components['else'][0] . $components['else'][1]; 00137 } 00138 $statement .= ' END'; 00139 $output = $statement; 00140 break; 00141 } 00142 return $output; 00143 } 00144 00145 /** 00146 * Add slashes function used for compiling queries 00147 * This method overrides the method from t3lib_sqlparser because 00148 * the input string is already properly escaped. 00149 * 00150 * @param string Input string 00151 * @return string Output string 00152 */ 00153 protected function compileAddslashes($str) { 00154 return $str; 00155 } 00156 00157 /************************* 00158 * 00159 * Compiling queries 00160 * 00161 *************************/ 00162 00163 /** 00164 * Compiles an INSERT statement from components array 00165 * 00166 * @param array Array of SQL query components 00167 * @return string SQL INSERT query / array 00168 * @see parseINSERT() 00169 */ 00170 protected function compileINSERT($components) { 00171 switch ((string) $GLOBALS['TYPO3_DB']->handlerCfg[$GLOBALS['TYPO3_DB']->lastHandlerKey]['type']) { 00172 case 'native': 00173 $query = parent::compileINSERT($components); 00174 break; 00175 case 'adodb': 00176 $values = array(); 00177 00178 if (isset($components['VALUES_ONLY']) && is_array($components['VALUES_ONLY'])) { 00179 $valuesComponents = $components['EXTENDED'] === '1' ? $components['VALUES_ONLY'] : array($components['VALUES_ONLY']); 00180 $tableFields = array_keys($GLOBALS['TYPO3_DB']->cache_fieldType[$components['TABLE']]); 00181 } else { 00182 $valuesComponents = $components['EXTENDED'] === '1' ? $components['FIELDS'] : array($components['FIELDS']); 00183 $tableFields = array_keys($valuesComponents[0]); 00184 } 00185 00186 foreach ($valuesComponents as $valuesComponent) { 00187 $fields = array(); 00188 $fc = 0; 00189 foreach ($valuesComponent as $fV) { 00190 $fields[$tableFields[$fc++]] = $fV[0]; 00191 } 00192 $values[] = $fields; 00193 } 00194 $query = count($values) === 1 ? $values[0] : $values; 00195 break; 00196 } 00197 00198 return $query; 00199 } 00200 00201 /** 00202 * Compiles a DROP TABLE statement from components array 00203 * 00204 * @param array Array of SQL query components 00205 * @return string SQL DROP TABLE query 00206 * @see compileSQL() 00207 */ 00208 private function compileDROPTABLE($components) { 00209 switch ((string) $GLOBALS['TYPO3_DB']->handlerCfg[$GLOBALS['TYPO3_DB']->lastHandlerKey]['type']) { 00210 case 'native': 00211 $query = 'DROP TABLE' . ($components['ifExists'] ? ' IF EXISTS' : '') . ' ' . $components['TABLE']; 00212 break; 00213 case 'adodb': 00214 $handlerKey = $GLOBALS['TYPO3_DB']->handler_getFromTableList($components['TABLE']); 00215 $tableName = $GLOBALS['TYPO3_DB']->quoteName($components['TABLE'], $handlerKey, TRUE); 00216 $query = $GLOBALS['TYPO3_DB']->handlerInstance[$handlerKey]->DataDictionary->DropTableSQL($tableName); 00217 break; 00218 } 00219 00220 return $query; 00221 } 00222 00223 /** 00224 * Compiles a CREATE TABLE statement from components array 00225 * 00226 * @param array Array of SQL query components 00227 * @return array array with SQL CREATE TABLE/INDEX command(s) 00228 * @see parseCREATETABLE() 00229 */ 00230 public function compileCREATETABLE($components) { 00231 // Execute query (based on handler derived from the TABLE name which we actually know for once!) 00232 switch ((string) $GLOBALS['TYPO3_DB']->handlerCfg[$GLOBALS['TYPO3_DB']->handler_getFromTableList($components['TABLE'])]['type']) { 00233 case 'native': 00234 $query[] = parent::compileCREATETABLE($components); 00235 break; 00236 case 'adodb': 00237 // Create fields and keys: 00238 $fieldsKeys = array(); 00239 $indexKeys = array(); 00240 00241 foreach ($components['FIELDS'] as $fN => $fCfg) { 00242 $handlerKey = $GLOBALS['TYPO3_DB']->handler_getFromTableList($components['TABLE']); 00243 $fieldsKeys[$fN] = $GLOBALS['TYPO3_DB']->quoteName($fN, $handlerKey, TRUE) . ' ' . $this->compileFieldCfg($fCfg['definition']); 00244 } 00245 00246 if (isset($components['KEYS']) && is_array($components['KEYS'])) { 00247 foreach ($components['KEYS'] as $kN => $kCfg) { 00248 if ($kN === 'PRIMARYKEY') { 00249 foreach ($kCfg as $n => $field) { 00250 $fieldsKeys[$field] .= ' PRIMARY'; 00251 } 00252 } elseif ($kN === 'UNIQUE') { 00253 foreach ($kCfg as $n => $field) { 00254 $indexKeys = array_merge($indexKeys, $GLOBALS['TYPO3_DB']->handlerInstance[$GLOBALS['TYPO3_DB']->handler_getFromTableList($components['TABLE'])]->DataDictionary->CreateIndexSQL($n, $components['TABLE'], $field, array('UNIQUE'))); 00255 } 00256 } else { 00257 $indexKeys = array_merge($indexKeys, $GLOBALS['TYPO3_DB']->handlerInstance[$GLOBALS['TYPO3_DB']->handler_getFromTableList($components['TABLE'])]->DataDictionary->CreateIndexSQL($components['TABLE'] . '_' . $kN, $components['TABLE'], $kCfg)); 00258 } 00259 } 00260 } 00261 00262 // Generally create without OID on PostgreSQL 00263 $tableOptions = array('postgres' => 'WITHOUT OIDS'); 00264 00265 // Fetch table/index generation query: 00266 $tableName = $GLOBALS['TYPO3_DB']->quoteName($components['TABLE'], NULL, TRUE); 00267 $query = array_merge($GLOBALS['TYPO3_DB']->handlerInstance[$GLOBALS['TYPO3_DB']->lastHandlerKey]->DataDictionary->CreateTableSQL($tableName, implode(',' . chr(10), $fieldsKeys), $tableOptions), $indexKeys); 00268 break; 00269 } 00270 00271 return $query; 00272 } 00273 00274 /** 00275 * Compiles an ALTER TABLE statement from components array 00276 * 00277 * @param array Array of SQL query components 00278 * @return string SQL ALTER TABLE query 00279 * @see parseALTERTABLE() 00280 */ 00281 public function compileALTERTABLE($components) { 00282 // Execute query (based on handler derived from the TABLE name which we actually know for once!) 00283 switch ((string) $GLOBALS['TYPO3_DB']->handlerCfg[$GLOBALS['TYPO3_DB']->lastHandlerKey]['type']) { 00284 case 'native': 00285 $query[] = parent::compileALTERTABLE($components); 00286 break; 00287 case 'adodb': 00288 $tableName = $GLOBALS['TYPO3_DB']->quoteName($components['TABLE'], NULL, TRUE); 00289 $fieldName = $GLOBALS['TYPO3_DB']->quoteName($components['FIELD'], NULL, TRUE); 00290 switch (strtoupper(str_replace(array(' ', "\n", "\r", "\t"), '', $components['action']))) { 00291 case 'ADD': 00292 $query = $GLOBALS['TYPO3_DB']->handlerInstance[$GLOBALS['TYPO3_DB']->lastHandlerKey]->DataDictionary->AddColumnSQL($tableName, $fieldName . ' ' . $this->compileFieldCfg($components['definition'])); 00293 break; 00294 case 'CHANGE': 00295 $query = $GLOBALS['TYPO3_DB']->handlerInstance[$GLOBALS['TYPO3_DB']->lastHandlerKey]->DataDictionary->AlterColumnSQL($tableName, $fieldName . ' ' . $this->compileFieldCfg($components['definition'])); 00296 break; 00297 case 'DROP': 00298 case 'DROPKEY': 00299 break; 00300 case 'ADDKEY': 00301 case 'ADDPRIMARYKEY': 00302 case 'ADDUNIQUE': 00303 $query .= ' (' . implode(',', $components['fields']) . ')'; 00304 break; 00305 case 'DEFAULTCHARACTERSET': 00306 case 'ENGINE': 00307 // ??? todo! 00308 break; 00309 } 00310 break; 00311 } 00312 00313 return $query; 00314 } 00315 00316 /** 00317 * Compile field definition 00318 * 00319 * @param array Field definition parts 00320 * @return string Field definition string 00321 */ 00322 public function compileFieldCfg($fieldCfg) { 00323 switch ((string) $GLOBALS['TYPO3_DB']->handlerCfg[$GLOBALS['TYPO3_DB']->lastHandlerKey]['type']) { 00324 case 'native': 00325 $cfg = parent::compileFieldCfg($fieldCfg); 00326 break; 00327 case 'adodb': 00328 // Set type: 00329 $type = $GLOBALS['TYPO3_DB']->MySQLMetaType($fieldCfg['fieldType']); 00330 $cfg = $type; 00331 00332 // Add value, if any: 00333 if (strlen($fieldCfg['value']) && (in_array($type, array('C', 'C2')))) { 00334 $cfg .= ' ' . $fieldCfg['value']; 00335 } elseif (!isset($fieldCfg['value']) && (in_array($type, array('C', 'C2')))) { 00336 $cfg .= ' 255'; // add 255 as length for varchar without specified length (e.g. coming from tinytext, tinyblob) 00337 } 00338 00339 // Add additional features: 00340 $noQuote = TRUE; 00341 if (is_array($fieldCfg['featureIndex'])) { 00342 00343 // MySQL assigns DEFAULT value automatically if NOT NULL, fake this here 00344 // numeric fields get 0 as default, other fields an empty string 00345 if (isset($fieldCfg['featureIndex']['NOTNULL']) && !isset($fieldCfg['featureIndex']['DEFAULT']) && !isset($fieldCfg['featureIndex']['AUTO_INCREMENT'])) { 00346 switch ($type) { 00347 case 'I8': 00348 case 'F': 00349 case 'N': 00350 $fieldCfg['featureIndex']['DEFAULT'] = array('keyword' => 'DEFAULT', 'value' => array('0', '')); 00351 break; 00352 default: 00353 $fieldCfg['featureIndex']['DEFAULT'] = array('keyword' => 'DEFAULT', 'value' => array('', '\'')); 00354 } 00355 } 00356 00357 foreach ($fieldCfg['featureIndex'] as $feature => $featureDef) { 00358 switch (TRUE) { 00359 // unsigned only for mysql, as it is mysql specific 00360 case ($feature === 'UNSIGNED' && !$GLOBALS['TYPO3_DB']->runningADOdbDriver('mysql')): 00361 // auto_increment is removed, it is handled by (emulated) sequences 00362 case ($feature === 'AUTO_INCREMENT'): 00363 // never add NOT NULL if running on Oracle and we have an empty string as default 00364 case ($feature === 'NOTNULL' && $GLOBALS['TYPO3_DB']->runningADOdbDriver('oci8')): 00365 continue; 00366 case ($feature === 'NOTNULL'): 00367 $cfg .= ' NOTNULL'; 00368 break; 00369 default: 00370 $cfg .= ' ' . $featureDef['keyword']; 00371 } 00372 00373 // Add value if found: 00374 if (is_array($featureDef['value'])) { 00375 if ($featureDef['value'][0] === '') { 00376 $cfg .= ' "\'\'"'; 00377 } else { 00378 $cfg .= ' ' . $featureDef['value'][1] . $this->compileAddslashes($featureDef['value'][0]) . $featureDef['value'][1]; 00379 if (!is_numeric($featureDef['value'][0])) { 00380 $noQuote = FALSE; 00381 } 00382 } 00383 } 00384 } 00385 } 00386 if ($noQuote) { 00387 $cfg .= ' NOQUOTE'; 00388 } 00389 break; 00390 } 00391 00392 // Return field definition string: 00393 return $cfg; 00394 } 00395 00396 /** 00397 * Checks if the submitted feature index contains a default value definition and the default value 00398 * 00399 * @param array $featureIndex A feature index as produced by parseFieldDef() 00400 * @return boolean 00401 * @see t3lib_sqlparser::parseFieldDef() 00402 */ 00403 public function checkEmptyDefaultValue($featureIndex) { 00404 if (is_array($featureIndex['DEFAULT']['value'])) { 00405 if (!is_numeric($featureIndex['DEFAULT']['value'][0]) && empty($featureIndex['DEFAULT']['value'][0])) { 00406 return TRUE; 00407 } else { 00408 return FALSE; 00409 } 00410 } 00411 return TRUE; 00412 } 00413 00414 /** 00415 * Implodes an array of WHERE clause configuration into a WHERE clause. 00416 * 00417 * DBAL-specific: The only(!) handled "calc" operators supported by parseWhereClause() are: 00418 * - the bitwise logical and (&) 00419 * - the addition (+) 00420 * - the substraction (-) 00421 * - the multiplication (*) 00422 * - the division (/) 00423 * - the modulo (%) 00424 * 00425 * @param array WHERE clause configuration 00426 * @return string WHERE clause as string. 00427 * @see t3lib_sqlparser::parseWhereClause() 00428 */ 00429 public function compileWhereClause($clauseArray, $functionMapping = TRUE) { 00430 switch ((string) $GLOBALS['TYPO3_DB']->handlerCfg[$GLOBALS['TYPO3_DB']->lastHandlerKey]['type']) { 00431 case 'native': 00432 $output = parent::compileWhereClause($clauseArray); 00433 break; 00434 case 'adodb': 00435 // Prepare buffer variable: 00436 $output = ''; 00437 00438 // Traverse clause array: 00439 if (is_array($clauseArray)) { 00440 foreach ($clauseArray as $k => $v) { 00441 00442 // Set operator: 00443 $output .= $v['operator'] ? ' ' . $v['operator'] : ''; 00444 00445 // Look for sublevel: 00446 if (is_array($v['sub'])) { 00447 $output .= ' (' . trim($this->compileWhereClause($v['sub'], $functionMapping)) . ')'; 00448 } elseif (isset($v['func']) && $v['func']['type'] === 'EXISTS') { 00449 $output .= ' ' . trim($v['modifier']) . ' EXISTS (' . $this->compileSELECT($v['func']['subquery']) . ')'; 00450 } else { 00451 00452 if (isset($v['func']) && $v['func']['type'] === 'LOCATE') { 00453 $output .= ' ' . trim($v['modifier']); 00454 switch (TRUE) { 00455 case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('mssql') && $functionMapping): 00456 $output .= ' CHARINDEX('; 00457 $output .= $v['func']['substr'][1] . $v['func']['substr'][0] . $v['func']['substr'][1]; 00458 $output .= ', ' . ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field']; 00459 $output .= isset($v['func']['pos']) ? ', ' . $v['func']['pos'][0] : ''; 00460 $output .= ')'; 00461 break; 00462 case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('oci8') && $functionMapping): 00463 $output .= ' INSTR('; 00464 $output .= ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field']; 00465 $output .= ', ' . $v['func']['substr'][1] . $v['func']['substr'][0] . $v['func']['substr'][1]; 00466 $output .= isset($v['func']['pos']) ? ', ' . $v['func']['pos'][0] : ''; 00467 $output .= ')'; 00468 break; 00469 default: 00470 $output .= ' LOCATE('; 00471 $output .= $v['func']['substr'][1] . $v['func']['substr'][0] . $v['func']['substr'][1]; 00472 $output .= ', ' . ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field']; 00473 $output .= isset($v['func']['pos']) ? ', ' . $v['func']['pos'][0] : ''; 00474 $output .= ')'; 00475 break; 00476 } 00477 } elseif (isset($v['func']) && $v['func']['type'] === 'IFNULL') { 00478 $output .= ' ' . trim($v['modifier']) . ' '; 00479 switch (TRUE) { 00480 case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('mssql') && $functionMapping): 00481 $output .= 'ISNULL'; 00482 break; 00483 case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('oci8') && $functionMapping): 00484 $output .= 'NVL'; 00485 break; 00486 default: 00487 $output .= 'IFNULL'; 00488 break; 00489 } 00490 $output .= '('; 00491 $output .= ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field']; 00492 $output .= ', ' . $v['func']['default'][1] . $this->compileAddslashes($v['func']['default'][0]) . $v['func']['default'][1]; 00493 $output .= ')'; 00494 } elseif (isset($v['func']) && $v['func']['type'] === 'FIND_IN_SET') { 00495 $output .= ' ' . trim($v['modifier']) . ' '; 00496 if ($functionMapping) { 00497 switch (TRUE) { 00498 case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('mssql')): 00499 $field = ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field']; 00500 if (!isset($v['func']['str_like'])) { 00501 $v['func']['str_like'] = $v['func']['str'][0]; 00502 } 00503 $output .= '\',\'+' . $field . '+\',\' LIKE \'%,' . $v['func']['str_like'] . ',%\''; 00504 break; 00505 case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('oci8')): 00506 $field = ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field']; 00507 if (!isset($v['func']['str_like'])) { 00508 $v['func']['str_like'] = $v['func']['str'][0]; 00509 } 00510 $output .= '\',\'||' . $field . '||\',\' LIKE \'%,' . $v['func']['str_like'] . ',%\''; 00511 break; 00512 case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('postgres')): 00513 $output .= ' FIND_IN_SET('; 00514 $output .= $v['func']['str'][1] . $v['func']['str'][0] . $v['func']['str'][1]; 00515 $output .= ', ' . ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field']; 00516 $output .= ') != 0'; 00517 break; 00518 default: 00519 $field = ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field']; 00520 if (!isset($v['func']['str_like'])) { 00521 $v['func']['str_like'] = $v['func']['str'][0]; 00522 } 00523 $output .= '(' 00524 . $field . ' LIKE \'%,' . $v['func']['str_like'] . ',%\'' 00525 . ' OR ' . $field . ' LIKE \'' . $v['func']['str_like'] . ',%\'' 00526 . ' OR ' . $field . ' LIKE \'%,' . $v['func']['str_like'] . '\'' 00527 . ' OR ' . $field . '= ' . $v['func']['str'][1] . $v['func']['str'][0] . $v['func']['str'][1] 00528 . ')'; 00529 break; 00530 } 00531 } else /* !$functionMapping */ { 00532 switch (TRUE) { 00533 case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('mssql')): 00534 case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('oci8')): 00535 case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('postgres')): 00536 $output .= ' FIND_IN_SET('; 00537 $output .= $v['func']['str'][1] . $v['func']['str'][0] . $v['func']['str'][1]; 00538 $output .= ', ' . ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field']; 00539 $output .= ')'; 00540 break; 00541 default: 00542 $field = ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field']; 00543 if (!isset($v['func']['str_like'])) { 00544 $v['func']['str_like'] = $v['func']['str'][0]; 00545 } 00546 $output .= '(' 00547 . $field . ' LIKE \'%,' . $v['func']['str_like'] . ',%\'' 00548 . ' OR ' . $field . ' LIKE \'' . $v['func']['str_like'] . ',%\'' 00549 . ' OR ' . $field . ' LIKE \'%,' . $v['func']['str_like'] . '\'' 00550 . ' OR ' . $field . '= ' . $v['func']['str'][1] . $v['func']['str'][0] . $v['func']['str'][1] 00551 . ')'; 00552 break; 00553 } 00554 } 00555 } else { 00556 00557 // Set field/table with modifying prefix if any: 00558 $output .= ' ' . trim($v['modifier']) . ' '; 00559 00560 // DBAL-specific: Set calculation, if any: 00561 if ($v['calc'] === '&' && $functionMapping) { 00562 switch (TRUE) { 00563 case $GLOBALS['TYPO3_DB']->runningADOdbDriver('oci8'): 00564 // Oracle only knows BITAND(x,y) - sigh 00565 $output .= 'BITAND(' . trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']) . ',' . $v['calc_value'][1] . $this->compileAddslashes($v['calc_value'][0]) . $v['calc_value'][1] . ')'; 00566 break; 00567 default: 00568 // MySQL, MS SQL Server, PostgreSQL support the &-syntax 00569 $output .= trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']) . $v['calc'] . $v['calc_value'][1] . $this->compileAddslashes($v['calc_value'][0]) . $v['calc_value'][1]; 00570 break; 00571 } 00572 } elseif ($v['calc']) { 00573 $output .= trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']) . $v['calc']; 00574 if (isset($v['calc_table'])) { 00575 $output .= trim(($v['calc_table'] ? $v['calc_table'] . '.' : '') . $v['calc_field']); 00576 } else { 00577 $output .= $v['calc_value'][1] . $this->compileAddslashes($v['calc_value'][0]) . $v['calc_value'][1]; 00578 } 00579 } elseif (!($GLOBALS['TYPO3_DB']->runningADOdbDriver('oci8') && preg_match('/(NOT )?LIKE( BINARY)?/', $v['comparator']) && $functionMapping)) { 00580 $output .= trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']); 00581 } 00582 } 00583 00584 // Set comparator: 00585 if ($v['comparator']) { 00586 $isLikeOperator = preg_match('/(NOT )?LIKE( BINARY)?/', $v['comparator']); 00587 switch (TRUE) { 00588 case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('oci8') && $isLikeOperator && $functionMapping): 00589 // Oracle cannot handle LIKE on CLOB fields - sigh 00590 if (isset($v['value']['operator'])) { 00591 $values = array(); 00592 foreach ($v['value']['args'] as $fieldDef) { 00593 $values[] = ($fieldDef['table'] ? $fieldDef['table'] . '.' : '') . $fieldDef['field']; 00594 } 00595 $compareValue = ' ' . $v['value']['operator'] . '(' . implode(',', $values) . ')'; 00596 } else { 00597 $compareValue = $v['value'][1] . $this->compileAddslashes(trim($v['value'][0], '%')) . $v['value'][1]; 00598 } 00599 if (t3lib_div::isFirstPartOfStr($v['comparator'], 'NOT')) { 00600 $output .= 'NOT '; 00601 } 00602 // To be on the safe side 00603 $isLob = TRUE; 00604 if ($v['table']) { 00605 // Table and field names are quoted: 00606 $tableName = substr($v['table'], 1, strlen($v['table']) - 2); 00607 $fieldName = substr($v['field'], 1, strlen($v['field']) - 2); 00608 $fieldType = $GLOBALS['TYPO3_DB']->sql_field_metatype($tableName, $fieldName); 00609 $isLob = ($fieldType === 'B' || $fieldType === 'XL'); 00610 } 00611 if (strtoupper(substr($v['comparator'], -6)) === 'BINARY') { 00612 if ($isLob) { 00613 $output .= '(dbms_lob.instr(' . trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']) . ', ' . $compareValue . ',1,1) > 0)'; 00614 } else { 00615 $output .= '(instr(' . trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']) . ', ' . $compareValue . ',1,1) > 0)'; 00616 } 00617 } else { 00618 if ($isLob) { 00619 $output .= '(dbms_lob.instr(LOWER(' . trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']) . '), ' . t3lib_div::strtolower($compareValue) . ',1,1) > 0)'; 00620 } else { 00621 $output .= '(instr(LOWER(' . trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']) . '), ' . t3lib_div::strtolower($compareValue) . ',1,1) > 0)'; 00622 } 00623 } 00624 break; 00625 default: 00626 if ($isLikeOperator && $functionMapping) { 00627 if ($GLOBALS['TYPO3_DB']->runningADOdbDriver('postgres') || 00628 $GLOBALS['TYPO3_DB']->runningADOdbDriver('postgres64') || 00629 $GLOBALS['TYPO3_DB']->runningADOdbDriver('postgres7') || 00630 $GLOBALS['TYPO3_DB']->runningADOdbDriver('postgres8')) { 00631 00632 // Remap (NOT)? LIKE to (NOT)? ILIKE 00633 // and (NOT)? LIKE BINARY to (NOT)? LIKE 00634 switch ($v['comparator']) { 00635 // Remap (NOT)? LIKE to (NOT)? ILIKE 00636 case 'LIKE': 00637 $v['comparator'] = 'ILIKE'; 00638 break; 00639 case 'NOT LIKE': 00640 $v['comparator'] = 'NOT ILIKE'; 00641 break; 00642 default: 00643 $v['comparator'] = str_replace(' BINARY', '', $v['comparator']); 00644 break; 00645 } 00646 } else { 00647 // No more BINARY operator 00648 $v['comparator'] = str_replace(' BINARY', '', $v['comparator']); 00649 } 00650 } 00651 00652 $output .= ' ' . $v['comparator']; 00653 00654 // Detecting value type; list or plain: 00655 if (t3lib_div::inList('NOTIN,IN', strtoupper(str_replace(array(' ', TAB, CR, LF), '', $v['comparator'])))) { 00656 if (isset($v['subquery'])) { 00657 $output .= ' (' . $this->compileSELECT($v['subquery']) . ')'; 00658 } else { 00659 $valueBuffer = array(); 00660 foreach ($v['value'] as $realValue) { 00661 $valueBuffer[] = $realValue[1] . $this->compileAddslashes($realValue[0]) . $realValue[1]; 00662 } 00663 $output .= ' (' . trim(implode(',', $valueBuffer)) . ')'; 00664 } 00665 } else if (t3lib_div::inList('BETWEEN,NOT BETWEEN', $v['comparator'])) { 00666 $lbound = $v['values'][0]; 00667 $ubound = $v['values'][1]; 00668 $output .= ' ' . $lbound[1] . $this->compileAddslashes($lbound[0]) . $lbound[1]; 00669 $output .= ' AND '; 00670 $output .= $ubound[1] . $this->compileAddslashes($ubound[0]) . $ubound[1]; 00671 } else if (isset($v['value']['operator'])) { 00672 $values = array(); 00673 foreach ($v['value']['args'] as $fieldDef) { 00674 $values[] = ($fieldDef['table'] ? $fieldDef['table'] . '.' : '') . $fieldDef['field']; 00675 } 00676 $output .= ' ' . $v['value']['operator'] . '(' . implode(',', $values) . ')'; 00677 } else { 00678 $output .= ' ' . $v['value'][1] . $this->compileAddslashes($v['value'][0]) . $v['value'][1]; 00679 } 00680 break; 00681 } 00682 } 00683 } 00684 } 00685 } 00686 break; 00687 } 00688 00689 return $output; 00690 } 00691 } 00692 00693 00694 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/dbal/class.ux_t3lib_sqlparser.php'])) { 00695 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/dbal/class.ux_t3lib_sqlparser.php']); 00696 } 00697 00698 ?>
1.8.0