はじめに
こんにちは、SHOJIです。
本記事はDjangoで発生したエラー対応の備忘録です。
今回のエラーはプログラムの作りに問題があるゆえに発生したしょうもないエラーですが、こんな制限があるんだなーと面白く感じたので記事にしています。
Model.objects.filter() 実行でエラーが発生
DjangoのQuerySetでModel.objects.filter()を実行したところ、django.db.utils.OperationalError: too many SQL variables というエラーが発生しました。
エラーが発生した箇所のプログラムは、テーブルAのカラムaとカラムbが特定の組合せであれば取得するというもので、さらにその組合せのパターンが多数存在するものでした。
SQLで表すと、SELECT * FROM tableA WHERE (col_a = 'X1' AND col_b ='Y1') OR (col_a = 'X2' AND col_b ='Y2') ... のような形です。
エラーメッセージから予想がつくと思うのですが、上記のSQLを実現するため、プログラムでは必要な全ての条件をQオブジェクトにaddしfilterメソッドに渡していました。
conditions = Q()
conditions.add(Q(col_a ='X1', col_b ='Y1'), Q.OR)
conditions.add(Q(col_a ='X2', col_b ='Y2'), Q.OR)
tableA.objects.filter(conditions)
実際には、conditions.add() のところは条件数分ループを回しているので書き方は違うのですが、処理としてはこのようなことを行っています。
この場合、conditionsの条件数が500を超えると too many SQL variables のエラーが発生します。
はい、エラーメッセージがおっしゃる通りです。SQLの変数が多すぎますね……。
おわりに
というわけで、Model.objects.filter() のちょっと珍しいエラーについてでした。
普通はこんな雑なプログラムはソースレビューで弾かれるでしょうから、Djangoを使っていてもまず見ることはないかと思います。
そして、ここまで書いてふと思ったのですが、これって本当にDjango側で出しているエラーなんでしょうか。
もしかしたら上限はDBMSによって変わるかもしれないですね。手元にDjango環境がないので確認できていませんが、接続先のデータベースをSQLite3からPostgreSQLに変えてどうなるか試してみたいと思いました。
なお、そもそものプログラムが汚すぎる点については、テスト用の書き捨てプログラムであったということでお目こぼし願います笑