click_house-client 0.8.2 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 27b81975f1f934997c497bd13dd33b01e9808f96640bea06bd79dbedb1fdaafd
4
- data.tar.gz: 92534981627408a2654ea29bca98746e99c205064c3a8ecd863bc54a84662f9a
3
+ metadata.gz: f12c7192094a0cec94c354381b9be928dff901c03a9e8522dde43a695ce99b62
4
+ data.tar.gz: bedf93d6760663e747598c2cf9f60b90106b5d6979a7fe11dd00749cb03e4326
5
5
  SHA512:
6
- metadata.gz: 730256f383d8a48927fe2a9a13541dacf6c63300a899c68e647d5457757b32db840e43eab17f2b19b02bed86582e5dbec8bbaa32d24215c5efa9f0c528b32169
7
- data.tar.gz: '09e366a8fbb135fe7bb6eee89f7cdb98c3e91a70b350045cfebaeb2ec4db1bc459343e38d5eb902cc30ee1cba7b9ed2ddb10cb17e9726f791abe7dc1800e132b'
6
+ metadata.gz: 5fe06dbc303e5b94e72e84b0da50c96defa1be6445a77236ad29f49ed4283cb0e0d5ce147e5bafba671ac01d7064be5c3f0e4f80ff83ffe74eae7207f1b6a56e
7
+ data.tar.gz: a183e8f5081a5f1c4463e0b35c5fde96968023555c6b65ef4e5495a52650f747a224dfb468145cb3c5d5a55333e859398db6284952fec9c323f0bec3a4b6247e
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- click_house-client (0.8.2)
4
+ click_house-client (0.8.3)
5
5
  activerecord (>= 7.0, < 9.0)
6
6
  activesupport (>= 7.0, < 9.0)
7
7
  addressable (~> 2.8)
@@ -136,7 +136,7 @@ CHECKSUMS
136
136
  benchmark (0.4.1) sha256=d4ef40037bba27f03b28013e219b950b82bace296549ec15a78016552f8d2cce
137
137
  bigdecimal (3.2.2) sha256=39085f76b495eb39a79ce07af716f3a6829bc35eb44f2195e2753749f2fa5adc
138
138
  byebug (12.0.0) sha256=d4a150d291cca40b66ec9ca31f754e93fed8aa266a17335f71bb0afa7fca1a1e
139
- click_house-client (0.8.2)
139
+ click_house-client (0.8.3)
140
140
  concurrent-ruby (1.3.5) sha256=813b3e37aca6df2a21a3b9f1d497f8cbab24a2b94cab325bffe65ee0f6cbebc6
141
141
  connection_pool (2.5.3) sha256=cfd74a82b9b094d1ce30c4f1a346da23ee19dc8a062a16a85f58eab1ced4305b
142
142
  diff-lcs (1.5.0) sha256=49b934001c8c6aedb37ba19daec5c634da27b318a7a3c654ae979d6ba1929b67
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_record'
4
+
3
5
  module ClickHouse
4
6
  module Client
5
7
  class ArelVisitor < Arel::Visitors::ToSql
@@ -29,8 +29,13 @@ module ClickHouse
29
29
  Arel::Nodes::As
30
30
  ].freeze
31
31
 
32
- def initialize(table_name)
33
- @table = Arel::Table.new(table_name)
32
+ def initialize(table, alias_name = nil)
33
+ @table = if table.is_a?(self.class) # subquery
34
+ Arel::Nodes::TableAlias.new(table.to_arel, alias_name)
35
+ else
36
+ Arel::Table.new(table)
37
+ end
38
+
34
39
  @manager = Arel::SelectManager.new(Arel::Table.engine).from(@table).project(Arel.star)
35
40
  end
36
41
 
@@ -315,7 +320,9 @@ module ClickHouse
315
320
  end
316
321
 
317
322
  def to_redacted_sql(bind_index_manager = ClickHouse::Client::BindIndexManager.new)
318
- ClickHouse::Client::Redactor.redact(self, bind_index_manager)
323
+ visitor = ClickHouse::Client::ToRedactedSqlVisitor.new(ClickHouse::Client::ArelEngine.new,
324
+ bind_manager: bind_index_manager)
325
+ visitor.accept(manager.ast, Arel::Collectors::SQLString.new).value
319
326
  end
320
327
 
321
328
  def to_arel
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ClickHouse
4
+ module Client
5
+ # Redacts the SQL query represented by the query builder.
6
+ #
7
+ # Example:
8
+ # query_builder = ClickHouse::QueryBuilder.new('users').where(name: 'John Doe')
9
+ # redacted_query = query_builder.to_redacted_sql
10
+ # # The redacted_query will contain the SQL query with values replaced by placeholders.
11
+ # output: "SELECT * FROM \"users\" WHERE \"users\".\"name\" = $1"
12
+ class ToRedactedSqlVisitor < ArelVisitor
13
+ attr_reader :bind_manager
14
+
15
+ def initialize(*args, bind_manager: ClickHouse::Client::BindIndexManager.new)
16
+ @bind_manager = bind_manager
17
+ super(*args)
18
+ end
19
+
20
+ private
21
+
22
+ def redaction_enabled?
23
+ !!@redaction_enabled
24
+ end
25
+
26
+ def collect_nodes_for(nodes, collector, spacer, *args)
27
+ return super unless spacer.strip.in?(%w[WHERE HAVING])
28
+
29
+ redaction_was = @redaction_enabled
30
+ @redaction_enabled = true
31
+ super
32
+ @redaction_enabled = redaction_was
33
+ end
34
+
35
+ # rubocop:disable Naming/MethodName -- following Arel::Visitors::Visitor pattern
36
+ # rubocop:disable Naming/MethodParameterName -- following Arel::Visitors::Visitor pattern
37
+
38
+ def visit_Arel_Nodes_In(o, collector)
39
+ return super unless redaction_enabled?
40
+
41
+ return super if o.right.is_a? Arel::Nodes::SelectStatement
42
+
43
+ super(redact_right(o), collector)
44
+ end
45
+
46
+ def visit_Arel_Nodes_Equality(o, collector)
47
+ return super unless redaction_enabled?
48
+
49
+ super(redact_right(o), collector)
50
+ end
51
+
52
+ def visit_Arel_Nodes_LessThan(o, collector)
53
+ return super unless redaction_enabled?
54
+
55
+ super(redact_right(o), collector)
56
+ end
57
+
58
+ def visit_Arel_Nodes_LessThanOrEqual(o, collector)
59
+ return super unless redaction_enabled?
60
+
61
+ super(redact_right(o), collector)
62
+ end
63
+
64
+ def visit_Arel_Nodes_GreaterThan(o, collector)
65
+ return super unless redaction_enabled?
66
+
67
+ super(redact_right(o), collector)
68
+ end
69
+
70
+ def visit_Arel_Nodes_GreaterThanOrEqual(o, collector)
71
+ return super unless redaction_enabled?
72
+
73
+ super(redact_right(o), collector)
74
+ end
75
+
76
+ def visit_Arel_Nodes_NamedFunction(o, collector)
77
+ return super unless redaction_enabled?
78
+
79
+ redacted_o = Arel::Nodes::NamedFunction.new(o.name, o.expressions.dup)
80
+
81
+ case redacted_o.name
82
+ when 'startsWith'
83
+ redacted_o.expressions[1] = Arel.sql(bind_manager.next_bind_str)
84
+ else
85
+ redacted_o.expressions = redacted_o.expressions.map do
86
+ Arel.sql(bind_manager.next_bind_str)
87
+ end
88
+ end
89
+
90
+ super(redacted_o, collector)
91
+ end
92
+
93
+ def visit_Arel_Nodes_Matches(o, collector)
94
+ return super unless redaction_enabled?
95
+
96
+ super(redact_right(o), collector)
97
+ end
98
+
99
+ def redact_right(o)
100
+ cloned_o = o.clone
101
+
102
+ redacted_right = if o.right.is_a?(Array)
103
+ Array.new(o.right.size) do
104
+ Arel.sql(bind_manager.next_bind_str)
105
+ end
106
+ else
107
+ Arel.sql(bind_manager.next_bind_str)
108
+ end
109
+
110
+ cloned_o.right = redacted_right
111
+ cloned_o
112
+ end
113
+
114
+ # rubocop:enable Naming/MethodName
115
+ # rubocop:enable Naming/MethodParameterName
116
+ end
117
+ end
118
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ClickHouse
4
4
  module Client
5
- VERSION = "0.8.2"
5
+ VERSION = "0.8.3"
6
6
  end
7
7
  end
@@ -15,11 +15,11 @@ require_relative "client/quoting"
15
15
  require_relative "client/arel_engine"
16
16
  require_relative "client/query_like"
17
17
  require_relative "client/query"
18
- require_relative "client/redactor"
18
+ require_relative "client/arel_visitor"
19
+ require_relative "client/to_redacted_sql_visitor"
19
20
  require_relative "client/query_builder"
20
21
  require_relative "client/formatter"
21
22
  require_relative "client/response"
22
- require_relative "client/arel_visitor"
23
23
 
