Skip to content

Commit e993ed3

Browse files
authored
Merge pull request #5 from php-openapi/3-bug-addremove-property-and-at-the-same-time-change-it-at-x-indexes
Resolve: Bug: add/remove property and at the same time change it at x-indexes: #3
2 parents 25da464 + 26c8a26 commit e993ed3

18 files changed

+218
-40
lines changed

src/lib/migrations/BaseMigrationBuilder.php

+7-3
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,13 @@ function (string $unknownColumn) {
209209
->addDownCode($builder->addPrimaryKey($tableName, $this->model->junctionCols));
210210
}
211211
}
212+
213+
if (!$relation) {
214+
$this->buildIndexChanges();
215+
}
216+
212217
$this->buildColumnsDrop($columnsForDrop);
218+
213219
foreach ($columnsForChange as $commonColumn) {
214220
$current = $this->tableSchema->columns[$commonColumn];
215221
/** @var \cebe\yii2openapi\db\ColumnSchema|\yii\db\ColumnSchema $desired */
@@ -224,9 +230,7 @@ function (string $unknownColumn) {
224230
}
225231
$this->buildColumnChanges($current, $desired, $changedAttributes);
226232
}
227-
if (!$relation) {
228-
$this->buildIndexChanges();
229-
}
233+
230234
if ($relation) {
231235
$this->buildRelationsForJunction($relation);
232236
} else {

tests/DbTestCase.php

+16-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use cebe\yii2openapi\generator\ApiGenerator;
66
use Yii;
7+
use yii\db\IndexConstraint;
78
use yii\di\Container;
89
use yii\db\mysql\Schema as MySqlSchema;
910
use yii\db\pgsql\Schema as PgSqlSchema;
@@ -167,8 +168,8 @@ protected function runUpMigrations(string $db = 'mysql', int $number = 2): void
167168
exec('cd tests; php -dxdebug.mode=develop ./yii migrate-'.$db.' --interactive=0', $upOutput, $upExitCode);
168169
$last = count($upOutput) - 1;
169170
$lastThird = count($upOutput) - 3;
170-
$this->assertSame($upExitCode, 0);
171171
$this->assertSame($upOutput[$last], 'Migrated up successfully.');
172+
$this->assertSame($upExitCode, 0);
172173
$this->assertSame($upOutput[$lastThird], $number.' '.(($number === 1) ? 'migration was' : 'migrations were').' applied.');
173174
// 1 migration was applied.
174175
// 2 migrations were applied.
@@ -192,4 +193,18 @@ protected function dropFkIfExists(string $table, string $fk): void
192193
Yii::$app->db->createCommand()->dropForeignKey($fk, $table)->execute();
193194
}
194195
}
196+
197+
protected function indexExists(string $indexName): bool
198+
{
199+
$indices = Yii::$app->db->schema->schemaIndexes;
200+
foreach ($indices as $subIndices) {
201+
foreach ($subIndices as $index) {
202+
/** @var IndexConstraint $index */
203+
if ($index->name === $indexName) {
204+
return true;
205+
}
206+
}
207+
}
208+
return false;
209+
}
195210
}

tests/specs/blog_v2/migrations_maria_db/m200000_000000_change_table_v2_posts.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,20 @@ public function up()
99
{
1010
$this->addColumn('{{%v2_posts}}', 'id', $this->bigPrimaryKey());
1111
$this->addColumn('{{%v2_posts}}', 'lang', 'enum("ru", "eng") NULL DEFAULT \'ru\' AFTER slug');
12+
$this->dropIndex('v2_posts_slug_key', '{{%v2_posts}}');
1213
$this->dropColumn('{{%v2_posts}}', 'uid');
1314
$this->alterColumn('{{%v2_posts}}', 'category_id', $this->bigInteger()->notNull());
1415
$this->alterColumn('{{%v2_posts}}', 'active', $this->tinyInteger(1)->notNull());
1516
$this->alterColumn('{{%v2_posts}}', 'created_by_id', $this->bigInteger()->null()->defaultValue(null));
16-
$this->dropIndex('v2_posts_slug_key', '{{%v2_posts}}');
1717
}
1818

