pgsync 0.3.1 → 0.3.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d12ffec2fc5681c48eb5f13eafca045330d3615f
4
- data.tar.gz: f8ed258ee86c6cc099299b1e962856500431d6ac
3
+ metadata.gz: 12edffcbf1375d06f4a56916e2581053711b3a81
4
+ data.tar.gz: c1b08b53a4f0dd07d32d87d921400f3718aaa07e
5
5
  SHA512:
6
- metadata.gz: f19de0157cf9e4ccadea5e787c6413995cfbcb9bd086750512c3392be495df3b7bc1868bd55fdc27d0e65c7a81adefbda6c9118dd9cf4f17b9102b2cc0628994
7
- data.tar.gz: 1248be9efc810bf5eb14685696e0b5214740549af940aa67cb9f6484651b72bed4ed8ca82d85a4ea26b840f69208606064c6eb9935f027ce64079c02b95f2baa
6
+ metadata.gz: e6484259d1dd62dde1b95b8472ae487298dae7848a0e14a95f68efc75bc954a370eb8b2ed74121c26dcc98c46c365a00a823386c88abe27e3ca02e81bbfa363a
7
+ data.tar.gz: e510ca2717985f8d2f1fd0fc2e16219f81a63f6a55171911508e4def6bc22769267c99d393df02dea15713fe80e030dab67690808517179f5a717953fda99308
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # 0.3.2
2
+
3
+ - Prefer `{1}` for interpolation
4
+ - Added `--overwrite` option
5
+ - Deprecated `--where` and `--limit`
6
+
1
7
  # 0.3.1
2
8
 
3
9
  - Added `-t` or `--tables`, `-g` or `--groups` options
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # pgsync
2
2
 
3
- Quickly and securely sync data between environments
3
+ Sync Postgres data to your local machine. Designed for:
4
+
5
+ - **speed** - up to 4x faster than traditional tools on a 4-core machine
6
+ - **security** - built-in methods to prevent sensitive data from ever leaving the server
7
+ - **convenience** - sync partial tables, groups of tables, and related records
4
8
 
5
9
  :tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
6
10
 
@@ -26,16 +30,30 @@ Sync all tables
26
30
  pgsync
27
31
  ```
28
32
 
33
+ **Note:** pgsync assumes your schema is already set up on your local machine. See the [schema section](#schema) if that’s not the case.
34
+
29
35
  Sync specific tables
30
36
 
31
37
  ```sh
32
38
  pgsync table1,table2
33
39
  ```
34
40
 
35
- Sync specific rows
41
+ Sync specific rows (existing rows are overwritten)
42
+
43
+ ```sh
44
+ pgsync products "where store_id = 1"
45
+ ```
46
+
47
+ You can also preserve existing rows
36
48
 
37
49
  ```sh
38
- pgsync products "WHERE id < 1000"
50
+ pgsync products "where store_id = 1" --preserve
51
+ ```
52
+
53
+ Or truncate them
54
+
55
+ ```sh
56
+ pgsync products "where store_id = 1" --truncate
39
57
  ```
40
58
 
41
59
  ### Exclude Tables
@@ -78,19 +96,21 @@ pgsync group1
78
96
 
79
97
  You can also use groups to sync a specific record and associated records in other tables.
80
98
 
81
- To get user `123` and his or her orders, use:
99
+ To get product `123` with its reviews, last 10 coupons, and store, use:
82
100
 
83
101
  ```yml
84
102
  groups:
85
- user:
86
- users: "WHERE id = {id}"
87
- orders: "WHERE user_id = {id}"
103
+ product:
104
+ products: "where id = {1}"
105
+ reviews: "where product_id = {1}"
106
+ coupons: "where product_id = {1} order by created_at desc limit 10"
107
+ stores: "where id in (select store_id from products where id = {1})
88
108
  ```
89
109
 
90
110
  And run:
91
111
 
92
112
  ```sh
93
- pgsync user:123
113
+ pgsync product:123
94
114
  ```
95
115
 
96
116
  ### Schema
@@ -161,6 +181,18 @@ To keep you from accidentally overwriting production, the destination is limited
161
181
 
162
182
  To use another host, add `to_safe: true` to your `.pgsync.yml`.
163
183
 
184
+ ## Setup Scripts
185
+
186
+ Use groups when possible to take advantage of parallelism.
187
+
188
+ For Ruby scripts, you may need to do:
189
+
190
+ ```rb
191
+ Bundler.with_clean_env do
192
+ system "pgsync ..."
193
+ end
194
+ ```
195
+
164
196
  ## Upgrading
165
197
 
166
198
  Run:
data/{bin → exe}/pgsync RENAMED
File without changes
data/lib/pgsync.rb CHANGED
@@ -18,7 +18,6 @@ end
18
18
 
19
19
  module PgSync
20
20
  class Error < StandardError; end
21
- class Rollback < StandardError; end
22
21
 
23
22
  class Client
24
23
  def initialize(args)
@@ -45,6 +44,10 @@ module PgSync
45
44
  args.shift
46
45
  opts[:setup] = true
47
46
  deprecated "Use `psync --setup` instead"
47
+ when "schema"
48
+ args.shift
49
+ opts[:schema_only] = true
50
+ deprecated "Use `psync --schema-only` instead"
48
51
  when "tables"
49
52
  args.shift
50
53
  opts[:tables] = args.shift
@@ -55,6 +58,18 @@ module PgSync
55
58
  deprecated "Use `pgsync #{opts[:groups]}` instead"
56
59
  end
57
60
 
61
+ if opts[:where]
62
+ opts[:sql] ||= String.new
63
+ opts[:sql] << " WHERE #{opts[:where]}"
64
+ deprecated "Use `\"WHERE #{opts[:where]}\"` instead"
65
+ end
66
+
67
+ if opts[:limit]
68
+ opts[:sql] ||= String.new
69
+ opts[:sql] << " LIMIT #{opts[:limit]}"
70
+ deprecated "Use `\"LIMIT #{opts[:limit]}\"` instead"
71
+ end
72
+
58
73
  if opts[:setup]
59
74
  setup(db_config_file(args[0]) || config_file || ".pgsync.yml")
60
75
  else
@@ -75,17 +90,14 @@ module PgSync
75
90
 
76
91
  tables = table_list(args, opts, from_uri)
77
92
 
78
- if args[0] == "schema" || opts[:schema_only]
79
- time =
80
- benchmark do
81
- log "* Dumping schema"
82
- tables = tables.keys.map { |t| "-t #{t}" }.join(" ")
83
- dump_command = "pg_dump --verbose --schema-only --no-owner --no-acl --clean #{tables} #{to_url(source_uri)}"
84
- restore_command = "psql -q -d #{to_url(destination_uri)}"
85
- system("#{dump_command} | #{restore_command}")
86
- end
93
+ if opts[:schema_only]
94
+ log "* Dumping schema"
95
+ tables = tables.keys.map { |t| "-t #{t}" }.join(" ")
96
+ dump_command = "pg_dump --verbose --schema-only --no-owner --no-acl --clean #{tables} #{to_url(source_uri)}"
97
+ restore_command = "psql -q -d #{to_url(destination_uri)}"
98
+ system("#{dump_command} | #{restore_command}")
87
99
 
88
- log "* DONE (#{time.round(1)}s)"
100
+ log_completed(start_time)
89
101
  else
90
102
  with_connection(to_uri, timeout: 3) do |conn|
91
103
  tables.keys.each do |table|
@@ -106,8 +118,7 @@ module PgSync
106
118
  sync_table(table, opts.merge(table_opts), from_uri, to_uri)
107
119
  end
108
120
 
109
- time = Time.now - start_time
110
- log "Completed in #{time.round(1)}s"
121
+ log_completed(start_time)
111
122
  end
112
123
  end
113
124
  end
@@ -135,8 +146,6 @@ module PgSync
135
146
  extra_sequences = to_sequences - from_sequences
136
147
  missing_sequences = from_sequences - to_sequences
137
148
 
138
- where = opts[:where]
139
- limit = opts[:limit]
140
149
  sql_clause = String.new
141
150
 
142
151
  @mutex.synchronize do
@@ -145,14 +154,6 @@ module PgSync
145
154
  log " #{opts[:sql]}"
146
155
  sql_clause << " #{opts[:sql]}"
147
156
  end
148
- if where
149
- log " #{where}"
150
- sql_clause << " WHERE #{opts[:where]}"
151
- end
152
- if limit
153
- log " LIMIT #{limit}"
154
- sql_clause << " LIMIT #{limit}"
155
- end
156
157
  log " Extra columns: #{extra_fields.join(", ")}" if extra_fields.any?
157
158
  log " Missing columns: #{missing_fields.join(", ")}" if missing_fields.any?
158
159
  log " Extra sequences: #{extra_sequences.join(", ")}" if extra_sequences.any?
@@ -173,7 +174,7 @@ module PgSync
173
174
  end
174
175
 
175
176
  copy_to_command = "COPY (SELECT #{copy_fields} FROM #{table}#{sql_clause}) TO STDOUT"
176
- if !opts[:truncate] && (opts[:preserve] || !sql_clause.empty?)
177
+ if !opts[:truncate] && (opts[:overwrite] || opts[:preserve] || !sql_clause.empty?)
177
178
  primary_key = self.primary_key(from_connection, table, "public")
178
179
  abort "No primary key" unless primary_key
179
180
 
@@ -246,8 +247,8 @@ Options:}
246
247
  o.string "-g", "--groups", "groups"
247
248
  o.string "--from", "source"
248
249
  o.string "--to", "destination"
249
- o.string "--where", "where"
250
- o.integer "--limit", "limit"
250
+ o.string "--where", "where", help: false
251
+ o.integer "--limit", "limit", help: false
251
252
  o.string "--exclude", "exclude tables"
252
253
  o.string "--config", "config file"
253
254
  o.string "--db", "database"
@@ -255,6 +256,7 @@ Options:}
255
256
  o.boolean "--to-safe", "accept danger", default: false
256
257
  o.boolean "--debug", "debug", default: false
257
258
  o.boolean "--list", "list", default: false
259
+ o.boolean "--overwrite", "overwrite existing rows", default: false, help: false
258
260
  o.boolean "--preserve", "preserve existing rows", default: false
259
261
  o.boolean "--truncate", "truncate existing rows", default: false
260
262
  o.boolean "--schema-only", "schema only", default: false
@@ -520,11 +522,15 @@ Options:}
520
522
  if table.is_a?(Array)
521
523
  table, sql = table
522
524
  end
523
- tables[table] = {}
524
- tables[table][:sql] = (boom || sql).to_s.gsub("{id}", cast(id)) if boom || sql
525
+ add_table(tables, table, id, boom || sql)
525
526
  end
526
527
  end
527
528
 
529
+ def add_table(tables, table, id, boom)
530
+ tables[table] = {}
531
+ tables[table][:sql] = boom.gsub("{id}", cast(id)).gsub("{1}", cast(id)) if boom
532
+ end
533
+
528
534
  def table_list(args, opts, from_uri)
529
535
  tables = nil
530
536
 
@@ -545,8 +551,7 @@ Options:}
545
551
  tables ||= Hash.new { |hash, key| hash[key] = {} }
546
552
  to_arr(opts[:tables]).each do |tag|
547
553
  table, id = tag.split(":", 2)
548
- tables[table] = {}
549
- tables[table][:sql] = args[1].to_s.gsub("{id}", cast(id)) if args[1]
554
+ add_table(tables, table, id, args[1])
550
555
  end
551
556
  end
552
557
 
@@ -559,8 +564,7 @@ Options:}
559
564
  if (t = (config["groups"] || {})[group])
560
565
  add_tables(tables, t, id, args[1])
561
566
  else
562
- tables[group] = {}
563
- tables[group][:sql] = args[1].to_s.gsub("{id}", cast(id)) if args[1]
567
+ add_table(tables, group, id, args[1])
564
568
  end
565
569
  end
566
570
  end
@@ -585,5 +589,10 @@ Options:}
585
589
  def deprecated(message)
586
590
  log "[DEPRECATED] #{message}"
587
591
  end
592
+
593
+ def log_completed(start_time)
594
+ time = Time.now - start_time
595
+ log "Completed in #{time.round(1)}s"
596
+ end
588
597
  end
589
598
  end
@@ -1,3 +1,3 @@
1
1
  module PgSync
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
data/pgsync.gemspec CHANGED
@@ -14,8 +14,8 @@ Gem::Specification.new do |spec|
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
- spec.bindir = "bin"
18
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency "slop", ">= 4.2.0"
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.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2016-04-07 00:00:00.000000000 Z
11
+ date: 2016-04-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: slop
@@ -122,8 +122,8 @@ files:
122
122
  - LICENSE.txt
123
123
  - README.md
124
124
  - Rakefile
125
- - bin/pgsync
126
125
  - config.yml
126
+ - exe/pgsync
127
127
  - lib/pgsync.rb
128
128
  - lib/pgsync/version.rb
129
129
  - pgsync.gemspec