blazer 2.0.1 → 2.0.2
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 +7 -0
- data/LICENSE.txt +1 -1
- data/README.md +52 -3
- data/app/assets/javascripts/blazer/application.js +1 -0
- data/app/assets/javascripts/blazer/stupidtable-custom-settings.js +13 -0
- data/app/controllers/blazer/base_controller.rb +2 -1
- data/app/views/blazer/dashboards/show.html.erb +1 -1
- data/app/views/blazer/queries/show.html.erb +1 -1
- data/lib/blazer.rb +5 -0
- data/lib/blazer/adapters/athena_adapter.rb +1 -1
- data/lib/blazer/adapters/neo4j_adapter.rb +47 -0
- data/lib/blazer/adapters/salesforce_adapter.rb +45 -0
- data/lib/blazer/data_source.rb +1 -1
- data/lib/blazer/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a6731164b551f139951303884ca6531d336249299f5ff6e295160348540a687
|
4
|
+
data.tar.gz: 784d957116c412f9ac526661e0ca7252d62c43ffd51a67bb106d1a401da44f25
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be8f6f7713953e505d76170f1e0e81284f0dd99b35ed28d42932542de702fd0e541e1a8b86e6428c47324d66f58ae98df2732221ad49ac512db221d0c664de07
|
7
|
+
data.tar.gz: 0e3c7202af0c73b9070e81c922167d46f387aea34d47797333aa3a1d89f8f6a7710a47f1a1eb61fe7d20e880d7183e2e7019263547b78d01124ebd80cd849d13
|
data/CHANGELOG.md
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -175,6 +175,19 @@ Also, make sure authorization is enabled when you start the server.
|
|
175
175
|
|
176
176
|
If your database contains sensitive or personal data, check out [Hypershield](https://github.com/ankane/hypershield) to shield it.
|
177
177
|
|
178
|
+
## Encrypted Data
|
179
|
+
|
180
|
+
If you need to search encrypted data, use [blind indexing](https://github.com/ankane/blind_index).
|
181
|
+
|
182
|
+
You can have Blazer transform specific variables with:
|
183
|
+
|
184
|
+
```ruby
|
185
|
+
Blazer.transform_variable = lambda do |name, value|
|
186
|
+
value = User.compute_email_bidx(value) if name == "email_bidx"
|
187
|
+
value
|
188
|
+
end
|
189
|
+
```
|
190
|
+
|
178
191
|
## Queries
|
179
192
|
|
180
193
|
### Variables
|
@@ -397,8 +410,8 @@ R is harder to set up but doesn’t use an external service. It uses Twitter’s
|
|
397
410
|
First, [install R](https://cloud.r-project.org/). Then, run:
|
398
411
|
|
399
412
|
```R
|
400
|
-
install.packages("
|
401
|
-
|
413
|
+
install.packages("remotes")
|
414
|
+
remotes::install_github("twitter/AnomalyDetection")
|
402
415
|
```
|
403
416
|
|
404
417
|
And add to `config/blazer.yml`:
|
@@ -462,9 +475,11 @@ data_sources:
|
|
462
475
|
- [IBM DB2 and Informix](#ibm-db2-and-informix)
|
463
476
|
- [MongoDB](#mongodb-1)
|
464
477
|
- [MySQL](#mysql-1)
|
478
|
+
- [Neo4j](#neo4j-experimental)
|
465
479
|
- [Oracle](#oracle)
|
466
480
|
- [PostgreSQL](#postgresql-1)
|
467
481
|
- [Presto](#presto)
|
482
|
+
- [Salesforce](#salesforce-experimental)
|
468
483
|
- [Snowflake](#snowflake)
|
469
484
|
- [SQLite](#sqlite)
|
470
485
|
- [SQL Server](#sql-server)
|
@@ -582,6 +597,17 @@ data_sources:
|
|
582
597
|
url: mysql2://user:password@hostname:3306/database
|
583
598
|
```
|
584
599
|
|
600
|
+
### Neo4j [experimental]
|
601
|
+
|
602
|
+
Add [neo4j-core](https://github.com/neo4jrb/neo4j-core) to your Gemfile and set:
|
603
|
+
|
604
|
+
```yml
|
605
|
+
data_sources:
|
606
|
+
my_source:
|
607
|
+
adapter: neo4j
|
608
|
+
url: http://user:password@hostname:7474
|
609
|
+
```
|
610
|
+
|
585
611
|
### Oracle
|
586
612
|
|
587
613
|
Use [activerecord-oracle_enhanced-adapter](https://github.com/rsim/oracle-enhanced).
|
@@ -606,6 +632,29 @@ data_sources:
|
|
606
632
|
url: presto://user@hostname:8080/catalog
|
607
633
|
```
|
608
634
|
|
635
|
+
### Salesforce [experimental]
|
636
|
+
|
637
|
+
Add [restforce](https://github.com/restforce/restforce) to your Gemfile and set:
|
638
|
+
|
639
|
+
```yml
|
640
|
+
data_sources:
|
641
|
+
my_source:
|
642
|
+
adapter: salesforce
|
643
|
+
```
|
644
|
+
|
645
|
+
And set the appropriate environment variables:
|
646
|
+
|
647
|
+
```sh
|
648
|
+
SALESFORCE_USERNAME="username"
|
649
|
+
SALESFORCE_PASSWORD="password"
|
650
|
+
SALESFORCE_SECURITY_TOKEN="security token"
|
651
|
+
SALESFORCE_CLIENT_ID="client id"
|
652
|
+
SALESFORCE_CLIENT_SECRET="client secret"
|
653
|
+
SALESFORCE_API_VERSION="41.0"
|
654
|
+
```
|
655
|
+
|
656
|
+
Supports [SOQL](https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql.htm)
|
657
|
+
|
609
658
|
### Snowflake
|
610
659
|
|
611
660
|
First, install the [ODBC driver](https://docs.snowflake.net/manuals/user-guide/odbc.html). Add [odbc_adapter](https://github.com/localytics/odbc_adapter) to your Gemfile and set:
|
@@ -675,7 +724,7 @@ Have team members who want to learn SQL? Here are a few great, free resources.
|
|
675
724
|
|
676
725
|
## Useful Tools
|
677
726
|
|
678
|
-
For an easy way to group by day, week, month, and more with correct time zones, check out [Groupdate](https://github.com/ankane/groupdate.sql).
|
727
|
+
For an easy way to group by day, week, month, and more with correct time zones, check out [Groupdate.sql](https://github.com/ankane/groupdate.sql).
|
679
728
|
|
680
729
|
## Standalone Version
|
681
730
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+
function removeCommas(string) {
|
2
|
+
return string.replace(/,/g, "")
|
3
|
+
}
|
4
|
+
|
5
|
+
// Remove commas for integers and floats to fix issues with sorting in the stupidtable plugin
|
6
|
+
var stupidtableCustomSettings = {
|
7
|
+
"int": function(a, b) {
|
8
|
+
return parseInt(removeCommas(a), 10) - parseInt(removeCommas(b), 10);
|
9
|
+
},
|
10
|
+
"float": function(a, b) {
|
11
|
+
return parseFloat(removeCommas(a)) - parseFloat(removeCommas(b));
|
12
|
+
}
|
13
|
+
}
|
@@ -63,6 +63,7 @@ module Blazer
|
|
63
63
|
value = value.to_f
|
64
64
|
end
|
65
65
|
end
|
66
|
+
value = Blazer.transform_variable.call(var, value) if Blazer.transform_variable
|
66
67
|
statement.gsub!("{#{var}}", ActiveRecord::Base.connection.quote(value))
|
67
68
|
end
|
68
69
|
end
|
@@ -95,7 +96,7 @@ module Blazer
|
|
95
96
|
helper_method :variable_params
|
96
97
|
|
97
98
|
def blazer_user
|
98
|
-
send(Blazer.user_method) if Blazer.user_method && respond_to?(Blazer.user_method)
|
99
|
+
send(Blazer.user_method) if Blazer.user_method && respond_to?(Blazer.user_method, true)
|
99
100
|
end
|
100
101
|
helper_method :blazer_user
|
101
102
|
|
@@ -43,7 +43,7 @@
|
|
43
43
|
|
44
44
|
runQuery(data, function (data) {
|
45
45
|
$("#chart-<%= i %>").html(data)
|
46
|
-
$("#chart-<%= i %> table").stupidtable()
|
46
|
+
$("#chart-<%= i %> table").stupidtable(stupidtableCustomSettings)
|
47
47
|
}, function (message) {
|
48
48
|
$("#chart-<%= i %>").addClass("query-error").html(message)
|
49
49
|
});
|
@@ -49,7 +49,7 @@
|
|
49
49
|
<script>
|
50
50
|
function showRun(data) {
|
51
51
|
$("#results").html(data)
|
52
|
-
$("#results table").stupidtable().stickyTableHeaders({fixedOffset: 60})
|
52
|
+
$("#results table").stupidtable(stupidtableCustomSettings).stickyTableHeaders({fixedOffset: 60})
|
53
53
|
}
|
54
54
|
|
55
55
|
function showError(message) {
|
data/lib/blazer.rb
CHANGED
@@ -19,7 +19,9 @@ require "blazer/adapters/drill_adapter"
|
|
19
19
|
require "blazer/adapters/druid_adapter"
|
20
20
|
require "blazer/adapters/elasticsearch_adapter"
|
21
21
|
require "blazer/adapters/mongodb_adapter"
|
22
|
+
require "blazer/adapters/neo4j_adapter"
|
22
23
|
require "blazer/adapters/presto_adapter"
|
24
|
+
require "blazer/adapters/salesforce_adapter"
|
23
25
|
require "blazer/adapters/sql_adapter"
|
24
26
|
require "blazer/adapters/snowflake_adapter"
|
25
27
|
|
@@ -40,6 +42,7 @@ module Blazer
|
|
40
42
|
attr_accessor :from_email
|
41
43
|
attr_accessor :cache
|
42
44
|
attr_accessor :transform_statement
|
45
|
+
attr_accessor :transform_variable
|
43
46
|
attr_accessor :check_schedules
|
44
47
|
attr_accessor :anomaly_checks
|
45
48
|
attr_accessor :forecasting
|
@@ -217,7 +220,9 @@ Blazer.register_adapter "cassandra", Blazer::Adapters::CassandraAdapter
|
|
217
220
|
Blazer.register_adapter "drill", Blazer::Adapters::DrillAdapter
|
218
221
|
Blazer.register_adapter "druid", Blazer::Adapters::DruidAdapter
|
219
222
|
Blazer.register_adapter "elasticsearch", Blazer::Adapters::ElasticsearchAdapter
|
223
|
+
Blazer.register_adapter "neo4j", Blazer::Adapters::Neo4jAdapter
|
220
224
|
Blazer.register_adapter "presto", Blazer::Adapters::PrestoAdapter
|
221
225
|
Blazer.register_adapter "mongodb", Blazer::Adapters::MongodbAdapter
|
226
|
+
Blazer.register_adapter "salesforce", Blazer::Adapters::SalesforceAdapter
|
222
227
|
Blazer.register_adapter "sql", Blazer::Adapters::SqlAdapter
|
223
228
|
Blazer.register_adapter "snowflake", Blazer::Adapters::SnowflakeAdapter
|
@@ -13,7 +13,7 @@ module Blazer
|
|
13
13
|
client.start_query_execution(
|
14
14
|
query_string: statement,
|
15
15
|
# use token so we fetch cached results after query is run
|
16
|
-
client_request_token: Digest::MD5.hexdigest(statement),
|
16
|
+
client_request_token: Digest::MD5.hexdigest([statement,data_source.id].join("/")),
|
17
17
|
query_execution_context: {
|
18
18
|
database: database,
|
19
19
|
},
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Blazer
|
2
|
+
module Adapters
|
3
|
+
class Neo4jAdapter < BaseAdapter
|
4
|
+
def run_statement(statement, comment)
|
5
|
+
columns = []
|
6
|
+
rows = []
|
7
|
+
error = nil
|
8
|
+
|
9
|
+
begin
|
10
|
+
result = session.query("#{statement} /*#{comment}*/")
|
11
|
+
columns = result.columns.map(&:to_s)
|
12
|
+
rows = []
|
13
|
+
result.each do |row|
|
14
|
+
rows << columns.map do |c|
|
15
|
+
v = row.send(c)
|
16
|
+
v = v.properties if v.respond_to?(:properties)
|
17
|
+
v
|
18
|
+
end
|
19
|
+
end
|
20
|
+
rescue => e
|
21
|
+
error = e.message
|
22
|
+
end
|
23
|
+
|
24
|
+
[columns, rows, error]
|
25
|
+
end
|
26
|
+
|
27
|
+
def tables
|
28
|
+
result = session.query("CALL db.labels()")
|
29
|
+
result.rows.map(&:first)
|
30
|
+
end
|
31
|
+
|
32
|
+
def preview_statement
|
33
|
+
"MATCH (n:{table}) RETURN n LIMIT 10"
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def session
|
39
|
+
@session ||= begin
|
40
|
+
require "neo4j/core/cypher_session/adaptors/http"
|
41
|
+
http_adaptor = Neo4j::Core::CypherSession::Adaptors::HTTP.new(settings["url"])
|
42
|
+
Neo4j::Core::CypherSession.new(http_adaptor)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Blazer
|
2
|
+
module Adapters
|
3
|
+
class SalesforceAdapter < BaseAdapter
|
4
|
+
def run_statement(statement, comment)
|
5
|
+
columns = []
|
6
|
+
rows = []
|
7
|
+
error = nil
|
8
|
+
|
9
|
+
# remove comments manually
|
10
|
+
statement = statement.gsub(/--.+/, "")
|
11
|
+
# only supports single line /* */ comments
|
12
|
+
# regex not perfect, but should be good enough
|
13
|
+
statement = statement.gsub(/\/\*.+\*\//, "")
|
14
|
+
|
15
|
+
# remove trailing semicolon
|
16
|
+
statement = statement.sub(/;\s*\z/, "")
|
17
|
+
|
18
|
+
begin
|
19
|
+
response = client.query(statement)
|
20
|
+
rows = response.map { |r| r.to_hash.except("attributes").values }
|
21
|
+
columns = rows.any? ? response.first.to_hash.except("attributes").keys : []
|
22
|
+
rescue => e
|
23
|
+
error = e.message
|
24
|
+
end
|
25
|
+
|
26
|
+
[columns, rows, error]
|
27
|
+
end
|
28
|
+
|
29
|
+
def tables
|
30
|
+
# cache
|
31
|
+
@tables ||= client.describe.select { |r| r.queryable }.map(&:name)
|
32
|
+
end
|
33
|
+
|
34
|
+
def preview_statement
|
35
|
+
"SELECT Id FROM {table} LIMIT 10"
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def client
|
41
|
+
@client ||= Restforce.new
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/blazer/data_source.rb
CHANGED
@@ -144,7 +144,7 @@ module Blazer
|
|
144
144
|
|
145
145
|
def adapter_instance
|
146
146
|
@adapter_instance ||= begin
|
147
|
-
unless settings["url"] || Rails.env.development? || ["bigquery", "athena", "snowflake"].include?(settings["adapter"])
|
147
|
+
unless settings["url"] || Rails.env.development? || ["bigquery", "athena", "snowflake", "salesforce"].include?(settings["adapter"])
|
148
148
|
raise Blazer::Error, "Empty url for data source: #{id}"
|
149
149
|
end
|
150
150
|
|
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: 2.0.
|
4
|
+
version: 2.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-05-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -133,6 +133,7 @@ files:
|
|
133
133
|
- app/assets/javascripts/blazer/queries.js
|
134
134
|
- app/assets/javascripts/blazer/routes.js
|
135
135
|
- app/assets/javascripts/blazer/selectize.js
|
136
|
+
- app/assets/javascripts/blazer/stupidtable-custom-settings.js
|
136
137
|
- app/assets/javascripts/blazer/stupidtable.js
|
137
138
|
- app/assets/javascripts/blazer/vue.js
|
138
139
|
- app/assets/stylesheets/blazer/application.css
|
@@ -185,7 +186,9 @@ files:
|
|
185
186
|
- lib/blazer/adapters/druid_adapter.rb
|
186
187
|
- lib/blazer/adapters/elasticsearch_adapter.rb
|
187
188
|
- lib/blazer/adapters/mongodb_adapter.rb
|
189
|
+
- lib/blazer/adapters/neo4j_adapter.rb
|
188
190
|
- lib/blazer/adapters/presto_adapter.rb
|
191
|
+
- lib/blazer/adapters/salesforce_adapter.rb
|
189
192
|
- lib/blazer/adapters/snowflake_adapter.rb
|
190
193
|
- lib/blazer/adapters/sql_adapter.rb
|
191
194
|
- lib/blazer/data_source.rb
|
@@ -218,8 +221,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
218
221
|
- !ruby/object:Gem::Version
|
219
222
|
version: '0'
|
220
223
|
requirements: []
|
221
|
-
|
222
|
-
rubygems_version: 2.7.6
|
224
|
+
rubygems_version: 3.0.3
|
223
225
|
signing_key:
|
224
226
|
specification_version: 4
|
225
227
|
summary: Explore your data with SQL. Easily create charts and dashboards, and share
|