[BUGFIX] Do not use named parameter for list of ids in plain data resolver 49/57849/16
authorGleb Levitin <gleb.levitin@dkd.de>
Thu, 9 Aug 2018 16:23:52 +0000 (18:23 +0200)
committerMarkus Klein <markus.klein@typo3.org>
Thu, 7 Mar 2019 21:08:05 +0000 (22:08 +0100)
The plain data resolver sorts records by a list of uids.
This list can get very big so the database will fail if the
number of placesholders exceeds its limit.

Resolves: #85797
Releases: master, 9.5
Change-Id: I0b8a623fe00660b8f2c87a83a7e48ba430790d2b
Reviewed-on: https://review.typo3.org/c/57849
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Richard Haeser <richard@maxserv.com>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Reviewed-by: Benni Mack <benni@typo3.org>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
typo3/sysext/core/Classes/DataHandling/PlainDataResolver.php
typo3/sysext/core/Tests/Functional/DataHandling/DataResolving/DataSet/Pages.csv [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/DataHandling/DataResolving/PlainDataResolverTest.php [new file with mode: 0644]

index 8a61365..46fd245 100644 (file)
@@ -290,7 +290,8 @@ class PlainDataResolver
             ->where(
                 $queryBuilder->expr()->in(
                     'uid',
-                    $queryBuilder->createNamedParameter($ids, Connection::PARAM_INT_ARRAY)
+                    // do not use named parameter here as the list can get too long
+                    array_map('intval', $ids)
                 )
             );
 
@@ -302,7 +303,7 @@ class PlainDataResolver
 
         $sortedIds = $queryBuilder->execute()->fetchAll();
 
-        return array_column($sortedIds, 'uid');
+        return array_map('intval', array_column($sortedIds, 'uid'));
     }
 
     /**
diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/DataResolving/DataSet/Pages.csv b/typo3/sysext/core/Tests/Functional/DataHandling/DataResolving/DataSet/Pages.csv
new file mode 100644 (file)
index 0000000..4854ab7
--- /dev/null
@@ -0,0 +1,12 @@
+pages,,,
+,uid,sorting,title
+,1,1,a
+,2,2,b
+,3,4,c
+,4,5,d
+,5,6,e
+,6,9,f
+,7,8,g
+,8,7,h
+,9,10,i
+,10,3,j
diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/DataResolving/PlainDataResolverTest.php b/typo3/sysext/core/Tests/Functional/DataHandling/DataResolving/PlainDataResolverTest.php
new file mode 100644 (file)
index 0000000..c728166
--- /dev/null
@@ -0,0 +1,131 @@
+<?php
+declare(strict_types = 1);
+
+/*
+ * This file is part of TYPO3 GmbHs software toolkit.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Core\Tests\Functional\DataHandling\DataResolving;
+
+use TYPO3\CMS\Core\DataHandling\PlainDataResolver;
+use TYPO3\CMS\Core\Tests\Functional\DataHandling\AbstractDataHandlerActionTestCase;
+
+class PlainDataResolverTest extends AbstractDataHandlerActionTestCase
+{
+    /**
+     * @var string
+     */
+    protected $scenarioDataSetDirectory = 'typo3/sysext/core/Tests/Functional/DataHandling/DataResolving/DataSet/';
+
+    protected function setUp()
+    {
+        parent::setUp();
+        $this->importScenarioDataSet('Pages');
+    }
+
+    /**
+     * @return array
+     * entries:
+     *  'key' => [
+     *      [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], // input
+     *      [1, 2, 10, 3, 4, 5, 8, 7, 6, 9], // output (expected output)
+     *      ['sorting']                      // sorting criteria
+     *  ]
+     */
+    public function sortingDataProvider(): array
+    {
+        return [
+            'sorting' => [
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                [1, 2, 10, 3, 4, 5, 8, 7, 6, 9],
+                ['sorting']
+            ],
+            'sorting asc' => [
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                [1, 2, 10, 3, 4, 5, 8, 7, 6, 9],
+                ['sorting asc']
+            ],
+            'sorting desc' => [
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                [9, 6, 7, 8, 5, 4, 3, 10, 2, 1],
+                ['sorting desc']
+            ],
+            'sorting ASC' => [
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                [1, 2, 10, 3, 4, 5, 8, 7, 6, 9],
+                ['sorting ASC']
+            ],
+            'sorting DESC' => [
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                [9, 6, 7, 8, 5, 4, 3, 10, 2, 1],
+                ['sorting DESC']
+            ],
+            'sorting ASC title' => [
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                [1, 2, 10, 3, 4, 5, 8, 7, 6, 9],
+                ['sorting ASC', 'title']
+            ],
+            'sorting ASC title asc' => [
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                [1, 2, 10, 3, 4, 5, 8, 7, 6, 9],
+                ['sorting ASC', 'title asc']
+            ],
+            'sorting ASC title desc' => [
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                [1, 2, 10, 3, 4, 5, 8, 7, 6, 9],
+                ['sorting ASC', 'title desc']
+            ],
+            'sorting ASC title ASC' => [
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                [1, 2, 10, 3, 4, 5, 8, 7, 6, 9],
+                ['sorting ASC', 'title ASC']
+            ],
+            'sorting ASC title DESC' => [
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                [1, 2, 10, 3, 4, 5, 8, 7, 6, 9],
+                ['sorting ASC', 'title DESC']
+            ],
+            'title sorting ASC' => [
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                ['title', 'sorting ASC']
+            ],
+            'title asc sorting ASC' => [
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                ['title asc', 'sorting ASC']
+            ],
+            'title desc sorting ASC' => [
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                [10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+                ['title desc', 'sorting ASC']
+            ],
+            'title ASC sorting ASC' => [
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                ['title ASC', 'sorting ASC']
+            ],
+            'title DESC sorting ASC' => [
+                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+                [10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+                ['title DESC', 'sorting ASC']
+            ],
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider sortingDataProvider
+     */
+    public function processSortingReturnsExpectedSequenceOfUids(array $input, array $expected, array $sortings): void
+    {
+        $subject = new PlainDataResolver('pages', [], $sortings);
+        $this->assertSame($expected, $subject->processSorting($input));
+    }
+}