Skip to content

Resolve: Description of a property in spec must correspond to DB TABLE COLUMN COMMENT #60 #61

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

Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9ec5b1b
Create PR
SOHELAHMED7 Sep 28, 2024
87b01da
Add failing test
SOHELAHMED7 Sep 28, 2024
1e408b7
Fix this issue
SOHELAHMED7 Sep 28, 2024
2fb2d7b
Move `resolve()` method
SOHELAHMED7 Sep 28, 2024
f998279
Add test to ensure existing comments are preserved
SOHELAHMED7 Sep 28, 2024
4a11785
Fix failing tests
SOHELAHMED7 Sep 28, 2024
d4dd074
Add comments handling for PgSQL as it is different from MySQL - WIP
SOHELAHMED7 Sep 28, 2024
b18c521
Add comments handling for PgSQL as it is different from MySQL - 2
SOHELAHMED7 Sep 29, 2024
72a7a6a
Add comments handling for PgSQL as it is different from MySQL - done
SOHELAHMED7 Sep 29, 2024
7d557c4
Complete the test
SOHELAHMED7 Sep 29, 2024
d0415fb
Fix bug and failing tests
SOHELAHMED7 Sep 30, 2024
fa47121
Rename function and constant
SOHELAHMED7 Sep 30, 2024
3fbf3c7
Handle quoting of values
SOHELAHMED7 Oct 1, 2024
6ea5f1d
Resolve TODOs
SOHELAHMED7 Oct 1, 2024
2647645
Merge branches 'master' and '60-description-of-a-property-in-spec-mus…
SOHELAHMED7 Nov 15, 2024
7fa9cde
Fix failing test
SOHELAHMED7 Nov 15, 2024
af961aa
Make this feature optional - WIP - https://github.com/php-openapi/yii…
SOHELAHMED7 Nov 15, 2024
d549831
Implement for table/compo schema - WIP
SOHELAHMED7 Nov 18, 2024
53416d2
WIP
SOHELAHMED7 Nov 19, 2024
3815cb3
Implement for property level extension
SOHELAHMED7 Nov 20, 2024
8fd5b8b
Add more tests
SOHELAHMED7 Nov 21, 2024
051900a
Fix failing tests
SOHELAHMED7 Nov 21, 2024
9d4dc38
Add doc
SOHELAHMED7 Nov 21, 2024
20fad45
Resolve TODO
SOHELAHMED7 Nov 21, 2024
692c4aa
Implement for PgSQL
SOHELAHMED7 Nov 21, 2024
d5be8ce
Refactor
SOHELAHMED7 Nov 21, 2024
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
8 changes: 4 additions & 4 deletions src/generator/default/dbmodel.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@
*/
abstract class <?= $model->getClassName() ?> extends \yii\db\ActiveRecord
{
<?php if($scenarios = $model->getScenarios()):
foreach($scenarios as $scenario): ?>
<?php if ($scenarios = $model->getScenarios()):
foreach ($scenarios as $scenario): ?>
/**
*<?= $scenario['description'] ?>

Expand All @@ -76,7 +76,7 @@ public static function tableName()
{
return <?= var_export($model->getTableAlias()) ?>;
}
<?php if($scenarios): ?>
<?php if ($scenarios): ?>

/**
* Automatically generated scenarios from the model 'x-scenarios'.
Expand All @@ -92,7 +92,7 @@ public function scenarios()
$default = parent::scenarios()[self::SCENARIO_DEFAULT];

return [
<?php foreach($scenarios as $scenario): ?>
<?php foreach ($scenarios as $scenario): ?>
self::<?= $scenario['const'] ?> => $default,
<?php endforeach; ?>
/**
Expand Down
118 changes: 63 additions & 55 deletions src/lib/ColumnToCode.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ class ColumnToCode
*/
private $isPk = false;

private $rawParts = ['type' => null, 'nullable' => null, 'default' => null, 'position' => null];
private $rawParts = ['type' => null, 'nullable' => null, 'default' => null, 'position' => null, 'comment' => null];

private $fluentParts = ['type' => null, 'nullable' => null, 'default' => null, 'position' => null];
private $fluentParts = ['type' => null, 'nullable' => null, 'default' => null, 'position' => null, 'comment' => null];

/**
* @var bool
Expand Down Expand Up @@ -150,6 +150,60 @@ public function __construct(
$this->resolve();
}

private function resolve():void
{
$dbType = $this->typeWithoutSize(strtolower($this->column->dbType));
$type = $this->column->type;
$this->resolvePosition();
//Primary Keys
if (array_key_exists($type, self::PK_TYPE_MAP)) {
$this->rawParts['type'] = $type;
$this->fluentParts['type'] = self::PK_TYPE_MAP[$type];
$this->isPk = true;
return;
}
if (array_key_exists($dbType, self::PK_TYPE_MAP)) {
$this->rawParts['type'] = $dbType;
$this->fluentParts['type'] = self::PK_TYPE_MAP[$dbType];
$this->isPk = true;
return;
}

if ($dbType === 'varchar') {
$type = $dbType = 'string';
}
$fluentSize = $this->column->size ? '(' . $this->column->size . ')' : '()';
$rawSize = $this->column->size ? '(' . $this->column->size . ')' : '';
$this->rawParts['nullable'] = $this->column->allowNull ? 'NULL' : 'NOT NULL';
$this->fluentParts['nullable'] = $this->column->allowNull === true ? 'null()' : 'notNull()';

$this->fluentParts['comment'] = $this->column->comment ? 'comment('.var_export($this->column->comment, true).')' : $this->fluentParts['comment'];
$this->rawParts['comment'] = $this->column->comment ? 'COMMENT '.var_export($this->column->comment, true) : $this->rawParts['comment'];

if (array_key_exists($dbType, self::INT_TYPE_MAP)) {
$this->fluentParts['type'] = self::INT_TYPE_MAP[$dbType] . $fluentSize;
$this->rawParts['type'] =
$this->column->dbType . (strpos($this->column->dbType, '(') !== false ? '' : $rawSize);
} elseif (array_key_exists($type, self::INT_TYPE_MAP)) {
$this->fluentParts['type'] = self::INT_TYPE_MAP[$type] . $fluentSize;
$this->rawParts['type'] =
$this->column->dbType . (strpos($this->column->dbType, '(') !== false ? '' : $rawSize);
} elseif ($this->isEnum()) {
$this->resolveEnumType();
} elseif ($this->isDecimal()) {
$this->fluentParts['type'] = $this->column->dbType;
$this->rawParts['type'] = $this->column->dbType;
} else {
$this->fluentParts['type'] = $type . $fluentSize;
$this->rawParts['type'] =
$this->column->dbType . (strpos($this->column->dbType, '(') !== false ? '' : $rawSize);
}

$this->isBuiltinType = $this->raw ? false : $this->getIsBuiltinType($type, $dbType);

$this->resolveDefaultValue();
}

public function getCode(bool $quoted = false):string
{
if ($this->isPk) {
Expand All @@ -160,7 +214,8 @@ public function getCode(bool $quoted = false):string
$this->fluentParts['type'],
$this->fluentParts['nullable'],
$this->fluentParts['default'],
$this->fluentParts['position']
$this->fluentParts['position'],
$this->fluentParts['comment'],
]);
array_unshift($parts, '$this');
return implode('->', array_filter(array_map('trim', $parts)));
Expand All @@ -175,9 +230,12 @@ public function getCode(bool $quoted = false):string
}

$code = $this->rawParts['type'] . ' ' . $this->rawParts['nullable'] . $default;
if ((ApiGenerator::isMysql() || ApiGenerator::isMariaDb()) && $this->rawParts['position']) {
$code .= ' ' . $this->rawParts['position'];

if ((ApiGenerator::isMysql() || ApiGenerator::isMariaDb())) {
$code .= $this->rawParts['position'] ? ' ' . $this->rawParts['position'] : '';
$code .= $this->rawParts['comment'] ? ' '.$this->rawParts['comment'] : '';
}

if (ApiGenerator::isPostgres() && $this->alterByXDbType) {
return $quoted ? VarDumper::export($this->rawParts['type']) : $this->rawParts['type'];
}
Expand Down Expand Up @@ -320,56 +378,6 @@ private function defaultValueArray(array $value):string
return "'{" . trim(Json::encode($value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_QUOT), '[]') . "}'";
}

private function resolve():void
{
$dbType = $this->typeWithoutSize(strtolower($this->column->dbType));
$type = $this->column->type;
$this->resolvePosition();
//Primary Keys
if (array_key_exists($type, self::PK_TYPE_MAP)) {
$this->rawParts['type'] = $type;
$this->fluentParts['type'] = self::PK_TYPE_MAP[$type];
$this->isPk = true;
return;
}
if (array_key_exists($dbType, self::PK_TYPE_MAP)) {
$this->rawParts['type'] = $dbType;
$this->fluentParts['type'] = self::PK_TYPE_MAP[$dbType];
$this->isPk = true;
return;
}

if ($dbType === 'varchar') {
$type = $dbType = 'string';
}
$fluentSize = $this->column->size ? '(' . $this->column->size . ')' : '()';
$rawSize = $this->column->size ? '(' . $this->column->size . ')' : '';
$this->rawParts['nullable'] = $this->column->allowNull ? 'NULL' : 'NOT NULL';
$this->fluentParts['nullable'] = $this->column->allowNull === true ? 'null()' : 'notNull()';
if (array_key_exists($dbType, self::INT_TYPE_MAP)) {
$this->fluentParts['type'] = self::INT_TYPE_MAP[$dbType] . $fluentSize;
$this->rawParts['type'] =
$this->column->dbType . (strpos($this->column->dbType, '(') !== false ? '' : $rawSize);
} elseif (array_key_exists($type, self::INT_TYPE_MAP)) {
$this->fluentParts['type'] = self::INT_TYPE_MAP[$type] . $fluentSize;
$this->rawParts['type'] =
$this->column->dbType . (strpos($this->column->dbType, '(') !== false ? '' : $rawSize);
} elseif ($this->isEnum()) {
$this->resolveEnumType();
} elseif ($this->isDecimal()) {
$this->fluentParts['type'] = $this->column->dbType;
$this->rawParts['type'] = $this->column->dbType;
} else {
$this->fluentParts['type'] = $type . $fluentSize;
$this->rawParts['type'] =
$this->column->dbType . (strpos($this->column->dbType, '(') !== false ? '' : $rawSize);
}

$this->isBuiltinType = $this->raw ? false : $this->getIsBuiltinType($type, $dbType);

$this->resolveDefaultValue();
}

/**
* @param $type
* @param $dbType
Expand Down
1 change: 1 addition & 0 deletions src/lib/items/Attribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ public function toColumnSchema():ColumnSchema
'allowNull' => $this->allowNull(),
'size' => $this->size > 0 ? $this->size : null,
'xDbType' => $this->xDbType,
'comment' => $this->description,
]);
$column->isPrimaryKey = $this->primary;
$column->autoIncrement = $this->primary && $this->phpType === 'int';
Expand Down
9 changes: 8 additions & 1 deletion src/lib/migrations/BaseMigrationBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ public function buildFresh():MigrationModel
}
}

$this->handleCommentsMigration();

return $this->migration;
}

Expand Down Expand Up @@ -275,6 +277,8 @@ abstract public static function getColumnSchemaBuilderClass(): string;
*/
abstract protected function findTableIndexes():array;

abstract public function handleCommentsMigration();

protected function buildIndexChanges():void
{
$haveIndexes = $this->findTableIndexes();
Expand Down Expand Up @@ -445,14 +449,17 @@ public function tmpSaveNewCol(string $tableAlias, \cebe\yii2openapi\db\ColumnSch
if (ApiGenerator::isPostgres() && static::isEnum($columnSchema)) {
$allEnumValues = $columnSchema->enumValues;
$allEnumValues = array_map(function ($aValue) {
return "'$aValue'";
return $this->db->quoteValue($aValue);
}, $allEnumValues);
Yii::$app->db->createCommand(
'CREATE TYPE '.$tmpEnumName($columnSchema->name).' AS ENUM('.implode(', ', $allEnumValues).')'
)->execute();
}

Yii::$app->db->createCommand()->createTable($tmpTableName, $column)->execute();
if (ApiGenerator::isPostgres() && $columnSchema->comment) {
Yii::$app->db->createCommand("COMMENT ON COLUMN $tmpTableName.$columnSchema->name IS {$this->db->quoteValue($columnSchema->comment)}")->execute();
}

$table = Yii::$app->db->getTableSchema($tmpTableName);

Expand Down
14 changes: 14 additions & 0 deletions src/lib/migrations/MigrationRecordBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ final class MigrationRecordBuilder

public const ALTER_COLUMN_RAW_PGSQL = MigrationRecordBuilder::INDENT . "\$this->db->createCommand('ALTER TABLE %s ALTER COLUMN \"%s\" SET DATA TYPE %s')->execute();";

public const ADD_COMMENT_ON_COLUMN = MigrationRecordBuilder::INDENT . "\$this->addCommentOnColumn('%s', '%s', %s);";

public const DROP_COMMENT_FROM_COLUMN = MigrationRecordBuilder::INDENT . "\$this->dropCommentFromColumn('%s', '%s');";

/**
* @var \yii\db\Schema
*/
Expand Down Expand Up @@ -345,4 +349,14 @@ public static function makeString(array $codeColumns): string
$codeColumns = '['.PHP_EOL.self::INDENT.' '.$codeColumns.PHP_EOL . self::INDENT.']';
return $codeColumns;
}

public function addCommentOnColumn($table, string $column, string $comment): string
{
return sprintf(self::ADD_COMMENT_ON_COLUMN, $table, $column, var_export($comment, true));
}

public function dropCommentFromColumn($table, string $column): string
{
return sprintf(self::DROP_COMMENT_FROM_COLUMN, $table, $column);
}
}
10 changes: 7 additions & 3 deletions src/lib/migrations/MysqlMigrationBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
use yii\db\ColumnSchema;
use yii\db\IndexConstraint;
use yii\db\Schema;
use \Yii;
use yii\helpers\ArrayHelper;
use yii\helpers\VarDumper;

final class MysqlMigrationBuilder extends BaseMigrationBuilder
{
Expand Down Expand Up @@ -56,7 +54,7 @@ protected function compareColumns(ColumnSchema $current, ColumnSchema $desired):

foreach (['type', 'size', 'allowNull', 'defaultValue', 'enumValues'
, 'dbType', 'phpType'
, 'precision', 'scale', 'unsigned'
, 'precision', 'scale', 'unsigned', 'comment'
] as $attr) {
if ($attr === 'defaultValue') {
if ($this->isDefaultValueChanged($current, $desiredFromDb)) {
Expand Down Expand Up @@ -159,4 +157,10 @@ public function modifyDesiredInContextOfCurrent(ColumnSchema $current, ColumnSch
$desired->size = $current->size;
}
}

public function handleCommentsMigration()
{
// nothing to do here as comments can be defined in same statement as of alter/add column in MySQL
// this method is only for PgSQL
}
}
27 changes: 24 additions & 3 deletions src/lib/migrations/PostgresMigrationBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

use cebe\yii2openapi\lib\items\DbIndex;
use yii\db\ColumnSchema;
use yii\helpers\VarDumper;
use yii\helpers\ArrayHelper;

final class PostgresMigrationBuilder extends BaseMigrationBuilder
Expand Down Expand Up @@ -65,7 +64,7 @@ protected function buildColumnChanges(ColumnSchema $current, ColumnSchema $desir

if (!empty(array_intersect(['type', 'size'
, 'dbType', 'phpType'
, 'precision', 'scale', 'unsigned'
, 'precision', 'scale', 'unsigned'
], $changed))) {
$addUsing = $this->isNeedUsingExpression($current->dbType, $desired->dbType);
$this->migration->addUpCode($this->recordBuilder->alterColumnType($tableName, $desired, $addUsing));
Expand All @@ -91,6 +90,17 @@ protected function buildColumnChanges(ColumnSchema $current, ColumnSchema $desir
$this->migration->addUpCode($upCode)->addDownCode($downCode, true);
}
}

if (in_array('comment', $changed, true)) {
if ($desired->comment) {
$this->migration->addUpCode($this->recordBuilder->addCommentOnColumn($tableName, $desired->name, $desired->comment));
$this->migration->addDownCode($this->recordBuilder->dropCommentFromColumn($tableName, $desired->name));
} else {
$this->migration->addUpCode($this->recordBuilder->dropCommentFromColumn($tableName, $desired->name));
$this->migration->addDownCode($this->recordBuilder->addCommentOnColumn($tableName, $desired->name, $current->comment));
}
}

if ($isChangeToEnum) {
$this->migration->addUpCode($this->recordBuilder->createEnum($tableName, $desired->name, $desired->enumValues), true);
}
Expand Down Expand Up @@ -127,7 +137,7 @@ protected function compareColumns(ColumnSchema $current, ColumnSchema $desired):

foreach (['type', 'size', 'allowNull', 'defaultValue', 'enumValues'
, 'dbType', 'phpType'
, 'precision', 'scale', 'unsigned'
, 'precision', 'scale', 'unsigned', 'comment'
] as $attr) {
if ($attr === 'defaultValue') {
if ($this->isDefaultValueChanged($current, $desiredFromDb)) {
Expand Down Expand Up @@ -248,4 +258,15 @@ public function modifyDesiredInContextOfCurrent(ColumnSchema $current, ColumnSch
$desired->size = $current->size;
}
}

public function handleCommentsMigration()
{
$tableAlias = $this->model->getTableAlias();
foreach ($this->newColumns as $column) {
if ($column->comment) {
$this->migration
->addUpCode($this->recordBuilder->addCommentOnColumn($tableAlias, $column->name, $column->comment));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ public function up()
0 => 'uid varchar(128) NOT NULL',
'title' => $this->string(255)->notNull(),
'slug' => $this->string(200)->null()->defaultValue(null),
'category_id' => $this->integer()->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),
'created_by_id' => $this->integer()->null()->defaultValue(null)->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,8 +9,8 @@ public function up()
{
$this->createTable('{{%post_comments}}', [
'id' => $this->bigPrimaryKey(),
'post_id' => $this->string(128)->notNull(),
'author_id' => $this->integer()->notNull(),
'post_id' => $this->string(128)->notNull()->comment('A blog post (uid used as pk for test purposes)'),
'author_id' => $this->integer()->notNull()->comment('The User'),
0 => 'message json NOT NULL',
1 => 'meta_data json NOT NULL',
'created_at' => $this->integer()->notNull(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ public function up()
0 => 'uid varchar(128) NOT NULL',
'title' => $this->string(255)->notNull(),
'slug' => $this->string(200)->null()->defaultValue(null),
'category_id' => $this->integer()->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),
'created_by_id' => $this->integer()->null()->defaultValue(null)->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,8 +9,8 @@ public function up()
{
$this->createTable('{{%post_comments}}', [
'id' => $this->bigPrimaryKey(),
'post_id' => $this->string(128)->notNull(),
'author_id' => $this->integer()->notNull(),
'post_id' => $this->string(128)->notNull()->comment('A blog post (uid used as pk for test purposes)'),
'author_id' => $this->integer()->notNull()->comment('The User'),
0 => 'message json NOT NULL DEFAULT \'[]\'',
1 => 'meta_data json NOT NULL DEFAULT \'[]\'',
'created_at' => $this->integer()->notNull(),
Expand Down
Loading
Loading