|
|
| |
POE::Component::LaDBI(3) |
User Contributed Perl Documentation |
POE::Component::LaDBI(3) |
POE::Component::LaDBI - POE Component that spawns a perl subprocess to handle
non-blocking access to the DBI API.
use POE::Component::LaDBI;
POE::Component::LaDBI->create( Alias => "ladbi" );
$k->call(ladbi => "register",
OfflineEvent => 'db_offline');
$k->post(ladbi => "connect",
SuccessEvent => "connected",
FailureEvent => "connect_failed",
Args => ["dbi:Pg:dbname=$dbname", $user, $passwd],
UserData => $stuff );
$k->post(ladbi => "disconnect",
SuccessEvent => "disconnected",
FailureEvent => "disconnect_failed",
HandleId => $dbh_id,
UserData => $stuff);
$k->post("ladbi" => "prepare",
SuccessEvent => "prepared",
FailureEvent => "prepare_failed",
HandleId => $dbh_id,
Args => [$sql],
UserData => $stuff);
$k->post("ladbi" => "finish",
SuccessEvent => "finished",
FailureEvent => "finish_failed",
HandleId => $sth_id,
UserData => $stuff);
$k->post("ladbi" => "execute",
SuccessEvent => "executed",
FailureEvent => "execute_failed",
HandleId => $sth_id,
Args => [$bind_val0, $bind_val1, ...],
UserData => $stuff);
$k->post("ladbi" => "rows",
SuccessEvent => "rows_found",
FailureEvent => "rows_failed",
HandleId => $sth_id,
UserData => $stuff);
$k->post("ladbi" => "fetchrow",
SuccessEvent => "row_fetched",
FailureEvent => "fetch_failed",
HandleId => $sth_id,
UserData => $stuff);
$k->post("ladbi" => "fetchrow_hash",
SuccessEvent => "row_fetched",
FailureEvent => "fetch_failed",
HandleId => $sth_id,
UserData => $stuff);
$k->post("ladbi" => "fetchall",
SuccessEvent => "all_fetched",
FailureEvent => "fetchall_failed",
HandleId => $sth_id,
Args => [ @optional_indicies ],
UserData => $stuff);
$k->post("ladbi" => "fetchall_hash",
SuccessEvent => "all_fetched",
FailureEvent => "fetchall_failed",
HandleId => $sth_id,
Args => [ @optional_keys ],
UserData => $stuff);
$k->post("ladbi" => "ping",
SuccessEvent => "check_ping_results",
FailureEvent => "ping_failed",
HandleId => $dbh_id,
UserData => $stuff);
$k->post("ladbi" => "do",
SuccessEvent => "check_do_results",
FailureEvent => "do_failed",
HandleId => $dbh_id,
Args => [ $sql, $attr_hashref, @bind_values ],
UserData => $stuff);
$k->post("ladbi" => "begin_work",
SuccessEvent => "check_transactions_enabled",
FailureEvent => "begin_work_failed",
HandleId => $dbh_id,
UserData => $stuff);
$k->post("ladbi" => "commit",
SuccessEvent => "check_commit",
FailureEvent => "commit_failed",
HandleId => $dbh_id,
UserData => $stuff);
$k->post("ladbi" => "rollback",
SuccessEvent => "check_rollback",
FailureEvent => "rollback_failed",
HandleId => $dbh_id,
UserData => $stuff);
$k->post("ladbi" => "selectall",
SuccessEvent => "check_results",
FailureEvent => "selectall_failed",
HandleId => $dbh_id,
Args => [ $sql ],
UserData => $stuff);
$k->post("ladbi" => "selectall_hash",
SuccessEvent => "check_results",
FailureEvent => "selectall_failed",
HandleId => $dbh_id,
Args => [ $sql, $key_field ],
UserData => $stuff);
$k->post("ladbi" => "selectcol",
SuccessEvent => "check_results",
FailureEvent => "selectcol_failed",
HandleId => $dbh_id,
Args => [ $sql, $attr_hashref ],
UserData => $stuff);
$k->post("ladbi" => "selectrow",
SuccessEvent => "check_results",
FailureEvent => "selectrow_failed",
HandleId => $dbh_id,
Args => [ $sql, $attr_hashref ],
UserData => $stuff);
$k->post("ladbi" => "quote",
SuccessEvent => "use_quote_results",
FailureEvent => "quote_failed",
HandleId => $dbh_id,
Args => [ $value ],
UserData => $stuff);
- "shutdown"
- This tells the LaDBI session to shutdown. It takes two optional arguments,
$cause and $errstr. Both
arguments get posted back to all registered sessions and all outstanding
requests.
For registered sessions the
"OfflineEvent" is called with
$cause and $errstr as
ARG0 and ARG1.
For the outstanding requests
"FailureEvent" is called with
$cause as ARG1 and
$errstr as ARG2.
- "register"
- "register" is a callable as well as
postable event, which registers your session with the LaDBI session. All
the other events you can post to a LaDBI session are request-response
events. "register" allows you to get
events posted back to your session when events occur which effect the
LaDBI session as a whole.
- "OfflineEvent"
- LaDBI can loose it's sub-process (which is actually doing the DBI calls).
In this case an "OfflineEvent" will be
posted to all the client sessions which have registered with this LaDBI
session.
The "OfflineEvent" passes
two arguments back to the client session.
sub db_offline {
my ($cause, $errstr, $alias) = @_[ARG0,ARG1,ARG2];
...
}
The $cause is the either
"SHUTDOWN" or the error string from the
"ErrorEvent" of LaDBI's internal
POE::Wheel::Run .
The $errstr is the value passed to the
"shutdown" event or the
"ARG0" of the internal POE::Wheel::Run
ErrorEvent.
The $alias is the alias of the
"POE::Component::LaDBI" session which
has lost it's subprocess and is shutting downn. This allows the
registered user of the
"POE::Component::LaDBI" session to
track LaDBI sessions from start up to shutdown.
All request events have the same handler. This is because the handler merely
creates a request message and sends it to the perl sub-process which is doing
the actuall DBI calls.
The handler takes the same arguments. Not all events use the all
the argument fields. The arguments fields/keys are:
- "UserData"
- "UserData" is a tool you, the
programmer, may use to correlate LaDBI requests with LaDBI responses. Both
"SuccessEvent" and
"ErrorEvent" handlers will be passed the
"UserData" originally submitted in the
"<$k-"post()>>.
"UserData" must be a scalar.
As a scalar it may be a reference to a hash, or array, or object, or
anything your twisted mind may come up with. Therefor you may use any
data in the scalar to correlate the response to the original request.
Further, you may just use this as a clever way to pass data from the
subroutine where the request was done to the response handler.
- "SuccessEvent"
- All "POE::Component::LaDBI" events
require "SuccessEvent".
The "SuccessEvent" is fired
off if the DBI call returned successfully. "Returning
Successfully" means that no exeption was called (as the
"RaiseError" attribute might cause)
AND that the return value from the DBI call was a
"defined()" value.
However a "SuccessEvent"
does not mean that the SQL completed in what you might commonly
think of as a successful manner. For instance, a SELECT statement might
not return anything. In that case, the returned data will be an empty
array ref. Further, somecalls, while well formed, will return an error
because that feature (like transactions ala
"$dbh->begin_work") are not
implemented in your DBI driver.
The handler for the
"SuccessEvent" is invoked the
following arguments.
sub success_event_handler {
...
my ($handle_id, $datatype, $data, $userdata) = @_[ARG0..ARG3];
...
}
- $handle_id
- This is a cookie representing a DBI handle object. There are two kinds of
DBI handle objects, database handles and statement handles. You use
$handle_id to refer to a DBI handle object you
want to call methods on.
Both, "connect" and
"prepare" generate new handle
ids. The "SuccessEvent" called by the
"connect" handler is passed a new
database handle id. The same is true for
"prepare" but the
$handle_id represents a DBI statement handler
object instead.
All other
"POE::Component::LaDBI" events just
return the $handle_id that was used to invoke
them. For exmple, the "execute" event
requires a statement handle id. When the
"SuccessEvent" for that
"execute" is called it just returns
the same statement handle id.
- $datatype
- The value of $datatype is a string that tells you
what kind of data structure is contained in $data.
$data can be a return code "RC", a
return value "RV", an array ref of array refs "TABLE",
a hash ref of hash refs "NAMED_TABLE", an array ref representing
a row "ROW", a hash ref representing a row
"NAMED_ROW", an array ref representing a column
"COLUMN", or a string meant to represent a part of a SQL
statement "SQL" (like from
"$dbh-"quote()>).
Here is a some rough descriptions of the format of the values
of $datatype:
- "TABLE"
- Data is an array ref of array refs to scalars.
Data = [
[row0col0, row0col1, ...],
[row1col0, row1col1, ...],
...
]
- "NAMED_TABLE"
- This one is odd. See the description of
"selectall_hashref()" in DBI. For
"*_hashref()" calls in DBI you have to
provide the database table field which will be the hash key into this hash
table. The values corresponding to each key is a hash of the rows returned
from the select or fetch. I did not invent this and do not quite
understand why is is this way.
Data = {
row0colX_val => {col0_name => row0_val, col1_name => row0_val, ...},
row1colX_val => {col0_name => row1_val, col1_name => row1_val, ...},
...
}
- "ROW"
- Data is an array ref of scalars.
Data = [ elt0, elt1, ... ]
- "NAMED_ROW"
- Data is an hash ref containing name-value pairs of each data item in the
row; the name is the column name, the value is the column value.
Data = { col0_name => elt0, col1_name => elt1, ... }
- "COLUMN"
-
Data = [ elt0, elt1, ... ]
- "RC"
- Return code is a scalar valude returned from the DBI call.
Data = $rc
- "RV"
- Return Value is a scalar value returned from the DBI call.
Data = $rv
- "SQL"
- This is the data type for the return value from DBI::quote() call.
Data = $sql_string
- $data
- This is scalar value or a reference to a more complex data structure (see
above).
Some calls may return successfully with
$data a defined value, yet
$data may be a "zero-but-true" value.
For example look at the DBI description of
"$dbh->ping".
- $userdata
- The scalar passed into the original request which resulted in this
response. It is entirely programmer defined what is held in this scalar
value.
Hint: you can set a hash ref as the user data,
aka \%stuff_assoc_with_ladbi_call
- "FailureEvent"
- All "POE::Component::LaDBI" events
require "FailureEvent".
When "FailureEvent" is
invoked, it can be for several different reasons.
One common reason is that your SQL is malformed. This one gets
me all the time.
Another common reason is that you did not provide the correct
arguements to the
"POE::Component::LaDBI" event. The
arguements you provide in the "Args"
field are passed literally to the DBI call. Bad arguements, or the wrong
number, will cause the DBI call to throw an execption.
Another reason might be that you are using an invalid
$handle_id. The
$handle_id might be invalid because it is
garbled, or it has be deleted due to a previous use of
"disconnect" or
"finish".
Finnally, it might just be that something bad happened
internally to
"POE::Component::LaDBI::Engine" or
"DBI" itself.
A "FailureEvent" is provided
the following arguments.
sub failure_event {
...
my ($handle_id, $errtype, $errstr, $err, $userdata) =
@_[ARG0..ARG4];
...
}
The argument $handle_id is either
"undef", a statement handle, or a
database handle depending on the type of request which was submitted and
now failed.
The argument $errtype can be
"SHUTDOWN", "ERROR", "EXCEPTION",
"INVALID_REQUEST".
The "$errtype eq
"EXCEPTION"" results from the fact that all the
actual DBI command are wrapped in and "eval
{}" and the $@ checked. In this
case, $errstr is set to
$@ and $err is
undefined.
The "$errtype eq
"ERROR"" results from the fact that the results of
the DBI command is checked for
"undef". Then the appropriate DBI
$DBI::errstr and
$DBI::err are passed back as
$errstr and $err
respectively.
The "$errtype eq
"SHUTDOWN"" results from abnomal termination of
the "POE::Component::LaDBI" session.
$err is set to the cause and
$errstr is set to a string explanation of the
cause. $errstr can be "signal" or a
POE::Wheel::Run operation. And $err is set to
the signal type or wheel operation string value of
$!.
The "$errtype eq
"INVALID_REQUEST"" means that
"POE::Component::LaDBI" failed to
instantiate a
"POE::Component::LaDBI::Request"
object. Hence, nothing was sent to the sub-process running
"POE::Component::LaDBI::Engine" for
execution. $errstr is set to an empty string and
$err is set to undef.
The "$errtype eq
"INVALIE_HANDLE_ID"" means that a
"POE::Component::LaDBI::Request"
object was create and the message sent to the sub-process, but the
"POE::Component::LaDBI::Engine" object
in the sub-process did not have a record of that handle id.
$errstr is set to empty string and
$err is set to undef.
- "HandleId"
- This is either a database handle id, a statement handle id to use, or
"undef" if a DBI handle type is not
required for the LaDBI command.
- "Args"
- This is always an array ref. The array is exact the arguemnts to pass to
the appropriate DBI method. You are required to pass the correct ones,
else you will recieve a "FailureEvent",
probably of "EXCEPTION" type.
use strict;
use warnings;
use POE;
use POE::Component::LaDBI;
my $LADBI_ALIAS = "ladbi";
my $DSN = "dbi:Pg:dbname=test";
my $USER = "dbuser";
my $PASSWD = "secret";
my $SQL = "SELECT * FROM contacts";
POE::Component::LaDBI->create(Alias => $LADBI_ALIAS)
or die "Failed to create a POE::Component::LaDBI session\n";
POE::Session->create
(args => [$DSN, $USER, $PASSWD, $SQL],
inline_states =>
{
_start => sub {
my ($dsn, $user, $passwd, $sql) = @_[ARG0..ARG3];
print STDERR "_start: args=($dsn,$user,$passwd)\n";
$_[HEAP]->{sql} = $sql;
$_[KERNEL]->post($LADBI_ALIAS => "connect",
SuccessEvent => "selectall",
FailureEvent => "dberror",
Args => [ $dsn, $user, $passwd ]);
},
_stop => sub {
print STDERR "_stop: client session ended.\n";
},
shutdown => sub {
print STDERR "shutdown: sending shutdown to $LADBI_ALIAS\n";
$_[KERNEL]->post($LADBI_ALIAS => "shutdown");
},
selectall => sub {
my ($dbh_id, $datatype, $data) = @_[ARG0..ARG2];
$_[HEAP]->{dbh_id} = $dbh_id;
print STDERR "selectall: dbh_id=$dbh_id\n";
$_[KERNEL]->post($LADBI_ALIAS => "selectall",
SuccessEvent => "display_results",
FailureEvent => "dberror",
HandleId => $dbh_id,
Args => [ $_[HEAP]->{sql} ] );
},
display_results => sub {
my ($dbh_id, $datatype, $data) = @_[ARG0..ARG2];
print STDERR "display_results: dbh_id=$dbh_id\n";
for my $row ( @$data ) {
print join(",", @$row), "\n";
}
$_[KERNEL]->post($LADBI_ALIAS => "disconnect",
SuccessEvent => "shutdown",
FailureEvent => "dberror",
HandleId => $dbh_id);
},
dberror => sub {
my ($dbh_id, $errtype, $errstr, $err) = @_[ARG0..ARG3];
print STDERR "dberror: dbh_id = $dbh_id\n";
print STDERR "dberror: errtype = $errtype\n";
print STDERR "dberror: errstr = $errstr\n";
print STDERR "dberror: err = $err\n" if $errtype eq "ERROR";
$_[KERNEL]->yield("shutdown");
}
} #end: inline_states
) #end: POE::Session->create()
or die "Failed to instantiate POE::Session\n";
$poe_kernel->run();
exit 0;
__END__
If the environment variable LADBI_DEBUG is set to a true value (perl-wise), or
the ":DEBUG" symbol is in the use statement import list (eg
"use POE::Component::LaDBI qw(:DEBUG)"),
then debugging will be turned on.
When debuggind is turned on,
POE::Component::LaDBI->run() will open and log messages to a file
whos name is indicated in
$POE::Component::LaDBI::DEBUG_FILE.
The debug log is set to "ladbi_run.log" by default.
Sean M. Egan, <seanegan:bigfoot_com>
perl, POE, DBI, POE::Component::LaDBI::Engine, POE::Component::LaDBI::Request,
POE::Component::LaDBI::Response
Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc. |