54 lines
2.1 KiB
Ruby
54 lines
2.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# rubocop:disable CodeReuse/ActiveRecord
|
|
module ClickHouse
|
|
module Redactor
|
|
# Redacts the SQL query represented by the query builder.
|
|
#
|
|
# @param query_builder [::ClickHouse::Querybuilder] The query builder object to be redacted.
|
|
# @return [String] The redacted SQL query as a string.
|
|
# @raise [ArgumentError] when the condition in the query is of an unsupported type.
|
|
#
|
|
# Example:
|
|
# query_builder = ClickHouse::QueryBuilder.new('users').where(name: 'John Doe')
|
|
# redacted_query = ClickHouse::Redactor.redact(query_builder)
|
|
# # The redacted_query will contain the SQL query with values replaced by placeholders.
|
|
# output: "SELECT * FROM \"users\" WHERE \"users\".\"name\" = $1"
|
|
def self.redact(query_builder)
|
|
cloned_query_builder = query_builder.clone
|
|
bind_manager = ::ClickHouse::BindIndexManager.new
|
|
|
|
cloned_query_builder.conditions = cloned_query_builder.conditions.map do |condition|
|
|
redact_condition(condition, bind_manager)
|
|
end
|
|
|
|
cloned_query_builder.manager.constraints.clear
|
|
cloned_query_builder.conditions.each do |condition|
|
|
cloned_query_builder.manager.where(condition)
|
|
end
|
|
|
|
cloned_query_builder.manager.to_sql
|
|
end
|
|
|
|
def self.redact_condition(condition, bind_manager)
|
|
case condition
|
|
when Arel::Nodes::In
|
|
condition.left.in(Array.new(condition.right.size) { Arel.sql(bind_manager.next_bind_str) })
|
|
when Arel::Nodes::Equality
|
|
condition.left.eq(Arel.sql(bind_manager.next_bind_str))
|
|
when Arel::Nodes::LessThan
|
|
condition.left.lt(Arel.sql(bind_manager.next_bind_str))
|
|
when Arel::Nodes::LessThanOrEqual
|
|
condition.left.lteq(Arel.sql(bind_manager.next_bind_str))
|
|
when Arel::Nodes::GreaterThan
|
|
condition.left.gt(Arel.sql(bind_manager.next_bind_str))
|
|
when Arel::Nodes::GreaterThanOrEqual
|
|
condition.left.gteq(Arel.sql(bind_manager.next_bind_str))
|
|
else
|
|
raise ArgumentError, "Unsupported Arel node type for Redactor: #{condition.class}"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
# rubocop:enable CodeReuse/ActiveRecord
|