influxdb-arel 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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