Fix MySQL enums with empty strings and leading/trailing quotes (RT#86091)
[dbsrgits/DBIx-Class-Schema-Loader.git] / t / 10_02mysql_common.t
1 use strict;
2 use warnings;
3 use Test::More;
4 use Test::Exception;
5 use Try::Tiny;
6 use File::Path 'rmtree';
7 use DBIx::Class::Schema::Loader::Utils 'slurp_file';
8 use DBIx::Class::Schema::Loader 'make_schema_at';
9
10 use lib qw(t/lib);
11
12 use dbixcsl_common_tests;
13 use dbixcsl_test_dir '$tdir';
14
15 use constant EXTRA_DUMP_DIR => "$tdir/mysql_extra_dump";
16
17 my $dsn         = $ENV{DBICTEST_MYSQL_DSN} || '';
18 my $user        = $ENV{DBICTEST_MYSQL_USER} || '';
19 my $password    = $ENV{DBICTEST_MYSQL_PASS} || '';
20 my $test_innodb = $ENV{DBICTEST_MYSQL_INNODB} || 0;
21
22 my $skip_rels_msg = 'You need to set the environment variable DBICTEST_MYSQL_INNODB=1 to test relationships.';
23
24 my $innodb = $test_innodb ? q{Engine=InnoDB} : '';
25
26 my ($schema, $databases_created); # for cleanup in END for extra tests
27
28 my $tester = dbixcsl_common_tests->new(
29     vendor            => 'Mysql',
30     auto_inc_pk       => 'INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT',
31     innodb            => $innodb,
32     dsn               => $dsn,
33     user              => $user,
34     password          => $password,
35     connect_info_opts => { on_connect_call => 'set_strict_mode' },
36     loader_options    => { preserve_case => 1 },
37     skip_rels         => $test_innodb ? 0 : $skip_rels_msg,
38     quote_char        => '`',
39     no_inline_rels    => 1,
40     no_implicit_rels  => 1,
41     default_on_clause => 'RESTRICT',
42     data_types  => {
43         # http://dev.mysql.com/doc/refman/5.5/en/data-type-overview.html
44         # Numeric Types
45         'bit'         => { data_type => 'bit', size => 1 },
46         'bit(11)'     => { data_type => 'bit', size => 11 },
47
48         'bool'        => { data_type => 'tinyint' },
49         'boolean'     => { data_type => 'tinyint' },
50         'tinyint'     => { data_type => 'tinyint' },
51         'tinyint unsigned'
52                       => { data_type => 'tinyint',   extra => { unsigned => 1 } },
53         'smallint'    => { data_type => 'smallint' },
54         'smallint unsigned'
55                       => { data_type => 'smallint',  extra => { unsigned => 1 } },
56         'mediumint'   => { data_type => 'mediumint' },
57         'mediumint unsigned'
58                       => { data_type => 'mediumint', extra => { unsigned => 1 } },
59         'int'         => { data_type => 'integer' },
60         'int unsigned'
61                       => { data_type => 'integer',   extra => { unsigned => 1 } },
62         'integer'     => { data_type => 'integer' },
63         'integer unsigned'
64                       => { data_type => 'integer',   extra => { unsigned => 1 } },
65         'integer not null'
66                       => { data_type => 'integer' },
67         'bigint'      => { data_type => 'bigint' },
68         'bigint unsigned'
69                       => { data_type => 'bigint',    extra => { unsigned => 1 } },
70
71         'serial'      => { data_type => 'bigint', is_auto_increment => 1, extra => { unsigned => 1 } },
72
73         'float'       => { data_type => 'float' },
74         'float unsigned'
75                       => { data_type => 'float',     extra => { unsigned => 1 } },
76         'double'      => { data_type => 'double precision' },
77         'double unsigned'
78                       => { data_type => 'double precision', extra => { unsigned => 1 } },
79         'double precision' =>
80                          { data_type => 'double precision' },
81         'double precision unsigned'
82                       => { data_type => 'double precision', extra => { unsigned => 1 } },
83
84         # we skip 'real' because its alias depends on the 'REAL AS FLOAT' setting
85
86         'float(2)'    => { data_type => 'float' },
87         'float(24)'   => { data_type => 'float' },
88         'float(25)'   => { data_type => 'double precision' },
89
90         'float(3,3)'  => { data_type => 'float', size => [3,3] },
91         'double(3,3)' => { data_type => 'double precision', size => [3,3] },
92         'double precision(3,3)'
93                       => { data_type => 'double precision', size => [3,3] },
94
95         'decimal'     => { data_type => 'decimal' },
96         'decimal unsigned'
97                       => { data_type => 'decimal', extra => { unsigned => 1 } },
98         'dec'         => { data_type => 'decimal' },
99         'numeric'     => { data_type => 'decimal' },
100         'fixed'       => { data_type => 'decimal' },
101
102         'decimal(3)'   => { data_type => 'decimal', size => [3,0] },
103
104         'decimal(3,3)' => { data_type => 'decimal', size => [3,3] },
105         'dec(3,3)'     => { data_type => 'decimal', size => [3,3] },
106         'numeric(3,3)' => { data_type => 'decimal', size => [3,3] },
107         'fixed(3,3)'   => { data_type => 'decimal', size => [3,3] },
108
109         # Date and Time Types
110         'date'        => { data_type => 'date', datetime_undef_if_invalid => 1 },
111         'datetime'    => { data_type => 'datetime', datetime_undef_if_invalid => 1 },
112         'timestamp default current_timestamp'
113                       => { data_type => 'timestamp', default_value => \'current_timestamp', datetime_undef_if_invalid => 1 },
114         'time'        => { data_type => 'time' },
115         'year'        => { data_type => 'year' },
116         'year(4)'     => { data_type => 'year' },
117         'year(2)'     => { data_type => 'year', size => 2 },
118
119         # String Types
120         'char'         => { data_type => 'char',      size => 1  },
121         'char(11)'     => { data_type => 'char',      size => 11 },
122         'varchar(20)'  => { data_type => 'varchar',   size => 20 },
123         'binary'       => { data_type => 'binary',    size => 1  },
124         'binary(11)'   => { data_type => 'binary',    size => 11 },
125         'varbinary(20)'=> { data_type => 'varbinary', size => 20 },
126
127         'tinyblob'    => { data_type => 'tinyblob' },
128         'tinytext'    => { data_type => 'tinytext' },
129         'blob'        => { data_type => 'blob' },
130
131         # text(M) types will map to the appropriate type, length is not stored
132         'text'        => { data_type => 'text' },
133
134         'mediumblob'  => { data_type => 'mediumblob' },
135         'mediumtext'  => { data_type => 'mediumtext' },
136         'longblob'    => { data_type => 'longblob' },
137         'longtext'    => { data_type => 'longtext' },
138
139         ( map {
140             "$_('','foo','bar','baz')"
141                       => { data_type => $_, extra => { list => ['', qw/foo bar baz/] } },
142             "$_('foo \\'bar\\' baz', 'foo ''bar'' quux')"
143                       => { data_type => $_, extra => { list => [q{foo 'bar' baz}, q{foo 'bar' quux}] } },
144             "$_('''', '''foo', 'bar''')"
145                       => { data_type => $_, extra => { list => [qw(' 'foo bar')] } },
146             "$_('\\'', '\\'foo', 'bar\\'')",
147                       => { data_type => $_, extra => { list => [qw(' 'foo bar')] } },
148             } qw(set enum)
149         ),
150
151         # RT#68717
152         "enum('11,10 (<500)/0 DUN','4,90 (<120)/0 EUR') NOT NULL default '11,10 (<500)/0 DUN'"
153                       => { data_type => 'enum', extra => { list => ['11,10 (<500)/0 DUN', '4,90 (<120)/0 EUR'] }, default_value => '11,10 (<500)/0 DUN' },
154         "set('11_10 (<500)/0 DUN','4_90 (<120)/0 EUR') NOT NULL default '11_10 (<500)/0 DUN'"
155                       => { data_type => 'set', extra => { list => ['11_10 (<500)/0 DUN', '4_90 (<120)/0 EUR'] }, default_value => '11_10 (<500)/0 DUN' },
156         "enum('19,90 (<500)/0 EUR','4,90 (<120)/0 EUR','7,90 (<200)/0 CHF','300 (<6000)/0 CZK','4,90 (<100)/0 EUR','39 (<900)/0 DKK','299 (<5000)/0 EEK','9,90 (<250)/0 EUR','3,90 (<100)/0 GBP','3000 (<70000)/0 HUF','4000 (<70000)/0 JPY','13,90 (<200)/0 LVL','99 (<2500)/0 NOK','39 (<1000)/0 PLN','1000 (<20000)/0 RUB','49 (<2500)/0 SEK','29 (<600)/0 USD','19,90 (<600)/0 EUR','0 EUR','0 CHF') NOT NULL default '19,90 (<500)/0 EUR'"
157                       => { data_type => 'enum', extra => { list => ['19,90 (<500)/0 EUR','4,90 (<120)/0 EUR','7,90 (<200)/0 CHF','300 (<6000)/0 CZK','4,90 (<100)/0 EUR','39 (<900)/0 DKK','299 (<5000)/0 EEK','9,90 (<250)/0 EUR','3,90 (<100)/0 GBP','3000 (<70000)/0 HUF','4000 (<70000)/0 JPY','13,90 (<200)/0 LVL','99 (<2500)/0 NOK','39 (<1000)/0 PLN','1000 (<20000)/0 RUB','49 (<2500)/0 SEK','29 (<600)/0 USD','19,90 (<600)/0 EUR','0 EUR','0 CHF'] }, default_value => '19,90 (<500)/0 EUR' },
158     },
159     extra => {
160         create => [
161             qq{
162                 CREATE TABLE `mysql_loader-test1` (
163                     id INT AUTO_INCREMENT PRIMARY KEY COMMENT 'The\15\12Column',
164                     value varchar(100)
165                 ) $innodb COMMENT 'The\15\12Table'
166             },
167             q{
168                 CREATE VIEW mysql_loader_test2 AS SELECT * FROM `mysql_loader-test1`
169             },
170             # RT#68717
171             qq{
172                 CREATE TABLE `mysql_loader_test3` (
173                   `ISO3_code` char(3) NOT NULL default '',
174                   `lang_pref` enum('de','en','fr','nl','dk','es','se') NOT NULL,
175                   `vat` decimal(4,2) default '16.00',
176                   `price_group` enum('EUR_DEFAULT','GBP_GBR','EUR_AUT_BEL_FRA_IRL_NLD','EUR_DNK_SWE','EUR_AUT','EUR_BEL','EUR_FIN','EUR_FRA','EUR_IRL','EUR_NLD','EUR_DNK','EUR_POL','EUR_PRT','EUR_SWE','CHF_CHE','DKK_DNK','SEK_SWE','NOK_NOR','USD_USA','CZK_CZE','PLN_POL','RUB_RUS','HUF_HUN','SKK_SVK','JPY_JPN','LVL_LVA','ROL_ROU','EEK_EST') NOT NULL default 'EUR_DEFAULT',
177                   `del_group` enum('19,90 (<500)/0 EUR','4,90 (<120)/0 EUR','7,90 (<200)/0 CHF','300 (<6000)/0 CZK','4,90 (<100)/0 EUR','39 (<900)/0 DKK','299 (<5000)/0 EEK','9,90 (<250)/0 EUR','3,90 (<100)/0 GBP','3000 (<70000)/0 HUF','4000 (<70000)/0 JPY','13,90 (<200)/0 LVL','99 (<2500)/0 NOK','39 (<1000)/0 PLN','1000 (<20000)/0 RUB','49 (<2500)/0 SEK','29 (<600)/0 USD','19,90 (<600)/0 EUR','0 EUR','0 CHF') NOT NULL default '19,90 (<500)/0 EUR',
178                   `express_del_group` enum('NO','39 EUR (EXPRESS)','59 EUR (EXPRESS)','79 CHF (EXPRESS)','49 EUR (EXPRESS)','990 CZK (EXPRESS)','19,9 EUR (EXPRESS)','290 DKK (EXPRESS)','990 EEK (EXPRESS)','39 GBP (EXPRESS)','14000 HUF (EXPRESS)','49 LVL (EXPRESS)','590 NOK (EXPRESS)','250 PLN (EXPRESS)','490 SEK (EXPRESS)') NOT NULL default 'NO',
179                   `pmethod` varchar(255) NOT NULL default 'VISA,MASTER',
180                   `delivery_time` varchar(5) default NULL,
181                   `express_delivery_time` varchar(5) default NULL,
182                   `eu` int(1) default '0',
183                   `cod_costs` varchar(12) default NULL,
184                   PRIMARY KEY (`ISO3_code`)
185                 ) $innodb
186             },
187             # 4 through 10 are used for the multi-schema tests
188             qq{
189                 create table mysql_loader_test11 (
190                     id int auto_increment primary key
191                 ) $innodb
192             },
193             qq{
194                 create table mysql_loader_test12 (
195                     id int auto_increment primary key,
196                     eleven_id int,
197                     foreign key (eleven_id) references mysql_loader_test11(id)
198                         on delete restrict on update set null
199                 ) $innodb
200             },
201         ],
202         pre_drop_ddl => [ 'DROP VIEW mysql_loader_test2', ],
203         drop => [ 'mysql_loader-test1', 'mysql_loader_test3', 'mysql_loader_test11', 'mysql_loader_test12' ],
204         count => 8 + 30 * 2,
205         run => sub {
206             my ($monikers, $classes);
207             ($schema, $monikers, $classes) = @_;
208
209             is $monikers->{'mysql_loader-test1'}, 'MysqlLoaderTest1',
210                 'table with dash correctly monikerized';
211
212             my $rsrc = $schema->source('MysqlLoaderTest2');
213
214             is $rsrc->column_info('value')->{data_type}, 'varchar',
215                 'view introspected successfully';
216
217             $rsrc = $schema->source('MysqlLoaderTest3');
218
219             is_deeply $rsrc->column_info('del_group')->{extra}{list}, ['19,90 (<500)/0 EUR','4,90 (<120)/0 EUR','7,90 (<200)/0 CHF','300 (<6000)/0 CZK','4,90 (<100)/0 EUR','39 (<900)/0 DKK','299 (<5000)/0 EEK','9,90 (<250)/0 EUR','3,90 (<100)/0 GBP','3000 (<70000)/0 HUF','4000 (<70000)/0 JPY','13,90 (<200)/0 LVL','99 (<2500)/0 NOK','39 (<1000)/0 PLN','1000 (<20000)/0 RUB','49 (<2500)/0 SEK','29 (<600)/0 USD','19,90 (<600)/0 EUR','0 EUR','0 CHF'],
220                 'hairy enum introspected correctly';
221
222             my $class    = $classes->{'mysql_loader-test1'};
223             my $filename = $schema->loader->get_dump_filename($class);
224
225             my $code = slurp_file $filename;
226
227             like $code, qr/^=head1 NAME\n\n^$class - The\nTable\n\n^=cut\n/m,
228                 'table comment';
229
230             like $code, qr/^=head2 id\n\n(.+:.+\n)+\nThe\nColumn\n\n/m,
231                 'column comment and attrs';
232
233             # test on delete/update fk clause introspection
234             ok ((my $rel_info = $schema->source('MysqlLoaderTest12')->relationship_info('eleven')),
235                 'got rel info');
236
237             is $rel_info->{attrs}{on_delete}, 'RESTRICT',
238                 'ON DELETE clause introspected correctly';
239
240             is $rel_info->{attrs}{on_update}, 'SET NULL',
241                 'ON UPDATE clause introspected correctly';
242
243             # multischema tests follow
244             SKIP: {
245                 my $dbh = $schema->storage->dbh;
246
247                 try {
248                     $dbh->do('CREATE DATABASE `dbicsl-test`');
249                 }
250                 catch {
251                     diag "CREATE DATABASE returned error: '$_'";
252                     skip "no CREATE DATABASE privileges", 30 * 2;
253                 };
254
255                 $dbh->do(<<"EOF");
256                     CREATE TABLE `dbicsl-test`.mysql_loader_test4 (
257                         id INT AUTO_INCREMENT PRIMARY KEY,
258                         value VARCHAR(100)
259                     ) $innodb
260 EOF
261                 $dbh->do(<<"EOF");
262                     CREATE TABLE `dbicsl-test`.mysql_loader_test5 (
263                         id INT AUTO_INCREMENT PRIMARY KEY,
264                         value VARCHAR(100),
265                         four_id INTEGER,
266                         CONSTRAINT loader_test5_uniq UNIQUE (four_id),
267                         FOREIGN KEY (four_id) REFERENCES `dbicsl-test`.mysql_loader_test4 (id)
268                     ) $innodb
269 EOF
270
271                 $dbh->do('CREATE DATABASE `dbicsl.test`');
272
273                 # Test that keys are correctly cached by naming the primary and
274                 # unique keys in this table with the same name as a table in
275                 # the `dbicsl-test` schema differently.
276                 $dbh->do(<<"EOF");
277                     CREATE TABLE `dbicsl.test`.mysql_loader_test5 (
278                         pk INT AUTO_INCREMENT PRIMARY KEY,
279                         value VARCHAR(100),
280                         four_id INTEGER,
281                         CONSTRAINT loader_test5_uniq UNIQUE (four_id),
282                         FOREIGN KEY (four_id) REFERENCES `dbicsl-test`.mysql_loader_test4 (id)
283                     ) $innodb
284 EOF
285
286                 $dbh->do(<<"EOF");
287                     CREATE TABLE `dbicsl.test`.mysql_loader_test6 (
288                         id INT AUTO_INCREMENT PRIMARY KEY,
289                         value VARCHAR(100),
290                         mysql_loader_test4_id INTEGER,
291                         FOREIGN KEY (mysql_loader_test4_id) REFERENCES `dbicsl-test`.mysql_loader_test4 (id)
292                     ) $innodb
293 EOF
294                 $dbh->do(<<"EOF");
295                     CREATE TABLE `dbicsl.test`.mysql_loader_test7 (
296                         id INT AUTO_INCREMENT PRIMARY KEY,
297                         value VARCHAR(100),
298                         six_id INTEGER UNIQUE,
299                         FOREIGN KEY (six_id) REFERENCES `dbicsl.test`.mysql_loader_test6 (id)
300                     ) $innodb
301 EOF
302                 $dbh->do(<<"EOF");
303                     CREATE TABLE `dbicsl-test`.mysql_loader_test8 (
304                         id INT AUTO_INCREMENT PRIMARY KEY,
305                         value VARCHAR(100),
306                         mysql_loader_test7_id INTEGER,
307                         FOREIGN KEY (mysql_loader_test7_id) REFERENCES `dbicsl.test`.mysql_loader_test7 (id)
308                     ) $innodb
309 EOF
310                 # Test dumping a rel to a table that's not part of the dump.
311                 $dbh->do('CREATE DATABASE `dbicsl_test_ignored`');
312                 $dbh->do(<<"EOF");
313                     CREATE TABLE `dbicsl_test_ignored`.mysql_loader_test9 (
314                         id INT AUTO_INCREMENT PRIMARY KEY,
315                         value VARCHAR(100)
316                     ) $innodb
317 EOF
318                 $dbh->do(<<"EOF");
319                     CREATE TABLE `dbicsl-test`.mysql_loader_test10 (
320                         id INT AUTO_INCREMENT PRIMARY KEY,
321                         value VARCHAR(100),
322                         mysql_loader_test9_id INTEGER,
323                         FOREIGN KEY (mysql_loader_test9_id) REFERENCES `dbicsl_test_ignored`.mysql_loader_test9 (id)
324                     ) $innodb
325 EOF
326
327                 $databases_created = 1;
328
329                 SKIP: foreach my $db_schema (['dbicsl-test', 'dbicsl.test'], '%') {
330                     if ($db_schema eq '%') {
331                         try {
332                             $dbh->selectall_arrayref('SHOW DATABASES');
333                         }
334                         catch {
335                             skip 'no SHOW DATABASES privileges', 28;
336                         }
337                     }
338
339                     lives_and {
340                         rmtree EXTRA_DUMP_DIR;
341
342                         my @warns;
343                         local $SIG{__WARN__} = sub {
344                             push @warns, $_[0] unless $_[0] =~ /\bcollides\b/;
345                         };
346
347                         make_schema_at(
348                             'MySQLMultiSchema',
349                             {
350                                 naming => 'current',
351                                 db_schema => $db_schema,
352                                 dump_directory => EXTRA_DUMP_DIR,
353                                 quiet => 1,
354                             },
355                             [ $dsn, $user, $password ],
356                         );
357
358                         diag join "\n", @warns if @warns;
359
360                         is @warns, 0;
361                     } 'dumped schema for "dbicsl-test" and "dbicsl.test" databases with no warnings';
362
363                     my ($test_schema, $rsrc, $rs, $row, %uniqs, $rel_info);
364
365                     lives_and {
366                         ok $test_schema = MySQLMultiSchema->connect($dsn, $user, $password);
367                     } 'connected test schema';
368
369                     lives_and {
370                         ok $rsrc = $test_schema->source('MysqlLoaderTest4');
371                     } 'got source for table in database name with dash';
372
373                     is try { $rsrc->column_info('id')->{is_auto_increment} }, 1,
374                         'column in database name with dash';
375
376                     is try { $rsrc->column_info('value')->{data_type} }, 'varchar',
377                         'column in database name with dash';
378
379                     is try { $rsrc->column_info('value')->{size} }, 100,
380                         'column in database name with dash';
381
382                     lives_and {
383                         ok $rs = $test_schema->resultset('MysqlLoaderTest4');
384                     } 'got resultset for table in database name with dash';
385
386                     lives_and {
387                         ok $row = $rs->create({ value => 'foo' });
388                     } 'executed SQL on table in database name with dash';
389
390                     SKIP: {
391                         skip 'set the environment variable DBICTEST_MYSQL_INNODB=1 to test relationships', 3 unless $test_innodb;
392
393                         $rel_info = try { $rsrc->relationship_info('dbicsl_dash_test_mysql_loader_test5') };
394
395                         is_deeply $rel_info->{cond}, {
396                             'foreign.four_id' => 'self.id'
397                         }, 'relationship in database name with dash';
398
399                         is $rel_info->{attrs}{accessor}, 'single',
400                             'relationship in database name with dash';
401
402                         is $rel_info->{attrs}{join_type}, 'LEFT',
403                             'relationship in database name with dash';
404                     }
405
406                     lives_and {
407                         ok $rsrc = $test_schema->source('DbicslDashTestMysqlLoaderTest5');
408                     } 'got source for table in database name with dash';
409
410                     %uniqs = try { $rsrc->unique_constraints };
411
412                     is keys %uniqs, 2,
413                         'got unique and primary constraint in database name with dash';
414
415                     delete $uniqs{primary};
416
417                     is_deeply ((values %uniqs)[0], ['four_id'],
418                         'unique constraint is correct in database name with dash');
419
420                     lives_and {
421                         ok $rsrc = $test_schema->source('MysqlLoaderTest6');
422                     } 'got source for table in database name with dot';
423
424                     is try { $rsrc->column_info('id')->{is_auto_increment} }, 1,
425                         'column in database name with dot introspected correctly';
426
427                     is try { $rsrc->column_info('value')->{data_type} }, 'varchar',
428                         'column in database name with dot introspected correctly';
429
430                     is try { $rsrc->column_info('value')->{size} }, 100,
431                         'column in database name with dot introspected correctly';
432
433                     lives_and {
434                         ok $rs = $test_schema->resultset('MysqlLoaderTest6');
435                     } 'got resultset for table in database name with dot';
436
437                     lives_and {
438                         ok $row = $rs->create({ value => 'foo' });
439                     } 'executed SQL on table in database name with dot';
440
441                     SKIP: {
442                         skip 'set the environment variable DBICTEST_MYSQL_INNODB=1 to test relationships', 3 unless $test_innodb;
443
444                         $rel_info = try { $rsrc->relationship_info('mysql_loader_test7') };
445
446                         is_deeply $rel_info->{cond}, {
447                             'foreign.six_id' => 'self.id'
448                         }, 'relationship in database name with dot';
449
450                         is $rel_info->{attrs}{accessor}, 'single',
451                             'relationship in database name with dot';
452
453                         is $rel_info->{attrs}{join_type}, 'LEFT',
454                             'relationship in database name with dot';
455                     }
456
457                     lives_and {
458                         ok $rsrc = $test_schema->source('MysqlLoaderTest7');
459                     } 'got source for table in database name with dot';
460
461                     %uniqs = try { $rsrc->unique_constraints };
462
463                     is keys %uniqs, 2,
464                         'got unique and primary constraint in database name with dot';
465
466                     delete $uniqs{primary};
467
468                     is_deeply ((values %uniqs)[0], ['six_id'],
469                         'unique constraint is correct in database name with dot');
470
471                     SKIP: {
472                         skip 'set the environment variable DBICTEST_MYSQL_INNODB=1 to test relationships', 4 unless $test_innodb;
473
474                         lives_and {
475                             ok $test_schema->source('MysqlLoaderTest6')
476                                 ->has_relationship('mysql_loader_test4');
477                         } 'cross-database relationship in multi-db_schema';
478
479                         lives_and {
480                             ok $test_schema->source('MysqlLoaderTest4')
481                                 ->has_relationship('mysql_loader_test6s');
482                         } 'cross-database relationship in multi-db_schema';
483
484                         lives_and {
485                             ok $test_schema->source('MysqlLoaderTest8')
486                                 ->has_relationship('mysql_loader_test7');
487                         } 'cross-database relationship in multi-db_schema';
488
489                         lives_and {
490                             ok $test_schema->source('MysqlLoaderTest7')
491                                 ->has_relationship('mysql_loader_test8s');
492                         } 'cross-database relationship in multi-db_schema';
493                     }
494                 }
495             }
496         },
497     },
498 );
499
500 if( !$dsn || !$user ) {
501     $tester->skip_tests('You need to set the DBICTEST_MYSQL_DSN, DBICTEST_MYSQL_USER, and DBICTEST_MYSQL_PASS environment variables');
502 }
503 else {
504     diag $skip_rels_msg if not $test_innodb;
505     $tester->run_tests();
506 }
507
508 END {
509     if (not $ENV{SCHEMA_LOADER_TESTS_NOCLEANUP}) {
510         if ($databases_created && (my $dbh = try { $schema->storage->dbh })) {
511             foreach my $table ('`dbicsl-test`.mysql_loader_test10',
512                                'dbicsl_test_ignored.mysql_loader_test9',
513                                '`dbicsl-test`.mysql_loader_test8',
514                                '`dbicsl.test`.mysql_loader_test7',
515                                '`dbicsl.test`.mysql_loader_test6',
516                                '`dbicsl.test`.mysql_loader_test5',
517                                '`dbicsl-test`.mysql_loader_test5',
518                                '`dbicsl-test`.mysql_loader_test4') {
519                 try {
520                     $dbh->do("DROP TABLE $table");
521                 }
522                 catch {
523                     diag "Error dropping table: $_";
524                 };
525             }
526
527             foreach my $db (qw/dbicsl-test dbicsl.test dbicsl_test_ignored/) {
528                 try {
529                     $dbh->do("DROP DATABASE `$db`");
530                 }
531                 catch {
532                     diag "Error dropping test database $db: $_";
533                 };
534             }
535         }
536         rmtree EXTRA_DUMP_DIR;
537     }
538 }
539 # vim:et sts=4 sw=4 tw=0: