blazer 1.7.9 → 1.7.10
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of blazer might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +26 -13
- data/app/controllers/blazer/base_controller.rb +3 -10
- data/app/controllers/blazer/queries_controller.rb +1 -1
- data/app/models/blazer/check.rb +7 -0
- data/app/models/blazer/query.rb +4 -0
- data/app/views/blazer/queries/show.html.erb +1 -1
- data/lib/blazer.rb +8 -0
- data/lib/blazer/adapters/bigquery_adapter.rb +67 -0
- data/lib/blazer/adapters/drill_adapter.rb +10 -16
- data/lib/blazer/data_source.rb +1 -1
- data/lib/blazer/run_statement.rb +1 -1
- data/lib/blazer/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f47130dee076e979384bf983f7faff420979a002
|
4
|
+
data.tar.gz: 3e0aa371bf99fb223b0db1bc5a85c97c51353cfc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 248be46d44525be01771768364029b0e0376a368c433957ef53dacdebae45d7d5b9114a36a16d48398e63860b29050d9346f8c52153ef3308e65854aa54a7f85
|
7
|
+
data.tar.gz: a4db6ce496c4b7fd20adc85ffc16b792867833f2d1f1340f5fae73ba2f227520904defd0371c3d34cad6339180888d278a2822447fc69c5e74ab8ca06d97894f
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -391,9 +391,10 @@ data_sources:
|
|
391
391
|
- [SQLite](#sqlite)
|
392
392
|
- [Redshift](#redshift)
|
393
393
|
- [Presto](#presto)
|
394
|
-
- [
|
394
|
+
- [Apache Drill](#apache-drill)
|
395
|
+
- [Google BigQuery](#google-bigquery-master)
|
396
|
+
- [MongoDB](#mongodb-1)
|
395
397
|
- [Elasticsearch](#elasticsearch) [beta]
|
396
|
-
- [Apache Drill](#apache-drill-master) [beta]
|
397
398
|
|
398
399
|
You can also [create an adapter](#creating-an-adapter) for any other data store.
|
399
400
|
|
@@ -473,36 +474,48 @@ data_sources:
|
|
473
474
|
url: presto://user@hostname:8080/catalog
|
474
475
|
```
|
475
476
|
|
476
|
-
###
|
477
|
+
### Apache Drill
|
477
478
|
|
478
|
-
Add [
|
479
|
+
Add [drill-sergeant](https://github.com/ankane/drill-sergeant) to your Gemfile and set:
|
479
480
|
|
480
481
|
```yml
|
481
482
|
data_sources:
|
482
483
|
my_source:
|
483
|
-
|
484
|
+
adapter: drill
|
485
|
+
url: http://hostname:8047
|
484
486
|
```
|
485
487
|
|
486
|
-
###
|
488
|
+
### Google BigQuery [master]
|
487
489
|
|
488
|
-
Add [
|
490
|
+
Add [google-cloud-bigquery](https://github.com/GoogleCloudPlatform/google-cloud-ruby/tree/master/google-cloud-bigquery) to your Gemfile and set:
|
489
491
|
|
490
492
|
```yml
|
491
493
|
data_sources:
|
492
494
|
my_source:
|
493
|
-
adapter:
|
494
|
-
|
495
|
+
adapter: bigquery
|
496
|
+
project: your-project
|
497
|
+
keyfile: path/to/keyfile.json
|
495
498
|
```
|
496
499
|
|
497
|
-
###
|
500
|
+
### MongoDB
|
498
501
|
|
499
|
-
|
502
|
+
Add [mongo](https://github.com/mongodb/mongo-ruby-driver) to your Gemfile and set:
|
500
503
|
|
501
504
|
```yml
|
502
505
|
data_sources:
|
503
506
|
my_source:
|
504
|
-
|
505
|
-
|
507
|
+
url: mongodb://user:password@hostname:27017/database
|
508
|
+
```
|
509
|
+
|
510
|
+
### Elasticsearch
|
511
|
+
|
512
|
+
Add [elasticsearch](https://github.com/elastic/elasticsearch-ruby) to your Gemfile and set:
|
513
|
+
|
514
|
+
```yml
|
515
|
+
data_sources:
|
516
|
+
my_source:
|
517
|
+
adapter: elasticsearch
|
518
|
+
url: http://user:password@hostname:9200
|
506
519
|
```
|
507
520
|
|
508
521
|
## Creating an Adapter
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Blazer
|
2
2
|
class BaseController < ApplicationController
|
3
|
-
# skip
|
4
|
-
filters = _process_action_callbacks.map(&:filter)
|
3
|
+
# skip filters
|
4
|
+
filters = _process_action_callbacks.map(&:filter) - [:activate_authlogic]
|
5
5
|
if Rails::VERSION::MAJOR >= 5
|
6
6
|
skip_before_action(*filters, raise: false)
|
7
7
|
skip_after_action(*filters, raise: false)
|
@@ -25,7 +25,7 @@ module Blazer
|
|
25
25
|
private
|
26
26
|
|
27
27
|
def process_vars(statement, data_source)
|
28
|
-
(@bind_vars ||= []).concat(extract_vars(statement)).uniq!
|
28
|
+
(@bind_vars ||= []).concat(Blazer.extract_vars(statement)).uniq!
|
29
29
|
@bind_vars.each do |var|
|
30
30
|
params[var] ||= Blazer.data_sources[data_source].variable_defaults[var]
|
31
31
|
end
|
@@ -79,13 +79,6 @@ module Blazer
|
|
79
79
|
[smart_var, error]
|
80
80
|
end
|
81
81
|
|
82
|
-
def extract_vars(statement)
|
83
|
-
# strip commented out lines
|
84
|
-
# and regex {1} or {1,2}
|
85
|
-
statement.gsub(/\-\-.+/, "").gsub(/\/\*.+\*\//m, "").scan(/\{\w*?\}/i).map { |v| v[1...-1] }.reject { |v| /\A\d+(\,\d+)?\z/.match(v) || v.empty? }.uniq
|
86
|
-
end
|
87
|
-
helper_method :extract_vars
|
88
|
-
|
89
82
|
def variable_params
|
90
83
|
params.except(:controller, :action, :id, :host, :query, :dashboard, :query_id, :query_ids, :table_names, :authenticity_token, :utf8, :_method, :commit, :statement, :data_source, :name, :fork_query_id, :blazer, :run_id).permit!
|
91
84
|
end
|
@@ -279,7 +279,7 @@ module Blazer
|
|
279
279
|
id: q.id,
|
280
280
|
name: q.name,
|
281
281
|
creator: blazer_user && q.try(:creator) == blazer_user ? "You" : q.try(:creator).try(Blazer.user_name),
|
282
|
-
vars:
|
282
|
+
vars: q.variables.join(", "),
|
283
283
|
to_param: q.to_param
|
284
284
|
}
|
285
285
|
end
|
data/app/models/blazer/check.rb
CHANGED
@@ -5,6 +5,7 @@ module Blazer
|
|
5
5
|
|
6
6
|
validates :query_id, presence: true
|
7
7
|
validate :validate_emails
|
8
|
+
validate :validate_variables, if: -> { query_id_changed? }
|
8
9
|
|
9
10
|
before_validation :set_state
|
10
11
|
before_validation :fix_emails
|
@@ -84,5 +85,11 @@ module Blazer
|
|
84
85
|
errors.add(:base, "Invalid emails")
|
85
86
|
end
|
86
87
|
end
|
88
|
+
|
89
|
+
def validate_variables
|
90
|
+
if query.variables.any?
|
91
|
+
errors.add(:base, "Query can't have variables")
|
92
|
+
end
|
93
|
+
end
|
87
94
|
end
|
88
95
|
end
|
data/app/models/blazer/query.rb
CHANGED
@@ -62,7 +62,7 @@
|
|
62
62
|
</script>
|
63
63
|
<% end %>
|
64
64
|
|
65
|
-
<% if %w[sql presto].include?(Blazer.data_sources[@query.data_source].adapter) %>
|
65
|
+
<% if %w[sql presto drill bigquery].include?(Blazer.data_sources[@query.data_source].adapter) %>
|
66
66
|
<script>
|
67
67
|
// do not highlight really long queries
|
68
68
|
// this can lead to performance issues
|
data/lib/blazer.rb
CHANGED
@@ -7,6 +7,7 @@ require "blazer/data_source"
|
|
7
7
|
require "blazer/result"
|
8
8
|
require "blazer/run_statement"
|
9
9
|
require "blazer/adapters/base_adapter"
|
10
|
+
require "blazer/adapters/bigquery_adapter"
|
10
11
|
require "blazer/adapters/drill_adapter"
|
11
12
|
require "blazer/adapters/elasticsearch_adapter"
|
12
13
|
require "blazer/adapters/mongodb_adapter"
|
@@ -87,6 +88,12 @@ module Blazer
|
|
87
88
|
end
|
88
89
|
end
|
89
90
|
|
91
|
+
def self.extract_vars(statement)
|
92
|
+
# strip commented out lines
|
93
|
+
# and regex {1} or {1,2}
|
94
|
+
statement.gsub(/\-\-.+/, "").gsub(/\/\*.+\*\//m, "").scan(/\{\w*?\}/i).map { |v| v[1...-1] }.reject { |v| /\A\d+(\,\d+)?\z/.match(v) || v.empty? }.uniq
|
95
|
+
end
|
96
|
+
|
90
97
|
def self.run_checks(schedule: nil)
|
91
98
|
checks = Blazer::Check.includes(:query)
|
92
99
|
checks = checks.where(schedule: schedule) if schedule
|
@@ -160,6 +167,7 @@ module Blazer
|
|
160
167
|
end
|
161
168
|
|
162
169
|
Blazer.register_adapter "drill", Blazer::Adapters::DrillAdapter
|
170
|
+
Blazer.register_adapter "bigquery", Blazer::Adapters::BigQueryAdapter
|
163
171
|
Blazer.register_adapter "elasticsearch", Blazer::Adapters::ElasticsearchAdapter
|
164
172
|
Blazer.register_adapter "mongodb", Blazer::Adapters::MongodbAdapter
|
165
173
|
Blazer.register_adapter "presto", Blazer::Adapters::PrestoAdapter
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Blazer
|
2
|
+
module Adapters
|
3
|
+
class BigQueryAdapter < BaseAdapter
|
4
|
+
def run_statement(statement, comment)
|
5
|
+
columns = []
|
6
|
+
rows = []
|
7
|
+
error = nil
|
8
|
+
|
9
|
+
begin
|
10
|
+
options = {}
|
11
|
+
options[:timeout] = data_source.timeout.to_i * 1000 if data_source.timeout
|
12
|
+
results = bigquery.query(statement, options) # ms
|
13
|
+
if results.complete?
|
14
|
+
columns = results.first.keys.map(&:to_s) if results.size > 0
|
15
|
+
rows = results.map(&:values)
|
16
|
+
else
|
17
|
+
error = Blazer::TIMEOUT_MESSAGE
|
18
|
+
end
|
19
|
+
rescue => e
|
20
|
+
error = e.message
|
21
|
+
end
|
22
|
+
|
23
|
+
[columns, rows, error]
|
24
|
+
end
|
25
|
+
|
26
|
+
def tables
|
27
|
+
table_refs.map { |t| "#{t.project_id}.#{t.dataset_id}.#{t.table_id}" }
|
28
|
+
end
|
29
|
+
|
30
|
+
def schema
|
31
|
+
table_refs.map do |table_ref|
|
32
|
+
{
|
33
|
+
schema: table_ref.dataset_id,
|
34
|
+
table: table_ref.table_id,
|
35
|
+
columns: table_columns(table_ref)
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def preview_statement
|
41
|
+
"SELECT * FROM `{table}` LIMIT 10"
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def bigquery
|
47
|
+
@bigquery ||= begin
|
48
|
+
require "google/cloud/bigquery"
|
49
|
+
Google::Cloud::Bigquery.new(
|
50
|
+
project: settings["project"],
|
51
|
+
keyfile: settings["keyfile"]
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def table_refs
|
57
|
+
bigquery.datasets.map(&:tables).flat_map { |table_list| table_list.map(&:table_ref) }
|
58
|
+
end
|
59
|
+
|
60
|
+
def table_columns(table_ref)
|
61
|
+
schema = bigquery.service.get_table(table_ref.dataset_id, table_ref.table_id).schema
|
62
|
+
return [] if schema.nil?
|
63
|
+
schema.fields.map { |field| {name: field.name, data_type: field.type} }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -6,29 +6,23 @@ module Blazer
|
|
6
6
|
rows = []
|
7
7
|
error = nil
|
8
8
|
|
9
|
-
header = {"Content-Type" => "application/json", "Accept" => "application/json"}
|
10
|
-
data = {
|
11
|
-
queryType: "sql",
|
12
|
-
query: statement
|
13
|
-
}
|
14
|
-
|
15
|
-
uri = URI.parse("#{settings["url"]}/query.json")
|
16
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
17
|
-
|
18
9
|
begin
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
columns = response["columns"]
|
24
|
-
rows = response["rows"].map { |r| r.values }
|
25
|
-
end
|
10
|
+
# remove trailing semicolon
|
11
|
+
response = drill.query(statement.sub(/;\s*\z/, ""))
|
12
|
+
rows = response.map { |r| r.values }
|
13
|
+
columns = rows.any? ? response.first.keys : []
|
26
14
|
rescue => e
|
27
15
|
error = e.message
|
28
16
|
end
|
29
17
|
|
30
18
|
[columns, rows, error]
|
31
19
|
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def drill
|
24
|
+
@drill ||= ::Drill.new(url: settings["url"])
|
25
|
+
end
|
32
26
|
end
|
33
27
|
end
|
34
28
|
end
|
data/lib/blazer/data_source.rb
CHANGED
@@ -12,7 +12,7 @@ module Blazer
|
|
12
12
|
@id = id
|
13
13
|
@settings = settings
|
14
14
|
|
15
|
-
unless settings["url"] || Rails.env.development?
|
15
|
+
unless settings["url"] || Rails.env.development? || settings["adapter"] == "bigquery"
|
16
16
|
raise Blazer::Error, "Empty url for data source: #{id}"
|
17
17
|
end
|
18
18
|
|
data/lib/blazer/run_statement.rb
CHANGED
data/lib/blazer/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blazer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.7.
|
4
|
+
version: 1.7.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -164,6 +164,7 @@ files:
|
|
164
164
|
- config/routes.rb
|
165
165
|
- lib/blazer.rb
|
166
166
|
- lib/blazer/adapters/base_adapter.rb
|
167
|
+
- lib/blazer/adapters/bigquery_adapter.rb
|
167
168
|
- lib/blazer/adapters/drill_adapter.rb
|
168
169
|
- lib/blazer/adapters/elasticsearch_adapter.rb
|
169
170
|
- lib/blazer/adapters/mongodb_adapter.rb
|