TYPO3 CMS  TYPO3_7-6
Adodb.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
20 
24 class Adodb extends AbstractCompiler
25 {
33  protected function compileINSERT($components)
34  {
35  $values = [];
36  if (isset($components['VALUES_ONLY']) && is_array($components['VALUES_ONLY'])) {
37  $valuesComponents = $components['EXTENDED'] === '1' ? $components['VALUES_ONLY'] : [$components['VALUES_ONLY']];
38  $tableFields = array_keys($this->databaseConnection->cache_fieldType[$components['TABLE']]);
39  } else {
40  $valuesComponents = $components['EXTENDED'] === '1' ? $components['FIELDS'] : [$components['FIELDS']];
41  $tableFields = array_keys($valuesComponents[0]);
42  }
43  foreach ($valuesComponents as $valuesComponent) {
44  $fields = [];
45  $fc = 0;
46  foreach ($valuesComponent as $fV) {
47  $fields[$tableFields[$fc++]] = $fV[0];
48  }
49  $values[] = $fields;
50  }
51  return count($values) === 1 ? $values[0] : $values;
52  }
53 
61  protected function compileCREATETABLE($components)
62  {
63  // Create fields and keys:
64  $fieldsKeys = [];
65  $indexKeys = [];
66  foreach ($components['FIELDS'] as $fN => $fCfg) {
67  $handlerKey = $this->databaseConnection->handler_getFromTableList($components['TABLE']);
68  $fieldsKeys[$fN] = $this->databaseConnection->quoteName($fN, $handlerKey, true) . ' ' . $this->compileFieldCfg($fCfg['definition']);
69  }
70  if (isset($components['KEYS']) && is_array($components['KEYS'])) {
71  foreach ($components['KEYS'] as $kN => $kCfg) {
72  if ($kN === 'PRIMARYKEY') {
73  foreach ($kCfg as $field) {
74  $fieldsKeys[$field] .= ' PRIMARY';
75  }
76  } elseif ($kN === 'UNIQUE') {
77  foreach ($kCfg as $n => $field) {
78  $indexKeys = array_merge($indexKeys, $this->compileCREATEINDEX($n, $components['TABLE'], $field, ['UNIQUE']));
79  }
80  } else {
81  $indexKeys = array_merge($indexKeys, $this->compileCREATEINDEX($kN, $components['TABLE'], $kCfg));
82  }
83  }
84  }
85  // Generally create without OID on PostgreSQL
86  $tableOptions = ['postgres' => 'WITHOUT OIDS'];
87  // Fetch table/index generation query:
88  $tableName = $this->databaseConnection->quoteName($components['TABLE'], null, true);
89  $query = array_merge($this->databaseConnection->handlerInstance[$this->databaseConnection->lastHandlerKey]->DataDictionary->CreateTableSQL($tableName, implode(',' . LF, $fieldsKeys), $tableOptions), $indexKeys);
90  return $query;
91  }
92 
100  protected function compileALTERTABLE($components)
101  {
102  $query = '';
103  $tableName = $this->databaseConnection->quoteName($components['TABLE'], null, true);
104  $fieldName = $this->databaseConnection->quoteName($components['FIELD'], null, true);
105  switch (strtoupper(str_replace([' ', "\n", "\r", "\t"], '', $components['action']))) {
106  case 'ADD':
107  $query = $this->databaseConnection->handlerInstance[$this->databaseConnection->lastHandlerKey]->DataDictionary->AddColumnSQL($tableName, $fieldName . ' ' . $this->compileFieldCfg($components['definition']));
108  break;
109  case 'CHANGE':
110  $query = $this->databaseConnection->handlerInstance[$this->databaseConnection->lastHandlerKey]->DataDictionary->AlterColumnSQL($tableName, $fieldName . ' ' . $this->compileFieldCfg($components['definition']));
111  break;
112  case 'RENAME':
113  $query = $this->databaseConnection->handlerInstance[$this->databaseConnection->lastHandlerKey]->DataDictionary->RenameTableSQL($tableName, $fieldName);
114  break;
115  case 'DROP':
116 
117  case 'DROPKEY':
118  $query = $this->compileDROPINDEX($components['KEY'], $components['TABLE']);
119  break;
120 
121  case 'ADDKEY':
122  $query = $this->compileCREATEINDEX($components['KEY'], $components['TABLE'], $components['fields']);
123  break;
124  case 'ADDUNIQUE':
125  $query = $this->compileCREATEINDEX($components['KEY'], $components['TABLE'], $components['fields'], ['UNIQUE']);
126  break;
127  case 'ADDPRIMARYKEY':
128  // @todo ???
129  break;
130  case 'DEFAULTCHARACTERSET':
131 
132  case 'ENGINE':
133  // @todo ???
134  break;
135  }
136  return $query;
137  }
138 
152  protected function compileCREATEINDEX($indexName, $tableName, $indexFields, $indexOptions = [])
153  {
154  $indexIdentifier = $this->databaseConnection->quoteName(hash('crc32b', $tableName) . '_' . $indexName, null, true);
155  $dbmsSpecifics = $this->databaseConnection->getSpecifics();
156  $keepFieldLengths = $dbmsSpecifics->specificExists(Specifics\AbstractSpecifics::PARTIAL_STRING_INDEX) && $dbmsSpecifics->getSpecific(Specifics\AbstractSpecifics::PARTIAL_STRING_INDEX);
157 
158  foreach ($indexFields as $key => $fieldName) {
159  if (!$keepFieldLengths) {
160  $fieldName = preg_replace('/\A([^\(]+)(\(\d+\))/', '\\1', $fieldName);
161  }
162  // Quote the fieldName in backticks with escaping, ADOdb will replace the backticks with the correct quoting
163  $indexFields[$key] = '`' . str_replace('`', '``', $fieldName) . '`';
164  }
165 
166  return $this->databaseConnection->handlerInstance[$this->databaseConnection->handler_getFromTableList($tableName)]->DataDictionary->CreateIndexSQL(
167  $indexIdentifier, $this->databaseConnection->quoteName($tableName, null, true), $indexFields, $indexOptions
168  );
169  }
170 
182  protected function compileDROPINDEX($indexName, $tableName)
183  {
184  $indexIdentifier = $this->databaseConnection->quoteName(hash('crc32b', $tableName) . '_' . $indexName, null, true);
185 
186  return $this->databaseConnection->handlerInstance[$this->databaseConnection->handler_getFromTableList($tableName)]->DataDictionary->DropIndexSQL(
187  $indexIdentifier, $this->databaseConnection->quoteName($tableName)
188  );
189  }
190 
201  public function compileFieldList($selectFields, $compileComments = true, $functionMapping = true)
202  {
203  $output = '';
204  // Traverse the selectFields if any:
205  if (is_array($selectFields)) {
206  $outputParts = [];
207  foreach ($selectFields as $k => $v) {
208  // Detecting type:
209  switch ($v['type']) {
210  case 'function':
211  $outputParts[$k] = $v['function'] . '(' . $v['func_content'] . ')';
212  break;
213  case 'flow-control':
214  if ($v['flow-control']['type'] === 'CASE') {
215  $outputParts[$k] = $this->compileCaseStatement($v['flow-control'], $functionMapping);
216  }
217  break;
218  case 'field':
219  $outputParts[$k] = ($v['distinct'] ? $v['distinct'] : '') . ($v['table'] ? $v['table'] . '.' : '') . $v['field'];
220  break;
221  }
222  // Alias:
223  if ($v['as']) {
224  $outputParts[$k] .= ' ' . $v['as_keyword'] . ' ' . $v['as'];
225  }
226  // Specifically for ORDER BY and GROUP BY field lists:
227  if ($v['sortDir']) {
228  $outputParts[$k] .= ' ' . $v['sortDir'];
229  }
230  }
231  // @todo Handle SQL hints in comments according to current DBMS
232  if (false && $selectFields[0]['comments']) {
233  $output = $selectFields[0]['comments'] . ' ';
234  }
235  $output .= implode(', ', $outputParts);
236  }
237  return $output;
238  }
239 
248  protected function compileAddslashes($str)
249  {
250  return $str;
251  }
252 
259  protected function compileFieldCfg($fieldCfg)
260  {
261  // Set type:
262  $type = $this->databaseConnection->getSpecifics()->getMetaFieldType($fieldCfg['fieldType']);
263  $cfg = $type;
264  // Add value, if any:
265  if ((string)$fieldCfg['value'] !== '' && in_array($type, ['C', 'C2'])) {
266  $cfg .= ' ' . $fieldCfg['value'];
267  } elseif (!isset($fieldCfg['value']) && in_array($type, ['C', 'C2'])) {
268  $cfg .= ' 255';
269  }
270  // Add additional features:
271  $noQuote = true;
272  if (is_array($fieldCfg['featureIndex'])) {
273  // MySQL assigns DEFAULT value automatically if NOT NULL, fake this here
274  // numeric fields get 0 as default, other fields an empty string
275  if (isset($fieldCfg['featureIndex']['NOTNULL']) && !isset($fieldCfg['featureIndex']['DEFAULT']) && !isset($fieldCfg['featureIndex']['AUTO_INCREMENT'])) {
276  switch ($type) {
277  case 'I8':
278 
279  case 'F':
280 
281  case 'N':
282  $fieldCfg['featureIndex']['DEFAULT'] = ['keyword' => 'DEFAULT', 'value' => ['0', '']];
283  break;
284  default:
285  $fieldCfg['featureIndex']['DEFAULT'] = ['keyword' => 'DEFAULT', 'value' => ['', '\'']];
286  }
287  }
288  foreach ($fieldCfg['featureIndex'] as $feature => $featureDef) {
289  switch (true) {
290  case $feature === 'UNSIGNED' && !$this->databaseConnection->runningADOdbDriver('mysql'):
291  case $feature === 'NOTNULL' && $this->databaseConnection->runningADOdbDriver('oci8'):
292  continue 2;
293  case $feature === 'AUTO_INCREMENT':
294  $cfg .= ' AUTOINCREMENT';
295  break;
296  case $feature === 'NOTNULL':
297  $cfg .= ' NOTNULL';
298  break;
299  default:
300  $cfg .= ' ' . $featureDef['keyword'];
301  }
302  // Add value if found:
303  if (is_array($featureDef['value'])) {
304  if ($featureDef['value'][0] === '') {
305  $cfg .= ' "\'\'"';
306  } else {
307  $cfg .= ' ' . $featureDef['value'][1] . $this->compileAddslashes($featureDef['value'][0]) . $featureDef['value'][1];
308  if (!is_numeric($featureDef['value'][0])) {
309  $noQuote = false;
310  }
311  }
312  }
313  }
314  }
315  if ($noQuote) {
316  $cfg .= ' NOQUOTE';
317  }
318  // Return field definition string:
319  return $cfg;
320  }
321 
338  public function compileWhereClause($clauseArray, $functionMapping = true)
339  {
340  // Prepare buffer variable:
341  $output = '';
342  // Traverse clause array:
343  if (is_array($clauseArray)) {
344  foreach ($clauseArray as $v) {
345  // Set operator:
346  $output .= $v['operator'] ? ' ' . $v['operator'] : '';
347  // Look for sublevel:
348  if (is_array($v['sub'])) {
349  $output .= ' (' . trim($this->compileWhereClause($v['sub'], $functionMapping)) . ')';
350  } elseif (isset($v['func']) && $v['func']['type'] === 'EXISTS') {
351  $output .= ' ' . trim($v['modifier']) . ' EXISTS (' . $this->compileSELECT($v['func']['subquery']) . ')';
352  } else {
353  if (isset($v['func']) && $v['func']['type'] === 'CAST') {
354  $output .= ' ' . trim($v['modifier']);
355  $output .= ' CAST(';
356  $output .= ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
357  $output .= ' AS ' . $v['func']['datatype'][0] . ')';
358  } elseif (isset($v['func']) && $v['func']['type'] === 'LOCATE') {
359  $output .= ' ' . trim($v['modifier']);
360  switch (true) {
361  case $this->databaseConnection->runningADOdbDriver('mssql') && $functionMapping:
362  $output .= ' CHARINDEX(';
363  $output .= $v['func']['substr'][1] . $v['func']['substr'][0] . $v['func']['substr'][1];
364  $output .= ', ' . ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
365  $output .= isset($v['func']['pos']) ? ', ' . $v['func']['pos'][0] : '';
366  $output .= ')';
367  break;
368  case $this->databaseConnection->runningADOdbDriver('oci8') && $functionMapping:
369  $output .= ' INSTR(';
370  $output .= ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
371  $output .= ', ' . $v['func']['substr'][1] . $v['func']['substr'][0] . $v['func']['substr'][1];
372  $output .= isset($v['func']['pos']) ? ', ' . $v['func']['pos'][0] : '';
373  $output .= ')';
374  break;
375  default:
376  $output .= ' LOCATE(';
377  $output .= $v['func']['substr'][1] . $v['func']['substr'][0] . $v['func']['substr'][1];
378  $output .= ', ' . ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
379  $output .= isset($v['func']['pos']) ? ', ' . $v['func']['pos'][0] : '';
380  $output .= ')';
381  }
382  } elseif (isset($v['func']) && $v['func']['type'] === 'IFNULL') {
383  $output .= ' ' . trim($v['modifier']) . ' ';
384  switch (true) {
385  case $this->databaseConnection->runningADOdbDriver('mssql') && $functionMapping:
386  $output .= 'ISNULL';
387  break;
388  case $this->databaseConnection->runningADOdbDriver('oci8') && $functionMapping:
389  $output .= 'NVL';
390  break;
391  default:
392  $output .= 'IFNULL';
393  }
394  $output .= '(';
395  $output .= ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
396  $output .= ', ' . $v['func']['default'][1] . $this->compileAddslashes($v['func']['default'][0]) . $v['func']['default'][1];
397  $output .= ')';
398  } elseif (isset($v['func']) && $v['func']['type'] === 'FIND_IN_SET') {
399  $output .= ' ' . trim($v['modifier']) . ' ';
400  if ($functionMapping) {
401  switch (true) {
402  case $this->databaseConnection->runningADOdbDriver('mssql'):
403  $field = ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
404  if (!isset($v['func']['str_like'])) {
405  $v['func']['str_like'] = $v['func']['str'][0];
406  }
407  $output .= '\',\'+' . $field . '+\',\' LIKE \'%,' . $v['func']['str_like'] . ',%\'';
408  break;
409  case $this->databaseConnection->runningADOdbDriver('oci8'):
410  $field = ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
411  if (!isset($v['func']['str_like'])) {
412  $v['func']['str_like'] = $v['func']['str'][0];
413  }
414  $output .= '\',\'||' . $field . '||\',\' LIKE \'%,' . $v['func']['str_like'] . ',%\'';
415  break;
416  case $this->databaseConnection->runningADOdbDriver('postgres'):
417  $output .= ' FIND_IN_SET(';
418  $output .= $v['func']['str'][1] . $v['func']['str'][0] . $v['func']['str'][1];
419  $output .= ', ' . ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
420  $output .= ') != 0';
421  break;
422  default:
423  $field = ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
424  if (!isset($v['func']['str_like'])) {
425  $v['func']['str_like'] = $v['func']['str'][0];
426  }
427  $output .= '(' . $field . ' LIKE \'%,' . $v['func']['str_like'] . ',%\'' . ' OR ' . $field . ' LIKE \'' . $v['func']['str_like'] . ',%\'' . ' OR ' . $field . ' LIKE \'%,' . $v['func']['str_like'] . '\'' . ' OR ' . $field . '= ' . $v['func']['str'][1] . $v['func']['str'][0] . $v['func']['str'][1] . ')';
428  }
429  } else {
430  switch (true) {
431  case $this->databaseConnection->runningADOdbDriver('mssql'):
432 
433  case $this->databaseConnection->runningADOdbDriver('oci8'):
434 
435  case $this->databaseConnection->runningADOdbDriver('postgres'):
436  $output .= ' FIND_IN_SET(';
437  $output .= $v['func']['str'][1] . $v['func']['str'][0] . $v['func']['str'][1];
438  $output .= ', ' . ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
439  $output .= ')';
440  break;
441  default:
442  $field = ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
443  if (!isset($v['func']['str_like'])) {
444  $v['func']['str_like'] = $v['func']['str'][0];
445  }
446  $output .= '(' . $field . ' LIKE \'%,' . $v['func']['str_like'] . ',%\'' . ' OR ' . $field . ' LIKE \'' . $v['func']['str_like'] . ',%\'' . ' OR ' . $field . ' LIKE \'%,' . $v['func']['str_like'] . '\'' . ' OR ' . $field . '= ' . $v['func']['str'][1] . $v['func']['str'][0] . $v['func']['str'][1] . ')';
447  }
448  }
449  } else {
450  // Set field/table with modifying prefix if any:
451  $output .= ' ' . trim($v['modifier']) . ' ';
452  // DBAL-specific: Set calculation, if any:
453  if ($v['calc'] === '&' && $functionMapping) {
454  switch (true) {
455  case $this->databaseConnection->runningADOdbDriver('oci8'):
456  // Oracle only knows BITAND(x,y) - sigh
457  $output .= 'BITAND(' . trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']) . ',' . $v['calc_value'][1] . $this->compileAddslashes($v['calc_value'][0]) . $v['calc_value'][1] . ')';
458  break;
459  default:
460  // MySQL, MS SQL Server, PostgreSQL support the &-syntax
461  $output .= trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']) . $v['calc'] . $v['calc_value'][1] . $this->compileAddslashes($v['calc_value'][0]) . $v['calc_value'][1];
462  }
463  } elseif ($v['calc']) {
464  $output .= trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']) . $v['calc'];
465  if (isset($v['calc_table'])) {
466  $output .= trim(($v['calc_table'] ? $v['calc_table'] . '.' : '') . $v['calc_field']);
467  } else {
468  $output .= $v['calc_value'][1] . $this->compileAddslashes($v['calc_value'][0]) . $v['calc_value'][1];
469  }
470  } elseif (!($this->databaseConnection->runningADOdbDriver('oci8') && preg_match('/(NOT )?LIKE( BINARY)?/', $v['comparator']) && $functionMapping)) {
471  $output .= trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']);
472  }
473  }
474  // Set comparator:
475  if ($v['comparator']) {
476  $isLikeOperator = preg_match('/(NOT )?LIKE( BINARY)?/', $v['comparator']);
477  switch (true) {
478  case $this->databaseConnection->runningADOdbDriver('oci8') && $isLikeOperator && $functionMapping:
479  // Oracle cannot handle LIKE on CLOB fields - sigh
480  if (isset($v['value']['operator'])) {
481  $values = [];
482  foreach ($v['value']['args'] as $fieldDef) {
483  $values[] = ($fieldDef['table'] ? $fieldDef['table'] . '.' : '') . $fieldDef['field'];
484  }
485  $compareValue = ' ' . $v['value']['operator'] . '(' . implode(',', $values) . ')';
486  } else {
487  $compareValue = $v['value'][1] . $this->compileAddslashes(trim($v['value'][0], '%')) . $v['value'][1];
488  }
489  if (GeneralUtility::isFirstPartOfStr($v['comparator'], 'NOT')) {
490  $output .= 'NOT ';
491  }
492  // To be on the safe side
493  $isLob = true;
494  if ($v['table']) {
495  // Table and field names are quoted:
496  $tableName = substr($v['table'], 1, strlen($v['table']) - 2);
497  $fieldName = substr($v['field'], 1, strlen($v['field']) - 2);
498  $fieldType = $this->databaseConnection->sql_field_metatype($tableName, $fieldName);
499  $isLob = $fieldType === 'B' || $fieldType === 'XL';
500  }
501  if (strtoupper(substr($v['comparator'], -6)) === 'BINARY') {
502  if ($isLob) {
503  $output .= '(dbms_lob.instr(' . trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']) . ', ' . $compareValue . ',1,1) > 0)';
504  } else {
505  $output .= '(instr(' . trim((($v['table'] ? $v['table'] . '.' : '') . $v['field'])) . ', ' . $compareValue . ',1,1) > 0)';
506  }
507  } else {
508  if ($isLob) {
509  $output .= '(dbms_lob.instr(LOWER(' . trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']) . '), ' . GeneralUtility::strtolower($compareValue) . ',1,1) > 0)';
510  } else {
511  $output .= '(instr(LOWER(' . trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']) . '), ' . GeneralUtility::strtolower($compareValue) . ',1,1) > 0)';
512  }
513  }
514  break;
515  default:
516  if ($isLikeOperator && $functionMapping) {
517  if ($this->databaseConnection->runningADOdbDriver('postgres') || $this->databaseConnection->runningADOdbDriver('postgres64') || $this->databaseConnection->runningADOdbDriver('postgres7') || $this->databaseConnection->runningADOdbDriver('postgres8')) {
518  // Remap (NOT)? LIKE to (NOT)? ILIKE
519  // and (NOT)? LIKE BINARY to (NOT)? LIKE
520  switch ($v['comparator']) {
521  case 'LIKE':
522  $v['comparator'] = 'ILIKE';
523  break;
524  case 'NOT LIKE':
525  $v['comparator'] = 'NOT ILIKE';
526  break;
527  default:
528  $v['comparator'] = str_replace(' BINARY', '', $v['comparator']);
529  }
530  } else {
531  // No more BINARY operator
532  $v['comparator'] = str_replace(' BINARY', '', $v['comparator']);
533  }
534  }
535  $output .= ' ' . $v['comparator'];
536  // Detecting value type; list or plain:
537  $comparator = SqlParser::normalizeKeyword($v['comparator']);
538  if ($comparator === 'NOTIN' || $comparator === 'IN') {
539  if (isset($v['subquery'])) {
540  $output .= ' (' . $this->compileSELECT($v['subquery']) . ')';
541  } else {
542  $valueBuffer = [];
543  foreach ($v['value'] as $realValue) {
544  $valueBuffer[] = $realValue[1] . $this->compileAddslashes($realValue[0]) . $realValue[1];
545  }
546 
547  $dbmsSpecifics = $this->databaseConnection->getSpecifics();
548  if ($dbmsSpecifics === null) {
549  $output .= ' (' . trim(implode(',', $valueBuffer)) . ')';
550  } else {
551  $chunkedList = $dbmsSpecifics->splitMaxExpressions($valueBuffer);
552  $chunkCount = count($chunkedList);
553 
554  if ($chunkCount === 1) {
555  $output .= ' (' . trim(implode(',', $valueBuffer)) . ')';
556  } else {
557  $listExpressions = [];
558  $field = trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']);
559 
560  switch ($comparator) {
561  case 'IN':
562  $operator = 'OR';
563  break;
564  case 'NOTIN':
565  $operator = 'AND';
566  break;
567  default:
568  $operator = '';
569  }
570 
571  for ($i = 0; $i < $chunkCount; ++$i) {
572  $listPart = trim(implode(',', $chunkedList[$i]));
573  $listExpressions[] = ' (' . $listPart . ')';
574  }
575 
576  $implodeString = ' ' . $operator . ' ' . $field . ' ' . $v['comparator'];
577 
578  // add opening brace before field
579  $lastFieldPos = strrpos($output, $field);
580  $output = substr_replace($output, '(', $lastFieldPos, 0);
581  $output .= implode($implodeString, $listExpressions) . ')';
582  }
583  }
584  }
585  } elseif ($comparator === 'BETWEEN' || $comparator === 'NOTBETWEEN') {
586  $lbound = $v['values'][0];
587  $ubound = $v['values'][1];
588  $output .= ' ' . $lbound[1] . $this->compileAddslashes($lbound[0]) . $lbound[1];
589  $output .= ' AND ';
590  $output .= $ubound[1] . $this->compileAddslashes($ubound[0]) . $ubound[1];
591  } elseif (isset($v['value']['operator'])) {
592  $values = [];
593  foreach ($v['value']['args'] as $fieldDef) {
594  $values[] = ($fieldDef['table'] ? $fieldDef['table'] . '.' : '') . $fieldDef['field'];
595  }
596  $output .= ' ' . $v['value']['operator'] . '(' . implode(',', $values) . ')';
597  } else {
598  $output .= ' ' . $v['value'][1] . $this->compileAddslashes($v['value'][0]) . $v['value'][1];
599  }
600  }
601  }
602  }
603  }
604  }
605  return $output;
606  }
607 }
static isFirstPartOfStr($str, $partStr)
compileFieldList($selectFields, $compileComments=true, $functionMapping=true)
Definition: Adodb.php:201
compileDROPINDEX($indexName, $tableName)
Definition: Adodb.php:182
compileCaseStatement(array $components, $functionMapping=true)
compileCREATEINDEX($indexName, $tableName, $indexFields, $indexOptions=[])
Definition: Adodb.php:152
compileWhereClause($clauseArray, $functionMapping=true)
Definition: Adodb.php:338