私が歌川です

@utgwkk が書いている

go-sql-driver/mysqlのプレースホルダ置換を有効にしつつJSONカラムを使うときは[]byte型を経由しない

tl;dr

  • JSONカラムをマッピングするときは []byte 型を使わない
  • string 型や json.RawMessage 型を使う

起こっていたこと

Goのwebアプリケーションで、go-sql-driver/mysqlの interpolateParams=true オプションを有効にしてテストを回したら、以下のようなエラーでテストが落ちた。 interpolateParams=true はプレースホルダ置換を有効にするオプションである*1

Cannot create a JSON value from a string with CHARACTER SET 'binary'.

アプリケーションのコードは interpolateParams=true を指定しただけで他の箇所は書き換えていない。MySQLと通信するときのcharacter setに binary を指定した覚えは全くない。何が起こっていたのか?

原因と解決策

DBの行をマップしているstructの構造をかいつまんで書くと以下の通り。JSON型のカラムを書き込むところでエラーになっていた。

type User struct {
  Id   string     `db:"id"`
  Data JsonColumn `db:"data"` // JSON NOT NULL
}

// JsonColumn は driver.Valuer, sql.Scanner を実装している
// 内部的に json.Marshal, json.Unmarshal を呼んでいる
type JsonColumn []byte

出てきたエラーメッセージで検索してみると以下のissueがヒットした。 JSON型のカラムをやり取りするときは []byte 型ではなく string 型や json.RawMessage 型を使うようにするといいらしい。

github.com

ということで、筆者が関わっているプロダクトではstructのフィールドの型を自由に調整できるのでこれで解決しました。

何が起こっていたのか

これだけで記事を終わっても備忘録*2としてはいいだろうけど、ついでなのでプレースホルダ置換を有効にしてエラーになったとき何が起こっていたのか見てみる。

mysqlConn structの interpolateParams メソッドの []byte 型に対する処理を読んでみると、文字列リテラルの前に _binary というのを書いていて、いかにもバイナリにしていそう。

github.com

これはイントロデューサというもので、文字列リテラルのcharacter setを指示しているらしい。謎が解けましたね。

dev.mysql.com

RubyKaigi 2023 follow upに参加した

しました。

rhc.connpass.com

聞いたトークのメモはScrapboxにまとめてあります。以下では特におもしろかったトピックを取り上げます。

scrapbox.io

Rubyの正規表現の改善について、ReDoSを回避できるようにするための取り組みが尊いというのと、正規表現の知らない機能が意外と多い!! というのが両立していました。現実の正規表現エンジンは、オートマトンの講義の文脈で習う「正規表現」よりも遥かに表現力が高くて考慮すべき点が多そうだけど、それらをちゃんとケアして現実の問題に反映していて最高。

Rubyのプロファイリング結果の可視化のためにFirefox Profilerを使うという発想がおもしろかったです。可視化は確かにノウハウのあるところに乗っかるほうが、自分でイチから作るよりも早くて見やすくできそう。個人的には、最近はOpenTelemetryによるトレーシング文脈での可視化が気になっています。

言語自体の自由度の高さと最適化しやすさのトレードオフみたいなのがありそうで、特にRubyだと既存のクラスに自由にメソッドを追加・オーバーライドできるのが大変そうでした。絶対やらないと思うけど理論的にはできてしまうのでちゃんとケアする、とか……。

Rubyの場合は、言語処理系や周辺エコシステムに貢献している人が身近に・国内にたくさんいて可視化されやすい、というのが他の言語から見たときにけっこう新鮮に見える、というのを実感しました。RubyKaigiで発表して終わり、ではなく続けて改善を進めていたり、RubyKaigiの発表に影響されて物作りを始めていたりしてよい流れができていそう。目の前にMatzがいて発表ごとにコメントしてもらえてよさそう。

カンファレンスに参加して学びがあって最高、というのはもちろんあるけど、カンファレンスのその後に焦点を当てることがなかなかない気がしていて、他のカンファレンスでも似たような取り組みがあったら参加したいですね。

go-sql-driver/mysqlを使ってMySQLの疎通確認を行うコマンドラインツールを書いた

絶対もうあるでしょう、と思いつつも書きました。go-sql-driver/mysql を使っているのでlibmysqlclientが入っていなくても動くと思います。

github.com

mysql コマンドでホスト名・ポート番号を指定して接続するのと同じコマンドライン引数が使えます。ほかのコマンドライン引数は必要になったら対応します。

$ go-mysqlping -h127.0.0.1 -P3306 -uroot -ppassword

1秒おきにDBアクセスしつつcontextでキャンセルできるようにする、みたいなのを初めて書いたけど意外と書けるものですね。time.Tickという関数があることは知っているけど、最初にアクセスするときに1秒待ってほしくないので手作りしています*1。goroutineがリークしていたら教えてください。

C102告知 日曜日 (8/13) 東地区 “フ” ブロック 21a

コミックマーケット102の告知です。

要約

最低限ここだけ読んでもらえれば十分です。

  • 日曜日 (8/13) 東地区 “フ” ブロック 21a
  • 新刊「わくわく活動報告 Go編」を100円で頒布します
  • 何らかのペーパーが出る可能性あり
  • キャッシュレス対応

薄い本が出ます

「わくわく活動報告 Go編」という薄い本が出ます。このブログでもいくつか記事を書いていると思いますが、最近書いたGoのコードや便利グッズの話を軽くまとめた本になります。

頒布価格は100円です。

既刊もたぶんあります

C100で頒布した「create-react-appの中身を見る」も頒布する予定です。

blog.utgw.net

最近のcreate-react-appの動向はどうなのか、という向きもあると思いますが、フロントエンドツールチェインについてなんとなく知る機会ということでいかがでしょうか*1

ペーパー

blog.pastak.net

id:Pasta-K さんの「2023年の良かった新作マンガ Ver.C102」が無料頒布される予定です。詳しくは当該記事をどうぞ。

キャッシュレス対応

各種クレジットカード (Visa/Mastercard/Amex/JCB/Diners Club/Discover) のタッチ決済に対応しています。現金支払いにも対応していますが、キャッシュレス支払いのほうが後から記録を正確に見返しやすいのでありがたいです。

*1:個人的には、在庫が掃けると嬉しい!!

27歳

7/28で27歳になりました。凪のような暮らしと、荒波のように手を動かし続ける暮らしを交互にやっていて、交互浴ですね。本当にそうか?

最近は、品質・手腕、システムに対する根源的な感情あたりについて考えることが増えたように思います。仕事って感じがしてきているんでしょうか。

相変わらず京都にいて、たまに東京にいるので、飲みに行きましょう。


とりあえず欲しい本のウィッシュリストを貼っておきます。ほかにもオススメの本がありましたらウィッシュリスト外から送ってください。

読書カテゴリScrapboxにある本は、読んだことがあるか、もしくは持っています。

blog.utgw.net