1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
#!perl
## ----------------------------------------------------------------------------
## 31lob_extended.t
## By John Scoles, The Pythian Group
## ----------------------------------------------------------------------------
## This run through some bugs that have been found in earlier versions of DBD::Oracle
## Checks to ensure that these bugs no longer come up
## Basically this is testing the use of LOBs when returned via stored procedures with bind_param_inout
## ----------------------------------------------------------------------------
use strict;
use warnings;
use lib 't/lib';
use DBDOracleTestLib qw/ oracle_test_dsn drop_table create_table db_handle /;
use Test::More;
use DBI;
use Config;
use DBD::Oracle qw(:ora_types);
$| = 1;
my $dbh = db_handle( { PrintError => 0 } );
if ($dbh) {
plan tests => 30;
$dbh->{LongReadLen} = 7000;
}
else {
plan skip_all => 'Unable to connect to Oracle';
diag('Test reported bugs');
}
my ( $table, $data0, $data1 ) = setup_test($dbh);
my $PLSQL = <<"PLSQL";
BEGIN
OPEN ? FOR SELECT x FROM $table;
END;
PLSQL
$dbh->{RaiseError} = 1;
#
# bug in DBD::Oracle 1.21 where if ora_auto_lobs is not set and we attempt to
# fetch from a table containing lobs which has more than one row
# we get a segfault. This was due to prefetching more than one row.
#
{
my $testname = 'ora_auto_lobs prefetch';
my ( $sth1, $ev );
eval { $sth1 = $dbh->prepare( $PLSQL, { ora_auto_lob => 0 } ); };
ok( !$@, "$testname - prepare call proc" );
my $sth2;
ok( $sth1->bind_param_inout( 1, \$sth2, 500, { ora_type => ORA_RSET } ),
"$testname - bind out cursor" );
ok( $sth1->execute, "$testname - execute to get out cursor" );
my ($lobl);
($lobl) = $sth2->fetchrow;
test_lob( $dbh, $lobl, $testname, 6000, $data0 );
($lobl) = $sth2->fetchrow;
test_lob( $dbh, $lobl, $testname, 6000, $data1 );
ok( $sth2->finish, "$testname - finished returned sth" );
ok( $sth1->finish, "$testname - finished sth" );
}
#
# prior to DBD::Oracle 1.22 if ora_auto_lob was set on a statement which
# was used to return a cursor on a result-set containing lobs, the lobs
# were not automatically fetched.
#
{
my $testname = 'ora_auto_lobs not fetching';
my ( $sth1, $ev, $lob );
# ora_auto_lobs is supposed to default to set
eval { $sth1 = $dbh->prepare($PLSQL); };
ok( !$@, "$testname prepare call proc" );
my $sth2;
ok( $sth1->bind_param_inout( 1, \$sth2, 500, { ora_type => ORA_RSET } ),
"$testname - bind out cursor" );
ok( $sth1->execute, "$testname - execute to get out cursor" );
($lob) = $sth2->fetchrow;
ok( $lob, "$testname - fetch returns something" );
isnt( ref $lob, 'OCILobLocatorPtr', "$testname - not a lob locator" );
is( $lob, $data0, "$testname, first lob matches" );
($lob) = $sth2->fetchrow;
ok( $lob, "$testname - fetch returns something" );
isnt( ref $lob, 'OCILobLocatorPtr', "$testname - not a lob locator" );
is( $lob, $data1, "$testname, second lob matches" );
ok( $sth2->finish, "$testname - finished returned sth" );
ok( $sth1->finish, "$testname - finished sth" );
}
sub test_lob {
my ( $h, $lobl, $testname, $size, $data ) = @_;
ok( $lobl, "$testname - lob locator retrieved" );
is( ref($lobl), 'OCILobLocatorPtr', "$testname - is a lob locator" );
SKIP: {
skip 'did not receive a lob locator', 4
unless ref($lobl) eq 'OCILobLocatorPtr';
my ( $lob_length, $lob, $ev );
eval { $lob_length = $h->ora_lob_length($lobl); };
$ev = $@;
diag($ev) if $ev;
ok( !$ev, "$testname - first lob length $lob_length" );
is( $lob_length, $size, "$testname - correct lob length" );
eval { $lob = $h->ora_lob_read( $lobl, 1, $lob_length ); };
$ev = $@;
diag($ev) if ($ev);
ok( !$ev, "$testname - read lob" );
is( $lob, $data, "$testname - lob returned matches lob inserted" );
}
}
sub setup_test {
my ($h) = @_;
my ( $table, $sth, $ev );
eval { $table = create_table( $h, { cols => [ [ 'x', 'clob' ] ] }, 1 ) };
BAIL_OUT("test table not created- $@") if $@;
ok( !$ev, 'created test table' );
eval { $sth = $h->prepare(qq/insert into $table (idx, x) values(?,?)/); };
BAIL_OUT("Failed to prepare insert into $table - $@") if $@;
my $data0 = 'x' x 6000;
my $data1 = 'y' x 6000;
eval {
$sth->execute( 1, $data0 );
$sth->execute( 2, $data1 );
};
BAIL_OUT("Failed to insert test data into $table - $@") if $@;
ok( !$ev, 'created test data' );
return ( $table, $data0, $data1 );
}
END {
return unless $dbh;
local $dbh->{PrintError} = 0;
local $dbh->{RaiseError} = 1;
eval { drop_table($dbh); };
if ($@) {
diag("table $table possibly not dropped - check - $@\n")
if $dbh->err ne '942';
}
}
|