pgdexter 0.5.1 → 0.5.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c68746f6134f6603c5549b561886b45ee3432df5d1e07e65a5907559901d333a
4
- data.tar.gz: 699c2744f3e2c9a79f8fa9ca6ae7a77586421243cbf7a1f92642f76724cc0cb0
3
+ metadata.gz: e51edc18f4049b9ca811e4662248aa7a23e748b000975a87fa4a431f49ec632b
4
+ data.tar.gz: f3aa243431e0aab1d84d4cbc48ee6a329581acedc7a9c70e2a13e7bb0e15b529
5
5
  SHA512:
6
- metadata.gz: 343bc52539ef09541fd0774667034ea02fb88b0e4f820e52c86d77df46d059c253576c22272b91a407b764965f66c554278154da6ab923249ce9979ab3a5aed0
7
- data.tar.gz: a9b86931b4fc58d2b89c87f46f5008dfd47274cc39f096ec2b5143bea8858e29a786e387f9ccc29fe74475b5b0317e9d348d36f2a686cb19457ee79179a270f5
6
+ metadata.gz: 67b04a3c336c3bec239490a386825153699c646a01f5fe30d84b42445695f2431b1545bace72c5b955e03e92ad531810b5a73971d559abb06f175a1965454b89
7
+ data.tar.gz: 63691b01566b54056201c2d0a5c73a8153252b7c2ce4619983feb3b20e58d49d4a738b210be61d46231d3b5c78c1787664c625c0eb0216ee0d9ba19dcc8a7621
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 0.5.2 (2024-01-10)
2
+
3
+ - Added Docker image for `linux/arm64`
4
+ - Switched to `GENERIC_PLAN` for Postgres 16
5
+ - Fixed error with `auto_explain`
6
+ - Fixed warning with Ruby 3.3
7
+
1
8
  ## 0.5.1 (2023-05-27)
2
9
 
3
10
  - Fixed `JSON::NestingError`
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2017-2023 Andrew Kane
1
+ Copyright (c) 2017-2024 Andrew Kane
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -4,7 +4,7 @@ The automatic indexer for Postgres
4
4
 
5
5
  [Read about how it works](https://ankane.org/introducing-dexter) or [watch the talk](https://www.youtube.com/watch?v=Mni_1yTaNbE)
6
6
 
7
- [![Build Status](https://github.com/ankane/dexter/workflows/build/badge.svg?branch=master)](https://github.com/ankane/dexter/actions)
7
+ [![Build Status](https://github.com/ankane/dexter/actions/workflows/build.yml/badge.svg)](https://github.com/ankane/dexter/actions)
8
8
 
9
9
  ## Installation
10
10
 
@@ -185,7 +185,7 @@ module Dexter
185
185
 
186
186
  # get initial costs for queries
187
187
  calculate_plan(queries)
188
- explainable_queries = queries.select { |q| q.explainable? && q.high_cost? }
188
+ explainable_queries = queries.select { |q| q.plans.any? && q.high_cost? }
189
189
 
190
190
  # filter tables for performance
191
191
  tables = Set.new(explainable_queries.flat_map(&:tables))
@@ -521,8 +521,8 @@ module Dexter
521
521
  raise Dexter::Abort, e.message
522
522
  end
523
523
 
524
- def execute(query, pretty: true, params: [])
525
- # use exec_params instead of exec for security
524
+ def execute(query, pretty: true, params: [], use_exec: false)
525
+ # use exec_params instead of exec when possible for security
526
526
  #
527
527
  # Unlike PQexec, PQexecParams allows at most one SQL command in the given string.
528
528
  # (There can be semicolons in it, but not more than one nonempty command.)
@@ -533,7 +533,11 @@ module Dexter
533
533
  log colorize("[sql] #{query}#{params.any? ? " /*#{params.to_json}*/" : ""}", :cyan) if @log_sql
534
534
 
535
535
  @mutex.synchronize do
536
- conn.exec_params("#{query} /*dexter*/", params).to_a
536
+ if use_exec
537
+ conn.exec("#{query} /*dexter*/").to_a
538
+ else
539
+ conn.exec_params("#{query} /*dexter*/", params).to_a
540
+ end
537
541
  end
538
542
  end
539
543
 
@@ -543,7 +547,9 @@ module Dexter
543
547
 
544
548
  # try to EXPLAIN normalized queries
545
549
  # https://dev.to/yugabyte/explain-from-pgstatstatements-normalized-queries-how-to-always-get-the-generic-plan-in--5cfi
546
- explain_normalized = query.include?("$1")
550
+ normalized = query.include?("$1")
551
+ generic_plan = normalized && server_version_num >= 160000
552
+ explain_normalized = normalized && !generic_plan
547
553
  if explain_normalized
548
554
  prepared_name = "dexter_prepared"
549
555
  execute("PREPARE #{prepared_name} AS #{safe_statement(query)}", pretty: false)
@@ -566,12 +572,14 @@ module Dexter
566
572
  end
567
573
  end
568
574
 
575
+ explain_prefix = generic_plan ? "GENERIC_PLAN, " : ""
576
+
569
577
  # strip semi-colons as another measure of defense
570
- plan = JSON.parse(execute("EXPLAIN (FORMAT JSON) #{safe_statement(query)}", pretty: false).first["QUERY PLAN"], max_nesting: 1000).first["Plan"]
578
+ plan = JSON.parse(execute("EXPLAIN (#{explain_prefix}FORMAT JSON) #{safe_statement(query)}", pretty: false, use_exec: generic_plan).first["QUERY PLAN"], max_nesting: 1000).first["Plan"]
571
579
 
572
580
  if @log_explain
573
581
  # Pass format to prevent ANALYZE
574
- puts execute("EXPLAIN (FORMAT TEXT) #{safe_statement(query)}", pretty: false).map { |r| r["QUERY PLAN"] }.join("\n")
582
+ puts execute("EXPLAIN (#{explain_prefix}FORMAT TEXT) #{safe_statement(query)}", pretty: false, use_exec: generic_plan).map { |r| r["QUERY PLAN"] }.join("\n")
575
583
  end
576
584
 
577
585
  plan
data/lib/dexter/query.rb CHANGED
@@ -31,7 +31,7 @@ module Dexter
31
31
  end
32
32
 
33
33
  def explainable?
34
- plans.any?
34
+ plans.size >= 3
35
35
  end
36
36
 
37
37
  def costs
@@ -1,3 +1,3 @@
1
1
  module Dexter
2
- VERSION = "0.5.1"
2
+ VERSION = "0.5.2"
3
3
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pgdexter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-27 00:00:00.000000000 Z
11
+ date: 2024-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: csv
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: pg
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -96,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
110
  - !ruby/object:Gem::Version
97
111
  version: '0'
98
112
  requirements: []
99
- rubygems_version: 3.4.10
113
+ rubygems_version: 3.5.3
100
114
  signing_key:
101
115
  specification_version: 4
102
116
  summary: The automatic indexer for Postgres