ch-client 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +22 -0
- data/.gitignore +9 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.md +58 -0
- data/Gemfile +3 -0
- data/MIT-LICENSE +20 -0
- data/README.md +262 -0
- data/Rakefile +15 -0
- data/VERSION +1 -0
- data/bin/clickhouse +9 -0
- data/clickhouse.gemspec +36 -0
- data/lib/clickhouse.rb +60 -0
- data/lib/clickhouse/cli.rb +46 -0
- data/lib/clickhouse/cli/client.rb +149 -0
- data/lib/clickhouse/cli/console.rb +73 -0
- data/lib/clickhouse/cli/server.rb +37 -0
- data/lib/clickhouse/cli/server/assets/css/clickhouse.css +177 -0
- data/lib/clickhouse/cli/server/assets/css/codemirror.css +341 -0
- data/lib/clickhouse/cli/server/assets/css/datatables.css +1 -0
- data/lib/clickhouse/cli/server/assets/css/normalize.css +427 -0
- data/lib/clickhouse/cli/server/assets/css/skeleton.css +418 -0
- data/lib/clickhouse/cli/server/assets/js/clickhouse.js +188 -0
- data/lib/clickhouse/cli/server/assets/js/codemirror.js +9096 -0
- data/lib/clickhouse/cli/server/assets/js/datatables.js +166 -0
- data/lib/clickhouse/cli/server/assets/js/disableswipeback.js +97 -0
- data/lib/clickhouse/cli/server/assets/js/jquery.js +11015 -0
- data/lib/clickhouse/cli/server/assets/js/sql.js +232 -0
- data/lib/clickhouse/cli/server/views/index.erb +46 -0
- data/lib/clickhouse/cluster.rb +43 -0
- data/lib/clickhouse/connection.rb +42 -0
- data/lib/clickhouse/connection/client.rb +135 -0
- data/lib/clickhouse/connection/logger.rb +12 -0
- data/lib/clickhouse/connection/query.rb +160 -0
- data/lib/clickhouse/connection/query/result_row.rb +36 -0
- data/lib/clickhouse/connection/query/result_set.rb +103 -0
- data/lib/clickhouse/connection/query/table.rb +50 -0
- data/lib/clickhouse/error.rb +18 -0
- data/lib/clickhouse/utils.rb +23 -0
- data/lib/clickhouse/version.rb +7 -0
- data/script/console +58 -0
- data/test/test_helper.rb +15 -0
- data/test/test_helper/coverage.rb +16 -0
- data/test/test_helper/minitest.rb +13 -0
- data/test/test_helper/simple_connection.rb +12 -0
- data/test/unit/connection/query/test_result_row.rb +36 -0
- data/test/unit/connection/query/test_result_set.rb +196 -0
- data/test/unit/connection/query/test_table.rb +39 -0
- data/test/unit/connection/test_client.rb +206 -0
- data/test/unit/connection/test_cluster.rb +81 -0
- data/test/unit/connection/test_logger.rb +35 -0
- data/test/unit/connection/test_query.rb +410 -0
- data/test/unit/test_clickhouse.rb +99 -0
- data/test/unit/test_connection.rb +55 -0
- data/test/unit/test_utils.rb +39 -0
- metadata +326 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
require_relative "../../test_helper"
|
2
|
+
|
3
|
+
module Unit
|
4
|
+
module Connection
|
5
|
+
class TestCluser < MiniTest::Test
|
6
|
+
|
7
|
+
describe Clickhouse::Cluster do
|
8
|
+
it "creates a connection pond" do
|
9
|
+
cluster = Clickhouse::Cluster.new :urls => %w(localhost:1234 localhost:1235 localhost:1236)
|
10
|
+
assert_equal true, cluster.pond.is_a?(Pond)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "does not modify the passed config" do
|
14
|
+
config = {:urls => %w(localhost:1234 localhost:1235 localhost:1236)}
|
15
|
+
Clickhouse::Cluster.new config
|
16
|
+
assert_equal({:urls => %w(http://localhost:1234 http://localhost:1235 http://localhost:1236)}, config)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "when connection succeeds" do
|
20
|
+
it "keeps valid connections from the pond" do
|
21
|
+
Clickhouse::Connection.any_instance.expects(:tables)
|
22
|
+
Clickhouse::Connection.any_instance.expects(:ping!)
|
23
|
+
|
24
|
+
cluster = Clickhouse::Cluster.new :urls => %w(http://localhost:1234 http://localhost:1235 http://localhost:1236)
|
25
|
+
assert_equal %w(
|
26
|
+
http://localhost:1234
|
27
|
+
http://localhost:1235
|
28
|
+
http://localhost:1236
|
29
|
+
), cluster.pond.available.collect(&:url)
|
30
|
+
|
31
|
+
cluster.tables
|
32
|
+
assert_equal %w(
|
33
|
+
http://localhost:1235
|
34
|
+
http://localhost:1236
|
35
|
+
http://localhost:1234
|
36
|
+
), cluster.pond.available.collect(&:url)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "when connection fails" do
|
41
|
+
it "removes invalid connections from the pond" do
|
42
|
+
cluster = Clickhouse::Cluster.new :urls => %w(http://localhost:1234 http://localhost:1235 http://localhost:1236)
|
43
|
+
|
44
|
+
assert_equal %w(
|
45
|
+
http://localhost:1234
|
46
|
+
http://localhost:1235
|
47
|
+
http://localhost:1236
|
48
|
+
), cluster.pond.available.collect(&:url)
|
49
|
+
|
50
|
+
cluster.tables
|
51
|
+
assert_equal [], cluster.pond.available.collect(&:url)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "when error gets raised other than Clickhouse::ConnectionError" do
|
56
|
+
it "does not remove the connection from the pond" do
|
57
|
+
Clickhouse::Connection.any_instance.expects(:ping!)
|
58
|
+
|
59
|
+
cluster = Clickhouse::Cluster.new :urls => %w(http://localhost:1234 http://localhost:1235 http://localhost:1236)
|
60
|
+
assert_equal %w(
|
61
|
+
http://localhost:1234
|
62
|
+
http://localhost:1235
|
63
|
+
http://localhost:1236
|
64
|
+
), cluster.pond.available.collect(&:url)
|
65
|
+
|
66
|
+
assert_raises NoMethodError do
|
67
|
+
cluster.select_rows ""
|
68
|
+
end
|
69
|
+
|
70
|
+
assert_equal %w(
|
71
|
+
http://localhost:1235
|
72
|
+
http://localhost:1236
|
73
|
+
http://localhost:1234
|
74
|
+
), cluster.pond.available.collect(&:url)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative "../../test_helper"
|
2
|
+
|
3
|
+
module Unit
|
4
|
+
module Connection
|
5
|
+
class TestLogger < MiniTest::Test
|
6
|
+
|
7
|
+
class Connection < SimpleConnection
|
8
|
+
include Clickhouse::Connection::Logger
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Clickhouse::Connection::Logger do
|
12
|
+
before do
|
13
|
+
@connection = Connection.new
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#log" do
|
17
|
+
describe "when having specified a logger" do
|
18
|
+
it "delegates to logger" do
|
19
|
+
(logger = mock).expects(:debug, "Hello world!")
|
20
|
+
Clickhouse.expects(:logger).returns(logger).twice
|
21
|
+
@connection.send(:log, :debug, "Hello world!")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "when not having specified a logger" do
|
26
|
+
it "does nothing" do
|
27
|
+
assert_nil @connection.send(:log, :debug, "Boo!")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,410 @@
|
|
1
|
+
require_relative "../../test_helper"
|
2
|
+
|
3
|
+
module Unit
|
4
|
+
module Connection
|
5
|
+
class TestQuery < MiniTest::Test
|
6
|
+
|
7
|
+
class Connection < SimpleConnection
|
8
|
+
include Clickhouse::Connection::Query
|
9
|
+
include Clickhouse::Connection::Logger
|
10
|
+
end
|
11
|
+
|
12
|
+
describe Clickhouse::Connection::Query do
|
13
|
+
before do
|
14
|
+
@connection = Connection.new
|
15
|
+
@connection.stubs(:parse_stats)
|
16
|
+
@connection.stubs(:write_log)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#execute" do
|
20
|
+
it "sends a POST request" do
|
21
|
+
@connection.expects(:post).with("sql", nil).returns("")
|
22
|
+
assert_equal true, @connection.execute("sql")
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "when server returns a non-empty body" do
|
26
|
+
it "returns the body of the response" do
|
27
|
+
@connection.expects(:post).with("sql", "body").returns("Ok.")
|
28
|
+
assert_equal "Ok.", @connection.execute("sql", "body")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#query" do
|
34
|
+
it "sends a GET request requesting a TSV response including names and types" do
|
35
|
+
@connection.expects(:get).with("sql FORMAT JSONCompact")
|
36
|
+
@connection.stubs(:parse_data)
|
37
|
+
assert_equal [], @connection.query("sql").to_a
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#databases" do
|
42
|
+
it "sends a 'SHOW DATABASES' query" do
|
43
|
+
@connection.expects(:get).with("SHOW DATABASES FORMAT JSONCompact")
|
44
|
+
@connection.stubs(:parse_data).returns([])
|
45
|
+
assert_equal [], @connection.databases
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#tables" do
|
50
|
+
it "sends a 'SHOW TABLES' query" do
|
51
|
+
@connection.expects(:get).with("SHOW TABLES FORMAT JSONCompact")
|
52
|
+
@connection.stubs(:parse_data).returns([])
|
53
|
+
@connection.tables
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#create_table" do
|
58
|
+
it "sends a 'CREATE TABLE' query" do
|
59
|
+
sql = <<-SQL
|
60
|
+
CREATE TABLE logs_test (
|
61
|
+
id UInt8,
|
62
|
+
price Float32,
|
63
|
+
name String,
|
64
|
+
date Date,
|
65
|
+
time DateTime,
|
66
|
+
hex_id FixedString(8)
|
67
|
+
)
|
68
|
+
ENGINE = MergeTree(date, 8192)
|
69
|
+
SQL
|
70
|
+
@connection.expects(:post).with(sql.strip, nil).returns("")
|
71
|
+
@connection.create_table("logs_test") do |t|
|
72
|
+
t.uint8 :id
|
73
|
+
t.float32 :price
|
74
|
+
t.string :name
|
75
|
+
t.date :date
|
76
|
+
t.date_time :time
|
77
|
+
t.fixed_string :hex_id, 8
|
78
|
+
t.engine "MergeTree(date, 8192)"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "#describe_table" do
|
84
|
+
it "sends a 'DESCRIBE TABLE <name>' query" do
|
85
|
+
@connection.expects(:get).with("DESCRIBE TABLE logs FORMAT JSONCompact")
|
86
|
+
@connection.stubs(:parse_data)
|
87
|
+
@connection.describe_table("logs")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#rename_table" do
|
92
|
+
describe "when passing an array with an even number of names" do
|
93
|
+
it "sends a POST request containing a RENAME TABLE statement" do
|
94
|
+
@connection.expects(:post).with("RENAME TABLE foo TO bar, baz TO qux", nil).returns("").twice
|
95
|
+
assert_equal true, @connection.rename_table("foo", "bar", "baz", "qux")
|
96
|
+
assert_equal true, @connection.rename_table(["foo", "bar"], ["baz", "qux"])
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "when passing an array with an odd number of names" do
|
101
|
+
it "raises an Clickhouse::InvalidQueryError" do
|
102
|
+
assert_raises Clickhouse::InvalidQueryError do
|
103
|
+
@connection.rename_table "foo"
|
104
|
+
end
|
105
|
+
assert_raises Clickhouse::InvalidQueryError do
|
106
|
+
@connection.rename_table ["foo"]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "when passing a hash" do
|
112
|
+
it "sends a POST request containing a RENAME TABLE statement" do
|
113
|
+
@connection.expects(:post).with("RENAME TABLE foo TO bar, baz TO qux", nil).returns("")
|
114
|
+
assert_equal true, @connection.rename_table(:foo => "bar", :baz => "qux")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "#drop_table" do
|
120
|
+
it "sends a POST request containing a 'DROP TABLE' statement" do
|
121
|
+
@connection.expects(:post).with("DROP TABLE logs", nil).returns("")
|
122
|
+
assert_equal true, @connection.drop_table("logs")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "#insert_rows" do
|
127
|
+
before do
|
128
|
+
@csv = <<-CSV
|
129
|
+
id,first_name,last_name
|
130
|
+
12345,Paul,Engel
|
131
|
+
67890,Bruce,Wayne
|
132
|
+
CSV
|
133
|
+
@csv.gsub!(/^\s+/, "")
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "when using hashes" do
|
137
|
+
it "sends a POST request containing a 'INSERT INTO' statement using CSV" do
|
138
|
+
@connection.expects(:post).with("INSERT INTO logs FORMAT CSVWithNames", @csv).returns("")
|
139
|
+
assert_equal true, @connection.insert_rows("logs") { |rows|
|
140
|
+
rows << {:id => 12345, :first_name => "Paul", :last_name => "Engel"}
|
141
|
+
rows << {:id => 67890, :first_name => "Bruce", :last_name => "Wayne"}
|
142
|
+
}
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "when using arrays" do
|
147
|
+
it "sends a POST request containing a 'INSERT INTO' statement using CSV" do
|
148
|
+
@connection.expects(:post).with("INSERT INTO logs FORMAT CSVWithNames", @csv).returns("")
|
149
|
+
assert_equal true, @connection.insert_rows("logs", :names => %w(id first_name last_name)) { |rows|
|
150
|
+
rows << [12345, "Paul", "Engel"]
|
151
|
+
rows << [67890, "Bruce", "Wayne"]
|
152
|
+
}
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
describe "#select_rows" do
|
158
|
+
it "sends a GET request and parses the result set" do
|
159
|
+
body = <<-JAVASCRIPT
|
160
|
+
{
|
161
|
+
"meta": [
|
162
|
+
{"name": "year", "type": "UInt16"},
|
163
|
+
{"name": "name", "type": "String"}
|
164
|
+
],
|
165
|
+
"data": [
|
166
|
+
[1982, "Paul"],
|
167
|
+
[1947, "Anna"]
|
168
|
+
]
|
169
|
+
}
|
170
|
+
JAVASCRIPT
|
171
|
+
|
172
|
+
@connection.expects(:to_select_query).with(options = {:from => "logs"}).returns("")
|
173
|
+
@connection.expects(:get).returns(JSON.parse(body))
|
174
|
+
|
175
|
+
assert_equal [
|
176
|
+
[1982, "Paul"],
|
177
|
+
[1947, "Anna"]
|
178
|
+
], @connection.select_rows(options).to_a
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe "#select_row" do
|
183
|
+
it "returns an empty array" do
|
184
|
+
@connection.expects(:select_rows).returns([["Paul", "Engel"], ["Bruce", "Wayne"]])
|
185
|
+
assert_equal ["Paul", "Engel"], @connection.select_row({})
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe "#select_values" do
|
190
|
+
describe "when empty result set" do
|
191
|
+
it "returns an empty array" do
|
192
|
+
@connection.expects(:to_select_query).returns("")
|
193
|
+
@connection.expects(:get).returns(stub(:body => ""))
|
194
|
+
@connection.stubs(:parse_data).returns([])
|
195
|
+
assert_equal [], @connection.select_values({})
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe "when getting data" do
|
200
|
+
it "returns every first value of every row" do
|
201
|
+
body = <<-JAVASCRIPT
|
202
|
+
{
|
203
|
+
"meta": [
|
204
|
+
{"name": "year", "type": "UInt16"},
|
205
|
+
{"name": "name", "type": "String"}
|
206
|
+
],
|
207
|
+
"data": [
|
208
|
+
[1982, "Paul"],
|
209
|
+
[1947, "Anna"]
|
210
|
+
]
|
211
|
+
}
|
212
|
+
JAVASCRIPT
|
213
|
+
|
214
|
+
@connection.expects(:to_select_query).returns("")
|
215
|
+
@connection.expects(:get).returns(JSON.parse(body))
|
216
|
+
assert_equal [
|
217
|
+
1982,
|
218
|
+
1947
|
219
|
+
], @connection.select_values({})
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
describe "#select_value" do
|
225
|
+
describe "when empty result set" do
|
226
|
+
it "returns nil" do
|
227
|
+
@connection.expects(:select_values).with(options = {:foo => "bar"}).returns([])
|
228
|
+
assert_nil @connection.select_value(options)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe "when getting data" do
|
233
|
+
it "returns the first value of the first row" do
|
234
|
+
@connection.expects(:select_values).with(options = {:foo => "bar"}).returns([1982])
|
235
|
+
assert_equal 1982, @connection.select_value(options)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
describe "#count" do
|
241
|
+
it "returns the first value of the first row" do
|
242
|
+
@connection.expects(:select_value).with(:select => "COUNT(*)", :from => "logs").returns(1982)
|
243
|
+
assert_equal 1982, @connection.count(:from => "logs")
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
describe "#to_select_query" do
|
248
|
+
describe "when passing :from option" do
|
249
|
+
it "generates a simple 'SELECT * FROM <table>' query" do
|
250
|
+
query = <<-SQL
|
251
|
+
SELECT *
|
252
|
+
FROM logs
|
253
|
+
SQL
|
254
|
+
options = {
|
255
|
+
:from => "logs"
|
256
|
+
}
|
257
|
+
assert_query(query, @connection.send(:to_select_query, options))
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
describe "when passing :from and :select option" do
|
262
|
+
describe "when passing a single column" do
|
263
|
+
it "respects the single column in the SELECT statement" do
|
264
|
+
query = <<-SQL
|
265
|
+
SELECT MIN(date)
|
266
|
+
FROM logs
|
267
|
+
SQL
|
268
|
+
options = {
|
269
|
+
:select => "MIN(date)",
|
270
|
+
:from => "logs"
|
271
|
+
}
|
272
|
+
assert_query(query, @connection.send(:to_select_query, options))
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
describe "when passing multiple columns" do
|
277
|
+
it "only includes the passed columns in the SELECT statement" do
|
278
|
+
query = <<-SQL
|
279
|
+
SELECT MIN(date), MAX(date)
|
280
|
+
FROM logs
|
281
|
+
SQL
|
282
|
+
options = {
|
283
|
+
:select => ["MIN(date)", "MAX(date)"],
|
284
|
+
:from => "logs"
|
285
|
+
}
|
286
|
+
assert_query(query, @connection.send(:to_select_query, options))
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
describe "when filtering on value is empty" do
|
291
|
+
it "uses the empty() function in the WHERE statement" do
|
292
|
+
query = <<-SQL
|
293
|
+
SELECT *
|
294
|
+
FROM logs
|
295
|
+
WHERE empty(parent_id)
|
296
|
+
SQL
|
297
|
+
options = {
|
298
|
+
:from => "logs",
|
299
|
+
:where => {
|
300
|
+
:parent_id => :empty
|
301
|
+
}
|
302
|
+
}
|
303
|
+
assert_query(query, @connection.send(:to_select_query, options))
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
describe "when filtering on value is within a certain range" do
|
308
|
+
it "includes the range in the WHERE statement" do
|
309
|
+
query = <<-SQL
|
310
|
+
SELECT *
|
311
|
+
FROM logs
|
312
|
+
WHERE code >= 6 AND code <= 10
|
313
|
+
SQL
|
314
|
+
options = {
|
315
|
+
:from => "logs",
|
316
|
+
:where => {
|
317
|
+
:code => 6..10
|
318
|
+
}
|
319
|
+
}
|
320
|
+
assert_query(query, @connection.send(:to_select_query, options))
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
describe "when filtering on value in array" do
|
325
|
+
it "uses an IN operator in the WHERE statement" do
|
326
|
+
query = <<-SQL
|
327
|
+
SELECT *
|
328
|
+
FROM logs
|
329
|
+
WHERE code IN (6, 7, 8, 9, 10)
|
330
|
+
SQL
|
331
|
+
options = {
|
332
|
+
:from => "logs",
|
333
|
+
:where => {
|
334
|
+
:code => [6, 7, 8, 9, 10]
|
335
|
+
}
|
336
|
+
}
|
337
|
+
assert_query(query, @connection.send(:to_select_query, options))
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
describe "when filtering using backticks" do
|
342
|
+
it "uses the specified SQL as is" do
|
343
|
+
query = <<-SQL
|
344
|
+
SELECT *
|
345
|
+
FROM logs
|
346
|
+
WHERE id != 'cb5a67d2932911e6'
|
347
|
+
SQL
|
348
|
+
options = {
|
349
|
+
:from => "logs",
|
350
|
+
:where => {
|
351
|
+
:id => "`!= 'cb5a67d2932911e6'`"
|
352
|
+
}
|
353
|
+
}
|
354
|
+
assert_query(query, @connection.send(:to_select_query, options))
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
describe "when filtering on a string" do
|
359
|
+
it "uses a single quoted string" do
|
360
|
+
query = <<-SQL
|
361
|
+
SELECT *
|
362
|
+
FROM logs
|
363
|
+
WHERE id = 'cb5a67d2932911e6'
|
364
|
+
SQL
|
365
|
+
options = {
|
366
|
+
:from => "logs",
|
367
|
+
:where => {
|
368
|
+
:id => "cb5a67d2932911e6"
|
369
|
+
}
|
370
|
+
}
|
371
|
+
assert_query(query, @connection.send(:to_select_query, options))
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
describe "when using all options" do
|
376
|
+
it "generates the complex query" do
|
377
|
+
query = <<-SQL
|
378
|
+
SELECT date, COUNT(id), groupUniqArray(severity), SUM(clicks)
|
379
|
+
FROM logs
|
380
|
+
WHERE date >= '2016-08-01' AND hidden = 0
|
381
|
+
GROUP BY date
|
382
|
+
HAVING MIN(severity) = 2
|
383
|
+
ORDER BY MIN(time) DESC
|
384
|
+
LIMIT 120, 60
|
385
|
+
SQL
|
386
|
+
options = {
|
387
|
+
:select => ["date", "COUNT(id)", "groupUniqArray(severity)", "SUM(clicks)"],
|
388
|
+
:from => "logs",
|
389
|
+
:where => {
|
390
|
+
:date => "`>= '2016-08-01'`",
|
391
|
+
:hidden => 0
|
392
|
+
},
|
393
|
+
:group => "date",
|
394
|
+
:having => {
|
395
|
+
"MIN(severity)" => 2
|
396
|
+
},
|
397
|
+
:order => "MIN(time) DESC",
|
398
|
+
:limit => 60,
|
399
|
+
:offset => 120
|
400
|
+
}
|
401
|
+
assert_query(query, @connection.send(:to_select_query, options))
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|