home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
perl502b.zip
/
ext
/
DB2CLI
/
DB2CLI.pm.in
< prev
next >
Wrap
Text File
|
1995-10-20
|
11KB
|
378 lines
package DB2CLI;
=head1 NAME
DB2CLI - Call Level Interface of DB2/x.
=head1 DESCRIPTION
This modules supports all CLI (Call Level Interface) calls of DB2 2.1,
except for SQLBind*, SQLExtendedFetch, SQLParam*, SQLPutData and
SQLSetParam.
=head2 CLI Functions
For a detailed description of the CLI functions, consult the CLI
reference. Parameters are passed one-to-one, with exceptions from this
rule noted below. Some functions have default values for trailing
parameters. Consult the implementation (db2cli.xs) for details on
default arguments.
Output (pointer) arguments expect an lvalue (variable).
String lengths are implicit, both in and out. Functions which return
data with a length argument of type SQLINTEGER can pass at most 1MB.
Parameters cannot be bound. Instead they are passed as trailing
arguments to SQLExecute|ExecDirect[2] (see below). Missing or "undef"
parameters are passed as NULL. Output parameters of stored procedures
are not supported.
=item SQLExecute|ExecDirect
expect one argument for each parameter. The data types are derived
from the Perl data type. Integer values are passed as SQL_INTEGER,
floating point values as SQL_DOUBLE and strings as SQL_CHAR.
=item SQLExecute2|ExecDirect2
expect three arguments for each parameter. The first is the C data
type (ignored if the value is of integer or floating point type), the
second is the SQL data type and the third is the value.
=item Result columns
cannot be bound. Get column data as SQL_C_CHAR strings by supplying
lvalue arguments to SQLFetch, or use SQLGetData. NULL values assign
"undef". When using SQLGetData, SQL_C_SHORT|LONG assign an integer
value, SQL_C_FLOAT|DOUBLE a floating point value and all others a
string.
=item SQLGet(EnvAttr|ConnectOption|StmtOption)
Use SQLGet(EnvAttr|ConnectOption|StmtOption)Long for integer
attributes/options and SQLGet(EnvAttr|ConnectOption|StmtOption)Str for
string attributes/options.
=item SQLGetInfo
Use SQLGetInfoShort for 16-bit integers, SQLGetInfoLong for 32-bit
integers and masks and SQLGetInfoStr for strings. Or use SQLGetInfoStr
for all and unpack the returned data.
=item SQLSet(EnvAttr|ConnectOption|StmtOption)
pass a string attribute/option if the argument is a string and an
integer attribute/option otherwise.
=item Constants
All constants defined in sqlcli.h, sqlcli1.h and sqlext.h are
available as parameterless functions (the usual way for xsubs). I
strongly recommend "use strict 'subs'", since a mistyped upper case
name without parentheses silently yields the name string instead of
the expected integer value (even with -w).
=back
=head2 High-Level Functions
On error, all high-level functions display an error message and die
with a stack trace.
=item $connRef = Connect DB2CLI $dbname, $userid=undef, $password=undef;
Initialize CLI (first call) and connect to database. Return a
reference to the database connection instance (object).
=item $connRef->Transact $type=SQL_COMMIT
Perform transaction. Return $connRef.
=item $connRef->Disconnect
Disconnect from database and deinitialize CLI (last call). $connRef is
set to undef.
=item $stmtRef = $connRef->Statement [$comment]
Create a statement instance. Returns a reference to the instance.
$comment is displayed in error messages.
=item $rc = $connRef->ExecDirect $sqlstmt, @args
Shorthand for Statement+Execute+Release. Pass the return code of
SQLExecute.
=item $rc = $stmtRef->Prepare $sqlstmt, [$stmtRef2]
Prepares a SQL statement. If $stmtRef2 is given, append the name of
its cursor to the SQL statement text - in this case the SQL statement
should end in "WHERE CURRENT OF". Returns $stmtRef.
=item $rc = $stmtRef->Execute @args
Execute the prepared statement, optionally passing the given
arguments. Pass the return code of SQLExecute.
=item $rc = $stmtRef->Fetch @cols
Fetch the next row into @cols (list of lvalues). Pass the return code
of SQLFetch.
=item $stmtRef->Close
Release resources and locks associated with a prepared
statement. Return $stmtRef.
=item $stmtRef->Release
Like Close, but release the statement instance too. Always returns
undef.
=item $anyRef->Message [$text]
Display available information about the last error associated with the
connection or statement instance. Transactions are rolled back. The
script is terminated by calling `confess' (see Carp.pm) with $text as
argument.
=item $connRef->{HENV}, $connRef->{HDBC}, $stmtRef->{HSTMT}
Environment, connection and statement handle of connection or
statement instance.
=back
=head2 EXAMPLE
use DB2CLI;
use strict 'subs';
die "Usage: runstats <database> <schema>\n"
if $#ARGV < 1;
$database = uc shift @ARGV;
$schema = uc shift @ARGV;
$dbc = Connect DB2CLI $database, undef, undef;
$stmt = $dbc->Statement("Select tables of schema $schema");
$rc = SQLTables($stmt->{HSTMT}, "", $schema, "%", "")
and $stmt->Message("SQLTables", $rc);
while (($rc = $stmt->Fetch($cat, $sch, $tab, $typ, $rem)) == 0) {
print "runstats on table $sch.$tab with distribution and detailed indexes all\n";
}
$stmt->Release();
$dbc->Disconnect();
=cut
use Carp;
require Exporter;
require DynaLoader;
require AutoLoader;
@ISA = qw(Exporter DynaLoader);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
@EXPORT = qw(
%%
);
sub AUTOLOAD {
# This AUTOLOAD is used to 'autoload' constants from the constant()
# XS function. If a constant is not found then control is passed
# to the AUTOLOAD in AutoLoader.
local($constname);
($constname = $AUTOLOAD) =~ s/.*:://;
$val = constant($constname, @_ ? $_[0] : 0);
if ($! != 0) {
if ($! =~ /Invalid/) {
$AutoLoader::AUTOLOAD = $AUTOLOAD;
goto &AutoLoader::AUTOLOAD;
}
else {
($pack,$file,$line) = caller;
die "Your vendor has not defined DB2CLI macro $constname, used at $file line $line.
";
}
}
eval "sub $AUTOLOAD { $val }";
goto &$AUTOLOAD;
}
bootstrap DB2CLI;
# Preloaded methods go here.
# Autoload methods go after __END__, and are processed by the autosplit program.
1;
__END__
#############################################################################
sub iMessage
{
my ($henv, $hdbc, $hstmt, $where, $failrc) = @_;
my ($state, $code, $message, $text);
my $rc = SQLError($henv, $hdbc, $hstmt, $state, $code, $message);
$text = "\n$where";
$text .= "\n\trc=$failrc"
if $failrc;
$text .= "\nCannot obtain SQL error message, API rc=$rc:\n"
if $rc < 0;
$text .= ", state=$state, code=$code\n$message\n\n";
if ($failrc >= 0) {
croak $text;
return 1;
}
SQLTransact($hdbc, SQL_ROLLBACK);
confess $text;
}
#############################################################################
# Connections
sub Connect
{
my ($class, $database, $user, $pw) = @_;
my ($henv, $hdbc, $rc);
if ($rc = SQLAllocEnv($henv)) {
warn "SQLAllocEnv failed with rc=$rc\n";
return undef;
}
if ($rc = SQLAllocConnect($henv, $hdbc)) {
iMessage($henv, undef, undef, "SQLAllocConnect", $rc);
SQLFreeEnv($henv);
return undef;
}
my $connRef = bless { HENV => $henv, HDBC => $hdbc, DATABASE => $database };
if ($rc = SQLConnect($hdbc, $database, $user, $pw)) {
$connRef->Message("SQLConnect to $database", $rc);
SQLFreeConnect($hdbc);
SQLFreeEnv($henv);
return undef;
}
return $connRef;
}
sub Transact
{
my ($connRef, $arg) = @_;
my ($rc);
if ($rc = SQLTransact($connRef->{HDBC}, $arg)) {
$connRef->Message("SQLTransact $connRef->{DATABASE}", $rc);
}
return $connRef;
}
sub Disconnect
{
my ($connRef) = @_;
my ($rc);
if ($rc = SQLDisconnect($connRef->{HDBC})) {
$connRef->Message("SQLDisconnect from $connRef->{DATABASE}", $rc);
}
SQLFreeConnect($connRef->{HDBC});
SQLFreeEnv($connRef->{HDBC});
return $_[0] = undef;
}
#############################################################################
# Statements
sub Statement
{
my ($connRef, $comment) = @_;
my ($hstmt, $rc);
if ($rc = SQLAllocStmt($connRef->{HDBC}, $hstmt)) {
$connRef->Message("SQLAllocStmt", $rc);
return undef;
}
return bless { %$connRef, HSTMT => $hstmt, TEXT => $comment };
}
sub ExecDirect
{
my ($connRef, $stmt, @args) = @_;
my $stmtRef = $connRef->Prepare($stmt);
my $rc = $stmtRef->Execute(@args);
$stmtRef->Release();
return $rc;
}
sub Prepare
{
my ($connRef, $stmt, $refStmt) = @_;
my ($hstmt, $rc);
if ($rc = SQLAllocStmt($connRef->{HDBC}, $hstmt)) {
$connRef->Message("SQLAllocStmt", $rc);
return undef;
}
if ($refStmt) {
my $cursor = "-Unknown-";
SQLGetCursorName($refStmt->{HSTMT}, $cursor);
$stmt .= " $cursor";
}
my $i = index($stmt, "\n", 1);
my $s = ($i >= 0) ? substr($stmt, 0, $i) : $stmt;
my $stmtRef = bless { %$connRef, HSTMT => $hstmt, TEXT => $s };
if ($rc = SQLPrepare($hstmt, $stmt)) {
$stmtRef->Message("SQLPrepare \"$s\"", $rc);
return undef;
}
return $stmtRef;
}
sub Execute
{
my ($stmtRef) = shift @_;
my ($rc);
if ($rc = SQLExecute($stmtRef->{HSTMT}, @_)) {
$stmtRef->Message("SQLExecute \"$stmtRef->{TEXT}\"", $rc);
}
return $rc;
}
sub Fetch
{
my ($stmtRef) = shift @_;
my ($rc);
if (($rc = SQLFetch($stmtRef->{HSTMT}, @_)) != SQL_SUCCESS && $rc != SQL_NO_DATA) {
$stmtRef->Message("SQLFetch \"$stmtRef->{TEXT}\"", $rc);
}
return $rc;
}
sub Close
{
my ($stmtRef) = @_;
my ($rc);
if ($rc = SQLFreeStmt($stmtRef->{HSTMT}, SQL_CLOSE)) {
$stmtRef->Message("SQLFreeStmt \"$stmtRef->{TEXT}\"", $rc);
}
return $stmtRef;
}
sub Release
{
my ($stmtRef) = @_;
my ($rc);
if ($rc = SQLFreeStmt($stmtRef->{HSTMT})) {
$stmtRef->Message("SQLFreeStmt \"$stmtRef->{TEXT}\"", $rc);
}
return undef;
}
sub Message
{
my ($stmtRef, $text, $rc) = @_;
iMessage($stmtRef->{HENV}, $stmtRef->{HDBC},
exists($stmtRef->{HSTMT}) ? $stmtRef->{HSTMT} : undef,
$text, $rc);
die if $rc < 0;
}