ch-client 0.0.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 +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
|