blazer 2.4.2 → 2.6.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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +46 -0
  3. data/README.md +147 -51
  4. data/app/assets/javascripts/blazer/Chart.js +14000 -13979
  5. data/app/assets/javascripts/blazer/bootstrap.js +300 -97
  6. data/app/assets/javascripts/blazer/vue.js +10754 -9687
  7. data/app/assets/stylesheets/blazer/application.css +5 -0
  8. data/app/assets/stylesheets/blazer/bootstrap-propshaft.css +10 -0
  9. data/app/assets/stylesheets/blazer/bootstrap-sprockets.css.erb +10 -0
  10. data/app/assets/stylesheets/blazer/{bootstrap.css.erb → bootstrap.css} +527 -455
  11. data/app/controllers/blazer/base_controller.rb +45 -45
  12. data/app/controllers/blazer/dashboards_controller.rb +4 -11
  13. data/app/controllers/blazer/queries_controller.rb +30 -49
  14. data/app/models/blazer/query.rb +9 -3
  15. data/app/views/blazer/_variables.html.erb +5 -4
  16. data/app/views/blazer/dashboards/_form.html.erb +1 -1
  17. data/app/views/blazer/dashboards/show.html.erb +4 -4
  18. data/app/views/blazer/queries/_caching.html.erb +1 -1
  19. data/app/views/blazer/queries/_form.html.erb +3 -3
  20. data/app/views/blazer/queries/run.html.erb +5 -3
  21. data/app/views/blazer/queries/show.html.erb +12 -7
  22. data/app/views/layouts/blazer/application.html.erb +7 -2
  23. data/lib/blazer/adapters/athena_adapter.rb +72 -20
  24. data/lib/blazer/adapters/base_adapter.rb +16 -1
  25. data/lib/blazer/adapters/bigquery_adapter.rb +14 -3
  26. data/lib/blazer/adapters/cassandra_adapter.rb +15 -4
  27. data/lib/blazer/adapters/drill_adapter.rb +10 -0
  28. data/lib/blazer/adapters/druid_adapter.rb +36 -1
  29. data/lib/blazer/adapters/elasticsearch_adapter.rb +19 -4
  30. data/lib/blazer/adapters/hive_adapter.rb +10 -0
  31. data/lib/blazer/adapters/ignite_adapter.rb +12 -2
  32. data/lib/blazer/adapters/influxdb_adapter.rb +22 -10
  33. data/lib/blazer/adapters/mongodb_adapter.rb +4 -0
  34. data/lib/blazer/adapters/neo4j_adapter.rb +17 -2
  35. data/lib/blazer/adapters/opensearch_adapter.rb +52 -0
  36. data/lib/blazer/adapters/presto_adapter.rb +9 -0
  37. data/lib/blazer/adapters/salesforce_adapter.rb +5 -0
  38. data/lib/blazer/adapters/snowflake_adapter.rb +9 -0
  39. data/lib/blazer/adapters/soda_adapter.rb +9 -0
  40. data/lib/blazer/adapters/spark_adapter.rb +5 -0
  41. data/lib/blazer/adapters/sql_adapter.rb +34 -4
  42. data/{app/mailers → lib}/blazer/check_mailer.rb +0 -0
  43. data/lib/blazer/data_source.rb +90 -8
  44. data/lib/blazer/engine.rb +1 -4
  45. data/lib/blazer/result.rb +17 -1
  46. data/lib/blazer/run_statement.rb +7 -3
  47. data/lib/blazer/run_statement_job.rb +4 -2
  48. data/{app/mailers → lib}/blazer/slack_notifier.rb +19 -4
  49. data/lib/blazer/statement.rb +75 -0
  50. data/lib/blazer/version.rb +1 -1
  51. data/lib/blazer.rb +32 -8
  52. data/lib/generators/blazer/templates/config.yml.tt +2 -2
  53. data/lib/tasks/blazer.rake +5 -5
  54. data/licenses/LICENSE-bootstrap.txt +1 -1
  55. metadata +10 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c8356dddcf7221e7bbf93eb4cc4d1e1b7804f08c29dd57006517d0e157f1ff4
