influxer 0.2.4 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +12 -0
  4. data/.travis.yml +1 -17
  5. data/Changelog.md +7 -0
  6. data/Gemfile +7 -0
  7. data/README.md +6 -20
  8. data/Rakefile +4 -0
  9. data/gemfiles/rails42.gemfile +4 -1
  10. data/influxer.gemspec +6 -6
  11. data/lib/influxer/client.rb +4 -44
  12. data/lib/influxer/config.rb +23 -14
  13. data/lib/influxer/engine.rb +0 -1
  14. data/lib/influxer/metrics/metrics.rb +40 -7
  15. data/lib/influxer/metrics/relation/calculations.rb +13 -7
  16. data/lib/influxer/metrics/relation/time_query.rb +14 -8
  17. data/lib/influxer/metrics/relation/where_clause.rb +62 -0
  18. data/lib/influxer/metrics/relation.rb +67 -76
  19. data/lib/influxer/metrics/scoping.rb +4 -4
  20. data/lib/influxer/model.rb +4 -0
  21. data/lib/influxer/rails/client.rb +47 -0
  22. data/lib/influxer/version.rb +1 -1
  23. data/lib/influxer.rb +4 -2
  24. data/spec/cases/points_spec.rb +34 -0
  25. data/spec/client_spec.rb +21 -24
  26. data/spec/fixtures/empty_result.json +21 -0
  27. data/spec/fixtures/single_series.json +29 -0
  28. data/spec/metrics/metrics_spec.rb +139 -113
  29. data/spec/metrics/relation_spec.rb +160 -105
  30. data/spec/metrics/scoping_spec.rb +11 -17
  31. data/spec/model/user_spec.rb +44 -0
  32. data/spec/spec_helper.rb +38 -8
  33. data/spec/support/metrics/action_metrics.rb +3 -0
  34. data/spec/support/metrics/custom_metrics.rb +4 -0
  35. data/spec/support/{dummy_metrics.rb → metrics/dummy_metrics.rb} +2 -1
  36. data/spec/support/metrics/user_metrics.rb +4 -0
  37. data/spec/support/metrics/visits_metrics.rb +4 -0
  38. data/spec/support/shared_contexts/shared_query.rb +16 -0
  39. data/spec/support/user.rb +14 -0
  40. metadata +42 -71
  41. data/gemfiles/rails40.gemfile +0 -7
  42. data/gemfiles/rails41.gemfile +0 -7
  43. data/lib/influxer/metrics/fanout.rb +0 -65
  44. data/lib/influxer/metrics/relation/fanout_query.rb +0 -49
  45. data/lib/tasks/influxer_tasks.rake +0 -4
  46. data/spec/config_spec.rb +0 -17
  47. data/spec/dummy/README.rdoc +0 -28
  48. data/spec/dummy/Rakefile +0 -6
  49. data/spec/dummy/app/assets/images/.keep +0 -0
  50. data/spec/dummy/app/assets/javascripts/application.js +0 -13
  51. data/spec/dummy/app/assets/stylesheets/application.css +0 -15
  52. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  53. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  54. data/spec/dummy/app/helpers/application_helper.rb +0 -2
  55. data/spec/dummy/app/mailers/.keep +0 -0
  56. data/spec/dummy/app/metrics/testo_metrics.rb +0 -3
  57. data/spec/dummy/app/models/.keep +0 -0
  58. data/spec/dummy/app/models/concerns/.keep +0 -0
  59. data/spec/dummy/app/models/testo.rb +0 -6
  60. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  61. data/spec/dummy/bin/bundle +0 -3
  62. data/spec/dummy/bin/rails +0 -4
  63. data/spec/dummy/bin/rake +0 -4
  64. data/spec/dummy/config/application.rb +0 -23
  65. data/spec/dummy/config/boot.rb +0 -5
  66. data/spec/dummy/config/database.yml +0 -25
  67. data/spec/dummy/config/environment.rb +0 -5
  68. data/spec/dummy/config/environments/development.rb +0 -37
  69. data/spec/dummy/config/environments/production.rb +0 -83
  70. data/spec/dummy/config/environments/test.rb +0 -38
  71. data/spec/dummy/config/influxdb.yml +0 -5
  72. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
  73. data/spec/dummy/config/initializers/cookies_serializer.rb +0 -3
  74. data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -4
  75. data/spec/dummy/config/initializers/inflections.rb +0 -16
  76. data/spec/dummy/config/initializers/mime_types.rb +0 -4
  77. data/spec/dummy/config/initializers/session_store.rb +0 -3
  78. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
  79. data/spec/dummy/config/locales/en.yml +0 -23
  80. data/spec/dummy/config/routes.rb +0 -56
  81. data/spec/dummy/config/secrets.yml +0 -25
  82. data/spec/dummy/config.ru +0 -4
  83. data/spec/dummy/db/migrate/20140730133818_add_testos.rb +0 -11
  84. data/spec/dummy/db/migrate/20140731162044_add_column_to_testos.rb +0 -5
  85. data/spec/dummy/db/schema.rb +0 -22
  86. data/spec/dummy/db/test.sqlite3 +0 -0
  87. data/spec/dummy/lib/assets/.keep +0 -0
  88. data/spec/dummy/log/.keep +0 -0
  89. data/spec/dummy/public/404.html +0 -67
  90. data/spec/dummy/public/422.html +0 -67
  91. data/spec/dummy/public/500.html +0 -66
  92. data/spec/dummy/public/favicon.ico +0 -0
  93. data/spec/fixtures/fanout_series.json +0 -23
  94. data/spec/metrics/fanout_spec.rb +0 -61
  95. data/spec/model/testo_spec.rb +0 -27
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a70e770a10a4ba180183d675081265ed34c96a18
4
- data.tar.gz: ce6d3d39937bc7eeabc4b4076bb9095e6b9eac59
3
+ metadata.gz: ed8a85c7e2c801bd415689ccfbf4bddf020df2b6
4
+ data.tar.gz: 9b42fc50e6dec5f287f193e0dbdb26ad983e533f
5
5
  SHA512:
6
- metadata.gz: 23a20e2f8130fa8ad58c1ad961afd71f8bfa3a55ed744dc999857c6dd505b69ddcfa659cc2a885175a6e21005f836e1ee1f6d01850e9fbf898234e8ff6108562
7
- data.tar.gz: 0373880b57e571673420d63297b81d4ffd8af6dee289adb2c9ccc8332447e736b841c92a0b2f6b11ec04e72ddd066a7ede9742d545706d1607d0a6891e3037b4
6
+ metadata.gz: 11ce8b4eb589f2a701603271b219f9c69004ed3854bc6c00cffb3b34ea7fd67faecfa5596c93af95b33f335c8105e390d2b9d5bf649164a1cf5b293cf3a79f36
7
+ data.tar.gz: c6711090feeef17151a69282a42d8db28ca4b90115571d17023b44b93453d5a843cd0200d4fa5b586807f86d682146ef77236d6c1665396ac7ce74224a2f1511
data/.gitignore CHANGED
@@ -32,5 +32,6 @@ spec/dummy/db/*.sqlite3-journal
32
32
  spec/dummy/tmp/
33
33
 
34
34
  Gemfile.lock
35
+ Gemfile.local
35
36
  .rspec
36
37
  *.gem
data/.rubocop.yml CHANGED
@@ -11,6 +11,12 @@ AllCops:
11
11
  DisplayCopNames: true
12
12
  StyleGuideCopsOnly: false
13
13
 
14
+ Style/AccessorMethodName:
15
+ Enabled: false
16
+
17
+ Style/TrivialAccessors:
18
+ Enabled: false
19
+
14
20
  Style/Documentation:
15
21
  Exclude:
16
22
  - 'spec/**/*.rb'
@@ -18,10 +24,16 @@ Style/Documentation:
18
24
  Style/StringLiterals:
19
25
  Enabled: false
20
26
 
27
+ Style/SpaceInsideStringInterpolation:
28
+ EnforcedStyle: no_space
29
+
21
30
  Style/BlockDelimiters:
22
31
  Exclude:
23
32
  - 'spec/**/*.rb'
24
33
 
34
+ Lint/AmbiguousRegexpLiteral:
35
+ Enabled: false
36
+
25
37
  Metrics/MethodLength:
26
38
  Exclude:
27
39
  - 'spec/**/*.rb'
data/.travis.yml CHANGED
@@ -1,22 +1,6 @@
1
1
  language: ruby
2
2
  cache: bundler
3
- rvm:
4
- - 2.0.0
5
- - 2.1
6
-
7
- gemfile:
8
- - Gemfile
9
-
10
3
  matrix:
11
4
  include:
12
- - rvm: 2.0.0
13
- gemfile: gemfiles/rails40.gemfile
14
-
15
- - rvm: 2.1
16
- gemfile: gemfiles/rails40.gemfile
17
-
18
- - rvm: 2.1
19
- gemfile: gemfiles/rails41.gemfile
20
-
21
- - rvm: 2.1
5
+ - rvm: 2.2.2
22
6
  gemfile: gemfiles/rails42.gemfile
data/Changelog.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 0.3.1
2
+ - Add order, soffset, slimit methods to Relation
3
+ - Fix query statements order
4
+
5
+ ## 0.3.0
6
+ - Upgrade to InfluxDB 0.9.x
7
+
1
8
  ## 0.2.3
2
9
  - Parse fanout queries points to handle _fanouted_ values
3
10
  - Add Rubocop config and cleanup code style
data/Gemfile CHANGED
@@ -1,3 +1,10 @@
1
1
  source "https://rubygems.org"
2
2
  gemspec
3
3
 
4
+ local_gemfile = 'Gemfile.local'
5
+
6
+ if File.exist?(local_gemfile)
7
+ eval(File.read(local_gemfile)) # rubocop:disable Lint/Eval
8
+ else
9
+ gem 'activerecord', '~>4.2'
10
+ end
data/README.md CHANGED
@@ -1,7 +1,8 @@
1
- [![Build Status](https://travis-ci.org/palkan/influxer.svg?branch=master)](https://travis-ci.org/palkan/influxer)
2
-
1
+ [![Build Status](https://travis-ci.org/palkan/influxer.svg?branch=master)](https://travis-ci.org/palkan/influxer) [![Vexor Status](https://ci.vexor.io/projects/55e92786-f1de-4e69-8f58-889453c2d71c/status.svg)](https://ci.vexor.io/ui/projects/55e92786-f1de-4e69-8f58-889453c2d71c/builds)
3
2
  ## Influxer
4
3
 
4
+ **NOTE**: Version 0.3.x supports InfluxDB >= 0.9.0. For InfluxDB 0.8.x use [version 0.2.5](https://github.com/palkan/influxer/tree/0.2.5).
5
+
5
6
  Influxer provides an ActiveRecord-style way to work with [InfluxDB](https://influxdb.com/) with many useful features, such as:
6
7
  - Familar query language (use `select`, `where`, `not`, `group` etc).
7
8
  - Support for Regex conditions: `where(page_id: /^home\/.*/) #=> select * ... where page_id=~/^home\/.*/`.
@@ -14,6 +15,8 @@ Influxer provides an ActiveRecord-style way to work with [InfluxDB](https://infl
14
15
  ```ruby
15
16
  class Metrics < Influxer::Metrics
16
17
  default_scope -> { time(:hour).limit(1000) }
18
+ tags :account_id
19
+ attributes :value
17
20
  scope :unlimited, -> { limit(nil) }
18
21
  scope :by_account, -> (id) { where(account_id: id) if id.present? }
19
22
  end
@@ -25,23 +28,6 @@ Influxer provides an ActiveRecord-style way to work with [InfluxDB](https://infl
25
28
  # => select * from "metrics" group by time(1w) where account_id=1
26
29
 
27
30
  ```
28
- - Support for handling fanout series as one metrics.
29
- ```ruby
30
- class Metrics < Influxer::Metrics
31
- fanout :account, :user, :page
32
- end
33
-
34
- Metrics.where(account: 1)
35
- # => select * from "metrics_account_1"
36
-
37
-
38
- Metrics.where(page: 'home').where(user: 12)
39
- # => select * from "metrics_user_12_page_home"
40
-
41
- Metrics.where(page: /(home|faq)/).where(account: 1).where(user: 12)
42
- # => select * from /^metrics_account_1_user_12_page_(home|faq)$/
43
-
44
- ```
45
31
  - Integrate with your model:
46
32
  ```ruby
47
33
  class UserVisits < Influxer::Metrics
@@ -59,4 +45,4 @@ Influxer provides an ActiveRecord-style way to work with [InfluxDB](https://infl
59
45
  #=> select * from user_visits where page_id='home'
60
46
  ```
61
47
 
62
- Find more on [Wiki](/palkan/influxer/wiki).
48
+ Find more on [Wiki](https://github.com/palkan/influxer/wiki).
data/Rakefile CHANGED
@@ -4,3 +4,7 @@ require 'rspec/core/rake_task'
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
6
  task :default => :spec
7
+
8
+ task :console do
9
+ sh 'pry -r ./lib/influxer.rb'
10
+ end
@@ -2,6 +2,9 @@ source 'https://rubygems.org'
2
2
 
3
3
  gem 'sqlite3', platform: :mri
4
4
  gem 'activerecord-jdbcsqlite3-adapter', platform: :jruby
5
- gem 'rails', '~> 4.2.0'
5
+ gem 'activerecord', '~> 4.2.0'
6
+
7
+ # TEMP
8
+ gem 'influxdb', github: 'influxdb/influxdb-ruby'
6
9
 
7
10
  gemspec path: '..'
data/influxer.gemspec CHANGED
@@ -15,16 +15,16 @@ Gem::Specification.new do |s|
15
15
  s.files = `git ls-files`.split($/)
16
16
  s.require_paths = ["lib"]
17
17
 
18
- s.add_runtime_dependency "rails", '~> 4.0'
19
- s.add_dependency "influxdb", "~> 0.1.8"
20
- s.add_dependency "anyway_config", "~>0.3"
18
+ s.add_dependency "activemodel", '>= 4.0'
19
+ s.add_dependency "influxdb", "~> 0.2.2"
20
+ s.add_dependency "anyway_config", "~>0.3.0"
21
21
 
22
22
  s.add_development_dependency "timecop"
23
23
  s.add_development_dependency "simplecov", ">= 0.3.8"
24
-
24
+ s.add_development_dependency 'rake', '~> 10.1'
25
25
  s.add_development_dependency 'sqlite3'
26
- s.add_development_dependency 'pry'
26
+ s.add_development_dependency 'activerecord', '>= 4.0'
27
27
  s.add_development_dependency 'pry-byebug'
28
28
  s.add_development_dependency "rspec", "~> 3.1.0"
29
- s.add_development_dependency "rspec-rails", "~> 3.1.0"
29
+ s.add_development_dependency "webmock", "~> 1.21.0"
30
30
  end
@@ -4,52 +4,12 @@ module Influxer
4
4
  # InfluxDB API client
5
5
  class Client < ::InfluxDB::Client
6
6
  def initialize
7
- @instrumenter = ActiveSupport::Notifications.instrumenter
8
- super Influxer.config.database, Influxer.config.as_json.symbolize_keys!
7
+ super Influxer.config.as_json.symbolize_keys!
9
8
  end
10
9
 
11
- def cached_query(sql)
12
- log(sql) do
13
- if Influxer.config.cache == false
14
- query(sql)
15
- else
16
- Rails.cache.fetch(normalized_cache_key(sql), cache_options(sql)) { query(sql) }
17
- end
18
- end
19
- end
20
-
21
- private
22
-
23
- def log(sql)
24
- return yield unless logger.debug?
25
-
26
- start_ts = Time.now
27
- res = yield
28
- duration = (Time.now - start_ts) * 1000
29
-
30
- name = "InfluxDB SQL (#{duration.round(1)}ms)"
31
-
32
- # bold black name and blue query string
33
- msg = "\e[1m\e[30m#{name}\e[0m \e[34m#{sql}\e[0m"
34
- logger.debug msg
35
- res
36
- end
37
-
38
- # if sql contains 'now()' set expires to 1 minute or :cache_now_for value
39
- # of config.cache if defined
40
- def cache_options(sql = nil)
41
- options = Influxer.config.cache.dup
42
- options[:expires_in] = (options[:cache_now_for] || 60) if sql =~ /\snow\(\)/
43
- options
44
- end
45
-
46
- # add prefix; remove whitespaces
47
- def normalized_cache_key(sql)
48
- "influxer:#{sql.gsub(/\s*/, '')}"
49
- end
50
-
51
- def logger
52
- Rails.logger
10
+ # Public #execute
11
+ def exec(sql)
12
+ execute(sql)
53
13
  end
54
14
  end
55
15
  end
@@ -5,20 +5,29 @@ module Influxer
5
5
  class Config < Anyway::Config
6
6
  config_name :influxdb
7
7
 
8
- attr_config database: 'db',
9
- host: 'localhost',
10
- port: 8086,
11
- username: 'root',
12
- password: 'root',
13
- use_ssl: false,
14
- async: true,
15
- cache: false,
16
- retry: false,
17
- time_precision: 's',
18
- initial_delay: 0.01,
19
- max_delay: 30,
20
- read_timeout: 30,
21
- write_timeout: 5
8
+ # influxdb-ruby configuration parameters + cache option
9
+ attr_config :hosts,
10
+ :host,
11
+ :port,
12
+ :username,
13
+ :password,
14
+ :database,
15
+ :time_precision,
16
+ :use_ssl,
17
+ :verify_ssl,
18
+ :ssl_ca_cert,
19
+ :auth_method,
20
+ :initial_delay,
21
+ :max_delay,
22
+ :open_timeout,
23
+ :read_timeout,
24
+ :retry,
25
+ :prefix,
26
+ :denormalize,
27
+ :udp,
28
+ :async,
29
+ database: 'db',
30
+ cache: false
22
31
 
23
32
  def load
24
33
  super
@@ -1,5 +1,4 @@
1
1
  require 'influxer'
2
- require 'rails'
3
2
 
4
3
  module Influxer
5
4
  class Engine < Rails::Engine # :nodoc:
@@ -1,6 +1,5 @@
1
1
  require 'influxer/metrics/relation'
2
2
  require 'influxer/metrics/scoping'
3
- require 'influxer/metrics/fanout'
4
3
  require 'active_model'
5
4
 
6
5
  module Influxer
@@ -8,13 +7,13 @@ module Influxer
8
7
  class MetricsInvalid < MetricsError; end
9
8
 
10
9
  # Base class for InfluxDB querying and writing
10
+ # rubocop:disable Metrics/ClassLength
11
11
  class Metrics
12
12
  include ActiveModel::Model
13
13
  include ActiveModel::Validations
14
14
  extend ActiveModel::Callbacks
15
15
 
16
16
  include Influxer::Scoping
17
- include Influxer::Fanout
18
17
 
19
18
  define_model_callbacks :write
20
19
 
@@ -23,15 +22,16 @@ module Influxer
23
22
  delegate(
24
23
  *(
25
24
  [
26
- :write, :select, :where, :group,
27
- :merge, :time, :past, :since, :limit,
28
- :fill, :delete_all
25
+ :write, :write!, :select, :where,
26
+ :group, :time, :past, :since,
27
+ :limit, :offset, :fill, :delete_all
29
28
  ] + Influxer::Calculations::CALCULATION_METHODS
30
29
  ),
31
30
  to: :all
32
31
  )
33
32
 
34
33
  attr_reader :series
34
+ attr_accessor :tag_names
35
35
 
36
36
  def attributes(*attrs)
37
37
  attrs.each do |name|
@@ -45,10 +45,23 @@ module Influxer
45
45
  end
46
46
  end
47
47
 
48
+ def tags(*attrs)
49
+ attributes(*attrs)
50
+ self.tag_names ||= []
51
+ self.tag_names += attrs.map(&:to_s)
52
+ end
53
+
54
+ def tag?(name)
55
+ tag_names.include?(name.to_s)
56
+ end
57
+
48
58
  def inherited(subclass)
49
59
  subclass.set_series
60
+ subclass.tag_names = tag_names.nil? ? [] : tag_names.dup
50
61
  end
51
62
 
63
+ # rubocop:disable Metrics/MethodLength
64
+ # rubocop:disable Metrics/AbcSize
52
65
  def set_series(*args)
53
66
  if args.empty?
54
67
  matches = to_s.match(/^(.*)Metrics$/)
@@ -63,6 +76,8 @@ module Influxer
63
76
  @series = args
64
77
  end
65
78
  end
79
+ # rubocop:enable Metrics/MethodLength
80
+ # rubocop:enable Metrics/AbcSize
66
81
 
67
82
  def all
68
83
  if current_scope
@@ -72,6 +87,7 @@ module Influxer
72
87
  end
73
88
  end
74
89
 
90
+ # rubocop:disable Metrics/MethodLength
75
91
  def quoted_series(val = @series, instance = nil)
76
92
  case val
77
93
  when Regexp
@@ -80,7 +96,7 @@ module Influxer
80
96
  quoted_series(val.call(instance))
81
97
  when Array
82
98
  if val.length > 1
83
- "merge(#{ val.map { |s| quoted_series(s) }.join(',') })"
99
+ "merge(#{val.map { |s| quoted_series(s) }.join(',')})"
84
100
  else
85
101
  quoted_series(val.first)
86
102
  end
@@ -88,8 +104,11 @@ module Influxer
88
104
  '"' + val.to_s.gsub(/\"/) { %q(\") } + '"'
89
105
  end
90
106
  end
107
+ # rubocop:enable Metrics/MethodLength
91
108
  end
92
109
 
110
+ delegate :tag_names, to: :class
111
+
93
112
  def initialize(attributes = {})
94
113
  @attributes = {}
95
114
  @persisted = false
@@ -113,7 +132,7 @@ module Influxer
113
132
  end
114
133
 
115
134
  def write_point
116
- client.write_point unquote(series), @attributes
135
+ client.write_point unquote(series), values: values, tags: tags
117
136
  @persisted = true
118
137
  end
119
138
 
@@ -129,6 +148,20 @@ module Influxer
129
148
  Influxer.client
130
149
  end
131
150
 
151
+ def dup
152
+ self.class.new(@attributes)
153
+ end
154
+
155
+ # Returns hash with metrics values
156
+ def values
157
+ @attributes.reject { |k, _| tag_names.include?(k.to_s) }
158
+ end
159
+
160
+ # Returns hash with metrics tags
161
+ def tags
162
+ @attributes.select { |k, _| tag_names.include?(k.to_s) }
163
+ end
164
+
132
165
  attributes :time
133
166
 
134
167
  private
@@ -4,18 +4,24 @@ module Influxer
4
4
  [
5
5
  :count, :min, :max, :mean,
6
6
  :mode, :median, :distinct, :derivative,
7
- :stddev, :sum, :first, :last, :difference,
8
- :percentile, :histogram, :top, :bottom
7
+ :stddev, :sum, :first, :last
9
8
  ]
10
9
 
10
+ # rubocop:disable Metrics/LineLength
11
11
  CALCULATION_METHODS.each do |name|
12
12
  class_eval <<-CODE, __FILE__, __LINE__ + 1
13
- def #{name}(val, option=nil) # def count(val)
14
- @values[:has_calculations] = true # @values[:has_calculations] = true
15
- select_values << "#{name}(\#\{val\}\#\{option ? ','+option.to_s : ''\})" # select_values << "count(\#\{val\})"
16
- self # self
17
- end # end
13
+ def #{name}(val, alias_name = nil) # def count(val)
14
+ @values[:has_calculations] = true # @values[:has_calculations] = true
15
+ select_values << "#{name}(\#\{val\})\#\{alias_name ? ' as '+alias_name.to_s : ''\}" # select_values << "count(\#\{val\})"
16
+ self # self
17
+ end # end
18
18
  CODE
19
19
  end
20
+
21
+ def percentile(name, val, alias_name = nil)
22
+ @values[:has_calculations] = true
23
+ select_values << "percentile(#{name},#{val})#{alias_name ? ' as ' + alias_name.to_s : ''}"
24
+ self
25
+ end
20
26
  end
21
27
  end
@@ -4,11 +4,14 @@ module Influxer
4
4
  hour: '1h',
5
5
  minute: '1m',
6
6
  second: '1s',
7
- ms: '1u',
7
+ ms: '1ms',
8
+ u: '1u',
8
9
  week: '1w',
9
10
  day: '1d',
10
11
  month: '30d'
11
- }
12
+ }.freeze
13
+
14
+ FILL_RESERVED = %i(null previous none).freeze
12
15
 
13
16
  # Add group value to relation. To be used instead of `group("time(...)").
14
17
  # Accepts symbols and strings.
@@ -20,7 +23,6 @@ module Influxer
20
23
  #
21
24
  # Metrics.time("4d", fill: 0)
22
25
  # # select * from metrics group by time(4d) fill(0)
23
-
24
26
  def time(val, options = {})
25
27
  if val.is_a?(Symbol)
26
28
  @values[:time] = TIME_ALIASES[val] || '1' + val.to_s
@@ -28,9 +30,7 @@ module Influxer
28
30
  @values[:time] = val
29
31
  end
30
32
 
31
- unless options[:fill].nil?
32
- fill((options[:fill] == :null) ? 'null' : options[:fill].to_i)
33
- end
33
+ build_fill(options[:fill])
34
34
  self
35
35
  end
36
36
 
@@ -45,11 +45,10 @@ module Influxer
45
45
  #
46
46
  # Metrics.past(2.days)
47
47
  # # select * from metrics where time > now() - 172800s
48
-
49
48
  def past(val)
50
49
  case val
51
50
  when Symbol
52
- where("time > now() - #{ TIME_ALIASES[val] || ('1'+val.to_s) }")
51
+ where("time > now() - #{TIME_ALIASES[val] || ('1' + val.to_s)}")
53
52
  when String
54
53
  where("time > now() - #{val}")
55
54
  else
@@ -69,5 +68,12 @@ module Influxer
69
68
  def since(val)
70
69
  where("time > #{val.to_i}s")
71
70
  end
71
+
72
+ private
73
+
74
+ def build_fill(val)
75
+ return if val.nil?
76
+ fill(FILL_RESERVED.include?(val) ? val.to_s : val.to_i)
77
+ end
72
78
  end
73
79
  end
@@ -0,0 +1,62 @@
1
+ module Influxer
2
+ module WhereClause #:nodoc:
3
+ # accepts hash or strings conditions
4
+ def where(*args, **hargs)
5
+ build_where(args, hargs, false)
6
+ self
7
+ end
8
+
9
+ def not(*args, **hargs)
10
+ build_where(args, hargs, true)
11
+ self
12
+ end
13
+
14
+ protected
15
+
16
+ def build_where(args, hargs, negate)
17
+ case
18
+ when (args.present? && args[0].is_a?(String))
19
+ where_values.concat args.map { |str| "(#{str})" }
20
+ when hargs.present?
21
+ build_hash_where(hargs, negate)
22
+ else
23
+ false
24
+ end
25
+ end
26
+
27
+ def build_hash_where(hargs, negate = false)
28
+ hargs.each do |key, val|
29
+ where_values << "(#{build_eql(key, val, negate)})"
30
+ end
31
+ end
32
+
33
+ def build_eql(key, val, negate)
34
+ case val
35
+ when Regexp
36
+ "#{key}#{negate ? '!~' : '=~'}#{val.inspect}"
37
+ when Array
38
+ build_in(key, val, negate)
39
+ when Range
40
+ build_range(key, val, negate)
41
+ else
42
+ "#{key}#{negate ? '<>' : '='}#{quoted(val, key)}"
43
+ end
44
+ end
45
+
46
+ def build_in(key, arr, negate)
47
+ buf = []
48
+ arr.each do |val|
49
+ buf << build_eql(key, val, negate)
50
+ end
51
+ "#{buf.join(negate ? ' and ' : ' or ')}"
52
+ end
53
+
54
+ def build_range(key, val, negate)
55
+ if negate
56
+ "#{key}<#{quoted(val.begin)} and #{key}>#{quoted(val.end)}"
57
+ else
58
+ "#{key}>#{quoted(val.begin)} and #{key}<#{quoted(val.end)}"
59
+ end
60
+ end
61
+ end
62
+ end