如何在 Arel 中"resuse"单个绑定变量?



我想用程序用Arel:用单绑定参数创建这个SQL

"users"."first_name" ILIKE $1 OR "users"."last_name" ILIKE $1

我试过了:

users = Arel::Table.new("users")
term = Arel::Nodes::BindParam.new("term") # what is the argument even used for?
users[:first_name].matches(p)
.or(
users[:last_name].matches(p)
)

但它导致了两个不同的绑定变量:

("users"."first_name" ILIKE $1 OR "users"."last_name" ILIKE $2)

有没有办法做到这一点,或者我应该只使用Arel::Nodes::SqlLiteral.new("$1")而不是BindParam

BindParam始终自动递增绑定变量,而不考虑参数。在此处添加绑定节点时

https://github.com/rails/rails/blob/v7.0.2.3/activerecord/lib/arel/visitors/to_sql.rb#L746

def visit_Arel_Nodes_BindParam(o, collector)
collector.add_bind(o.value, &bind_block) # o.value # => 'term'
end

最后的值只是来自自动递增的@bind_index,这里是

https://github.com/rails/rails/blob/v7.0.2.3/activerecord/lib/arel/collectors/sql_string.rb#L15

def add_bind(bind) # bind # => 'term'
self << yield(@bind_index)
@bind_index += 1
self
end

此时未使用BindParam参数。当构建完整的ActiveRecord查询(如Arel::Collectors::SubstituteBinds(时涉及其他收集器时,会使用它https://github.com/rails/rails/blob/v7.0.2.3/activerecord/lib/arel/collectors/substitute_binds.rb#L18

def add_bind(bind)
bind = bind.value_for_database if bind.respond_to?(:value_for_database)
self << quoter.quote(bind)
end

如果不创建自定义收集器类,除了Arel::Nodes::SqlLiteral.new("$1"),我看不到任何其他选项。

相关内容

  • 没有找到相关文章

最新更新