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 +4 -4
- data/CHANGELOG.md +5 -1
- data/README.md +24 -13
- data/lib/clickhouse/config.rb +4 -2
- data/lib/clickhouse/connection.rb +5 -4
- data/lib/clickhouse/http_transport.rb +5 -6
- data/lib/clickhouse/null_instrumenter.rb +17 -0
- data/lib/clickhouse/response.rb +3 -18
- data/lib/clickhouse/transport_result.rb +2 -6
- data/lib/clickhouse/version.rb +1 -1
- data/lib/clickhouse-rb.rb +3 -0
- data/lib/clickhouse.rb +4 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1ccbd22754bea20c9ca9fed064ef2b4e7a5cf936b9e6c8c3f819f732adfc25e7
|
|
4
|
+
data.tar.gz: 9537ffae5678fa0bf7ffbdd7b0cbb505aa66a8471072271765e98e99456a7f9d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a289ee47e7d21efdf378737f101dca5efb11a0938ff41b0be804a39a2b0e2d6a694a78e57b0037d65a0e9fe136042d32f3d4377f5320bf9f63d0119d7bb51d33
|
|
7
|
+
data.tar.gz: e836803b9664e2e5548af277978ed7170b8f18e79b767d908f2bbe8005464bc016fb6261bec5fa84d60774c632b6a42578e1d56899a63f90309c49941050750f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
## [
|
|
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
|
-
|
|
57
|
-
|
|
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
|
-
##
|
|
148
|
+
## Instrumentation
|
|
149
|
+
|
|
150
|
+
You can instrument queries by providing an instrumenter that responds to `#instrument`:
|
|
155
151
|
|
|
156
152
|
```ruby
|
|
157
|
-
|
|
153
|
+
Clickhouse.configure do |config|
|
|
154
|
+
config.instrumenter = ActiveSupport::Notifications
|
|
155
|
+
end
|
|
158
156
|
|
|
159
|
-
|
|
160
|
-
|
|
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
|
data/lib/clickhouse/config.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
data/lib/clickhouse/response.rb
CHANGED
|
@@ -3,35 +3,20 @@
|
|
|
3
3
|
module Clickhouse
|
|
4
4
|
# Immutable response object containing query results.
|
|
5
5
|
#
|
|
6
|
-
# @example
|
|
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: [],
|
|
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
|
|
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(:
|
|
11
|
+
TransportResult = Data.define(:body, :summary)
|
|
16
12
|
end
|
data/lib/clickhouse/version.rb
CHANGED
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.
|
|
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
|