Skip to content

Commit 17742cb

Browse files
egorrishesamdarkBizley
authored
don't convert int to string if db type of column is numeric (#18741)
* write adequate test for issue #14663 * don't convert int to string if db type of column is numeric (#14663) * fix bigint schema test for MySql >8.0.17 (#14663) * Update CHANGELOG.md * Update CHANGELOG.md * update phpdoc [ci skip] (#14663) * refactoring test case to make it clearer [ci skip] (#14663) * check `int unsigned` in `QueryBuilderTest::testInsertInteger()` (#14663) * Update Upgrade.md (#14663) * fix `int unsigned` schema test for MySql >8.0.17 (#14663) * fix `int unsigned` schema test for MySql <5.7 (#14663) Co-authored-by: Alexander Makarov <[email protected]> Co-authored-by: Bizley <[email protected]>
1 parent 8d43241 commit 17742cb

File tree

7 files changed

+84
-17
lines changed

7 files changed

+84
-17
lines changed

framework/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Yii Framework 2 Change Log
44
2.0.43 under development
55
------------------------
66

7+
- Bug #14663: Do not convert int to string if database type of a column is numeric (egorrishe)
78
- Bug #18650: Refactor `framework/assets/yii.activeForm.js` arrow function into traditional function for IE11 compatibility (marcovtwout)
89
- Enh #18724: Allow jQuery 3.6 to be installed (marcovtwout)
910
- Enh #18628: Added strings "software", and "hardware" to `$specials` array in `yii\helpers\BaseInflector` (kjusupov)

framework/UPGRADE.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ Upgrade from Yii 2.0.42
5555
-----------------------
5656

5757
* `yii\base\ErrorHandler` does not expose the `$_SERVER` information implicitely anymore.
58+
* The methods `phpTypecast()` and `dbTypecast()` of `yii\db\ColumnSchema` will no longer convert `$value` from `int` to
59+
`string`, if database column type is `INTEGER UNSIGNED` or `BIGINT UNSIGNED`.
60+
* I.e. it affects update and insert queries. For example:
61+
```php
62+
\Yii::$app->db->createCommand()->insert('{{some_table}}', ['int_unsigned_col' => 22])->execute();
63+
```
64+
will execute next SQL:
65+
```sql
66+
INSERT INTO `some_table` (`int_unsigned_col`) VALUES (22)
67+
```
5868

5969
Upgrade from Yii 2.0.41
6070
-----------------------

framework/db/ColumnSchema.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,13 @@ protected function typecast($value)
154154
// ensure type cast always has . as decimal separator in all locales
155155
return StringHelper::floatToString($value);
156156
}
157+
if (is_numeric($value)
158+
&& ColumnSchemaBuilder::CATEGORY_NUMERIC === ColumnSchemaBuilder::$typeCategoryMap[$this->type]
159+
) {
160+
// https://github.com/yiisoft/yii2/issues/14663
161+
return $value;
162+
}
163+
157164
return (string) $value;
158165
case 'integer':
159166
return (int) $value;

framework/db/ColumnSchemaBuilder.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
*
1717
* See [[SchemaBuilderTrait]] for more detailed description and usage examples.
1818
*
19+
* @property array $categoryMap mapping of abstract column types (keys) to type categories (values). (since version 2.0.8)
20+
*
1921
* @author Vasenin Matvey <[email protected]>
2022
* @since 2.0.6
2123
*/
@@ -81,9 +83,9 @@ class ColumnSchemaBuilder extends BaseObject
8183

