influxdb-arel 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.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +8 -0
  5. data/Gemfile +6 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +350 -0
  8. data/Rakefile +6 -0
  9. data/influxdb-arel.gemspec +24 -0
  10. data/lib/influxdb-arel.rb +1 -0
  11. data/lib/influxdb.rb +4 -0
  12. data/lib/influxdb/arel.rb +38 -0
  13. data/lib/influxdb/arel/alias_predication.rb +9 -0
  14. data/lib/influxdb/arel/attributes.rb +1 -0
  15. data/lib/influxdb/arel/attributes/attribute.rb +74 -0
  16. data/lib/influxdb/arel/core_extensions.rb +49 -0
  17. data/lib/influxdb/arel/expressions.rb +73 -0
  18. data/lib/influxdb/arel/math.rb +21 -0
  19. data/lib/influxdb/arel/nodes.rb +27 -0
  20. data/lib/influxdb/arel/nodes/and.rb +32 -0
  21. data/lib/influxdb/arel/nodes/binary.rb +47 -0
  22. data/lib/influxdb/arel/nodes/duration.rb +30 -0
  23. data/lib/influxdb/arel/nodes/equality.rb +11 -0
  24. data/lib/influxdb/arel/nodes/function.rb +47 -0
  25. data/lib/influxdb/arel/nodes/grouping.rb +11 -0
  26. data/lib/influxdb/arel/nodes/in.rb +8 -0
  27. data/lib/influxdb/arel/nodes/infix_operation.rb +51 -0
  28. data/lib/influxdb/arel/nodes/node.rb +19 -0
  29. data/lib/influxdb/arel/nodes/now.rb +15 -0
  30. data/lib/influxdb/arel/nodes/select_statement.rb +59 -0
  31. data/lib/influxdb/arel/nodes/sql_literal.rb +23 -0
  32. data/lib/influxdb/arel/nodes/table_alias.rb +23 -0
  33. data/lib/influxdb/arel/nodes/time.rb +13 -0
  34. data/lib/influxdb/arel/nodes/unary.rb +35 -0
  35. data/lib/influxdb/arel/predications.rb +137 -0
  36. data/lib/influxdb/arel/select_manager.rb +129 -0
  37. data/lib/influxdb/arel/table.rb +219 -0
  38. data/lib/influxdb/arel/tree_manager.rb +30 -0
  39. data/lib/influxdb/arel/version.rb +5 -0
  40. data/lib/influxdb/arel/visitor.rb +287 -0
  41. data/spec/lib/influxdb/arel/core_extensions_spec.rb +49 -0
  42. data/spec/lib/influxdb/arel/nodes/and_spec.rb +17 -0
  43. data/spec/lib/influxdb/arel/nodes/binary_spec.rb +49 -0
  44. data/spec/lib/influxdb/arel/nodes/duration_spec.rb +72 -0
  45. data/spec/lib/influxdb/arel/nodes/equality_spec.rb +5 -0
  46. data/spec/lib/influxdb/arel/nodes/function_spec.rb +69 -0
  47. data/spec/lib/influxdb/arel/nodes/grouping_spec.rb +10 -0
  48. data/spec/lib/influxdb/arel/nodes/in_spec.rb +13 -0
  49. data/spec/lib/influxdb/arel/nodes/now_spec.rb +8 -0
  50. data/spec/lib/influxdb/arel/nodes/sql_literal_spec.rb +28 -0
  51. data/spec/lib/influxdb/arel/nodes/table_alias_spec.rb +36 -0
  52. data/spec/lib/influxdb/arel/nodes/time_spec.rb +5 -0
  53. data/spec/lib/influxdb/arel/nodes/unary_spec.rb +25 -0
  54. data/spec/lib/influxdb/arel/select_manager_spec.rb +459 -0
  55. data/spec/lib/influxdb/arel/table_spec.rb +193 -0
  56. data/spec/lib/influxdb/arel_spec.rb +11 -0
  57. data/spec/spec_helper.rb +20 -0
  58. data/spec/support/examples/binary_node.rb +10 -0
  59. data/spec/support/examples/function_node.rb +14 -0
  60. data/spec/support/examples/node_as.rb +8 -0
  61. data/spec/support/examples/node_expressions.rb +145 -0
  62. data/spec/support/examples/node_math.rb +29 -0
  63. data/spec/support/examples/node_predications.rb +248 -0
  64. data/spec/support/examples/node_to_sql.rb +5 -0
  65. data/spec/support/examples/unary_node.rb +10 -0
  66. data/spec/support/fabrics.rb +21 -0
  67. metadata +177 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 93f531a5801d11ca235b597b784dbbaa4913c095
4
+ data.tar.gz: 3dee249e2b4273d429e5c368c80e5d36ad093255
5
+ SHA512:
6
+ metadata.gz: 2166d603b4dfc1be19b9513298968f24b712c75459e775f518c6a013439e95849ce629fd3594aea6f943c7e1a82c22de8d48de8868893125f423acf656cf6af7
7
+ data.tar.gz: 5f34262b49084e14b4ac57f380eb0c873f8ff9955dd653a7ebf6ed694812c88fa67f772cc59e953a4aab0c3f26653e202cbb879c0fb22463349f00e926083968
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --backtrace
3
+ --order random
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.1
6
+ - 2.1.2
7
+ - 2.1.3
8
+ - rbx-2
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in influxdb-arel.gemspec
4
+ gemspec
5
+
6
+ gem 'pry'
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 undr
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,350 @@
1
+ # Influxdb::Arel
2
+
3
+ Influxdb::Arel is a SQL AST manager for Influxdb dialect. It simplifies the generation of complex SQL queries.
4
+
5
+ [![Build Status](https://travis-ci.org/undr/influxdb-arel.svg?branch=master)](https://travis-ci.org/undr/influxdb-arel) [![Code Climate](https://codeclimate.com/github/undr/influxdb-arel/badges/gpa.svg)](https://codeclimate.com/github/undr/influxdb-arel)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'influxdb-arel'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ ```
18
+ $ bundle
19
+ ```
20
+
21
+ Or install it yourself as:
22
+
23
+ ```
24
+ $ gem install influxdb-arel
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ### Introduction
30
+
31
+ At start you should create a table which you will work with:
32
+
33
+ ```ruby
34
+ events = Influxdb::Arel::Table.new(:events)
35
+ events.to_sql
36
+ # => SELECT * FROM events
37
+ ```
38
+
39
+ You can use both string and symbol as table name:
40
+
41
+ ```ruby
42
+ Influxdb::Arel::Table.new('events') == Influxdb::Arel::Table.new(:events)
43
+ # => true
44
+ ```
45
+
46
+ You will get the same result.
47
+
48
+ If you want to use convenient shortcuts, such as `10.h.ago` or `1.w.time` you should require file with core extensions
49
+
50
+ ```ruby
51
+ require 'influxdb/arel/core_extensions'
52
+
53
+ 1.h
54
+ # => #<Influxdb::Arel::Nodes::Duration:0x00000102143a68 @left=1, @right="h">
55
+
56
+ 1.h.to_sql
57
+ # => "1h"
58
+
59
+ 1.h.time
60
+ # => #<Influxdb::Arel::Nodes::Time:0x0000010282f728 @expr=#<Influxdb::Arel::Nodes::Duration:0x0000010282f868 @left=1, @right="h">>
61
+
62
+ 1.h.time.to_sql
63
+ # => "time(1h)"
64
+
65
+ 1.h.ago.to_sql
66
+ # => "(now() - 1h)"
67
+
68
+ 1.h.since.to_sql
69
+ # => "(now() + 1h)"
70
+
71
+ 'time(1s)'.to_arel == Influxdb::Arel::Nodes::SqlLiteral.new('time(1s)')
72
+ # => true
73
+
74
+ 'time(1s)'.to_influxdb_arel == Influxdb::Arel::Nodes::SqlLiteral.new('time(1s)')
75
+ # => true
76
+
77
+ :events.to_arel == Influxdb::Arel::Table.new('events')
78
+ # => true
79
+
80
+ :events.to_influxdb_arel == Influxdb::Arel::Table.new('events')
81
+ # => true
82
+
83
+ 'MEAN(value)'.as('user_events')
84
+ # => #<Influxdb::Arel::Nodes::As:0x00000101218f70 @left="MEAN(value)", @right="user_events">
85
+
86
+ 'MEAN(value)'.as('user_events').to_sql
87
+ # => "MEAN(value) AS user_events"
88
+
89
+ :events.as('user_events')
90
+ # => #<Influxdb::Arel::Nodes::TableAlias:0x0000010180f8c0 @left=#<Influxdb::Arel::Table:0x0000010180f938 @name="events">, @right="user_events">
91
+
92
+ :events.as('user_events').to_sql
93
+ # => "events AS user_events"
94
+ ```
95
+
96
+ ### Setting of table names
97
+
98
+ There are several ways to set another table name to table object. You should call `from` method:
99
+
100
+ - With strings or symbols
101
+
102
+ ```ruby
103
+ events.from('events', :errors).to_sql
104
+ # => SELECT * FROM events, errors
105
+ ```
106
+
107
+ - With table objects
108
+
109
+ ```ruby
110
+ events.from(Influxdb::Arel::Table.new(:errors)).to_sql
111
+ # => SELECT * FROM errors
112
+ ```
113
+
114
+ - With sql literal objects
115
+
116
+ ```ruby
117
+ events.from(Influxdb::Arel::Nodes::SqlLiteral.new('errors')).to_sql
118
+ # => SELECT * FROM errors
119
+ ```
120
+
121
+ - With table aliases
122
+
123
+ *There will be only a table name without alias in result SQL because aliases are used only when joining tables*
124
+
125
+ ```ruby
126
+ events.from(events.as('user_errors')).to_sql
127
+ # => SELECT * FROM errors
128
+ ```
129
+
130
+ - With regexp object
131
+
132
+ ```ruby
133
+ events.from(/.*/).to_sql
134
+ # => SELECT * FROM /.*/
135
+ ```
136
+
137
+ ### Joining tables
138
+
139
+ You can join two tables using `join` method.
140
+
141
+ It will join two first tables from tables list if method is called without argument
142
+
143
+ ```ruby
144
+ table = Influxdb::Arel::Table.new('table')
145
+ table.from('table1', 'table2').join.to_sql
146
+ # => SELECT * FROM table1 INNER JOIN table2
147
+ ```
148
+
149
+ It will change nothing if method is called without argument and tables list contains less than two table.
150
+
151
+ ```ruby
152
+ table.join.to_sql
153
+ # => SELECT * FROM table
154
+ ```
155
+
156
+ It will join first table from tables list with given table if argument exists.
157
+
158
+ ```ruby
159
+ table.join('table2').to_sql
160
+ # => SELECT * FROM table INNER JOIN table2
161
+ ```
162
+
163
+ ```ruby
164
+ table.from('table1', 'table2').join('table3').to_sql
165
+ # => SELECT * FROM table1 INNER JOIN table3
166
+ ```
167
+
168
+ Also, you can define alias for each joined table. It would be useful for self joining table.
169
+
170
+ ```ruby
171
+ table.from(table.as(:table_one)).join(table.as(:table_two)).to_sql
172
+ # => SELECT * FROM table AS table_one INNER JOIN table AS table_two
173
+ ```
174
+
175
+ Chaining this method will replace previous join definition.
176
+
177
+ ```ruby
178
+ table1 = Influxdb::Arel::Table.new('table')
179
+ table.join(table1).join(table1.as('alias')).to_sql
180
+ # => SELECT * FROM table INNER JOIN table1 AS alias
181
+ ```
182
+
183
+ ### Merging tables
184
+
185
+ You can merge tables using `merge` method.
186
+
187
+ It will merge two first tables from tables list if method is called without argument.
188
+
189
+ ```ruby
190
+ table = Influxdb::Arel::Table.new('table')
191
+ table.from('table1', 'table2').merge.to_sql
192
+ # => SELECT * FROM table1 MERGE table2
193
+ ```
194
+
195
+ It will change nothing if method is called without argument and tables list contains less than two table.
196
+
197
+ ```ruby
198
+ table.merge.to_sql
199
+ # => SELECT * FROM table
200
+ ```
201
+
202
+ It will merge first table from tables list with given table if argument exists.
203
+
204
+ ```ruby
205
+ table.merge('table2').to_sql
206
+ # => SELECT * FROM table MERGE table2
207
+
208
+ table.from('table1', 'table2').merge('table3').to_sql
209
+ # => SELECT * FROM table1 MERGE table3
210
+ ```
211
+
212
+ Chaining this method will replace previous merge definition.
213
+
214
+ ```ruby
215
+ table.megre('table1').merge('table2').to_sql
216
+ # => SELECT * FROM table MERGE table2
217
+ ```
218
+
219
+ ### Grouping of results
220
+
221
+ Grouping of results by specified columns or expressions, such as `time(10m)`:
222
+
223
+ ```ruby
224
+ table = Influxdb::Arel::Table.new('table')
225
+ table.group(table.time(10.m), table[:host]).to_sql
226
+ # => SELECT * FROM table GROUP BY time(10m), host
227
+ ```
228
+
229
+ If you want to fill intervals with no data you should call `fill` method:
230
+
231
+ ```ruby
232
+ table.group(10.m.time, table[:host]).fill(0).to_sql
233
+ # => SELECT * FROM table GROUP BY time(10m), host fill(0)
234
+ ```
235
+
236
+ Chaining this method will add expression to the grouping set.
237
+
238
+ ```ruby
239
+ table.group(table.time(10.m)).group(:host).to_sql
240
+ # => SELECT * FROM table GROUP BY time(10m), host
241
+ ```
242
+
243
+ ### Ordering of results
244
+
245
+ Yo can set the ordering of results using `order` method
246
+
247
+ Possible values:
248
+
249
+ * `:asc`- Default value. Results will be sorted by ascending order.
250
+ * `'asc'`- Results will be sorted by ascending order.
251
+ * `:desc`- Results will be sorted by descending order.
252
+ * `'desc'`- Results will be sorted by descending order.
253
+
254
+ ```ruby
255
+ table = Influxdb::Arel::Table.new('table')
256
+ table.order(:desc).to_sql
257
+ table.order('desc').to_sql
258
+ # => SELECT * FROM table ORDER DESC
259
+
260
+ table.order(:asc).to_sql
261
+ table.order('asc').to_sql
262
+ # => SELECT * FROM table ORDER ASC
263
+ ```
264
+
265
+ As well it's possible to use `asc` and `desc` methods
266
+
267
+ ```ruby
268
+ table.where(table[:time].lteq(Time.now)).asc.to_sql
269
+ # => SELECT * FROM table WHERE time <= 1412137303000000 ORDER ASC
270
+ table.where(table[:time].lteq(Time.now)).desc.to_sql
271
+ # => SELECT * FROM table WHERE time <= 1412137303000000 ORDER DESC
272
+ ```
273
+
274
+ Chaining this methods will replace previous order definition.
275
+
276
+ ```ruby
277
+ table.where(table[:time].lteq(Time.now)).asc.desc.to_sql
278
+ # => SELECT * FROM table WHERE time <= 1412137303000000 ORDER DESC
279
+ ```
280
+
281
+ ### Query conditions
282
+
283
+ You can specify conditions for selection query using `where` method
284
+
285
+ ```ruby
286
+ table = Influxdb::Arel::Table.new('table')
287
+ table.where(table[:name].eq('Undr')).to_sql
288
+ # => SELECT * FROM table WHERE name = 'Undr'
289
+ ```
290
+
291
+ ```ruby
292
+ table.where(table[:name].eq('Undr').or(table[:name].eq('Andrei'))).to_sql
293
+ # => SELECT * FROM table WHERE name = 'Undr' OR name = 'Andrei'
294
+ ```
295
+
296
+ Chaining this method will add expression to the condition set. They will join using `AND` boolean expression.
297
+
298
+ ```ruby
299
+ table.where(table[:name].eq('Undr')).where(table[:time].lt(10.h.ago).to_sql
300
+ # => SELECT * FROM table WHERE name = 'Undr' AND time < (now() - 10h)
301
+ ```
302
+
303
+
304
+ ### SELECT clause
305
+
306
+ You can specify columns or expressions for SELECT clause using `column` method. By default, it's `*`.
307
+
308
+ ```ruby
309
+ table = Influxdb::Arel::Table.new('cpu_load')
310
+ table.to_sql
311
+ # => SELECT * FROM cpu_load
312
+
313
+ table.column((table[:system] + table[:user]).as(:sum)).to_sql
314
+ # => SELECT (system + user) AS sum FROM cpu_load
315
+
316
+ table.column(
317
+ table[:idle].mean.as(:idle_mean),
318
+ table[:user].mean.as(:user_mean)
319
+ ).group(1.d.time).to_sql
320
+ # => SELECT MEAN(idle) AS idle_mean, MEAN(user) AS user_mean FROM cpu_load GROUP BY time(1d)
321
+ ```
322
+
323
+ It might be convenient to use aliases for complex expressions, such as functions or some mathematical expressions. Also the aliasing needed when joining tables. For example:
324
+
325
+ ```ruby
326
+ alias1 = table.as('table1')
327
+ alias2 = table.as('table2')
328
+ table.from(alias1, alias2).
329
+ column(alias1[:idle], alias2[:idle]).
330
+ join.to_sql
331
+ # => SELECT table1.idle, table2.idle FROM table AS table1 INNER JOIN table AS table2
332
+ ```
333
+
334
+ ### Limits
335
+
336
+ You can set a limit for a result set
337
+
338
+ ```ruby
339
+ table = Influxdb::Arel::Table.new('cpu_load')
340
+ table.take(100).to_sql
341
+ # => SELECT * FROM cpu_load LIMIT 100
342
+ ```
343
+
344
+ ## Contributing
345
+
346
+ 1. Fork it ( https://github.com/undr/influxdb-arel/fork )
347
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
348
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
349
+ 4. Push to the branch (`git push origin my-new-feature`)
350
+ 5. Create a new Pull Request
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'influxdb/arel/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "influxdb-arel"
8
+ spec.version = Influxdb::Arel::VERSION
9
+ spec.authors = ["undr"]
10
+ spec.email = ["undr@yandex.ru"]
11
+ spec.summary = %q{Influxdb SQL AST manager.}
12
+ spec.description = %q{Influxdb::Arel is a SQL AST manager for Influxdb dialect.}
13
+ spec.homepage = "https://github.com/undr/influxdb-arel"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ end