click_house-client 0.12.0 → 0.13.0

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: 5513d15d8bf17295cf98d021b30650f46d0101a6d828b2620499f87a949f2e3d
4
- data.tar.gz: 27fd28cc07d8b67d8de72031de4e3c7e343cef51a3230afd96ba0adf3d24c252
3
+ metadata.gz: 839c38cadbcf3638fc513c949c9f7d1b40453c92c0274e32db1d1e9da86df156
4
+ data.tar.gz: f23d52098f04a9cdb460bf0d8479b19947641546b37ccd85519eeeaba3e59eb6
5
5
  SHA512:
6
- metadata.gz: b3d7bf7328dd7ab42b004e3e35e58c35b4869267e4a2e701f7d29f963c2c445c3d63f0bbd5e45db679cc4d2fda6880ef367aff18e0a04b1a030f54ede2317ead
7
- data.tar.gz: 40125fc9d75f13be2f1230ea872b72c6d01e797384674064d3fb42c613d1792c827e58d6ccfcd894b783ff4d89b838c04e9f50b2e297f4b085bba5c33b95585e
6
+ metadata.gz: 3c6f54deb213de89f6a5e2e5ad3cccf3e4b3412eb2b22624dc4fda38a41e8a21555736fa7b453fc2e7a07c1cf9fe6f07ef5f5b7bef0aee58019f0e7faa77604c
7
+ data.tar.gz: 2bbbcf502cba7cb5ed185674afd8eae30a28173ab599b2b00f582a21ed65a140b2d92b0ed523ad1dad192c35fbc0a5eb19ec98a3c815f7212f4f98d739795a53
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- click_house-client (0.11.0)
4
+ click_house-client (0.13.0)
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.11.0)
139
+ click_house-client (0.13.0)
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
data/README.md CHANGED
@@ -231,6 +231,28 @@ query.final.where(active: true).to_sql
231
231
 
232
232
  `FINAL` is currently applied only to the main `FROM` table. When joining, joined tables are not marked `FINAL`. Calling `.final` multiple times is idempotent.
233
233
 
234
+ ### Query Settings
235
+
236
+ Use `.settings` to append a ClickHouse
237
+ [`SETTINGS`](https://clickhouse.com/docs/en/sql-reference/statements/select#settings-in-select-query)
238
+ clause to the query. Chained calls merge, with later values overriding earlier ones.
239
+ Booleans are rendered as `1` / `0` and strings are quoted.
240
+
241
+ ```ruby
242
+ query.where(active: true).settings(max_execution_time: 60, use_query_cache: true).limit(10).to_sql
243
+ # => "SELECT * FROM `users` WHERE `users`.`active` = 'true' LIMIT 10 SETTINGS max_execution_time = 60, use_query_cache = 1"
244
+ ```
245
+
246
+ Settings belong to the query they are set on. When that builder is embedded as a
247
+ subquery, CTE, `UNION` member or `{var:Subquery}` placeholder, its `SETTINGS` clause is
248
+ rendered inside that part of the query, and ClickHouse applies it there:
249
+
250
+ ```ruby
251
+ subquery = ClickHouse::Client::QueryBuilder.new('orders').select(:user_id).settings(max_threads: 2)
252
+ query.where(id: subquery).to_sql
253
+ # => "SELECT * FROM `users` WHERE `users`.`id` IN (SELECT `orders`.`user_id` FROM `orders` SETTINGS max_threads = 2)"
254
+ ```
255
+
234
256
  ### Working with JOINs
235
257
 
236
258
  `#joins` supports `INNER JOIN` (default) and `LEFT OUTER JOIN` via
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'arel'
4
+
5
+ module ClickHouse
6
+ module Client
7
+ module ArelExtensions
8
+ module Nodes
9
+ # Holds the settings hash rendered as a trailing ClickHouse `SETTINGS` clause.
10
+ class Settings < ::Arel::Nodes::Unary
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -40,7 +40,20 @@ module ClickHouse
40
40
  collector << " FINAL"
41
41
  end
42
42
 
43
+ def visit_ClickHouse_Client_ArelExtensions_Nodes_Settings(object, collector)
44
+ rendered = object.expr.map { |name, value| "#{name} = #{quote_setting_value(value)}" }
45
+ collector << "SETTINGS #{rendered.join(', ')}"
46
+ end
47
+
43
48
  # rubocop:enable Naming/MethodName
49
+
50
+ def quote_setting_value(value)
51
+ case value
52
+ when true then '1'
53
+ when false then '0'
54
+ else ClickHouse::Client::Quoting.quote(value)
55
+ end
56
+ end
44
57
  end
45
58
  end
46
59
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'active_record'
4
4
  require_relative 'arel_extensions/nodes/final'
5
+ require_relative 'arel_extensions/nodes/settings'
5
6
 
6
7
  module ClickHouse
7
8
  module Client
@@ -30,6 +31,8 @@ module ClickHouse
30
31
  Arel::Nodes::As
31
32
  ].freeze
