From c1936e2f2de3a4449898b0a2ac7616ad6fabc91c Mon Sep 17 00:00:00 2001 From: bbldn05 Date: Sun, 16 Mar 2025 20:06:59 +0300 Subject: [PATCH 1/9] feat: Add getComment() method to ColumnInterface --- src/ColumnInterface.php | 5 +++++ src/Driver/MySQL/Schema/MySQLColumn.php | 1 + src/Driver/Postgres/Schema/PostgresColumn.php | 1 + src/Driver/Postgres/Schema/PostgresTable.php | 18 ++++++++++++------ src/Schema/AbstractColumn.php | 11 +++++++++++ 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/ColumnInterface.php b/src/ColumnInterface.php index b306ccb8..4741485e 100644 --- a/src/ColumnInterface.php +++ b/src/ColumnInterface.php @@ -63,6 +63,11 @@ public function getPrecision(): int; */ public function getScale(): int; + /** + * Column comment. + */ + public function getComment(): string; + /** * Can column store null value? */ diff --git a/src/Driver/MySQL/Schema/MySQLColumn.php b/src/Driver/MySQL/Schema/MySQLColumn.php index bc530fb2..dc25bdbe 100644 --- a/src/Driver/MySQL/Schema/MySQLColumn.php +++ b/src/Driver/MySQL/Schema/MySQLColumn.php @@ -185,6 +185,7 @@ public static function createInstance(string $table, array $schema, ?\DateTimeZo $column = new self($table, $schema['Field'], $timezone); $column->type = $schema['Type']; + $column->comment = $schema['Comment']; $column->nullable = \strtolower($schema['Null']) === 'yes'; $column->defaultValue = $schema['Default']; $column->autoIncrement = \stripos($schema['Extra'], 'auto_increment') !== false; diff --git a/src/Driver/Postgres/Schema/PostgresColumn.php b/src/Driver/Postgres/Schema/PostgresColumn.php index 6f6748b5..4a62d1f8 100644 --- a/src/Driver/Postgres/Schema/PostgresColumn.php +++ b/src/Driver/Postgres/Schema/PostgresColumn.php @@ -317,6 +317,7 @@ public static function createInstance( }; $column->defaultValue = $schema['column_default']; + $column->comment = (string) $schema['description']; $column->nullable = $schema['is_nullable'] === 'YES'; if ( diff --git a/src/Driver/Postgres/Schema/PostgresTable.php b/src/Driver/Postgres/Schema/PostgresTable.php index da00c4be..5d3f7c2e 100644 --- a/src/Driver/Postgres/Schema/PostgresTable.php +++ b/src/Driver/Postgres/Schema/PostgresTable.php @@ -93,12 +93,18 @@ protected function fetchColumns(): array )->fetchColumn(); $query = $this->driver->query( - 'SELECT * - FROM information_schema.columns - JOIN pg_type - ON (pg_type.typname = columns.udt_name) - WHERE table_schema = ? - AND table_name = ?', + 'SELECT columns.*, pg_type.*, pg_description.description + FROM information_schema.columns + JOIN pg_catalog.pg_type + ON (pg_type.typname = columns.udt_name) + JOIN pg_catalog.pg_statio_all_tables + ON (pg_statio_all_tables.relname = columns.table_name + AND pg_statio_all_tables.schemaname = columns.table_schema) + LEFT JOIN pg_catalog.pg_description + ON (pg_description.objoid = pg_statio_all_tables.relid + AND pg_description.objsubid = columns.ordinal_position) + WHERE columns.table_schema = ? + AND columns.table_name = ?', [$tableSchema, $tableName], ); diff --git a/src/Schema/AbstractColumn.php b/src/Schema/AbstractColumn.php index 5d3f2347..64bf417d 100644 --- a/src/Schema/AbstractColumn.php +++ b/src/Schema/AbstractColumn.php @@ -212,6 +212,12 @@ abstract class AbstractColumn implements ColumnInterface, ElementInterface #[ColumnAttribute(['decimal'])] protected int $scale = 0; + /** + * Column comment. + */ + #[ColumnAttribute] + protected string $comment = ''; + /** * List of allowed enum values. */ @@ -270,6 +276,11 @@ public function getScale(): int return $this->scale; } + public function getComment(): string + { + return $this->comment; + } + public function isNullable(): bool { return $this->nullable; From 4eada1a8e5f13431ab7850618393dbd7fbeb48cb Mon Sep 17 00:00:00 2001 From: bbldn05 Date: Sun, 16 Mar 2025 21:44:25 +0300 Subject: [PATCH 2/9] fix: Moved getComment() to supported implementations --- src/ColumnInterface.php | 5 ----- src/Driver/MySQL/Schema/MySQLColumn.php | 11 +++++++++++ src/Driver/Postgres/Schema/PostgresColumn.php | 11 +++++++++++ src/Schema/AbstractColumn.php | 11 ----------- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/ColumnInterface.php b/src/ColumnInterface.php index 4741485e..b306ccb8 100644 --- a/src/ColumnInterface.php +++ b/src/ColumnInterface.php @@ -63,11 +63,6 @@ public function getPrecision(): int; */ public function getScale(): int; - /** - * Column comment. - */ - public function getComment(): string; - /** * Can column store null value? */ diff --git a/src/Driver/MySQL/Schema/MySQLColumn.php b/src/Driver/MySQL/Schema/MySQLColumn.php index dc25bdbe..06400a32 100644 --- a/src/Driver/MySQL/Schema/MySQLColumn.php +++ b/src/Driver/MySQL/Schema/MySQLColumn.php @@ -177,6 +177,12 @@ class MySQLColumn extends AbstractColumn #[ColumnAttribute(self::INTEGER_TYPES)] protected bool $zerofill = false; + /** + * Column comment. + */ + #[ColumnAttribute] + protected string $comment = ''; + /** * @psalm-param non-empty-string $table */ @@ -356,6 +362,11 @@ public function binary(int $size = 0): self return $this; } + public function getComment(): string + { + return $this->comment; + } + protected static function isEnum(AbstractColumn $column): bool { return $column->getAbstractType() === 'enum' || $column->getAbstractType() === 'set'; diff --git a/src/Driver/Postgres/Schema/PostgresColumn.php b/src/Driver/Postgres/Schema/PostgresColumn.php index 4a62d1f8..f3a75e44 100644 --- a/src/Driver/Postgres/Schema/PostgresColumn.php +++ b/src/Driver/Postgres/Schema/PostgresColumn.php @@ -289,6 +289,12 @@ class PostgresColumn extends AbstractColumn #[ColumnAttribute(['numeric'])] protected int $scale = 0; + /** + * Column comment. + */ + #[ColumnAttribute] + protected string $comment = ''; + /** * Internal field to determine if the serial is PK. */ @@ -617,6 +623,11 @@ public function compare(AbstractColumn $initial): bool ); } + public function getComment(): string + { + return $this->comment; + } + protected static function isJson(AbstractColumn $column): bool { return $column->getAbstractType() === 'json' || $column->getAbstractType() === 'jsonb'; diff --git a/src/Schema/AbstractColumn.php b/src/Schema/AbstractColumn.php index 64bf417d..5d3f2347 100644 --- a/src/Schema/AbstractColumn.php +++ b/src/Schema/AbstractColumn.php @@ -212,12 +212,6 @@ abstract class AbstractColumn implements ColumnInterface, ElementInterface #[ColumnAttribute(['decimal'])] protected int $scale = 0; - /** - * Column comment. - */ - #[ColumnAttribute] - protected string $comment = ''; - /** * List of allowed enum values. */ @@ -276,11 +270,6 @@ public function getScale(): int return $this->scale; } - public function getComment(): string - { - return $this->comment; - } - public function isNullable(): bool { return $this->nullable; From 8af21e36d57c717239aee9d227ef0bb5d103192c Mon Sep 17 00:00:00 2001 From: bbldn05 Date: Sat, 22 Mar 2025 10:01:44 +0300 Subject: [PATCH 3/9] fix: Added comment support for create table statement and alter table statement --- psalm-baseline.xml | 7 +++ src/Driver/MySQL/Schema/MySQLColumn.php | 6 ++- src/Driver/Postgres/PostgresHandler.php | 43 ++++++++++++++----- src/Driver/Postgres/Schema/PostgresColumn.php | 29 ++++++++++++- src/Driver/Postgres/Schema/PostgresTable.php | 2 + 5 files changed, 73 insertions(+), 14 deletions(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 603162a6..4440ea0a 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -895,6 +895,7 @@ + comment]]> type]]> @@ -905,6 +906,7 @@ + @@ -1299,10 +1301,12 @@ + + @@ -1326,6 +1330,7 @@ + + + diff --git a/src/Driver/MySQL/Schema/MySQLColumn.php b/src/Driver/MySQL/Schema/MySQLColumn.php index 06400a32..466cb2e9 100644 --- a/src/Driver/MySQL/Schema/MySQLColumn.php +++ b/src/Driver/MySQL/Schema/MySQLColumn.php @@ -32,11 +32,12 @@ * @method $this|AbstractColumn bigInteger(int $size, bool $unsigned = false, $zerofill = false) * @method $this|AbstractColumn unsigned(bool $value) * @method $this|AbstractColumn zerofill(bool $value) + * @method $this|AbstractColumn comment(string $value) */ class MySQLColumn extends AbstractColumn { /** - * Default timestamp expression (driver specific). + * Default timestamp expression (). */ public const DATETIME_NOW = 'CURRENT_TIMESTAMP'; @@ -393,11 +394,12 @@ protected function formatDatetime( private function sqlStatementInteger(DriverInterface $driver): string { return \sprintf( - '%s %s(%s)%s%s%s%s%s', + '%s %s(%s)%s%s%s%s%s%s', $driver->identifier($this->name), $this->type, $this->size, $this->unsigned ? ' UNSIGNED' : '', + $this->comment !== '' ? ' COMMENT' : '', $this->zerofill ? ' ZEROFILL' : '', $this->nullable ? ' NULL' : ' NOT NULL', $this->defaultValue !== null ? " DEFAULT {$this->quoteDefault($driver)}" : '', diff --git a/src/Driver/Postgres/PostgresHandler.php b/src/Driver/Postgres/PostgresHandler.php index 8015269a..5e9bfbc8 100644 --- a/src/Driver/Postgres/PostgresHandler.php +++ b/src/Driver/Postgres/PostgresHandler.php @@ -117,18 +117,21 @@ public function alterColumn( //Postgres columns should be altered using set of operations $operations = $column->alterOperations($this->driver, $initial); - if (empty($operations)) { - return; + if (\count($operations) > 0) { + //Postgres columns should be altered using set of operations + $query = \sprintf( + 'ALTER TABLE %s %s', + $this->identify($table), + \trim(\implode(', ', $operations), ', '), + ); + + $this->run($query); } - //Postgres columns should be altered using set of operations - $query = \sprintf( - 'ALTER TABLE %s %s', - $this->identify($table), - \trim(\implode(', ', $operations), ', '), - ); - - $this->run($query); + $operation = $column->commentOperation($this->driver, $initial); + if ($operation !== null) { + $this->run($operation); + } } public function enableForeignKeyConstraints(): void @@ -141,6 +144,26 @@ public function disableForeignKeyConstraints(): void $this->run('SET CONSTRAINTS ALL DEFERRED;'); } + public function createTable(AbstractTable $table): void + { + if (!$table instanceof PostgresTable) { + throw new SchemaException('Postgres handler can work only with Postgres table'); + } + + parent::createTable($table); + + foreach ($table->getColumns() as $column) { + $this->createComment($column); + } + } + + public function createComment(PostgresColumn $column): void + { + if ($column->getComment() !== '') { + $this->run($column->createComment($this->driver)); + } + } + /** * @psalm-param non-empty-string $statement */ diff --git a/src/Driver/Postgres/Schema/PostgresColumn.php b/src/Driver/Postgres/Schema/PostgresColumn.php index f3a75e44..49bc1cc1 100644 --- a/src/Driver/Postgres/Schema/PostgresColumn.php +++ b/src/Driver/Postgres/Schema/PostgresColumn.php @@ -11,10 +11,10 @@ namespace Cycle\Database\Driver\Postgres\Schema; -use Cycle\Database\Driver\DriverInterface; -use Cycle\Database\Exception\SchemaException; use Cycle\Database\Injection\Fragment; use Cycle\Database\Schema\AbstractColumn; +use Cycle\Database\Driver\DriverInterface; +use Cycle\Database\Exception\SchemaException; use Cycle\Database\Schema\Attribute\ColumnAttribute; /** @@ -44,6 +44,7 @@ * @method $this smallSerial() * @method $this serial() * @method $this bigSerial() + * @method $this comment(string $value) */ class PostgresColumn extends AbstractColumn { @@ -540,6 +541,19 @@ public function sqlStatement(DriverInterface $driver): string return $statement; } + /** + * @psalm-return non-empty-string|null + */ + public function commentOperation(DriverInterface $driver, PostgresColumn $initial): ?string + { + //Comment + if ($initial->comment !== $this->comment) { + return $this->createComment($driver); + } + + return null; + } + /** * Generate set of operations need to change column. */ @@ -628,6 +642,17 @@ public function getComment(): string return $this->comment; } + /** + * @psalm-return non-empty-string + */ + public function createComment(DriverInterface $driver): string + { + $tableName = $driver->identifier($this->getTable()); + $identifier = $driver->identifier($this->getName()); + + return "COMMENT ON COLUMN {$tableName}.{$identifier} IS " . $driver->quote($this->comment); + } + protected static function isJson(AbstractColumn $column): bool { return $column->getAbstractType() === 'json' || $column->getAbstractType() === 'jsonb'; diff --git a/src/Driver/Postgres/Schema/PostgresTable.php b/src/Driver/Postgres/Schema/PostgresTable.php index 5d3f7c2e..676ec899 100644 --- a/src/Driver/Postgres/Schema/PostgresTable.php +++ b/src/Driver/Postgres/Schema/PostgresTable.php @@ -20,6 +20,8 @@ /** * @property PostgresDriver $driver + * + * @method PostgresColumn[] getColumns() */ class PostgresTable extends AbstractTable { From 80aff29099d1b94d330233099842a98ce8eddb55 Mon Sep 17 00:00:00 2001 From: bbldn05 Date: Sat, 22 Mar 2025 16:04:50 +0300 Subject: [PATCH 4/9] fix: Added comment support for create table statement and alter table statement --- src/Driver/MySQL/Schema/MySQLColumn.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Driver/MySQL/Schema/MySQLColumn.php b/src/Driver/MySQL/Schema/MySQLColumn.php index 466cb2e9..479df4c1 100644 --- a/src/Driver/MySQL/Schema/MySQLColumn.php +++ b/src/Driver/MySQL/Schema/MySQLColumn.php @@ -300,6 +300,10 @@ public function sqlStatement(DriverInterface $driver): string return "{$statement} AUTO_INCREMENT"; } + if ($this->comment !== '') { + return "{$statement} COMMENT {$driver->quote($this->comment)}"; + } + return $statement; } @@ -399,7 +403,7 @@ private function sqlStatementInteger(DriverInterface $driver): string $this->type, $this->size, $this->unsigned ? ' UNSIGNED' : '', - $this->comment !== '' ? ' COMMENT' : '', + $this->comment !== '' ? " COMMENT {$driver->quote($this->comment)}" : '', $this->zerofill ? ' ZEROFILL' : '', $this->nullable ? ' NULL' : ' NOT NULL', $this->defaultValue !== null ? " DEFAULT {$this->quoteDefault($driver)}" : '', From 0069b6fcdc094928b5660b424bd8e8f75f4d70fb Mon Sep 17 00:00:00 2001 From: bbldn05 Date: Sat, 22 Mar 2025 16:06:38 +0300 Subject: [PATCH 5/9] fix: Added tests for the comments functionality --- .../Driver/MySQL/Schema/CommentTest.php | 57 +++++++++++++++++++ .../Driver/Postgres/Schema/CommentTest.php | 57 +++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 tests/Database/Functional/Driver/MySQL/Schema/CommentTest.php create mode 100644 tests/Database/Functional/Driver/Postgres/Schema/CommentTest.php diff --git a/tests/Database/Functional/Driver/MySQL/Schema/CommentTest.php b/tests/Database/Functional/Driver/MySQL/Schema/CommentTest.php new file mode 100644 index 00000000..39824b65 --- /dev/null +++ b/tests/Database/Functional/Driver/MySQL/Schema/CommentTest.php @@ -0,0 +1,57 @@ +schema('table'); + $this->assertFalse($schema->exists()); + + /** @var MySqlColumn $column */ + $column = $schema->string('target'); + $column->comment('foo'); + + $schema->save(); + + $schema = $this->schema('table'); + $this->assertTrue($schema->exists()); + $this->assertTrue($schema->column('target')->compare($column)); + } + + public function testChangeComment(): void + { + $schema = $this->schema('table'); + $this->assertFalse($schema->exists()); + + /** @var MySqlColumn $column */ + $column = $schema->string('target'); + $column->comment('foo'); + + $schema->save(); + + $schema = $this->schema('table'); + $this->assertTrue($schema->exists()); + + /** @var MySqlColumn $column */ + $column = $schema->string('target'); + $column->comment('bar'); + + $schema->save(); + + $this->assertTrue($schema->column('target')->compare($column)); + } +} diff --git a/tests/Database/Functional/Driver/Postgres/Schema/CommentTest.php b/tests/Database/Functional/Driver/Postgres/Schema/CommentTest.php new file mode 100644 index 00000000..470ddc65 --- /dev/null +++ b/tests/Database/Functional/Driver/Postgres/Schema/CommentTest.php @@ -0,0 +1,57 @@ +schema('table'); + $this->assertFalse($schema->exists()); + + /** @var PostgresColumn $column */ + $column = $schema->string('target'); + $column->comment('foo'); + + $schema->save(); + + $schema = $this->schema('table'); + $this->assertTrue($schema->exists()); + $this->assertTrue($schema->column('target')->compare($column)); + } + + public function testChangeComment(): void + { + $schema = $this->schema('table'); + $this->assertFalse($schema->exists()); + + /** @var PostgresColumn $column */ + $column = $schema->string('target'); + $column->comment('foo'); + + $schema->save(); + + $schema = $this->schema('table'); + $this->assertTrue($schema->exists()); + + /** @var PostgresColumn $column */ + $column = $schema->string('target'); + $column->comment('bar'); + + $schema->save(); + + $this->assertTrue($schema->column('target')->compare($column)); + } +} From a59a33f05e498c3ffc7a928292afeb0705812205 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Thu, 27 Mar 2025 18:01:25 +0400 Subject: [PATCH 6/9] tests: enhance test generator; reorganize comment tests (move similar methods into common class) --- src/Driver/MySQL/Schema/MySQLColumn.php | 3 - .../Functional/Driver/Common/BaseTest.php | 1 + .../Common/Connection/BaseConnectionTest.php | 2 + .../Driver/Common/Schema/CommentTest.php | 124 ++++++++++++++++++ .../Driver/MySQL/Schema/CommentTest.php | 44 +------ .../Driver/Postgres/Schema/CommentTest.php | 44 +------ .../Database/Utils/DontGenerateAttribute.php | 8 ++ tests/generate.php | 20 ++- 8 files changed, 153 insertions(+), 93 deletions(-) create mode 100644 tests/Database/Functional/Driver/Common/Schema/CommentTest.php create mode 100644 tests/Database/Utils/DontGenerateAttribute.php diff --git a/src/Driver/MySQL/Schema/MySQLColumn.php b/src/Driver/MySQL/Schema/MySQLColumn.php index 479df4c1..f9a3b084 100644 --- a/src/Driver/MySQL/Schema/MySQLColumn.php +++ b/src/Driver/MySQL/Schema/MySQLColumn.php @@ -296,9 +296,6 @@ public function sqlStatement(DriverInterface $driver): string $statement = parent::sqlStatement($driver); $this->defaultValue = $defaultValue; - if ($this->autoIncrement) { - return "{$statement} AUTO_INCREMENT"; - } if ($this->comment !== '') { return "{$statement} COMMENT {$driver->quote($this->comment)}"; diff --git a/tests/Database/Functional/Driver/Common/BaseTest.php b/tests/Database/Functional/Driver/Common/BaseTest.php index f7b40549..27929de9 100644 --- a/tests/Database/Functional/Driver/Common/BaseTest.php +++ b/tests/Database/Functional/Driver/Common/BaseTest.php @@ -41,6 +41,7 @@ public function setUp(): void public function tearDown(): void { + $this->disableProfiling(); $this->dropDatabase($this->database); } diff --git a/tests/Database/Functional/Driver/Common/Connection/BaseConnectionTest.php b/tests/Database/Functional/Driver/Common/Connection/BaseConnectionTest.php index a2c145f6..76e901a4 100644 --- a/tests/Database/Functional/Driver/Common/Connection/BaseConnectionTest.php +++ b/tests/Database/Functional/Driver/Common/Connection/BaseConnectionTest.php @@ -9,7 +9,9 @@ use Cycle\Database\Tests\Stub\Driver\MysqlWrapDriver; use Cycle\Database\Tests\Stub\Driver\PostgresWrapDriver; use Cycle\Database\Tests\Stub\Driver\SQLiteWrapDriver; +use Cycle\Database\Tests\Utils\DontGenerateAttribute; +#[DontGenerateAttribute] abstract class BaseConnectionTest extends BaseTest { public function setUp(): void diff --git a/tests/Database/Functional/Driver/Common/Schema/CommentTest.php b/tests/Database/Functional/Driver/Common/Schema/CommentTest.php new file mode 100644 index 00000000..2671d3f9 --- /dev/null +++ b/tests/Database/Functional/Driver/Common/Schema/CommentTest.php @@ -0,0 +1,124 @@ +schema('table'); + $this->assertFalse($schema->exists()); + + $column = $schema->string('target'); + $column->comment('foo'); + + $schema->save(); + + $schema = $this->schema('table'); + $this->assertTrue($schema->exists()); + + $column2 = $schema->column('target'); + $this->assertTrue($column2->compare($column)); + self::assertSame('foo', $column2->getComment()); + } + + public function testChangeComment(): void + { + $schema = $this->schema('table'); + $this->assertFalse($schema->exists()); + + $column = $schema->string('target'); + $column->comment('foo'); + + $schema->save(); + + $schema = $this->schema('table'); + $this->assertTrue($schema->exists()); + + $column2 = $schema->column('target'); + $column2->comment('bar'); + + $schema->save(); + + $this->assertTrue($schema->column('target')->compare($column2)); + self::assertSame('bar', $schema->column('target')->getComment()); + } + + public function testChangeCommentToEmpty(): void + { + $schema = $this->schema('table'); + $column = $schema->string('target'); + $column->comment('foo'); + + $schema->save(); + + $schema = $this->schema('table'); + $this->assertTrue($schema->exists()); + + $column2 = $schema->column('target'); + self::assertSame('foo', $column2->getComment()); + + $column2->comment(''); + + $schema->save(); + + $schema = $this->schema('table'); + $column3 = $schema->column('target'); + self::assertSame('', $column3->getComment()); + } + + public function testCommentWithAutoIncrement(): void + { + $schema = $this->schema('table'); + $column = $schema->primary('target'); + $column->comment('foo'); + + $schema->save(); + + $schema = $this->schema('table'); + $this->assertTrue($schema->exists()); + + $column2 = $schema->column('target'); + $this->assertTrue($column2->compare($column)); + self::assertSame('foo', $column2->getComment()); + } + + public function testSQLInjection(): void + { + $schema = $this->schema('table'); + $column = $schema->string('target'); + $column->comment('f"o\'o`'); + + $schema->save(); + + $schema = $this->schema('table'); + $this->assertTrue($schema->exists()); + + $column2 = $schema->column('target'); + $this->assertTrue($column2->compare($column)); + self::assertSame('f"o\'o`', $column2->getComment()); + } + + public function testSQLInjectionIntegers(): void + { + $schema = $this->schema('table'); + $column = $schema->primary('target'); + $column->comment('f"o\'o`'); + + $schema->save(); + + $schema = $this->schema('table'); + $this->assertTrue($schema->exists()); + + $column2 = $schema->column('target'); + $this->assertTrue($column2->compare($column)); + self::assertSame('f"o\'o`', $column2->getComment()); + } +} diff --git a/tests/Database/Functional/Driver/MySQL/Schema/CommentTest.php b/tests/Database/Functional/Driver/MySQL/Schema/CommentTest.php index 39824b65..4a0f0c5d 100644 --- a/tests/Database/Functional/Driver/MySQL/Schema/CommentTest.php +++ b/tests/Database/Functional/Driver/MySQL/Schema/CommentTest.php @@ -5,53 +5,13 @@ namespace Cycle\Database\Tests\Functional\Driver\MySQL\Schema; // phpcs:ignore -use Cycle\Database\Driver\MySQL\Schema\MySQLColumn; -use Cycle\Database\Tests\Functional\Driver\Common\BaseTest; +use Cycle\Database\Tests\Functional\Driver\Common\Schema\CommentTest as CommonClass; /** * @group driver * @group driver-mysql */ -class CommentTest extends BaseTest +class CommentTest extends CommonClass { public const DRIVER = 'mysql'; - - public function testAddComment(): void - { - $schema = $this->schema('table'); - $this->assertFalse($schema->exists()); - - /** @var MySqlColumn $column */ - $column = $schema->string('target'); - $column->comment('foo'); - - $schema->save(); - - $schema = $this->schema('table'); - $this->assertTrue($schema->exists()); - $this->assertTrue($schema->column('target')->compare($column)); - } - - public function testChangeComment(): void - { - $schema = $this->schema('table'); - $this->assertFalse($schema->exists()); - - /** @var MySqlColumn $column */ - $column = $schema->string('target'); - $column->comment('foo'); - - $schema->save(); - - $schema = $this->schema('table'); - $this->assertTrue($schema->exists()); - - /** @var MySqlColumn $column */ - $column = $schema->string('target'); - $column->comment('bar'); - - $schema->save(); - - $this->assertTrue($schema->column('target')->compare($column)); - } } diff --git a/tests/Database/Functional/Driver/Postgres/Schema/CommentTest.php b/tests/Database/Functional/Driver/Postgres/Schema/CommentTest.php index 470ddc65..c103bc41 100644 --- a/tests/Database/Functional/Driver/Postgres/Schema/CommentTest.php +++ b/tests/Database/Functional/Driver/Postgres/Schema/CommentTest.php @@ -5,53 +5,13 @@ namespace Cycle\Database\Tests\Functional\Driver\Postgres\Schema; // phpcs:ignore -use Cycle\Database\Driver\Postgres\Schema\PostgresColumn; -use Cycle\Database\Tests\Functional\Driver\Common\BaseTest; +use Cycle\Database\Tests\Functional\Driver\Common\Schema\CommentTest as CommonClass; /** * @group driver * @group driver-postgres */ -class CommentTest extends BaseTest +class CommentTest extends CommonClass { public const DRIVER = 'postgres'; - - public function testAddComment(): void - { - $schema = $this->schema('table'); - $this->assertFalse($schema->exists()); - - /** @var PostgresColumn $column */ - $column = $schema->string('target'); - $column->comment('foo'); - - $schema->save(); - - $schema = $this->schema('table'); - $this->assertTrue($schema->exists()); - $this->assertTrue($schema->column('target')->compare($column)); - } - - public function testChangeComment(): void - { - $schema = $this->schema('table'); - $this->assertFalse($schema->exists()); - - /** @var PostgresColumn $column */ - $column = $schema->string('target'); - $column->comment('foo'); - - $schema->save(); - - $schema = $this->schema('table'); - $this->assertTrue($schema->exists()); - - /** @var PostgresColumn $column */ - $column = $schema->string('target'); - $column->comment('bar'); - - $schema->save(); - - $this->assertTrue($schema->column('target')->compare($column)); - } } diff --git a/tests/Database/Utils/DontGenerateAttribute.php b/tests/Database/Utils/DontGenerateAttribute.php new file mode 100644 index 00000000..01d2a7e5 --- /dev/null +++ b/tests/Database/Utils/DontGenerateAttribute.php @@ -0,0 +1,8 @@ + [__DIR__ . '/Database/Functional/Driver/Common'], @@ -56,7 +57,9 @@ continue; } - echo "Found {$class->getName()}\n"; + if ($class->getAttributes(DontGenerateAttribute::class) !== []) { + continue; + } $path = \str_replace( [\str_replace('\\', '/', __DIR__), 'Database/Functional/Driver/Common/'], @@ -64,10 +67,15 @@ \str_replace('\\', '/', $class->getFileName()), ); - $path = \ltrim($path, '/'); + $path = ltrim($path, '/'); foreach ($databases as $driver => $details) { - $filename = \sprintf('%s%s', $details['directory'], $path); + $filename = $details['directory'] . $path; + if (\file_exists($filename)) { + continue; + } + echo "Processing $filename\n"; + $dir = \pathinfo($filename, PATHINFO_DIRNAME); $namespace = \str_replace( From c3cab76a58eb0308285aefc4721a5389770c8c92 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Thu, 27 Mar 2025 18:10:33 +0400 Subject: [PATCH 7/9] feat: add `getColumn()` method into ColumnInterface --- src/ColumnInterface.php | 3 +++ src/Schema/AbstractColumn.php | 9 +++++++++ .../Functional/Driver/Common/Schema/CommentTest.php | 1 + 3 files changed, 13 insertions(+) diff --git a/src/ColumnInterface.php b/src/ColumnInterface.php index b306ccb8..1fbe8284 100644 --- a/src/ColumnInterface.php +++ b/src/ColumnInterface.php @@ -13,6 +13,9 @@ /** * Represents table schema column abstraction. + * + * @method string getComment() Get column comment. + * An empty string will be returned if the feature is not supported by the driver. */ interface ColumnInterface { diff --git a/src/Schema/AbstractColumn.php b/src/Schema/AbstractColumn.php index 5d3f2347..a9078841 100644 --- a/src/Schema/AbstractColumn.php +++ b/src/Schema/AbstractColumn.php @@ -785,4 +785,13 @@ protected function formatDatetime( default => $value, }; } + + /** + * Get column comment. + * An empty string will be returned if the feature is not supported by the driver. + */ + public function getComment(): string + { + return ''; + } } diff --git a/tests/Database/Functional/Driver/Common/Schema/CommentTest.php b/tests/Database/Functional/Driver/Common/Schema/CommentTest.php index 2671d3f9..963065c1 100644 --- a/tests/Database/Functional/Driver/Common/Schema/CommentTest.php +++ b/tests/Database/Functional/Driver/Common/Schema/CommentTest.php @@ -5,6 +5,7 @@ namespace Cycle\Database\Tests\Functional\Driver\Common\Schema; // phpcs:ignore +use Cycle\Database\ColumnInterface; use Cycle\Database\Tests\Functional\Driver\Common\BaseTest; use Cycle\Database\Tests\Utils\DontGenerateAttribute; From a694ee15718267baddf56c96c82557d09bfc00f6 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Thu, 27 Mar 2025 18:31:40 +0400 Subject: [PATCH 8/9] ci: update workflow actions --- .github/workflows/ci.yml | 19 ++++------------ .github/workflows/main.yml | 44 +++++++++++--------------------------- 2 files changed, 16 insertions(+), 47 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 26377678..2ebbd5ed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,12 +54,11 @@ jobs: strict: true - name: 🛠️ Setup PHP - uses: shivammathur/setup-php@2.30.2 + uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} extensions: mbstring, pdo, pdo_sqlite ini-values: error_reporting=E_ALL - coverage: xdebug - name: 🛠️ Setup problem matchers run: | @@ -68,20 +67,10 @@ jobs: - name: 🤖 Validate composer.json and composer.lock run: composer validate --ansi --strict - - name: 🔍 Get composer cache directory - uses: cycle/gh-actions/actions/composer/get-cache-directory@v4.0.0 - - - name: ♻️ Restore cached dependencies installed with composer - uses: actions/cache@v4.0.2 - with: - path: ${{ env.COMPOSER_CACHE_DIR }} - key: php-${{ matrix.php-version }}-composer-${{ matrix.dependencies }}-${{ hashFiles('composer.lock') }} - restore-keys: php-${{ matrix.php-version }}-composer-${{ matrix.dependencies }}- - - - name: 📥 Install "${{ matrix.dependencies }}" dependencies - uses: cycle/gh-actions/actions/composer/install@v4.0.0 + - name: 📥 Install dependencies with composer + uses: ramsey/composer-install@v3 with: - dependencies: ${{ matrix.dependencies }} + dependency-versions: ${{ matrix.dependencies }} - name: 🔍 Run composer-normalize run: composer normalize --ansi --dry-run diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 91905d50..7b4d3c86 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: ['8.0', '8.1', '8.2', '8.3'] + php-versions: ['8.0', '8.1', '8.2', '8.3', '8.4'] steps: - name: Install ODBC driver. run: | @@ -37,33 +37,24 @@ jobs: coverage: pcov tools: pecl extensions: mbstring, pdo, pdo_sqlite, pdo_pgsql, pdo_sqlsrv, pdo_mysql - - name: Get Composer Cache Directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Restore Composer Cache - uses: actions/cache@v2 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Install dependencies with composer - if: matrix.php-versions != '8.3' - run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi + - name: Validate composer.json and composer.lock + run: composer validate --ansi --strict - - name: Install dependencies with composer php 8.3 - if: matrix.php-versions == '8.3' - run: composer update --ignore-platform-reqs --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi + - name: Install dependencies with composer + uses: ramsey/composer-install@v3 - name: Execute Tests run: | vendor/bin/phpunit --coverage-clover=coverage.clover + - name: Upload coverage to Codecov continue-on-error: true # if is fork uses: codecov/codecov-action@v1 with: token: ${{ secrets.CODECOV_TOKEN }} file: ./coverage.clover + - name: Upload coverage to Scrutinizer continue-on-error: true # if is fork uses: sudo-bot/action-scrutinizer@latest @@ -75,7 +66,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: ['8.0', '8.1', '8.2', '8.3'] + php-versions: ['8.0', '8.1', '8.2', '8.3', '8.4'] steps: - name: Checkout uses: actions/checkout@v2 @@ -86,23 +77,12 @@ jobs: coverage: pcov tools: pecl extensions: mbstring, pdo, pdo_sqlite - - name: Get Composer Cache Directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Restore Composer Cache - uses: actions/cache@v2 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Install dependencies with composer - if: matrix.php-versions != '8.3' - run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi + - name: Validate composer.json and composer.lock + run: composer validate --ansi --strict - - name: Install dependencies with composer php 8.3 - if: matrix.php-versions == '8.3' - run: composer update --ignore-platform-reqs --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi + - name: Install dependencies with composer + uses: ramsey/composer-install@v3 - name: Execute Tests env: From fd1a7d085bd8bc1eb85136a0aeb9c9a99b197781 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Thu, 27 Mar 2025 18:35:20 +0400 Subject: [PATCH 9/9] ci: fix labeler permissions; use composer update in tests --- .github/workflows/apply-labels.yml | 3 +++ .github/workflows/main.yml | 30 +++++++++++++++++------------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/.github/workflows/apply-labels.yml b/.github/workflows/apply-labels.yml index 3e5f992d..931bccf1 100644 --- a/.github/workflows/apply-labels.yml +++ b/.github/workflows/apply-labels.yml @@ -14,6 +14,9 @@ name: 🏷️ Add labels jobs: label: + permissions: + contents: read + pull-requests: write uses: cycle/gh-actions/.github/workflows/apply-labels.yml@v4.0.0 with: os: ubuntu-latest diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7b4d3c86..500cb4f9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,14 +23,14 @@ jobs: sudo curl https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/prod.list | sudo tee /etc/apt/sources.list.d/mssql-release.list sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18 - - name: Checkout + - name: 📦 Checkout uses: actions/checkout@v2 - - name: Setup DB services + - name: 🛠️ Setup DB services run: | cd tests docker compose up -d cd .. - - name: Setup PHP ${{ matrix.php-versions }} + - name: 🛠️ Setup PHP ${{ matrix.php-versions }} uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} @@ -38,24 +38,26 @@ jobs: tools: pecl extensions: mbstring, pdo, pdo_sqlite, pdo_pgsql, pdo_sqlsrv, pdo_mysql - - name: Validate composer.json and composer.lock + - name: 🤖 Validate composer.json and composer.lock run: composer validate --ansi --strict - - name: Install dependencies with composer + - name: 📥 Install dependencies with composer uses: ramsey/composer-install@v3 + with: + dependency-versions: "highest" - - name: Execute Tests + - name: 🚀 Execute Tests run: | vendor/bin/phpunit --coverage-clover=coverage.clover - - name: Upload coverage to Codecov + - name: 🦆 Upload coverage to Codecov continue-on-error: true # if is fork uses: codecov/codecov-action@v1 with: token: ${{ secrets.CODECOV_TOKEN }} file: ./coverage.clover - - name: Upload coverage to Scrutinizer + - name: 🦆 Upload coverage to Scrutinizer continue-on-error: true # if is fork uses: sudo-bot/action-scrutinizer@latest with: @@ -68,9 +70,9 @@ jobs: matrix: php-versions: ['8.0', '8.1', '8.2', '8.3', '8.4'] steps: - - name: Checkout + - name: 📦 Checkout uses: actions/checkout@v2 - - name: Setup PHP ${{ matrix.php-versions }} + - name: 🛠️ Setup PHP ${{ matrix.php-versions }} uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} @@ -78,13 +80,15 @@ jobs: tools: pecl extensions: mbstring, pdo, pdo_sqlite - - name: Validate composer.json and composer.lock + - name: 🤖 Validate composer.json and composer.lock run: composer validate --ansi --strict - - name: Install dependencies with composer + - name: 📥 Install dependencies with composer uses: ramsey/composer-install@v3 + with: + dependency-versions: "highest" - - name: Execute Tests + - name: 🚀 Execute Tests env: DB: sqlite run: |