pgsync 0.6.4 → 0.6.8

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: 0ecb467f4d3112edfcfebe19913e29daeddfe1e4cc10e18bd9e8850fbceced57
4
- data.tar.gz: 4d8309dec9e8238074267baf583fe333c7b1d3300ad80398748e15905eb1e539
3
+ metadata.gz: 07f27052ca6f110b7b6ace2ad5b56399876ee1e3905dd0fc21f6c7d459ec84ca
4
+ data.tar.gz: 897b2b49d184ba7adf4610c4bb3bd779102982ee0f42d1592fb7b4f5bcf1a5fd
5
5
  SHA512:
6
- metadata.gz: 145eb31e2565257a5adedc05c1308692dffb1e0785728ecd38230bb23c34c4ba6ecf08512201f707f457b136e0b7a22ca511b46fb7834f2045c041ff43dd6ccc
7
- data.tar.gz: cde51dee36149f9f8c21e26eecd504de68d8a47c2524f084b74962d7ceae1a01b59841261fc6c112cf94b31a89f55b9a991c05d1af0db41c46ed615fc56e888f
6
+ metadata.gz: ae0a54b59689868a51a212436d064ac59431cd5fe86606031f7f20797fd2e66effac1d2387a2531700b7bc62a6909d2dc1091700fccebbf6631972e901d46166
7
+ data.tar.gz: 847b20e665fa5184975177c193dc0bf74b1c368008db663d69ba526602508c7d18cae61330487e892e8b0faf799966e74c8f5c2d7ffc1a23067bffb3b61f0b45
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## 0.6.8 (2021-09-21)
2
+
3
+ - Fixed error when schema missing in destination with `--schema-first` and `--schema-only`
4
+
5
+ ## 0.6.7 (2021-04-26)
6
+
7
+ - Fixed connection security for `--schema-first` and `--schema-only` - [more info](https://github.com/ankane/pgsync/issues/121)
8
+
9
+ ## 0.6.6 (2020-10-29)
10
+
11
+ - Added support for tables with generated columns
12
+
13
+ ## 0.6.5 (2020-07-10)
14
+
15
+ - Improved help
16
+
1
17
  ## 0.6.4 (2020-06-10)
2
18
 
3
19
  - Log SQL with `--debug` option
data/README.md CHANGED
@@ -9,7 +9,7 @@ Sync data from one Postgres database to another (like `pg_dump`/`pg_restore`). D
9
9
 
10
10
  :tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
11
11
 
12
- [![Build Status](https://travis-ci.org/ankane/pgsync.svg?branch=master)](https://travis-ci.org/ankane/pgsync)
12
+ [![Build Status](https://github.com/ankane/pgsync/workflows/build/badge.svg?branch=master)](https://github.com/ankane/pgsync/actions)
13
13
 
14
14
  ## Installation
15
15
 
@@ -390,6 +390,10 @@ Also check out:
390
390
 
391
391
  Inspired by [heroku-pg-transfer](https://github.com/ddollar/heroku-pg-transfer).
392
392
 
393
+ ## History
394
+
395
+ View the [changelog](https://github.com/ankane/pgsync/blob/master/CHANGELOG.md)
396
+
393
397
  ## Contributing
394
398
 
395
399
  Everyone is encouraged to help improve this project. Here are a few ways you can help:
data/lib/pgsync/client.rb CHANGED
@@ -39,42 +39,74 @@ module PgSync
39
39
  def slop_options
40
40
  o = Slop::Options.new
41
41
  o.banner = %{Usage:
42
- pgsync [options]
42
+ pgsync [tables,groups] [sql] [options]}
43
43
 
44
- Options:}
45
- o.string "-d", "--db", "database"
46
- o.string "-t", "--tables", "tables to sync"
47
- o.string "-g", "--groups", "groups to sync"
48
- o.integer "-j", "--jobs", "number of tables to sync at a time"
44
+ # not shown
45
+ o.string "-t", "--tables", "tables to sync", help: false
46
+ o.string "-g", "--groups", "groups to sync", help: false
47
+
48
+ o.separator ""
49
+ o.separator "Table options:"
50
+ o.string "--exclude", "tables to exclude"
49
51
  o.string "--schemas", "schemas to sync"
50
- o.string "--from", "source"
51
- o.string "--to", "destination"
52
- o.string "--exclude", "exclude tables"
53
- o.string "--config", "config file"
54
- o.boolean "--to-safe", "accept danger", default: false
55
- o.boolean "--debug", "debug", default: false
56
- o.boolean "--list", "list", default: false
57
- o.boolean "--overwrite", "overwrite existing rows", default: false, help: false
52
+ o.boolean "--all-schemas", "sync all schemas", default: false
53
+
54
+ o.separator ""
55
+ o.separator "Row options:"
56
+ o.boolean "--overwrite", "overwrite existing rows", default: false
58
57
  o.boolean "--preserve", "preserve existing rows", default: false
59
58
  o.boolean "--truncate", "truncate existing rows", default: false
60
- o.boolean "--schema-first", "schema first", default: false
61
- o.boolean "--schema-only", "schema only", default: false
62
- o.boolean "--all-schemas", "all schemas", default: false
63
- o.boolean "--no-rules", "do not apply data rules", default: false
64
- o.boolean "--no-sequences", "do not sync sequences", default: false
65
- o.boolean "--init", "init", default: false
66
- o.boolean "--in-batches", "in batches", default: false, help: false
67
- o.integer "--batch-size", "batch size", default: 10000, help: false
68
- o.float "--sleep", "sleep", default: 0, help: false
69
- o.boolean "--fail-fast", "stop on the first failed table", default: false
70
- o.boolean "--defer-constraints", "defer constraints", default: false, help: false
59
+
60
+ o.separator ""
61
+ o.separator "Foreign key options:"
71
62
  o.boolean "--defer-constraints-v2", "defer constraints", default: false
72
- o.boolean "--disable-user-triggers", "disable non-system triggers", default: false
73
63
  o.boolean "--disable-integrity", "disable foreign key triggers", default: false
64
+ o.integer "-j", "--jobs", "number of tables to sync at a time"
65
+
66
+ # replaced by v2
67
+ o.boolean "--defer-constraints", "defer constraints", default: false, help: false
74
68
  # private, for testing
75
69
  o.boolean "--disable-integrity-v2", "disable foreign key triggers", default: false, help: false
76
- o.boolean "-v", "--version", "print the version"
77
- o.boolean "-h", "--help", "prints help"
70
+
71
+ o.separator ""
72
+ o.separator "Schema options:"
73
+ o.boolean "--schema-first", "sync schema first", default: false
74
+ o.boolean "--schema-only", "sync schema only", default: false
75
+
76
+ o.separator ""
77
+ o.separator "Config options:"
78
+ # technically, defaults to searching path for .pgsync.yml, but this is simpler
79
+ o.string "--config", "config file (defaults to .pgsync.yml)"
80
+ o.string "-d", "--db", "database-specific config file"
81
+
82
+ o.separator ""
83
+ o.separator "Connection options:"
84
+ o.string "--from", "source database URL"
85
+ o.string "--to", "destination database URL"
86
+ o.boolean "--to-safe", "confirms destination is safe (when not localhost)", default: false
87
+
88
+ o.separator ""
89
+ o.separator "Other options:"
90
+ o.boolean "--debug", "show SQL statements", default: false
91
+ o.boolean "--disable-user-triggers", "disable non-system triggers", default: false
92
+ o.boolean "--fail-fast", "stop on the first failed table", default: false
93
+ o.boolean "--no-rules", "don't apply data rules", default: false
94
+ o.boolean "--no-sequences", "don't sync sequences", default: false
95
+
96
+ # not shown in help
97
+ # o.separator ""
98
+ # o.separator "Append-only table options:"
99
+ o.boolean "--in-batches", "sync in batches", default: false, help: false
100
+ o.integer "--batch-size", "batch size", default: 10000, help: false
101
+ o.float "--sleep", "time to sleep between batches", default: 0, help: false
102
+
103
+ o.separator ""
104
+ o.separator "Other commands:"
105
+ o.boolean "--init", "create config file", default: false
106
+ o.boolean "--list", "list tables", default: false
107
+ o.boolean "-h", "--help", "print help"
108
+ o.boolean "-v", "--version", "print version"
109
+
78
110
  o
79
111
  end
80
112
  end
@@ -68,6 +68,23 @@ module PgSync
68
68
  execute("TRUNCATE #{quote_ident_full(table)} CASCADE")
69
69
  end
70
70
 
71
+ def schemas
72
+ @schemas ||= begin
73
+ query = <<~SQL
74
+ SELECT
75
+ schema_name
76
+ FROM
77
+ information_schema.schemata
78
+ ORDER BY 1
79
+ SQL
80
+ execute(query).map { |row| row["schema_name"] }
81
+ end
82
+ end
83
+
84
+ def create_schema(schema)
85
+ execute("CREATE SCHEMA #{quote_ident(schema)}")
86
+ end
87
+
71
88
  def triggers(table)
72
89
  query = <<~SQL
73
90
  SELECT
@@ -24,10 +24,12 @@ module PgSync
24
24
  spinner.auto_spin
25
25
  end
26
26
 
27
+ create_schemas if specify_tables?
28
+
27
29
  # if spinner, capture lines to show on error
28
30
  lines = []
29
31
  success =
30
- run_command("#{dump_command} | #{restore_command}") do |line|
32
+ run_command do |line|
31
33
  if show_spinner
32
34
  lines << line
33
35
  else
@@ -49,12 +51,14 @@ module PgSync
49
51
 
50
52
  private
51
53
 
52
- def run_command(command)
53
- Open3.popen2e(command) do |stdin, stdout, wait_thr|
54
- stdout.each do |line|
54
+ def run_command
55
+ err_r, err_w = IO.pipe
56
+ Open3.pipeline_start(dump_command, restore_command, err: err_w) do |wait_thrs|
57
+ err_w.close
58
+ err_r.each do |line|
55
59
  yield line
56
60
  end
57
- wait_thr.value.success?
61
+ wait_thrs.all? { |t| t.value.success? }
58
62
  end
59
63
  end
60
64
 
@@ -65,19 +69,32 @@ module PgSync
65
69
  end
66
70
 
67
71
  def dump_command
68
- tables =
69
- if !opts[:all_schemas] || opts[:tables] || opts[:groups] || args[0] || opts[:exclude] || opts[:schemas]
70
- @tasks.map { |task| "-t #{Shellwords.escape(task.quoted_table)}" }
71
- else
72
- []
72
+ cmd = ["pg_dump", "-Fc", "--verbose", "--schema-only", "--no-owner", "--no-acl"]
73
+ if specify_tables?
74
+ @tasks.each do |task|
75
+ cmd.concat(["-t", task.quoted_table])
73
76
  end
74
-
75
- "pg_dump -Fc --verbose --schema-only --no-owner --no-acl #{tables.join(" ")} -d #{@source.url}"
77
+ end
78
+ cmd.concat(["-d", @source.url])
76
79
  end
77
80
 
78
81
  def restore_command
79
- if_exists = Gem::Version.new(pg_restore_version) >= Gem::Version.new("9.4.0")
80
- "pg_restore --verbose --no-owner --no-acl --clean #{if_exists ? "--if-exists" : nil} -d #{@destination.url}"
82
+ cmd = ["pg_restore", "--verbose", "--no-owner", "--no-acl", "--clean"]
83
+ cmd << "--if-exists" if Gem::Version.new(pg_restore_version) >= Gem::Version.new("9.4.0")
84
+ cmd.concat(["-d", @destination.url])
85
+ end
86
+
87
+ # pg_dump -t won't create schemas (even with -n)
88
+ # not ideal that this happens outside restore transaction
89
+ def create_schemas
90
+ schemas = @tasks.map { |t| t.table.schema }.uniq - @destination.schemas
91
+ schemas.sort.each do |schema|
92
+ @destination.create_schema(schema)
93
+ end
94
+ end
95
+
96
+ def specify_tables?
97
+ !opts[:all_schemas] || opts[:tables] || opts[:groups] || args[0] || opts[:exclude] || opts[:schemas]
81
98
  end
82
99
  end
83
100
  end
@@ -141,6 +141,8 @@ module PgSync
141
141
  data_type AS type
142
142
  FROM
143
143
  information_schema.columns
144
+ WHERE
145
+ is_generated = 'NEVER'
144
146
  ORDER BY 1, 2, 3
145
147
  SQL
146
148
  data_source.execute(query).group_by { |r| Table.new(r["schema"], r["table"]) }.map do |k, v|
data/lib/pgsync/task.rb CHANGED
@@ -140,9 +140,13 @@ module PgSync
140
140
  "NOTHING"
141
141
  else # overwrite or sql clause
142
142
  setter = shared_fields.reject { |f| primary_key.include?(f) }.map { |f| "#{quote_ident(f)} = EXCLUDED.#{quote_ident(f)}" }
143
- "UPDATE SET #{setter.join(", ")}"
143
+ if setter.any?
144
+ "UPDATE SET #{setter.join(", ")}"
145
+ else
146
+ "NOTHING"
147
+ end
144
148
  end
145
- destination.execute("INSERT INTO #{quoted_table} (SELECT * FROM #{quote_ident_full(temp_table)}) ON CONFLICT (#{on_conflict}) DO #{action}")
149
+ destination.execute("INSERT INTO #{quoted_table} (#{fields}) (SELECT #{fields} FROM #{quote_ident_full(temp_table)}) ON CONFLICT (#{on_conflict}) DO #{action}")
146
150
  else
147
151
  # use delete instead of truncate for foreign keys
148
152
  if opts[:defer_constraints] || opts[:defer_constraints_v2]
@@ -1,3 +1,3 @@
1
1
  module PgSync
2
- VERSION = "0.6.4"
2
+ VERSION = "0.6.8"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pgsync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.4
4
+ version: 0.6.8
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-06-11 00:00:00.000000000 Z
11
+ date: 2021-09-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parallel
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 4.8.1
47
+ version: 4.8.2
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: 4.8.1
54
+ version: 4.8.2
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: tty-spinner
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,49 +66,7 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: bundler
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
- - !ruby/object:Gem::Dependency
98
- name: rake
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- description:
69
+ description:
112
70
  email: andrew@chartkick.com
113
71
  executables:
114
72
  - pgsync
@@ -137,7 +95,7 @@ homepage: https://github.com/ankane/pgsync
137
95
  licenses:
138
96
  - MIT
139
97
  metadata: {}
140
- post_install_message:
98
+ post_install_message:
141
99
  rdoc_options: []
142
100
  require_paths:
143
101
  - lib
@@ -152,8 +110,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
152
110
  - !ruby/object:Gem::Version
153
111
  version: '0'
154
112
  requirements: []
155
- rubygems_version: 3.1.2
156
- signing_key:
113
+ rubygems_version: 3.2.22
114
+ signing_key:
157
115
  specification_version: 4
158
116
  summary: Sync Postgres data between databases
159
117
  test_files: []