blazer 2.4.4 → 2.4.8

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.
@@ -71,7 +71,7 @@ module Blazer
71
71
  @sql_errors << error if error
72
72
  end
73
73
 
74
- @query.update!(status: "active") if @query.try(:status) == "archived"
74
+ @query.update!(status: "active") if @query.respond_to?(:status) && @query.status.in?(["archived", nil])
75
75
 
76
76
  Blazer.transform_statement.call(data_source, @statement) if Blazer.transform_statement
77
77
 
@@ -179,8 +179,8 @@ module Blazer
179
179
  if params[:commit] == "Fork"
180
180
  @query = Blazer::Query.new
181
181
  @query.creator = blazer_user if @query.respond_to?(:creator)
182
- @query.status = "active" if @query.respond_to?(:status)
183
182
  end
183
+ @query.status = "active" if @query.respond_to?(:status)
184
184
  unless @query.editable?(blazer_user)
185
185
  @query.errors.add(:base, "Sorry, permission denied")
186
186
  end
@@ -8,7 +8,7 @@ module Blazer
8
8
 
9
9
  validates :statement, presence: true
10
10
 
11
- scope :active, -> { column_names.include?("status") ? where(status: "active") : all }
11
+ scope :active, -> { column_names.include?("status") ? where(status: ["active", nil]) : all }
12
12
  scope :named, -> { where.not(name: "") }
13
13
 
14
14
  def to_param
@@ -73,12 +73,14 @@
73
73
  <% series_library[1] = {borderDash: [8], borderColor: color, pointBackgroundColor: color, backgroundColor: color, pointHoverBackgroundColor: color} %>
74
74
  <% end %>
75
75
  <% if blazer_maps? && @markers.any? %>
76
- <div id="map" style="height: <%= @only_chart ? 300 : 500 %>px;"></div>
76
+ <% map_id = SecureRandom.hex %>
77
+ <%= content_tag :div, nil, id: map_id, style: "height: #{@only_chart ? 300 : 500}px;" %>
77
78
  <script>
78
79
  <%= blazer_js_var "mapboxAccessToken", Blazer.mapbox_access_token %>
79
80
  <%= blazer_js_var "markers", @markers %>
81
+ <%= blazer_js_var "mapId", map_id %>
80
82
  L.mapbox.accessToken = mapboxAccessToken;
81
- var map = L.mapbox.map('map')
83
+ var map = L.mapbox.map(mapId)
82
84
  .addLayer(L.mapbox.styleLayer('mapbox://styles/mapbox/streets-v11'));
83
85
  var featureLayer = L.mapbox.featureLayer().addTo(map);
84
86
  var geojson = [];
@@ -8,19 +8,25 @@ module Blazer
8
8
  rows = []
9
9
  error = nil
10
10
 
11
+ query_options = {
12
+ query_string: statement,
13
+ # use token so we fetch cached results after query is run
14
+ client_request_token: Digest::MD5.hexdigest([statement, data_source.id, settings["workgroup"]].compact.join("/")),
15
+ query_execution_context: {
16
+ database: database,
17
+ }
18
+ }
19
+
20
+ if settings["output_location"]
21
+ query_options[:result_configuration] = {output_location: settings["output_location"]}
22
+ end
23
+
24
+ if settings["workgroup"]
25
+ query_options[:work_group] = settings["workgroup"]
26
+ end
27
+
11
28
  begin
12
- resp =
13
- client.start_query_execution(
14
- query_string: statement,
15
- # use token so we fetch cached results after query is run
16
- client_request_token: Digest::MD5.hexdigest([statement,data_source.id].join("/")),
17
- query_execution_context: {
18
- database: database,
19
- },
20
- result_configuration: {
21
- output_location: settings["output_location"]
22
- }
23
- )
29
+ resp = client.start_query_execution(**query_options)
24
30
  query_execution_id = resp.query_execution_id
25
31
 
26
32
  timeout = data_source.timeout || 300
@@ -60,21 +66,21 @@ module Blazer
60
66
  column_types.each_with_index do |ct, i|
61
67
  # TODO more column_types
62
68
  case ct
63
- when "timestamp"
69
+ when "timestamp", "timestamp with time zone"
64
70
  rows.each do |row|
65
- row[i] = utc.parse(row[i])
71
+ row[i] &&= utc.parse(row[i])
66
72
  end
67
73
  when "date"
68
74
  rows.each do |row|
69
- row[i] = Date.parse(row[i])
75
+ row[i] &&= Date.parse(row[i])
70
76
  end
71
77
  when "bigint"
72
78
  rows.each do |row|
73
- row[i] = row[i].to_i
79
+ row[i] &&= row[i].to_i
74
80
  end
75
81
  when "double"