24
24
  module ClickHouse
25
25
  module Client
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: click_house-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.8.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - group::optimize
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-10-13 00:00:00.000000000 Z
11
+ date: 2025-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -193,8 +193,8 @@ files:
193
193
  - lib/click_house/client/query_builder.rb
194
194
  - lib/click_house/client/query_like.rb
195
195
  - lib/click_house/client/quoting.rb
196
- - lib/click_house/client/redactor.rb
197
196
  - lib/click_house/client/response.rb
197
+ - lib/click_house/client/to_redacted_sql_visitor.rb
198
198
  - lib/click_house/client/version.rb
199
199
  homepage: https://gitlab.com/gitlab-org/ruby/gems/clickhouse-client
200
200
  licenses:
@@ -1,93 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ClickHouse
4
- module Client
5
- module Redactor
6
- class << self
7
- # Redacts the SQL query represented by the query builder.
8
- #
9
- # @param query_builder [::ClickHouse::Querybuilder] The query builder object to be redacted.
10
- # @return [String] The redacted SQL query as a string.
11
- # @raise [ArgumentError] when the condition in the query is of an unsupported type.
12
- #
13
- # Example:
14
- # query_builder = ClickHouse::QueryBuilder.new('users').where(name: 'John Doe')
15
- # redacted_query = ClickHouse::Redactor.redact(query_builder)
16
- # # The redacted_query will contain the SQL query with values replaced by placeholders.
17
- # output: "SELECT * FROM \"users\" WHERE \"users\".\"name\" = $1"
18
- def redact(query_builder, bind_manager = ClickHouse::Client::BindIndexManager.new)
19
- redacted_constraints = query_builder.manager.constraints.map do |constraint|
20
- redact_constraint(constraint, bind_manager)
21
- end
22
-
23
- cloned_query_builder = query_builder.clone
24
-
25
- cloned_query_builder.manager.constraints.clear
26
- redacted_constraints.each do |constraint|
27
- cloned_query_builder.manager.where(constraint)
28
- end
29
-
30
- cloned_query_builder.to_sql
31
- end
32
-
33
- private
34
-
35
- def redact_constraint(constraint, bind_manager)
36
- case constraint
37
- when Arel::Nodes::In
38
- if constraint.right.is_a? Arel::Nodes::SelectStatement
39
- constraint.left.in(redact_select_statement(constraint.right, bind_manager))
40
- else
41
- constraint.left.in(Array.new(constraint.right.size) { Arel.sql(bind_manager.next_bind_str) })
42
- end
43
- when Arel::Nodes::Equality
44
- constraint.left.eq(Arel.sql(bind_manager.next_bind_str))
45
- when Arel::Nodes::LessThan
46
- constraint.left.lt(Arel.sql(bind_manager.next_bind_str))
47
- when Arel::Nodes::LessThanOrEqual
48
- constraint.left.lteq(Arel.sql(bind_manager.next_bind_str))
49
- when Arel::Nodes::GreaterThan
50
- constraint.left.gt(Arel.sql(bind_manager.next_bind_str))
51
- when Arel::Nodes::GreaterThanOrEqual
52
- constraint.left.gteq(Arel.sql(bind_manager.next_bind_str))
53
- when Arel::Nodes::NamedFunction
54
- redact_named_function(constraint, bind_manager)
55
- when Arel::Nodes::Matches
56
- constraint.left.matches(Arel.sql(bind_manager.next_bind_str), constraint.escape, constraint.case_sensitive)
57
- else
58
- raise ArgumentError, "Unsupported Arel node type for Redactor: #{constraint.class}"
59
- end
60
- end
61
-
62
- def redact_named_function(constraint, bind_manager)
63
- redacted_constraint =
64
- Arel::Nodes::NamedFunction.new(constraint.name, constraint.expressions.dup)
65
-
66
- case redacted_constraint.name
67
- when 'startsWith'
68
- redacted_constraint.expressions[1] = Arel.sql(bind_manager.next_bind_str)
69
- else
70
- redacted_constraint.expressions = redacted_constraint.expressions.map do
71
- Arel.sql(bind_manager.next_bind_str)
72
- end
73
- end
74
-
75
- redacted_constraint
76
- end
77
-
78
- def redact_select_statement(select_statement, bind_manager)
79
- cloned_statement = select_statement.clone
80
- cloned_statement.cores.map! do |select_core|
81
- select_core.wheres = select_core.wheres.map do |where|
82
- redact_constraint(where, bind_manager)
83
- end
84
-
85
- select_core
86
- end
87
-
88
- cloned_statement
89
- end
90
- end
91
- end
92
- end
93
- end