diff options
Diffstat (limited to 'tests/lib/DB/QueryBuilder')
8 files changed, 709 insertions, 246 deletions
diff --git a/tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php b/tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php index 671bcfc209e..153993f396e 100644 --- a/tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php +++ b/tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -7,10 +8,11 @@ namespace Test\DB\QueryBuilder; use Doctrine\DBAL\Schema\SchemaException; -use Doctrine\DBAL\Types\Types; 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; @@ -18,19 +20,19 @@ 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], @@ -46,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')) @@ -65,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], @@ -83,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')) @@ -141,53 +143,53 @@ class ExpressionBuilderDBTest extends TestCase { self::assertEquals('myvalue', $entries[0]['configvalue']); } - public function testDateTimeEquals() { + public function testDateTimeEquals(): void { $dateTime = new \DateTime('2023-01-01'); $insert = $this->connection->getQueryBuilder(); $insert->insert('testing') - ->values(['datetime' => $insert->createNamedParameter($dateTime, IQueryBuilder::PARAM_DATE)]) + ->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_DATE))) + ->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() { + 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_DATE)]) + ->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_DATE))) + ->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() { + 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_DATE)]) + ->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_DATE))) + ->where($query->expr()->gt('datetime', $query->createNamedParameter($dateTimeCompare, IQueryBuilder::PARAM_DATETIME_MUTABLE))) ->executeQuery(); $entries = $result->fetchAll(); $result->closeCursor(); @@ -199,8 +201,8 @@ class ExpressionBuilderDBTest 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(); } @@ -223,7 +225,7 @@ class ExpressionBuilderDBTest extends TestCase { 'notnull' => true, ]); - $table->addColumn('datetime', Types::DATETIME_MUTABLE, [ + $table->addColumn('datetime', Types::DATETIME, [ 'notnull' => false, ]); diff --git a/tests/lib/DB/QueryBuilder/ExpressionBuilderTest.php b/tests/lib/DB/QueryBuilder/ExpressionBuilderTest.php index d8147035b16..1f84ebfbec1 100644 --- a/tests/lib/DB/QueryBuilder/ExpressionBuilderTest.php +++ b/tests/lib/DB/QueryBuilder/ExpressionBuilderTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -10,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; /** @@ -26,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 = []; @@ -59,7 +67,6 @@ class ExpressionBuilderTest extends TestCase { } /** - * @dataProvider dataComparison * * @param string $comparison * @param mixed $input1 @@ -67,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); @@ -77,7 +85,7 @@ class ExpressionBuilderTest extends TestCase { ); } - public function dataComparisons() { + public static function dataComparisons(): array { return [ ['value', false, 'value', false], ['value', false, 'value', true], @@ -87,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); @@ -105,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); @@ -123,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); @@ -141,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); @@ -159,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); @@ -177,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); @@ -194,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], @@ -216,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( @@ -231,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( @@ -245,7 +253,7 @@ class ExpressionBuilderTest extends TestCase { ); } - public function dataIn() { + public static function dataIn(): array { return [ ['value', false], ['value', true], @@ -255,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( @@ -270,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( @@ -312,7 +320,7 @@ class ExpressionBuilderTest extends TestCase { return [$doctrineInput, $ocInput]; } - public function dataLiteral() { + public static function dataLiteral(): array { return [ ['value', null], ['1', null], @@ -324,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); @@ -340,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], @@ -368,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); @@ -415,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 d991c78f113..5a111c91aa7 100644 --- a/tests/lib/DB/QueryBuilder/FunctionBuilderTest.php +++ b/tests/lib/DB/QueryBuilder/FunctionBuilderTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-only @@ -8,6 +9,8 @@ namespace Test\DB\QueryBuilder; use OC\DB\QueryBuilder\Literal; use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IDBConnection; +use OCP\Server; use Test\TestCase; /** @@ -18,19 +21,17 @@ 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) { @@ -49,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"]; }], ]; } @@ -232,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'))); @@ -245,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))); @@ -258,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))); @@ -271,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'))); @@ -284,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))); @@ -297,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))); @@ -310,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')); @@ -323,7 +324,7 @@ class FunctionBuilderTest extends TestCase { $this->assertGreaterThan(1, $column); } - public function octetLengthProvider() { + public static function octetLengthProvider(): array { return [ ['', 0], ['foobar', 6], @@ -332,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))); @@ -348,7 +347,7 @@ class FunctionBuilderTest extends TestCase { $this->assertEquals($bytes, $column); } - public function charLengthProvider() { + public static function charLengthProvider(): array { return [ ['', 0], ['foobar', 6], @@ -357,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))); @@ -370,6 +367,7 @@ class FunctionBuilderTest extends TestCase { $result = $query->execute(); $column = $result->fetchOne(); $result->closeCursor(); + $this->assertNotNull($column); $this->assertEquals($bytes, $column); } @@ -393,7 +391,7 @@ class FunctionBuilderTest extends TestCase { $query->execute(); } - public function testMaxEmpty() { + public function testMaxEmpty(): void { $this->clearMinMax(); $query = $this->connection->getQueryBuilder(); @@ -409,7 +407,7 @@ class FunctionBuilderTest extends TestCase { $this->assertEquals(null, $row); } - public function testMinEmpty() { + public function testMinEmpty(): void { $this->clearMinMax(); $query = $this->connection->getQueryBuilder(); @@ -425,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); @@ -444,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); @@ -463,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))); @@ -476,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 96cde8ba1f9..990191a9ff5 100644 --- a/tests/lib/DB/QueryBuilder/QueryBuilderTest.php +++ b/tests/lib/DB/QueryBuilder/QueryBuilderTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -9,13 +10,15 @@ 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; /** @@ -41,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); @@ -87,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]], @@ -97,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(); @@ -123,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 @@ -134,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(); @@ -160,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']], @@ -186,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(); @@ -228,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']], @@ -239,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(); @@ -271,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'); @@ -299,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'); @@ -337,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']], @@ -363,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(); @@ -407,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'], @@ -415,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( @@ -436,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'], @@ -444,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( @@ -465,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( @@ -492,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`'] @@ -514,7 +517,6 @@ class QueryBuilderTest extends \Test\TestCase { } /** - * @dataProvider dataFrom * * @param string|IQueryFunction $table1Name * @param string $table1Alias @@ -523,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); @@ -540,7 +543,7 @@ class QueryBuilderTest extends \Test\TestCase { ); } - public function dataJoin() { + public static function dataJoin(): array { return [ [ 'd1', 'data2', null, null, @@ -562,7 +565,6 @@ class QueryBuilderTest extends \Test\TestCase { } /** - * @dataProvider dataJoin * * @param string $fromAlias * @param string $tableName @@ -571,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, @@ -592,7 +595,6 @@ class QueryBuilderTest extends \Test\TestCase { } /** - * @dataProvider dataJoin * * @param string $fromAlias * @param string $tableName @@ -601,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, @@ -621,7 +624,7 @@ class QueryBuilderTest extends \Test\TestCase { ); } - public function dataLeftJoin() { + public static function dataLeftJoin(): array { return [ [ 'd1', 'data2', null, null, @@ -642,7 +645,6 @@ class QueryBuilderTest extends \Test\TestCase { } /** - * @dataProvider dataLeftJoin * * @param string $fromAlias * @param string $tableName @@ -651,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, @@ -671,7 +674,7 @@ class QueryBuilderTest extends \Test\TestCase { ); } - public function dataRightJoin() { + public static function dataRightJoin(): array { return [ [ 'd1', 'data2', null, null, @@ -692,7 +695,6 @@ class QueryBuilderTest extends \Test\TestCase { } /** - * @dataProvider dataRightJoin * * @param string $fromAlias * @param string $tableName @@ -701,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, @@ -721,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'], @@ -731,7 +734,6 @@ class QueryBuilderTest extends \Test\TestCase { } /** - * @dataProvider dataSet * * @param string $partOne1 * @param string $partOne2 @@ -740,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) { @@ -758,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)'], @@ -766,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'], @@ -791,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'], @@ -815,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)'], @@ -823,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'], @@ -847,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`'], @@ -855,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'], @@ -879,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`'], @@ -887,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( @@ -912,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); @@ -942,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, @@ -966,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)'], @@ -984,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 @@ -1007,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)'], @@ -1025,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'], @@ -1049,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)'], @@ -1067,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'], @@ -1091,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'], @@ -1100,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( @@ -1121,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'], @@ -1136,7 +1139,6 @@ class QueryBuilderTest extends \Test\TestCase { } /** - * @dataProvider dataAddOrderBy * * @param string $sort2 * @param string $order2 @@ -1144,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); @@ -1159,7 +1162,7 @@ class QueryBuilderTest extends \Test\TestCase { ); } - public function testGetLastInsertId() { + public function testGetLastInsertId(): void { $qB = $this->connection->getQueryBuilder(); try { @@ -1196,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`'], @@ -1216,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); } @@ -1233,7 +1236,7 @@ class QueryBuilderTest extends \Test\TestCase { ); } - public function dataGetColumnName() { + public static function dataGetColumnName(): array { return [ ['column', '', '`column`'], ['column', 'a', '`a`.`column`'], @@ -1241,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'); @@ -1273,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()) @@ -1286,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', ] @@ -1311,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', ] @@ -1346,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', ] ); @@ -1380,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 @@ -1391,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.', @@ -1415,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 @@ -1426,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.', @@ -1450,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 12984bac3e0..6efb55708a1 100644 --- a/tests/lib/DB/QueryBuilder/QuoteHelperTest.php +++ b/tests/lib/DB/QueryBuilder/QuoteHelperTest.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -23,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'], @@ -37,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`'], @@ -72,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()); + } +} |