Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid calling getSerializableData() #98

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
Draft
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ created_at:
x-db-default-expression: current_timestamp()
```

Note: If both `default` and `x-db-default-expression` are present then `default` will be considered.
Note: If both `default` and `x-db-default-expression` are present, then `default` will be considered.

```yaml
created_at:
Expand Down Expand Up @@ -815,10 +815,13 @@ User:

## Handling of `NOT NULL` constraints

`NOT NULL` in DB migrations is determined by `nullable` and `required` properties of the OpenAPI schema.
`NOT NULL` in DB migrations is determined by `nullable` properties of the OpenAPI schema.
e.g. attribute = 'my_property'.

- 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)):
- If you define attribute neither "required" nor via "nullable", then it is by default `NOT NULL` ([as per OpenAPI spec](https://github.com/OAI/OpenAPI-Specification/blob/main/proposals/2019-10-31-Clarify-Nullable.md)):
- `nullable` and `required` of OpenAPI spec is not related. They have separate purpose.
- `nullable` will help in creating migrations ([`null()`](https://www.yiiframework.com/doc/api/2.0/yii-db-columnschemabuilder#null()-detail) and [`notNull()`](https://www.yiiframework.com/doc/api/2.0/yii-db-columnschemabuilder#notNull()-detail)) only
- `required` will help in creating model validation rules only

```yaml
ExampleSchema:
Expand All @@ -827,7 +830,7 @@ e.g. attribute = 'my_property'.
type: string
```

- If you define attribute in "required", then it is `NOT NULL`
- In below example, if you define attribute in "required", then it is `NOT NULL`, because `nullable` is present and it defaults to `false`

```yaml
ExampleSchema:
Expand All @@ -838,7 +841,7 @@ e.g. attribute = 'my_property'.
type: string
```

- If you define attribute via "nullable", then it overrides "required", e.g. allow `NULL` in this case:
- If you define attribute via "nullable", e.g. allow `NULL` in this case:

```yaml
ExampleSchema:
Expand All @@ -850,7 +853,7 @@ e.g. attribute = 'my_property'.
nullable: true
```

- If you define attribute via "nullable", then it overrides "required", e.g. `NOT NULL` in this case:
- If you define attribute via "nullable" e.g. `NOT NULL` in this case:

```yaml
test_table:
Expand Down
21 changes: 16 additions & 5 deletions src/lib/AttributeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,7 @@ public function resolve(): DbModel
/** @var $property PropertySchema */

$isRequired = $this->componentSchema->isRequiredProperty($property->getName());
$nullableValue = $property->getProperty()->getSerializableData()->nullable ?? null;
if ($nullableValue === false) { // see docs in README regarding NOT NULL, required and nullable
$isRequired = true;
}
$nullableValue = $this->nullableValue($property);

if ($this->isJunctionSchema) {
$this->resolveJunctionTableProperty($property, $isRequired);
Expand Down Expand Up @@ -211,7 +208,7 @@ protected function resolveProperty(
$nullableValue = 'ARG_ABSENT'
): void {
if ($nullableValue === 'ARG_ABSENT') {
$nullableValue = $property->getProperty()->getSerializableData()->nullable ?? null;
$nullableValue = $this->nullableValue($property);
}
$attribute = Yii::createObject(Attribute::class, [$property->getName()]);

Expand Down Expand Up @@ -536,4 +533,18 @@ public function addInverseRelation(
$inverseRelation->setInverse($property->getName());
$this->inverseRelations[$relatedClassName][] = $inverseRelation;
}

/**
* Compute nullable value
*/
private function nullableValue(PropertySchema $property): bool
{
$nullableValue = false; # https://github.com/OAI/OpenAPI-Specification/blob/main/proposals/2019-10-31-Clarify-Nullable.md

if ($property->hasAttr('nullable') && $property->getAttr('nullable') === true) {
$nullableValue = true;
}

return $nullableValue;
}
}
2 changes: 1 addition & 1 deletion tests/migrations/m100000_000000_maria.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use yii\db\Schema;

/**
* Initial migration for blog_v2 (based on blog.yaml), so result for blog_v2 should be as secondary mogration
* Initial migration for blog_v2 (based on blog.yaml), so result for blog_v2 should be as secondary migration
**/
class m100000_000000_maria extends Migration
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ 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)"),
'role' => $this->string(20)->notNull()->defaultValue('reader'),
'flags' => $this->integer()->notNull()->defaultValue(0),
'created_at' => $this->timestamp()->notNull()->defaultExpression("(CURRENT_TIMESTAMP)"),
]);
$this->createIndex('users_username_key', '{{%users}}', 'username', true);
$this->createIndex('users_email_key', '{{%users}}', 'email', true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ public function up()
$this->createTable('{{%blog_posts}}', [
0 => 'uid varchar(128) NOT NULL',
'title' => $this->string(255)->notNull(),
'slug' => $this->string(200)->null()->defaultValue(null),
'slug' => $this->string(200)->notNull(),
'category_id' => $this->integer()->notNull()->comment('Category of posts'),
'active' => $this->boolean()->notNull()->defaultValue(false),
'created_at' => $this->date()->null()->defaultValue(null),
'created_by_id' => $this->integer()->null()->defaultValue(null)->comment('The User'),
'created_at' => $this->date()->notNull(),
'created_by_id' => $this->integer()->notNull()->comment('The User'),
]);
$this->addPrimaryKey('pk_blog_posts_uid', '{{%blog_posts}}', 'uid');
$this->createIndex('blog_posts_title_key', '{{%blog_posts}}', 'title', true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ public function up()
{
$this->createTable('{{%fakerable}}', [
'id' => $this->bigPrimaryKey(),
'active' => $this->boolean()->null()->defaultValue(null),
'floatval' => $this->float()->null()->defaultValue(null),
'floatval_lim' => $this->float()->null()->defaultValue(null),
'doubleval' => $this->double()->null()->defaultValue(null),
'int_min' => $this->integer()->null()->defaultValue(3),
'int_max' => $this->integer()->null()->defaultValue(null),
'int_minmax' => $this->integer()->null()->defaultValue(null),
'int_created_at' => $this->integer()->null()->defaultValue(null),
'int_simple' => $this->integer()->null()->defaultValue(null),
'str_text' => $this->text()->null(),
'str_varchar' => $this->string(100)->null()->defaultValue(null),
'str_date' => $this->date()->null()->defaultValue(null),
'str_datetime' => $this->timestamp()->null()->defaultValue(null),
'str_country' => $this->text()->null(),
'active' => $this->boolean()->notNull(),
'floatval' => $this->float()->notNull(),
'floatval_lim' => $this->float()->notNull(),
'doubleval' => $this->double()->notNull(),
'int_min' => $this->integer()->notNull()->defaultValue(3),
'int_max' => $this->integer()->notNull(),
'int_minmax' => $this->integer()->notNull(),
'int_created_at' => $this->integer()->notNull(),
'int_simple' => $this->integer()->notNull(),
'str_text' => $this->text()->notNull(),
'str_varchar' => $this->string(100)->notNull(),
'str_date' => $this->date()->notNull(),
'str_datetime' => $this->timestamp()->notNull(),
'str_country' => $this->text()->notNull(),
]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ 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)"),
'role' => $this->string(20)->notNull()->defaultValue('reader'),
'flags' => $this->integer()->notNull()->defaultValue(0),
'created_at' => $this->timestamp()->notNull()->defaultExpression("(CURRENT_TIMESTAMP)"),
]);
$this->createIndex('users_username_key', '{{%users}}', 'username', true);
$this->createIndex('users_email_key', '{{%users}}', 'email', true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ public function up()
$this->createTable('{{%blog_posts}}', [
0 => 'uid varchar(128) NOT NULL',
'title' => $this->string(255)->notNull(),
'slug' => $this->string(200)->null()->defaultValue(null),
'slug' => $this->string(200)->notNull(),
'category_id' => $this->integer()->notNull()->comment('Category of posts'),
'active' => $this->boolean()->notNull()->defaultValue(false),
'created_at' => $this->date()->null()->defaultValue(null),
'created_by_id' => $this->integer()->null()->defaultValue(null)->comment('The User'),
'created_at' => $this->date()->notNull(),
'created_by_id' => $this->integer()->notNull()->comment('The User'),
]);
$this->addPrimaryKey('pk_blog_posts_uid', '{{%blog_posts}}', 'uid');
$this->createIndex('blog_posts_title_key', '{{%blog_posts}}', 'title', true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ public function up()
{
$this->createTable('{{%fakerable}}', [
'id' => $this->bigPrimaryKey(),
'active' => $this->boolean()->null()->defaultValue(null),
'floatval' => $this->float()->null()->defaultValue(null),
'floatval_lim' => $this->float()->null()->defaultValue(null),
'doubleval' => $this->double()->null()->defaultValue(null),
'int_min' => $this->integer()->null()->defaultValue(3),
'int_max' => $this->integer()->null()->defaultValue(null),
'int_minmax' => $this->integer()->null()->defaultValue(null),
'int_created_at' => $this->integer()->null()->defaultValue(null),
'int_simple' => $this->integer()->null()->defaultValue(null),
'str_text' => $this->text()->null()->defaultValue(null),
'str_varchar' => $this->string(100)->null()->defaultValue(null),
'str_date' => $this->date()->null()->defaultValue(null),
'str_datetime' => $this->timestamp()->null()->defaultValue(null),
'str_country' => $this->text()->null()->defaultValue(null),
'active' => $this->boolean()->notNull(),
'floatval' => $this->float()->notNull(),
'floatval_lim' => $this->float()->notNull(),
'doubleval' => $this->double()->notNull(),
'int_min' => $this->integer()->notNull()->defaultValue(3),
'int_max' => $this->integer()->notNull(),
'int_minmax' => $this->integer()->notNull(),
'int_created_at' => $this->integer()->notNull(),
'int_simple' => $this->integer()->notNull(),
'str_text' => $this->text()->notNull(),
'str_varchar' => $this->string(100)->notNull(),
'str_date' => $this->date()->notNull(),
'str_datetime' => $this->timestamp()->notNull(),
'str_country' => $this->text()->notNull(),
]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ 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)"),
'role' => $this->string(20)->notNull()->defaultValue('reader'),
'flags' => $this->integer()->notNull()->defaultValue(0),
'created_at' => $this->timestamp()->notNull()->defaultExpression("(CURRENT_TIMESTAMP)"),
]);
$this->createIndex('users_username_key', '{{%users}}', 'username', true);
$this->createIndex('users_email_key', '{{%users}}', 'email', true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ public function up()
$this->createTable('{{%blog_posts}}', [
0 => 'uid varchar(128) NOT NULL',
'title' => $this->string(255)->notNull(),
'slug' => $this->string(200)->null()->defaultValue(null),
'slug' => $this->string(200)->notNull(),
'category_id' => $this->integer()->notNull()->comment('Category of posts'),
'active' => $this->boolean()->notNull()->defaultValue(false),
'created_at' => $this->date()->null()->defaultValue(null),
'created_by_id' => $this->integer()->null()->defaultValue(null)->comment('The User'),
'created_at' => $this->date()->notNull(),
'created_by_id' => $this->integer()->notNull()->comment('The User'),
]);
$this->addPrimaryKey('pk_blog_posts_uid', '{{%blog_posts}}', 'uid');
$this->createIndex('blog_posts_title_key', '{{%blog_posts}}', 'title', true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ public function up()
{
$this->createTable('{{%fakerable}}', [
'id' => $this->bigPrimaryKey(),
'active' => $this->boolean()->null()->defaultValue(null),
'floatval' => $this->float()->null()->defaultValue(null),
'floatval_lim' => $this->float()->null()->defaultValue(null),
'doubleval' => $this->double()->null()->defaultValue(null),
'int_min' => $this->integer()->null()->defaultValue(3),
'int_max' => $this->integer()->null()->defaultValue(null),
'int_minmax' => $this->integer()->null()->defaultValue(null),
'int_created_at' => $this->integer()->null()->defaultValue(null),
'int_simple' => $this->integer()->null()->defaultValue(null),
'str_text' => $this->text()->null(),
'str_varchar' => $this->string(100)->null()->defaultValue(null),
'str_date' => $this->date()->null()->defaultValue(null),
'str_datetime' => $this->timestamp()->null()->defaultValue(null),
'str_country' => $this->text()->null(),
'active' => $this->boolean()->notNull(),
'floatval' => $this->float()->notNull(),
'floatval_lim' => $this->float()->notNull(),
'doubleval' => $this->double()->notNull(),
'int_min' => $this->integer()->notNull()->defaultValue(3),
'int_max' => $this->integer()->notNull(),
'int_minmax' => $this->integer()->notNull(),
'int_created_at' => $this->integer()->notNull(),
'int_simple' => $this->integer()->notNull(),
'str_text' => $this->text()->notNull(),
'str_varchar' => $this->string(100)->notNull(),
'str_date' => $this->date()->notNull(),
'str_datetime' => $this->timestamp()->notNull(),
'str_country' => $this->text()->notNull(),
]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ 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)"),
'role' => $this->string(20)->notNull()->defaultValue('reader'),
'flags' => $this->integer()->notNull()->defaultValue(0),
'created_at' => $this->timestamp()->notNull()->defaultExpression("(CURRENT_TIMESTAMP)"),
]);
$this->createIndex('users_username_key', '{{%users}}', 'username', true);
$this->createIndex('users_email_key', '{{%users}}', 'email', true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ public function safeUp()
$this->createTable('{{%blog_posts}}', [
0 => '"uid" varchar(128) NOT NULL',
'title' => $this->string(255)->notNull(),
'slug' => $this->string(200)->null()->defaultValue(null),
'slug' => $this->string(200)->notNull(),
'category_id' => $this->integer()->notNull()->comment('Category of posts'),
'active' => $this->boolean()->notNull()->defaultValue(false),
'created_at' => $this->date()->null()->defaultValue(null),
'created_by_id' => $this->integer()->null()->defaultValue(null)->comment('The User'),
'created_at' => $this->date()->notNull(),
'created_by_id' => $this->integer()->notNull()->comment('The User'),
]);
$this->addPrimaryKey('pk_blog_posts_uid', '{{%blog_posts}}', 'uid');
$this->createIndex('blog_posts_title_key', '{{%blog_posts}}', 'title', true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ public function safeUp()
{
$this->createTable('{{%fakerable}}', [
'id' => $this->bigPrimaryKey(),
'active' => $this->boolean()->null()->defaultValue(null),
'floatval' => $this->float()->null()->defaultValue(null),
'floatval_lim' => $this->float()->null()->defaultValue(null),
'doubleval' => $this->double()->null()->defaultValue(null),
'int_min' => $this->integer()->null()->defaultValue(3),
'int_max' => $this->integer()->null()->defaultValue(null),
'int_minmax' => $this->integer()->null()->defaultValue(null),
'int_created_at' => $this->integer()->null()->defaultValue(null),
'int_simple' => $this->integer()->null()->defaultValue(null),
'str_text' => $this->text()->null()->defaultValue(null),
'str_varchar' => $this->string(100)->null()->defaultValue(null),
'str_date' => $this->date()->null()->defaultValue(null),
'str_datetime' => $this->timestamp()->null()->defaultValue(null),
'str_country' => $this->text()->null()->defaultValue(null),
'active' => $this->boolean()->notNull(),
'floatval' => $this->float()->notNull(),
'floatval_lim' => $this->float()->notNull(),
'doubleval' => $this->double()->notNull(),
'int_min' => $this->integer()->notNull()->defaultValue(3),
'int_max' => $this->integer()->notNull(),
'int_minmax' => $this->integer()->notNull(),
'int_created_at' => $this->integer()->notNull(),
'int_simple' => $this->integer()->notNull(),
'str_text' => $this->text()->notNull(),
'str_varchar' => $this->string(100)->notNull(),
'str_date' => $this->date()->notNull(),
'str_datetime' => $this->timestamp()->notNull(),
'str_country' => $this->text()->notNull(),
]);
}

Expand Down
Loading