Author: spadkins
Date: Thu Dec  7 12:57:24 2006
New Revision: 8371

Modified:
   p5ee/trunk/App-Repository/lib/App/Repository/DBI.pm

Log:
add call_procedure()

Modified: p5ee/trunk/App-Repository/lib/App/Repository/DBI.pm
==============================================================================
--- p5ee/trunk/App-Repository/lib/App/Repository/DBI.pm (original)
+++ p5ee/trunk/App-Repository/lib/App/Repository/DBI.pm Thu Dec  7 12:57:24 2006
@@ -2472,8 +2472,10 @@
 =cut
 
 sub begin {
+    &App::sub_entry if ($App::trace);
     my $self = shift;
     $self->_do("begin");
+    &App::sub_exit() if ($App::trace);
 }
 
 #############################################################################
@@ -2495,8 +2497,10 @@
 =cut
 
 sub commit {
+    &App::sub_entry if ($App::trace);
     my $self = shift;
     $self->_do("commit");
+    &App::sub_exit() if ($App::trace);
 }
 
 #############################################################################
@@ -2518,13 +2522,119 @@
 =cut
 
 sub rollback {
+    &App::sub_entry if ($App::trace);
     my $self = shift;
     $self->_do("rollback");
+    &App::sub_exit() if ($App::trace);
+}
+
+#############################################################################
+# call_procedure()
+#############################################################################
+
+=head2 call_procedure()
+
+    * Signature: $rep->call_procedure($call_str);
+    * Signature: $rep->call_procedure($call_str, $return_type, $param_types, 
@params);
+    * Signature: $result  = $rep->call_procedure($call_str, $return_type);
+    * Signature: $result  = $rep->call_procedure($call_str, $return_type, 
$param_types, @params);
+    * Signature: @results = $rep->call_procedure($call_str, $return_type);
+    * Signature: @results = $rep->call_procedure($call_str, $return_type, 
$param_types, @params);
+    * Signature: $rows    = $rep->call_procedure($call_str, $return_type);
+    * Signature: $rows    = $rep->call_procedure($call_str, $return_type, 
$param_types, @params);
+    * Param:     void
+    * Return:    $result   string    (if $return_type is "SCALAR")
+    * Return:    @results  ARRAY     (if $return_type is "LIST")
+    * Return:    $row      ARRAY     (if $return_type is "ROW")
+    * Return:    $rows     ARRAY     (if $return_type is "ROWS")
+    * Throws:    App::Exception::Repository
+    * Since:     0.01
+
+There is no standard way to call stored procedures in the DBI.
+This is an attempt to provide access to them.
+
+    MySQL: Sample Usage
+    1. As of DBD-mysql-3.0008 and MySQL 5.1.12, INOUT and OUT parameters are 
not supported
+    2. In order to receive values back from a stored procedure in MySQL,
+       you need to have applied the "dbd-mysql-multi-statements.patch" patch.
+       https://rt.cpan.org/Public/Bug/Display.html?id=12322
+       
https://rt.cpan.org/Ticket/Attachment/167152/53763/dbd-mysql-multi-statements.patch
+       This supports the "SCALAR" return type (and maybe "LIST" and "ROW"), but
+       a stored procedure can still not return multiple rows ("ROWS"). (I 
think.)
+       You DSN needs to have "mysql_multi_results=1" set to activate the 
ability to
+       get rows back from a stored procedure.
+
+    $rep->call_procedure("call sp_doit('prod',5)");
+    $val           = $rep->call_procedure("call sp_doit_return_val('prod',5)", 
"SCALAR");
+    ($val1, $val2) = $rep->call_procedure("call 
sp_doit_return_vals('prod',5)", "LIST");
+    $row           = $rep->call_procedure("call 
sp_doit_return_vals('prod',5)", "ROW");
+
+=cut
+
+sub call_procedure {
+    &App::sub_entry if ($App::trace);
+    my ($self, $call_str, $return_type, $param_options, @params) = @_;
+    my $dbh = $self->{dbh};
+    my $sth = $dbh->prepare($call_str);
+    my ($i, $param_option, $param_direction, $param_length, $param_type);
+    for ($i = 0; $i <= $#params; $i++) {
+        $param_option = $param_options->[$i];
+        if (!ref($param_option)) {
+            $param_direction = $param_option || "IN";
+            $param_length    = 100;
+            $param_type      = undef;
+        }
+        else {
+            $param_direction = $param_option->{direction} || "IN";
+            $param_length    = $param_option->{length} || 100;
+            $param_type      = $param_option;
+        }
+        if ($param_direction eq "OUT") {
+            $sth->bind_param_inout($i+1, \$_[$i+4], $param_length);
+        }
+        elsif ($param_direction eq "INOUT") {
+            $sth->bind_param_inout($i+1, \$_[$i+4], $param_length);
+        }
+        else {
+            $sth->bind_param($i+1, $params[$i], $param_type);
+        }
+    }
+    $sth->execute();
+    my (@values);
+    my $rows = [];
+    if (defined $return_type) {
+        while (@values = $sth->fetchrow_array()) {
+            push(@$rows, [EMAIL PROTECTED]);
+        }
+        if ($return_type eq "LIST") {
+            @values = @{$rows->[0]} if ($#$rows > -1);
+        }
+        elsif ($return_type eq "SCALAR") {
+            @values = ($rows->[0][0]) if ($#$rows > -1 && $#{$rows->[0]} > -1);
+        }
+        elsif ($return_type eq "ROW") {
+            @values = ( $rows->[0] ) if ($#$rows > -1);
+        }
+        elsif ($return_type eq "ROWS") {
+            @values = ( $rows );
+        }
+    }
+    $sth->finish(); 
+    if ($return_type eq "LIST") {
+        &App::sub_exit(@values) if ($App::trace);
+        return(@values);
+    }
+    else {
+        &App::sub_exit($values[0]) if ($App::trace);
+        return($values[0]);
+    }
 }
 
 sub explain_sql {
+    &App::sub_entry if ($App::trace);
     my ($self, $sql) = @_;
     # to be overridden in each Repository class
+    &App::sub_exit() if ($App::trace);
 }
 
 sub _get_timer {

Reply via email to