rails/activerecord/lib/arel/update_manager.rb
Jean Boussier 8e6a5deca6 Relation#where build BoundSqlLiteral rather than eagerly interpolate
Ref: https://github.com/rails/rails/pull/50793

To make not caching connection checkout viable, we need to reduced
the amount of places where we need a connection.

Once big source of this is query/relation building, where in many
cases it eagerly quote and interpolation bound values in SQL fragments.

Doing this requires an active connection because both MySQL and Postgres
may quote values differently based on the connection settings.

Instead of eagerly doing all this, we can instead just insert these
as bound values in the Arel AST. For adapters with prepared statements
this is better anyway as it will avoid leaking statements, and for those
that don't support it, it will simply delay the quoting to just
before the query is executed.

However, the `%` API (`where("title = %s", something)`) can't realistically
be fixed this way, but I don't see much value in it and it probably should
be deprecated and removed.
2024-02-21 13:22:55 +01:00

50 lines
1007 B
Ruby

# frozen_string_literal: true
module Arel # :nodoc: all
class UpdateManager < Arel::TreeManager
include TreeManager::StatementMethods
def initialize(table = nil)
@ast = Nodes::UpdateStatement.new(table)
end
###
# UPDATE +table+
def table(table)
@ast.relation = table
self
end
def set(values)
case values
when String, Nodes::BoundSqlLiteral
@ast.values = [values]
else
@ast.values = values.map { |column, value|
Nodes::Assignment.new(
Nodes::UnqualifiedColumn.new(column),
value
)
}
end
self
end
def group(columns)
columns.each do |column|
column = Nodes::SqlLiteral.new(column) if String === column
column = Nodes::SqlLiteral.new(column.to_s) if Symbol === column
@ast.groups.push Nodes::Group.new column
end
self
end
def having(expr)
@ast.havings << expr
self
end
end
end