Skip to content
This repository was archived by the owner on Jun 4, 2024. It is now read-only.

Do not generate ENUM types on postgres if x-db-type is specified for the enum column #174

Merged
merged 3 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 12 additions & 19 deletions src/lib/ColumnToCode.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ public function getCode(bool $quoted = false):string
$default = '';
} elseif (ApiGenerator::isPostgres() && $this->isEnum()) {
$default =
$this->rawParts['default'] !== null ? ' DEFAULT ' . self::escapeQuotes(trim($this->rawParts['default'])) : '';
$this->rawParts['default'] !== null ? ' DEFAULT ' . trim($this->rawParts['default']) : '';
} else {
$default = $this->rawParts['default'] !== null ? ' DEFAULT ' . trim($this->rawParts['default']) : '';
}
Expand All @@ -178,13 +178,10 @@ public function getCode(bool $quoted = false):string
if ((ApiGenerator::isMysql() || ApiGenerator::isMariaDb()) && $this->rawParts['position']) {
$code .= ' ' . $this->rawParts['position'];
}
if ((ApiGenerator::isMysql() || ApiGenerator::isMariaDb()) && $this->isEnum()) {
return $quoted ? "'" . $code . "'" : $code;
}
if (ApiGenerator::isPostgres() && $this->alterByXDbType) {
return $quoted ? "'" . $this->rawParts['type'] . "'" : $this->rawParts['type'];
return $quoted ? VarDumper::export($this->rawParts['type']) : $this->rawParts['type'];
}
return $quoted ? "'" . $code . "'" : $code;
return $quoted ? VarDumper::export($code) : $code;
}

public function getAlterExpression(bool $addUsingExpression = false):string
Expand Down Expand Up @@ -226,7 +223,7 @@ public function isJson():bool

public function isEnum():bool
{
return !empty($this->column->enumValues);
return BaseMigrationBuilder::isEnum($this->column);
}

public function isDecimal()
Expand Down Expand Up @@ -313,14 +310,14 @@ public static function mysqlEnumToString(array $enum):string
private function defaultValueJson(array $value):string
{
if ($this->alter === true) {
return "'" . str_replace('"', '\"', Json::encode($value)). "'";
return "'" . str_replace('"', '\"', Json::encode($value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_QUOT)) . "'";
}
return "\\'" . new Expression(Json::encode($value)) . "\\'";
return "'" . Json::encode($value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_QUOT) . "'";
}

private function defaultValueArray(array $value):string
{
return "'{" . str_replace('"', "\"", trim(Json::encode($value), '[]')) . "}'";
return "'{" . trim(Json::encode($value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_QUOT), '[]') . "}'";
}

private function resolve():void
Expand Down Expand Up @@ -442,10 +439,10 @@ private function resolveDefaultValue():void
break;
case 'object':
if ($value instanceof JsonExpression) {
$this->fluentParts['default'] = "defaultValue('" . Json::encode($value->getValue()) . "')";
$this->fluentParts['default'] = "defaultValue('" . Json::encode($value->getValue(), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_QUOT) . "')";
$this->rawParts['default'] = $this->defaultValueJson($value->getValue());
} elseif ($value instanceof ArrayExpression) {
$this->fluentParts['default'] = "defaultValue('" . Json::encode($value->getValue()) . "')";
$this->fluentParts['default'] = "defaultValue('" . Json::encode($value->getValue(), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_QUOT) . "')";
$this->rawParts['default'] = $this->defaultValueArray($value->getValue());
} else {
// $value instanceof \yii\db\Expression
Expand All @@ -454,19 +451,15 @@ private function resolveDefaultValue():void
}
break;
case 'array':
$this->fluentParts['default'] = "defaultValue('" . Json::encode($value) . "')";
$this->fluentParts['default'] = "defaultValue('" . Json::encode($value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_QUOT) . "')";
$this->rawParts['default'] = $this->isJson()
? $this->defaultValueJson($value)
: $this->defaultValueArray($value);
break;
default:
$this->fluentParts['default'] = $expectInteger
? 'defaultValue(' . $value . ')' : 'defaultValue("' . self::escapeQuotes((string)$value) . '")';
$this->rawParts['default'] = $expectInteger ? $value : self::wrapQuotes($value);

