X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=t%2F73oracle.t;h=bb34e5049abfb643ffdb8d0695be097fa7aaf4a1;hb=f121db2ead727832c55a6d4435722612648515c8;hp=3192acbac419c02e52b8c9b2c6c937fb1fa93139;hpb=df6e3f5c0c1a8250692b4f89e4c72c235d178bd2;p=dbsrgits%2FDBIx-Class.git diff --git a/t/73oracle.t b/t/73oracle.t index 3192acb..bb34e50 100644 --- a/t/73oracle.t +++ b/t/73oracle.t @@ -19,6 +19,10 @@ size => 100, is_nullable => 1, }, + 'autoinc_col' => { + data_type => 'integer', + is_auto_increment => 1, + }, ); __PACKAGE__->set_primary_key('artistid'); @@ -38,7 +42,7 @@ use DBIC::SqlMakerTest; my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_ORA_${_}" } qw/DSN USER PASS/}; # optional: -my ($dsn2, $user2, $pass2) = @ENV{map { "DBICTEST_ORA2_${_}" } qw/DSN USER PASS/}; +my ($dsn2, $user2, $pass2) = @ENV{map { "DBICTEST_ORA_EXTRAUSER_${_}" } qw/DSN USER PASS/}; plan skip_all => 'Set $ENV{DBICTEST_ORA_DSN}, _USER and _PASS to run this test. ' . 'Warning: This test drops and creates tables called \'artist\', \'cd\', \'track\' and \'sequence_test\''. @@ -75,42 +79,74 @@ $schema->class('Artist')->load_components('PK::Auto'); $schema->class('CD')->load_components('PK::Auto::Oracle'); $schema->class('Track')->load_components('PK::Auto::Oracle'); -# test primary key handling + +# test primary key handling with multiple triggers my $new = $schema->resultset('Artist')->create({ name => 'foo' }); is($new->artistid, 1, "Oracle Auto-PK worked"); -my $cd = $schema->resultset('CD')->create({ artist => 1, title => 'EP C', year => '2003' }); -is($cd->cdid, 1, "Oracle Auto-PK worked - using scalar ref as table name"); +like ($new->result_source->column_info('artistid')->{sequence}, qr/\.artist_pk_seq$/, 'Correct PK sequence selected'); # test again with fully-qualified table name -$new = $schema->resultset('ArtistFQN')->create( { name => 'bar' } ); +my $artistfqn_rs = $schema->resultset('ArtistFQN'); +my $artist_rsrc = $artistfqn_rs->result_source; + +delete $artist_rsrc->column_info('artistid')->{sequence}; + +$new = $artistfqn_rs->create( { name => 'bar' } ); is( $new->artistid, 2, "Oracle Auto-PK worked with fully-qualified tablename" ); +delete $artist_rsrc->column_info('artistid')->{sequence}; + +$new = $artistfqn_rs->create( { name => 'bar', autoinc_col => 1000 } ); +is( $new->artistid, 3, "Oracle Auto-PK worked with fully-qualified tablename" ); +is( $new->autoinc_col, 1000, "Oracle Auto-Inc overruled with fully-qualified tablename"); + +like ($artist_rsrc->column_info('artistid')->{sequence}, qr/\.artist_pk_seq$/, 'Still correct PK sequence'); + +# test LIMIT support +for (1..6) { + $schema->resultset('Artist')->create({ name => 'Artist ' . $_ }); +} +my $it = $schema->resultset('Artist')->search( { name => { -like => 'Artist %' }}, + { rows => 3, + offset => 4, + order_by => 'artistid' } +); +is( $it->count, 2, "LIMIT count past end of RS ok" ); +is( $it->next->name, "Artist 5", "iterator->next ok" ); +is( $it->next->name, "Artist 6", "iterator->next ok" ); +is( $it->next, undef, "next past end of resultset ok" ); + +my $cd = $schema->resultset('CD')->create({ artist => 1, title => 'EP C', year => '2003' }); +is($cd->cdid, 1, "Oracle Auto-PK worked - using scalar ref as table name"); + # test rel names over the 30 char limit -my $query = $schema->resultset('Artist')->search({ - artistid => 1 -}, { - prefetch => 'cds_very_very_very_long_relationship_name' -}); - -lives_and { - is $query->first->cds_very_very_very_long_relationship_name->first->cdid, 1 -} 'query with rel name over 30 chars survived and worked'; - -# rel name over 30 char limit with user condition -# This requires walking the SQLA data structure. { - local $TODO = 'user condition on rel longer than 30 chars'; - - $query = $schema->resultset('Artist')->search({ - 'cds_very_very_very_long_relationship_name.title' => 'EP C' + my $query = $schema->resultset('Artist')->search({ + artistid => 1 }, { prefetch => 'cds_very_very_very_long_relationship_name' }); lives_and { is $query->first->cds_very_very_very_long_relationship_name->first->cdid, 1 - } 'query with rel name over 30 chars and user condition survived and worked'; + } 'query with rel name over 30 chars survived and worked'; + + # rel name over 30 char limit with user condition + # This requires walking the SQLA data structure. + { + local $TODO = 'user condition on rel longer than 30 chars'; + + $query = $schema->resultset('Artist')->search({ + 'cds_very_very_very_long_relationship_name.title' => 'EP C' + }, { + prefetch => 'cds_very_very_very_long_relationship_name' + }); + + lives_and { + is $query->first->cds_very_very_very_long_relationship_name->first->cdid, 1 + } 'query with rel name over 30 chars and user condition survived and worked'; + } } # test join with row count ambiguity @@ -155,21 +191,6 @@ $tcount = $schema->resultset('Track')->search( ); is($tcount->count, 2, 'multiple column COUNT DISTINCT using column syntax ok'); -# test LIMIT support -for (1..6) { - $schema->resultset('Artist')->create({ name => 'Artist ' . $_ }); -} -my $it = $schema->resultset('Artist')->search( {}, - { rows => 3, - offset => 3, - order_by => 'artistid' } -); -is( $it->count, 3, "LIMIT count ok" ); -is( $it->next->name, "Artist 2", "iterator->next ok" ); -$it->next; -$it->next; -is( $it->next, undef, "next past end of resultset ok" ); - { my $rs = $schema->resultset('Track')->search( undef, { columns=>[qw/trackid position/], group_by=> [ qw/trackid position/ ] , rows => 2, offset=>1 }); my @results = $rs->all; @@ -238,6 +259,10 @@ SKIP: { skip 'buggy BLOB support in DBD::Oracle 1.23', 7; } + # disable BLOB mega-output + my $orig_debug = $schema->storage->debug; + $schema->storage->debug (0); + foreach my $type (qw( blob clob )) { foreach my $size (qw( small large )) { $id++; @@ -248,6 +273,8 @@ SKIP: { ok($rs->find($id)->$type eq $binstr{$size}, "verified inserted $size $type" ); } } + + $schema->storage->debug ($orig_debug); } @@ -511,22 +538,20 @@ if ( $schema->storage->isa('DBIx::Class::Storage::DBI::Oracle::Generic') ) { is_same_sql_bind ( $rs->as_query, - '( + '( SELECT artistid, name, rank, charfield, parentid FROM ( - SELECT artistid, name, rank, charfield, parentid, ROWNUM rownum__index FROM ( - SELECT - me.artistid, - me.name, - me.rank, - me.charfield, - me.parentid - FROM artist me - START WITH name = ? - CONNECT BY parentid = PRIOR artistid - ORDER BY name ASC - ) me + SELECT + me.artistid, + me.name, + me.rank, + me.charfield, + me.parentid + FROM artist me + START WITH name = ? + CONNECT BY parentid = PRIOR artistid + ORDER BY name ASC ) me - WHERE rownum__index BETWEEN 1 AND 2 + WHERE ROWNUM <= 2 )', [ [ name => 'root' ] ], ); @@ -545,19 +570,18 @@ if ( $schema->storage->isa('DBIx::Class::Storage::DBI::Oracle::Generic') ) { # is_same_sql_bind ( $rs->count_rs->as_query, - '( - SELECT COUNT( * ) FROM ( - SELECT artistid FROM ( - SELECT artistid, ROWNUM rownum__index FROM ( - SELECT - me.artistid - FROM artist me - START WITH name = ? - CONNECT BY parentid = PRIOR artistid - ) me - ) me - WHERE rownum__index BETWEEN 1 AND 2 - ) me + '( + SELECT COUNT( * ) FROM ( + SELECT artistid + FROM ( + SELECT + me.artistid + FROM artist me + START WITH name = ? + CONNECT BY parentid = PRIOR artistid + ) me + WHERE ROWNUM <= 2 + ) me )', [ [ name => 'root' ] ], ); @@ -657,24 +681,55 @@ if ( $schema->storage->isa('DBIx::Class::Storage::DBI::Oracle::Generic') ) { my $schema2; # test sequence detection from a different schema -if ($dsn2 && $user2) { +SKIP: { + skip ((join '', +'Set DBICTEST_ORA_EXTRAUSER_DSN, _USER and _PASS to a *DIFFERENT* Oracle user', +' to run the cross-schema autoincrement test.'), + 1) unless $dsn2 && $user2 && $user2 ne $user; + $schema2 = DBICTest::Schema->connect($dsn2, $user2, $pass2); - my $dbh = $schema->storage->dbh; - my $dbh2 = $schema2->storage->dbh; + my $schema1_dbh = $schema->storage->dbh; - $dbh->do("GRANT INSERT ON artist TO $user2"); - $dbh->do("GRANT SELECT ON artist_seq TO $user2"); + $schema1_dbh->do("GRANT INSERT ON artist TO $user2"); + $schema1_dbh->do("GRANT SELECT ON artist_pk_seq TO $user2"); - my $rs = $schema2->resultset('Artist'); + my $rs = $schema2->resultset('ArtistFQN'); - # qualify table with schema - local $rs->result_source->{name} = "${user}.artist"; + # first test with unquoted (default) sequence name in trigger body lives_and { - my $row = $rs->create({ name => 'Different Schema' }); + my $row = $rs->create({ name => 'From Different Schema' }); ok $row->artistid; - } 'detected autoinc sequence across schemas'; + } 'used autoinc sequence across schemas'; + + # now quote the sequence name + $schema1_dbh->do(qq{ + CREATE OR REPLACE TRIGGER artist_insert_trg_pk + BEFORE INSERT ON artist + FOR EACH ROW + BEGIN + IF :new.artistid IS NULL THEN + SELECT "ARTIST_PK_SEQ".nextval + INTO :new.artistid + FROM DUAL; + END IF; + END; + }); + + # sequence is cached in the rsrc + delete $rs->result_source->column_info('artistid')->{sequence}; + + lives_and { + my $row = $rs->create({ name => 'From Different Schema With Quoted Sequence' }); + ok $row->artistid; + } 'used quoted autoinc sequence across schemas'; + + my $schema_name = uc $user; + + is $rs->result_source->column_info('artistid')->{sequence}, + qq[${schema_name}."ARTIST_PK_SEQ"], + 'quoted sequence name correctly extracted'; } done_testing; @@ -683,7 +738,8 @@ sub do_creates { my $dbh = shift; eval { - $dbh->do("DROP SEQUENCE artist_seq"); + $dbh->do("DROP SEQUENCE artist_autoinc_seq"); + $dbh->do("DROP SEQUENCE artist_pk_seq"); $dbh->do("DROP SEQUENCE cd_seq"); $dbh->do("DROP SEQUENCE track_seq"); $dbh->do("DROP SEQUENCE pkid1_seq"); @@ -694,14 +750,15 @@ sub do_creates { $dbh->do("DROP TABLE track"); $dbh->do("DROP TABLE cd"); }; - $dbh->do("CREATE SEQUENCE artist_seq START WITH 1 MAXVALUE 999999 MINVALUE 0"); + $dbh->do("CREATE SEQUENCE artist_autoinc_seq START WITH 1 MAXVALUE 999999 MINVALUE 0"); + $dbh->do("CREATE SEQUENCE artist_pk_seq START WITH 1 MAXVALUE 999999 MINVALUE 0"); $dbh->do("CREATE SEQUENCE cd_seq START WITH 1 MAXVALUE 999999 MINVALUE 0"); $dbh->do("CREATE SEQUENCE track_seq START WITH 1 MAXVALUE 999999 MINVALUE 0"); $dbh->do("CREATE SEQUENCE pkid1_seq START WITH 1 MAXVALUE 999999 MINVALUE 0"); $dbh->do("CREATE SEQUENCE pkid2_seq START WITH 10 MAXVALUE 999999 MINVALUE 0"); $dbh->do("CREATE SEQUENCE nonpkid_seq START WITH 20 MAXVALUE 999999 MINVALUE 0"); - $dbh->do("CREATE TABLE artist (artistid NUMBER(12), parentid NUMBER(12), name VARCHAR(255), rank NUMBER(38), charfield VARCHAR2(10))"); + $dbh->do("CREATE TABLE artist (artistid NUMBER(12), parentid NUMBER(12), name VARCHAR(255), autoinc_col NUMBER(12), rank NUMBER(38), charfield VARCHAR2(10))"); $dbh->do("ALTER TABLE artist ADD (CONSTRAINT artist_pk PRIMARY KEY (artistid))"); $dbh->do("CREATE TABLE sequence_test (pkid1 NUMBER(12), pkid2 NUMBER(12), nonpkid NUMBER(12), name VARCHAR(255))"); @@ -714,12 +771,24 @@ sub do_creates { $dbh->do("ALTER TABLE track ADD (CONSTRAINT track_pk PRIMARY KEY (trackid))"); $dbh->do(qq{ - CREATE OR REPLACE TRIGGER artist_insert_trg + CREATE OR REPLACE TRIGGER artist_insert_trg_auto + BEFORE INSERT ON artist + FOR EACH ROW + BEGIN + IF :new.autoinc_col IS NULL THEN + SELECT artist_autoinc_seq.nextval + INTO :new.autoinc_col + FROM DUAL; + END IF; + END; + }); + $dbh->do(qq{ + CREATE OR REPLACE TRIGGER artist_insert_trg_pk BEFORE INSERT ON artist FOR EACH ROW BEGIN IF :new.artistid IS NULL THEN - SELECT artist_seq.nextval + SELECT artist_pk_seq.nextval INTO :new.artistid FROM DUAL; END IF; @@ -767,7 +836,8 @@ sub do_creates { END { for my $dbh (map $_->storage->dbh, grep $_, ($schema, $schema2)) { eval { - $dbh->do("DROP SEQUENCE artist_seq"); + $dbh->do("DROP SEQUENCE artist_autoinc_seq"); + $dbh->do("DROP SEQUENCE artist_pk_seq"); $dbh->do("DROP SEQUENCE cd_seq"); $dbh->do("DROP SEQUENCE track_seq"); $dbh->do("DROP SEQUENCE pkid1_seq"); @@ -779,7 +849,5 @@ END { $dbh->do("DROP TABLE cd"); $dbh->do("DROP TABLE bindtype_test"); }; - - eval { $dbh->do('DROP SYNONYM artist') }; } }