4
- data.tar.gz: 7ac1354b00daa9905901a6c11c6e8a948962e2c6830feeaa19d065bfa1bde9a6
3
+ metadata.gz: 8bdfc1e428f7e01bf9a06461a5f0143a6e940cd1e3d708ba2bd504132bbaa1db
4
+ data.tar.gz: 729e9a408e7f4fa5203ab4c133800e49087fccf634efcf7c9dd6ca80a610a861
5
5
  SHA512:
6
- metadata.gz: 5959df81b7c5dbe0b608bfe565f1d98d2a7119a6309bbf934d86d1154227cd6315051ec131c9e8a8d9641022468c42724152620b4a226ee8300791d1095df858
7
- data.tar.gz: 694140d5e5fe1904f16ccbcd95f9e18b8fcd54e7630d0df05637ddc977ab223220cb749798c8d365d77f962b131a91135bcfa9c12dc4d849f3d4caea1a642f79
6
+ metadata.gz: e6c7a7be80246c1030170a5df95656947b2431cf908bb6d37d668cbe3f57006ef096d63186976c63c683f0e2511873cabb5d2be56e389de331487666ba297dc3
7
+ data.tar.gz: 9feb70216244f77d37357376cd68b9ec85a6d3eeb3c89f3e58196688e81618ca2ae38372e5491e0811bdd7d9e0082317a711040f5782cc54f5d9f99ec57d624a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,49 @@
1
+ ## 2.6.0 (2022-04-20)
2
+
3
+ - Fixed quoting issue with variables
4
+ - Custom adapters now need to specify how to quote variables in queries
5
+ - Added experimental support for Propshaft
6
+ - Fixed error with empty results with InfluxDB
7
+
8
+ ## 2.5.0 (2022-01-04)
9
+
10
+ - Added support for Slack OAuth tokens
11
+ - Added experimental support for AnomalyDetection.rb
12
+ - Improved table preview for MySQL
13
+ - Fixed cohort analysis for MySQL
14
+
15
+ ## 2.4.8 (2021-12-07)
16
+
17
+ - Added support for OpenSearch
18
+ - Removed `elasticsearch-xpack` dependency for Elasticsearch
19
+
20
+ ## 2.4.7 (2021-09-25)
21
+
22
+ - Made Action Mailer optional
23
+ - Fixed error with multiple maps on dashboard
24
+
25
+ ## 2.4.6 (2021-09-20)
26
+
27
+ - Added support for workgroup with Amazon Athena
28
+ - Added casting for timestamp with time zone columns with Amazon Athena
29
+ - Added support for setting credentials in config file with Amazon Athena
30
+ - Made output location optional with Amazon Athena
31
+ - Fixed casting error for `NULL` values with Amazon Athena
32
+ - Fixed issue with Google BigQuery only showing first page of results
33
+
34
+ ## 2.4.5 (2021-09-15)
35
+
36
+ - Improved fix for some forked queries not appearing on home page
37
+
38
+ ## 2.4.4 (2021-09-15)
39
+
40
+ - Fixed issue with some forked queries not appearing on home page
41
+
42
+ ## 2.4.3 (2021-07-27)
43
+
44
+ - Added Prophet anomaly detection
45
+ - Fixed style for new select items
46
+
1
47
  ## 2.4.2 (2021-02-08)
2
48
 
3
49
  - Added support for Apache Ignite
