aboutsummaryrefslogtreecommitdiffstats
path: root/tests/lib/DB/QueryBuilder
diff options
context:
space:
mode:
Diffstat (limited to 'tests/lib/DB/QueryBuilder')
-rw-r--r--tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php131
-rw-r--r--tests/lib/DB/QueryBuilder/ExpressionBuilderTest.php110
-rw-r--r--tests/lib/DB/QueryBuilder/FunctionBuilderTest.php111
-rw-r--r--tests/lib/DB/QueryBuilder/Partitioned/JoinConditionTest.php74
-rw-r--r--tests/lib/DB/QueryBuilder/Partitioned/PartitionedQueryBuilderTest.php223
-rw-r--r--tests/lib/DB/QueryBuilder/QueryBuilderTest.php309
-rw-r--r--tests/lib/DB/QueryBuilder/QuoteHelperTest.php33
-rw-r--r--tests/lib/DB/QueryBuilder/Sharded/SharedQueryBuilderTest.php128
8 files changed, 799 insertions, 320 deletions
diff --git a/tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php b/tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php
index 35d8b4faa34..153993f396e 100644
--- a/tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php
+++ b/tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php
@@ -1,45 +1,38 @@
<?php
+
/**
- * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\DB\QueryBuilder;
+use Doctrine\DBAL\Schema\SchemaException;
use OC\DB\QueryBuilder\Literal;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\DB\Types;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\Server;
use Test\TestCase;
/**
* @group DB
*/
class ExpressionBuilderDBTest extends TestCase {
- /** @var \Doctrine\DBAL\Connection|\OCP\IDBConnection */
+ /** @var \Doctrine\DBAL\Connection|IDBConnection */
protected $connection;
+ protected $schemaSetup = false;
protected function setUp(): void {
parent::setUp();
- $this->connection = \OC::$server->getDatabaseConnection();
+ $this->connection = Server::get(IDBConnection::class);
+ $this->prepareTestingTable();
}
- public function likeProvider() {
- $connection = \OC::$server->getDatabaseConnection();
+ public static function likeProvider(): array {
+ $connection = Server::get(IDBConnection::class);
return [
['foo', 'bar', false],
@@ -55,13 +48,13 @@ class ExpressionBuilderDBTest extends TestCase {
}
/**
- * @dataProvider likeProvider
*
* @param string $param1
* @param string $param2
* @param boolean $match
*/
- public function testLike($param1, $param2, $match) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('likeProvider')]
+ public function testLike($param1, $param2, $match): void {
$query = $this->connection->getQueryBuilder();
$query->select(new Literal('1'))
@@ -74,8 +67,8 @@ class ExpressionBuilderDBTest extends TestCase {
$this->assertEquals($match, $column);
}
- public function ilikeProvider() {
- $connection = \OC::$server->getDatabaseConnection();
+ public static function ilikeProvider(): array {
+ $connection = Server::get(IDBConnection::class);
return [
['foo', 'bar', false],
@@ -92,13 +85,13 @@ class ExpressionBuilderDBTest extends TestCase {
}
/**
- * @dataProvider ilikeProvider
*
* @param string $param1
* @param string $param2
* @param boolean $match
*/
- public function testILike($param1, $param2, $match) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('ilikeProvider')]
+ public function testILike($param1, $param2, $match): void {
$query = $this->connection->getQueryBuilder();
$query->select(new Literal('1'))
@@ -150,14 +143,94 @@ class ExpressionBuilderDBTest extends TestCase {
self::assertEquals('myvalue', $entries[0]['configvalue']);
}
+ public function testDateTimeEquals(): void {
+ $dateTime = new \DateTime('2023-01-01');
+ $insert = $this->connection->getQueryBuilder();
+ $insert->insert('testing')
+ ->values(['datetime' => $insert->createNamedParameter($dateTime, IQueryBuilder::PARAM_DATETIME_MUTABLE)])
+ ->executeStatement();
+
+ $query = $this->connection->getQueryBuilder();
+ $result = $query->select('*')
+ ->from('testing')
+ ->where($query->expr()->eq('datetime', $query->createNamedParameter($dateTime, IQueryBuilder::PARAM_DATETIME_MUTABLE)))
+ ->executeQuery();
+ $entries = $result->fetchAll();
+ $result->closeCursor();
+ self::assertCount(1, $entries);
+ }
+
+ public function testDateTimeLess(): void {
+ $dateTime = new \DateTime('2022-01-01');
+ $dateTimeCompare = new \DateTime('2022-01-02');
+ $insert = $this->connection->getQueryBuilder();
+ $insert->insert('testing')
+ ->values(['datetime' => $insert->createNamedParameter($dateTime, IQueryBuilder::PARAM_DATETIME_MUTABLE)])
+ ->executeStatement();
+
+ $query = $this->connection->getQueryBuilder();
+ $result = $query->select('*')
+ ->from('testing')
+ ->where($query->expr()->lt('datetime', $query->createNamedParameter($dateTimeCompare, IQueryBuilder::PARAM_DATETIME_MUTABLE)))
+ ->executeQuery();
+ $entries = $result->fetchAll();
+ $result->closeCursor();
+ self::assertCount(1, $entries);
+ }
+
+ public function testDateTimeGreater(): void {
+ $dateTime = new \DateTime('2023-01-02');
+ $dateTimeCompare = new \DateTime('2023-01-01');
+ $insert = $this->connection->getQueryBuilder();
+ $insert->insert('testing')
+ ->values(['datetime' => $insert->createNamedParameter($dateTime, IQueryBuilder::PARAM_DATETIME_MUTABLE)])
+ ->executeStatement();
+
+ $query = $this->connection->getQueryBuilder();
+ $result = $query->select('*')
+ ->from('testing')
+ ->where($query->expr()->gt('datetime', $query->createNamedParameter($dateTimeCompare, IQueryBuilder::PARAM_DATETIME_MUTABLE)))
+ ->executeQuery();
+ $entries = $result->fetchAll();
+ $result->closeCursor();
+ self::assertCount(1, $entries);
+ }
+
protected function createConfig($appId, $key, $value) {
$query = $this->connection->getQueryBuilder();
$query->insert('appconfig')
->values([
'appid' => $query->createNamedParameter($appId),
- 'configkey' => $query->createNamedParameter((string) $key),
- 'configvalue' => $query->createNamedParameter((string) $value),
+ 'configkey' => $query->createNamedParameter((string)$key),
+ 'configvalue' => $query->createNamedParameter((string)$value),
])
->execute();
}
+
+ protected function prepareTestingTable(): void {
+ if ($this->schemaSetup) {
+ $this->connection->getQueryBuilder()->delete('testing')->executeStatement();
+ }
+
+ $prefix = Server::get(IConfig::class)->getSystemValueString('dbtableprefix', 'oc_');
+ $schema = $this->connection->createSchema();
+ try {
+ $schema->getTable($prefix . 'testing');
+ $this->connection->getQueryBuilder()->delete('testing')->executeStatement();
+ } catch (SchemaException $e) {
+ $this->schemaSetup = true;
+ $table = $schema->createTable($prefix . 'testing');
+ $table->addColumn('id', Types::BIGINT, [
+ 'autoincrement' => true,
+ 'notnull' => true,
+ ]);
+
+ $table->addColumn('datetime', Types::DATETIME, [
+ 'notnull' => false,
+ ]);
+
+ $table->setPrimaryKey(['id']);
+ $this->connection->migrateToSchema($schema);
+ }
+ }
}
diff --git a/tests/lib/DB/QueryBuilder/ExpressionBuilderTest.php b/tests/lib/DB/QueryBuilder/ExpressionBuilderTest.php
index 76d9dab75ee..1f84ebfbec1 100644
--- a/tests/lib/DB/QueryBuilder/ExpressionBuilderTest.php
+++ b/tests/lib/DB/QueryBuilder/ExpressionBuilderTest.php
@@ -1,22 +1,9 @@
<?php
+
/**
- * @author Joas Schilling <nickvergessen@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace Test\DB\QueryBuilder;
@@ -24,6 +11,9 @@ namespace Test\DB\QueryBuilder;
use Doctrine\DBAL\Query\Expression\ExpressionBuilder as DoctrineExpressionBuilder;
use OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+use OCP\Server;
+use Psr\Log\LoggerInterface;
use Test\TestCase;
/**
@@ -40,27 +30,31 @@ class ExpressionBuilderTest extends TestCase {
/** @var DoctrineExpressionBuilder */
protected $doctrineExpressionBuilder;
- /** @var \OCP\IDBConnection */
+ /** @var IDBConnection */
protected $connection;
/** @var \Doctrine\DBAL\Connection */
protected $internalConnection;
+ /** @var LoggerInterface */
+ protected $logger;
+
protected function setUp(): void {
parent::setUp();
- $this->connection = \OC::$server->getDatabaseConnection();
- $this->internalConnection = \OC::$server->get(\OC\DB\Connection::class);
+ $this->connection = Server::get(IDBConnection::class);
+ $this->internalConnection = Server::get(\OC\DB\Connection::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
$queryBuilder = $this->createMock(IQueryBuilder::class);
- $this->expressionBuilder = new ExpressionBuilder($this->connection, $queryBuilder);
+ $this->expressionBuilder = new ExpressionBuilder($this->connection, $queryBuilder, $this->logger);
$this->doctrineExpressionBuilder = new DoctrineExpressionBuilder($this->internalConnection);
}
- public function dataComparison() {
- $valueSets = $this->dataComparisons();
+ public static function dataComparison(): array {
+ $valueSets = self::dataComparisons();
$comparisonOperators = ['=', '<>', '<', '>', '<=', '>='];
$testSets = [];
@@ -73,7 +67,6 @@ class ExpressionBuilderTest extends TestCase {
}
/**
- * @dataProvider dataComparison
*
* @param string $comparison
* @param mixed $input1
@@ -81,7 +74,8 @@ class ExpressionBuilderTest extends TestCase {
* @param mixed $input2
* @param bool $isInput2Literal
*/
- public function testComparison($comparison, $input1, $isInput1Literal, $input2, $isInput2Literal) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataComparison')]
+ public function testComparison($comparison, $input1, $isInput1Literal, $input2, $isInput2Literal): void {
[$doctrineInput1, $ocInput1] = $this->helpWithLiteral($input1, $isInput1Literal);
[$doctrineInput2, $ocInput2] = $this->helpWithLiteral($input2, $isInput2Literal);
@@ -91,7 +85,7 @@ class ExpressionBuilderTest extends TestCase {
);
}
- public function dataComparisons() {
+ public static function dataComparisons(): array {
return [
['value', false, 'value', false],
['value', false, 'value', true],
@@ -101,14 +95,14 @@ class ExpressionBuilderTest extends TestCase {
}
/**
- * @dataProvider dataComparisons
*
* @param mixed $input1
* @param bool $isInput1Literal
* @param mixed $input2
* @param bool $isInput2Literal
*/
- public function testEquals($input1, $isInput1Literal, $input2, $isInput2Literal) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataComparisons')]
+ public function testEquals($input1, $isInput1Literal, $input2, $isInput2Literal): void {
[$doctrineInput1, $ocInput1] = $this->helpWithLiteral($input1, $isInput1Literal);
[$doctrineInput2, $ocInput2] = $this->helpWithLiteral($input2, $isInput2Literal);
@@ -119,14 +113,14 @@ class ExpressionBuilderTest extends TestCase {
}
/**
- * @dataProvider dataComparisons
*
* @param mixed $input1
* @param bool $isInput1Literal
* @param mixed $input2
* @param bool $isInput2Literal
*/
- public function testNotEquals($input1, $isInput1Literal, $input2, $isInput2Literal) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataComparisons')]
+ public function testNotEquals($input1, $isInput1Literal, $input2, $isInput2Literal): void {
[$doctrineInput1, $ocInput1] = $this->helpWithLiteral($input1, $isInput1Literal);
[$doctrineInput2, $ocInput2] = $this->helpWithLiteral($input2, $isInput2Literal);
@@ -137,14 +131,14 @@ class ExpressionBuilderTest extends TestCase {
}
/**
- * @dataProvider dataComparisons
*
* @param mixed $input1
* @param bool $isInput1Literal
* @param mixed $input2
* @param bool $isInput2Literal
*/
- public function testLowerThan($input1, $isInput1Literal, $input2, $isInput2Literal) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataComparisons')]
+ public function testLowerThan($input1, $isInput1Literal, $input2, $isInput2Literal): void {
[$doctrineInput1, $ocInput1] = $this->helpWithLiteral($input1, $isInput1Literal);
[$doctrineInput2, $ocInput2] = $this->helpWithLiteral($input2, $isInput2Literal);
@@ -155,14 +149,14 @@ class ExpressionBuilderTest extends TestCase {
}
/**
- * @dataProvider dataComparisons
*
* @param mixed $input1
* @param bool $isInput1Literal
* @param mixed $input2
* @param bool $isInput2Literal
*/
- public function testLowerThanEquals($input1, $isInput1Literal, $input2, $isInput2Literal) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataComparisons')]
+ public function testLowerThanEquals($input1, $isInput1Literal, $input2, $isInput2Literal): void {
[$doctrineInput1, $ocInput1] = $this->helpWithLiteral($input1, $isInput1Literal);
[$doctrineInput2, $ocInput2] = $this->helpWithLiteral($input2, $isInput2Literal);
@@ -173,14 +167,14 @@ class ExpressionBuilderTest extends TestCase {
}
/**
- * @dataProvider dataComparisons
*
* @param mixed $input1
* @param bool $isInput1Literal
* @param mixed $input2
* @param bool $isInput2Literal
*/
- public function testGreaterThan($input1, $isInput1Literal, $input2, $isInput2Literal) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataComparisons')]
+ public function testGreaterThan($input1, $isInput1Literal, $input2, $isInput2Literal): void {
[$doctrineInput1, $ocInput1] = $this->helpWithLiteral($input1, $isInput1Literal);
[$doctrineInput2, $ocInput2] = $this->helpWithLiteral($input2, $isInput2Literal);
@@ -191,14 +185,14 @@ class ExpressionBuilderTest extends TestCase {
}
/**
- * @dataProvider dataComparisons
*
* @param mixed $input1
* @param bool $isInput1Literal
* @param mixed $input2
* @param bool $isInput2Literal
*/
- public function testGreaterThanEquals($input1, $isInput1Literal, $input2, $isInput2Literal) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataComparisons')]
+ public function testGreaterThanEquals($input1, $isInput1Literal, $input2, $isInput2Literal): void {
[$doctrineInput1, $ocInput1] = $this->helpWithLiteral($input1, $isInput1Literal);
[$doctrineInput2, $ocInput2] = $this->helpWithLiteral($input2, $isInput2Literal);
@@ -208,21 +202,21 @@ class ExpressionBuilderTest extends TestCase {
);
}
- public function testIsNull() {
+ public function testIsNull(): void {
$this->assertEquals(
$this->doctrineExpressionBuilder->isNull('`test`'),
$this->expressionBuilder->isNull('test')
);
}
- public function testIsNotNull() {
+ public function testIsNotNull(): void {
$this->assertEquals(
$this->doctrineExpressionBuilder->isNotNull('`test`'),
$this->expressionBuilder->isNotNull('test')
);
}
- public function dataLike() {
+ public static function dataLike(): array {
return [
['value', false],
['value', true],
@@ -230,12 +224,12 @@ class ExpressionBuilderTest extends TestCase {
}
/**
- * @dataProvider dataLike
*
* @param mixed $input
* @param bool $isLiteral
*/
- public function testLike($input, $isLiteral) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataLike')]
+ public function testLike($input, $isLiteral): void {
[$doctrineInput, $ocInput] = $this->helpWithLiteral($input, $isLiteral);
$this->assertEquals(
@@ -245,12 +239,12 @@ class ExpressionBuilderTest extends TestCase {
}
/**
- * @dataProvider dataLike
*
* @param mixed $input
* @param bool $isLiteral
*/
- public function testNotLike($input, $isLiteral) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataLike')]
+ public function testNotLike($input, $isLiteral): void {
[$doctrineInput, $ocInput] = $this->helpWithLiteral($input, $isLiteral);
$this->assertEquals(
@@ -259,7 +253,7 @@ class ExpressionBuilderTest extends TestCase {
);
}
- public function dataIn() {
+ public static function dataIn(): array {
return [
['value', false],
['value', true],
@@ -269,12 +263,12 @@ class ExpressionBuilderTest extends TestCase {
}
/**
- * @dataProvider dataIn
*
* @param mixed $input
* @param bool $isLiteral
*/
- public function testIn($input, $isLiteral) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataIn')]
+ public function testIn($input, $isLiteral): void {
[$doctrineInput, $ocInput] = $this->helpWithLiteral($input, $isLiteral);
$this->assertEquals(
@@ -284,12 +278,12 @@ class ExpressionBuilderTest extends TestCase {
}
/**
- * @dataProvider dataIn
*
* @param mixed $input
* @param bool $isLiteral
*/
- public function testNotIn($input, $isLiteral) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataIn')]
+ public function testNotIn($input, $isLiteral): void {
[$doctrineInput, $ocInput] = $this->helpWithLiteral($input, $isLiteral);
$this->assertEquals(
@@ -326,7 +320,7 @@ class ExpressionBuilderTest extends TestCase {
return [$doctrineInput, $ocInput];
}
- public function dataLiteral() {
+ public static function dataLiteral(): array {
return [
['value', null],
['1', null],
@@ -338,12 +332,12 @@ class ExpressionBuilderTest extends TestCase {
}
/**
- * @dataProvider dataLiteral
*
* @param mixed $input
* @param string|null $type
*/
- public function testLiteral($input, $type) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataLiteral')]
+ public function testLiteral($input, $type): void {
/** @var \OC\DB\QueryBuilder\Literal $actual */
$actual = $this->expressionBuilder->literal($input, $type);
@@ -354,7 +348,7 @@ class ExpressionBuilderTest extends TestCase {
);
}
- public function dataClobComparisons() {
+ public static function dataClobComparisons(): array {
return [
['eq', '5', IQueryBuilder::PARAM_STR, false, 3],
['eq', '5', IQueryBuilder::PARAM_STR, true, 1],
@@ -382,14 +376,14 @@ class ExpressionBuilderTest extends TestCase {
}
/**
- * @dataProvider dataClobComparisons
* @param string $function
* @param mixed $value
* @param mixed $type
* @param bool $compareKeyToValue
* @param int $expected
*/
- public function testClobComparisons($function, $value, $type, $compareKeyToValue, $expected) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataClobComparisons')]
+ public function testClobComparisons($function, $value, $type, $compareKeyToValue, $expected): void {
$appId = $this->getUniqueID('testing');
$this->createConfig($appId, 1, 4);
$this->createConfig($appId, 2, 5);
@@ -429,8 +423,8 @@ class ExpressionBuilderTest extends TestCase {
$query->insert('appconfig')
->values([
'appid' => $query->createNamedParameter($appId),
- 'configkey' => $query->createNamedParameter((string) $key),
- 'configvalue' => $query->createNamedParameter((string) $value),
+ 'configkey' => $query->createNamedParameter((string)$key),
+ 'configvalue' => $query->createNamedParameter((string)$value),
])
->execute();
}
diff --git a/tests/lib/DB/QueryBuilder/FunctionBuilderTest.php b/tests/lib/DB/QueryBuilder/FunctionBuilderTest.php
index 08392b09d8d..5a111c91aa7 100644
--- a/tests/lib/DB/QueryBuilder/FunctionBuilderTest.php
+++ b/tests/lib/DB/QueryBuilder/FunctionBuilderTest.php
@@ -1,27 +1,16 @@
<?php
+
/**
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace Test\DB\QueryBuilder;
use OC\DB\QueryBuilder\Literal;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+use OCP\Server;
use Test\TestCase;
/**
@@ -32,24 +21,23 @@ use Test\TestCase;
* @package Test\DB\QueryBuilder
*/
class FunctionBuilderTest extends TestCase {
- /** @var \Doctrine\DBAL\Connection|\OCP\IDBConnection */
+ /** @var \Doctrine\DBAL\Connection|IDBConnection */
protected $connection;
protected function setUp(): void {
parent::setUp();
- $this->connection = \OC::$server->getDatabaseConnection();
+ $this->connection = Server::get(IDBConnection::class);
}
- /**
- * @dataProvider providerTestConcatString
- */
- public function testConcatString($closure) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providerTestConcatString')]
+ public function testConcatString($closure): void {
$query = $this->connection->getQueryBuilder();
[$real, $arguments, $return] = $closure($query);
if ($real) {
$this->addDummyData();
$query->where($query->expr()->eq('appid', $query->createNamedParameter('group_concat')));
+ $query->orderBy('configkey', 'asc');
}
$query->select($query->func()->concat(...$arguments));
@@ -62,39 +50,39 @@ class FunctionBuilderTest extends TestCase {
$this->assertEquals($return, $column);
}
- public function providerTestConcatString(): array {
+ public static function providerTestConcatString(): array {
return [
- '1 column: string param unicode' =>
- [function ($q) {
+ '1 column: string param unicode'
+ => [function ($q) {
return [false, [$q->createNamedParameter('👍')], '👍'];
}],
- '2 columns: string param and string param' =>
- [function ($q) {
+ '2 columns: string param and string param'
+ => [function ($q) {
return [false, [$q->createNamedParameter('foo'), $q->createNamedParameter('bar')], 'foobar'];
}],
- '2 columns: string param and int literal' =>
- [function ($q) {
+ '2 columns: string param and int literal'
+ => [function ($q) {
return [false, [$q->createNamedParameter('foo'), $q->expr()->literal(1)], 'foo1'];
}],
- '2 columns: string param and string literal' =>
- [function ($q) {
+ '2 columns: string param and string literal'
+ => [function ($q) {
return [false, [$q->createNamedParameter('foo'), $q->expr()->literal('bar')], 'foobar'];
}],
- '2 columns: string real and int literal' =>
- [function ($q) {
+ '2 columns: string real and int literal'
+ => [function ($q) {
return [true, ['configkey', $q->expr()->literal(2)], '12'];
}],
- '4 columns: string literal' =>
- [function ($q) {
+ '4 columns: string literal'
+ => [function ($q) {
return [false, [$q->expr()->literal('foo'), $q->expr()->literal('bar'), $q->expr()->literal('foo'), $q->expr()->literal('bar')], 'foobarfoobar'];
}],
- '4 columns: int literal' =>
- [function ($q) {
+ '4 columns: int literal'
+ => [function ($q) {
return [false, [$q->expr()->literal(1), $q->expr()->literal(2), $q->expr()->literal(3), $q->expr()->literal(4)], '1234'];
}],
- '5 columns: string param with special chars used in the function' =>
- [function ($q) {
- return [false, [$q->createNamedParameter("b"), $q->createNamedParameter("'"), $q->createNamedParameter('||'), $q->createNamedParameter(','), $q->createNamedParameter('a')], "b'||,a"];
+ '5 columns: string param with special chars used in the function'
+ => [function ($q) {
+ return [false, [$q->createNamedParameter('b'), $q->createNamedParameter("'"), $q->createNamedParameter('||'), $q->createNamedParameter(','), $q->createNamedParameter('a')], "b'||,a"];
}],
];
}
@@ -245,7 +233,7 @@ class FunctionBuilderTest extends TestCase {
$this->assertEqualsCanonicalizing([1,2,3], $actual);
}
- public function testMd5() {
+ public function testMd5(): void {
$query = $this->connection->getQueryBuilder();
$query->select($query->func()->md5($query->createNamedParameter('foobar')));
@@ -258,7 +246,7 @@ class FunctionBuilderTest extends TestCase {
$this->assertEquals(md5('foobar'), $column);
}
- public function testSubstring() {
+ public function testSubstring(): void {
$query = $this->connection->getQueryBuilder();
$query->select($query->func()->substring($query->createNamedParameter('foobar'), new Literal(2), $query->createNamedParameter(2)));
@@ -271,7 +259,7 @@ class FunctionBuilderTest extends TestCase {
$this->assertEquals('oo', $column);
}
- public function testSubstringNoLength() {
+ public function testSubstringNoLength(): void {
$query = $this->connection->getQueryBuilder();
$query->select($query->func()->substring($query->createNamedParameter('foobar'), new Literal(2)));
@@ -284,7 +272,7 @@ class FunctionBuilderTest extends TestCase {
$this->assertEquals('oobar', $column);
}
- public function testLower() {
+ public function testLower(): void {
$query = $this->connection->getQueryBuilder();
$query->select($query->func()->lower($query->createNamedParameter('FooBar')));
@@ -297,7 +285,7 @@ class FunctionBuilderTest extends TestCase {
$this->assertEquals('foobar', $column);
}
- public function testAdd() {
+ public function testAdd(): void {
$query = $this->connection->getQueryBuilder();
$query->select($query->func()->add($query->createNamedParameter(2, IQueryBuilder::PARAM_INT), new Literal(1)));
@@ -310,7 +298,7 @@ class FunctionBuilderTest extends TestCase {
$this->assertEquals(3, $column);
}
- public function testSubtract() {
+ public function testSubtract(): void {
$query = $this->connection->getQueryBuilder();
$query->select($query->func()->subtract($query->createNamedParameter(2, IQueryBuilder::PARAM_INT), new Literal(1)));
@@ -323,7 +311,7 @@ class FunctionBuilderTest extends TestCase {
$this->assertEquals(1, $column);
}
- public function testCount() {
+ public function testCount(): void {
$query = $this->connection->getQueryBuilder();
$query->select($query->func()->count('appid'));
@@ -336,7 +324,7 @@ class FunctionBuilderTest extends TestCase {
$this->assertGreaterThan(1, $column);
}
- public function octetLengthProvider() {
+ public static function octetLengthProvider(): array {
return [
['', 0],
['foobar', 6],
@@ -345,10 +333,8 @@ class FunctionBuilderTest extends TestCase {
];
}
- /**
- * @dataProvider octetLengthProvider
- */
- public function testOctetLength(string $str, int $bytes) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('octetLengthProvider')]
+ public function testOctetLength(string $str, int $bytes): void {
$query = $this->connection->getQueryBuilder();
$query->select($query->func()->octetLength($query->createNamedParameter($str, IQueryBuilder::PARAM_STR)));
@@ -361,7 +347,7 @@ class FunctionBuilderTest extends TestCase {
$this->assertEquals($bytes, $column);
}
- public function charLengthProvider() {
+ public static function charLengthProvider(): array {
return [
['', 0],
['foobar', 6],
@@ -370,10 +356,8 @@ class FunctionBuilderTest extends TestCase {
];
}
- /**
- * @dataProvider charLengthProvider
- */
- public function testCharLength(string $str, int $bytes) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('charLengthProvider')]
+ public function testCharLength(string $str, int $bytes): void {
$query = $this->connection->getQueryBuilder();
$query->select($query->func()->charLength($query->createNamedParameter($str, IQueryBuilder::PARAM_STR)));
@@ -383,6 +367,7 @@ class FunctionBuilderTest extends TestCase {
$result = $query->execute();
$column = $result->fetchOne();
$result->closeCursor();
+ $this->assertNotNull($column);
$this->assertEquals($bytes, $column);
}
@@ -406,7 +391,7 @@ class FunctionBuilderTest extends TestCase {
$query->execute();
}
- public function testMaxEmpty() {
+ public function testMaxEmpty(): void {
$this->clearMinMax();
$query = $this->connection->getQueryBuilder();
@@ -422,7 +407,7 @@ class FunctionBuilderTest extends TestCase {
$this->assertEquals(null, $row);
}
- public function testMinEmpty() {
+ public function testMinEmpty(): void {
$this->clearMinMax();
$query = $this->connection->getQueryBuilder();
@@ -438,7 +423,7 @@ class FunctionBuilderTest extends TestCase {
$this->assertEquals(null, $row);
}
- public function testMax() {
+ public function testMax(): void {
$this->clearMinMax();
$this->setUpMinMax(10);
$this->setUpMinMax(11);
@@ -457,7 +442,7 @@ class FunctionBuilderTest extends TestCase {
$this->assertEquals(20, $row);
}
- public function testMin() {
+ public function testMin(): void {
$this->clearMinMax();
$this->setUpMinMax(10);
$this->setUpMinMax(11);
@@ -476,7 +461,7 @@ class FunctionBuilderTest extends TestCase {
$this->assertEquals(10, $row);
}
- public function testGreatest() {
+ public function testGreatest(): void {
$query = $this->connection->getQueryBuilder();
$query->select($query->func()->greatest($query->createNamedParameter(2, IQueryBuilder::PARAM_INT), new Literal(1)));
@@ -489,7 +474,7 @@ class FunctionBuilderTest extends TestCase {
$this->assertEquals(2, $row);
}
- public function testLeast() {
+ public function testLeast(): void {
$query = $this->connection->getQueryBuilder();
$query->select($query->func()->least($query->createNamedParameter(2, IQueryBuilder::PARAM_INT), new Literal(1)));
diff --git a/tests/lib/DB/QueryBuilder/Partitioned/JoinConditionTest.php b/tests/lib/DB/QueryBuilder/Partitioned/JoinConditionTest.php
new file mode 100644
index 00000000000..8f84d6a0d2c
--- /dev/null
+++ b/tests/lib/DB/QueryBuilder/Partitioned/JoinConditionTest.php
@@ -0,0 +1,74 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2024 Robin Appelman <robin@icewind.nl>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace lib\DB\QueryBuilder\Partitioned;
+
+use OC\DB\ConnectionAdapter;
+use OC\DB\QueryBuilder\Partitioned\JoinCondition;
+use OC\DB\QueryBuilder\QueryBuilder;
+use OC\SystemConfig;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+use Psr\Log\LoggerInterface;
+use Test\TestCase;
+
+class JoinConditionTest extends TestCase {
+ protected function setUp(): void {
+ parent::setUp();
+ }
+
+ public static function platformProvider(): array {
+ return [
+ [IDBConnection::PLATFORM_SQLITE],
+ [IDBConnection::PLATFORM_POSTGRES],
+ [IDBConnection::PLATFORM_MYSQL],
+ [IDBConnection::PLATFORM_ORACLE],
+ ];
+ }
+
+ private function getBuilder(string $platform): IQueryBuilder {
+ $connection = $this->createMock(ConnectionAdapter::class);
+ $connection->method('getDatabaseProvider')->willReturn($platform);
+ return new QueryBuilder(
+ $connection,
+ $this->createMock(SystemConfig::class),
+ $this->createMock(LoggerInterface::class)
+ );
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('platformProvider')]
+ public function testParseCondition(string $platform): void {
+ $query = $this->getBuilder($platform);
+ $param1 = $query->createNamedParameter('files');
+ $param2 = $query->createNamedParameter('test');
+ $condition = $query->expr()->andX(
+ $query->expr()->eq('tagmap.categoryid', 'tag.id'),
+ $query->expr()->eq('tag.type', $param1),
+ $query->expr()->eq('tag.uid', $param2)
+ );
+ $parsed = JoinCondition::parse($condition, 'vcategory', 'tag', 'tagmap');
+ $this->assertEquals('tagmap.categoryid', $parsed->fromColumn);
+ $this->assertEquals('tag.id', $parsed->toColumn);
+ $this->assertEquals([], $parsed->fromConditions);
+ $this->assertEquals([
+ $query->expr()->eq('tag.type', $param1),
+ $query->expr()->eq('tag.uid', $param2),
+ ], $parsed->toConditions);
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('platformProvider')]
+ public function testParseCastCondition(string $platform): void {
+ $query = $this->getBuilder($platform);
+
+ $condition = $query->expr()->eq($query->expr()->castColumn('m.objectid', IQueryBuilder::PARAM_INT), 'f.fileid');
+ $parsed = JoinCondition::parse($condition, 'filecache', 'f', 'm');
+ $this->assertEquals('m.objectid', $parsed->fromColumn);
+ $this->assertEquals('f.fileid', $parsed->toColumn);
+ $this->assertEquals([], $parsed->fromConditions);
+ }
+}
diff --git a/tests/lib/DB/QueryBuilder/Partitioned/PartitionedQueryBuilderTest.php b/tests/lib/DB/QueryBuilder/Partitioned/PartitionedQueryBuilderTest.php
new file mode 100644
index 00000000000..f99adc73aa8
--- /dev/null
+++ b/tests/lib/DB/QueryBuilder/Partitioned/PartitionedQueryBuilderTest.php
@@ -0,0 +1,223 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+declare(strict_types=1);
+
+namespace Test\DB\QueryBuilder\Partitioned;
+
+use OC\DB\QueryBuilder\Partitioned\PartitionedQueryBuilder;
+use OC\DB\QueryBuilder\Partitioned\PartitionSplit;
+use OC\DB\QueryBuilder\Sharded\AutoIncrementHandler;
+use OC\DB\QueryBuilder\Sharded\ShardConnectionManager;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+use OCP\Server;
+use Test\TestCase;
+
+/**
+ * @group DB
+ */
+class PartitionedQueryBuilderTest extends TestCase {
+ private IDBConnection $connection;
+ private ShardConnectionManager $shardConnectionManager;
+ private AutoIncrementHandler $autoIncrementHandler;
+
+ protected function setUp(): void {
+ if (PHP_INT_SIZE < 8) {
+ $this->markTestSkipped('Test requires 64bit');
+ }
+ $this->connection = Server::get(IDBConnection::class);
+ $this->shardConnectionManager = Server::get(ShardConnectionManager::class);
+ $this->autoIncrementHandler = Server::get(AutoIncrementHandler::class);
+
+ $this->setupFileCache();
+ }
+
+ protected function tearDown(): void {
+ $this->cleanupDb();
+ parent::tearDown();
+ }
+
+
+ private function getQueryBuilder(): PartitionedQueryBuilder {
+ $builder = $this->connection->getQueryBuilder();
+ if ($builder instanceof PartitionedQueryBuilder) {
+ return $builder;
+ } else {
+ return new PartitionedQueryBuilder($builder, [], $this->shardConnectionManager, $this->autoIncrementHandler);
+ }
+ }
+
+ private function setupFileCache(): void {
+ $this->cleanupDb();
+ $query = $this->getQueryBuilder();
+ $query->insert('storages')
+ ->values([
+ 'numeric_id' => $query->createNamedParameter(1001001, IQueryBuilder::PARAM_INT),
+ 'id' => $query->createNamedParameter('test1'),
+ ]);
+ $query->executeStatement();
+
+ $query = $this->getQueryBuilder();
+ $query->insert('filecache')
+ ->values([
+ 'storage' => $query->createNamedParameter(1001001, IQueryBuilder::PARAM_INT),
+ 'path' => $query->createNamedParameter('file1'),
+ 'path_hash' => $query->createNamedParameter(md5('file1')),
+ ]);
+ $query->executeStatement();
+ $fileId = $query->getLastInsertId();
+
+ $query = $this->getQueryBuilder();
+ $query->insert('filecache_extended')
+ ->hintShardKey('storage', 1001001)
+ ->values([
+ 'fileid' => $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT),
+ 'upload_time' => $query->createNamedParameter(1234, IQueryBuilder::PARAM_INT),
+ ]);
+ $query->executeStatement();
+
+ $query = $this->getQueryBuilder();
+ $query->insert('mounts')
+ ->values([
+ 'storage_id' => $query->createNamedParameter(1001001, IQueryBuilder::PARAM_INT),
+ 'user_id' => $query->createNamedParameter('partitioned_test'),
+ 'mount_point' => $query->createNamedParameter('/mount/point'),
+ 'mount_provider_class' => $query->createNamedParameter('test'),
+ 'root_id' => $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT),
+ ]);
+ $query->executeStatement();
+ }
+
+ private function cleanupDb(): void {
+ $query = $this->getQueryBuilder();
+ $query->delete('storages')
+ ->where($query->expr()->gt('numeric_id', $query->createNamedParameter(1000000, IQueryBuilder::PARAM_INT)));
+ $query->executeStatement();
+
+ $query = $this->getQueryBuilder();
+ $query->delete('filecache')
+ ->where($query->expr()->gt('storage', $query->createNamedParameter(1000000, IQueryBuilder::PARAM_INT)))
+ ->runAcrossAllShards();
+ $query->executeStatement();
+
+ $query = $this->getQueryBuilder();
+ $query->delete('filecache_extended')
+ ->runAcrossAllShards();
+ $query->executeStatement();
+
+ $query = $this->getQueryBuilder();
+ $query->delete('mounts')
+ ->where($query->expr()->like('user_id', $query->createNamedParameter('partitioned_%')));
+ $query->executeStatement();
+ }
+
+ public function testSimpleOnlyPartitionQuery(): void {
+ $builder = $this->getQueryBuilder();
+ $builder->addPartition(new PartitionSplit('filecache', ['filecache']));
+
+ // query borrowed from UserMountCache
+ $query = $builder->select('path')
+ ->from('filecache')
+ ->where($builder->expr()->eq('storage', $builder->createNamedParameter(1001001, IQueryBuilder::PARAM_INT)));
+
+ $results = $query->executeQuery()->fetchAll();
+ $this->assertCount(1, $results);
+ $this->assertEquals($results[0]['path'], 'file1');
+ }
+
+ public function testSimplePartitionedQuery(): void {
+ $builder = $this->getQueryBuilder();
+ $builder->addPartition(new PartitionSplit('filecache', ['filecache']));
+
+ // query borrowed from UserMountCache
+ $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path', 'mount_provider_class')
+ ->from('mounts', 'm')
+ ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid'))
+ ->where($builder->expr()->eq('storage_id', $builder->createNamedParameter(1001001, IQueryBuilder::PARAM_INT)));
+
+ $query->andWhere($builder->expr()->eq('user_id', $builder->createNamedParameter('partitioned_test')));
+
+ $this->assertEquals(2, $query->getPartitionCount());
+
+ $results = $query->executeQuery()->fetchAll();
+ $this->assertCount(1, $results);
+ $this->assertEquals($results[0]['user_id'], 'partitioned_test');
+ $this->assertEquals($results[0]['mount_point'], '/mount/point');
+ $this->assertEquals($results[0]['mount_provider_class'], 'test');
+ $this->assertEquals($results[0]['path'], 'file1');
+ }
+
+ public function testMultiTablePartitionedQuery(): void {
+ $builder = $this->getQueryBuilder();
+ $builder->addPartition(new PartitionSplit('filecache', ['filecache', 'filecache_extended']));
+
+ $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path', 'mount_provider_class', 'fe.upload_time')
+ ->from('mounts', 'm')
+ ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid'))
+ ->innerJoin('f', 'filecache_extended', 'fe', $builder->expr()->eq('f.fileid', 'fe.fileid'))
+ ->where($builder->expr()->eq('storage_id', $builder->createNamedParameter(1001001, IQueryBuilder::PARAM_INT)));
+
+ $query->andWhere($builder->expr()->eq('user_id', $builder->createNamedParameter('partitioned_test')));
+
+ $this->assertEquals(2, $query->getPartitionCount());
+
+ $results = $query->executeQuery()->fetchAll();
+ $this->assertCount(1, $results);
+ $this->assertEquals($results[0]['user_id'], 'partitioned_test');
+ $this->assertEquals($results[0]['mount_point'], '/mount/point');
+ $this->assertEquals($results[0]['mount_provider_class'], 'test');
+ $this->assertEquals($results[0]['path'], 'file1');
+ $this->assertEquals($results[0]['upload_time'], 1234);
+ }
+
+ public function testPartitionedQueryFromSplit(): void {
+ $builder = $this->getQueryBuilder();
+ $builder->addPartition(new PartitionSplit('filecache', ['filecache']));
+
+ $query = $builder->select('storage', 'm.root_id', 'm.user_id', 'm.mount_point', 'm.mount_id', 'path', 'm.mount_provider_class')
+ ->from('filecache', 'f')
+ ->innerJoin('f', 'mounts', 'm', $builder->expr()->eq('m.root_id', 'f.fileid'));
+ $query->where($builder->expr()->eq('storage', $builder->createNamedParameter(1001001, IQueryBuilder::PARAM_INT)));
+
+ $query->andWhere($builder->expr()->eq('m.user_id', $builder->createNamedParameter('partitioned_test')));
+
+ $this->assertEquals(2, $query->getPartitionCount());
+
+ $results = $query->executeQuery()->fetchAll();
+ $this->assertCount(1, $results);
+ $this->assertEquals($results[0]['user_id'], 'partitioned_test');
+ $this->assertEquals($results[0]['mount_point'], '/mount/point');
+ $this->assertEquals($results[0]['mount_provider_class'], 'test');
+ $this->assertEquals($results[0]['path'], 'file1');
+ }
+
+ public function testMultiJoinPartitionedQuery(): void {
+ $builder = $this->getQueryBuilder();
+ $builder->addPartition(new PartitionSplit('filecache', ['filecache']));
+
+ // query borrowed from UserMountCache
+ $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path', 'mount_provider_class')
+ ->selectAlias('s.id', 'storage_string_id')
+ ->from('mounts', 'm')
+ ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid'))
+ ->innerJoin('f', 'storages', 's', $builder->expr()->eq('f.storage', 's.numeric_id'))
+ ->where($builder->expr()->eq('storage_id', $builder->createNamedParameter(1001001, IQueryBuilder::PARAM_INT)));
+
+ $query->andWhere($builder->expr()->eq('user_id', $builder->createNamedParameter('partitioned_test')));
+
+ $this->assertEquals(3, $query->getPartitionCount());
+
+ $results = $query->executeQuery()->fetchAll();
+ $this->assertCount(1, $results);
+ $this->assertEquals($results[0]['user_id'], 'partitioned_test');
+ $this->assertEquals($results[0]['mount_point'], '/mount/point');
+ $this->assertEquals($results[0]['mount_provider_class'], 'test');
+ $this->assertEquals($results[0]['path'], 'file1');
+ $this->assertEquals($results[0]['storage_string_id'], 'test1');
+ }
+}
diff --git a/tests/lib/DB/QueryBuilder/QueryBuilderTest.php b/tests/lib/DB/QueryBuilder/QueryBuilderTest.php
index 6e9a7a84925..990191a9ff5 100644
--- a/tests/lib/DB/QueryBuilder/QueryBuilderTest.php
+++ b/tests/lib/DB/QueryBuilder/QueryBuilderTest.php
@@ -1,35 +1,24 @@
<?php
+
/**
- * @author Joas Schilling <nickvergessen@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace Test\DB\QueryBuilder;
use Doctrine\DBAL\Query\Expression\CompositeExpression;
use Doctrine\DBAL\Query\QueryException;
-use Doctrine\DBAL\Result;
use OC\DB\QueryBuilder\Literal;
use OC\DB\QueryBuilder\Parameter;
use OC\DB\QueryBuilder\QueryBuilder;
use OC\SystemConfig;
+use OCP\DB\IResult;
+use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\DB\QueryBuilder\IQueryFunction;
use OCP\IDBConnection;
+use OCP\Server;
use Psr\Log\LoggerInterface;
/**
@@ -55,7 +44,7 @@ class QueryBuilderTest extends \Test\TestCase {
protected function setUp(): void {
parent::setUp();
- $this->connection = \OC::$server->getDatabaseConnection();
+ $this->connection = Server::get(IDBConnection::class);
$this->config = $this->createMock(SystemConfig::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->queryBuilder = new QueryBuilder($this->connection, $this->config, $this->logger);
@@ -101,7 +90,7 @@ class QueryBuilderTest extends \Test\TestCase {
->execute();
}
- public function dataFirstResult() {
+ public static function dataFirstResult(): array {
return [
[0, [99, 98, 97, 96, 95, 94, 93, 92, 91]],
[0, [99, 98, 97, 96, 95, 94, 93, 92, 91]],
@@ -111,12 +100,12 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataFirstResult
*
* @param int|null $firstResult
* @param array $expectedSet
*/
- public function testFirstResult($firstResult, $expectedSet) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataFirstResult')]
+ public function testFirstResult($firstResult, $expectedSet): void {
$this->deleteTestingRows();
$this->createTestingRows();
@@ -137,7 +126,7 @@ class QueryBuilderTest extends \Test\TestCase {
$this->deleteTestingRows();
}
- public function dataMaxResults() {
+ public static function dataMaxResults(): array {
return [
[null, [99, 98, 97, 96, 95, 94, 93, 92, 91]],
// Limit 0 gives mixed results: either all entries or none is returned
@@ -148,12 +137,12 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataMaxResults
*
* @param int $maxResult
* @param array $expectedSet
*/
- public function testMaxResults($maxResult, $expectedSet) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataMaxResults')]
+ public function testMaxResults($maxResult, $expectedSet): void {
$this->deleteTestingRows();
$this->createTestingRows();
@@ -174,10 +163,10 @@ class QueryBuilderTest extends \Test\TestCase {
$this->deleteTestingRows();
}
- public function dataSelect() {
+ public function dataSelect(): array {
$config = $this->createMock(SystemConfig::class);
$logger = $this->createMock(LoggerInterface::class);
- $queryBuilder = new QueryBuilder(\OC::$server->getDatabaseConnection(), $config, $logger);
+ $queryBuilder = new QueryBuilder(Server::get(IDBConnection::class), $config, $logger);
return [
// select('column1')
[['configvalue'], ['configvalue' => '99']],
@@ -200,13 +189,13 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataSelect
*
* @param array $selectArguments
* @param array $expected
* @param string $expectedLiteral
*/
- public function testSelect($selectArguments, $expected, $expectedLiteral = '') {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataSelect')]
+ public function testSelect($selectArguments, $expected, $expectedLiteral = ''): void {
$this->deleteTestingRows();
$this->createTestingRows();
@@ -242,10 +231,10 @@ class QueryBuilderTest extends \Test\TestCase {
$this->deleteTestingRows();
}
- public function dataSelectAlias() {
+ public function dataSelectAlias(): array {
$config = $this->createMock(SystemConfig::class);
$logger = $this->createMock(LoggerInterface::class);
- $queryBuilder = new QueryBuilder(\OC::$server->getDatabaseConnection(), $config, $logger);
+ $queryBuilder = new QueryBuilder(Server::get(IDBConnection::class), $config, $logger);
return [
['configvalue', 'cv', ['cv' => '99']],
[$queryBuilder->expr()->literal('column1'), 'thing', ['thing' => 'column1']],
@@ -253,13 +242,13 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataSelectAlias
*
* @param mixed $select
* @param array $alias
* @param array $expected
*/
- public function testSelectAlias($select, $alias, $expected) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataSelectAlias')]
+ public function testSelectAlias($select, $alias, $expected): void {
$this->deleteTestingRows();
$this->createTestingRows();
@@ -285,7 +274,7 @@ class QueryBuilderTest extends \Test\TestCase {
$this->deleteTestingRows();
}
- public function testSelectDistinct() {
+ public function testSelectDistinct(): void {
$this->deleteTestingRows('testFirstResult1');
$this->deleteTestingRows('testFirstResult2');
$this->createTestingRows('testFirstResult1');
@@ -313,7 +302,7 @@ class QueryBuilderTest extends \Test\TestCase {
$this->deleteTestingRows('testFirstResult2');
}
- public function testSelectDistinctMultiple() {
+ public function testSelectDistinctMultiple(): void {
$this->deleteTestingRows('testFirstResult1');
$this->deleteTestingRows('testFirstResult2');
$this->createTestingRows('testFirstResult1');
@@ -326,7 +315,7 @@ class QueryBuilderTest extends \Test\TestCase {
'appid',
$this->queryBuilder->expr()->literal('testFirstResult1')
))
- ->orderBy('appid', 'DESC');
+ ->orderBy('configkey', 'ASC');
$query = $this->queryBuilder->execute();
$rows = $query->fetchAll();
@@ -351,10 +340,10 @@ class QueryBuilderTest extends \Test\TestCase {
$this->deleteTestingRows('testFirstResult2');
}
- public function dataAddSelect() {
+ public function dataAddSelect(): array {
$config = $this->createMock(SystemConfig::class);
$logger = $this->createMock(LoggerInterface::class);
- $queryBuilder = new QueryBuilder(\OC::$server->getDatabaseConnection(), $config, $logger);
+ $queryBuilder = new QueryBuilder(Server::get(IDBConnection::class), $config, $logger);
return [
// addSelect('column1')
[['configvalue'], ['appid' => 'testFirstResult', 'configvalue' => '99']],
@@ -377,13 +366,13 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataAddSelect
*
* @param array $selectArguments
* @param array $expected
* @param string $expectedLiteral
*/
- public function testAddSelect($selectArguments, $expected, $expectedLiteral = '') {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataAddSelect')]
+ public function testAddSelect($selectArguments, $expected, $expectedLiteral = ''): void {
$this->deleteTestingRows();
$this->createTestingRows();
@@ -421,7 +410,7 @@ class QueryBuilderTest extends \Test\TestCase {
$this->deleteTestingRows();
}
- public function dataDelete() {
+ public static function dataDelete(): array {
return [
['data', null, ['table' => '`*PREFIX*data`', 'alias' => null], '`*PREFIX*data`'],
['data', 't', ['table' => '`*PREFIX*data`', 'alias' => 't'], '`*PREFIX*data` t'],
@@ -429,14 +418,14 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataDelete
*
* @param string $tableName
* @param string $tableAlias
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testDelete($tableName, $tableAlias, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataDelete')]
+ public function testDelete($tableName, $tableAlias, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->delete($tableName, $tableAlias);
$this->assertSame(
@@ -450,7 +439,7 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataUpdate() {
+ public static function dataUpdate(): array {
return [
['data', null, ['table' => '`*PREFIX*data`', 'alias' => null], '`*PREFIX*data`'],
['data', 't', ['table' => '`*PREFIX*data`', 'alias' => 't'], '`*PREFIX*data` t'],
@@ -458,14 +447,14 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataUpdate
*
* @param string $tableName
* @param string $tableAlias
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testUpdate($tableName, $tableAlias, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataUpdate')]
+ public function testUpdate($tableName, $tableAlias, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->update($tableName, $tableAlias);
$this->assertSame(
@@ -479,20 +468,20 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataInsert() {
+ public static function dataInsert(): array {
return [
['data', ['table' => '`*PREFIX*data`'], '`*PREFIX*data`'],
];
}
/**
- * @dataProvider dataInsert
*
* @param string $tableName
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testInsert($tableName, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataInsert')]
+ public function testInsert($tableName, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->insert($tableName);
$this->assertSame(
@@ -506,10 +495,10 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataFrom() {
+ public function dataFrom(): array {
$config = $this->createMock(SystemConfig::class);
$logger = $this->createMock(LoggerInterface::class);
- $qb = new QueryBuilder(\OC::$server->getDatabaseConnection(), $config, $logger);
+ $qb = new QueryBuilder(Server::get(IDBConnection::class), $config, $logger);
return [
[$qb->createFunction('(' . $qb->select('*')->from('test')->getSQL() . ')'), 'q', null, null, [
['table' => '(SELECT * FROM `*PREFIX*test`)', 'alias' => '`q`']
@@ -528,7 +517,6 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataFrom
*
* @param string|IQueryFunction $table1Name
* @param string $table1Alias
@@ -537,7 +525,8 @@ class QueryBuilderTest extends \Test\TestCase {
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testFrom($table1Name, $table1Alias, $table2Name, $table2Alias, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataFrom')]
+ public function testFrom($table1Name, $table1Alias, $table2Name, $table2Alias, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->from($table1Name, $table1Alias);
if ($table2Name !== null) {
$this->queryBuilder->from($table2Name, $table2Alias);
@@ -554,7 +543,7 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataJoin() {
+ public static function dataJoin(): array {
return [
[
'd1', 'data2', null, null,
@@ -576,7 +565,6 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataJoin
*
* @param string $fromAlias
* @param string $tableName
@@ -585,7 +573,8 @@ class QueryBuilderTest extends \Test\TestCase {
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testJoin($fromAlias, $tableName, $tableAlias, $condition, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataJoin')]
+ public function testJoin($fromAlias, $tableName, $tableAlias, $condition, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->from('data1', 'd1');
$this->queryBuilder->join(
$fromAlias,
@@ -606,7 +595,6 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataJoin
*
* @param string $fromAlias
* @param string $tableName
@@ -615,7 +603,8 @@ class QueryBuilderTest extends \Test\TestCase {
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testInnerJoin($fromAlias, $tableName, $tableAlias, $condition, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataJoin')]
+ public function testInnerJoin($fromAlias, $tableName, $tableAlias, $condition, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->from('data1', 'd1');
$this->queryBuilder->innerJoin(
$fromAlias,
@@ -635,7 +624,7 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataLeftJoin() {
+ public static function dataLeftJoin(): array {
return [
[
'd1', 'data2', null, null,
@@ -656,7 +645,6 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataLeftJoin
*
* @param string $fromAlias
* @param string $tableName
@@ -665,7 +653,8 @@ class QueryBuilderTest extends \Test\TestCase {
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testLeftJoin($fromAlias, $tableName, $tableAlias, $condition, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataLeftJoin')]
+ public function testLeftJoin($fromAlias, $tableName, $tableAlias, $condition, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->from('data1', 'd1');
$this->queryBuilder->leftJoin(
$fromAlias,
@@ -685,7 +674,7 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataRightJoin() {
+ public static function dataRightJoin(): array {
return [
[
'd1', 'data2', null, null,
@@ -706,7 +695,6 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataRightJoin
*
* @param string $fromAlias
* @param string $tableName
@@ -715,7 +703,8 @@ class QueryBuilderTest extends \Test\TestCase {
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testRightJoin($fromAlias, $tableName, $tableAlias, $condition, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataRightJoin')]
+ public function testRightJoin($fromAlias, $tableName, $tableAlias, $condition, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->from('data1', 'd1');
$this->queryBuilder->rightJoin(
$fromAlias,
@@ -735,7 +724,7 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataSet() {
+ public static function dataSet(): array {
return [
['column1', new Literal('value'), null, null, ['`column1` = value'], '`column1` = value'],
['column1', new Parameter(':param'), null, null, ['`column1` = :param'], '`column1` = :param'],
@@ -745,7 +734,6 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataSet
*
* @param string $partOne1
* @param string $partOne2
@@ -754,7 +742,8 @@ class QueryBuilderTest extends \Test\TestCase {
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testSet($partOne1, $partOne2, $partTwo1, $partTwo2, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataSet')]
+ public function testSet($partOne1, $partOne2, $partTwo1, $partTwo2, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->update('data');
$this->queryBuilder->set($partOne1, $partOne2);
if ($partTwo1 !== null) {
@@ -772,7 +761,7 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataWhere() {
+ public static function dataWhere(): array {
return [
[['where1'], new CompositeExpression('AND', ['where1']), 'where1'],
[['where1', 'where2'], new CompositeExpression('AND', ['where1', 'where2']), '(where1) AND (where2)'],
@@ -780,13 +769,13 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataWhere
*
* @param array $whereArguments
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testWhere($whereArguments, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataWhere')]
+ public function testWhere($whereArguments, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->select('column');
call_user_func_array(
[$this->queryBuilder, 'where'],
@@ -805,13 +794,13 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataWhere
*
* @param array $whereArguments
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testAndWhere($whereArguments, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataWhere')]
+ public function testAndWhere($whereArguments, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->select('column');
call_user_func_array(
[$this->queryBuilder, 'andWhere'],
@@ -829,7 +818,7 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataOrWhere() {
+ public static function dataOrWhere(): array {
return [
[['where1'], new CompositeExpression('OR', ['where1']), 'where1'],
[['where1', 'where2'], new CompositeExpression('OR', ['where1', 'where2']), '(where1) OR (where2)'],
@@ -837,13 +826,13 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataOrWhere
*
* @param array $whereArguments
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testOrWhere($whereArguments, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataOrWhere')]
+ public function testOrWhere($whereArguments, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->select('column');
call_user_func_array(
[$this->queryBuilder, 'orWhere'],
@@ -861,7 +850,7 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataGroupBy() {
+ public static function dataGroupBy(): array {
return [
[['column1'], ['`column1`'], '`column1`'],
[['column1', 'column2'], ['`column1`', '`column2`'], '`column1`, `column2`'],
@@ -869,13 +858,13 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataGroupBy
*
* @param array $groupByArguments
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testGroupBy($groupByArguments, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataGroupBy')]
+ public function testGroupBy($groupByArguments, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->select('column');
call_user_func_array(
[$this->queryBuilder, 'groupBy'],
@@ -893,7 +882,7 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataAddGroupBy() {
+ public static function dataAddGroupBy(): array {
return [
[['column2'], ['`column1`', '`column2`'], '`column1`, `column2`'],
[['column2', 'column3'], ['`column1`', '`column2`', '`column3`'], '`column1`, `column2`, `column3`'],
@@ -901,13 +890,13 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataAddGroupBy
*
* @param array $groupByArguments
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testAddGroupBy($groupByArguments, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataAddGroupBy')]
+ public function testAddGroupBy($groupByArguments, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->select('column');
$this->queryBuilder->groupBy('column1');
call_user_func_array(
@@ -926,21 +915,21 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataSetValue() {
+ public static function dataSetValue(): array {
return [
['column', 'value', ['`column`' => 'value'], '(`column`) VALUES(value)'],
];
}
/**
- * @dataProvider dataSetValue
*
* @param string $column
* @param string $value
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testSetValue($column, $value, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataSetValue')]
+ public function testSetValue($column, $value, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->insert('data');
$this->queryBuilder->setValue($column, $value);
@@ -956,14 +945,14 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataSetValue
*
* @param string $column
* @param string $value
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testValues($column, $value, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataSetValue')]
+ public function testValues($column, $value, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->insert('data');
$this->queryBuilder->values([
$column => $value,
@@ -980,7 +969,7 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataHaving() {
+ public static function dataHaving(): array {
return [
[['condition1'], new CompositeExpression('AND', ['condition1']), 'HAVING condition1'],
[['condition1', 'condition2'], new CompositeExpression('AND', ['condition1', 'condition2']), 'HAVING (condition1) AND (condition2)'],
@@ -998,13 +987,13 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataHaving
*
* @param array $havingArguments
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testHaving($havingArguments, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataHaving')]
+ public function testHaving($havingArguments, $expectedQueryPart, $expectedQuery): void {
call_user_func_array(
[$this->queryBuilder, 'having'],
$havingArguments
@@ -1021,7 +1010,7 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataAndHaving() {
+ public static function dataAndHaving(): array {
return [
[['condition2'], new CompositeExpression('AND', ['condition1', 'condition2']), 'HAVING (condition1) AND (condition2)'],
[['condition2', 'condition3'], new CompositeExpression('AND', ['condition1', 'condition2', 'condition3']), 'HAVING (condition1) AND (condition2) AND (condition3)'],
@@ -1039,13 +1028,13 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataAndHaving
*
* @param array $havingArguments
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testAndHaving($havingArguments, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataAndHaving')]
+ public function testAndHaving($havingArguments, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->having('condition1');
call_user_func_array(
[$this->queryBuilder, 'andHaving'],
@@ -1063,7 +1052,7 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataOrHaving() {
+ public static function dataOrHaving(): array {
return [
[['condition2'], new CompositeExpression('OR', ['condition1', 'condition2']), 'HAVING (condition1) OR (condition2)'],
[['condition2', 'condition3'], new CompositeExpression('OR', ['condition1', 'condition2', 'condition3']), 'HAVING (condition1) OR (condition2) OR (condition3)'],
@@ -1081,13 +1070,13 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataOrHaving
*
* @param array $havingArguments
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testOrHaving($havingArguments, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataOrHaving')]
+ public function testOrHaving($havingArguments, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->having('condition1');
call_user_func_array(
[$this->queryBuilder, 'orHaving'],
@@ -1105,7 +1094,7 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataOrderBy() {
+ public static function dataOrderBy(): array {
return [
['column', null, ['`column` ASC'], 'ORDER BY `column` ASC'],
['column', 'ASC', ['`column` ASC'], 'ORDER BY `column` ASC'],
@@ -1114,14 +1103,14 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataOrderBy
*
* @param string $sort
* @param string $order
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testOrderBy($sort, $order, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataOrderBy')]
+ public function testOrderBy($sort, $order, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->orderBy($sort, $order);
$this->assertEquals(
@@ -1135,7 +1124,7 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataAddOrderBy() {
+ public static function dataAddOrderBy(): array {
return [
['column2', null, null, ['`column1` ASC', '`column2` ASC'], 'ORDER BY `column1` ASC, `column2` ASC'],
['column2', null, 'ASC', ['`column1` ASC', '`column2` ASC'], 'ORDER BY `column1` ASC, `column2` ASC'],
@@ -1150,7 +1139,6 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataAddOrderBy
*
* @param string $sort2
* @param string $order2
@@ -1158,7 +1146,8 @@ class QueryBuilderTest extends \Test\TestCase {
* @param array $expectedQueryPart
* @param string $expectedQuery
*/
- public function testAddOrderBy($sort2, $order2, $order1, $expectedQueryPart, $expectedQuery) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataAddOrderBy')]
+ public function testAddOrderBy($sort2, $order2, $order1, $expectedQueryPart, $expectedQuery): void {
$this->queryBuilder->orderBy('column1', $order1);
$this->queryBuilder->addOrderBy($sort2, $order2);
@@ -1173,7 +1162,7 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function testGetLastInsertId() {
+ public function testGetLastInsertId(): void {
$qB = $this->connection->getQueryBuilder();
try {
@@ -1210,10 +1199,10 @@ class QueryBuilderTest extends \Test\TestCase {
}
}
- public function dataGetTableName() {
+ public function dataGetTableName(): array {
$config = $this->createMock(SystemConfig::class);
$logger = $this->createMock(LoggerInterface::class);
- $qb = new QueryBuilder(\OC::$server->getDatabaseConnection(), $config, $logger);
+ $qb = new QueryBuilder(Server::get(IDBConnection::class), $config, $logger);
return [
['*PREFIX*table', null, '`*PREFIX*table`'],
['*PREFIX*table', true, '`*PREFIX*table`'],
@@ -1230,13 +1219,13 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataGetTableName
*
* @param string|IQueryFunction $tableName
* @param bool $automatic
* @param string $expected
*/
- public function testGetTableName($tableName, $automatic, $expected) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataGetTableName')]
+ public function testGetTableName($tableName, $automatic, $expected): void {
if ($automatic !== null) {
$this->queryBuilder->automaticTablePrefix($automatic);
}
@@ -1247,7 +1236,7 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
- public function dataGetColumnName() {
+ public static function dataGetColumnName(): array {
return [
['column', '', '`column`'],
['column', 'a', '`a`.`column`'],
@@ -1255,28 +1244,41 @@ class QueryBuilderTest extends \Test\TestCase {
}
/**
- * @dataProvider dataGetColumnName
* @param string $column
* @param string $prefix
* @param string $expected
*/
- public function testGetColumnName($column, $prefix, $expected) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataGetColumnName')]
+ public function testGetColumnName($column, $prefix, $expected): void {
$this->assertSame(
$expected,
$this->queryBuilder->getColumnName($column, $prefix)
);
}
- public function testExecuteWithoutLogger() {
+ private function getConnection(): IDBConnection {
+ $connection = $this->createMock(IDBConnection::class);
+ $connection->method('executeStatement')
+ ->willReturn(3);
+ $connection->method('executeQuery')
+ ->willReturn($this->createMock(IResult::class));
+ return $connection;
+ }
+
+ public function testExecuteWithoutLogger(): void {
$queryBuilder = $this->createMock(\Doctrine\DBAL\Query\QueryBuilder::class);
$queryBuilder
- ->expects($this->once())
- ->method('execute')
- ->willReturn(3);
+ ->method('getSQL')
+ ->willReturn('');
$queryBuilder
- ->expects($this->any())
->method('getParameters')
->willReturn([]);
+ $queryBuilder
+ ->method('getParameterTypes')
+ ->willReturn([]);
+ $queryBuilder
+ ->method('getType')
+ ->willReturn(\Doctrine\DBAL\Query\QueryBuilder::UPDATE);
$this->logger
->expects($this->never())
->method('debug');
@@ -1287,10 +1289,11 @@ class QueryBuilderTest extends \Test\TestCase {
->willReturn(false);
$this->invokePrivate($this->queryBuilder, 'queryBuilder', [$queryBuilder]);
+ $this->invokePrivate($this->queryBuilder, 'connection', [$this->getConnection()]);
$this->assertEquals(3, $this->queryBuilder->execute());
}
- public function testExecuteWithLoggerAndNamedArray() {
+ public function testExecuteWithLoggerAndNamedArray(): void {
$queryBuilder = $this->createMock(\Doctrine\DBAL\Query\QueryBuilder::class);
$queryBuilder
->expects($this->any())
@@ -1300,20 +1303,25 @@ class QueryBuilderTest extends \Test\TestCase {
'key' => 'value',
]);
$queryBuilder
+ ->method('getParameterTypes')
+ ->willReturn([
+ 'foo' => IQueryBuilder::PARAM_STR,
+ 'key' => IQueryBuilder::PARAM_STR,
+ ]);
+ $queryBuilder
+ ->method('getType')
+ ->willReturn(\Doctrine\DBAL\Query\QueryBuilder::UPDATE);
+ $queryBuilder
->expects($this->any())
->method('getSQL')
- ->willReturn('SELECT * FROM FOO WHERE BAR = ?');
- $queryBuilder
- ->expects($this->once())
- ->method('execute')
- ->willReturn(3);
+ ->willReturn('UPDATE FOO SET bar = 1 WHERE BAR = ?');
$this->logger
->expects($this->once())
->method('debug')
->with(
'DB QueryBuilder: \'{query}\' with parameters: {params}',
[
- 'query' => 'SELECT * FROM FOO WHERE BAR = ?',
+ 'query' => 'UPDATE FOO SET bar = 1 WHERE BAR = ?',
'params' => 'foo => \'bar\', key => \'value\'',
'app' => 'core',
]
@@ -1325,30 +1333,33 @@ class QueryBuilderTest extends \Test\TestCase {
->willReturn(true);
$this->invokePrivate($this->queryBuilder, 'queryBuilder', [$queryBuilder]);
+ $this->invokePrivate($this->queryBuilder, 'connection', [$this->getConnection()]);
$this->assertEquals(3, $this->queryBuilder->execute());
}
- public function testExecuteWithLoggerAndUnnamedArray() {
+ public function testExecuteWithLoggerAndUnnamedArray(): void {
$queryBuilder = $this->createMock(\Doctrine\DBAL\Query\QueryBuilder::class);
$queryBuilder
->expects($this->any())
->method('getParameters')
->willReturn(['Bar']);
$queryBuilder
+ ->method('getParameterTypes')
+ ->willReturn([IQueryBuilder::PARAM_STR]);
+ $queryBuilder
+ ->method('getType')
+ ->willReturn(\Doctrine\DBAL\Query\QueryBuilder::UPDATE);
+ $queryBuilder
->expects($this->any())
->method('getSQL')
- ->willReturn('SELECT * FROM FOO WHERE BAR = ?');
- $queryBuilder
- ->expects($this->once())
- ->method('execute')
- ->willReturn(3);
+ ->willReturn('UPDATE FOO SET bar = false WHERE BAR = ?');
$this->logger
->expects($this->once())
->method('debug')
->with(
'DB QueryBuilder: \'{query}\' with parameters: {params}',
[
- 'query' => 'SELECT * FROM FOO WHERE BAR = ?',
+ 'query' => 'UPDATE FOO SET bar = false WHERE BAR = ?',
'params' => '0 => \'Bar\'',
'app' => 'core',
]
@@ -1360,30 +1371,33 @@ class QueryBuilderTest extends \Test\TestCase {
->willReturn(true);
$this->invokePrivate($this->queryBuilder, 'queryBuilder', [$queryBuilder]);
+ $this->invokePrivate($this->queryBuilder, 'connection', [$this->getConnection()]);
$this->assertEquals(3, $this->queryBuilder->execute());
}
- public function testExecuteWithLoggerAndNoParams() {
+ public function testExecuteWithLoggerAndNoParams(): void {
$queryBuilder = $this->createMock(\Doctrine\DBAL\Query\QueryBuilder::class);
$queryBuilder
->expects($this->any())
->method('getParameters')
->willReturn([]);
$queryBuilder
+ ->method('getParameterTypes')
+ ->willReturn([]);
+ $queryBuilder
+ ->method('getType')
+ ->willReturn(\Doctrine\DBAL\Query\QueryBuilder::UPDATE);
+ $queryBuilder
->expects($this->any())
->method('getSQL')
- ->willReturn('SELECT * FROM FOO WHERE BAR = ?');
- $queryBuilder
- ->expects($this->once())
- ->method('execute')
- ->willReturn(3);
+ ->willReturn('UPDATE FOO SET bar = false WHERE BAR = ?');
$this->logger
->expects($this->once())
->method('debug')
->with(
'DB QueryBuilder: \'{query}\'',
[
- 'query' => 'SELECT * FROM FOO WHERE BAR = ?',
+ 'query' => 'UPDATE FOO SET bar = false WHERE BAR = ?',
'app' => 'core',
]
);
@@ -1394,10 +1408,11 @@ class QueryBuilderTest extends \Test\TestCase {
->willReturn(true);
$this->invokePrivate($this->queryBuilder, 'queryBuilder', [$queryBuilder]);
+ $this->invokePrivate($this->queryBuilder, 'connection', [$this->getConnection()]);
$this->assertEquals(3, $this->queryBuilder->execute());
}
- public function testExecuteWithParameterTooLarge() {
+ public function testExecuteWithParameterTooLarge(): void {
$queryBuilder = $this->createMock(\Doctrine\DBAL\Query\QueryBuilder::class);
$p = array_fill(0, 1001, 'foo');
$queryBuilder
@@ -1405,17 +1420,16 @@ class QueryBuilderTest extends \Test\TestCase {
->method('getParameters')
->willReturn([$p]);
$queryBuilder
+ ->method('getParameterTypes')
+ ->willReturn([IQueryBuilder::PARAM_STR_ARRAY]);
+ $queryBuilder
->expects($this->any())
->method('getSQL')
->willReturn('SELECT * FROM FOO WHERE BAR IN (?)');
- $queryBuilder
- ->expects($this->once())
- ->method('execute')
- ->willReturn($this->createMock(Result::class));
$this->logger
->expects($this->once())
->method('error')
- ->willReturnCallback(function ($message, $parameters) {
+ ->willReturnCallback(function ($message, $parameters): void {
$this->assertInstanceOf(QueryException::class, $parameters['exception']);
$this->assertSame(
'More than 1000 expressions in a list are not allowed on Oracle.',
@@ -1429,10 +1443,11 @@ class QueryBuilderTest extends \Test\TestCase {
->willReturn(false);
$this->invokePrivate($this->queryBuilder, 'queryBuilder', [$queryBuilder]);
+ $this->invokePrivate($this->queryBuilder, 'connection', [$this->getConnection()]);
$this->queryBuilder->execute();
}
- public function testExecuteWithParametersTooMany() {
+ public function testExecuteWithParametersTooMany(): void {
$queryBuilder = $this->createMock(\Doctrine\DBAL\Query\QueryBuilder::class);
$p = array_fill(0, 999, 'foo');
$queryBuilder
@@ -1440,17 +1455,16 @@ class QueryBuilderTest extends \Test\TestCase {
->method('getParameters')
->willReturn(array_fill(0, 66, $p));
$queryBuilder
+ ->method('getParameterTypes')
+ ->willReturn([IQueryBuilder::PARAM_STR_ARRAY]);
+ $queryBuilder
->expects($this->any())
->method('getSQL')
->willReturn('SELECT * FROM FOO WHERE BAR IN (?) OR BAR IN (?)');
- $queryBuilder
- ->expects($this->once())
- ->method('execute')
- ->willReturn($this->createMock(Result::class));
$this->logger
->expects($this->once())
->method('error')
- ->willReturnCallback(function ($message, $parameters) {
+ ->willReturnCallback(function ($message, $parameters): void {
$this->assertInstanceOf(QueryException::class, $parameters['exception']);
$this->assertSame(
'The number of parameters must not exceed 65535. Restriction by PostgreSQL.',
@@ -1464,6 +1478,7 @@ class QueryBuilderTest extends \Test\TestCase {
->willReturn(false);
$this->invokePrivate($this->queryBuilder, 'queryBuilder', [$queryBuilder]);
+ $this->invokePrivate($this->queryBuilder, 'connection', [$this->getConnection()]);
$this->queryBuilder->execute();
}
}
diff --git a/tests/lib/DB/QueryBuilder/QuoteHelperTest.php b/tests/lib/DB/QueryBuilder/QuoteHelperTest.php
index 17e7ac14a02..6efb55708a1 100644
--- a/tests/lib/DB/QueryBuilder/QuoteHelperTest.php
+++ b/tests/lib/DB/QueryBuilder/QuoteHelperTest.php
@@ -1,22 +1,9 @@
<?php
+
/**
- * @author Joas Schilling <nickvergessen@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace Test\DB\QueryBuilder;
@@ -37,7 +24,7 @@ class QuoteHelperTest extends \Test\TestCase {
$this->helper = new QuoteHelper();
}
- public function dataQuoteColumnName() {
+ public static function dataQuoteColumnName(): array {
return [
['column', '`column`'],
[new Literal('literal'), 'literal'],
@@ -51,18 +38,18 @@ class QuoteHelperTest extends \Test\TestCase {
}
/**
- * @dataProvider dataQuoteColumnName
* @param mixed $input
* @param string $expected
*/
- public function testQuoteColumnName($input, $expected) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataQuoteColumnName')]
+ public function testQuoteColumnName($input, $expected): void {
$this->assertSame(
$expected,
$this->helper->quoteColumnName($input)
);
}
- public function dataQuoteColumnNames() {
+ public static function dataQuoteColumnNames(): array {
return [
// Single case
['d.column', '`d`.`column`'],
@@ -86,11 +73,11 @@ class QuoteHelperTest extends \Test\TestCase {
}
/**
- * @dataProvider dataQuoteColumnNames
* @param mixed $input
* @param string $expected
*/
- public function testQuoteColumnNames($input, $expected) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataQuoteColumnNames')]
+ public function testQuoteColumnNames($input, $expected): void {
$this->assertSame(
$expected,
$this->helper->quoteColumnNames($input)
diff --git a/tests/lib/DB/QueryBuilder/Sharded/SharedQueryBuilderTest.php b/tests/lib/DB/QueryBuilder/Sharded/SharedQueryBuilderTest.php
new file mode 100644
index 00000000000..d0f232cb03f
--- /dev/null
+++ b/tests/lib/DB/QueryBuilder/Sharded/SharedQueryBuilderTest.php
@@ -0,0 +1,128 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2024 Robin Appelman <robin@icewind.nl>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace Test\DB\QueryBuilder\Sharded;
+
+use OC\DB\QueryBuilder\Sharded\AutoIncrementHandler;
+use OC\DB\QueryBuilder\Sharded\InvalidShardedQueryException;
+use OC\DB\QueryBuilder\Sharded\RoundRobinShardMapper;
+use OC\DB\QueryBuilder\Sharded\ShardConnectionManager;
+use OC\DB\QueryBuilder\Sharded\ShardDefinition;
+use OC\DB\QueryBuilder\Sharded\ShardedQueryBuilder;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+use OCP\Server;
+use Test\TestCase;
+
+/**
+ * @group DB
+ */
+class SharedQueryBuilderTest extends TestCase {
+ private IDBConnection $connection;
+ private AutoIncrementHandler $autoIncrementHandler;
+
+ protected function setUp(): void {
+ if (PHP_INT_SIZE < 8) {
+ $this->markTestSkipped('Test requires 64bit');
+ }
+ $this->connection = Server::get(IDBConnection::class);
+ $this->autoIncrementHandler = Server::get(AutoIncrementHandler::class);
+ }
+
+
+ private function getQueryBuilder(string $table, string $shardColumn, string $primaryColumn, array $companionTables = []): ShardedQueryBuilder {
+ return new ShardedQueryBuilder(
+ $this->connection->getQueryBuilder(),
+ [
+ new ShardDefinition($table, $primaryColumn, [], $shardColumn, new RoundRobinShardMapper(), $companionTables, [], 0, 0),
+ ],
+ $this->createMock(ShardConnectionManager::class),
+ $this->autoIncrementHandler,
+ );
+ }
+
+ public function testGetShardKeySingleParam(): void {
+ $query = $this->getQueryBuilder('filecache', 'storage', 'fileid');
+ $query->select('fileid', 'path')
+ ->from('filecache')
+ ->where($query->expr()->eq('storage', $query->createNamedParameter(10, IQueryBuilder::PARAM_INT)));
+
+ $this->assertEquals([], $query->getPrimaryKeys());
+ $this->assertEquals([10], $query->getShardKeys());
+ }
+
+ public function testGetPrimaryKeyParam(): void {
+ $query = $this->getQueryBuilder('filecache', 'storage', 'fileid');
+ $query->select('fileid', 'path')
+ ->from('filecache')
+ ->where($query->expr()->in('fileid', $query->createNamedParameter([10, 11], IQueryBuilder::PARAM_INT)));
+
+ $this->assertEquals([10, 11], $query->getPrimaryKeys());
+ $this->assertEquals([], $query->getShardKeys());
+ }
+
+ public function testValidateWithShardKey(): void {
+ $query = $this->getQueryBuilder('filecache', 'storage', 'fileid');
+ $query->select('fileid', 'path')
+ ->from('filecache')
+ ->where($query->expr()->eq('storage', $query->createNamedParameter(10)));
+
+ $query->validate();
+ $this->assertTrue(true);
+ }
+
+ public function testValidateWithPrimaryKey(): void {
+ $query = $this->getQueryBuilder('filecache', 'storage', 'fileid');
+ $query->select('fileid', 'path')
+ ->from('filecache')
+ ->where($query->expr()->in('fileid', $query->createNamedParameter([10, 11], IQueryBuilder::PARAM_INT)));
+
+ $query->validate();
+ $this->assertTrue(true);
+ }
+
+ public function testValidateWithNoKey(): void {
+ $query = $this->getQueryBuilder('filecache', 'storage', 'fileid');
+ $query->select('fileid', 'path')
+ ->from('filecache')
+ ->where($query->expr()->lt('size', $query->createNamedParameter(0)));
+
+ $this->expectException(InvalidShardedQueryException::class);
+ $query->validate();
+ $this->fail('exception expected');
+ }
+
+ public function testValidateNonSharedTable(): void {
+ $query = $this->getQueryBuilder('filecache', 'storage', 'fileid');
+ $query->select('configvalue')
+ ->from('appconfig')
+ ->where($query->expr()->eq('configkey', $query->createNamedParameter('test')));
+
+ $query->validate();
+ $this->assertTrue(true);
+ }
+
+ public function testGetShardKeyMultipleSingleParam(): void {
+ $query = $this->getQueryBuilder('filecache', 'storage', 'fileid');
+ $query->select('fileid', 'path')
+ ->from('filecache')
+ ->where($query->expr()->andX(
+ $query->expr()->gt('mtime', $query->createNamedParameter(0), IQueryBuilder::PARAM_INT),
+ $query->expr()->orX(
+ $query->expr()->eq('storage', $query->createNamedParameter(10, IQueryBuilder::PARAM_INT)),
+ $query->expr()->andX(
+ $query->expr()->eq('storage', $query->createNamedParameter(11, IQueryBuilder::PARAM_INT)),
+ $query->expr()->like('path', $query->createNamedParameter('foo/%'))
+ )
+ )
+ ));
+
+ $this->assertEquals([], $query->getPrimaryKeys());
+ $this->assertEquals([10, 11], $query->getShardKeys());
+ }
+}