Author: timbo
Date: Tue Sep 26 15:33:45 2006
New Revision: 7857

Modified:
   dbi/trunk/lib/DBD/Proxy.pm
   dbi/trunk/lib/DBI/ProxyServer.pm
   dbi/trunk/t/80proxy.t

Log:
Fixed DBD::Proxy handling of some methods, including commit and rollback.
(Looks like there's scope for significant speedups as select*_* methods
currently aren't proxied, so the rows are fetch by lower-level code.)


Modified: dbi/trunk/lib/DBD/Proxy.pm
==============================================================================
--- dbi/trunk/lib/DBD/Proxy.pm  (original)
+++ dbi/trunk/lib/DBD/Proxy.pm  Tue Sep 26 15:33:45 2006
@@ -219,13 +219,21 @@
 
 $DBD::Proxy::db::imp_data_size = 0;
 
-# XXX probably many more methods need to be added here.
+# XXX probably many more methods need to be added here
+# in order to trigger our AUTOLOAD to redirect them to the server.
+# (Unless the sub is declared it's bypassed by perl method lookup.)
 # See notes in ToDo about method metadata
+# The question is whether to add all the methods in %DBI::DBI_methods
+# to the corresponding classes (::db, ::st etc)
+# Also need to consider methods that, if proxied, would change the server state
+# in a way that might not be visible on the client, ie begin_work -> 
AutoCommit.
+
 sub commit;
 sub connected;
 sub rollback;
 sub ping;
 
+
 use vars qw(%ATTR $AUTOLOAD);
 
 # inherited: STORE / FETCH against this class.
@@ -249,38 +257,31 @@
 sub AUTOLOAD {
     my $method = $AUTOLOAD;
     $method =~ s/(.*::(.*)):://;
-    # warn "AUTOLOAD of $method";
     my $class = $1;
     my $type = $2;
-    my %expand =
-       ( 'method' => $method,
-         'class' => $class,
-         'type' => $type,
-         'h' => "DBI::_::$type"
-       );
-    my $method_code = UNIVERSAL::can($expand{'h'}, $method) ?
-       q/package ~class~;
-          sub ~method~ {
+    #warn "AUTOLOAD of $method (class=$class, type=$type)";
+    my %expand = (
+        'method' => $method,
+        'class' => $class,
+        'type' => $type,
+        'call' => "$method([EMAIL PROTECTED])",
+        # XXX was trying to be smart but was tripping up over the DBI's own
+        # smartness. Disabled, but left here in case there are issues.
+    #   'call' => (UNIVERSAL::can("DBI::_::$type", $method)) ? "$method([EMAIL 
PROTECTED])" : "func([EMAIL PROTECTED], '$method')",
+    );
+
+    my $method_code = q{
+        package ~class~;
+        sub ~method~ {
             my $h = shift;
-           local $@;
-           my @result = wantarray
-               ? eval {        $h->{'proxy_~type~h'}->~method~(@_) }
-               : eval { scalar $h->{'proxy_~type~h'}->~method~(@_) };
+            local $@;
+            my @result = wantarray
+                ? eval {        $h->{'proxy_~type~h'}->~call~ }
+                : eval { scalar $h->{'proxy_~type~h'}->~call~ };
             return DBD::Proxy::proxy_set_err($h, $@) if $@;
-            wantarray ? @result : $result[0];
-          }
-        / :
-        q/package ~class~;
-         sub ~method~ {
-           my $h = shift;
-           local $@;
-           my @result = wantarray
-               ? eval {        $h->{'proxy_~type~h'}->func(@_, '~method~') }
-               : eval { scalar $h->{'proxy_~type~h'}->func(@_, '~method~') };
-           return DBD::Proxy::proxy_set_err($h, $@) if $@;
-           wantarray ? @result : $result[0];
-          }
-         /;
+            return wantarray ? @result : $result[0];
+        }
+    };
     $method_code =~ s/\~(\w+)\~/$expand{$1}/eg;
     local $SIG{__DIE__} = 'DEFAULT';
     my $err = do { local $@; eval $method_code.2; $@ };
