[BUGFIX] FOLLOWUP Queries with NULL don't work 15/28715/6
authorFelix Oertel <felix@oer.tel>
Mon, 24 Mar 2014 17:33:35 +0000 (18:33 +0100)
committerMarkus Klein <klein.t3@mfc-linz.at>
Mon, 24 Mar 2014 21:32:13 +0000 (22:32 +0100)
In https://review.typo3.org/28592 we apparently did not
fix the whole problem. This followup will deal with
the edge-case of using a similar built statement, which
results in the same hash being generated from the
QueryParser.

Resolves: #57130
Related: #55167
Releases: 6.2
Change-Id: I02a478fcabb89d11054f8f0a3c800965edfd7844
Reviewed-on: https://review.typo3.org/28715
Reviewed-by: Marc Bastian Heinrichs
Tested-by: Marc Bastian Heinrichs
Reviewed-by: Markus Klein
Tested-by: Markus Klein
typo3/sysext/extbase/Classes/Persistence/Generic/Qom/Comparison.php
typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php
typo3/sysext/extbase/Classes/Persistence/QueryInterface.php
typo3/sysext/extbase/Tests/Functional/Persistence/QueryParserTest.php

index 80b5be0..0ffa587 100644 (file)
@@ -45,25 +45,25 @@ namespace TYPO3\CMS\Extbase\Persistence\Generic\Qom;
  * If operand1 evaluates to null (for example, if the operand evaluates the value
  * of a property which does not exist), the constraint is not satisfied.
  *
- * The JCR_OPERATOR_EQUAL_TO operator is satisfied only if the value of operand1
+ * The OPERATOR_EQUAL_TO operator is satisfied only if the value of operand1
  * equals the value of operand2.
  *
- * The JCR_OPERATOR_NOT_EQUAL_TO operator is satisfied unless the value of
+ * The OPERATOR_NOT_EQUAL_TO operator is satisfied unless the value of
  * operand1 equals the value of operand2.
  *
- * The JCR_OPERATOR_LESSS_THAN operator is satisfied only if the value of
+ * The OPERATOR_LESSS_THAN operator is satisfied only if the value of
  * operand1 is ordered before the value of operand2.
  *
- * The JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO operator is satisfied unless the value
+ * The OPERATOR_LESS_THAN_OR_EQUAL_TO operator is satisfied unless the value
  * of operand1 is ordered after the value of operand2.
  *
- * The JCR_OPERATOR_GREATER_THAN operator is satisfied only if the value of
+ * The OPERATOR_GREATER_THAN operator is satisfied only if the value of
  * operand1 is ordered after the value of operand2.
  *
- * The JCR_OPERATOR_GREATER_THAN_OR_EQUAL_TO operator is satisfied unless the
+ * The OPERATOR_GREATER_THAN_OR_EQUAL_TO operator is satisfied unless the
  * value of operand1 is ordered before the value of operand2.
  *
- * The JCR_OPERATOR_LIKE operator is satisfied only if the value of operand1
+ * The OPERATOR_LIKE operator is satisfied only if the value of operand1
  * matches the pattern specified by the value of operand2, where in the pattern:
  * the character "%" matches zero or more characters, and
  * the character "_" (underscore) matches exactly one character, and
@@ -117,10 +117,20 @@ class Comparison implements \TYPO3\CMS\Extbase\Persistence\Generic\Qom\Compariso
        /**
         * Gets the operator.
         *
-        * @return string one of \TYPO3\CMS\Extbase\Persistence\Generic\Qom\QueryObjectModelConstantsInterface.JCR_OPERATOR_*
+        * @return string one of \TYPO3\CMS\Extbase\Persistence\QueryInterface.OPERATOR_*
         */
        public function getOperator() {
-               return $this->operator;
+               $operator = $this->operator;
+
+               if ($this->getOperand2() === NULL) {
+                       if ($operator === \TYPO3\CMS\Extbase\Persistence\QueryInterface::OPERATOR_EQUAL_TO) {
+                               $operator = \TYPO3\CMS\Extbase\Persistence\QueryInterface::OPERATOR_EQUAL_TO_NULL;
+                       } elseif ($operator === \TYPO3\CMS\Extbase\Persistence\QueryInterface::OPERATOR_NOT_EQUAL_TO) {
+                               $operator = \TYPO3\CMS\Extbase\Persistence\QueryInterface::OPERATOR_NOT_EQUAL_TO_NULL;
+                       }
+               }
+
+               return $operator;
        }
 
        /**
index a4875ed..d8960a4 100644 (file)
@@ -36,9 +36,6 @@ use TYPO3\CMS\Extbase\Utility\TypeHandlingUtility;
  */
 class Typo3DbQueryParser {
 
-       const OPERATOR_EQUAL_TO_NULL = 'operatorEqualToNull';
-       const OPERATOR_NOT_EQUAL_TO_NULL = 'operatorNotEqualToNull';
-
        /**
         * The TYPO3 database object
         *
@@ -375,13 +372,6 @@ class Typo3DbQueryParser {
                                }
                        }
                } else {
-                       if ($operand2 === NULL) {
-                               if ($operator === \TYPO3\CMS\Extbase\Persistence\QueryInterface::OPERATOR_EQUAL_TO) {
-                                       $operator = self::OPERATOR_EQUAL_TO_NULL;
-                               } elseif ($operator === \TYPO3\CMS\Extbase\Persistence\QueryInterface::OPERATOR_NOT_EQUAL_TO) {
-                                       $operator = self::OPERATOR_NOT_EQUAL_TO_NULL;
-                               }
-                       }
                        $this->parseDynamicOperand($comparison, $operator, $source, $sql);
                }
        }
@@ -757,21 +747,21 @@ class Typo3DbQueryParser {
         */
        protected function resolveOperator($operator) {
                switch ($operator) {
-                       case self::OPERATOR_EQUAL_TO_NULL:
-                               $operator = 'IS';
-                               break;
-                       case self::OPERATOR_NOT_EQUAL_TO_NULL:
-                               $operator = 'IS NOT';
-                               break;
                        case \TYPO3\CMS\Extbase\Persistence\QueryInterface::OPERATOR_IN:
                                $operator = 'IN';
                                break;
                        case \TYPO3\CMS\Extbase\Persistence\QueryInterface::OPERATOR_EQUAL_TO:
                                $operator = '=';
                                break;
+                       case \TYPO3\CMS\Extbase\Persistence\QueryInterface::OPERATOR_EQUAL_TO_NULL:
+                               $operator = 'IS';
+                               break;
                        case \TYPO3\CMS\Extbase\Persistence\QueryInterface::OPERATOR_NOT_EQUAL_TO:
                                $operator = '!=';
                                break;
+                       case \TYPO3\CMS\Extbase\Persistence\QueryInterface::OPERATOR_NOT_EQUAL_TO_NULL:
+                               $operator = 'IS NOT';
+                               break;
                        case \TYPO3\CMS\Extbase\Persistence\QueryInterface::OPERATOR_LESS_THAN:
                                $operator = '<';
                                break;
index 06fd7f5..e63b57a 100644 (file)
@@ -42,6 +42,13 @@ interface QueryInterface {
        const OPERATOR_EQUAL_TO = 1;
 
        /**
+        * For NULL we have to use 'IS' instead of '='
+        *
+        * @api
+        */
+       const OPERATOR_EQUAL_TO_NULL = 101;
+
+       /**
         * The '!=' comparison operator.
         *
         * @api
@@ -49,6 +56,13 @@ interface QueryInterface {
        const OPERATOR_NOT_EQUAL_TO = 2;
 
        /**
+        * For NULL we have to use 'IS NOT' instead of '!='
+        *
+        * @api
+        */
+       const OPERATOR_NOT_EQUAL_TO_NULL = 202;
+
+       /**
         * The '<' comparison operator.
         *
         * @api
index 1af535f..2ef7a06 100644 (file)
@@ -82,4 +82,27 @@ class QueryParserTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
 
                $this->assertNotSame($hashWithEquals, $hashWithIn);
        }
+
+       /**
+        * @test
+        */
+       public function preparseQueryHasDiffersForIsNullOperator() {
+               $queryWithIsNull = $this->blogRepository->createQuery();
+
+               $queryWithIsNull->matching(
+                       $queryWithIsNull->equals('title', NULL)
+               );
+
+               list($hashWithIsNull) = $this->queryParser->preparseQuery($queryWithIsNull);
+
+               $queryWithoutIsNull = $this->blogRepository->createQuery();
+
+               $queryWithoutIsNull->matching(
+                       $queryWithoutIsNull->equals('title', '')
+               );
+
+               list($hashWithoutIsNull) = $this->queryParser->preparseQuery($queryWithoutIsNull);
+
+               $this->assertNotSame($hashWithIsNull, $hashWithoutIsNull);
+       }
 }