32
33
 
34
+ SETTING_NAME_REGEX = /\A[a-zA-Z_][a-zA-Z0-9_]*\z/
35
+
33
36
  delegate :[], to: :table
34
37
 
35
38
  def initialize(table, alias_name = nil)
@@ -224,6 +227,35 @@ module ClickHouse
224
227
  end
225
228
  end
226
229
 
230
+ # Appends a ClickHouse `SETTINGS` clause to the end of the query.
231
+ # See https://clickhouse.com/docs/en/sql-reference/statements/select#settings-in-select-query
232
+ #
233
+ # Chained calls merge settings; a later value overrides an earlier one.
234
+ # Boolean values are rendered as 1 / 0 and strings are quoted.
235
+ #
236
+ # Settings are part of the query AST, so they are also rendered when the
237
+ # builder is embedded as a subquery, CTE or UNION member, and ClickHouse
238
+ # applies them to that part of the query.
239
+ #
240
+ # @example
241
+ # query.settings(max_execution_time: 60, use_query_cache: true).to_sql
242
+ # # => "SELECT * FROM `test_table` SETTINGS max_execution_time = 60, use_query_cache = 1"
243
+ #
244
+ # @param new_settings [Hash{Symbol, String => Integer, Float, String, Symbol, Boolean}]
245
+ # @raise [ArgumentError] if a setting name or value is invalid
246
+ # @return [ClickHouse::Client::QueryBuilder] New instance of query builder.
247
+ def settings(new_settings)
248
+ new_settings.each { |name, value| validate_setting!(name, value) }
249
+
250
+ clone.tap do |new_instance|
251
+ ast = new_instance.manager.ast
252
+ merged = (ast.lock&.expr || {}).merge(new_settings.transform_keys(&:to_s)).freeze
253
+ # ClickHouse has no row locking, so the `lock` slot (rendered after LIMIT / OFFSET)
254
+ # is free to carry the SETTINGS clause.
255
+ ast.lock = ArelExtensions::Nodes::Settings.new(merged)
256
+ end
257
+ end
258
+
227
259
  def from(subquery, alias_name)
228
260
  clone.tap do |new_instance|
229
261
  new_from = if subquery.is_a?(self.class)
@@ -501,6 +533,16 @@ module ClickHouse
501
533
 
502
534
  private
503
535
 
536
+ def validate_setting!(name, value)
537
+ unless (name.is_a?(String) || name.is_a?(Symbol)) && name.to_s.match?(SETTING_NAME_REGEX)
538
+ raise ArgumentError, "Invalid setting name '#{name}'"
539
+ end
540
+
541
+ return if [Integer, Float, String, Symbol, TrueClass, FalseClass].any? { |klass| value.is_a?(klass) }
542
+
543
+ raise ArgumentError, "Invalid value for setting '#{name}': #{value.class.name}"
544
+ end
545
+
504
546
  def normalize_operand(operand)
505
547
  case operand
506
548
  when Arel::Expressions
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ClickHouse
4
4
  module Client
5
- VERSION = "0.12.0"
5
+ VERSION = "0.13.0"
6
6
  end
7
7
  end
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.12.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - group::optimize
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-08-04 00:00:00.000000000 Z
11
+ date: 2026-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -186,6 +186,7 @@ files:
186
186
  - lib/click_house/client.rb
187
187
  - lib/click_house/client/arel_engine.rb
188
188
  - lib/click_house/client/arel_extensions/nodes/final.rb
189
+ - lib/click_house/client/arel_extensions/nodes/settings.rb
189
190
  - lib/click_house/client/arel_visitor.rb
190
191
  - lib/click_house/client/configuration.rb
191
192
  - lib/click_house/client/database.rb