76
82
  rows.each do |row|
77
- row[i] = row[i].to_f
83
+ row[i] &&= row[i].to_f
78
84
  end
79
85
  end
80
86
  end
@@ -118,11 +124,21 @@ module Blazer
118
124
  end
119
125
 
120
126
  def client
121
- @client ||= Aws::Athena::Client.new
127
+ @client ||= Aws::Athena::Client.new(**client_options)
122
128
  end
123
129
 
124
130
  def glue
125
- @glue ||= Aws::Glue::Client.new
131
+ @glue ||= Aws::Glue::Client.new(**client_options)
132
+ end
133
+
134
+ def client_options
135
+ @client_options ||= begin
136
+ if settings["access_key_id"] || settings["secret_access_key"]
137
+ {credentials: Aws::Credentials.new(settings["access_key_id"], settings["secret_access_key"])}
138
+ else
139
+ {}
140
+ end
141
+ end
126
142
  end
127
143
  end
128
144
  end
@@ -13,7 +13,7 @@ module Blazer
13
13
  # code is for backward compatibility
14
14
  if !results.respond_to?(:complete?) || results.complete?
15
15
  columns = results.first.keys.map(&:to_s) if results.size > 0
16
- rows = results.map(&:values)
16
+ rows = results.all.map(&:values)
17
17
  else
18
18
  error = Blazer::TIMEOUT_MESSAGE
19
19
  end
@@ -7,15 +7,15 @@ module Blazer
7
7
  error = nil
8
8
 
9
9
  begin
10
- response = client.xpack.sql.query(body: {query: "#{statement} /*#{comment}*/"})
10
+ response = client.transport.perform_request("POST", endpoint, {}, {query: "#{statement} /*#{comment}*/"}).body
11
11
  columns = response["columns"].map { |v| v["name"] }
12
12
  # Elasticsearch does not differentiate between dates and times
13
- date_indexes = response["columns"].each_index.select { |i| response["columns"][i]["type"] == "date" }
13
+ date_indexes = response["columns"].each_index.select { |i| ["date", "datetime"].include?(response["columns"][i]["type"]) }
14
14
  if columns.any?
15
15
  rows = response["rows"]
16
16
  date_indexes.each do |i|
17
17
  rows.each do |row|
18
- row[i] = Time.parse(row[i])
18
+ row[i] &&= Time.parse(row[i])
19
19
  end
20
20
  end
21
21
  end
@@ -38,6 +38,10 @@ module Blazer
38
38
 
39
39
  protected
40
40
 
41
+ def endpoint
42
+ @endpoint ||= client.info["version"]["number"].to_i >= 7 ? "_sql" : "_xpack/sql"
43
+ end
44
+
41
45
  def client
42
46
  @client ||= Elasticsearch::Client.new(url: settings["url"])
43
47
  end
@@ -0,0 +1,48 @@
1
+ module Blazer
2
+ module Adapters
3
+ class OpensearchAdapter < BaseAdapter
4
+ def run_statement(statement, comment)
5
+ columns = []
6
+ rows = []
7
+ error = nil
8
+
9
+ begin
10
+ response = client.transport.perform_request("POST", "_plugins/_sql", {}, {query: "#{statement} /*#{comment}*/"}).body
11
+ columns = response["schema"].map { |v| v["name"] }
12
+ # TODO typecast more types
13
+ # https://github.com/opensearch-project/sql/blob/main/docs/user/general/datatypes.rst
14
+ date_indexes = response["schema"].each_index.select { |i| response["schema"][i]["type"] == "timestamp" }
15
+ if columns.any?
16
+ rows = response["datarows"]
17
+ utc = ActiveSupport::TimeZone["Etc/UTC"]
18
+ date_indexes.each do |i|
19
+ rows.each do |row|
20
+ row[i] &&= utc.parse(row[i])
21
+ end
22
+ end
23
+ end
24
+ rescue => e
25
+ error = e.message
26
+ end
27
+
28
+ [columns, rows, error]
29
+ end
30
+
31
+ def tables
32
+ indices = client.cat.indices(format: "json").map { |v| v["index"] }
33
+ aliases = client.cat.aliases(format: "json").map { |v| v["alias"] }
34
+ (indices + aliases).uniq.sort
35
+ end
36
+
37
+ def preview_statement
38
+ "SELECT * FROM `{table}` LIMIT 10"
39
+ end
40
+
41
+ protected
42
+
43
+ def client
44
+ @client ||= OpenSearch::Client.new(url: settings["url"])
45
+ end
46
+ end
47
+ end
48
+ end
File without changes
File without changes
@@ -1,3 +1,3 @@
1
1
  module Blazer
2
- VERSION = "2.4.4"
2
+ VERSION = "2.4.8"
3
3
  end
