今日はなにの日。

気になったこと勉強になったことのメモ。

今日は、MySQL 8.0.28でもとに戻った「解決されたブール式の型」についての日。

目次

とある日

昨日MySQL リリースノートでわいわい言う勉強会 8.0.28に参加してきました。

仕事があったので途中からの参加でしたがためになりました。

その中の話題として上がった、MySQL8.0.28のリリース内容でINT符号付きに戻った話について調べてた内容記録します。

MySQL 8.0.28変更内容について

今回調べる変更について記述します。

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の各整数型もサポートしています。次の表は、各整数型に必要なストレージと範囲を示しています。

MySQL :: MySQL 8.0 Reference Manual :: 11.1.2 Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT

INT/BIGINT

SQLで整数型を表す型です。

INTBIGINTの違いとしてわかりやすいのが扱える値の範囲が異なる点です。

タイプ ストレージ(バイト) 署名された最小値 符号なしの最小値 署名された最大値 符号なしの最大値
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 です。

    MySQL :: MySQL 8.0 リファレンスマニュアル :: 11.1.1 数値データ型の構文

符号あり/なし

負数を扱わない型として定義する際に使用します。

符号なし整数型とは、整数を格納するデータ型の一種で、0と正の数のみを表現できる整数型。単純に全ビットを2進数の各桁に対応付けて数を表す。

符号なし整数型(unsigned integer type)とは - IT用語辞典 e-Words

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に接続するときにオプションとして設定すると、実行結果にメタデータが表示されるようになります。

結果セットのメタデータを表示します。

MySQL :: MySQL 8.0 リファレンスマニュアル :: 4.5.1.1 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)

勉強会はすごい人達ばかりなのですごく勉強になりました。

リリースノート見ててもわからないことを聞いたりできる場なのですごいためになりました。