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