clickhouse-rb 0.2.0 → 0.3.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 +6 -0
- data/README.md +18 -8
- data/lib/clickhouse/http_transport.rb +1 -1
- data/lib/clickhouse/native_format_parser.rb +42 -14
- data/lib/clickhouse/response.rb +15 -8
- data/lib/clickhouse/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b3665b6f44472615341970c7b6169eaa3e54e7df0132ad866d24b8e24cb170df
|
|
4
|
+
data.tar.gz: b5948f2b40a4e969ed35daf92dfb24f3da23215fa113b86b168c3ab911f20335
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 777e4c17a2d3278fb7a1221ed16f5d4ea01f16eeaac31c5e24ba52f81a2b5dc81613ea379c1e722b9d75f55c3850f6761a1ad5e45265e3be4a2199449777f68c
|
|
7
|
+
data.tar.gz: af8ac7a565c217142e5234d4d83dc9caf70cf2aca86714985b76155ecf8434076f27b9716794f09090b392033a49a7b14097645bc8b180190d089df4e45616c5
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## Unreleased
|
|
2
|
+
|
|
3
|
+
## [0.3.0] - 2025-12-31
|
|
4
|
+
|
|
5
|
+
- Make responses more user-friendly ([#1](https://github.com/kukicola/clickhouse-rb/pull/1))
|
|
6
|
+
|
|
1
7
|
## [0.2.0] - 2025-12-28
|
|
2
8
|
|
|
3
9
|
- Added instrumentation support with configurable `instrumenter` (defaults to `NullInstrumenter`)
|
data/README.md
CHANGED
|
@@ -51,10 +51,10 @@ end
|
|
|
51
51
|
|
|
52
52
|
```ruby
|
|
53
53
|
conn = Clickhouse::Connection.new
|
|
54
|
-
response = conn.query("SELECT
|
|
54
|
+
response = conn.query("SELECT id, name FROM users WHERE active = true")
|
|
55
55
|
|
|
56
|
-
response.
|
|
57
|
-
puts row
|
|
56
|
+
response.each do |row|
|
|
57
|
+
puts "#{row[:id]}: #{row[:name]}"
|
|
58
58
|
end
|
|
59
59
|
```
|
|
60
60
|
|
|
@@ -83,19 +83,29 @@ end
|
|
|
83
83
|
|
|
84
84
|
### Working with Results
|
|
85
85
|
|
|
86
|
+
Response objects implement `Enumerable`, allowing direct iteration:
|
|
87
|
+
|
|
86
88
|
```ruby
|
|
87
89
|
response = conn.query("SELECT id, name, created_at FROM users")
|
|
88
90
|
|
|
91
|
+
# Iterate over rows as hashes with symbol keys
|
|
92
|
+
response.each { |row| puts row[:name] }
|
|
93
|
+
|
|
94
|
+
# Use any Enumerable method
|
|
95
|
+
response.map { |row| row[:id] }
|
|
96
|
+
response.select { |row| row[:id] > 10 }
|
|
97
|
+
response.first # => {id: 1, name: "Alice", created_at: 2024-01-01 00:00:00 UTC}
|
|
98
|
+
|
|
89
99
|
# Access raw rows (arrays)
|
|
90
100
|
response.rows # => [[1, "Alice", 2024-01-01 00:00:00 UTC], ...]
|
|
91
|
-
response.columns # => [
|
|
92
|
-
response.types # => [
|
|
101
|
+
response.columns # => [:id, :name, :created_at]
|
|
102
|
+
response.types # => [:UInt64, :String, :DateTime]
|
|
93
103
|
|
|
94
104
|
# Convert to array of hashes
|
|
95
|
-
response.to_a # => [{
|
|
105
|
+
response.to_a # => [{id: 1, name: "Alice", ...}, ...]
|
|
96
106
|
|
|
97
|
-
# Query summary from ClickHouse
|
|
98
|
-
response.summary # => {
|
|
107
|
+
# Query summary from ClickHouse (symbol keys)
|
|
108
|
+
response.summary # => {read_rows: "1", read_bytes: "42", ...}
|
|
99
109
|
```
|
|
100
110
|
|
|
101
111
|
### Query Parameters
|
|
@@ -36,7 +36,7 @@ module Clickhouse
|
|
|
36
36
|
query_params = {database: @config.database}.merge(options[:params] || {})
|
|
37
37
|
response = @http_client.post("/", params: query_params, body: sql, headers: @default_headers)
|
|
38
38
|
|
|
39
|
-
summary = JSON.parse(response.headers["X-ClickHouse-Summary"])
|
|
39
|
+
summary = JSON.parse(response.headers["X-ClickHouse-Summary"], symbolize_names: true)
|
|
40
40
|
|
|
41
41
|
raise QueryError, response.body.to_s unless response.status.success?
|
|
42
42
|
|
|
@@ -46,8 +46,8 @@ module Clickhouse
|
|
|
46
46
|
col_type = read_string
|
|
47
47
|
|
|
48
48
|
if @columns.length < num_columns
|
|
49
|
-
@columns << col_name
|
|
50
|
-
@types << col_type
|
|
49
|
+
@columns << col_name.to_sym
|
|
50
|
+
@types << col_type.to_sym
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
columns_data << read_column(col_type, num_rows)
|
|
@@ -65,14 +65,14 @@ module Clickhouse
|
|
|
65
65
|
when "UInt16" then read_uint16_column(num_rows)
|
|
66
66
|
when "UInt32" then read_uint32_column(num_rows)
|
|
67
67
|
when "UInt64" then read_uint64_column(num_rows)
|
|
68
|
-
when "UInt128" then
|
|
69
|
-
when "UInt256" then
|
|
68
|
+
when "UInt128" then read_uint128_column(num_rows)
|
|
69
|
+
when "UInt256" then read_uint256_column(num_rows)
|
|
70
70
|
when "Int8" then read_int8_column(num_rows)
|
|
71
71
|
when "Int16" then read_int16_column(num_rows)
|
|
72
72
|
when "Int32" then read_int32_column(num_rows)
|
|
73
73
|
when "Int64" then read_int64_column(num_rows)
|
|
74
|
-
when "Int128" then
|
|
75
|
-
when "Int256" then
|
|
74
|
+
when "Int128" then read_int128_column(num_rows)
|
|
75
|
+
when "Int256" then read_int256_column(num_rows)
|
|
76
76
|
|
|
77
77
|
# Floats
|
|
78
78
|
when "Float32" then read_float32_column(num_rows)
|
|
@@ -82,7 +82,7 @@ module Clickhouse
|
|
|
82
82
|
when "Bool" then read_bool_column(num_rows)
|
|
83
83
|
|
|
84
84
|
# Strings
|
|
85
|
-
when "String" then
|
|
85
|
+
when "String" then read_string_column(num_rows)
|
|
86
86
|
when /^FixedString\((\d+)\)$/ then read_fixed_string_column($1.to_i, num_rows)
|
|
87
87
|
|
|
88
88
|
# Dates and Times
|
|
@@ -92,11 +92,11 @@ module Clickhouse
|
|
|
92
92
|
when /^DateTime64\((\d+)(?:,.*)?\)$/ then read_datetime64_column($1.to_i, num_rows)
|
|
93
93
|
|
|
94
94
|
# UUID
|
|
95
|
-
when "UUID" then
|
|
95
|
+
when "UUID" then read_uuid_column(num_rows)
|
|
96
96
|
|
|
97
97
|
# IP addresses
|
|
98
|
-
when "IPv4" then
|
|
99
|
-
when "IPv6" then
|
|
98
|
+
when "IPv4" then read_ipv4_column(num_rows)
|
|
99
|
+
when "IPv6" then read_ipv6_column(num_rows)
|
|
100
100
|
|
|
101
101
|
# Decimals - ClickHouse always returns Decimal(precision, scale)
|
|
102
102
|
when /^Decimal\((\d+),\s*(\d+)\)$/ then read_decimal_column($1.to_i, $2.to_i, num_rows)
|
|
@@ -145,6 +145,14 @@ module Clickhouse
|
|
|
145
145
|
@reader.read(num_rows * 8).unpack("Q<*")
|
|
146
146
|
end
|
|
147
147
|
|
|
148
|
+
def read_uint128_column(num_rows)
|
|
149
|
+
Array.new(num_rows) { read_le_bytes(16) }
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def read_uint256_column(num_rows)
|
|
153
|
+
Array.new(num_rows) { read_le_bytes(32) }
|
|
154
|
+
end
|
|
155
|
+
|
|
148
156
|
def read_int8_column(num_rows)
|
|
149
157
|
@reader.read(num_rows).unpack("c*")
|
|
150
158
|
end
|
|
@@ -161,6 +169,14 @@ module Clickhouse
|
|
|
161
169
|
@reader.read(num_rows * 8).unpack("q<*")
|
|
162
170
|
end
|
|
163
171
|
|
|
172
|
+
def read_int128_column(num_rows)
|
|
173
|
+
Array.new(num_rows) { read_signed_le_bytes(16) }
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def read_int256_column(num_rows)
|
|
177
|
+
Array.new(num_rows) { read_signed_le_bytes(32) }
|
|
178
|
+
end
|
|
179
|
+
|
|
164
180
|
def read_float32_column(num_rows)
|
|
165
181
|
@reader.read(num_rows * 4).unpack("e*")
|
|
166
182
|
end
|
|
@@ -173,6 +189,10 @@ module Clickhouse
|
|
|
173
189
|
@reader.read(num_rows).bytes.map { |b| b == 1 }
|
|
174
190
|
end
|
|
175
191
|
|
|
192
|
+
def read_string_column(num_rows)
|
|
193
|
+
Array.new(num_rows) { read_string }
|
|
194
|
+
end
|
|
195
|
+
|
|
176
196
|
def read_fixed_string_column(length, num_rows)
|
|
177
197
|
Array.new(num_rows) { @reader.read(length).force_encoding(Encoding::UTF_8) }
|
|
178
198
|
end
|
|
@@ -197,6 +217,18 @@ module Clickhouse
|
|
|
197
217
|
end
|
|
198
218
|
end
|
|
199
219
|
|
|
220
|
+
def read_uuid_column(num_rows)
|
|
221
|
+
Array.new(num_rows) { read_uuid }
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def read_ipv4_column(num_rows)
|
|
225
|
+
Array.new(num_rows) { read_ipv4 }
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def read_ipv6_column(num_rows)
|
|
229
|
+
Array.new(num_rows) { read_ipv6 }
|
|
230
|
+
end
|
|
231
|
+
|
|
200
232
|
def read_decimal_column(precision, scale, num_rows)
|
|
201
233
|
divisor = 10**scale
|
|
202
234
|
if precision <= 9
|
|
@@ -230,10 +262,6 @@ module Clickhouse
|
|
|
230
262
|
end
|
|
231
263
|
|
|
232
264
|
def read_uint64 = @reader.read(8).unpack1("Q<")
|
|
233
|
-
def read_uint128 = read_le_bytes(16)
|
|
234
|
-
def read_uint256 = read_le_bytes(32)
|
|
235
|
-
def read_int128 = read_signed_le_bytes(16)
|
|
236
|
-
def read_int256 = read_signed_le_bytes(32)
|
|
237
265
|
|
|
238
266
|
def read_uuid
|
|
239
267
|
first_half = @reader.read(8).bytes.reverse
|
data/lib/clickhouse/response.rb
CHANGED
|
@@ -5,20 +5,27 @@ module Clickhouse
|
|
|
5
5
|
#
|
|
6
6
|
# @example
|
|
7
7
|
# response = conn.query("SELECT id, name FROM users")
|
|
8
|
-
# response.columns # => [
|
|
8
|
+
# response.columns # => [:id, :name]
|
|
9
9
|
# response.rows # => [[1, "Alice"], [2, "Bob"]]
|
|
10
|
-
# response.
|
|
10
|
+
# response.each { |row| puts row[:name] }
|
|
11
11
|
Response = Data.define(:columns, :types, :rows, :summary) do
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
include Enumerable
|
|
13
|
+
|
|
14
|
+
# @param columns [Array<Symbol>] column names
|
|
15
|
+
# @param types [Array<Symbol>] column types
|
|
14
16
|
# @param rows [Array<Array>] row data
|
|
15
|
-
# @param summary [Hash, nil] ClickHouse query summary
|
|
17
|
+
# @param summary [Hash, nil] ClickHouse query summary with symbol keys
|
|
16
18
|
def initialize(columns: [], types: [], rows: [], summary: nil)
|
|
17
19
|
super
|
|
18
20
|
end
|
|
19
21
|
|
|
20
|
-
#
|
|
21
|
-
# @
|
|
22
|
-
|
|
22
|
+
# Iterates over rows as hashes with symbol keys.
|
|
23
|
+
# @yield [Hash] each row as a hash
|
|
24
|
+
# @return [Enumerator] if no block given
|
|
25
|
+
def each
|
|
26
|
+
return to_enum(:each) unless block_given?
|
|
27
|
+
|
|
28
|
+
rows.each { |row| yield columns.zip(row).to_h }
|
|
29
|
+
end
|
|
23
30
|
end
|
|
24
31
|
end
|
data/lib/clickhouse/version.rb
CHANGED