if ((ApiGenerator::isMysql() || ApiGenerator::isMariaDb()) && $this->isEnum()) {
$this->rawParts['default'] = self::escapeQuotes($this->rawParts['default']);
}
? 'defaultValue(' . $value . ')' : 'defaultValue(' . VarDumper::export((string)$value) . ')';
$this->rawParts['default'] = $expectInteger ? $value : VarDumper::export((string)$value);
}
}

Expand Down
5 changes: 1 addition & 4 deletions src/lib/migrations/BaseMigrationBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -479,10 +479,7 @@ public function newColStr(string $tableAlias, \cebe\yii2openapi\db\ColumnSchema

public static function isEnum(\yii\db\ColumnSchema $columnSchema): bool
{
if (!empty($columnSchema->enumValues) && is_array($columnSchema->enumValues)) {
return true;
}
return false;
return !empty($columnSchema->enumValues) && is_array($columnSchema->enumValues) && empty($columnSchema->xDbType);
}

public static function isEnumValuesChanged(
Expand Down
8 changes: 4 additions & 4 deletions src/lib/migrations/MigrationRecordBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public function addColumn(string $tableAlias, ColumnSchema $column, ?string $pos
if (is_string($column->xDbType) && !empty($column->xDbType)) {
$converter = $this->columnToCode($tableAlias, $column, false, false, false, false, $position);
$name = static::quote($column->name);
return sprintf(self::ADD_COLUMN_RAW, $tableAlias, $name, $converter->getCode());
return sprintf(self::ADD_COLUMN_RAW, $tableAlias, $name, ColumnToCode::escapeQuotes($converter->getCode()));
}

$converter = $this->columnToCode($tableAlias, $column, false, false, false, false, $position);
Expand All @@ -103,7 +103,7 @@ public function addDbColumn(string $tableAlias, ColumnSchema $column, ?string $p
if (property_exists($column, 'xDbType') && is_string($column->xDbType) && !empty($column->xDbType)) {
$converter = $this->columnToCode($tableAlias, $column, true, false, false, false, $position);
$name = static::quote($column->name);
return sprintf(self::ADD_COLUMN_RAW, $tableAlias, $column->name, $converter->getCode());
return sprintf(self::ADD_COLUMN_RAW, $tableAlias, $column->name, ColumnToCode::escapeQuotes($converter->getCode()));
}
$converter = $this->columnToCode($tableAlias, $column, true, false, false, false, $position);
return sprintf(self::ADD_COLUMN, $tableAlias, $column->name, $converter->getCode(true));
Expand All @@ -120,7 +120,7 @@ public function alterColumn(string $tableAlias, ColumnSchema $column):string
ApiGenerator::isPostgres() ? self::ALTER_COLUMN_RAW_PGSQL : self::ALTER_COLUMN_RAW,
$tableAlias,
$column->name,
$converter->getCode()
ColumnToCode::escapeQuotes($converter->getCode())
);
}
$converter = $this->columnToCode($tableAlias, $column, true);
Expand Down Expand Up @@ -340,7 +340,7 @@ public static function makeString(array $codeColumns): string
}
}

