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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0c856080eb1bc2dc870a499745d4eba632a36ff3
4
- data.tar.gz: 39e040fd3054a54d5a46369646d416efab0e1b87
3
+ metadata.gz: f47130dee076e979384bf983f7faff420979a002
4
+ data.tar.gz: 3e0aa371bf99fb223b0db1bc5a85c97c51353cfc
5
5
  SHA512:
6
- metadata.gz: d03c45609d8a09648f949f300571fe9ecd4c8f3c3ffbab1be6f1668efc22dc7e4892dcdc441a2dd9c0a018a40b797f6bd0283672bce17f205e80237cd465435d
7
- data.tar.gz: 29f45987e40c2e0e03f005caf703231300ed1bc8ea55cf2344e84e313566ba5f1b683606f3bbe5eb187e5cac85dc90acfa144c971e3d951778100c3eae0523b2
6
+ metadata.gz: 248be46d44525be01771768364029b0e0376a368c433957ef53dacdebae45d7d5b9114a36a16d48398e63860b29050d9346f8c52153ef3308e65854aa54a7f85
7
+ data.tar.gz: a4db6ce496c4b7fd20adc85ffc16b792867833f2d1f1340f5fae73ba2f227520904defd0371c3d34cad6339180888d278a2822447fc69c5e74ab8ca06d97894f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 1.7.10
2
+
3
+ - Added support for Google BigQuery
4
+ - Require `drill-sergeant` gem for Apache Drill
5
+ - Better handling of checks with variables
6
+
1
7
  ## 1.7.9
2
8
 
3
9
  - Added beta support for Apache Drill
data/README.md CHANGED
@@ -391,9 +391,10 @@ data_sources:
391
391
  - [SQLite](#sqlite)
392
392
  - [Redshift](#redshift)
393
393
  - [Presto](#presto)
394
- - [MongoDB](#mongodb-1) [beta]
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
- ### MongoDB
477
+ ### Apache Drill
477
478
 
478
- Add [mongo](https://github.com/mongodb/mongo-ruby-driver) to your Gemfile and set:
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
- url: mongodb://user:password@hostname:27017/database
484
+ adapter: drill
485
+ url: http://hostname:8047
484
486
  ```
485
487
 
486
- ### Elasticsearch
488
+ ### Google BigQuery [master]
487
489
 
488
- Add [elasticsearch](https://github.com/elastic/elasticsearch-ruby) to your Gemfile and set:
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: elasticsearch
494
- url: http://user:password@hostname:9200/
495
+ adapter: bigquery
496
+ project: your-project
497
+ keyfile: path/to/keyfile.json
495
498
  ```
496
499
 
497
- ### Apache Drill [master]
500
+ ### MongoDB
498
501
 
499
- Set:
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
- adapter: drill
505
- url: http://hostname:8047
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 all filters
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: extract_vars(q.statement).join(", "),
282
+ vars: q.variables.join(", "),
283
283
  to_param: q.to_param
284
284
  }
285
285
  end
@@ -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
@@ -23,5 +23,9 @@ module Blazer
23
23
  editable &&= Blazer.query_editable.call(self, user) if Blazer.query_editable
24
24
  editable
25
25
  end
26
+
27
+ def variables
28
+ Blazer.extract_vars(statement)
29
+ end
26
30
  end
27
31
  end
@@ -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
- response = JSON.parse(http.post(uri.request_uri, data.to_json, header).body)
20
- if response["errorMessage"]
21
- error = response["errorMessage"]
22
- else
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
@@ -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
 
@@ -28,7 +28,7 @@ module Blazer
28
28
  audit.save! if audit.changed?
29
29
  end
30
30
 
31
- if query && !result.timed_out?
31
+ if query && !result.timed_out? && !query.variables.any?
32
32
  query.checks.each do |check|
33
33
  check.update_state(result)
34
34
  end
@@ -1,3 +1,3 @@
1
1
  module Blazer
2
- VERSION = "1.7.9"
2
+ VERSION = "1.7.10"
3
3
  end
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.9
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-03-21 00:00:00.000000000 Z
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