data/README.md CHANGED
@@ -10,6 +10,8 @@ Blazer is also available as a [Docker image](https://github.com/ankane/blazer-do
10
10
 
11
11
  :tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
12
12
 
13
+ [![Build Status](https://github.com/ankane/blazer/workflows/build/badge.svg?branch=master)](https://github.com/ankane/blazer/actions)
14
+
13
15
  ## Features
14
16
 
15
17
  - **Multiple data sources** - PostgreSQL, MySQL, Redshift, and [many more](#full-list)
@@ -37,7 +39,7 @@ Blazer is also available as a [Docker image](https://github.com/ankane/blazer-do
37
39
  Add this line to your application’s Gemfile:
38
40
 
39
41
  ```ruby
40
- gem 'blazer'
42
+ gem "blazer"
41
43
  ```
42
44
 
43
45
  Run:
@@ -59,7 +61,7 @@ For production, specify your database:
59
61
  ENV["BLAZER_DATABASE_URL"] = "postgres://user:password@hostname:5432/database"
60
62
  ```
61
63
 
62
- Blazer tries to protect against queries which modify data (by running each query in a transaction and rolling it back), but a safer approach is to use a read-only user. [See how to create one](#permissions).
64
+ When possible, Blazer tries to protect against queries which modify data by running each query in a transaction and rolling it back, but a safer approach is to use a read-only user. [See how to create one](#permissions).
63
65
 
64
66
  #### Checks (optional)
65
67
 
@@ -142,11 +144,9 @@ Be sure to render or redirect for unauthorized users.
142
144
 
143
145
  ## Permissions
144
146
 
145
- Blazer runs each query in a transaction and rolls it back to prevent queries from modifying data. As an additional line of defense, we recommend using a read only user.
146
-
147
147
  ### PostgreSQL
148
148
 
149
- Create a user with read only permissions:
149
+ Create a user with read-only permissions:
150
150
 
151
151
  ```sql
152
152
  BEGIN;
@@ -160,7 +160,7 @@ COMMIT;
160
160
 
161
161
  ### MySQL
162
162
 
163
- Create a user with read only permissions:
163
+ Create a user with read-only permissions:
164
164
 
165
165
  ```sql
166
166
  GRANT SELECT, SHOW VIEW ON database_name.* TO blazer@’127.0.0.1′ IDENTIFIED BY ‘secret123‘;
@@ -169,7 +169,7 @@ FLUSH PRIVILEGES;
169
169
 
170
170
  ### MongoDB
171
171
 
172
- Create a user with read only permissions:
172
+ Create a user with read-only permissions:
173
173
 
174
174
  ```
175
175
  db.createUser({user: "blazer", pwd: "password", roles: ["read"]})
@@ -412,74 +412,62 @@ SELECT users.id AS user_id, orders.created_at AS conversion_time, users.created_
412
412
  FROM users LEFT JOIN orders ON orders.user_id = users.id
413
413
  ```
414
414
 
415
- This feature requires PostgreSQL or MySQL.
415
+ This feature requires PostgreSQL or MySQL 8.
416
416
 
417
417
  ## Anomaly Detection
418
418
 
419
- Blazer supports two different approaches to anomaly detection.
419
+ Blazer supports three different approaches to anomaly detection.
420
420
 
421
- ### Trend
421
+ ### Prophet
422
422
 
423
- [Trend](https://trendapi.org/) is easiest to set up. By default, it uses an external service, but you can run it on your own infrastructure as well.
424
-
425
- Add [trend](https://github.com/ankane/trend) to your Gemfile:
423
+ Add [prophet-rb](https://github.com/ankane/prophet) to your Gemfile:
426
424
 
427
425
  ```ruby
428
- gem 'trend'
426
+ gem "prophet-rb"
429
427
  ```
430
428
 
431
429
  And add to `config/blazer.yml`:
432
430
 
433
431
  ```yml
434
- anomaly_checks: trend
432
+ anomaly_checks: prophet
435
433
  ```
436
434
 
437
- For the [self-hosted API](https://github.com/ankane/trend-api), create an initializer with:
438
-
439
- ```ruby
440
- Trend.url = "http://localhost:8000"
441
- ```
442
-
443
- ### R
435
+ ### Trend
444
436
 
445
- R is harder to set up but doesn’t use an external service. It uses Twitter’s [AnomalyDetection](https://github.com/twitter/AnomalyDetection) library.
437
+ [Trend](https://trendapi.org/) uses an external service by default, but you can run it on your own infrastructure as well.
446
438
 
447
- First, [install R](https://cloud.r-project.org/). Then, run:
439
+ Add [trend](https://github.com/ankane/trend) to your Gemfile:
448
440
 
449
- ```R
450
- install.packages("remotes")
451
- remotes::install_github("twitter/AnomalyDetection")
441
+ ```ruby
442
+ gem "trend"
452
443
  ```
453
444
 
454
445
  And add to `config/blazer.yml`:
455
446
 
456
447
  ```yml
457
- anomaly_checks: r
448
+ anomaly_checks: trend
458
449
  ```
459
450
 
460
- If upgrading from version 1.4 or below, also follow the [upgrade instructions](#15).
451
+ For the [self-hosted API](https://github.com/ankane/trend-api), create an initializer with:
461
452
 
462
- If you’re on Heroku, follow the additional instructions below.
453
+ ```ruby
454
+ Trend.url = "http://localhost:8000"
455
+ ```
463
456
 
464
- ### R on Heroku
457
+ ### AnomalyDetection.rb (experimental)
465
458
 
466
- Add the [R buildpack](https://github.com/virtualstaticvoid/heroku-buildpack-r) to your app.
459
+ Add [anomaly_detection](https://github.com/ankane/AnomalyDetection.rb) to your Gemfile:
467
460
 
468
- ```sh
469
- heroku buildpacks:add --index 1 https://github.com/virtualstaticvoid/heroku-buildpack-r.git
461
+ ```ruby
462
+ gem "anomaly_detection"
470
463
  ```
471
464
 
472
- And create an `init.R` with:
465
+ And add to `config/blazer.yml`:
473
466
 
474
- ```r
475
- if (!"AnomalyDetection" %in% installed.packages()) {
476
- install.packages("remotes")
477
- remotes::install_github("twitter/AnomalyDetection")
478
- }
467
+ ```yml
468
+ anomaly_checks: anomaly_detection
479
469
  ```
480
470
 
481
- Commit and deploy away. The first deploy may take a few minutes.
482
-
483
471
  ## Forecasting
484
472
 
485
473
  Blazer supports for two different forecasting methods. [Example](https://blazer.dokkuapp.com/queries/18-forecast?forecast=t)
@@ -488,10 +476,10 @@ A forecast link will appear for queries that return 2 columns with types timesta
488
476
 
489
477
  ### Prophet
490
478
 
491
- Add [prophet](https://github.com/ankane/prophet) to your Gemfile:
479
+ Add [prophet-rb](https://github.com/ankane/prophet) to your Gemfile:
492
480
 
493
481
  ```ruby
494
- gem 'prophet-rb', '>= 0.2.1'
482
+ gem "prophet-rb", ">= 0.2.1"
495
483
  ```
496
484
 
497
485
  And add to `config/blazer.yml`:
@@ -502,12 +490,12 @@ forecasting: prophet
502
490
 
503
491
  ### Trend
504
492
 
505
- [Trend](https://trendapi.org/) uses an external service.
493
+ [Trend](https://trendapi.org/) uses an external service by default, but you can run it on your own infrastructure as well.
506
494
 
507
495
  Add [trend](https://github.com/ankane/trend) to your Gemfile:
508
496
 
509
497
  ```ruby
510
- gem 'trend'
498
+ gem "trend"
511
499
  ```
512
500
 
513
501
  And add to `config/blazer.yml`:
@@ -516,6 +504,12 @@ And add to `config/blazer.yml`:
516
504
  forecasting: trend
517
505
  ```
518
506
 
507
+ For the [self-hosted API](https://github.com/ankane/trend-api), create an initializer with:
508
+
509
+ ```ruby
510
+ Trend.url = "http://localhost:8000"
511
+ ```
512
+
519
513
  ## Uploads
520
514
 
521
515
  Creating database tables from CSV files. [Example](https://blazer.dokkuapp.com/uploads)
@@ -567,7 +561,7 @@ data_sources:
567
561
  - [Amazon Redshift](#amazon-redshift)
568
562
  - [Apache Drill](#apache-drill)
569
563
  - [Apache Hive](#apache-hive)
570
- - [Apache Ignite](#apache-ignite) [master]
564
+ - [Apache Ignite](#apache-ignite)
571
565
  - [Apache Spark](#apache-spark)
572
566
  - [Cassandra](#cassandra)
573
567
  - [Druid](#druid)
@@ -578,6 +572,7 @@ data_sources:
578
572
  - [MongoDB](#mongodb-1)
579
573
  - [MySQL](#mysql-1)
580
574
  - [Neo4j](#neo4j)
575
+ - [OpenSearch](#opensearch)
581
576
  - [Oracle](#oracle)
582
577
  - [PostgreSQL](#postgresql-1)
583
578
  - [Presto](#presto)
@@ -606,9 +601,49 @@ data_sources:
606
601
  my_source:
607
602
  adapter: athena
608
603
  database: database
604
+
605
+ # optional settings
609
606
  output_location: s3://some-bucket/
607
+ workgroup: primary
608
+ access_key_id: ...
609
+ secret_access_key: ...
610
+ ```
611
+
612
+ Here’s an example IAM policy:
613
+
614
+ ```json
615
+ {
616
+ "Version": "2012-10-17",
617
+ "Statement": [
618
+ {
619
+ "Effect": "Allow",
620
+ "Action": [
621
+ "athena:GetQueryExecution",
622
+ "athena:GetQueryResults",
623
+ "athena:StartQueryExecution"
624
+ ],
625
+ "Resource": [
626
+ "arn:aws:athena:region:account-id:workgroup/primary"
627
+ ]
628
+ },
629
+ {
630
+ "Effect": "Allow",
631
+ "Action": [
632
+ "glue:GetTable",
633
+ "glue:GetTables"
634
+ ],
635
+ "Resource": [
636
+ "arn:aws:glue:region:account-id:catalog",
637
+ "arn:aws:glue:region:account-id:database/default",
638
+ "arn:aws:glue:region:account-id:table/default/*"
639
+ ]
640
+ }
641
+ ]
642
+ }
610
643
  ```
611
644
 
645
+ You also need to configure [S3 permissions](https://aws.amazon.com/premiumsupport/knowledge-center/access-denied-athena/).
646
+
612
647
  ### Amazon Redshift
613
648
 
614
649
  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:
@@ -619,6 +654,8 @@ data_sources:
619
654
  url: redshift://user:password@hostname:5439/database
620
655
  ```
621
656
 
657
+ Use a [read-only user](https://docs.aws.amazon.com/redshift/latest/dg/r_GRANT.html).
658
+
622
659
  ### Apache Drill
623
660
 
624
661
  Add [drill-sergeant](https://github.com/ankane/drill-sergeant) to your Gemfile and set:
@@ -630,6 +667,8 @@ data_sources:
630
667
  url: http://hostname:8047
631
668
  ```
632
669
 
670
+ Use a [read-only user](https://drill.apache.org/docs/roles-and-privileges/).
671
+
633
672
  ### Apache Hive
634
673
 
635
674
  Add [hexspace](https://github.com/ankane/hexspace) to your Gemfile and set:
@@ -653,6 +692,8 @@ data_sources:
653
692
  url: ignite://user:password@hostname:10800
654
693
  ```
655
694
 
695
+ Use a [read-only user](https://www.gridgain.com/docs/latest/administrators-guide/security/authorization-permissions) (requires a third-party plugin).
696
+
656
697
  ### Apache Spark
657
698
 
658
699
  Add [hexspace](https://github.com/ankane/hexspace) to your Gemfile and set:
@@ -676,6 +717,8 @@ data_sources:
676
717
  url: cassandra://user:password@hostname:9042/keyspace
677
718
  ```
678
719
 
720
+ Use a [read-only role](https://docs.datastax.com/en/cql-oss/3.3/cql/cql_using/useSecurePermission.html).
721
+
679
722
  ### Druid
680
723
 
681
724
  Enable [SQL support](http://druid.io/docs/latest/querying/sql.html#configuration) on the broker and set:
@@ -687,9 +730,11 @@ data_sources:
687
730
  url: http://hostname:8082
688
731
  ```
689
732
 
733
+ Use a [read-only role](https://druid.apache.org/docs/latest/development/extensions-core/druid-basic-security.html).
734
+
690
735
  ### Elasticsearch
691
736
 
692
- Add [elasticsearch](https://github.com/elastic/elasticsearch-ruby) and [elasticsearch-xpack](https://github.com/elastic/elasticsearch-ruby/tree/master/elasticsearch-xpack) to your Gemfile and set:
737
+ Add [elasticsearch](https://github.com/elastic/elasticsearch-ruby) to your Gemfile and set:
693
738
 
694
739
  ```yml
695
740
  data_sources:
@@ -698,6 +743,8 @@ data_sources:
698
743
  url: http://user:password@hostname:9200
699
744
  ```
700
745
 
746
+ Use a [read-only role](https://www.elastic.co/guide/en/elasticsearch/reference/current/security-privileges.html).
747
+
701
748
  ### Google BigQuery
702
749
 
703
750
  Add [google-cloud-bigquery](https://github.com/GoogleCloudPlatform/google-cloud-ruby/tree/master/google-cloud-bigquery) to your Gemfile and set:
@@ -720,6 +767,8 @@ data_sources:
720
767
  url: ibm-db://user:password@hostname:50000/database
721
768
  ```
722
769
 
770
+ Use a [read-only user](https://www.ibm.com/support/pages/creating-read-only-database-permissions-user).
771
+
723
772
  ### InfluxDB
724
773
 
725
774
  Add [influxdb](https://github.com/influxdata/influxdb-ruby) to your Gemfile and set:
@@ -731,10 +780,12 @@ data_sources:
731
780
  url: http://user:password@hostname:8086/database
732
781
  ```
733
782
 
734
- Supports [InfluxQL](https://docs.influxdata.com/influxdb/v1.8/query_language/explore-data/)
783
+ 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/).
735
784
 
736
785
  ### MongoDB
737
786
 
787
+ *Requires MongoDB < 4.2 at the moment*
788
+
738
789
  Add [mongo](https://github.com/mongodb/mongo-ruby-driver) to your Gemfile and set:
739
790
 
740
791
  ```yml
@@ -743,6 +794,8 @@ data_sources:
743
794
  url: mongodb://user:password@hostname:27017/database
744
795
  ```
745
796
 
797
+ Use a [read-only user](#mongodb).
798
+
746
799
  ### MySQL
747
800
 
748
801
  Add [mysql2](https://github.com/brianmario/mysql2) to your Gemfile (if it’s not there) and set:
@@ -753,6 +806,8 @@ data_sources:
753
806
  url: mysql2://user:password@hostname:3306/database
754
807
  ```
755
808
 
809
+ Use a [read-only user](#mysql).
810
+
756
811
  ### Neo4j
757
812
 
758
813
  Add [neo4j-core](https://github.com/neo4jrb/neo4j-core) to your Gemfile and set:
@@ -764,6 +819,21 @@ data_sources:
764
819
  url: http://user:password@hostname:7474
765
820
  ```
766
821
 
822
+ Use a [read-only user](https://neo4j.com/docs/cypher-manual/current/access-control/manage-privileges/).
823
+
824
+ ### OpenSearch
825
+
826
+ Add [opensearch-ruby](https://github.com/opensearch-project/opensearch-ruby) to your Gemfile and set:
827
+
828
+ ```yml
829
+ data_sources:
830
+ my_source:
831
+ adapter: opensearch
832
+ url: http://user:password@hostname:9200
833
+ ```
834
+
835
+ Use a [read-only user](https://opensearch.org/docs/latest/security-plugin/access-control/permissions/).
836
+
767
837
  ### Oracle
768
838
 
769
839
  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:
@@ -774,6 +844,8 @@ data_sources:
774
844
  url: oracle-enhanced://user:password@hostname:1521/database
775
845
  ```
776
846
 
847
+ Use a [read-only user](https://docs.oracle.com/cd/B19306_01/network.102/b14266/authoriz.htm).
848
+
777
849
  ### PostgreSQL
778
850
 
779
851
  Add [pg](https://github.com/ged/ruby-pg) to your Gemfile (if it’s not there) and set:
@@ -784,6 +856,8 @@ data_sources:
784
856
  url: postgres://user:password@hostname:5432/database
785
857
  ```
786
858
 
859
+ Use a [read-only user](#postgresql).
860
+
787
861
  ### Presto
788
862
 
789
863
  Add [presto-client](https://github.com/treasure-data/presto-client-ruby) to your Gemfile and set:
@@ -794,6 +868,8 @@ data_sources:
794
868
  url: presto://user@hostname:8080/catalog
795
869
  ```
796
870
 
871
+ Use a [read-only user](https://prestodb.io/docs/current/security/built-in-system-access-control.html).
872
+
797
873
  ### Salesforce
798
874
 
799
875
  Add [restforce](https://github.com/restforce/restforce) to your Gemfile and set:
@@ -815,7 +891,7 @@ SALESFORCE_CLIENT_SECRET="client secret"
815
891
  SALESFORCE_API_VERSION="41.0"
816
892
  ```
817
893
 
818
- Supports [SOQL](https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql.htm)
894
+ 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).
819
895
 
820
896
  ### Socrata Open Data API (SODA)
821
897
 
@@ -829,7 +905,7 @@ data_sources:
829
905
  app_token: ...
830
906
  ```
831
907
 
832
- Supports [SoQL](https://dev.socrata.com/docs/functions/)
908
+ Supports [SoQL](https://dev.socrata.com/docs/functions/).
833
909
 
834
910
  ### Snowflake
835
911
 
@@ -863,6 +939,8 @@ data_sources:
863
939
  conn_str: Driver=/path/to/libSnowflake.so;uid=user;pwd=password;server=host.snowflakecomputing.com
864
940
  ```
865
941
 
942
+ Use a [read-only role](https://docs.snowflake.com/en/user-guide/security-access-control-configure.html).
943
+
866
944
  ### SQLite
867
945
 
868
946
  Add [sqlite3](https://github.com/sparklemotion/sqlite3-ruby) to your Gemfile and set:
@@ -883,6 +961,8 @@ data_sources:
883
961
  url: sqlserver://user:password@hostname:1433/database
884
962
  ```
885
963
 
964
+ Use a [read-only user](https://docs.microsoft.com/en-us/sql/relational-databases/security/authentication-access/getting-started-with-database-engine-permissions?view=sql-server-ver15).
965
+
886
966
  ## Creating an Adapter
887
967
 
888
968
  Create an adapter for any data store with:
@@ -959,6 +1039,22 @@ override_csp: true
959
1039
 
960
1040
  ## Upgrading
961
1041
 
1042
+ ### 2.6
1043
+
1044
+ Custom adapters now need to specify how to quote variables in queries (there is no longer a default)
1045
+
1046
+ ```ruby
1047
+ class FooAdapter < Blazer::Adapters::BaseAdapter
1048
+ def quoting
1049
+ :backslash_escape # single quote strings and convert ' to \' and \ to \\
1050
+ # or
1051
+ :single_quote_escape # single quote strings and convert ' to ''
1052
+ # or
1053
+ ->(value) { ... } # custom method
1054
+ end
1055
+ end
1056
+ ```
1057
+
962
1058
  ### 2.3
963
1059
 
964
1060
  To archive queries, create a migration