convergence 1.1.0 → 1.2.0
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/CHANGELOG.md +11 -0
- data/Gemfile.lock +7 -6
- data/README.md +30 -1
- data/convergence.gemspec +2 -0
- data/lib/convergence/column.rb +3 -2
- data/lib/convergence/diff.rb +37 -1
- data/lib/convergence/sql_generator/mysql_generator.rb +14 -0
- data/lib/convergence/sql_generator/postgres_generator.rb +14 -0
- data/lib/convergence/sql_generator/sqlite_generator.rb +14 -0
- data/lib/convergence/table.rb +3 -2
- data/lib/convergence/version.rb +1 -1
- data/spec/convergence/diff_spec.rb +167 -0
- data/spec/convergence/table_spec.rb +23 -0
- data/spec/fixtures/postgres/rename_column_on_paper.schema +28 -0
- data/spec/fixtures/postgres/rename_table.schema +28 -0
- data/spec/fixtures/rename_column_to_author.schema +26 -0
- data/spec/fixtures/rename_table.schema +26 -0
- data/spec/fixtures/sqlite/rename_column_on_paper.schema +28 -0
- data/spec/fixtures/sqlite/rename_table.schema +27 -0
- data/spec/integrations/command_dryrun.rb +22 -0
- data/spec/postgres_integrations/command_dryrun.rb +22 -0
- data/spec/sqlite_integrations/command_dryrun.rb +22 -0
- metadata +41 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 633f45bac912daa7950afa5535bfd87d13a7b33b25ff72489fb7fa125d0b6bdd
|
|
4
|
+
data.tar.gz: 392d293827a735cfeb515e878eb6f565d593259d0ff9f36e7aae8c0b4076b1ec
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f4255769af38418d8d336b8db4ef7e1ec2844ed3fbcf99cfd4e4bafa055e9765e5d30aaa92d2962ea8152c0b0688821e632ab71e2700158bcbe2f6a212f06270
|
|
7
|
+
data.tar.gz: 481f9bbebb0423275c0695445ab065ca6d54771f7dc25f94b005ac2918a1d7ad94730766a0d8a7c869fb76e49d7b6cc8e8da7cfea177d77c6fd2c049dbf0051b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
## Convergence 1.2.0 (August 26, 2026) ##
|
|
2
|
+
|
|
3
|
+
* Add `renamed_from:` support to detect table/column renames instead of a
|
|
4
|
+
destructive drop+add, for MySQL, PostgreSQL, and SQLite (PR: #101)
|
|
5
|
+
|
|
6
|
+
*nishio-dens*
|
|
7
|
+
|
|
8
|
+
* Bump rexml to fix CVE-2024-49761 (PR: #103)
|
|
9
|
+
|
|
10
|
+
*nishio-dens*
|
|
11
|
+
|
|
1
12
|
## Convergence 1.1.0 (August 25, 2026) ##
|
|
2
13
|
|
|
3
14
|
* Add PostgreSQL support (PR: #93)
|
data/Gemfile.lock
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
convergence (1.
|
|
4
|
+
convergence (1.2.0)
|
|
5
|
+
benchmark
|
|
5
6
|
diff-lcs
|
|
6
7
|
diffy (>= 3.4.2)
|
|
8
|
+
logger
|
|
7
9
|
mysql2
|
|
8
10
|
pg
|
|
9
11
|
sqlite3
|
|
@@ -13,6 +15,7 @@ GEM
|
|
|
13
15
|
remote: https://rubygems.org/
|
|
14
16
|
specs:
|
|
15
17
|
ast (2.4.1)
|
|
18
|
+
benchmark (0.5.0)
|
|
16
19
|
bigdecimal (4.1.2)
|
|
17
20
|
coderay (1.1.3)
|
|
18
21
|
diff-lcs (1.4.4)
|
|
@@ -37,6 +40,7 @@ GEM
|
|
|
37
40
|
listen (3.3.3)
|
|
38
41
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
|
39
42
|
rb-inotify (~> 0.9, >= 0.9.10)
|
|
43
|
+
logger (1.7.0)
|
|
40
44
|
lumberjack (1.2.8)
|
|
41
45
|
method_source (1.1.0)
|
|
42
46
|
mini_portile2 (2.8.9)
|
|
@@ -50,7 +54,6 @@ GEM
|
|
|
50
54
|
parser (3.0.0.0)
|
|
51
55
|
ast (~> 2.4.1)
|
|
52
56
|
pg (1.6.3)
|
|
53
|
-
pg (1.6.3-x86_64-linux)
|
|
54
57
|
pry (0.16.0)
|
|
55
58
|
coderay (~> 1.1)
|
|
56
59
|
method_source (~> 1.0)
|
|
@@ -63,7 +66,7 @@ GEM
|
|
|
63
66
|
regexp_parser (2.0.3)
|
|
64
67
|
reline (0.7.0)
|
|
65
68
|
io-console (~> 0.5)
|
|
66
|
-
rexml (3.
|
|
69
|
+
rexml (3.4.4)
|
|
67
70
|
rspec (3.10.0)
|
|
68
71
|
rspec-core (~> 3.10.0)
|
|
69
72
|
rspec-expectations (~> 3.10.0)
|
|
@@ -92,13 +95,11 @@ GEM
|
|
|
92
95
|
shellany (0.0.1)
|
|
93
96
|
sqlite3 (2.8.1)
|
|
94
97
|
mini_portile2 (~> 2.8.0)
|
|
95
|
-
sqlite3 (2.8.1-x86_64-linux-gnu)
|
|
96
98
|
thor (1.0.1)
|
|
97
99
|
unicode-display_width (1.7.0)
|
|
98
100
|
|
|
99
101
|
PLATFORMS
|
|
100
102
|
ruby
|
|
101
|
-
x86_64-linux
|
|
102
103
|
|
|
103
104
|
DEPENDENCIES
|
|
104
105
|
convergence!
|
|
@@ -110,4 +111,4 @@ DEPENDENCIES
|
|
|
110
111
|
rubocop
|
|
111
112
|
|
|
112
113
|
BUNDLED WITH
|
|
113
|
-
|
|
114
|
+
4.0.19
|
data/README.md
CHANGED
|
@@ -191,7 +191,9 @@ create/drop indexes on an existing table. Changing a column's type/null/default,
|
|
|
191
191
|
foreign key or primary key on an existing table, all require SQLite's own "rebuild the table" procedure
|
|
192
192
|
(create a new table, copy the data over, drop the old one, rename it), which this adapter does not implement
|
|
193
193
|
yet -- it raises `NotImplementedError` instead of generating SQL that SQLite would reject. Creating a brand new
|
|
194
|
-
table with any of the above (including foreign keys) works fine.
|
|
194
|
+
table with any of the above (including foreign keys) works fine. Renaming a table/column via `renamed_from:`
|
|
195
|
+
(see [Rename tables and columns](#rename-tables-and-columns)) is an exception to this limitation -- SQLite has
|
|
196
|
+
natively supported `RENAME TABLE`/`RENAME COLUMN` since 3.25.0, so it doesn't need the rebuild procedure.
|
|
195
197
|
|
|
196
198
|
Like PostgreSQL, MySQL-only table options (`engine`, `row_format`, `default_charset`/`character_set`, `collate`,
|
|
197
199
|
table/column `comment`) have no SQLite equivalent and are ignored. `extra: 'auto_increment'` maps to SQLite's
|
|
@@ -340,6 +342,33 @@ $ convergence apply example.schema -c database.yml --safe-migration
|
|
|
340
342
|
|
|
341
343
|
This also applies to `--dry-run` and `--rollback-dry-run`.
|
|
342
344
|
|
|
345
|
+
### Rename tables and columns
|
|
346
|
+
|
|
347
|
+
Without `renamed_from:`, convergence detects a renamed table/column as a drop followed by an add -- which loses
|
|
348
|
+
the data in that table/column. Add `renamed_from:` to the new name so convergence generates `RENAME TABLE`/`RENAME
|
|
349
|
+
COLUMN` instead:
|
|
350
|
+
|
|
351
|
+
```ruby
|
|
352
|
+
create_table "user_accounts", renamed_from: "users" do |t|
|
|
353
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
354
|
+
t.varchar "full_name", limit: 200, renamed_from: "name"
|
|
355
|
+
end
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
A few things to know:
|
|
359
|
+
|
|
360
|
+
* When a table or column has `renamed_from:`, **only the rename is applied on that pass** -- any other change to
|
|
361
|
+
the same table/column (a type change, a new `null`/`default`, ...) is ignored until you run `apply` again. Run
|
|
362
|
+
`apply` a second time (with `renamed_from:` still in place, or removed) to pick up the rest.
|
|
363
|
+
* `renamed_from:` is safe to leave in the schema file after the rename has been applied -- convergence detects
|
|
364
|
+
that the target name already exists and treats it as a no-op.
|
|
365
|
+
* Swapping two names (A ↔ B) or chaining renames (A → B → C) in a single `apply` is not supported. Use an
|
|
366
|
+
intermediate temporary name and apply in multiple steps instead.
|
|
367
|
+
* MySQL's `RENAME COLUMN` requires MySQL 8.0+; there's no fallback for 5.7.
|
|
368
|
+
* `convergence diff`'s pretty-printed output does not yet understand renames -- it will describe a rename as "no
|
|
369
|
+
change" for the renamed table/column. This is a known limitation, unrelated to the SQL that `apply`/`dry-run`
|
|
370
|
+
actually generate.
|
|
371
|
+
|
|
343
372
|
### Include Other Schema files
|
|
344
373
|
|
|
345
374
|
```
|
data/convergence.gemspec
CHANGED
data/lib/convergence/column.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
class Convergence::Column
|
|
2
|
-
attr_accessor :type, :column_name, :options
|
|
2
|
+
attr_accessor :type, :column_name, :options, :renamed_from
|
|
3
3
|
|
|
4
4
|
COLUMN_TYPE = %i(
|
|
5
5
|
tinyint
|
|
@@ -38,6 +38,7 @@ class Convergence::Column
|
|
|
38
38
|
def initialize(type, column_name, options = {})
|
|
39
39
|
@type = type
|
|
40
40
|
@column_name = column_name
|
|
41
|
-
@
|
|
41
|
+
@renamed_from = options[:renamed_from]&.to_s
|
|
42
|
+
@options = options.reject { |k| k == :renamed_from }
|
|
42
43
|
end
|
|
43
44
|
end
|
data/lib/convergence/diff.rb
CHANGED
|
@@ -11,6 +11,9 @@ class Convergence::Diff
|
|
|
11
11
|
def diff(from_database, to_database)
|
|
12
12
|
delta = {}
|
|
13
13
|
from_database = {} if from_database.nil?
|
|
14
|
+
delta[:rename_table] = scan_rename_table(from_database, to_database)
|
|
15
|
+
from_database = from_database.reject { |name, _| delta[:rename_table].key?(name) }
|
|
16
|
+
to_database = to_database.reject { |name, _| delta[:rename_table].value?(name) }
|
|
14
17
|
delta[:add_table] = scan_add_table(from_database, to_database)
|
|
15
18
|
delta[:remove_table] = scan_remove_table(from_database, to_database)
|
|
16
19
|
change_table = scan_change_table(from_database, to_database)
|
|
@@ -24,8 +27,11 @@ class Convergence::Diff
|
|
|
24
27
|
from = from_table.dup
|
|
25
28
|
to = to_table.dup
|
|
26
29
|
delta = {}
|
|
30
|
+
delta[:rename_column] = scan_rename_column(from, to)
|
|
31
|
+
from.columns = from.columns.reject { |name, _| delta[:rename_column].key?(name) }
|
|
32
|
+
to.columns = to.columns.reject { |name, _| delta[:rename_column].value?(name) }
|
|
27
33
|
delta[:remove_column] = scan_remove_column(from, to)
|
|
28
|
-
return delta if removed_all_columns?(
|
|
34
|
+
return delta if removed_all_columns?(from_table, delta)
|
|
29
35
|
delta[:add_column] = scan_add_column(from, to)
|
|
30
36
|
delta[:change_column] = scan_change_column(from, to)
|
|
31
37
|
scan_change_order_column(from, to, delta)
|
|
@@ -39,6 +45,36 @@ class Convergence::Diff
|
|
|
39
45
|
|
|
40
46
|
private
|
|
41
47
|
|
|
48
|
+
def scan_rename_table(from, to)
|
|
49
|
+
renames = {}
|
|
50
|
+
to.each do |new_name, to_table|
|
|
51
|
+
old_name = to_table.renamed_from
|
|
52
|
+
next if old_name.nil?
|
|
53
|
+
next unless from.key?(old_name)
|
|
54
|
+
next if from.key?(new_name)
|
|
55
|
+
if renames.key?(old_name)
|
|
56
|
+
fail ArgumentError.new("renamed_from '#{old_name}' is specified for multiple tables")
|
|
57
|
+
end
|
|
58
|
+
renames[old_name] = new_name
|
|
59
|
+
end
|
|
60
|
+
renames
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def scan_rename_column(from, to)
|
|
64
|
+
renames = {}
|
|
65
|
+
to.columns.each do |new_name, to_column|
|
|
66
|
+
old_name = to_column.renamed_from
|
|
67
|
+
next if old_name.nil?
|
|
68
|
+
next unless from.columns.key?(old_name)
|
|
69
|
+
next if from.columns.key?(new_name)
|
|
70
|
+
if renames.key?(old_name)
|
|
71
|
+
fail ArgumentError.new("#{to.table_name}: renamed_from '#{old_name}' is specified for multiple columns")
|
|
72
|
+
end
|
|
73
|
+
renames[old_name] = new_name
|
|
74
|
+
end
|
|
75
|
+
renames
|
|
76
|
+
end
|
|
77
|
+
|
|
42
78
|
def scan_add_table(from, to)
|
|
43
79
|
to.reject { |table_name, _| from.map { |k, _| k }.include?(table_name) }
|
|
44
80
|
end
|
|
@@ -16,6 +16,7 @@ class SQLGenerator::MysqlGenerator < SQLGenerator
|
|
|
16
16
|
def generate(to_table, delta, original_table, safe_migration: false)
|
|
17
17
|
@original_table = original_table
|
|
18
18
|
sqls = []
|
|
19
|
+
sqls << rename_table_sqls(delta)
|
|
19
20
|
sqls << change_table_sql(to_table, delta)
|
|
20
21
|
sqls << (safe_migration ? [] : drop_table_sqls(delta))
|
|
21
22
|
sqls << create_table_sqls(delta)
|
|
@@ -25,6 +26,12 @@ class SQLGenerator::MysqlGenerator < SQLGenerator
|
|
|
25
26
|
|
|
26
27
|
private
|
|
27
28
|
|
|
29
|
+
def rename_table_sqls(delta)
|
|
30
|
+
results = delta[:rename_table].map { |old_name, new_name| %(ALTER TABLE `#{old_name}` RENAME TO `#{new_name}`;) }
|
|
31
|
+
results << '' unless results.empty?
|
|
32
|
+
results
|
|
33
|
+
end
|
|
34
|
+
|
|
28
35
|
# FIXME: multiple pk change not supported yet
|
|
29
36
|
def change_table_sql(to_table, delta)
|
|
30
37
|
change_table = delta[:change_table]
|
|
@@ -36,6 +43,9 @@ class SQLGenerator::MysqlGenerator < SQLGenerator
|
|
|
36
43
|
table_delta[:remove_index].each do |index_name, _index|
|
|
37
44
|
results << alter_remove_index_sql(table_name, index_name)
|
|
38
45
|
end
|
|
46
|
+
table_delta[:rename_column].each do |old_name, new_name|
|
|
47
|
+
results << alter_rename_column_sql(table_name, old_name, new_name)
|
|
48
|
+
end
|
|
39
49
|
unless table_delta[:remove_column].empty?
|
|
40
50
|
results << alter_remove_columns_sql(table_name, table_delta[:remove_column].values)
|
|
41
51
|
end
|
|
@@ -73,6 +83,10 @@ class SQLGenerator::MysqlGenerator < SQLGenerator
|
|
|
73
83
|
sql
|
|
74
84
|
end
|
|
75
85
|
|
|
86
|
+
def alter_rename_column_sql(table_name, old_name, new_name)
|
|
87
|
+
%(ALTER TABLE `#{table_name}` RENAME COLUMN `#{old_name}` TO `#{new_name}`;)
|
|
88
|
+
end
|
|
89
|
+
|
|
76
90
|
def alter_change_column_sql(table_name, column_name, change_column_option, to_table)
|
|
77
91
|
column = to_table[table_name].columns[column_name]
|
|
78
92
|
column.options.merge!(after: change_column_option[:after]) unless change_column_option[:after].nil?
|
|
@@ -37,6 +37,7 @@ class SQLGenerator::PostgresGenerator < SQLGenerator
|
|
|
37
37
|
def generate(to_table, delta, original_table, safe_migration: false)
|
|
38
38
|
@original_table = original_table
|
|
39
39
|
sqls = []
|
|
40
|
+
sqls << rename_table_sqls(delta)
|
|
40
41
|
sqls << change_table_sql(to_table, delta)
|
|
41
42
|
sqls << (safe_migration ? [] : drop_table_sqls(delta))
|
|
42
43
|
sqls << create_table_sqls(delta)
|
|
@@ -46,6 +47,12 @@ class SQLGenerator::PostgresGenerator < SQLGenerator
|
|
|
46
47
|
|
|
47
48
|
private
|
|
48
49
|
|
|
50
|
+
def rename_table_sqls(delta)
|
|
51
|
+
results = delta[:rename_table].map { |old_name, new_name| %(ALTER TABLE "#{old_name}" RENAME TO "#{new_name}";) }
|
|
52
|
+
results << '' unless results.empty?
|
|
53
|
+
results
|
|
54
|
+
end
|
|
55
|
+
|
|
49
56
|
# FIXME: multiple pk change not supported yet
|
|
50
57
|
def change_table_sql(to_table, delta)
|
|
51
58
|
change_table = delta[:change_table]
|
|
@@ -57,6 +64,9 @@ class SQLGenerator::PostgresGenerator < SQLGenerator
|
|
|
57
64
|
table_delta[:remove_index].each do |index_name, _index|
|
|
58
65
|
results << alter_remove_index_sql(index_name)
|
|
59
66
|
end
|
|
67
|
+
table_delta[:rename_column].each do |old_name, new_name|
|
|
68
|
+
results << alter_rename_column_sql(table_name, old_name, new_name)
|
|
69
|
+
end
|
|
60
70
|
unless table_delta[:remove_column].empty?
|
|
61
71
|
results << alter_remove_columns_sql(table_name, table_delta[:remove_column].values)
|
|
62
72
|
end
|
|
@@ -90,6 +100,10 @@ class SQLGenerator::PostgresGenerator < SQLGenerator
|
|
|
90
100
|
columns.map { |column| %(ALTER TABLE "#{table_name}" DROP COLUMN "#{column.column_name}";) }.join("\n")
|
|
91
101
|
end
|
|
92
102
|
|
|
103
|
+
def alter_rename_column_sql(table_name, old_name, new_name)
|
|
104
|
+
%(ALTER TABLE "#{table_name}" RENAME COLUMN "#{old_name}" TO "#{new_name}";)
|
|
105
|
+
end
|
|
106
|
+
|
|
93
107
|
def alter_change_column_sql(table_name, column_name, change_column_option, to_table)
|
|
94
108
|
column = to_table[table_name].columns[column_name]
|
|
95
109
|
column.options.merge!(after: change_column_option[:after]) unless change_column_option[:after].nil?
|
|
@@ -15,6 +15,7 @@ class SQLGenerator::SqliteGenerator < SQLGenerator
|
|
|
15
15
|
def generate(to_table, delta, original_table, safe_migration: false)
|
|
16
16
|
@original_table = original_table
|
|
17
17
|
sqls = []
|
|
18
|
+
sqls << rename_table_sqls(delta)
|
|
18
19
|
sqls << change_table_sql(to_table, delta)
|
|
19
20
|
sqls << (safe_migration ? [] : drop_table_sqls(delta))
|
|
20
21
|
sqls << create_table_sqls(delta)
|
|
@@ -24,6 +25,12 @@ class SQLGenerator::SqliteGenerator < SQLGenerator
|
|
|
24
25
|
|
|
25
26
|
private
|
|
26
27
|
|
|
28
|
+
def rename_table_sqls(delta)
|
|
29
|
+
results = delta[:rename_table].map { |old_name, new_name| %(ALTER TABLE "#{old_name}" RENAME TO "#{new_name}";) }
|
|
30
|
+
results << '' unless results.empty?
|
|
31
|
+
results
|
|
32
|
+
end
|
|
33
|
+
|
|
27
34
|
def change_table_sql(to_table, delta)
|
|
28
35
|
change_table = delta[:change_table]
|
|
29
36
|
results = []
|
|
@@ -41,6 +48,9 @@ class SQLGenerator::SqliteGenerator < SQLGenerator
|
|
|
41
48
|
table_delta[:remove_index].each do |index_name, _index|
|
|
42
49
|
results << alter_remove_index_sql(index_name)
|
|
43
50
|
end
|
|
51
|
+
table_delta[:rename_column].each do |old_name, new_name|
|
|
52
|
+
results << alter_rename_column_sql(table_name, old_name, new_name)
|
|
53
|
+
end
|
|
44
54
|
unless table_delta[:remove_column].empty?
|
|
45
55
|
results << alter_remove_columns_sql(table_name, table_delta[:remove_column].values)
|
|
46
56
|
end
|
|
@@ -72,6 +82,10 @@ class SQLGenerator::SqliteGenerator < SQLGenerator
|
|
|
72
82
|
columns.map { |column| %(ALTER TABLE "#{table_name}" DROP COLUMN "#{column.column_name}";) }.join("\n")
|
|
73
83
|
end
|
|
74
84
|
|
|
85
|
+
def alter_rename_column_sql(table_name, old_name, new_name)
|
|
86
|
+
%(ALTER TABLE "#{table_name}" RENAME COLUMN "#{old_name}" TO "#{new_name}";)
|
|
87
|
+
end
|
|
88
|
+
|
|
75
89
|
def alter_remove_index_sql(index_name)
|
|
76
90
|
%(DROP INDEX "#{index_name}";)
|
|
77
91
|
end
|
data/lib/convergence/table.rb
CHANGED
|
@@ -3,7 +3,7 @@ require 'convergence/index'
|
|
|
3
3
|
require 'convergence/foreign_key'
|
|
4
4
|
|
|
5
5
|
class Convergence::Table
|
|
6
|
-
attr_accessor :table_name, :table_options, :columns, :indexes, :foreign_keys
|
|
6
|
+
attr_accessor :table_name, :table_options, :columns, :indexes, :foreign_keys, :renamed_from
|
|
7
7
|
|
|
8
8
|
Convergence::Column::COLUMN_TYPE.each do |column_type|
|
|
9
9
|
define_method "#{column_type}" do |column_name, options = {}|
|
|
@@ -46,7 +46,8 @@ class Convergence::Table
|
|
|
46
46
|
|
|
47
47
|
def initialize(table_name, options = {})
|
|
48
48
|
@table_name = table_name
|
|
49
|
-
@
|
|
49
|
+
@renamed_from = options[:renamed_from]&.to_s
|
|
50
|
+
@table_options = options.reject { |k| k == :id || k == :renamed_from }
|
|
50
51
|
@columns = {}
|
|
51
52
|
@indexes = {}
|
|
52
53
|
@foreign_keys = {}
|
data/lib/convergence/version.rb
CHANGED
|
@@ -64,6 +64,96 @@ describe Convergence::DSL do
|
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
+
context 'when a table is renamed' do
|
|
68
|
+
let(:renamed_table) do
|
|
69
|
+
Convergence::Table.new('simple_table_renamed', renamed_from: 'simple_table').tap do |t|
|
|
70
|
+
t.int('id', primary_key: true)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
let(:from_db) do
|
|
74
|
+
{ 'simple_table' => simple_table }
|
|
75
|
+
end
|
|
76
|
+
let(:to_db) do
|
|
77
|
+
{ 'simple_table_renamed' => renamed_table }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
subject { Convergence::Diff.new.diff(from_db, to_db) }
|
|
81
|
+
|
|
82
|
+
it 'should detect it as a rename, not add/remove' do
|
|
83
|
+
expect(subject[:rename_table]).to eq('simple_table' => 'simple_table_renamed')
|
|
84
|
+
expect(subject[:add_table]).to be_empty
|
|
85
|
+
expect(subject[:remove_table]).to be_empty
|
|
86
|
+
expect(subject[:change_table]).to be_empty
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context 'when renamed_from references a table that does not exist' do
|
|
91
|
+
let(:renamed_table) do
|
|
92
|
+
Convergence::Table.new('simple_table2', renamed_from: 'nonexistent_table').tap do |t|
|
|
93
|
+
t.int('id', primary_key: true)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
let(:from_db) do
|
|
97
|
+
{ 'simple_table' => simple_table }
|
|
98
|
+
end
|
|
99
|
+
let(:to_db) do
|
|
100
|
+
{ 'simple_table' => simple_table, 'simple_table2' => renamed_table }
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
subject { Convergence::Diff.new.diff(from_db, to_db) }
|
|
104
|
+
|
|
105
|
+
it 'should fall back to a normal add' do
|
|
106
|
+
expect(subject[:rename_table]).to be_empty
|
|
107
|
+
expect(subject[:add_table]['simple_table2']).not_to be_nil
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
context 'when the renamed_from target already exists (idempotent re-apply)' do
|
|
112
|
+
let(:renamed_table) do
|
|
113
|
+
Convergence::Table.new('simple_table2', renamed_from: 'simple_table').tap do |t|
|
|
114
|
+
t.int('id', primary_key: true)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
let(:from_db) do
|
|
118
|
+
{ 'simple_table' => simple_table, 'simple_table2' => simple_table2 }
|
|
119
|
+
end
|
|
120
|
+
let(:to_db) do
|
|
121
|
+
{ 'simple_table' => simple_table, 'simple_table2' => renamed_table }
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
subject { Convergence::Diff.new.diff(from_db, to_db) }
|
|
125
|
+
|
|
126
|
+
it 'should be a no-op for the rename' do
|
|
127
|
+
expect(subject[:rename_table]).to be_empty
|
|
128
|
+
expect(subject[:add_table]).to be_empty
|
|
129
|
+
expect(subject[:remove_table]).to be_empty
|
|
130
|
+
expect(subject[:change_table]).to be_empty
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
context 'when multiple tables claim the same renamed_from (ambiguous)' do
|
|
135
|
+
let(:renamed_table1) do
|
|
136
|
+
Convergence::Table.new('simple_table_a', renamed_from: 'simple_table').tap do |t|
|
|
137
|
+
t.int('id', primary_key: true)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
let(:renamed_table2) do
|
|
141
|
+
Convergence::Table.new('simple_table_b', renamed_from: 'simple_table').tap do |t|
|
|
142
|
+
t.int('id', primary_key: true)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
let(:from_db) do
|
|
146
|
+
{ 'simple_table' => simple_table }
|
|
147
|
+
end
|
|
148
|
+
let(:to_db) do
|
|
149
|
+
{ 'simple_table_a' => renamed_table1, 'simple_table_b' => renamed_table2 }
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it 'should raise an ArgumentError' do
|
|
153
|
+
expect { Convergence::Diff.new.diff(from_db, to_db) }.to raise_error(ArgumentError)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
67
157
|
context 'table column are changed' do
|
|
68
158
|
let(:table_from) do
|
|
69
159
|
Convergence::Table.new('table1').tap do |t|
|
|
@@ -132,6 +222,23 @@ describe Convergence::DSL do
|
|
|
132
222
|
expect(included_after_option).to eq false
|
|
133
223
|
end
|
|
134
224
|
end
|
|
225
|
+
|
|
226
|
+
context 'all columns are renamed' do
|
|
227
|
+
let(:table_to) do
|
|
228
|
+
Convergence::Table.new('table1').tap do |t|
|
|
229
|
+
t.int('id_rename', primary_key: true, renamed_from: 'id')
|
|
230
|
+
t.varchar('name_rename', limit: 200, null: false, renamed_from: 'name')
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
it 'should detect it as a change_table with rename_column, not a drop+add' do
|
|
235
|
+
results = Convergence::Diff.new.diff({ 'table1' => table_from }, { 'table1' => table_to })
|
|
236
|
+
expect(results[:add_table]).to be_empty
|
|
237
|
+
expect(results[:remove_table]).to be_empty
|
|
238
|
+
expect(results[:change_table]).not_to be_empty
|
|
239
|
+
expect(results[:change_table]['table1'][:rename_column]).to eq('id' => 'id_rename', 'name' => 'name_rename')
|
|
240
|
+
end
|
|
241
|
+
end
|
|
135
242
|
end
|
|
136
243
|
end
|
|
137
244
|
|
|
@@ -248,6 +355,66 @@ describe Convergence::DSL do
|
|
|
248
355
|
end
|
|
249
356
|
end
|
|
250
357
|
|
|
358
|
+
context 'rename column' do
|
|
359
|
+
let(:table_from) do
|
|
360
|
+
Convergence::Table.new('table1').tap do |t|
|
|
361
|
+
t.int('id', primary_key: true)
|
|
362
|
+
t.varchar('name', limit: 200, null: false)
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
let(:table_to) do
|
|
366
|
+
Convergence::Table.new('table1').tap do |t|
|
|
367
|
+
t.int('id', primary_key: true)
|
|
368
|
+
t.varchar('full_name', limit: 200, null: false, renamed_from: 'name')
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
it 'should detect it as a rename, not remove+add' do
|
|
373
|
+
expect(results[:rename_column]).to eq('name' => 'full_name')
|
|
374
|
+
expect(results[:remove_column]).to be_empty
|
|
375
|
+
expect(results[:add_column]).to be_empty
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
context 'rename column together with an unrelated change on another column' do
|
|
380
|
+
let(:table_from) do
|
|
381
|
+
Convergence::Table.new('table1').tap do |t|
|
|
382
|
+
t.int('id', primary_key: true)
|
|
383
|
+
t.varchar('name', limit: 200, null: false)
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
let(:table_to) do
|
|
387
|
+
Convergence::Table.new('table1').tap do |t|
|
|
388
|
+
t.int('id', primary_key: true)
|
|
389
|
+
t.varchar('full_name', limit: 300, null: false, renamed_from: 'name')
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
it 'should detect only the rename, deferring the other change to the next apply pass' do
|
|
394
|
+
expect(results[:rename_column]).to eq('name' => 'full_name')
|
|
395
|
+
expect(results[:change_column]).to be_empty
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
context 'rename the only column in a table' do
|
|
400
|
+
let(:table_from) do
|
|
401
|
+
Convergence::Table.new('table1').tap do |t|
|
|
402
|
+
t.int('id', primary_key: true)
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
let(:table_to) do
|
|
406
|
+
Convergence::Table.new('table1').tap do |t|
|
|
407
|
+
t.int('identifier', primary_key: true, renamed_from: 'id')
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
it 'should not be misdetected as removing all columns' do
|
|
412
|
+
expect(results[:rename_column]).to eq('id' => 'identifier')
|
|
413
|
+
expect(results[:remove_column]).to be_empty
|
|
414
|
+
expect(results[:add_column]).to be_empty
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
251
418
|
context 'remove index' do
|
|
252
419
|
let(:table_from) do
|
|
253
420
|
Convergence::Table.new('table1').tap do |t|
|
|
@@ -26,6 +26,29 @@ describe Convergence::Table do
|
|
|
26
26
|
table.decimal(dummy_column, default: 1)
|
|
27
27
|
expect(table.columns[dummy_column].options[:default]).to eq(1.0)
|
|
28
28
|
end
|
|
29
|
+
|
|
30
|
+
it 'should extract renamed_from into its own accessor' do
|
|
31
|
+
table.int(dummy_column, renamed_from: 'old_column')
|
|
32
|
+
expect(table.columns[dummy_column].renamed_from).to eq('old_column')
|
|
33
|
+
expect(table.columns[dummy_column].options).not_to have_key(:renamed_from)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'should have a nil renamed_from when not specified' do
|
|
37
|
+
table.int(dummy_column)
|
|
38
|
+
expect(table.columns[dummy_column].renamed_from).to be_nil
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe 'renamed_from' do
|
|
43
|
+
it 'should extract renamed_from into its own accessor' do
|
|
44
|
+
renamed_table = Convergence::Table.new('new_table', renamed_from: 'old_table')
|
|
45
|
+
expect(renamed_table.renamed_from).to eq('old_table')
|
|
46
|
+
expect(renamed_table.table_options).not_to have_key(:renamed_from)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'should have a nil renamed_from when not specified' do
|
|
50
|
+
expect(table.renamed_from).to be_nil
|
|
51
|
+
end
|
|
29
52
|
end
|
|
30
53
|
|
|
31
54
|
describe '#boolean' do
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
create_table "authors" do |t|
|
|
2
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
3
|
+
t.varchar "name", limit: 110
|
|
4
|
+
t.int "age"
|
|
5
|
+
t.datetime "created_at", null: true
|
|
6
|
+
t.datetime "updated_at", null: true
|
|
7
|
+
|
|
8
|
+
t.index "created_at", name: "index_authors_on_created_at"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
create_table "papers", comment: "Paper" do |t|
|
|
12
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
13
|
+
t.varchar "slug", comment: "Slug"
|
|
14
|
+
t.varchar "title1", limit: 300, comment: "Title 1"
|
|
15
|
+
t.varchar "title2", limit: 300, comment: "Title 2"
|
|
16
|
+
t.text "notes", null: true, comment: "Description", renamed_from: "description"
|
|
17
|
+
|
|
18
|
+
t.index "slug", name: "index_papers_on_slug", unique: true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
create_table "paper_authors", comment: "Paper Author Relation" do |t|
|
|
22
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
23
|
+
t.int "paper_id", comment: "Paper id"
|
|
24
|
+
t.int "author_id", comment: "Paper author id"
|
|
25
|
+
|
|
26
|
+
t.foreign_key "author_id", reference: "authors", reference_column: "id", name: "paper_authors_author_id_fk"
|
|
27
|
+
t.foreign_key "paper_id", reference: "papers", reference_column: "id", name: "paper_authors_paper_id_fk"
|
|
28
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
create_table "authors" do |t|
|
|
2
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
3
|
+
t.varchar "name", limit: 110
|
|
4
|
+
t.int "age"
|
|
5
|
+
t.datetime "created_at", null: true
|
|
6
|
+
t.datetime "updated_at", null: true
|
|
7
|
+
|
|
8
|
+
t.index "created_at", name: "index_authors_on_created_at"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
create_table "papers", comment: "Paper" do |t|
|
|
12
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
13
|
+
t.varchar "slug", comment: "Slug"
|
|
14
|
+
t.varchar "title1", limit: 300, comment: "Title 1"
|
|
15
|
+
t.varchar "title2", limit: 300, comment: "Title 2"
|
|
16
|
+
t.text "description", null: true, comment: "Description"
|
|
17
|
+
|
|
18
|
+
t.index "slug", name: "index_papers_on_slug", unique: true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
create_table "paper_author_links", comment: "Paper Author Relation", renamed_from: "paper_authors" do |t|
|
|
22
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
23
|
+
t.int "paper_id", comment: "Paper id"
|
|
24
|
+
t.int "author_id", comment: "Paper author id"
|
|
25
|
+
|
|
26
|
+
t.foreign_key "author_id", reference: "authors", reference_column: "id", name: "paper_authors_author_id_fk"
|
|
27
|
+
t.foreign_key "paper_id", reference: "papers", reference_column: "id", name: "paper_authors_paper_id_fk"
|
|
28
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
create_table "authors", collate: "utf8_general_ci", comment: "" do |t|
|
|
2
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
3
|
+
t.varchar "full_name", limit: 110, renamed_from: "name"
|
|
4
|
+
t.int "age", unsigned: true
|
|
5
|
+
t.datetime "created_at", null: true
|
|
6
|
+
t.datetime "updated_at", null: true
|
|
7
|
+
|
|
8
|
+
t.index "created_at", name: "index_authors_on_created_at"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
create_table "papers", collate: "utf8_general_ci", comment: "Paper" do |t|
|
|
12
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
13
|
+
t.varchar "slug", comment: "Slug"
|
|
14
|
+
t.varchar "title1", limit: 300, comment: "Title 1"
|
|
15
|
+
t.varchar "title2", limit: 300, comment: "Title 2"
|
|
16
|
+
t.text "description", null: true, comment: "Description"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
create_table "paper_authors", collate: "utf8_general_ci", comment: "Paper Author Relation" do |t|
|
|
20
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
21
|
+
t.int "paper_id", comment: "Paper id"
|
|
22
|
+
t.int "author_id", comment: "Paper author id"
|
|
23
|
+
|
|
24
|
+
t.foreign_key "author_id", reference: "authors", reference_column: "id", name: "paper_authors_author_id_fk"
|
|
25
|
+
t.foreign_key "paper_id", reference: "papers", reference_column: "id", name: "paper_authors_paper_id_fk"
|
|
26
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
create_table "authors", collate: "utf8_general_ci", comment: "" do |t|
|
|
2
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
3
|
+
t.varchar "name", limit: 110
|
|
4
|
+
t.int "age", unsigned: true
|
|
5
|
+
t.datetime "created_at", null: true
|
|
6
|
+
t.datetime "updated_at", null: true
|
|
7
|
+
|
|
8
|
+
t.index "created_at", name: "index_authors_on_created_at"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
create_table "papers", collate: "utf8_general_ci", comment: "Paper" do |t|
|
|
12
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
13
|
+
t.varchar "slug", comment: "Slug"
|
|
14
|
+
t.varchar "title1", limit: 300, comment: "Title 1"
|
|
15
|
+
t.varchar "title2", limit: 300, comment: "Title 2"
|
|
16
|
+
t.text "description", null: true, comment: "Description"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
create_table "paper_author_links", collate: "utf8_general_ci", comment: "Paper Author Relation", renamed_from: "paper_authors" do |t|
|
|
20
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
21
|
+
t.int "paper_id", comment: "Paper id"
|
|
22
|
+
t.int "author_id", comment: "Paper author id"
|
|
23
|
+
|
|
24
|
+
t.foreign_key "author_id", reference: "authors", reference_column: "id", name: "paper_authors_author_id_fk"
|
|
25
|
+
t.foreign_key "paper_id", reference: "papers", reference_column: "id", name: "paper_authors_paper_id_fk"
|
|
26
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
create_table "authors" do |t|
|
|
2
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
3
|
+
t.varchar "name", limit: 110
|
|
4
|
+
t.int "age"
|
|
5
|
+
t.datetime "created_at", null: true
|
|
6
|
+
t.datetime "updated_at", null: true
|
|
7
|
+
|
|
8
|
+
t.index "created_at", name: "index_authors_on_created_at"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
create_table "papers" do |t|
|
|
12
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
13
|
+
t.varchar "slug", limit: 255
|
|
14
|
+
t.varchar "title1", limit: 300
|
|
15
|
+
t.varchar "title2", limit: 300
|
|
16
|
+
t.text "notes", null: true, renamed_from: "description"
|
|
17
|
+
|
|
18
|
+
t.index "slug", name: "index_papers_on_slug", unique: true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
create_table "paper_authors" do |t|
|
|
22
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
23
|
+
t.int "paper_id"
|
|
24
|
+
t.int "author_id"
|
|
25
|
+
|
|
26
|
+
t.foreign_key "author_id", reference: "authors", reference_column: "id", name: "paper_authors_author_id_fk"
|
|
27
|
+
t.foreign_key "paper_id", reference: "papers", reference_column: "id", name: "paper_authors_paper_id_fk"
|
|
28
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
create_table "authors" do |t|
|
|
2
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
3
|
+
t.varchar "name", limit: 110
|
|
4
|
+
t.int "age"
|
|
5
|
+
t.datetime "created_at", null: true
|
|
6
|
+
t.datetime "updated_at", null: true
|
|
7
|
+
|
|
8
|
+
t.index "created_at", name: "index_authors_on_created_at"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
create_table "papers" do |t|
|
|
12
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
13
|
+
t.varchar "slug", limit: 255
|
|
14
|
+
t.varchar "title1", limit: 300
|
|
15
|
+
t.varchar "title2", limit: 300
|
|
16
|
+
|
|
17
|
+
t.index "slug", name: "index_papers_on_slug", unique: true
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
create_table "paper_author_links", renamed_from: "paper_authors" do |t|
|
|
21
|
+
t.int "id", primary_key: true, extra: "auto_increment"
|
|
22
|
+
t.int "paper_id"
|
|
23
|
+
t.int "author_id"
|
|
24
|
+
|
|
25
|
+
t.foreign_key "author_id", reference: "authors", reference_column: "id", name: "paper_authors_author_id_fk"
|
|
26
|
+
t.foreign_key "paper_id", reference: "papers", reference_column: "id", name: "paper_authors_paper_id_fk"
|
|
27
|
+
end
|
|
@@ -108,6 +108,28 @@ describe 'Command::Dryrun#execute' do
|
|
|
108
108
|
end
|
|
109
109
|
end
|
|
110
110
|
|
|
111
|
+
describe 'rename column' do
|
|
112
|
+
let(:exec_dsl) { 'rename_column_to_author.schema' }
|
|
113
|
+
|
|
114
|
+
it 'should be output rename column query, not drop+add' do
|
|
115
|
+
result = execute(exec_dsl)
|
|
116
|
+
expect(result).to be_include('# ALTER TABLE `authors` RENAME COLUMN `name` TO `full_name`;')
|
|
117
|
+
expect(result).not_to be_include('DROP COLUMN `name`')
|
|
118
|
+
expect(result).not_to be_include('ADD COLUMN `full_name`')
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
describe 'rename table' do
|
|
123
|
+
let(:exec_dsl) { 'rename_table.schema' }
|
|
124
|
+
|
|
125
|
+
it 'should be output rename table query, not drop+add' do
|
|
126
|
+
result = execute(exec_dsl)
|
|
127
|
+
expect(result).to be_include('# ALTER TABLE `paper_authors` RENAME TO `paper_author_links`;')
|
|
128
|
+
expect(result).not_to be_include('DROP TABLE `paper_authors`')
|
|
129
|
+
expect(result).not_to be_include('CREATE TABLE `paper_author_links`')
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
111
133
|
describe 'auto increment' do
|
|
112
134
|
describe 'create table with auto increment option' do
|
|
113
135
|
let(:exec_dsl) { 'add_table.schema' }
|
|
@@ -67,6 +67,28 @@ describe 'PostgreSQL Command::Dryrun#execute' do
|
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
+
describe 'rename column' do
|
|
71
|
+
let(:exec_dsl) { 'rename_column_on_paper.schema' }
|
|
72
|
+
|
|
73
|
+
it 'should be output rename column query, not drop+add' do
|
|
74
|
+
result = execute(exec_dsl)
|
|
75
|
+
expect(result).to be_include(%(# ALTER TABLE "papers" RENAME COLUMN "description" TO "notes";))
|
|
76
|
+
expect(result).not_to be_include('DROP COLUMN "description"')
|
|
77
|
+
expect(result).not_to be_include('ADD COLUMN "notes"')
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe 'rename table' do
|
|
82
|
+
let(:exec_dsl) { 'rename_table.schema' }
|
|
83
|
+
|
|
84
|
+
it 'should be output rename table query, not drop+add' do
|
|
85
|
+
result = execute(exec_dsl)
|
|
86
|
+
expect(result).to be_include(%(# ALTER TABLE "paper_authors" RENAME TO "paper_author_links";))
|
|
87
|
+
expect(result).not_to be_include('DROP TABLE "paper_authors"')
|
|
88
|
+
expect(result).not_to be_include('CREATE TABLE "paper_author_links"')
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
70
92
|
describe 'drop foreign key' do
|
|
71
93
|
let(:exec_dsl) { 'drop_foreign_key.schema' }
|
|
72
94
|
|
|
@@ -60,6 +60,28 @@ describe 'SQLite Command::Dryrun#execute' do
|
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
+
describe 'rename column' do
|
|
64
|
+
let(:exec_dsl) { 'rename_column_on_paper.schema' }
|
|
65
|
+
|
|
66
|
+
it 'should be output rename column query, not drop+add' do
|
|
67
|
+
result = execute(exec_dsl)
|
|
68
|
+
expect(result).to be_include(%(# ALTER TABLE "papers" RENAME COLUMN "description" TO "notes";))
|
|
69
|
+
expect(result).not_to be_include('DROP COLUMN "description"')
|
|
70
|
+
expect(result).not_to be_include('ADD COLUMN "notes"')
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe 'rename table' do
|
|
75
|
+
let(:exec_dsl) { 'rename_table.schema' }
|
|
76
|
+
|
|
77
|
+
it 'should be output rename table query, not drop+add' do
|
|
78
|
+
result = execute(exec_dsl)
|
|
79
|
+
expect(result).to be_include(%(# ALTER TABLE "paper_authors" RENAME TO "paper_author_links";))
|
|
80
|
+
expect(result).not_to be_include('DROP TABLE "paper_authors"')
|
|
81
|
+
expect(result).not_to be_include('CREATE TABLE "paper_author_links"')
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
63
85
|
describe 'drop foreign key' do
|
|
64
86
|
let(:exec_dsl) { 'drop_foreign_key.schema' }
|
|
65
87
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: convergence
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Shinsuke Nishio
|
|
@@ -93,6 +93,34 @@ dependencies:
|
|
|
93
93
|
- - ">="
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
95
|
version: '0'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: logger
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0'
|
|
103
|
+
type: :runtime
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: benchmark
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - ">="
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '0'
|
|
117
|
+
type: :runtime
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - ">="
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '0'
|
|
96
124
|
- !ruby/object:Gem::Dependency
|
|
97
125
|
name: rake
|
|
98
126
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -263,14 +291,20 @@ files:
|
|
|
263
291
|
- spec/fixtures/postgres/drop_foreign_key.schema
|
|
264
292
|
- spec/fixtures/postgres/drop_table.schema
|
|
265
293
|
- spec/fixtures/postgres/remove_columns_to_paper.schema
|
|
294
|
+
- spec/fixtures/postgres/rename_column_on_paper.schema
|
|
295
|
+
- spec/fixtures/postgres/rename_table.schema
|
|
266
296
|
- spec/fixtures/postgres_test_db.sql
|
|
267
297
|
- spec/fixtures/remove_columns_to_paper.schema
|
|
298
|
+
- spec/fixtures/rename_column_to_author.schema
|
|
299
|
+
- spec/fixtures/rename_table.schema
|
|
268
300
|
- spec/fixtures/sqlite/add_columns_to_paper.schema
|
|
269
301
|
- spec/fixtures/sqlite/add_table.schema
|
|
270
302
|
- spec/fixtures/sqlite/change_columns_to_paper.schema
|
|
271
303
|
- spec/fixtures/sqlite/drop_foreign_key.schema
|
|
272
304
|
- spec/fixtures/sqlite/drop_table.schema
|
|
273
305
|
- spec/fixtures/sqlite/remove_columns_to_paper.schema
|
|
306
|
+
- spec/fixtures/sqlite/rename_column_on_paper.schema
|
|
307
|
+
- spec/fixtures/sqlite/rename_table.schema
|
|
274
308
|
- spec/fixtures/sqlite_test_db.sql
|
|
275
309
|
- spec/fixtures/test_db.sql
|
|
276
310
|
- spec/integrations/command_diff.rb
|
|
@@ -330,14 +364,20 @@ test_files:
|
|
|
330
364
|
- spec/fixtures/postgres/drop_foreign_key.schema
|
|
331
365
|
- spec/fixtures/postgres/drop_table.schema
|
|
332
366
|
- spec/fixtures/postgres/remove_columns_to_paper.schema
|
|
367
|
+
- spec/fixtures/postgres/rename_column_on_paper.schema
|
|
368
|
+
- spec/fixtures/postgres/rename_table.schema
|
|
333
369
|
- spec/fixtures/postgres_test_db.sql
|
|
334
370
|
- spec/fixtures/remove_columns_to_paper.schema
|
|
371
|
+
- spec/fixtures/rename_column_to_author.schema
|
|
372
|
+
- spec/fixtures/rename_table.schema
|
|
335
373
|
- spec/fixtures/sqlite/add_columns_to_paper.schema
|
|
336
374
|
- spec/fixtures/sqlite/add_table.schema
|
|
337
375
|
- spec/fixtures/sqlite/change_columns_to_paper.schema
|
|
338
376
|
- spec/fixtures/sqlite/drop_foreign_key.schema
|
|
339
377
|
- spec/fixtures/sqlite/drop_table.schema
|
|
340
378
|
- spec/fixtures/sqlite/remove_columns_to_paper.schema
|
|
379
|
+
- spec/fixtures/sqlite/rename_column_on_paper.schema
|
|
380
|
+
- spec/fixtures/sqlite/rename_table.schema
|
|
341
381
|
- spec/fixtures/sqlite_test_db.sql
|
|
342
382
|
- spec/fixtures/test_db.sql
|
|
343
383
|
- spec/integrations/command_diff.rb
|