diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c3966cec..e53b62115 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -162,7 +162,7 @@ - Enh #1065: Allow to use table name as a column prefix in update queries (@Tigrov) - Enh #1068: Quote string values as column names when join condition is an associative array (@Tigrov) - Chg #1070: Change "IndexBy" closure signature to `Closure(array|object):int|string` (@vjik) -- Enh #1072, #1077, #1078, #1079, #1080, #1085, #1087: Improve psalm types (@vjik) +- Enh #1072, #1077, #1078, #1079, #1080, #1085, #1087, #1096: Improve psalm types (@vjik) - New #1074: Add `ConnectionProvider` class (@Tigrov) - Chg #1075: Rename `Query::$join` property to `$joins` (@vjik) - New #1076: Allow to use expressions as table name or condition in "join" query methods (@vjik) diff --git a/src/Schema/Column/AbstractColumnFactory.php b/src/Schema/Column/AbstractColumnFactory.php index 3c3c60bb4..5f2c217d3 100644 --- a/src/Schema/Column/AbstractColumnFactory.php +++ b/src/Schema/Column/AbstractColumnFactory.php @@ -227,7 +227,6 @@ protected function columnDefinitionParser(): ColumnDefinitionParser } /** - * @psalm-param ColumnType::* $type * @psalm-param ColumnInfo $info * @psalm-return class-string */ @@ -291,8 +290,6 @@ protected function isDbType(string $dbType): bool /** * Checks if the column type is a pseudo-type. - * - * @psalm-assert-if-true PseudoType::* $pseudoType */ protected function isPseudoType(string $pseudoType): bool { @@ -309,8 +306,6 @@ protected function isPseudoType(string $pseudoType): bool /** * Checks if the column type is an abstract type. - * - * @psalm-assert-if-true ColumnType::* $type */ protected function isType(string $type): bool { diff --git a/src/Schema/Column/ColumnFactoryInterface.php b/src/Schema/Column/ColumnFactoryInterface.php index 5a5e4c007..6f94b7a25 100644 --- a/src/Schema/Column/ColumnFactoryInterface.php +++ b/src/Schema/Column/ColumnFactoryInterface.php @@ -73,7 +73,6 @@ public function fromDefinition(string $definition, array $info = []): ColumnInte * @param string $pseudoType The pseudo-type. * @param array $info The column information. The set of parameters may be different for a specific DBMS. * - * @psalm-param PseudoType::* $pseudoType * @psalm-param ColumnInfo $info */ public function fromPseudoType(string $pseudoType, array $info = []): ColumnInterface; @@ -84,7 +83,6 @@ public function fromPseudoType(string $pseudoType, array $info = []): ColumnInte * @param string $type The abstract database type. * @param array $info The column information. The set of parameters may be different for a specific DBMS. * - * @psalm-param ColumnType::* $type * @psalm-param ColumnInfo $info */ public function fromType(string $type, array $info = []): ColumnInterface; diff --git a/src/Schema/Column/ColumnInterface.php b/src/Schema/Column/ColumnInterface.php index 31095089b..af3eccc2c 100644 --- a/src/Schema/Column/ColumnInterface.php +++ b/src/Schema/Column/ColumnInterface.php @@ -6,6 +6,7 @@ use Yiisoft\Db\Constant\ColumnType; use Yiisoft\Db\Constraint\ForeignKey; +use Yiisoft\Db\Exception\NotSupportedException; /** * This interface defines a set of methods that must be implemented by a class that represents a database table column. @@ -86,6 +87,8 @@ public function dbType(?string $dbType): static; * directly in your code. * * If the value is `null` or an {@see Expression}, there will be no conversion. + * + * @throws NotSupportedException */ public function dbTypecast(mixed $value): mixed; @@ -291,6 +294,8 @@ public function null(): static; /** * Converts the input value after retrieval from the database. + * + * @throws NotSupportedException */ public function phpTypecast(mixed $value): mixed; diff --git a/tests/AbstractCommandTest.php b/tests/AbstractCommandTest.php index 064152f2c..3e82cd594 100644 --- a/tests/AbstractCommandTest.php +++ b/tests/AbstractCommandTest.php @@ -5,29 +5,18 @@ namespace Yiisoft\Db\Tests; use PHPUnit\Framework\TestCase; -use Throwable; use Yiisoft\Db\Expression\Value\Param; -use Yiisoft\Db\Exception\Exception; -use Yiisoft\Db\Exception\InvalidConfigException; -use Yiisoft\Db\Exception\NotSupportedException; use Yiisoft\Db\Profiler\Context\CommandContext; use Yiisoft\Db\Profiler\ContextInterface; use Yiisoft\Db\Profiler\ProfilerInterface; use Yiisoft\Db\Tests\Support\TestTrait; -/** - * @psalm-suppress RedundantCondition - */ abstract class AbstractCommandTest extends TestCase { use TestTrait; protected string $upsertTestCharCast = ''; - /** - * @throws Exception - * @throws InvalidConfigException - */ public function testAutoQuoting(): void { $db = $this->getConnection(); @@ -47,10 +36,6 @@ public function testAutoQuoting(): void ); } - /** - * @throws Exception - * @throws InvalidConfigException - */ public function testConstruct(): void { $db = $this->getConnection(); @@ -68,10 +53,6 @@ public function testConstruct(): void $this->assertSame([':name' => 'John Doe'], $command->getParams()); } - /** - * @throws Exception - * @throws InvalidConfigException - */ public function testGetParams(): void { $db = $this->getConnection(); @@ -103,19 +84,14 @@ public function testGetParams(): void $this->assertContainsOnlyInstancesOf(Param::class, $bindedValues); $this->assertCount(3, $bindedValues); $this->assertEquals($param, $bindedValues['int']); + + $db->close(); } /** - * Test command getRawSql. - * * @dataProvider \Yiisoft\Db\Tests\Provider\CommandProvider::rawSql * - * @throws Exception - * @throws InvalidConfigException - * @throws NotSupportedException - * @throws \Exception - * - * {@see https://github.com/yiisoft/yii2/issues/8592} + * @see https://github.com/yiisoft/yii2/issues/8592 */ public function testGetRawSql(string $sql, array $params, string $expectedRawSql): void { @@ -124,12 +100,10 @@ public function testGetRawSql(string $sql, array $params, string $expectedRawSql $command = $db->createCommand($sql, $params); $this->assertSame($expectedRawSql, $command->getRawSql()); + + $db->close(); } - /** - * @throws Exception - * @throws InvalidConfigException - */ public function testGetSetSql(): void { $db = $this->getConnection(); @@ -145,12 +119,10 @@ public function testGetSetSql(): void SQL; $command->setSql($sql2); $this->assertSame($sql2, $command->getSql()); + + $db->close(); } - /** - * @throws Exception - * @throws InvalidConfigException - */ public function testPrepareCancel(): void { $db = $this->getConnection(true); @@ -171,13 +143,10 @@ public function testPrepareCancel(): void $command->cancel(); $this->assertNull($command->getPdoStatement()); + + $db->close(); } - /** - * @throws Exception - * @throws InvalidConfigException - * @throws \Exception - */ public function testSetRawSql(): void { $db = $this->getConnection(); @@ -190,12 +159,10 @@ public function testSetRawSql(): void ); $this->assertSame('SELECT 123', $command->getRawSql()); + + $db->close(); } - /** - * @throws Exception - * @throws InvalidConfigException - */ public function testSetSql(): void { $db = $this->getConnection(); @@ -208,14 +175,10 @@ public function testSetSql(): void ); $this->assertSame('SELECT 123', $command->getSql()); + + $db->close(); } - /** - * @throws Exception - * @throws InvalidConfigException - * @throws Throwable - * @throws \PHPUnit\Framework\MockObject\Exception - */ public function testProfiler(?string $sql = null): void { $sql ??= 'SELECT 123'; @@ -233,14 +196,10 @@ public function testProfiler(?string $sql = null): void $db->setProfiler($profiler); $db->createCommand($sql)->execute(); + + $db->close(); } - /** - * @throws Exception - * @throws InvalidConfigException - * @throws Throwable - * @throws \PHPUnit\Framework\MockObject\Exception - */ public function testProfilerData(?string $sql = null): void { $sql ??= 'SELECT 123'; @@ -271,5 +230,7 @@ public function end(string $token, ContextInterface|array $context = []): void $db->setProfiler($profiler); $db->createCommand($sql)->execute(); + + $db->close(); } } diff --git a/tests/AbstractQueryBuilderTest.php b/tests/AbstractQueryBuilderTest.php index eb86a95e5..6abdf139c 100644 --- a/tests/AbstractQueryBuilderTest.php +++ b/tests/AbstractQueryBuilderTest.php @@ -37,9 +37,6 @@ use function PHPUnit\Framework\assertEmpty; use function PHPUnit\Framework\assertSame; -/** - * @psalm-suppress PropertyNotSetInConstructor - */ abstract class AbstractQueryBuilderTest extends TestCase { use TestTrait; @@ -142,9 +139,6 @@ public function testAddDefaultValue(): void /** * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::addForeignKey - * - * @throws Exception - * @throws InvalidArgumentException */ public function testAddForeignKey( string $name, diff --git a/tests/AbstractQueryGetTableAliasTest.php b/tests/AbstractQueryGetTableAliasTest.php index 59a24da64..383bf6dc0 100644 --- a/tests/AbstractQueryGetTableAliasTest.php +++ b/tests/AbstractQueryGetTableAliasTest.php @@ -14,9 +14,6 @@ abstract class AbstractQueryGetTableAliasTest extends TestCase { use TestTrait; - /** - * @throws InvalidArgumentException - */ public function testAliasesFromString(): void { $db = $this->getConnection(); @@ -25,6 +22,8 @@ public function testAliasesFromString(): void $query->from('profile AS \'prf\', user "usr", service srv, order, [a b] [c d], {{something}} AS myalias'); $tables = $query->getTablesUsedInFrom(); + $db->close(); + $this->assertSame( [ '{{prf}}' => '{{profile}}', diff --git a/tests/AbstractQueryTest.php b/tests/AbstractQueryTest.php index d1021be45..a66ca1d2f 100644 --- a/tests/AbstractQueryTest.php +++ b/tests/AbstractQueryTest.php @@ -786,6 +786,8 @@ public function testColumnWithIndexBy(): void ->where(['id' => null]); $this->assertSame([], $query->column()); + + $db->close(); } /** @@ -853,5 +855,7 @@ public function testResultCallback(): void $query->resultCallback(null); $this->assertNull($query->getResultCallback()); + + $db->close(); } } diff --git a/tests/AbstractSchemaTest.php b/tests/AbstractSchemaTest.php index 3ab8340c9..c5c98a82e 100644 --- a/tests/AbstractSchemaTest.php +++ b/tests/AbstractSchemaTest.php @@ -23,6 +23,8 @@ public function testGetDefaultSchema(): void $schema = $db->getSchema(); + $db->close(); + $this->assertSame('', $schema->getDefaultSchema()); } @@ -44,6 +46,8 @@ public function testGetDataType(): void $schema = $db->getSchema(); + $db->close(); + foreach ($values as $value) { $this->assertSame( $value[1], @@ -62,6 +66,8 @@ public function testRefresh(): void $schema = $db->getSchema(); $schema->refresh(); + $db->close(); + $this->assertSame([], Assert::getPropertyValue($schema, 'tableMetadata')); $this->assertSame([], Assert::getPropertyValue($schema, 'tableNames')); } diff --git a/tests/Common/CommonBatchQueryResultTest.php b/tests/Common/CommonBatchQueryResultTest.php index 390bcf99e..20d5a6f07 100644 --- a/tests/Common/CommonBatchQueryResultTest.php +++ b/tests/Common/CommonBatchQueryResultTest.php @@ -128,6 +128,8 @@ public function testBatchWithoutDbParameter(): void $query = $query->from('customer')->orderBy('id')->limit(3); $customers = $this->getAllRowsFromBatch($query->batch(2)); + $db->close(); + $this->assertCount(3, $customers); $this->assertEquals('user1', $customers[0]['name']); $this->assertEquals('user2', $customers[1]['name']); @@ -161,6 +163,8 @@ public function testBatchQueryResultWithoutPopulate(): void $customers = $this->getAllRowsFromBatch($batchQueryResult); + $db->close(); + $this->assertCount(3, $customers); $this->assertEquals('user1', $customers[0]['name']); $this->assertEquals('user2', $customers[1]['name']); diff --git a/tests/Common/CommonQueryBuilderTest.php b/tests/Common/CommonQueryBuilderTest.php index e7df5fa52..c37897d45 100644 --- a/tests/Common/CommonQueryBuilderTest.php +++ b/tests/Common/CommonQueryBuilderTest.php @@ -245,6 +245,8 @@ public function testMultiOperandFunctionBuilder( sort($result, SORT_NATURAL); } + $db->close(); + $this->assertEquals($expectedResult, $result); } diff --git a/tests/Common/CommonSchemaTest.php b/tests/Common/CommonSchemaTest.php index 36252e59e..5c537d75e 100644 --- a/tests/Common/CommonSchemaTest.php +++ b/tests/Common/CommonSchemaTest.php @@ -7,6 +7,7 @@ use PDO; use PHPUnit\Framework\Attributes\DataProviderExternal; use PHPUnit\Framework\Attributes\Depends; +use Throwable; use Yiisoft\Db\Connection\ConnectionInterface; use Yiisoft\Db\Constant\ColumnType; use Yiisoft\Db\Constraint\Check; @@ -74,7 +75,7 @@ public function testCompositeFk(): void $db->close(); } - public function testContraintTablesExistance(): void + public function testConstraintTablesExistance(): void { $db = $this->getConnection(true); @@ -539,53 +540,62 @@ public function testTableSchemaCacheWithTablePrefixes( #[DataProviderExternal(SchemaProvider::class, 'constraints')] public function testTableSchemaConstraints(string $tableName, string $type, mixed $expected): void { - if ($expected === false) { - $this->expectException(NotSupportedException::class); - } - $db = $this->getConnection(true); $schema = $db->getSchema(); - $constraints = $schema->{"getTable$type"}($tableName); - Assert::constraintsEquals($expected, $constraints); + $exception = null; + try { + $constraints = $schema->{"getTable$type"}($tableName); + } catch (Throwable $exception) { + } $db->close(); + + $expected === false + ? $this->assertInstanceOf(NotSupportedException::class, $exception) + : Assert::constraintsEquals($expected, $constraints); } #[DataProviderExternal(SchemaProvider::class, 'constraints')] public function testTableSchemaConstraintsWithPdoLowercase(string $tableName, string $type, mixed $expected): void { - if ($expected === false) { - $this->expectException(NotSupportedException::class); - } - $db = $this->getConnection(true); $schema = $db->getSchema(); $db->getActivePdo()->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER); - $constraints = $schema->{"getTable$type"}($tableName, true); - Assert::constraintsEquals($expected, $constraints); + $exception = null; + try { + $constraints = $schema->{"getTable$type"}($tableName, true); + } catch (Throwable $exception) { + } $db->close(); + + $expected === false + ? $this->assertInstanceOf(NotSupportedException::class, $exception) + : Assert::constraintsEquals($expected, $constraints); } #[DataProviderExternal(SchemaProvider::class, 'constraints')] public function testTableSchemaConstraintsWithPdoUppercase(string $tableName, string $type, mixed $expected): void { - if ($expected === false) { - $this->expectException(NotSupportedException::class); - } - $db = $this->getConnection(true); $schema = $db->getSchema(); $db->getActivePdo()->setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER); - $constraints = $schema->{'getTable' . ucfirst($type)}($tableName, true); - Assert::constraintsEquals($expected, $constraints); + $exception = null; + try { + $constraints = $schema->{'getTable' . ucfirst($type)}($tableName, true); + } catch (Throwable $exception) { + } $db->close(); + + $expected === false + ? $this->assertInstanceOf(NotSupportedException::class, $exception) + : Assert::constraintsEquals($expected, $constraints); } public function testWorkWithUniqueConstraint(): void diff --git a/tests/Db/Query/QueryTest.php b/tests/Db/Query/QueryTest.php index a4588d7a1..d6d08eeeb 100644 --- a/tests/Db/Query/QueryTest.php +++ b/tests/Db/Query/QueryTest.php @@ -110,6 +110,8 @@ public function testWithTypecasting(): void $query = $query->withTypecasting(false); $this->assertFalse(Assert::getPropertyValue($query, 'typecasting')); + + $db->close(); } public function testCreateCommandWithTypecasting(): void @@ -124,6 +126,8 @@ public function testCreateCommandWithTypecasting(): void $command = $query->withTypecasting()->createCommand(); $this->assertTrue(Assert::getPropertyValue($command, 'phpTypecasting')); + + $db->close(); } public static function dataFor(): iterable diff --git a/tests/Db/Schema/SchemaTest.php b/tests/Db/Schema/SchemaTest.php index 7ac04a635..7430e4e51 100644 --- a/tests/Db/Schema/SchemaTest.php +++ b/tests/Db/Schema/SchemaTest.php @@ -31,6 +31,8 @@ public function testFindTableNames(): void $schema = $db->getSchema(); + $db->close(); + $this->expectException(NotSupportedException::class); $this->expectExceptionMessage('Yiisoft\Db\Tests\Support\Stub\Schema does not support fetching all table names.'); @@ -43,6 +45,8 @@ public function testFindViewNames(): void $schema = $db->getSchema(); + $db->close(); + $this->assertSame([], Assert::invokeMethod($schema, 'findViewNames', ['dbo'])); } @@ -60,6 +64,8 @@ public function testGetSchemaChecks(): void $tableChecks = $schemaMock->getSchemaChecks(); $this->assertSame([$checks], $tableChecks); + + $db->close(); } public function testGetSchemaDefaultValues(): void @@ -76,6 +82,8 @@ public function testGetSchemaDefaultValues(): void $tableDefaultValues = $schemaMock->getSchemaDefaultValues(); $this->assertSame([$defaultValues], $tableDefaultValues); + + $db->close(); } public function testGetSchemaForeignKeys(): void @@ -98,6 +106,8 @@ public function testGetSchemaForeignKeys(): void $tableForeignKeys = $schemaMock->getSchemaForeignKeys(); $this->assertSame([$foreignKeys], $tableForeignKeys); + + $db->close(); } public function testGetSchemaIndexes(): void @@ -114,6 +124,8 @@ public function testGetSchemaIndexes(): void $tableIndexes = $schemaMock->getSchemaIndexes(); $this->assertSame([$indexes], $tableIndexes); + + $db->close(); } public function testGetSchemaNames(): void @@ -128,6 +140,8 @@ public function testGetSchemaNames(): void ); $schema->getSchemaNames(); + + $db->close(); } public function testGetSchemaNamesWithSchema(): void @@ -138,6 +152,8 @@ public function testGetSchemaNamesWithSchema(): void Assert::setPropertyValue($schema, 'schemaNames', ['dbo', 'public']); $this->assertSame(['dbo', 'public'], $schema->getSchemaNames()); + + $db->close(); } public function testHasSchema(): void @@ -167,6 +183,8 @@ public function testGetSchemaPrimaryKeys(): void $schemaMock->expects($this->once())->method('getTablePrimaryKey')->willReturn($pksConstraint); $tablePks = $schemaMock->getSchemaPrimaryKeys(); + $db->close(); + $this->assertIsArray($tablePks); $this->assertContainsOnlyInstancesOf(Index::class, $tablePks); } @@ -184,6 +202,8 @@ public function testGetSchemaUniques(): void $schemaMock->expects($this->once())->method('getTableUniques')->willReturn($uniquesConstraint); $tableUniques = $schemaMock->getSchemaUniques(); + $db->close(); + $this->assertIsArray($tableUniques); foreach ($tableUniques as $uniques) { @@ -204,6 +224,8 @@ public function getTableSchema(): void $schemaMock->expects($this->once())->method('loadTableSchema')->willReturn($this->createTableSchemaStub()); $table = $schemaMock->getTableSchema('T_constraints_1'); + $db->close(); + $this->assertInstanceOf(TableSchema::class, $table); $this->assertSame('T_constraints_1', $table->getName()); $this->assertSame('dbo', $table->getSchemaName()); @@ -229,6 +251,8 @@ public function testGetTableSchemas(): void foreach ($tables as $table) { $this->assertInstanceOf(TableSchemaInterface::class, $table); } + + $db->close(); } public function testGetViewNames(): void @@ -237,6 +261,8 @@ public function testGetViewNames(): void $schema = $db->getSchema(); + $db->close(); + $this->assertSame([], $schema->getViewNames()); } @@ -259,6 +285,8 @@ public function testRefreshTableSchema(): void $schemaMock->refreshTableSchema('T_constraints_1'); $refreshedTable = $schemaMock->getTableSchema('T_constraints_1'); + $db->close(); + $this->assertNotSame($noCacheTable, $refreshedTable); } @@ -281,6 +309,8 @@ public function testRefreshTableSchemaWithSchemaCaseDisabled(): void $schemaMock->refreshTableSchema('T_constraints_1'); $refreshedTable = $schemaMock->getTableSchema('T_constraints_1'); + $db->close(); + $this->assertNotSame($noCacheTable, $refreshedTable); } @@ -294,6 +324,8 @@ public function testSetTableMetadata(): void Assert::invokeMethod($schema, 'setTableMetadata', ['T_constraints_1', 'checks', $check]); $this->assertSame($check, $schema->getTableChecks('T_constraints_1')); + + $db->close(); } public function testGetResultColumn(): void @@ -307,6 +339,8 @@ public function testGetResultColumn(): void $this->expectExceptionMessage('Yiisoft\Db\Tests\Support\Stub\Schema::loadResultColumn is not supported by this DBMS.'); $schema->getResultColumn(['native_type' => 'integer']); + + $db->close(); } private function createTableSchemaStub(): TableSchemaInterface