Better tests (and fix bug) in batch alter with renamed tables + constraints
[dbsrgits/SQL-Translator.git] / t / 30sqlt-new-diff-mysql.t
CommitLineData
4d438549 1#!/usr/bin/perl
2# vim: set ft=perl:
3
4use strict;
5use warnings;
6use SQL::Translator;
7
8use File::Spec::Functions qw(catfile updir tmpdir);
9use FindBin qw($Bin);
10use Test::More;
11use Test::Differences;
12use Test::SQL::Translator qw(maybe_plan);
f9ed5d54 13use SQL::Translator::Schema::Constants;
14use Storable 'dclone';
4d438549 15
4104f82b 16plan tests => 7;
4d438549 17
18use_ok('SQL::Translator::Diff') or die "Cannot continue\n";
19
20my $tr = SQL::Translator->new;
21
07d6e5f7 22my ( $source_schema, $target_schema, $parsed_sql_schema ) = map {
4d438549 23 my $t = SQL::Translator->new;
24 $t->parser( 'YAML' )
25 or die $tr->error;
26 my $out = $t->translate( catfile($Bin, qw/data diff/, $_ ) )
27 or die $tr->error;
28
29 my $schema = $t->schema;
30 unless ( $schema->name ) {
31 $schema->name( $_ );
32 }
33 ($schema);
07d6e5f7 34} (qw( create1.yml create2.yml ));
4d438549 35
36# Test for differences
37my $out = SQL::Translator::Diff::schema_diff( $source_schema, 'MySQL', $target_schema, 'MySQL', { no_batch_alters => 1} );
38eq_or_diff($out, <<'## END OF DIFF', "Diff as expected");
39-- Convert schema 'create1.yml' to 'create2.yml':
40
f9ed5d54 41BEGIN;
4d438549 42
43SET foreign_key_checks=0;
44
45
46CREATE TABLE added (
47 id integer(11)
48);
49
50
51SET foreign_key_checks=1;
52
53
46bf5655 54ALTER TABLE old_name RENAME TO new_name;
4d438549 55ALTER TABLE employee DROP FOREIGN KEY FK5302D47D93FE702E;
56ALTER TABLE person DROP UNIQUE UC_age_name;
57ALTER TABLE person DROP INDEX u_name;
58ALTER TABLE employee DROP COLUMN job_title;
46bf5655 59ALTER TABLE new_name ADD COLUMN new_field integer;
4d438549 60ALTER TABLE person ADD COLUMN is_rock_star tinyint(4) DEFAULT '1';
61ALTER TABLE person CHANGE COLUMN person_id person_id integer(11) NOT NULL auto_increment;
62ALTER TABLE person CHANGE COLUMN name name varchar(20) NOT NULL;
63ALTER TABLE person CHANGE COLUMN age age integer(11) DEFAULT '18';
64ALTER TABLE person CHANGE COLUMN iq iq integer(11) DEFAULT '0';
65ALTER TABLE person CHANGE COLUMN description physical_description text;
66ALTER TABLE person ADD UNIQUE INDEX unique_name (name);
67ALTER TABLE employee ADD CONSTRAINT FK5302D47D93FE702E_diff FOREIGN KEY (employee_id) REFERENCES person (person_id);
68ALTER TABLE person ADD UNIQUE UC_person_id (person_id);
69ALTER TABLE person ADD UNIQUE UC_age_name (age, name);
70ALTER TABLE person ENGINE=InnoDB;
71ALTER TABLE deleted DROP FOREIGN KEY fk_fake;
72DROP TABLE deleted;
73
74COMMIT;
75## END OF DIFF
76
4d438549 77$out = SQL::Translator::Diff::schema_diff($source_schema, 'MySQL', $target_schema, 'MySQL',
78 { ignore_index_names => 1,
79 ignore_constraint_names => 1
80 });
81
82eq_or_diff($out, <<'## END OF DIFF', "Diff as expected");
83-- Convert schema 'create1.yml' to 'create2.yml':
84
f9ed5d54 85BEGIN;
4d438549 86
87SET foreign_key_checks=0;
88
89
90CREATE TABLE added (
91 id integer(11)
92);
93
94
95SET foreign_key_checks=1;
96
97
98ALTER TABLE employee DROP COLUMN job_title;
46bf5655 99ALTER TABLE old_name RENAME TO new_name,
100 ADD COLUMN new_field integer;
4d438549 101ALTER TABLE person DROP UNIQUE UC_age_name,
102 ADD COLUMN is_rock_star tinyint(4) DEFAULT '1',
103 CHANGE COLUMN person_id person_id integer(11) NOT NULL auto_increment,
104 CHANGE COLUMN name name varchar(20) NOT NULL,
105 CHANGE COLUMN age age integer(11) DEFAULT '18',
106 CHANGE COLUMN iq iq integer(11) DEFAULT '0',
107 CHANGE COLUMN description physical_description text,
108 ADD UNIQUE UC_person_id (person_id),
109 ADD UNIQUE UC_age_name (age, name),
110 ENGINE=InnoDB;
111ALTER TABLE deleted DROP FOREIGN KEY fk_fake;
112DROP TABLE deleted;
113
114COMMIT;
115## END OF DIFF
116
117
118# Test for sameness
119$out = SQL::Translator::Diff::schema_diff($source_schema, 'MySQL', $source_schema, 'MySQL' );
120
121eq_or_diff($out, <<'## END OF DIFF', "No differences found");
122-- Convert schema 'create1.yml' to 'create1.yml':
123
124-- No differences found
125
126## END OF DIFF
127
07d6e5f7 128{
129 my $t = SQL::Translator->new;
130 $t->parser( 'MySQL' )
131 or die $tr->error;
132 my $out = $t->translate( catfile($Bin, qw/data mysql create.sql/ ) )
133 or die $tr->error;
46bf5655 134
135 # Lets remove the renamed table so we dont have to change the SQL or other tests
136 $target_schema->drop_table('new_name');
07d6e5f7 137
138 my $schema = $t->schema;
139 unless ( $schema->name ) {
140 $schema->name( 'create.sql' );
141 }
142
143 # Now lets change the type of one of the 'integer' columns so that it
144 # matches what the mysql parser sees for '<col> interger'.
145 my $field = $target_schema->get_table('employee')->get_field('employee_id');
146 $field->data_type('integer');
147 $field->size(0);
148 $out = SQL::Translator::Diff::schema_diff($schema, 'MySQL', $target_schema, 'MySQL' );
149 eq_or_diff($out, <<'## END OF DIFF', "No differences found");
150-- Convert schema 'create.sql' to 'create2.yml':
151
f9ed5d54 152BEGIN;
07d6e5f7 153
154SET foreign_key_checks=0;
155
156
157CREATE TABLE added (
158 id integer(11)
159);
160
161
162SET foreign_key_checks=1;
163
164
165ALTER TABLE employee DROP FOREIGN KEY FK5302D47D93FE702E,
166 DROP COLUMN job_title,
1c680eb9 167 ADD CONSTRAINT FK5302D47D93FE702E_diff FOREIGN KEY (employee_id) REFERENCES person (person_id);
07d6e5f7 168ALTER TABLE person DROP UNIQUE UC_age_name,
169 DROP INDEX u_name,
170 ADD COLUMN is_rock_star tinyint(4) DEFAULT '1',
171 CHANGE COLUMN person_id person_id integer(11) NOT NULL auto_increment,
172 CHANGE COLUMN name name varchar(20) NOT NULL,
173 CHANGE COLUMN age age integer(11) DEFAULT '18',
174 CHANGE COLUMN iq iq integer(11) DEFAULT '0',
175 CHANGE COLUMN description physical_description text,
176 ADD UNIQUE INDEX unique_name (name),
177 ADD UNIQUE UC_person_id (person_id),
178 ADD UNIQUE UC_age_name (age, name),
179 ENGINE=InnoDB;
180DROP TABLE deleted;
181
182COMMIT;
183## END OF DIFF
184}
f9ed5d54 185
186# Test InnoDB stupidness. Have to drop constraints before re-adding them if
187# they are just alters.
188
189
190{
191 my $s1 = SQL::Translator::Schema->new;
192 my $s2 = SQL::Translator::Schema->new;
193
194 $s1->name('Schema 1');
195 $s2->name('Schema 2');
196
197 my $t1 = $s1->add_table($target_schema->get_table('employee'));
198 my $t2 = $s2->add_table(dclone($target_schema->get_table('employee')));
199
200
201 my ($c) = grep { $_->name eq 'FK5302D47D93FE702E_diff' } $t2->get_constraints;
202 $c->on_delete('CASCADE');
203
204 $t2->add_constraint(
205 name => 'new_constraint',
206 type => 'FOREIGN KEY',
207 fields => ['employee_id'],
208 reference_fields => ['fake'],
209 reference_table => 'patty',
210 );
211
212 $t2->add_field(
213 name => 'new',
214 data_type => 'int'
215 );
216
4104f82b 217 my $out = SQL::Translator::Diff::schema_diff($s1, 'MySQL', $s2, 'MySQL' );
f9ed5d54 218
219 eq_or_diff($out, <<'## END OF DIFF', "Batch alter of constraints work for InnoDB");
220-- Convert schema 'Schema 1' to 'Schema 2':
221
222BEGIN;
223
224ALTER TABLE employee DROP FOREIGN KEY FK5302D47D93FE702E_diff;
225ALTER TABLE employee ADD COLUMN new integer,
226 ADD CONSTRAINT FK5302D47D93FE702E_diff FOREIGN KEY (employee_id) REFERENCES person (person_id) ON DELETE CASCADE,
227 ADD CONSTRAINT new_constraint FOREIGN KEY (employee_id) REFERENCES patty (fake);
228
229COMMIT;
230## END OF DIFF
231}
4104f82b 232
233{
234 # Test other things about renaming tables to - namely that renames
235 # constraints are still formated right.
236
237 my $s1 = SQL::Translator::Schema->new;
238 my $s2 = SQL::Translator::Schema->new;
239
240 $s1->name('Schema 3');
241 $s2->name('Schema 4');
242
243 my $t1 = $s1->add_table(dclone($target_schema->get_table('employee')));
244 my $t2 = dclone($target_schema->get_table('employee'));
245 $t2->name('fnord');
246 $t2->extra(renamed_from => 'employee');
247 $s2->add_table($t2);
248
249
250 $t1->add_constraint(
251 name => 'bar_fk',
252 type => 'FOREIGN KEY',
253 fields => ['employee_id'],
254 reference_fields => ['id'],
255 reference_table => 'bar',
256 );
257 $t2->add_constraint(
258 name => 'foo_fk',
259 type => 'FOREIGN KEY',
260 fields => ['employee_id'],
261 reference_fields => ['id'],
262 reference_table => 'foo',
263 );
264
265 my $out = SQL::Translator::Diff::schema_diff($s1, 'MySQL', $s2, 'MySQL' );
266 eq_or_diff($out, <<'## END OF DIFF', "Alter/drop constraints works with rename table");
267-- Convert schema 'Schema 3' to 'Schema 4':
268
269BEGIN;
270
271ALTER TABLE employee RENAME TO fnord,
272 DROP FOREIGN KEY bar_fk,
273 ADD CONSTRAINT foo_fk FOREIGN KEY (employee_id) REFERENCES foo (id);
274
275COMMIT;
276## END OF DIFF
277}