clickhouse-rb 0.1.0 → 0.2.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: a02afdcdcdd890944f581300c9ff98218ec8b7458d7dee112d35d8c0a1ce947b
4
- data.tar.gz: d09c320b71796475a012155a2d9b8b8b845e638c947e7e9551f22bd6fcbb1288
3
+ metadata.gz: 1ccbd22754bea20c9ca9fed064ef2b4e7a5cf936b9e6c8c3f819f732adfc25e7
4
+ data.tar.gz: 9537ffae5678fa0bf7ffbdd7b0cbb505aa66a8471072271765e98e99456a7f9d
5
5
  SHA512:
6
- metadata.gz: 9882fa7f3d7e3727922536b05523405678806ad3b57be3094bddfa4e6430fb10ae86148b05582a6e648efa662a15cea7f78f8bc6fc2064da0427d15dc4b95787
7
- data.tar.gz: 0e4ff78680cdedd9ef3271b84cd4bf1b1550eaf27199644f4b64a30a1fad1bb30429d98f39e270630fc201505d094abf11e09194a4b527ce3e9eac816a3ab8b4
6
+ metadata.gz: a289ee47e7d21efdf378737f101dca5efb11a0938ff41b0be804a39a2b0e2d6a694a78e57b0037d65a0e9fe136042d32f3d4377f5320bf9f63d0119d7bb51d33
7
+ data.tar.gz: e836803b9664e2e5548af277978ed7170b8f18e79b767d908f2bbe8005464bc016fb6261bec5fa84d60774c632b6a42578e1d56899a63f90309c49941050750f
data/CHANGELOG.md CHANGED
@@ -1,4 +1,8 @@
1
- ## [Unreleased]
1
+ ## [0.2.0] - 2025-12-28
2
+
3
+ - Added instrumentation support with configurable `instrumenter` (defaults to `NullInstrumenter`)
4
+ - Query errors now raise `Clickhouse::QueryError` instead of returning a failed response
5
+ - Removed `Response#success?`, `Response#failure?`, and `Response#error` methods
2
6
 
3
7
  ## [0.1.0] - 2025-12-28
4
8
 
data/README.md CHANGED
@@ -53,10 +53,8 @@ end
53
53
  conn = Clickhouse::Connection.new
54
54
  response = conn.query("SELECT * FROM users WHERE id = 1")
55
55
 
56
- if response.success?
57
- response.rows.each do |row|
58
- puts row.inspect
59
- end
56
+ response.rows.each do |row|
57
+ puts row.inspect
60
58
  end
61
59
  ```
62
60
 
@@ -96,11 +94,6 @@ response.types # => ["UInt64", "String", "DateTime"]
96
94
  # Convert to array of hashes
97
95
  response.to_a # => [{"id" => 1, "name" => "Alice", ...}, ...]
98
96
 
99
- # Check for errors
100
- response.success? # => true
101
- response.failure? # => false
102
- response.error # => nil (or error message string)
103
-
104
97
  # Query summary from ClickHouse
105
98
  response.summary # => {"read_rows" => "1", "read_bytes" => "42", ...}
106
99
  ```
@@ -150,14 +143,32 @@ response = conn.query(
150
143
  | `connection_timeout` | `5` | Connection timeout in seconds |
151
144
  | `pool_size` | `100` | Connection pool size |
152
145
  | `pool_timeout` | `5` | Pool checkout timeout in seconds |
146
+ | `instrumenter` | `NullInstrumenter` | Instrumenter for query instrumentation |
153
147
 
154
- ## Error Handling
148
+ ## Instrumentation
149
+
150
+ You can instrument queries by providing an instrumenter that responds to `#instrument`:
155
151
 
156
152
  ```ruby
157
- response = conn.query("INVALID SQL")
153
+ Clickhouse.configure do |config|
154
+ config.instrumenter = ActiveSupport::Notifications
155
+ end
158
156
 
159
- if response.failure?
160
- puts "Query failed: #{response.error}"
157
+ # Subscribe to events
158
+ ActiveSupport::Notifications.subscribe("query.clickhouse") do |name, start, finish, id, payload|
159
+ puts "Query: #{payload[:sql]} took #{finish - start}s"
160
+ end
161
+ ```
162
+
163
+ The instrumenter receives event name `"query.clickhouse"` and payload `{sql: "..."}`.
164
+
165
+ ## Error Handling
166
+
167
+ ```ruby
168
+ begin
169
+ conn.query("INVALID SQL")
170
+ rescue Clickhouse::QueryError => e
171
+ puts "Query failed: #{e.message}"
161
172
  end
162
173
 
163
174
  # Unsupported types raise an exception
@@ -21,7 +21,8 @@ module Clickhouse
21
21
  password: "",
22
22
  connection_timeout: 5,
23
23
  pool_size: 100,
24
- pool_timeout: 5
24
+ pool_timeout: 5,
25
+ instrumenter: NullInstrumenter.new
25
26
  }.freeze
26
27
 
27
28
  # @return [String] URL scheme (http or https)
@@ -33,7 +34,8 @@ module Clickhouse
33
34
  # @return [Integer] Connection timeout in seconds
34
35
  # @return [Integer] Connection pool size
35
36
  # @return [Integer] Pool checkout timeout in seconds
36
- attr_accessor :scheme, :host, :port, :database, :username, :password, :connection_timeout, :pool_size, :pool_timeout
37
+ # @return [#instrument] Instrumenter for query instrumentation
38
+ attr_accessor :scheme, :host, :port, :database, :username, :password, :connection_timeout, :pool_size, :pool_timeout, :instrumenter
37
39
 
38
40
  # Creates a new configuration instance.
39
41
  #
@@ -24,11 +24,12 @@ module Clickhouse
24
24
  # @param options [Hash] query options
25
25
  # @option options [Hash] :params query parameters
26
26
  # @return [Response] query response with rows, columns, and metadata
27
+ # @raise [QueryError] if the query fails
27
28
  def query(sql, options = {})
28
- result = @transport.execute(sql, options)
29
- return Response.new(error: result.error, summary: result.summary) unless result.success
30
-
31
- NativeFormatParser.new(result.body).parse.with(summary: result.summary)
29
+ @config.instrumenter.instrument("query.clickhouse", {sql: sql}) do
30
+ result = @transport.execute(sql, options)
31
+ NativeFormatParser.new(result.body).parse.with(summary: result.summary)
32
+ end
32
33
  end
33
34
  end
34
35
  end
@@ -30,18 +30,17 @@ module Clickhouse
30
30
  # @param sql [String] SQL query to execute
31
31
  # @param options [Hash] query options
32
32
  # @option options [Hash] :params query parameters
33
- # @return [TransportResult] result containing body or error
33
+ # @return [TransportResult] result containing body and summary
34
+ # @raise [QueryError] if the query fails
34
35
  def execute(sql, options = {})
35
36
  query_params = {database: @config.database}.merge(options[:params] || {})
36
37
  response = @http_client.post("/", params: query_params, body: sql, headers: @default_headers)
37
38
 
38
39
  summary = JSON.parse(response.headers["X-ClickHouse-Summary"])
39
40
 
40
- if response.status.success?
41
- TransportResult.new(success: true, body: response.body, error: nil, summary: summary)
42
- else
43
- TransportResult.new(success: false, body: nil, error: response.body.to_s, summary: summary)
44
- end
41
+ raise QueryError, response.body.to_s unless response.status.success?
42
+
43
+ TransportResult.new(body: response.body, summary: summary)
45
44
  end
46
45
  end
47
46
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Clickhouse
4
+ # Null instrumenter that does nothing.
5
+ # This is the default instrumenter used when no custom instrumenter is configured.
6
+ class NullInstrumenter
7
+ # Executes block without any instrumentation.
8
+ #
9
+ # @param _name [String] event name (ignored)
10
+ # @param _payload [Hash] event payload (ignored)
11
+ # @yield block to execute
12
+ # @return [Object] result of the block
13
+ def instrument(_name, _payload = {})
14
+ yield
15
+ end
16
+ end
17
+ end
@@ -3,35 +3,20 @@
3
3
  module Clickhouse
4
4
  # Immutable response object containing query results.
5
5
  #
6
- # @example Successful response
6
+ # @example
7
7
  # response = conn.query("SELECT id, name FROM users")
8
- # response.success? # => true
9
8
  # response.columns # => ["id", "name"]
10
9
  # response.rows # => [[1, "Alice"], [2, "Bob"]]
11
10
  # response.to_a # => [{"id" => 1, "name" => "Alice"}, ...]
12
- #
13
- # @example Failed response
14
- # response = conn.query("INVALID SQL")
15
- # response.failure? # => true
16
- # response.error # => "Syntax error..."
17
- Response = Data.define(:columns, :types, :rows, :error, :summary) do
11
+ Response = Data.define(:columns, :types, :rows, :summary) do
18
12
  # @param columns [Array<String>] column names
19
13
  # @param types [Array<String>] column types
20
14
  # @param rows [Array<Array>] row data
21
- # @param error [String, nil] error message if query failed
22
15
  # @param summary [Hash, nil] ClickHouse query summary
23
- def initialize(columns: [], types: [], rows: [], error: nil, summary: nil)
16
+ def initialize(columns: [], types: [], rows: [], summary: nil)
24
17
  super
25
18
  end
26
19
 
27
- # Returns true if the query succeeded.
28
- # @return [Boolean]
29
- def success? = error.nil?
30
-
31
- # Returns true if the query failed.
32
- # @return [Boolean]
33
- def failure? = !success?
34
-
35
20
  # Converts rows to an array of hashes.
36
21
  # @return [Array<Hash>] rows as hashes with column names as keys
37
22
  def to_a = rows.map { |row| columns.zip(row).to_h }
@@ -4,13 +4,9 @@ module Clickhouse
4
4
  # Immutable result from transport layer.
5
5
  # @api private
6
6
  #
7
- # @!attribute [r] success
8
- # @return [Boolean] true if request succeeded
9
7
  # @!attribute [r] body
10
- # @return [HTTP::Response::Body, nil] response body for successful requests
11
- # @!attribute [r] error
12
- # @return [String, nil] error message for failed requests
8
+ # @return [HTTP::Response::Body] response body
13
9
  # @!attribute [r] summary
14
10
  # @return [Hash] ClickHouse query summary
15
- TransportResult = Data.define(:success, :body, :error, :summary)
11
+ TransportResult = Data.define(:body, :summary)
16
12
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Clickhouse
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "clickhouse"
data/lib/clickhouse.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "clickhouse/version"
4
+ require_relative "clickhouse/null_instrumenter"
4
5
  require_relative "clickhouse/config"
5
6
  require_relative "clickhouse/transport_result"
6
7
  require_relative "clickhouse/http_transport"
@@ -28,6 +29,9 @@ module Clickhouse
28
29
  # Base error class for all Clickhouse errors
29
30
  class Error < StandardError; end
30
31
 
32
+ # Raised when a query fails (syntax error, unknown table, etc.)
33
+ class QueryError < Error; end
34
+
31
35
  # Raised when encountering an unsupported ClickHouse data type
32
36
  class UnsupportedTypeError < Error; end
33
37
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clickhouse-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karol Bąk
@@ -63,12 +63,14 @@ files:
63
63
  - ".standard.yml"
64
64
  - CHANGELOG.md
65
65
  - README.md
66
+ - lib/clickhouse-rb.rb
66
67
  - lib/clickhouse.rb
67
68
  - lib/clickhouse/buffered_reader.rb
68
69
  - lib/clickhouse/config.rb
69
70
  - lib/clickhouse/connection.rb
70
71
  - lib/clickhouse/http_transport.rb
71
72
  - lib/clickhouse/native_format_parser.rb
73
+ - lib/clickhouse/null_instrumenter.rb
72
74
  - lib/clickhouse/pool.rb
73
75
  - lib/clickhouse/response.rb
74
76
  - lib/clickhouse/transport_result.rb