今日は、MySQL 8.0.28でもとに戻った「解決されたブール式の型」についての日。
目次
とある日
昨日MySQL リリースノートでわいわい言う勉強会 8.0.28に参加してきました。
仕事があったので途中からの参加でしたがためになりました。
その中の話題として上がった、MySQL8.0.28のリリース内容でINT
符号付きに戻った話について調べてた内容記録します。
MySQL 8.0.28変更内容について
今回調べる変更について記述します。
以前の問題に対するMySQL8.0.27の修正により、型の処理を簡素化するために、解決されたブール式の型が
INT
符号付きから符号なしBIGINT
に変更されましたが、無害なメタデータの変更として表示されたものが、一部のMySQLコネクタに問題を引き起こすことが判明しました。
max_length
メタデータの変更を元に戻し、整数の否定を少なくとも2文字に 調整することで、元の問題に対して別の修正を提供します 。(バグ#33516898)参照:この問題は、バグ#33117410のリグレッションです。
MySQL :: MySQL8.0リリースノート:: MySQL 8.0.28での変更(2022-01-18、一般提供)
MySQL8.0.27の修正により、解決されたブール式の型が INT
符号付きから符号なし BIGINT
に変更されました。
しかし、問題が発生するためMySQL8.0.28の修正でもとに戻りました。
バージョンの差分も検証してみます。
解決されたブール式の型について分かりづらいですが下記のような結果のことを指してます。
mysql> SELECT 10 IS TRUE; +------------+ | 10 IS TRUE | +------------+ | 1 | +------------+ 1 row in set (0.00 sec)
型について
変更内容について理解するためにそれぞれの型について軽くおさらいします。
MySQLは、SQL標準の整数型であるINTEGER(またはINT)とSMALLINTをサポートしています。標準の拡張として、MySQLはTINYINT、MEDIUMINT、およびBIGINTの各整数型もサポートしています。次の表は、各整数型に必要なストレージと範囲を示しています。
INT/BIGINT
SQLで整数型を表す型です。
INT
とBIGINT
の違いとしてわかりやすいのが扱える値の範囲が異なる点です。
タイプ | ストレージ(バイト) | 署名された最小値 | 符号なしの最小値 | 署名された最大値 | 符号なしの最大値 |
---|---|---|---|---|---|
INT |
4 | -2147483648 |
0 |
2147483647 |
4294967295 |
BIGINT |
8 | -2^63 |
0 |
2^63-1 |
2^64-1 |
INT[(*
M*)] [UNSIGNED] [ZEROFILL]
普通サイズの整数。 符号付きの範囲は
-2147483648
から2147483647
です。 符号なしの範囲は0
から4294967295
です。BIGINT[(
M
)] [UNSIGNED] [ZEROFILL]大きい整数。 符号付きの範囲は
-9223372036854775808
から9223372036854775807
です。 符号なしの範囲は0
から18446744073709551615
です。
符号あり/なし
負数を扱わない型として定義する際に使用します。
符号なし整数型とは、整数を格納するデータ型の一種で、0と正の数のみを表現できる整数型。単純に全ビットを2進数の各桁に対応付けて数を表す。
MySQLだと下記のように指定します。
CREATE TABLE test2 ( i int UNSIGNED PRIMARY KEY AUTO_INCREMENT ); mysql> desc test2; +-------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+----------------+ | i | int unsigned | NO | PRI | NULL | auto_increment | +-------+--------------+------+-----+---------+----------------+ 1 row in set (0.00 sec)
バージョン検証
では実際にどうなる変化があるのかを検証してみます。
検証環境は下記の3つです。
- MySQL8.0.26(
INT
符号付き) - MySQL8.0.27(
BIGINT
符号なし) - MySQL8.0.28(
INT
符号付き)
環境はdocker-composeでサックと構築してやります。
接続する前に、メタデータで型をチェックする方法を記述します。
--column-type-infoについて
MySQLに接続するときにオプションとして設定すると、実行結果にメタデータが表示されるようになります。
結果セットのメタデータを表示します。
root@1b7dbcd9e302:/# mysql -u docker -p --column-type-info Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 15 Server version: 8.0.28 MySQL Community Server - GPL Copyright (c) 2000, 2022, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> select 1; Field 1: `1` Catalog: `def` Database: `` Table: `` Org_table: `` Type: LONGLONG Collation: binary (63) Length: 2 Max_length: 1 Decimals: 0 Flags: NOT_NULL BINARY NUM +---+ | 1 | +---+ | 1 | +---+ 1 row in set (0.00 sec)
ここの部分がそれに該当します。
Field 1: `1` Catalog: `def` Database: `` Table: `` Org_table: `` Type: LONGLONG Collation: binary (63) Length: 2 Max_length: 1 Decimals: 0 Flags: NOT_NULL BINARY NUM
MySQL8.0.27
先にMySQL8.0.27で変更された内容を確認します。
mysql> select version(); Field 1: `version()` Catalog: `def` Database: `` Table: `` Org_table: `` Type: VAR_STRING Collation: utf8mb4_0900_ai_ci (255) Length: 24 Max_length: 6 Decimals: 31 Flags: NOT_NULL +-----------+ | version() | +-----------+ | 8.0.27 | +-----------+ 1 row in set (0.01 sec) mysql> SELECT 10 IS TRUE; Field 1: `10 IS TRUE` Catalog: `def` Database: `` Table: `` Org_table: `` Type: LONGLONG Collation: binary (63) Length: 1 Max_length: 1 Decimals: 0 Flags: NOT_NULL UNSIGNED BINARY NUM +------------+ | 10 IS TRUE | +------------+ | 1 | +------------+ 1 row in set (0.00 sec)
Flags: NOT_NULL UNSIGNED BINARY NUM
結果にUNSIGNED がある通り符号なしという結果となっています。
MySQL8.0.26
mysql> select version(); Field 1: `version()` Catalog: `def` Database: `` Table: `` Org_table: `` Type: VAR_STRING Collation: utf8mb4_0900_ai_ci (255) Length: 24 Max_length: 6 Decimals: 31 Flags: NOT_NULL +-----------+ | version() | +-----------+ | 8.0.26 | +-----------+ 1 row in set (0.00 sec) mysql> SELECT 10 IS TRUE; Field 1: `10 IS TRUE` Catalog: `def` Database: `` Table: `` Org_table: `` Type: LONGLONG Collation: binary (63) Length: 1 Max_length: 1 Decimals: 0 Flags: NOT_NULL BINARY NUM +------------+ | 10 IS TRUE | +------------+ | 1 | +------------+ 1 row in set (0.00 sec)
以前のバージョンだとUNSIGNEDは表示されません。
MySQL8.0.28
mysql> select version(); Field 1: `version()` Catalog: `def` Database: `` Table: `` Org_table: `` Type: VAR_STRING Collation: utf8mb4_0900_ai_ci (255) Length: 24 Max_length: 6 Decimals: 31 Flags: NOT_NULL +-----------+ | version() | +-----------+ | 8.0.28 | +-----------+ 1 row in set (0.00 sec) mysql> SELECT 10 IS TRUE; Field 1: `10 IS TRUE` Catalog: `def` Database: `` Table: `` Org_table: `` Type: LONGLONG Collation: binary (63) Length: 1 Max_length: 1 Decimals: 0 Flags: NOT_NULL BINARY NUM +------------+ | 10 IS TRUE | +------------+ | 1 | +------------+ 1 row in set (0.00 sec)
最新のバージョンでも、UNSIGNEDが表示されません。
おまけ
リリースノートであったバクについて見てみました。
MySQLのバグ:#105481:BIGINT UNSIGNED値:SELECT(2 <3)* -1;
MySQL8.0.27だとERRORになります。
mysql> select (2 < 3) * -1; ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((2 < 3) * -(1))' mysql>
理屈としては、(2 < 3)の結果で「1」BIGINT符号なしが返ってきます。
そのため負数をかけると符号なしなのでエラーになるということです。
MySQL8.0.28だと結果が表示されます。
mysql> select (2 < 3) * -1; Field 1: `(2 < 3) * -1` Catalog: `def` Database: `` Table: `` Org_table: `` Type: LONGLONG Collation: binary (63) Length: 3 Max_length: 2 Decimals: 0 Flags: NOT_NULL BINARY NUM +--------------+ | (2 < 3) * -1 | +--------------+ | -1 | +--------------+ 1 row in set (0.00 sec)
〆
勉強会はすごい人達ばかりなのですごく勉強になりました。
リリースノート見ててもわからないことを聞いたりできる場なのですごいためになりました。