6 use File::Path 'rmtree';
7 use DBIx::Class::Schema::Loader 'make_schema_at';
13 use dbixcsl_common_tests ();
14 use dbixcsl_test_dir '$tdir';
16 use constant EXTRA_DUMP_DIR => "$tdir/sybase_extra_dump";
18 my $dsn = $ENV{DBICTEST_SYBASE_DSN} || '';
19 my $user = $ENV{DBICTEST_SYBASE_USER} || '';
20 my $password = $ENV{DBICTEST_SYBASE_PASS} || '';
22 my ($schema, $databases_created); # for cleanup in END for extra tests
24 my $tester = dbixcsl_common_tests->new(
26 auto_inc_pk => 'INTEGER IDENTITY NOT NULL PRIMARY KEY',
27 default_function => 'getdate()',
28 default_function_def => 'AS getdate()',
31 password => $password,
33 # http://ispirer.com/wiki/sqlways/sybase/data-types
36 'integer identity' => { data_type => 'integer', is_auto_increment => 1 },
37 int => { data_type => 'integer' },
38 integer => { data_type => 'integer' },
39 bigint => { data_type => 'bigint' },
40 smallint => { data_type => 'smallint' },
41 tinyint => { data_type => 'tinyint' },
42 'double precision' => { data_type => 'double precision' },
43 real => { data_type => 'real' },
44 float => { data_type => 'double precision' },
45 'float(14)' => { data_type => 'real' },
46 'float(15)' => { data_type => 'real' },
47 'float(16)' => { data_type => 'double precision' },
48 'float(48)' => { data_type => 'double precision' },
49 'numeric(6,3)' => { data_type => 'numeric', size => [6,3] },
50 'decimal(6,3)' => { data_type => 'numeric', size => [6,3] },
51 numeric => { data_type => 'numeric' },
52 decimal => { data_type => 'numeric' },
53 bit => { data_type => 'bit' },
56 money => { data_type => 'money' },
57 smallmoney => { data_type => 'smallmoney' },
60 'AS getdate()' => { data_type => undef, inflate_datetime => 1, default_value => \'getdate()' },
63 text => { data_type => 'text' },
64 unitext => { data_type => 'unitext' },
65 image => { data_type => 'image' },
68 date => { data_type => 'date' },
69 time => { data_type => 'time' },
70 datetime => { data_type => 'datetime' },
71 smalldatetime => { data_type => 'smalldatetime' },
74 timestamp => { data_type => 'timestamp', inflate_datetime => 0 },
77 'char' => { data_type => 'char', size => 1 },
78 'char(2)' => { data_type => 'char', size => 2 },
79 'nchar' => { data_type => 'nchar', size => 1 },
80 'nchar(2)' => { data_type => 'nchar', size => 2 },
81 'unichar(2)' => { data_type => 'unichar', size => 2 },
82 'varchar(2)' => { data_type => 'varchar', size => 2 },
83 'nvarchar(2)' => { data_type => 'nvarchar', size => 2 },
84 'univarchar(2)' => { data_type => 'univarchar', size => 2 },
87 'binary' => { data_type => 'binary', size => 1 },
88 'binary(2)' => { data_type => 'binary', size => 2 },
89 'varbinary(2)' => { data_type => 'varbinary', size => 2 },
91 # test that named constraints aren't picked up as tables (I can't reproduce this on my machine)
92 failtrigger_warnings => [ qr/^Bad table or view 'sybase_loader_test2_ref_slt1'/ ],
96 CREATE TABLE sybase_loader_test1 (
97 id int identity primary key
101 CREATE TABLE sybase_loader_test2 (
102 id int identity primary key,
103 sybase_loader_test1_id int,
104 CONSTRAINT sybase_loader_test2_ref_slt1 FOREIGN KEY (sybase_loader_test1_id) REFERENCES sybase_loader_test1 (id)
108 drop => [ qw/sybase_loader_test1 sybase_loader_test2/ ],
114 my $dbh = $schema->storage->dbh;
117 $dbh->do('USE master');
120 skip "these tests require the sysadmin role", 30 * 4;
124 $dbh->do('CREATE DATABASE [dbicsl_test1]');
125 $dbh->do('CREATE DATABASE [dbicsl_test2]');
128 skip "cannot create databases: $_", 30 * 4;
132 my $warn_handler = $SIG{__WARN__} || sub { warn @_ };
133 local $SIG{__WARN__} = sub {
135 unless $_[0] =~ /^Password correctly set\.$|^Account unlocked\.$|^New login created\.$|^New user added\.$/;
138 $dbh->do("sp_addlogin dbicsl_user1, dbicsl, [dbicsl_test1]");
139 $dbh->do("sp_addlogin dbicsl_user2, dbicsl, [dbicsl_test2]");
141 $dbh->do("USE [dbicsl_test1]");
142 $dbh->do("sp_adduser dbicsl_user1");
143 $dbh->do("sp_adduser dbicsl_user2");
144 $dbh->do("GRANT ALL TO dbicsl_user1");
145 $dbh->do("GRANT ALL TO dbicsl_user2");
147 $dbh->do("USE [dbicsl_test2]");
148 $dbh->do("sp_adduser dbicsl_user2");
149 $dbh->do("sp_adduser dbicsl_user1");
150 $dbh->do("GRANT ALL TO dbicsl_user2");
151 $dbh->do("GRANT ALL TO dbicsl_user1");
154 skip "cannot add logins: $_", 30 * 4;
159 my $warn_handler = $SIG{__WARN__} || sub { warn @_ };
160 local $SIG{__WARN__} = sub {
161 $warn_handler->(@_) unless $_[0] =~ /can't change context/;
164 $dbh1 = DBI->connect($dsn, 'dbicsl_user1', 'dbicsl', {
168 $dbh1->do('USE [dbicsl_test1]');
170 $dbh2 = DBI->connect($dsn, 'dbicsl_user2', 'dbicsl', {
174 $dbh2->do('USE [dbicsl_test2]');
178 CREATE TABLE sybase_loader_test4 (
179 id INT IDENTITY PRIMARY KEY,
180 value VARCHAR(100) NULL
183 $dbh1->do('GRANT ALL ON sybase_loader_test4 TO dbicsl_user2');
185 CREATE TABLE sybase_loader_test5 (
186 id INT IDENTITY PRIMARY KEY,
187 value VARCHAR(100) NULL,
189 CONSTRAINT loader_test5_uniq UNIQUE (four_id),
190 FOREIGN KEY (four_id) REFERENCES sybase_loader_test4 (id)
194 CREATE TABLE sybase_loader_test5 (
195 pk INT IDENTITY PRIMARY KEY,
196 value VARCHAR(100) NULL,
198 CONSTRAINT loader_test5_uniq UNIQUE (four_id),
199 FOREIGN KEY (four_id) REFERENCES [dbicsl_test1].dbicsl_user1.sybase_loader_test4 (id)
203 CREATE TABLE sybase_loader_test6 (
204 id INT IDENTITY PRIMARY KEY,
205 value VARCHAR(100) NULL,
206 sybase_loader_test4_id INTEGER NULL,
207 FOREIGN KEY (sybase_loader_test4_id) REFERENCES [dbicsl_test1].dbicsl_user1.sybase_loader_test4 (id)
211 CREATE TABLE sybase_loader_test7 (
212 id INT IDENTITY PRIMARY KEY,
213 value VARCHAR(100) NULL,
214 six_id INTEGER UNIQUE,
215 FOREIGN KEY (six_id) REFERENCES sybase_loader_test6 (id)
218 $dbh2->do('GRANT ALL ON sybase_loader_test7 TO dbicsl_user1');
220 CREATE TABLE sybase_loader_test8 (
221 id INT IDENTITY PRIMARY KEY,
222 value VARCHAR(100) NULL,
223 sybase_loader_test7_id INTEGER,
224 FOREIGN KEY (sybase_loader_test7_id) REFERENCES [dbicsl_test2].dbicsl_user2.sybase_loader_test7 (id)
228 $databases_created = 1;
230 foreach my $databases (['dbicsl_test1', 'dbicsl_test2'], '%') {
231 foreach my $owners ([qw/dbicsl_user1 dbicsl_user2/], '%') {
233 rmtree EXTRA_DUMP_DIR;
236 local $SIG{__WARN__} = sub {
237 push @warns, $_[0] unless $_[0] =~ /\bcollides\b/
238 || $_[0] =~ /can't change context/;
241 my $database = $databases;
243 $database = [ $database ] unless ref $database;
247 foreach my $db (@$database) {
248 $db_schema->{$db} = $owners;
255 db_schema => $db_schema,
256 moniker_parts => [qw/database name/],
257 dump_directory => EXTRA_DUMP_DIR,
260 [ $dsn, $user, $password ],
263 diag join "\n", @warns if @warns;
266 } 'dumped schema for "dbicsl_test1" and "dbicsl_test2" databases with no warnings';
268 my ($test_schema, $rsrc, $rs, $row, %uniqs, $rel_info);
271 ok $test_schema = SybaseMultiSchema->connect($dsn, $user, $password);
272 } 'connected test schema';
275 ok $rsrc = $test_schema->source('DbicslTest1SybaseLoaderTest4');
276 } 'got source for table in database one';
278 is try { $rsrc->column_info('id')->{is_auto_increment} }, 1,
279 'column in database one';
281 is try { $rsrc->column_info('value')->{data_type} }, 'varchar',
282 'column in database one';
284 is try { $rsrc->column_info('value')->{size} }, 100,
285 'column in database one';
288 ok $rs = $test_schema->resultset('DbicslTest1SybaseLoaderTest4');
289 } 'got resultset for table in database one';
292 ok $row = $rs->create({ value => 'foo' });
293 } 'executed SQL on table in database one';
295 $rel_info = try { $rsrc->relationship_info('dbicsl_test1_sybase_loader_test5') };
297 is_deeply $rel_info->{cond}, {
298 'foreign.four_id' => 'self.id'
299 }, 'relationship in database one';
301 is $rel_info->{attrs}{accessor}, 'single',
302 'relationship in database one';
304 is $rel_info->{attrs}{join_type}, 'LEFT',
305 'relationship in database one';
308 ok $rsrc = $test_schema->source('DbicslTest1SybaseLoaderTest5');
309 } 'got source for table in database one';
311 %uniqs = try { $rsrc->unique_constraints };
314 'got unique and primary constraint in database one';
316 delete $uniqs{primary};
318 is_deeply ((values %uniqs)[0], ['four_id'],
319 'correct unique constraint in database one');
322 ok $rsrc = $test_schema->source('DbicslTest2SybaseLoaderTest6');
323 } 'got source for table in database two';
325 is try { $rsrc->column_info('id')->{is_auto_increment} }, 1,
326 'column in database two introspected correctly';
328 is try { $rsrc->column_info('value')->{data_type} }, 'varchar',
329 'column in database two introspected correctly';
331 is try { $rsrc->column_info('value')->{size} }, 100,
332 'column in database two introspected correctly';
335 ok $rs = $test_schema->resultset('DbicslTest2SybaseLoaderTest6');
336 } 'got resultset for table in database two';
339 ok $row = $rs->create({ value => 'foo' });
340 } 'executed SQL on table in database two';
342 $rel_info = try { $rsrc->relationship_info('sybase_loader_test7') };
344 is_deeply $rel_info->{cond}, {
345 'foreign.six_id' => 'self.id'
346 }, 'relationship in database two';
348 is $rel_info->{attrs}{accessor}, 'single',
349 'relationship in database two';
351 is $rel_info->{attrs}{join_type}, 'LEFT',
352 'relationship in database two';
355 ok $rsrc = $test_schema->source('DbicslTest2SybaseLoaderTest7');
356 } 'got source for table in database two';
358 %uniqs = try { $rsrc->unique_constraints };
361 'got unique and primary constraint in database two';
363 delete $uniqs{primary};
365 is_deeply ((values %uniqs)[0], ['six_id'],
366 'correct unique constraint in database two');
369 ok $test_schema->source('DbicslTest2SybaseLoaderTest6')
370 ->has_relationship('sybase_loader_test4');
371 } 'cross-database relationship in multi database schema';
374 ok $test_schema->source('DbicslTest1SybaseLoaderTest4')
375 ->has_relationship('sybase_loader_test6s');
376 } 'cross-database relationship in multi database schema';
379 ok $test_schema->source('DbicslTest1SybaseLoaderTest8')
380 ->has_relationship('sybase_loader_test7');
381 } 'cross-database relationship in multi database schema';
384 ok $test_schema->source('DbicslTest2SybaseLoaderTest7')
385 ->has_relationship('sybase_loader_test8s');
386 } 'cross-database relationship in multi database schema';
394 if( !$dsn || !$user ) {
395 $tester->skip_tests('You need to set the DBICTEST_SYBASE_DSN, _USER, and _PASS environment variables');
398 $tester->run_tests();
402 if (not $ENV{SCHEMA_LOADER_TESTS_NOCLEANUP}) {
403 rmtree EXTRA_DUMP_DIR;
405 if ($databases_created) {
406 my $dbh = $schema->storage->dbh;
408 $dbh->do('USE master');
410 local $dbh->{FetchHashKeyName} = 'NAME_lc';
412 my $sth = $dbh->prepare('sp_who');
415 while (my $row = $sth->fetchrow_hashref) {
416 if ($row->{dbname} =~ /^dbicsl_test[12]\z/) {
417 $dbh->do("kill $row->{spid}");
421 foreach my $table ('[dbicsl_test1].dbicsl_user1.sybase_loader_test8',
422 '[dbicsl_test2].dbicsl_user2.sybase_loader_test7',
423 '[dbicsl_test2].dbicsl_user2.sybase_loader_test6',
424 '[dbicsl_test2].dbicsl_user2.sybase_loader_test5',
425 '[dbicsl_test1].dbicsl_user1.sybase_loader_test5',
426 '[dbicsl_test1].dbicsl_user1.sybase_loader_test4') {
428 $dbh->do("DROP TABLE $table");
431 diag "Error dropping table $table: $_";
435 foreach my $db (qw/dbicsl_test1 dbicsl_test2/) {
437 $dbh->do("DROP DATABASE [$db]");
440 diag "Error dropping test database $db: $_";
444 foreach my $login (qw/dbicsl_user1 dbicsl_user2/) {
446 my $warn_handler = $SIG{__WARN__} || sub { warn @_ };
447 local $SIG{__WARN__} = sub {
449 unless $_[0] =~ /^Account locked\.$|^Login dropped\.$/;
452 $dbh->do("sp_droplogin $login");
455 diag "Error dropping login $login: $_"
456 unless /Incorrect syntax/;
462 # vim:et sts=4 sw=4 tw=0: