pgsync 0.5.2 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of pgsync might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +37 -0
- data/LICENSE.txt +1 -1
- data/README.md +121 -38
- data/config.yml +4 -0
- data/exe/pgsync +0 -4
- data/lib/pgsync.rb +5 -1
- data/lib/pgsync/client.rb +54 -52
- data/lib/pgsync/data_source.rb +78 -80
- data/lib/pgsync/init.rb +48 -10
- data/lib/pgsync/schema_sync.rb +83 -0
- data/lib/pgsync/sync.rb +98 -175
- data/lib/pgsync/table.rb +28 -0
- data/lib/pgsync/table_sync.rb +167 -219
- data/lib/pgsync/task.rb +315 -0
- data/lib/pgsync/task_resolver.rb +235 -0
- data/lib/pgsync/utils.rb +64 -24
- data/lib/pgsync/version.rb +1 -1
- metadata +8 -5
- data/lib/pgsync/table_list.rb +0 -143
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c4a582f7fd5b997ba91247f2b57ad68aae7b5fad282c32dca873d75667922af
|
4
|
+
data.tar.gz: a7ae6518b84d28c8ad14786793b8d4257d898214b8071ccc6c91e9d4d144e316
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f008b6d7114e3f11395479de0e85006c5eb48681b13ab613e1468d20a99acf0121566fe5499e236d1e8b07fdd12acc2c3a99399daac3e3e99269efac5e6bd4e5
|
7
|
+
data.tar.gz: 536af357b17f35c7afb0e8efba5411a0ecbec67adbfe364d465a8831dd0e56d108055b1ccb55bc0203d92d9a3215a11d3a287f52e89b40b6526534ddfbc8371e
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,40 @@
|
|
1
|
+
## 0.6.1 (2020-06-07)
|
2
|
+
|
3
|
+
- Added Django and Laravel integrations
|
4
|
+
|
5
|
+
## 0.6.0 (2020-06-07)
|
6
|
+
|
7
|
+
- Added messages for different column types and non-deferrable constraints
|
8
|
+
- Added support for wildcards to `--exclude`
|
9
|
+
- Improved `--overwrite` and `--preserve` options for foreign keys
|
10
|
+
- Improved output for schema sync
|
11
|
+
- Fixed `--overwrite` and `--preserve` options for multicolumn primary keys
|
12
|
+
- Fixed output for notices
|
13
|
+
|
14
|
+
Breaking
|
15
|
+
|
16
|
+
- Syncs shared tables instead of raising an error when tables missing in destination
|
17
|
+
- Raise an error when `--config` or `--db` option provided and config not found
|
18
|
+
- Removed deprecated options
|
19
|
+
- Dropped support for Postgres < 9.5
|
20
|
+
|
21
|
+
## 0.5.5 (2020-05-13)
|
22
|
+
|
23
|
+
- Added `--jobs` option
|
24
|
+
- Added `--defer-constraints` option
|
25
|
+
- Added `--disable-user-triggers` option
|
26
|
+
- Added `--disable-integrity` option
|
27
|
+
- Improved error message for older libpq
|
28
|
+
|
29
|
+
## 0.5.4 (2020-05-09)
|
30
|
+
|
31
|
+
- Fixed output for `--in-batches`
|
32
|
+
|
33
|
+
## 0.5.3 (2020-04-03)
|
34
|
+
|
35
|
+
- Improved Postgres error messages
|
36
|
+
- Fixed behavior of wildcard without schema
|
37
|
+
|
1
38
|
## 0.5.2 (2020-03-27)
|
2
39
|
|
3
40
|
- Added `--fail-fast` option
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -33,20 +33,26 @@ This creates `.pgsync.yml` for you to customize. We recommend checking this into
|
|
33
33
|
|
34
34
|
## How to Use
|
35
35
|
|
36
|
-
|
36
|
+
First, make sure your schema is set up in both databases. We recommend using a schema migration tool for this, but pgsync also provides a few [convenience methods](#schema). Once that’s done, you’re ready to sync data.
|
37
|
+
|
38
|
+
Sync tables
|
37
39
|
|
38
40
|
```sh
|
39
41
|
pgsync
|
40
42
|
```
|
41
43
|
|
42
|
-
**Note:** pgsync assumes your schema is setup in your `to` database. See the [schema section](#schema) if that’s not the case.
|
43
|
-
|
44
44
|
Sync specific tables
|
45
45
|
|
46
46
|
```sh
|
47
47
|
pgsync table1,table2
|
48
48
|
```
|
49
49
|
|
50
|
+
Works with wildcards as well
|
51
|
+
|
52
|
+
```sh
|
53
|
+
pgsync "table*"
|
54
|
+
```
|
55
|
+
|
50
56
|
Sync specific rows (existing rows are overwritten)
|
51
57
|
|
52
58
|
```sh
|
@@ -65,13 +71,15 @@ Or truncate them
|
|
65
71
|
pgsync products "where store_id = 1" --truncate
|
66
72
|
```
|
67
73
|
|
68
|
-
|
74
|
+
## Tables
|
75
|
+
|
76
|
+
Exclude specific tables
|
69
77
|
|
70
78
|
```sh
|
71
|
-
pgsync --exclude
|
79
|
+
pgsync --exclude table1,table2
|
72
80
|
```
|
73
81
|
|
74
|
-
|
82
|
+
Add to `.pgsync.yml` to exclude by default
|
75
83
|
|
76
84
|
```yml
|
77
85
|
exclude:
|
@@ -79,15 +87,17 @@ exclude:
|
|
79
87
|
- table2
|
80
88
|
```
|
81
89
|
|
82
|
-
|
90
|
+
Sync tables from all schemas or specific schemas (by default, only the search path is synced)
|
83
91
|
|
84
|
-
```
|
85
|
-
|
86
|
-
|
87
|
-
|
92
|
+
```sh
|
93
|
+
pgsync --all-schemas
|
94
|
+
# or
|
95
|
+
pgsync --schemas public,other
|
96
|
+
# or
|
97
|
+
pgsync public.table1,other.table2
|
88
98
|
```
|
89
99
|
|
90
|
-
|
100
|
+
## Groups
|
91
101
|
|
92
102
|
Define groups in `.pgsync.yml`:
|
93
103
|
|
@@ -104,6 +114,8 @@ And run:
|
|
104
114
|
pgsync group1
|
105
115
|
```
|
106
116
|
|
117
|
+
## Variables
|
118
|
+
|
107
119
|
You can also use groups to sync a specific record and associated records in other tables.
|
108
120
|
|
109
121
|
To get product `123` with its reviews, last 10 coupons, and store, use:
|
@@ -123,18 +135,14 @@ And run:
|
|
123
135
|
pgsync product:123
|
124
136
|
```
|
125
137
|
|
126
|
-
|
127
|
-
|
128
|
-
**Note:** pgsync is designed to sync data. You should use a schema migration tool to manage schema changes. The methods in this section are provided for convenience but not recommended.
|
138
|
+
## Schema
|
129
139
|
|
130
|
-
Sync schema before the data
|
140
|
+
Sync schema before the data (this wipes out existing data)
|
131
141
|
|
132
142
|
```sh
|
133
143
|
pgsync --schema-first
|
134
144
|
```
|
135
145
|
|
136
|
-
**Note:** This wipes out existing data
|
137
|
-
|
138
146
|
Specify tables
|
139
147
|
|
140
148
|
```sh
|
@@ -149,13 +157,9 @@ pgsync --schema-only
|
|
149
157
|
|
150
158
|
pgsync does not try to sync Postgres extensions.
|
151
159
|
|
152
|
-
## Data
|
153
|
-
|
154
|
-
Always make sure your [connection is secure](https://ankane.org/postgres-sslmode-explained) when connecting to a database over a network you don’t fully trust. Your best option is to connect over SSH or a VPN. Another option is to use `sslmode=verify-full`. If you don’t do this, your database credentials can be compromised.
|
155
|
-
|
156
|
-
## Sensitive Information
|
160
|
+
## Sensitive Data
|
157
161
|
|
158
|
-
Prevent sensitive
|
162
|
+
Prevent sensitive data like email addresses from leaving the remote server.
|
159
163
|
|
160
164
|
Define rules in `.pgsync.yml`:
|
161
165
|
|
@@ -188,7 +192,61 @@ Options for replacement are:
|
|
188
192
|
- `null`
|
189
193
|
- `untouched`
|
190
194
|
|
191
|
-
Rules starting with `unique_` require the table to have a primary key. `unique_phone` requires a numeric primary key.
|
195
|
+
Rules starting with `unique_` require the table to have a single column primary key. `unique_phone` requires a numeric primary key.
|
196
|
+
|
197
|
+
## Foreign Keys
|
198
|
+
|
199
|
+
Foreign keys can make it difficult to sync data. Three options are:
|
200
|
+
|
201
|
+
1. Manually specify the order of tables
|
202
|
+
2. Use deferrable constraints
|
203
|
+
3. Disable foreign key triggers, which can silently break referential integrity
|
204
|
+
|
205
|
+
When manually specifying the order, use `--jobs 1` so tables are synced one-at-a-time.
|
206
|
+
|
207
|
+
```sh
|
208
|
+
pgsync table1,table2,table3 --jobs 1
|
209
|
+
```
|
210
|
+
|
211
|
+
If your tables have [deferrable constraints](https://begriffs.com/posts/2017-08-27-deferrable-sql-constraints.html), use:
|
212
|
+
|
213
|
+
```sh
|
214
|
+
pgsync --defer-constraints
|
215
|
+
```
|
216
|
+
|
217
|
+
To disable foreign key triggers and potentially break referential integrity, use:
|
218
|
+
|
219
|
+
```sh
|
220
|
+
pgsync --disable-integrity
|
221
|
+
```
|
222
|
+
|
223
|
+
## Triggers
|
224
|
+
|
225
|
+
Disable user triggers with:
|
226
|
+
|
227
|
+
```sh
|
228
|
+
pgsync --disable-user-triggers
|
229
|
+
```
|
230
|
+
|
231
|
+
## Append-Only Tables
|
232
|
+
|
233
|
+
For extremely large, append-only tables, sync in batches.
|
234
|
+
|
235
|
+
```sh
|
236
|
+
pgsync large_table --in-batches
|
237
|
+
```
|
238
|
+
|
239
|
+
The script will resume where it left off when run again, making it great for backfills.
|
240
|
+
|
241
|
+
## Connection Security
|
242
|
+
|
243
|
+
Always make sure your [connection is secure](https://ankane.org/postgres-sslmode-explained) when connecting to a database over a network you don’t fully trust. Your best option is to connect over SSH or a VPN. Another option is to use `sslmode=verify-full`. If you don’t do this, your database credentials can be compromised.
|
244
|
+
|
245
|
+
## Safety
|
246
|
+
|
247
|
+
To keep you from accidentally overwriting production, the destination is limited to `localhost` or `127.0.0.1` by default.
|
248
|
+
|
249
|
+
To use another host, add `to_safe: true` to your `.pgsync.yml`.
|
192
250
|
|
193
251
|
## Multiple Databases
|
194
252
|
|
@@ -204,31 +262,50 @@ This creates `.pgsync-db2.yml` for you to edit. Specify a database in commands w
|
|
204
262
|
pgsync --db db2
|
205
263
|
```
|
206
264
|
|
207
|
-
##
|
265
|
+
## Integrations
|
208
266
|
|
209
|
-
|
267
|
+
- [Django](#django)
|
268
|
+
- [Heroku](#heroku)
|
269
|
+
- [Laravel](#laravel)
|
270
|
+
- [Rails](#rails)
|
210
271
|
|
211
|
-
|
272
|
+
### Django
|
212
273
|
|
213
|
-
|
274
|
+
If you run `pgsync --init` in a Django project, migrations will be excluded in `.pgsync.yml`.
|
214
275
|
|
215
|
-
|
276
|
+
```yml
|
277
|
+
exclude:
|
278
|
+
- django_migrations
|
279
|
+
```
|
216
280
|
|
217
|
-
|
218
|
-
|
281
|
+
### Heroku
|
282
|
+
|
283
|
+
If you run `pgsync --init` in a Heroku project, the `from` database will be set in `.pgsync.yml`.
|
284
|
+
|
285
|
+
```yml
|
286
|
+
from: $(heroku config:get DATABASE_URL)?sslmode=require
|
219
287
|
```
|
220
288
|
|
221
|
-
|
289
|
+
### Laravel
|
222
290
|
|
223
|
-
|
291
|
+
If you run `pgsync --init` in a Laravel project, migrations will be excluded in `.pgsync.yml`.
|
224
292
|
|
225
|
-
|
293
|
+
```yml
|
294
|
+
exclude:
|
295
|
+
- migrations
|
296
|
+
```
|
226
297
|
|
227
|
-
|
228
|
-
|
298
|
+
### Rails
|
299
|
+
|
300
|
+
If you run `pgsync --init` in a Rails project, Active Record metadata and schema migrations will be excluded in `.pgsync.yml`.
|
301
|
+
|
302
|
+
```yml
|
303
|
+
exclude:
|
304
|
+
- ar_internal_metadata
|
305
|
+
- schema_migrations
|
229
306
|
```
|
230
307
|
|
231
|
-
##
|
308
|
+
## Other Commands
|
232
309
|
|
233
310
|
Help
|
234
311
|
|
@@ -242,6 +319,12 @@ Version
|
|
242
319
|
pgsync --version
|
243
320
|
```
|
244
321
|
|
322
|
+
List tables
|
323
|
+
|
324
|
+
```sh
|
325
|
+
pgsync --list
|
326
|
+
```
|
327
|
+
|
245
328
|
## Scripts
|
246
329
|
|
247
330
|
Use groups when possible to take advantage of parallelism.
|
data/config.yml
CHANGED
data/exe/pgsync
CHANGED
data/lib/pgsync.rb
CHANGED
@@ -10,15 +10,19 @@ require "shellwords"
|
|
10
10
|
require "tempfile"
|
11
11
|
require "uri"
|
12
12
|
require "yaml"
|
13
|
+
require "open3"
|
13
14
|
|
14
15
|
# modules
|
15
16
|
require "pgsync/utils"
|
16
17
|
require "pgsync/client"
|
17
18
|
require "pgsync/data_source"
|
18
19
|
require "pgsync/init"
|
20
|
+
require "pgsync/schema_sync"
|
19
21
|
require "pgsync/sync"
|
20
|
-
require "pgsync/
|
22
|
+
require "pgsync/table"
|
21
23
|
require "pgsync/table_sync"
|
24
|
+
require "pgsync/task"
|
25
|
+
require "pgsync/task_resolver"
|
22
26
|
require "pgsync/version"
|
23
27
|
|
24
28
|
module PgSync
|
data/lib/pgsync/client.rb
CHANGED
@@ -4,73 +4,75 @@ module PgSync
|
|
4
4
|
|
5
5
|
def initialize(args)
|
6
6
|
@args = args
|
7
|
-
|
7
|
+
output.sync = true
|
8
8
|
end
|
9
9
|
|
10
|
-
def perform
|
11
|
-
|
10
|
+
def perform
|
11
|
+
result = Slop::Parser.new(slop_options).parse(@args)
|
12
|
+
arguments = result.arguments
|
13
|
+
options = result.to_h
|
12
14
|
|
13
|
-
if
|
15
|
+
raise Error, "Specify either --db or --config, not both" if options[:db] && options[:config]
|
16
|
+
raise Error, "Cannot use --overwrite with --in-batches" if options[:overwrite] && options[:in_batches]
|
17
|
+
|
18
|
+
if options[:version]
|
14
19
|
log VERSION
|
15
|
-
elsif
|
16
|
-
log
|
17
|
-
|
18
|
-
|
19
|
-
Init.new.perform(opts)
|
20
|
+
elsif options[:help]
|
21
|
+
log slop_options
|
22
|
+
elsif options[:init]
|
23
|
+
Init.new(arguments, options).perform
|
20
24
|
else
|
21
|
-
Sync.new.perform
|
25
|
+
Sync.new(arguments, options).perform
|
22
26
|
end
|
23
|
-
rescue
|
24
|
-
|
25
|
-
|
27
|
+
rescue => e
|
28
|
+
# Error, PG::ConnectionBad, Slop::Error
|
29
|
+
raise e if options && options[:debug]
|
30
|
+
abort colorize(e.message.strip, :red)
|
26
31
|
end
|
27
32
|
|
28
33
|
def self.start
|
29
|
-
new(ARGV).perform
|
34
|
+
new(ARGV).perform
|
30
35
|
end
|
31
36
|
|
32
37
|
protected
|
33
38
|
|
34
|
-
def
|
35
|
-
Slop.
|
36
|
-
|
37
|
-
|
39
|
+
def slop_options
|
40
|
+
o = Slop::Options.new
|
41
|
+
o.banner = %{Usage:
|
42
|
+
pgsync [options]
|
38
43
|
|
39
44
|
Options:}
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
72
|
-
rescue Slop::Error => e
|
73
|
-
raise Error, e.message
|
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"
|
49
|
+
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
|
58
|
+
o.boolean "--preserve", "preserve existing rows", default: false
|
59
|
+
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
|
71
|
+
o.boolean "--disable-user-triggers", "disable non-system triggers", default: false
|
72
|
+
o.boolean "--disable-integrity", "disable foreign key triggers", default: false
|
73
|
+
o.boolean "-v", "--version", "print the version"
|
74
|
+
o.boolean "-h", "--help", "prints help"
|
75
|
+
o
|
74
76
|
end
|
75
77
|
end
|
76
78
|
end
|