Closed3

Goとmysqlで開発していたときにびっくりしたメモ

koheiyamayamakoheiyamayama

前提

  • mysql 8.0.31
  • golang 1.19.5
  • mysqlのタイムゾーンはAsia/Tokyo

こんなテーブルがあったとする。

create table users (
  id int
  name varchar(255)
  login_at date
);
select *
from users 
where login_at >= begin
and login_at <= end

begin~end内にログインしたユーザーを取得する。

このときにGoだとこんな感じのコードがあるとする。

yearAndMonth := "2023-04"
// 月初
begin := time.Parse(DateOnly, yearAndMonth+"-01")
// 月末
end := begin.Add(0, 1, -1)

rows, err := mysql.ListUsersWithLoginAt(ctx, begin, end)
yearAndMonth := "2023-04"
// 月初
jst := time.FixedZone("Asia/Tokyo", 9*60*60)
beginning, err := time.ParseInLocation(times.DateTime, yearAndMonth+"-01 00:00:00", jst)
// 月末
end := begin.Add(0, 1, -1)

rows, err := mysql.ListUsersWithLoginAt(ctx, begin, end)

前者と後者で発行されるSQLに違いがある。

前者の場合

select *
from users 
where login_at >= "2023-04-01"
and login_at <= "2023-04-31"

後者の場合

select *
from users 
where login_at >= "2023-04-01 09:00:00'"
and login_at <= "2023-04-31 09:00:00'"

これがどうしてなのか調べる。
これだと本当は4/1にログインしたことのあるユーザーを検索したいのに、ヒットしない。

koheiyamayamakoheiyamayama

これはmysqlのコネクションにloc=Asia/Tokyoをつけたことも一因っぽい?
検証が必要。

koheiyamayamakoheiyamayama

もしかして、MySQLってARRAY式がなくて、

select u.id, u.name, p.id, p.title
from users as u
join posts as p
on p.user_id = u.id;

こんなSQLの結果を

type User struct {
  ID string
  Name string
  Posts []*Post
}

type Post struct {
  ID string
  Title string
}

にかんたんに変換できない?

このスクラップは2023/10/13にクローズされました