8284
/**
8385
* @var array mapping of abstract column types (keys) to type categories (values).
84-
* @since 2.0.8
86+
* @since 2.0.43
8587
*/
86-
public $categoryMap = [
88+
public static $typeCategoryMap = [
8789
Schema::TYPE_PK => self::CATEGORY_PK,
8890
Schema::TYPE_UPK => self::CATEGORY_PK,
8991
Schema::TYPE_BIGPK => self::CATEGORY_PK,
@@ -106,6 +108,8 @@ class ColumnSchemaBuilder extends BaseObject
106108
Schema::TYPE_BOOLEAN => self::CATEGORY_NUMERIC,
107109
Schema::TYPE_MONEY => self::CATEGORY_NUMERIC,
108110
];
111+
112+
109113
/**
110114
* @var \yii\db\Connection the current database connection. It is used mainly to escape strings
111115
* safely when building the final column schema string.
@@ -289,6 +293,24 @@ public function __toString()
289293
return $this->buildCompleteString($format);
290294
}
291295

296+
/**
297+
* @return array mapping of abstract column types (keys) to type categories (values).
298+
* @since 2.0.43
299+
*/
300+
public function getCategoryMap()
301+
{
302+
return static::$typeCategoryMap;
303+
}
304+
305+
/**
306+
* @param array $categoryMap mapping of abstract column types (keys) to type categories (values).
307+
* @since 2.0.43
308+
*/
309+
public function setCategoryMap($categoryMap)
310+
{
311+
static::$typeCategoryMap = $categoryMap;
312+
}
313+
292314
/**
293315
* Builds the length/precision part of the column.
294316
* @return string

tests/data/mysql.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,10 @@ CREATE TABLE `negative_default_values` (
138138
CREATE TABLE `type` (
139139
`int_col` integer NOT NULL,
140140
`int_col2` integer DEFAULT '1',
141+
`int_col3` integer(11) unsigned DEFAULT '1',
141142
`tinyint_col` tinyint(3) DEFAULT '1',
142143
`smallint_col` smallint(1) DEFAULT '1',
144+
`bigint_col` bigint unsigned,
143145
`char_col` char(100) NOT NULL,
144146
`char_col2` varchar(100) DEFAULT 'something',
145147
`char_col3` text,

tests/framework/db/mysql/QueryBuilderTest.php

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -374,23 +374,22 @@ public function testIssue17449()
374374
public function testInsertInteger()
375375
{
376376
$db = $this->getConnection();
377-
378377
$command = $db->createCommand();
379378

380-
$sql = $command->insert(
381-
'{{customer}}',
382-
[
383-
'profile_id' => 22,
384-
]
385-
)->getRawSql();
386-
$this->assertEquals('INSERT INTO `customer` (`profile_id`) VALUES (22)', $sql);
379+
// int value should not be converted to string, when column is `int`
380+
$sql = $command->insert('{{type}}', ['int_col' => 22])->getRawSql();
381+
$this->assertEquals('INSERT INTO `type` (`int_col`) VALUES (22)', $sql);
387382

388-
$sql = $command->insert(
389-
'{{customer}}',
390-
[
391-
'profile_id' => '1000000000000',
392-
]
393-
)->getRawSql();
394-
$this->assertEquals('INSERT INTO `customer` (`profile_id`) VALUES (1000000000000)', $sql);
383+
// int value should not be converted to string, when column is `int unsigned`
384+
$sql = $command->insert('{{type}}', ['int_col3' => 22])->getRawSql();
385+
$this->assertEquals('INSERT INTO `type` (`int_col3`) VALUES (22)', $sql);
386+
387+
// int value should not be converted to string, when column is `bigint unsigned`
388+
$sql = $command->insert('{{type}}', ['bigint_col' => 22])->getRawSql();
389+
$this->assertEquals("INSERT INTO `type` (`bigint_col`) VALUES (22)", $sql);
390+
391+
// string value should not be converted
392+
$sql = $command->insert('{{type}}', ['bigint_col' => '1000000000000'])->getRawSql();
393+
$this->assertEquals("INSERT INTO `type` (`bigint_col`) VALUES ('1000000000000')", $sql);
395394
}
396395
}

tests/framework/db/mysql/SchemaTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,18 @@ public function getExpectedColumns()
150150
'scale' => null,
151151
'defaultValue' => 1,
152152
],
153+
'int_col3' => [
154+
'type' => 'integer',
155+
'dbType' => \version_compare($version, '8.0.17', '>') ? 'int unsigned' : 'int(11) unsigned',
156+
'phpType' => 'integer',
157+
'allowNull' => true,
158+
'autoIncrement' => false,
159+
'enumValues' => null,
160+
'size' => \version_compare($version, '8.0.17', '>') ? null : 11,
161+
'precision' => \version_compare($version, '8.0.17', '>') ? null : 11,
162+
'scale' => null,
163+
'defaultValue' => 1,
164+
],
153165
'tinyint_col' => [
154166
'type' => 'tinyint',
155167
'dbType' => \version_compare($version, '8.0.17', '>') ? 'tinyint' : 'tinyint(3)',
@@ -174,10 +186,24 @@ public function getExpectedColumns()
174186
'scale' => null,
175187
'defaultValue' => 1,
176188
],
189+
'bigint_col' => [
190+
'type' => 'bigint',
191+
'dbType' => \version_compare($version, '8.0.17', '>') ? 'bigint unsigned' : 'bigint(20) unsigned',
192+
'phpType' => 'string',
193+
'allowNull' => true,
194+
'autoIncrement' => false,
195+
'enumValues' => null,
196+
'size' => \version_compare($version, '8.0.17', '>') ? null : 20,
197+
'precision' => \version_compare($version, '8.0.17', '>') ? null : 20,
198+
'scale' => null,
199+
'defaultValue' => null,
200+
],
177201
]
178202
);
179203

180204
if (version_compare($version, '5.7', '<')) {
205+
$columns['int_col3']['phpType'] = 'string';
206+
181207
$columns['json_col']['type'] = 'text';
182208
$columns['json_col']['dbType'] = 'longtext';
183209
$columns['json_col']['phpType'] = 'string';

0 commit comments

Comments
 (0)