🫵

Gormでprepared statementのエラーの被害者へ

2023/10/11に公開

TL;DR

db, err := gorm.Open(postgres.New(postgres.Config{
	DSN:                  uri,
+	PreferSimpleProtocol: true,
}), &gorm.Config{})

そもそもprepared statementってなんだ

プリペアドステートメントとは、プログラム上で動的にSQL文を生成する必要があるとき、可変部分を変数のようにしたSQL文をあらかじめ作成しておき、値の挿入は処理系に行わせる方式。実行効率を向上させ、SQLインジェクションを防止する効果がある。(引用: https://e-words.jp/w/プリペアドステートメント.html)

prepared statement "stmtcache_1" already existsの原因

PGError: prepared statement “a30” already exists
​ (PGError: プリペアドステートメント “a30” がすでに存在します)
このエラーは、上記と似ています。プロトコル違反はありません。しかし、クライアントが誤って設定しようとしているプリペアドステートメントが既存ものと同じ名前で、元のプリペアドステートメントが除去されていません (エラーの中のプリペアドステートメントの名前は変化します)。
この原因も、一般には複数のプロセスまたはスレッド間で Postgres 接続の共有が適正に行われていないこと が挙げられます。(引用: https://devcenter.heroku.com/ja/articles/postgres-logs-errors)

つまり

接続が適切に行われていなかった。(筆者の場合はsupabaseを使用しており、dbのURIを取得して接続しているのみだった)

結論

SDKを使おう!(ない場合はprepared statementをオフにしましょ)

参考文献

https://e-words.jp/w/プリペアドステートメント.html

https://devcenter.heroku.com/ja/articles/postgres-logs-errors

Discussion