data/lib/blazer.rb CHANGED
@@ -23,6 +23,7 @@ require "blazer/adapters/ignite_adapter"
23
23
  require "blazer/adapters/influxdb_adapter"
24
24
  require "blazer/adapters/mongodb_adapter"
25
25
  require "blazer/adapters/neo4j_adapter"
26
+ require "blazer/adapters/opensearch_adapter"
26
27
  require "blazer/adapters/presto_adapter"
27
28
  require "blazer/adapters/salesforce_adapter"
28
29
  require "blazer/adapters/soda_adapter"
@@ -38,6 +39,11 @@ module Blazer
38
39
  class UploadError < Error; end
39
40
  class TimeoutNotSupported < Error; end
40
41
 
42
+ # actionmailer optional
43
+ autoload :CheckMailer, "blazer/check_mailer"
44
+ # net/http optional
45
+ autoload :SlackNotifier, "blazer/slack_notifier"
46
+
41
47
  class << self
42
48
  attr_accessor :audit
43
49
  attr_reader :time_zone
@@ -245,9 +251,10 @@ Blazer.register_adapter "elasticsearch", Blazer::Adapters::ElasticsearchAdapter
245
251
  Blazer.register_adapter "hive", Blazer::Adapters::HiveAdapter
246
252
  Blazer.register_adapter "ignite", Blazer::Adapters::IgniteAdapter
247
253
  Blazer.register_adapter "influxdb", Blazer::Adapters::InfluxdbAdapter
254
+ Blazer.register_adapter "mongodb", Blazer::Adapters::MongodbAdapter
248
255
  Blazer.register_adapter "neo4j", Blazer::Adapters::Neo4jAdapter
256
+ Blazer.register_adapter "opensearch", Blazer::Adapters::OpensearchAdapter
249
257
  Blazer.register_adapter "presto", Blazer::Adapters::PrestoAdapter
250
- Blazer.register_adapter "mongodb", Blazer::Adapters::MongodbAdapter
251
258
  Blazer.register_adapter "salesforce", Blazer::Adapters::SalesforceAdapter
252
259
  Blazer.register_adapter "soda", Blazer::Adapters::SodaAdapter
253
260
  Blazer.register_adapter "spark", Blazer::Adapters::SparkAdapter
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2011-2016 Twitter, Inc.
3
+ Copyright (c) 2011-2019 Twitter, Inc.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
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: 2.4.4
4
+ version: 2.4.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-16 00:00:00.000000000 Z
11
+ date: 2021-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -119,8 +119,6 @@ files:
119
119
  - app/controllers/blazer/queries_controller.rb
120
120
  - app/controllers/blazer/uploads_controller.rb
121
121
  - app/helpers/blazer/base_helper.rb
122
- - app/mailers/blazer/check_mailer.rb
123
- - app/mailers/blazer/slack_notifier.rb
124
122
  - app/models/blazer/audit.rb
125
123
  - app/models/blazer/check.rb
126
124
  - app/models/blazer/connection.rb
@@ -171,18 +169,21 @@ files:
171
169
  - lib/blazer/adapters/influxdb_adapter.rb
172
170
  - lib/blazer/adapters/mongodb_adapter.rb
173
171
  - lib/blazer/adapters/neo4j_adapter.rb
172
+ - lib/blazer/adapters/opensearch_adapter.rb
174
173
  - lib/blazer/adapters/presto_adapter.rb
175
174
  - lib/blazer/adapters/salesforce_adapter.rb
176
175
  - lib/blazer/adapters/snowflake_adapter.rb
177
176
  - lib/blazer/adapters/soda_adapter.rb
178
177
  - lib/blazer/adapters/spark_adapter.rb
179
178
  - lib/blazer/adapters/sql_adapter.rb
179
+ - lib/blazer/check_mailer.rb
180
180
  - lib/blazer/data_source.rb
181
181
  - lib/blazer/detect_anomalies.R
182
182
  - lib/blazer/engine.rb
183
183
  - lib/blazer/result.rb
184
184
  - lib/blazer/run_statement.rb
185
185
  - lib/blazer/run_statement_job.rb
186
+ - lib/blazer/slack_notifier.rb
186
187
  - lib/blazer/version.rb
187
188
  - lib/generators/blazer/install_generator.rb
188
189
  - lib/generators/blazer/templates/config.yml.tt
@@ -225,7 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
225
226
  - !ruby/object:Gem::Version
226
227
  version: '0'
227
228
  requirements: []
228
- rubygems_version: 3.2.22
229
+ rubygems_version: 3.2.32
229
230
  signing_key:
230
231
  specification_version: 4
231
232
  summary: Explore your data with SQL. Easily create charts and dashboards, and share