From 4ee32a5b59d82a5d941d33928b185b404c3dc0ad Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Fri, 28 Jun 2024 16:17:19 +0530 Subject: [PATCH 1/7] Initial commit to create PR --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1cd2090b..3bb79307 100644 --- a/README.md +++ b/README.md @@ -568,3 +568,4 @@ Professional support, consulting as well as software development services are av https://www.cebe.cc/en/contact Development of this library is sponsored by [cebe.:cloud: "Your Professional Deployment Platform"](https://cebe.cloud). + From eeb7a7216b87252d38a94b3309dfc1d7d51f7f01 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Mon, 1 Jul 2024 20:42:27 +0530 Subject: [PATCH 2/7] Fix main part of this issue --- README.md | 1 - src/lib/AttributeResolver.php | 4 +++- tests/specs/postgres_custom.yaml | 2 +- .../m200000_000000_change_table_v3_pgcustom.php | 2 +- tests/unit/MultiDbSecondaryMigrationTest.php | 1 + 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3bb79307..1cd2090b 100644 --- a/README.md +++ b/README.md @@ -568,4 +568,3 @@ Professional support, consulting as well as software development services are av https://www.cebe.cc/en/contact Development of this library is sponsored by [cebe.:cloud: "Your Professional Deployment Platform"](https://cebe.cloud). - diff --git a/src/lib/AttributeResolver.php b/src/lib/AttributeResolver.php index 0063d8df..aca8b1a9 100644 --- a/src/lib/AttributeResolver.php +++ b/src/lib/AttributeResolver.php @@ -425,7 +425,9 @@ protected function prepareIndexes(array $indexes):array foreach ($indexes as $index) { $unique = false; if (strpos($index, ':') !== false) { - [$indexType, $props] = explode(':', $index); + $props = strrchr($index, ':'); + $props = substr($props, 1); + $indexType = str_replace(':'.$props, '', $index); } else { $props = $index; $indexType = null; diff --git a/tests/specs/postgres_custom.yaml b/tests/specs/postgres_custom.yaml index e3d9a810..d6137a3d 100644 --- a/tests/specs/postgres_custom.yaml +++ b/tests/specs/postgres_custom.yaml @@ -35,7 +35,7 @@ components: Custom: x-table: v3_pgcustom x-indexes: - - "gin(to_tsvector('english', status)):search" + - "gin(to_tsvector('english', search::text)):search" required: - id properties: diff --git a/tests/specs/postgres_custom/migrations_pgsql_db/m200000_000000_change_table_v3_pgcustom.php b/tests/specs/postgres_custom/migrations_pgsql_db/m200000_000000_change_table_v3_pgcustom.php index a1ffe61a..6d1badd0 100644 --- a/tests/specs/postgres_custom/migrations_pgsql_db/m200000_000000_change_table_v3_pgcustom.php +++ b/tests/specs/postgres_custom/migrations_pgsql_db/m200000_000000_change_table_v3_pgcustom.php @@ -17,7 +17,7 @@ public function safeUp() $this->alterColumn('{{%v3_pgcustom}}', 'json4', "SET DEFAULT '{\"foo\":\"bar\",\"bar\":\"baz\"}'"); $this->alterColumn('{{%v3_pgcustom}}', 'status', "SET DEFAULT 'draft'"); $this->alterColumn('{{%v3_pgcustom}}', 'status_x', "SET DEFAULT 'draft'"); - $this->createIndex('v3_pgcustom_search_gin_index', '{{%v3_pgcustom}}', 'search', 'gin(to_tsvector(\'english\', status))'); + $this->createIndex('v3_pgcustom_search_gin_index', '{{%v3_pgcustom}}', 'search', 'gin(to_tsvector(\'english\', search::text))'); } public function safeDown() diff --git a/tests/unit/MultiDbSecondaryMigrationTest.php b/tests/unit/MultiDbSecondaryMigrationTest.php index f20b3e93..cc3d90cb 100644 --- a/tests/unit/MultiDbSecondaryMigrationTest.php +++ b/tests/unit/MultiDbSecondaryMigrationTest.php @@ -22,6 +22,7 @@ public function testPostgresCustom() $this->assertInstanceOf(PgSqlSchema::class, Yii::$app->db->schema); $testFile = Yii::getAlias('@specs/postgres_custom.php'); $this->runGenerator($testFile, $dbName); + $this->runActualMigrations('pgsql', 1); $expectedFiles = $this->findExpectedFiles($testFile, $dbName); $actualFiles = $this->findActualFiles(); $this->assertEquals($expectedFiles, $actualFiles); From 25c2e5f5e6a5aed974323fa584e57ca4a46fd201 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Tue, 2 Jul 2024 19:24:31 +0530 Subject: [PATCH 3/7] WIP --- src/lib/AttributeResolver.php | 8 +++++--- src/lib/migrations/MigrationRecordBuilder.php | 2 +- tests/unit/MultiDbSecondaryMigrationTest.php | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/lib/AttributeResolver.php b/src/lib/AttributeResolver.php index aca8b1a9..cba2bbdd 100644 --- a/src/lib/AttributeResolver.php +++ b/src/lib/AttributeResolver.php @@ -425,9 +425,11 @@ protected function prepareIndexes(array $indexes):array foreach ($indexes as $index) { $unique = false; if (strpos($index, ':') !== false) { - $props = strrchr($index, ':'); - $props = substr($props, 1); - $indexType = str_replace(':'.$props, '', $index); + // [$indexType, $props] = explode(':', $index); + // if `$index` is `gin(to_tsvector('english', search::text)):search,prop2` + $props = strrchr($index, ':'); # `$props` is now `:search,prop2` + $props = substr($props, 1); # search,prop2 + $indexType = str_replace(':'.$props, '', $index); # `gin(to_tsvector('english', search::text))` } else { $props = $index; $indexType = null; diff --git a/src/lib/migrations/MigrationRecordBuilder.php b/src/lib/migrations/MigrationRecordBuilder.php index 98ee03b8..e12f5d72 100644 --- a/src/lib/migrations/MigrationRecordBuilder.php +++ b/src/lib/migrations/MigrationRecordBuilder.php @@ -246,7 +246,7 @@ public function addIndex(string $tableAlias, string $indexName, array $columns, self::ADD_INDEX, $indexName, $tableAlias, - count($columns) === 1 ? "'{$columns[0]}'" : '["'.implode('", "', $columns).'"]', + count($columns) === 1 ? "'". ColumnToCode::escapeQuotes($columns[0])."'" : '["'.implode('", "', $columns).'"]', $indexType ); } diff --git a/tests/unit/MultiDbSecondaryMigrationTest.php b/tests/unit/MultiDbSecondaryMigrationTest.php index cc3d90cb..8ae94374 100644 --- a/tests/unit/MultiDbSecondaryMigrationTest.php +++ b/tests/unit/MultiDbSecondaryMigrationTest.php @@ -22,7 +22,7 @@ public function testPostgresCustom() $this->assertInstanceOf(PgSqlSchema::class, Yii::$app->db->schema); $testFile = Yii::getAlias('@specs/postgres_custom.php'); $this->runGenerator($testFile, $dbName); - $this->runActualMigrations('pgsql', 1); +// $this->runActualMigrations('pgsql', 1); $expectedFiles = $this->findExpectedFiles($testFile, $dbName); $actualFiles = $this->findActualFiles(); $this->assertEquals($expectedFiles, $actualFiles); From 4ddf375ceb60f69156fdaa8e406eeaf43bc41f60 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Tue, 2 Jul 2024 21:03:30 +0530 Subject: [PATCH 4/7] Fix bug --- src/lib/AttributeResolver.php | 2 +- src/lib/migrations/MigrationRecordBuilder.php | 11 ++++++++++- .../m200000_000000_change_table_v3_pgcustom.php | 2 +- tests/unit/MultiDbSecondaryMigrationTest.php | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/lib/AttributeResolver.php b/src/lib/AttributeResolver.php index cba2bbdd..3a6374a2 100644 --- a/src/lib/AttributeResolver.php +++ b/src/lib/AttributeResolver.php @@ -434,7 +434,7 @@ protected function prepareIndexes(array $indexes):array $props = $index; $indexType = null; } - if ($indexType === 'unique') { + if (strtolower($indexType) === 'unique') { $indexType = null; $unique = true; } diff --git a/src/lib/migrations/MigrationRecordBuilder.php b/src/lib/migrations/MigrationRecordBuilder.php index e12f5d72..886658bd 100644 --- a/src/lib/migrations/MigrationRecordBuilder.php +++ b/src/lib/migrations/MigrationRecordBuilder.php @@ -227,6 +227,7 @@ public function addFk(string $fkName, string $tableAlias, string $fkCol, string $onUpdate ); } + throw new \Exception('Cannot add foreign key'); } public function addUniqueIndex(string $tableAlias, string $indexName, array $columns):string @@ -242,11 +243,19 @@ public function addUniqueIndex(string $tableAlias, string $indexName, array $col public function addIndex(string $tableAlias, string $indexName, array $columns, ?string $using = null):string { $indexType = $using === null ? 'false' : "'".ColumnToCode::escapeQuotes($using)."'"; + + if (ApiGenerator::isPostgres() && $using && stripos($using, '(') !== false) { + $r = explode('(', $using, 2); + $indexType = "'".$r[0]."'"; # `gin` + $columnDbIndexExpression = substr($r[1], 0, -1); # to_tsvector('english', search::text) + $columns = [ColumnToCode::escapeQuotes($columnDbIndexExpression)]; + } + return sprintf( self::ADD_INDEX, $indexName, $tableAlias, - count($columns) === 1 ? "'". ColumnToCode::escapeQuotes($columns[0])."'" : '["'.implode('", "', $columns).'"]', + count($columns) === 1 ? "'". $columns[0]."'" : '["'.implode('", "', $columns).'"]', $indexType ); } diff --git a/tests/specs/postgres_custom/migrations_pgsql_db/m200000_000000_change_table_v3_pgcustom.php b/tests/specs/postgres_custom/migrations_pgsql_db/m200000_000000_change_table_v3_pgcustom.php index 6d1badd0..37cb7765 100644 --- a/tests/specs/postgres_custom/migrations_pgsql_db/m200000_000000_change_table_v3_pgcustom.php +++ b/tests/specs/postgres_custom/migrations_pgsql_db/m200000_000000_change_table_v3_pgcustom.php @@ -17,7 +17,7 @@ public function safeUp() $this->alterColumn('{{%v3_pgcustom}}', 'json4', "SET DEFAULT '{\"foo\":\"bar\",\"bar\":\"baz\"}'"); $this->alterColumn('{{%v3_pgcustom}}', 'status', "SET DEFAULT 'draft'"); $this->alterColumn('{{%v3_pgcustom}}', 'status_x', "SET DEFAULT 'draft'"); - $this->createIndex('v3_pgcustom_search_gin_index', '{{%v3_pgcustom}}', 'search', 'gin(to_tsvector(\'english\', search::text))'); + $this->createIndex('v3_pgcustom_search_gin_index', '{{%v3_pgcustom}}', 'to_tsvector(\'english\', search::text)', 'gin'); } public function safeDown() diff --git a/tests/unit/MultiDbSecondaryMigrationTest.php b/tests/unit/MultiDbSecondaryMigrationTest.php index 8ae94374..cc3d90cb 100644 --- a/tests/unit/MultiDbSecondaryMigrationTest.php +++ b/tests/unit/MultiDbSecondaryMigrationTest.php @@ -22,7 +22,7 @@ public function testPostgresCustom() $this->assertInstanceOf(PgSqlSchema::class, Yii::$app->db->schema); $testFile = Yii::getAlias('@specs/postgres_custom.php'); $this->runGenerator($testFile, $dbName); -// $this->runActualMigrations('pgsql', 1); + $this->runActualMigrations('pgsql', 1); $expectedFiles = $this->findExpectedFiles($testFile, $dbName); $actualFiles = $this->findActualFiles(); $this->assertEquals($expectedFiles, $actualFiles); From b66fe48599bb93dc2d8de816ab6feaeaecfefacd Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Tue, 2 Jul 2024 21:13:19 +0530 Subject: [PATCH 5/7] Add docs --- README.md | 8 ++++++++ src/lib/migrations/MigrationRecordBuilder.php | 1 + 2 files changed, 9 insertions(+) diff --git a/README.md b/README.md index 1cd2090b..7fec4f9e 100644 --- a/README.md +++ b/README.md @@ -212,6 +212,14 @@ Specify table indexes default: '{}' ``` +If raw DB expression is needed in index, then it must be for only one column. Example: + +```yaml + x-indexes: + - "gin(to_tsvector('english', search::text)):search" # valid + - "gin(to_tsvector('english', search::text)):search,column2" # invalid +``` + ### `x-db-default-expression` Ability to provide default value by database expression diff --git a/src/lib/migrations/MigrationRecordBuilder.php b/src/lib/migrations/MigrationRecordBuilder.php index 886658bd..0251be3a 100644 --- a/src/lib/migrations/MigrationRecordBuilder.php +++ b/src/lib/migrations/MigrationRecordBuilder.php @@ -245,6 +245,7 @@ public function addIndex(string $tableAlias, string $indexName, array $columns, $indexType = $using === null ? 'false' : "'".ColumnToCode::escapeQuotes($using)."'"; if (ApiGenerator::isPostgres() && $using && stripos($using, '(') !== false) { + // if `$using` is `gin(to_tsvector('english', search::text))` $r = explode('(', $using, 2); $indexType = "'".$r[0]."'"; # `gin` $columnDbIndexExpression = substr($r[1], 0, -1); # to_tsvector('english', search::text) From 1adc170a10c58ef58c7c0d673fd1fe8d645912da Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Tue, 2 Jul 2024 21:19:43 +0530 Subject: [PATCH 6/7] Fix failing test --- src/lib/AttributeResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/AttributeResolver.php b/src/lib/AttributeResolver.php index 3a6374a2..79ff91f6 100644 --- a/src/lib/AttributeResolver.php +++ b/src/lib/AttributeResolver.php @@ -434,7 +434,7 @@ protected function prepareIndexes(array $indexes):array $props = $index; $indexType = null; } - if (strtolower($indexType) === 'unique') { + if (strtolower((string) $indexType) === 'unique') { $indexType = null; $unique = true; } From e934a3dd9e21b3ffdd7292d5f78942d2cc05ec64 Mon Sep 17 00:00:00 2001 From: Sohel Ahmed Mesaniya Date: Wed, 3 Jul 2024 18:12:19 +0530 Subject: [PATCH 7/7] Run actual generated migrations in tests --- src/lib/migrations/MigrationRecordBuilder.php | 2 +- tests/unit/MultiDbFreshMigrationTest.php | 3 +++ tests/unit/MultiDbSecondaryMigrationTest.php | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lib/migrations/MigrationRecordBuilder.php b/src/lib/migrations/MigrationRecordBuilder.php index 0251be3a..1d4b0ed0 100644 --- a/src/lib/migrations/MigrationRecordBuilder.php +++ b/src/lib/migrations/MigrationRecordBuilder.php @@ -244,7 +244,7 @@ public function addIndex(string $tableAlias, string $indexName, array $columns, { $indexType = $using === null ? 'false' : "'".ColumnToCode::escapeQuotes($using)."'"; - if (ApiGenerator::isPostgres() && $using && stripos($using, '(') !== false) { + if ($using && (stripos($using, '(') !== false) && ApiGenerator::isPostgres()) { // if `$using` is `gin(to_tsvector('english', search::text))` $r = explode('(', $using, 2); $indexType = "'".$r[0]."'"; # `gin` diff --git a/tests/unit/MultiDbFreshMigrationTest.php b/tests/unit/MultiDbFreshMigrationTest.php index 366bfb0b..f2495903 100644 --- a/tests/unit/MultiDbFreshMigrationTest.php +++ b/tests/unit/MultiDbFreshMigrationTest.php @@ -26,6 +26,7 @@ public function testMaria() $this->assertInstanceOf(MySqlSchema::class, Yii::$app->db->schema); $testFile = Yii::getAlias('@specs/blog.php'); $this->runGenerator($testFile, $dbName); + $this->runActualMigrations($dbName, 5); $expectedFiles = $this->findExpectedFiles($testFile, $dbName); $actualFiles = $this->findActualFiles(); $this->assertEquals($expectedFiles, $actualFiles); @@ -39,6 +40,7 @@ public function testPostgres() $this->assertInstanceOf(PgSqlSchema::class, Yii::$app->db->schema); $testFile = Yii::getAlias('@specs/blog.php'); $this->runGenerator($testFile, $dbName); + $this->runActualMigrations($dbName, 5); $expectedFiles = $this->findExpectedFiles($testFile, $dbName); $actualFiles = $this->findActualFiles(); $this->assertEquals($expectedFiles, $actualFiles); @@ -52,6 +54,7 @@ public function testMysql() $this->assertInstanceOf(MySqlSchema::class, Yii::$app->db->schema); $testFile = Yii::getAlias('@specs/blog.php'); $this->runGenerator($testFile, $dbName); + $this->runActualMigrations($dbName, 5); $expectedFiles = $this->findExpectedFiles($testFile, $dbName); $actualFiles = $this->findActualFiles(); $this->assertEquals($expectedFiles, $actualFiles); diff --git a/tests/unit/MultiDbSecondaryMigrationTest.php b/tests/unit/MultiDbSecondaryMigrationTest.php index cc3d90cb..36f9179c 100644 --- a/tests/unit/MultiDbSecondaryMigrationTest.php +++ b/tests/unit/MultiDbSecondaryMigrationTest.php @@ -22,7 +22,7 @@ public function testPostgresCustom() $this->assertInstanceOf(PgSqlSchema::class, Yii::$app->db->schema); $testFile = Yii::getAlias('@specs/postgres_custom.php'); $this->runGenerator($testFile, $dbName); - $this->runActualMigrations('pgsql', 1); + $this->runActualMigrations($dbName, 1); $expectedFiles = $this->findExpectedFiles($testFile, $dbName); $actualFiles = $this->findActualFiles(); $this->assertEquals($expectedFiles, $actualFiles); @@ -36,6 +36,7 @@ public function testMaria() $this->assertInstanceOf(MySqlSchema::class, Yii::$app->db->schema); $testFile = Yii::getAlias('@specs/blog_v2.php'); $this->runGenerator($testFile, $dbName); +// $this->runActualMigrations($dbName, 6); since PK is changed, no need to run actual migrations here $expectedFiles = $this->findExpectedFiles($testFile, $dbName); $actualFiles = $this->findActualFiles(); $this->assertEquals($expectedFiles, $actualFiles);