diff --git a/Makefile b/Makefile index 44086f91..9a7e0370 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,9 @@ up: docker-compose up -d echo "Waiting for mariadb to start up..." docker-compose exec -T mysql timeout 60s sh -c "while ! (mysql -udbuser -pdbpass -h maria --execute 'SELECT 1;' > /dev/null 2>&1); do echo -n '.'; sleep 0.1 ; done; echo 'ok'" || (docker-compose ps; docker-compose logs; exit 1) + echo "Create another test DB for PgSQL ..." # created because of enum in PgSQL are different than MySQL + docker-compose exec -T postgres bash -c "psql --username dbuser --dbname testdb -c 'create database pg_test_db_2;'; psql --username dbuser --dbname testdb -c 'grant all privileges on database pg_test_db_2 to dbuser;'" || (docker-compose ps; docker-compose logs; exit 1) + cli: docker-compose exec php bash diff --git a/README.md b/README.md index 94b53f46..9d20b16a 100644 --- a/README.md +++ b/README.md @@ -316,8 +316,8 @@ e.g. attribute = 'my_property'. nullable: false ``` -### Handling of `enum` (#enum, #MariaDb) -It work on MariaDb. +### Handling of `enum` (#enum) +It works on all 3 DB: MySQL, MariaDb and PgSQL. ```yaml test_table: @@ -329,6 +329,8 @@ It work on MariaDb. - three ``` +Note: Change in enum values are not very simple. For Mysql and Mariadb, migrations will be generated but in many cases custom modification in it are required. For Pgsql migrations for change in enum values will not be generated. It should be handled manually. + ### Handling of `numeric` (#numeric, #MariaDb) precision-default = 10 scale-default = 2 @@ -372,9 +374,10 @@ Generated files: # Development -There commands are available to develop and check the tests. It can be used inside the Docker container. To enter into bash of container run `make cli` . +There commands are available to develop and check the tests. It is available inside the Docker container. To enter into bash shell of container, run `make cli` . ```bash +cd tests ./yii migrate-mysql/up ./yii migrate-mysql/down 4 diff --git a/src/lib/ColumnToCode.php b/src/lib/ColumnToCode.php index 7a0188e2..2eb47ba1 100644 --- a/src/lib/ColumnToCode.php +++ b/src/lib/ColumnToCode.php @@ -148,8 +148,8 @@ public function getCode(bool $quoted = false):string } $code = $this->rawParts['type'] . ' ' . $this->rawParts['nullable'] . $default; - if (ApiGenerator::isMysql() && $this->isEnum()) { - return $quoted ? '"' . str_replace("\'", "'", $code) . '"' : $code; + if ((ApiGenerator::isMysql() || ApiGenerator::isMariaDb()) && $this->isEnum()) { + return $quoted ? "'" . $code . "'" : $code; } if (ApiGenerator::isPostgres() && $this->alterByXDbType) { return $quoted ? "'" . $this->rawParts['type'] . "'" : $this->rawParts['type']; @@ -160,7 +160,7 @@ public function getCode(bool $quoted = false):string public function getAlterExpression(bool $addUsingExpression = false):string { if ($this->isEnum() && ApiGenerator::isPostgres()) { - return "'" . sprintf('enum_%1$s USING %1$s::enum_%1$s', $this->column->name) . "'"; + return "'" . sprintf('enum_%1$s USING "%1$s"::enum_%1$s', $this->column->name) . "'"; } if ($this->column->dbType === 'tsvector') { return "'" . $this->rawParts['type'] . "'"; @@ -270,7 +270,9 @@ public static function enumToString(array $enum):string public static function mysqlEnumToString(array $enum):string { - return implode(', ', array_map('self::wrapQuotes', $enum)); + return implode(', ', array_map(function ($aEnumValue) { + return self::wrapQuotes($aEnumValue, '"'); + }, $enum)); } private function defaultValueJson(array $value):string @@ -329,7 +331,7 @@ private function resolve():void $this->rawParts['type'] = $this->column->dbType . (strpos($this->column->dbType, '(') !== false ? '' : $rawSize); } - + $this->isBuiltinType = $this->raw ? false : $this->getIsBuiltinType($type, $dbType); $this->resolveDefaultValue(); @@ -346,7 +348,7 @@ private function getIsBuiltinType($type, $dbType) return false; } - if ($this->isEnum() && ApiGenerator::isMariaDb()) { + if ($this->isEnum()) { return false; } if ($this->fromDb === true) { @@ -421,16 +423,18 @@ private function resolveDefaultValue():void break; default: $isExpression = StringHelper::startsWith($value, 'CURRENT') + || StringHelper::startsWith($value, 'current') || StringHelper::startsWith($value, 'LOCAL') || substr($value, -1, 1) === ')'; if ($isExpression) { $this->fluentParts['default'] = 'defaultExpression("' . self::escapeQuotes((string)$value) . '")'; + $this->rawParts['default'] = $value; } else { $this->fluentParts['default'] = $expectInteger ? 'defaultValue(' . $value . ')' : 'defaultValue("' . self::escapeQuotes((string)$value) . '")'; + $this->rawParts['default'] = $expectInteger ? $value : self::wrapQuotes($value); } - $this->rawParts['default'] = $expectInteger ? $value : self::wrapQuotes($value); - if (ApiGenerator::isMysql() && $this->isEnum()) { + if ((ApiGenerator::isMysql() || ApiGenerator::isMariaDb()) && $this->isEnum()) { $this->rawParts['default'] = self::escapeQuotes($this->rawParts['default']); } } diff --git a/src/lib/migrations/BaseMigrationBuilder.php b/src/lib/migrations/BaseMigrationBuilder.php index 82becfb9..072628ad 100644 --- a/src/lib/migrations/BaseMigrationBuilder.php +++ b/src/lib/migrations/BaseMigrationBuilder.php @@ -7,6 +7,7 @@ namespace cebe\yii2openapi\lib\migrations; +use cebe\yii2openapi\generator\ApiGenerator; use cebe\yii2openapi\lib\ColumnToCode; use cebe\yii2openapi\lib\items\DbModel; use cebe\yii2openapi\lib\items\ManyToManyRelation; @@ -203,14 +204,6 @@ function (string $unknownColumn) { // do not adjust existing primary keys continue; } - if (!empty($current->enumValues)) { - $current->type = 'enum'; - $current->dbType = 'enum'; - } - if (!empty($desired->enumValues)) { - $desired->type = 'enum'; - $desired->dbType = 'enum'; - } $changedAttributes = $this->compareColumns($current, $desired); if (empty($changedAttributes)) { continue; @@ -423,8 +416,12 @@ protected function isNeedUsingExpression(string $fromType, string $toType):bool public function tmpSaveNewCol(\cebe\yii2openapi\db\ColumnSchema $columnSchema): \yii\db\ColumnSchema { $tableName = 'tmp_table_'; + $db = 'db'; + if (ApiGenerator::isPostgres() && static::isEnum($columnSchema)) { + $db = 'pg_test_db_2'; + } - Yii::$app->db->createCommand('DROP TABLE IF EXISTS '.$tableName)->execute(); + Yii::$app->{$db}->createCommand('DROP TABLE IF EXISTS '.$tableName)->execute(); if (is_string($columnSchema->xDbType) && !empty($columnSchema->xDbType)) { $column = [$columnSchema->name.' '.$this->newColStr($columnSchema)]; @@ -432,11 +429,26 @@ public function tmpSaveNewCol(\cebe\yii2openapi\db\ColumnSchema $columnSchema): $column = [$columnSchema->name => $this->newColStr($columnSchema)]; } - Yii::$app->db->createCommand()->createTable($tableName, $column)->execute(); + // create enum if relevant + if (ApiGenerator::isPostgres() && static::isEnum($columnSchema)) { + $allEnumValues = $columnSchema->enumValues; + $allEnumValues = array_map(function ($aValue) { + return "'$aValue'"; + }, $allEnumValues); + Yii::$app->{$db}->createCommand( + 'CREATE TYPE enum_'.$columnSchema->name.' AS ENUM('.implode(', ', $allEnumValues).')' + )->execute(); + } - $table = Yii::$app->db->getTableSchema($tableName); + Yii::$app->{$db}->createCommand()->createTable($tableName, $column)->execute(); - Yii::$app->db->createCommand()->dropTable($tableName)->execute(); + $table = Yii::$app->{$db}->getTableSchema($tableName); + + Yii::$app->{$db}->createCommand()->dropTable($tableName)->execute(); + + if (ApiGenerator::isPostgres() && static::isEnum($columnSchema)) {// drop enum + Yii::$app->{$db}->createCommand('DROP TYPE enum_'.$columnSchema->name)->execute(); + } return $table->columns[$columnSchema->name]; } @@ -446,4 +458,23 @@ public function newColStr(\cebe\yii2openapi\db\ColumnSchema $columnSchema): stri $ctc = new ColumnToCode(\Yii::$app->db->schema, $columnSchema, false, false, true); return ColumnToCode::undoEscapeQuotes($ctc->getCode()); } + + public static function isEnum(\yii\db\ColumnSchema $columnSchema): bool + { + if (!empty($columnSchema->enumValues) && is_array($columnSchema->enumValues)) { + return true; + } + return false; + } + + public static function isEnumValuesChanged( + \yii\db\ColumnSchema $current, + \yii\db\ColumnSchema $desired + ): bool { + if (static::isEnum($current) && static::isEnum($desired) && + $current->enumValues !== $desired->enumValues) { + return true; + } + return false; + } } diff --git a/src/lib/migrations/MysqlMigrationBuilder.php b/src/lib/migrations/MysqlMigrationBuilder.php index 9cb17c79..c9f13c32 100644 --- a/src/lib/migrations/MysqlMigrationBuilder.php +++ b/src/lib/migrations/MysqlMigrationBuilder.php @@ -29,8 +29,8 @@ protected function buildColumnChanges(ColumnSchema $current, ColumnSchema $desir foreach ($changed as $attr) { $newColumn->$attr = $desired->$attr; } - if (!empty($newColumn->enumValues)) { - $newColumn->dbType = 'enum'; + if (static::isEnum($newColumn)) { + $newColumn->dbType = 'enum'; // TODO this is concretely not correct } $this->migration->addUpCode($this->recordBuilder->alterColumn($this->model->getTableAlias(), $newColumn)) ->addDownCode($this->recordBuilder->alterColumn($this->model->getTableAlias(), $current)); diff --git a/src/lib/migrations/PostgresMigrationBuilder.php b/src/lib/migrations/PostgresMigrationBuilder.php index edd9ec4d..c1e109f6 100644 --- a/src/lib/migrations/PostgresMigrationBuilder.php +++ b/src/lib/migrations/PostgresMigrationBuilder.php @@ -22,9 +22,9 @@ protected function buildColumnsCreation(array $columns):void { foreach ($columns as $column) { $tableName = $this->model->getTableAlias(); - if ($column->dbType === 'enum') { + if (static::isEnum($column)) { $this->migration->addUpCode($this->recordBuilder->createEnum($column->name, $column->enumValues)) - ->addDownCode($this->recordBuilder->dropEnum($column->name)); + ->addDownCode($this->recordBuilder->dropEnum($column->name), true); } $this->migration->addUpCode($this->recordBuilder->addColumn($tableName, $column)) ->addDownCode($this->recordBuilder->dropColumn($tableName, $column->name)); @@ -41,9 +41,9 @@ protected function buildColumnsDrop(array $columns):void $tableName = $this->model->getTableAlias(); $this->migration->addDownCode($this->recordBuilder->addDbColumn($tableName, $column)) ->addUpCode($this->recordBuilder->dropColumn($tableName, $column->name)); - if ($column->dbType === 'enum') { + if (static::isEnum($column)) { $this->migration->addDownCode($this->recordBuilder->createEnum($column->name, $column->enumValues)) - ->addUpCode($this->recordBuilder->dropEnum($column->name), true); + ->addUpCode($this->recordBuilder->dropEnum($column->name)); } } } @@ -54,22 +54,20 @@ protected function buildColumnsDrop(array $columns):void protected function buildColumnChanges(ColumnSchema $current, ColumnSchema $desired, array $changed):void { $tableName = $this->model->getTableAlias(); - $isChangeToEnum = $current->type !== $desired->type && !empty($desired->enumValues); - $isChangeFromEnum = $current->type !== $desired->type && !empty($current->enumValues); - $isChangedEnum = $current->type === $desired->type && !empty($current->enumValues); + $isChangeToEnum = !static::isEnum($current) && static::isEnum($desired); + $isChangeFromEnum = static::isEnum($current) && !static::isEnum($desired); + $isChangedEnum = static::isEnumValuesChanged($current, $desired); if ($isChangedEnum) { // Generation for change enum values not supported. Do it manually // This action require several steps and can't be applied during single transaction return; } - if ($isChangeToEnum) { - $this->migration->addUpCode($this->recordBuilder->createEnum($desired->name, $desired->enumValues), true); - } - if ($isChangeFromEnum) { - $this->migration->addUpCode($this->recordBuilder->dropEnum($current->name)); - } - if (!empty(array_intersect(['type', 'size'], $changed))) { - $addUsing = $this->isNeedUsingExpression($desired->type, $current->type); + + if (!empty(array_intersect(['type', 'size' + , 'dbType', 'phpType' + , 'precision', 'scale', 'unsigned' + ], $changed))) { + $addUsing = $this->isNeedUsingExpression($current->type, $desired->type); $this->migration->addUpCode($this->recordBuilder->alterColumnType($tableName, $desired)); $this->migration->addDownCode($this->recordBuilder->alterColumnTypeFromDb($tableName, $current, $addUsing)); } @@ -93,9 +91,16 @@ protected function buildColumnChanges(ColumnSchema $current, ColumnSchema $desir $this->migration->addUpCode($upCode)->addDownCode($downCode, true); } } + if ($isChangeToEnum) { + $this->migration->addUpCode($this->recordBuilder->createEnum($desired->name, $desired->enumValues), true); + } + if ($isChangeFromEnum) { + $this->migration->addUpCode($this->recordBuilder->dropEnum($current->name)); + } + if ($isChangeFromEnum) { $this->migration - ->addDownCode($this->recordBuilder->createEnum($current->name, $current->enumValues), true); + ->addDownCode($this->recordBuilder->createEnum($current->name, $current->enumValues)); } if ($isChangeToEnum) { $this->migration->addDownCode($this->recordBuilder->dropEnum($current->name), true); @@ -132,7 +137,7 @@ protected function createEnumMigrations():void foreach ($enums as $attr) { $this->migration ->addUpCode($this->recordBuilder->createEnum($attr->columnName, $attr->enumValues), true) - ->addDownCode($this->recordBuilder->dropEnum($attr->columnName)); + ->addDownCode($this->recordBuilder->dropEnum($attr->columnName), true); } } diff --git a/src/lib/openapi/PropertySchema.php b/src/lib/openapi/PropertySchema.php index 4137f99a..9e6b638f 100644 --- a/src/lib/openapi/PropertySchema.php +++ b/src/lib/openapi/PropertySchema.php @@ -530,7 +530,7 @@ public static function findMoreDetailOf(string $xDbType): array } /** - * This method is copied from protected method `getColumnPhpType()` of \yii\db\Schema class + * This method is copied + enhanced from protected method `getColumnPhpType()` of \yii\db\Schema class * Extracts the PHP type from abstract DB type. * @param \yii\db\ColumnSchema $column the column schema information * @return string PHP type name @@ -546,6 +546,7 @@ public static function getColumnPhpType(ColumnSchema $column): string YiiDbSchema::TYPE_BOOLEAN => 'boolean', YiiDbSchema::TYPE_FLOAT => 'double', YiiDbSchema::TYPE_DOUBLE => 'double', + YiiDbSchema::TYPE_DECIMAL => 'double', # (enhanced) YiiDbSchema::TYPE_BINARY => 'resource', YiiDbSchema::TYPE_JSON => 'array', ]; diff --git a/tests/DbTestCase.php b/tests/DbTestCase.php index 8e59422a..1013cea0 100644 --- a/tests/DbTestCase.php +++ b/tests/DbTestCase.php @@ -89,4 +89,19 @@ protected function changeDbToPgsql() self::assertNotInstanceOf(MySqlSchema::class, Yii::$app->db->schema); self::assertInstanceOf(PgSqlSchema::class, Yii::$app->db->schema); } + + protected function checkFiles(array $actual, array $expected) + { + self::assertEquals( + count($actual), + count($expected) + ); + foreach ($actual as $index => $file) { + $expectedFilePath = $expected[$index]; + self::assertFileExists($file); + self::assertFileExists($expectedFilePath); + + $this->assertFileEquals($expectedFilePath, $file, "Failed asserting that file contents of\n$file\nare equal to file contents of\n$expectedFilePath"); + } + } } diff --git a/tests/config/console.php b/tests/config/console.php index a562c131..e3bb729e 100644 --- a/tests/config/console.php +++ b/tests/config/console.php @@ -53,6 +53,13 @@ 'charset' => 'utf8', 'tablePrefix'=>'itt_', ], + 'pg_test_db_2' => [ + 'class' => \yii\db\Connection::class, + 'dsn' => 'pgsql:host=postgres;dbname=pg_test_db_2', + 'username' => 'dbuser', + 'password' => 'dbpass', + 'charset' => 'utf8', + ], 'mysql' => [ 'class' => \yii\db\Connection::class, 'dsn' => 'mysql:host=mysql;dbname=testdb', diff --git a/tests/fixtures/blog.php b/tests/fixtures/blog.php index c9737bb9..deffbd6d 100644 --- a/tests/fixtures/blog.php +++ b/tests/fixtures/blog.php @@ -19,6 +19,10 @@ ->setSize(200)->setRequired()->setFakerStub('substr($faker->safeEmail, 0, 200)'), 'password' => (new Attribute('password', ['phpType' => 'string', 'dbType' => 'string'])) ->setRequired()->setFakerStub('$faker->password'), + 'role' => (new Attribute('role', ['phpType' => 'string', 'dbType' => 'string'])) + ->setSize(20) + ->setDefault('reader') + ->setFakerStub('$faker->randomElement([\'admin\', \'editor\', \'reader\'])'), 'flags' => (new Attribute('flags', ['phpType'=>'int', 'dbType'=>'integer']))->setDefault(0)->setFakerStub ('$faker->numberBetween(0, 1000000)'), 'created_at' => (new Attribute('created_at', ['phpType' => 'string', 'dbType' => 'datetime'])) @@ -28,7 +32,7 @@ 'indexes' => [ 'users_email_key' => DbIndex::make('users', ['email'], null, true), 'users_username_key' => DbIndex::make('users', ['username'], null, true), - 'users_flags_index' => DbIndex::make('users', ['flags']) + 'users_role_flags_index' => DbIndex::make('users', ['role', 'flags']) ] ]), 'category' => new DbModel([ diff --git a/tests/migrations/m100000_000000_maria.php b/tests/migrations/m100000_000000_maria.php index 53dc91df..936f7c83 100644 --- a/tests/migrations/m100000_000000_maria.php +++ b/tests/migrations/m100000_000000_maria.php @@ -34,6 +34,7 @@ public function up() 'username' => $this->string(200)->notNull()->unique(), 'email' => $this->string(200)->notNull()->unique(), 'password' => $this->string()->notNull(), + 'role' => $this->string(20)->null()->defaultValue('reader'), 'flags' => $this->integer()->null()->defaultValue(0), 'created_at' => $this->timestamp()->null()->defaultExpression("CURRENT_TIMESTAMP"), ]); diff --git a/tests/migrations/m100000_000000_mysql.php b/tests/migrations/m100000_000000_mysql.php index d1d0c19a..5b249c06 100644 --- a/tests/migrations/m100000_000000_mysql.php +++ b/tests/migrations/m100000_000000_mysql.php @@ -33,6 +33,7 @@ public function up() 'username' => $this->string(200)->notNull()->unique(), 'email' => $this->string(200)->notNull()->unique(), 'password' => $this->string()->notNull(), + 'role' => $this->string(20)->null()->defaultValue('reader'), 'flags' => $this->integer()->null()->defaultValue(0), 'created_at' => $this->timestamp()->null()->defaultExpression("CURRENT_TIMESTAMP"), ]); diff --git a/tests/migrations/m100000_000000_pgsql.php b/tests/migrations/m100000_000000_pgsql.php index 0780107d..0a42c8e9 100644 --- a/tests/migrations/m100000_000000_pgsql.php +++ b/tests/migrations/m100000_000000_pgsql.php @@ -29,6 +29,7 @@ public function safeUp() 'username' => $this->string(200)->notNull()->unique(), 'email' => $this->string(200)->notNull()->unique(), 'password' => $this->string()->notNull(), + 'role' => $this->string(20)->null()->defaultValue('reader'), 'flags' => $this->integer()->null()->defaultValue(0), 'created_at' => $this->timestamp()->null()->defaultExpression("CURRENT_TIMESTAMP"), ]); @@ -90,6 +91,7 @@ public function safeUp() 'str_country' => $this->text()->null()->defaultValue(null), ]); + $this->execute('CREATE TYPE enum_status AS ENUM(\'active\', \'draft\')'); $this->createTable('{{%v3_pgcustom}}', [ 'id' => $this->bigPrimaryKey(), @@ -98,6 +100,7 @@ public function safeUp() 'json2' => $this->json()->null()->defaultValue(null), 'json3' => $this->json()->defaultValue(Json::encode(['foo' => 'bar', 'bar' => 'baz'])), 'json4' => "json DEFAULT '" . new Expression(Json::encode(['ffo' => 'bar'])) . "'", + 'status' => 'enum_status', 'search' => 'tsvector' ]); $columns = [ @@ -135,6 +138,7 @@ public function safeDown() $this->dropTable('{{%v2_users}}'); $this->dropTable('{{%v2_categories}}'); $this->dropTable('{{%v3_pgcustom}}'); + $this->execute('DROP TYPE enum_status'); $this->dropTable('{{%default_sizes}}'); } } diff --git a/tests/specs/blog.yaml b/tests/specs/blog.yaml index cd03139d..1021b843 100644 --- a/tests/specs/blog.yaml +++ b/tests/specs/blog.yaml @@ -51,7 +51,7 @@ components: x-indexes: - unique:username - unique:email - - flags + - role,flags properties: id: type: integer @@ -66,6 +66,11 @@ components: password: type: string format: password + role: + type: string + maxLength: 20 + x-faker: "$faker->randomElement(['admin', 'editor', 'reader'])" + default: reader flags: type: integer default: 0 diff --git a/tests/specs/blog/migrations/m200000_000001_create_table_users.php b/tests/specs/blog/migrations/m200000_000001_create_table_users.php index 7afd35d4..f8cd744a 100644 --- a/tests/specs/blog/migrations/m200000_000001_create_table_users.php +++ b/tests/specs/blog/migrations/m200000_000001_create_table_users.php @@ -12,17 +12,18 @@ public function up() 'username' => $this->string(200)->notNull(), 'email' => $this->string(200)->notNull(), 'password' => $this->string()->notNull(), + 'role' => $this->string(20)->null()->defaultValue("reader"), 'flags' => $this->integer()->null()->defaultValue(0), 'created_at' => $this->timestamp()->null()->defaultExpression("CURRENT_TIMESTAMP"), ]); $this->createIndex('users_username_key', '{{%users}}', 'username', true); $this->createIndex('users_email_key', '{{%users}}', 'email', true); - $this->createIndex('users_flags_index', '{{%users}}', 'flags', false); + $this->createIndex('users_role_flags_index', '{{%users}}', 'role,flags', false); } public function down() { - $this->dropIndex('users_flags_index', '{{%users}}'); + $this->dropIndex('users_role_flags_index', '{{%users}}'); $this->dropIndex('users_email_key', '{{%users}}'); $this->dropIndex('users_username_key', '{{%users}}'); $this->dropTable('{{%users}}'); diff --git a/tests/specs/blog/migrations_maria_db/m200000_000001_create_table_users.php b/tests/specs/blog/migrations_maria_db/m200000_000001_create_table_users.php index 7afd35d4..f8cd744a 100644 --- a/tests/specs/blog/migrations_maria_db/m200000_000001_create_table_users.php +++ b/tests/specs/blog/migrations_maria_db/m200000_000001_create_table_users.php @@ -12,17 +12,18 @@ public function up() 'username' => $this->string(200)->notNull(), 'email' => $this->string(200)->notNull(), 'password' => $this->string()->notNull(), + 'role' => $this->string(20)->null()->defaultValue("reader"), 'flags' => $this->integer()->null()->defaultValue(0), 'created_at' => $this->timestamp()->null()->defaultExpression("CURRENT_TIMESTAMP"), ]); $this->createIndex('users_username_key', '{{%users}}', 'username', true); $this->createIndex('users_email_key', '{{%users}}', 'email', true); - $this->createIndex('users_flags_index', '{{%users}}', 'flags', false); + $this->createIndex('users_role_flags_index', '{{%users}}', 'role,flags', false); } public function down() { - $this->dropIndex('users_flags_index', '{{%users}}'); + $this->dropIndex('users_role_flags_index', '{{%users}}'); $this->dropIndex('users_email_key', '{{%users}}'); $this->dropIndex('users_username_key', '{{%users}}'); $this->dropTable('{{%users}}'); diff --git a/tests/specs/blog/migrations_mysql_db/m200000_000001_create_table_users.php b/tests/specs/blog/migrations_mysql_db/m200000_000001_create_table_users.php index 7afd35d4..f8cd744a 100644 --- a/tests/specs/blog/migrations_mysql_db/m200000_000001_create_table_users.php +++ b/tests/specs/blog/migrations_mysql_db/m200000_000001_create_table_users.php @@ -12,17 +12,18 @@ public function up() 'username' => $this->string(200)->notNull(), 'email' => $this->string(200)->notNull(), 'password' => $this->string()->notNull(), + 'role' => $this->string(20)->null()->defaultValue("reader"), 'flags' => $this->integer()->null()->defaultValue(0), 'created_at' => $this->timestamp()->null()->defaultExpression("CURRENT_TIMESTAMP"), ]); $this->createIndex('users_username_key', '{{%users}}', 'username', true); $this->createIndex('users_email_key', '{{%users}}', 'email', true); - $this->createIndex('users_flags_index', '{{%users}}', 'flags', false); + $this->createIndex('users_role_flags_index', '{{%users}}', 'role,flags', false); } public function down() { - $this->dropIndex('users_flags_index', '{{%users}}'); + $this->dropIndex('users_role_flags_index', '{{%users}}'); $this->dropIndex('users_email_key', '{{%users}}'); $this->dropIndex('users_username_key', '{{%users}}'); $this->dropTable('{{%users}}'); diff --git a/tests/specs/blog/migrations_pgsql_db/m200000_000001_create_table_users.php b/tests/specs/blog/migrations_pgsql_db/m200000_000001_create_table_users.php index ceeb4494..23fadf71 100644 --- a/tests/specs/blog/migrations_pgsql_db/m200000_000001_create_table_users.php +++ b/tests/specs/blog/migrations_pgsql_db/m200000_000001_create_table_users.php @@ -12,17 +12,18 @@ public function safeUp() 'username' => $this->string(200)->notNull(), 'email' => $this->string(200)->notNull(), 'password' => $this->string()->notNull(), + 'role' => $this->string(20)->null()->defaultValue("reader"), 'flags' => $this->integer()->null()->defaultValue(0), 'created_at' => $this->timestamp()->null()->defaultExpression("CURRENT_TIMESTAMP"), ]); $this->createIndex('users_username_key', '{{%users}}', 'username', true); $this->createIndex('users_email_key', '{{%users}}', 'email', true); - $this->createIndex('users_flags_index', '{{%users}}', 'flags', false); + $this->createIndex('users_role_flags_index', '{{%users}}', 'role,flags', false); } public function safeDown() { - $this->dropIndex('users_flags_index', '{{%users}}'); + $this->dropIndex('users_role_flags_index', '{{%users}}'); $this->dropIndex('users_email_key', '{{%users}}'); $this->dropIndex('users_username_key', '{{%users}}'); $this->dropTable('{{%users}}'); diff --git a/tests/specs/blog/models/UserFaker.php b/tests/specs/blog/models/UserFaker.php index 943eea86..d42fb940 100644 --- a/tests/specs/blog/models/UserFaker.php +++ b/tests/specs/blog/models/UserFaker.php @@ -33,6 +33,7 @@ public function generateModel($attributes = []) $model->username = substr($faker->userName, 0, 200); $model->email = substr($faker->safeEmail, 0, 200); $model->password = $faker->password; + $model->role = $faker->randomElement(['admin', 'editor', 'reader']); $model->flags = $faker->numberBetween(0, 1000000); $model->created_at = $faker->dateTimeThisYear('now', 'UTC')->format(DATE_ATOM); if (!is_callable($attributes)) { diff --git a/tests/specs/blog/models/base/User.php b/tests/specs/blog/models/base/User.php index bc2f5493..614718da 100644 --- a/tests/specs/blog/models/base/User.php +++ b/tests/specs/blog/models/base/User.php @@ -9,6 +9,7 @@ * @property string $username * @property string $email * @property string $password + * @property string $role * @property int $flags * @property string $created_at * @@ -23,7 +24,7 @@ public static function tableName() public function rules() { return [ - 'trim' => [['username', 'email', 'password', 'created_at'], 'trim'], + 'trim' => [['username', 'email', 'password', 'role', 'created_at'], 'trim'], 'required' => [['username', 'email', 'password'], 'required'], 'username_unique' => [['username'], 'unique'], 'email_unique' => [['email'], 'unique'], @@ -31,6 +32,7 @@ public function rules() 'email_string' => [['email'], 'string', 'max' => 200], 'email_email' => [['email'], 'email'], 'password_string' => [['password'], 'string'], + 'role_string' => [['role'], 'string', 'max' => 20], 'flags_integer' => [['flags'], 'integer'], 'created_at_datetime' => [['created_at'], 'datetime'], ]; diff --git a/tests/specs/blog_v2.yaml b/tests/specs/blog_v2.yaml index 81076078..68d09367 100644 --- a/tests/specs/blog_v2.yaml +++ b/tests/specs/blog_v2.yaml @@ -241,7 +241,7 @@ components: x-indexes: - unique:login - unique:email - - hash:flags + - hash:role,flags required: - id - login @@ -261,6 +261,13 @@ components: password: type: string format: password + role: + type: string + enum: + - admin + - editor + - reader + x-faker: "$faker->randomElement(['admin', 'editor', 'reader'])" flags: type: integer default: 0 @@ -325,12 +332,12 @@ components: type: string minLength: 1 maxLength: 200 - # lang: - # type: string - # enum: - # - ru - # - eng - # default: ru + lang: + type: string + enum: + - ru + - eng + default: ru category: $ref: "#/components/schemas/Category" active: @@ -372,7 +379,7 @@ components: type: string meta_data: type: string - example: "type=='ticket'" + example: "type=='ticket' && status=='closed'" minLength: 1 maxLength: 300 default: '' @@ -390,7 +397,7 @@ components: required: - id - name - # - lang + - lang properties: id: type: integer @@ -400,11 +407,11 @@ components: type: string x-db-type: VARCHAR maxLength: 100 - # lang: - # type: string - # enum: - # - ru - # - eng + lang: + type: string + enum: + - ru + - eng posts: type: array items: diff --git a/tests/specs/blog_v2/migrations/m200000_000001_create_table_v2_users.php b/tests/specs/blog_v2/migrations/m200000_000001_create_table_v2_users.php index fd61f856..5dbcb200 100644 --- a/tests/specs/blog_v2/migrations/m200000_000001_create_table_v2_users.php +++ b/tests/specs/blog_v2/migrations/m200000_000001_create_table_v2_users.php @@ -12,17 +12,18 @@ public function up() 'login' => $this->text()->notNull(), 'email' => $this->text()->notNull(), 'password' => $this->string()->notNull(), + 'role' => 'enum(\'admin\', \'editor\', \'reader\') NULL DEFAULT NULL', 'flags' => $this->integer()->null()->defaultValue(0), 'created_at' => $this->timestamp()->null()->defaultValue(null), ]); $this->createIndex('v2_users_login_key', '{{%v2_users}}', 'login', true); $this->createIndex('v2_users_email_key', '{{%v2_users}}', 'email', true); - $this->createIndex('v2_users_flags_hash_index', '{{%v2_users}}', 'flags', 'hash'); + $this->createIndex('v2_users_role_flags_hash_index', '{{%v2_users}}', 'role,flags', 'hash'); } public function down() { - $this->dropIndex('v2_users_flags_hash_index', '{{%v2_users}}'); + $this->dropIndex('v2_users_role_flags_hash_index', '{{%v2_users}}'); $this->dropIndex('v2_users_email_key', '{{%v2_users}}'); $this->dropIndex('v2_users_login_key', '{{%v2_users}}'); $this->dropTable('{{%v2_users}}'); diff --git a/tests/specs/blog_v2/migrations/m200000_000002_create_table_v2_posts.php b/tests/specs/blog_v2/migrations/m200000_000002_create_table_v2_posts.php index cf3ca27a..ba307de6 100644 --- a/tests/specs/blog_v2/migrations/m200000_000002_create_table_v2_posts.php +++ b/tests/specs/blog_v2/migrations/m200000_000002_create_table_v2_posts.php @@ -11,6 +11,7 @@ public function up() 'id' => $this->bigPrimaryKey(), 'title' => $this->string(255)->notNull(), 'slug' => $this->string(200)->null()->defaultValue(null), + 'lang' => 'enum(\'ru\', \'eng\') NULL DEFAULT \'ru\'', 'category_id' => $this->bigInteger()->notNull(), 'active' => $this->boolean()->notNull(), 'created_at' => $this->date()->null()->defaultValue(null), diff --git a/tests/specs/blog_v2/migrations/m200000_000003_create_table_v2_tags.php b/tests/specs/blog_v2/migrations/m200000_000003_create_table_v2_tags.php index f27f11fe..32aefd34 100644 --- a/tests/specs/blog_v2/migrations/m200000_000003_create_table_v2_tags.php +++ b/tests/specs/blog_v2/migrations/m200000_000003_create_table_v2_tags.php @@ -10,6 +10,7 @@ public function up() $this->createTable('{{%v2_tags}}', [ 'id' => $this->bigPrimaryKey(), 'name' => $this->string(100)->notNull(), + 'lang' => 'enum(\'ru\', \'eng\') NOT NULL', ]); $this->createIndex('v2_tags_name_key', '{{%v2_tags}}', 'name', true); } diff --git a/tests/specs/blog_v2/migrations_maria_db/m200000_000000_change_table_v2_posts.php b/tests/specs/blog_v2/migrations_maria_db/m200000_000000_change_table_v2_posts.php index c7f6a2a3..e42208b9 100644 --- a/tests/specs/blog_v2/migrations_maria_db/m200000_000000_change_table_v2_posts.php +++ b/tests/specs/blog_v2/migrations_maria_db/m200000_000000_change_table_v2_posts.php @@ -8,6 +8,7 @@ class m200000_000000_change_table_v2_posts extends \yii\db\Migration public function up() { $this->addColumn('{{%v2_posts}}', 'id', $this->bigPrimaryKey()); + $this->addColumn('{{%v2_posts}}', 'lang', 'enum("ru", "eng") NULL DEFAULT \'ru\''); $this->dropColumn('{{%v2_posts}}', 'uid'); $this->alterColumn('{{%v2_posts}}', 'active', $this->tinyInteger(1)->notNull()); $this->alterColumn('{{%v2_posts}}', 'category_id', $this->bigInteger()->notNull()); @@ -22,6 +23,7 @@ public function down() $this->alterColumn('{{%v2_posts}}', 'category_id', $this->integer(11)->notNull()); $this->alterColumn('{{%v2_posts}}', 'active', $this->tinyInteger(1)->notNull()->defaultValue(0)); $this->addColumn('{{%v2_posts}}', 'uid', $this->bigInteger(20)->notNull()); + $this->dropColumn('{{%v2_posts}}', 'lang'); $this->dropColumn('{{%v2_posts}}', 'id'); } } diff --git a/tests/specs/blog_v2/migrations_maria_db/m200000_000001_create_table_v2_tags.php b/tests/specs/blog_v2/migrations_maria_db/m200000_000001_create_table_v2_tags.php index 50ffc28d..1e671e96 100644 --- a/tests/specs/blog_v2/migrations_maria_db/m200000_000001_create_table_v2_tags.php +++ b/tests/specs/blog_v2/migrations_maria_db/m200000_000001_create_table_v2_tags.php @@ -10,6 +10,7 @@ public function up() $this->createTable('{{%v2_tags}}', [ 'id' => $this->bigPrimaryKey(), 0 => 'name varchar(100) NOT NULL', + 'lang' => 'enum("ru", "eng") NOT NULL', ]); $this->createIndex('v2_tags_name_key', '{{%v2_tags}}', 'name', true); } diff --git a/tests/specs/blog_v2/migrations_maria_db/m200000_000004_change_table_v2_users.php b/tests/specs/blog_v2/migrations_maria_db/m200000_000004_change_table_v2_users.php index 59003105..c175f1b5 100644 --- a/tests/specs/blog_v2/migrations_maria_db/m200000_000004_change_table_v2_users.php +++ b/tests/specs/blog_v2/migrations_maria_db/m200000_000004_change_table_v2_users.php @@ -11,16 +11,18 @@ public function up() $this->dropColumn('{{%v2_users}}', 'username'); $this->alterColumn('{{%v2_users}}', 'created_at', $this->timestamp()->null()->defaultValue(null)); $this->alterColumn('{{%v2_users}}', 'email', $this->string(255)->notNull()); + $this->alterColumn('{{%v2_users}}', 'role', 'enum("admin", "editor", "reader") NULL DEFAULT NULL'); $this->dropIndex('v2_users_username_key', '{{%v2_users}}'); $this->createIndex('v2_users_login_key', '{{%v2_users}}', 'login', true); - $this->createIndex('v2_users_flags_hash_index', '{{%v2_users}}', 'flags', 'hash'); + $this->createIndex('v2_users_role_flags_hash_index', '{{%v2_users}}', 'role,flags', 'hash'); } public function down() { - $this->dropIndex('v2_users_flags_hash_index', '{{%v2_users}}'); + $this->dropIndex('v2_users_role_flags_hash_index', '{{%v2_users}}'); $this->dropIndex('v2_users_login_key', '{{%v2_users}}'); $this->createIndex('v2_users_username_key', '{{%v2_users}}', 'username', true); + $this->alterColumn('{{%v2_users}}', 'role', $this->string(20)->null()->defaultValue("reader")); $this->alterColumn('{{%v2_users}}', 'email', $this->string(200)->notNull()); $this->alterColumn('{{%v2_users}}', 'created_at', $this->timestamp()->null()->defaultExpression("current_timestamp()")); $this->addColumn('{{%v2_users}}', 'username', $this->string(200)->notNull()); diff --git a/tests/specs/blog_v2/migrations_mysql_db/m200000_000000_change_table_v2_posts.php b/tests/specs/blog_v2/migrations_mysql_db/m200000_000000_change_table_v2_posts.php index c7f6a2a3..e42208b9 100644 --- a/tests/specs/blog_v2/migrations_mysql_db/m200000_000000_change_table_v2_posts.php +++ b/tests/specs/blog_v2/migrations_mysql_db/m200000_000000_change_table_v2_posts.php @@ -8,6 +8,7 @@ class m200000_000000_change_table_v2_posts extends \yii\db\Migration public function up() { $this->addColumn('{{%v2_posts}}', 'id', $this->bigPrimaryKey()); + $this->addColumn('{{%v2_posts}}', 'lang', 'enum("ru", "eng") NULL DEFAULT \'ru\''); $this->dropColumn('{{%v2_posts}}', 'uid'); $this->alterColumn('{{%v2_posts}}', 'active', $this->tinyInteger(1)->notNull()); $this->alterColumn('{{%v2_posts}}', 'category_id', $this->bigInteger()->notNull()); @@ -22,6 +23,7 @@ public function down() $this->alterColumn('{{%v2_posts}}', 'category_id', $this->integer(11)->notNull()); $this->alterColumn('{{%v2_posts}}', 'active', $this->tinyInteger(1)->notNull()->defaultValue(0)); $this->addColumn('{{%v2_posts}}', 'uid', $this->bigInteger(20)->notNull()); + $this->dropColumn('{{%v2_posts}}', 'lang'); $this->dropColumn('{{%v2_posts}}', 'id'); } } diff --git a/tests/specs/blog_v2/migrations_mysql_db/m200000_000001_create_table_v2_tags.php b/tests/specs/blog_v2/migrations_mysql_db/m200000_000001_create_table_v2_tags.php index 50ffc28d..1e671e96 100644 --- a/tests/specs/blog_v2/migrations_mysql_db/m200000_000001_create_table_v2_tags.php +++ b/tests/specs/blog_v2/migrations_mysql_db/m200000_000001_create_table_v2_tags.php @@ -10,6 +10,7 @@ public function up() $this->createTable('{{%v2_tags}}', [ 'id' => $this->bigPrimaryKey(), 0 => 'name varchar(100) NOT NULL', + 'lang' => 'enum("ru", "eng") NOT NULL', ]); $this->createIndex('v2_tags_name_key', '{{%v2_tags}}', 'name', true); } diff --git a/tests/specs/blog_v2/migrations_mysql_db/m200000_000004_change_table_v2_users.php b/tests/specs/blog_v2/migrations_mysql_db/m200000_000004_change_table_v2_users.php index db190e42..87d83448 100644 --- a/tests/specs/blog_v2/migrations_mysql_db/m200000_000004_change_table_v2_users.php +++ b/tests/specs/blog_v2/migrations_mysql_db/m200000_000004_change_table_v2_users.php @@ -11,16 +11,18 @@ public function up() $this->dropColumn('{{%v2_users}}', 'username'); $this->alterColumn('{{%v2_users}}', 'created_at', $this->timestamp()->null()->defaultValue(null)); $this->alterColumn('{{%v2_users}}', 'email', $this->string(255)->notNull()); + $this->alterColumn('{{%v2_users}}', 'role', 'enum("admin", "editor", "reader") NULL DEFAULT NULL'); $this->dropIndex('v2_users_username_key', '{{%v2_users}}'); $this->createIndex('v2_users_login_key', '{{%v2_users}}', 'login', true); - $this->createIndex('v2_users_flags_hash_index', '{{%v2_users}}', 'flags', 'hash'); + $this->createIndex('v2_users_role_flags_hash_index', '{{%v2_users}}', 'role,flags', 'hash'); } public function down() { - $this->dropIndex('v2_users_flags_hash_index', '{{%v2_users}}'); + $this->dropIndex('v2_users_role_flags_hash_index', '{{%v2_users}}'); $this->dropIndex('v2_users_login_key', '{{%v2_users}}'); $this->createIndex('v2_users_username_key', '{{%v2_users}}', 'username', true); + $this->alterColumn('{{%v2_users}}', 'role', $this->string(20)->null()->defaultValue("reader")); $this->alterColumn('{{%v2_users}}', 'email', $this->string(200)->notNull()); $this->alterColumn('{{%v2_users}}', 'created_at', $this->timestamp()->null()->defaultExpression("CURRENT_TIMESTAMP")); $this->addColumn('{{%v2_users}}', 'username', $this->string(200)->notNull()); diff --git a/tests/specs/blog_v2/migrations_pgsql_db/m200000_000000_change_table_v2_posts.php b/tests/specs/blog_v2/migrations_pgsql_db/m200000_000000_change_table_v2_posts.php index a03de14a..22a0029b 100644 --- a/tests/specs/blog_v2/migrations_pgsql_db/m200000_000000_change_table_v2_posts.php +++ b/tests/specs/blog_v2/migrations_pgsql_db/m200000_000000_change_table_v2_posts.php @@ -8,6 +8,8 @@ class m200000_000000_change_table_v2_posts extends \yii\db\Migration public function safeUp() { $this->addColumn('{{%v2_posts}}', 'id', $this->bigPrimaryKey()); + $this->execute('CREATE TYPE enum_lang AS ENUM(\'ru\', \'eng\')'); + $this->addColumn('{{%v2_posts}}', 'lang', 'enum_lang NULL DEFAULT \'ru\''); $this->dropColumn('{{%v2_posts}}', 'uid'); $this->alterColumn('{{%v2_posts}}', 'active', "DROP DEFAULT"); $this->alterColumn('{{%v2_posts}}', 'category_id', $this->bigInteger()->notNull()); @@ -21,7 +23,9 @@ public function safeDown() $this->alterColumn('{{%v2_posts}}', 'created_by_id', $this->integer()->null()); $this->alterColumn('{{%v2_posts}}', 'category_id', $this->integer()->notNull()); $this->addColumn('{{%v2_posts}}', 'uid', $this->bigInteger()->notNull()); + $this->dropColumn('{{%v2_posts}}', 'lang'); $this->dropColumn('{{%v2_posts}}', 'id'); + $this->execute('DROP TYPE enum_lang'); $this->alterColumn('{{%v2_posts}}', 'active', "SET DEFAULT 'f'"); } } diff --git a/tests/specs/blog_v2/migrations_pgsql_db/m200000_000001_create_table_v2_tags.php b/tests/specs/blog_v2/migrations_pgsql_db/m200000_000001_create_table_v2_tags.php index a8d8a98c..ea6d7ff8 100644 --- a/tests/specs/blog_v2/migrations_pgsql_db/m200000_000001_create_table_v2_tags.php +++ b/tests/specs/blog_v2/migrations_pgsql_db/m200000_000001_create_table_v2_tags.php @@ -7,9 +7,11 @@ class m200000_000001_create_table_v2_tags extends \yii\db\Migration { public function safeUp() { + $this->execute('CREATE TYPE enum_lang AS ENUM(\'ru\', \'eng\')'); $this->createTable('{{%v2_tags}}', [ 'id' => $this->bigPrimaryKey(), 0 => 'name varchar(100) NOT NULL', + 'lang' => 'enum_lang NOT NULL', ]); $this->createIndex('v2_tags_name_key', '{{%v2_tags}}', 'name', true); } @@ -18,5 +20,6 @@ public function safeDown() { $this->dropIndex('v2_tags_name_key', '{{%v2_tags}}'); $this->dropTable('{{%v2_tags}}'); + $this->execute('DROP TYPE enum_lang'); } } diff --git a/tests/specs/blog_v2/migrations_pgsql_db/m200000_000004_change_table_v2_users.php b/tests/specs/blog_v2/migrations_pgsql_db/m200000_000004_change_table_v2_users.php index 8dbf692d..7bfe1bf9 100644 --- a/tests/specs/blog_v2/migrations_pgsql_db/m200000_000004_change_table_v2_users.php +++ b/tests/specs/blog_v2/migrations_pgsql_db/m200000_000004_change_table_v2_users.php @@ -7,23 +7,29 @@ class m200000_000004_change_table_v2_users extends \yii\db\Migration { public function safeUp() { + $this->execute('CREATE TYPE enum_role AS ENUM(\'admin\', \'editor\', \'reader\')'); $this->addColumn('{{%v2_users}}', 'login', $this->text()->notNull()); $this->dropColumn('{{%v2_users}}', 'username'); $this->alterColumn('{{%v2_users}}', 'created_at', "DROP DEFAULT"); $this->db->createCommand('ALTER TABLE {{%v2_users}} ALTER COLUMN email SET DATA TYPE varchar(255)')->execute(); + $this->alterColumn('{{%v2_users}}', 'role', 'enum_role USING "role"::enum_role'); + $this->alterColumn('{{%v2_users}}', 'role', "DROP DEFAULT"); $this->dropIndex('v2_users_username_key', '{{%v2_users}}'); $this->createIndex('v2_users_login_key', '{{%v2_users}}', 'login', true); - $this->createIndex('v2_users_flags_hash_index', '{{%v2_users}}', 'flags', 'hash'); + $this->createIndex('v2_users_role_flags_hash_index', '{{%v2_users}}', 'role,flags', 'hash'); } public function safeDown() { - $this->dropIndex('v2_users_flags_hash_index', '{{%v2_users}}'); + $this->dropIndex('v2_users_role_flags_hash_index', '{{%v2_users}}'); $this->dropIndex('v2_users_login_key', '{{%v2_users}}'); $this->createIndex('v2_users_username_key', '{{%v2_users}}', 'username', true); + $this->alterColumn('{{%v2_users}}', 'role', $this->string(20)->null()); $this->alterColumn('{{%v2_users}}', 'email', $this->string(200)->notNull()); $this->addColumn('{{%v2_users}}', 'username', $this->string(200)->notNull()); $this->dropColumn('{{%v2_users}}', 'login'); $this->alterColumn('{{%v2_users}}', 'created_at', "SET DEFAULT CURRENT_TIMESTAMP"); + $this->alterColumn('{{%v2_users}}', 'role', "SET DEFAULT 'reader'"); + $this->execute('DROP TYPE enum_role'); } } diff --git a/tests/specs/blog_v2/models/PostFaker.php b/tests/specs/blog_v2/models/PostFaker.php index 6fc36c0e..a1e8eb81 100644 --- a/tests/specs/blog_v2/models/PostFaker.php +++ b/tests/specs/blog_v2/models/PostFaker.php @@ -32,6 +32,7 @@ public function generateModel($attributes = []) //$model->id = $uniqueFaker->numberBetween(0, 1000000); $model->title = substr($faker->sentence, 0, 255); $model->slug = substr($uniqueFaker->slug, 0, 200); + $model->lang = $faker->randomElement(['ru','eng']); $model->active = $faker->boolean; $model->created_at = $faker->dateTimeThisCentury->format('Y-m-d'); if (!is_callable($attributes)) { diff --git a/tests/specs/blog_v2/models/TagFaker.php b/tests/specs/blog_v2/models/TagFaker.php index 6308fa68..8e0af887 100644 --- a/tests/specs/blog_v2/models/TagFaker.php +++ b/tests/specs/blog_v2/models/TagFaker.php @@ -31,6 +31,7 @@ public function generateModel($attributes = []) $model = new Tag(); //$model->id = $uniqueFaker->numberBetween(0, 1000000); $model->name = substr($faker->text(100), 0, 100); + $model->lang = $faker->randomElement(['ru','eng']); if (!is_callable($attributes)) { $model->setAttributes($attributes, false); } else { diff --git a/tests/specs/blog_v2/models/UserFaker.php b/tests/specs/blog_v2/models/UserFaker.php index 9810c37a..9e2344f9 100644 --- a/tests/specs/blog_v2/models/UserFaker.php +++ b/tests/specs/blog_v2/models/UserFaker.php @@ -33,6 +33,7 @@ public function generateModel($attributes = []) $model->login = $faker->userName; $model->email = substr($faker->safeEmail, 0, 255); $model->password = $faker->password; + $model->role = $faker->randomElement(['admin', 'editor', 'reader']); $model->flags = $faker->numberBetween(0, 1000000); $model->created_at = $faker->dateTimeThisYear('now', 'UTC')->format(DATE_ATOM); if (!is_callable($attributes)) { diff --git a/tests/specs/blog_v2/models/base/Post.php b/tests/specs/blog_v2/models/base/Post.php index 3599eb90..aec86342 100644 --- a/tests/specs/blog_v2/models/base/Post.php +++ b/tests/specs/blog_v2/models/base/Post.php @@ -8,6 +8,7 @@ * @property int $id * @property string $title * @property string $slug + * @property string $lang * @property int $category_id Category of posts * @property bool $active * @property string $created_at @@ -28,7 +29,7 @@ public static function tableName() public function rules() { return [ - 'trim' => [['title', 'slug', 'created_at'], 'trim'], + 'trim' => [['title', 'slug', 'lang', 'created_at'], 'trim'], 'required' => [['title', 'category_id', 'active'], 'required'], 'category_id_integer' => [['category_id'], 'integer'], 'category_id_exist' => [['category_id'], 'exist', 'targetRelation' => 'Category'], @@ -37,6 +38,8 @@ public function rules() 'title_unique' => [['title'], 'unique'], 'title_string' => [['title'], 'string', 'max' => 255], 'slug_string' => [['slug'], 'string', 'min' => 1, 'max' => 200], + 'lang_string' => [['lang'], 'string'], + 'lang_in' => [['lang'], 'in', 'range' => ['ru', 'eng']], 'active_boolean' => [['active'], 'boolean'], 'created_at_date' => [['created_at'], 'date'], ]; diff --git a/tests/specs/blog_v2/models/base/Tag.php b/tests/specs/blog_v2/models/base/Tag.php index 761507a8..2d0e7d6c 100644 --- a/tests/specs/blog_v2/models/base/Tag.php +++ b/tests/specs/blog_v2/models/base/Tag.php @@ -7,6 +7,7 @@ * * @property int $id * @property string $name + * @property string $lang * * @property array|\app\models\Post[] $posts */ @@ -20,10 +21,12 @@ public static function tableName() public function rules() { return [ - 'trim' => [['name'], 'trim'], - 'required' => [['name'], 'required'], + 'trim' => [['name', 'lang'], 'trim'], + 'required' => [['name', 'lang'], 'required'], 'name_unique' => [['name'], 'unique'], 'name_string' => [['name'], 'string', 'max' => 100], + 'lang_string' => [['lang'], 'string'], + 'lang_in' => [['lang'], 'in', 'range' => ['ru', 'eng']], ]; } diff --git a/tests/specs/blog_v2/models/base/User.php b/tests/specs/blog_v2/models/base/User.php index 3470798f..3ac6d337 100644 --- a/tests/specs/blog_v2/models/base/User.php +++ b/tests/specs/blog_v2/models/base/User.php @@ -9,6 +9,7 @@ * @property string $login * @property string $email * @property string $password + * @property string $role * @property int $flags * @property string $created_at * @@ -23,7 +24,7 @@ public static function tableName() public function rules() { return [ - 'trim' => [['login', 'email', 'password', 'created_at'], 'trim'], + 'trim' => [['login', 'email', 'password', 'role', 'created_at'], 'trim'], 'required' => [['login', 'email', 'password'], 'required'], 'login_unique' => [['login'], 'unique'], 'email_unique' => [['email'], 'unique'], @@ -31,6 +32,8 @@ public function rules() 'email_string' => [['email'], 'string', 'max' => 255], 'email_email' => [['email'], 'email'], 'password_string' => [['password'], 'string'], + 'role_string' => [['role'], 'string'], + 'role_in' => [['role'], 'in', 'range' => ['admin', 'editor', 'reader']], 'flags_integer' => [['flags'], 'integer'], 'created_at_datetime' => [['created_at'], 'datetime'], ]; diff --git a/tests/specs/enum/change/maria/app/migrations_maria_db/m200000_000000_change_table_editcolumns.php b/tests/specs/enum/change/maria/app/migrations_maria_db/m200000_000000_change_table_editcolumns.php new file mode 100644 index 00000000..9d0b16ab --- /dev/null +++ b/tests/specs/enum/change/maria/app/migrations_maria_db/m200000_000000_change_table_editcolumns.php @@ -0,0 +1,19 @@ +alterColumn('{{%editcolumns}}', 'connection', 'enum("WIRED", "WIRELESS") NOT NULL DEFAULT \'WIRED\''); + $this->alterColumn('{{%editcolumns}}', 'device', $this->text()->null()->defaultValue(null)); + } + + public function down() + { + $this->alterColumn('{{%editcolumns}}', 'device', 'enum("MOBILE", "TV", "COMPUTER") NOT NULL DEFAULT \'TV\''); + $this->alterColumn('{{%editcolumns}}', 'connection', $this->string(255)->null()->defaultValue(null)); + } +} diff --git a/tests/specs/enum/change/maria/app/migrations_maria_db/m200000_000001_create_table_newcolumns.php b/tests/specs/enum/change/maria/app/migrations_maria_db/m200000_000001_create_table_newcolumns.php new file mode 100644 index 00000000..36971de6 --- /dev/null +++ b/tests/specs/enum/change/maria/app/migrations_maria_db/m200000_000001_create_table_newcolumns.php @@ -0,0 +1,20 @@ +createTable('{{%newcolumns}}', [ + 'id' => $this->primaryKey(), + 'new_column' => 'enum("ONE", "TWO", "THREE") NOT NULL DEFAULT \'ONE\'', + ]); + } + + public function down() + { + $this->dropTable('{{%newcolumns}}'); + } +} diff --git a/tests/specs/enum/change/maria/app/migrations_maria_db/m200000_000002_create_table_pristines.php b/tests/specs/enum/change/maria/app/migrations_maria_db/m200000_000002_create_table_pristines.php new file mode 100644 index 00000000..bdd46f98 --- /dev/null +++ b/tests/specs/enum/change/maria/app/migrations_maria_db/m200000_000002_create_table_pristines.php @@ -0,0 +1,20 @@ +createTable('{{%pristines}}', [ + 'id' => $this->primaryKey(), + 'device' => 'enum("MOBILE", "TV", "COMPUTER") NOT NULL DEFAULT \'TV\'', + ]); + } + + public function down() + { + $this->dropTable('{{%pristines}}'); + } +} diff --git a/tests/specs/enum/change/mysql/app/migrations_mysql_db/m200000_000000_change_table_editcolumns.php b/tests/specs/enum/change/mysql/app/migrations_mysql_db/m200000_000000_change_table_editcolumns.php new file mode 100644 index 00000000..7a79e1fc --- /dev/null +++ b/tests/specs/enum/change/mysql/app/migrations_mysql_db/m200000_000000_change_table_editcolumns.php @@ -0,0 +1,19 @@ +alterColumn('{{%editcolumns}}', 'connection', 'enum("WIRED", "WIRELESS") NOT NULL DEFAULT \'WIRED\''); + $this->alterColumn('{{%editcolumns}}', 'device', $this->text()->null()); + } + + public function down() + { + $this->alterColumn('{{%editcolumns}}', 'device', 'enum("MOBILE", "TV", "COMPUTER") NOT NULL DEFAULT \'TV\''); + $this->alterColumn('{{%editcolumns}}', 'connection', $this->string(255)->null()->defaultValue(null)); + } +} diff --git a/tests/specs/enum/change/mysql/app/migrations_mysql_db/m200000_000001_create_table_newcolumns.php b/tests/specs/enum/change/mysql/app/migrations_mysql_db/m200000_000001_create_table_newcolumns.php new file mode 100644 index 00000000..36971de6 --- /dev/null +++ b/tests/specs/enum/change/mysql/app/migrations_mysql_db/m200000_000001_create_table_newcolumns.php @@ -0,0 +1,20 @@ +createTable('{{%newcolumns}}', [ + 'id' => $this->primaryKey(), + 'new_column' => 'enum("ONE", "TWO", "THREE") NOT NULL DEFAULT \'ONE\'', + ]); + } + + public function down() + { + $this->dropTable('{{%newcolumns}}'); + } +} diff --git a/tests/specs/enum/change/mysql/app/migrations_mysql_db/m200000_000002_create_table_pristines.php b/tests/specs/enum/change/mysql/app/migrations_mysql_db/m200000_000002_create_table_pristines.php new file mode 100644 index 00000000..bdd46f98 --- /dev/null +++ b/tests/specs/enum/change/mysql/app/migrations_mysql_db/m200000_000002_create_table_pristines.php @@ -0,0 +1,20 @@ +createTable('{{%pristines}}', [ + 'id' => $this->primaryKey(), + 'device' => 'enum("MOBILE", "TV", "COMPUTER") NOT NULL DEFAULT \'TV\'', + ]); + } + + public function down() + { + $this->dropTable('{{%pristines}}'); + } +} diff --git a/tests/specs/enum/change/pgsql/app/migrations_pgsql_db/m200000_000000_change_table_editcolumns.php b/tests/specs/enum/change/pgsql/app/migrations_pgsql_db/m200000_000000_change_table_editcolumns.php new file mode 100644 index 00000000..5069d918 --- /dev/null +++ b/tests/specs/enum/change/pgsql/app/migrations_pgsql_db/m200000_000000_change_table_editcolumns.php @@ -0,0 +1,31 @@ +execute('CREATE TYPE enum_connection AS ENUM(\'WIRED\', \'WIRELESS\')'); + $this->alterColumn('{{%editcolumns}}', 'connection', 'enum_connection USING "connection"::enum_connection'); + $this->alterColumn('{{%editcolumns}}', 'connection', "SET NOT NULL"); + $this->alterColumn('{{%editcolumns}}', 'connection', "SET DEFAULT 'WIRED'"); + $this->alterColumn('{{%editcolumns}}', 'device', $this->text()->null()); + $this->alterColumn('{{%editcolumns}}', 'device', "DROP NOT NULL"); + $this->alterColumn('{{%editcolumns}}', 'device', "DROP DEFAULT"); + $this->execute('DROP TYPE enum_device'); + } + + public function safeDown() + { + $this->execute('CREATE TYPE enum_device AS ENUM(\'MOBILE\', \'TV\', \'COMPUTER\')'); + $this->alterColumn('{{%editcolumns}}', 'device', 'enum_device USING "device"::enum_device'); + $this->alterColumn('{{%editcolumns}}', 'connection', $this->string(255)->null()); + $this->alterColumn('{{%editcolumns}}', 'connection', "DROP NOT NULL"); + $this->alterColumn('{{%editcolumns}}', 'connection', "DROP DEFAULT"); + $this->execute('DROP TYPE enum_connection'); + $this->alterColumn('{{%editcolumns}}', 'device', "SET NOT NULL"); + $this->alterColumn('{{%editcolumns}}', 'device', "SET DEFAULT 'TV'"); + } +} diff --git a/tests/specs/enum/change/pgsql/app/migrations_pgsql_db/m200000_000001_create_table_newcolumns.php b/tests/specs/enum/change/pgsql/app/migrations_pgsql_db/m200000_000001_create_table_newcolumns.php new file mode 100644 index 00000000..75c86ca3 --- /dev/null +++ b/tests/specs/enum/change/pgsql/app/migrations_pgsql_db/m200000_000001_create_table_newcolumns.php @@ -0,0 +1,22 @@ +execute('CREATE TYPE enum_new_column AS ENUM(\'ONE\', \'TWO\', \'THREE\')'); + $this->createTable('{{%newcolumns}}', [ + 'id' => $this->primaryKey(), + 'new_column' => 'enum_new_column NOT NULL DEFAULT \'ONE\'', + ]); + } + + public function safeDown() + { + $this->dropTable('{{%newcolumns}}'); + $this->execute('DROP TYPE enum_new_column'); + } +} diff --git a/tests/specs/enum/change/pgsql/app/migrations_pgsql_db/m200000_000002_create_table_pristines.php b/tests/specs/enum/change/pgsql/app/migrations_pgsql_db/m200000_000002_create_table_pristines.php new file mode 100644 index 00000000..57dbe3c2 --- /dev/null +++ b/tests/specs/enum/change/pgsql/app/migrations_pgsql_db/m200000_000002_create_table_pristines.php @@ -0,0 +1,22 @@ +execute('CREATE TYPE enum_device AS ENUM(\'MOBILE\', \'TV\', \'COMPUTER\')'); + $this->createTable('{{%pristines}}', [ + 'id' => $this->primaryKey(), + 'device' => 'enum_device NOT NULL DEFAULT \'TV\'', + ]); + } + + public function safeDown() + { + $this->dropTable('{{%pristines}}'); + $this->execute('DROP TYPE enum_device'); + } +} diff --git a/tests/specs/enum/fresh/maria/app/migrations_maria_db/m200000_000000_create_table_editcolumns.php b/tests/specs/enum/fresh/maria/app/migrations_maria_db/m200000_000000_create_table_editcolumns.php new file mode 100644 index 00000000..1778bc15 --- /dev/null +++ b/tests/specs/enum/fresh/maria/app/migrations_maria_db/m200000_000000_create_table_editcolumns.php @@ -0,0 +1,21 @@ +createTable('{{%editcolumns}}', [ + 'id' => $this->primaryKey(), + 'device' => $this->text()->null()->defaultValue(null), + 'connection' => 'enum("WIRED", "WIRELESS") NOT NULL DEFAULT \'WIRED\'', + ]); + } + + public function down() + { + $this->dropTable('{{%editcolumns}}'); + } +} diff --git a/tests/specs/enum/fresh/maria/app/migrations_maria_db/m200000_000001_create_table_newcolumns.php b/tests/specs/enum/fresh/maria/app/migrations_maria_db/m200000_000001_create_table_newcolumns.php new file mode 100644 index 00000000..36971de6 --- /dev/null +++ b/tests/specs/enum/fresh/maria/app/migrations_maria_db/m200000_000001_create_table_newcolumns.php @@ -0,0 +1,20 @@ +createTable('{{%newcolumns}}', [ + 'id' => $this->primaryKey(), + 'new_column' => 'enum("ONE", "TWO", "THREE") NOT NULL DEFAULT \'ONE\'', + ]); + } + + public function down() + { + $this->dropTable('{{%newcolumns}}'); + } +} diff --git a/tests/specs/enum/fresh/maria/app/migrations_maria_db/m200000_000002_create_table_pristines.php b/tests/specs/enum/fresh/maria/app/migrations_maria_db/m200000_000002_create_table_pristines.php new file mode 100644 index 00000000..bdd46f98 --- /dev/null +++ b/tests/specs/enum/fresh/maria/app/migrations_maria_db/m200000_000002_create_table_pristines.php @@ -0,0 +1,20 @@ +createTable('{{%pristines}}', [ + 'id' => $this->primaryKey(), + 'device' => 'enum("MOBILE", "TV", "COMPUTER") NOT NULL DEFAULT \'TV\'', + ]); + } + + public function down() + { + $this->dropTable('{{%pristines}}'); + } +} diff --git a/tests/specs/enum/fresh/mysql/app/migrations_mysql_db/m200000_000000_create_table_editcolumns.php b/tests/specs/enum/fresh/mysql/app/migrations_mysql_db/m200000_000000_create_table_editcolumns.php new file mode 100644 index 00000000..78e27f4f --- /dev/null +++ b/tests/specs/enum/fresh/mysql/app/migrations_mysql_db/m200000_000000_create_table_editcolumns.php @@ -0,0 +1,21 @@ +createTable('{{%editcolumns}}', [ + 'id' => $this->primaryKey(), + 'device' => $this->text()->null(), + 'connection' => 'enum("WIRED", "WIRELESS") NOT NULL DEFAULT \'WIRED\'', + ]); + } + + public function down() + { + $this->dropTable('{{%editcolumns}}'); + } +} diff --git a/tests/specs/enum/fresh/mysql/app/migrations_mysql_db/m200000_000001_create_table_newcolumns.php b/tests/specs/enum/fresh/mysql/app/migrations_mysql_db/m200000_000001_create_table_newcolumns.php new file mode 100644 index 00000000..36971de6 --- /dev/null +++ b/tests/specs/enum/fresh/mysql/app/migrations_mysql_db/m200000_000001_create_table_newcolumns.php @@ -0,0 +1,20 @@ +createTable('{{%newcolumns}}', [ + 'id' => $this->primaryKey(), + 'new_column' => 'enum("ONE", "TWO", "THREE") NOT NULL DEFAULT \'ONE\'', + ]); + } + + public function down() + { + $this->dropTable('{{%newcolumns}}'); + } +} diff --git a/tests/specs/enum/fresh/mysql/app/migrations_mysql_db/m200000_000002_create_table_pristines.php b/tests/specs/enum/fresh/mysql/app/migrations_mysql_db/m200000_000002_create_table_pristines.php new file mode 100644 index 00000000..bdd46f98 --- /dev/null +++ b/tests/specs/enum/fresh/mysql/app/migrations_mysql_db/m200000_000002_create_table_pristines.php @@ -0,0 +1,20 @@ +createTable('{{%pristines}}', [ + 'id' => $this->primaryKey(), + 'device' => 'enum("MOBILE", "TV", "COMPUTER") NOT NULL DEFAULT \'TV\'', + ]); + } + + public function down() + { + $this->dropTable('{{%pristines}}'); + } +} diff --git a/tests/specs/enum/fresh/mysql/enum.php b/tests/specs/enum/fresh/mysql/enum.php new file mode 100644 index 00000000..fa0cac3a --- /dev/null +++ b/tests/specs/enum/fresh/mysql/enum.php @@ -0,0 +1,13 @@ + '@specs/enum/fresh/mysql/enum.yaml', + 'generateUrls' => false, + 'generateModels' => false, + 'excludeModels' => [ + 'Error', + ], + 'generateControllers' => false, + 'generateMigrations' => true, + 'generateModelFaker' => false, +]; diff --git a/tests/specs/enum/fresh/mysql/enum.yaml b/tests/specs/enum/fresh/mysql/enum.yaml new file mode 100644 index 00000000..3017f013 --- /dev/null +++ b/tests/specs/enum/fresh/mysql/enum.yaml @@ -0,0 +1,116 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Enum test +paths: + /: + get: + summary: List + operationId: list + responses: + '200': + description: The information + +components: + schemas: + Pristine: + type: object + description: Enum for migration code generation + required: + - id + properties: + id: + type: integer + device: + type: string + maxLength: 8 + enum: + - MOBILE + - TV + - COMPUTER + default: + TV + nullable: false + + Newcolumn: + type: object + description: New Fresh table with new enum column for migration code generation + required: + - id + properties: + id: + type: integer + # device: + # type: string + # maxLength: 8 + # enum: + # - MOBILE + # - TV + # - COMPUTER + # default: + # TV + # nullable: false + new_column: + type: string + enum: + - ONE + - TWO + - THREE + default: + ONE + nullable: false + + Editcolumn: + type: object + description: Table with edit enum columns for migration code generation + required: + - id + properties: + id: + type: integer + device: + type: string + connection: + type: string + enum: + - WIRED + - WIRELESS + default: + WIRED + nullable: false + + # Enumvaluechange: + # type: object + # description: Table with enum value change for migration code generation + # required: + # - id + # properties: + # id: + # type: integer + # add_one_mood_at_last: + # type: string + # enum: + # # admiration, adoration, appreciation of beauty, amusement, anger, anxiety, awe, awkwardness, boredom, calmness, confusion, craving, disgust, empathic pain, entrancement, excitement, fear, horror, interest, joy, nostalgia, relief + # - INTEREST + # - JOY + # - NOSTALGIA + # - RELIEF # this is it + # remove_last_mood: + # type: string + # enum: + # - INTEREST + # - JOY + # add_mood_in_between: + # type: string + # enum: + # - INTEREST + # - RELIEF # this is it + # - JOY + # - NOSTALGIA + # rename_last_mood: + # type: string + # enum: + # - INTEREST + # - JOY + # - NOSTALGIA_2 + diff --git a/tests/specs/enum/fresh/pgsql/app/migrations_pgsql_db/m200000_000000_create_table_editcolumns.php b/tests/specs/enum/fresh/pgsql/app/migrations_pgsql_db/m200000_000000_create_table_editcolumns.php new file mode 100644 index 00000000..5d4a4340 --- /dev/null +++ b/tests/specs/enum/fresh/pgsql/app/migrations_pgsql_db/m200000_000000_create_table_editcolumns.php @@ -0,0 +1,23 @@ +execute('CREATE TYPE enum_connection AS ENUM(\'WIRED\', \'WIRELESS\')'); + $this->createTable('{{%editcolumns}}', [ + 'id' => $this->primaryKey(), + 'device' => $this->text()->null()->defaultValue(null), + 'connection' => 'enum_connection NOT NULL DEFAULT \'WIRED\'', + ]); + } + + public function safeDown() + { + $this->dropTable('{{%editcolumns}}'); + $this->execute('DROP TYPE enum_connection'); + } +} diff --git a/tests/specs/enum/fresh/pgsql/app/migrations_pgsql_db/m200000_000001_create_table_newcolumns.php b/tests/specs/enum/fresh/pgsql/app/migrations_pgsql_db/m200000_000001_create_table_newcolumns.php new file mode 100644 index 00000000..75c86ca3 --- /dev/null +++ b/tests/specs/enum/fresh/pgsql/app/migrations_pgsql_db/m200000_000001_create_table_newcolumns.php @@ -0,0 +1,22 @@ +execute('CREATE TYPE enum_new_column AS ENUM(\'ONE\', \'TWO\', \'THREE\')'); + $this->createTable('{{%newcolumns}}', [ + 'id' => $this->primaryKey(), + 'new_column' => 'enum_new_column NOT NULL DEFAULT \'ONE\'', + ]); + } + + public function safeDown() + { + $this->dropTable('{{%newcolumns}}'); + $this->execute('DROP TYPE enum_new_column'); + } +} diff --git a/tests/specs/enum/fresh/pgsql/app/migrations_pgsql_db/m200000_000002_create_table_pristines.php b/tests/specs/enum/fresh/pgsql/app/migrations_pgsql_db/m200000_000002_create_table_pristines.php new file mode 100644 index 00000000..57dbe3c2 --- /dev/null +++ b/tests/specs/enum/fresh/pgsql/app/migrations_pgsql_db/m200000_000002_create_table_pristines.php @@ -0,0 +1,22 @@ +execute('CREATE TYPE enum_device AS ENUM(\'MOBILE\', \'TV\', \'COMPUTER\')'); + $this->createTable('{{%pristines}}', [ + 'id' => $this->primaryKey(), + 'device' => 'enum_device NOT NULL DEFAULT \'TV\'', + ]); + } + + public function safeDown() + { + $this->dropTable('{{%pristines}}'); + $this->execute('DROP TYPE enum_device'); + } +} diff --git a/tests/specs/enum/new_column/maria/app/migrations_maria_db/m200000_000000_create_table_editcolumns.php b/tests/specs/enum/new_column/maria/app/migrations_maria_db/m200000_000000_create_table_editcolumns.php new file mode 100644 index 00000000..1778bc15 --- /dev/null +++ b/tests/specs/enum/new_column/maria/app/migrations_maria_db/m200000_000000_create_table_editcolumns.php @@ -0,0 +1,21 @@ +createTable('{{%editcolumns}}', [ + 'id' => $this->primaryKey(), + 'device' => $this->text()->null()->defaultValue(null), + 'connection' => 'enum("WIRED", "WIRELESS") NOT NULL DEFAULT \'WIRED\'', + ]); + } + + public function down() + { + $this->dropTable('{{%editcolumns}}'); + } +} diff --git a/tests/specs/enum/new_column/maria/app/migrations_maria_db/m200000_000001_change_table_newcolumns.php b/tests/specs/enum/new_column/maria/app/migrations_maria_db/m200000_000001_change_table_newcolumns.php new file mode 100644 index 00000000..4ef6a191 --- /dev/null +++ b/tests/specs/enum/new_column/maria/app/migrations_maria_db/m200000_000001_change_table_newcolumns.php @@ -0,0 +1,19 @@ +addColumn('{{%newcolumns}}', 'new_column', 'enum("ONE", "TWO", "THREE") NOT NULL DEFAULT \'ONE\''); + $this->dropColumn('{{%newcolumns}}', 'delete_col'); + } + + public function down() + { + $this->addColumn('{{%newcolumns}}', 'delete_col', 'enum("FOUR", "FIVE", "SIX") NULL DEFAULT NULL'); + $this->dropColumn('{{%newcolumns}}', 'new_column'); + } +} diff --git a/tests/specs/enum/new_column/maria/app/migrations_maria_db/m200000_000002_create_table_pristines.php b/tests/specs/enum/new_column/maria/app/migrations_maria_db/m200000_000002_create_table_pristines.php new file mode 100644 index 00000000..bdd46f98 --- /dev/null +++ b/tests/specs/enum/new_column/maria/app/migrations_maria_db/m200000_000002_create_table_pristines.php @@ -0,0 +1,20 @@ +createTable('{{%pristines}}', [ + 'id' => $this->primaryKey(), + 'device' => 'enum("MOBILE", "TV", "COMPUTER") NOT NULL DEFAULT \'TV\'', + ]); + } + + public function down() + { + $this->dropTable('{{%pristines}}'); + } +} diff --git a/tests/specs/enum/new_column/mysql/app/migrations_mysql_db/m200000_000000_create_table_editcolumns.php b/tests/specs/enum/new_column/mysql/app/migrations_mysql_db/m200000_000000_create_table_editcolumns.php new file mode 100644 index 00000000..78e27f4f --- /dev/null +++ b/tests/specs/enum/new_column/mysql/app/migrations_mysql_db/m200000_000000_create_table_editcolumns.php @@ -0,0 +1,21 @@ +createTable('{{%editcolumns}}', [ + 'id' => $this->primaryKey(), + 'device' => $this->text()->null(), + 'connection' => 'enum("WIRED", "WIRELESS") NOT NULL DEFAULT \'WIRED\'', + ]); + } + + public function down() + { + $this->dropTable('{{%editcolumns}}'); + } +} diff --git a/tests/specs/enum/new_column/mysql/app/migrations_mysql_db/m200000_000001_change_table_newcolumns.php b/tests/specs/enum/new_column/mysql/app/migrations_mysql_db/m200000_000001_change_table_newcolumns.php new file mode 100644 index 00000000..4ef6a191 --- /dev/null +++ b/tests/specs/enum/new_column/mysql/app/migrations_mysql_db/m200000_000001_change_table_newcolumns.php @@ -0,0 +1,19 @@ +addColumn('{{%newcolumns}}', 'new_column', 'enum("ONE", "TWO", "THREE") NOT NULL DEFAULT \'ONE\''); + $this->dropColumn('{{%newcolumns}}', 'delete_col'); + } + + public function down() + { + $this->addColumn('{{%newcolumns}}', 'delete_col', 'enum("FOUR", "FIVE", "SIX") NULL DEFAULT NULL'); + $this->dropColumn('{{%newcolumns}}', 'new_column'); + } +} diff --git a/tests/specs/enum/new_column/mysql/app/migrations_mysql_db/m200000_000002_create_table_pristines.php b/tests/specs/enum/new_column/mysql/app/migrations_mysql_db/m200000_000002_create_table_pristines.php new file mode 100644 index 00000000..bdd46f98 --- /dev/null +++ b/tests/specs/enum/new_column/mysql/app/migrations_mysql_db/m200000_000002_create_table_pristines.php @@ -0,0 +1,20 @@ +createTable('{{%pristines}}', [ + 'id' => $this->primaryKey(), + 'device' => 'enum("MOBILE", "TV", "COMPUTER") NOT NULL DEFAULT \'TV\'', + ]); + } + + public function down() + { + $this->dropTable('{{%pristines}}'); + } +} diff --git a/tests/specs/enum/new_column/pgsql/app/migrations_pgsql_db/m200000_000000_create_table_editcolumns.php b/tests/specs/enum/new_column/pgsql/app/migrations_pgsql_db/m200000_000000_create_table_editcolumns.php new file mode 100644 index 00000000..5d4a4340 --- /dev/null +++ b/tests/specs/enum/new_column/pgsql/app/migrations_pgsql_db/m200000_000000_create_table_editcolumns.php @@ -0,0 +1,23 @@ +execute('CREATE TYPE enum_connection AS ENUM(\'WIRED\', \'WIRELESS\')'); + $this->createTable('{{%editcolumns}}', [ + 'id' => $this->primaryKey(), + 'device' => $this->text()->null()->defaultValue(null), + 'connection' => 'enum_connection NOT NULL DEFAULT \'WIRED\'', + ]); + } + + public function safeDown() + { + $this->dropTable('{{%editcolumns}}'); + $this->execute('DROP TYPE enum_connection'); + } +} diff --git a/tests/specs/enum/new_column/pgsql/app/migrations_pgsql_db/m200000_000001_change_table_newcolumns.php b/tests/specs/enum/new_column/pgsql/app/migrations_pgsql_db/m200000_000001_change_table_newcolumns.php new file mode 100644 index 00000000..084a0be3 --- /dev/null +++ b/tests/specs/enum/new_column/pgsql/app/migrations_pgsql_db/m200000_000001_change_table_newcolumns.php @@ -0,0 +1,23 @@ +execute('CREATE TYPE enum_new_column AS ENUM(\'ONE\', \'TWO\', \'THREE\')'); + $this->addColumn('{{%newcolumns}}', 'new_column', 'enum_new_column NOT NULL DEFAULT \'ONE\''); + $this->dropColumn('{{%newcolumns}}', 'delete_col'); + $this->execute('DROP TYPE enum_delete_col'); + } + + public function safeDown() + { + $this->execute('CREATE TYPE enum_delete_col AS ENUM(\'FOUR\', \'FIVE\', \'SIX\')'); + $this->addColumn('{{%newcolumns}}', 'delete_col', 'enum_delete_col NULL DEFAULT NULL'); + $this->dropColumn('{{%newcolumns}}', 'new_column'); + $this->execute('DROP TYPE enum_new_column'); + } +} diff --git a/tests/specs/enum/new_column/pgsql/app/migrations_pgsql_db/m200000_000002_create_table_pristines.php b/tests/specs/enum/new_column/pgsql/app/migrations_pgsql_db/m200000_000002_create_table_pristines.php new file mode 100644 index 00000000..57dbe3c2 --- /dev/null +++ b/tests/specs/enum/new_column/pgsql/app/migrations_pgsql_db/m200000_000002_create_table_pristines.php @@ -0,0 +1,22 @@ +execute('CREATE TYPE enum_device AS ENUM(\'MOBILE\', \'TV\', \'COMPUTER\')'); + $this->createTable('{{%pristines}}', [ + 'id' => $this->primaryKey(), + 'device' => 'enum_device NOT NULL DEFAULT \'TV\'', + ]); + } + + public function safeDown() + { + $this->dropTable('{{%pristines}}'); + $this->execute('DROP TYPE enum_device'); + } +} diff --git a/tests/specs/postgres_custom.yaml b/tests/specs/postgres_custom.yaml index fce6664c..519af1ab 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')):search" + - "gin(to_tsvector('english', status)):search" required: - id properties: @@ -48,28 +48,28 @@ components: default: 0 json1: type: array - x-db-type: json + x-db-type: jsonb default: [] json2: type: array - x-db-type: json + x-db-type: jsonb default: '{}' json3: type: array - x-db-type: json + x-db-type: jsonb default: - foo: foobar - xxx: yyy json4: type: array - x-db-type: json + x-db-type: jsonb default: '{"foo": "bar", "bar": "baz"}' - # status: - # type: string - # default: draft - # enum: - # - active - # - draft + status: + type: string + default: draft + enum: + - active + - draft search: type: string x-db-type: tsvector diff --git a/tests/specs/postgres_custom/migrations/m200000_000000_create_table_v3_pgcustom.php b/tests/specs/postgres_custom/migrations/m200000_000000_create_table_v3_pgcustom.php index 6855df2a..fbf76227 100644 --- a/tests/specs/postgres_custom/migrations/m200000_000000_create_table_v3_pgcustom.php +++ b/tests/specs/postgres_custom/migrations/m200000_000000_create_table_v3_pgcustom.php @@ -14,9 +14,10 @@ public function up() 'json2' => 'json NOT NULL DEFAULT \'[]\'', 'json3' => 'json NOT NULL DEFAULT \'[{"foo":"foobar"},{"xxx":"yyy"}]\'', 'json4' => 'json NOT NULL DEFAULT \'{"foo":"bar","bar":"baz"}\'', + 'status' => 'enum(\'active\', \'draft\') NULL DEFAULT \'draft\'', 'search' => 'tsvector NULL', ]); - $this->createIndex('v3_pgcustom_search_gin_index', '{{%v3_pgcustom}}', 'search', 'gin(to_tsvector(\'english\'))'); + $this->createIndex('v3_pgcustom_search_gin_index', '{{%v3_pgcustom}}', 'search', 'gin(to_tsvector(\'english\', status))'); } public function down() 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 f0608474..c04adc88 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 @@ -15,7 +15,8 @@ public function safeUp() $this->alterColumn('{{%v3_pgcustom}}', 'json3', "SET DEFAULT '[{\"foo\":\"foobar\"},{\"xxx\":\"yyy\"}]'"); $this->alterColumn('{{%v3_pgcustom}}', 'json4', "SET NOT NULL"); $this->alterColumn('{{%v3_pgcustom}}', 'json4', "SET DEFAULT '{\"foo\":\"bar\",\"bar\":\"baz\"}'"); - $this->createIndex('v3_pgcustom_search_gin_index', '{{%v3_pgcustom}}', 'search', 'gin(to_tsvector(\'english\'))'); + $this->alterColumn('{{%v3_pgcustom}}', 'status', "SET DEFAULT 'draft'"); + $this->createIndex('v3_pgcustom_search_gin_index', '{{%v3_pgcustom}}', 'search', 'gin(to_tsvector(\'english\', status))'); } public function safeDown() @@ -29,5 +30,6 @@ public function safeDown() $this->alterColumn('{{%v3_pgcustom}}', 'json3', "SET DEFAULT '{\"bar\":\"baz\",\"foo\":\"bar\"}'"); $this->alterColumn('{{%v3_pgcustom}}', 'json4', "DROP NOT NULL"); $this->alterColumn('{{%v3_pgcustom}}', 'json4', "SET DEFAULT '{\"ffo\":\"bar\"}'"); + $this->alterColumn('{{%v3_pgcustom}}', 'status', "DROP DEFAULT"); } } diff --git a/tests/specs/postgres_custom/models/CustomFaker.php b/tests/specs/postgres_custom/models/CustomFaker.php index 373217df..6c7de598 100644 --- a/tests/specs/postgres_custom/models/CustomFaker.php +++ b/tests/specs/postgres_custom/models/CustomFaker.php @@ -35,6 +35,7 @@ public function generateModel($attributes = []) $model->json2 = []; $model->json3 = []; $model->json4 = []; + $model->status = $faker->randomElement(['active','draft']); if (!is_callable($attributes)) { $model->setAttributes($attributes, false); } else { diff --git a/tests/specs/postgres_custom/models/base/Custom.php b/tests/specs/postgres_custom/models/base/Custom.php index 9190b60a..e19f3700 100644 --- a/tests/specs/postgres_custom/models/base/Custom.php +++ b/tests/specs/postgres_custom/models/base/Custom.php @@ -11,6 +11,7 @@ * @property array $json2 * @property array $json3 * @property array $json4 + * @property string $status * @property string $search * */ @@ -24,7 +25,10 @@ public static function tableName() public function rules() { return [ + 'trim' => [['status'], 'trim'], 'num_integer' => [['num'], 'integer'], + 'status_string' => [['status'], 'string'], + 'status_in' => [['status'], 'in', 'range' => ['active', 'draft']], 'safe' => [['json1', 'json2', 'json3', 'json4'], 'safe'], ]; } diff --git a/tests/specs/x_db_type/edit_column/pgsql/app/migrations_pgsql_db/m200000_000001_change_table_editcolumns.php b/tests/specs/x_db_type/edit_column/pgsql/app/migrations_pgsql_db/m200000_000001_change_table_editcolumns.php index d412271c..79e81cd7 100644 --- a/tests/specs/x_db_type/edit_column/pgsql/app/migrations_pgsql_db/m200000_000001_change_table_editcolumns.php +++ b/tests/specs/x_db_type/edit_column/pgsql/app/migrations_pgsql_db/m200000_000001_change_table_editcolumns.php @@ -11,6 +11,7 @@ public function safeUp() $this->db->createCommand('ALTER TABLE {{%editcolumns}} ADD COLUMN json_col_def_n json NOT NULL DEFAULT \'[]\'')->execute(); $this->db->createCommand('ALTER TABLE {{%editcolumns}} ADD COLUMN json_col_def_n_2 json NOT NULL DEFAULT \'[]\'')->execute(); $this->db->createCommand('ALTER TABLE {{%editcolumns}} ADD COLUMN text_col_array text[] NULL DEFAULT NULL')->execute(); + $this->db->createCommand('ALTER TABLE {{%editcolumns}} ALTER COLUMN dec_col SET DATA TYPE decimal(12,2)')->execute(); $this->alterColumn('{{%editcolumns}}', 'dec_col', "SET DEFAULT 3.14"); $this->db->createCommand('ALTER TABLE {{%editcolumns}} ALTER COLUMN json_col SET DATA TYPE text')->execute(); $this->alterColumn('{{%editcolumns}}', 'json_col', "SET NOT NULL"); @@ -32,6 +33,7 @@ public function safeDown() $this->alterColumn('{{%editcolumns}}', 'numeric_col', 'int4 NULL USING "numeric_col"::int4'); $this->alterColumn('{{%editcolumns}}', 'name', $this->string(255)->notNull()); $this->alterColumn('{{%editcolumns}}', 'json_col', 'jsonb NULL USING "json_col"::jsonb'); + $this->alterColumn('{{%editcolumns}}', 'dec_col', $this->decimal()->null()); $this->dropColumn('{{%editcolumns}}', 'text_col_array'); $this->dropColumn('{{%editcolumns}}', 'json_col_def_n_2'); $this->dropColumn('{{%editcolumns}}', 'json_col_def_n'); diff --git a/tests/specs/x_db_type/fresh/pgsql/app/migrations_pgsql_db/m200000_000001_create_table_editcolumns.php b/tests/specs/x_db_type/fresh/pgsql/app/migrations_pgsql_db/m200000_000001_create_table_editcolumns.php index 93111403..cf34df76 100644 --- a/tests/specs/x_db_type/fresh/pgsql/app/migrations_pgsql_db/m200000_000001_create_table_editcolumns.php +++ b/tests/specs/x_db_type/fresh/pgsql/app/migrations_pgsql_db/m200000_000001_create_table_editcolumns.php @@ -16,7 +16,7 @@ public function safeUp() 2 => 'dec_col decimal(12,2) NULL DEFAULT 3.14', 3 => 'str_col_def varchar NOT NULL', 4 => 'json_col text NOT NULL DEFAULT \'fox jumps over dog\'', - 5 => 'json_col_2 json NOT NULL DEFAULT \'[]\'', + 5 => 'json_col_2 jsonb NOT NULL DEFAULT \'[]\'', 6 => 'numeric_col double precision NULL DEFAULT NULL', 7 => 'json_col_def_n json NOT NULL DEFAULT \'[]\'', 8 => 'json_col_def_n_2 json NOT NULL DEFAULT \'[]\'', diff --git a/tests/specs/x_db_type/fresh/pgsql/x_db_type_pgsql.yaml b/tests/specs/x_db_type/fresh/pgsql/x_db_type_pgsql.yaml index b472ecc3..692a9831 100644 --- a/tests/specs/x_db_type/fresh/pgsql/x_db_type_pgsql.yaml +++ b/tests/specs/x_db_type/fresh/pgsql/x_db_type_pgsql.yaml @@ -505,7 +505,7 @@ components: default: fox jumps over dog json_col_2: type: string - x-db-type: json + x-db-type: jsonb nullable: false default: [] numeric_col: diff --git a/tests/specs/x_db_type/new_column/pgsql/app/migrations_pgsql_db/m200000_000001_create_table_editcolumns.php b/tests/specs/x_db_type/new_column/pgsql/app/migrations_pgsql_db/m200000_000001_create_table_editcolumns.php index 93111403..cf34df76 100644 --- a/tests/specs/x_db_type/new_column/pgsql/app/migrations_pgsql_db/m200000_000001_create_table_editcolumns.php +++ b/tests/specs/x_db_type/new_column/pgsql/app/migrations_pgsql_db/m200000_000001_create_table_editcolumns.php @@ -16,7 +16,7 @@ public function safeUp() 2 => 'dec_col decimal(12,2) NULL DEFAULT 3.14', 3 => 'str_col_def varchar NOT NULL', 4 => 'json_col text NOT NULL DEFAULT \'fox jumps over dog\'', - 5 => 'json_col_2 json NOT NULL DEFAULT \'[]\'', + 5 => 'json_col_2 jsonb NOT NULL DEFAULT \'[]\'', 6 => 'numeric_col double precision NULL DEFAULT NULL', 7 => 'json_col_def_n json NOT NULL DEFAULT \'[]\'', 8 => 'json_col_def_n_2 json NOT NULL DEFAULT \'[]\'', diff --git a/tests/unit/EnumTest.php b/tests/unit/EnumTest.php new file mode 100644 index 00000000..247ee344 --- /dev/null +++ b/tests/unit/EnumTest.php @@ -0,0 +1,264 @@ +deleteTables(); + $testFile = Yii::getAlias("@specs/enum/fresh/mysql/enum.php"); + $this->runGenerator($testFile, 'mysql'); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + 'except' => ['migrations_maria_db', 'migrations_pgsql_db'] + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/enum/fresh/mysql/app"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + + $this->changeDbToMariadb(); + $this->deleteTables(); + $testFile = Yii::getAlias("@specs/enum/fresh/mysql/enum.php"); + $this->runGenerator($testFile, 'maria'); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + 'except' => ['migrations_mysql_db', 'migrations_pgsql_db'] + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/enum/fresh/maria/app"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + + $this->changeDbToPgsql(); + $this->deleteTables(); + $testFile = Yii::getAlias("@specs/enum/fresh/mysql/enum.php"); + $this->runGenerator($testFile, 'pgsql'); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + 'except' => ['migrations_mysql_db', 'migrations_maria_db'] + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/enum/fresh/pgsql/app"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + } + + public function testAddNewColumn() // and drop enum column + { + // MySQL + $this->deleteTables(); + $this->createTableForNewEnumColumn(); + $testFile = Yii::getAlias("@specs/enum/fresh/mysql/enum.php"); + $this->runGenerator($testFile, 'mysql'); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + 'except' => ['migrations_maria_db', 'migrations_pgsql_db'] + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/enum/new_column/mysql/app"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + + // Mariadb + $this->changeDbToMariadb(); + $this->deleteTables(); + $this->createTableForNewEnumColumn(); + $testFile = Yii::getAlias("@specs/enum/fresh/mysql/enum.php"); + $this->runGenerator($testFile, 'maria'); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + 'except' => ['migrations_mysql_db', 'migrations_pgsql_db'] + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/enum/new_column/maria/app"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + + // Pgsql + $this->changeDbToPgsql(); + $this->deleteTables(); + $this->createTableForNewEnumColumn(); + $testFile = Yii::getAlias("@specs/enum/fresh/mysql/enum.php"); + $this->runGenerator($testFile, 'pgsql'); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + 'except' => ['migrations_mysql_db', 'migrations_maria_db'] + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/enum/new_column/pgsql/app"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + } + + public function testChangeToAndFromEnum() // edit enum to string and vice versa + { + $this->deleteTables(); + $this->createTableForEditEnumToString(); + $testFile = Yii::getAlias("@specs/enum/fresh/mysql/enum.php"); + $this->runGenerator($testFile, 'mysql'); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + 'except' => ['migrations_maria_db', 'migrations_pgsql_db'] + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/enum/change/mysql/app"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + + // Mariadb + $this->changeDbToMariadb(); + $this->deleteTables(); + $this->createTableForEditEnumToString(); + $testFile = Yii::getAlias("@specs/enum/fresh/mysql/enum.php"); + $this->runGenerator($testFile, 'maria'); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + 'except' => ['migrations_mysql_db', 'migrations_pgsql_db'] + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/enum/change/maria/app"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + + + $this->changeDbToPgsql(); + $this->deleteTables(); + $this->createTableForEditEnumToString(); + $testFile = Yii::getAlias("@specs/enum/fresh/mysql/enum.php"); + $this->runGenerator($testFile, 'pgsql'); + $actualFiles = FileHelper::findFiles(Yii::getAlias('@app'), [ + 'recursive' => true, + 'except' => ['migrations_mysql_db', 'migrations_maria_db'] + ]); + $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/enum/change/pgsql/app"), [ + 'recursive' => true, + ]); + $this->checkFiles($actualFiles, $expectedFiles); + } + + // TODO ENH enum change is more work than just changing the eunm values. And for PgSQL it is even more + // public function testEnumValuesChange() + // { + // $this->deleteTables(); + // $this->createTableForEnumValueChange(); + // $testFile = Yii::getAlias("@specs/enum/fresh/mysql/enum.php"); + // $this->runGenerator($testFile, 'mysql'); + + + // $this->changeDbToMariadb(); + // $this->deleteTables(); + // $this->createTableForEnumValueChange(); + // $testFile = Yii::getAlias("@specs/enum/fresh/mysql/enum.php"); + // $this->runGenerator($testFile, 'maria'); + + + // $this->changeDbToPgsql(); + // $this->deleteTables(); + // $this->createTableForEnumValueChange(); + // $testFile = Yii::getAlias("@specs/enum/fresh/mysql/enum.php"); + // $this->runGenerator($testFile, 'pgsql'); + // } + + // public function testStringToEnum() + // { + // $this->deleteTables(); + // $this->createTableForEditEnumToString(); + // $testFile = Yii::getAlias("@specs/enum/fresh/mysql/enum.php"); + // $this->runGenerator($testFile, 'mysql'); + // } + + // public function testChangeEnumValues() + // { + // // TODO + // // add a value to list + // // fix a typo in a enum value present in existing list + // // remove a value from list + // } + + private function deleteTables() + { + if (ApiGenerator::isPostgres()) { + Yii::$app->db->createCommand('DROP TYPE IF EXISTS enum_device CASCADE')->execute(); + Yii::$app->db->createCommand('DROP TYPE IF EXISTS enum_connection CASCADE')->execute(); + Yii::$app->db->createCommand('DROP TYPE IF EXISTS enum_new_column CASCADE')->execute(); + Yii::$app->db->createCommand('DROP TYPE IF EXISTS enum_delete_col CASCADE')->execute(); + Yii::$app->db->createCommand('DROP TYPE IF EXISTS enum_add_one_mood_at_last CASCADE')->execute(); + } + Yii::$app->db->createCommand('DROP TABLE IF EXISTS {{%pristines}}')->execute(); + Yii::$app->db->createCommand('DROP TABLE IF EXISTS {{%newcolumns}}')->execute(); + Yii::$app->db->createCommand('DROP TABLE IF EXISTS {{%editcolumns}}')->execute(); + Yii::$app->db->createCommand('DROP TABLE IF EXISTS {{%alldbdatatypes}}')->execute(); + Yii::$app->db->createCommand('DROP TABLE IF EXISTS {{%enumvaluechanges}}')->execute(); + } + + private function createTableForEditEnumToString() // and vice versa + { + if (ApiGenerator::isPostgres()) { + Yii::$app->db->createCommand('CREATE TYPE enum_device AS ENUM(\'MOBILE\', \'TV\', \'COMPUTER\')')->execute(); + Yii::$app->db->createCommand()->createTable('{{%editcolumns}}', [ + 'id' => 'pk', + 'device' => 'enum_device NOT NULL DEFAULT \'TV\'', + 'connection' => 'string' + ])->execute(); + return; + } + Yii::$app->db->createCommand()->createTable('{{%editcolumns}}', [ + 'id' => 'pk', + 'device' => 'enum("MOBILE", "TV", "COMPUTER") NOT NULL DEFAULT \'TV\'', + 'connection' => 'string' + ])->execute(); + } + + private function createTableForNewEnumColumn() + { + if (ApiGenerator::isPostgres()) { + Yii::$app->db->createCommand('CREATE TYPE enum_delete_col AS ENUM(\'FOUR\', \'FIVE\', \'SIX\')')->execute(); + Yii::$app->db->createCommand()->createTable('{{%newcolumns}}', [ + 'id' => 'pk', + 'delete_col' => 'enum_delete_col' + ])->execute(); + return; + } + + Yii::$app->db->createCommand()->createTable('{{%newcolumns}}', [ + 'id' => 'pk', + 'delete_col' => 'enum("FOUR", "FIVE", "SIX")' + ])->execute(); + } + + // private function createTableForEnumValueChange() + // { + // // removing a enum value is directly not supported in PgSQL + // if (ApiGenerator::isPostgres()) { + // Yii::$app->db->createCommand('CREATE TYPE enum_add_one_mood_at_last AS ENUM(\'INTEREST\', \'JOY\', \'NOSTALGIA\')')->execute(); + // Yii::$app->db->createCommand()->createTable('{{%enumvaluechanges}}', [ + // 'id' => 'pk', + // 'add_one_mood_at_last' => 'enum_add_one_mood_at_last' + // ])->execute(); + // return; + // } + + // Yii::$app->db->createCommand()->createTable('{{%enumvaluechanges}}', [ + // 'id' => 'pk', + // 'add_one_mood_at_last' => 'enum("INTEREST", "JOY", "NOSTALGIA")', + // 'remove_last_mood' => 'enum("INTEREST", "JOY", "NOSTALGIA")', + // 'add_mood_in_between' => 'enum("INTEREST", "JOY", "NOSTALGIA")', + // 'rename_last_mood' => 'enum("INTEREST", "JOY", "NOSTALGIA")', + // ])->execute(); + // } +} diff --git a/tests/unit/PropertySchemaTest.php b/tests/unit/PropertySchemaTest.php index 417d91fd..68b6e07d 100644 --- a/tests/unit/PropertySchemaTest.php +++ b/tests/unit/PropertySchemaTest.php @@ -26,6 +26,7 @@ public function testPkProperty() self::assertEquals(128, $prop->getMaxLength()); self::assertEquals(null, $prop->getMinLength()); self::assertEquals(true, $prop->isReadonly()); + self::assertFalse($prop->hasEnum()); } public function testSimpleProperty() diff --git a/tests/unit/ValidatorRulesBuilderTest.php b/tests/unit/ValidatorRulesBuilderTest.php index 86e4d832..dbad43b9 100644 --- a/tests/unit/ValidatorRulesBuilderTest.php +++ b/tests/unit/ValidatorRulesBuilderTest.php @@ -28,6 +28,7 @@ public function testBuild() (new Attribute('active'))->setPhpType('bool')->setDbType('boolean'), (new Attribute('category'))->asReference('Category') ->setRequired(true)->setPhpType('int')->setDbType('integer'), + (new Attribute('state'))->setPhpType('string')->setDbType('string')->setEnumValues(['active', 'draft']), (new Attribute('created_at'))->setPhpType('string')->setDbType('datetime'), (new Attribute('contact_email'))->setPhpType('string')->setDbType('string'), (new Attribute('required_with_def'))->setPhpType('string') @@ -41,6 +42,7 @@ public function testBuild() 'trim' => new ValidationRule([ 'title', 'article', + 'state', 'created_at', 'contact_email', 'required_with_def', @@ -55,6 +57,8 @@ public function testBuild() 'title_string' => new ValidationRule(['title'], 'string', ['max' => 60]), 'article_string' => new ValidationRule(['article'], 'string'), 'active_boolean' => new ValidationRule(['active'], 'boolean'), + 'state_string' => new ValidationRule(['state'], 'string'), + 'state_in' => new ValidationRule(['state'], 'in', ['range' => ['active', 'draft']]), 'created_at_datetime' => new ValidationRule(['created_at'], 'datetime'), 'contact_email_string' => new ValidationRule(['contact_email'], 'string'), 'contact_email_email' => new ValidationRule(['contact_email'], 'email'), diff --git a/tests/unit/XDbTypeTest.php b/tests/unit/XDbTypeTest.php index 223a782b..7f492c22 100644 --- a/tests/unit/XDbTypeTest.php +++ b/tests/unit/XDbTypeTest.php @@ -28,7 +28,7 @@ public function testXDbTypeFresh() $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/x_db_type/fresh/mysql/app"), [ 'recursive' => true, ]); - $this->compareFiles($actualFiles, $expectedFiles); + $this->checkFiles($actualFiles, $expectedFiles); // same yaml file is used for MySQL and MariaDB ---------------------- $this->changeDbToMariadb(); @@ -42,7 +42,7 @@ public function testXDbTypeFresh() $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/x_db_type/fresh/maria/app"), [ 'recursive' => true, ]); - $this->compareFiles($actualFiles, $expectedFiles); + $this->checkFiles($actualFiles, $expectedFiles); // PgSQL ------------------------------------------------ $this->changeDbToPgsql(); @@ -56,7 +56,7 @@ public function testXDbTypeFresh() $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/x_db_type/fresh/pgsql/app"), [ 'recursive' => true, ]); - $this->compareFiles($actualFiles, $expectedFiles); + $this->checkFiles($actualFiles, $expectedFiles); } public function testXDbTypeSecondaryWithNewColumn() // v2 @@ -73,7 +73,7 @@ public function testXDbTypeSecondaryWithNewColumn() // v2 $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/x_db_type/new_column/mysql/app"), [ 'recursive' => true, ]); - $this->compareFiles($actualFiles, $expectedFiles); + $this->checkFiles($actualFiles, $expectedFiles); // same yaml file is used for MySQL and MariaDB ---------------------- $this->changeDbToMariadb(); @@ -89,7 +89,7 @@ public function testXDbTypeSecondaryWithNewColumn() // v2 $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/x_db_type/new_column/maria/app"), [ 'recursive' => true, ]); - $this->compareFiles($actualFiles, $expectedFiles); + $this->checkFiles($actualFiles, $expectedFiles); // PgSQL ------------------------------------------------ $this->changeDbToPgsql(); @@ -105,7 +105,7 @@ public function testXDbTypeSecondaryWithNewColumn() // v2 $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/x_db_type/new_column/pgsql/app"), [ 'recursive' => true, ]); - $this->compareFiles($actualFiles, $expectedFiles); + $this->checkFiles($actualFiles, $expectedFiles); } public function testXDbTypeSecondaryWithEditColumn() // v3 @@ -122,7 +122,7 @@ public function testXDbTypeSecondaryWithEditColumn() // v3 $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/x_db_type/edit_column/mysql/app"), [ 'recursive' => true, ]); - $this->compareFiles($actualFiles, $expectedFiles); + $this->checkFiles($actualFiles, $expectedFiles); // same yaml file is used for MySQL and MariaDB ---------------------- $this->changeDbToMariadb(); @@ -138,7 +138,7 @@ public function testXDbTypeSecondaryWithEditColumn() // v3 $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/x_db_type/edit_column/maria/app"), [ 'recursive' => true, ]); - $this->compareFiles($actualFiles, $expectedFiles); + $this->checkFiles($actualFiles, $expectedFiles); // PgSQL ------------------------------------------------ $this->changeDbToPgsql(); @@ -154,22 +154,7 @@ public function testXDbTypeSecondaryWithEditColumn() // v3 $expectedFiles = FileHelper::findFiles(Yii::getAlias("@specs/x_db_type/edit_column/pgsql/app"), [ 'recursive' => true, ]); - $this->compareFiles($actualFiles, $expectedFiles); - } - - protected function compareFiles(array $actual, array $expected) - { - self::assertEquals( - count($actual), - count($expected) - ); - foreach ($actual as $index => $file) { - $expectedFilePath = $expected[$index]; - self::assertFileExists($file); - self::assertFileExists($expectedFilePath); - - $this->assertFileEquals($expectedFilePath, $file, "Failed asserting that file contents of\n$file\nare equal to file contents of\n$expectedFilePath"); - } + $this->checkFiles($actualFiles, $expectedFiles); } private function deleteTables() @@ -197,7 +182,7 @@ private function createTableForEditColumns() 'string_col' => 'string not null', 'dec_col' => 'decimal(12, 4)', 'str_col_def' => 'string default \'hi there\'', - 'json_col' => 'json', + 'json_col' => 'json', // json is jsonb in Pgsql via Yii Pgsql Schema 'json_col_2' => 'json', 'numeric_col' => 'integer', ])->execute();