click_house-client 0.7.0 → 0.7.1
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/Gemfile.lock +2 -2
- data/README.md +178 -0
- data/lib/click_house/client/version.rb +1 -1
- data/lib/click_house/client.rb +0 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 321e868b4cca95b643f90153b5ae1912f1960b13f5dafda79aea4056e130edc8
|
4
|
+
data.tar.gz: c89e9e47c42a8550d6a7e899a7c30a6807ca7c8119f66cbb573a9cfc082ab175
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 54aecdd0475745b881b40074122a06cee33f4d6d7dcb2c38c2622dfc484ffaa364bc57260ce8858277d524c62b62ce83dd3ea19711ff1f94c5df5852ef57b1c0
|
7
|
+
data.tar.gz: 3416500a2e4b09074e421c99f363323d79af92fbc6a14e015f52c5ae0eb5a4dd86142bc3a913eef3879a5f12255f9e0435a556b3f5a9375bf6b2b1eca9a8d392
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
click_house-client (0.7.
|
4
|
+
click_house-client (0.7.1)
|
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.7.
|
139
|
+
click_house-client (0.7.1)
|
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
@@ -61,6 +61,184 @@ puts ClickHouse::Client.execute('CREATE TABLE IF NOT EXISTS t1 (id Int64) ENGINE
|
|
61
61
|
puts ClickHouse::Client.execute('DROP TABLE IF EXISTS t1', :main)
|
62
62
|
```
|
63
63
|
|
64
|
+
## ClickHouse::Client::QueryBuilder
|
65
|
+
|
66
|
+
The QueryBuilder provides an ActiveRecord-like interface for constructing ClickHouse queries programmatically. While similar to ActiveRecord's query interface, it has been tailored specifically for ClickHouse's SQL dialect and features.
|
67
|
+
|
68
|
+
### Basic Usage
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
# Initialize a query builder for a table
|
72
|
+
query = ClickHouse::Client::QueryBuilder.new('users')
|
73
|
+
|
74
|
+
# Build and execute queries
|
75
|
+
query.select(:id, :name).where(active: true).to_sql
|
76
|
+
# => "SELECT `users`.`id`, `users`.`name` FROM `users` WHERE `users`.`active` = 'true'"
|
77
|
+
```
|
78
|
+
|
79
|
+
### WHERE Clause
|
80
|
+
|
81
|
+
The `where` method supports various types of conditions:
|
82
|
+
|
83
|
+
#### Simple Equality Conditions
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
query.where(status: 'active').to_sql
|
87
|
+
# => "SELECT * FROM `users` WHERE `users`.`status` = 'active'"
|
88
|
+
|
89
|
+
# Multiple conditions (joined with AND)
|
90
|
+
query.where(status: 'active', role: 'admin').to_sql
|
91
|
+
# => "SELECT * FROM `users` WHERE `users`.`status` = 'active' AND `users`.`role` = 'admin'"
|
92
|
+
```
|
93
|
+
|
94
|
+
#### Array Conditions (IN clause)
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
query.where(id: [1, 2, 3]).to_sql
|
98
|
+
# => "SELECT * FROM `users` WHERE `users`.`id` IN (1, 2, 3)"
|
99
|
+
```
|
100
|
+
|
101
|
+
#### Using Arel Nodes for Complex Conditions
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
# Greater than
|
105
|
+
query.where(query.table[:age].gt(18)).to_sql
|
106
|
+
# => "SELECT * FROM `users` WHERE `users`.`age` > 18"
|
107
|
+
|
108
|
+
# Less than
|
109
|
+
query.where(query.table[:price].lt(100)).to_sql
|
110
|
+
# => "SELECT * FROM `users` WHERE `users`.`price` < 100"
|
111
|
+
|
112
|
+
# Between
|
113
|
+
query.where(query.table[:created_at].between(Date.yesterday..Date.today)).to_sql
|
114
|
+
# => "SELECT * FROM `users` WHERE `users`.`created_at` BETWEEN '2025-09-10' AND '2025-09-11'"
|
115
|
+
|
116
|
+
# Combining conditions with AND
|
117
|
+
condition = query.table[:age].gt(18).and(query.table[:status].eq('active'))
|
118
|
+
query.where(condition).to_sql
|
119
|
+
# => "SELECT * FROM `users` WHERE `users`.`age` > 18 AND `users`.`status` = 'active'"
|
120
|
+
|
121
|
+
# Combining conditions with OR
|
122
|
+
condition = query.table[:role].eq('admin').or(query.table[:role].eq('moderator'))
|
123
|
+
query.where(condition).to_sql
|
124
|
+
# => "SELECT * FROM `users` WHERE (`users`.`role` = 'admin' OR `users`.`role` = 'moderator')"
|
125
|
+
|
126
|
+
# List of supported node types in where clause
|
127
|
+
puts ClickHouse::Client::QueryBuilder::VALID_NODES
|
128
|
+
```
|
129
|
+
|
130
|
+
#### Pattern Matching with LIKE/ILIKE
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
# Case-insensitive pattern matching (ILIKE - default)
|
134
|
+
query.where(query.table[:email].matches('%@example.com')).to_sql
|
135
|
+
# => "SELECT * FROM `users` WHERE `users`.`email` ILIKE '%@example.com'"
|
136
|
+
|
137
|
+
# Case-sensitive pattern matching (LIKE)
|
138
|
+
query.where(query.table[:name].matches('John%', nil, true)).to_sql
|
139
|
+
# => "SELECT * FROM `users` WHERE `users`.`name` LIKE 'John%'"
|
140
|
+
|
141
|
+
# Negative pattern matching (NOT ILIKE)
|
142
|
+
query.where(query.table[:email].does_not_match('%@spam.com')).to_sql
|
143
|
+
# => "SELECT * FROM `users` WHERE `users`.`email` NOT ILIKE '%@spam.com'"
|
144
|
+
```
|
145
|
+
|
146
|
+
#### Subqueries
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
# Using a subquery in WHERE clause
|
150
|
+
subquery = ClickHouse::Client::QueryBuilder.new('orders')
|
151
|
+
.select(:user_id)
|
152
|
+
.where(status: 'completed')
|
153
|
+
|
154
|
+
query.where(id: subquery).to_sql
|
155
|
+
# => "SELECT * FROM `users` WHERE `users`.`id` IN (SELECT `orders`.`user_id` FROM `orders` WHERE `orders`.`status` = 'completed')"
|
156
|
+
```
|
157
|
+
|
158
|
+
### HAVING Clause
|
159
|
+
|
160
|
+
The `having` method works similarly to `where` but is used for filtering aggregated results:
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
# Using COUNT(*) in HAVING clause
|
164
|
+
count_func = Arel::Nodes::NamedFunction.new('COUNT', [Arel.star])
|
165
|
+
query.group(:department).having(count_func.gt(10)).to_sql
|
166
|
+
# => "SELECT * FROM `users` GROUP BY `users`.`department` HAVING COUNT(*) > 10"
|
167
|
+
|
168
|
+
# Using other aggregation functions
|
169
|
+
sum_func = Arel::Nodes::NamedFunction.new('SUM', [query.table[:salary]])
|
170
|
+
query.group(:department).having(sum_func.gt(100000)).to_sql
|
171
|
+
# => "SELECT * FROM `users` GROUP BY `users`.`department` HAVING SUM(`users`.`salary`) > 100000"
|
172
|
+
```
|
173
|
+
|
174
|
+
#### Combining WHERE and HAVING
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
query
|
178
|
+
.where(active: true)
|
179
|
+
.group(:department)
|
180
|
+
.having(query.table[:avg_salary].gt(50000))
|
181
|
+
.to_sql
|
182
|
+
# => "SELECT * FROM `users` WHERE `users`.`active` = 'true' GROUP BY `users`.`department` HAVING `users`.`avg_salary` > 50000"
|
183
|
+
```
|
184
|
+
|
185
|
+
### Working with JOINs
|
186
|
+
|
187
|
+
When using JOINs, you can apply conditions to joined tables: _(Supports only `INNER JOIN`)_
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
# Join with conditions on joined table
|
191
|
+
query
|
192
|
+
.joins('orders', { 'id' => 'user_id' })
|
193
|
+
.where(orders: { status: 'pending' })
|
194
|
+
.to_sql
|
195
|
+
# => "SELECT * FROM `users` INNER JOIN `orders` ON `users`.`id` = `orders`.`user_id` WHERE `orders`.`status` = 'pending'"
|
196
|
+
|
197
|
+
# HAVING clause with joined tables
|
198
|
+
query
|
199
|
+
.joins('orders', { 'id' => 'user_id' })
|
200
|
+
.group(:department)
|
201
|
+
.having(orders: { total: [100, 200, 300] })
|
202
|
+
.to_sql
|
203
|
+
# => "SELECT * FROM `users` INNER JOIN `orders` ON `users`.`id` = `orders`.`user_id` GROUP BY `users`.`department` HAVING `orders`.`total` IN (100, 200, 300)"
|
204
|
+
```
|
205
|
+
|
206
|
+
### Complete Example
|
207
|
+
|
208
|
+
Here's a comprehensive example combining multiple QueryBuilder features:
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
# Find active users in specific departments who have completed orders
|
212
|
+
# Group by department and filter groups with more than 5 users
|
213
|
+
|
214
|
+
completed_orders = ClickHouse::Client::QueryBuilder.new('orders')
|
215
|
+
.select(:user_id)
|
216
|
+
.where(status: 'completed')
|
217
|
+
.where(query.table[:created_at].gt(Date.today - 30))
|
218
|
+
|
219
|
+
count_func = Arel::Nodes::NamedFunction.new('COUNT', [Arel.star])
|
220
|
+
|
221
|
+
result = ClickHouse::Client::QueryBuilder.new('users')
|
222
|
+
.select(:department, count_func.as('user_count'))
|
223
|
+
.where(active: true)
|
224
|
+
.where(department: ['Sales', 'Marketing', 'Engineering'])
|
225
|
+
.where(id: completed_orders)
|
226
|
+
.where(query.table[:email].matches('%@company.com'))
|
227
|
+
.group(:department)
|
228
|
+
.having(count_func.gt(5))
|
229
|
+
.order(Arel.sql('user_count'), :desc)
|
230
|
+
.limit(10)
|
231
|
+
|
232
|
+
puts result.to_sql
|
233
|
+
"SELECT `users`.`department`, COUNT(*) AS user_count FROM `users` WHERE `users`.`active` = 'true'
|
234
|
+
AND `users`.`department` IN ('Sales', 'Marketing', 'Engineering')
|
235
|
+
AND `users`.`id` IN (SELECT `orders`.`user_id` FROM `orders` WHERE `orders`.`status` = 'completed'
|
236
|
+
AND `users`.`created_at` > '2025-08-12')
|
237
|
+
AND `users`.`email` ILIKE '%@company.com'
|
238
|
+
GROUP BY department HAVING COUNT(*) AS user_count > 5
|
239
|
+
ORDER BY user_count DESC LIMIT 10"
|
240
|
+
```
|
241
|
+
|
64
242
|
## License
|
65
243
|
|
66
244
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/lib/click_house/client.rb
CHANGED
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.7.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- group::optimize
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-09-
|
11
|
+
date: 2025-09-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|