pgdexter 0.3.8 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3940bf892014f2337cc5cd95c85b66f245b3725ad7ce84397c4eb4f9e3751c3c
4
- data.tar.gz: b8fc834cda0161c8ef0b44853c14f5f608c00f373e6a95481321e45611d2d5b4
3
+ metadata.gz: 62ad383008579d8dbe952b3f96c827e01aa198c0eb74b3b884188472459b34b8
4
+ data.tar.gz: b77596742f0e13bb058354edcd901d1e93ec94f61bf6a695957c51fe9c7e41dc
5
5
  SHA512:
6
- metadata.gz: 463430e69b2a1f08ca411db0a4938c7243839e78f81db72455d508ff1e9de1a752889bff8a3e42486cf4859042065b0847f0b6c0216c80c9b9a36a10cf360753
7
- data.tar.gz: d31949fc719e863aa56672fd807141dfbeb521d2ce2525ca551109e09840115c3091e7130cc47617a6b836ff31853dbf12a1bb9fb4dea492b17cbf7c9bfd5c8e
6
+ metadata.gz: 1b5f18ce901729f9e22d4222b0ba7ee498be18edb7897221c28069f8beceb65058342c47e9211ce94814d04b380387b95506722b1568a1d44b4d3c8386beeb17
7
+ data.tar.gz: fa51ae2cde49dfcf9fc181a30bda4941c2ea01f1186fdd6a8cd002059a71c4b3341686cd62f2d1366874c941b92db1a4f74a6abd272baa66063907602e1376c5
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## 0.4.0 (2022-07-27)
2
+
3
+ - Added support for pg_query 2
4
+ - Switched to monotonic time
5
+ - Dropped support for Ruby < 2.5
6
+
7
+ ## 0.3.10 (2021-03-25)
8
+
9
+ - Require pg_query < 2
10
+
11
+ ## 0.3.9 (2020-11-23)
12
+
13
+ - Added `--tablespace` option
14
+
1
15
  ## 0.3.8 (2020-08-17)
2
16
 
3
17
  - Colorize output
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2017-2020 Andrew Kane
1
+ Copyright (c) 2017-2021 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)
6
6
 
7
- [![Build Status](https://travis-ci.org/ankane/dexter.svg?branch=master)](https://travis-ci.org/ankane/dexter)
7
+ [![Build Status](https://github.com/ankane/dexter/workflows/build/badge.svg?branch=master)](https://github.com/ankane/dexter/actions)
8
8
 
9
9
  ## Installation
10
10
 
@@ -12,8 +12,8 @@ First, install [HypoPG](https://github.com/HypoPG/hypopg) on your database serve
12
12
 
13
13
  ```sh
14
14
  cd /tmp
15
- curl -L https://github.com/HypoPG/hypopg/archive/1.1.4.tar.gz | tar xz
16
- cd hypopg-1.1.4
15
+ curl -L https://github.com/HypoPG/hypopg/archive/1.3.1.tar.gz | tar xz
16
+ cd hypopg-1.3.1
17
17
  make
18
18
  make install # may need sudo
19
19
  ```
@@ -32,7 +32,7 @@ And install the command line tool with:
32
32
  gem install pgdexter
33
33
  ```
34
34
 
35
- The command line tool is also available as a [Linux package](guides/Linux.md).
35
+ The command line tool is also available with [Docker](#docker), [Homebrew](#homebrew), or as a [Linux package](guides/Linux.md).
36
36
 
37
37
  ## How to Use
38
38
 
@@ -190,7 +190,37 @@ dexter --log-sql --log-level debug2
190
190
 
191
191
  ## Hosted Postgres
192
192
 
193
- Some hosted providers like Amazon RDS and Heroku do not support the HypoPG extension, which Dexter needs to run. See [how to use Dexter](guides/Hosted-Postgres.md) in these cases.
193
+ Some hosted providers like Amazon RDS and Heroku do not support the HypoPG extension, which Dexter needs to run. See [how to use Dexter](guides/Hosted-Postgres.md) in these cases. To request the extension:
194
+
195
+ - Amazon RDS - follow the instructions on [this page](https://aws.amazon.com/rds/postgresql/faqs/)
196
+ - Google Cloud SQL - star the [feature request](https://issuetracker.google.com/issues/69250435)
197
+ - DigitalOcean Managed Databases - follow the instructions on [this page](https://docs.digitalocean.com/products/databases/postgresql/details/supported-extensions/#supported-extensions)
198
+
199
+ ## Additional Installation Methods
200
+
201
+ ### Docker
202
+
203
+ Get the [Docker image](https://hub.docker.com/r/ankane/dexter) with:
204
+
205
+ ```sh
206
+ docker pull ankane/dexter
207
+ ```
208
+
209
+ And run it with:
210
+
211
+ ```sh
212
+ docker run -ti ankane/dexter <connection-options>
213
+ ```
214
+
215
+ On Mac and Windows, use `host.docker.internal` as the database hostname for databases on your local machine.
216
+
217
+ ### Homebrew
218
+
219
+ With Homebrew, you can use:
220
+
221
+ ```sh
222
+ brew install ankane/brew/dexter
223
+ ```
194
224
 
195
225
  ## Future Work
196
226
 
@@ -213,7 +243,7 @@ gem specific_install https://github.com/ankane/dexter.git
213
243
 
214
244
  ## Thanks
215
245
 
216
- This software wouldn’t be possible without [HypoPG](https://github.com/dalibo/hypopg), which allows you to create hypothetical indexes, and [pg_query](https://github.com/lfittl/pg_query), which allows you to parse and fingerprint queries. A big thanks to Dalibo and Lukas Fittl respectively.
246
+ This software wouldn’t be possible without [HypoPG](https://github.com/HypoPG/hypopg), which allows you to create hypothetical indexes, and [pg_query](https://github.com/lfittl/pg_query), which allows you to parse and fingerprint queries. A big thanks to Dalibo and Lukas Fittl respectively.
217
247
 
218
248
  ## Research
219
249
 
data/lib/dexter/client.rb CHANGED
@@ -56,6 +56,7 @@ module Dexter
56
56
  o.boolean "--pg-stat-activity", "use pg_stat_activity", default: false, help: false
57
57
  o.boolean "--pg-stat-statements", "use pg_stat_statements", default: false, help: false
58
58
  o.string "-s", "--statement", "process a single statement"
59
+ o.string "--tablespace", "tablespace to create indexes"
59
60
  o.on "-v", "--version", "print the version" do
60
61
  log Dexter::VERSION
61
62
  exit
@@ -4,6 +4,7 @@ module Dexter
4
4
 
5
5
  def initialize(options)
6
6
  @create = options[:create]
7
+ @tablespace = options[:tablespace]
7
8
  @log_level = options[:log_level]
8
9
  @exclude_tables = options[:exclude]
9
10
  @include_tables = Array(options[:include].split(",")) if options[:include]
@@ -239,6 +240,7 @@ module Dexter
239
240
  end
240
241
 
241
242
  def find_columns(plan)
243
+ plan = JSON.parse(plan.to_json)
242
244
  find_by_key(plan, "ColumnRef")
243
245
  end
244
246
 
@@ -247,20 +249,24 @@ module Dexter
247
249
  end
248
250
 
249
251
  def find_by_key(plan, key)
250
- indexes = []
251
- case plan
252
- when Hash
253
- plan.each do |k, v|
254
- if k == key
255
- indexes << v
256
- else
257
- indexes.concat(find_by_key(v, key))
252
+ result = []
253
+ queue = [plan]
254
+ while queue.any?
255
+ node = queue.pop
256
+ case node
257
+ when Hash
258
+ node.each do |k, v|
259
+ if k == key
260
+ result << v
261
+ elsif !v.nil?
262
+ queue << v
263
+ end
258
264
  end
265
+ when Array
266
+ queue.concat(node)
259
267
  end
260
- when Array
261
- indexes.concat(plan.flat_map { |v| find_by_key(v, key) })
262
268
  end
263
- indexes
269
+ result
264
270
  end
265
271
 
266
272
  def hypo_indexes_from_plan(index_name_to_columns, plan, index_set)
@@ -479,12 +485,13 @@ module Dexter
479
485
  with_advisory_lock do
480
486
  new_indexes.each do |index|
481
487
  unless index_exists?(index)
482
- statement = "CREATE INDEX CONCURRENTLY ON #{quote_ident(index[:table])} (#{index[:columns].map { |c| quote_ident(c) }.join(", ")})"
488
+ statement = String.new("CREATE INDEX CONCURRENTLY ON #{quote_ident(index[:table])} (#{index[:columns].map { |c| quote_ident(c) }.join(", ")})")
489
+ statement << " TABLESPACE #{quote_ident(@tablespace)}" if @tablespace
483
490
  log "Creating index: #{statement}"
484
- started_at = Time.now
491
+ started_at = monotonic_time
485
492
  begin
486
493
  execute(statement)
487
- log "Index created: #{((Time.now - started_at) * 1000).to_i} ms"
494
+ log "Index created: #{((monotonic_time - started_at) * 1000).to_i} ms"
488
495
  rescue PG::LockNotAvailable
489
496
  log "Could not acquire lock: #{index[:table]}"
490
497
  end
@@ -496,6 +503,10 @@ module Dexter
496
503
  new_indexes
497
504
  end
498
505
 
506
+ def monotonic_time
507
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
508
+ end
509
+
499
510
  def conn
500
511
  @conn ||= begin
501
512
  # set connect timeout if none set
@@ -62,7 +62,7 @@ module Dexter
62
62
  end
63
63
 
64
64
  def process_queries_without_lock
65
- now = Time.now
65
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
66
66
  min_checked_at = now - 3600 # don't recheck for an hour
67
67
  queries = []
68
68
  @collector.fetch_queries.each do |query|
@@ -1,3 +1,3 @@
1
1
  module Dexter
2
- VERSION = "0.3.8"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/dexter.rb CHANGED
@@ -4,6 +4,7 @@ require "pg_query"
4
4
  require "slop"
5
5
 
6
6
  # stdlib
7
+ require "json"
7
8
  require "set"
8
9
  require "time"
9
10
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pgdexter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.8
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-17 00:00:00.000000000 Z
11
+ date: 2022-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: slop
@@ -44,58 +44,16 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '2.1'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: bundler
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: rake
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: minitest
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- description:
98
- email: andrew@chartkick.com
54
+ version: '2.1'
55
+ description:
56
+ email: andrew@ankane.org
99
57
  executables:
100
58
  - dexter
101
59
  extensions: []
@@ -121,7 +79,7 @@ homepage: https://github.com/ankane/dexter
121
79
  licenses:
122
80
  - MIT
123
81
  metadata: {}
124
- post_install_message:
82
+ post_install_message:
125
83
  rdoc_options: []
126
84
  require_paths:
127
85
  - lib
@@ -129,15 +87,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
129
87
  requirements:
130
88
  - - ">="
131
89
  - !ruby/object:Gem::Version
132
- version: '2.2'
90
+ version: '2.5'
133
91
  required_rubygems_version: !ruby/object:Gem::Requirement
134
92
  requirements:
135
93
  - - ">="
136
94
  - !ruby/object:Gem::Version
137
95
  version: '0'
138
96
  requirements: []
139
- rubygems_version: 3.1.2
140
- signing_key:
97
+ rubygems_version: 3.3.7
98
+ signing_key:
141
99
  specification_version: 4
142
100
  summary: The automatic indexer for Postgres
143
101
  test_files: []