=head1 NAME

extproc_perl - Oracle Perl Procedure Library

=head1 SYNOPSIS

=head2 FUNCTION SYNTAX

=over 4

select perl('sub1','1','2') from dual;

=back

=head2 PROCEDURE SYNTAX

=over 4

exec perl('sub2','arg1');

=back

=head1 DESCRIPTION

extproc_perl enables Oracle stored procedures and functions to be written
in Perl.  It uses Oracle 8's external procedure interface to create Perl
interpreters on the fly to execute Perl subroutines.  Code is stored in
a central "bootstrap" file that is interpreted after each interpreter is
initialized.  In the current implementation of Oracle external procedures,
the Perl interpreter is persistent for the life of a client session.  This
has the effect of keeping both interpreted code and data in memory for the
life of that particular session.

=head1 MODULES

The Oracle external procedure process and DynaLoader do not work well
together.  In fact, DynaLoader doesn't work at all in this environment.
Therefore, in order to use dynamically loaded modules like Socket, hooks for
each module need to be compiled into the extproc_perl shared library.  This
means that for each module you want to use, you must declare it at build time.
The Makefile.PL file provides gives you the option of declaring these modules.
Note that this restriction does not apply to Perl-only modules, but it's safe
to declare them as well during this process -- they will be ignored.

ExtProc is a module that is statically linked into the extproc_perl object.
It provides several functions that interact with the Oracle database itself.
See the ExtProc(3) manpage for details.

=head1 SPECIAL SUBROUTINES

The following subroutines are reserved for extproc_perl, and can be called
like any other Perl subroutine from Oracle.

=over 4

=item _flush()

Destroys Perl interpreter and all Perl data.  A new interpreter will be started
for the next query.

=item _version()

Reports the version of the currently loaded extproc_perl.

=item _modules()

Returns a space separated list of modules that were requested to be statically
linked into extproc_perl.

=item _codetable(table_name)

Sets or returns the database table queried for code.

=item _error()

Returns the most recent error string.

=item _errno()

Returns the most recent system error message ($! in Perl).

=item _preload()

Force extproc_perl to load code from the database immediately.

=back

=head1 DBI CALLBACKS

If you are using DBD::Oracle with the supplied patch, you can query the calling
database using DBI.  This is a surprisingly fast operation, as there is no
need to establish a new session to the database.  There are three basic steps
to use a DBI callback:

=over 4

1. Fetch the OCI context using the ExtProc module as follows:

=over 4

use ExtProc;
my $context = ExtProc::context;

=back

2. Initialize the callback infrastructure using DBI->connect.  Connect to the
database "extproc" and pass the context from step 1 as the attribute
"ora_context":

=over 4

my $dbh = DBI->connect("dbi:Oracle:extproc", "", "",
    { 'ora_context' => $context } );

=back

3. Query/Update the database using standard DBI methods.

=back

NOTE: External procedure callbacks are stateless, therefore you MUST call
DBI->connect before EACH callback to the database to reestablish the callback
infrastructure.

The following rules apply when using DBI callbacks:

=over 4

=item

* Queries work from both functions and procedures.

=item

* DML statements (insert, update, delete, etc.) only work from procedures.
This is an Oracle restriction.

=item

* DDL statements (create table, drop table, etc.) will not work at all.
Again, an Oracle restriction.

=item

* Due to a bug in the passing of contexts between extproc_perl and DBI, you
MUST call the special _preload subroutine under the following conditions:

=over 4

=item

* You are calling the subroutine as a procedure.

=item

* The procedure to be called is stored in the database.

=item

* The procedure uses DBI to query or modify the database

=item

* The procedure is the first subroutine to be called in the session that
is stored in the database.  If a previous subroutine has been called that
was stored in the database, it is not necessary to call _preload.

=back

These rules are necessary becuase there appears to be some mishandling
of the OCI context between the internal callback to fetch the database code
and the callback in the procedure.  It's a bug for sure, but _preload works
around it for now.  If this really bothers you, store your DBI code in the
bootstrap file.  There is no ETA on a fix for this bug.

=back

=head1 AUTHOR

Jeff Horwitz <jeff@smashing.org>

=head1 SEE ALSO

perl(1), perlembed(1), ExtProc(3)

=cut
