table_copy 0.0.5 → 0.0.6

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
  SHA1:
3
- metadata.gz: 82e2e7bc03e341d5b10e172c080499d174abd238
4
- data.tar.gz: ccf3b5eebc929cefe8b9eeec212d7869b3cacb2c
3
+ metadata.gz: a22be48d16345c92700399d3cffdddff1df4378e
4
+ data.tar.gz: b7df0eafee1cd537a06931fd036a7663a0ebf539
5
5
  SHA512:
6
- metadata.gz: 9be2278b5259705cbfb905422385a334145eeb5325d8f97b33eb253343e3838014d081e3f86417c7456c519364ad29e19ea40e3cedece2fe84550ca2514c9567
7
- data.tar.gz: 4191cd39eda48dd99414e3f300a962d6de22e0ad756aaa9f7da8755ac5d0a4d42d14d185d4cf717a40e80524b254f8a80bbfacd4b4c842ba02dbf885a4e698cf
6
+ metadata.gz: f914d7745eb8e29085dcac211c7fef39dc03374bde943528d1e9037eb2dea78789be06b0e5b1c84600315189a02f2e3e18da7990584b7da7568f1216412e63ee
7
+ data.tar.gz: b927514b338af025f253de8cf6897ed1f3208d18e7b644bc678586332dea0e9a3022784773f4df216b44ef9d119920bfb52091e4b66937283be947fe1e68c9a1
@@ -10,27 +10,25 @@ module TableCopy
10
10
  end
11
11
 
12
12
  def update
13
- if destination_table.none?
14
- droppy
15
- elsif (max_sequence = destination_table.max_sequence)
16
- update_data(max_sequence)
17
- else
18
- diffy_update
13
+ with_rescue do
14
+ if destination_table.none?
15
+ droppy
16
+ elsif (max_sequence = destination_table.max_sequence)
17
+ update_data(max_sequence)
18
+ else
19
+ diffy_update
20
+ end
19
21
  end
20
- rescue ::PG::UndefinedTable => e
21
- ([e.inspect] + e.backtrace).each { |l| logger.warn(l) }
22
- create_table
23
- retry
24
- rescue ::PG::UndefinedColumn => e
25
- ([e.inspect] + e.backtrace).each { |l| logger.warn(l) }
26
- droppy
27
22
  end
28
23
 
29
24
  def droppy
30
25
  logger.info { "Droppy #{destination_table.table_name}" }
31
26
  destination_table.transaction do
27
+ views = destination_table.query_views
32
28
  destination_table.drop(cascade: true)
33
29
  create_table
30
+ destination_table.create_views(views)
31
+ logger.info { "Created #{views.count} views for #{destination_table.table_name}" }
34
32
  moved_count = destination_table.copy_data_from(source_table)
35
33
  logger.info { "#{moved_count} rows moved to #{destination_table.table_name}" }
36
34
  destination_table.create_indexes
@@ -91,6 +89,17 @@ module TableCopy
91
89
  destination_table.create(source_table.fields_ddl)
92
90
  end
93
91
 
92
+ def with_rescue
93
+ yield
94
+ rescue ::PG::UndefinedTable => e
95
+ ([e.inspect] + e.backtrace).each { |l| logger.warn(l) }
96
+ create_table
97
+ yield
98
+ rescue ::PG::UndefinedColumn => e
99
+ ([e.inspect] + e.backtrace).each { |l| logger.warn(l) }
100
+ droppy
101
+ end
102
+
94
103
  def logger
95
104
  TableCopy.logger
96
105
  end
@@ -101,8 +101,24 @@ module TableCopy
101
101
  end
102
102
  end
103
103
 
104
+ def query_views
105
+ with_conn do |conn|
106
+ conn.exec(views_sql)
107
+ end
108
+ end
109
+
110
+ def create_views(views)
111
+ with_conn do |conn|
112
+ views.each do |view|
113
+ conn.exec("create or replace view #{view['viewname']} as (#{view['definition'].gsub(/;\z/, '')})")
114
+ end
115
+ end
116
+ end
117
+
104
118
  private
105
119
 
120
+ attr_reader :primary_key
121
+
106
122
  def fields_list
107
123
  @fields_list ||= fields.join(', ')
108
124
  end
@@ -111,7 +127,6 @@ module TableCopy
111
127
  conn_method.call(&block)
112
128
  end
113
129
 
114
- attr_reader :primary_key
115
130
 
116
131
  def drop_sql
117
132
  @drop_sql ||= "drop table if exists #{table_name}"
