Rails 5.2: 如何将 'where' 中数组的 Postgres 特定解释恢复为参数化 IN 子句?
Rails 5.2: how do I revert the Postgres specific interpretation of an array in 'where' as a parameterized IN clause?
从 Rails 5.1 升级到 Rails 5.2 后,仅针对 Postgres(使用 pg gem,但不使用 MySql)执行查询,如 Foo.where(id: [1, 2, 3])
从 SELECT "foos".* FROM "foos" WHERE "foos"."id" IN (1, 2, 3)
更改为 SELECT "foos".* FROM "foos" WHERE "foos"."id" IN (, , ) [["id", 1], ["id", 2], ["id", 3]]
。
这不是一个不合理的改变,除了 PG 在参数化查询中有 ~65K 参数的限制,而 IN 子句中值的数量的唯一限制是查询字符串的总大小,这将导致中断如果我们升级到 5.2,生产系统中的行为。
有谁知道是否可以在不降级的情况下恢复到旧行为 Rails?除非有关于此更改的任何文档的任何指针?
谢谢。
哎呀,这是一个不幸的边缘案例。
它没有具体记录,因为它只是所有查询参数绑定化一般过程的另一个步骤。
最好的建议是不要那样做:如果这些 ID 来自数据库,请使用子查询而不是通过应用程序层将它们弹回。 (我见过很多应用程序在子查询等效代码更少且数据库效率更高时强制使用 ID 列表。)如果它们来自其他地方并且您别无选择,我会尝试将查询安排在允许将它们分成 50k 或类似的集合的方式。
无法请求旧行为...如果您需要,您可能必须编写自己的查询片段生成器:
# Obviously be very careful when doing this; we're deliberately avoiding
# the feature that normally protects against SQL injection
foos.where("id IN (#{[1, 2, 3].map(&:to_i).join(",")})")
您 不必 去那么原始 -- 稍微安全一些
foos.where(Foo.sanitize_sql(["id IN (?)", [1, 2, 3]]))
...但是虽然现在可以使用,但该方法完全有可能在未来(6.0 或更高版本)版本中开始使用绑定。
从 Rails 5.1 升级到 Rails 5.2 后,仅针对 Postgres(使用 pg gem,但不使用 MySql)执行查询,如 Foo.where(id: [1, 2, 3])
从 SELECT "foos".* FROM "foos" WHERE "foos"."id" IN (1, 2, 3)
更改为 SELECT "foos".* FROM "foos" WHERE "foos"."id" IN (, , ) [["id", 1], ["id", 2], ["id", 3]]
。
这不是一个不合理的改变,除了 PG 在参数化查询中有 ~65K 参数的限制,而 IN 子句中值的数量的唯一限制是查询字符串的总大小,这将导致中断如果我们升级到 5.2,生产系统中的行为。
有谁知道是否可以在不降级的情况下恢复到旧行为 Rails?除非有关于此更改的任何文档的任何指针?
谢谢。
哎呀,这是一个不幸的边缘案例。
它没有具体记录,因为它只是所有查询参数绑定化一般过程的另一个步骤。
最好的建议是不要那样做:如果这些 ID 来自数据库,请使用子查询而不是通过应用程序层将它们弹回。 (我见过很多应用程序在子查询等效代码更少且数据库效率更高时强制使用 ID 列表。)如果它们来自其他地方并且您别无选择,我会尝试将查询安排在允许将它们分成 50k 或类似的集合的方式。
无法请求旧行为...如果您需要,您可能必须编写自己的查询片段生成器:
# Obviously be very careful when doing this; we're deliberately avoiding
# the feature that normally protects against SQL injection
foos.where("id IN (#{[1, 2, 3].map(&:to_i).join(",")})")
您 不必 去那么原始 -- 稍微安全一些
foos.where(Foo.sanitize_sql(["id IN (?)", [1, 2, 3]]))
...但是虽然现在可以使用,但该方法完全有可能在未来(6.0 或更高版本)版本中开始使用绑定。