webdack-uuid_migration 1.0.1 → 1.0.2
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/.travis.yml +15 -0
- data/README.md +37 -2
- data/lib/webdack/uuid_migration/helpers.rb +30 -0
- data/lib/webdack/uuid_migration/schema_helpers.rb +55 -0
- data/lib/webdack/uuid_migration/version.rb +1 -1
- data/spec/schema_helper_spec.rb +68 -0
- data/spec/support/initial_schema.rb +14 -0
- data/spec/support/pg_database_helper.rb +2 -4
- data/spec/uuid_migrate_helper_spec.rb +31 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e73ae10fca41d84505cb6f9237f9b45f2da850c
|
4
|
+
data.tar.gz: 5abb88d0a9bc06de553e2e7b1e6fcae13fc85d88
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3005d3ba1bde0da93c33714b05cc7d831ede40dc91a977c836442c5b7be10f0a08e2d7a58fcf878e21fb1fafef26cc9b8d86ece4978270b1c49034a3824e8a9
|
7
|
+
data.tar.gz: 1631e47e420df4926c7ce6ab4775925cf7a3f53389c7369a4d473cda7e63febdb0fb6782995da3ff786b4947ed0092123835b5d1851309c7f46e2a52ec1d531a
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Webdack::UuidMigration
|
2
2
|
|
3
|
+
[](https://travis-ci.org/kreatio-sw/webdack-uuid_migration)
|
4
|
+
|
3
5
|
Helper methods to migrate Integer columns to UUID columns during migrations in PostgreSQL.
|
4
6
|
It supports migrating primary key columns as well.
|
5
7
|
|
@@ -60,6 +62,39 @@ retrieve old id in future.
|
|
60
62
|
See {Webdack::UUIDMigration::Helpers} for more details. {Webdack::UUIDMigration::Helpers} is mixed
|
61
63
|
into {ActiveRecord::Migration}, so that all methods can directly be used within migrations.
|
62
64
|
|
65
|
+
### Schema with Foreign Key References
|
66
|
+
|
67
|
+
Please see [https://github.com/kreatio-sw/webdack-uuid_migration/issues/4]
|
68
|
+
|
69
|
+
To update a primary key and all columns referencing it please use
|
70
|
+
{Webdack::UUIDMigration::Helpers#primary_key_and_all_references_to_uuid}. For example:
|
71
|
+
|
72
|
+
```
|
73
|
+
class MigrateWithFk < ActiveRecord::Migration
|
74
|
+
def change
|
75
|
+
reversible do |dir|
|
76
|
+
dir.up do
|
77
|
+
enable_extension 'uuid-ossp'
|
78
|
+
|
79
|
+
primary_key_and_all_references_to_uuid :cities
|
80
|
+
end
|
81
|
+
|
82
|
+
dir.down do
|
83
|
+
raise ActiveRecord::IrreversibleMigration
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
Internally it will query the database to find all tables & columns referring to this primary key as foreign keys
|
91
|
+
and do the following:
|
92
|
+
|
93
|
+
- Drop all foreign key constraints referring to this primary key
|
94
|
+
- Convert the primary key to UUID
|
95
|
+
- Convert all referring columns to UUID
|
96
|
+
- Restore all foreign keys
|
97
|
+
|
63
98
|
### Polymorphic references
|
64
99
|
|
65
100
|
Migrating Polymorphic references may get tricky if not all the participating entities are getting migrated to
|
@@ -93,10 +128,10 @@ Example:
|
|
93
128
|
|
94
129
|
## Compatibility
|
95
130
|
|
96
|
-
Works only with Rails 4. It uses Rails4's out-of-the-box UUID support for PostgreSQL. Works with Ruby 1.9.3,
|
131
|
+
Works only with Rails 4 & Rails 5. It uses Rails4's out-of-the-box UUID support for PostgreSQL. Works with Ruby 1.9.3,
|
97
132
|
2.0.0, 2.1.1, and 2.3.0.
|
98
133
|
|
99
|
-
Tested with Rails 5.0.0.
|
134
|
+
Tested with Rails 5.0.0.
|
100
135
|
|
101
136
|
To run the test suite:
|
102
137
|
|
@@ -1,6 +1,10 @@
|
|
1
|
+
require_relative 'schema_helpers'
|
2
|
+
|
1
3
|
module Webdack
|
2
4
|
module UUIDMigration
|
3
5
|
module Helpers
|
6
|
+
include SchemaHelpers
|
7
|
+
|
4
8
|
|
5
9
|
# Converts primary key from Serial Integer to UUID, migrates all data by left padding with 0's
|
6
10
|
# sets uuid_generate_v4() as default for the column
|
@@ -72,6 +76,32 @@ module Webdack
|
|
72
76
|
}
|
73
77
|
end
|
74
78
|
|
79
|
+
# Convert primary key of a table and all referring columns to UUID. Useful if migrations were generated
|
80
|
+
# with newer version of Rails that automatically creates foreign key constraints in the database.
|
81
|
+
#
|
82
|
+
# Internally it will query the database to find all tables & columns referring to this primary key as foreign keys
|
83
|
+
# and do the following:
|
84
|
+
#
|
85
|
+
# - Drop all foreign key constraints referring to this primary key
|
86
|
+
# - Convert the primary key to UUID
|
87
|
+
# - Convert all referring columns to UUID
|
88
|
+
# - Restore all foreign keys
|
89
|
+
#
|
90
|
+
# @param table[Symbol]
|
91
|
+
def primary_key_and_all_references_to_uuid(table)
|
92
|
+
fk_specs = foreign_keys_into(:cities)
|
93
|
+
|
94
|
+
drop_foreign_keys(fk_specs)
|
95
|
+
|
96
|
+
primary_key_to_uuid(table)
|
97
|
+
|
98
|
+
fk_specs.each do |fk_spec|
|
99
|
+
columns_to_uuid fk_spec[:from_table], fk_spec[:column]
|
100
|
+
end
|
101
|
+
|
102
|
+
create_foreign_keys(fk_specs.deep_dup)
|
103
|
+
end
|
104
|
+
|
75
105
|
private
|
76
106
|
# Prepare a fragment that can be used in SQL statements that converts teh data value
|
77
107
|
# from integer, string, or UUID to valid UUID string as per Postgres guidelines
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Webdack
|
2
|
+
module UUIDMigration
|
3
|
+
module SchemaHelpers
|
4
|
+
def foreign_keys_into(to_table_name)
|
5
|
+
to_primary_key = primary_key(to_table_name)
|
6
|
+
|
7
|
+
|
8
|
+
fk_info = select_all <<-SQL.strip_heredoc
|
9
|
+
SELECT t2.oid::regclass::text AS to_table, a2.attname AS primary_key, t1.relname as from_table, a1.attname AS column, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete FROM pg_constraint c
|
10
|
+
JOIN pg_class t1 ON c.conrelid = t1.oid
|
11
|
+
JOIN pg_class t2 ON c.confrelid = t2.oid
|
12
|
+
JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
|
13
|
+
JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
|
14
|
+
JOIN pg_namespace t3 ON c.connamespace = t3.oid
|
15
|
+
WHERE c.contype = 'f'
|
16
|
+
AND t2.oid::regclass::text = #{quote(to_table_name)}
|
17
|
+
AND a2.attname = #{quote(to_primary_key)}
|
18
|
+
ORDER BY t1.relname, a1.attname
|
19
|
+
SQL
|
20
|
+
|
21
|
+
fk_info.map do |row|
|
22
|
+
options = {
|
23
|
+
to_table: row['to_table'],
|
24
|
+
primary_key: row['primary_key'],
|
25
|
+
from_table: row['from_table'],
|
26
|
+
column: row['column'],
|
27
|
+
name: row['name']
|
28
|
+
}
|
29
|
+
|
30
|
+
options[:on_delete] = extract_foreign_key_action(row['on_delete'])
|
31
|
+
options[:on_update] = extract_foreign_key_action(row['on_update'])
|
32
|
+
|
33
|
+
options
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def drop_foreign_keys(foreign_keys)
|
38
|
+
foreign_keys.each do |fk_key_spec|
|
39
|
+
foreign_key_spec = fk_key_spec.dup
|
40
|
+
from_table = foreign_key_spec.delete(:from_table)
|
41
|
+
remove_foreign_key from_table, name: foreign_key_spec[:name]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def create_foreign_keys(foreign_keys)
|
46
|
+
foreign_keys.each do |fk_key_spec|
|
47
|
+
foreign_key_spec = fk_key_spec.dup
|
48
|
+
from_table = foreign_key_spec.delete(:from_table)
|
49
|
+
to_table = foreign_key_spec.delete(:to_table)
|
50
|
+
add_foreign_key from_table, to_table, foreign_key_spec
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
|
4
|
+
include Webdack::UUIDMigration::SchemaHelpers
|
5
|
+
end
|
6
|
+
|
7
|
+
describe Webdack::UUIDMigration::SchemaHelpers do
|
8
|
+
def initial_setup
|
9
|
+
init_database
|
10
|
+
create_initial_schema
|
11
|
+
|
12
|
+
# Create 2 more tables similar to the way new version of Rails will do
|
13
|
+
create_tables_with_fk
|
14
|
+
end
|
15
|
+
|
16
|
+
before(:each) do
|
17
|
+
initial_setup
|
18
|
+
|
19
|
+
@connection = ActiveRecord::Base.connection
|
20
|
+
|
21
|
+
# Create one more foreign key constraints
|
22
|
+
@connection.add_foreign_key :students, :cities
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should get all foreign keys into a table' do
|
26
|
+
foreign_keys_into = @connection.foreign_keys_into(:cities)
|
27
|
+
|
28
|
+
expect(foreign_keys_into).to eq([{:to_table => "cities",
|
29
|
+
:primary_key => "id",
|
30
|
+
:from_table => "dummy01",
|
31
|
+
:column => "city_id",
|
32
|
+
:name => "fk_rails_d0b87897d5",
|
33
|
+
:on_delete => :nullify,
|
34
|
+
:on_update => :cascade},
|
35
|
+
{:to_table => "cities",
|
36
|
+
:primary_key => "id",
|
37
|
+
:from_table => "dummy02",
|
38
|
+
:column => "city_id",
|
39
|
+
:name => "fk_rails_bc0a81611b",
|
40
|
+
:on_delete => :restrict,
|
41
|
+
:on_update => :restrict},
|
42
|
+
{:to_table => "cities",
|
43
|
+
:primary_key => "id",
|
44
|
+
:from_table => "students",
|
45
|
+
:column => "city_id",
|
46
|
+
:name => "fk_rails_c4b8171c0a",
|
47
|
+
:on_delete => nil,
|
48
|
+
:on_update => nil}])
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should drop all foreign keys into a table' do
|
52
|
+
fk_specs = @connection.foreign_keys_into(:cities)
|
53
|
+
|
54
|
+
@connection.drop_foreign_keys(fk_specs)
|
55
|
+
|
56
|
+
expect(@connection.foreign_keys_into(:cities)).to eq([])
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should drop all recreate all foreign keys into a table' do
|
60
|
+
fk_specs = @connection.foreign_keys_into(:cities)
|
61
|
+
|
62
|
+
@connection.drop_foreign_keys(fk_specs)
|
63
|
+
@connection.create_foreign_keys(fk_specs)
|
64
|
+
|
65
|
+
expect(@connection.foreign_keys_into(:cities)).to eq(fk_specs)
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -38,3 +38,17 @@ def create_initial_schema
|
|
38
38
|
|
39
39
|
end
|
40
40
|
end
|
41
|
+
|
42
|
+
def create_tables_with_fk
|
43
|
+
connection = ActiveRecord::Base.connection
|
44
|
+
|
45
|
+
connection.create_table "dummy01", force: true do |t|
|
46
|
+
t.string "name"
|
47
|
+
t.references "city", index: true, foreign_key: {on_update: :cascade, on_delete: :nullify}
|
48
|
+
end
|
49
|
+
|
50
|
+
connection.create_table "dummy02", force: true do |t|
|
51
|
+
t.string "name"
|
52
|
+
t.references "city", index: true, foreign_key: {on_update: :restrict, on_delete: :restrict}
|
53
|
+
end
|
54
|
+
end
|
@@ -2,11 +2,9 @@
|
|
2
2
|
|
3
3
|
PG_SPEC = {
|
4
4
|
:adapter => 'postgresql',
|
5
|
-
:host => 'localhost',
|
6
5
|
:database => 'webdack_uuid_migration_helper_test',
|
7
|
-
:username => '
|
8
|
-
:encoding => 'utf8'
|
9
|
-
:password => 'kreatio'
|
6
|
+
:username => 'postgres',
|
7
|
+
:encoding => 'utf8'
|
10
8
|
}
|
11
9
|
|
12
10
|
def init_database
|
@@ -38,6 +38,22 @@ class MigrateAllOneGo < ActiveRecord::Migration
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
class MigrateWithFk < ActiveRecord::Migration
|
42
|
+
def change
|
43
|
+
reversible do |dir|
|
44
|
+
dir.up do
|
45
|
+
enable_extension 'uuid-ossp'
|
46
|
+
|
47
|
+
primary_key_and_all_references_to_uuid :cities
|
48
|
+
end
|
49
|
+
|
50
|
+
dir.down do
|
51
|
+
raise ActiveRecord::IrreversibleMigration
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
41
57
|
class MigrateStep01 < ActiveRecord::Migration
|
42
58
|
def change
|
43
59
|
reversible do |dir|
|
@@ -154,6 +170,21 @@ describe Webdack::UUIDMigration::Helpers do
|
|
154
170
|
}
|
155
171
|
end
|
156
172
|
|
173
|
+
it 'should migrate a primary key and all columns referencing it using foreign keys' do
|
174
|
+
# Create 2 more tables similar to the way new version of Rails will do
|
175
|
+
create_tables_with_fk
|
176
|
+
|
177
|
+
# Add Foreign key for this reference as well
|
178
|
+
ActiveRecord::Base.connection.add_foreign_key :students, :cities
|
179
|
+
|
180
|
+
expect {
|
181
|
+
MigrateWithFk.migrate(:up)
|
182
|
+
reset_columns_data
|
183
|
+
}.to_not change {
|
184
|
+
key_relationships
|
185
|
+
}
|
186
|
+
end
|
187
|
+
|
157
188
|
it 'should handle nulls' do
|
158
189
|
Student.create(name: 'Student without city or institution')
|
159
190
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: webdack-uuid_migration
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Deepak Kumar
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-08-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -117,13 +117,16 @@ extensions: []
|
|
117
117
|
extra_rdoc_files: []
|
118
118
|
files:
|
119
119
|
- ".gitignore"
|
120
|
+
- ".travis.yml"
|
120
121
|
- Gemfile
|
121
122
|
- LICENSE.txt
|
122
123
|
- README.md
|
123
124
|
- Rakefile
|
124
125
|
- lib/webdack/uuid_migration.rb
|
125
126
|
- lib/webdack/uuid_migration/helpers.rb
|
127
|
+
- lib/webdack/uuid_migration/schema_helpers.rb
|
126
128
|
- lib/webdack/uuid_migration/version.rb
|
129
|
+
- spec/schema_helper_spec.rb
|
127
130
|
- spec/spec_helper.rb
|
128
131
|
- spec/support/initial_data.rb
|
129
132
|
- spec/support/initial_schema.rb
|
@@ -160,6 +163,7 @@ signing_key:
|
|
160
163
|
specification_version: 4
|
161
164
|
summary: Useful helpers to migrate Integer id columns to UUID in PostgreSql.
|
162
165
|
test_files:
|
166
|
+
- spec/schema_helper_spec.rb
|
163
167
|
- spec/spec_helper.rb
|
164
168
|
- spec/support/initial_data.rb
|
165
169
|
- spec/support/initial_schema.rb
|
@@ -170,4 +174,3 @@ test_files:
|
|
170
174
|
- spec/support/pg_database_helper.rb
|
171
175
|
- spec/uuid_custom_pk_spec.rb
|
172
176
|
- spec/uuid_migrate_helper_spec.rb
|
173
|
-
has_rdoc: yard
|