@@ -157,6 +172,21 @@ module TableCopy
157
172
  "nv.#{key}"
158
173
  end.join(',')
159
174
  end
175
+
176
+ def views_sql
177
+ <<-SQL
178
+ select viewname, definition from pg_views where viewname in
179
+ (SELECT distinct dependee.relname
180
+ FROM pg_depend
181
+ JOIN pg_rewrite ON pg_depend.objid = pg_rewrite.oid
182
+ JOIN pg_class as dependee ON pg_rewrite.ev_class = dependee.oid
183
+ JOIN pg_class as dependent ON pg_depend.refobjid = dependent.oid
184
+ JOIN pg_attribute ON pg_depend.refobjid = pg_attribute.attrelid
185
+ AND pg_depend.refobjsubid = pg_attribute.attnum
186
+ WHERE dependent.relname = '#{table_name}'
187
+ AND pg_attribute.attnum > 0)
188
+ SQL
189
+ end
160
190
  end
161
191
  end
162
192
  end
@@ -1,3 +1,3 @@
1
1
  module TableCopy
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -88,9 +88,11 @@ describe TableCopy::Copier do
88
88
 
89
89
  describe '#droppy' do
90
90
  it 'drops and rebuilds the destination table' do
91
+ expect(destination).to receive(:query_views).and_return('views')
91
92
  expect(destination).to receive(:drop).with(cascade: true)
92
93
  expect(source).to receive(:fields_ddl).and_return(fields_ddl)
93
94
  expect(destination).to receive(:create).with(fields_ddl)
95
+ expect(destination).to receive(:create_views).with('views')
94
96
  expect(destination).to receive(:copy_data_from).with(source)
95
97
  expect(destination).to receive(:create_indexes)
96
98
  copier.droppy
@@ -4,6 +4,7 @@ require 'table_copy/pg/index'
4
4
  describe TableCopy::PG::Destination do
5
5
  let(:conn) { $pg_conn }
6
6
  let(:table_name) { 'table_name' }
7
+ let(:view_name) { 'view_name' }
7
8
  let(:indexes_sql) {
8
9
  <<-SQL
9
10
  select
@@ -35,6 +36,10 @@ describe TableCopy::PG::Destination do
35
36
  conn.exec("select count(*) from pg_tables where tablename='#{name}'").first['count'] == '1'
36
37
  end
37
38
 
39
+ def view_exists?(name=view_name)
40
+ conn.exec("select count(*) from pg_views where viewname='#{name}'").first['count'] == '1'
41
+ end
42
+
38
43
  def insert_data(name=table_name)
39
44
  conn.exec("insert into #{name} values(1, 'foo', '{bar, baz}')")
40
45
  end
@@ -57,7 +62,7 @@ describe TableCopy::PG::Destination do
57
62
  )}
58
63
 
59
64
  after do
60
- conn.exec("drop table if exists #{table_name}")
65
+ conn.exec("drop table if exists #{table_name} cascade")
61
66
  end
62
67
 
63
68
  describe '#to_s' do
@@ -71,6 +76,37 @@ describe TableCopy::PG::Destination do
71
76
  create_table
72
77
  end
73
78
 
79
+ let(:expected_view) {
80
+ [
81
+ {
82
+ "viewname" => view_name,
83
+ "definition" => "SELECT #{table_name}.column1, #{table_name}.column2, #{table_name}.column3 FROM #{table_name};"
84
+ }
85
+ ]
86
+ }
87
+
88
+ context 'a view exists' do
89
+ before do
90
+ conn.exec("create view #{view_name} as (select * from #{table_name})")
91
+ end
92
+
93
+ describe '#query_views' do
94
+ it 'returns a hash of name => query for views dependent on this table' do
95
+ expect(dest.query_views.to_a).to eq expected_view
96
+ end
97
+ end
98
+ end
99
+
100
+ describe '#create_views' do
101
+ it 'creates the given views' do
102
+ expect {
103
+ dest.create_views(expected_view)
104
+ }.to change {
105
+ view_exists?
106
+ }.from(false).to(true)
107
+ end
108
+ end
109
+
74
110
  describe '#none?' do
75
111
  it 'indicates whether the table has any data' do
76
112
  expect {
@@ -108,6 +144,7 @@ describe TableCopy::PG::Destination do
108
144
  }
109
145
  end
110
146
  end
147
+
111
148
  end
112
149
 
113
150
  describe '#drop' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: table_copy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - TLH
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-29 00:00:00.000000000 Z
11
+ date: 2014-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler