clickhouse-activerecord 1.6.1 → 1.6.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: 3e606a08261b2238dab5e6fbd6fb826fb40631ea063d9dcfc25d99aab052d619
4
- data.tar.gz: ad9281c124450ad0784c8442c4b20b3c8603f7028ca94f7aa1dbd73d8b0483d3
3
+ metadata.gz: 5bfabbcebb77881c7199f5895b1c3e4a7066c2eddaeec138432434f0a754fb70
4
+ data.tar.gz: a17ff604e9b01015f4a100f1e83267aad340c847541f8aeb0467d083afeb789a
5
5
  SHA512:
6
- metadata.gz: 70e11a39c963dedc824a9b5b54b805902691f9ed335a33796524ffd50c2f1a3bdea65709accc9847239123973c1b3f77fd675ca0ac40022195c54f5c9410ce96
7
- data.tar.gz: 768f6a409b98b66a80a6455d97fe4053f97dc60c35ee64d9a9a0310d64a6dbc00fe4b65bba90e7433114d536ed666f6716f2c1c05f13f34287f3e7f0905ebcb1
6
+ metadata.gz: 266b0794fe05ec58183b61cb7b7e8cefd99b44ce7fbc8a92810651f897dff514df09b48f16e8d50cdd394d7f00833039094caaf671c7e322a1a3b44c470b05df
7
+ data.tar.gz: afb3f2a22842ea4caef138ab206e73151fe237f89fa136c0fb2f4b1b160ff9e5594b4045224f8ab0c46512e1fe158eaf35cd698a66f4ff9d1542c69baebf9fa8
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ### Version 1.6.3 (Feb 04, 2026)
2
+
3
+ * Rename method `execute_streaming` to `execute_to_file`
4
+
5
+ ### Version 1.6.2 (Jan 30, 2026)
6
+
7
+ * Add streaming request and save response to tmp file
8
+
1
9
  ### Version 1.6.1 (Jan 20, 2026)
2
10
 
3
11
  * Fix prepare rake task on ClickHouse 24.6
