===========================================================================
DBperl API Specification
------------------------
Version 0.5
* D R A F T *
Abstract
--------
DBperl is a database access Application Programming Interface (API)
for the Perl Language. The DBperl API Specification defines a set
of functions, variables and conventions that provide a consistent
database interface independant of the actual database being used.
---------------------------------------------------------------------------
Mailing list:
[email protected]
Subscribe to:
[email protected]
FTP Archive: ftp.demon.co.uk:/pub/perl/db (read the README file)
Current editor: Tim Bunce <
[email protected]> (Version 0.5 onwards)
Editors notes: lines of text that begin with an exclamation:
! are editors notes to the reviewers and not part of the spec.
---------------------------------------------------------------------------
Copyright (c) Tim Bunce 1994 England.
Permission is hereby granted to make and distribute verbatim
(complete and unedited) copies of this document. Permission is also
granted to translate this document into other languages and formats
provided that all text is included.
===========================================================================
TABLE OF CONTENTS
1. INTRODUCTION TO DBperl
1.1 Purpose of DBperl
1.2 Background
1.3 Current Work
1.4 Guiding Principles
1.5 Specification Originators And Contributors
1.6 Intellectual Property and Copyright
1.7 For More Information Or To Contribute Constructive Feedback
1.8 Structure Of The Specification
2. CONVENTIONS, STRUCTURE and OPEN ISSUES
2.1 Architecture of a DBperl Application
2.2 Terms
2.3 General Interface Rules & Caveats
2.4 Naming Conventions
2.5 Notation
2.6 Document Conventions
2.7 Open Issues
3. DATABASE INTERACTION FUNCTIONS
3.1 Session Management
3.1.1 Introduction
3.1.2 connect
3.1.3 disconnect
3.2 Data Query Functions
3.2.1 Introduction
3.2.2 prepare
3.2.3 execute
3.2.4 titles
3.2.5 fetch
3.2.6 finish
3.2.7 do (Library Function)
3.2.8 lookup (Library Function)
3.2.9 proc
3.3 Transaction Management
3.3.1 Introduction
3.3.2 commit
3.3.3 rollback
3.3.4 savepoint
3.4 Navigational Data Query Functions
4. ERROR AND EVENT HANDLING
4.1 Error Status Functions
4.1.1 errno
4.1.2 errstr
4.1.3 errstate
4.1.4 errmsg
4.2 Event Handler Functions
4.2.1 Introduction
4.2.2 handler
4.2.3 example_handler
4.3 Event Types
4.3.1 Introduction
4.3.2 Standard Event Types
4.3.3 DBperl Defined Event Types
4.3.4 Example Module Specific Event Types
4.4 Using An Event Handler
4.4.1 Introduction
4.4.2 The Retry Mechanism
4.4 DBperl Generic Event Handler Function
5. THE DBPERL SWITCH AND MODULES
5.1 Introduction
5.2 Switch Variables
5.2.1 $db'version
5.2.2 $db'attribution
5.2.3 $db'last_func
5.2.4 $db'last_handle
5.2.5 $db'last_modh
5.2.6 $ENV{DBPERL_PATH}
5.2.7 $ENV{DBPERL_AUTOLOAD}
5.2.8 $ENV{DBPERL_MODULE}
5.3 Switch Functions
5.3.1 modules
5.3.2 install
5.3.3 call_func
5.4 Switch Basics
5.4.1 DBperl Modules
5.4.2 DBperl Handles
5.4.3 Function Call Routing
5.4.4 Automatic Handle Promotions
5.5 Module Selection
5.5.1 Introduction
5.5.2 Using Module Names
5.5.3 Using Database Type Names
5.6 Module Dynamic Loading
5.6.1 Introduction
5.6.2 Search Method
5.6.3 Automatic Loading on Startup
5.6.4 Example
5.7 Module Layering
5.7.1 Introduction
5.7.2 Examples
6. ATTRIBUTE NAMES AND VALUES
6.1 Introduction
6.2 Attribute Functions
6.2.1 getvalue
6.2.2 setvalue
6.2.3 Using Attributes With Other Functions
6.3 Attribute Names
6.3.2 MixedcaseNames
6.3.3 lowercase_names
6.3.4 Attribute Scope
6.3.5 Attribute Values
6.3.6 Attribute Listing Legend
6.4 Module Attributes ($modh, $dbh, $sh)
6.4.1 ModuleName S
6.4.2 ModuleAttribution S
6.4.3 ModuleHandle H
6.5 Database Attributes ($dbh, $sh)
6.5.1 IDENTIFIER_LENGTH I
6.5.2 IDENTIFIER_CASE S
6.5.3 ROW_LENGTH I
6.5.4 DbTimeZoneType S
6.5.5 DbReadCache I,M
6.5.6 DbNumRows I
6.5.7 DbHandle H
6.6 Statement Attributes ($sh)
6.7 Module Specific Attributes
6.8 Switch Specific Attributes
6.8.1 DBperlPortable B,M
6.8.2 DBperlTrace S,M
6.8.3 DBperlLog S,M
7. DATA TYPE CONVERSION FUNCTIONS
7.1 Introduction
7.2 String Formatting Functions
7.2.1 quote
7.3 Date & Time Functions
7.3.1 Notation & Nomenclature
7.3.2 ndt2udt
7.3.3 udt2ndt
8. DATA DICTIONARY FUNCTIONS
8.1 Introduction
8.2 Data Dictionary Core Functions
8.2.1 info_table_names
8.2.2 info_table
8.2.3 info_col_names
8.2.4 info_col
9. EXAMPLES
9.1 Simple SELECT
9.2 Simple INSERT
9.3 Iterative insert from flatfile
9.4 Creating a temporary table
9.5 Error handling
9.6 Bind parameter handling
10 APPENDICES
10.1 Function and Variable Summary
10.2 Portability
10.2.1 Detecting and Declaring Non-Portability
10.3 Ideas for Utilities and Packages
10.5 Module Implementors Template
10.5.1 Example for Oracle Module
10.5.2 Example for Ingres Module
===========================================================================
1. INTRODUCTION TO DBperl
===========================================================================
(This section was last modified on $Date: 1994/05/02 14:02:39 $
is currently at $Revision: 5.0 $ and is stable.)
1.1 Purpose of DBperl
---------------------------------------------------------------------------
The purpose of the DBperl API (Application Perl-script Interface) is to
create a common set of extensions to perl to enable interaction between
applications and various database engines. DBperl (yes this is the
officially recognized and approved capitalization and spelling) will
allow the creation of database-manipulation scripts without regard for
the engine being used to service the SQL requests.
1.2 Background
---------------------------------------------------------------------------
A number of independent efforts have been made to connect database
engines to perl. Interfaces currently exist for Oracle, Sybase,
Ingres, Interbase, Informix, Unify, Postgres and perhaps others that we
are not aware of. All of these interfaces have APIs that are atuned to
the peculiarities of their engine back-end and thus a perl script must
be changed to work with different engines.
1.3 Current Work
---------------------------------------------------------------------------
Since around October 1992, a group of interested parties, including the
authors of some of the interfaces named above, have been working on
(thrashing out) an engine-independent interface specification for what
we are calling DBperl.
The specification is currently at the 0.5 revision level and is nearing
completion. It's around 3000 lines and 100Kb long. Details of the
DBperl mailing list and ftp archive are given in Section 1.7.
We are now working on the next, and hopefully final, draft (0.6). This
will take the functionality of the 0.5 draft and rework it to make best
use of the new features in Perl 5.
1.4 Guiding Principles
---------------------------------------------------------------------------
It is hoped that DBperl will:
o Provide an interface with sufficient capability to be useful.
o Be simple to use for simple applications.
o Have sufficient flexibility to accommodate unusual or proprietary
functionality (events etc) and even non-sql databases.
o Conform to or anticipate applicable standards where practical.
Especially the X/Open & SQL Access Group SQL and CLI standards.
o Enable the creation of database-independent perl scripts
but not limit you to the lowest common functionality.
o Be freely available. See below.
o More exotic goals include: support for concurrent access to
multiple database engines, dynamic loading of database interface
modules, easy to implement database modules in C or perl code.
1.5 Specification Originators And Contributors
---------------------------------------------------------------------------
- Kurt Andersen <*> Informix
- Kevin Stock <*> Oracle
- Buzz Moschetti <
[email protected]> Interbase
- Michael Peppler <
[email protected]> Sybase
- Tim Bunce <
[email protected]> DBperl Switch
- Ted Lemon <
[email protected]> Ingres
<*> Unfortunately Kevin (a major contributor) and Kurt (the original
specification editor upto and including v0.4) have both lost their
access to the net.
List of Top Contributors (automatically generated):
Tim Bunce, Kevin Stock, Buzz Moschetti, Kurt Andersen, Ted Lemon,
William Hails, Garth Kennedy, Michael Peppler, Neil S. Briscoe,
David J. Hughes, Jeff Stander, Forrest D Whitcher, Larry Wall,
Jeff Fried, Roy Johnson, Paul Hudson, Georg Rehfeld, Steve Sizemore,
Ron Pool, Jon Meek, Tom Christiansen, Steve Baumgarten,
Randal L. Schwartz, ... and a whole lot more people (100+) who have
put up with the discussions and contributed from time to time on the
mailing list (see below).
We always need more active contributors. Please join in this effort.
1.6 Intellectual Property and Copyright
---------------------------------------------------------------------------
Our collective intention is that all of the DBperl materials (DBperl API
specifications, switch and modules) will be distributed under the same
terms and mechanisms as perl itself (e.g., can be used under the GNU
_or_ Artistic License).
Thus individual Module implementors and DBperl application developers
are free to exploit their work commercially. They are not required to
release their work or source code, but we hope that they will.
This DBperl API Specification is Copyright (c) Tim Bunce 1994 England.
Permission is hereby granted to make and distribute verbatim (complete
and unedited) copies of this document. Permission is also granted to
translate this document into other languages and formats provided that
all text is included.
1.7 For More Information Or To Contribute Constructive Feedback
---------------------------------------------------------------------------
Very little of this specification has been arbitrarily chosen. If you
are interested in the reasoning behind any particular portion of the
API, please send your queries to the address below and you will
probably get one (or more) versions of the discussions that have led up
to this current formulation. Be warned that more than 18 months and
over 500 messages totaling more than 1.5Mb have transpired, so the
succinct version you receive will not preserve the nuances of the
give-and-take that has happened.
For feedback on this specification, please send that to the DBperl
mailing list from whence it will be echoed to the interested parties:
[email protected]
If you would like to be added to (or removed from) the list of
interested parties, please send your request to:
[email protected]
Archives of the perldb-interest mail and copies of the DBperl API
specification are kept at ftp.demon.co.uk:/pub/perl/db by kind
permission of demon.net (Demon Internet Services Limited, UK). This
archive also holds other database/perl related software (oraperl,
sybperl, sqlperl, uniperl, rdb, shql etc).
Please contact one of the people listed above if you have specific
questions about the handling of database engine peculiarities.
1.8 Structure Of The Specification
---------------------------------------------------------------------------
Because the specification is long it is divided into several parts:
1) Introduction to DBperl (this section)
2) Structure, Conventions and Open Issues
3) Database Interaction Functions
4) Error and Event Handling
5) The Switch and Modules
6) Attribute Names and Values
7) Data Type Conversion Functions
8) Data Dictionary Functions
9) Examples
10) Appendix
Eventually this specification will become a man page for DBperl
(hopefully somewhat shorter then perl's man page :-). Each Module
implementor will also supply a man page for their module in a standard
format and style.
End of DBperl API Section 1.
===========================================================================
2. CONVENTIONS, STRUCTURE and OPEN ISSUES
===========================================================================
(This section was last modified on $Date: 1994/05/02 14:02:39 $
is currently at $Revision: 5.0 $ and is stable.)
2.1 Architecture of a DBperl Application
---------------------------------------------------------------------------
|<-- Scope of DBperl --->|
.-. .-------------. .-------------.
.------. | |---| XYZ Module |---| XYZ Engine |
|Perl | |S| `-------------' `-------------'
|script| |A| |w| .-------------. .-------------.
|using |--|P|--|i|---|Oracle Module|---|Oracle Engine|
|DBperl| |I| |t| `-------------' `-------------'
| API | |c|...
|funcs | |h|... Other modules
`------' | |...
`-'
2.2 Terms
---------------------------------------------------------------------------
API -- Application Perl-script Interface
The call interface and variables provided by DBperl to perl
scripts. The API is implemented via the perl usub mechanism.
Switch
The code that provides the DBperl API and re-directs the DBperl
function calls to the appropriate Module for actual execution.
The Switch is also responsible for the dynamic loading of Modules,
error checking/handling and other general duties.
Module
A Module implements support for a given type of Engine (database).
Modules contain implementations of the DBperl functions written
using the private interface functions of the corresponding Engine.
Only authors of sophisticated/multi-database applications or
generic library functions need be concerned with Modules.
The Switch itself has a Module interface and can be conveniently
treated as a Module by applications.
Engine
The actual "engine" that is being communicated with by a Module,
e.g., Oracle, Ingres, Sybase etc. Note that Engines need not be
databases, consider DNS, X.500, SNMP for example.
MPI -- Module Programmer's Interface
This is the interface provided by the Switch which is used to
communicate with Modules. Only module implementors need be
concerned with this interface. The Switch and MPI will take most of
the work out of writing Modules for DBperl. Hopefully this will
encourage people to implement Modules for their favourite database.
Work on the MPI specification is unlikely to start until the DBperl
specification is stable and implementation of the Switch has begun.
The MPI is likely to provide both perl usub and C style interfaces
so Modules can be implemented with whichever is the most appropriate.
It should be possible to implement DBperl Modules in perl code!
Handle
Handles are opaque values returned by some functions which can be
passed back to DBperl functions to refer to objects such as a
Module, a database connection or a prepared SQL statement. The full
implications of Perl 5 Object Orientation on the DBperl API have
yet to be considered. It is likely that handles will be blessed.
Library
A perl package of utility functions to aid the DBperl user in
performing common activities. Within the DBperl spec these
functions are not separated out but are located in their
appropriate sections and identified by the label 'Library
Function'.
Bundle
The actual collection of DBperl Switch and DBperl Modules which are
built and installed on the system where the perl script is being
executed.
TBD
To Be Decided. Parts of the specification that have not yet been
completed. These are often just section cross references.
2.3 General Interface Rules & Caveats
---------------------------------------------------------------------------
a) Most data is returned to the perl script as perl strings. This
allows arbitrary precision representations within the scope of the
engine/module to be handled without loss of accuracy. Beware that
perl conversions and other engines/modules may not preserve the
same accuracy.
b) Dates and times are returned as character strings in the native
format of the corresponding Engine. Functions are provided to
convert the native format values into integers representing the
number of seconds since 1 January 1970, e.g., 'unix time'. Other
conversion functions may be defined later. Time Zone effects are
engine/module dependent and can be deduced from parameters
available from &db'getvalue(), q.v.
c) Binary data types are not yet explicitly supported by DBperl.
Perl itself supports binary data in perl strings and the Switch
will pass binary data to and from the Modules without change. It is
up to the Module implementors to decide how they wish to handle
such binary data.
d) Multiple SQL statements may not be combined in a single statement
handle, e.g., a single $sh. This restriction has most impact upon
Sybase users. An alternative approach may be possible later.
e) Non-sequential record reads are not supported in this version of the
DBperl API. E.g., records can only be fetched in the order that the
database returned them and once fetched they are forgotten.
f) Positioned updates and deletes are not currently supported by
DBperl. E.g., it is not possible to execute a select query, fetch a
number of rows and then update or delete the 'current row' before
fetching more rows. All cursors are assumed to be read-only and
unnamed. This may change in the future.
g) Individual Module implementors are free to provide any private
mechanisms that they feel are useful (e.g., for items d, e and f
above). These private functions can be invoked using the DBperl
&db'exec() function but they are not part of this specification.
2.4 Naming Conventions
---------------------------------------------------------------------------
a) All DBperl functions and variables exist in the 'db' or 'dbperl'
packages. These package name are reserved for use by DBperl.
b) The package name space 'db_*' is reserved for the private use of
DBperl module packages. E.g., the 'oracle' DBperl module has
private use of the db_oracle package namespace. DBperl does not
currently define any use for this namespace, this will change.
Scripts using packages with names which begin with db_ may
experience compatibility problems with future versions of the
DBperl API or specific DBperl modules.
c) The DBperl module names 'switch' and 'dbperl' are reserved.
d) All environment variables used by the DBperl Switch or Modules
begin with 'DBPERL_'.
e) Attribute name-value pairs are used in many places throughout the
DBperl specification. They provide a very simple and flexible way
to determine or alter the behaviour of a Module or a particular
database query.
Attribute names and values are described in detail in section 6.
For now it is only important to note that the case of the attribute
name is used to signify who defined the meaning of that name and
its values.
Case of name Meaning defined by
------------ ------------------
UPPER_CASE Standards, e.g., X/Open, SQL92 etc (portable)
MixedCase DBperl API (portable), underscores are not used.
lower_case Module or engine specific (non-portable)
2.5 Notation
---------------------------------------------------------------------------
a) "Handles", if defined, are assumed to be active:
$modh - designates a handle for a database module and is
generally interchangeable with the name of the module
to which it connects. Typically users need not be
concerned with modules or module handles.
$dbh - designates a handle for an open database connection and
presumes a module designation.
$sh - designates a statement handle for a single prepared SQL
statement and presumes a $dbh to which it is connected.
There is no separate cursor handle for active queries in
DBperl. The $sh serves as a handle for both the prepared
statement and its cursor. Multi-statements tied to a
single handle are not supported.
$handle - designates that a handle is required but no specific
type is most appropriate. The accompanying documentation
will describe which types of handles may be used.
Handle overloading is allowed, e.g., any function specified to
accept a $modh parameter can also accept a $dbh or a $sh to
indirectly specify the module. Similarly, any function that calls
for a $dbh parameter can accept a $sh to specify the $dbh
indirectly. This applies everywhere.
b) Return values are noted as:
$rc - return condition (or a handle), evaluates (in Perl) to boolean
false on an error condition to facilitate short-cut chaining.
Typical values: 1=success, 0=error, undef=unsupported (error).
E.g., &db'something() || die "db'something failed"
$rv - return value, does not necessarily evaluate as false on an error
condition.
@ary - returns an array of values. Typically an error condition will
result in an empty array being returned.
2.6 Document Conventions
---------------------------------------------------------------------------
Each function is documented with the following general structure:
5.4.3 something
$rv = &db'something($dbh, $arg [,%attr]);
$dbh -- database handle
$arg -- description of argument
%attr -- associative array of additional attributes that can
be passed to this function to affect its behaviour
$rv -- description of returned value
Several sentences describing the purpose and behaviour of the function.
Events: description of events/errors that may occur (if any)
EVENT_NAME -- description of this event and its meaning
...
Attributes: description of optional attributes (where appropriate)
name, value -- description of this attribute and its possible values
...
Portability:
Any aspects of this functions behaviour that might not be supported
by some modules. (Also see the Portability section of the appendix.)
Example:
...
Events and errors are described in detail in section 4.
Standard events and errors such as ERROR and WARN are also
described in that section. Only events that are specific to a
function are listed in that functions description.
2.7 Open Issues
---------------------------------------------------------------------------
a) The contents of the DBperl Library are open to suggestion.
Please let me know what other common patterns of SQL execution you
think would be useful to DBperl application developers.
b) Suggestions for additional attribute names and values to be
accessible via functions &db'getvalue() and &db'setvalue() are
requested. See section 6.
c) How to handle date and time intervals in a distinct manner from
absolute dates and times is yet to be defined. It may be ignored.
d) Data typing issues in general have been put to one side for now
(other than the absolute vs interval date/time issue noted above).
It seems best to ignore them until implementations of the spec
actually exist.
e) Do we need functions to control:
autocommit -- on / off
locking -- level=row/page/table, readlocks, timeouts etc
etc
f) Do we need functions to:
call database procedures
return space left in/for the database
return list of available databases
etc
g) Implications of Perl 5 Object Orientation need to be considered.
The DBperl API is already OO clean in the sense that all
appropriate functions take a handle as their first argument
(representing 'this'). So we can bless handles into the db
package, allowing: @ary = $sh->fetch; The package name will
need to change to DBperl to avoid conflict with dbm packages.
Version 0.6 of the DBperl specification (currently being worked on)
will address these issues.
End of DBperl API Section 2.
===========================================================================
3. DATABASE INTERACTION FUNCTIONS
===========================================================================
(This section was last modified on $Date: 1994/05/02 14:02:39 $
is currently at $Revision: 5.0 $ and is stable.)
3.1 Session Management
---------------------------------------------------------------------------
3.1.1 Introduction
Before an application can interact with a database engine it must
establish a connection to that engine using the &db'connect function.
A database connection is also known as a database session.
DBperl does not have a concept of a `current session'. Every session
has a handle (e.g., a $dbh) returned from the &db'connect function, and
that handle (or a handle derived from it) must be passed to every
DBperl function.
3.1.2 connect
$dbh = &db'connect([$database [, $username [, $password
[, $module [, %attr]]]]]);
$database -- a database name
$username -- user name by which to connect to the database
$password -- password by which to connect as $username
$module -- name or handle of module to use
%attr -- attributes for this connection
$dbh -- returns a database connection handle or undef on error.
Establishes a database connection (session) to the requested database.
The $database, $username and $password arguments are passed to the
module for processing. The DBperl API does not define ANY
interpretation for the contents of these fields. As a convenience, if
the $database field is undefined or empty the Switch will substitute
the value of the environment variable DBPERL_DBNAME if any.
If $module is not specified, the environment variable DBPERL_MODULE
is used. If that variable is not set and the Switch has more than one
Module loaded then the connect fails and undef is returned. Modules
are defined in Section 5.
The module is free to interpret the database, username and password
fields in any way and supply whatever defaults are appropriate for
the engine being accessed.
The &db'connect() function automatically starts a transaction for
those database types which require explicit control over
transactions. There is no need for the user to invoke an explicit
'start transaction' function. Whenever a transaction is commited or
rolled-back a new transaction is started automatically. This emulates
the SQL-92 standard behaviour.
Each session ($dbh) is independent from the transactions in other
sessions. This is useful where you need to hold cursors open across
transactions, e.g., use one session for your long lifespan cursors
(typically read-only) and another for your short update transactions.
Portability:
Portable applications should not assume that a single module will
be able to support multiple simultaneous sessions. For example:
$dbh_1 = &db'connect(@args);
$dbh_2 = &db'connect(@args); # may not be portable
Attributes:
Handler, function -- establish the event handler for this connection
(see Section 4: Error and Event Handlers). This is an alternative
to calling &db'handler and allows the handler to process events in
the midst of establishing a connection whereas &db'handler
requires a preexisting $dbh.
See Section 6 and "Modules" in the Appendix for details of general
and Module specific attributes.
3.1.3 disconnect
$rc = &db'disconnect([$handle]);
$handle -- an optional handle: $modh or $dbh
Release all resources being used in conjunction with the specified
handle (typically a $dbh) and disconnect the session from the
engine. Note that any changes associated with the session
will be rolled back. To commit work use &db'commit before calling
&db'disconnect.
If a module handle is specified, all connections via that module will
be &db'disconnect()'d and, if dynamic loading is implemented, the
module will be unloaded. If no parameter is specified, all modules
will be detached.
3.2 Data Query Functions
------------------------------------------------------------
3.2.1 Introduction
DBperl allows the application to `prepare' a statement for later
execution. A prepared statement is identified by a statement handle,
e.g., $sh. A statement handle can be in one of three states:
Prepared -- after &db'prepare() or &db'finish() succeeded.
Open -- after &db'execute() if the statement is a select.
Invalid -- after &db'disconnect() (or &db'prepare() failed).
Typical function call sequence (for select statement):
prepare,
execute, fetch, fetch, ... finish,
execute, fetch, fetch, ... finish,
execute, fetch, fetch, ... finish.
Typical function call sequence (for non-select statement):
prepare,
execute,
execute,
execute.
Some database engines invalidate prepared statements after a commit or
rollback. DBperl Modules for these engines will automatically and
transparently re-prepare any statements whose handles are used after
they become invalid in this way.
Portability restrictions (also see "Portability" in the Appendix):
Portable applications should not rely on a single module being able to
support multiple simultaneous open selects. For example:
$sh_1 = &db'prepare($dbh, $select_statement_1);
$sh_2 = &db'prepare($dbh, $select_statement_2);
&db'execute($sh_1);
&db'execute($sh_2); # $sh_1 still open, may not be portable
Changes from DBperl v0.4 (and oraperl):
a) $qh handles (previously $sqlh) are now called statement handles ($sh)
b) &db'prepare NEVER executes a statement.
c) &db'bind is now called &db'execute to better describe its function
and conform more closely with the SQL CLI standard.
d) &db'execute and &db'do are the only (non-library) functions that
execute statements.
3.2.2 prepare
$sh = &db'prepare($dbh, $statement [, %attr]);
$dbh -- a database handle
$statement -- a database language statement (e.g. SQL)
%attr -- additional attributes
$sh -- returned statement handle
Prepare a single statement for execution by the database and return a
handle for it.
The statement can include 'placeholders' for values to be supplied
when the prepared statement is executed. Placeholders are identified
with a question mark in the statement (as per the X/Open standard).
The &db'execute function (see below) is used to associate values with
any placeholders in a prepared statement before executing it.
The &db'getvalue($sh, 'IsSelect') function can be used to determine
if the prepared statement is a select.
There is no mechanism to unprepare or forget a prepared statement.
Attributes
ReadAheadCache, n -- number of rows to read ahead (if supported)
CursorLife, HOLD -- cursor should span transactions (if supported)
Events/Errors:
InvalidAttribute --
3.2.3 execute
$rc = &db'execute($sh [, @bind_values]);
$sh -- a statement handle from &db'prepare
@bind_values -- values to be bound to placeholders in $sh.
$rc -- return code, '' (false) on error else a true value.
Perform whatever processing is necessary to execute the prepared
statement.
If the prepared statement contained placeholders then the correct
number of values for those placeholders must be supplied as arguments
to &db'execute. NULL values are indicated by undefined values
(undef) in the @bind_values array.
* Execution of non-select statements:
There is no need to call &db'finish after the execution of non-select
statements. Note that it is not possible to identify the number of
rows affected by a non-select statement if there was a warning; use
&db'getvalue($sh,'RowCount') instead.
$rc = 'SUCCESS' -- No rows (or an unknown number) affected
$rc = 'WARN' -- Warning, with an unknown number of rows affected
$rc = integer>0 -- Number of rows affected (success)
* Execution of select statements:
The &db'execute function for a select statement is similar to the
Open Cursor function provided by many database interfaces.
If the statement handle was already open then &db'finish is called
automatically to complete the previous select.
The &db'fetch function can be used to fetch result rows. The
&db'finish function should be called to complete the processing of
the select statement (free read locks, etc) and return the statement
handle to its prepared state.
$rc = 'SUCCESS' -- Select started without any problems
$rc = 'WARN' -- Select started with warnings
3.2.4 titles
@ary | $rv = &db'titles($sh);
$sh -- a statement handle
@ary | $rv -- returns array of column names or number of columns
In an array context &db'titles returns an array of column names. In a
scalar context it returns the number of columns. Returns () or 0 if
$sh is not a select statement.
If the engine does not provide column names then the module will return
('col1','col2','col3') etc.
3.2.5 fetch
@ary = &db'fetch($sh);
$sh -- a statement handle
@ary -- returns fetched record as an array of field values
Fetches and returns a row of data from the statement handle $sh.
NULL values are indicated by undefined values (undef) in the returned
array or by the value of the current setting of the ReturnNullAs
attribute.
There is currently no DBperl function that supports non-sequential
(and non-standard) record read orders, e.g, First, Last, Next,
Previous etc. This may be addressed in a future version of the DBperl
spec. Meanwhile Module implementors can provide a private function
for users to invoke via the &db'call_func() function (see Section 5).
Calling &db'fetch in a scalar context will generate a warning if the
query has more than one field and perl was invoked with the -w flag.
Errors:
NonSelectHandle -- $sh is not a handle you can fetch from.
3.2.6 finish
$rc = &db'finish($sh);
$sh -- a statement handle
$rc -- return code
Release all resources (and locks, etc) being used by an Open $sh.
This is equivalent to closing a cursor in many database types. After
this call, the $sh statement handle will no longer be Open. The
statement remains Prepared, the statement handle can be passed to
&db'execute again if required. This function may be called for
non-select statements but it does nothing.
Note that there is no function to forget or delete a prepared
statement handle. Prepared statements live until &db'disconnect.
3.2.7 do (Library Function)
$rc = &db'do($dbh, $statement [, @bind_values]);
$dbh -- database handle
$statement -- a non-select statement
@bind_values -- optional bind values
$rc -- return code
Immediately executes $statement. This function provides a simple way
to execute self-contained statements such as deletes, updates and
inserts. It avoids the need to use &db'prepare, &db'execute and
possibly &db'finish.
Example
&db'do($dbh, "delete from $table where key_1=?", $key_1);
Library Implementation:
local($sh) = &db'prepare($dbh, $statement) || return undef;
&db'execute($sh, @bind_values) || return undef;
local($err) = $db'errno; # save the errno from execute
&db'finish($sh); # just in case it was a select
$err;
3.2.8 lookup (Library Function)
@ary = &db'lookup($dbh, $statement [, @bind_values]);
$dbh -- database handle
$statement -- a statement
@bind_values -- optional bind values
@ary -- returned first record as array of field values
Immediately executes $statement, fetching and returning the
first row of data. This function provides a simple way
to execute occasional select statements that need only
return one row of data.
Library Implementation:
local($sh) = &db'prepare($dbh, $statement) || return undef;
&db'execute($sh, @bind_values) || return undef;
local(@row) = &db'fetch($sh);
&db'finish($sh);
@row;
3.2.9 proc
This version of DBperl does not define a standard function for
invoking stored procedures. Too many differences exist between
the major database vendors implementations for it to be practical
to define a standard interface for DBperl.
Module implementors are encouraged to provide a module private
function called _proc for invoking stored procedures for their engine
type. Applications can call this function using the DBperl
&db'call_func() function described in Section 5.
For example:
&db'call_func($handle, '_proc', $procedure_name, @args);
3.3 Transaction Management
------------------------------------------------------------
3.3.1 Introduction
Most DBperl modules for relational database engines will support
transaction processing with commit and rollback.
The &db'connect, &db'commit and &db'rollback functions automatically
start a new transaction for those database engines which require
explicit control over transactions. There is no need for the user to
invoke an explicit 'start transaction' function. Whenever a
transaction is commited or rolled-back a new transaction is started
automatically. This emulates the SQL-92 standard behaviour.
3.3.2 commit
$rc = &db'commit($dbh);
$dbh -- database handle
$rc -- return code
Perform any processing needed to commit a transaction. If
transactions are not supported by the engine, the function does
nothing and returns success.
By default any open statement handles associated with the $dbh
session will be returned to the prepared state.
The &db'commit() function automatically starts a new transaction for
those database types which require explicit control over
transactions. There is no need for the user to invoke an explicit
'start transaction' function. Whenever a transaction is commited or
rolled-back a new transaction is started automatically. This emulates
the SQL-92 standard behaviour.
3.3.3 rollback
$rc = &db'rollback($dbh, [$savepoint_name]);
$dbh -- database handle
$savepoint_name -- optional name of a transaction savepoint
$rc -- return code
Perform any processing needed to rollback a transaction. If
transactions are not supported by the engine, the function returns an
error.
* Partial rollbacks (to named savepoints):
If savepoints are supported then the transaction is rolled back
to the named savepoint. Behaviour if the savepoint is not known
is undefined. Savepoints are defined using the &db'savepoint
function (section 3.3.3).
If savepoints are not supported by the engine, the entire transaction
is rolled back (see below) and the function raises an error.
&db'getvalue($dbh, 'Savepoints') can be used to determine if a
database supports transaction savepoints.
* Complete rollbacks (no savepoint or savepoint error):
By default any open statement handles associated with the $dbh
session will be returned to the prepared state.
After an entire transaction has been rolled back, &db'rollback($dbh)
automatically starts a new transaction for those database types which
require explicit control over transactions. There is no need for the
user to invoke an explicit 'start transaction' function. Whenever a
transaction is commited or rolled-back a new transaction is started
automatically. This emulates the SQL-92 standard behaviour.
3.3.4 savepoint
$rc = &db'savepoint($dbh, $savepoint_name);
$dbh -- database handle
$rc -- return code
Mark this point within a transaction as a named savepoint.
If savepoints are not supported by the engine, returns undefined.
3.4 Navigational Data Query Functions
------------------------------------------------------------
It is intended that future versions of the DBperl specification be
extended to include a simple non query language interface.
This `navigational' style interface would allow DBperl to act as a
single standard Perl interface for both SQL and flat-file databases
(including the whole range of xBase .DBF databases and unix system
files). This work is likely to be based loosely on the Borland IDAPI
specification.
When using these interface functions against an SQL database the DBperl
Switch could automatically translate the query into SQL before passing
it to the Module for processing. In this way simple applications that
don't require the facilities of a query language can be made portable
across a wider range of databases.
Note that non-query language `databases' could include systems like NIS,
DNS, SNMP, X.500 etc.
End of DBperl API Section 3.
===========================================================================
4. ERROR AND EVENT HANDLING
===========================================================================
(This section was last modified on $Date: 1994/05/02 14:02:39 $
is currently at $Revision: 5.0 $ and is nearly stable.)
4.1 Error Status Functions
---------------------------------------------------------------------------
4.1.1 errno
$db'errno
Holds the native error code returned by the last DBperl function.
Note that this variable has a *very* short lifespan. It is reset
to '' (false) by the Switch before *every* DBperl function call.
See also the &db'errstate($dbh) function below.
Users should not assume that this variable will hold an integer
value, engines that use the newly standardised 5 character SQLSTATE
variable will store that value in $db'errno instead.
4.1.2 errstr
$db'errstr
Holds the error text associated with the current value of $db'errno.
The text does not have a trailing newline character.
This is equivalent to join("\n", &db'errmsg($db'last_handle)).
See &db'errmsg below and Section 5 "Switch and Modules".
4.1.3 errstate
$rv = &db'errstate($dbh);
$dbh -- database handle
$rv -- returns last native error code for this handle
Returns the last native error code associated with this $dbh. The
lifespan of this value is determined by the module but it should be
valid for longer than $db'errno. Most modules will only reset this
value when another error occurs (like unix errno).
Portability:
Note that although a $dbh is indicated here, some modules will only
be able to store one errstate value for all their sessions.
4.1.4 errmsg
@ary = &db'errmsg($dbh);
$dbh -- database handle
@ary -- returns diagnostic message strings
Returns one or more diagnostic text strings associated with the last
operation performed on the designated handle.
The X/Open standard provides for multiple diagnostic messages to
be generated and stored by a database engine during the processing
of a function. The individual diagnostic messages strings do not have
trailing newlines.
As a convenience, if the function is called in a scalar context it will
return a single string containing all the available messages joined
by newlines (but still without a trailing newline).
4.2 Event Handler Functions
---------------------------------------------------------------------------
4.2.1 Introduction
DBperl provides a very general ``event'' handling mechanism. This
mechanism can easily support a wide variety of event types in a simple
and consistent manner. DBperl treats errors and warnings as types of
event.
Databases that support events/alerters/messages etc can use the DBperl
event handler mechanism to provide a clean and consistent interface for
them.
When a module raises an event/error it defines a default behaviour to
be followed if no event handler is registered or the handler returns
undef.
There is no default handler installed but a simple generic handler
is supplied in the DBperl library.
4.2.2 handler
$rv = &db'handler($dbh, $handler_function);
$dbh -- a database handle
$handler_function -- name of function to be called
$rv -- returns the name of previous handler function or ''.
Installs the named perl function as an event handler for the
specified $dbh. The handler function will be called by the Switch
when certain events/conditions occur in DBperl functions acting for
this $dbh, including errors and warnings.
An example handler function is defined below.
Because &db'handler() returns the name of the previously installed
handler (if any) the application developer can chain handlers
together. For example, a new handler could call the previous handler
to deal with any event types it did not wish to handle itself.
Example:
$prev_handler = &db'handler($dbh, 'example_handler');
4.2.3 example_handler
sub example_handler {
local($event_type, $function_name, $handle, %params) = @_;
... code ...
return undef if (< default behaviour is ok >);
... code ...
return ($action, @values); # alter behaviour to $action
}
Parameters:
$event_type -- Event type which triggered this call.
$function_name -- DBperl function being called when the event occurred.
$handle -- The handle passed to the DBperl function.
%params -- An associative array, the contents of which are
defined in conjunction with the $event_type and
$function_name. This will often be empty.
Results:
undef -- handler does not want to handle event
($action, @values) -- where $action is one of: Ok, Fail, Retry, Abort
The first three parameters provide 'core' information (information
that is independent of any given event type). The $handle can be used
to provide other useful information (such as the module name) via the
&db'getvalue($handle,...) function.
The $event_type names follow the DBperl naming convention whereby the
case of the name identifies who defined the meaning of that event
type. See section 2.4.a for more details. If the event is an error
then $db'errno (etc) will be set correctly by the module before the
handler is called.
The contents of %params will vary according to the function name,
event name, the functions arguments and the module type.
Note that very few fixed parameters are passed (e.g., just the 3) in
order that event handling can be as fast as possible. Future uses of
event handlers might require much higher 'bandwidth' than the
occasional error event.
The handler can return undef to indicate that it does not wish to
alter the default behaviour for this event.
Returned Action Values:
Ok -- The calling function should return success using @values
Fail -- The calling function should return failure using @values
Abort -- DBperl will rollback and abort the entire application
Retry -- Attempt to retry the action that generated the event
A handler is free to return any $action value that the module
supports (by DBperl convention such $action values would be lowercase
names). In this way modules can easily extend the functionality of
event handlers to suit their needs. Action values that are unknown
to the Module cause a warning to be printed to stderr and the action
is treated as 'Fail'.
4.3 Event Types
---------------------------------------------------------------------------
4.3.1 Introduction
Events are identified by Event Type Names. Event type names are defined
below in a similar manner to functions:
EventTypeName ([param_name_1 [, ...]])
The EventTypeName is the value passed to the handler function as its first
argument ($event_type in the example handler shown above).
The optional names listed in parentheses are the names of key value
pairs passed to the handler in the %params argument. The key names
follow the DBperl letter case convention defined in Section 2.4.d.
Where possible, modules should use DBperl defined event types and not
define their own. Modules are free to supply extra module-specific key
value pairs for DBperl defined events in order to convey any extra
information that is available for the event.
4.3.2 Standard Event Types
These three events are the `standard' events supported by most
engines. No extra parameters (%params) are supplied to the handler for
these event types.
ERROR ()
An operation failed.
WARN ()
An operation succeeded but with a warning.
NO_MORE_DATA ()
A &db'fetch reached the end of result set.
4.3.3 DBperl Defined Event Types
These events cover both DBperl internal issues (such as
AttributeUnknown) and attempt to provide a standard interface for a
range of engine related events (e.g., DbMessage).
AttributeUnknown (Name)
An attempt was made to refer to an unknown attribute name (Name) by a
function with a %attr parameter or by a call to &db'setvalue or
&db'getvalue.
AttributeValueBad (Name, Value)
An attempt was made to set an known attribute (Name) to an invalid
value (Value). The attribute value remains unchanged.
DbMessage (Text [, Id])
A message string (Text), with an optional identifier (Id), has been
received from the engine. Typically these messages originate from
the execution of stored procedures.
DbEvent (Name)
An event (identified by Name) has occurred within the engine.
Debug (Level, Text)
The Switch and/or Modules may choose to use the event mechanism to produce
and filter debugging information. This event type name is a placeholder for
that purpose which may be more fully defined in the future.
4.3.4 Example Module Specific Event Types
All module specific (private) event types have lowercase names that
begin with the name of the module.
oracle_?
... any suggestions ?
4.4 Using An Event Handler
---------------------------------------------------------------------------
4.4.1 Introduction
The event handler mechanism is very flexible. It is unlikely that a
full definition of its behaviour will be available until the DBperl
Switch and one or more Modules have been implemented.
Initially the handler function will only be able to return undef (to
signify default behaviour) and hence will not be able to control the
further processing of the event.
The notes below attempt to outline the current thinking.
4.4.2 The Retry Mechanism
For certain types of event it is useful to be able to retry the action
that triggered the event. Typical examples are Deadlock and LockTimeout.
It is likely that only a few events and only some modules will support
the retry mechanism.
Sequence of actions:
a) A retryable event occurs. The module prepares to call the handler.
b) The module indicates to the handler that a Retry is possible by
supplying a RetryCount (with the value 0) in the %params array.
c) The handler requests a retry by returning `Retry' to the module.
d) The module retries the action.
e) If the retry fails then the handler is called again with an
incremented RetryCount.
This activity can be viewed as a dialogue between Module and handler.
If a RetryCount is NOT passed to the handler then the Module is saying
"I cannot retry this so don't bother asking for a Retry". If a RetryCount
IS passed to the handler then the Module is saying "I can retry this for
you if you want me to". The value of the RetryCount gives the number of
failed retries so far attempted (initially zero).
A call tree might look like:
--> DBperl Function called
Switch
Module [Module detects retryable event]
Event_Handler(..., 'RetryCount', 0) [responds 'Retry']
Module [Module retries but fails again]
Event_Handler(..., 'RetryCount', 1) [responds 'Retry']
Module [succeeds and returns via Switch]
Switch
<-- DBperl Function returns
The application has no (direct) visibility of this activity.
Note that there is no mechanism to define a maximum retry count because
it's the users own event handler that is controlling the retries. It can
stop retrying whenever it likes and for whatever reasons it likes (for
example, "retry as many times as possible within one minute").
Example of handler function return code:
return ('Abort', 1) if ($params{'RetryCount'} > 3);
return ('Retry'); if (defined($params{'RetryCount'});
return undef; # else default behaviour if I can't retry
4.4 DBperl Generic Event Handler Function
---------------------------------------------------------------------------
This subsection lists the source code for the DBperl generic event handler
function supplied in the DBperl library. This function is not installed as
a handler by default. It must be explicitly installed by an application.
! this should be expanded...
sub db'generic_event_handler{
local($event_type, $function_name, $handle, %params) = @_;
local(@p_list, $p_name, $p_value)=(''); # for processing %params
# <do lots of &db'getvalue calls to gather info about $handle>
# build list of name=value strings for each item in %params
while(($p_name, $p_value) = each(%params)){
push(@p_list, "$p_name='$p_value'");
}
# print a reasonably generic event message
print "$event_type event in $function_name",
join(', ','',@p_list),"\n";
# retry twice if possible else request default behaviour
return ('Retry') if (defined($params{'RetryCount'})
&& $params{'RetryCount'} < 2);
return undef; # request default behaviour for this event
}
End of DBperl API Section 4.
===========================================================================
5. THE DBPERL SWITCH AND MODULES
===========================================================================
(This section was last modified on $Date: 1994/05/02 14:02:39 $
is currently at $Revision: 5.0 $ and is nearly stable.)
5.1 Introduction
---------------------------------------------------------------------------
Recall the diagram from section 2.1:
|<-- Scope of DBperl --->|
.-. .-------------. .-------------.
.------. | |---| XYZ Module |---| XYZ Engine |
|Perl | |S| `-------------' `-------------'
|script| |A| |w| .-------------. .-------------.
|using |--|P|--|i|---|Oracle Module|---|Oracle Engine|
|DBperl| |I| |t| `-------------' `-------------'
| API | |c|...
|funcs | |h|... Other modules
`------' | |...
`-'
The Switch is at the heart of DBperl. It provides the DBperl API and
re-directs the DBperl function calls to the appropriate Module for
actual execution. The Switch is also responsible for the dynamic
loading of Modules, error checking/handling and other general duties.
Note that it is not necessary to understand the contents of this
section of the DBperl API in order to be able to write DBperl
applications. This section deals with deeper issues that should only
be of interest to advanced users and the curious.
5.2 Switch Variables
---------------------------------------------------------------------------
5.2.1 $db'version
The version number of the DBperl interface specification (e.g., 1.1)
Note that this value is *not* the version of any software actually
being used. It only defines the version of the DBperl *specification*
that the software claims to implement.
This value can be used to ensure that the DBperl being used to execute
an application is recent enough to have all the required features. This
is similar to the perl $] special variable.
The &db'getvalue($modh, 'ModuleVersion') function can be used to find
the version of a particular Module. To find the version of the Switch
software use &db'getvalue('switch', 'ModuleVersion').
Also see the $db'attribution variable below.
5.2.2 $db'attribution
The attribution strings for DBperl, the Switch and all the loaded
Modules.
Attributions are similar to the output of perl -v and would typically
include: author, copyright notice, compile time options and revision
information (e.g., version number, patch level, release date etc).
Would typically be used as: DBperl -e "print \$db'attribution".
5.2.3 $db'last_func
The name of the last DBperl function called. Also see $db'last_modh
below.
5.2.4 $db'last_handle
The handle passed to the last DBperl function called. Also see
$db'last_modh below.
5.2.5 $db'last_modh
The handle of the last module invoked by the Switch to implement the last
function called.
If $db'errno is set, then $db'last_modh corresponds to the module that
recorded the error in $db'errno. Note that errors detected by the
Switch (e.g. invalid handle) result in $db'last_modh being set the
handle of the notional Switch Module and $db'last_handle being set to
undef.
These last_* variables would typically only be of use in sophisticated
multi-database applications or generic library functions.
5.2.6 $ENV{DBPERL_PATH}
The colon separated path used by the DBperl Switch when searching for
modules to dynamically link/load. Defaults to the value of @INC.
5.2.7 $ENV{DBPERL_AUTOLOAD}
Defines dynamically linked modules to be pre-loaded by the DBperl
Switch on startup and precedence for activation.
The full specification for DBPERL_AUTOLOAD will not be defined until
a DBperl switch which supports autoloading is being implemented.
5.2.8 $ENV{DBPERL_MODULE}
The default Module name to use if no module parameter supplied to the
&db'connect function. (Also used if an empty $modh is passed to any
function. See below.)
5.3 Switch Functions
---------------------------------------------------------------------------
These functions only exist in the Switch and not in any Modules.
5.3.1 modules
@ary = &db'modules();
Returns an array of names of all the installed modules.
E.g., ('oracle', 'xbase', 'informix'). The notional 'switch'
module is not included in the list.
DBperl does not have a function that lists modules which could be
dynamically loaded (if supported) from external files. Such a
function may be added later.
5.3.2 install
$modh = &db'install($module_name [, %install_attributes ] );
$module_name -- the name of the module to install
%install_attributes -- optional installation attributes
$modh -- returned module handles or undef
Install and initialize a named module and make it available for use.
This function is normally never called directly by a DBperl
application. Typically all module loading and initialization is
performed automatically and transparently by the Switch either on
start-up (DBPERL_AUTOLOAD) or when the application calls &db'connect.
5.3.3 call_func
$rv | @ary = &db'call_func($any_handle, $function [, @params]);
$any_handle
$function -- a module specific function name
@params -- function specific parameters
$rv|@ary -- Result dependent on the function specified.
Executes the named function of the module identified by $any_handle
(passing it $any_handle and @params) and returns the result thereof.
This is the recommended method for calling private module functions
via the DBperl specification.
In order to prevent name space clashes with future versions of the
DBperl API, non-DBperl standard function names (private functions)
must begin with an underscore.
Examples
# call module private function to invoke stored procedure
$rv = &db'call_func($dbh, '_proc', $proc_name, @proc_args);
# call module private function to fetch previous row
@ary = &db'call_func($sh, '_fetch_prev');
5.4 Switch Basics
---------------------------------------------------------------------------
5.4.1 DBperl Modules
A DBperl Module typically enables access to one or more types of
database, e.g., the 'oracle' module implements an interface to Oracle
databases.
The DBperl Switch manages one or more modules and provides Perl
applications with a single consistent interface to them. The Switch
ensures that the correct module handles each request.
Future versions of the Switch are planned to support dynamic loading of
Modules automatically on demand. This specification assumes that such
functionality already exists.
Module names are always lowercase and globally unique. To avoid clashes
the DBperl API appendix will list (register) all known module names.
5.4.2 DBperl Handles
A DBperl handle is an opaque scalar value. The actual contents of the
handle are private to the Switch and the Module that provided the
handle. Applications should not attempt to examine or print the
contents of a DBperl handle.
Recall that DBperl defines three types of handle:
$modh -- a handle for an instance of a loaded Module
$dbh -- a handle for an instance of a database session
$sh -- a handle for a prepared statement within a session
Module handles exist to provide an unambiguous reference to a specific
installed module. Few applications will ever need to deal with module
handles directly, applications typically deal only with database and
statement handles.
In Perl 5, DBperl handles are likely to be blessed with Object Oriented
magic to give them special powers. Full details must await a Perl 5
implementation of DBperl.
5.4.3 Function Call Routing
In order for the Switch to `route' a function call to the correct
module it must be able to determine which module should handle the call.
Nearly all DBperl functions take a handle as their first parameter.
The Switch is always able to instantly determine the Module that owns
any given type of handle and uses this ability to rapidly invoke the
appropriate function in the correct Module.
5.4.4 Automatic Handle Promotions
Each Module function has a range of handles that it's willing to accept
from the Switch, e.g., &db'disconnect() will accept $dbh or $modh.
If the handle supplied by the application is too specific, e.g., a $sh
where a $dbh is required, the Switch will `promote' the handle upwards
(from $sh -> $dbh -> $modh) until within the range the function will
accept.
Handle promotions generate warnings if the perl -w flag is in effect.
5.5 Module Selection
---------------------------------------------------------------------------
5.5.1 Introduction
This section describes how the Switch selects which module to use when
an application calls the &db'connect function.
Whenever the switch requires a handle it will accept a name. This can
either be the name of a module or the name of a type of database. The
Switch will automatically try to convert the name into a corresponding
module handle using the methods described below.
Names that begin with a lowercase letter are Module names (see 5.5.2
below). Names that begin with a capital letter are treated as Database
Type names (see 5.5.3 below). Names that do not begin with a letter
generate an error.
An empty name is equivalent to the value of $ENV{'DBPERL_MODULE'}.
5.5.2 Using Module Names
If the supplied name begins with a lowercase letter then the Switch
assumes that it is an explicit module name.
The Switch checks to see if it already has a module with that name
loaded. If it does then its handle is used.
If no module with that name is already loaded then the Switch will
attempt to dynamically load a module with that name (if dynamic loading
is supported). See section 5.6 below.
The names of loaded Modules are kept on a list and checked in order. By
default newly installed modules are added to the end of the list.
Note that module selection by name is much slower than using module
handles. Also, a module name cannot identify a single instance of a
module if that module has been (dynamically) loaded more than once
(very unusual but possible). The Switch will simply pick the first
module on its list with that name. For these reasons widespread use of
module names is discouraged.
5.5.3 Using Database Type Names
If the supplied name begins with a capital letter then the Switch
assumes that it is a `database type name' (dbtype for short).
As with a module name the DBperl Switch will automatically convert the
name into a module handle, however the method it uses is different.
The Switch will `ask' each installed module in turn if it wants to
`support' this database type, the handle of the first module to accept
is returned. If no installed module accepts then the dbtype name is
converted to lowercase and treated as a module name. See 5.5.1 above.
Database type names are a simple but powerful addition to DBperl. They
open up the association between applications and modules. For example:
When you look a little into the future (say late 1994) you can
imagine a single DBperl module 'sqlcli' implemented using the ISO
Standard SQL Call Level Interface specification. This module would be
able to support a *multitude* of database types. It would accept
requests to connect to DbTypes of 'Oracle', 'Ingres', 'Informix' etc.
The dbtype mechanism allows special purpose modules to be `layered'
in between the application and the module that actually does the
work. Consider a debugging or logging module layered above a
database module. In this case the layered module would pass all
parameters and return values to and fro but would write trace
information to a log file.
See section 5.7 for further examples of layered modules.
A dbtype name can be used wherever a module name or a handle is
required. DbType names should always begin with a capital letter,
this distinguishes them from Module names which are always lowercase.
In order to gain maximum benefit from this scheme the recommended
practice is that modules be called 'ingres', 'oracle', 'sybase' etc and
that application code be written (or $DBPERL_MODULE defined) to use the
corresponding dbtype name, e.g., 'Ingres', 'Oracle', 'Sybase'.
If you DO care which specific module you use then you ask for it by
MODULE name. If you DON'T care, you ask for any suitable module by
using a DBTYPE name. E.g., If you specifically want "Dbase III" you
would ask for the module by name (say) 'dbase3'. If you don't really
care (and want to be more portable) you would ask for a module by
dbtype (say) 'Xbase'.
5.6 Module Dynamic Loading
---------------------------------------------------------------------------
5.6.1 Introduction
It is anticipated that the DBperl Switch will support the dynamic
loading of Modules. These modules may be implemented either as Perl
scripts or as dynamically linkable binary object files.
Any attempt to refer to a Module name which is not loaded will cause
the Switch to automatically attempt to find, load and initialize that
module.
5.6.2 Search Method
When searching for a external module to dynamically load the Switch
will search along a defined path which defaults to @INC (PERLLIB).
This path could be set via an environment variable DBPERL_PATH.
File names for modules: dbp*.pl for modules implemented in perl and
dbp*.o (maybe .so as well) for dynamically linkable object code.
5.6.3 Automatic Loading on Startup
DBperl provides a mechanism to automatically load modules on
startup.
To do this the user can define the DBPERL_AUTOLOAD environment variable
to either be a string that specifies what to load or is the name of a
file that contains a specification (perhaps ~/.dbperl). This will be
fully defined in a later version of this specification.
Remember that the dbtype mechanism only works for modules that are
already installed and queries them in a specific order. Using the
DBPERL_AUTOLOAD mechanism the user can force desired modules to appear
earlier in the list and hence be used in preference to others.
5.6.4 Example
Consider an application calling &db'connect and using the database type
name 'Xbase' for the module parameter. (Xbase is the name of the flat-file
database standard based on Dbase and supported by Paradox, FoxPro etc.)
Assume that you don't have any modules that accept the Xbase dbtype
statically linked into your DBperl. In this case the 'Xbase' dbtype
will fail and be converted to the module name 'xbase'. The Switch will
then try to load a module called 'xbase' and fail if one is not found.
Now, lets assume that you don't have a loadable module called xbase but
you do have one called 'dbase3' that will accept requests for the
'Xbase' dbtype. You have two choices, either copy the dbase3 module
file and call it dbpxbase.o or force the dbase3 module to be loaded
before the request for 'Xbase' is executed (using DBPERL_AUTOLOAD for
example).
5.7 Module Layering
---------------------------------------------------------------------------
5.7.1 Introduction
It is possible for one module to `bounce' calls on to another module.
In this way modules can be `layered' one on top of another.
For example, a `logging' module could pass all DBperl calls on to another
module unchanged but keep a log file of all parameters and return values.
It is also possible for a layered module to modify the apparent
behaviour of the underlying module. For example, if an ingres-to-oracle
translation module existed it could be layered above the oracle module
to allow an Ingres SQL specific application to run unaltered on an
Oracle database.
5.7.2 Examples
The following examples consider what can be done with callbacks
into perl packages.
Provide stubs that feed dummy/test data
---------------------------------------
_____________ ____________
Perl | Application || Perl Code |
---- --v--------------^-----------
C | \...Switch.../ |
---------------------------
Provide remote network access to a non-networked database
---------------------------------------------------------
_____________ _________ _______________
Perl | Application || Package | <== socket ==> | Slave Client |
---- --v--------------^-------- --v--------------
C | `... Switch ...^ | | `. Switch .. |
|________________________| |____________v__|
------------v--
| Database I/F |
---------------
Provide Perl Layer(s) for a multitude of uses
---------------------------------------------
_____________ ____________
Perl | Application || Perl Layer |
---- --v--------------^--------v--
C | \............/ | |
| ......................./ |
-v-------------------------
-v-------------
| Database I/F |
---------------
The possible uses of this sort of layering are endless, here's one:
Provide SQL Portability through SQL (etc) Translation
-----------------------------------------------------
_____________ _____________________
| Ingres || Ingres to Oracle |
Perl | Application || Translation Package |
---- --v--------------^----------------v---
C | `..............^ | |
| ................................' |
-v----------------------------------
-v-----------
| Oracle I/F |
-------------
Implement SQL Interface to Non-SQL Databases
--------------------------------------------
Recently the source code to an RDBMS with SQL support was posted to the
net, it was written entirely using /bin/sh and the unix utilities cut,
paste and join! Given that Perl database layers can be stacked upon one
another it should be possible to have a generic SQL interpreter in one layer
that could use other (non-sql) layers to gather the raw data.
_____________ _________________
| SQL || SQL Interpreter |
Perl | Application || in perl |
---- --v--------------^------------v---
C | `..............^ | |
| ............................' |
-v------------------------------
-v--------------------------------------
| Non-Query Language Module (e.g. xbase) |
----------------------------------------
End of DBperl API Section 5.
===========================================================================
6. ATTRIBUTE NAMES AND VALUES
===========================================================================
(This section was last modified on $Date: 1994/05/02 14:02:39 $
is currently at $Revision: 5.0 $ and is nearly stable.)
6.1 Introduction
---------------------------------------------------------------------------
Attributes provide an extra means of communication between an
application and DBperl modules.
They are typically used by an application to get extra information
about a DBperl entity such as a database handle or cursor. They can
also be used by an application to alter the default behaviour of DBperl
modules or database engines.
6.2 Attribute Functions
---------------------------------------------------------------------------
6.2.1 getvalue
$rv | @ary = &db'getvalue($handle, $attribute_name);
$handle -- any handle
$attribute_name -- the name of the attribute
Returns the current value of the named attribute.
The return value may be a scalar or an array depending on the type of
the attribute. Returns undefined if the attribute is not known or
not valid for the handle type given (e.g., a statement level
attribute with a module handle).
6.2.2 setvalue
$rv | @ary = &db'setvalue($handle, $attribute_name, @values);
$handle -- any handle
$attribute_name -- the name of the attribute
@values -- scalar or array to be assigned to the attribute
Sets the value of the named attribute.
Returns the previous value of the attribute to allow later
resetting. The return value may be a scalar or an array depending on
the type of the attribute. Returns undefined if the attribute is not
known or not valid for the handle type given (e.g., a statement level
attribute with a module handle).
If an invalid value is given then an error event is raised (see
section 4.2.2), the value remains unchanged and the current value is
returned.
6.2.3 Using Attributes With Other Functions
A few DBperl functions allow attribute-value pairs to be passed as optional
parameters. These functions include connect(), prepare() and install().
Generally the attributes are applied to the handle being created by the
function.
It is important to note that attributes not known by the module being
used may be ignored. If you wish to be told whenever an attribute is
being ignored you can install an event handler to either tell you or to
force an error. See section 4.
6.3 Attribute Names
---------------------------------------------------------------------------
Attribute names share a single namespace so the DBperl standard defines
how attribute names must be created so as to indicate their meaning and
scope of effect.
The letter case of attribute names is used to denote who specified the
semantics (meaning) of the attribute and it's values:
6.3.1 UPPERCASE_NAMES
These attributes have the meaning and values that are assigned to them
by various standards. The standards include X/Open and SQL92.
6.3.2 MixedcaseNames
These attributes have the meaning and values that are assigned to them
by this DBperl specification. New 'DBperl standard' attributes will be
defined by the 'DBperl standard committee' :-) via the perldb-interest
mailing list.
6.3.3 lowercase_names
These attributes have the meaning and values that are assigned to them
by the implementor of the module being used. A module implementor is
free to add any lowercase attribute names at any time. Module specific
attribute names must begin with the name of the module, e.g., oracle_*,
ingres_*.
6.3.4 Attribute Scope
An attribute has a scope of effect: some attributes apply to a module
as a whole and not to individual database sessions, other attributes
apply to a particular database session while others apply to an
individual cursor.
To reduce the risk of confusion, DBperl attribute names generally
consist of at least two words with the first word indicating the scope
of the attribute. For example: ModuleVersion, DbName, CursorName etc.
Attributes such as ROW_LENGTH, which are defined by external
standards, do not follow this naming scheme. However their meaning is
well defined and should never be ambiguous.
Not many module attributes exist. Many attributes that you may think of
as module attributes are only available for a database session handle.
This means that you will need to connect to a database before being
able to determine many attributes of the engine being used.
This is an important design decision. With time the DBperl modules will
become more generic. Eventually a single X/Open standards based module
will be able to connect to many types of database server (ingres, oracle,
sybase etc). In this case the module itself will not have any knowledge
about a particular type of server until it has connected to it.
6.3.5 Attribute Values
Boolean values should be set to 0 for false and 1 for true. Other
non-zero values may work but should not be used in order to allow for
future use.
6.3.6 Attribute Listing Legend
The following sections list the attributes currently defined by DBperl.
Each section lists the attributes for a given scope (Module, Database etc)
and the handle types that can be used ($modh, $dbh etc).
Each attribute name is followed by a series of one or more flags that
indicate the data type of the attribute value and whether the attribute is
modifiable:
S -- String type
I -- Integer type
B -- Boolean type (0 or 1)
H -- Handle type
M -- Modifyable via &db'setvalue()
6.4 Module Attributes ($modh, $dbh, $sh)
---------------------------------------------------------------------------
6.4.1 ModuleName S
Name of module that created the supplied handle.
6.4.2 ModuleAttribution S
Attribution string for the module that created the supplied handle.
6.4.3 ModuleHandle H
A handle to the module that created the supplied handle (typically a
database or statement handle).
6.5 Database Attributes ($dbh, $sh)
---------------------------------------------------------------------------
6.5.1 IDENTIFIER_LENGTH I
Returns the maximum number of characters for a user defined name.
6.5.2 IDENTIFIER_CASE S
Returns either 'UPPER', 'LOWER' or 'MIXED'.
6.5.3 ROW_LENGTH I
Returns maximum byte width of a row.
6.5.4 DbTimeZoneType S
This is a read-only attribute that attempts to describe how the
database server deals with timezones. DBperl does not use the value
itself. Returns one of the following values:
GMT = always returns the time as true GMT/UTC.
LocalServer = always returns the time as local time at the server.
LocalClient = always returns the time as local time at the client.
Transparent = does not consider timezones at all, e.g. the time value
returned is exactly the value originally inserted.
6.5.5 DbReadCache I,M
The number of rows that the module will pre-fetch and cache when
fetching from read-only cursors.
6.5.6 DbNumRows I
Returns the number of rows affected by the last operation on $dbh.
6.5.7 DbHandle H
A handle to the database associated with the supplied handle (typically
a statement handle).
! Others will be defined here in the light of experience.
6.6 Statement Attributes ($sh)
---------------------------------------------------------------------------
! To be defined in the light of experience.
6.7 Module Specific Attributes
---------------------------------------------------------------------------
Module attributes will be defined in the documentation that accompanies
the modules being used.
6.8 Switch Specific Attributes
---------------------------------------------------------------------------
These attributes only apply to the internal Switch pseudo-module. They
provide a means of communicating with DBperl directly.
When using these attributes you can avoid the need to get a handle by
using the module name (see section 5.5) , e.g., &db'getvalue('switch',...).
The name 'dbperl' may be used as an alias for 'switch'.
Generally these attributes are related to services that the Switch
provides for the other modules. These include holding global attributes
and providing debugging trace files etc.
6.8.1 DBperlPortable B,M
A global flag used by the switch and other modules to warn about
non-portable DBperl usage. See the appendix for portability issues.
6.8.2 DBperlTrace S,M
Defines DBperl debug trace level. Specification to be defined.
6.8.3 DBperlLog S,M
Specifies a filename to which DBperlTrace information should be written.
End of DBperl API Section 6.
===========================================================================
7. DATA TYPE CONVERSION FUNCTIONS
===========================================================================
(This section was last modified on $Date: 1994/05/02 14:02:39 $
is currently at $Revision: 5.0 $ and is nearly stable.)
7.1 Introduction
---------------------------------------------------------------------------
Currently DBperl does not try to address a wide range of data type issues.
Only sql string formatting and very basic date/time issues are covered.
7.2 String Formatting Functions
---------------------------------------------------------------------------
7.2.1 quote
$sqlstr = &db'quote($handle, $str);
$handle
$str -- string to be quoted as an entity
$sqlstr -- returned fully quoted sql string literal
Returns the input string suitably quoted for use as a string constant
in an SQL statement for the engine implied by $handle. This function
adds the required type of surrounding quotes and will also
escape/quote any internal characters as required.
Using literal string constants may allow a query optimizer to
generate a better query plan than would be possible if a placeholder
was used. It can also be used to reduce the number of parameters that
need to be bound using &db'execute() thus improving efficiency.
Examples:
Input string: don't
Output (oracle): 'don''t'
Output (ingres): 'don'+X'27+'t'
7.3 Date & Time Functions
---------------------------------------------------------------------------
7.3.1 Notation & Nomenclature
udt -- Unix date/time
Expressed as seconds since 1 January 1970. ALWAYS GMT/UTC.
ndt -- Native date/time
The natural datetime format of a given database (indicated by
$handle in functions). This is generally the format used by the
database when a datetime field is selected without any formatting
applied to it.
For example:
Ingres "select date('now')" => "22-Apr-1994 15:45:02"
Oracle "select ?" => "22-Apr-94 15:45:02"
The time component is optional and defaults to 00:00:00.
7.3.2 ndt2udt
$udt = &db'ndt2udt($handle, $ndt [, $local]);
$handle
$ndt -- a native datetime string
$local -- boolean, 0=ntd is GMT, 1=ntd is in local timezone
$udt -- a Unix datetime integer (GMT)
Returns a Unix datetime integer corresponding to the native date
time string value supplied.
If $local is 0 then $ntd is assumed to be in GMT timezone. If $local
is 1 then $ntd is assumed to be in the local timezone. If $local is
undefined then it is assumed to have whatever value is appropriate
for default format ntd's in the module being used, e.g., 1 for Ingres.
7.3.3 udt2ndt
$ndt = &db'udt2ndt($handle, $udt [, $local]);
$handle
$udt -- a Unix datetime integer (GMT)
$local -- boolean, 0=return GMT ntd, 1=return localtime ntd
$ndt -- a native datetime string
Returns a native datetime format string corresponding to the unix
datetime value supplied.
If $local is 0 then $ntd is returned as a GMT timezone value (also,
if the database allows it, ' GMT' will be appended to the value).
If $local is 1 then $ntd is returned as a local timezone value. If
$local is undefined then it is assumed to have whatever value is
appropriate for default format ntd's in the module being used, e.g.,
1 for Ingres.
Examples:
&db'udt2ndt($h, time, 0) => "22-Apr-1994 14:45:02 GMT"
&db'udt2ndt($h, time, 1) => "22-Apr-1994 15:45:02"
End of DBperl API Section 7.
===========================================================================
8. DATA DICTIONARY FUNCTIONS
===========================================================================
(This section was last modified on $Date: 1994/05/02 14:02:39 $
is currently at $Revision: 5.0 $ and is nearly stable.)
8.1 Introduction
---------------------------------------------------------------------------
A data dictionary holds detailed information about objects within a
database including the tables and views it contains and the columns
within those tables and views.
The DBperl specification defines three core data dictionary functions
that provide a simple but effective way to query the data dictionary of
a given database. Other utility functions may be added later.
These data dictionary functions and the values they return are based on
the X/Open SQL standard description of the INFORMATION_SCHEMA. This
defines a standard and hence portable way of representing data
dictionary information. Generally DBperl Module implementors will be
able to implement these functions by executing an SQL query on that
databases own proprietary data dictionary tables.
The functions are defined in such a way that all available attributes
can be returned. This allows for both portable applications that will
only use the standard attribute names (in uppercase and mixed case) and
non-portable applications that can use proprietary module-specific
attribute names (in lowercase).
8.2 Data Dictionary Core Functions
---------------------------------------------------------------------------
8.2.1 info_table_names
@ary = &db'info_table_names($dbh);
$dbh
@ary -- returned list of names of table and view names.
Return a list of table and view names. This will contain the names of
all the tables and views in the database to which the user has access.
It may also contain some table and view names to which the user does
not have access.
For databases that use schema names each returned table name will be
prefixed by its schema name, e.g., "SCHEMA.TABLE".
8.2.2 info_table
%attr = &db'info_table($dbh, $table_name);
$dbh
$table_name -- name of table in database to be reported upon.
%attr -- returned associative array of table attributes.
Look up data dictionary information about the specified table. For
databases that require a schema name it should be included in
$table_name, e.g., $table_name = "$schema.$table"
Associative array keys may include:
TABLE_SCHEMA -- The name of the schema containing TABLE_NAME.
TABLE_NAME -- The name of this table of view.
TABLE_TYPE -- Either 'BASE TABLE' or 'VIEW'.
REMARKS -- Descriptive information about the table.
For full definitions of these attributes, consult the X/Open standard.
See appendix for details of Module specific attributes.
8.2.3 info_col_names
@ary = &db'info_col_names($dbh, $table_name);
$dbh
@ary -- returned list of column names.
Return a list of column names for the specified table or view. For
databases that require a schema name it should be included in
$table_name, e.g., $table_name = "$schema.$table"
8.2.4 info_col
%attr = &db'info_col($dbh, $table_name, $col_name);
$dbh
$table_name -- name of table in database containing $col_name.
$col_name -- name of column in table $table_name.
%attr -- returned associative array of column attributes.
Look up data dictionary information about the specified column.
For databases that require a schema name it should be included
in $table_name, e.g., $table_name = "$schema.$table"
Associative array keys may include
TABLE_SCHEMA -- The name of the schema containing TABLE_NAME.
TABLE_NAME -- The name of this table of view.
COLUMN_NAME -- The name of the column.
DATA_TYPE -- Identifies the type (string, see below).
CHAR_MAX_LENGTH -- Max length if col is a character DATA_TYPE.
NUMERIC_PRECISION -- ...
NUMERIC_PREC_RADIX -- ...
NUMERIC_SCALE -- ...
NULLABLE -- Either 'NO' or 'YES'.
REMARKS -- Descriptive information about the column.
For full definitions of these attributes, consult the X/Open standard.
See appendix for details of Module specific attributes.
Standard DATA_TYPE values:
'CHARACTER', 'CHARACTER VARYING', 'DECIMAL', 'FLOAT',
'DOUBLE PRECISION', 'INTEGER', 'NUMERIC', 'REAL', 'SMALLINT',
'BIT', 'BIT VARYING', 'DATE', 'TIME', 'TIMESTAMP'.
End of DBperl API Section 8.
===========================================================================
9. EXAMPLES
===========================================================================
(This section was last modified on $Date: 1994/05/02 14:02:39 $
is currently at $Revision: 5.0 $ and is out of date and NOT STABLE)
This section is very incomplete and inaccurate. It will not be completed
for issue 0.5 because issue 0.6 will change much of what would be
written here.
9.1 Simple SELECT
---------------------------------------------------------------------------
$dbh = &db_connect($database, $name, $password) || &Abort;
$sh = &db_prepare($dbh, "select A, B, C from tablename");
while(@ary = &db_fetch($sh)) {
print @ary;
}
&db_finish($sh);
&db_disconnect($dbh);
9.2 Simple INSERT
---------------------------------------------------------------------------
The return value may be checked for errors.
&db_execute($dbh, "insert into table (A, B, C) values $a, $b, $c")
|| warn "INSERT failed: $db_error\n$db_errstr\n";
9.3 Iterative insert from flatfile
---------------------------------------------------------------------------
$sh = &db_prepare($dbh,
"insert into table tablename(col1, col2, col3) values (?, ?, ?)");
open(INFILE, "<$infile"); # data file of comma delimited ASCII
while(<INFILE>) {
&db_execute(&sqlh, split(/,/)) || &Abort;
}
&db_finish($sh);
9.4 Creating a temporary table
---------------------------------------------------------------------------
&db_do($dbh, "create table TMP (col1 char(12), col2 double)")
|| &Abort;
9.5 Error handling
---------------------------------------------------------------------------
Instead of doing something like:
$state = $closed;
$dbh = &db_connect(..) || &Abort("Didn't open.");
$state = $open;
$sh = &db_do($dbh, "select ...") || &Abort("Didn't open.")
...
$rc = &db_commit($dbh) || &Abort("Couldn't commit.")
...
sub Abort {
print "various warnings...";
if($state == $open) {
&db_rollback($dbh);
&db_disconnect($dbh);
}
}
The event handler allows you to do:
...
$dbh = &db_connect('foo', 'bar',, 'Handler','errhandler');
$sh = &db_execute($dbh, "select ...");
...
$sh = &db_commit($dbh);
...
sub errhandler {
local($event_name, $function_name, $handle, %params) = @_;
...
}
9.6 Bind parameter handling
---------------------------------------------------------------------------
$sh = &db_prepare("select a from x where y = ?");
while(...) {
&db_execute($sh, $conditional_value_1);
while(@_ = &db_fetch()) {
...
}
}
&db_close($sh);
End of DBperl API Section 9.
===========================================================================
10 APPENDICES
===========================================================================
(This section was last modified on $Date: 1994/05/02 14:45:40 $
is currently at $Revision: 5.2 $ and is NOT STABLE.)
10.1 Function and Variable Summary
---------------------------------------------------------------------------
3. DATABASE INTERACTION FUNCTIONS
connect $dbh = &db'connect([$database [, $username [, $password
[, $module [, %attr]]]]]);
disconnect $rc = &db'disconnect([$handle]);
prepare $sh = &db'prepare($dbh, $statement [, %attr]);
execute $rc = &db'execute($sh [, @bind_values]);
titles @ary | $rv = &db'titles($sh);
fetch @ary = &db'fetch($sh);
finish $rc = &db'finish($sh);
commit $rc = &db'commit($dbh);
rollback $rc = &db'rollback($dbh, [$savepoint_name]);
savepoint $rc = &db'savepoint($dbh, $savepoint_name);
4. ERROR AND EVENT HANDLING
errno $db'errno
errstr $db'errstr
errstate $rv = &db'errstate($dbh);
errmsg @ary = &db'errmsg($dbh);
handler $rv = &db'handler($dbh, $handler_function);
5. THE DBPERL SWITCH AND MODULES
modules @ary = &db'modules();
install $modh = &db'install($module_name [, %install_attributes ] );
call_func $rv | @ary = &db'call_func($any_handle, $function [, @params]);
6. ATTRIBUTE NAMES AND VALUES
getvalue $rv | @ary = &db'getvalue($handle, $attribute_name);
setvalue $rv | @ary = &db'setvalue($handle, $attribute_name, @values);
7. DATA TYPE CONVERSION FUNCTIONS
quote $sqlstr = &db'quote($handle, $str);
ndt2udt $udt = &db'ndt2udt($handle, $ndt [, $local]);
udt2ndt $ndt = &db'udt2ndt($handle, $udt [, $local]);
8. DATA DICTIONARY FUNCTIONS
info_table_names @ary = &db'info_table_names($dbh);
info_table %attr = &db'info_table($dbh, $table_name);
info_col_names @ary = &db'info_col_names($dbh, $table_name);
info_col %attr = &db'info_col($dbh, $table_name, $col_name);
10.2 Portability
---------------------------------------------------------------------------
! This section will be expanded and refined in the light of experience.
We have to strike a balance between focusing on known engines,
available standards (SQL-92 etc) and unknown or future systems.
If you know that feature X is supported on, say, Ingres, Oracle and
Sybase and you're only going to support your DBperl application on
those platforms then that's fine.
I guess what many of the portability statements in the DBperl
specification are saying is "A DBperl module is not REQUIRED to support
this feature, therefore it may not be supported in all modules".
This is an incomplete list of what may not be portable:
1) Interpretation of error codes/messages etc.
2) Any 'all lowercase' attribute name for &db'[gs]etvalue() etc.
3) All but the most trivial SQL strings should be regarded as suspect.
4) Any non-trivial data type related issues (money, dates, intervals).
5) Any use of &db'exec()
6) Savepoints
7) ... ?
10.2.1 Detecting and Declaring Non-Portability
Using the 'Portable' module attribute:
- The module attribute 'Portable' defaults to true for all modules.
- If the module attribute 'Portable' is true and the application
invokes a non portable action etc then the module will issue
a warning message.
- The application developer can either choose to modify the code
to make it portable or to disable the warnings by adding the
code: &db'setvalue($dbh, 'Portable', 0);
- By explicitly setting 'Portable' to false the application
developer is admitting and documenting that it's not portable.
- Anyone getting an application from the network can tell that
it's NOT portable if it has that code in it.
- Of course, if it does not have that code then it's not actually
guaranteed to be portable but you have a better chance.
Boolean Attribute Values
As for the values, I'd have to agree that '0' is not ideal.
In another message I've recommended that 1 and 0 be used for now to
allow for meanings to be attached to other values later. This is still
a valid point but I think the "TRUE" and "FALSE" would also be valuable.
TRUE and FALSE would also be handy for setting other boolean attributes.
But consider:
&db_setvalue($dbh, $boolean_attrib, 'TRUE');
print $value if ($value = &db_getvalue($dbh, $boolean_attrib));
&db_setvalue($dbh, $boolean_attrib, 'FALSE');
print $value unless ($value = &db_getvalue($dbh, $boolean_attrib));
What should/would be printed?
We must translate FALSE to 0 but should we also translate TRUE to 1?
I'd say yes. 0 and 1 are the natural perl boolean values and it
simplifies module implementation (use of ints and bit fields etc).
One last issue, what about applications that try to use strings/numbers
other than 0/1/TRUE/FALSE to set a boolean attribute?
10.3 Ideas for Utilities and Packages
---------------------------------------------------------------------
Lee McLoughlin and Tim Bunce
> } 5. Is there anything in one of the other database interfaces that you
> } would like to have in yours?
> An automatic i/o generator. Something that given a table name generates
> a format statment for output and a read routine for input.
An interesting thought. That would make a good utility library function.
> } 6. Is there any additional functionality that you would like to have?
> I'd like to be able to say something like:
> lookup( table, select_statement, assoc_arrays )
> and have the assoc arrays filled in for me with the result of the select
> statement.
So far an @ary=&db_fetchall($sqh, $separator); is as close as we have got.
This would do a push(@ary, join($separator, @field_values)) for each row
and return the array. I'd like to see a similar function for associative
arrays, but at this stage it might have just be penciled in for version 2.
A key issue (excuse the pun) is how to identify the key(s) to be
used for the array, perhaps:
@keys= (1, 2);
%ary = &db_fetch_assoc($sqh, $separator, @keys);
1) @keys indicates which fields are to be used to form the assoc key
2) Values of composite key fields are joined using $,
3) $separator is used to join the data field values
4) Assumes keys are unique else earlier rows are lost.
5) Are the key field values also stored in the data?
&db_fetch_assoc() could join &db_fetchall() as a library function.
Query-By-Forms
Something that takes a table or view name, turns it into a query page on
screen, the user fills in the blanks (by answering questions I guess) and
then returns a select statment.
A very interesting project and one I could find a lot of use for. I
might have a shot at it myself once DBperl is real and stable.
Size of: an object, tablespace (or equivalent), etc
Amount of free space left to work with (oracle in tablespace)
Privileges of the user
Efficiency of table storage (size of data stored vs disk space used)
Depth of B-Tree index
Database configuration parameters
e) Do we need functions to control:
autocommit -- on / off
locking -- level=row/page/table, readlocks, timeouts etc
f) Do we need functions to:
call database procedures
return space left in/for the database
---
=============
Apendices
-------------
10.5 Module Implementors Template
10.5.1 Example for Oracle Module
oracle_cache
10.5.2 Example for Ingres Module
-------------
End of DBperl API Section 10.