multi db_schema support
[dbsrgits/DBIx-Class-Schema-Loader.git] / t / 10_06sybase_common.t
CommitLineData
fe67d343 1use strict;
c4a69b87 2use warnings;
804c115d 3use Test::More;
2d1dc6de 4use Test::Exception;
c4a69b87 5use Try::Tiny;
6use File::Path 'rmtree';
7use DBIx::Class::Schema::Loader 'make_schema_at';
8use DBI ();
9
10use lib qw(t/lib);
11
12use dbixcsl_common_tests ();
13use dbixcsl_test_dir '$tdir';
14
15use constant EXTRA_DUMP_DIR => "$tdir/sybase_extra_dump";
f9f65ded 16
fe67d343 17my $dsn = $ENV{DBICTEST_SYBASE_DSN} || '';
18my $user = $ENV{DBICTEST_SYBASE_USER} || '';
19my $password = $ENV{DBICTEST_SYBASE_PASS} || '';
20
c4a69b87 21my ($schema, $databases_created); # for cleanup in END for extra tests
22
fe67d343 23my $tester = dbixcsl_common_tests->new(
7cb9244f 24 vendor => 'sybase',
fe67d343 25 auto_inc_pk => 'INTEGER IDENTITY NOT NULL PRIMARY KEY',
41968729 26 default_function => 'getdate()',
27 default_function_def => 'AS getdate()',
fe67d343 28 dsn => $dsn,
29 user => $user,
30 password => $password,
5163dc4a 31 data_types => {
760fd65c 32 # http://ispirer.com/wiki/sqlways/sybase/data-types
6bbfc7ed 33 #
34 # Numeric Types
5163dc4a 35 'integer identity' => { data_type => 'integer', is_auto_increment => 1 },
5163dc4a 36 int => { data_type => 'integer' },
37 integer => { data_type => 'integer' },
6bbfc7ed 38 bigint => { data_type => 'bigint' },
5163dc4a 39 smallint => { data_type => 'smallint' },
40 tinyint => { data_type => 'tinyint' },
6bbfc7ed 41 'double precision' => { data_type => 'double precision' },
42 real => { data_type => 'real' },
43 float => { data_type => 'double precision' },
44 'float(14)' => { data_type => 'real' },
45 'float(15)' => { data_type => 'real' },
46 'float(16)' => { data_type => 'double precision' },
47 'float(48)' => { data_type => 'double precision' },
48 'numeric(6,3)' => { data_type => 'numeric', size => [6,3] },
49 'decimal(6,3)' => { data_type => 'numeric', size => [6,3] },
50 numeric => { data_type => 'numeric' },
51 decimal => { data_type => 'numeric' },
52 bit => { data_type => 'bit' },
53
54 # Money Types
55 money => { data_type => 'money' },
56 smallmoney => { data_type => 'smallmoney' },
57
58 # Computed Column
59 'AS getdate()' => { data_type => undef, inflate_datetime => 1, default_value => \'getdate()' },
60
61 # Blob Types
62 text => { data_type => 'text' },
63 unitext => { data_type => 'unitext' },
64 image => { data_type => 'image' },
65
66 # DateTime Types
5163dc4a 67 date => { data_type => 'date' },
68 time => { data_type => 'time' },
69 datetime => { data_type => 'datetime' },
70 smalldatetime => { data_type => 'smalldatetime' },
6bbfc7ed 71
72 # Timestamp column
5163dc4a 73 timestamp => { data_type => 'timestamp', inflate_datetime => 0 },
6bbfc7ed 74
75 # String Types
76 'char' => { data_type => 'char', size => 1 },
5163dc4a 77 'char(2)' => { data_type => 'char', size => 2 },
6bbfc7ed 78 'nchar' => { data_type => 'nchar', size => 1 },
5163dc4a 79 'nchar(2)' => { data_type => 'nchar', size => 2 },
80 'unichar(2)' => { data_type => 'unichar', size => 2 },
81 'varchar(2)' => { data_type => 'varchar', size => 2 },
82 'nvarchar(2)' => { data_type => 'nvarchar', size => 2 },
83 'univarchar(2)' => { data_type => 'univarchar', size => 2 },
6bbfc7ed 84
85 # Binary Types
86 'binary' => { data_type => 'binary', size => 1 },
5163dc4a 87 'binary(2)' => { data_type => 'binary', size => 2 },
88 'varbinary(2)' => { data_type => 'varbinary', size => 2 },
804c115d 89 },
8f65b7e5 90 # test that named constraints aren't picked up as tables (I can't reproduce this on my machine)
91 failtrigger_warnings => [ qr/^Bad table or view 'sybase_loader_test2_ref_slt1'/ ],
5c1b0a23 92 extra => {
93 create => [
94 q{
95 CREATE TABLE sybase_loader_test1 (
96 id int identity primary key
97 )
98 },
99 q{
100 CREATE TABLE sybase_loader_test2 (
101 id int identity primary key,
102 sybase_loader_test1_id int,
103 CONSTRAINT sybase_loader_test2_ref_slt1 FOREIGN KEY (sybase_loader_test1_id) REFERENCES sybase_loader_test1 (id)
104 )
105 },
106 ],
107 drop => [ qw/sybase_loader_test1 sybase_loader_test2/ ],
c4a69b87 108 count => 28 * 4,
109 run => sub {
110 $schema = shift;
111
112 SKIP: {
113 my $dbh = $schema->storage->dbh;
114
115 try {
116 $dbh->do('USE master');
117 }
118 catch {
119 skip "these tests require the sysadmin role", 28 * 4;
120 };
121
122 try {
123 $dbh->do('CREATE DATABASE [dbicsl_test1]');
124 $dbh->do('CREATE DATABASE [dbicsl_test2]');
125 }
126 catch {
127 skip "cannot create databases: $_", 28 * 4;
128 };
129
130 try {
131 my $warn_handler = $SIG{__WARN__} || sub { warn @_ };
132 local $SIG{__WARN__} = sub {
133 $warn_handler->(@_)
134 unless $_[0] =~ /^Password correctly set\.$|^Account unlocked\.$|^New login created\.$|^New user added\.$/;
135 };
136
137 $dbh->do("sp_addlogin dbicsl_user1, dbicsl, [dbicsl_test1]");
138 $dbh->do("sp_addlogin dbicsl_user2, dbicsl, [dbicsl_test2]");
139
140 $dbh->do("USE [dbicsl_test1]");
141 $dbh->do("sp_adduser dbicsl_user1");
142 $dbh->do("sp_adduser dbicsl_user2");
143 $dbh->do("GRANT ALL TO dbicsl_user1");
144 $dbh->do("GRANT ALL TO dbicsl_user2");
145
146 $dbh->do("USE [dbicsl_test2]");
147 $dbh->do("sp_adduser dbicsl_user2");
148 $dbh->do("sp_adduser dbicsl_user1");
149 $dbh->do("GRANT ALL TO dbicsl_user2");
150 $dbh->do("GRANT ALL TO dbicsl_user1");
151 }
152 catch {
153 skip "cannot add logins: $_", 28 * 4;
154 };
155
156 my ($dbh1, $dbh2);
157 {
158 my $warn_handler = $SIG{__WARN__} || sub { warn @_ };
159 local $SIG{__WARN__} = sub {
160 $warn_handler->(@_) unless $_[0] =~ /can't change context/;
161 };
162
163 $dbh1 = DBI->connect($dsn, 'dbicsl_user1', 'dbicsl', {
164 RaiseError => 1,
165 PrintError => 0,
166 });
167 $dbh1->do('USE [dbicsl_test1]');
168
169 $dbh2 = DBI->connect($dsn, 'dbicsl_user2', 'dbicsl', {
170 RaiseError => 1,
171 PrintError => 0,
172 });
173 $dbh2->do('USE [dbicsl_test2]');
174 }
175
176 $dbh1->do(<<"EOF");
177 CREATE TABLE sybase_loader_test4 (
178 id INT IDENTITY PRIMARY KEY,
179 value VARCHAR(100) NULL
180 )
181EOF
182 $dbh1->do('GRANT ALL ON sybase_loader_test4 TO dbicsl_user2');
183 $dbh1->do(<<"EOF");
184 CREATE TABLE sybase_loader_test5 (
185 id INT IDENTITY PRIMARY KEY,
186 value VARCHAR(100) NULL,
187 four_id INTEGER UNIQUE,
188 FOREIGN KEY (four_id) REFERENCES sybase_loader_test4 (id)
189 )
190EOF
191 $dbh2->do(<<"EOF");
192 CREATE TABLE sybase_loader_test6 (
193 id INT IDENTITY PRIMARY KEY,
194 value VARCHAR(100) NULL,
195 sybase_loader_test4_id INTEGER NULL,
196 FOREIGN KEY (sybase_loader_test4_id) REFERENCES [dbicsl_test1].dbicsl_user1.sybase_loader_test4 (id)
197 )
198EOF
199 $dbh2->do(<<"EOF");
200 CREATE TABLE sybase_loader_test7 (
201 id INT IDENTITY PRIMARY KEY,
202 value VARCHAR(100) NULL,
203 six_id INTEGER UNIQUE,
204 FOREIGN KEY (six_id) REFERENCES sybase_loader_test6 (id)
205 )
206EOF
207 $dbh2->do('GRANT ALL ON sybase_loader_test7 TO dbicsl_user1');
208 $dbh1->do(<<"EOF");
209 CREATE TABLE sybase_loader_test8 (
210 id INT IDENTITY PRIMARY KEY,
211 value VARCHAR(100) NULL,
212 sybase_loader_test7_id INTEGER,
213 FOREIGN KEY (sybase_loader_test7_id) REFERENCES [dbicsl_test2].dbicsl_user2.sybase_loader_test7 (id)
214 )
215EOF
216
217 $databases_created = 1;
218
219 foreach my $databases (['dbicsl_test1', 'dbicsl_test2'], '%') {
220 foreach my $owners ([qw/dbicsl_user1 dbicsl_user2/], '%') {
221 lives_and {
222 rmtree EXTRA_DUMP_DIR;
223
224 my @warns;
225 local $SIG{__WARN__} = sub {
226 push @warns, $_[0] unless $_[0] =~ /\bcollides\b/
227 || $_[0] =~ /can't change context/;
228 };
229
230 my $database = $databases;
231
232 $database = [ $database ] unless ref $database;
233
234 my $db_schema = {};
235
236 foreach my $db (@$database) {
237 $db_schema->{$db} = $owners;
238 }
239
240 make_schema_at(
241 'SybaseMultiSchema',
242 {
243 naming => 'current',
244 db_schema => $db_schema,
245 dump_directory => EXTRA_DUMP_DIR,
246 quiet => 1,
247 },
248 [ $dsn, $user, $password ],
249 );
250
251 diag join "\n", @warns if @warns;
252
253 is @warns, 0;
254 } 'dumped schema for "dbicsl_test1" and "dbicsl_test2" databases with no warnings';
255
256 my ($test_schema, $rsrc, $rs, $row, %uniqs, $rel_info);
257
258 lives_and {
259 ok $test_schema = SybaseMultiSchema->connect($dsn, $user, $password);
260 } 'connected test schema';
261
262 lives_and {
263 ok $rsrc = $test_schema->source('SybaseLoaderTest4');
264 } 'got source for table in database one';
265
266 is try { $rsrc->column_info('id')->{is_auto_increment} }, 1,
267 'column in database one';
268
269 is try { $rsrc->column_info('value')->{data_type} }, 'varchar',
270 'column in database one';
271
272 is try { $rsrc->column_info('value')->{size} }, 100,
273 'column in database one';
274
275 lives_and {
276 ok $rs = $test_schema->resultset('SybaseLoaderTest4');
277 } 'got resultset for table in database one';
278
279 lives_and {
280 ok $row = $rs->create({ value => 'foo' });
281 } 'executed SQL on table in database one';
282
283 $rel_info = try { $rsrc->relationship_info('sybase_loader_test5') };
284
285 is_deeply $rel_info->{cond}, {
286 'foreign.four_id' => 'self.id'
287 }, 'relationship in database one';
288
289 is $rel_info->{attrs}{accessor}, 'single',
290 'relationship in database one';
291
292 is $rel_info->{attrs}{join_type}, 'LEFT',
293 'relationship in database one';
294
295 lives_and {
296 ok $rsrc = $test_schema->source('SybaseLoaderTest5');
297 } 'got source for table in database one';
298
299 %uniqs = try { $rsrc->unique_constraints };
300
301 is keys %uniqs, 2,
302 'got unique and primary constraint in database one';
303
304 lives_and {
305 ok $rsrc = $test_schema->source('SybaseLoaderTest6');
306 } 'got source for table in database two';
307
308 is try { $rsrc->column_info('id')->{is_auto_increment} }, 1,
309 'column in database two introspected correctly';
310
311 is try { $rsrc->column_info('value')->{data_type} }, 'varchar',
312 'column in database two introspected correctly';
313
314 is try { $rsrc->column_info('value')->{size} }, 100,
315 'column in database two introspected correctly';
316
317 lives_and {
318 ok $rs = $test_schema->resultset('SybaseLoaderTest6');
319 } 'got resultset for table in database two';
320
321 lives_and {
322 ok $row = $rs->create({ value => 'foo' });
323 } 'executed SQL on table in database two';
324
325 $rel_info = try { $rsrc->relationship_info('sybase_loader_test7') };
326
327 is_deeply $rel_info->{cond}, {
328 'foreign.six_id' => 'self.id'
329 }, 'relationship in database two';
330
331 is $rel_info->{attrs}{accessor}, 'single',
332 'relationship in database two';
333
334 is $rel_info->{attrs}{join_type}, 'LEFT',
335 'relationship in database two';
336
337 lives_and {
338 ok $rsrc = $test_schema->source('SybaseLoaderTest7');
339 } 'got source for table in database two';
340
341 %uniqs = try { $rsrc->unique_constraints };
342
343 is keys %uniqs, 2,
344 'got unique and primary constraint in database two';
345
346 lives_and {
347 ok $test_schema->source('SybaseLoaderTest6')
348 ->has_relationship('sybase_loader_test4');
349 } 'cross-database relationship in multi database schema';
350
351 lives_and {
352 ok $test_schema->source('SybaseLoaderTest4')
353 ->has_relationship('sybase_loader_test6s');
354 } 'cross-database relationship in multi database schema';
355
356 lives_and {
357 ok $test_schema->source('SybaseLoaderTest8')
358 ->has_relationship('sybase_loader_test7');
359 } 'cross-database relationship in multi database schema';
360
361 lives_and {
362 ok $test_schema->source('SybaseLoaderTest7')
363 ->has_relationship('sybase_loader_test8s');
364 } 'cross-database relationship in multi database schema';
365 }
366 }
367 }
368 },
5c1b0a23 369 },
fe67d343 370);
371
372if( !$dsn || !$user ) {
373 $tester->skip_tests('You need to set the DBICTEST_SYBASE_DSN, _USER, and _PASS environment variables');
374}
375else {
376 $tester->run_tests();
377}
5c1b0a23 378
c4a69b87 379END {
380 if (not $ENV{SCHEMA_LOADER_TESTS_NOCLEANUP}) {
381 rmtree EXTRA_DUMP_DIR;
382
383 if ($databases_created) {
384 my $dbh = $schema->storage->dbh;
385
386 $dbh->do('USE master');
387
388 local $dbh->{FetchHashKeyName} = 'NAME_lc';
389
390 my $sth = $dbh->prepare('sp_who');
391 $sth->execute;
392
393 while (my $row = $sth->fetchrow_hashref) {
394 if ($row->{dbname} =~ /^dbicsl_test[12]\z/) {
395 $dbh->do("kill $row->{spid}");
396 }
397 }
398
399 foreach my $table ('[dbicsl_test1].dbicsl_user1.sybase_loader_test8',
400 '[dbicsl_test2].dbicsl_user2.sybase_loader_test7',
401 '[dbicsl_test2].dbicsl_user2.sybase_loader_test6',
402 '[dbicsl_test1].dbicsl_user1.sybase_loader_test5',
403 '[dbicsl_test1].dbicsl_user1.sybase_loader_test4') {
404 try {
405 $dbh->do("DROP TABLE $table");
406 }
407 catch {
408 diag "Error dropping table $table: $_";
409 };
410 }
411
412 foreach my $db (qw/dbicsl_test1 dbicsl_test2/) {
413 try {
414 $dbh->do("DROP DATABASE [$db]");
415 }
416 catch {
417 diag "Error dropping test database $db: $_";
418 };
419 }
420
421 foreach my $login (qw/dbicsl_user1 dbicsl_user2/) {
422 try {
423 my $warn_handler = $SIG{__WARN__} || sub { warn @_ };
424 local $SIG{__WARN__} = sub {
425 $warn_handler->(@_)
426 unless $_[0] =~ /^Account locked\.$|^Login dropped\.$/;
427 };
428
429 $dbh->do("sp_droplogin $login");
430 }
431 catch {
432 diag "Error dropping login $login: $_"
433 unless /Incorrect syntax/;
434 };
435 }
436 }
437 }
438}
5c1b0a23 439# vim:et sts=4 sw=4 tw=0: