clickhouse 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c0be7eb44c6eed3df458e031647a9cad1bc40181
4
- data.tar.gz: 724c2dbce96c466eaad983d720f7da01a899571d
3
+ metadata.gz: 382f431988af06b9879728821c0c002676cb930d
4
+ data.tar.gz: 7fc6c4674ef83c45989bd8d3759ad85629beecee
5
5
  SHA512:
6
- metadata.gz: 2c2e727bbcffefa01ae315b19cddbddf6050afefaf82f8b5379496d79ba7add71e5aa0fed8b977c2d8fd012a12affbf7179654cd3fe61fac99d49222fb9820b7
7
- data.tar.gz: 5893a3e5919b5d19779f4ffd35f3858a10b33e6e2b7eb9510501d9c7e528be01c256890c53d92d329856e0b85fcb36d9a7398a21840c2472df1939a1fb9345d2
6
+ metadata.gz: 83868f46b3dbbd9e977c6ac14a4badf252f9cc213cfbab9545a777ff241003357bd90241bbea1cedd58871457e0a4c43598385839a827e1815a897848bc5bcab
7
+ data.tar.gz: 39d8d2ab4a094e5e5f7b3d269d40d6fad75619fd97a3bee5c04b7bd766eff2096398a5c798fad6cf29d6ee0bafbe33d908cd7068e5c0a98e68c37a051d9a79f5
@@ -1,5 +1,13 @@
1
1
  ## Clickhouse CHANGELOG
2
2
 
3
+ ### Version 0.1.1 (October 19, 2016)
4
+
5
+ * Using the JSONCompact format as query output which does not brake when having a JSON string within the data
6
+ * Ensuring that Clickhouse::Connection::Query#count return an integer
7
+ * Made Clickhouse::Connection::Query#to_select_query public
8
+ * Being able to pass strings as :where or :having option
9
+ * Being able to symbolize the row to hash parsing
10
+
3
11
  ### Version 0.1.0 (October 18, 2016)
4
12
 
5
13
  * Initial release
data/README.md CHANGED
@@ -17,6 +17,14 @@ Well, the developers of Clickhouse themselves [discourage](https://github.com/ya
17
17
  > TCP transport is more specific, we don't want to expose details.
18
18
  Despite we have full compatibility of protocol of different versions of client and server, we want to keep the ability to "break" it for very old clients. And that protocol is not too clean to make a specification.
19
19
 
20
+ ### Why use the JSONCompact format and not the native format?
21
+
22
+ Despite of it being the most efficient format, using the native format is also [discouraged] by the Clickhouse developers.
23
+
24
+ > The most efficient format. Data is written and read by blocks in binary format. For each block, the number of rows, number of columns, column names and types, and parts of columns in this block are recorded one after another. In other words, this format is "columnar" - it doesn't convert columns to rows. This is the format used in the native interface for interaction between servers, for using the command-line client, and for C++ clients.
25
+ >
26
+ > You can use this format to quickly generate dumps that can only be read by the ClickHouse DBMS. It doesn't make sense to work with this format yourself.
27
+
20
28
  ## Installation
21
29
 
22
30
  Run the following command to install `Clickhouse`:
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.1
@@ -13,7 +13,7 @@ module Clickhouse
13
13
 
14
14
  def query(query)
15
15
  query = query.to_s.gsub(/(;|\bFORMAT \w+)/i, "").strip
16
- query += " FORMAT TabSeparatedWithNamesAndTypes"
16
+ query += " FORMAT JSONCompact"
17
17
  parse_response get(query).body.to_s
18
18
  end
19
19
 
@@ -70,7 +70,20 @@ module Clickhouse
70
70
  end
71
71
 
72
72
  def count(options)
73
- select_value options.merge(:select => "COUNT(*)")
73
+ options = options.merge(:select => "COUNT(*)")
74
+ select_value(options).to_i
75
+ end
76
+
77
+ def to_select_query(options)
78
+ to_select_options(options).collect do |(key, value)|
79
+ next if value.nil? || (value.respond_to?(:empty?) && value.empty?)
80
+
81
+ statement = [key.to_s.upcase]
82
+ statement << "BY" if %W(GROUP ORDER).include?(statement[0])
83
+ statement << to_segment(key, value)
84
+ statement.join(" ")
85
+
86
+ end.compact.join("\n").force_encoding("UTF-8")
74
87
  end
75
88
 
76
89
  private
@@ -111,7 +124,7 @@ module Clickhouse
111
124
  when :select
112
125
  [value].flatten.join(", ")
113
126
  when :where, :having
114
- to_condition_statements(value)
127
+ value.is_a?(Hash) ? to_condition_statements(value) : value
115
128
  else
116
129
  value
117
130
  end
@@ -136,23 +149,11 @@ module Clickhouse
136
149
  end.flatten.join(" AND ")
137
150
  end
138
151
 
139
- def to_select_query(options)
140
- to_select_options(options).collect do |(key, value)|
141
- next if value.nil? && (!value.respond_to?(:empty?) || value.empty?)
142
-
143
- statement = [key.to_s.upcase]
144
- statement << "BY" if %W(GROUP ORDER).include?(statement[0])
145
- statement << to_segment(key, value)
146
- statement.join(" ")
147
-
148
- end.compact.join("\n").force_encoding("UTF-8")
149
- end
150
-
151
152
  def parse_response(response)
152
- rows = CSV.parse response, :col_sep => "\t"
153
- names = rows.shift
154
- types = rows.shift
155
- ResultSet.new rows, names, types
153
+ data = JSON.parse response
154
+ names = data["meta"].collect{|column| column["name"]}
155
+ types = data["meta"].collect{|column| column["type"]}
156
+ ResultSet.new data["data"], names, types
156
157
  end
157
158
 
158
159
  end
@@ -5,11 +5,29 @@ module Clickhouse
5
5
 
6
6
  def initialize(values = [], keys = nil)
7
7
  super values
8
- @keys = keys || (0..(values.size - 1)).collect{|i| "column#{i}"}
8
+ @keys = normalize_keys(keys)
9
9
  end
10
10
 
11
- def to_hash
12
- @hash ||= Hash[@keys.zip(self)]
11
+ def to_hash(symbolize = false)
12
+ @hash ||= begin
13
+ keys = symbolize ? @keys.collect(&:to_sym) : @keys
14
+ Hash[keys.zip(self)]
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def normalize_keys(keys)
21
+ if keys
22
+ keys.collect do |key|
23
+ key.match(/^any\(([^\)]+)\)$/)
24
+ $1 || key
25
+ end
26
+ else
27
+ (0..(size - 1)).collect do |index|
28
+ "column#{index}"
29
+ end
30
+ end
13
31
  end
14
32
 
15
33
  end
@@ -31,8 +31,8 @@ module Clickhouse
31
31
  !empty?
32
32
  end
33
33
 
34
- def to_hashes
35
- collect(&:to_hash)
34
+ def to_hashes(symbolize = false)
35
+ collect{|row| row.to_hash(symbolize)}
36
36
  end
37
37
 
38
38
  private
@@ -92,7 +92,7 @@ module Clickhouse
92
92
  end
93
93
 
94
94
  def parse_array_value(value)
95
- JSON.parse(value)
95
+ value
96
96
  end
97
97
 
98
98
  end
@@ -1,7 +1,7 @@
1
1
  module Clickhouse
2
2
  MAJOR = 0
3
3
  MINOR = 1
4
- TINY = 0
4
+ TINY = 1
5
5
 
6
6
  VERSION = [MAJOR, MINOR, TINY].join(".")
7
7
  end
@@ -17,7 +17,7 @@ module Unit
17
17
  "d91d1c90\u0000\u0000\u0000",
18
18
  "2016-03-20",
19
19
  "2016-03-20 23:49:11",
20
- "[4,2,5,7]"
20
+ [4, 2, 5, 7]
21
21
  ], [
22
22
  "12948140",
23
23
  "9320.11",
@@ -25,7 +25,7 @@ module Unit
25
25
  "d91d217c\u0000\u0000",
26
26
  "2016-03-20",
27
27
  "2016-03-20 23:58:34",
28
- "[6,2,9,8,1]"
28
+ [6, 2, 9, 8, 1]
29
29
  ], [
30
30
  "319384",
31
31
  "101.02",
@@ -33,7 +33,7 @@ module Unit
33
33
  "d91d2294\u0000\u0000\u0000",
34
34
  "2016-03-20",
35
35
  "2016-03-20 22:55:39",
36
- "[3,1,2]"
36
+ [3, 1, 2]
37
37
  ]
38
38
  ],
39
39
  %w(
@@ -30,21 +30,24 @@ module Unit
30
30
 
31
31
  describe "#query" do
32
32
  it "sends a GET request requesting a TSV response including names and types" do
33
- @connection.expects(:get).with("sql FORMAT TabSeparatedWithNamesAndTypes").returns(stub(:status => 200, :body => ""))
33
+ @connection.expects(:get).with("sql FORMAT JSONCompact").returns(stub(:status => 200, :body => ""))
34
+ @connection.stubs(:parse_response)
34
35
  assert_equal [], @connection.query("sql").to_a
35
36
  end
36
37
  end
37
38
 
38
39
  describe "#databases" do
39
40
  it "sends a 'SHOW DATABASES' query" do
40
- @connection.expects(:get).with("SHOW DATABASES FORMAT TabSeparatedWithNamesAndTypes").returns(stub(:status => 200, :body => ""))
41
+ @connection.expects(:get).with("SHOW DATABASES FORMAT JSONCompact").returns(stub(:status => 200, :body => "{}"))
42
+ @connection.stubs(:parse_response).returns([])
41
43
  @connection.databases
42
44
  end
43
45
  end
44
46
 
45
47
  describe "#tables" do
46
48
  it "sends a 'SHOW TABLES' query" do
47
- @connection.expects(:get).with("SHOW TABLES FORMAT TabSeparatedWithNamesAndTypes").returns(stub(:status => 200, :body => ""))
49
+ @connection.expects(:get).with("SHOW TABLES FORMAT JSONCompact").returns(stub(:status => 200, :body => "{}"))
50
+ @connection.stubs(:parse_response).returns([])
48
51
  @connection.tables
49
52
  end
50
53
  end
@@ -77,7 +80,8 @@ ENGINE = MergeTree(date, 8192)
77
80
 
78
81
  describe "#describe_table" do
79
82
  it "sends a 'DESCRIBE TABLE <name>' query" do
80
- @connection.expects(:get).with("DESCRIBE TABLE logs FORMAT TabSeparatedWithNamesAndTypes").returns(stub(:status => 200, :body => ""))
83
+ @connection.expects(:get).with("DESCRIBE TABLE logs FORMAT JSONCompact").returns(stub(:status => 200, :body => ""))
84
+ @connection.stubs(:parse_response)
81
85
  @connection.describe_table("logs")
82
86
  end
83
87
  end
@@ -150,15 +154,21 @@ ENGINE = MergeTree(date, 8192)
150
154
 
151
155
  describe "#select_rows" do
152
156
  it "sends a GET request and parses the result set" do
153
- body = <<-TSV
154
- year\tname
155
- UInt16\tString
156
- 1982\tPaul
157
- 1947\tAnna
158
- TSV
157
+ body = <<-JAVASCRIPT
158
+ {
159
+ "meta": [
160
+ {"name": "year", "type": "UInt16"},
161
+ {"name": "name", "type": "String"}
162
+ ],
163
+ "data": [
164
+ [1982, "Paul"],
165
+ [1947, "Anna"]
166
+ ]
167
+ }
168
+ JAVASCRIPT
159
169
 
160
170
  @connection.expects(:to_select_query).with(options = {:from => "logs"})
161
- @connection.expects(:get).returns(stub(:body => body.gsub(/^\s+/, "")))
171
+ @connection.expects(:get).returns(stub(:body => body))
162
172
 
163
173
  assert_equal [
164
174
  [1982, "Paul"],
@@ -179,21 +189,28 @@ ENGINE = MergeTree(date, 8192)
179
189
  it "returns an empty array" do
180
190
  @connection.expects(:to_select_query)
181
191
  @connection.expects(:get).returns(stub(:body => ""))
192
+ @connection.stubs(:parse_response).returns([])
182
193
  assert_equal [], @connection.select_values({})
183
194
  end
184
195
  end
185
196
 
186
197
  describe "when getting data" do
187
198
  it "returns every first value of every row" do
188
- body = <<-TSV
189
- year\tname
190
- UInt16\tString
191
- 1982\tPaul
192
- 1947\tAnna
193
- TSV
199
+ body = <<-JAVASCRIPT
200
+ {
201
+ "meta": [
202
+ {"name": "year", "type": "UInt16"},
203
+ {"name": "name", "type": "String"}
204
+ ],
205
+ "data": [
206
+ [1982, "Paul"],
207
+ [1947, "Anna"]
208
+ ]
209
+ }
210
+ JAVASCRIPT
194
211
 
195
212
  @connection.expects(:to_select_query)
196
- @connection.expects(:get).returns(stub(:body => body.gsub(/^\s+/, "")))
213
+ @connection.expects(:get).returns(stub(:body => body))
197
214
  assert_equal [
198
215
  1982,
199
216
  1947
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clickhouse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Engel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-17 00:00:00.000000000 Z
11
+ date: 2016-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday