blazer 2.2.1 → 2.2.6
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 +71 -48
- data/README.md +81 -14
- data/app/controllers/blazer/base_controller.rb +16 -2
- data/app/controllers/blazer/dashboards_controller.rb +2 -2
- data/app/controllers/blazer/queries_controller.rb +7 -5
- data/app/helpers/blazer/base_helper.rb +1 -1
- data/app/mailers/blazer/slack_notifier.rb +3 -0
- data/app/models/blazer/dashboard.rb +4 -0
- data/app/views/blazer/check_mailer/failing_checks.html.erb +1 -0
- data/app/views/blazer/check_mailer/state_change.html.erb +1 -0
- data/app/views/blazer/dashboards/_form.html.erb +1 -1
- data/app/views/blazer/dashboards/show.html.erb +3 -3
- data/app/views/blazer/queries/_form.html.erb +2 -2
- data/app/views/blazer/queries/home.html.erb +1 -1
- data/app/views/blazer/queries/run.html.erb +4 -3
- data/app/views/blazer/queries/show.html.erb +5 -3
- data/app/views/layouts/blazer/application.html.erb +2 -2
- data/lib/blazer.rb +5 -1
- data/lib/blazer/adapters/influxdb_adapter.rb +45 -0
- data/lib/blazer/adapters/soda_adapter.rb +96 -0
- data/lib/blazer/result.rb +19 -4
- data/lib/blazer/version.rb +1 -1
- data/lib/generators/blazer/templates/config.yml.tt +1 -1
- data/lib/generators/blazer/templates/install.rb.tt +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cfb774d21d8d5756c2fc273c2148542e26550452ea886adf92023c411b45200a
|
4
|
+
data.tar.gz: 8200979166341f38e0647fbb566f1fd8ead6895ea254a12ead4901e344d80f38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d6705d3dd2c27db9aeb36b9afd2e9a335d876f36865c5bbaade10f13cca80436ec3c31787231c16b591fd78481cdbb7f11df82de00417fd71d5005b1db038b11
|
7
|
+
data.tar.gz: 50c2230e80ad2a0e487197c8593a4c774a0f58304ed88b704860ce4550029202f677042a685b7457a57c67b6e660a82f4692ba529a5eabb41c17d2d1182c3fce
|
data/CHANGELOG.md
CHANGED
@@ -1,27 +1,51 @@
|
|
1
|
-
## 2.2.
|
1
|
+
## 2.2.6 (2020-07-21)
|
2
|
+
|
3
|
+
- Added experimental support for InfluxDB
|
4
|
+
- Added support for forecasting week, month, quarter, and year with Prophet
|
5
|
+
- Fixed forecasting link not showing up
|
6
|
+
|
7
|
+
## 2.2.5 (2020-06-03)
|
8
|
+
|
9
|
+
- Updated maps to fix deprecation error
|
10
|
+
|
11
|
+
## 2.2.4 (2020-05-30)
|
12
|
+
|
13
|
+
- Fixed error with new queries
|
14
|
+
|
15
|
+
## 2.2.3 (2020-05-30)
|
16
|
+
|
17
|
+
- Improved query parameter handling
|
18
|
+
|
19
|
+
## 2.2.2 (2020-04-13)
|
20
|
+
|
21
|
+
- Added experimental support for the Socrata Open Data API (SODA)
|
22
|
+
- Added experimental Prophet forecasting
|
23
|
+
- Fixed query search for non-ASCII characters
|
24
|
+
|
25
|
+
## 2.2.1 (2019-10-08)
|
2
26
|
|
3
27
|
- Added support for Sprockets 4
|
4
28
|
- Improved Snowflake table preview
|
5
29
|
- Fixed bug with refresh link not showing
|
6
30
|
|
7
|
-
## 2.2.0
|
31
|
+
## 2.2.0 (2019-07-12)
|
8
32
|
|
9
33
|
- Added schema to table preview for Postgres and Redshift
|
10
34
|
- Fixed bug with Slack notifications not sending
|
11
35
|
- Dropped support for Rails 4.2
|
12
36
|
|
13
|
-
## 2.1.0
|
37
|
+
## 2.1.0 (2019-06-04)
|
14
38
|
|
15
39
|
- Require latest Chartkick to prevent possible XSS - see [#245](https://github.com/ankane/blazer/issues/245)
|
16
40
|
|
17
|
-
## 2.0.2
|
41
|
+
## 2.0.2 (2019-05-26)
|
18
42
|
|
19
43
|
- Added support for variable transformation for blind indexing
|
20
44
|
- Added experimental support for Neo4j
|
21
45
|
- Added experimental support for Salesforce
|
22
46
|
- Fixed JavaScript sorting for numbers with commas
|
23
47
|
|
24
|
-
## 2.0.1
|
48
|
+
## 2.0.1 (2019-01-07)
|
25
49
|
|
26
50
|
- Added favicon
|
27
51
|
- Added search for checks and schema
|
@@ -32,7 +56,7 @@
|
|
32
56
|
- Improved docs for new installs
|
33
57
|
- Fixed error with canceling queries
|
34
58
|
|
35
|
-
## 2.0.0
|
59
|
+
## 2.0.0 (2019-01-03)
|
36
60
|
|
37
61
|
- Added support for Slack
|
38
62
|
- Added `async` option
|
@@ -45,68 +69,67 @@ Breaking changes
|
|
45
69
|
|
46
70
|
- Dropped support for Rails < 4.2
|
47
71
|
|
48
|
-
## 1.9.0
|
72
|
+
## 1.9.0 (2018-06-17)
|
49
73
|
|
50
74
|
- Prompt developers to check custom `before_action`
|
51
75
|
- Better ordering on home page
|
52
76
|
- Added support for Snowflake
|
53
77
|
|
54
|
-
## 1.8.2
|
78
|
+
## 1.8.2 (2018-02-22)
|
55
79
|
|
56
80
|
- Added support for Cassandra
|
57
81
|
- Fixes for Druid
|
58
|
-
|
59
|
-
## 1.8.1
|
60
|
-
|
61
82
|
- Added support for Amazon Athena
|
62
83
|
- Added support for Druid
|
63
84
|
- Fixed query cancellation
|
64
85
|
|
65
|
-
|
86
|
+
There was no 1.8.1 release.
|
87
|
+
|
88
|
+
## 1.8.0 (2017-05-01)
|
66
89
|
|
67
90
|
- Added support for Rails 5.1
|
68
91
|
|
69
|
-
## 1.7.10
|
92
|
+
## 1.7.10 (2017-04-03)
|
70
93
|
|
71
94
|
- Added support for Google BigQuery
|
72
95
|
- Require `drill-sergeant` gem for Apache Drill
|
73
96
|
- Better handling of checks with variables
|
74
97
|
|
75
|
-
## 1.7.9
|
98
|
+
## 1.7.9 (2017-03-20)
|
76
99
|
|
77
100
|
- Added beta support for Apache Drill
|
78
101
|
- Added email validation for checks
|
79
102
|
- Updated Chart.js to 2.5.0
|
80
103
|
|
81
|
-
## 1.7.8
|
104
|
+
## 1.7.8 (2017-02-06)
|
82
105
|
|
83
106
|
- Added support for custom adapters
|
84
107
|
- Fixed bug with scatter charts on dashboards
|
85
108
|
- Fixed table preview for SQL Server
|
86
109
|
- Fixed issue when `default_url_options` set
|
87
110
|
|
88
|
-
## 1.7.7
|
111
|
+
## 1.7.7 (2016-12-17)
|
89
112
|
|
90
113
|
- Fixed preview error for MySQL
|
91
114
|
- Fixed error with timeouts for MySQL
|
92
115
|
|
93
|
-
## 1.7.6
|
116
|
+
## 1.7.6 (2016-12-13)
|
94
117
|
|
95
118
|
- Added scatter chart
|
96
119
|
- Fixed issue with false values showing up blank
|
97
120
|
- Fixed preview for table names with certain characters
|
98
121
|
|
99
|
-
## 1.7.5
|
122
|
+
## 1.7.5 (2016-11-22)
|
100
123
|
|
101
124
|
- Fixed issue with check emails sometimes failing for default Rails 5 ActiveJob adapter
|
102
125
|
- Fixed sorting for new dashboards
|
103
126
|
|
104
|
-
## 1.7.4
|
127
|
+
## 1.7.4 (2016-11-06)
|
105
128
|
|
106
129
|
- Removed extra dependencies added in 1.7.1
|
107
130
|
- Fixed `send_failing_checks` for default Rails 5 ActiveJob adapter
|
108
131
|
|
109
|
-
## 1.7.3
|
132
|
+
## 1.7.3 (2016-11-01)
|
110
133
|
|
111
134
|
- Fixed JavaScript errors
|
112
135
|
- Fixed query cancel error
|
@@ -114,20 +137,20 @@ Breaking changes
|
|
114
137
|
- Include sample data in email when bad data checks fail
|
115
138
|
- Fixed deprecation warnings
|
116
139
|
|
117
|
-
## 1.7.2
|
140
|
+
## 1.7.2 (2016-10-30)
|
118
141
|
|
119
142
|
- Cancel all queries on page nav
|
120
143
|
- Prevent Ace from taking over find command
|
121
144
|
- Added ability to use hashes for smart columns
|
122
145
|
- Added ability to inherit smart variables and columns from other data sources
|
123
146
|
|
124
|
-
## 1.7.1
|
147
|
+
## 1.7.1 (2016-10-29)
|
125
148
|
|
126
149
|
- Do not fork when enter key pressed
|
127
150
|
- Use custom version of Chart.js to fix label overlap
|
128
151
|
- Improved performance of home page
|
129
152
|
|
130
|
-
## 1.7.0
|
153
|
+
## 1.7.0 (2016-09-07)
|
131
154
|
|
132
155
|
- Added ability to cancel queries on backend for Postgres and Redshift
|
133
156
|
- Only run 3 queries at a time on dashboards
|
@@ -135,65 +158,65 @@ Breaking changes
|
|
135
158
|
- Attempt to reconnect when connection issues
|
136
159
|
- Fixed issues with caching
|
137
160
|
|
138
|
-
## 1.6.2
|
161
|
+
## 1.6.2 (2016-08-11)
|
139
162
|
|
140
163
|
- Added basic query permissions
|
141
164
|
- Added ability to use arrays and hashes for smart variables
|
142
165
|
- Added cancel button for queries
|
143
166
|
- Added `lat` and `lng` as map keys
|
144
167
|
|
145
|
-
## 1.6.1
|
168
|
+
## 1.6.1 (2016-07-30)
|
146
169
|
|
147
170
|
- Added support for Presto [beta]
|
148
171
|
- Added support for Elasticsearch timeouts
|
149
172
|
- Fixed error in Rails 5
|
150
173
|
|
151
|
-
## 1.6.0
|
174
|
+
## 1.6.0 (2016-07-28)
|
152
175
|
|
153
176
|
- Added support for MongoDB [beta]
|
154
177
|
- Added support for Elasticsearch [beta]
|
155
178
|
- Fixed deprecation warning in Rails 5
|
156
179
|
|
157
|
-
## 1.5.1
|
180
|
+
## 1.5.1 (2016-07-24)
|
158
181
|
|
159
182
|
- Added anomaly detection for data less than 2 weeks
|
160
183
|
- Added autolinking urls
|
161
184
|
- Added support for images
|
162
185
|
|
163
|
-
## 1.5.0
|
186
|
+
## 1.5.0 (2016-06-29)
|
164
187
|
|
165
188
|
- Added new bar chart format
|
166
189
|
- Added anomaly detection checks
|
167
190
|
- Added `async` option for polling
|
168
191
|
|
169
|
-
## 1.4.0
|
192
|
+
## 1.4.0 (2016-06-09)
|
170
193
|
|
171
194
|
- Added `slow` cache mode
|
172
195
|
- Fixed `BLAZER_DATABASE_URL required` error
|
173
196
|
- Fixed issue with duplicate column names
|
174
197
|
|
175
|
-
## 1.3.5
|
198
|
+
## 1.3.5 (2016-05-11)
|
176
199
|
|
177
200
|
- Fixed error with checks
|
178
201
|
|
179
|
-
## 1.3.4
|
202
|
+
## 1.3.4 (2016-05-11)
|
180
203
|
|
181
204
|
- Fixed issue with missing queries
|
182
205
|
|
183
|
-
## 1.3.3
|
206
|
+
## 1.3.3 (2016-05-08)
|
184
207
|
|
185
208
|
- Fixed error with Rails 4.1 and below
|
186
209
|
|
187
|
-
## 1.3.2
|
210
|
+
## 1.3.2 (2016-05-07)
|
188
211
|
|
189
212
|
- Added support for Rails 5
|
190
213
|
- Attempt to reconnect for checks
|
191
214
|
|
192
|
-
## 1.3.1
|
215
|
+
## 1.3.1 (2016-05-06)
|
193
216
|
|
194
217
|
- Fixed migration error
|
195
218
|
|
196
|
-
## 1.3.0
|
219
|
+
## 1.3.0 (2016-05-06)
|
197
220
|
|
198
221
|
- Added schedule for checks
|
199
222
|
- Switched to Chart.js for charts
|
@@ -202,11 +225,11 @@ Breaking changes
|
|
202
225
|
- Raise error when timeout not supported
|
203
226
|
- Added creator to dashboards and checks
|
204
227
|
|
205
|
-
## 1.2.1
|
228
|
+
## 1.2.1 (2016-04-26)
|
206
229
|
|
207
230
|
- Fixed checks
|
208
231
|
|
209
|
-
## 1.2.0
|
232
|
+
## 1.2.0 (2016-03-22)
|
210
233
|
|
211
234
|
- Added non-editable queries
|
212
235
|
- Added variable defaults
|
@@ -215,7 +238,7 @@ Breaking changes
|
|
215
238
|
- Hide variables from commented out lines
|
216
239
|
- Fixed regex as variable names
|
217
240
|
|
218
|
-
## 1.1.1
|
241
|
+
## 1.1.1 (2016-03-06)
|
219
242
|
|
220
243
|
- Added `before_action` option
|
221
244
|
- Added invert option for checks
|
@@ -224,7 +247,7 @@ Breaking changes
|
|
224
247
|
- Fixed request URI too large
|
225
248
|
- Prevent accidental backspace nav on query page
|
226
249
|
|
227
|
-
## 1.1.0
|
250
|
+
## 1.1.0 (2015-12-27)
|
228
251
|
|
229
252
|
- Replaced pie charts with column charts
|
230
253
|
- Fixed error with datepicker
|
@@ -232,55 +255,55 @@ Breaking changes
|
|
232
255
|
- Added a notice when editing a query that is part of a dashboard
|
233
256
|
- Added refresh for dashboards
|
234
257
|
|
235
|
-
## 1.0.4
|
258
|
+
## 1.0.4 (2015-11-04)
|
236
259
|
|
237
260
|
- Added recently viewed queries and dashboards to home page
|
238
261
|
- Fixed refresh when transform statement is used
|
239
262
|
- Fixed error when no user model
|
240
263
|
|
241
|
-
## 1.0.3
|
264
|
+
## 1.0.3 (2015-10-18)
|
242
265
|
|
243
266
|
- Added maps
|
244
267
|
- Added support for Rails 4.0
|
245
268
|
|
246
|
-
## 1.0.2
|
269
|
+
## 1.0.2 (2015-10-11)
|
247
270
|
|
248
271
|
- Fixed error when installing
|
249
272
|
- Added `schemas` option
|
250
273
|
|
251
|
-
## 1.0.1
|
274
|
+
## 1.0.1 (2015-10-08)
|
252
275
|
|
253
276
|
- Added comments to queries
|
254
277
|
- Added `cache` option
|
255
278
|
- Added `user_method` option
|
256
279
|
- Added `use_transaction` option
|
257
280
|
|
258
|
-
## 1.0.0
|
281
|
+
## 1.0.0 (2015-10-04)
|
259
282
|
|
260
283
|
- Added support for multiple data sources
|
261
284
|
- Added dashboards
|
262
285
|
- Added checks
|
263
286
|
- Added support for Redshift
|
264
287
|
|
265
|
-
## 0.0.8
|
288
|
+
## 0.0.8 (2015-09-05)
|
266
289
|
|
267
290
|
- Easier to edit queries with variables
|
268
291
|
- Dynamically expand editor height as needed
|
269
292
|
- No need for spaces in search
|
270
293
|
|
271
|
-
## 0.0.7
|
294
|
+
## 0.0.7 (2015-07-23)
|
272
295
|
|
273
296
|
- Fixed error when no `User` class
|
274
297
|
- Fixed forking a query with variables
|
275
298
|
- Set time zone after Rails initializes
|
276
299
|
|
277
|
-
## 0.0.6
|
300
|
+
## 0.0.6 (2015-06-18)
|
278
301
|
|
279
302
|
- Added fork button
|
280
303
|
- Fixed trending
|
281
304
|
- Fixed time zones for date select
|
282
305
|
|
283
|
-
## 0.0.5
|
306
|
+
## 0.0.5 (2015-01-31)
|
284
307
|
|
285
308
|
- Added support for Rails 4.2
|
286
309
|
- Fixed error with `mysql2` adapter
|
data/README.md
CHANGED
@@ -4,9 +4,9 @@ Explore your data with SQL. Easily create charts and dashboards, and share them
|
|
4
4
|
|
5
5
|
[Try it out](https://blazer.dokkuapp.com)
|
6
6
|
|
7
|
-
[![Screenshot](https://blazer.dokkuapp.com/assets/
|
7
|
+
[![Screenshot](https://blazer.dokkuapp.com/assets/blazer-90fb6ce8ad25614c6f9c3b4619cbfbd66fa3d6567dac34d83df540f6688665f1.png)](https://blazer.dokkuapp.com)
|
8
8
|
|
9
|
-
Blazer
|
9
|
+
Blazer is also available as a [Docker image](https://github.com/ankane/blazer-docker).
|
10
10
|
|
11
11
|
:tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
|
12
12
|
|
@@ -426,10 +426,30 @@ If you’re on Heroku, follow [these additional instructions](#anomaly-detection
|
|
426
426
|
|
427
427
|
## Forecasting
|
428
428
|
|
429
|
-
Blazer has experimental support for forecasting
|
429
|
+
Blazer has experimental support for two different forecasting methods.
|
430
|
+
|
431
|
+
A forecast link will appear for queries that return 2 columns with types timestamp and numeric.
|
430
432
|
|
431
433
|
[Example](https://blazer.dokkuapp.com/queries/18-forecast?forecast=t)
|
432
434
|
|
435
|
+
### Prophet
|
436
|
+
|
437
|
+
Add [prophet](https://github.com/ankane/prophet) to your Gemfile:
|
438
|
+
|
439
|
+
```ruby
|
440
|
+
gem 'prophet-rb', '>= 0.2.1'
|
441
|
+
```
|
442
|
+
|
443
|
+
And add to `config/blazer.yml`:
|
444
|
+
|
445
|
+
```yml
|
446
|
+
forecasting: prophet
|
447
|
+
```
|
448
|
+
|
449
|
+
### Trend
|
450
|
+
|
451
|
+
[Trend](https://trendapi.org/) uses an external service.
|
452
|
+
|
433
453
|
Add [trend](https://github.com/ankane/trend) to your Gemfile:
|
434
454
|
|
435
455
|
```ruby
|
@@ -442,8 +462,6 @@ And add to `config/blazer.yml`:
|
|
442
462
|
forecasting: trend
|
443
463
|
```
|
444
464
|
|
445
|
-
A forecast link will appear for queries that return 2 columns with types timestamp and numeric.
|
446
|
-
|
447
465
|
## Data Sources
|
448
466
|
|
449
467
|
Blazer supports multiple data sources :tada:
|
@@ -473,13 +491,15 @@ data_sources:
|
|
473
491
|
- [Elasticsearch](#elasticsearch)
|
474
492
|
- [Google BigQuery](#google-bigquery)
|
475
493
|
- [IBM DB2 and Informix](#ibm-db2-and-informix)
|
494
|
+
- [InfluxDB](#influxdb)
|
476
495
|
- [MongoDB](#mongodb-1)
|
477
496
|
- [MySQL](#mysql-1)
|
478
|
-
- [Neo4j](#neo4j
|
497
|
+
- [Neo4j](#neo4j)
|
479
498
|
- [Oracle](#oracle)
|
480
499
|
- [PostgreSQL](#postgresql-1)
|
481
500
|
- [Presto](#presto)
|
482
|
-
- [Salesforce](#salesforce
|
501
|
+
- [Salesforce](#salesforce)
|
502
|
+
- [Socrata Open Data API (SODA)](#socrata-open-data-api-soda)
|
483
503
|
- [Snowflake](#snowflake)
|
484
504
|
- [SQLite](#sqlite)
|
485
505
|
- [SQL Server](#sql-server)
|
@@ -508,7 +528,7 @@ data_sources:
|
|
508
528
|
|
509
529
|
### Amazon Redshift
|
510
530
|
|
511
|
-
Add [
|
531
|
+
Add [activerecord6-redshift-adapter](https://github.com/kwent/activerecord6-redshift-adapter) or [activerecord5-redshift-adapter](https://github.com/ConsultingMD/activerecord5-redshift-adapter) to your Gemfile and set:
|
512
532
|
|
513
533
|
```yml
|
514
534
|
data_sources:
|
@@ -573,7 +593,28 @@ data_sources:
|
|
573
593
|
|
574
594
|
### IBM DB2 and Informix
|
575
595
|
|
576
|
-
|
596
|
+
Add [ibm_db](https://github.com/ibmdb/ruby-ibmdb) to your Gemfile and set:
|
597
|
+
|
598
|
+
```yml
|
599
|
+
data_sources:
|
600
|
+
my_source:
|
601
|
+
url: ibm-db://user:password@hostname:50000/database
|
602
|
+
```
|
603
|
+
|
604
|
+
### InfluxDB
|
605
|
+
|
606
|
+
*Experimental*
|
607
|
+
|
608
|
+
Add [influxdb](https://github.com/influxdata/influxdb-ruby) to your Gemfile and set:
|
609
|
+
|
610
|
+
```yml
|
611
|
+
data_sources:
|
612
|
+
my_source:
|
613
|
+
adapter: influxdb
|
614
|
+
url: http://user:password@hostname:8086/database
|
615
|
+
```
|
616
|
+
|
617
|
+
Supports [InfluxQL](https://docs.influxdata.com/influxdb/v1.8/query_language/explore-data/)
|
577
618
|
|
578
619
|
### MongoDB
|
579
620
|
|
@@ -595,7 +636,9 @@ data_sources:
|
|
595
636
|
url: mysql2://user:password@hostname:3306/database
|
596
637
|
```
|
597
638
|
|
598
|
-
### Neo4j
|
639
|
+
### Neo4j
|
640
|
+
|
641
|
+
*Experimental*
|
599
642
|
|
600
643
|
Add [neo4j-core](https://github.com/neo4jrb/neo4j-core) to your Gemfile and set:
|
601
644
|
|
@@ -608,11 +651,17 @@ data_sources:
|
|
608
651
|
|
609
652
|
### Oracle
|
610
653
|
|
611
|
-
|
654
|
+
Add [activerecord-oracle_enhanced-adapter](https://github.com/rsim/oracle-enhanced) and [ruby-oci8](https://github.com/kubo/ruby-oci8) to your Gemfile and set:
|
655
|
+
|
656
|
+
```yml
|
657
|
+
data_sources:
|
658
|
+
my_source:
|
659
|
+
url: oracle-enhanced://user:password@hostname:1521/database
|
660
|
+
```
|
612
661
|
|
613
662
|
### PostgreSQL
|
614
663
|
|
615
|
-
Add [pg](https://
|
664
|
+
Add [pg](https://github.com/ged/ruby-pg) to your Gemfile (if it’s not there) and set:
|
616
665
|
|
617
666
|
```yml
|
618
667
|
data_sources:
|
@@ -630,7 +679,9 @@ data_sources:
|
|
630
679
|
url: presto://user@hostname:8080/catalog
|
631
680
|
```
|
632
681
|
|
633
|
-
### Salesforce
|
682
|
+
### Salesforce
|
683
|
+
|
684
|
+
*Experimental*
|
634
685
|
|
635
686
|
Add [restforce](https://github.com/restforce/restforce) to your Gemfile and set:
|
636
687
|
|
@@ -653,6 +704,22 @@ SALESFORCE_API_VERSION="41.0"
|
|
653
704
|
|
654
705
|
Supports [SOQL](https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql.htm)
|
655
706
|
|
707
|
+
### Socrata Open Data API (SODA)
|
708
|
+
|
709
|
+
*Experimental*
|
710
|
+
|
711
|
+
Set:
|
712
|
+
|
713
|
+
```yml
|
714
|
+
data_sources:
|
715
|
+
my_source:
|
716
|
+
adapter: soda
|
717
|
+
url: https://soda.demo.socrata.com/resource/4tka-6guv.json
|
718
|
+
app_token: ...
|
719
|
+
```
|
720
|
+
|
721
|
+
Supports [SoQL](https://dev.socrata.com/docs/functions/)
|
722
|
+
|
656
723
|
### Snowflake
|
657
724
|
|
658
725
|
First, install ODBC. For Homebrew, use:
|
@@ -671,7 +738,7 @@ For Heroku, use the [Apt buildpack](https://github.com/heroku/heroku-buildpack-a
|
|
671
738
|
|
672
739
|
```text
|
673
740
|
unixodbc-dev
|
674
|
-
https://sfc-repo.snowflakecomputing.com/odbc/linux/2.
|
741
|
+
https://sfc-repo.snowflakecomputing.com/odbc/linux/2.21.5/snowflake-odbc-2.21.5.x86_64.deb
|
675
742
|
```
|
676
743
|
|
677
744
|
> This installs the driver at `/app/.apt/usr/lib/snowflake/odbc/lib/libSnowflake.so`
|
@@ -86,8 +86,22 @@ module Blazer
|
|
86
86
|
[smart_var, error]
|
87
87
|
end
|
88
88
|
|
89
|
-
|
90
|
-
|
89
|
+
# don't pass to url helpers
|
90
|
+
#
|
91
|
+
# some are dangerous when passed as symbols
|
92
|
+
# root_url({host: "evilsite.com"})
|
93
|
+
#
|
94
|
+
# certain ones (like host) only affect *_url and not *_path
|
95
|
+
#
|
96
|
+
# when permitted parameters are passed in Rails 6,
|
97
|
+
# they appear to be added as GET parameters
|
98
|
+
# root_url(params.permit(:host))
|
99
|
+
BLACKLISTED_KEYS = [: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, :script_name, :original_script_name]
|
100
|
+
|
101
|
+
# remove blacklisted keys from both params and permitted keys for better sleep
|
102
|
+
def variable_params(resource)
|
103
|
+
permitted_keys = resource.variables - BLACKLISTED_KEYS.map(&:to_s)
|
104
|
+
params.except(*BLACKLISTED_KEYS).permit(*permitted_keys)
|
91
105
|
end
|
92
106
|
helper_method :variable_params
|
93
107
|
|
@@ -43,7 +43,7 @@ module Blazer
|
|
43
43
|
|
44
44
|
def update
|
45
45
|
if update_dashboard(@dashboard)
|
46
|
-
redirect_to dashboard_path(@dashboard, variable_params)
|
46
|
+
redirect_to dashboard_path(@dashboard, variable_params(@dashboard))
|
47
47
|
else
|
48
48
|
render_errors @dashboard
|
49
49
|
end
|
@@ -62,7 +62,7 @@ module Blazer
|
|
62
62
|
Blazer.transform_statement.call(data_source, statement) if Blazer.transform_statement
|
63
63
|
data_source.clear_cache(statement)
|
64
64
|
end
|
65
|
-
redirect_to dashboard_path(@dashboard, variable_params)
|
65
|
+
redirect_to dashboard_path(@dashboard, variable_params(@dashboard))
|
66
66
|
end
|
67
67
|
|
68
68
|
private
|
@@ -45,7 +45,7 @@ module Blazer
|
|
45
45
|
@query.creator = blazer_user if @query.respond_to?(:creator)
|
46
46
|
|
47
47
|
if @query.save
|
48
|
-
redirect_to query_path(@query, variable_params)
|
48
|
+
redirect_to query_path(@query, variable_params(@query))
|
49
49
|
else
|
50
50
|
render_errors @query
|
51
51
|
end
|
@@ -156,7 +156,7 @@ module Blazer
|
|
156
156
|
process_vars(@statement, @query.data_source)
|
157
157
|
Blazer.transform_statement.call(data_source, @statement) if Blazer.transform_statement
|
158
158
|
data_source.clear_cache(@statement)
|
159
|
-
redirect_to query_path(@query, variable_params)
|
159
|
+
redirect_to query_path(@query, variable_params(@query))
|
160
160
|
end
|
161
161
|
|
162
162
|
def update
|
@@ -168,7 +168,7 @@ module Blazer
|
|
168
168
|
@query.errors.add(:base, "Sorry, permission denied")
|
169
169
|
end
|
170
170
|
if @query.errors.empty? && @query.update(query_params)
|
171
|
-
redirect_to query_path(@query, variable_params)
|
171
|
+
redirect_to query_path(@query, variable_params(@query))
|
172
172
|
else
|
173
173
|
render_errors @query
|
174
174
|
end
|
@@ -176,7 +176,7 @@ module Blazer
|
|
176
176
|
|
177
177
|
def destroy
|
178
178
|
@query.destroy if @query.editable?(blazer_user)
|
179
|
-
redirect_to
|
179
|
+
redirect_to root_path
|
180
180
|
end
|
181
181
|
|
182
182
|
def tables
|
@@ -249,7 +249,9 @@ module Blazer
|
|
249
249
|
r[lat_index] && r[lon_index]
|
250
250
|
end.map do |r|
|
251
251
|
{
|
252
|
-
|
252
|
+
# Mapbox.js does sanitization with https://github.com/mapbox/sanitize-caja
|
253
|
+
# but we should do it here as well
|
254
|
+
title: r.each_with_index.map { |v, i| i == lat_index || i == lon_index ? nil : "<strong>#{ERB::Util.html_escape(@columns[i])}:</strong> #{ERB::Util.html_escape(v)}" }.compact.join("<br />").truncate(140),
|
253
255
|
latitude: r[lat_index],
|
254
256
|
longitude: r[lon_index]
|
255
257
|
}
|
@@ -14,7 +14,7 @@ module Blazer
|
|
14
14
|
def blazer_format_value(key, value)
|
15
15
|
if value.is_a?(Numeric) && !key.to_s.end_with?("id") && !key.to_s.start_with?("id")
|
16
16
|
number_with_delimiter(value)
|
17
|
-
elsif value =~ BLAZER_URL_REGEX
|
17
|
+
elsif value.is_a?(String) && value =~ BLAZER_URL_REGEX
|
18
18
|
# see if image or link
|
19
19
|
if Blazer.images && (key.include?("image") || BLAZER_IMAGE_EXT.include?(value.split(".").last.split("?").first.try(:downcase)))
|
20
20
|
link_to value, target: "_blank" do
|
@@ -60,6 +60,9 @@ module Blazer
|
|
60
60
|
ActionController::Base.helpers.pluralize(*args)
|
61
61
|
end
|
62
62
|
|
63
|
+
# checks shouldn't have variables, but in any case,
|
64
|
+
# avoid passing variable params to url helpers
|
65
|
+
# (known unsafe parameters are removed, but blacklist isn't ideal)
|
63
66
|
def self.query_url(id)
|
64
67
|
Blazer::Engine.routes.url_helpers.query_url(id, ActionMailer::Base.default_url_options)
|
65
68
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
<head>
|
3
3
|
</head>
|
4
4
|
<body style="font-family: 'Helvetica Neue', Arial, Helvetica; font-size: 14px; color: #333;">
|
5
|
+
<%# check queries shouldn't have variables, but in any case, don't pass them to url helpers %>
|
5
6
|
<p><%= link_to "View", query_url(@check.query_id) %></p>
|
6
7
|
<% if @error %>
|
7
8
|
<p><%= @error %></p>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<%= form_for @dashboard, url: (@dashboard.persisted? ? dashboard_path(@dashboard, variable_params) : dashboards_path(variable_params)), html: {id: "app", class: "small-form"} do |f| %>
|
1
|
+
<%= form_for @dashboard, url: (@dashboard.persisted? ? dashboard_path(@dashboard, variable_params(@dashboard)) : dashboards_path(variable_params(@dashboard))), html: {id: "app", class: "small-form"} do |f| %>
|
2
2
|
<% if @dashboard.errors.any? %>
|
3
3
|
<div class="alert alert-danger"><%= @dashboard.errors.full_messages.first %></div>
|
4
4
|
<% end %>
|
@@ -10,7 +10,7 @@
|
|
10
10
|
</h3>
|
11
11
|
</div>
|
12
12
|
<div class="col-sm-3 text-right">
|
13
|
-
<%= link_to "Edit", edit_dashboard_path(@dashboard, variable_params), class: "btn btn-info" %>
|
13
|
+
<%= link_to "Edit", edit_dashboard_path(@dashboard, variable_params(@dashboard)), class: "btn btn-info" %>
|
14
14
|
</div>
|
15
15
|
</div>
|
16
16
|
</div>
|
@@ -21,7 +21,7 @@
|
|
21
21
|
<% if @data_sources.any? { |ds| ds.cache_mode != "off" } %>
|
22
22
|
<p class="text-muted" style="float: right;">
|
23
23
|
Some queries may be cached
|
24
|
-
<%= link_to "Refresh", refresh_dashboard_path(@dashboard, variable_params), method: :post %>
|
24
|
+
<%= link_to "Refresh", refresh_dashboard_path(@dashboard, variable_params(@dashboard)), method: :post %>
|
25
25
|
</p>
|
26
26
|
<% end %>
|
27
27
|
|
@@ -33,7 +33,7 @@
|
|
33
33
|
|
34
34
|
<% @queries.each_with_index do |query, i| %>
|
35
35
|
<div class="chart-container">
|
36
|
-
<h4><%= link_to query.friendly_name, query_path(query, variable_params), target: "_blank" %></h4>
|
36
|
+
<h4><%= link_to query.friendly_name, query_path(query, variable_params(query)), target: "_blank" %></h4>
|
37
37
|
<div id="chart-<%= i %>" class="chart">
|
38
38
|
<p class="text-muted">Loading...</p>
|
39
39
|
</div>
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<% end %>
|
4
4
|
|
5
5
|
<div id="app" v-cloak>
|
6
|
-
<%= form_for @query, url: (@query.persisted? ? query_path(@query, variable_params) : queries_path(variable_params)), html: {autocomplete: "off"} do |f| %>
|
6
|
+
<%= form_for @query, url: (@query.persisted? ? query_path(@query, variable_params(@query)) : queries_path(variable_params(@query))), html: {autocomplete: "off"} do |f| %>
|
7
7
|
<div class="row">
|
8
8
|
<div id="statement-box" class="col-xs-8">
|
9
9
|
<div class= "form-group">
|
@@ -67,7 +67,7 @@
|
|
67
67
|
</div>
|
68
68
|
|
69
69
|
<script>
|
70
|
-
<%= blazer_js_var "params", variable_params %>
|
70
|
+
<%= blazer_js_var "params", variable_params(@query) %>
|
71
71
|
<%= blazer_js_var "previewStatement", Hash[Blazer.data_sources.map { |k, v| [k, (v.preview_statement rescue "")] }] %>
|
72
72
|
|
73
73
|
var app = new Vue({
|
@@ -20,7 +20,7 @@
|
|
20
20
|
<% end %>
|
21
21
|
|
22
22
|
<% if @query && params[:query_id] %>
|
23
|
-
<%= link_to "Refresh", refresh_query_path(@query, variable_params), method: :post %>
|
23
|
+
<%= link_to "Refresh", refresh_query_path(@query, variable_params(@query)), method: :post %>
|
24
24
|
<% end %>
|
25
25
|
</p>
|
26
26
|
<% end %>
|
@@ -36,7 +36,7 @@
|
|
36
36
|
|
37
37
|
<% if @query && @result.forecastable? && !params[:forecast] %>
|
38
38
|
·
|
39
|
-
<%= link_to "Forecast", query_path(@query, {forecast: "t"}.merge(variable_params)) %>
|
39
|
+
<%= link_to "Forecast", query_path(@query, {forecast: "t"}.merge(variable_params(@query))) %>
|
40
40
|
<% end %>
|
41
41
|
</p>
|
42
42
|
<% end %>
|
@@ -80,7 +80,8 @@
|
|
80
80
|
<%= blazer_js_var "mapboxAccessToken", Blazer.mapbox_access_token %>
|
81
81
|
<%= blazer_js_var "markers", @markers %>
|
82
82
|
L.mapbox.accessToken = mapboxAccessToken;
|
83
|
-
var map = L.mapbox.map('map'
|
83
|
+
var map = L.mapbox.map('map')
|
84
|
+
.addLayer(L.mapbox.styleLayer('mapbox://styles/mapbox/streets-v11'));
|
84
85
|
var featureLayer = L.mapbox.featureLayer().addTo(map);
|
85
86
|
var geojson = [];
|
86
87
|
for (var i = 0; i < markers.length; i++) {
|
@@ -10,8 +10,8 @@
|
|
10
10
|
</h3>
|
11
11
|
</div>
|
12
12
|
<div class="col-sm-3 text-right">
|
13
|
-
<%= link_to "Edit", edit_query_path(@query, variable_params), class: "btn btn-default", disabled: !@query.editable?(blazer_user) %>
|
14
|
-
<%= link_to "Fork", new_query_path(variable_params.merge(fork_query_id: @query.id, data_source: @query.data_source, name: @query.name)), class: "btn btn-info" %>
|
13
|
+
<%= link_to "Edit", edit_query_path(@query, variable_params(@query)), class: "btn btn-default", disabled: !@query.editable?(blazer_user) %>
|
14
|
+
<%= link_to "Fork", new_query_path(variable_params(@query).merge(fork_query_id: @query.id, data_source: @query.data_source, name: @query.name)), class: "btn btn-info" %>
|
15
15
|
|
16
16
|
<% if !@error && @success %>
|
17
17
|
<%= button_to "Download", run_queries_path(query_id: @query.id, format: "csv", forecast: params[:forecast]), params: {statement: @statement}, class: "btn btn-primary" %>
|
@@ -56,7 +56,9 @@
|
|
56
56
|
$("#results").addClass("query-error").html(message)
|
57
57
|
}
|
58
58
|
|
59
|
-
|
59
|
+
<% data = variable_params(@query).merge(statement: @statement, query_id: @query.id, data_source: @query.data_source) %>
|
60
|
+
<% data.merge!(forecast: "t") if params[:forecast] %>
|
61
|
+
<%= blazer_js_var "data", data %>
|
60
62
|
|
61
63
|
runQuery(data, showRun, showError)
|
62
64
|
</script>
|
@@ -11,8 +11,8 @@
|
|
11
11
|
<%= blazer_js_var "rootPath", root_path %>
|
12
12
|
</script>
|
13
13
|
<% if blazer_maps? %>
|
14
|
-
<%= stylesheet_link_tag "https://api.mapbox.com/mapbox.js/v3.
|
15
|
-
<%= javascript_include_tag "https://api.mapbox.com/mapbox.js/v3.
|
14
|
+
<%= stylesheet_link_tag "https://api.mapbox.com/mapbox.js/v3.3.1/mapbox.css", integrity: "sha384-vxzdEt+wZRPNQbhChjmiaFMLWg86IGuq1NGDehJHsD2mphYkxXll/eSs16WWi6Dq", crossorigin: "anonymous" %>
|
15
|
+
<%= javascript_include_tag "https://api.mapbox.com/mapbox.js/v3.3.1/mapbox.js", integrity: "sha384-CTBEiDLiZJ8gkAQ3fYGoeiRp81/ecNiBkGz11jXFALOZ6++rbnqmdo6OImkmr1MO", crossorigin: "anonymous" %>
|
16
16
|
<% end %>
|
17
17
|
<%= csrf_meta_tags %>
|
18
18
|
</head>
|
data/lib/blazer.rb
CHANGED
@@ -18,10 +18,12 @@ require "blazer/adapters/cassandra_adapter"
|
|
18
18
|
require "blazer/adapters/drill_adapter"
|
19
19
|
require "blazer/adapters/druid_adapter"
|
20
20
|
require "blazer/adapters/elasticsearch_adapter"
|
21
|
+
require "blazer/adapters/influxdb_adapter"
|
21
22
|
require "blazer/adapters/mongodb_adapter"
|
22
23
|
require "blazer/adapters/neo4j_adapter"
|
23
24
|
require "blazer/adapters/presto_adapter"
|
24
25
|
require "blazer/adapters/salesforce_adapter"
|
26
|
+
require "blazer/adapters/soda_adapter"
|
25
27
|
require "blazer/adapters/sql_adapter"
|
26
28
|
require "blazer/adapters/snowflake_adapter"
|
27
29
|
|
@@ -118,7 +120,7 @@ module Blazer
|
|
118
120
|
def self.extract_vars(statement)
|
119
121
|
# strip commented out lines
|
120
122
|
# and regex {1} or {1,2}
|
121
|
-
statement.gsub(/\-\-.+/, "").gsub(/\/\*.+\*\//m, "").scan(/\{\w*?\}/i).map { |v| v[1...-1] }.reject { |v| /\A\d+(\,\d+)?\z/.match(v) || v.empty? }.uniq
|
123
|
+
statement.to_s.gsub(/\-\-.+/, "").gsub(/\/\*.+\*\//m, "").scan(/\{\w*?\}/i).map { |v| v[1...-1] }.reject { |v| /\A\d+(\,\d+)?\z/.match(v) || v.empty? }.uniq
|
122
124
|
end
|
123
125
|
|
124
126
|
def self.run_checks(schedule: nil)
|
@@ -219,9 +221,11 @@ Blazer.register_adapter "cassandra", Blazer::Adapters::CassandraAdapter
|
|
219
221
|
Blazer.register_adapter "drill", Blazer::Adapters::DrillAdapter
|
220
222
|
Blazer.register_adapter "druid", Blazer::Adapters::DruidAdapter
|
221
223
|
Blazer.register_adapter "elasticsearch", Blazer::Adapters::ElasticsearchAdapter
|
224
|
+
Blazer.register_adapter "influxdb", Blazer::Adapters::InfluxdbAdapter
|
222
225
|
Blazer.register_adapter "neo4j", Blazer::Adapters::Neo4jAdapter
|
223
226
|
Blazer.register_adapter "presto", Blazer::Adapters::PrestoAdapter
|
224
227
|
Blazer.register_adapter "mongodb", Blazer::Adapters::MongodbAdapter
|
225
228
|
Blazer.register_adapter "salesforce", Blazer::Adapters::SalesforceAdapter
|
229
|
+
Blazer.register_adapter "soda", Blazer::Adapters::SodaAdapter
|
226
230
|
Blazer.register_adapter "sql", Blazer::Adapters::SqlAdapter
|
227
231
|
Blazer.register_adapter "snowflake", Blazer::Adapters::SnowflakeAdapter
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Blazer
|
2
|
+
module Adapters
|
3
|
+
class InfluxdbAdapter < BaseAdapter
|
4
|
+
def run_statement(statement, comment)
|
5
|
+
columns = []
|
6
|
+
rows = []
|
7
|
+
error = nil
|
8
|
+
|
9
|
+
begin
|
10
|
+
result = client.query(statement, denormalize: false).first
|
11
|
+
columns = result["columns"]
|
12
|
+
rows = result["values"]
|
13
|
+
|
14
|
+
# parse time columns
|
15
|
+
# current approach isn't ideal, but result doesn't include types
|
16
|
+
# another approach would be to check the format
|
17
|
+
time_index = columns.index("time")
|
18
|
+
if time_index
|
19
|
+
rows.each do |row|
|
20
|
+
row[time_index] = Time.parse(row[time_index]) if row[time_index]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
rescue => e
|
24
|
+
error = e.message
|
25
|
+
end
|
26
|
+
|
27
|
+
[columns, rows, error]
|
28
|
+
end
|
29
|
+
|
30
|
+
def tables
|
31
|
+
client.list_series
|
32
|
+
end
|
33
|
+
|
34
|
+
def preview_statement
|
35
|
+
"SELECT * FROM {table} LIMIT 10"
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def client
|
41
|
+
@client ||= InfluxDB::Client.new(url: settings["url"])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Blazer
|
2
|
+
module Adapters
|
3
|
+
class SodaAdapter < 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
|
+
# remove whitespace
|
19
|
+
statement = statement.squish
|
20
|
+
|
21
|
+
uri = URI(settings["url"])
|
22
|
+
uri.query = URI.encode_www_form("$query" => statement)
|
23
|
+
|
24
|
+
req = Net::HTTP::Get.new(uri)
|
25
|
+
req["X-App-Token"] = settings["app_token"] if settings["app_token"]
|
26
|
+
|
27
|
+
options = {
|
28
|
+
use_ssl: uri.scheme == "https",
|
29
|
+
open_timeout: 3,
|
30
|
+
read_timeout: 30
|
31
|
+
}
|
32
|
+
|
33
|
+
begin
|
34
|
+
# use Net::HTTP instead of soda-ruby for types and better error messages
|
35
|
+
res = Net::HTTP.start(uri.hostname, uri.port, options) do |http|
|
36
|
+
http.request(req)
|
37
|
+
end
|
38
|
+
|
39
|
+
if res.is_a?(Net::HTTPSuccess)
|
40
|
+
body = JSON.parse(res.body)
|
41
|
+
|
42
|
+
columns = JSON.parse(res["x-soda2-fields"])
|
43
|
+
column_types = columns.zip(JSON.parse(res["x-soda2-types"])).to_h
|
44
|
+
|
45
|
+
columns.reject! { |f| f.start_with?(":@") }
|
46
|
+
# rows can be missing some keys in JSON, so need to map by column
|
47
|
+
rows = body.map { |r| columns.map { |c| r[c] } }
|
48
|
+
|
49
|
+
columns.each_with_index do |column, i|
|
50
|
+
# nothing to do for boolean
|
51
|
+
case column_types[column]
|
52
|
+
when "number"
|
53
|
+
# check if likely an integer column
|
54
|
+
if rows.all? { |r| r[i].to_i == r[i].to_f }
|
55
|
+
rows.each do |row|
|
56
|
+
row[i] = row[i].to_i
|
57
|
+
end
|
58
|
+
else
|
59
|
+
rows.each do |row|
|
60
|
+
row[i] = row[i].to_f
|
61
|
+
end
|
62
|
+
end
|
63
|
+
when "floating_timestamp"
|
64
|
+
# check if likely a date column
|
65
|
+
if rows.all? { |r| r[i].end_with?("T00:00:00.000") }
|
66
|
+
rows.each do |row|
|
67
|
+
row[i] = Date.parse(row[i])
|
68
|
+
end
|
69
|
+
else
|
70
|
+
utc = ActiveSupport::TimeZone["Etc/UTC"]
|
71
|
+
rows.each do |row|
|
72
|
+
row[i] = utc.parse(row[i])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
else
|
78
|
+
error = JSON.parse(res.body)["message"] rescue "Bad response: #{res.code}"
|
79
|
+
end
|
80
|
+
rescue => e
|
81
|
+
error = e.message
|
82
|
+
end
|
83
|
+
|
84
|
+
[columns, rows, error]
|
85
|
+
end
|
86
|
+
|
87
|
+
def preview_statement
|
88
|
+
"SELECT * LIMIT 10"
|
89
|
+
end
|
90
|
+
|
91
|
+
def tables
|
92
|
+
["all"]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/blazer/result.rb
CHANGED
@@ -85,11 +85,26 @@ module Blazer
|
|
85
85
|
@forecastable ||= Blazer.forecasting && column_types == ["time", "numeric"] && @rows.size >= 10
|
86
86
|
end
|
87
87
|
|
88
|
+
# TODO cache it?
|
89
|
+
# don't want to put result data (even hashed version)
|
90
|
+
# into cache without developer opt-in
|
88
91
|
def forecast
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
92
|
+
count = (@rows.size * 0.25).round.clamp(30, 365)
|
93
|
+
|
94
|
+
case Blazer.forecasting
|
95
|
+
when "prophet"
|
96
|
+
require "prophet"
|
97
|
+
forecast = Prophet.forecast(@rows.to_h, count: count)
|
98
|
+
else
|
99
|
+
require "trend"
|
100
|
+
forecast = Trend.forecast(@rows.to_h, count: count)
|
101
|
+
end
|
102
|
+
|
103
|
+
# round integers
|
104
|
+
if @rows[0][1].is_a?(Integer)
|
105
|
+
forecast = forecast.map { |k, v| [k, v.round] }.to_h
|
106
|
+
end
|
107
|
+
|
93
108
|
@rows.each do |row|
|
94
109
|
row[2] = nil
|
95
110
|
end
|
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.2.
|
4
|
+
version: 2.2.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-07-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -185,11 +185,13 @@ files:
|
|
185
185
|
- lib/blazer/adapters/drill_adapter.rb
|
186
186
|
- lib/blazer/adapters/druid_adapter.rb
|
187
187
|
- lib/blazer/adapters/elasticsearch_adapter.rb
|
188
|
+
- lib/blazer/adapters/influxdb_adapter.rb
|
188
189
|
- lib/blazer/adapters/mongodb_adapter.rb
|
189
190
|
- lib/blazer/adapters/neo4j_adapter.rb
|
190
191
|
- lib/blazer/adapters/presto_adapter.rb
|
191
192
|
- lib/blazer/adapters/salesforce_adapter.rb
|
192
193
|
- lib/blazer/adapters/snowflake_adapter.rb
|
194
|
+
- lib/blazer/adapters/soda_adapter.rb
|
193
195
|
- lib/blazer/adapters/sql_adapter.rb
|
194
196
|
- lib/blazer/data_source.rb
|
195
197
|
- lib/blazer/detect_anomalies.R
|
@@ -221,7 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
221
223
|
- !ruby/object:Gem::Version
|
222
224
|
version: '0'
|
223
225
|
requirements: []
|
224
|
-
rubygems_version: 3.
|
226
|
+
rubygems_version: 3.1.2
|
225
227
|
signing_key:
|
226
228
|
specification_version: 4
|
227
229
|
summary: Explore your data with SQL. Easily create charts and dashboards, and share
|