From cb9801fdebbaf221b17901a6b4b03637002fb288 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Fri, 1 Sep 2023 18:59:35 +0700 Subject: [PATCH 1/8] Column type classes --- src/ColumnSchema.php | 9 ++ src/Schema.php | 147 ++++++++++++------------------ tests/ColumnSchemaTest.php | 38 ++++++-- tests/Provider/SchemaProvider.php | 14 +++ tests/SchemaTest.php | 6 +- tests/Support/Fixture/mysql.sql | 1 + 6 files changed, 114 insertions(+), 101 deletions(-) diff --git a/src/ColumnSchema.php b/src/ColumnSchema.php index 90d5852c..9d81cd14 100644 --- a/src/ColumnSchema.php +++ b/src/ColumnSchema.php @@ -13,6 +13,10 @@ use function json_decode; /** + * @deprecated Use the following class for specific type: + * `StringColumnSchema`, `IntegerColumnSchema`, `BigIntColumnSchema`, `DoubleColumnSchema`, `BooleanColumnSchema`, + * `BinaryColumnSchema`, `JsonColumnSchema` + * * Represents the metadata of a column in a database table for MySQL, MariaDB. * * It provides information about the column's name, type, size, precision, and other details. @@ -35,6 +39,9 @@ * $column->autoIncrement(true); * $column->primaryKey(true); * ``` + * + * @psalm-suppress DeprecatedInterface + * @psalm-suppress DeprecatedClass */ final class ColumnSchema extends AbstractColumnSchema { @@ -59,6 +66,7 @@ public function phpTypecast(mixed $value): mixed return json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR); } + /** @psalm-suppress DeprecatedClass */ return parent::phpTypecast($value); } @@ -82,6 +90,7 @@ public function dbTypecast(mixed $value): mixed return new JsonExpression($value, $this->getDbType()); } + /** @psalm-suppress DeprecatedClass */ return parent::dbTypecast($value); } } diff --git a/src/Schema.php b/src/Schema.php index 15df52a8..a7b5e2ef 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -4,7 +4,6 @@ namespace Yiisoft\Db\Mysql; -use JsonException; use Throwable; use Yiisoft\Db\Constraint\Constraint; use Yiisoft\Db\Constraint\ForeignKeyConstraint; @@ -16,7 +15,7 @@ use Yiisoft\Db\Expression\Expression; use Yiisoft\Db\Helper\DbArrayHelper; use Yiisoft\Db\Schema\Builder\ColumnInterface; -use Yiisoft\Db\Schema\ColumnSchemaInterface; +use Yiisoft\Db\Schema\Column\ColumnSchemaInterface; use Yiisoft\Db\Schema\TableSchemaInterface; use function array_map; @@ -38,26 +37,6 @@ /** * Implements MySQL, MariaDB specific schema, supporting MySQL Server 5.7, MariaDB Server 10.4 and higher. * - * @psalm-type ColumnArray = array{ - * table_schema: string, - * table_name: string, - * column_name: string, - * data_type: string, - * type_type: string|null, - * character_maximum_length: int, - * column_comment: string|null, - * modifier: int, - * is_nullable: bool, - * column_default: mixed, - * is_autoinc: bool, - * sequence_name: string|null, - * enum_values: array|string|null, - * numeric_precision: int|null, - * numeric_scale: int|null, - * size: string|null, - * is_pkey: bool|null, - * dimension: int - * } * @psalm-type ColumnInfoArray = array{ * field: string, * type: string, @@ -68,7 +47,11 @@ * extra: string, * extra_default_value: string|null, * privileges: string, - * comment: string + * comment: string, + * enum_values?: string[], + * size?: int, + * precision?: int, + * scale?: int, * } * @psalm-type RowConstraint = array{ * constraint_name: string, @@ -194,8 +177,7 @@ protected function findColumns(TableSchemaInterface $table): bool // Chapter 1: crutches for MariaDB. {@see https://github.com/yiisoft/yii2/issues/19747} $columnsExtra = []; if (str_contains($this->db->getServerVersion(), 'MariaDB')) { - /** @psalm-var array[] $columnsExtra */ - $columnsExtra = $this->db->createCommand( + $rows = $this->db->createCommand( <<queryAll(); /** @psalm-var string[] $cols */ - foreach ($columnsExtra as $cols) { + foreach ($rows as $cols) { $columnsExtra[$cols['name']] = $cols['default_value']; } } @@ -230,15 +212,15 @@ protected function findColumns(TableSchemaInterface $table): bool /** @psalm-var ColumnInfoArray $info */ foreach ($columns as $info) { + /** @psalm-var ColumnInfoArray $info */ $info = $this->normalizeRowKeyCase($info, false); - $info['extra_default_value'] = $columnsExtra[(string) $info['field']] ?? ''; + $info['extra_default_value'] = $columnsExtra[$info['field']] ?? ''; if (in_array($info['field'], $jsonColumns, true)) { $info['type'] = self::TYPE_JSON; } - /** @psalm-var ColumnInfoArray $info */ $column = $this->loadColumnSchema($info); $table->column($column->getName(), $column); @@ -466,64 +448,26 @@ protected function getCreateTableSql(TableSchemaInterface $table): string * * @param array $info The column information. * - * @throws JsonException - * * @return ColumnSchemaInterface The column schema object. * * @psalm-param ColumnInfoArray $info The column information. */ - protected function loadColumnSchema(array $info): ColumnSchemaInterface + private function loadColumnSchema(array $info): ColumnSchemaInterface { $dbType = $info['type']; - - $column = $this->createColumnSchema($info['field']); - + $type = $this->getColumnType($dbType, $info); + $isUnsigned = stripos($dbType, 'unsigned') !== false; /** @psalm-var ColumnInfoArray $info */ + $column = $this->createColumnSchema($type, $info['field'], unsigned: $isUnsigned); + $column->enumValues($info['enum_values'] ?? null); + $column->size($info['size'] ?? null); + $column->precision($info['precision'] ?? null); + $column->scale($info['scale'] ?? null); $column->allowNull($info['null'] === 'YES'); $column->primaryKey(str_contains($info['key'], 'PRI')); $column->autoIncrement(stripos($info['extra'], 'auto_increment') !== false); $column->comment($info['comment']); $column->dbType($dbType); - $column->unsigned(stripos($dbType, 'unsigned') !== false); - $column->type(self::TYPE_STRING); - - if (preg_match('/^(\w+)(?:\(([^)]+)\))?/', $dbType, $matches)) { - $type = strtolower($matches[1]); - - if (isset($this->typeMap[$type])) { - $column->type($this->typeMap[$type]); - } - - if (!empty($matches[2])) { - if ($type === 'enum') { - preg_match_all("/'[^']*'/", $matches[2], $values); - - foreach ($values[0] as $i => $value) { - $values[$i] = trim($value, "'"); - } - - $column->enumValues($values); - } else { - $values = explode(',', $matches[2]); - $column->precision((int) $values[0]); - $column->size((int) $values[0]); - - if (isset($values[1])) { - $column->scale((int) $values[1]); - } - - if ($type === 'bit') { - if ($column->getSize() === 1) { - $column->type(self::TYPE_BOOLEAN); - } elseif ($column->getSize() > 32) { - $column->type(self::TYPE_BIGINT); - } elseif ($column->getSize() === 32) { - $column->type(self::TYPE_INTEGER); - } - } - } - } - } // Chapter 2: crutches for MariaDB {@see https://github.com/yiisoft/yii2/issues/19747} $extra = $info['extra']; @@ -531,7 +475,7 @@ protected function loadColumnSchema(array $info): ColumnSchemaInterface empty($extra) && !empty($info['extra_default_value']) && !str_starts_with($info['extra_default_value'], '\'') - && in_array($column->getType(), [ + && in_array($type, [ self::TYPE_CHAR, self::TYPE_STRING, self::TYPE_TEXT, self::TYPE_DATETIME, self::TYPE_TIMESTAMP, self::TYPE_TIME, self::TYPE_DATE, ], true) @@ -540,7 +484,7 @@ protected function loadColumnSchema(array $info): ColumnSchemaInterface } $column->extra($extra); - $column->phpType($this->getColumnPhpType($column)); + $column->phpType($this->getColumnPhpType($type)); $column->defaultValue($this->normalizeDefaultValue($info['default'], $column)); if (str_starts_with($extra, 'DEFAULT_GENERATED')) { @@ -550,6 +494,45 @@ protected function loadColumnSchema(array $info): ColumnSchemaInterface return $column; } + /** + * Get the abstract data type for the database data type. + * + * @param string $dbType The database data type + * @param array $info Column information. + * + * @return string The abstract data type. + */ + private function getColumnType(string $dbType, array &$info): string + { + preg_match('/^(\w*)(?:\(([^)]+)\))?/', $dbType, $matches); + $dbType = strtolower($matches[1]); + + if (!empty($matches[2])) { + if ($dbType === 'enum') { + preg_match_all("/'([^']*)'/", $matches[2], $values); + $info['enum_values'] = $values[1]; + } else { + $values = explode(',', $matches[2], 2); + $info['size'] = (int) $values[0]; + $info['precision'] = (int) $values[0]; + + if (isset($values[1])) { + $info['scale'] = (int) $values[1]; + } + + if ($dbType === 'bit') { + return match (true) { + $info['size'] === 1 => self::TYPE_BOOLEAN, + $info['size'] > 32 => self::TYPE_BIGINT, + default => self::TYPE_INTEGER, + }; + } + } + } + + return $this->typeMap[$dbType] ?? self::TYPE_STRING; + } + /** * Converts column's default value according to {@see ColumnSchema::phpType} after retrieval from the database. * @@ -904,18 +887,6 @@ protected function resolveTableCreateSql(TableSchemaInterface $table): void $table->createSql($sql); } - /** - * Creates a column schema for the database. - * - * This method may be overridden by child classes to create a DBMS-specific column schema. - * - * @param string $name Name of the column. - */ - private function createColumnSchema(string $name): ColumnSchema - { - return new ColumnSchema($name); - } - /** * @throws Exception * @throws InvalidConfigException diff --git a/tests/ColumnSchemaTest.php b/tests/ColumnSchemaTest.php index ec89e1ce..03e629a7 100644 --- a/tests/ColumnSchemaTest.php +++ b/tests/ColumnSchemaTest.php @@ -9,9 +9,14 @@ use Throwable; use Yiisoft\Db\Exception\Exception; use Yiisoft\Db\Expression\JsonExpression; -use Yiisoft\Db\Mysql\ColumnSchema; use Yiisoft\Db\Mysql\Tests\Support\TestTrait; use Yiisoft\Db\Query\Query; +use Yiisoft\Db\Schema\Column\BinaryColumnSchema; +use Yiisoft\Db\Schema\Column\BooleanColumnSchema; +use Yiisoft\Db\Schema\Column\DoubleColumnSchema; +use Yiisoft\Db\Schema\Column\IntegerColumnSchema; +use Yiisoft\Db\Schema\Column\JsonColumnSchema; +use Yiisoft\Db\Schema\Column\StringColumnSchema; use Yiisoft\Db\Schema\SchemaInterface; use function str_repeat; @@ -45,12 +50,10 @@ public function testColumnBigInt(string $bigint): void public function testDbTypeCastJson(): void { - $columnSchema = new ColumnSchema('json'); + $columnSchema = new JsonColumnSchema('json'); - $columnSchema->dbType(SchemaInterface::TYPE_JSON); - $columnSchema->type(SchemaInterface::TYPE_JSON); - - $this->assertEquals(new JsonExpression('{"a":1}', SchemaInterface::TYPE_JSON), $columnSchema->dbTypeCast('{"a":1}')); + $this->assertSame('{"a":1}', $columnSchema->dbTypecast('{"a":1}')); + $this->assertEquals(new JsonExpression(['a' => 1], SchemaInterface::TYPE_JSON), $columnSchema->dbTypecast(['a' => 1])); } /** @@ -58,11 +61,9 @@ public function testDbTypeCastJson(): void */ public function testPhpTypeCastJson(): void { - $columnSchema = new ColumnSchema('json'); - - $columnSchema->type(SchemaInterface::TYPE_JSON); + $columnSchema = new JsonColumnSchema('json'); - $this->assertSame(['a' => 1], $columnSchema->phpTypeCast('{"a":1}')); + $this->assertSame(['a' => 1], $columnSchema->phpTypecast('{"a":1}')); } public function testPhpTypeCast(): void @@ -77,6 +78,7 @@ public function testPhpTypeCast(): void 'type', [ 'int_col' => 1, + 'bigunsigned_col' => 1234567890, 'char_col' => str_repeat('x', 100), 'char_col3' => null, 'float_col' => 1.234, @@ -93,6 +95,7 @@ public function testPhpTypeCast(): void $this->assertNotNull($tableSchema); $intColPhpType = $tableSchema->getColumn('int_col')?->phpTypecast($query['int_col']); + $bigUnsignedColPhpType = $tableSchema->getColumn('bigunsigned_col')?->phpTypecast($query['bigunsigned_col']); $charColPhpType = $tableSchema->getColumn('char_col')?->phpTypecast($query['char_col']); $charCol3PhpType = $tableSchema->getColumn('char_col3')?->phpTypecast($query['char_col3']); $floatColPhpType = $tableSchema->getColumn('float_col')?->phpTypecast($query['float_col']); @@ -103,6 +106,7 @@ public function testPhpTypeCast(): void $jsonColPhpType = $tableSchema->getColumn('json_col')?->phpTypecast($query['json_col']); $this->assertSame(1, $intColPhpType); + $this->assertSame(1234567890, $bigUnsignedColPhpType); $this->assertSame(str_repeat('x', 100), $charColPhpType); $this->assertNull($charCol3PhpType); $this->assertSame(1.234, $floatColPhpType); @@ -114,4 +118,18 @@ public function testPhpTypeCast(): void $db->close(); } + + public function testColumnSchemaInstance() + { + $db = $this->getConnection(true); + $schema = $db->getSchema(); + $tableSchema = $schema->getTableSchema('type'); + + $this->assertInstanceOf(IntegerColumnSchema::class, $tableSchema->getColumn('int_col')); + $this->assertInstanceOf(StringColumnSchema::class, $tableSchema->getColumn('char_col')); + $this->assertInstanceOf(DoubleColumnSchema::class, $tableSchema->getColumn('float_col')); + $this->assertInstanceOf(BinaryColumnSchema::class, $tableSchema->getColumn('blob_col')); + $this->assertInstanceOf(BooleanColumnSchema::class, $tableSchema->getColumn('bool_col')); + $this->assertInstanceOf(JsonColumnSchema::class, $tableSchema->getColumn('json_col')); + } } diff --git a/tests/Provider/SchemaProvider.php b/tests/Provider/SchemaProvider.php index 960578df..77e677d4 100644 --- a/tests/Provider/SchemaProvider.php +++ b/tests/Provider/SchemaProvider.php @@ -42,6 +42,20 @@ public static function columns(): array 'scale' => null, 'defaultValue' => 1, ], + 'bigunsigned_col' => [ + 'type' => 'bigint', + 'dbType' => 'bigint(20) unsigned', + 'phpType' => 'integer', + 'primaryKey' => false, + 'allowNull' => true, + 'autoIncrement' => false, + 'enumValues' => null, + 'size' => 20, + 'precision' => 20, + 'scale' => null, + 'unsigned' => true, + 'defaultValue' => '12345678901234567890', + ], 'tinyint_col' => [ 'type' => 'tinyint', 'dbType' => 'tinyint(3)', diff --git a/tests/SchemaTest.php b/tests/SchemaTest.php index a3e4e2d3..bae6eed2 100644 --- a/tests/SchemaTest.php +++ b/tests/SchemaTest.php @@ -15,10 +15,10 @@ use Yiisoft\Db\Exception\NotSupportedException; use Yiisoft\Db\Expression\Expression; use Yiisoft\Db\Mysql\Column; -use Yiisoft\Db\Mysql\ColumnSchema; use Yiisoft\Db\Mysql\Schema; use Yiisoft\Db\Mysql\Tests\Support\TestTrait; use Yiisoft\Db\Query\Query; +use Yiisoft\Db\Schema\Column\StringColumnSchema; use Yiisoft\Db\Schema\SchemaInterface; use Yiisoft\Db\Tests\Common\CommonSchemaTest; use Yiisoft\Db\Tests\Support\Assert; @@ -67,7 +67,7 @@ public function testAlternativeDisplayOfDefaultCurrentTimestampInMariaDB(): void 'comment' => '', ]]); - $this->assertInstanceOf(ColumnSchema::class, $column); + $this->assertInstanceOf(StringColumnSchema::class, $column); $this->assertInstanceOf(Expression::class, $column->getDefaultValue()); $this->assertEquals('CURRENT_TIMESTAMP', $column->getDefaultValue()); } @@ -96,7 +96,7 @@ public function testAlternativeDisplayOfDefaultCurrentTimestampAsNullInMariaDB() 'comment' => '', ]]); - $this->assertInstanceOf(ColumnSchema::class, $column); + $this->assertInstanceOf(StringColumnSchema::class, $column); $this->assertEquals(null, $column->getDefaultValue()); } diff --git a/tests/Support/Fixture/mysql.sql b/tests/Support/Fixture/mysql.sql index 92ea625b..f18170a6 100644 --- a/tests/Support/Fixture/mysql.sql +++ b/tests/Support/Fixture/mysql.sql @@ -148,6 +148,7 @@ CREATE TABLE `negative_default_values` ( CREATE TABLE `type` ( `int_col` integer NOT NULL, `int_col2` integer DEFAULT '1', + `bigunsigned_col` bigint unsigned DEFAULT '12345678901234567890', `tinyint_col` tinyint(3) DEFAULT '1', `smallint_col` smallint(1) DEFAULT '1', `char_col` char(100) NOT NULL, From 66e209ce08fca393d599683338adb054d468553b Mon Sep 17 00:00:00 2001 From: Tigrov Date: Fri, 1 Sep 2023 19:03:41 +0700 Subject: [PATCH 2/8] Revert testDbTypeCastJson() --- tests/ColumnSchemaTest.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/ColumnSchemaTest.php b/tests/ColumnSchemaTest.php index 03e629a7..45e304c8 100644 --- a/tests/ColumnSchemaTest.php +++ b/tests/ColumnSchemaTest.php @@ -52,8 +52,7 @@ public function testDbTypeCastJson(): void { $columnSchema = new JsonColumnSchema('json'); - $this->assertSame('{"a":1}', $columnSchema->dbTypecast('{"a":1}')); - $this->assertEquals(new JsonExpression(['a' => 1], SchemaInterface::TYPE_JSON), $columnSchema->dbTypecast(['a' => 1])); + $this->assertEquals(new JsonExpression('{"a":1}', SchemaInterface::TYPE_JSON), $columnSchema->dbTypeCast('{"a":1}')); } /** From 36b127e01ea91f5ed24b082f29074d10ba4eb398 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Fri, 1 Sep 2023 19:08:54 +0700 Subject: [PATCH 3/8] Refactor tests --- tests/ColumnSchemaTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ColumnSchemaTest.php b/tests/ColumnSchemaTest.php index 45e304c8..a14cbe36 100644 --- a/tests/ColumnSchemaTest.php +++ b/tests/ColumnSchemaTest.php @@ -5,7 +5,6 @@ namespace Yiisoft\Db\Mysql\Tests; use JsonException; -use PHPUnit\Framework\TestCase; use Throwable; use Yiisoft\Db\Exception\Exception; use Yiisoft\Db\Expression\JsonExpression; @@ -18,6 +17,7 @@ use Yiisoft\Db\Schema\Column\JsonColumnSchema; use Yiisoft\Db\Schema\Column\StringColumnSchema; use Yiisoft\Db\Schema\SchemaInterface; +use Yiisoft\Db\Tests\Common\CommonColumnSchemaTest; use function str_repeat; @@ -26,7 +26,7 @@ * * @psalm-suppress PropertyNotSetInConstructor */ -final class ColumnSchemaTest extends TestCase +final class ColumnSchemaTest extends CommonColumnSchemaTest { use TestTrait; From 81b488f67ce614a0c9253a61ad3d02fe47b84581 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Fri, 1 Sep 2023 21:41:06 +0700 Subject: [PATCH 4/8] Fix test issue for Mysql 8.0.17+ --- tests/SchemaTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/SchemaTest.php b/tests/SchemaTest.php index bae6eed2..fb0bd973 100644 --- a/tests/SchemaTest.php +++ b/tests/SchemaTest.php @@ -124,6 +124,11 @@ public function testColumnSchema(array $columns, string $tableName): void $columns['int_col2']['size'] = null; $columns['int_col2']['precision'] = null; + // bigunsigned_col Mysql 8.0.17+. + $columns['bigunsigned_col']['dbType'] = 'bigint unsigned'; + $columns['bigunsigned_col']['size'] = null; + $columns['bigunsigned_col']['precision'] = null; + // tinyint_col Mysql 8.0.17+. $columns['tinyint_col']['dbType'] = 'tinyint'; $columns['tinyint_col']['size'] = null; From 7b1b7c4a02f85d0007fadc3958fde27f8e5f4f35 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Tue, 5 Sep 2023 14:19:23 +0700 Subject: [PATCH 5/8] Add line to CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 033bc60f..9456eeb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ - Chg #297: Remove `QueryBuilder::getColumnType()` child method as legacy code (@Tigrov) - Enh #300: Refactor insert default values (@Tigrov) +- Enh #303: Implement `ColumnSchemaInterface` classes according to the data type of database table columns + for type casting performance. Related with yiisoft/db#752 (@Tigrov) ## 1.0.1 July 24, 2023 From 7e900d32866794b058a5538ef160e2fa0e779313 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Sat, 27 Apr 2024 18:02:29 +0700 Subject: [PATCH 6/8] Update according to main PR --- src/Schema.php | 5 +++-- tests/ColumnSchemaTest.php | 20 -------------------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/src/Schema.php b/src/Schema.php index 77eba03a..5ff6ee3d 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -461,7 +461,8 @@ private function loadColumnSchema(array $info): ColumnSchemaInterface $type = $this->getColumnType($dbType, $info); $isUnsigned = stripos($dbType, 'unsigned') !== false; /** @psalm-var ColumnInfoArray $info */ - $column = $this->createColumnSchema($type, $info['field'], unsigned: $isUnsigned); + $column = $this->createColumnSchema($type, unsigned: $isUnsigned); + $column->name($info['field']); $column->enumValues($info['enum_values'] ?? null); $column->size($info['size'] ?? null); $column->precision($info['precision'] ?? null); @@ -533,7 +534,7 @@ private function getColumnType(string $dbType, array &$info): string } } - return $this->TYPE_MAP[$dbType] ?? self::TYPE_STRING; + return self::TYPE_MAP[$dbType] ?? self::TYPE_STRING; } /** diff --git a/tests/ColumnSchemaTest.php b/tests/ColumnSchemaTest.php index a14cbe36..385b1dad 100644 --- a/tests/ColumnSchemaTest.php +++ b/tests/ColumnSchemaTest.php @@ -4,10 +4,8 @@ namespace Yiisoft\Db\Mysql\Tests; -use JsonException; use Throwable; use Yiisoft\Db\Exception\Exception; -use Yiisoft\Db\Expression\JsonExpression; use Yiisoft\Db\Mysql\Tests\Support\TestTrait; use Yiisoft\Db\Query\Query; use Yiisoft\Db\Schema\Column\BinaryColumnSchema; @@ -16,7 +14,6 @@ use Yiisoft\Db\Schema\Column\IntegerColumnSchema; use Yiisoft\Db\Schema\Column\JsonColumnSchema; use Yiisoft\Db\Schema\Column\StringColumnSchema; -use Yiisoft\Db\Schema\SchemaInterface; use Yiisoft\Db\Tests\Common\CommonColumnSchemaTest; use function str_repeat; @@ -48,23 +45,6 @@ public function testColumnBigInt(string $bigint): void $this->assertSame($bigint, $query['bigint_col']); } - public function testDbTypeCastJson(): void - { - $columnSchema = new JsonColumnSchema('json'); - - $this->assertEquals(new JsonExpression('{"a":1}', SchemaInterface::TYPE_JSON), $columnSchema->dbTypeCast('{"a":1}')); - } - - /** - * @throws JsonException - */ - public function testPhpTypeCastJson(): void - { - $columnSchema = new JsonColumnSchema('json'); - - $this->assertSame(['a' => 1], $columnSchema->phpTypecast('{"a":1}')); - } - public function testPhpTypeCast(): void { $db = $this->getConnection(true); From 02df1819e9c890fcd6f3dbfd49cda7ab4cfbd5a7 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Sun, 5 May 2024 08:35:04 +0700 Subject: [PATCH 7/8] Improve --- src/ColumnSchema.php | 96 ------------------------------- src/Schema.php | 3 +- tests/ColumnSchemaTest.php | 2 +- tests/Provider/SchemaProvider.php | 2 +- 4 files changed, 3 insertions(+), 100 deletions(-) delete mode 100644 src/ColumnSchema.php diff --git a/src/ColumnSchema.php b/src/ColumnSchema.php deleted file mode 100644 index 9d81cd14..00000000 --- a/src/ColumnSchema.php +++ /dev/null @@ -1,96 +0,0 @@ -name('id'); - * $column->allowNull(false); - * $column->dbType('int(11)'); - * $column->phpType('integer'); - * $column->type('integer'); - * $column->defaultValue(0); - * $column->autoIncrement(true); - * $column->primaryKey(true); - * ``` - * - * @psalm-suppress DeprecatedInterface - * @psalm-suppress DeprecatedClass - */ -final class ColumnSchema extends AbstractColumnSchema -{ - /** - * Converts the input value according to {@see phpType} after retrieval from the database. - * - * If the value is `null` or an {@see \Yiisoft\Db\Expression\Expression}, it won't be converted. - * - * @param mixed $value The value to convert. - * - * @throws JsonException If the value can't be decoded. - * - * @return mixed The converted value. - */ - public function phpTypecast(mixed $value): mixed - { - if ($value === null) { - return null; - } - - if ($this->getType() === SchemaInterface::TYPE_JSON) { - return json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR); - } - - /** @psalm-suppress DeprecatedClass */ - return parent::phpTypecast($value); - } - - /** - * Converts the input value according to {@see type} and {@see dbType} for use in a db query. - * - * If the value is `null` or an {@see \Yiisoft\Db\Expression\Expression}, it won't be converted. - * - * @param mixed $value The value to convert. - * - * @return mixed The converted value. This may also be an array containing the value as the first element and the - * PDO type as the second element. - */ - public function dbTypecast(mixed $value): mixed - { - if ($value === null || $value instanceof ExpressionInterface) { - return $value; - } - - if ($this->getType() === SchemaInterface::TYPE_JSON) { - return new JsonExpression($value, $this->getDbType()); - } - - /** @psalm-suppress DeprecatedClass */ - return parent::dbTypecast($value); - } -} diff --git a/src/Schema.php b/src/Schema.php index 5ff6ee3d..9230ff7b 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -223,7 +223,7 @@ protected function findColumns(TableSchemaInterface $table): bool } $column = $this->loadColumnSchema($info); - $table->column($column->getName(), $column); + $table->column($info['field'], $column); if ($column->isPrimaryKey()) { $table->primaryKey($column->getName()); @@ -488,7 +488,6 @@ private function loadColumnSchema(array $info): ColumnSchemaInterface } $column->extra($extra); - $column->phpType($this->getColumnPhpType($type)); $column->defaultValue($this->normalizeDefaultValue($info['default'], $column)); if (str_starts_with($extra, 'DEFAULT_GENERATED')) { diff --git a/tests/ColumnSchemaTest.php b/tests/ColumnSchemaTest.php index 385b1dad..1f026d0e 100644 --- a/tests/ColumnSchemaTest.php +++ b/tests/ColumnSchemaTest.php @@ -85,7 +85,7 @@ public function testPhpTypeCast(): void $jsonColPhpType = $tableSchema->getColumn('json_col')?->phpTypecast($query['json_col']); $this->assertSame(1, $intColPhpType); - $this->assertSame(1234567890, $bigUnsignedColPhpType); + $this->assertSame('1234567890', $bigUnsignedColPhpType); $this->assertSame(str_repeat('x', 100), $charColPhpType); $this->assertNull($charCol3PhpType); $this->assertSame(1.234, $floatColPhpType); diff --git a/tests/Provider/SchemaProvider.php b/tests/Provider/SchemaProvider.php index 77e677d4..880f597e 100644 --- a/tests/Provider/SchemaProvider.php +++ b/tests/Provider/SchemaProvider.php @@ -45,7 +45,7 @@ public static function columns(): array 'bigunsigned_col' => [ 'type' => 'bigint', 'dbType' => 'bigint(20) unsigned', - 'phpType' => 'integer', + 'phpType' => 'string', 'primaryKey' => false, 'allowNull' => true, 'autoIncrement' => false, From 0b9a0d6011f7d8291742ef61322f010cf7671258 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Sun, 5 May 2024 08:41:45 +0700 Subject: [PATCH 8/8] Fix psalm --- src/Schema.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Schema.php b/src/Schema.php index 9230ff7b..59d142fc 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -226,7 +226,7 @@ protected function findColumns(TableSchemaInterface $table): bool $table->column($info['field'], $column); if ($column->isPrimaryKey()) { - $table->primaryKey($column->getName()); + $table->primaryKey($info['field']); if ($column->isAutoIncrement()) { $table->sequenceName(''); }