Skip to content

Commit 6fbf532

Browse files
authored
Merge pull request #11 from php-openapi/151-remove-unnecessary-null-or-default-related-migrations-in-pgsql
Resolve: Remove unnecessary null or default related migrations in PgSQL cebe#151
2 parents 65d9146 + e73d9a0 commit 6fbf532

File tree

10 files changed

+29
-15
lines changed

10 files changed

+29
-15
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ User:
398398
`NOT NULL` in DB migrations is determined by `nullable` and `required` properties of the OpenAPI schema.
399399
e.g. attribute = 'my_property'.
400400

401-
- If you define attribute neither "required" nor via "nullable", then it is by default `NULL`:
401+
- If you define attribute neither "required" nor via "nullable", then it is by default `NULL` ([opposite of OpenAPI spec](https://swagger.io/specification/v3/?sbsearch=nullable)):
402402

403403
```yaml
404404
ExampleSchema:

src/lib/ColumnToCode.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class ColumnToCode
6969
* @var bool
7070
* Built In Type means the \cebe\yii2openapi\lib\items\Attribute::$type or \cebe\yii2openapi\lib\items\Attribute::$dbType is in list of Yii abstract data type list or not. And if is found we can use \yii\db\SchemaBuilderTrait methods to build migration instead of putting raw SQL
7171
*/
72-
private $isBuiltinType = false;
72+
public $isBuiltinType = false;
7373

7474
/**
7575
* @var bool
@@ -384,6 +384,7 @@ private function getIsBuiltinType($type, $dbType)
384384
if ($this->isEnum()) {
385385
return false;
386386
}
387+
387388
if ($this->fromDb === true) {
388389
return isset(
389390
(new ColumnSchemaBuilder(''))->categoryMap[$type]
@@ -465,7 +466,7 @@ private function resolveDefaultValue():void
465466

466467
private function isDefaultAllowed():bool
467468
{
468-
// default expression with parenthases is allowed
469+
// default expression with parentheses is allowed
469470
if ($this->column->defaultValue instanceof \yii\db\Expression) {
470471
return true;
471472
}

src/lib/migrations/MigrationRecordBuilder.php

+10
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ final class MigrationRecordBuilder
5151
*/
5252
private $dbSchema;
5353

54+
/**
55+
* @var bool
56+
* Only required for PgSQL alter column for set null/set default related statement
57+
*/
58+
public $isBuiltInType = false;
59+
5460
public function __construct(Schema $dbSchema)
5561
{
5662
$this->dbSchema = $dbSchema;
@@ -134,6 +140,7 @@ public function alterColumnType(string $tableAlias, ColumnSchema $column, bool $
134140
{
135141
if (property_exists($column, 'xDbType') && is_string($column->xDbType) && !empty($column->xDbType)) {
136142
$converter = $this->columnToCode($tableAlias, $column, false, false, true, true);
143+
$this->isBuiltInType = $converter->isBuiltinType;
137144
return sprintf(
138145
ApiGenerator::isPostgres() ? self::ALTER_COLUMN_RAW_PGSQL : self::ALTER_COLUMN_RAW,
139146
$tableAlias,
@@ -142,6 +149,7 @@ public function alterColumnType(string $tableAlias, ColumnSchema $column, bool $
142149
);
143150
}
144151
$converter = $this->columnToCode($tableAlias, $column, false);
152+
$this->isBuiltInType = $converter->isBuiltinType;
145153
return sprintf(self::ALTER_COLUMN, $tableAlias, $column->name, $converter->getAlterExpression($addUsing));
146154
}
147155

@@ -153,6 +161,7 @@ public function alterColumnTypeFromDb(string $tableAlias, ColumnSchema $column,
153161
{
154162
if (property_exists($column, 'xDbType') && is_string($column->xDbType) && !empty($column->xDbType)) {
155163
$converter = $this->columnToCode($tableAlias, $column, true, false, true, true);
164+
$this->isBuiltInType = $converter->isBuiltinType;
156165
return sprintf(
157166
ApiGenerator::isPostgres() ? self::ALTER_COLUMN_RAW_PGSQL : self::ALTER_COLUMN_RAW,
158167
$tableAlias,
@@ -161,6 +170,7 @@ public function alterColumnTypeFromDb(string $tableAlias, ColumnSchema $column,
161170
);
162171
}
163172
$converter = $this->columnToCode($tableAlias, $column, true);
173+
$this->isBuiltInType = $converter->isBuiltinType;
164174
return sprintf(self::ALTER_COLUMN, $tableAlias, $column->name, $converter->getAlterExpression($addUsing));
165175
}
166176

src/lib/migrations/PostgresMigrationBuilder.php

+9-5
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,20 @@ protected function buildColumnChanges(ColumnSchema $current, ColumnSchema $desir
6262
// This action require several steps and can't be applied during single transaction
6363
return;
6464
}
65-
65+
$forUp = $forDown = false;
6666
if (!empty(array_intersect(['type', 'size'
6767
, 'dbType', 'phpType'
6868
, 'precision', 'scale', 'unsigned'
6969
], $changed))) {
7070
$addUsing = $this->isNeedUsingExpression($current->dbType, $desired->dbType);
7171
$this->migration->addUpCode($this->recordBuilder->alterColumnType($tableName, $desired, $addUsing));
72+
$forUp = $this->recordBuilder->isBuiltInType;
7273
$this->migration->addDownCode($this->recordBuilder->alterColumnTypeFromDb($tableName, $current, $addUsing));
74+
$forDown = $this->recordBuilder->isBuiltInType;
7375
}
74-
if (in_array('allowNull', $changed, true)) {
76+
if (in_array('allowNull', $changed, true)
77+
&& ($forUp === false || $forDown === false)
78+
) {
7579
if ($desired->allowNull === true) {
7680
$this->migration->addUpCode($this->recordBuilder->dropColumnNotNull($tableName, $desired));
7781
$this->migration->addDownCode($this->recordBuilder->setColumnNotNull($tableName, $current), true);
@@ -80,6 +84,9 @@ protected function buildColumnChanges(ColumnSchema $current, ColumnSchema $desir
8084
$this->migration->addDownCode($this->recordBuilder->dropColumnNotNull($tableName, $current), true);
8185
}
8286
}
87+
88+
$this->recordBuilder->isBuiltInType = $forUp = $forDown = false;
89+
8390
if (in_array('defaultValue', $changed, true)) {
8491
$upCode = $desired->defaultValue === null
8592
? $this->recordBuilder->dropColumnDefault($tableName, $desired)
@@ -96,9 +103,6 @@ protected function buildColumnChanges(ColumnSchema $current, ColumnSchema $desir
96103
}
97104
if ($isChangeFromEnum) {
98105
$this->migration->addUpCode($this->recordBuilder->dropEnum($tableName, $current->name));
99-
}
100-
101-
if ($isChangeFromEnum) {
102106
$this->migration
103107
->addDownCode($this->recordBuilder->createEnum($tableName, $current->name, $current->enumValues));
104108
}

tests/specs/issue_fix/wrong_migration_for_pgsql_is_generated_for_string_varchar_datatype_149/app/migrations_pgsql_db/m200000_000000_change_table_fruits.php

-2
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,10 @@ class m200000_000000_change_table_fruits extends \yii\db\Migration
88
public function safeUp()
99
{
1010
$this->alterColumn('{{%fruits}}', 'name', $this->string(151)->notNull());
11-
$this->alterColumn('{{%fruits}}', 'name', "SET NOT NULL");
1211
}
1312

1413
public function safeDown()
1514
{
1615
$this->alterColumn('{{%fruits}}', 'name', $this->string(150)->null());
17-
$this->alterColumn('{{%fruits}}', 'name', "DROP NOT NULL");
1816
}
1917
}

tests/specs/x_db_type/edit_column/pgsql/app/migrations_pgsql_db/m200000_000001_change_table_editcolumns.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ public function safeUp()
1414
$this->db->createCommand('ALTER TABLE {{%editcolumns}} ALTER COLUMN "name" SET DATA TYPE varchar(254)')->execute();
1515
$this->alterColumn('{{%editcolumns}}', 'name', "SET DEFAULT 'Horse-2'");
1616
$this->alterColumn('{{%editcolumns}}', 'string_col', 'text NULL USING "string_col"::text');
17-
$this->alterColumn('{{%editcolumns}}', 'string_col', "DROP NOT NULL");
1817
$this->db->createCommand('ALTER TABLE {{%editcolumns}} ALTER COLUMN "dec_col" SET DATA TYPE decimal(12,2) USING "dec_col"::decimal(12,2)')->execute();
1918
$this->alterColumn('{{%editcolumns}}', 'dec_col', "SET DEFAULT 3.14");
2019
$this->alterColumn('{{%editcolumns}}', 'str_col_def', "SET NOT NULL");
@@ -25,6 +24,7 @@ public function safeUp()
2524
$this->alterColumn('{{%editcolumns}}', 'json_col_2', "SET NOT NULL");
2625
$this->alterColumn('{{%editcolumns}}', 'json_col_2', "SET DEFAULT '[]'");
2726
$this->db->createCommand('ALTER TABLE {{%editcolumns}} ALTER COLUMN "numeric_col" SET DATA TYPE double precision USING "numeric_col"::double precision')->execute();
27+
$this->alterColumn('{{%editcolumns}}', 'numeric_col', "SET NOT NULL");
2828
}
2929

3030
public function safeDown()
@@ -39,13 +39,13 @@ public function safeDown()
3939
$this->dropColumn('{{%editcolumns}}', 'json_col_def_n');
4040
$this->dropColumn('{{%editcolumns}}', 'first_name');
4141
$this->alterColumn('{{%editcolumns}}', 'name', "SET DEFAULT 'Horse'");
42-
$this->alterColumn('{{%editcolumns}}', 'string_col', "SET NOT NULL");
4342
$this->alterColumn('{{%editcolumns}}', 'dec_col', "DROP DEFAULT");
4443
$this->alterColumn('{{%editcolumns}}', 'str_col_def', "DROP NOT NULL");
4544
$this->alterColumn('{{%editcolumns}}', 'str_col_def', "SET DEFAULT 'hi there'");
4645
$this->alterColumn('{{%editcolumns}}', 'json_col', "DROP NOT NULL");
4746
$this->alterColumn('{{%editcolumns}}', 'json_col', "DROP DEFAULT");
4847
$this->alterColumn('{{%editcolumns}}', 'json_col_2', "DROP NOT NULL");
4948
$this->alterColumn('{{%editcolumns}}', 'json_col_2', "DROP DEFAULT");
49+
$this->alterColumn('{{%editcolumns}}', 'numeric_col', "DROP NOT NULL");
5050
}
5151
}

tests/specs/x_db_type/fresh/pgsql/app/migrations_pgsql_db/m200000_000001_create_table_editcolumns.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function safeUp()
1717
3 => '"str_col_def" varchar NOT NULL',
1818
4 => '"json_col" text NOT NULL DEFAULT \'fox jumps over dog\'',
1919
5 => '"json_col_2" jsonb NOT NULL DEFAULT \'[]\'',
20-
6 => '"numeric_col" double precision NULL DEFAULT NULL',
20+
6 => '"numeric_col" double precision NOT NULL',
2121
7 => '"json_col_def_n" json NOT NULL DEFAULT \'[]\'',
2222
8 => '"json_col_def_n_2" json NOT NULL DEFAULT \'[]\'',
2323
9 => '"text_col_array" text[] NULL DEFAULT NULL',

tests/specs/x_db_type/fresh/pgsql/x_db_type_pgsql.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ components:
516516
numeric_col:
517517
type: string
518518
x-db-type: double precision
519+
nullable: false
519520
json_col_def_n:
520521
type: string
521522
x-db-type: json

tests/specs/x_db_type/new_column/pgsql/app/migrations_pgsql_db/m200000_000001_create_table_editcolumns.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function safeUp()
1717
3 => '"str_col_def" varchar NOT NULL',
1818
4 => '"json_col" text NOT NULL DEFAULT \'fox jumps over dog\'',
1919
5 => '"json_col_2" jsonb NOT NULL DEFAULT \'[]\'',
20-
6 => '"numeric_col" double precision NULL DEFAULT NULL',
20+
6 => '"numeric_col" double precision NOT NULL',
2121
7 => '"json_col_def_n" json NOT NULL DEFAULT \'[]\'',
2222
8 => '"json_col_def_n_2" json NOT NULL DEFAULT \'[]\'',
2323
9 => '"text_col_array" text[] NULL DEFAULT NULL',

tests/specs/x_db_type/rules_and_more/pgsql/app/models/pgsqlmodel/base/Editcolumn.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public function rules()
3535
{
3636
return [
3737
'trim' => [['name', 'tag', 'first_name', 'string_col', 'str_col_def', 'json_col'], 'trim'],
38-
'required' => [['name', 'str_col_def', 'json_col', 'json_col_2'], 'required'],
38+
'required' => [['name', 'str_col_def', 'json_col', 'json_col_2', 'numeric_col'], 'required'],
3939
'name_string' => [['name'], 'string', 'max' => 254],
4040
'name_default' => [['name'], 'default', 'value' => 'Horse-2'],
4141
'tag_string' => [['tag'], 'string'],

0 commit comments

Comments
 (0)