Convert the tests with multiple DBDs to new optdeps system
[dbsrgits/DBIx-Class-Schema-Loader.git] / t / 10_07mssql_common.t
1 use strict;
2 use warnings;
3 use Test::More;
4 use Test::Exception;
5 use DBIx::Class::Schema::Loader::Optional::Dependencies;
6 use DBIx::Class::Schema::Loader::Utils qw/warnings_exist_silent sigwarn_silencer/;
7 use Try::Tiny;
8 use File::Path 'rmtree';
9 use DBIx::Class::Schema::Loader 'make_schema_at';
10 use namespace::clean;
11 use Scope::Guard ();
12
13 # use this if you keep a copy of DBD::Sybase linked to FreeTDS somewhere else
14 BEGIN {
15     if (my $lib_dirs = $ENV{DBICTEST_MSSQL_PERL5LIB}) {
16         unshift @INC, $_ for split /:/, $lib_dirs;
17     }
18 }
19
20 use lib qw(t/lib);
21
22 use dbixcsl_common_tests ();
23 use dbixcsl_test_dir '$tdir';
24
25 use constant EXTRA_DUMP_DIR => "$tdir/mssql_extra_dump";
26
27 # for extra tests cleanup
28 my $schema;
29
30 my (%dsns, $common_version);
31
32 my %env2optdep = (
33     MSSQL => 'test_rdbms_mssql_sybase',
34     MSSQL_ODBC => 'test_rdbms_mssql_odbc',
35     MSSQL_ADO => 'test_rdbms_mssql_ado',
36 );
37
38 plan skip_all => 'requirements not satisfied:  ' . (join '  OR  ', map
39     { "[ @{[ DBIx::Class::Schema::Loader::Optional::Dependencies->req_missing_for( $_ ) ]} ]" }
40     values %env2optdep
41 ) unless scalar grep
42     { DBIx::Class::Schema::Loader::Optional::Dependencies->req_ok_for( $_ ) }
43     values %env2optdep
44 ;
45
46 for my $type (keys %env2optdep) {
47     my %conninfo;
48     @conninfo{qw(dsn user password)} = map { $ENV{"DBICTEST_${type}_$_"} } qw(DSN USER PASS);
49     next unless $conninfo{dsn};
50
51     my $dep_group = $env2optdep{$type};
52     if (!DBIx::Class::Schema::Loader::Optional::Dependencies->req_ok_for($dep_group)) {
53         diag "Testing with DBICTEST_${type}_DSN needs " . DBIx::Class::Schema::Loader::Optional::Dependencies->req_missing_for($dep_group);
54         next;
55     }
56
57     $dsns{$type} = \%conninfo;
58
59     require DBI;
60     my $dbh = DBI->connect (@{$dsns{$type}}{qw/dsn user password/}, { RaiseError => 1, PrintError => 0} );
61     my $srv_ver = eval {
62         $dbh->get_info(18)
63             ||
64         $dbh->selectrow_hashref('master.dbo.xp_msver ProductVersion')->{Character_Value}
65     } || 0;
66
67     my ($maj_srv_ver) = $srv_ver =~ /^(\d+)/;
68
69     if (! defined $common_version or $common_version > $maj_srv_ver ) {
70         $common_version = $maj_srv_ver;
71     }
72 }
73
74 my $mssql_2008_new_data_types = {
75     date     => { data_type => 'date' },
76     time     => { data_type => 'time' },
77     'time(0)'=> { data_type => 'time', size => 0 },
78     'time(1)'=> { data_type => 'time', size => 1 },
79     'time(2)'=> { data_type => 'time', size => 2 },
80     'time(3)'=> { data_type => 'time', size => 3 },
81     'time(4)'=> { data_type => 'time', size => 4 },
82     'time(5)'=> { data_type => 'time', size => 5 },
83     'time(6)'=> { data_type => 'time', size => 6 },
84     'time(7)'=> { data_type => 'time' },
85     datetimeoffset => { data_type => 'datetimeoffset' },
86     'datetimeoffset(0)' => { data_type => 'datetimeoffset', size => 0 },
87     'datetimeoffset(1)' => { data_type => 'datetimeoffset', size => 1 },
88     'datetimeoffset(2)' => { data_type => 'datetimeoffset', size => 2 },
89     'datetimeoffset(3)' => { data_type => 'datetimeoffset', size => 3 },
90     'datetimeoffset(4)' => { data_type => 'datetimeoffset', size => 4 },
91     'datetimeoffset(5)' => { data_type => 'datetimeoffset', size => 5 },
92     'datetimeoffset(6)' => { data_type => 'datetimeoffset', size => 6 },
93     'datetimeoffset(7)' => { data_type => 'datetimeoffset' },
94     datetime2      => { data_type => 'datetime2' },
95     'datetime2(0)' => { data_type => 'datetime2', size => 0 },
96     'datetime2(1)' => { data_type => 'datetime2', size => 1 },
97     'datetime2(2)' => { data_type => 'datetime2', size => 2 },
98     'datetime2(3)' => { data_type => 'datetime2', size => 3 },
99     'datetime2(4)' => { data_type => 'datetime2', size => 4 },
100     'datetime2(5)' => { data_type => 'datetime2', size => 5 },
101     'datetime2(6)' => { data_type => 'datetime2', size => 6 },
102     'datetime2(7)' => { data_type => 'datetime2' },
103
104     hierarchyid      => { data_type => 'hierarchyid' },
105 };
106
107 my $tester = dbixcsl_common_tests->new(
108     vendor      => 'mssql',
109     auto_inc_pk => 'INTEGER IDENTITY NOT NULL PRIMARY KEY',
110     default_function_def => 'DATETIME DEFAULT getdate()',
111     connect_info => [ map { $dsns{$_} } sort keys %dsns ],
112     preserve_case_mode_is_exclusive => 1,
113     quote_char => [ qw/[ ]/ ],
114     basic_date_datatype => ($common_version >= 10) ? 'DATE' : 'SMALLDATETIME',
115     default_on_clause => 'NO ACTION',
116     data_types => {
117         # http://msdn.microsoft.com/en-us/library/ms187752.aspx
118
119         # numeric types
120         'int identity' => { data_type => 'integer', is_auto_increment => 1 },
121         bigint   => { data_type => 'bigint' },
122         int      => { data_type => 'integer' },
123         integer  => { data_type => 'integer' },
124         smallint => { data_type => 'smallint' },
125         tinyint  => { data_type => 'tinyint' },
126         money       => { data_type => 'money' },
127         smallmoney  => { data_type => 'smallmoney' },
128         bit         => { data_type => 'bit' },
129         real           => { data_type => 'real' },
130         'float(14)'    => { data_type => 'real' },
131         'float(24)'    => { data_type => 'real' },
132         'float(25)'    => { data_type => 'double precision' },
133         'float(53)'    => { data_type => 'double precision' },
134         float          => { data_type => 'double precision' },
135         'double precision'
136                        => { data_type => 'double precision' },
137         'numeric(6)'   => { data_type => 'numeric', size => [6,0] },
138         'numeric(6,3)' => { data_type => 'numeric', size => [6,3] },
139         'decimal(6)'   => { data_type => 'decimal', size => [6,0] },
140         'decimal(6,3)' => { data_type => 'decimal', size => [6,3] },
141         'dec(6,3)'     => { data_type => 'decimal', size => [6,3] },
142         numeric        => { data_type => 'numeric' },
143         decimal        => { data_type => 'decimal' },
144         dec            => { data_type => 'decimal' },
145
146         # datetime types
147         datetime => { data_type => 'datetime' },
148         # test rewriting getdate() to current_timestamp
149         'datetime default getdate()'
150                  => { data_type => 'datetime', default_value => \'current_timestamp',
151                       original => { default_value => \'getdate()' } },
152         smalldatetime  => { data_type => 'smalldatetime' },
153
154         ($common_version >= 10) ? %$mssql_2008_new_data_types : (),
155
156         # string types
157         char           => { data_type => 'char', size => 1 },
158         'char(2)'      => { data_type => 'char', size => 2 },
159         character      => { data_type => 'char', size => 1 },
160         'character(2)' => { data_type => 'char', size => 2 },
161         'varchar(2)'   => { data_type => 'varchar', size => 2 },
162
163         nchar          => { data_type => 'nchar', size => 1 },
164         'nchar(2)'     => { data_type => 'nchar', size => 2 },
165         'nvarchar(2)'  => { data_type => 'nvarchar', size => 2 },
166
167         # binary types
168         'binary'       => { data_type => 'binary', size => 1 },
169         'binary(2)'    => { data_type => 'binary', size => 2 },
170         'varbinary(2)' => { data_type => 'varbinary', size => 2 },
171
172         # blob types
173         'varchar(max)'   => { data_type => 'text' },
174         text             => { data_type => 'text' },
175
176         'nvarchar(max)'  => { data_type => 'ntext' },
177         ntext            => { data_type => 'ntext' },
178
179         'varbinary(max)' => { data_type => 'image' },
180         image            => { data_type => 'image' },
181
182         # other types
183         timestamp        => { data_type => 'timestamp', inflate_datetime => 0 },
184         rowversion       => { data_type => 'rowversion' },
185         uniqueidentifier => { data_type => 'uniqueidentifier' },
186         sql_variant      => { data_type => 'sql_variant' },
187         xml              => { data_type => 'xml' },
188     },
189     extra => {
190         create => [
191             q{
192                 CREATE TABLE [mssql_loader_test1.dot] (
193                     id INT IDENTITY NOT NULL PRIMARY KEY,
194                     dat VARCHAR(8)
195                 )
196             },
197             q{
198                 CREATE TABLE mssql_loader_test3 (
199                     id INT IDENTITY NOT NULL PRIMARY KEY
200                 )
201             },
202             q{
203                 CREATE VIEW mssql_loader_test4 AS
204                 SELECT * FROM mssql_loader_test3
205             },
206             # test capitalization of cols in unique constraints and rels
207             q{ SET QUOTED_IDENTIFIER ON },
208             q{ SET ANSI_NULLS ON },
209             q{
210                 CREATE TABLE [MSSQL_Loader_Test5] (
211                     [Id] INT IDENTITY NOT NULL PRIMARY KEY,
212                     [FooCol] INT NOT NULL,
213                     [BarCol] INT NOT NULL,
214                     UNIQUE ([FooCol], [BarCol])
215                 )
216             },
217             q{
218                 CREATE TABLE [MSSQL_Loader_Test6] (
219                     [Five_Id] INT REFERENCES [MSSQL_Loader_Test5] ([Id])
220                 )
221             },
222             # 8 through 12 are used for the multi-schema tests and 13 through 16 are used for multi-db tests
223             q{
224                 create table mssql_loader_test17 (
225                     id int identity primary key
226                 )
227             },
228             q{
229                 create table mssql_loader_test18 (
230                     id int identity primary key,
231                     seventeen_id int,
232                     foreign key (seventeen_id) references mssql_loader_test17(id)
233                         on delete set default on update set null
234                 )
235             },
236         ],
237         pre_drop_ddl => [
238             'CREATE TABLE mssql_loader_test3 (id INT IDENTITY NOT NULL PRIMARY KEY)',
239             'DROP VIEW mssql_loader_test4',
240         ],
241         drop   => [
242             '[mssql_loader_test1.dot]',
243             'mssql_loader_test3',
244             'MSSQL_Loader_Test6',
245             'MSSQL_Loader_Test5',
246             'mssql_loader_test17',
247             'mssql_loader_test18',
248         ],
249         count  => 14 + 30 * 2 + 26 * 2, # extra + multi-schema + mutli-db
250         run    => sub {
251             my ($monikers, $classes, $self);
252             ($schema, $monikers, $classes, $self) = @_;
253
254             my $connect_info = [@$self{qw/dsn user password/}];
255
256 # Test that the table above (with '.' in name) gets loaded correctly.
257             ok((my $rs = eval {
258                 $schema->resultset('MssqlLoaderTest1Dot') }),
259                 'got a resultset for table with dot in name');
260
261             ok((my $from = eval { $rs->result_source->from }),
262                 'got an $rsrc->from for table with dot in name');
263
264             is ref($from), 'SCALAR', '->table with dot in name is a scalar ref';
265
266             is eval { $$from }, "[mssql_loader_test1.dot]",
267                 '->table with dot in name has correct name';
268
269 # Test capitalization of columns and unique constraints
270             ok ((my $rsrc = $schema->resultset($monikers->{mssql_loader_test5})->result_source),
271                 'got result_source');
272
273             if ($schema->loader->preserve_case) {
274                 is_deeply [ $rsrc->columns ], [qw/Id FooCol BarCol/],
275                     'column name case is preserved with case-sensitive collation';
276
277                 my %uniqs = $rsrc->unique_constraints;
278                 delete $uniqs{primary};
279
280                 is_deeply ((values %uniqs)[0], [qw/FooCol BarCol/],
281                     'column name case is preserved in unique constraint with case-sensitive collation');
282             }
283             else {
284                 is_deeply [ $rsrc->columns ], [qw/id foocol barcol/],
285                     'column names are lowercased for case-insensitive collation';
286
287                 my %uniqs = $rsrc->unique_constraints;
288                 delete $uniqs{primary};
289
290                 is_deeply ((values %uniqs)[0], [qw/foocol barcol/],
291                     'columns in unique constraint lowercased for case-insensitive collation');
292             }
293
294             lives_and {
295                 my $five_row = $schema->resultset($monikers->{mssql_loader_test5})->new_result({});
296
297                 if ($schema->loader->preserve_case) {
298                     $five_row->foo_col(1);
299                     $five_row->bar_col(2);
300                 }
301                 else {
302                     $five_row->foocol(1);
303                     $five_row->barcol(2);
304                 }
305                 $five_row->insert;
306
307                 my $six_row = $five_row->create_related('mssql_loader_test6s', {});
308
309                 is $six_row->five->id, 1;
310             } 'relationships for mixed-case tables/columns detected';
311
312 # Test that a bad view (where underlying table is gone) is ignored.
313             my $dbh = $schema->storage->dbh;
314             $dbh->do("DROP TABLE mssql_loader_test3");
315
316             warnings_exist_silent { $schema->rescan }
317               qr/^Bad table or view 'mssql_loader_test4'/, 'bad view ignored';
318
319             throws_ok {
320                 $schema->resultset($monikers->{mssql_loader_test4})
321             } qr/Can't find source/,
322                 'no source registered for bad view';
323
324             # test on delete/update fk clause introspection
325             ok ((my $rel_info = $schema->source('MssqlLoaderTest18')->relationship_info('seventeen')),
326                 'got rel info');
327
328             is $rel_info->{attrs}{on_delete}, 'SET DEFAULT',
329                 'ON DELETE clause introspected correctly';
330
331             is $rel_info->{attrs}{on_update}, 'SET NULL',
332                 'ON UPDATE clause introspected correctly';
333
334             is $rel_info->{attrs}{is_deferrable}, 1,
335                 'is_deferrable defaults to 1';
336
337             SKIP: {
338                 my $dbh = $schema->storage->dbh;
339
340                 try {
341                     $dbh->do('CREATE SCHEMA [dbicsl-test]');
342                 }
343                 catch {
344                     skip "no CREATE SCHEMA privileges", 30 * 2;
345                 };
346
347                 $dbh->do(<<"EOF");
348                     CREATE TABLE [dbicsl-test].mssql_loader_test8 (
349                         id INT IDENTITY PRIMARY KEY,
350                         value VARCHAR(100)
351                     )
352 EOF
353                 $dbh->do(<<"EOF");
354                     CREATE TABLE [dbicsl-test].mssql_loader_test9 (
355                         id INT IDENTITY PRIMARY KEY,
356                         value VARCHAR(100),
357                         eight_id INTEGER NOT NULL,
358                         CONSTRAINT loader_test9_uniq UNIQUE (eight_id),
359                         FOREIGN KEY (eight_id) REFERENCES [dbicsl-test].mssql_loader_test8 (id)
360                     )
361 EOF
362                 $dbh->do('CREATE SCHEMA [dbicsl.test]');
363                 $dbh->do(<<"EOF");
364                     CREATE TABLE [dbicsl.test].mssql_loader_test9 (
365                         pk INT IDENTITY PRIMARY KEY,
366                         value VARCHAR(100),
367                         eight_id INTEGER NOT NULL,
368                         CONSTRAINT loader_test9_uniq UNIQUE (eight_id),
369                         FOREIGN KEY (eight_id) REFERENCES [dbicsl-test].mssql_loader_test8 (id)
370                     )
371 EOF
372                 $dbh->do(<<"EOF");
373                     CREATE TABLE [dbicsl.test].mssql_loader_test10 (
374                         id INT IDENTITY PRIMARY KEY,
375                         value VARCHAR(100),
376                         mssql_loader_test8_id INTEGER,
377                         FOREIGN KEY (mssql_loader_test8_id) REFERENCES [dbicsl-test].mssql_loader_test8 (id)
378                     )
379 EOF
380                 $dbh->do(<<"EOF");
381                     CREATE TABLE [dbicsl.test].mssql_loader_test11 (
382                         id INT IDENTITY PRIMARY KEY,
383                         value VARCHAR(100),
384                         ten_id INTEGER NOT NULL UNIQUE,
385                         FOREIGN KEY (ten_id) REFERENCES [dbicsl.test].mssql_loader_test10 (id)
386                     )
387 EOF
388                 $dbh->do(<<"EOF");
389                     CREATE TABLE [dbicsl-test].mssql_loader_test12 (
390                         id INT IDENTITY PRIMARY KEY,
391                         value VARCHAR(100),
392                         mssql_loader_test11_id INTEGER,
393                         FOREIGN KEY (mssql_loader_test11_id) REFERENCES [dbicsl.test].mssql_loader_test11 (id)
394                     )
395 EOF
396
397                 my $guard = Scope::Guard->new(\&cleanup_schemas);
398
399                 foreach my $db_schema (['dbicsl-test', 'dbicsl.test'], '%') {
400                     lives_and {
401                         rmtree EXTRA_DUMP_DIR;
402
403                         my @warns;
404                         local $SIG{__WARN__} = sub {
405                             push @warns, $_[0] unless $_[0] =~ /\bcollides\b/;
406                         };
407
408                         make_schema_at(
409                             'MSSQLMultiSchema',
410                             {
411                                 naming => 'current',
412                                 db_schema => $db_schema,
413                                 dump_directory => EXTRA_DUMP_DIR,
414                                 quiet => 1,
415                             },
416                             $connect_info,
417                         );
418
419                         diag join "\n", @warns if @warns;
420
421                         is @warns, 0;
422                     } 'dumped schema for "dbicsl-test" and "dbicsl.test" schemas with no warnings';
423
424                     my ($test_schema, $rsrc, $rs, $row, %uniqs, $rel_info);
425
426                     lives_and {
427                         ok $test_schema = MSSQLMultiSchema->connect(@$connect_info);
428                     } 'connected test schema';
429
430                     lives_and {
431                         ok $rsrc = $test_schema->source('MssqlLoaderTest8');
432                     } 'got source for table in schema name with dash';
433
434                     is try { $rsrc->column_info('id')->{is_auto_increment} }, 1,
435                         'column in schema name with dash';
436
437                     is try { $rsrc->column_info('value')->{data_type} }, 'varchar',
438                         'column in schema name with dash';
439
440                     is try { $rsrc->column_info('value')->{size} }, 100,
441                         'column in schema name with dash';
442
443                     lives_and {
444                         ok $rs = $test_schema->resultset('MssqlLoaderTest8');
445                     } 'got resultset for table in schema name with dash';
446
447                     lives_and {
448                         ok $row = $rs->create({ value => 'foo' });
449                     } 'executed SQL on table in schema name with dash';
450
451                     $rel_info = try { $rsrc->relationship_info('dbicsl_dash_test_mssql_loader_test9') };
452
453                     is_deeply $rel_info->{cond}, {
454                         'foreign.eight_id' => 'self.id'
455                     }, 'relationship in schema name with dash';
456
457                     is $rel_info->{attrs}{accessor}, 'single',
458                         'relationship in schema name with dash';
459
460                     is $rel_info->{attrs}{join_type}, 'LEFT',
461                         'relationship in schema name with dash';
462
463                     lives_and {
464                         ok $rsrc = $test_schema->source('DbicslDashTestMssqlLoaderTest9');
465                     } 'got source for table in schema name with dash';
466
467                     %uniqs = try { $rsrc->unique_constraints };
468
469                     is keys %uniqs, 2,
470                         'got unique and primary constraint in schema name with dash';
471
472                     delete $uniqs{primary};
473
474                     is_deeply ((values %uniqs)[0], ['eight_id'],
475                         'correct unique constraint in schema name with dash');
476
477                     lives_and {
478                         ok $rsrc = $test_schema->source('MssqlLoaderTest10');
479                     } 'got source for table in schema name with dot';
480
481                     is try { $rsrc->column_info('id')->{is_auto_increment} }, 1,
482                         'column in schema name with dot introspected correctly';
483
484                     is try { $rsrc->column_info('value')->{data_type} }, 'varchar',
485                         'column in schema name with dot introspected correctly';
486
487                     is try { $rsrc->column_info('value')->{size} }, 100,
488                         'column in schema name with dot introspected correctly';
489
490                     lives_and {
491                         ok $rs = $test_schema->resultset('MssqlLoaderTest10');
492                     } 'got resultset for table in schema name with dot';
493
494                     lives_and {
495                         ok $row = $rs->create({ value => 'foo' });
496                     } 'executed SQL on table in schema name with dot';
497
498                     $rel_info = try { $rsrc->relationship_info('mssql_loader_test11') };
499
500                     is_deeply $rel_info->{cond}, {
501                         'foreign.ten_id' => 'self.id'
502                     }, 'relationship in schema name with dot';
503
504                     is $rel_info->{attrs}{accessor}, 'single',
505                         'relationship in schema name with dot';
506
507                     is $rel_info->{attrs}{join_type}, 'LEFT',
508                         'relationship in schema name with dot';
509
510                     lives_and {
511                         ok $rsrc = $test_schema->source('MssqlLoaderTest11');
512                     } 'got source for table in schema name with dot';
513
514                     %uniqs = try { $rsrc->unique_constraints };
515
516                     is keys %uniqs, 2,
517                         'got unique and primary constraint in schema name with dot';
518
519                     delete $uniqs{primary};
520
521                     is_deeply ((values %uniqs)[0], ['ten_id'],
522                         'correct unique constraint in schema name with dot');
523
524                     lives_and {
525                         ok $test_schema->source('MssqlLoaderTest10')
526                             ->has_relationship('mssql_loader_test8');
527                     } 'cross-schema relationship in multi-db_schema';
528
529                     lives_and {
530                         ok $test_schema->source('MssqlLoaderTest8')
531                             ->has_relationship('mssql_loader_test10s');
532                     } 'cross-schema relationship in multi-db_schema';
533
534                     lives_and {
535                         ok $test_schema->source('MssqlLoaderTest12')
536                             ->has_relationship('mssql_loader_test11');
537                     } 'cross-schema relationship in multi-db_schema';
538
539                     lives_and {
540                         ok $test_schema->source('MssqlLoaderTest11')
541                             ->has_relationship('mssql_loader_test12s');
542                     } 'cross-schema relationship in multi-db_schema';
543                 }
544             }
545
546             SKIP: {
547                 # for ADO
548                 local $SIG{__WARN__} = sigwarn_silencer(
549                     qr/Changed database context/
550                 );
551
552                 my $dbh = $schema->storage->dbh;
553
554                 try {
555                     $dbh->do('USE master');
556                     $dbh->do('CREATE DATABASE dbicsl_test1');
557                 }
558                 catch {
559                     diag "no CREATE DATABASE privileges: '$_'";
560                     skip "no CREATE DATABASE privileges", 26 * 2;
561                 };
562
563                 $dbh->do('CREATE DATABASE dbicsl_test2');
564
565                 $dbh->do('USE dbicsl_test1');
566
567                 $dbh->do(<<'EOF');
568                     CREATE TABLE mssql_loader_test13 (
569                         id INT IDENTITY PRIMARY KEY,
570                         value VARCHAR(100)
571                     )
572 EOF
573                 $dbh->do(<<'EOF');
574                     CREATE TABLE mssql_loader_test14 (
575                         id INT IDENTITY PRIMARY KEY,
576                         value VARCHAR(100),
577                         thirteen_id INTEGER REFERENCES mssql_loader_test13 (id),
578                         CONSTRAINT loader_test14_uniq UNIQUE (thirteen_id)
579                     )
580 EOF
581
582                 $dbh->do('USE dbicsl_test2');
583
584                 $dbh->do(<<'EOF');
585                     CREATE TABLE mssql_loader_test14 (
586                         pk INT IDENTITY PRIMARY KEY,
587                         value VARCHAR(100),
588                         thirteen_id INTEGER,
589                         CONSTRAINT loader_test14_uniq UNIQUE (thirteen_id)
590                     )
591 EOF
592
593                 $dbh->do(<<"EOF");
594                     CREATE TABLE mssql_loader_test15 (
595                         id INT IDENTITY PRIMARY KEY,
596                         value VARCHAR(100)
597                     )
598 EOF
599                 $dbh->do(<<"EOF");
600                     CREATE TABLE mssql_loader_test16 (
601                         id INT IDENTITY PRIMARY KEY,
602                         value VARCHAR(100),
603                         fifteen_id INTEGER UNIQUE REFERENCES mssql_loader_test15 (id)
604                     )
605 EOF
606
607                 my $guard = Scope::Guard->new(\&cleanup_databases);
608
609                 foreach my $db_schema ({ dbicsl_test1 => '%', dbicsl_test2 => '%' }, { '%' => '%' }) {
610                     lives_and {
611                         my @warns;
612                         local $SIG{__WARN__} = sub {
613                             push @warns, $_[0] unless $_[0] =~ /\bcollides\b/;
614                         };
615
616                         make_schema_at(
617                             'MSSQLMultiDatabase',
618                             {
619                                 naming => 'current',
620                                 db_schema => $db_schema,
621                                 dump_directory => EXTRA_DUMP_DIR,
622                                 quiet => 1,
623                             },
624                             $connect_info,
625                         );
626
627                         diag join "\n", @warns if @warns;
628
629                         is @warns, 0;
630                     } "dumped schema for databases 'dbicsl_test1' and 'dbicsl_test2' with no warnings";
631
632                     my $test_schema;
633
634                     lives_and {
635                         ok $test_schema = MSSQLMultiDatabase->connect(@$connect_info);
636                     } 'connected test schema';
637
638                     my ($rsrc, $rs, $row, $rel_info, %uniqs);
639
640                     lives_and {
641                         ok $rsrc = $test_schema->source('MssqlLoaderTest13');
642                     } 'got source for table in database one';
643
644                     is try { $rsrc->column_info('id')->{is_auto_increment} }, 1,
645                         'column in database one';
646
647                     is try { $rsrc->column_info('value')->{data_type} }, 'varchar',
648                         'column in database one';
649
650                     is try { $rsrc->column_info('value')->{size} }, 100,
651                         'column in database one';
652
653                     lives_and {
654                         ok $rs = $test_schema->resultset('MssqlLoaderTest13');
655                     } 'got resultset for table in database one';
656
657                     lives_and {
658                         ok $row = $rs->create({ value => 'foo' });
659                     } 'executed SQL on table in database one';
660
661                     $rel_info = try { $rsrc->relationship_info('mssql_loader_test14') };
662
663                     is_deeply $rel_info->{cond}, {
664                         'foreign.thirteen_id' => 'self.id'
665                     }, 'relationship in database one';
666
667                     is $rel_info->{attrs}{accessor}, 'single',
668                         'relationship in database one';
669
670                     is $rel_info->{attrs}{join_type}, 'LEFT',
671                         'relationship in database one';
672
673                     lives_and {
674                         ok $rsrc = $test_schema->source('DbicslTest1MssqlLoaderTest14');
675                     } 'got source for table in database one';
676
677                     %uniqs = try { $rsrc->unique_constraints };
678
679                     is keys %uniqs, 2,
680                         'got unique and primary constraint in database one';
681
682                     delete $uniqs{primary};
683
684                     is_deeply ((values %uniqs)[0], ['thirteen_id'],
685                         'correct unique constraint in database one');
686
687                     lives_and {
688                         ok $rsrc = $test_schema->source('MssqlLoaderTest15');
689                     } 'got source for table in database two';
690
691                     is try { $rsrc->column_info('id')->{is_auto_increment} }, 1,
692                         'column in database two introspected correctly';
693
694                     is try { $rsrc->column_info('value')->{data_type} }, 'varchar',
695                         'column in database two introspected correctly';
696
697                     is try { $rsrc->column_info('value')->{size} }, 100,
698                         'column in database two introspected correctly';
699
700                     lives_and {
701                         ok $rs = $test_schema->resultset('MssqlLoaderTest15');
702                     } 'got resultset for table in database two';
703
704                     lives_and {
705                         ok $row = $rs->create({ value => 'foo' });
706                     } 'executed SQL on table in database two';
707
708                     $rel_info = try { $rsrc->relationship_info('mssql_loader_test16') };
709
710                     is_deeply $rel_info->{cond}, {
711                         'foreign.fifteen_id' => 'self.id'
712                     }, 'relationship in database two';
713
714                     is $rel_info->{attrs}{accessor}, 'single',
715                         'relationship in database two';
716
717                     is $rel_info->{attrs}{join_type}, 'LEFT',
718                         'relationship in database two';
719
720                     lives_and {
721                         ok $rsrc = $test_schema->source('MssqlLoaderTest16');
722                     } 'got source for table in database two';
723
724                     %uniqs = try { $rsrc->unique_constraints };
725
726                     is keys %uniqs, 2,
727                         'got unique and primary constraint in database two';
728
729                     delete $uniqs{primary};
730
731                     is_deeply ((values %uniqs)[0], ['fifteen_id'],
732                         'correct unique constraint in database two');
733                 }
734             }
735         },
736     },
737 );
738
739 $tester->run_tests();
740
741 sub cleanup_schemas {
742     return if $ENV{SCHEMA_LOADER_TESTS_NOCLEANUP};
743
744     # switch back to default database
745     $schema->storage->disconnect;
746     my $dbh = $schema->storage->dbh;
747
748     foreach my $table ('[dbicsl-test].mssql_loader_test12',
749                        '[dbicsl.test].mssql_loader_test11',
750                        '[dbicsl.test].mssql_loader_test10',
751                        '[dbicsl.test].mssql_loader_test9',
752                        '[dbicsl-test].mssql_loader_test9',
753                        '[dbicsl-test].mssql_loader_test8') {
754         try {
755             $dbh->do("DROP TABLE $table");
756         }
757         catch {
758             diag "Error dropping table: $_";
759         };
760     }
761
762     foreach my $db_schema (qw/dbicsl-test dbicsl.test/) {
763         try {
764             $dbh->do(qq{DROP SCHEMA [$db_schema]});
765         }
766         catch {
767             diag "Error dropping test schema $db_schema: $_";
768         };
769     }
770
771     rmtree EXTRA_DUMP_DIR;
772 }
773
774 sub cleanup_databases {
775     return if $ENV{SCHEMA_LOADER_TESTS_NOCLEANUP};
776
777     # for ADO
778     local $SIG{__WARN__} = sigwarn_silencer(
779         qr/Changed database context/
780     );
781
782     my $dbh = $schema->storage->dbh;
783
784     $dbh->do('USE dbicsl_test1');
785
786     foreach my $table ('mssql_loader_test14',
787                        'mssql_loader_test13') {
788         try {
789             $dbh->do("DROP TABLE $table");
790         }
791         catch {
792             diag "Error dropping table: $_";
793         };
794     }
795
796     $dbh->do('USE dbicsl_test2');
797
798     foreach my $table ('mssql_loader_test16',
799                        'mssql_loader_test15',
800                        'mssql_loader_test14') {
801         try {
802             $dbh->do("DROP TABLE $table");
803         }
804         catch {
805             diag "Error dropping table: $_";
806         };
807     }
808
809     $dbh->do('USE master');
810
811     foreach my $database (qw/dbicsl_test1 dbicsl_test2/) {
812         try {
813             $dbh->do(qq{DROP DATABASE $database});
814         }
815         catch {
816             diag "Error dropping test database '$database': $_";
817         };
818     }
819
820     rmtree EXTRA_DUMP_DIR;
821 }
822 # vim:et sts=4 sw=4 tw=0: