Fixed bug RFC #12515: DAM-related: CONCAT operator cannot be used after LIKE
authorXavier Perseguers <typo3@perseguers.ch>
Mon, 9 Nov 2009 15:30:01 +0000 (15:30 +0000)
committerXavier Perseguers <typo3@perseguers.ch>
Mon, 9 Nov 2009 15:30:01 +0000 (15:30 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Extensions/dbal/trunk@26334 735d13b6-9817-0410-8766-e36946ffe9aa

typo3/sysext/dbal/ChangeLog
typo3/sysext/dbal/class.ux_t3lib_db.php
typo3/sysext/dbal/class.ux_t3lib_sqlparser.php
typo3/sysext/dbal/tests/db_oracle_testcase.php
typo3/sysext/dbal/tests/fixtures/oci8.config.php

index 14a8c3a..1b87613 100644 (file)
@@ -1,5 +1,6 @@
 2009-11-09  Xavier Perseguers  <typo3@perseguers.ch>
 
+       * Fixed bug RFC #12515: DAM-related: CONCAT operator cannot be used after LIKE
        * Fixed bug RFC #10411: Applied missing chunks of patch
 
 2009-11-07  Xavier Perseguers  <typo3@perseguers.ch>
index 34fcfae..7888984 100644 (file)
@@ -1051,9 +1051,16 @@ class ux_t3lib_DB extends t3lib_DB {
                                }
                        }
                        if ($where_clause[$k]['comparator']) {
-                                       // Detecting value type; list or plain:
-                               if ((!isset($where_clause[$k]['value'][1]) || $where_clause[$k]['value'][1] == '') && is_string($where_clause[$k]['value'][0]) && strstr($where_clause[$k]['value'][0], '.') && !t3lib_div::inList('NOTIN,IN',strtoupper(str_replace(array(" ","\n","\r","\t"),'',$where_clause[$k]['comparator'])))) {
-                                       $where_clause[$k]['value'][0] = $this->quoteFieldNames($where_clause[$k]['value'][0]);
+                               if (isset($v['value']['operator'])) {
+                                       foreach ($where_clause[$k]['value']['args'] as $argK => $fieldDef) {
+                                               $where_clause[$k]['value']['args'][$argK]['table'] = $this->quoteName($fieldDef['table']);
+                                               $where_clause[$k]['value']['args'][$argK]['field'] = $this->quoteName($fieldDef['field']);
+                                       }
+                               } else {
+                                               // Detecting value type; list or plain:
+                                       if ((!isset($where_clause[$k]['value'][1]) || $where_clause[$k]['value'][1] == '') && is_string($where_clause[$k]['value'][0]) && strstr($where_clause[$k]['value'][0], '.') && !t3lib_div::inList('NOTIN,IN',strtoupper(str_replace(array(" ","\n","\r","\t"),'',$where_clause[$k]['comparator'])))) {
+                                               $where_clause[$k]['value'][0] = $this->quoteFieldNames($where_clause[$k]['value'][0]);
+                                       }
                                }
                        }
                }
@@ -2497,6 +2504,18 @@ class ux_t3lib_DB extends t3lib_DB {
                                                }
                                        }
 
+                                               // Do we have a function (e.g., CONCAT)
+                                       if (isset($v['value']['operator'])) {
+                                               foreach ($sqlPartArray[$k]['value']['args'] as $argK => $fieldDef) {
+                                                       if (isset($this->mapping[$fieldDef['table']]['mapTableName'])) {
+                                                               $sqlPartArray[$k]['value']['args'][$argK]['table'] = $this->mapping[$fieldDef['table']]['mapTableName'];
+                                                       }
+                                                       if (is_array($this->mapping[$fieldDef['table']]['mapFieldNames']) && isset($this->mapping[$fieldDef['table']]['mapFieldNames'][$fieldDef['field']])) {
+                                                               $sqlPartArray[$k]['value']['args'][$argK]['field'] = $this->mapping[$fieldDef['table']]['mapFieldNames'][$fieldDef['field']];   
+                                                       }
+                                               }
+                                       }
+
                                                // do we have a field name in the value?
                                                // this is a very simplistic check, beware
                                        if (!is_numeric($sqlPartArray[$k]['value'][0]) && !isset($sqlPartArray[$k]['value'][1])) {
index d5db019..c546d10 100644 (file)
@@ -217,10 +217,36 @@ class ux_t3lib_sqlparser extends t3lib_sqlparser {
                                        // Find "comparator":
                                $stack[$level][$pnt[$level]]['comparator'] = $this->nextPart($parseString, '^(<=|>=|<|>|=|!=|NOT[[:space:]]+IN|IN|NOT[[:space:]]+LIKE|LIKE|IS[[:space:]]+NOT|IS)');
                                if (strlen($stack[$level][$pnt[$level]]['comparator'])) {
-                                               // Finding value for comparator:
-                                       $stack[$level][$pnt[$level]]['value'] = $this->getValue($parseString, $stack[$level][$pnt[$level]]['comparator']);
-                                       if ($this->parse_error) {
-                                               return $this->parse_error;
+                                       if (preg_match('/^CONCAT[[:space:]]*\(/i', $parseString)) {
+                                               $this->nextPart($parseString, '^(CONCAT[[:space:]]?[(])');
+                                               $values = array(
+                                                       'operator' => 'CONCAT',
+                                                       'args' => array(),
+                                               );
+                                               $cnt = 0;
+                                               while ($fieldName = $this->nextPart($parseString, '^([[:alnum:]._]+)')) {
+                                                               // Parse field name into field and table:
+                                                       $tableField = explode('.', $fieldName, 2);
+                                                       if (count($tableField) == 2) {
+                                                               $values['args'][$cnt]['table'] = $tableField[0];
+                                                               $values['args'][$cnt]['field'] = $tableField[1];
+                                                       } else {
+                                                               $values['args'][$cnt]['table'] = '';
+                                                               $values['args'][$cnt]['field'] = $tableField[0];
+                                                       }
+                                                               // Looking for comma:
+                                                       $this->nextPart($parseString, '^(,)');
+                                                       $cnt++;
+                                               }
+                                                       // Look for ending parenthese:
+                                               $this->nextPart($parseString, '([)])');
+                                               $stack[$level][$pnt[$level]]['value'] = $values;
+                                       } else {
+                                                       // Finding value for comparator:
+                                               $stack[$level][$pnt[$level]]['value'] = $this->getValue($parseString, $stack[$level][$pnt[$level]]['comparator']);
+                                               if ($this->parse_error) {
+                                                       return $this->parse_error;
+                                               }
                                        }
                                }
 
@@ -360,6 +386,12 @@ class ux_t3lib_sqlparser extends t3lib_sqlparser {
                                                                $valueBuffer[] = $realValue[1] . $this->compileAddslashes($realValue[0]) . $realValue[1];
                                                        }
                                                        $output .= ' (' . trim(implode(',', $valueBuffer)) . ')';
+                                               } else if (isset($v['value']['operator'])) {
+                                                       $values = array();
+                                                       foreach ($v['value']['args'] as $fieldDef) {
+                                                               $values[] = ($fieldDef['table'] ? $fieldDef['table'] . '.' : '') . $fieldDef['field'];
+                                                       }
+                                                       $output .= ' ' . $v['value']['operator'] . '(' . implode(',', $values) . ')';
                                                } else {
                                                        $output .= ' ' . $v['value'][1] . $this->compileAddslashes($v['value'][0]) . $v['value'][1];
                                                }
@@ -731,6 +763,12 @@ class ux_t3lib_sqlparser extends t3lib_sqlparser {
                                                                                                $valueBuffer[] = $realValue[1] . $this->compileAddslashes($realValue[0]) . $realValue[1];
                                                                                        }
                                                                                        $output .= ' (' . trim(implode(',', $valueBuffer)) . ')';
+                                                                               } else if (isset($v['value']['operator'])) {
+                                                                                       $values = array();
+                                                                                       foreach ($v['value']['args'] as $fieldDef) {
+                                                                                               $values[] = ($fieldDef['table'] ? $fieldDef['table'] . '.' : '') . $fieldDef['field'];
+                                                                                       }
+                                                                                       $output .= ' ' . $v['value']['operator'] . '(' . implode(',', $values) . ')';
                                                                                } else {
                                                                                        $output .= ' ' . $v['value'][1] . $this->compileAddslashes($v['value'][0]) . $v['value'][1];
                                                                                }
index 5a725b2..8ebe1d9 100644 (file)
@@ -239,4 +239,42 @@ class db_oracle_testcase extends BaseTestCase {
                $expected .= ' WHERE "ext_tt_news_cat_mm"."local_uid" > 50';
                $this->assertEquals($expected, $query);
        }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=12515
+        * @remark Remapping is not expected here
+        */
+       public function concatAfterLikeOperatorIsProperlyQuoted() {
+               $query = $this->cleanSql($this->fixture->SELECTquery(
+                       '*',
+                       'sys_refindex, tx_dam_file_tracking',
+                       'sys_refindex.tablename = \'tx_dam_file_tracking\''
+                       . ' AND sys_refindex.ref_string LIKE CONCAT(tx_dam_file_tracking.file_path, tx_dam_file_tracking.file_name)'
+               ));
+               $expected = 'SELECT * FROM "sys_refindex", "tx_dam_file_tracking" WHERE "sys_refindex"."tablename" = \'tx_dam_file_tracking\'';
+               $expected .= ' AND "sys_refindex"."ref_string" LIKE CONCAT("tx_dam_file_tracking"."file_path","tx_dam_file_tracking"."file_name")';
+               $this->assertEquals($expected, $query);
+       }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=12515
+        * @remark Remapping is expected here
+        */
+       public function concatAfterLikeOperatorIsRemapped() {
+               $selectFields = '*';
+               $fromTables   = 'sys_refindex, tx_dam_file_tracking';
+               $whereClause  = 'sys_refindex.tablename = \'tx_dam_file_tracking\''
+                                                       . ' AND sys_refindex.ref_string LIKE CONCAT(tx_dam_file_tracking.file_path, tx_dam_file_tracking.file_name)';
+               $groupBy      = '';
+               $orderBy      = '';
+
+               $this->fixture->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($this->fixture->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+
+               $expected = 'SELECT * FROM "sys_refindex", "tx_dam_file_tracking" WHERE "sys_refindex"."tablename" = \'tx_dam_file_tracking\'';
+               $expected .= ' AND "sys_refindex"."ref_string" LIKE CONCAT("tx_dam_file_tracking"."path","tx_dam_file_tracking"."filename")';
+               $this->assertEquals($expected, $query);
+       }
 }
\ No newline at end of file
index 242df01..7d94b3c 100644 (file)
@@ -42,6 +42,12 @@ $TYPO3_CONF_VARS['EXTCONF']['dbal']['mapping'] = array(
                        'uid_local' => 'local_uid',
                ),
        ),
+       'tx_dam_file_tracking' => array(
+               'mapFieldNames' => array(
+                       'file_name' => 'filename',
+                       'file_path' => 'path',
+               ),
+       ),
        'tx_dbal_debuglog' => array(
                'mapFieldNames' => array(
                        'errorFlag' => 'errorflag',