@@ -895,6 +896,26 @@
 
 =head1 KNOWN ISSUES
 
+=head2 Unproxied method calls
+
+If a method isn't being proxied, try declaring a stub sub in the appropriate
+package (DBD::Proxy::db for a dbh method, and DBD::Proxy::st for an sth 
method).
+For example:
+
+    sub DBD::Proxy::db::selectall_arrayref;
+
+That will enable selectall_arrayref to be proxied.
+
+Currently many methods aren't explicitly proxied and so you get the DBI's
+default methods executed on the client.
+
+Some of those methods, like selectall_arrayref, may then call other methods
+that are proxied (selectall_arrayref calls fetchall_arrayref which calls fetch
+which is proxied). So things may appear to work but operate more slowly than
+the could.
+
+This may all change in a later version.
+
 =head2 Complex handle attributes
 
 Sometimes handles are having complex attributes like hash refs or

Modified: dbi/trunk/lib/DBI/ProxyServer.pm
==============================================================================
--- dbi/trunk/lib/DBI/ProxyServer.pm    (original)
+++ dbi/trunk/lib/DBI/ProxyServer.pm    Tue Sep 26 15:33:45 2006
@@ -68,7 +68,9 @@
     $o->{'localport'}  = undef;         # Must set port number on the
                                        # command line.
     $o->{'logfile'}    = undef;         # Use syslog or EventLog.
-    $o->{'methods'}    = {
+
+    # XXX don't restrict methods that can be called (trust users once 
connected)
+    $o->{'XXX_methods'}    = {
        'DBI::ProxyServer' => {
            'Version' => 1,
            'NewHandle' => 1,

Modified: dbi/trunk/t/80proxy.t
==============================================================================
--- dbi/trunk/t/80proxy.t       (original)
+++ dbi/trunk/t/80proxy.t       Tue Sep 26 15:33:45 2006
@@ -71,10 +71,12 @@
     or die "Failed to create config file $config_file: $!";
 
 my($handle, $port);
-my $numTests = 125;
+my $numTests = 135;
+
 if (@ARGV) {
     $port = $ARGV[0];
-} else {
+}
+else {
 
     # set DBI_TRACE to 0 to just get dbiproxy.log DBI trace for server
     # set DBI_TRACE > 0 to also get DBD::Proxy trace
@@ -87,11 +89,13 @@
     # If desperate uncomment this and add '-d' after $^X below:
     # local $ENV{PERLDB_OPTS} = "AutoTrace NonStop=1 LineInfo=dbiproxy.dbg";
 
+    # pass our @INC to children (e.g., so -Mblib passes through)
+    $ENV{PERL5LIB} = join(':', @INC);
+
     my $dbi_trace_level = DBI->trace(0);
     my @child_args = (
        #'truss', '-o', 'dbiproxy.truss',
-       $^X, '-Iblib/lib', '-Iblib/arch', 
-       'dbiproxy', '--test', # --test must be first command line arg
+       $^X, 'dbiproxy', '--test', # --test must be first command line arg
        ($dbi_trace_level ? ('--dbitrace=dbiproxy.log') : ()),
        '--configfile', $config_file,
        (($dbi_trace_level) ? ('--logfile=1') : ()),
@@ -131,6 +135,25 @@
 };
 Test($@ eq "BANG!!!\n", "\$@ value lost");
 
+
+print "begin_work...\n";
+Test($dbh->{AutoCommit});
+Test(!$dbh->{BegunWork});
+
+Test($dbh->begin_work);
+Test(!$dbh->{AutoCommit});
+Test($dbh->{BegunWork});
+
+$dbh->commit;
+Test(!$dbh->{BegunWork});
+Test($dbh->{AutoCommit});
+
+Test($dbh->begin_work({}));
+$dbh->rollback;
+Test($dbh->{AutoCommit});
+Test(!$dbh->{BegunWork});
+
+
 print "Doing a ping.\n";
 $_ = $dbh->ping;
 Test($_);

Reply via email to