Influxdb::Arel is a SQL AST manager for Influxdb dialect. It simplifies the generation of complex SQL queries.
Add this line to your application's Gemfile:
gem 'influxdb-arel'And then execute:
$ bundle
Or install it yourself as:
$ gem install influxdb-arel
At start you should create a builder:
builder = Influxdb::Arel::Builder.new(:events)
builder.to_sql
# => SELECT * FROM eventsYou can set default table name for the builder. Possible to use both strings and symbols:
Influxdb::Arel::Builder.new('events') == Influxdb::Arel::Builder.new(:events)
# => trueIf you want to use convenient shortcuts, such as 10.h.ago or 1.w you should require a file with core extensions
require 'influxdb/arel/core_extensions'
1.h
# => #<Influxdb::Arel::Nodes::Duration:0x00000102143a68 @left=1, @right="h">
1.h.to_sql
# => "1h"
1.h.ago.to_sql
# => "(now() - 1h)"
1.h.since.to_sql
# => "(now() + 1h)"A builder has methods for SQL construction.
-
Specifying which attributes should be used in the query:
select. -
Specifying which tables and how they should be used in the query:
from,mergeandjoin. -
Conditions of query:
where. -
Grouping methods:
groupandfill. -
Ordering methods:
order,asc,descandinvert_order. -
Specifying limitations of result set:
limit. -
The part of continuous queries:
into.
Most of them accept a block for building part of SQL. Inside a block calling of method will be interpreted depending on current context. For example:
- All undefined methods will be interpreted as attributes:
builder.where{ pp name.is_a?(Influxdb::Arel::Nodes::Attribute) }
# true
# => ...
builder.where{ name =~ /undr/ }.to_sql
# => SELECT * FROM table WHERE name =~ /undr/- Method
areturns attribute node.
builder.where{ pp a(:name) == name }
# true
# => ...-
Method
timereturnsInfluxdb::Arel::Nodes::Timeobject. (It will be available only inGROUPcontext) -
Method
nowreturnsInfluxdb::Arel::Nodes::Nowobject. (It will be available only inWHEREcontext)
- All undefined methods will be interpreted as tables:
builder.select{ pp events.is_a?(Influxdb::Arel::Nodes::Table) }
# true
# => ...
builder.from{ events }.to_sql
# => SELECT * FROM events- Method
treturns table node.
builder.from{ pp t(:table) == table }
# true
# => ...- Method
joinused for joining tables (available only inJOINcontext).
builder.from{ join(table.as(:alias1), table.as(:alias2)) }.to_sql
# => SELECT * FROM table AS alias1 INNER JOIN table AS alias2- Method
mergeused for merging tables (available only inJOINcontext).
builder.from{ merge(table1, table2) }.to_sql
# => SELECT * FROM table1 MERGE table2Also, into the block will be available o method. It used for access to outer scope. For example:
regexp = /events\..*/
builder.from{ o{ regexp } }.to_sql
# => SELECT * FROM /events\..*/You can specify attributes or expressions for SELECT clause using select method.
builder = Influxdb::Arel::Builder.new(:cpu_load)
builder.to_sql
# => SELECT * FROM cpu_load
builder.select{ (system + user).as(:sum) }.to_sql
# => SELECT (system + user) AS sum FROM cpu_load
builder.select{
[mean(idle).as(:idle_mean), mean(user).as(:user_mean)]
}.group{ time(1.d) }.to_sql
# => SELECT MEAN(idle) AS idle_mean, MEAN(user) AS user_mean FROM cpu_load GROUP BY time(1d)It might be convenient to use aliases for complex expressions, such as functions or some mathematical expressions.
Chaining select method will add attributes or expressions to the set. If you want to override expressions when use select! method.
builder.select(:name).select(:age).to_sql
# => SELECT name, age FROM table
builder.select(:name).select!(:age).to_sql
# => SELECT age FROM tableYou can specify tables for query using from method.
Possible to call method:
- With strings or symbols as arguments
builder.from('events', :errors).to_sql
# => SELECT * FROM events, errors- With block
builder.from{ errors }.to_sql
# => SELECT * FROM errors
builder.from{ [errors, :events] }.to_sql
# => SELECT * FROM errors, events- You can mix both
builder.from(:events){ errors }.to_sql
# => SELECT * FROM events, errors- With regexp object
builder.from(/.*/).to_sql
# => SELECT * FROM /.*/Warning: You can call method with more then one regexp but only first will be used as table name
builder.from(/.*/, /logs\..*/).to_sql
# => SELECT * FROM /.*/Chaining this method will replace previous FORM definition.
builder.from(:table1).from{ table2 }.to_sql
# => SELECT * FROM table2You can join two tables using join method.
It will join two first tables from tables list if method is called without argument
builder = Influxdb::Arel::Builder.new(:table)
builder.from(:table1, :table2).join.to_sql
# => SELECT * FROM table1 INNER JOIN table2
builder.from{ [table1.as(:alias1), table2.as(:alias2)] }.join.to_sql
# => SELECT * FROM table1 AS alias1 INNER JOIN table2 AS alias2It will raise error if method is called without argument and tables list contains less than two table.
builder.join.to_sql
# => IllegalSQLConstruct: Ambiguous joining clauseIt will join first table from tables list with given table if argument exists.
builder.join(:table2).to_sql
# => SELECT * FROM table INNER JOIN table2And it will raise error if number of tables is more than two.
builder.from(:table1, :table2).join(:table3).to_sql
# => IllegalSQLConstruct: Ambiguous joining clauseAlso, you can define alias for each joined table. It would be useful for self joining table.
builder.from{ table.as(:table_one).join(table.as(:table_two)) }.to_sql
# => SELECT * FROM table AS table_one INNER JOIN table AS table_twoChaining this method will replace previous join definition.
builder.join(:table1).join{ table1.as(:alias) }.to_sql
# => SELECT * FROM table INNER JOIN table1 AS aliasYou can merge two tables using merge method.
It will merge two first tables from tables list if method is called without argument
builder = Influxdb::Arel::Builder.new(:table)
builder.from(:table1, :table2).merge.to_sql
# => SELECT * FROM table1 MERGE table2
builder.from{ [table1.as(:alias1), table2.as(:alias2)] }.merge.to_sql
# => SELECT * FROM table1 MERGE table2It will raise error if method is called without argument and tables list contains less than two table.
builder.join.to_sql
# => IllegalSQLConstruct: Ambiguous merging clauseIt will merge first table from tables list with given table if argument exists.
builder.merge(:table2).to_sql
# => SELECT * FROM table MERGE table2And it will raise error if number of tables is more than two.
builder.from(:table1, :table2).merge(:table3).to_sql
# => IllegalSQLConstruct: Ambiguous merging clauseAlso, you can define alias for each table, but it doesn't influence on result. Because aliases make sense only for joining tables.
builder.from{ table1.as(:table1).merge(table1.as(:table2)) }.to_sql
# => SELECT * FROM table1 MERGE table2Chaining this method will replace previous merge definition.
builder.merge(:table1).merge(:table2).to_sql
# => SELECT * FROM table MERGE table2Grouping of results by specified attributes or expressions, such as time(10m):
builder = Influxdb::Arel::Builder.new(:table)
builder.group{ [time(10.m), host] }.to_sql
# => SELECT * FROM table GROUP BY time(10m), hostIf you want to fill intervals with no data you should call fill method:
builder.group{ [time(10.m), host] }.fill(0).to_sql
# => SELECT * FROM table GROUP BY time(10m), host fill(0)Chaining this method will add expression to the grouping set. If you want to override expressions when use group! method.
builder.group{ time(10.m) }.group(:host).to_sql
# => SELECT * FROM table GROUP BY time(10m), host
builder.group{ time(10.m) }.group!(:host).to_sql
# => SELECT * FROM table GROUP BY hostYo can set the ordering of results using order method
Possible values:
:asc- Default value. Results will be sorted by ascending order.'asc'- Results will be sorted by ascending order.:desc- Results will be sorted by descending order.'desc'- Results will be sorted by descending order.
builder = Influxdb::Arel::Builder.new(:table)
builder.order(:desc).to_sql
builder.order('desc').to_sql
# => SELECT * FROM table ORDER DESC
builder.order(:asc).to_sql
builder.order('asc').to_sql
# => SELECT * FROM table ORDER ASCAs well it's possible to use asc and desc methods
builder.asc.to_sql
# => SELECT * FROM table ORDER ASC
builder.desc.to_sql
# => SELECT * FROM table ORDER DESCInverting of the order direction:
builder.asc.invert_order.to_sql
# => SELECT * FROM table ORDER DESC
builder.desc.invert_order.to_sql
# => SELECT * FROM table ORDER ASCChaining this methods will replace previous order definition.
builder.asc.desc.to_sql
# => SELECT * FROM table ORDER DESCYou can specify conditions for query using where method
builder = Influxdb::Arel::Builder.new(:table)
builder.where(name: 'Undr').to_sql
# => SELECT * FROM table WHERE name = 'Undr'builder.where{ name.eq('Undr').or(name.eq('Andrei')) }.to_sql
# => SELECT * FROM table WHERE name = 'Undr' OR name = 'Andrei'Chaining this method will add expression to the condition set. They will join using AND boolean expression. If you want to override conditions when use where! method.
builder.where(name: 'Undr').where{ time.lt(10.h.ago) }.to_sql
# => SELECT * FROM table WHERE name = 'Undr' AND time < (now() - 10h)
builder.where(name: 'Undr').where!{ time.lt(10.h.ago) }.to_sql
# => SELECT * FROM table WHERE time < (now() - 10h)You can set a limit for a result set
builder = Influxdb::Arel::Builder.new(:cpu_load)
builder.limit(100).to_sql
# => SELECT * FROM cpu_load LIMIT 100- Fork it ( https://github.com/undr/influxdb-arel/fork )
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request