$codeColumns = str_replace([PHP_EOL, "\\\'"], [PHP_EOL . self::INDENT.' ', "'"], $finalStr);
$codeColumns = str_replace([PHP_EOL], [PHP_EOL . self::INDENT.' '], $finalStr);
$codeColumns = trim($codeColumns);
$codeColumns = '['.PHP_EOL.self::INDENT.' '.$codeColumns.PHP_EOL . self::INDENT.']';
return $codeColumns;
Expand Down
4 changes: 4 additions & 0 deletions src/lib/migrations/PostgresMigrationBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ protected function createEnumMigrations():void
$tableAlias = $this->model->getTableAlias();
$enums = $this->model->getEnumAttributes();
foreach ($enums as $attr) {
if (!empty($attr->xDbType)) {
// do not generate enum types when custom x-db-type is used
continue;
}
$this->migration
->addUpCode($this->recordBuilder->createEnum($tableAlias, $attr->columnName, $attr->enumValues), true)
->addDownCode($this->recordBuilder->dropEnum($tableAlias, $attr->columnName), true);
Expand Down
1 change: 1 addition & 0 deletions tests/migrations/m100000_000000_pgsql.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public function safeUp()
'json3' => $this->json()->defaultValue(Json::encode(['foo' => 'bar', 'bar' => 'baz'])),
'json4' => "json DEFAULT '" . new Expression(Json::encode(['ffo' => 'bar'])) . "'",
'status' => '"'.$enumTypeName.'"',
'status_x' => 'varchar(10)',
'search' => 'tsvector'
]);
$columns = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public function up()
'username' => $this->string(200)->notNull(),
'email' => $this->string(200)->notNull(),
'password' => $this->string()->notNull(),
'role' => $this->string(20)->null()->defaultValue("reader"),
'role' => $this->string(20)->null()->defaultValue('reader'),
'flags' => $this->integer()->null()->defaultValue(0),
'created_at' => $this->timestamp()->null()->defaultExpression("(CURRENT_TIMESTAMP)"),
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public function up()
'username' => $this->string(200)->notNull(),
'email' => $this->string(200)->notNull(),
'password' => $this->string()->notNull(),
'role' => $this->string(20)->null()->defaultValue("reader"),
'role' => $this->string(20)->null()->defaultValue('reader'),
'flags' => $this->integer()->null()->defaultValue(0),
'created_at' => $this->timestamp()->null()->defaultExpression("(CURRENT_TIMESTAMP)"),
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public function up()
'username' => $this->string(200)->notNull(),
'email' => $this->string(200)->notNull(),
'password' => $this->string()->notNull(),
'role' => $this->string(20)->null()->defaultValue("reader"),
'role' => $this->string(20)->null()->defaultValue('reader'),
'flags' => $this->integer()->null()->defaultValue(0),
'created_at' => $this->timestamp()->null()->defaultExpression("(CURRENT_TIMESTAMP)"),
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public function safeUp()
'username' => $this->string(200)->notNull(),
'email' => $this->string(200)->notNull(),
'password' => $this->string()->notNull(),
'role' => $this->string(20)->null()->defaultValue("reader"),
'role' => $this->string(20)->null()->defaultValue('reader'),
'flags' => $this->integer()->null()->defaultValue(0),
'created_at' => $this->timestamp()->null()->defaultExpression("(CURRENT_TIMESTAMP)"),
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public function up()
'post_id' => $this->bigInteger()->notNull(),
'user_id' => $this->bigInteger()->null()->defaultValue(null),
'message' => $this->text()->notNull(),
'meta_data' => $this->string(300)->null()->defaultValue(""),
'meta_data' => $this->string(300)->null()->defaultValue(''),
'created_at' => $this->timestamp()->notNull(),
]);
$this->addForeignKey('fk_v2_comments_post_id_v2_posts_id', '{{%v2_comments}}', 'post_id', '{{%v2_posts}}', 'id');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function down()
$this->dropIndex('v2_users_login_key', '{{%v2_users}}');
$this->createIndex('v2_users_username_key', '{{%v2_users}}', 'username', true);
$this->alterColumn('{{%v2_users}}', 'created_at', $this->timestamp()->null()->defaultExpression("current_timestamp()"));
$this->alterColumn('{{%v2_users}}', 'role', $this->string(20)->null()->defaultValue("reader"));
$this->alterColumn('{{%v2_users}}', 'role', $this->string(20)->null()->defaultValue('reader'));
$this->alterColumn('{{%v2_users}}', 'email', $this->string(200)->notNull());
$this->addColumn('{{%v2_users}}', 'username', $this->string(200)->notNull());
$this->dropColumn('{{%v2_users}}', 'login');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public function up()
$this->addColumn('{{%v2_comments}}', 'user_id', $this->bigInteger()->null()->defaultValue(null)->after('post_id'));
$this->dropColumn('{{%v2_comments}}', 'author_id');
$this->alterColumn('{{%v2_comments}}', 'message', $this->text()->notNull());
$this->alterColumn('{{%v2_comments}}', 'meta_data', $this->string(300)->null()->defaultValue(""));
$this->alterColumn('{{%v2_comments}}', 'meta_data', $this->string(300)->null()->defaultValue(''));
$this->alterColumn('{{%v2_comments}}', 'created_at', $this->timestamp()->notNull());
$this->addForeignKey('fk_v2_comments_post_id_v2_posts_id', '{{%v2_comments}}', 'post_id', '{{%v2_posts}}', 'id');
$this->addForeignKey('fk_v2_comments_user_id_v2_users_id', '{{%v2_comments}}', 'user_id', '{{%v2_users}}', 'id');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function down()
$this->dropIndex('v2_users_login_key', '{{%v2_users}}');
$this->createIndex('v2_users_username_key', '{{%v2_users}}', 'username', true);
$this->alterColumn('{{%v2_users}}', 'created_at', $this->timestamp()->null()->defaultExpression("CURRENT_TIMESTAMP"));
$this->alterColumn('{{%v2_users}}', 'role', $this->string(20)->null()->defaultValue("reader"));
$this->alterColumn('{{%v2_users}}', 'role', $this->string(20)->null()->defaultValue('reader'));
$this->alterColumn('{{%v2_users}}', 'email', $this->string(200)->notNull());
$this->addColumn('{{%v2_users}}', 'username', $this->string(200)->notNull());
$this->dropColumn('{{%v2_users}}', 'login');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public function up()
$this->addColumn('{{%v2_comments}}', 'user_id', $this->bigInteger()->null()->defaultValue(null)->after('post_id'));
$this->dropColumn('{{%v2_comments}}', 'author_id');
$this->alterColumn('{{%v2_comments}}', 'message', $this->text()->notNull());
$this->alterColumn('{{%v2_comments}}', 'meta_data', $this->string(300)->null()->defaultValue(""));
$this->alterColumn('{{%v2_comments}}', 'meta_data', $this->string(300)->null()->defaultValue(''));
$this->alterColumn('{{%v2_comments}}', 'created_at', $this->timestamp()->notNull());
$this->addForeignKey('fk_v2_comments_post_id_v2_posts_id', '{{%v2_comments}}', 'post_id', '{{%v2_posts}}', 'id');
$this->addForeignKey('fk_v2_comments_user_id_v2_users_id', '{{%v2_comments}}', 'user_id', '{{%v2_users}}', 'id');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public function up()
$this->createTable('{{%newcolumns}}', [
'id' => $this->primaryKey(),
'new_column' => 'enum("ONE", "TWO", "THREE") NOT NULL DEFAULT \'ONE\'',
0 => 'new_column_x varchar(10) NOT NULL DEFAULT \'ONE\'',
]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public function up()
$this->createTable('{{%newcolumns}}', [
'id' => $this->primaryKey(),
'new_column' => 'enum("ONE", "TWO", "THREE") NOT NULL DEFAULT \'ONE\'',
0 => 'new_column_x varchar(10) NOT NULL DEFAULT \'ONE\'',
]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public function safeUp()
$this->createTable('{{%newcolumns}}', [
'id' => $this->primaryKey(),
'new_column' => '"enum_itt_newcolumns_new_column" NOT NULL DEFAULT \'ONE\'',
0 => '"new_column_x" varchar(10) NOT NULL DEFAULT \'ONE\'',
]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public function up()
$this->createTable('{{%newcolumns}}', [
'id' => $this->primaryKey(),
'new_column' => 'enum("ONE", "TWO", "THREE") NOT NULL DEFAULT \'ONE\'',
0 => 'new_column_x varchar(10) NOT NULL DEFAULT \'ONE\'',
]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public function up()
$this->createTable('{{%newcolumns}}', [
'id' => $this->primaryKey(),
'new_column' => 'enum("ONE", "TWO", "THREE") NOT NULL DEFAULT \'ONE\'',
0 => 'new_column_x varchar(10) NOT NULL DEFAULT \'ONE\'',
]);
}

Expand Down
10 changes: 10 additions & 0 deletions tests/specs/enum/fresh/mysql/enum.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ components:
default:
ONE
nullable: false
new_column_x:
type: string
enum:
- ONE
- TWO
- THREE
default:
ONE
x-db-type: varchar(10)
nullable: false

Editcolumn:
type: object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public function safeUp()
$this->createTable('{{%newcolumns}}', [
'id' => $this->primaryKey(),
'new_column' => '"enum_itt_newcolumns_new_column" NOT NULL DEFAULT \'ONE\'',
0 => '"new_column_x" varchar(10) NOT NULL DEFAULT \'ONE\'',
]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ class m200000_000001_change_table_newcolumns extends \yii\db\Migration
{
public function up()
{
$this->addColumn('{{%newcolumns}}', 'new_column', 'enum("ONE", "TWO", "THREE") NOT NULL DEFAULT \'ONE\'');
$this->addColumn('{{%newcolumns}}', 'new_column', 'enum("ONE", "TWO", "THREE") NOT NULL DEFAULT \'ONE\' AFTER id');
$this->db->createCommand('ALTER TABLE {{%newcolumns}} ADD COLUMN new_column_x varchar(10) NOT NULL DEFAULT \'ONE\'')->execute();
$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_x');
$this->dropColumn('{{%newcolumns}}', 'new_column');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ class m200000_000001_change_table_newcolumns extends \yii\db\Migration
{
public function up()
{
$this->addColumn('{{%newcolumns}}', 'new_column', 'enum("ONE", "TWO", "THREE") NOT NULL DEFAULT \'ONE\'');
$this->addColumn('{{%newcolumns}}', 'new_column', 'enum("ONE", "TWO", "THREE") NOT NULL DEFAULT \'ONE\' AFTER id');
$this->db->createCommand('ALTER TABLE {{%newcolumns}} ADD COLUMN new_column_x varchar(10) NOT NULL DEFAULT \'ONE\'')->execute();
$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_x');
$this->dropColumn('{{%newcolumns}}', 'new_column');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public function safeUp()
{
$this->execute('CREATE TYPE "enum_itt_newcolumns_new_column" AS ENUM(\'ONE\', \'TWO\', \'THREE\')');
$this->addColumn('{{%newcolumns}}', 'new_column', '"enum_itt_newcolumns_new_column" NOT NULL DEFAULT \'ONE\'');
$this->db->createCommand('ALTER TABLE {{%newcolumns}} ADD COLUMN "new_column_x" varchar(10) NOT NULL DEFAULT \'ONE\'')->execute();
$this->dropColumn('{{%newcolumns}}', 'delete_col');
$this->execute('DROP TYPE "enum_itt_newcolumns_delete_col"');
}
Expand All @@ -17,6 +18,7 @@ public function safeDown()
{
$this->execute('CREATE TYPE "enum_itt_newcolumns_delete_col" AS ENUM(\'FOUR\', \'FIVE\', \'SIX\')');
$this->addColumn('{{%newcolumns}}', 'delete_col', '"enum_itt_newcolumns_delete_col" NULL DEFAULT NULL');
$this->dropColumn('{{%newcolumns}}', 'new_column_x');
$this->dropColumn('{{%newcolumns}}', 'new_column');
$this->execute('DROP TYPE "enum_itt_newcolumns_new_column"');
}
Expand Down
7 changes: 7 additions & 0 deletions tests/specs/postgres_custom.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ components:
enum:
- active
- draft
status_x:
type: string
default: draft
enum:
- active
- draft
x-db-type: varchar(10)
search:
type: string
x-db-type: tsvector
Expand Down
Loading