Author: timbo
Date: Tue Apr 10 08:16:05 2007
New Revision: 9391

Modified:
   dbi/trunk/Changes
   dbi/trunk/DBI.xs
   dbi/trunk/lib/DBD/Gofer.pm
   dbi/trunk/lib/DBD/Gofer/Policy/Base.pm
   dbi/trunk/lib/DBD/Gofer/Policy/classic.pm
   dbi/trunk/lib/DBD/Gofer/Policy/rush.pm
   dbi/trunk/lib/DBI/Gofer/Execute.pm
   dbi/trunk/lib/DBI/Gofer/Request.pm

Log:
Add connect_method and prepare_method gofer policies.
Add connect_cached to gofer like prepare_cached.
Change connect_args to dbh_connect_call and include method name and all args.
(Some t/zvg_09trace tests fail, oddly)


Modified: dbi/trunk/Changes
==============================================================================
--- dbi/trunk/Changes   (original)
+++ dbi/trunk/Changes   Tue Apr 10 08:16:05 2007
@@ -8,9 +8,16 @@
 
 
http://buildd.debian.org/fetch.cgi?&pkg=libdbi-perl&ver=1.54-1&arch=m68k&stamp=1174636818&file=log
 
+Policy principle:
+    Designed to influence behaviour of unaltered programs
+    ie go_* attributes take precidence over policy
+    on the basis that if you can alter the code to add go_* attributes
+    then you can also put your required logic at that place
+
+Gofer request flags:
+    return current executor stats as an attribute - handy for tests
+    only fetch one result set - handy for Sybase/MSSQL users
 Pedantic policy should force a fresh connect each time - add new policy item
-Allow connect via subclass to support DBIx::HA
-prepare(...,{ Err=>\my $isolated_err, ...})
 Add attr-passthru to prepare()? ie for gofer cache control
 Terminology for client and server ends
 Document user/passwd issues at the various levels of the stack
@@ -23,6 +30,8 @@
 Call method on transport timeout so transport can cleanup/reset it it wants
 
 Implement tie in C.
+Make CachedKids a plain attrib to avoid FETCH in connect_cached/prepare_cached
+prepare(...,{ Err=>\my $isolated_err, ...})
 Add trace modules that just records the last N trace messages into an array
 and prepends them to any error message.
 

Modified: dbi/trunk/DBI.xs
==============================================================================
--- dbi/trunk/DBI.xs    (original)
+++ dbi/trunk/DBI.xs    Tue Apr 10 08:16:05 2007
@@ -792,8 +792,8 @@
        if (!what)
            return NULL;
        sv_dump(orv);
-       croak("panic: %s inner handle %s is not a hash ref",
-               what, neatsvpv(hrv,0));
+       croak("panic: %s inner handle %s is not a hash ref (isref=%d, type=%d)",
+               what, neatsvpv(hrv,0), SvROK(hrv), 
(SvROK(hrv))?SvTYPE(SvRV(hrv)):-1);
     }
     return hrv;
 }

Modified: dbi/trunk/lib/DBD/Gofer.pm
==============================================================================
--- dbi/trunk/lib/DBD/Gofer.pm  (original)
+++ dbi/trunk/lib/DBD/Gofer.pm  Tue Apr 10 08:16:05 2007
@@ -120,6 +120,16 @@
     $imp_data_size = 0;
     use strict;
 
