#!/usr/local/bin/perl -w
die
"Use 'perl -Mblib test.pl' or 'make test' to run test.pl\n"
unless
"@INC"
=~ /\bblib\b/;
$| = 1;
my
$os
=
$Config
{osname};
GetOptions(
'm!'
=> \
my
$opt_m
,
'n=i'
=> \
my
$opt_n
,
'c=i'
=> \
my
$opt_c
,
'f=i'
=> \
my
$opt_f
,
'p!'
=> \
my
$opt_p
,
) or
die
;
$opt_n
||= 10;
exit
0
if
$ENV
{ORACLE_DSN};
$dbname
=
$ARGV
[0] ||
''
;
$dbuser
=
$ENV
{ORACLE_USERID} ||
'scott/tiger'
;
exit
test_extfetch_perf(
$opt_f
)
if
$opt_f
;
exit
test_leak(10 *
$opt_n
)
if
$opt_m
;
&ora_version
;
my
@data_sources
= DBI->data_sources(
'Oracle'
);
print
"Data sources:\n\t"
,
join
(
"\n\t"
,
@data_sources
),
"\n"
;
print
"Connecting\n"
,
" to '$dbname' (from command line, else uses ORACLE_SID or TWO_TASK - recommended)\n"
;
print
" as '$dbuser' (via ORACLE_USERID env var or default - recommend name/passwd\@dbname)\n"
;
printf
(
"(ORACLE_SID='%s', TWO_TASK='%s')\n"
,
$ENV
{ORACLE_SID}||
''
,
$ENV
{TWO_TASK}||
''
);
printf
(
"(LOCAL='%s', REMOTE='%s')\n"
,
$ENV
{LOCAL}||
''
,
$ENV
{REMOTE}||
''
)
if
$os
eq
'MSWin32'
;
{
local
(
$l
) =
&ora_login
(
$dbname
,
$dbuser
,
''
);
unless
(
$l
) {
$ora_errno
= 0
unless
defined
$ora_errno
;
$ora_errstr
=
''
unless
defined
$ora_errstr
;
warn
"ora_login: $ora_errno: $ora_errstr\n"
;
warn
"\nHave you set the environment variable ORACLE_USERID ?\n"
if
(
$ora_errno
== 1017);
warn
"\nHave you included your password in ORACLE_USERID ? (e.g., 'user/passwd')\n"
if
(
$ora_errno
== 1017 and
$dbuser
!~ m:/:);
warn
"\nHave you set the environment variable ORACLE_SID or TWO_TASK?\n"
if
(
$ora_errno
== 2700);
warn
"\nORACLE_SID or TWO_TASK possibly not right, or server not running.\n"
if
(
$ora_errno
== 1034);
warn
"\nTWO_TASK possibly not set correctly right.\n"
if
(
$ora_errno
== 12545);
warn
"\n"
;
warn
"Generally set TWO_TASK or ORACLE_SID but not both at the same time.\n"
;
warn
"Try to connect to the database using an oracle tool like sqlplus\n"
;
warn
"only if that works should you suspect problems with DBD::Oracle.\n"
;
warn
"Try leaving dbname value empty and set dbuser to name/passwd\@dbname.\n"
;
die
"\nTest aborted.\n"
;
}
if
(
$os
ne
'MSWin32'
and
$os
ne
'VMS'
) {
my
$backtick
= `
sleep
1; echo Backticks OK`;
unless
(
$backtick
) {
print
"Warning: Oracle's SIGCHLD signal handler breaks perl "
,
"`backticks` commands: $!\n(d_sigaction=$Config{d_sigaction})\n"
;
}
}
&ora_logoff
(
$l
) ||
warn
"ora_logoff($l): $ora_errno: $ora_errstr\n"
;
}
&test_intfetch_perf
()
if
$opt_p
;
&test1
();
print
"\nRepetitive connect/open/close/disconnect:\n"
;
my
$connect_loop_start
= DBI::dbi_time();
foreach
(1..
$opt_n
) {
print
"$_ "
;
&test2
(); }
my
$dur
= DBI::dbi_time() -
$connect_loop_start
;
printf
"(~%.3f seconds each)\n"
,
$dur
/
$opt_n
;
print
"test.pl complete.\n\n"
;
exit
0;
sub
test1 {
local
(
$lda
) =
&ora_login
(
$dbname
,
$dbuser
,
''
)
||
die
"ora_login: $ora_errno: $ora_errstr\n"
;
&ora_commit
(
$lda
) ||
warn
"ora_commit($lda): $ora_errno: $ora_errstr\n"
;
&ora_rollback
(
$lda
) ||
warn
"ora_rollback($lda): $ora_errno: $ora_errstr\n"
;
&ora_autocommit
(
$lda
, 1);
&ora_autocommit
(
$lda
, 0);
&ora_do
(
$lda
,
"set transaction read only "
)
||
warn
"ora_do: $ora_errno: $ora_errstr"
;
{
local
(
$csr
) =
&ora_open
(
$lda
,
"
select
to_number(
'7.2'
,
'9D9'
,
'NLS_NUMERIC_CHARACTERS ='
'.,'
''
) num_t,
SYSDATE date_t,
USER char_t,
ROWID rowid_t,
HEXTORAW(
'7D'
) raw_t,
NULL null_t
from dual
") || die "
ora_open:
$ora_errno
:
$ora_errstr
\n";
$csr
->{RaiseError} = 1;
print
"Fields: "
,
scalar
(
&ora_fetch
(
$csr
)),
"\n"
;
die
"ora_fetch in scalar context error"
unless
&ora_fetch
(
$csr
)==6;
print
"Names: \t"
,
join
(
"\t"
,
&ora_titles
(
$csr
)),
"\n"
;
print
"Lengths: \t"
,DBI::neat_list([
&ora_lengths
(
$csr
)],0,
"\t"
),
"\n"
;
print
"OraTypes: \t"
,DBI::neat_list([
&ora_types
(
$csr
)], 0,
"\t"
),
"\n"
;
print
"SQLTypes: \t"
,DBI::neat_list(
$csr
->{TYPE}, 0,
"\t"
),
"\n"
;
print
"Scale: \t"
,DBI::neat_list(
$csr
->{SCALE}, 0,
"\t"
),
"\n"
;
print
"Precision: \t"
,DBI::neat_list(
$csr
->{PRECISION}, 0,
"\t"
),
"\n"
;
print
"Nullable: \t"
,DBI::neat_list(
$csr
->{NULLABLE}, 0,
"\t"
),
"\n"
;
print
"Est row width:\t$csr->{ora_est_row_width}\n"
;
print
"Prefetch cache: $csr->{RowsInCache}\n"
if
$csr
->{RowsInCache};
print
"Data rows:\n"
;
while
(
@fields
=
$csr
->fetchrow_array) {
die
"ora_fetch returned "
.
@fields
.
" fields instead of 6!"
if
@fields
!= 6;
die
"Perl list/scalar context error"
if
@fields
==1;
print
" fetch: "
, DBI::neat_list(\
@fields
),
"\n"
;
}
&ora_close
(
$csr
) ||
warn
"ora_close($csr): $ora_errno: $ora_errstr\n"
;
}
&ora_logoff
(
$lda
) ||
warn
"ora_logoff($lda): $ora_errno: $ora_errstr\n"
;
}
sub
test2 {
my
$execute_sth
=
shift
;
my
$dbh
= DBI->
connect
(
"dbi:Oracle:$dbname"
,
$dbuser
,
''
, {
RaiseError
=>1 });
if
(
$execute_sth
) {
my
$sth
=
$dbh
->prepare(
"select 42,'foo',sysdate from dual where ? >= 1"
);
while
(
$execute_sth
-- > 0) {
$sth
->execute(1);
my
@row
=
$sth
->fetchrow_array;
$sth
->finish;
}
}
$dbh
->disconnect;
}
sub
test_leak {
local
(
$count
) =
@_
;
local
(
$ps
) = (-d
'/proc'
) ?
"ps -lp "
:
"ps -l"
;
local
(
$i
) = 0;
my
$execute_sth
= 100;
print
"\nMemory leak test: (execute $execute_sth):\n"
;
while
(++
$i
<=
$count
) {
&test2
(
$execute_sth
);
system
(
"echo $i; $ps$$"
)
if
((
$i
% 10) == 1);
}
system
(
"echo $i; $ps$$"
);
print
"Done.\n\n"
;
}
sub
count_fetch {
local
(
$csr
) =
@_
;
local
(
$rows
) = 0;
while
((
@row
) =
$csr
->fetchrow_array) {
++
$rows
;
}
die
"count_fetch $ora_errstr"
if
$ora_errno
;
return
$rows
;
}
sub
test_intfetch_perf {
print
"\nTesting internal row fetch overhead.\n"
;
local
(
$lda
) =
&ora_login
(
$dbname
,
$dbuser
,
''
)
||
die
"ora_login: $ora_errno: $ora_errstr\n"
;
DBI->trace(0);
$lda
->trace(0);
local
(
$csr
) =
&ora_open
(
$lda
,
"select 0,1,2,3,4,5,6,7,8,9 from dual"
);
local
(
$max
) = 50000;
$csr
->{ora_fetchtest} =
$max
;
$t0
= new Benchmark;
1
while
$csr
->fetchrow_arrayref;
$td
= Benchmark::timediff((new Benchmark),
$t0
);
$csr
->{ora_fetchtest} = 0;
printf
(
"$max fetches: "
.Benchmark::timestr(
$td
).
"\n"
);
printf
(
"%d per clock second, %d per cpu second\n\n"
,
$max
/(
$td
->real ?
$td
->real : 1),
$max
/(
$td
->cpu_a ?
$td
->cpu_a : 1));
}
sub
test_extfetch_perf {
my
$max
=
shift
;
print
"\nTesting external row fetch overhead.\n"
;
my
$rows
= 0;
my
$dbh
= DBI->
connect
(
"dbi:Oracle:$dbname"
,
$dbuser
,
''
, {
RaiseError
=> 1 });
$dbh
->{RowCacheSize} = $::opt_c
if
defined
$::opt_c;
my
$fields
= (0) ?
"*"
:
"object_name, status, object_type"
;
my
$sth
=
$dbh
->prepare(
q{
select all * from all_objects o1
union all select all * from all_objects o1
union all select all * from all_objects o1
union all select all * from all_objects o1
union all select all * from all_objects o1
union all select all * from all_objects o1
union all select all * from all_objects o1
union all select all * from all_objects o1
union all select all * from all_objects o1
--, all_objects o2
--where o1.object_id <= 400 and o2.object_id <= 400
}
, {
ora_check_sql
=> 1 });
$t0
= new Benchmark;
$sth
->execute;
$sth
->trace(0);
$sth
->fetchrow_arrayref;
$td
= Benchmark::timediff((new Benchmark),
$t0
);
printf
(
"Execute: "
.Benchmark::timestr(
$td
).
"\n"
);
print
"Fetching data with RowCacheSize $dbh->{RowCacheSize}...\n"
;
$t1
= new Benchmark;
1
while
$sth
->fetchrow_arrayref && ++
$rows
<
$max
;
$td
= Benchmark::timediff((new Benchmark),
$t1
);
printf
(
"$rows fetches: "
.Benchmark::timestr(
$td
).
"\n"
);
printf
(
"%d per clock second, %d per cpu second\n"
,
$rows
/(
$td
->real ?
$td
->real : 1),
$rows
/(
$td
->cpu_a ?
$td
->cpu_a : 1));
my
$ps
= (-d
'/proc'
) ?
"ps -lp "
:
"ps -l"
;
system
(
"echo Process memory size; $ps$$"
);
print
"\n"
;
$sth
->finish;
$dbh
->disconnect;
exit
1;
}
sub
test_bind_csr {
local
(
$lda
) =
@_
;
$lda
->{RaiseError} =1;
$lda
->trace(2);
my
$out_csr
=
$lda
->prepare(
q{select 42 from dual}
);
$csr
=
$lda
->prepare(
q{
begin
OPEN :csr_var FOR select * from all_tables;
end;
}
);
$csr
->bind_param_inout(
':csr_var'
, \
$out_csr
, 100, {
ora_type
=> 102 });
$csr
->execute();
@row
=
$out_csr
->fetchrow_array;
exit
1;
}
sub
test_auto_reprepare {
local
(
$dbh
) =
@_
;
$dbh
->
do
(
q{drop table timbo}
);
$dbh
->{RaiseError} =1;
$dbh
->
do
(
q{create table timbo ( foo integer)}
);
$dbh
->
do
(
q{insert into timbo values (91)}
);
$dbh
->
do
(
q{insert into timbo values (92)}
);
$dbh
->
do
(
q{insert into timbo values (93)}
);
$dbh
->commit;
$Oraperl::ora_cache
=
$Oraperl::ora_cache
= 1;
my
$sth
=
$dbh
->prepare(
q{select * from timbo for update}
);
$sth
->execute;
$sth
->dump_results;
$sth
->execute;
print
$sth
->fetchrow_array,
"\n"
;
$dbh
->commit;
print
$sth
->fetchrow_array,
"\n"
;
$dbh
->
do
(
q{drop table timbo}
);
exit
1;
}