data/README.md CHANGED
@@ -235,6 +235,14 @@ Action.with(ActionView.select(Arel.sql('min(date)')) => :min_date).where(Arel.sq
235
235
  #=> #<ActiveRecord::Relation [#<Action *** >]>
236
236
  ```
237
237
 
238
+ ### Streaming request
239
+
240
+ ```ruby
241
+ path = Action.connection.execute_to_file(Action.where(date: Date.current), format: 'CSVWithNames')
242
+ # Clickhouse Stream (10.3ms) SELECT actions.* FROM actions WHERE actions.date = '2017-11-29'
243
+ file = File.open(path)
244
+ ```
245
+
238
246
 
239
247
  ### Migration Data Types
240
248
 
@@ -53,6 +53,19 @@ module ActiveRecord
53
53
  end
54
54
  end
55
55
 
56
+ # Execute an SQL query and save the result to a file in stream mode
57
+ # @return [String]
58
+ def execute_to_file(sql, name = nil, format: @response_format, settings: {})
59
+ with_response_format(format) do
60
+ log(sql, [adapter_name, 'Stream', name].compact.join(' ')) do
61
+ statement = Statement.new(sql, format: @response_format)
62
+ request(statement, settings: settings) do |response|
63
+ return statement.streaming_response(response)
64
+ end
65
+ end
66
+ end
67
+ end
68
+
56
69
  def exec_insert(sql, name = nil, _binds = [], _pk = nil, _sequence_name = nil, returning: nil)
57
70
  new_sql = sql.sub(/ (DEFAULT )?VALUES/, " VALUES")
58
71
  with_response_format(nil) { execute(new_sql, name) }
@@ -268,8 +281,8 @@ module ActiveRecord
268
281
 
269
282
  def raw_execute(sql, settings: {}, except_params: [])
270
283
  statement = Statement.new(sql, format: @response_format)
271
- statement.response = request(statement, settings: settings, except_params: except_params)
272
- statement.processed_response
284
+ response = request(statement, settings: settings, except_params: except_params)
285
+ statement.processed_response(response)
273
286
  end
274
287
 
275
288
  # Make HTTP request to ClickHouse server
@@ -277,12 +290,13 @@ module ActiveRecord
277
290
  # @param [Hash] settings
278
291
  # @param [Array] except_params
279
292
  # @return [Net::HTTPResponse]
280
- def request(statement, settings: {}, except_params: [])
293
+ def request(statement, settings: {}, except_params: [], &block)
281
294
  @lock.synchronize do
282
- @connection.post("/?#{settings_params(settings, except: except_params)}",
283
- statement.formatted_sql,
284
- 'Content-Type' => 'application/x-www-form-urlencoded',
285
- 'User-Agent' => ClickhouseAdapter::USER_AGENT)
295
+ req = Net::HTTP::Post.new("/?#{settings_params(settings, except: except_params)}", {
296
+ 'Content-Type' => 'application/x-www-form-urlencoded',
297
+ 'User-Agent' => ClickhouseAdapter::USER_AGENT,
298
+ })
299
+ @connection.request(req, statement.formatted_sql, &block)
286
300
  end
287
301
  end
288
302
 
@@ -8,14 +8,18 @@ module ActiveRecord
8
8
 
9
9
  DB_EXCEPTION_REGEXP = /\ACode:\s+\d+\.\s+DB::Exception:/.freeze
10
10
 
11
+ # @param [Net::HTTPResponse] raw_response
12
+ # @param [String, nil] format
13
+ # @param [String] sql
11
14
  def initialize(raw_response, format, sql)
12
15
  @raw_response = raw_response
13
- @body = raw_response.body
14
16
  @format = format
15
17
  @sql = sql
16
18
  end
17
19
 
20
+ # @return [String, Hash, Array, nil]
18
21
  def process
22
+ @body = @raw_response.body
19
23
  if success?
20
24
  process_successful_response
21
25
  else
@@ -25,12 +29,28 @@ module ActiveRecord
25
29
  @body
26
30
  end
27
31
 
32
+ # @return [String, nil]
33
+ def streaming_process
34
+ file = Tempfile.new('clickhouse-activerecord', binmode: true)
35
+ if success?
36
+ @raw_response.read_body do |chunk|
37
+ file.write(chunk)
38
+ end
39
+ file.close
40
+ file.path
41
+ else
42
+ @body = @raw_response.body
43
+ raise_database_error!
44
+ end
45
+ end
46
+
28
47
  private
29
48
 
30
49
  def success?
31
50
  @raw_response.code.to_i == 200
32
51
  end
33
52
 
53
+ # @return [String, Hash, Array]
34
54
  def process_successful_response
35
55
  raise_generic!(@sql) if @body.include?('DB::Exception') && @body.match?(DB_EXCEPTION_REGEXP)
36
56
 
@@ -9,19 +9,27 @@ module ActiveRecord
9
9
  class Statement
10
10
 
11
11
  attr_reader :format
12
- attr_writer :response
13
12
 
14
13
  def initialize(sql, format:)
15
14
  @sql = sql
16
15
  @format = format
17
16
  end
18
17
 
18
+ # @return [String]
19
19
  def formatted_sql
20
20
  @formatted_sql ||= FormatManager.new(@sql, format: @format).apply
21
21
  end
22
22
 
23
- def processed_response
24
- ResponseProcessor.new(@response, @format, @sql).process
23
+ # @param [Net::HTTPResponse] response
24
+ # @return [String, Hash, Array, nil]
25
+ def processed_response(response)
26
+ ResponseProcessor.new(response, @format, @sql).process
27
+ end
28
+
29
+ # @param [Net::HTTPResponse] response
30
+ # @return [String, nil]
31
+ def streaming_response(response)
32
+ ResponseProcessor.new(response, @format, @sql).streaming_process
25
33
  end
26
34
 
27
35
  end
@@ -4,10 +4,13 @@ module ClickhouseActiverecord
4
4
  module TestHelper
5
5
  def before_setup
6
6
  super
7
+ original_connection_config = ActiveRecord::Base.connection_db_config
7
8
  ActiveRecord::Base.configurations.configurations.select { |x| x.env_name == Rails.env && x.adapter == 'clickhouse' }.each do |config|
8
9
  ActiveRecord::Base.establish_connection(config)
9
10
  ActiveRecord::Base.connection.truncate_tables(*ActiveRecord::Base.connection.tables)
10
11
  end
12
+ ensure
13
+ ActiveRecord::Base.establish_connection(original_connection_config) if original_connection_config
11
14
  end
12
15
  end
13
16
  end
@@ -2,9 +2,11 @@
2
2
 
3
3
  RSpec.configure do |config|
4
4
  config.before do
5
- ActiveRecord::Base.configurations.configurations.select { |x| x.env_name == Rails.env && x.adapter == 'clickhouse' }.each do |config|
6
- ActiveRecord::Base.establish_connection(config)
5
+ original_connection_config = ActiveRecord::Base.connection_db_config
6
+ ActiveRecord::Base.configurations.configurations.select { |x| x.env_name == Rails.env && x.adapter == 'clickhouse' }.each do |db_config|
7
+ ActiveRecord::Base.establish_connection(db_config)
7
8
  ActiveRecord::Base.connection.truncate_tables(*ActiveRecord::Base.connection.tables)
8
9
  end
10
+ ActiveRecord::Base.establish_connection(original_connection_config)
9
11
  end
10
12
  end
@@ -1,3 +1,3 @@
1
1
  module ClickhouseActiverecord
2
- VERSION = '1.6.1'
2
+ VERSION = '1.6.3'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clickhouse-activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.1
4
+ version: 1.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergey Odintsov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-01-20 00:00:00.000000000 Z
11
+ date: 2026-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler