blazer 3.0.4 → 3.2.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -0
- data/LICENSE.txt +1 -1
- data/README.md +66 -54
- data/app/controllers/blazer/queries_controller.rb +9 -2
- data/app/views/blazer/queries/schema.html.erb +1 -1
- data/app/views/layouts/blazer/application.html.erb +1 -1
- data/lib/blazer/adapters/neo4j_adapter.rb +41 -13
- data/lib/blazer/adapters/presto_adapter.rb +2 -1
- data/lib/blazer/adapters/sql_adapter.rb +37 -15
- data/lib/blazer/adapters.rb +1 -0
- data/lib/blazer/data_source.rb +1 -1
- data/lib/blazer/engine.rb +18 -16
- data/lib/blazer/version.rb +1 -1
- metadata +6 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 26fc3acf3a9967fb5d4be9d0f8ebb76076343227a47bb9293eab6e60b4b2bcda
|
4
|
+
data.tar.gz: 468eb44da7deffd9d826188d111e6ab292739e3e7a396778b6c623f4c7d52050
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3455614272c734308c56afc122b98be8dbae766fb45b04a339b681c9ddb12ef9e2f3361d417ce9025afa189f5a8aa9307840f31a2de268f970b33fc1c3215a0d
|
7
|
+
data.tar.gz: c2db32633b784143a51e46d9e316daf5df9c0b08b000921f47d9878d1e2d372e42ce08aba99c03c4c6a226d0d3db8633abb8c4e3fa06d73e3d76907adaa889ea
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
## 3.2.0 (2025-02-23)
|
2
|
+
|
3
|
+
- Added support for Trino
|
4
|
+
- Added support for `neo4j-ruby-driver` gem
|
5
|
+
- Fixed types for SQLite
|
6
|
+
- Fixed table preview and schema page for SQLite
|
7
|
+
|
8
|
+
## 3.1.0 (2024-10-14)
|
9
|
+
|
10
|
+
- Fixed error when Propshaft is installed but not used
|
11
|
+
- Dropped support for Ruby < 3.1 and Rails < 7
|
12
|
+
|
1
13
|
## 3.0.4 (2024-09-04)
|
2
14
|
|
3
15
|
- Improved CSP support
|
@@ -441,3 +453,20 @@ There was no 1.8.1 release.
|
|
441
453
|
- Added support for Rails 4.2
|
442
454
|
- Fixed error with `mysql2` adapter
|
443
455
|
- Added `user_class` option
|
456
|
+
|
457
|
+
## 0.0.4 (2014-11-19)
|
458
|
+
|
459
|
+
- Added timeout
|
460
|
+
|
461
|
+
## 0.0.3 (2014-10-08)
|
462
|
+
|
463
|
+
- Made editor bigger
|
464
|
+
|
465
|
+
## 0.0.2 (2014-10-01)
|
466
|
+
|
467
|
+
- Added query to audits
|
468
|
+
- Added `user_name` option
|
469
|
+
|
470
|
+
## 0.0.1 (2014-09-30)
|
471
|
+
|
472
|
+
- First release
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -4,7 +4,7 @@ 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
|
-
[](https://blazer.dokkuapp.com)
|
8
8
|
|
9
9
|
Blazer is also available as a [Docker image](https://github.com/ankane/blazer-docker).
|
10
10
|
|
@@ -71,7 +71,7 @@ Be sure to set a host in `config/environments/production.rb` for emails to work.
|
|
71
71
|
config.action_mailer.default_url_options = {host: "blazer.dokkuapp.com"}
|
72
72
|
```
|
73
73
|
|
74
|
-
Schedule checks to run (with cron, [Heroku Scheduler](https://elements.heroku.com/addons/scheduler), etc). The default options are every 5 minutes, 1 hour, or 1 day, which you can customize. For each of these options, set up a task to run.
|
74
|
+
Schedule checks to run (with cron, Solid Queue, [Heroku Scheduler](https://elements.heroku.com/addons/scheduler), etc). The default options are every 5 minutes, 1 hour, or 1 day, which you can customize. For each of these options, set up a task to run.
|
75
75
|
|
76
76
|
```sh
|
77
77
|
rake blazer:run_checks SCHEDULE="5 minutes"
|
@@ -94,6 +94,24 @@ Here’s what it looks like with cron.
|
|
94
94
|
0 8 * * * rake blazer:send_failing_checks
|
95
95
|
```
|
96
96
|
|
97
|
+
For Solid Queue, update `config/recurring.yml`.
|
98
|
+
|
99
|
+
```yml
|
100
|
+
production:
|
101
|
+
blazer_run_checks_5_minutes:
|
102
|
+
command: "Blazer.run_checks(schedule: '5 minutes')"
|
103
|
+
schedule: every 5 minutes
|
104
|
+
blazer_run_checks_1_hour:
|
105
|
+
command: "Blazer.run_checks(schedule: '1 hour')"
|
106
|
+
schedule: every hour
|
107
|
+
blazer_run_checks_1_day:
|
108
|
+
command: "Blazer.run_checks(schedule: '1 day')"
|
109
|
+
schedule: every day at 7:30am
|
110
|
+
blazer_send_failing_checks:
|
111
|
+
command: "Blazer.send_failing_checks"
|
112
|
+
schedule: every day at 8am
|
113
|
+
```
|
114
|
+
|
97
115
|
For Slack notifications, create an [incoming webhook](https://slack.com/apps/A0F7XDUAZ-incoming-webhooks) and set:
|
98
116
|
|
99
117
|
```sh
|
@@ -136,7 +154,7 @@ You can define this method in your `ApplicationController`.
|
|
136
154
|
```ruby
|
137
155
|
def require_admin
|
138
156
|
# depending on your auth, something like...
|
139
|
-
redirect_to root_path unless current_user && current_user.admin?
|
157
|
+
redirect_to main_app.root_path unless current_user && current_user.admin?
|
140
158
|
end
|
141
159
|
```
|
142
160
|
|
@@ -158,7 +176,7 @@ ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO blazer;
|
|
158
176
|
COMMIT;
|
159
177
|
```
|
160
178
|
|
161
|
-
### MySQL
|
179
|
+
### MySQL and MariaDB
|
162
180
|
|
163
181
|
Create a user with read-only permissions:
|
164
182
|
|
@@ -431,24 +449,22 @@ anomaly_checks: prophet
|
|
431
449
|
|
432
450
|
### Trend
|
433
451
|
|
434
|
-
[Trend](https://trendapi.org/) uses an external service by default, but you can run it on your own infrastructure as well.
|
435
|
-
|
436
452
|
Add [trend](https://github.com/ankane/trend) to your Gemfile:
|
437
453
|
|
438
454
|
```ruby
|
439
455
|
gem "trend"
|
440
456
|
```
|
441
457
|
|
442
|
-
|
458
|
+
Set the URL to the [API](https://github.com/ankane/trend-api) in an initializer:
|
443
459
|
|
444
|
-
```
|
445
|
-
|
460
|
+
```ruby
|
461
|
+
Trend.url = "http://localhost:8000"
|
446
462
|
```
|
447
463
|
|
448
|
-
|
464
|
+
And add to `config/blazer.yml`:
|
449
465
|
|
450
|
-
```
|
451
|
-
|
466
|
+
```yml
|
467
|
+
anomaly_checks: trend
|
452
468
|
```
|
453
469
|
|
454
470
|
### AnomalyDetection.rb
|
@@ -487,24 +503,22 @@ forecasting: prophet
|
|
487
503
|
|
488
504
|
### Trend
|
489
505
|
|
490
|
-
[Trend](https://trendapi.org/) uses an external service by default, but you can run it on your own infrastructure as well.
|
491
|
-
|
492
506
|
Add [trend](https://github.com/ankane/trend) to your Gemfile:
|
493
507
|
|
494
508
|
```ruby
|
495
509
|
gem "trend"
|
496
510
|
```
|
497
511
|
|
498
|
-
|
512
|
+
Set the URL to the [API](https://github.com/ankane/trend-api) in an initializer:
|
499
513
|
|
500
|
-
```
|
501
|
-
|
514
|
+
```ruby
|
515
|
+
Trend.url = "http://localhost:8000"
|
502
516
|
```
|
503
517
|
|
504
|
-
|
518
|
+
And add to `config/blazer.yml`:
|
505
519
|
|
506
|
-
```
|
507
|
-
|
520
|
+
```yml
|
521
|
+
forecasting: trend
|
508
522
|
```
|
509
523
|
|
510
524
|
## Uploads
|
@@ -566,15 +580,15 @@ data_sources:
|
|
566
580
|
- [Google BigQuery](#google-bigquery)
|
567
581
|
- [IBM DB2 and Informix](#ibm-db2-and-informix)
|
568
582
|
- [InfluxDB](#influxdb)
|
569
|
-
- [MySQL](#mysql-1)
|
583
|
+
- [MySQL and MariaDB](#mysql-and-mariadb-1)
|
570
584
|
- [Neo4j](#neo4j)
|
571
585
|
- [OpenSearch](#opensearch)
|
572
586
|
- [Oracle](#oracle)
|
573
587
|
- [PostgreSQL](#postgresql-1)
|
574
|
-
- [Presto](#presto)
|
588
|
+
- [Presto and Trino](#presto-and-trino)
|
575
589
|
- [Salesforce](#salesforce)
|
576
|
-
- [Socrata Open Data API (SODA)](#socrata-open-data-api-soda)
|
577
590
|
- [Snowflake](#snowflake)
|
591
|
+
- [Socrata Open Data API (SODA)](#socrata-open-data-api-soda)
|
578
592
|
- [SQLite](#sqlite)
|
579
593
|
- [SQL Server](#sql-server)
|
580
594
|
|
@@ -639,11 +653,11 @@ Here’s an example IAM policy:
|
|
639
653
|
}
|
640
654
|
```
|
641
655
|
|
642
|
-
You also need to configure [S3 permissions](https://aws
|
656
|
+
You also need to configure [S3 permissions](https://repost.aws/knowledge-center/access-denied-athena).
|
643
657
|
|
644
658
|
### Amazon Redshift
|
645
659
|
|
646
|
-
Add [
|
660
|
+
Add [activerecord7-redshift-adapter-pennylane](https://github.com/pennylane-hq/activerecord-adapter-redshift) to your Gemfile and set:
|
647
661
|
|
648
662
|
```yml
|
649
663
|
data_sources:
|
@@ -706,7 +720,7 @@ Use a read-only user. Requires the [Thrift server](https://spark.apache.org/docs
|
|
706
720
|
|
707
721
|
### Cassandra
|
708
722
|
|
709
|
-
Add [cassandra-driver](https://github.com/datastax/ruby-driver)
|
723
|
+
Add [cassandra-driver](https://github.com/datastax/ruby-driver) and [sorted_set](https://github.com/knu/sorted_set) to your Gemfile and set:
|
710
724
|
|
711
725
|
```yml
|
712
726
|
data_sources:
|
@@ -718,7 +732,7 @@ Use a [read-only role](https://docs.datastax.com/en/cql-oss/3.3/cql/cql_using/us
|
|
718
732
|
|
719
733
|
### Druid
|
720
734
|
|
721
|
-
Enable [SQL support](
|
735
|
+
Enable [SQL support](https://druid.apache.org/docs/latest/querying/sql) on the broker and set:
|
722
736
|
|
723
737
|
```yml
|
724
738
|
data_sources:
|
@@ -744,7 +758,7 @@ Use a [read-only role](https://www.elastic.co/guide/en/elasticsearch/reference/c
|
|
744
758
|
|
745
759
|
### Google BigQuery
|
746
760
|
|
747
|
-
Add [google-cloud-bigquery](https://github.com/GoogleCloudPlatform/google-cloud-ruby/tree/
|
761
|
+
Add [google-cloud-bigquery](https://github.com/GoogleCloudPlatform/google-cloud-ruby/tree/main/google-cloud-bigquery) to your Gemfile and set:
|
748
762
|
|
749
763
|
```yml
|
750
764
|
data_sources:
|
@@ -779,7 +793,7 @@ data_sources:
|
|
779
793
|
|
780
794
|
Use a [read-only user](https://docs.influxdata.com/influxdb/v1.8/administration/authentication_and_authorization/). Supports [InfluxQL](https://docs.influxdata.com/influxdb/v1.8/query_language/explore-data/).
|
781
795
|
|
782
|
-
### MySQL
|
796
|
+
### MySQL and MariaDB
|
783
797
|
|
784
798
|
Add [mysql2](https://github.com/brianmario/mysql2) to your Gemfile (if it’s not there) and set:
|
785
799
|
|
@@ -789,17 +803,17 @@ data_sources:
|
|
789
803
|
url: mysql2://user:password@hostname:3306/database
|
790
804
|
```
|
791
805
|
|
792
|
-
Use a [read-only user](#mysql).
|
806
|
+
Use a [read-only user](#mysql-and-mariadb).
|
793
807
|
|
794
808
|
### Neo4j
|
795
809
|
|
796
|
-
Add [neo4j-
|
810
|
+
Add [neo4j-ruby-driver](https://github.com/neo4jrb/neo4j-ruby-driver) to your Gemfile and set:
|
797
811
|
|
798
812
|
```yml
|
799
813
|
data_sources:
|
800
814
|
my_source:
|
801
815
|
adapter: neo4j
|
802
|
-
url:
|
816
|
+
url: bolt://user:password@hostname:7687/database
|
803
817
|
```
|
804
818
|
|
805
819
|
Use a [read-only user](https://neo4j.com/docs/cypher-manual/current/access-control/manage-privileges/).
|
@@ -841,17 +855,19 @@ data_sources:
|
|
841
855
|
|
842
856
|
Use a [read-only user](#postgresql).
|
843
857
|
|
844
|
-
### Presto
|
858
|
+
### Presto and Trino
|
845
859
|
|
846
|
-
Add [presto-client](https://github.com/treasure-data/
|
860
|
+
Add [presto-client](https://github.com/treasure-data/trino-client-ruby/tree/v0.6.5) or [trino-client](https://github.com/treasure-data/trino-client-ruby) to your Gemfile and set:
|
847
861
|
|
848
862
|
```yml
|
849
863
|
data_sources:
|
850
864
|
my_source:
|
851
865
|
url: presto://user@hostname:8080/catalog
|
866
|
+
# or
|
867
|
+
url: trino://user@hostname:8080/catalog
|
852
868
|
```
|
853
869
|
|
854
|
-
Use a
|
870
|
+
Use a read-only user for [Presto](https://prestodb.io/docs/current/security/built-in-system-access-control.html) or [Trino](https://trino.io/docs/current/security/built-in-system-access-control.html).
|
855
871
|
|
856
872
|
### Salesforce
|
857
873
|
|
@@ -876,20 +892,6 @@ SALESFORCE_API_VERSION="41.0"
|
|
876
892
|
|
877
893
|
Use a read-only user. Supports [SOQL](https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql.htm).
|
878
894
|
|
879
|
-
### Socrata Open Data API (SODA)
|
880
|
-
|
881
|
-
Set:
|
882
|
-
|
883
|
-
```yml
|
884
|
-
data_sources:
|
885
|
-
my_source:
|
886
|
-
adapter: soda
|
887
|
-
url: https://soda.demo.socrata.com/resource/4tka-6guv.json
|
888
|
-
app_token: ...
|
889
|
-
```
|
890
|
-
|
891
|
-
Supports [SoQL](https://dev.socrata.com/docs/functions/).
|
892
|
-
|
893
895
|
### Snowflake
|
894
896
|
|
895
897
|
First, install ODBC. For Homebrew, use:
|
@@ -913,7 +915,7 @@ https://sfc-repo.snowflakecomputing.com/odbc/linux/2.21.5/snowflake-odbc-2.21.5.
|
|
913
915
|
|
914
916
|
> This installs the driver at `/app/.apt/usr/lib/snowflake/odbc/lib/libSnowflake.so`
|
915
917
|
|
916
|
-
Then, download the [Snowflake ODBC driver](https://docs.snowflake.
|
918
|
+
Then, download the [Snowflake ODBC driver](https://docs.snowflake.com/developer-guide/odbc/odbc-download). Add [odbc_adapter](https://github.com/localytics/odbc_adapter) to your Gemfile and set:
|
917
919
|
|
918
920
|
```yml
|
919
921
|
data_sources:
|
@@ -924,6 +926,20 @@ data_sources:
|
|
924
926
|
|
925
927
|
Use a [read-only role](https://docs.snowflake.com/en/user-guide/security-access-control-configure.html).
|
926
928
|
|
929
|
+
### Socrata Open Data API (SODA)
|
930
|
+
|
931
|
+
Set:
|
932
|
+
|
933
|
+
```yml
|
934
|
+
data_sources:
|
935
|
+
my_source:
|
936
|
+
adapter: soda
|
937
|
+
url: https://soda.demo.socrata.com/resource/4tka-6guv.json
|
938
|
+
app_token: ...
|
939
|
+
```
|
940
|
+
|
941
|
+
Supports [SoQL](https://dev.socrata.com/docs/functions/).
|
942
|
+
|
927
943
|
### SQLite
|
928
944
|
|
929
945
|
Add [sqlite3](https://github.com/sparklemotion/sqlite3-ruby) to your Gemfile and set:
|
@@ -986,10 +1002,6 @@ Have team members who want to learn SQL? Here are a few great, free resources.
|
|
986
1002
|
|
987
1003
|
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).
|
988
1004
|
|
989
|
-
## Standalone Version
|
990
|
-
|
991
|
-
Looking for a standalone version? Check out [Ghost Blazer](https://github.com/buren/ghost_blazer).
|
992
|
-
|
993
1005
|
## Performance
|
994
1006
|
|
995
1007
|
By default, queries take up a request while they are running. To run queries asynchronously, add to your config:
|
@@ -26,8 +26,15 @@ module Blazer
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def index
|
29
|
-
|
30
|
-
|
29
|
+
respond_to do |format|
|
30
|
+
format.html do
|
31
|
+
redirect_to root_path
|
32
|
+
end
|
33
|
+
format.json do
|
34
|
+
set_queries
|
35
|
+
render json: @queries
|
36
|
+
end
|
37
|
+
end
|
31
38
|
end
|
32
39
|
|
33
40
|
def new
|
@@ -13,7 +13,7 @@
|
|
13
13
|
<thead>
|
14
14
|
<tr>
|
15
15
|
<th colspan="2">
|
16
|
-
<% if table[:schema] != "public" %><%= table[:schema] %>.<% end %><%= table[:table] %>
|
16
|
+
<% if table[:schema] && table[:schema] != "public" %><%= table[:schema] %>.<% end %><%= table[:table] %>
|
17
17
|
</th>
|
18
18
|
</tr>
|
19
19
|
</thead>
|
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
<meta charset="utf-8" />
|
7
7
|
<%= favicon_link_tag "blazer/favicon.png" %>
|
8
|
-
<% if defined?(Propshaft::Railtie) %>
|
8
|
+
<% if defined?(Propshaft::Railtie) && Rails.application.assets.is_a?(Propshaft::Assembly) %>
|
9
9
|
<%= stylesheet_link_tag "blazer/bootstrap-propshaft", "blazer/bootstrap", "blazer/selectize", "blazer/github", "blazer/daterangepicker", "blazer/application" %>
|
10
10
|
<%= javascript_include_tag "blazer/jquery", "blazer/rails-ujs", "blazer/stupidtable", "blazer/stupidtable-custom-settings", "blazer/jquery.stickytableheaders", "blazer/selectize", "blazer/highlight.min", "blazer/moment", "blazer/moment-timezone-with-data", "blazer/daterangepicker", "blazer/chart.umd", "blazer/chartjs-adapter-date-fns.bundle", "blazer/chartkick", "blazer/mapkick.bundle", "blazer/ace/ace", "blazer/ace/ext-language_tools", "blazer/ace/theme-twilight", "blazer/ace/mode-sql", "blazer/ace/snippets/text", "blazer/ace/snippets/sql", "blazer/Sortable", "blazer/bootstrap", "blazer/vue.global.prod", "blazer/routes", "blazer/queries", "blazer/fuzzysearch", "blazer/application", nonce: true %>
|
11
11
|
<% else %>
|
@@ -7,14 +7,20 @@ module Blazer
|
|
7
7
|
error = nil
|
8
8
|
|
9
9
|
begin
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
if bolt?
|
11
|
+
result = session.run("#{statement} /*#{comment}*/", bind_params).to_a
|
12
|
+
columns = result.any? ? result.first.keys.map(&:to_s) : []
|
13
|
+
rows = result.map(&:values)
|
14
|
+
else
|
15
|
+
result = session.query("#{statement} /*#{comment}*/", bind_params)
|
16
|
+
columns = result.columns.map(&:to_s)
|
17
|
+
rows = []
|
18
|
+
result.each do |row|
|
19
|
+
rows << columns.map do |c|
|
20
|
+
v = row.send(c)
|
21
|
+
v = v.properties if v.respond_to?(:properties)
|
22
|
+
v
|
23
|
+
end
|
18
24
|
end
|
19
25
|
end
|
20
26
|
rescue => e
|
@@ -26,8 +32,13 @@ module Blazer
|
|
26
32
|
end
|
27
33
|
|
28
34
|
def tables
|
29
|
-
|
30
|
-
|
35
|
+
if bolt?
|
36
|
+
result = session.run("CALL db.labels()").to_a
|
37
|
+
result.map { |r| r.values.first }
|
38
|
+
else
|
39
|
+
result = session.query("CALL db.labels()")
|
40
|
+
result.rows.map(&:first)
|
41
|
+
end
|
31
42
|
end
|
32
43
|
|
33
44
|
def preview_statement
|
@@ -52,10 +63,27 @@ module Blazer
|
|
52
63
|
|
53
64
|
def session
|
54
65
|
@session ||= begin
|
55
|
-
|
56
|
-
|
57
|
-
|
66
|
+
if bolt?
|
67
|
+
uri = URI.parse(settings["url"])
|
68
|
+
auth = Neo4j::Driver::AuthTokens.basic(uri.user, uri.password)
|
69
|
+
database = uri.path.delete_prefix("/")
|
70
|
+
uri.user = nil
|
71
|
+
uri.password = nil
|
72
|
+
uri.path = ""
|
73
|
+
Neo4j::Driver::GraphDatabase.driver(uri, auth).session(database: database)
|
74
|
+
else
|
75
|
+
require "neo4j/core/cypher_session/adaptors/http"
|
76
|
+
http_adaptor = Neo4j::Core::CypherSession::Adaptors::HTTP.new(settings["url"])
|
77
|
+
Neo4j::Core::CypherSession.new(http_adaptor)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def bolt?
|
83
|
+
if !defined?(@bolt)
|
84
|
+
@bolt = settings["url"].start_with?("bolt")
|
58
85
|
end
|
86
|
+
@bolt
|
59
87
|
end
|
60
88
|
end
|
61
89
|
end
|
@@ -40,7 +40,8 @@ module Blazer
|
|
40
40
|
@client ||= begin
|
41
41
|
uri = URI.parse(settings["url"])
|
42
42
|
query = uri.query ? CGI.parse(uri.query) : {}
|
43
|
-
Presto::Client
|
43
|
+
cls = uri.scheme == "trino" ? Trino::Client : Presto::Client
|
44
|
+
cls.new(
|
44
45
|
server: "#{uri.host}:#{uri.port}",
|
45
46
|
catalog: uri.path.to_s.delete_prefix("/"),
|
46
47
|
schema: query["schema"] || "public",
|
@@ -21,19 +21,30 @@ module Blazer
|
|
21
21
|
error = nil
|
22
22
|
|
23
23
|
begin
|
24
|
-
|
25
|
-
in_transaction do
|
24
|
+
types = []
|
25
|
+
in_transaction do |connection|
|
26
26
|
set_timeout(data_source.timeout) if data_source.timeout
|
27
27
|
binds = bind_params.map { |v| ActiveRecord::Relation::QueryAttribute.new(nil, v, ActiveRecord::Type::Value.new) }
|
28
|
-
|
28
|
+
if sqlite?
|
29
|
+
type_map = connection.send(:type_map)
|
30
|
+
connection.raw_connection.prepare("#{statement} /*#{comment}*/") do |stmt|
|
31
|
+
stmt.bind_params(connection.send(:type_casted_binds, binds))
|
32
|
+
columns = stmt.columns
|
33
|
+
rows = stmt.to_a
|
34
|
+
types = stmt.types.map { |t| type_map.lookup(t) }
|
35
|
+
end
|
36
|
+
else
|
37
|
+
result = connection.select_all("#{statement} /*#{comment}*/", nil, binds)
|
38
|
+
columns = result.columns
|
39
|
+
rows = result.rows
|
40
|
+
if result.column_types.any?
|
41
|
+
types = columns.size.times.map { |i| result.column_types[i] }
|
42
|
+
end
|
43
|
+
end
|
29
44
|
end
|
30
45
|
|
31
|
-
columns = result.columns
|
32
|
-
rows = result.rows
|
33
|
-
|
34
46
|
# cast values
|
35
|
-
if
|
36
|
-
types = columns.map { |c| result.column_types[c] }
|
47
|
+
if types.any?
|
37
48
|
rows =
|
38
49
|
rows.map do |row|
|
39
50
|
row.map.with_index do |v, i|
|
@@ -60,7 +71,12 @@ module Blazer
|
|
60
71
|
end
|
61
72
|
|
62
73
|
def tables
|
63
|
-
sql =
|
74
|
+
sql =
|
75
|
+
if sqlite?
|
76
|
+
"SELECT NULL, name FROM sqlite_master WHERE type IN ('table', 'view') ORDER BY name"
|
77
|
+
else
|
78
|
+
add_schemas("SELECT table_schema, table_name FROM information_schema.tables")
|
79
|
+
end
|
64
80
|
result = data_source.run_statement(sql, refresh_cache: true)
|
65
81
|
if postgresql? || redshift? || snowflake?
|
66
82
|
result.rows.sort_by { |r| [r[0] == default_schema ? "" : r[0], r[1]] }.map do |row|
|
@@ -84,7 +100,12 @@ module Blazer
|
|
84
100
|
end
|
85
101
|
|
86
102
|
def schema
|
87
|
-
sql =
|
103
|
+
sql =
|
104
|
+
if sqlite?
|
105
|
+
"SELECT NULL, t.name, c.name, c.type, c.cid FROM sqlite_master t INNER JOIN pragma_table_info(t.name) c WHERE t.type IN ('table', 'view')"
|
106
|
+
else
|
107
|
+
add_schemas("SELECT table_schema, table_name, column_name, data_type, ordinal_position FROM information_schema.columns")
|
108
|
+
end
|
88
109
|
result = data_source.run_statement(sql)
|
89
110
|
result.rows.group_by { |r| [r[0], r[1]] }.map { |k, vs| {schema: k[0], table: k[1], columns: vs.sort_by { |v| v[2] }.map { |v| {name: v[2], data_type: v[3]} }} }.sort_by { |t| [t[:schema] == default_schema ? "" : t[:schema], t[:table]] }
|
90
111
|
end
|
@@ -274,6 +295,8 @@ module Blazer
|
|
274
295
|
"public"
|
275
296
|
elsif sqlserver?
|
276
297
|
"dbo"
|
298
|
+
elsif sqlite?
|
299
|
+
nil
|
277
300
|
elsif connection_model.respond_to?(:connection_db_config)
|
278
301
|
connection_model.connection_db_config.database
|
279
302
|
else
|
@@ -302,8 +325,7 @@ module Blazer
|
|
302
325
|
if postgresql? || redshift?
|
303
326
|
execute("SET #{use_transaction? ? "LOCAL " : ""}statement_timeout = #{timeout.to_i * 1000}")
|
304
327
|
elsif mysql?
|
305
|
-
|
306
|
-
mariadb = connection_model.connection.send(:mariadb?) rescue false
|
328
|
+
mariadb = connection_model.connection.mariadb? rescue false
|
307
329
|
if mariadb
|
308
330
|
execute("SET max_statement_time = #{timeout.to_i * 1000}")
|
309
331
|
else
|
@@ -319,14 +341,14 @@ module Blazer
|
|
319
341
|
end
|
320
342
|
|
321
343
|
def in_transaction
|
322
|
-
connection_model.connection_pool.with_connection do
|
344
|
+
connection_model.connection_pool.with_connection do |connection|
|
323
345
|
if use_transaction?
|
324
346
|
connection_model.transaction do
|
325
|
-
yield
|
347
|
+
yield connection
|
326
348
|
raise ActiveRecord::Rollback
|
327
349
|
end
|
328
350
|
else
|
329
|
-
yield
|
351
|
+
yield connection
|
330
352
|
end
|
331
353
|
end
|
332
354
|
end
|
data/lib/blazer/adapters.rb
CHANGED
@@ -15,3 +15,4 @@ Blazer.register_adapter "soda", Blazer::Adapters::SodaAdapter
|
|
15
15
|
Blazer.register_adapter "spark", Blazer::Adapters::SparkAdapter
|
16
16
|
Blazer.register_adapter "sql", Blazer::Adapters::SqlAdapter
|
17
17
|
Blazer.register_adapter "snowflake", Blazer::Adapters::SnowflakeAdapter
|
18
|
+
Blazer.register_adapter "trino", Blazer::Adapters::PrestoAdapter
|
data/lib/blazer/data_source.rb
CHANGED
data/lib/blazer/engine.rb
CHANGED
@@ -3,22 +3,24 @@ module Blazer
|
|
3
3
|
isolate_namespace Blazer
|
4
4
|
|
5
5
|
initializer "blazer" do |app|
|
6
|
-
if
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
6
|
+
if app.config.respond_to?(:assets) && defined?(Sprockets)
|
7
|
+
if Sprockets::VERSION.to_i >= 4
|
8
|
+
app.config.assets.precompile += [
|
9
|
+
"blazer/application.js",
|
10
|
+
"blazer/application.css",
|
11
|
+
"blazer/glyphicons-halflings-regular.eot",
|
12
|
+
"blazer/glyphicons-halflings-regular.svg",
|
13
|
+
"blazer/glyphicons-halflings-regular.ttf",
|
14
|
+
"blazer/glyphicons-halflings-regular.woff",
|
15
|
+
"blazer/glyphicons-halflings-regular.woff2",
|
16
|
+
"blazer/favicon.png"
|
17
|
+
]
|
18
|
+
else
|
19
|
+
# use a proc instead of a string
|
20
|
+
app.config.assets.precompile << proc { |path| path =~ /\Ablazer\/application\.(js|css)\z/ }
|
21
|
+
app.config.assets.precompile << proc { |path| path =~ /\Ablazer\/.+\.(eot|svg|ttf|woff|woff2)\z/ }
|
22
|
+
app.config.assets.precompile << proc { |path| path == "blazer/favicon.png" }
|
23
|
+
end
|
22
24
|
end
|
23
25
|
|
24
26
|
Blazer.time_zone ||= Blazer.settings["time_zone"] || Time.zone
|
data/lib/blazer/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blazer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-02-23 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: railties
|
@@ -16,14 +15,14 @@ dependencies:
|
|
16
15
|
requirements:
|
17
16
|
- - ">="
|
18
17
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
18
|
+
version: '7'
|
20
19
|
type: :runtime
|
21
20
|
prerelease: false
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
23
22
|
requirements:
|
24
23
|
- - ">="
|
25
24
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
25
|
+
version: '7'
|
27
26
|
- !ruby/object:Gem::Dependency
|
28
27
|
name: activerecord
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,7 +79,6 @@ dependencies:
|
|
80
79
|
- - ">="
|
81
80
|
- !ruby/object:Gem::Version
|
82
81
|
version: '0'
|
83
|
-
description:
|
84
82
|
email: andrew@ankane.org
|
85
83
|
executables: []
|
86
84
|
extensions: []
|
@@ -236,7 +234,6 @@ homepage: https://github.com/ankane/blazer
|
|
236
234
|
licenses:
|
237
235
|
- MIT
|
238
236
|
metadata: {}
|
239
|
-
post_install_message:
|
240
237
|
rdoc_options: []
|
241
238
|
require_paths:
|
242
239
|
- lib
|
@@ -244,15 +241,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
244
241
|
requirements:
|
245
242
|
- - ">="
|
246
243
|
- !ruby/object:Gem::Version
|
247
|
-
version: '3'
|
244
|
+
version: '3.1'
|
248
245
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
249
246
|
requirements:
|
250
247
|
- - ">="
|
251
248
|
- !ruby/object:Gem::Version
|
252
249
|
version: '0'
|
253
250
|
requirements: []
|
254
|
-
rubygems_version: 3.
|
255
|
-
signing_key:
|
251
|
+
rubygems_version: 3.6.2
|
256
252
|
specification_version: 4
|
257
253
|
summary: Explore your data with SQL. Easily create charts and dashboards, and share
|
258
254
|
them with your team.
|