26f086a530bf05bffcf55b7e4ee091962183f3bc
[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 => 9 + 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             # test that views are marked as such
218             isa_ok $schema->resultset($monikers->{mysql_loader_test2})->result_source, 'DBIx::Class::ResultSource::View',
219                 'views have table_class set correctly';
220
221             $rsrc = $schema->source('MysqlLoaderTest3');
222
223             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'],
224                 'hairy enum introspected correctly';
225
226             my $class    = $classes->{'mysql_loader-test1'};
227             my $filename = $schema->loader->get_dump_filename($class);
228
229             my $code = slurp_file $filename;
230
231             like $code, qr/^=head1 NAME\n\n^$class - The\nTable\n\n^=cut\n/m,
232                 'table comment';
233
234             like $code, qr/^=head2 id\n\n(.+:.+\n)+\nThe\nColumn\n\n/m,
235                 'column comment and attrs';
236
237             # test on delete/update fk clause introspection
238             ok ((my $rel_info = $schema->source('MysqlLoaderTest12')->relationship_info('eleven')),
239                 'got rel info');
240
241             is $rel_info->{attrs}{on_delete}, 'RESTRICT',
242                 'ON DELETE clause introspected correctly';
243
244             is $rel_info->{attrs}{on_update}, 'SET NULL',
245                 'ON UPDATE clause introspected correctly';
246
247             # multischema tests follow
248             SKIP: {
249                 my $dbh = $schema->storage->dbh;
250
251                 try {
252                     $dbh->do('CREATE DATABASE `dbicsl-test`');
253                 }
254                 catch {
255                     note "CREATE DATABASE returned error: '$_'";
256                     skip "no CREATE DATABASE privileges", 30 * 2;
257                 };
258
259                 $dbh->do(<<"EOF");
260                     CREATE TABLE `dbicsl-test`.mysql_loader_test4 (
261                         id INT AUTO_INCREMENT PRIMARY KEY,
262                         value VARCHAR(100)
263                     ) $innodb
264 EOF
265                 $dbh->do(<<"EOF");
266                     CREATE TABLE `dbicsl-test`.mysql_loader_test5 (
267                         id INT AUTO_INCREMENT PRIMARY KEY,
268                         value VARCHAR(100),
269                         four_id INTEGER,
270                         CONSTRAINT loader_test5_uniq UNIQUE (four_id),
271                         FOREIGN KEY (four_id) REFERENCES `dbicsl-test`.mysql_loader_test4 (id)
272                     ) $innodb
273 EOF
274
275                 $dbh->do('CREATE DATABASE `dbicsl.test`');
276
277                 # Test that keys are correctly cached by naming the primary and
278                 # unique keys in this table with the same name as a table in
279                 # the `dbicsl-test` schema differently.
280                 $dbh->do(<<"EOF");
281                     CREATE TABLE `dbicsl.test`.mysql_loader_test5 (
282                         pk INT AUTO_INCREMENT PRIMARY KEY,
283                         value VARCHAR(100),
284                         four_id INTEGER,
285                         CONSTRAINT loader_test5_uniq UNIQUE (four_id),
286                         FOREIGN KEY (four_id) REFERENCES `dbicsl-test`.mysql_loader_test4 (id)
287                     ) $innodb
288 EOF
289
290                 $dbh->do(<<"EOF");
291                     CREATE TABLE `dbicsl.test`.mysql_loader_test6 (
292                         id INT AUTO_INCREMENT PRIMARY KEY,
293                         value VARCHAR(100),
294                         mysql_loader_test4_id INTEGER,
295                         FOREIGN KEY (mysql_loader_test4_id) REFERENCES `dbicsl-test`.mysql_loader_test4 (id)
296                     ) $innodb
297 EOF
298                 $dbh->do(<<"EOF");
299                     CREATE TABLE `dbicsl.test`.mysql_loader_test7 (
300                         id INT AUTO_INCREMENT PRIMARY KEY,
301                         value VARCHAR(100),
302                         six_id INTEGER UNIQUE,
303                         FOREIGN KEY (six_id) REFERENCES `dbicsl.test`.mysql_loader_test6 (id)
304                     ) $innodb
305 EOF
306                 $dbh->do(<<"EOF");
307                     CREATE TABLE `dbicsl-test`.mysql_loader_test8 (
308                         id INT AUTO_INCREMENT PRIMARY KEY,
309                         value VARCHAR(100),
310                         mysql_loader_test7_id INTEGER,
311                         FOREIGN KEY (mysql_loader_test7_id) REFERENCES `dbicsl.test`.mysql_loader_test7 (id)
312                     ) $innodb
313 EOF
314                 # Test dumping a rel to a table that's not part of the dump.
315                 $dbh->do('CREATE DATABASE `dbicsl_test_ignored`');
316                 $dbh->do(<<"EOF");
317                     CREATE TABLE `dbicsl_test_ignored`.mysql_loader_test9 (
318                         id INT AUTO_INCREMENT PRIMARY KEY,
319                         value VARCHAR(100)
320                     ) $innodb
321 EOF
322                 $dbh->do(<<"EOF");
323                     CREATE TABLE `dbicsl-test`.mysql_loader_test10 (
324                         id INT AUTO_INCREMENT PRIMARY KEY,
325                         value VARCHAR(100),
326                         mysql_loader_test9_id INTEGER,
327                         FOREIGN KEY (mysql_loader_test9_id) REFERENCES `dbicsl_test_ignored`.mysql_loader_test9 (id)
328                     ) $innodb
329 EOF
330
331                 $databases_created = 1;
332
333                 SKIP: foreach my $db_schema (['dbicsl-test', 'dbicsl.test'], '%') {
334                     if ($db_schema eq '%') {
335                         try {
336                             $dbh->selectall_arrayref('SHOW DATABASES');
337                         }
338                         catch {
339                             skip 'no SHOW DATABASES privileges', 28;
340                         }
341                     }
342
343                     lives_and {
344                         rmtree EXTRA_DUMP_DIR;
345
346                         my @warns;
347                         local $SIG{__WARN__} = sub {
348                             push @warns, $_[0] unless $_[0] =~ /\bcollides\b/;
349                         };
350
351                         make_schema_at(
352                             'MySQLMultiSchema',
353                             {
354                                 naming => 'current',
355                                 db_schema => $db_schema,
356                                 dump_directory => EXTRA_DUMP_DIR,
357                                 quiet => 1,
358                             },
359                             [ $dsn, $user, $password ],
360                         );
361
362                         diag join "\n", @warns if @warns;
363
364                         is @warns, 0;
365                     } 'dumped schema for "dbicsl-test" and "dbicsl.test" databases with no warnings';
366
367                     my ($test_schema, $rsrc, $rs, $row, %uniqs, $rel_info);
368
369                     lives_and {
370                         ok $test_schema = MySQLMultiSchema->connect($dsn, $user, $password);
371                     } 'connected test schema';
372
373                     lives_and {
374                         ok $rsrc = $test_schema->source('MysqlLoaderTest4');
375                     } 'got source for table in database name with dash';
376
377                     is try { $rsrc->column_info('id')->{is_auto_increment} }, 1,
378                         'column in database name with dash';
379
380                     is try { $rsrc->column_info('value')->{data_type} }, 'varchar',
381                         'column in database name with dash';
382
383                     is try { $rsrc->column_info('value')->{size} }, 100,
384                         'column in database name with dash';
385
386                     lives_and {
387                         ok $rs = $test_schema->resultset('MysqlLoaderTest4');
388                     } 'got resultset for table in database name with dash';
389
390                     lives_and {
391                         ok $row = $rs->create({ value => 'foo' });
392                     } 'executed SQL on table in database name with dash';
393
394                     SKIP: {
395                         skip 'set the environment variable DBICTEST_MYSQL_INNODB=1 to test relationships', 3 unless $test_innodb;
396
397                         $rel_info = try { $rsrc->relationship_info('dbicsl_dash_test_mysql_loader_test5') };
398
399                         is_deeply $rel_info->{cond}, {
400                             'foreign.four_id' => 'self.id'
401                         }, 'relationship in database name with dash';
402
403                         is $rel_info->{attrs}{accessor}, 'single',
404                             'relationship in database name with dash';
405
406                         is $rel_info->{attrs}{join_type}, 'LEFT',
407                             'relationship in database name with dash';
408                     }
409
410                     lives_and {
411                         ok $rsrc = $test_schema->source('DbicslDashTestMysqlLoaderTest5');
412                     } 'got source for table in database name with dash';
413
414                     %uniqs = try { $rsrc->unique_constraints };
415
416                     is keys %uniqs, 2,
417                         'got unique and primary constraint in database name with dash';
418
419                     delete $uniqs{primary};
420
421                     is_deeply ((values %uniqs)[0], ['four_id'],
422                         'unique constraint is correct in database name with dash');
423
424                     lives_and {
425                         ok $rsrc = $test_schema->source('MysqlLoaderTest6');
426                     } 'got source for table in database name with dot';
427
428                     is try { $rsrc->column_info('id')->{is_auto_increment} }, 1,
429                         'column in database name with dot introspected correctly';
430
431                     is try { $rsrc->column_info('value')->{data_type} }, 'varchar',
432                         'column in database name with dot introspected correctly';
433
434                     is try { $rsrc->column_info('value')->{size} }, 100,
435                         'column in database name with dot introspected correctly';
436
437                     lives_and {
438                         ok $rs = $test_schema->resultset('MysqlLoaderTest6');
439                     } 'got resultset for table in database name with dot';
440
441                     lives_and {
442                         ok $row = $rs->create({ value => 'foo' });
443                     } 'executed SQL on table in database name with dot';
444
445                     SKIP: {
446                         skip 'set the environment variable DBICTEST_MYSQL_INNODB=1 to test relationships', 3 unless $test_innodb;
447
448                         $rel_info = try { $rsrc->relationship_info('mysql_loader_test7') };
449
450                         is_deeply $rel_info->{cond}, {
451                             'foreign.six_id' => 'self.id'
452                         }, 'relationship in database name with dot';
453
454                         is $rel_info->{attrs}{accessor}, 'single',
455                             'relationship in database name with dot';
456
457                         is $rel_info->{attrs}{join_type}, 'LEFT',
458                             'relationship in database name with dot';
459                     }
460
461                     lives_and {
462                         ok $rsrc = $test_schema->source('MysqlLoaderTest7');
463                     } 'got source for table in database name with dot';
464
465                     %uniqs = try { $rsrc->unique_constraints };
466
467                     is keys %uniqs, 2,
468                         'got unique and primary constraint in database name with dot';
469
470                     delete $uniqs{primary};
471
472                     is_deeply ((values %uniqs)[0], ['six_id'],
473                         'unique constraint is correct in database name with dot');
474
475                     SKIP: {
476                         skip 'set the environment variable DBICTEST_MYSQL_INNODB=1 to test relationships', 4 unless $test_innodb;
477
478                         lives_and {
479                             ok $test_schema->source('MysqlLoaderTest6')
480                                 ->has_relationship('mysql_loader_test4');
481                         } 'cross-database relationship in multi-db_schema';
482
483                         lives_and {
484                             ok $test_schema->source('MysqlLoaderTest4')
485                                 ->has_relationship('mysql_loader_test6s');
486                         } 'cross-database relationship in multi-db_schema';
487
488                         lives_and {
489                             ok $test_schema->source('MysqlLoaderTest8')
490                                 ->has_relationship('mysql_loader_test7');
491                         } 'cross-database relationship in multi-db_schema';
492
493                         lives_and {
494                             ok $test_schema->source('MysqlLoaderTest7')
495                                 ->has_relationship('mysql_loader_test8s');
496                         } 'cross-database relationship in multi-db_schema';
497                     }
498                 }
499             }
500         },
501     },
502 );
503
504 if( !$dsn || !$user ) {
505     $tester->skip_tests('You need to set the DBICTEST_MYSQL_DSN, DBICTEST_MYSQL_USER, and DBICTEST_MYSQL_PASS environment variables');
506 }
507 else {
508     diag $skip_rels_msg if not $test_innodb;
509     $tester->run_tests();
510 }
511
512 END {
513     if (not $ENV{SCHEMA_LOADER_TESTS_NOCLEANUP}) {
514         if ($databases_created && (my $dbh = try { $schema->storage->dbh })) {
515             foreach my $table ('`dbicsl-test`.mysql_loader_test10',
516                                'dbicsl_test_ignored.mysql_loader_test9',
517                                '`dbicsl-test`.mysql_loader_test8',
518                                '`dbicsl.test`.mysql_loader_test7',
519                                '`dbicsl.test`.mysql_loader_test6',
520                                '`dbicsl.test`.mysql_loader_test5',
521                                '`dbicsl-test`.mysql_loader_test5',
522                                '`dbicsl-test`.mysql_loader_test4') {
523                 try {
524                     $dbh->do("DROP TABLE $table");
525                 }
526                 catch {
527                     diag "Error dropping table: $_";
528                 };
529             }
530
531             foreach my $db (qw/dbicsl-test dbicsl.test dbicsl_test_ignored/) {
532                 try {
533                     $dbh->do("DROP DATABASE `$db`");
534                 }
535                 catch {
536                     diag "Error dropping test database $db: $_";
537                 };
538             }
539         }
540         rmtree EXTRA_DUMP_DIR;
541     }
542 }
543 # vim:et sts=4 sw=4 tw=0: