aboutsummaryrefslogtreecommitdiffstats
path: root/tests/lib/Files/Search
diff options
context:
space:
mode:
Diffstat (limited to 'tests/lib/Files/Search')
-rw-r--r--tests/lib/Files/Search/QueryOptimizer/CombinedTests.php195
-rw-r--r--tests/lib/Files/Search/QueryOptimizer/FlattenNestedBoolTest.php46
-rw-r--r--tests/lib/Files/Search/QueryOptimizer/MergeDistributiveOperationsTest.php164
-rw-r--r--tests/lib/Files/Search/QueryOptimizer/OrEqualsToInTest.php124
-rw-r--r--tests/lib/Files/Search/SearchIntegrationTest.php48
5 files changed, 577 insertions, 0 deletions
diff --git a/tests/lib/Files/Search/QueryOptimizer/CombinedTests.php b/tests/lib/Files/Search/QueryOptimizer/CombinedTests.php
new file mode 100644
index 00000000000..665224cb63e
--- /dev/null
+++ b/tests/lib/Files/Search/QueryOptimizer/CombinedTests.php
@@ -0,0 +1,195 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace Test\Files\Search\QueryOptimizer;
+
+use OC\Files\Search\QueryOptimizer\QueryOptimizer;
+use OC\Files\Search\SearchBinaryOperator;
+use OC\Files\Search\SearchComparison;
+use OCP\Files\Search\ISearchBinaryOperator;
+use OCP\Files\Search\ISearchComparison;
+use Test\TestCase;
+
+class CombinedTests extends TestCase {
+ private QueryOptimizer $optimizer;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->optimizer = new QueryOptimizer();
+ }
+
+ public function testBasicOrOfAnds(): void {
+ $operator = new SearchBinaryOperator(
+ ISearchBinaryOperator::OPERATOR_OR,
+ [
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'),
+ ])
+ ]
+ );
+ $this->assertEquals('((storage eq 1 and path eq "foo") or (storage eq 1 and path eq "bar") or (storage eq 1 and path eq "asd"))', $operator->__toString());
+
+ $this->optimizer->processOperator($operator);
+
+ $this->assertEquals('(storage eq 1 and path in ["foo","bar","asd"])', $operator->__toString());
+ }
+
+ public function testComplexSearchPattern1(): void {
+ $operator = new SearchBinaryOperator(
+ ISearchBinaryOperator::OPERATOR_OR,
+ [
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 2),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '201'),
+ new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', '201/%'),
+ ]),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '301'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 4),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '401'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '302'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 4),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '402'),
+ ]),
+ ]
+ );
+ $this->assertEquals('((storage eq 1) or (storage eq 2 and (path eq "201" or path like "201\/%")) or (storage eq 3 and path eq "301") or (storage eq 4 and path eq "401") or (storage eq 3 and path eq "302") or (storage eq 4 and path eq "402"))', $operator->__toString());
+
+ $this->optimizer->processOperator($operator);
+
+ $this->assertEquals('(storage eq 1 or (storage eq 2 and (path eq "201" or path like "201\/%")) or (storage eq 3 and path in ["301","302"]) or (storage eq 4 and path in ["401","402"]))', $operator->__toString());
+ }
+
+ public function testComplexSearchPattern2(): void {
+ $operator = new SearchBinaryOperator(
+ ISearchBinaryOperator::OPERATOR_OR,
+ [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 2),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '201'),
+ new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', '201/%'),
+ ]),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '301'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 4),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '401'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '302'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 4),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', '402'),
+ ]),
+ ]
+ );
+ $this->assertEquals('(storage eq 1 or (storage eq 2 and (path eq "201" or path like "201\/%")) or (storage eq 3 and path eq "301") or (storage eq 4 and path eq "401") or (storage eq 3 and path eq "302") or (storage eq 4 and path eq "402"))', $operator->__toString());
+
+ $this->optimizer->processOperator($operator);
+
+ $this->assertEquals('(storage eq 1 or (storage eq 2 and (path eq "201" or path like "201\/%")) or (storage eq 3 and path in ["301","302"]) or (storage eq 4 and path in ["401","402"]))', $operator->__toString());
+ }
+
+ public function testApplySearchConstraints1(): void {
+ $operator = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', 'image/png'),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', 'image/jpeg'),
+ ]),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'files'),
+ new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', 'files/%'),
+ ]),
+ ]),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 2),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'files/301'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'files/302'),
+ ]),
+ ]),
+ ]);
+ $this->assertEquals('(((mimetype eq "image\/png" or mimetype eq "image\/jpeg")) and ((storage eq 1 and (path eq "files" or path like "files\/%")) or storage eq 2 or (storage eq 3 and path eq "files\/301") or (storage eq 3 and path eq "files\/302")))', $operator->__toString());
+
+ $this->optimizer->processOperator($operator);
+
+ $this->assertEquals('(mimetype in ["image\/png","image\/jpeg"] and ((storage eq 1 and (path eq "files" or path like "files\/%")) or storage eq 2 or (storage eq 3 and path in ["files\/301","files\/302"])))', $operator->__toString());
+ }
+
+ public function testApplySearchConstraints2(): void {
+ $operator = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', 'image/png'),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', 'image/jpeg'),
+ ]),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'files'),
+ new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', 'files/%'),
+ ]),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 2),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'files/301'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'files/302'),
+ ]),
+ ]),
+ ]);
+ $this->assertEquals('(((mimetype eq "image\/png" or mimetype eq "image\/jpeg")) and ((storage eq 1 and (path eq "files" or path like "files\/%")) or (storage eq 2) or (storage eq 3 and path eq "files\/301") or (storage eq 3 and path eq "files\/302")))', $operator->__toString());
+
+ $this->optimizer->processOperator($operator);
+
+ $this->assertEquals('(mimetype in ["image\/png","image\/jpeg"] and ((storage eq 1 and (path eq "files" or path like "files\/%")) or storage eq 2 or (storage eq 3 and path in ["files\/301","files\/302"])))', $operator->__toString());
+ }
+}
diff --git a/tests/lib/Files/Search/QueryOptimizer/FlattenNestedBoolTest.php b/tests/lib/Files/Search/QueryOptimizer/FlattenNestedBoolTest.php
new file mode 100644
index 00000000000..1d43541a5a0
--- /dev/null
+++ b/tests/lib/Files/Search/QueryOptimizer/FlattenNestedBoolTest.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace Test\Files\Search\QueryOptimizer;
+
+use OC\Files\Search\QueryOptimizer\FlattenNestedBool;
+use OC\Files\Search\QueryOptimizer\FlattenSingleArgumentBinaryOperation;
+use OC\Files\Search\SearchBinaryOperator;
+use OC\Files\Search\SearchComparison;
+use OCP\Files\Search\ISearchBinaryOperator;
+use OCP\Files\Search\ISearchComparison;
+use Test\TestCase;
+
+class FlattenNestedBoolTest extends TestCase {
+ private $optimizer;
+ private $simplifier;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->optimizer = new FlattenNestedBool();
+ $this->simplifier = new FlattenSingleArgumentBinaryOperation();
+ }
+
+ public function testOrs(): void {
+ $operator = new SearchBinaryOperator(
+ ISearchBinaryOperator::OPERATOR_OR,
+ [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'),
+ ])
+ ]
+ );
+ $this->assertEquals('(path eq "foo" or (path eq "bar" or path eq "asd"))', $operator->__toString());
+
+ $this->optimizer->processOperator($operator);
+ $this->simplifier->processOperator($operator);
+
+ $this->assertEquals('(path eq "foo" or path eq "bar" or path eq "asd")', $operator->__toString());
+ }
+}
diff --git a/tests/lib/Files/Search/QueryOptimizer/MergeDistributiveOperationsTest.php b/tests/lib/Files/Search/QueryOptimizer/MergeDistributiveOperationsTest.php
new file mode 100644
index 00000000000..9aaa7030aac
--- /dev/null
+++ b/tests/lib/Files/Search/QueryOptimizer/MergeDistributiveOperationsTest.php
@@ -0,0 +1,164 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace Test\Files\Search\QueryOptimizer;
+
+use OC\Files\Search\QueryOptimizer\FlattenSingleArgumentBinaryOperation;
+use OC\Files\Search\QueryOptimizer\MergeDistributiveOperations;
+use OC\Files\Search\SearchBinaryOperator;
+use OC\Files\Search\SearchComparison;
+use OCP\Files\Search\ISearchBinaryOperator;
+use OCP\Files\Search\ISearchComparison;
+use Test\TestCase;
+
+class MergeDistributiveOperationsTest extends TestCase {
+ private $optimizer;
+ private $simplifier;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->optimizer = new MergeDistributiveOperations();
+ $this->simplifier = new FlattenSingleArgumentBinaryOperation();
+ }
+
+ public function testBasicOrOfAnds(): void {
+ $operator = new SearchBinaryOperator(
+ ISearchBinaryOperator::OPERATOR_OR,
+ [
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'),
+ ])
+ ]
+ );
+ $this->assertEquals('((storage eq 1 and path eq "foo") or (storage eq 1 and path eq "bar") or (storage eq 1 and path eq "asd"))', $operator->__toString());
+
+ $this->optimizer->processOperator($operator);
+ $this->simplifier->processOperator($operator);
+
+ $this->assertEquals('(storage eq 1 and (path eq "foo" or path eq "bar" or path eq "asd"))', $operator->__toString());
+ }
+
+ public function testDontTouchIfNotSame(): void {
+ $operator = new SearchBinaryOperator(
+ ISearchBinaryOperator::OPERATOR_OR,
+ [
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 2),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 3),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'),
+ ])
+ ]
+ );
+ $this->assertEquals('((storage eq 1 and path eq "foo") or (storage eq 2 and path eq "bar") or (storage eq 3 and path eq "asd"))', $operator->__toString());
+
+ $this->optimizer->processOperator($operator);
+ $this->simplifier->processOperator($operator);
+
+ $this->assertEquals('((storage eq 1 and path eq "foo") or (storage eq 2 and path eq "bar") or (storage eq 3 and path eq "asd"))', $operator->__toString());
+ }
+
+ public function testMergePartial(): void {
+ $operator = new SearchBinaryOperator(
+ ISearchBinaryOperator::OPERATOR_OR,
+ [
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 2),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'),
+ ])
+ ]
+ );
+ $this->assertEquals('((storage eq 1 and path eq "foo") or (storage eq 1 and path eq "bar") or (storage eq 2 and path eq "asd"))', $operator->__toString());
+
+ $this->optimizer->processOperator($operator);
+ $this->simplifier->processOperator($operator);
+
+ $this->assertEquals('((storage eq 1 and (path eq "foo" or path eq "bar")) or (storage eq 2 and path eq "asd"))', $operator->__toString());
+ }
+
+ public function testOptimizeInside(): void {
+ $operator = new SearchBinaryOperator(
+ ISearchBinaryOperator::OPERATOR_AND,
+ [
+ new SearchBinaryOperator(
+ ISearchBinaryOperator::OPERATOR_OR,
+ [
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'),
+ ])
+ ]
+ ),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', 'text')
+ ]
+ );
+ $this->assertEquals('(((storage eq 1 and path eq "foo") or (storage eq 1 and path eq "bar") or (storage eq 1 and path eq "asd")) and mimetype eq "text")', $operator->__toString());
+
+ $this->optimizer->processOperator($operator);
+ $this->simplifier->processOperator($operator);
+
+ $this->assertEquals('((storage eq 1 and (path eq "foo" or path eq "bar" or path eq "asd")) and mimetype eq "text")', $operator->__toString());
+ }
+
+ public function testMoveInnerOperations(): void {
+ $operator = new SearchBinaryOperator(
+ ISearchBinaryOperator::OPERATOR_OR,
+ [
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'),
+ ]),
+ new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'storage', 1),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'),
+ new SearchComparison(ISearchComparison::COMPARE_GREATER_THAN, 'size', '100'),
+ ])
+ ]
+ );
+ $this->assertEquals('((storage eq 1 and path eq "foo") or (storage eq 1 and path eq "bar") or (storage eq 1 and path eq "asd" and size gt "100"))', $operator->__toString());
+
+ $this->optimizer->processOperator($operator);
+ $this->simplifier->processOperator($operator);
+
+ $this->assertEquals('(storage eq 1 and (path eq "foo" or path eq "bar" or (path eq "asd" and size gt "100")))', $operator->__toString());
+ }
+}
diff --git a/tests/lib/Files/Search/QueryOptimizer/OrEqualsToInTest.php b/tests/lib/Files/Search/QueryOptimizer/OrEqualsToInTest.php
new file mode 100644
index 00000000000..d51fe3d0d16
--- /dev/null
+++ b/tests/lib/Files/Search/QueryOptimizer/OrEqualsToInTest.php
@@ -0,0 +1,124 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace Test\Files\Search\QueryOptimizer;
+
+use OC\Files\Search\QueryOptimizer\FlattenSingleArgumentBinaryOperation;
+use OC\Files\Search\QueryOptimizer\OrEqualsToIn;
+use OC\Files\Search\SearchBinaryOperator;
+use OC\Files\Search\SearchComparison;
+use OCP\Files\Search\ISearchBinaryOperator;
+use OCP\Files\Search\ISearchComparison;
+use Test\TestCase;
+
+class OrEqualsToInTest extends TestCase {
+ private $optimizer;
+ private $simplifier;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->optimizer = new OrEqualsToIn();
+ $this->simplifier = new FlattenSingleArgumentBinaryOperation();
+ }
+
+ public function testOrs(): void {
+ $operator = new SearchBinaryOperator(
+ ISearchBinaryOperator::OPERATOR_OR,
+ [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'),
+ ]
+ );
+ $this->assertEquals('(path eq "foo" or path eq "bar" or path eq "asd")', $operator->__toString());
+
+ $this->optimizer->processOperator($operator);
+ $this->simplifier->processOperator($operator);
+
+ $this->assertEquals('path in ["foo","bar","asd"]', $operator->__toString());
+ }
+
+ public function testOrsMultipleFields(): void {
+ $operator = new SearchBinaryOperator(
+ ISearchBinaryOperator::OPERATOR_OR,
+ [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'fileid', 1),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'fileid', 2),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', 'asd'),
+ ]
+ );
+ $this->assertEquals('(path eq "foo" or path eq "bar" or fileid eq 1 or fileid eq 2 or mimetype eq "asd")', $operator->__toString());
+
+ $this->optimizer->processOperator($operator);
+ $this->simplifier->processOperator($operator);
+
+ $this->assertEquals('(path in ["foo","bar"] or fileid in [1,2] or mimetype eq "asd")', $operator->__toString());
+ }
+
+ public function testPreserveHints(): void {
+ $operator = new SearchBinaryOperator(
+ ISearchBinaryOperator::OPERATOR_OR,
+ [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'),
+ ]
+ );
+ foreach ($operator->getArguments() as $argument) {
+ $argument->setQueryHint(ISearchComparison::HINT_PATH_EQ_HASH, false);
+ }
+ $this->assertEquals('(path eq "foo" or path eq "bar" or path eq "asd")', $operator->__toString());
+
+ $this->optimizer->processOperator($operator);
+ $this->simplifier->processOperator($operator);
+
+ $this->assertEquals('path in ["foo","bar","asd"]', $operator->__toString());
+ $this->assertEquals(false, $operator->getQueryHint(ISearchComparison::HINT_PATH_EQ_HASH, true));
+ }
+
+ public function testOrSomeEq(): void {
+ $operator = new SearchBinaryOperator(
+ ISearchBinaryOperator::OPERATOR_OR,
+ [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'),
+ new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', 'foo%'),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'),
+ ]
+ );
+ $this->assertEquals('(path eq "foo" or path like "foo%" or path eq "bar")', $operator->__toString());
+
+ $this->optimizer->processOperator($operator);
+ $this->simplifier->processOperator($operator);
+
+ $this->assertEquals('(path in ["foo","bar"] or path like "foo%")', $operator->__toString());
+ }
+
+ public function testOrsInside(): void {
+ $operator = new SearchBinaryOperator(
+ ISearchBinaryOperator::OPERATOR_AND,
+ [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', 'text'),
+ new SearchBinaryOperator(
+ ISearchBinaryOperator::OPERATOR_OR,
+ [
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'foo'),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'bar'),
+ new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', 'asd'),
+ ]
+ )
+ ]
+ );
+ $this->assertEquals('(mimetype eq "text" and (path eq "foo" or path eq "bar" or path eq "asd"))', $operator->__toString());
+
+ $this->optimizer->processOperator($operator);
+ $this->simplifier->processOperator($operator);
+
+ $this->assertEquals('(mimetype eq "text" and path in ["foo","bar","asd"])', $operator->__toString());
+ }
+}
diff --git a/tests/lib/Files/Search/SearchIntegrationTest.php b/tests/lib/Files/Search/SearchIntegrationTest.php
new file mode 100644
index 00000000000..e3e99bbfadd
--- /dev/null
+++ b/tests/lib/Files/Search/SearchIntegrationTest.php
@@ -0,0 +1,48 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace Test\Files\Search;
+
+use OC\Files\Search\SearchBinaryOperator;
+use OC\Files\Search\SearchComparison;
+use OC\Files\Search\SearchQuery;
+use OC\Files\Storage\Temporary;
+use OCP\Files\Search\ISearchBinaryOperator;
+use OCP\Files\Search\ISearchComparison;
+use Test\TestCase;
+
+/**
+ * @group DB
+ */
+class SearchIntegrationTest extends TestCase {
+ private $cache;
+ private $storage;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->storage = new Temporary([]);
+ $this->cache = $this->storage->getCache();
+ $this->storage->getScanner()->scan('');
+ }
+
+
+ public function testThousandAndOneFilters(): void {
+ $id = $this->cache->put('file10', ['size' => 1, 'mtime' => 50, 'mimetype' => 'foo/folder']);
+
+ $comparisons = [];
+ for ($i = 1; $i <= 1001; $i++) {
+ $comparisons[] = new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'name', "file$i");
+ }
+ $operator = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, $comparisons);
+ $query = new SearchQuery($operator, 10, 0, []);
+
+ $results = $this->cache->searchQuery($query);
+
+ $this->assertCount(1, $results);
+ $this->assertEquals($id, $results[0]->getId());
+ }
+}