table_copy 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/table_copy/copier.rb +22 -13
- data/lib/table_copy/pg/destination.rb +31 -1
- data/lib/table_copy/version.rb +1 -1
- data/spec/lib/table_copy/copier_spec.rb +2 -0
- data/spec/lib/table_copy/pg/destination_spec.rb +38 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a22be48d16345c92700399d3cffdddff1df4378e
|
4
|
+
data.tar.gz: b7df0eafee1cd537a06931fd036a7663a0ebf539
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f914d7745eb8e29085dcac211c7fef39dc03374bde943528d1e9037eb2dea78789be06b0e5b1c84600315189a02f2e3e18da7990584b7da7568f1216412e63ee
|
7
|
+
data.tar.gz: b927514b338af025f253de8cf6897ed1f3208d18e7b644bc678586332dea0e9a3022784773f4df216b44ef9d119920bfb52091e4b66937283be947fe1e68c9a1
|
data/lib/table_copy/copier.rb
CHANGED
@@ -10,27 +10,25 @@ module TableCopy
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def update
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
data/lib/table_copy/version.rb
CHANGED
@@ -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.
|
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-
|
11
|
+
date: 2014-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|