25064d4f238164e81c157fdadd2b66a3be3bd6b4
[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 INDEX 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 INDEX 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 COLUMN job_title,
197                      ADD CONSTRAINT FK5302D47D93FE702E_diff FOREIGN KEY (employee_id) REFERENCES person (person_id);
198
199 ALTER TABLE person DROP INDEX UC_age_name,
200                    DROP INDEX u_name,
201                    ADD COLUMN is_rock_star tinyint(4) NULL DEFAULT 1,
202                    ADD COLUMN value double(8, 2) NULL DEFAULT 0.00,
203                    CHANGE COLUMN person_id person_id integer(11) NOT NULL auto_increment,
204                    CHANGE COLUMN name name varchar(20) NOT NULL,
205                    CHANGE COLUMN age age integer(11) NULL DEFAULT 18,
206                    CHANGE COLUMN iq iq integer(11) NULL DEFAULT 0,
207                    CHANGE COLUMN description physical_description text NULL,
208                    ADD UNIQUE INDEX unique_name (name),
209                    ADD UNIQUE UC_person_id (person_id),
210                    ADD UNIQUE UC_age_name (age, name),
211                    ENGINE=InnoDB;
212
213 DROP TABLE deleted;
214
215
216 COMMIT;
217
218 ## END OF DIFF
219 }
220
221 # Test InnoDB stupidness. Have to drop constraints before re-adding them if
222 # they are just alters.
223
224
225 {
226   my $s1 = SQL::Translator::Schema->new;
227   my $s2 = SQL::Translator::Schema->new;
228
229   $s1->name('Schema 1');
230   $s2->name('Schema 2');
231
232   my $t1 = $s1->add_table($target_schema->get_table('employee'));
233   my $t2 = $s2->add_table(dclone($target_schema->get_table('employee')));
234
235
236   my ($c) = grep { $_->name eq 'FK5302D47D93FE702E_diff' } $t2->get_constraints;
237   $c->on_delete('CASCADE');
238
239   $t2->add_constraint(
240     name => 'new_constraint',
241     type => 'FOREIGN KEY',
242     fields => ['employee_id'],
243     reference_fields => ['fake'],
244     reference_table => 'patty',
245   );
246
247   $t2->add_field(
248     name => 'new',
249     data_type => 'int'
250   );
251
252   my $out = SQL::Translator::Diff::schema_diff($s1, 'MySQL', $s2, 'MySQL' );
253
254   eq_or_diff($out, <<'## END OF DIFF', "Batch alter of constraints work for InnoDB", { context => 1 });
255 -- Convert schema 'Schema 1' to 'Schema 2':;
256
257 BEGIN;
258
259 ALTER TABLE employee DROP FOREIGN KEY FK5302D47D93FE702E_diff;
260
261 ALTER TABLE employee ADD COLUMN new integer NULL,
262                      ADD CONSTRAINT FK5302D47D93FE702E_diff FOREIGN KEY (employee_id) REFERENCES person (person_id) ON DELETE CASCADE,
263                      ADD CONSTRAINT new_constraint FOREIGN KEY (employee_id) REFERENCES patty (fake);
264
265
266 COMMIT;
267
268 ## END OF DIFF
269 }
270
271 {
272   # Test other things about renaming tables to - namely that renames
273   # constraints are still formated right.
274
275   my $s1 = SQL::Translator::Schema->new;
276   my $s2 = SQL::Translator::Schema->new;
277
278   $s1->name('Schema 3');
279   $s2->name('Schema 4');
280
281   my $t1 = $s1->add_table(dclone($target_schema->get_table('employee')));
282   $s1->add_table(dclone($source_schema->get_table('deleted')));
283   my $t2 = dclone($target_schema->get_table('employee'));
284   $t2->name('fnord');
285   $t2->extra(renamed_from => 'employee');
286   $s2->add_table($t2);
287
288
289   $t1->add_constraint(
290     name => 'bar_fk',
291     type => 'FOREIGN KEY',
292     fields => ['employee_id'],
293     reference_fields => ['id'],
294     reference_table => 'bar',
295   );
296   $t2->add_constraint(
297     name => 'foo_fk',
298     type => 'FOREIGN KEY',
299     fields => ['employee_id'],
300     reference_fields => ['id'],
301     reference_table => 'foo',
302   );
303
304   my $out = SQL::Translator::Diff::schema_diff($s1, 'MySQL', $s2, 'MySQL' );
305   eq_or_diff($out, <<'## END OF DIFF', "Alter/drop constraints works with rename table", { context => 1 });
306 -- Convert schema 'Schema 3' to 'Schema 4':;
307
308 BEGIN;
309
310 ALTER TABLE employee RENAME TO fnord,
311                      DROP FOREIGN KEY bar_fk,
312                      ADD CONSTRAINT foo_fk FOREIGN KEY (employee_id) REFERENCES foo (id);
313
314 ALTER TABLE deleted DROP FOREIGN KEY fk_fake;
315
316 DROP TABLE deleted;
317
318
319 COMMIT;
320
321 ## END OF DIFF
322
323   # Test quoting works too.
324   $out = SQL::Translator::Diff::schema_diff($s1, 'MySQL', $s2, 'MySQL',
325     { producer_args => { quote_identifiers => 1 } }
326   );
327   eq_or_diff($out, <<'## END OF DIFF', "Quoting can be turned on", { context => 1 });
328 -- Convert schema 'Schema 3' to 'Schema 4':;
329
330 BEGIN;
331
332 ALTER TABLE `employee` RENAME TO `fnord`,
333                        DROP FOREIGN KEY `bar_fk`,
334                        ADD CONSTRAINT `foo_fk` FOREIGN KEY (`employee_id`) REFERENCES `foo` (`id`);
335
336 ALTER TABLE `deleted` DROP FOREIGN KEY `fk_fake`;
337
338 DROP TABLE `deleted`;
339
340
341 COMMIT;
342
343 ## END OF DIFF
344 }