diff options
Diffstat (limited to 'lib/click_house/redactor.rb')
-rw-r--r-- | lib/click_house/redactor.rb | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/lib/click_house/redactor.rb b/lib/click_house/redactor.rb new file mode 100644 index 00000000000..9b8e2bc90d9 --- /dev/null +++ b/lib/click_house/redactor.rb @@ -0,0 +1,53 @@ +# 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 |