influxdb 0.3.7 → 0.3.8

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: de7cdbcf5a4222dcaa8d992605533a4b1961da0f
4
- data.tar.gz: e449d025b563a796dde3412612713383a1a9f0ab
3
+ metadata.gz: 1338ae151de766b8f05c29b117133b19e4d993e0
4
+ data.tar.gz: e9f74096f0c73ca57877354f14919e02a81d5db6
5
5
  SHA512:
6
- metadata.gz: 0959fc07ab3a1753edfef682273bfb5472e7b492098b8e0c466f4ebc9f24851818868bda53ef323efc5e903bb865e8f02095a46e9bac3784aae4cb271b094b3c
7
- data.tar.gz: 506cd94546133b923bdb40b120364f48182124df319d1d5994be3b557679b2d52f5d2309d7530be6284e1cb5c60493844e08ecf2b9104e61ac0544d1a6437d78
6
+ metadata.gz: a18bb479c32e71163beb834f8141bdc4cf6ce4bb2f4e4f153ca0a0b28c820be8f765e1cc29a89d37868b7878fb6b9c9921f56347b5e9c4cf12802d9b8a7da66a
7
+ data.tar.gz: 2f008e1a615393c162cb1491317495f47b076484a275b6e9e01e42995b68835cd92523224d008dad24413a8b8739647cee82274e827359db5b20d75e8560dbf5
@@ -22,3 +22,7 @@ Metrics/LineLength:
22
22
  Max: 100
23
23
  Exclude:
24
24
  - 'spec/**/*.rb'
25
+
26
+ Metrics/ModuleLength:
27
+ CountComments: false # count full line comments?
28
+ Max: 120
@@ -6,14 +6,18 @@ For the full commit log, [see here](https://github.com/influxdata/influxdb-ruby/
6
6
 
7
7
  - None.
8
8
 
9
+ ## v0.3.8, released 2016-08-31
10
+
11
+ - Added support for named and positional query parameters (#160, @retorquere).
12
+
9
13
  ## v0.3.7, released 2016-08-14
10
14
 
11
- - Fixed `prefix` handling for `#ping` and `#version` (#157, @dimiii)
15
+ - Fixed `prefix` handling for `#ping` and `#version` (#157, @dimiii).
12
16
 
13
17
  ## v0.3.6, released 2016-07-24
14
18
 
15
19
  - Added feature for JSON streaming response, via `"chunk_size"` parameter
16
- (#155, @mhodson-qxbranch)
20
+ (#155, @mhodson-qxbranch).
17
21
 
18
22
  ## v0.3.5, released 2016-06-09
19
23
 
@@ -24,7 +28,7 @@ For the full commit log, [see here](https://github.com/influxdata/influxdb-ruby/
24
28
 
25
29
  - Added resample options to `Client#create_continuous_query` (#149).
26
30
  - Fixed resample options to be Ruby 1.9 compatible (#150, @SebastianCoetzee).
27
- - Mentioned in README, that 0.3.x series is the last one to support Ruby 1.9
31
+ - Mentioned in README, that 0.3.x series is the last one to support Ruby 1.9.
28
32
 
29
33
  ## v0.3.3, released 2016-06-06 (yanked)
30
34
 
data/README.md CHANGED
@@ -471,6 +471,23 @@ influxdb.query 'select * from time_series', epoch: 'ms'
471
471
  # [{"name"=>"time_series", "tags"=>{"region"=>"uk"}, "values"=>[{"time"=>1438411376000, "count"=>32, "value"=>0.9673}]}]
472
472
  ```
473
473
 
474
+ Working with parameterized query strings works as expected:
475
+
476
+ ``` ruby
477
+ influxdb = InfluxDB::Client.new database
478
+
479
+ named_parameter_query = "select * from time_series_0 where time > %{min_time}"
480
+ influxdb.query named_parameter_query, params: { min_time: 0 }
481
+ # compiles to:
482
+ # select * from time_series_0 where time > 0
483
+
484
+ positional_params_query = "select * from time_series_0 where f = %{1} and i < %{2}"
485
+ influxdb.query positional_params_query, params: ["foobar", 42]
486
+ # compiles to (note the automatic escaping):
487
+ # select * from time_series_0 where f = 'foobar' and i < 42
488
+ ```
489
+
490
+
474
491
  #### (De-) Normalization
475
492
 
476
493
  By default, InfluxDB::Client will denormalize points (received from InfluxDB as columns and rows), if you want to get _raw_ data add `denormalize: false` to initialization options or to query itself:
@@ -4,7 +4,6 @@ require 'net/http'
4
4
  require 'net/https'
5
5
 
6
6
  module InfluxDB
7
- # rubocop:disable Metrics/ModuleLength
8
7
  # rubocop:disable Metrics/MethodLength
9
8
  # rubocop:disable Metrics/AbcSize
10
9
  module HTTP # :nodoc:
@@ -0,0 +1,44 @@
1
+ module InfluxDB
2
+ module Query # :nodoc: all
3
+ class Builder
4
+ def build(query, params)
5
+ case params
6
+ when Array then params = params_from_array(params)
7
+ when Hash then params = params_from_hash(params)
8
+ when NilClass then params = {}
9
+ else raise ArgumentError, "Unsupported #{params.class} params"
10
+ end
11
+
12
+ query % params
13
+
14
+ rescue KeyError => e
15
+ raise ArgumentError, e.message
16
+ end
17
+
18
+ def quote(param)
19
+ case param
20
+ when String, Symbol
21
+ "'" + param.to_s.gsub(/['"\\\x0]/, '\\\\\0') + "'"
22
+ when Integer, Float, TrueClass, FalseClass
23
+ param.to_s
24
+ else
25
+ raise ArgumentError, "Unexpected parameter type #{p.class} (#{p.inspect})"
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def params_from_hash(params)
32
+ params.each_with_object({}) do |(k, v), hash|
33
+ hash[k.to_sym] = quote(v)
34
+ end
35
+ end
36
+
37
+ def params_from_array(params)
38
+ params.each_with_object({}).with_index do |(param, hash), i|
39
+ hash[(i + 1).to_s.to_sym] = quote(param)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,7 +1,13 @@
1
+ require_relative 'builder'
2
+
1
3
  module InfluxDB
2
4
  module Query # :nodoc: all
3
5
  # rubocop:disable Metrics/AbcSize
4
6
  module Core
7
+ def builder
8
+ @builder ||= Builder.new
9
+ end
10
+
5
11
  def ping
6
12
  url = URI::Generic.build(path: File.join(config.prefix, '/ping')).to_s
7
13
  get url
@@ -13,6 +19,7 @@ module InfluxDB
13
19
 
14
20
  # rubocop:disable Metrics/MethodLength
15
21
  def query(query, opts = {})
22
+ query = builder.build(query, opts[:params])
16
23
  denormalize = opts.fetch(:denormalize, config.denormalize)
17
24
  json_streaming = !opts.fetch(:chunk_size, config.chunk_size).nil?
18
25
 
@@ -1,3 +1,3 @@
1
1
  module InfluxDB # :nodoc:
2
- VERSION = "0.3.7".freeze
2
+ VERSION = "0.3.8".freeze
3
3
  end
@@ -0,0 +1,69 @@
1
+ require "spec_helper"
2
+
3
+ describe InfluxDB::Client do
4
+ let(:subject) do
5
+ described_class.new "database", {
6
+ host: "influxdb.test",
7
+ port: 9999,
8
+ username: "username",
9
+ password: "password",
10
+ time_precision: "s"
11
+ }.merge(args)
12
+ end
13
+
14
+ let(:args) { {} }
15
+
16
+ describe "#query with parameters" do
17
+ let(:query) { "SELECT value FROM requests_per_minute WHERE time > %{start}" }
18
+ let(:query_params) { { start: 1_437_019_900 } }
19
+ let(:query_compiled) { "SELECT value FROM requests_per_minute WHERE time > 1437019900" }
20
+
21
+ let(:response) do
22
+ { "results" => [{ "series" => [{ "name" => "requests_per_minute",
23
+ "columns" => %w( time value ) }] }] }
24
+ end
25
+
26
+ before do
27
+ stub_request(:get, "http://influxdb.test:9999/query")
28
+ .with(query: { db: "database", precision: "s", u: "username", p: "password", q: query_compiled })
29
+ .to_return(body: JSON.generate(response), status: 200)
30
+ end
31
+
32
+ it "should handle responses with no values" do
33
+ # Some requests (such as trying to retrieve values from the future)
34
+ # return a result with no "values" key set.
35
+ expected_result = [{ "name" => "requests_per_minute", "tags" => nil, "values" => [] }]
36
+ expect(subject.query(query, params: query_params)).to eq(expected_result)
37
+ end
38
+ end
39
+
40
+ describe "#query_with_params" do
41
+ let(:query) { "select * from foo where bar > %{param}" }
42
+ let(:compiled_query) { subject.builder.build(query, query_params) }
43
+
44
+ context "with empty params hash" do
45
+ let(:query_params) { {} }
46
+ it { expect { compiled_query }.to raise_error ArgumentError }
47
+ end
48
+
49
+ context "with empty params array" do
50
+ let(:query_params) { [] }
51
+ it { expect { compiled_query }.to raise_error ArgumentError }
52
+ end
53
+
54
+ context "with empty params" do
55
+ let(:query_params) { nil }
56
+ it { expect { compiled_query }.to raise_error ArgumentError }
57
+ end
58
+
59
+ context "with simple params" do
60
+ let(:query_params) { { param: 42 } }
61
+ it { expect(compiled_query).to eq "select * from foo where bar > 42" }
62
+ end
63
+
64
+ context "string escaping" do
65
+ let(:query_params) { { param: "string" } }
66
+ it { expect(compiled_query).to eq "select * from foo where bar > 'string'" }
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,61 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe InfluxDB::Query::Builder do
4
+ let(:builder) { described_class.new }
5
+
6
+ describe "#quote" do
7
+ subject { builder }
8
+
9
+ it "should quote parameters properly" do
10
+ expect(subject.quote(3.14)).to eq "3.14"
11
+ expect(subject.quote(14)).to eq "14"
12
+
13
+ expect(subject.quote("3.14")).to eq "'3.14'"
14
+ expect(subject.quote("Ben Hur's Carriage")).to eq "'Ben Hur\\'s Carriage'"
15
+
16
+ expect(subject.quote(true)).to eq "true"
17
+ expect(subject.quote(false)).to eq "false"
18
+ expect(subject.quote(0 || 1)).to eq "0"
19
+
20
+ expect(subject.quote(:symbol)).to eq "'symbol'"
21
+ end
22
+ end
23
+
24
+ describe "#build" do
25
+ subject { builder.build(query, params) }
26
+
27
+ context "named parameters" do
28
+ let(:query) { "SELECT value FROM rpm WHERE f = %{f_val} group by time(%{minutes}m)" }
29
+ let(:params) { { f_val: "value", minutes: 5 } }
30
+
31
+ it { is_expected.to eq "SELECT value FROM rpm WHERE f = 'value' group by time(5m)" }
32
+
33
+ context "with string keys" do
34
+ let(:params) { { "f_val" => "value", "minutes" => 5 } }
35
+
36
+ it { is_expected.to eq "SELECT value FROM rpm WHERE f = 'value' group by time(5m)" }
37
+ end
38
+ end
39
+
40
+ context "positional parameter" do
41
+ let(:query) { "SELECT value FROM rpm WHERE time > %{1}" }
42
+ let(:params) { [1_437_019_900] }
43
+
44
+ it { is_expected.to eq "SELECT value FROM rpm WHERE time > 1437019900" }
45
+ end
46
+
47
+ context "missing parameters" do
48
+ let(:query) { "SELECT value FROM rpm WHERE time > %{1}" }
49
+ let(:params) { [] }
50
+
51
+ it { expect { subject }.to raise_error(/key\{1\} not found/) }
52
+ end
53
+
54
+ context "extra parameters" do
55
+ let(:query) { "SELECT value FROM rpm WHERE time > %{a}" }
56
+ let(:params) { { "a" => 0, "b" => 2 } }
57
+
58
+ it { is_expected.to eq "SELECT value FROM rpm WHERE time > 0" }
59
+ end
60
+ end
61
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: influxdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.7
4
+ version: 0.3.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Todd Persen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-14 00:00:00.000000000 Z
11
+ date: 2016-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -132,6 +132,7 @@ files:
132
132
  - lib/influxdb/logging.rb
133
133
  - lib/influxdb/max_queue.rb
134
134
  - lib/influxdb/point_value.rb
135
+ - lib/influxdb/query/builder.rb
135
136
  - lib/influxdb/query/cluster.rb
136
137
  - lib/influxdb/query/continuous_query.rb
137
138
  - lib/influxdb/query/core.rb
@@ -151,6 +152,7 @@ files:
151
152
  - spec/influxdb/cases/query_shard_space_spec.rb
152
153
  - spec/influxdb/cases/query_shard_spec.rb
153
154
  - spec/influxdb/cases/query_user_spec.rb
155
+ - spec/influxdb/cases/query_with_params_spec.rb
154
156
  - spec/influxdb/cases/querying_issue_7000_spec.rb
155
157
  - spec/influxdb/cases/querying_spec.rb
156
158
  - spec/influxdb/cases/retry_requests_spec.rb
@@ -161,6 +163,7 @@ files:
161
163
  - spec/influxdb/logging_spec.rb
162
164
  - spec/influxdb/max_queue_spec.rb
163
165
  - spec/influxdb/point_value_spec.rb
166
+ - spec/influxdb/query_builder_spec.rb
164
167
  - spec/influxdb/worker_spec.rb
165
168
  - spec/spec_helper.rb
166
169
  homepage: http://influxdb.org
@@ -198,6 +201,7 @@ test_files:
198
201
  - spec/influxdb/cases/query_shard_space_spec.rb
199
202
  - spec/influxdb/cases/query_shard_spec.rb
200
203
  - spec/influxdb/cases/query_user_spec.rb
204
+ - spec/influxdb/cases/query_with_params_spec.rb
201
205
  - spec/influxdb/cases/querying_issue_7000_spec.rb
202
206
  - spec/influxdb/cases/querying_spec.rb
203
207
  - spec/influxdb/cases/retry_requests_spec.rb
@@ -208,5 +212,6 @@ test_files:
208
212
  - spec/influxdb/logging_spec.rb
209
213
  - spec/influxdb/max_queue_spec.rb
210
214
  - spec/influxdb/point_value_spec.rb
215
+ - spec/influxdb/query_builder_spec.rb
211
216
  - spec/influxdb/worker_spec.rb
212
217
  - spec/spec_helper.rb