1#!/usr/bin/perl -w 2 3use strict; 4 5use Test::More tests => 598; 6 7BEGIN 8{ 9 require 't/test-lib.pl'; 10 use_ok('Rose::DB::Object'); 11 use_ok('Rose::DB::Object::Util'); 12} 13 14Rose::DB::Object::Util->import(':all'); 15 16eval { require Time::HiRes }; 17our $Have_HiRes_Time = $@ ? 0 : 1; 18 19our($PG_HAS_CHKPASS, $HAVE_PG, $HAVE_MYSQL, $HAVE_INFORMIX, $HAVE_SQLITE, 20 $HAVE_ORACLE, $INNODB); 21 22# 23# PostgreSQL 24# 25 26SKIP: foreach my $db_type (qw(pg pg_with_schema)) 27{ 28 skip("PostgreSQL tests", 242) unless($HAVE_PG); 29 30 Rose::DB->default_type($db_type); 31 32 TEST_HACK: 33 { 34 no warnings; 35 *MyPgObject::init_db = sub { Rose::DB->new($db_type) }; 36 } 37 38 my $o = MyPgObject->new(name => 'John', 39 k1 => 1, 40 k2 => undef, 41 k3 => 3); 42 43 ok(ref $o && $o->isa('MyPgObject'), "new() 1 - $db_type"); 44 45 $o->flag2('TRUE'); 46 $o->date_created('now'); 47 $o->date_created_tz('now'); 48 $o->timestamp_tz2('now'); 49 $o->last_modified($o->date_created); 50 $o->save_col(7); 51 52 if(rand >= 0.5) 53 { 54 ok($o->save, "save() 1 - $db_type"); 55 } 56 else 57 { 58 ok($o->insert, "insert() 1 - $db_type"); 59 } 60 61 MyPgObject->meta->sql_qualify_column_names_on_load(1); 62 63 my $schema = $db_type eq 'pg_with_schema' ? 'rose_db_object_private.' : ''; 64 65 is(MyPgObject->meta->load_all_sql(undef, $o->db), 66 qq(SELECT rose_db_object_test.name, rose_db_object_test.code, rose_db_object_test.id, rose_db_object_test.k1, rose_db_object_test.k2, rose_db_object_test.k3,@{[ $PG_HAS_CHKPASS ? ' rose_db_object_test.passwd,' : '' ]} rose_db_object_test.flag, rose_db_object_test.flag2, rose_db_object_test.status, rose_db_object_test.start, rose_db_object_test.save, rose_db_object_test.nums, rose_db_object_test.bitz, rose_db_object_test.decs, rose_db_object_test.dur, rose_db_object_test.epoch, rose_db_object_test.hiepoch, rose_db_object_test.bint1, rose_db_object_test.bint2, rose_db_object_test.bint3, rose_db_object_test.bint4, rose_db_object_test.tee_time, rose_db_object_test.tee_time0, rose_db_object_test.tee_time5, rose_db_object_test.tee_time9, rose_db_object_test.date_created, rose_db_object_test.date_created_tz, rose_db_object_test.timestamp_tz2, rose_db_object_test.last_modified FROM ${schema}rose_db_object_test WHERE rose_db_object_test.id = ?), 67 "sql_qualify_column_names_on_load() 1 - $db_type"); 68 69 is(MyPgObject->meta->load_sql(undef, $o->db), 70 qq(SELECT rose_db_object_test.name, rose_db_object_test.code, rose_db_object_test.id, rose_db_object_test.k1, rose_db_object_test.k3,@{[ $PG_HAS_CHKPASS ? ' rose_db_object_test.passwd,' : '' ]} rose_db_object_test.flag, rose_db_object_test.flag2, rose_db_object_test.status, rose_db_object_test.save, rose_db_object_test.nums, rose_db_object_test.bitz, rose_db_object_test.decs, rose_db_object_test.dur, rose_db_object_test.epoch, rose_db_object_test.hiepoch, rose_db_object_test.bint1, rose_db_object_test.bint2, rose_db_object_test.bint3, rose_db_object_test.bint4, rose_db_object_test.tee_time, rose_db_object_test.tee_time0, rose_db_object_test.tee_time5, rose_db_object_test.tee_time9, rose_db_object_test.date_created, rose_db_object_test.date_created_tz, rose_db_object_test.timestamp_tz2, rose_db_object_test.last_modified FROM ${schema}rose_db_object_test WHERE rose_db_object_test.id = ?), 71 "sql_qualify_column_names_on_load() 2 - $db_type"); 72 73 is(MyPgObject->meta->load_all_sql_with_null_key([ qw(k1 k2 k3) ], [ 1, undef, 3 ], $o->db), 74 qq(SELECT rose_db_object_test.name, rose_db_object_test.code, rose_db_object_test.id, rose_db_object_test.k1, rose_db_object_test.k2, rose_db_object_test.k3,@{[ $PG_HAS_CHKPASS ? ' rose_db_object_test.passwd,' : '' ]} rose_db_object_test.flag, rose_db_object_test.flag2, rose_db_object_test.status, rose_db_object_test.start, rose_db_object_test.save, rose_db_object_test.nums, rose_db_object_test.bitz, rose_db_object_test.decs, rose_db_object_test.dur, rose_db_object_test.epoch, rose_db_object_test.hiepoch, rose_db_object_test.bint1, rose_db_object_test.bint2, rose_db_object_test.bint3, rose_db_object_test.bint4, rose_db_object_test.tee_time, rose_db_object_test.tee_time0, rose_db_object_test.tee_time5, rose_db_object_test.tee_time9, rose_db_object_test.date_created, rose_db_object_test.date_created_tz, rose_db_object_test.timestamp_tz2, rose_db_object_test.last_modified FROM ${schema}rose_db_object_test WHERE rose_db_object_test.k1 = ? AND rose_db_object_test.k2 IS NULL AND rose_db_object_test.k3 = ?), 75 "sql_qualify_column_names_on_load() 3 - $db_type"); 76 77 is(MyPgObject->meta->load_sql_with_null_key([ qw(k1 k2 k3) ], [ 1, undef, 3 ], $o->db), 78 qq(SELECT rose_db_object_test.name, rose_db_object_test.code, rose_db_object_test.id, rose_db_object_test.k1, rose_db_object_test.k3,@{[ $PG_HAS_CHKPASS ? ' rose_db_object_test.passwd,' : '' ]} rose_db_object_test.flag, rose_db_object_test.flag2, rose_db_object_test.status, rose_db_object_test.save, rose_db_object_test.nums, rose_db_object_test.bitz, rose_db_object_test.decs, rose_db_object_test.dur, rose_db_object_test.epoch, rose_db_object_test.hiepoch, rose_db_object_test.bint1, rose_db_object_test.bint2, rose_db_object_test.bint3, rose_db_object_test.bint4, rose_db_object_test.tee_time, rose_db_object_test.tee_time0, rose_db_object_test.tee_time5, rose_db_object_test.tee_time9, rose_db_object_test.date_created, rose_db_object_test.date_created_tz, rose_db_object_test.timestamp_tz2, rose_db_object_test.last_modified FROM ${schema}rose_db_object_test WHERE rose_db_object_test.k1 = ? AND rose_db_object_test.k2 IS NULL AND rose_db_object_test.k3 = ?), 79 "sql_qualify_column_names_on_load() 4 - $db_type"); 80 81 MyPgObject->meta->sql_qualify_column_names_on_load(rand > 0.6 ? 0 : 1); # excitement! :) 82 83 is($o->meta->primary_key->sequence_names->[0], 'rose_db_object_test_id_seq', 84 "pk sequence name - $db_type"); 85 86 ok(is_in_db($o), "is_in_db - $db_type"); 87 88 is($o->id, 1, "auto-generated primary key - $db_type"); 89 90 ok($o->load, "load() 1 - $db_type"); 91 92 is($o->date_created->time_zone->name, 'floating', "timestamp without time zone - $db_type"); 93 isnt($o->date_created_tz->time_zone->name, 'floating', "timestamp with time zone - $db_type"); 94 is($o->timestamp_tz2->time_zone->name, 'Antarctica/Vostok', "timestamp with time zone override - $db_type"); 95 96 # Make sure we're not in the Antarctica/Vostok time zone or any other 97 # time zone with the same offset. 98 my $error; 99 100 TRY: 101 { 102 local $@; 103 104 eval 105 { 106 my $dt1 = DateTime->now(time_zone => 'local'); 107 my $dt2 = $dt1->clone; 108 $dt2->set_time_zone('Antarctica/Vostok'); 109 die "local is equivalent to Antarctica/Vostok" if($dt1->iso8601 eq $dt2->iso8601); 110 }; 111 112 $error = $@; 113 } 114 115 if($error) 116 { 117 SKIP: { skip("timestamp with time zone time change - $db_type", 2) } 118 } 119 else 120 { 121 isnt($o->date_created_tz->iso8601, $o->timestamp_tz2->iso8601, "timestamp with time zone time change - $db_type"); 122 123 $o->save; 124 $o->load; 125 126 my $dt = $o->timestamp_tz2->clone; 127 $dt->set_time_zone($o->date_created_tz->time_zone); 128 129 is($o->date_created_tz->iso8601, $dt->iso8601, "timestamp with time zone time change 2 - $db_type"); 130 } 131 132 $o->name('C' x 50); 133 is($o->name, 'C' x 32, "varchar truncation - $db_type"); 134 135 $o->name('John'); 136 137 $o->code('A'); 138 is($o->code, 'A ', "character padding - $db_type"); 139 140 $o->code('C' x 50); 141 is($o->code, 'C' x 6, "character truncation - $db_type"); 142 143 my $ouk; 144 ok($ouk = MyPgObject->new(k1 => 1, 145 k2 => undef, 146 k3 => 3)->load, "load() uk 1 - $db_type"); 147 148 ok(!$ouk->not_found, "not_found() uk 1 - $db_type"); 149 150 is($ouk->id, 1, "load() uk 2 - $db_type"); 151 is($ouk->name, 'John', "load() uk 3 - $db_type"); 152 153 ok($ouk->save, "save() uk 1 - $db_type"); 154 155 my $o2 = MyPgObject->new(id => $o->id); 156 157 ok(ref $o2 && $o2->isa('MyPgObject'), "new() 2 - $db_type"); 158 159 is($o2->bits->to_Bin, '00101', "bits() (bitfield default value) - $db_type"); 160 161 ok($o2->load, "load() 2 - $db_type"); 162 ok(!$o2->not_found, "not_found() 1 - $db_type"); 163 164 is($o2->name, $o->name, "load() verify 1 - $db_type"); 165 is($o2->date_created, $o->date_created, "load() verify 2 - $db_type"); 166 is($o2->last_modified, $o->last_modified, "load() verify 3 - $db_type"); 167 is($o2->status, 'active', "load() verify 4 (default value) - $db_type"); 168 is($o2->flag, 1, "load() verify 5 (default boolean value) - $db_type"); 169 is($o2->flag2, 1, "load() verify 6 (boolean value) - $db_type"); 170 is($o2->save_col, 7, "load() verify 7 (aliased column) - $db_type"); 171 is($o2->start->ymd, '1980-12-24', "load() verify 8 (date value) - $db_type"); 172 173 $o2->flag2(undef); 174 $o2->save; 175 176 is($o2->flag2, undef, "boolean null - $db_type"); 177 178 $o2->set_status('foo'); 179 is($o2->get_status, 'foo', "get_status() - $db_type"); 180 $o2->set_status('active'); 181 eval { $o2->set_status }; 182 ok($@, "set_status() - $db_type"); 183 184 is($o2->bits->to_Bin, '00101', "load() verify 9 (bitfield value) - $db_type"); 185 186 my $clone = $o2->clone; 187 ok($o2->start eq $clone->start, "clone() 1 - $db_type"); 188 $clone->start->set(year => '1960'); 189 ok($o2->start ne $clone->start, "clone() 2 - $db_type"); 190 191 $o2->start('5/24/2001'); 192 193 sleep(1); # keep the last modified dates from being the same 194 195 $o2->last_modified('now'); 196 ok($o2->save, "save() 2 - $db_type"); 197 ok($o2->load, "load() 3 - $db_type"); 198 199 ok(!has_modified_columns($o2), "no modified columns after load() - $db_type"); 200 201 $o2->name('John 2'); 202 $o2->save(changes_only => 1); 203 204 is($o2->date_created, $o->date_created, "save() verify 1 - $db_type"); 205 ok($o2->last_modified ne $o->last_modified, "save() verify 2 - $db_type"); 206 is($o2->start->ymd, '2001-05-24', "save() verify 3 (date value) - $db_type"); 207 208 my $bo = MyPgObject->new(id => $o->id); 209 $bo->load; 210 $bo->flag(0); 211 $bo->save; 212 213 $bo = MyPgObject->new(id => $o->id); 214 $bo->load; 215 216 ok(!$bo->flag, "boolean check - $db_type"); 217 218 $bo->flag(0); 219 $bo->save; 220 221 my $o3 = MyPgObject->new(); 222 223 my $db = $o3->db or die $o3->error; 224 225 ok(ref $db && $db->isa('Rose::DB'), "db() - $db_type"); 226 227 is($db->dbh, $o3->dbh, "dbh() - $db_type"); 228 229 my $o4 = MyPgObject->new(id => 999); 230 ok(!$o4->load(speculative => 1), "load() nonexistent - $db_type"); 231 ok($o4->not_found, "not_found() 2 - $db_type"); 232 233 ok($o->load, "load() 4 - $db_type"); 234 235 SKIP: 236 { 237 if($PG_HAS_CHKPASS) 238 { 239 $o->{'password_encrypted'} = ':8R1Kf2nOS0bRE'; 240 241 ok($o->password_is('xyzzy'), "chkpass() 1 - $db_type"); 242 is($o->password, 'xyzzy', "chkpass() 2 - $db_type"); 243 244 $o->password('foobar'); 245 246 ok($o->password_is('foobar'), "chkpass() 3 - $db_type"); 247 is($o->password, 'foobar', "chkpass() 4 - $db_type"); 248 249 $o->code('C1'); 250 #local $Rose::DB::Object::Debug = 1; 251 ok($o->save, "save() 3 - $db_type"); 252 253 $o = MyPgObject->new(id => $o->id)->load; 254 $o->code('C2'); 255 $o->save; 256 257 $o = MyPgObject->new(id => $o->id)->load; 258 ok($o->password_is('foobar'), "chkpass() 6 - $db_type"); 259 } 260 else 261 { 262 skip("chkpass tests", 6); 263 } 264 } 265 266 my $o5 = MyPgObject->new(id => $o->id); 267 268 ok($o5->load, "load() 5 - $db_type"); 269 270 SKIP: 271 { 272 if($PG_HAS_CHKPASS) 273 { 274 ok($o5->password_is('foobar'), "chkpass() 7 - $db_type"); 275 is($o5->password, 'foobar', "chkpass() 8 - $db_type"); 276 } 277 else 278 { 279 skip("chkpass tests", 2); 280 } 281 } 282 283 $o5->nums([ 4, 5, 6 ]); 284 ok($o5->save, "save() 4 - $db_type"); 285 ok($o->load, "load() 6 - $db_type"); 286 287 is($o5->nums->[0], 4, "load() verify 10 (array value) - $db_type"); 288 is($o5->nums->[1], 5, "load() verify 11 (array value) - $db_type"); 289 is($o5->nums->[2], 6, "load() verify 12 (array value) - $db_type"); 290 291 my @a = $o5->nums; 292 293 is($a[0], 4, "load() verify 13 (array value) - $db_type"); 294 is($a[1], 5, "load() verify 14 (array value) - $db_type"); 295 is($a[2], 6, "load() verify 15 (array value) - $db_type"); 296 is(@a, 3, "load() verify 16 (array value) - $db_type"); 297 298 ok($o->delete, "delete() - $db_type"); 299 300 $o = MyPgObject->new(name => 'John', id => 9); 301 $o->save_col(22); 302 ok($o->save, "save() 4 - $db_type"); 303 $o->save_col(50); 304 ok($o->save, "save() 5 - $db_type"); 305 306 $ouk = MyPgObject->new(save_col => 50); 307 ok($ouk->load, "load() aliased unique key - $db_type"); 308 309 eval { $o->meta->alias_column(nonesuch => 'foo') }; 310 ok($@, "alias_column() nonesuch - $db_type"); 311 312 # This is okay now 313 #eval { $o->meta->alias_column(id => 'foo') }; 314 #ok($@, "alias_column() primary key - $db_type"); 315 316 $o = MyPgObject->new(id => 777); 317 318 $o->meta->error_mode('fatal'); 319 320 $o->dbh->{'PrintError'} = 0; 321 322 eval { $o->load }; 323 ok($@ && $o->not_found, "load() not found fatal - $db_type"); 324 325 $o->id('abc'); 326 327 eval { $o->load }; 328 ok($@ && !$o->not_found, "load() fatal - $db_type"); 329 330 eval { $o->save }; 331 ok($@, "save() fatal - $db_type"); 332 333 $o = MyPgObject->new(id => 9999); # no such id 334 335 $o->meta->error_mode('fatal'); 336 337 eval { $o->load() }; 338 ok($@, "load() non-speculative implicit - $db_type"); 339 ok(!$o->load(speculative => 1), "load() speculative explicit 1 - $db_type"); 340 eval { $o->load(speculative => 0) }; 341 ok($@, "load() non-speculative explicit 2 - $db_type"); 342 343 $o->meta->default_load_speculative(1); 344 345 ok(!$o->load(), "load() speculative implicit - $db_type"); 346 ok(!$o->load(speculative => 1), "load() speculative explicit 2 - $db_type"); 347 eval { $o->load(speculative => 0) }; 348 ok($@, "load() non-speculative explicit 2 - $db_type"); 349 350 # Reset for next trip through loop 351 $o->meta->default_load_speculative(0); 352 $o->meta->error_mode('return'); 353 354 $o = MyPgObject->new(name => 'John', 355 k1 => 1, 356 k2 => undef, 357 k3 => 3)->save; 358 359 is($o->dur->months, 2, "interval months 1 - $db_type"); 360 is($o->dur->days, 5, "interval days 1 - $db_type"); 361 is($o->dur->seconds, 3, "interval seconds 1 - $db_type"); 362 363 $o->dur(DateTime::Duration->new(years => 7, nanoseconds => 3000)); 364 365 is($o->dur->in_units('years'), 7, "interval in_units years 1 - $db_type"); 366 is($o->dur->in_units('months'), 84, "interval in_units months 1 - $db_type"); 367 is($o->dur->nanoseconds, 3000, "interval nanoseconds 1 - $db_type"); 368 is($o->dur->days, 0, "interval days 2 - $db_type"); 369 is($o->dur->minutes, 0, "interval minutes 2 - $db_type"); 370 is($o->dur->seconds, 0, "interval seconds 2 - $db_type"); 371 372 $o->save; 373 374 # Select for update tests 375 $o = MyPgObject->new(id => $o->id); 376 377 $o->db->begin_work; 378 $o->load(for_update => 1); 379 380 # Silence errors in eval blocks below 381 Rose::DB->modify_db(type => $db_type)->print_error(0); 382 383 my $lo; 384 385 eval 386 { 387 $lo = MyPgObject->new(id => $o->id); 388 $lo->meta->error_mode('fatal'); 389 $lo->load(lock => { for_update => 1, nowait => 1 }); 390 }; 391 392 is(DBI->err, 7, "select for update wait 1 error 7 - $db_type"); 393 ok($@, "select for update no wait - $db_type"); 394 395 $o->db->commit; 396 397 Rose::DB->modify_db(type => $db_type)->print_error(1); 398 399 $lo = MyPgObject->new(id => $o->id); 400 $lo->load(lock => { type => 'shared' }); 401 402 $o = MyPgObject->new(id => $o->id)->load; 403 404 is($o->dur->in_units('years'), 7, "interval in_units years 2 - $db_type"); 405 is($o->dur->in_units('months'), 84, "interval in_units months 2 - $db_type"); 406 is($o->dur->nanoseconds, 3000, "interval nanoseconds 2 - $db_type"); 407 is($o->dur->days, 0, "interval days 3 - $db_type"); 408 is($o->dur->minutes, 0, "interval minutes 3 - $db_type"); 409 is($o->dur->seconds, 0, "interval seconds 3 - $db_type"); 410 411 is($o->epoch(format => '%Y-%m-%d %H:%M:%S'), '1999-11-30 21:30:00', "epoch 1 - $db_type"); 412 413 $o->hiepoch('943997400.123456'); 414 is($o->hiepoch(format => '%Y-%m-%d %H:%M:%S.%6N'), '1999-11-30 21:30:00.123456', "epoch hires 1 - $db_type"); 415 416 $o->epoch('5/6/1980 12:34:56'); 417 418 $o->save; 419 420 $o = MyPgObject->new(id => $o->id)->load; 421 422 is($o->epoch(format => '%Y-%m-%d %H:%M:%S'), '1980-05-06 12:34:56', "epoch 2 - $db_type"); 423 is($o->hiepoch(format => '%Y-%m-%d %H:%M:%S.%6N'), '1999-11-30 21:30:00.123456', "epoch hires 2 - $db_type"); 424 425 is($o->bint1, '9223372036854775800', "bigint 1 - $db_type"); 426 is($o->bint2, '-9223372036854775800', "bigint 2 - $db_type"); 427 is($o->bint3, '9223372036854775000', "bigint 3 - $db_type"); 428 is($o->bint4, undef, "bigint null 1 - $db_type"); 429 430 $o->bint4(555); 431 $o->bint1($o->bint1 + 1); 432 $o->save; 433 434 $o = MyPgObject->new(id => $o->id)->load; 435 is($o->bint1, '9223372036854775801', "bigint 4 - $db_type"); 436 is($o->bint4, 555, "bigint null 2 - $db_type"); 437 438 $o->bint4(undef); 439 440 $o->bint3(5); 441 eval { $o->bint3(7) }; 442 ok($@, "bigint 5 - $db_type"); 443 444 is($o->tee_time5->as_string, '12:34:56.12345', "time(5) - $db_type"); 445 446 $o->tee_time0('1pm'); 447 $o->tee_time('allballs'); 448 $o->tee_time9('now'); 449 $o->save; 450 451 $o = MyPgObject->new(id => $o->id)->load; 452 is($o->tee_time->as_string, '00:00:00', "time allballs - $db_type"); 453 ok($o->tee_time9->as_string =~ /^\d\d:\d\d:\d\d\.\d{1,6}$/, "time now - $db_type"); 454 is($o->bint4, undef, "bigint null 3 - $db_type"); 455 456 $o->tee_time(Time::Clock->new->parse('6:30 PM')); 457 $o->save; 458 459 $o = MyPgObject->new(id => $o->id)->load; 460 is($o->tee_time->as_string, '18:30:00', "time 6:30 PM - $db_type"); 461} 462 463# 464# MySQL 465# 466 467SKIP: foreach my $db_type ('mysql') 468{ 469 skip("MySQL tests", 121) unless($HAVE_MYSQL); 470 471 Rose::DB->default_type($db_type); 472 473 my $o = MyMySQLObject->new(name => 'John', 474 k1 => 1, 475 k2 => undef, 476 k3 => 3); 477 478 # Checking to see that Perl code generation methods don't die (See: 0.767 changes) 479 $o->meta->column('name')->check_in([ qw(a b c) ]); 480 $o->meta->perl_class_definition; 481 $o->meta->column('name')->check_in(undef); 482 483 ok(ref $o && $o->isa('MyMySQLObject'), "new() 1 - $db_type"); 484 485 $o->flag2('true'); 486 $o->date_created('now'); 487 $o->last_modified($o->date_created); 488 $o->save_col(22); 489 490 $o->bitz3('11'); 491 492 if(rand >= 0.5) 493 { 494 ok($o->save, "save() 1 - $db_type"); 495 } 496 else 497 { 498 ok($o->insert, "insert() 1 - $db_type"); 499 } 500 501 # Select for update tests 502 if($INNODB && $ENV{'RDBO_SLOW_TESTS'}) 503 { 504 $o = MyMySQLObject->new(id => $o->id); 505 506 $o->db->begin_work; 507 $o->load(for_update => 1); 508 509 # Silence errors in eval blocks below 510 Rose::DB->modify_db(type => $db_type)->print_error(0); 511 512 my $lo; 513 514 eval 515 { 516 $lo = MyMySQLObject->new(id => $o->id); 517 $lo->meta->error_mode('fatal'); 518 $lo->load(lock => { for_update => 1 }); 519 }; 520 521 is(DBI->err, 1205, "select for update wait 1 error 1205 - $db_type"); 522 ok($@, "select for update - $db_type"); 523 524 $o->db->commit; 525 } 526 else 527 { 528 if($INNODB) 529 { 530 SKIP: { skip("Select for update tests: RDBO_SLOW_TESTS not set - $db_type", 2) } 531 } 532 else 533 { 534 SKIP: { skip("Select for update tests: no InnoDB - $db_type", 2) } 535 } 536 } 537 538 $o = MyMySQLObject->new(id => $o->id); 539 $o->load(lock => { type => 'shared' }); 540 541 ok($o->load, "load() 1 - $db_type"); 542 543 is(ref $o->dt_default, 'DateTime', "now() default - $db_type"); 544 545 is($o->zepoch->ymd, '1970-01-01', "zero epoch default - $db_type"); 546 547 is_deeply([ sort $o->items ], [ qw(a c) ], "set default - $db_type"); 548 549 my $os = MyMySQLObject->new(id => $o->id)->load; 550 $os->items; 551 552 CATCH_STDERR: 553 { 554 local *STDERR; 555 my $stderr; 556 open(STDERR, '>', \$stderr) or die "Could not redirect STDERR - $!"; 557 558 local $Rose::DB::Object::Debug = 1; 559 $os->save(changes_only => 1); 560 is($stderr, undef, "save changes only for set column - $db_type"); 561 } 562 563 my $ox = MyMySQLObject->new(id => $o->id)->load; 564 is($ox->bitz2->to_Bin(), '00', "spot check bitfield 1 - $db_type"); 565 is($ox->bitz3->to_Bin(), '0011', "spot check bitfield 2 - $db_type"); 566 567 eval { $o->name('C' x 50) }; 568 ok($@, "varchar overflow fatal - $db_type"); 569 570 $o->name('John'); 571 572 $o->code('A'); 573 is($o->code, 'A ', "character padding - $db_type"); 574 575 eval { $o->code('C' x 50) }; 576 ok($@, "code overflow fatal - $db_type"); 577 $o->code('C' x 6); 578 579 is($o->enums, 'foo', "enum 1 - $db_type"); 580 eval { $o->enums('blee') }; 581 ok($@, "enum 2 - $db_type"); 582 583 $o->enums('bar'); 584 585 my $ouk; 586 587 ok($ouk = MyMySQLObject->new(k1 => 1, 588 k2 => undef, 589 k3 => 3)->load, "load() uk 1 - $db_type"); 590 591 ok(!$ouk->not_found, "not_found() uk 1 - $db_type"); 592 593 is($ouk->id, 1, "load() uk 2 - $db_type"); 594 is($ouk->name, 'John', "load() uk 3 - $db_type"); 595 596 ok($ouk->save, "save() uk 1 - $db_type"); 597 598 my $o2 = MyMySQLObject->new(id => $o->id); 599 600 ok(ref $o2 && $o2->isa('MyMySQLObject'), "new() 2 - $db_type"); 601 602 is($o2->bits->to_Bin, '00101', "bits() (bitfield default value) - $db_type"); 603 is($o2->bitz2->to_Bin, '00', "bitz2() (bitfield default value) - $db_type"); 604 605 ok($o2->load, "load() 2 - $db_type"); 606 607 ok(!$o2->not_found, "not_found() 1 - $db_type"); 608 609 is($o2->name, $o->name, "load() verify 1 - $db_type"); 610 is($o2->date_created, $o->date_created, "load() verify 2 - $db_type"); 611 is($o2->last_modified, $o->last_modified, "load() verify 3 - $db_type"); 612 is($o2->status, 'active', "load() verify 4 (default value) - $db_type"); 613 is($o2->flag, 1, "load() verify 5 (default boolean value) - $db_type"); 614 is($o2->flag2, 1, "load() verify 6 (boolean value) - $db_type"); 615 is($o2->save_col, 22, "load() verify 7 (aliased column) - $db_type"); 616 is($o2->start->ymd, '1980-12-24', "load() verify 8 (date value) - $db_type"); 617 618 $o2->set_status('foo'); 619 is($o2->get_status, 'foo', 'get_status()'); 620 $o2->set_status('active'); 621 eval { $o2->set_status }; 622 ok($@, 'set_status()'); 623 624 is($o2->bits->to_Bin, '00101', "load() verify 9 (bitfield value) - $db_type"); 625 is($o2->bitz2->to_Bin, '00', "load() verify 10 (bitfield value) - $db_type"); 626 is($o2->bitz3->to_Bin, '0011', "load() verify 11 (bitfield value) - $db_type"); 627 628 my $clone = $o2->clone; 629 ok($o2->start eq $clone->start, "clone() 1 - $db_type"); 630 $clone->start->set(year => '1960'); 631 ok($o2->start ne $clone->start, "clone() 2 - $db_type"); 632 633 $o2->name('John 2'); 634 $o2->start('5/24/2001'); 635 636 sleep(1); # keep the last modified dates from being the same 637 638 $o2->last_modified('now'); 639 ok($o2->save, "save() 2 - $db_type"); 640 ok($o2->load, "load() 3 - $db_type"); 641 642 is($o2->date_created, $o->date_created, "save() verify 1 - $db_type"); 643 ok($o2->last_modified ne $o->last_modified, "save() verify 2 - $db_type"); 644 is($o2->start->ymd, '2001-05-24', "save() verify 3 (date value) - $db_type"); 645 646 my $o3 = MyMySQLObject->new(); 647 648 my $db = $o3->db or die $o3->error; 649 650 ok(ref $db && $db->isa('Rose::DB'), "db() - $db_type"); 651 652 is($db->dbh, $o3->dbh, "dbh() - $db_type"); 653 654 my $o4 = MyMySQLObject->new(id => 999); 655 ok(!$o4->load(speculative => 1), "load() nonexistent - $db_type"); 656 ok($o4->not_found, "not_found() 2 - $db_type"); 657 658 eval { $o->items('z') }; 659 660 ok($@ =~ /Invalid value/, "set invalid value - $db_type"); 661 662 663 $o->items('a', 'b'); 664 $o->nums([ 4, 5, 6 ]); 665 666 ok($o->save, "save() 3 - $db_type"); 667 ok($o->load, "load() 4 - $db_type"); 668 669 is_deeply([ sort $o->items ], [ qw(a b) ], "set default - $db_type"); 670 671 is($o->nums->[0], 4, "load() verify 10 (array value) - $db_type"); 672 is($o->nums->[1], 5, "load() verify 11 (array value) - $db_type"); 673 is($o->nums->[2], 6, "load() verify 12 (array value) - $db_type"); 674 675 my @a = $o->nums; 676 677 is($a[0], 4, "load() verify 13 (array value) - $db_type"); 678 is($a[1], 5, "load() verify 14 (array value) - $db_type"); 679 is($a[2], 6, "load() verify 15 (array value) - $db_type"); 680 is(@a, 3, "load() verify 16 (array value) - $db_type"); 681 682 ok($o->delete, "delete() - $db_type"); 683 684 $o = MyMySQLObject->new(name => 'John', id => 9); 685 $o->save_col(22); 686 687 ok($o->save, "save() 4 - $db_type"); 688 $o->save_col(50); 689 ok($o->save, "save() 5 - $db_type"); 690 691 $ouk = MyMySQLObject->new(save_col => 50); 692 ok($ouk->load, "load() aliased unique key - $db_type"); 693 694 eval { $o->meta->alias_column(nonesuch => 'foo') }; 695 ok($@, "alias_column() nonesuch - $db_type"); 696 697 # This is okay now 698 #eval { $o->meta->alias_column(id => 'foo') }; 699 #ok($@, "alias_column() primary key - $db_type"); 700 701 $o = MyMySQLObject->new(id => 777); 702 703 $o->meta->error_mode('fatal'); 704 705 $o->dbh->{'PrintError'} = 0; 706 707 eval { $o->load }; 708 ok($@ && $o->not_found, "load() not found fatal - $db_type"); 709 710 my $old_table = $o->meta->table; 711 712 $o->meta->table('nonesuch'); 713 714 eval { $o->load }; 715 ok($@ && !$o->not_found, "load() fatal - $db_type"); 716 717 eval { $o->save }; 718 ok($@, "save() fatal - $db_type"); 719 720 $o->meta->table($old_table); 721 $o->meta->error_mode('return'); 722 723 $o = MyMPKMySQLObject->new(name => 'John'); 724 725 ok($o->save, "save() 1 multi-value primary key with generated values - $db_type"); 726 727 is($o->k1, 1, "save() verify 1 multi-value primary key with generated values - $db_type"); 728 is($o->k2, 2, "save() verify 2 multi-value primary key with generated values - $db_type"); 729 730 $o = MyMPKMySQLObject->new(name => 'Alex'); 731 732 ok($o->save, "save() 2 multi-value primary key with generated values - $db_type"); 733 734 is($o->k1, 3, "save() verify 3 multi-value primary key with generated values - $db_type"); 735 is($o->k2, 4, "save() verify 4 multi-value primary key with generated values - $db_type"); 736 737 is($ox->bitz3->to_Bin(), '0011', "spot check bitfield 3 - $db_type"); 738 739 $ox->bitz3->Bit_On(3); 740 is($ox->bitz3->to_Bin(), '1011', "spot check bitfield 4 - $db_type"); 741 742 $ox->save(insert => 1); 743 744 $ox = MyMySQLObject->new(id => $ox->id)->load; 745 is($ox->bitz3->to_Bin(), '1011', "spot check bitfield 5 - $db_type"); 746 747 $ox->bitz3->Bit_On(2); 748 $ox->save; 749 $ox = MyMySQLObject->new(id => $ox->id)->load; 750 is($ox->bitz3->to_Bin(), '1111', "spot check bitfield 6 - $db_type"); 751 752 $o = MyMySQLObject->new(id => 9999); # no such id 753 754 $o->meta->error_mode('fatal'); 755 756 eval { $o->load() }; 757 ok($@, "load() non-speculative implicit - $db_type"); 758 ok(!$o->load(speculative => 1), "load() speculative explicit 1 - $db_type"); 759 eval { $o->load(speculative => 0) }; 760 ok($@, "load() non-speculative explicit 2 - $db_type"); 761 762 $o->meta->default_load_speculative(1); 763 764 ok(!$o->load(), "load() speculative implicit - $db_type"); 765 ok(!$o->load(speculative => 1), "load() speculative explicit 2 - $db_type"); 766 eval { $o->load(speculative => 0) }; 767 ok($@, "load() non-speculative explicit 2 - $db_type"); 768 769 $o->meta->default_load_speculative(0); 770 771 $o = MyMySQLObject->new(id => 1)->load; 772 773 is($o->dur->months, 2, "interval months 1 - $db_type"); 774 is($o->dur->days, 5, "interval days 1 - $db_type"); 775 is($o->dur->seconds, 3, "interval seconds 1 - $db_type"); 776 777 $o->dur(DateTime::Duration->new(years => 7, nanoseconds => 3000)); 778 779 is($o->dur->in_units('years'), 7, "interval in_units years 1 - $db_type"); 780 is($o->dur->in_units('months'), 84, "interval in_units months 1 - $db_type"); 781 is($o->dur->nanoseconds, 3000, "interval nanoseconds 1 - $db_type"); 782 is($o->dur->days, 0, "interval days 2 - $db_type"); 783 is($o->dur->minutes, 0, "interval minutes 2 - $db_type"); 784 is($o->dur->seconds, 0, "interval seconds 2 - $db_type"); 785 786 $o->save; 787 788 $o = MyMySQLObject->new(id => $o->id)->load; 789 790 is($o->dur->in_units('years'), 7, "interval in_units years 2 - $db_type"); 791 is($o->dur->in_units('months'), 84, "interval in_units months 2 - $db_type"); 792 is($o->dur->nanoseconds, 3000, "interval nanoseconds 2 - $db_type"); 793 is($o->dur->days, 0, "interval days 3 - $db_type"); 794 is($o->dur->minutes, 0, "interval minutes 3 - $db_type"); 795 is($o->dur->seconds, 0, "interval seconds 3 - $db_type"); 796 797 is($o->meta->column('dur')->scale, 6, "interval scale - $db_type"); 798 799 is($o->epoch(format => '%Y-%m-%d %H:%M:%S'), '1999-11-30 21:30:00', "epoch 1 - $db_type"); 800 801 $o->hiepoch('943997400.123456'); 802 is($o->hiepoch(format => '%Y-%m-%d %H:%M:%S.%6N'), '1999-11-30 21:30:00.123456', "epoch hires 1 - $db_type"); 803 804 $o->epoch('5/6/1980 12:34:56'); 805 806 $o->save; 807 808 $o = MyMySQLObject->new(id => $o->id)->load; 809 810 is($o->epoch(format => '%Y-%m-%d %H:%M:%S'), '1980-05-06 12:34:56', "epoch 2 - $db_type"); 811 is($o->hiepoch(format => '%Y-%m-%d %H:%M:%S.%6N'), '1999-11-30 21:30:00.123456', "epoch hires 2 - $db_type"); 812 813 is($o->tee_time5->as_string, '12:34:56.12345', "time(5) - $db_type"); 814 815 $o->tee_time0('1pm'); 816 eval { $o->tee_time('allballs') }; 817 ok($@, "allballs - $db_type"); 818 $o->tee_time('0:00'); 819 $o->tee_time9('now'); 820 $o->save; 821 822 $o = MyMySQLObject->new(id => $o->id)->load; 823 is($o->tee_time->as_string, '00:00:00', "time allballs - $db_type"); 824 825 if($Have_HiRes_Time) 826 { 827 ok($o->tee_time9->as_string =~ /^\d\d:\d\d:\d\d\.\d+$/, "time now - $db_type"); 828 } 829 else 830 { 831 ok($o->tee_time9->as_string =~ /^\d\d:\d\d:\d\d$/, "time now - $db_type"); 832 } 833 834 $o->tee_time(Time::Clock->new->parse('6:30 PM')); 835 $o->save; 836 837 $o = MyMySQLObject->new(id => $o->id)->load; 838 is($o->tee_time->as_string, '18:30:00', "time 6:30 PM - $db_type"); 839 840 MyMySQLObject->meta->column('save')->default('x'); 841 MyMySQLObject->meta->make_column_methods(replace_existing => 1); 842 843 $o->meta->default_load_speculative(0); 844 845 $o = MyMySQLObject->new(k1 => 1, k3 => 3); 846 ok(!$o->load(speculative => 1), "load default key - $db_type"); 847 848 eval { $o->load(use_key => 'id') }; 849 ok($@, "use_key no such key - $db_type"); 850 851 $o->load(use_key => 'k1_k2_k3'); 852 is($o->k1, 1, "load specific key 1 - $db_type"); 853 is($o->k3, 3, "load specific key 2 - $db_type"); 854 is($o->name, 'John', "load specific key 3 - $db_type"); 855} 856 857# 858# Informix 859# 860 861SKIP: foreach my $db_type ('informix') 862{ 863 skip("Informix tests", 73) unless($HAVE_INFORMIX); 864 865 Rose::DB->default_type($db_type); 866 867 my $o = MyInformixObject->new(name => 'John', 868 id => 1, 869 k1 => 1, 870 k2 => undef, 871 k3 => 3); 872 873 ok(ref $o && $o->isa('MyInformixObject'), "new() 1 - $db_type"); 874 875 $o->meta->allow_inline_column_values(1); 876 877 $o->flag2('true'); 878 $o->date_created('current year to fraction(5)'); 879 $o->last_modified($o->date_created); 880 $o->save_col(22); 881 882 if(rand >= 0.5) 883 { 884 ok($o->save, "save() 1 - $db_type"); 885 } 886 else 887 { 888 ok($o->insert, "insert() 1 - $db_type"); 889 } 890 891 ok($o->load, "load() 1 - $db_type"); 892 893 $o->name('C' x 50); 894 is($o->name, 'C' x 32, "varchar truncation - $db_type"); 895 896 $o->name('John'); 897 898 $o->code('A'); 899 is($o->code, 'A ', "character padding - $db_type"); 900 901 $o->code('C' x 50); 902 is($o->code, 'C' x 6, "character truncation - $db_type"); 903 904 my $ouk; 905 ok($ouk = MyInformixObject->new(k1 => 1, 906 k2 => undef, 907 k3 => 3)->load, "load() uk 1 - $db_type"); 908 909 ok(!$ouk->not_found, "not_found() uk 1 - $db_type"); 910 911 is($ouk->id, 1, "load() uk 2 - $db_type"); 912 is($ouk->name, 'John', "load() uk 3 - $db_type"); 913 914 ok($ouk->save, "save() uk 1 - $db_type"); 915 916 my $o2 = MyInformixObject->new(id => $o->id); 917 918 ok(ref $o2 && $o2->isa('MyInformixObject'), "new() 2 - $db_type"); 919 920 is($o2->bits->to_Bin, '00101', "bits() (bitfield default value) - $db_type"); 921 922 ok($o2->load, "load() 2 - $db_type"); 923 ok(!$o2->not_found, "not_found() 1 - $db_type"); 924 925 is($o2->name, $o->name, "load() verify 1 - $db_type"); 926 is($o2->date_created, $o->date_created, "load() verify 2 - $db_type"); 927 is($o2->last_modified, $o->last_modified, "load() verify 3 - $db_type"); 928 is($o2->status, 'active', "load() verify 4 (default value) - $db_type"); 929 is($o2->flag, 1, "load() verify 5 (default boolean value) - $db_type"); 930 is($o2->flag2, 1, "load() verify 6 (boolean value) - $db_type"); 931 is($o2->save_col, 22, "load() verify 7 (aliased column) - $db_type"); 932 is($o2->start->ymd, '1980-12-24', "load() verify 8 (date value) - $db_type"); 933 934 $o2->set_status('foo'); 935 is($o2->get_status, 'foo', 'get_status()'); 936 $o2->set_status('active'); 937 eval { $o2->set_status }; 938 ok($@, 'set_status()'); 939 940 is($o2->bits->to_Bin, '00101', "load() verify 9 (bitfield value) - $db_type"); 941 942 my $clone = $o2->clone; 943 ok($o2->start eq $clone->start, "clone() 1 - $db_type"); 944 $clone->start->set(year => '1960'); 945 ok($o2->start ne $clone->start, "clone() 2 - $db_type"); 946 947 $o2->name('John 2'); 948 $o2->start('5/24/2001'); 949 950 sleep(1); # keep the last modified dates from being the same 951 952 $o2->last_modified('current year to second'); 953 ok($o2->save, "save() 2 - $db_type"); 954 ok($o2->load, "load() 3 - $db_type"); 955 956 is($o2->date_created, $o->date_created, "save() verify 1 - $db_type"); 957 ok($o2->last_modified ne $o->last_modified, "save() verify 2 - $db_type"); 958 is($o2->start->ymd, '2001-05-24', "save() verify 3 (date value) - $db_type"); 959 960 my $o3 = MyInformixObject->new(); 961 962 my $db = $o3->db or die $o3->error; 963 964 ok(ref $db && $db->isa('Rose::DB'), "db() - $db_type"); 965 966 is($db->dbh, $o3->dbh, "dbh() - $db_type"); 967 968 my $o4 = MyInformixObject->new(id => 999); 969 ok(!$o4->load(speculative => 1), "load() nonexistent - $db_type"); 970 ok($o4->not_found, "not_found() 2 - $db_type"); 971 972 $o->nums([ 4, 5, 6 ]); 973 $o->names([ qw(a b 3.1) ]); 974 975 ok($o->save, "save() 3 - $db_type"); 976 ok($o->load, "load() 4 - $db_type"); 977 978 is($o->nums->[0], 4, "load() verify 10 (array value) - $db_type"); 979 is($o->nums->[1], 5, "load() verify 11 (array value) - $db_type"); 980 is($o->nums->[2], 6, "load() verify 12 (array value) - $db_type"); 981 982 $o->nums(7, 8, 9); 983 984 my @a = $o->nums; 985 986 is($a[0], 7, "load() verify 13 (array value) - $db_type"); 987 is($a[1], 8, "load() verify 14 (array value) - $db_type"); 988 is($a[2], 9, "load() verify 15 (array value) - $db_type"); 989 is(@a, 3, "load() verify 16 (array value) - $db_type"); 990 991 is($o->names->[0], 'a', "load() verify 10 (set value) - $db_type"); 992 is($o->names->[1], 'b', "load() verify 11 (set value) - $db_type"); 993 is($o->names->[2], '3.1', "load() verify 12 (set value) - $db_type"); 994 995 $o->names('c', 'd', '4.2'); 996 997 @a = $o->names; 998 999 is($a[0], 'c', "load() verify 13 (set value) - $db_type"); 1000 is($a[1], 'd', "load() verify 14 (set value) - $db_type"); 1001 is($a[2], '4.2', "load() verify 15 (set value) - $db_type"); 1002 is(@a, 3, "load() verify 16 (set value) - $db_type"); 1003 1004 ok($o->delete, "delete() - $db_type"); 1005 1006 $o = MyInformixObject->new(name => 'John', id => 9); 1007 1008 $o->flag2('true'); 1009 $o->date_created('current year to fraction(5)'); 1010 $o->last_modified($o->date_created); 1011 $o->save_col(22); 1012 1013 ok($o->save, "save() 4 - $db_type"); 1014 $o->save_col(50); 1015 1016 ok($o->save, "save() 5 - $db_type"); 1017 1018 $ouk = MyInformixObject->new(save_col => 50); 1019 ok($ouk->load, "load() aliased unique key - $db_type"); 1020 1021 eval { $o->meta->alias_column(nonesuch => 'foo') }; 1022 ok($@, "alias_column() nonesuch - $db_type"); 1023 1024 # This is okay now 1025 #eval { $o->meta->alias_column(id => 'foo') }; 1026 #ok($@, "alias_column() primary key - $db_type"); 1027 1028 $o = MyInformixObject->new(id => 777); 1029 1030 $o->meta->error_mode('fatal'); 1031 1032 $o->dbh->{'PrintError'} = 0; 1033 1034 eval { $o->load }; 1035 ok($@ && $o->not_found, "load() not found fatal - $db_type"); 1036 1037 $o->id('abc'); 1038 1039 eval { $o->load }; 1040 ok($@ && !$o->not_found, "load() fatal - $db_type"); 1041 1042 eval { $o->save }; 1043 ok($@, "save() fatal - $db_type"); 1044 1045 #$o->meta->error_mode('return'); 1046 1047 $o = MyInformixObject->new(id => 9999); # no such id 1048 1049 $o->meta->error_mode('fatal'); 1050 1051 eval { $o->load() }; 1052 ok($@, "load() non-speculative implicit - $db_type"); 1053 ok(!$o->load(speculative => 1), "load() speculative explicit 1 - $db_type"); 1054 eval { $o->load(speculative => 0) }; 1055 ok($@, "load() non-speculative explicit 2 - $db_type"); 1056 1057 $o->meta->default_load_speculative(1); 1058 1059 ok(!$o->load(), "load() speculative implicit - $db_type"); 1060 ok(!$o->load(speculative => 1), "load() speculative explicit 2 - $db_type"); 1061 eval { $o->load(speculative => 0) }; 1062 ok($@, "load() non-speculative explicit 2 - $db_type"); 1063} 1064 1065# 1066# SQLite 1067# 1068 1069SKIP: foreach my $db_type ('sqlite') 1070{ 1071 skip("SQLite tests", 75) unless($HAVE_SQLITE); 1072 1073 Rose::DB->default_type($db_type); 1074 1075 my $o = MySQLiteObject->new(name => 'John', 1076 k1 => 1, 1077 k2 => undef, 1078 k3 => 3); 1079 1080 ok(ref $o && $o->isa('MySQLiteObject'), "new() 1 - $db_type"); 1081 1082 $o->flag2('true'); 1083 $o->date_created('now'); 1084 $o->last_modified($o->date_created); 1085 $o->save_col(22); 1086 1087 if(rand >= 0.5) 1088 { 1089 ok($o->save, "save() 1 - $db_type"); 1090 } 1091 else 1092 { 1093 ok($o->insert, "insert() 1 - $db_type"); 1094 } 1095 1096 ok($o->load, "load() 1 - $db_type"); 1097 1098 $o->name('C' x 50); 1099 is($o->name, 'C' x 32, "varchar truncation - $db_type"); 1100 1101 $o->name('John'); 1102 1103 $o->code('A'); 1104 is($o->code, 'A ', "character padding - $db_type"); 1105 1106 $o->code('C' x 50); 1107 is($o->code, 'C' x 6, "character truncation - $db_type"); 1108 1109 my $ouk; 1110 ok($ouk = MySQLiteObject->new(k1 => 1, 1111 k2 => undef, 1112 k3 => 3)->load, "load() uk 1 - $db_type"); 1113 1114 ok(!$ouk->not_found, "not_found() uk 1 - $db_type"); 1115 1116 is($ouk->id->[0], 1, "load() uk 2 - $db_type"); 1117 is($ouk->name, 'John', "load() uk 3 - $db_type"); 1118 1119 ok($ouk->save, "save() uk 1 - $db_type"); 1120 1121 my $o2 = MySQLiteObject->new(id => $o->id); 1122 1123 ok(ref $o2 && $o2->isa('MySQLiteObject'), "new() 2 - $db_type"); 1124 1125 is($o2->bits->to_Bin, '00101', "bits() (bitfield default value) - $db_type"); 1126 1127 ok($o2->load, "load() 2 - $db_type"); 1128 ok(!$o2->not_found, "not_found() 1 - $db_type"); 1129 1130 is($o2->name, $o->name, "load() verify 1 - $db_type"); 1131 is($o2->date_created, $o->date_created, "load() verify 2 - $db_type"); 1132 is($o2->last_modified, $o->last_modified, "load() verify 3 - $db_type"); 1133 is($o2->status, 'active', "load() verify 4 (default value) - $db_type"); 1134 is($o2->flag, 1, "load() verify 5 (default boolean value) - $db_type"); 1135 is($o2->flag2, 1, "load() verify 6 (boolean value) - $db_type"); 1136 is($o2->save_col, 22, "load() verify 7 (aliased column) - $db_type"); 1137 is($o2->start->ymd, '1980-12-24', "load() verify 8 (date value) - $db_type"); 1138 1139 $o2->set_status('foo'); 1140 is($o2->get_status, 'foo', 'get_status()'); 1141 $o2->set_status('active'); 1142 eval { $o2->set_status }; 1143 ok($@, 'set_status()'); 1144 1145 is($o2->bits->to_Bin, '00101', "load() verify 9 (bitfield value) - $db_type"); 1146 1147 my $clone = $o2->clone; 1148 ok($o2->start eq $clone->start, "clone() 1 - $db_type"); 1149 $clone->start->set(year => '1960'); 1150 ok($o2->start ne $clone->start, "clone() 2 - $db_type"); 1151 1152 $o2->name('John 2'); 1153 $o2->start('5/24/2001'); 1154 1155 sleep(1); # keep the last modified dates from being the same 1156 1157 $o2->last_modified('now'); 1158 ok($o2->save, "save() 2 - $db_type"); 1159 ok($o2->load, "load() 3 - $db_type"); 1160 1161 is($o2->date_created, $o->date_created, "save() verify 1 - $db_type"); 1162 ok($o2->last_modified ne $o->last_modified, "save() verify 2 - $db_type"); 1163 is($o2->start->ymd, '2001-05-24', "save() verify 3 (date value) - $db_type"); 1164 1165 my $o3 = MySQLiteObject->new(); 1166 1167 my $db = $o3->db or die $o3->error; 1168 1169 ok(ref $db && $db->isa('Rose::DB'), "db() - $db_type"); 1170 1171 is($db->dbh, $o3->dbh, "dbh() - $db_type"); 1172 1173 my $o4 = MySQLiteObject->new(id => 999); 1174 ok(!$o4->load(speculative => 1), "load() nonexistent - $db_type"); 1175 ok($o4->not_found, "not_found() 2 - $db_type"); 1176 1177 $o->nums([ 4, 5, 6 ]); 1178 ok($o->save, "save() 3 - $db_type"); 1179 ok($o->load, "load() 4 - $db_type"); 1180 1181 is($o->nums->[0], 4, "load() verify 10 (array value) - $db_type"); 1182 is($o->nums->[1], 5, "load() verify 11 (array value) - $db_type"); 1183 is($o->nums->[2], 6, "load() verify 12 (array value) - $db_type"); 1184 1185 my @a = $o->nums; 1186 1187 is($a[0], 4, "load() verify 13 (array value) - $db_type"); 1188 is($a[1], 5, "load() verify 14 (array value) - $db_type"); 1189 is($a[2], 6, "load() verify 15 (array value) - $db_type"); 1190 is(@a, 3, "load() verify 16 (array value) - $db_type"); 1191 1192 ok($o->delete, "delete() - $db_type"); 1193 1194 $o = MySQLiteObject->new(name => 'John', id => 9); 1195 $o->save_col(22); 1196 ok($o->save, "save() 4 - $db_type"); 1197 $o->save_col(50); 1198 ok($o->save, "save() 5 - $db_type"); 1199 1200 $ouk = MySQLiteObject->new(save_col => 50); 1201 ok($ouk->load, "load() aliased unique key - $db_type"); 1202 1203 eval { $o->meta->alias_column(nonesuch => 'foo') }; 1204 ok($@, "alias_column() nonesuch - $db_type"); 1205 1206 # This is okay now 1207 #eval { $o->meta->alias_column(id => 'foo') }; 1208 #ok($@, "alias_column() primary key - $db_type"); 1209 1210 $o = MySQLiteObject->new(id => 777); 1211 1212 $o->meta->error_mode('fatal'); 1213 1214 $o->dbh->{'PrintError'} = 0; 1215 1216 eval { $o->load }; 1217 ok($@ && $o->not_found, "load() not found fatal - $db_type"); 1218 1219 my $old_table = $o->meta->table; 1220 1221 $o->meta->table('nonesuch'); 1222 1223 eval { $o->load }; 1224 ok($@ && !$o->not_found, "load() fatal - $db_type"); 1225 1226 eval { $o->save }; 1227 ok($@, "save() fatal - $db_type"); 1228 1229 $o->meta->table($old_table); 1230 $o->meta->error_mode('return'); 1231 1232 $o = MyMPKSQLiteObject->new(name => 'John'); 1233 1234 ok($o->save, "save() 1 multi-value primary key with generated values - $db_type"); 1235 1236 is($o->k1, 1, "save() verify 1 multi-value primary key with generated values - $db_type"); 1237 is($o->k2, 2, "save() verify 2 multi-value primary key with generated values - $db_type"); 1238 1239 $o = MyMPKSQLiteObject->new(name => 'Alex'); 1240 1241 ok($o->save, "save() 2 multi-value primary key with generated values - $db_type"); 1242 1243 is($o->k1, 3, "save() verify 3 multi-value primary key with generated values - $db_type"); 1244 is($o->k2, 4, "save() verify 4 multi-value primary key with generated values - $db_type"); 1245 1246 $o = MySQLiteObject->new(id => 9999); # no such id 1247 1248 $o->meta->error_mode('fatal'); 1249 1250 eval { $o->load() }; 1251 ok($@, "load() non-speculative implicit - $db_type"); 1252 ok(!$o->load(speculative => 1), "load() speculative explicit 1 - $db_type"); 1253 eval { $o->load(speculative => 0) }; 1254 ok($@, "load() non-speculative explicit 2 - $db_type"); 1255 1256 $o->meta->default_load_speculative(1); 1257 1258 ok(!$o->load(), "load() speculative implicit - $db_type"); 1259 ok(!$o->load(speculative => 1), "load() speculative explicit 2 - $db_type"); 1260 eval { $o->load(speculative => 0) }; 1261 ok($@, "load() non-speculative explicit 2 - $db_type"); 1262 1263 # 1264 # Test SQLite BLOB support 1265 # 1266 1267 my $blob = "abc\0def"; 1268 $o = MySQLiteObject->new(id => 888, name => 'Blob', data => $blob); 1269 $o->save; 1270 1271 $o = MySQLiteObject->new(id => $o->id)->load; 1272 is($o->data, $blob, "blob check - $db_type"); 1273} 1274 1275SKIP: foreach my $db_type (qw(oracle)) 1276{ 1277 skip("Oracle tests", 85) unless($HAVE_ORACLE); 1278 1279 Rose::DB->default_type($db_type); 1280 1281 TEST_HACK: 1282 { 1283 no warnings; 1284 *MyOracleObject::init_db = sub { Rose::DB->new($db_type) }; 1285 } 1286 1287 my $o = MyOracleObject->new(name => 'John', 1288 k1 => 1, 1289 k2 => undef, 1290 k3 => 3); 1291 1292 ok(ref $o && $o->isa('MyOracleObject'), "new() 1 - $db_type"); 1293 1294 $o->flag2('TRUE'); 1295 $o->date_created('now'); 1296 $o->date_created_tz('now'); 1297 $o->timestamp_tz2('now'); 1298 $o->last_modified($o->date_created); 1299 $o->save_col(7); 1300 1301 if(rand >= 0.5) 1302 { 1303 ok($o->save, "save() 1 - $db_type"); 1304 } 1305 else 1306 { 1307 ok($o->insert, "insert() 1 - $db_type"); 1308 } 1309 1310 is($o->meta->primary_key->sequence_names->[0], 'ROSE_DB_OBJECT_TEST_ID_SEQ', 1311 "pk sequence name - $db_type"); 1312 1313 ok(is_in_db($o), "is_in_db - $db_type"); 1314 1315 is($o->id, 1, "auto-generated primary key - $db_type"); 1316 1317 if(oracle_is_broken()) 1318 { 1319 SKIP: { skip("tests that trigger the dreaded ORA-00600 kpofdr-long error", 4) } 1320 } 1321 else 1322 { 1323 ok($o->load, "load() 1 - $db_type"); 1324 1325 is($o->date_created->time_zone->name, 'floating', "timestamp without time zone - $db_type"); 1326 isnt($o->date_created_tz->time_zone->name, 'floating', "timestamp with time zone - $db_type"); 1327 is($o->timestamp_tz2->time_zone->name, 'Antarctica/Vostok', "timestamp with time zone override - $db_type"); 1328 1329 # Make sure we're not in the Antarctica/Vostok time zone or any other 1330 # time zone with the same offset. 1331 my $error; 1332 1333 TRY: 1334 { 1335 local $@; 1336 1337 eval 1338 { 1339 my $dt1 = DateTime->now(time_zone => 'local'); 1340 my $dt2 = $dt1->clone; 1341 $dt2->set_time_zone('Antarctica/Vostok'); 1342 die "local is equivalent to Antarctica/Vostok" if($dt1->iso8601 eq $dt2->iso8601); 1343 }; 1344 1345 $error = $@; 1346 } 1347 1348 if($error) 1349 { 1350 SKIP: { skip("timestamp with time zone time change - $db_type", 2) } 1351 } 1352 else 1353 { 1354 isnt($o->date_created_tz->iso8601, $o->timestamp_tz2->iso8601, "timestamp with time zone time change - $db_type"); 1355 1356 $o->save; 1357 $o->load; 1358 1359 my $dt = $o->timestamp_tz2->clone; 1360 $dt->set_time_zone($o->date_created_tz->time_zone); 1361 1362 is($o->date_created_tz->iso8601, $dt->iso8601, "timestamp with time zone time change 2 - $db_type"); 1363 } 1364 1365 $o->name('C' x 50); 1366 is($o->name, 'C' x 32, "varchar truncation - $db_type"); 1367 1368 $o->name('John'); 1369 1370 $o->code('A'); 1371 is($o->code, 'A ', "character padding - $db_type"); 1372 1373 $o->code('C' x 50); 1374 is($o->code, 'C' x 6, "character truncation - $db_type"); 1375 } 1376 1377 my $ouk; 1378 ok($ouk = MyOracleObject->new(k1 => 1, 1379 k2 => undef, 1380 k3 => 3)->load, "load() uk 1 - $db_type"); 1381 1382 ok(!$ouk->not_found, "not_found() uk 1 - $db_type"); 1383 1384 is($ouk->id, 1, "load() uk 2 - $db_type"); 1385 is($ouk->name, 'John', "load() uk 3 - $db_type"); 1386 1387 ok($ouk->save, "save() uk 1 - $db_type"); 1388 1389 my $o2 = MyOracleObject->new(id => $o->id); 1390 1391 ok(ref $o2 && $o2->isa('MyOracleObject'), "new() 2 - $db_type"); 1392 1393 is($o2->bits->to_Bin, '00101', "bits() (bitfield default value) - $db_type"); 1394 1395 if(oracle_is_broken()) 1396 { 1397 SKIP: { skip("tests that trigger the dreaded ORA-00600 kpofdr-long error", 22) } 1398 } 1399 else 1400 { 1401 ok($o2->load, "load() 2 - $db_type"); 1402 ok(!$o2->not_found, "not_found() 1 - $db_type"); 1403 1404 is($o2->name, $o->name, "load() verify 1 - $db_type"); 1405 is($o2->date_created, $o->date_created, "load() verify 2 - $db_type"); 1406 is($o2->last_modified, $o->last_modified, "load() verify 3 - $db_type"); 1407 is($o2->status, 'active', "load() verify 4 (default value) - $db_type"); 1408 is($o2->flag, 1, "load() verify 5 (default boolean value) - $db_type"); 1409 is($o2->flag2, 1, "load() verify 6 (boolean value) - $db_type"); 1410 is($o2->save_col, 7, "load() verify 7 (aliased column) - $db_type"); 1411 is($o2->start_date->ymd, '1980-12-24', "load() verify 8 (date value) - $db_type"); 1412 1413 $o2->set_status('foo'); 1414 is($o2->get_status, 'foo', "get_status() - $db_type"); 1415 $o2->set_status('active'); 1416 eval { $o2->set_status }; 1417 ok($@, "set_status() - $db_type"); 1418 1419 is($o2->bits->to_Bin, '00101', "load() verify 9 (bitfield value) - $db_type"); 1420 1421 my $clone = $o2->clone; 1422 ok($o2->start_date eq $clone->start_date, "clone() 1 - $db_type"); 1423 $clone->start_date->set(year => '1960'); 1424 ok($o2->start_date ne $clone->start_date, "clone() 2 - $db_type"); 1425 1426 $o2->start_date('5/24/2001'); 1427 1428 sleep(1); # keep the last modified dates from being the same 1429 1430 $o2->last_modified('now'); 1431 ok($o2->save, "save() 2 - $db_type"); 1432 ok($o2->load, "load() 3 - $db_type"); 1433 1434 ok(!has_modified_columns($o2), "no modified columns after load() - $db_type"); 1435 1436 $o2->name('John 2'); 1437 $o2->save(changes_only => 1); 1438 1439 is($o2->date_created, $o->date_created, "save() verify 1 - $db_type"); 1440 ok($o2->last_modified ne $o->last_modified, "save() verify 2 - $db_type"); 1441 is($o2->start_date->ymd, '2001-05-24', "save() verify 3 (date value) - $db_type"); 1442 1443 my $bo = MyOracleObject->new(id => $o->id); 1444 $bo->load; 1445 $bo->flag(0); 1446 $bo->save; 1447 1448 $bo = MyOracleObject->new(id => $o->id); 1449 $bo->load; 1450 1451 ok(!$bo->flag, "boolean check - $db_type"); 1452 1453 $bo->flag(0); 1454 $bo->save; 1455 } 1456 1457 my $o3 = MyOracleObject->new(); 1458 1459 my $db = $o3->db or die $o3->error; 1460 1461 ok(ref $db && $db->isa('Rose::DB'), "db() - $db_type"); 1462 1463 is($db->dbh, $o3->dbh, "dbh() - $db_type"); 1464 1465 my $o4 = MyOracleObject->new(id => 999); 1466 ok(!$o4->load(speculative => 1), "load() nonexistent - $db_type"); 1467 ok($o4->not_found, "not_found() 2 - $db_type"); 1468 1469 ok($o->load, "load() 4 - $db_type"); 1470 1471 my $o5 = MyOracleObject->new(id => $o->id); 1472 1473 ok($o5->load, "load() 5 - $db_type"); 1474 1475 $o5->nums([ 4, 5, 6 ]); 1476 ok($o5->save, "save() 4 - $db_type"); 1477 ok($o->load, "load() 6 - $db_type"); 1478 1479 is($o5->nums->[0], 4, "load() verify 10 (array value) - $db_type"); 1480 is($o5->nums->[1], 5, "load() verify 11 (array value) - $db_type"); 1481 is($o5->nums->[2], 6, "load() verify 12 (array value) - $db_type"); 1482 1483 my @a = $o5->nums; 1484 1485 is($a[0], 4, "load() verify 13 (array value) - $db_type"); 1486 is($a[1], 5, "load() verify 14 (array value) - $db_type"); 1487 is($a[2], 6, "load() verify 15 (array value) - $db_type"); 1488 is(@a, 3, "load() verify 16 (array value) - $db_type"); 1489 1490 ok($o->delete, "delete() - $db_type"); 1491 1492 $o = MyOracleObject->new(name => 'John', id => 9); 1493 $o->save_col(22); 1494 ok($o->save, "save() 4 - $db_type"); 1495 $o->save_col(50); 1496 ok($o->save, "save() 5 - $db_type"); 1497 1498 $ouk = MyOracleObject->new(save_col => 50); 1499 ok($ouk->load, "load() aliased unique key - $db_type"); 1500 1501 eval { $o->meta->alias_column(nonesuch => 'foo') }; 1502 ok($@, "alias_column() nonesuch - $db_type"); 1503 1504 # This is okay now 1505 #eval { $o->meta->alias_column(id => 'foo') }; 1506 #ok($@, "alias_column() primary key - $db_type"); 1507 1508 $o = MyOracleObject->new(id => 777); 1509 1510 $o->meta->error_mode('fatal'); 1511 1512 $o->dbh->{'PrintError'} = 0; 1513 1514 eval { $o->load }; 1515 ok($@ && $o->not_found, "load() not found fatal - $db_type"); 1516 1517 $o->id('abc'); 1518 1519 eval { $o->load }; 1520 ok($@ && !$o->not_found, "load() fatal - $db_type"); 1521 1522 eval { $o->save }; 1523 ok($@, "save() fatal - $db_type"); 1524 1525 $o = MyOracleObject->new(id => 9999); # no such id 1526 1527 $o->meta->error_mode('fatal'); 1528 1529 eval { $o->load() }; 1530 ok($@, "load() non-speculative implicit - $db_type"); 1531 ok(!$o->load(speculative => 1), "load() speculative explicit 1 - $db_type"); 1532 eval { $o->load(speculative => 0) }; 1533 ok($@, "load() non-speculative explicit 2 - $db_type"); 1534 1535 $o->meta->default_load_speculative(1); 1536 1537 ok(!$o->load(), "load() speculative implicit - $db_type"); 1538 ok(!$o->load(speculative => 1), "load() speculative explicit 2 - $db_type"); 1539 eval { $o->load(speculative => 0) }; 1540 ok($@, "load() non-speculative explicit 2 - $db_type"); 1541 1542 $o = MyOracleObject->new(name => 'Sequence Test', 1543 k1 => 4, 1544 k2 => 5, 1545 k3 => 6, 1546 key => 123); 1547 1548 $o->save; 1549 1550 like($o->id, qr/^\d+$/, "save() serial - $db_type"); 1551 1552 # Select for update tests 1553 1554 $o = MyOracleObject->new(id => $o->id)->load(for_update => 1, lock => { columns => [ qw(k2 k3) ] }); 1555 1556 # Silence errors in eval blocks below 1557 Rose::DB->modify_db(type => $db_type)->print_error(0); 1558 1559 eval 1560 { 1561 $o = 1562 MyOracleObject->new(id => $o->id)->load( 1563 lock => 1564 { 1565 type => 'for update', 1566 on => [ qw(k2 k3) ], 1567 nowait => 1, 1568 }); 1569 }; 1570 1571 ok($@, "select for update failure - $db_type"); 1572 1573 my $lo; 1574 1575 eval 1576 { 1577 $lo = MyOracleObject->new(id => $o->id); 1578 $lo->load(lock => { for_update => 1, nowait => 1 }); 1579 }; 1580 1581 is(DBI->err, 54, "select for update no wait ORA-00054 - $db_type"); 1582 ok($@, "select for update no wait - $db_type"); 1583 1584 eval 1585 { 1586 $lo = MyOracleObject->new(id => $o->id); 1587 $lo->load(lock => { type => 'for update', wait => 1 }); 1588 }; 1589 1590 is(DBI->err, 30006, "select for update wait 1 ORA-30006 - $db_type"); 1591 ok($@, "select for update wait 1 - $db_type"); 1592 1593 $o->save; 1594 1595 Rose::DB->modify_db(type => $db_type)->print_error(1); 1596 1597 # Reset for next trip through loop (if any) 1598 $o->meta->default_load_speculative(0); 1599 $o->meta->error_mode('return'); 1600 1601 $o = MyOracleObject->new(key => 123); 1602 eval { $o->load }; 1603 1604 ok(!$@, "reserved-word load() - $db_type"); 1605} 1606 1607BEGIN 1608{ 1609 # 1610 # PostgreSQL 1611 # 1612 1613 my $dbh; 1614 1615 eval 1616 { 1617 $dbh = Rose::DB->new('pg_admin')->retain_dbh() 1618 or die Rose::DB->error; 1619 }; 1620 1621 if(!$@ && $dbh) 1622 { 1623 our $HAVE_PG = 1; 1624 1625 # Drop existing table and create schema, ignoring errors 1626 { 1627 local $dbh->{'RaiseError'} = 0; 1628 local $dbh->{'PrintError'} = 0; 1629 $dbh->do('DROP TABLE rose_db_object_test'); 1630 $dbh->do('DROP TABLE rose_db_object_private.rose_db_object_test'); 1631 $dbh->do('DROP TABLE rose_db_object_chkpass_test'); 1632 $dbh->do('CREATE SCHEMA rose_db_object_private'); 1633 } 1634 1635 our $PG_HAS_CHKPASS = pg_has_chkpass(); 1636 1637 $dbh->do(<<"EOF"); 1638CREATE TABLE rose_db_object_test 1639( 1640 id SERIAL NOT NULL PRIMARY KEY, 1641 k1 INT, 1642 k2 INT, 1643 k3 INT, 1644 @{[ $PG_HAS_CHKPASS ? 'passwd CHKPASS,' : '' ]} 1645 name VARCHAR(32) NOT NULL, 1646 code CHAR(6), 1647 flag BOOLEAN NOT NULL, 1648 flag2 BOOLEAN, 1649 status VARCHAR(32) DEFAULT 'active', 1650 bitz BIT(5) NOT NULL DEFAULT B'00101', 1651 decs DECIMAL(10,2), 1652 start DATE, 1653 save INT, 1654 nums INT[], 1655 dur INTERVAL(6) DEFAULT '2 months 5 days 3 seconds', 1656 epoch INT DEFAULT 943997400, 1657 hiepoch DECIMAL(16,6), 1658 bint1 BIGINT DEFAULT 9223372036854775800, 1659 bint2 BIGINT DEFAULT -9223372036854775800, 1660 bint3 BIGINT, 1661 bint4 BIGINT, 1662 tee_time TIME, 1663 tee_time0 TIME(0), 1664 tee_time5 TIME(5), 1665 tee_time9 TIME(9), 1666 last_modified TIMESTAMP, 1667 date_created TIMESTAMP, 1668 date_created_tz TIMESTAMP WITH TIME ZONE, 1669 timestamp_tz2 TIMESTAMP WITH TIME ZONE, 1670 1671 UNIQUE(k1, k2, k3) 1672) 1673EOF 1674 1675 $dbh->do(<<"EOF"); 1676CREATE TABLE rose_db_object_private.rose_db_object_test 1677( 1678 id SERIAL NOT NULL PRIMARY KEY, 1679 k1 INT, 1680 k2 INT, 1681 k3 INT, 1682 @{[ $PG_HAS_CHKPASS ? 'passwd CHKPASS,' : '' ]} 1683 name VARCHAR(32) NOT NULL, 1684 code CHAR(6), 1685 flag BOOLEAN NOT NULL, 1686 flag2 BOOLEAN, 1687 status VARCHAR(32) DEFAULT 'active', 1688 bitz BIT(5) NOT NULL DEFAULT B'00101', 1689 decs DECIMAL(10,2), 1690 start DATE, 1691 save INT, 1692 nums INT[], 1693 dur INTERVAL(6) DEFAULT '2 months 5 days 3 seconds', 1694 epoch INT DEFAULT 943997400, 1695 hiepoch DECIMAL(16,6), 1696 bint1 BIGINT DEFAULT 9223372036854775800, 1697 bint2 BIGINT DEFAULT -9223372036854775800, 1698 bint3 BIGINT, 1699 bint4 BIGINT, 1700 tee_time TIME, 1701 tee_time0 TIME(0), 1702 tee_time5 TIME(5), 1703 tee_time9 TIME(9), 1704 last_modified TIMESTAMP, 1705 date_created TIMESTAMP, 1706 date_created_tz TIMESTAMP WITH TIME ZONE, 1707 timestamp_tz2 TIMESTAMP WITH TIME ZONE, 1708 1709 UNIQUE(k1, k2, k3) 1710) 1711EOF 1712 1713 $dbh->disconnect; 1714 1715 # Create test subclass 1716 1717 package MyPgObject; 1718 1719 use Rose::DB::Object::Helpers qw(clone); 1720 1721 our @ISA = qw(Rose::DB::Object); 1722 1723 sub init_db { Rose::DB->new('pg') } 1724 1725 MyPgObject->meta->table('rose_db_object_test'); 1726 1727 MyPgObject->meta->columns 1728 ( 1729 name => { type => 'varchar', length => 32, overflow => 'truncate' }, 1730 code => { type => 'char', length => 6, overflow => 'truncate' }, 1731 id => { primary_key => 1, not_null => 1 }, 1732 k1 => { type => 'int' }, 1733 k2 => { type => 'int', lazy => 1 }, 1734 k3 => { type => 'int' }, 1735 ($PG_HAS_CHKPASS ? (passwd => { type => 'chkpass', alias => 'password' }) : ()), 1736 flag => { type => 'boolean', default => 1 }, 1737 flag2 => { type => 'boolean' }, 1738 status => { default => 'active', add_methods => [ qw(get set) ] }, 1739 start => { type => 'date', default => '12/24/1980', lazy => 1 }, 1740 save => { type => 'scalar' }, 1741 nums => { type => 'array' }, 1742 bitz => { type => 'bitfield', bits => 5, default => 101, alias => 'bits' }, 1743 decs => { type => 'decimal', precision => 10, scale => 2 }, 1744 dur => { type => 'interval', scale => 6, default => '2 months 5 days 3 seconds' }, 1745 epoch => { type => 'epoch', default => '11/30/1999 9:30pm' }, 1746 hiepoch => { type => 'epoch hires', default => '1144004926.123456' }, 1747 bint1 => { type => 'bigint', default => '9223372036854775800' }, 1748 bint2 => { type => 'bigint', default => '-9223372036854775800' }, 1749 bint3 => { type => 'bigint', with_init => 1, check_in => [ '9223372036854775000', 5 ] }, 1750 bint4 => { type => 'bigint' }, 1751 tee_time => { type => 'time' }, 1752 tee_time0 => { type => 'time', scale => 0 }, 1753 tee_time5 => { type => 'time', scale => 5, default => '12:34:56.123456789' }, 1754 tee_time9 => { type => 'time', scale => 9 }, 1755 #last_modified => { type => 'timestamp' }, 1756 date_created => { type => 'timestamp' }, 1757 date_created_tz => { type => 'timestamp with time zone' }, 1758 timestamp_tz2 => { type => 'timestamp with time zone', time_zone => 'Antarctica/Vostok' }, 1759 main::nonpersistent_column_definitions(), 1760 ); 1761 1762 MyPgObject->meta->add_unique_key('save'); 1763 1764 MyPgObject->meta->add_unique_key([ qw(k1 k2 k3) ]); 1765 1766 MyPgObject->meta->add_columns( 1767 Rose::DB::Object::Metadata::Column::Timestamp->new( 1768 name => 'last_modified')); 1769 1770 eval { MyPgObject->meta->initialize }; 1771 Test::More::ok($@, 'meta->initialize() reserved method'); 1772 1773 MyPgObject->meta->alias_column(save => 'save_col'); 1774 1775 eval { MyPgObject->meta->initialize }; 1776 Test::More::ok($@, 'meta->initialize() no override'); 1777 1778 MyPgObject->meta->initialize(preserve_existing => 1); 1779 1780 Test::More::is(MyPgObject->meta->column('id')->is_primary_key_member, 1, 'is_primary_key_member - pg'); 1781 Test::More::is(MyPgObject->meta->column('id')->primary_key_position, 1, 'primary_key_position 1 - pg'); 1782 Test::More::ok(!defined MyPgObject->meta->column('k1')->primary_key_position, 'primary_key_position 2 - pg'); 1783 MyPgObject->meta->column('k1')->primary_key_position(7); 1784 Test::More::ok(!defined MyPgObject->meta->column('k1')->primary_key_position, 'primary_key_position 3 - pg'); 1785 1786 sub init_bint3 { '9223372036854775000' } 1787 } 1788 1789 # 1790 # MySQL 1791 # 1792 1793 my $db_version; 1794 1795 eval 1796 { 1797 my $db = Rose::DB->new('mysql_admin'); 1798 $dbh = $db->retain_dbh() or die Rose::DB->error; 1799 $db_version = $db->database_version; 1800 }; 1801 1802 if(!$@ && $dbh) 1803 { 1804 our $HAVE_MYSQL = 1; 1805 1806 # Drop existing table and create schema, ignoring errors 1807 { 1808 local $dbh->{'RaiseError'} = 0; 1809 local $dbh->{'PrintError'} = 0; 1810 $dbh->do('DROP TABLE rose_db_object_test'); 1811 $dbh->do('DROP TABLE rose_db_object_test2'); 1812 } 1813 1814 # MySQL 5.0.3 or later has a completely stupid "native" BIT type 1815 my $bit_col1 = 1816 ($db_version >= 5_000_003) ? 1817 q(bitz BIT(5) NOT NULL DEFAULT B'00101') : 1818 q(bitz BIT(5) NOT NULL DEFAULT '00101'); 1819 1820 my $bit_col2 = 1821 ($db_version >= 5_000_003) ? 1822 q(bitz2 BIT(2) NOT NULL DEFAULT B'00') : 1823 q(bitz2 BIT(2) NOT NULL DEFAULT '0'); 1824 1825 my $set_col = 1826 ($db_version >= 5_000_000) ? 1827 q(items SET('a','b','c') NOT NULL DEFAULT 'a,c') : 1828 q(items VARCHAR(255) NOT NULL DEFAULT 'a,c'); 1829 1830 my $engine = ''; 1831 1832 if(our $INNODB = mysql_supports_innodb()) 1833 { 1834 $engine = 'ENGINE=InnoDB'; 1835 } 1836 1837 $dbh->do(<<"EOF"); 1838CREATE TABLE rose_db_object_test 1839( 1840 id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, 1841 k1 INT, 1842 k2 INT, 1843 k3 INT, 1844 name VARCHAR(32) NOT NULL, 1845 code CHAR(6), 1846 flag TINYINT(1) NOT NULL, 1847 flag2 TINYINT(1), 1848 status VARCHAR(32) DEFAULT 'active', 1849 $bit_col1, 1850 $bit_col2, 1851 $set_col, 1852 bitz3 BIT(4), 1853 decs FLOAT(10,2), 1854 nums VARCHAR(255), 1855 start DATE, 1856 save INT, 1857 enums ENUM('foo', 'bar', 'baz') DEFAULT 'foo', 1858 ndate DATE NOT NULL DEFAULT '0000-00-00', 1859 dur VARCHAR(255) DEFAULT '2 months 5 days 3 seconds', 1860 epoch INT DEFAULT 943997400, 1861 hiepoch DECIMAL(16,6), 1862 zepoch INT NOT NULL DEFAULT 0, 1863 tee_time VARCHAR(32), 1864 tee_time0 VARCHAR(32), 1865 tee_time5 VARCHAR(32) DEFAULT '12:34:56.123456789', 1866 tee_time9 VARCHAR(32), 1867 dt_default TIMESTAMP, 1868 last_modified TIMESTAMP, 1869 date_created TIMESTAMP, 1870 1871 UNIQUE(k1, k2, k3) 1872) 1873$engine 1874EOF 1875 1876 $dbh->do(<<"EOF"); 1877CREATE TABLE rose_db_object_test2 1878( 1879 k1 INT NOT NULL, 1880 k2 INT NOT NULL, 1881 name VARCHAR(32), 1882 1883 UNIQUE(k1, k2) 1884) 1885EOF 1886 1887 $dbh->disconnect; 1888 1889 # Create test subclass 1890 1891 package MyMySQLObject; 1892 1893 use Rose::DB::Object::Helpers qw(clone); 1894 1895 our @ISA = qw(Rose::DB::Object); 1896 1897 sub init_db { Rose::DB->new('mysql') } 1898 1899 MyMySQLObject->meta->allow_inline_column_values(1); 1900 1901 MyMySQLObject->meta->table('rose_db_object_test'); 1902 1903 MyMySQLObject->meta->columns 1904 ( 1905 name => { type => 'varchar', length => 32 }, 1906 code => { type => 'char', length => 6 }, 1907 id => { primary_key => 1, not_null => 1 }, 1908 k1 => { type => 'int' }, 1909 k2 => { type => 'int', lazy => 1 }, 1910 k3 => { type => 'int' }, 1911 flag => { type => 'boolean', default => 1 }, 1912 flag2 => { type => 'boolean' }, 1913 status => { default => 'active', methods => [ qw(get_set get set) ] }, 1914 start => { type => 'date', default => '12/24/1980', lazy => 1 }, 1915 ndate => { type => 'date', not_null => 1, default => '0000-00-00' }, 1916 save => { type => 'scalar' }, 1917 nums => { type => 'array' }, 1918 enums => { type => 'enum', values => [ qw(foo bar baz) ], default => 'foo' }, 1919 bitz => { type => 'bitfield', bits => 5, default => 101, alias => 'bits' }, 1920 bitz2 => { type => 'bits', bits => 2, default => '0' }, 1921 bitz3 => { type => 'bits', bits => 4 }, 1922 items => { type => 'set', check_in => [ qw(a b c) ], default => 'a,c' }, 1923 decs => { type => 'decimal', precision => 10, scale => 2 }, 1924 dur => { type => 'interval', scale => 6, default => '2 months 5 days 3 seconds' }, 1925 epoch => { type => 'epoch', default => '11/30/1999 9:30pm' }, 1926 hiepoch => { type => 'epoch hires', default => '1144004926.123456' }, 1927 zepoch => { type => 'epoch', default => 0, not_null => 1, time_zone => 'UTC' }, 1928 tee_time => { type => 'time' }, 1929 tee_time0 => { type => 'time', scale => 0 }, 1930 tee_time5 => { type => 'time', scale => 5, default => '12:34:56.123456789' }, 1931 tee_time9 => { type => 'time', scale => 9 }, 1932 dt_default => { type => 'timestamp', default => 'now()' }, 1933 last_modified => { type => 'timestamp' }, 1934 date_created => { type => 'timestamp' }, 1935 main::nonpersistent_column_definitions(), 1936 ); 1937 1938 eval { MyMySQLObject->meta->initialize }; 1939 Test::More::ok($@, 'meta->initialize() reserved method'); 1940 1941 MyMySQLObject->meta->alias_column(save => 'save_col'); 1942 1943 eval { MyMySQLObject->meta->initialize }; 1944 Test::More::ok($@, 'meta->initialize() no override'); 1945 1946 MyMySQLObject->meta->add_unique_key('save'); 1947 MyMySQLObject->meta->add_unique_key([ qw(k1 k2 k3) ]); 1948 1949 MyMySQLObject->meta->initialize(preserve_existing => 1); 1950 1951 Test::More::is(MyMySQLObject->meta->column('id')->is_primary_key_member, 1, 'is_primary_key_member - mysql'); 1952 Test::More::is(MyMySQLObject->meta->column('id')->primary_key_position, 1, 'primary_key_position 1 - mysql'); 1953 Test::More::ok(!defined MyMySQLObject->meta->column('k1')->primary_key_position, 'primary_key_position 2 - mysql'); 1954 MyMySQLObject->meta->column('k1')->primary_key_position(7); 1955 Test::More::ok(!defined MyMySQLObject->meta->column('k1')->primary_key_position, 'primary_key_position 3 - mysql'); 1956 1957 package MyMPKMySQLObject; 1958 1959 use Rose::DB::Object; 1960 1961 our @ISA = qw(Rose::DB::Object); 1962 1963 sub init_db { Rose::DB->new('mysql') } 1964 1965 MyMPKMySQLObject->meta->table('rose_db_object_test2'); 1966 1967 MyMPKMySQLObject->meta->columns 1968 ( 1969 k1 => { type => 'int', not_null => 1 }, 1970 k2 => { type => 'int', not_null => 1 }, 1971 name => { type => 'varchar', length => 32 }, 1972 ); 1973 1974 MyMPKMySQLObject->meta->primary_key_columns('k1', 'k2'); 1975 1976 my $i = 1; 1977 1978 MyMPKMySQLObject->meta->setup 1979 ( 1980 primary_key_generator => sub 1981 { 1982 my($meta, $db) = @_; 1983 1984 my $k1 = $i++; 1985 my $k2 = $i++; 1986 1987 return $k1, $k2; 1988 }, 1989 ); 1990 } 1991 1992 # 1993 # Informix 1994 # 1995 1996 eval 1997 { 1998 $dbh = Rose::DB->new('informix_admin')->retain_dbh() 1999 or die Rose::DB->error; 2000 }; 2001 2002 if(!$@ && $dbh) 2003 { 2004 our $HAVE_INFORMIX = 1; 2005 2006 # Drop existing table and create schema, ignoring errors 2007 { 2008 local $dbh->{'RaiseError'} = 0; 2009 local $dbh->{'PrintError'} = 0; 2010 $dbh->do('DROP TABLE rose_db_object_test'); 2011 } 2012 2013 $dbh->do(<<"EOF"); 2014CREATE TABLE rose_db_object_test 2015( 2016 id SERIAL NOT NULL PRIMARY KEY, 2017 k1 INT, 2018 k2 INT, 2019 k3 INT, 2020 name VARCHAR(32) NOT NULL, 2021 code CHAR(6), 2022 flag BOOLEAN NOT NULL, 2023 flag2 BOOLEAN, 2024 status VARCHAR(32) DEFAULT 'active', 2025 bitz VARCHAR(5) DEFAULT '00101' NOT NULL, 2026 decs DECIMAL(10,2), 2027 nums VARCHAR(255), 2028 start DATE, 2029 save INT, 2030 names SET(VARCHAR(64) NOT NULL), 2031 last_modified DATETIME YEAR TO FRACTION(5), 2032 date_created DATETIME YEAR TO FRACTION(5) 2033) 2034EOF 2035 2036 $dbh->disconnect; 2037 2038 # Create test subclass 2039 2040 package MyInformixObject; 2041 2042 use Rose::DB::Object::Helpers qw(clone); 2043 2044 our @ISA = qw(Rose::DB::Object); 2045 2046 sub init_db { Rose::DB->new('informix') } 2047 2048 MyInformixObject->meta->allow_inline_column_values(1); 2049 2050 MyInformixObject->meta->table('rose_db_object_test'); 2051 2052 MyInformixObject->meta->columns 2053 ( 2054 name => { type => 'varchar', length => 32, overflow => 'truncate' }, 2055 code => { type => 'char', length => 6, overflow => 'truncate' }, 2056 id => { type => 'serial', primary_key => 1, not_null => 1 }, 2057 k1 => { type => 'int' }, 2058 k2 => { type => 'int', lazy => 1 }, 2059 k3 => { type => 'int' }, 2060 flag => { type => 'boolean', default => 1 }, 2061 flag2 => { type => 'boolean' }, 2062 status => { default => 'active', add_methods => [ qw(get set) ] }, 2063 start => { type => 'date', default => '12/24/1980', lazy => 1 }, 2064 save => { type => 'scalar' }, 2065 nums => { type => 'array' }, 2066 bitz => { type => 'bitfield', bits => 5, default => 101, alias => 'bits' }, 2067 decs => { type => 'decimal', precision => 10, scale => 2 }, 2068 names => { type => 'set' }, 2069 last_modified => { type => 'timestamp' }, 2070 date_created => { type => 'datetime year to fraction(5)' }, 2071 main::nonpersistent_column_definitions(), 2072 ); 2073 2074 eval { MyInformixObject->meta->initialize }; 2075 Test::More::ok($@, 'meta->initialize() reserved method'); 2076 2077 MyInformixObject->meta->prepare_options({ix_CursorWithHold => 1}); 2078 2079 MyInformixObject->meta->alias_column(save => 'save_col'); 2080 2081 eval { MyInformixObject->meta->initialize }; 2082 Test::More::ok($@, 'meta->initialize() no override'); 2083 2084 MyInformixObject->meta->add_unique_key('save'); 2085 MyInformixObject->meta->add_unique_key([ qw(k1 k2 k3) ]); 2086 2087 MyInformixObject->meta->initialize(preserve_existing => 1); 2088 2089 Test::More::is(MyInformixObject->meta->column('id')->is_primary_key_member, 1, 'is_primary_key_member - informix'); 2090 Test::More::is(MyInformixObject->meta->column('id')->primary_key_position, 1, 'primary_key_position 1 - informix'); 2091 Test::More::ok(!defined MyInformixObject->meta->column('k1')->primary_key_position, 'primary_key_position 2 - informix'); 2092 MyInformixObject->meta->column('k1')->primary_key_position(7); 2093 Test::More::ok(!defined MyInformixObject->meta->column('k1')->primary_key_position, 'primary_key_position 3 - informix'); 2094 } 2095 2096 # 2097 # SQLite 2098 # 2099 2100 eval 2101 { 2102 $dbh = Rose::DB->new('sqlite_admin')->retain_dbh() 2103 or die Rose::DB->error; 2104 }; 2105 2106 if(!$@ && $dbh) 2107 { 2108 our $HAVE_SQLITE = 1; 2109 2110 # 2111 # Method name conflict tests 2112 # 2113 2114 local $@; 2115 2116 eval 2117 { 2118 package MyNameConflictB; 2119 2120 our @ISA = qw(Rose::DB::Object); 2121 2122 sub init_db { Rose::DB->new('sqlite') } 2123 2124 __PACKAGE__->meta->setup 2125 ( 2126 table => 'foob', 2127 columns => [ qw(id blee) ], 2128 ); 2129 2130 package MyNameConflictA; 2131 2132 our @ISA = qw(Rose::DB::Object); 2133 2134 sub init_db { Rose::DB->new('sqlite') } 2135 2136 __PACKAGE__->meta->setup 2137 ( 2138 table => 'fooa', 2139 columns => [ qw(bar baz) ], 2140 foreign_keys => 2141 [ 2142 new => 2143 { 2144 class => 'MyNameConflictB', 2145 key_columns => { baz => 'id' }, 2146 }, 2147 ], 2148 ); 2149 }; 2150 2151 like($@, qr/Rose::DB::Object defines a method with the same name/, 'method name conflict'); 2152 2153 # Drop existing table and create schema, ignoring errors 2154 { 2155 local $dbh->{'RaiseError'} = 0; 2156 local $dbh->{'PrintError'} = 0; 2157 $dbh->do('DROP TABLE rose_db_object_test'); 2158 $dbh->do('DROP TABLE rose_db_object_test2'); 2159 } 2160 2161 $dbh->do(<<"EOF"); 2162CREATE TABLE rose_db_object_test 2163( 2164 id INTEGER PRIMARY KEY AUTOINCREMENT, 2165 k1 INT, 2166 k2 INT, 2167 k3 INT, 2168 name VARCHAR(32) NOT NULL, 2169 code CHAR(6), 2170 flag BOOLEAN NOT NULL, 2171 flag2 BOOLEAN, 2172 status VARCHAR(32) DEFAULT 'active', 2173 bitz VARCHAR(5) DEFAULT '00101' NOT NULL, 2174 decs DECIMAL(10,2), 2175 start DATE, 2176 save INT, 2177 nums VARCHAR(255), 2178 data BLOB, 2179 last_modified TIMESTAMP, 2180 date_created TIMESTAMP, 2181 2182 UNIQUE(k1, k2, k3) 2183) 2184EOF 2185 2186 $dbh->do(<<"EOF"); 2187CREATE TABLE rose_db_object_test2 2188( 2189 k1 INT NOT NULL, 2190 k2 INT NOT NULL, 2191 name VARCHAR(32), 2192 2193 UNIQUE(k1, k2) 2194) 2195EOF 2196 2197 $dbh->disconnect; 2198 2199 # Create test subclass 2200 2201 package MySQLiteObject; 2202 2203 use Rose::DB::Object::Helpers qw(clone); 2204 2205 our @ISA = qw(Rose::DB::Object); 2206 2207 sub init_db { Rose::DB->new('sqlite') } 2208 2209 MySQLiteObject->meta->table('rose_db_object_test'); 2210 2211 MySQLiteObject->meta->columns 2212 ( 2213 name => { type => 'varchar', length => 32, overflow => 'truncate' }, 2214 code => { type => 'char', length => 6, overflow => 'truncate' }, 2215 id => { primary_key => 1, not_null => 1 }, 2216 k1 => { type => 'int' }, 2217 k2 => { type => 'int', lazy => 1 }, 2218 k3 => { type => 'int' }, 2219 flag => { type => 'boolean', default => 1 }, 2220 flag2 => { type => 'boolean' }, 2221 status => { default => 'active', add_methods => [ qw(get set) ] }, 2222 start => { type => 'date', default => '12/24/1980', lazy => 1 }, 2223 save => { type => 'scalar' }, 2224 nums => { type => 'array' }, 2225 bitz => { type => 'bitfield', bits => 5, default => 101, alias => 'bits' }, 2226 decs => { type => 'decimal', precision => 10, scale => 2 }, 2227 data => { type => 'blob' }, 2228 #last_modified => { type => 'timestamp' }, 2229 date_created => { type => 'scalar' }, 2230 main::nonpersistent_column_definitions(), 2231 ); 2232 2233 MySQLiteObject->meta->replace_column(date_created => { type => 'timestamp' }); 2234 2235 MySQLiteObject->meta->add_unique_key('save'); 2236 2237 MySQLiteObject->meta->add_unique_key([ qw(k1 k2 k3) ]); 2238 2239 MySQLiteObject->meta->add_columns( 2240 Rose::DB::Object::Metadata::Column::Timestamp->new( 2241 name => 'last_modified')); 2242 2243 MySQLiteObject->meta->column('id')->add_trigger(inflate => sub { defined $_[1] ? [ $_[1] ] : undef }); 2244 MySQLiteObject->meta->column('id')->add_trigger(deflate => sub { ref $_[1] ? (wantarray ? @{$_[1]} : $_[1]->[0]) : $_[1] }); 2245 2246 my $pre_inited = 0; 2247 MySQLiteObject->meta->pre_init_hook(sub { $pre_inited++ }); 2248 2249 eval { MySQLiteObject->meta->initialize }; 2250 Test::More::ok($@, 'meta->initialize() reserved method'); 2251 Test::More::is($pre_inited, 1, 'meta->pre_init_hook()'); 2252 2253 MySQLiteObject->meta->alias_column(save => 'save_col'); 2254 2255 eval { MySQLiteObject->meta->initialize }; 2256 Test::More::ok($@, 'meta->initialize() no override'); 2257 2258 MySQLiteObject->meta->initialize(preserve_existing => 1); 2259 2260 Test::More::is(MySQLiteObject->meta->column('id')->is_primary_key_member, 1, 'is_primary_key_member - sqlite'); 2261 Test::More::is(MySQLiteObject->meta->column('id')->primary_key_position, 1, 'primary_key_position 1 - sqlite'); 2262 Test::More::ok(!defined MySQLiteObject->meta->column('k1')->primary_key_position, 'primary_key_position 2 - sqlite'); 2263 MySQLiteObject->meta->column('k1')->primary_key_position(7); 2264 Test::More::ok(!defined MySQLiteObject->meta->column('k1')->primary_key_position, 'primary_key_position 3 - sqlite'); 2265 2266 package MyMPKSQLiteObject; 2267 2268 use Rose::DB::Object; 2269 2270 our @ISA = qw(Rose::DB::Object); 2271 2272 sub init_db { Rose::DB->new('sqlite') } 2273 2274 MyMPKSQLiteObject->meta->table('rose_db_object_test2'); 2275 2276 MyMPKSQLiteObject->meta->columns 2277 ( 2278 k1 => { type => 'int', not_null => 1 }, 2279 k2 => { type => 'int', not_null => 1 }, 2280 name => { type => 'varchar', length => 32 }, 2281 ); 2282 2283 MyMPKSQLiteObject->meta->primary_key_columns('k1', 'k2'); 2284 2285 MyMPKSQLiteObject->meta->initialize; 2286 2287 my $i = 1; 2288 2289 MyMPKSQLiteObject->meta->primary_key_generator(sub 2290 { 2291 my($meta, $db) = @_; 2292 2293 my $k1 = $i++; 2294 my $k2 = $i++; 2295 2296 return $k1, $k2; 2297 }); 2298 } 2299 2300 # 2301 # Oracle 2302 # 2303 2304 eval 2305 { 2306 $dbh = Rose::DB->new('oracle_admin')->retain_dbh() 2307 or die Rose::DB->error; 2308 }; 2309 2310 if(!$@ && $dbh) 2311 { 2312 our $HAVE_ORACLE = 1; 2313 2314 # Drop existing table and create schema, ignoring errors 2315 { 2316 local $dbh->{'RaiseError'} = 0; 2317 local $dbh->{'PrintError'} = 0; 2318 $dbh->do('DROP TABLE rose_db_object_test'); 2319 $dbh->do('DROP SEQUENCE rose_db_object_test_id_seq'); 2320 } 2321 2322 $dbh->do(<<"EOF"); 2323CREATE TABLE rose_db_object_test 2324( 2325 id INT NOT NULL PRIMARY KEY, 2326 k1 INT, 2327 k2 INT, 2328 k3 INT, 2329 name VARCHAR(32) NOT NULL, 2330 code CHAR(6), 2331 flag CHAR(1) NOT NULL CHECK(flag IN ('t', 'f')), 2332 flag2 CHAR(1) CHECK(flag2 IN ('t', 'f')), 2333 status VARCHAR(32) DEFAULT 'active', 2334 bitz VARCHAR(5) DEFAULT '00101' NOT NULL, 2335 decs NUMBER(10,2), 2336 nums VARCHAR(255), 2337 start_date DATE, 2338 save INT, 2339 claim# INT, 2340 key INT, 2341 last_modified TIMESTAMP, 2342 date_created TIMESTAMP, 2343 date_created_tz TIMESTAMP WITH TIME ZONE, 2344 timestamp_tz2 TIMESTAMP WITH TIME ZONE 2345) 2346EOF 2347 2348 $dbh->do(<<"EOF"); 2349CREATE SEQUENCE rose_db_object_test_id_seq 2350EOF 2351 2352 $dbh->do(<<"EOF"); 2353CREATE OR REPLACE TRIGGER rose_db_object_test_insert 2354BEFORE INSERT ON rose_db_object_test FOR EACH ROW 2355BEGIN 2356 SELECT NVL(:new.id, rose_db_object_test_id_seq.nextval) INTO :new.id FROM dual; 2357END; 2358EOF 2359 2360 $dbh->commit; 2361 $dbh->disconnect; 2362 2363 # Create test subclass 2364 2365 package MyOracleObject; 2366 2367 use Rose::DB::Object::Helpers qw(clone); 2368 2369 our @ISA = qw(Rose::DB::Object); 2370 2371 sub init_db { Rose::DB->new('oracle') } 2372 2373 MyOracleObject->meta->allow_inline_column_values(1); 2374 2375 MyOracleObject->meta->table('rose_db_object_test'); 2376 2377 MyOracleObject->meta->columns 2378 ( 2379 name => { type => 'varchar', length => 32, overflow => 'truncate' }, 2380 code => { type => 'char', length => 6, overflow => 'truncate' }, 2381 id => { type => 'serial', primary_key => 1, not_null => 1 }, 2382 k1 => { type => 'int' }, 2383 k2 => { type => 'int', lazy => 1 }, 2384 k3 => { type => 'int' }, 2385 key => { type => 'int' }, 2386 flag => { type => 'boolean', default => 1 }, 2387 flag2 => { type => 'boolean' }, 2388 status => { default => 'active', add_methods => [ qw(get set) ] }, 2389 start_date => { type => 'date', default => '12/24/1980', lazy => 1 }, 2390 save => { type => 'scalar' }, 2391 'claim#' => { type => 'int' }, 2392 nums => { type => 'array' }, 2393 bitz => { type => 'bitfield', bits => 5, default => 101, alias => 'bits' }, 2394 decs => { type => 'decimal', precision => 10, scale => 2 }, 2395 last_modified => { type => 'timestamp' }, 2396 date_created => { type => 'timestamp' }, 2397 date_created_tz => { type => 'timestamp with time zone' }, 2398 timestamp_tz2 => { type => 'timestamp with time zone', time_zone => 'Antarctica/Vostok' }, 2399 main::nonpersistent_column_definitions(), 2400 ); 2401 2402 eval { MyOracleObject->meta->initialize }; 2403 Test::More::ok($@, 'meta->initialize() reserved method'); 2404 2405 MyOracleObject->meta->prepare_options({ix_CursorWithHold => 1}); 2406 2407 MyOracleObject->meta->alias_column(save => 'save_col'); 2408 2409 eval { MyOracleObject->meta->initialize }; 2410 Test::More::ok($@, 'meta->initialize() no override'); 2411 2412 MyOracleObject->meta->add_unique_key('save'); 2413 MyOracleObject->meta->add_unique_key('key'); 2414 MyOracleObject->meta->add_unique_key([ qw(k1 k2 k3) ]); 2415 2416 MyOracleObject->meta->initialize(preserve_existing => 1); 2417 2418 Test::More::is(MyOracleObject->meta->column('id')->is_primary_key_member, 1, 'is_primary_key_member - oracle'); 2419 Test::More::is(MyOracleObject->meta->column('id')->primary_key_position, 1, 'primary_key_position 1 - oracle'); 2420 Test::More::ok(!defined MyOracleObject->meta->column('k1')->primary_key_position, 'primary_key_position 2 - oracle'); 2421 MyOracleObject->meta->column('k1')->primary_key_position(7); 2422 Test::More::ok(!defined MyOracleObject->meta->column('k1')->primary_key_position, 'primary_key_position 3 - oracle'); 2423 } 2424} 2425 2426END 2427{ 2428 # Delete test table 2429 2430 if($HAVE_PG) 2431 { 2432 # PostgreSQL 2433 my $dbh = Rose::DB->new('pg_admin')->retain_dbh() 2434 or die Rose::DB->error; 2435 2436 $dbh->do('DROP TABLE rose_db_object_test'); 2437 $dbh->do('DROP TABLE rose_db_object_private.rose_db_object_test'); 2438 $dbh->do('DROP SCHEMA rose_db_object_private CASCADE'); 2439 2440 $dbh->disconnect; 2441 } 2442 2443 if($HAVE_MYSQL) 2444 { 2445 my $dbh = Rose::DB->new('mysql_admin')->retain_dbh() 2446 or die Rose::DB->error; 2447 2448 $dbh->do('DROP TABLE rose_db_object_test'); 2449 $dbh->do('DROP TABLE rose_db_object_test2'); 2450 2451 $dbh->disconnect; 2452 } 2453 2454 if($HAVE_INFORMIX) 2455 { 2456 my $dbh = Rose::DB->new('informix_admin')->retain_dbh() 2457 or die Rose::DB->error; 2458 2459 $dbh->do('DROP TABLE rose_db_object_test'); 2460 2461 $dbh->disconnect; 2462 } 2463 2464 if($HAVE_SQLITE) 2465 { 2466 my $dbh = Rose::DB->new('sqlite_admin')->retain_dbh() 2467 or die Rose::DB->error; 2468 2469 $dbh->do('DROP TABLE rose_db_object_test'); 2470 $dbh->do('DROP TABLE rose_db_object_test2'); 2471 2472 $dbh->disconnect; 2473 } 2474 2475 if($HAVE_ORACLE) 2476 { 2477 my $dbh = Rose::DB->new('oracle_admin')->retain_dbh() 2478 or die Rose::DB->error; 2479 2480 $dbh->do('DROP TABLE rose_db_object_test'); 2481 $dbh->do('DROP SEQUENCE rose_db_object_test_id_seq'); 2482 2483 $dbh->disconnect; 2484 } 2485} 2486