1919
public function down()
2020
{
21-
$this->createIndex('v2_posts_slug_key', '{{%v2_posts}}', 'slug', true);
2221
$this->alterColumn('{{%v2_posts}}', 'created_by_id', $this->integer(11)->null()->defaultValue(null));
2322
$this->alterColumn('{{%v2_posts}}', 'active', $this->tinyInteger(1)->notNull()->defaultValue(0));
2423
$this->alterColumn('{{%v2_posts}}', 'category_id', $this->integer(11)->notNull());
2524
$this->addColumn('{{%v2_posts}}', 'uid', $this->bigInteger(20)->notNull()->first());
25+
$this->createIndex('v2_posts_slug_key', '{{%v2_posts}}', 'slug', true);
2626
$this->dropColumn('{{%v2_posts}}', 'lang');
2727
$this->dropColumn('{{%v2_posts}}', 'id');
2828
}

tests/specs/blog_v2/migrations_maria_db/m200000_000003_change_table_v2_categories.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@ class m200000_000003_change_table_v2_categories extends \yii\db\Migration
88
public function up()
99
{
1010
$this->addColumn('{{%v2_categories}}', 'cover', $this->text()->notNull()->after('title'));
11-
$this->alterColumn('{{%v2_categories}}', 'title', $this->string(100)->notNull());
12-
$this->alterColumn('{{%v2_categories}}', 'active', $this->tinyInteger(1)->notNull());
1311
$this->dropIndex('v2_categories_title_key', '{{%v2_categories}}');
1412
$this->createIndex('v2_categories_title_index', '{{%v2_categories}}', 'title', false);
13+
$this->alterColumn('{{%v2_categories}}', 'title', $this->string(100)->notNull());
14+
$this->alterColumn('{{%v2_categories}}', 'active', $this->tinyInteger(1)->notNull());
1515
}
1616

1717
public function down()
1818
{
19-
$this->dropIndex('v2_categories_title_index', '{{%v2_categories}}');
20-
$this->createIndex('v2_categories_title_key', '{{%v2_categories}}', 'title', true);
2119
$this->alterColumn('{{%v2_categories}}', 'active', $this->tinyInteger(1)->notNull()->defaultValue(0));
2220
$this->alterColumn('{{%v2_categories}}', 'title', $this->string(255)->notNull());
21+
$this->dropIndex('v2_categories_title_index', '{{%v2_categories}}');
22+
$this->createIndex('v2_categories_title_key', '{{%v2_categories}}', 'title', true);
2323
$this->dropColumn('{{%v2_categories}}', 'cover');
2424
}
2525
}

tests/specs/blog_v2/migrations_maria_db/m200000_000004_change_table_v2_users.php

+6-6
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,24 @@ class m200000_000004_change_table_v2_users extends \yii\db\Migration
88
public function up()
99
{
1010
$this->addColumn('{{%v2_users}}', 'login', $this->text()->notNull()->after('id'));
11+
$this->dropIndex('v2_users_username_key', '{{%v2_users}}');
12+
$this->createIndex('v2_users_login_key', '{{%v2_users}}', 'login', true);
13+
$this->createIndex('v2_users_role_flags_hash_index', '{{%v2_users}}', ["role", "flags"], 'hash');
1114
$this->dropColumn('{{%v2_users}}', 'username');
1215
$this->alterColumn('{{%v2_users}}', 'email', $this->string(255)->notNull());
1316
$this->alterColumn('{{%v2_users}}', 'role', 'enum("admin", "editor", "reader") NULL DEFAULT NULL');
1417
$this->alterColumn('{{%v2_users}}', 'created_at', $this->timestamp()->null()->defaultValue(null));
15-
$this->dropIndex('v2_users_username_key', '{{%v2_users}}');
16-
$this->createIndex('v2_users_login_key', '{{%v2_users}}', 'login', true);
17-
$this->createIndex('v2_users_role_flags_hash_index', '{{%v2_users}}', ["role", "flags"], 'hash');
1818
}
1919

2020
public function down()
2121
{
22-
$this->dropIndex('v2_users_role_flags_hash_index', '{{%v2_users}}');
23-
$this->dropIndex('v2_users_login_key', '{{%v2_users}}');
24-
$this->createIndex('v2_users_username_key', '{{%v2_users}}', 'username', true);
2522
$this->alterColumn('{{%v2_users}}', 'created_at', $this->timestamp()->null()->defaultExpression("current_timestamp()"));
2623
$this->alterColumn('{{%v2_users}}', 'role', $this->string(20)->null()->defaultValue('reader'));
2724
$this->alterColumn('{{%v2_users}}', 'email', $this->string(200)->notNull());
2825
$this->addColumn('{{%v2_users}}', 'username', $this->string(200)->notNull()->after('id'));
26+
$this->dropIndex('v2_users_role_flags_hash_index', '{{%v2_users}}');
27+
$this->dropIndex('v2_users_login_key', '{{%v2_users}}');
28+
$this->createIndex('v2_users_username_key', '{{%v2_users}}', 'username', true);
2929
$this->dropColumn('{{%v2_users}}', 'login');
3030
}
3131
}

tests/specs/blog_v2/migrations_mysql_db/m200000_000000_change_table_v2_posts.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,20 @@ public function up()
99
{
1010
$this->addColumn('{{%v2_posts}}', 'id', $this->bigPrimaryKey());
1111
$this->addColumn('{{%v2_posts}}', 'lang', 'enum("ru", "eng") NULL DEFAULT \'ru\' AFTER slug');
12+
$this->dropIndex('v2_posts_slug_key', '{{%v2_posts}}');
1213
$this->dropColumn('{{%v2_posts}}', 'uid');
1314
$this->alterColumn('{{%v2_posts}}', 'category_id', $this->bigInteger()->notNull());
1415
$this->alterColumn('{{%v2_posts}}', 'active', $this->tinyInteger(1)->notNull());
1516
$this->alterColumn('{{%v2_posts}}', 'created_by_id', $this->bigInteger()->null()->defaultValue(null));
16-
$this->dropIndex('v2_posts_slug_key', '{{%v2_posts}}');
1717
}
1818

1919
public function down()
2020
{
21-
$this->createIndex('v2_posts_slug_key', '{{%v2_posts}}', 'slug', true);
2221
$this->alterColumn('{{%v2_posts}}', 'created_by_id', $this->integer()->null()->defaultValue(null));
2322
$this->alterColumn('{{%v2_posts}}', 'active', $this->tinyInteger(1)->notNull()->defaultValue(0));
2423
$this->alterColumn('{{%v2_posts}}', 'category_id', $this->integer()->notNull());
2524
$this->addColumn('{{%v2_posts}}', 'uid', $this->bigInteger()->notNull()->first());
25+
$this->createIndex('v2_posts_slug_key', '{{%v2_posts}}', 'slug', true);
2626
$this->dropColumn('{{%v2_posts}}', 'lang');
2727
$this->dropColumn('{{%v2_posts}}', 'id');
2828
}

tests/specs/blog_v2/migrations_mysql_db/m200000_000003_change_table_v2_categories.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@ class m200000_000003_change_table_v2_categories extends \yii\db\Migration
88
public function up()
99
{
1010
$this->addColumn('{{%v2_categories}}', 'cover', $this->text()->notNull()->after('title'));
11-
$this->alterColumn('{{%v2_categories}}', 'title', $this->string(100)->notNull());
12-
$this->alterColumn('{{%v2_categories}}', 'active', $this->tinyInteger(1)->notNull());
1311
$this->dropIndex('v2_categories_title_key', '{{%v2_categories}}');
1412
$this->createIndex('v2_categories_title_index', '{{%v2_categories}}', 'title', false);
13+
$this->alterColumn('{{%v2_categories}}', 'title', $this->string(100)->notNull());
14+
$this->alterColumn('{{%v2_categories}}', 'active', $this->tinyInteger(1)->notNull());
1515
}
1616

1717
public function down()
1818
{
19-
$this->dropIndex('v2_categories_title_index', '{{%v2_categories}}');
20-
$this->createIndex('v2_categories_title_key', '{{%v2_categories}}', 'title', true);
2119
$this->alterColumn('{{%v2_categories}}', 'active', $this->tinyInteger(1)->notNull()->defaultValue(0));
2220
$this->alterColumn('{{%v2_categories}}', 'title', $this->string(255)->notNull());
21+
$this->dropIndex('v2_categories_title_index', '{{%v2_categories}}');
22+
$this->createIndex('v2_categories_title_key', '{{%v2_categories}}', 'title', true);
2323
$this->dropColumn('{{%v2_categories}}', 'cover');
2424
}
2525
}

tests/specs/blog_v2/migrations_mysql_db/m200000_000004_change_table_v2_users.php

+6-6
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,24 @@ class m200000_000004_change_table_v2_users extends \yii\db\Migration
88
public function up()
99
{
1010
$this->addColumn('{{%v2_users}}', 'login', $this->text()->notNull()->after('id'));
11+
$this->dropIndex('v2_users_username_key', '{{%v2_users}}');
12+
$this->createIndex('v2_users_login_key', '{{%v2_users}}', 'login', true);
13+
$this->createIndex('v2_users_role_flags_hash_index', '{{%v2_users}}', ["role", "flags"], 'hash');
1114
$this->dropColumn('{{%v2_users}}', 'username');
1215
$this->alterColumn('{{%v2_users}}', 'email', $this->string(255)->notNull());
1316
$this->alterColumn('{{%v2_users}}', 'role', 'enum("admin", "editor", "reader") NULL DEFAULT NULL');
1417
$this->alterColumn('{{%v2_users}}', 'created_at', $this->timestamp()->null()->defaultValue(null));
15-
$this->dropIndex('v2_users_username_key', '{{%v2_users}}');
16-
$this->createIndex('v2_users_login_key', '{{%v2_users}}', 'login', true);
17-
$this->createIndex('v2_users_role_flags_hash_index', '{{%v2_users}}', ["role", "flags"], 'hash');
1818
}
1919

2020
public function down()
2121
{
22-
$this->dropIndex('v2_users_role_flags_hash_index', '{{%v2_users}}');
23-
$this->dropIndex('v2_users_login_key', '{{%v2_users}}');
24-
$this->createIndex('v2_users_username_key', '{{%v2_users}}', 'username', true);
2522
$this->alterColumn('{{%v2_users}}', 'created_at', $this->timestamp()->null()->defaultExpression("CURRENT_TIMESTAMP"));
2623
$this->alterColumn('{{%v2_users}}', 'role', $this->string(20)->null()->defaultValue('reader'));
2724
$this->alterColumn('{{%v2_users}}', 'email', $this->string(200)->notNull());
2825
$this->addColumn('{{%v2_users}}', 'username', $this->string(200)->notNull()->after('id'));
26+
$this->dropIndex('v2_users_role_flags_hash_index', '{{%v2_users}}');
27+
$this->dropIndex('v2_users_login_key', '{{%v2_users}}');
28+
$this->createIndex('v2_users_username_key', '{{%v2_users}}', 'username', true);
2929
$this->dropColumn('{{%v2_users}}', 'login');
3030
}
3131
}

tests/specs/blog_v2/migrations_pgsql_db/m200000_000000_change_table_v2_posts.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@ public function safeUp()
1010
$this->addColumn('{{%v2_posts}}', 'id', $this->bigPrimaryKey());
1111
$this->execute('CREATE TYPE "enum_itt_v2_posts_lang" AS ENUM(\'ru\', \'eng\')');
1212
$this->addColumn('{{%v2_posts}}', 'lang', '"enum_itt_v2_posts_lang" NULL DEFAULT \'ru\'');
13+
$this->dropIndex('v2_posts_slug_key', '{{%v2_posts}}');
1314
$this->dropColumn('{{%v2_posts}}', 'uid');
1415
$this->alterColumn('{{%v2_posts}}', 'category_id', 'int8 NOT NULL USING "category_id"::int8');
1516
$this->alterColumn('{{%v2_posts}}', 'active', "DROP DEFAULT");
1617
$this->alterColumn('{{%v2_posts}}', 'created_by_id', 'int8 NULL USING "created_by_id"::int8');
17-
$this->dropIndex('v2_posts_slug_key', '{{%v2_posts}}');
1818
}
1919

2020
public function safeDown()
2121
{
22-
$this->createIndex('v2_posts_slug_key', '{{%v2_posts}}', 'slug', true);
2322
$this->alterColumn('{{%v2_posts}}', 'created_by_id', 'int4 NULL USING "created_by_id"::int4');
2423
$this->alterColumn('{{%v2_posts}}', 'category_id', 'int4 NOT NULL USING "category_id"::int4');
2524
$this->addColumn('{{%v2_posts}}', 'uid', $this->bigInteger()->notNull());
25+
$this->createIndex('v2_posts_slug_key', '{{%v2_posts}}', 'slug', true);
2626
$this->dropColumn('{{%v2_posts}}', 'lang');
2727
$this->dropColumn('{{%v2_posts}}', 'id');
2828
$this->execute('DROP TYPE "enum_itt_v2_posts_lang"');

tests/specs/blog_v2/migrations_pgsql_db/m200000_000003_change_table_v2_categories.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@ class m200000_000003_change_table_v2_categories extends \yii\db\Migration
88
public function safeUp()
99
{
1010
$this->addColumn('{{%v2_categories}}', 'cover', $this->text()->notNull());
11-
$this->alterColumn('{{%v2_categories}}', 'title', $this->string(100)->notNull());
12-
$this->alterColumn('{{%v2_categories}}', 'active', "DROP DEFAULT");
1311
$this->dropIndex('v2_categories_title_key', '{{%v2_categories}}');
1412
$this->createIndex('v2_categories_title_index', '{{%v2_categories}}', 'title', false);
13+
$this->alterColumn('{{%v2_categories}}', 'title', $this->string(100)->notNull());
14+
$this->alterColumn('{{%v2_categories}}', 'active', "DROP DEFAULT");
1515
}
1616

1717
public function safeDown()
1818
{
19+
$this->alterColumn('{{%v2_categories}}', 'title', $this->string(255)->notNull());
1920
$this->dropIndex('v2_categories_title_index', '{{%v2_categories}}');
2021
$this->createIndex('v2_categories_title_key', '{{%v2_categories}}', 'title', true);
21-
$this->alterColumn('{{%v2_categories}}', 'title', $this->string(255)->notNull());
2222
$this->dropColumn('{{%v2_categories}}', 'cover');
2323
$this->alterColumn('{{%v2_categories}}', 'active', "SET DEFAULT 'f'");
2424
}

tests/specs/blog_v2/migrations_pgsql_db/m200000_000004_change_table_v2_users.php

+6-6
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,24 @@ public function safeUp()
99
{
1010
$this->execute('CREATE TYPE "enum_itt_v2_users_role" AS ENUM(\'admin\', \'editor\', \'reader\')');
1111
$this->addColumn('{{%v2_users}}', 'login', $this->text()->notNull());
12+
$this->dropIndex('v2_users_username_key', '{{%v2_users}}');
13+
$this->createIndex('v2_users_login_key', '{{%v2_users}}', 'login', true);
14+
$this->createIndex('v2_users_role_flags_hash_index', '{{%v2_users}}', ["role", "flags"], 'hash');
1215
$this->dropColumn('{{%v2_users}}', 'username');
1316
$this->db->createCommand('ALTER TABLE {{%v2_users}} ALTER COLUMN "email" SET DATA TYPE varchar(255)')->execute();
1417
$this->alterColumn('{{%v2_users}}', 'role', '"enum_itt_v2_users_role" USING "role"::"enum_itt_v2_users_role"');
1518
$this->alterColumn('{{%v2_users}}', 'role', "DROP DEFAULT");
1619
$this->alterColumn('{{%v2_users}}', 'created_at', "DROP DEFAULT");
17-
$this->dropIndex('v2_users_username_key', '{{%v2_users}}');
18-
$this->createIndex('v2_users_login_key', '{{%v2_users}}', 'login', true);
19-
$this->createIndex('v2_users_role_flags_hash_index', '{{%v2_users}}', ["role", "flags"], 'hash');
2020
}
2121

2222
public function safeDown()
2323
{
24-
$this->dropIndex('v2_users_role_flags_hash_index', '{{%v2_users}}');
25-
$this->dropIndex('v2_users_login_key', '{{%v2_users}}');
26-
$this->createIndex('v2_users_username_key', '{{%v2_users}}', 'username', true);
2724
$this->alterColumn('{{%v2_users}}', 'role', 'varchar(20) NULL USING "role"::varchar');
2825
$this->alterColumn('{{%v2_users}}', 'email', $this->string(200)->notNull());
2926
$this->addColumn('{{%v2_users}}', 'username', $this->string(200)->notNull());
27+
$this->dropIndex('v2_users_role_flags_hash_index', '{{%v2_users}}');
28+
$this->dropIndex('v2_users_login_key', '{{%v2_users}}');
29+
$this->createIndex('v2_users_username_key', '{{%v2_users}}', 'username', true);
3030
$this->dropColumn('{{%v2_users}}', 'login');
3131
$this->alterColumn('{{%v2_users}}', 'role', "SET DEFAULT 'reader'");
3232
$this->execute('DROP TYPE "enum_itt_v2_users_role"');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
return [
4+
'openApiPath' => '@specs/issue_fix/3_bug_add_remove_property_and_at_the_same_time_change_it_at_x_indexes/index.yaml',
5+
'generateUrls' => false,
6+
'generateModels' => true,
7+
'excludeModels' => [
8+
'Error',
9+
],
10+
'generateControllers' => false,
11+
'generateMigrations' => true,
12+
'generateModelFaker' => false,
13+
];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
openapi: "3.0.0"
2+
info:
3+
version: 1.0.0
4+
title: 3_bug_add_remove_property_and_at_the_same_time_change_it_at_x_indexes
5+
paths:
6+
/:
7+
get:
8+
summary: List
9+
operationId: list
10+
responses:
11+
'200':
12+
description: The information
13+
14+
components:
15+
schemas:
16+
Address:
17+
type: object
18+
description: desc
19+
x-indexes:
20+
- 'unique:shortName,postCode'
21+
required:
22+
- id
23+
properties:
24+
id:
25+
type: integer
26+
readOnly: true
27+
28+
name:
29+
type: string
30+
maxLength: 64
31+
32+
shortName:
33+
type: string
34+
maxLength: 64
35+
36+
postCode:
37+
type: string
38+
maxLength: 64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
/**
4+
* Table for Address
5+
*/
6+
class m200000_000000_change_table_addresses extends \yii\db\Migration
7+
{
8+
public function up()
9+
{
10+
$this->addColumn('{{%addresses}}', 'postCode', $this->string(64)->null()->defaultValue(null));
11+
$this->dropIndex('addresses_shortName_postalCode_key', '{{%addresses}}');
12+
$this->createIndex('addresses_shortName_postCode_key', '{{%addresses}}', ["shortName", "postCode"], true);
13+
$this->dropColumn('{{%addresses}}', 'postalCode');
14+
}
15+
16+
public function down()
17+
{
18+
$this->addColumn('{{%addresses}}', 'postalCode', $this->string(64)->null()->defaultValue(null));
19+
$this->dropIndex('addresses_shortName_postCode_key', '{{%addresses}}');
20+
$this->createIndex('addresses_shortName_postalCode_key', '{{%addresses}}', ["shortName", "postalCode"], true);
21+
$this->dropColumn('{{%addresses}}', 'postCode');
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace app\models;
4+
5+
class Address extends \app\models\base\Address
6+
{
7+
8+
9+
}
10+

0 commit comments

Comments
 (0)