+    sub connect_cached {
+        my ($drh, $dsn, $user, $auth, $attr)= @_;
+        $attr ||= {};
+        return $drh->SUPER::connect_cached($dsn, $user, $auth, {
+            (%$attr),
+            go_connect_method => $attr->{go_connect_method} || 
'connect_cached',
+        });
+    }
+
+
     sub connect {
         my($drh, $dsn, $user, $auth, $attr)= @_;
         my $orig_dsn = $dsn;
@@ -157,6 +167,9 @@
         # policy object is left in $go_attr{go_policy} so transport can see it
         my $go_policy = $go_attr{go_policy};
 
+        # but delete any other attributes that don't appy to transport
+        my $go_connect_method = delete $go_attr{go_connect_method};
+
         my $transport_class = delete $go_attr{go_transport}
             or return $drh->set_err(1, "No transport= argument in 
'$orig_dsn'");
         $transport_class = "DBD::Gofer::Transport::$transport_class"
@@ -178,8 +191,10 @@
             delete @{$go_attr}{qw(Profile HandleError HandleSetErr Callbacks)};
             # delete any attributes that should only apply to the client-side
             delete @{$go_attr}{qw(RootClass DbTypeSubclass)};
+
+            $go_connect_method ||= $go_policy->connect_method($remote_dsn, 
$go_attr) || 'connect';
             $request_class->new({
-                connect_args => [ $remote_dsn, $go_attr ]
+                dbh_connect_call => [ $go_connect_method, $remote_dsn, $user, 
$auth, $go_attr ],
             })
         } or return $drh->set_err(1, "Can't instanciate $request_class: $@");
 
@@ -482,7 +497,11 @@
 
         my $policy     = delete($attr->{go_policy}) || $dbh->{go_policy};
         my $lii_args   = delete $attr->{go_last_insert_id_args};
-        my $go_prepare = delete($attr->{go_prepare}) || $dbh->{go_prepare} || 
'prepare';
+        my $go_prepare = delete($attr->{go_prepare_method})
+                      || $dbh->{go_prepare_method}
+                      || $policy->prepare_method($dbh, $statement, $attr)
+                      || 'prepare'; # e.g. for code not using placeholders
+        # set to undef if there are no attributes left for the actual prepare 
call
         $attr = undef if $attr and not %$attr;
 
         my ($sth, $sth_inner) = DBI::_new_sth($dbh, {
@@ -506,9 +525,10 @@
 
     sub prepare_cached {
         my ($dbh, $sql, $attr, $if_active)= @_;
+        $attr ||= {};
         return $dbh->SUPER::prepare_cached($sql, {
-            ($attr ? %$attr : ()),
-            go_prepare => 'prepare_cached',
+            %$attr,
+            go_prepare_method => $attr->{go_prepare_method} || 
'prepare_cached',
         }, $if_active);
     }
 

Modified: dbi/trunk/lib/DBD/Gofer/Policy/Base.pm
==============================================================================
--- dbi/trunk/lib/DBD/Gofer/Policy/Base.pm      (original)
+++ dbi/trunk/lib/DBD/Gofer/Policy/Base.pm      Tue Apr 10 08:16:05 2007
@@ -15,6 +15,12 @@
 our $AUTOLOAD;
 
 my %policy_defaults = (
+    # force connect method (unless overridden by go_connect_method=>'...' 
attribute)
+    # if false: call same method on client as on server
+    connect_method => 'connect',
+    # force prepare method (unless overridden by go_prepare_method=>'...' 
attribute)
+    # if false: call same method on client as on server
+    prepare_method => 'prepare',
     skip_connect_check => 0,
     skip_default_methods => 0,
     skip_prepare_check => 0,
@@ -50,7 +56,7 @@
             # $policy->foo($attr, ...)
             #carp "$policy_name($_[1],...)";
             # return the policy default value unless an attribute overrides it
-            return ($_[1] && exists $_[1]->{$policy_attr_name})
+            return (ref $_[1] && exists $_[1]->{$policy_attr_name})
                 ? $_[1]->{$policy_attr_name}
                 : $policy_default;
         };

Modified: dbi/trunk/lib/DBD/Gofer/Policy/classic.pm
==============================================================================
--- dbi/trunk/lib/DBD/Gofer/Policy/classic.pm   (original)
+++ dbi/trunk/lib/DBD/Gofer/Policy/classic.pm   Tue Apr 10 08:16:05 2007
@@ -16,6 +16,12 @@
 
 __PACKAGE__->create_policy_subs({
 
+    # always use connect_cached on server
+    connect_method => 'connect_cached',
+
+    # use same methods on server as is called on client
+    prepare_method => '',
+
     # don't skip the connect check since that also sets dbh attributes
     # although this makes connect more expensive, that's partly offset
     # by skip_ping=>1 below, which makes connect_cached very fast.

Modified: dbi/trunk/lib/DBD/Gofer/Policy/rush.pm
==============================================================================
--- dbi/trunk/lib/DBD/Gofer/Policy/rush.pm      (original)
+++ dbi/trunk/lib/DBD/Gofer/Policy/rush.pm      Tue Apr 10 08:16:05 2007
@@ -16,6 +16,13 @@
 
 __PACKAGE__->create_policy_subs({
 
+    # always use connect_cached on server
+    connect_method => 'connect_cached',
+
+    # use same methods on server as is called on client
+    # (because code not using placeholders would bloat the sth cache)
+    prepare_method => '',
+
     # Skipping the connect check is fast, but it also skips
     # fetching the remote dbh attributes!
     # Make sure that your application doesn't need access to dbh attributes.

Modified: dbi/trunk/lib/DBI/Gofer/Execute.pm
==============================================================================
--- dbi/trunk/lib/DBI/Gofer/Execute.pm  (original)
+++ dbi/trunk/lib/DBI/Gofer/Execute.pm  Tue Apr 10 08:16:05 2007
@@ -133,14 +133,16 @@
         }
     }
 
-    my ($dsn, $attr) = @{ $request->connect_args };
+    my ($connect_method, $dsn, $username, $password, $attr) = @{ 
$request->dbh_connect_call };
+    $connect_method ||= 'connect_cached';
+
     # delete attributes we don't want to affect the server-side
     # (Could just do this on client-side and trust the client. DoS?)
     delete @{$attr}{qw(Profile InactiveDestroy HandleError HandleSetErr 
TraceLevel Taint TaintIn TaintOut)};
-    my $connect_method = 'connect_cached';
 
-    my $check_connect = $self->check_connect;
-    $check_connect->($dsn, $attr, $connect_method, $request) if $check_connect;
+    if (my $check_connect = $self->check_connect) {
+        $check_connect->($dsn, $attr, $connect_method, $request);
+    }
 
     $dsn = $self->forced_connect_dsn || $dsn || $self->default_connect_dsn
         or die "No forced_connect_dsn, requested dsn, or default_connect_dsn 
for request";

Modified: dbi/trunk/lib/DBI/Gofer/Request.pm
==============================================================================
--- dbi/trunk/lib/DBI/Gofer/Request.pm  (original)
+++ dbi/trunk/lib/DBI/Gofer/Request.pm  Tue Apr 10 08:16:05 2007
@@ -18,7 +18,7 @@
 
 __PACKAGE__->mk_accessors(qw(
     version
-    connect_args
+    dbh_connect_call
     dbh_method_call
     dbh_wantarray
     dbh_attributes
@@ -38,7 +38,7 @@
 sub reset {
     my $self = shift;
     # remove everything except connect and version
-    %$self = ( version => $self->{version}, connect_args => 
$self->{connect_args} );
+    %$self = ( version => $self->{version}, dbh_connect_call => 
$self->{dbh_connect_call} );
 }
 
 sub is_sth_request {
@@ -62,10 +62,16 @@
         push @s, join(", ", map { "$_=>".$context->{$_} } @keys);
     }
 
-    my ($dsn, $attr) = @{ $self->connect_args };
-    my $tmp = { %{$attr||{}} }; # copy so we can edit
-    $tmp->{Password} = '***' if exists $tmp->{Password};
-    push @s, sprintf "dbh= connect('%s', , , { %s })", $dsn, neat_list([ %$tmp 
]);
+    my ($method, $dsn, $user, $pass, $attr) = @{ $self->dbh_connect_call };
+    $method ||= 'connect_cached';
+    $pass = '***' if defined $pass;
+    my $tmp = '';
+    if ($attr) { 
+        $tmp = { %{$attr||{}} }; # copy so we can edit
+        $tmp->{Password} = '***' if exists $tmp->{Password};
+        $tmp = "{ ".neat_list([ %$tmp ])." }";
+    }
+    push @s, sprintf "dbh= $method(%s, %s)", neat_list([$dsn, $user, $pass]), 
$tmp;
 
     if (my $dbh_attr = $self->dbh_attributes) {
         push @s, sprintf "dbh->FETCH: %s", @$dbh_attr

Reply via email to