Author: timbo Date: Tue Mar 27 15:16:45 2007 New Revision: 9353 Modified: dbi/trunk/Changes dbi/trunk/lib/DBD/File.pm 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/t/85gofer.t
Log: Implement skip_default_methods policy: pass back info from server to client about which dbh methods are not overridden by the driver, those need not be forwarded by gofer because the DBIs local default method will do the same. (One t/85gofer test fails because Gofer needs to be smarted with the rush policy) Modified: dbi/trunk/Changes ============================================================================== --- dbi/trunk/Changes (original) +++ dbi/trunk/Changes Tue Mar 27 15:16:45 2007 @@ -8,6 +8,9 @@ http://buildd.debian.org/fetch.cgi?&pkg=libdbi-perl&ver=1.54-1&arch=m68k&stamp=1174636818&file=log +Implement quote() in C fallback to perl _quote() if $datatype true (and not var/char?) +Implement tie in C. + Add attr-passthru to prepare()? Terminology for client and server ends Document user/passwd issues at the various levels of the stack Modified: dbi/trunk/lib/DBD/File.pm ============================================================================== --- dbi/trunk/lib/DBD/File.pm (original) +++ dbi/trunk/lib/DBD/File.pm Tue Mar 27 15:16:45 2007 @@ -381,6 +381,7 @@ sub quote ($$;$) { my($self, $str, $type) = @_; + if (!defined($str)) { return "NULL" } if (defined($type) && ($type == DBI::SQL_NUMERIC() || $type == DBI::SQL_DECIMAL() || @@ -392,7 +393,6 @@ $type == DBI::SQL_TINYINT())) { return $str; } - if (!defined($str)) { return "NULL" } $str =~ s/\\/\\\\/sg; $str =~ s/\0/\\0/sg; $str =~ s/\'/\\\'/sg; Modified: dbi/trunk/lib/DBD/Gofer.pm ============================================================================== --- dbi/trunk/lib/DBD/Gofer.pm (original) +++ dbi/trunk/lib/DBD/Gofer.pm Tue Mar 27 15:16:45 2007 @@ -298,10 +298,19 @@ func )) { my $policy_name = "cache_$method"; + my $super_name = "SUPER::$method"; my $sub = sub { my $dbh = shift; my $rv; + # if we know the remote side doesn't override the DBI's default method + # then we might as well just call the DBI's default method on the client + # (which may, in turn, call other methods that are forwarded, like get_info) + if ($dbh->{dbi_default_methods}{$method} && $dbh->{go_policy}->skip_default_methods()) { + $dbh->trace_msg(" !! $method: using local default as remote method is also default\n"); + return $dbh->$super_name(@_); + } + my $cache; my $cache_key; if (my $cache_it = $dbh->{go_policy}->$policy_name(undef, $dbh, @_)) { @@ -352,6 +361,15 @@ my $super_name = "SUPER::$method"; my $sub = sub { my $dbh = shift; + + # if we know the remote side doesn't override the DBI's default method + # then we might as well just call the DBI's default method on the client + # (which may, in turn, call other methods that are forwarded, like get_info) + if ($dbh->{dbi_default_methods}{$method} && $dbh->{go_policy}->skip_default_methods()) { + $dbh->trace_msg(" !! $method: using local default as remote method is also default\n"); + return $dbh->$super_name(@_); + } + # false: use remote gofer # 1: use local DBI default method # code ref: use the code ref 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 Mar 27 15:16:45 2007 @@ -16,6 +16,7 @@ my %policy_defaults = ( skip_connect_check => 0, + skip_default_methods => 0, skip_prepare_check => 0, skip_ping => 0, dbh_attribute_update => 'every', 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 Mar 27 15:16:45 2007 @@ -24,6 +24,9 @@ # most code doesn't rely on sth attributes being set after prepare skip_prepare_check => 1, + # we're happy to use local method if that's the same as the remote + skip_default_methods => 1, + # ping is not important for DBD::Gofer and most transports skip_ping => 1, 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 Mar 27 15:16:45 2007 @@ -24,6 +24,9 @@ # most code doesn't rely on sth attributes being set after prepare skip_prepare_check => 1, + # we're happy to use local method if that's the same as the remote + skip_default_methods => 1, + # ping is almost meaningless for DBD::Gofer and most transports anyway skip_ping => 1, Modified: dbi/trunk/lib/DBI/Gofer/Execute.pm ============================================================================== --- dbi/trunk/lib/DBI/Gofer/Execute.pm (original) +++ dbi/trunk/lib/DBI/Gofer/Execute.pm Tue Mar 27 15:16:45 2007 @@ -19,6 +19,8 @@ our $VERSION = sprintf("0.%06d", q$Revision$ =~ /(\d+)/o); our $local_log = $ENV{DBI_GOFER_TRACE} || $ENV{DBI_GOFER_LOCAL_LOG}; +our @all_dbh_methods = sort map { keys %$_ } $DBI::DBI_methods{db}, $DBI::DBI_methods{common}; +our %all_dbh_methods = map { $_ => DBD::_::db->can($_) } @all_dbh_methods; __PACKAGE__->mk_accessors(qw( check_connect @@ -265,6 +267,9 @@ # XXX piggyback installed_methods onto dbh_attributes for now $dbh_attr_values{dbi_installed_methods} = { DBI->installed_methods }; + # XXX piggyback default_methods onto dbh_attributes for now + $dbh_attr_values{dbi_default_methods} = _get_default_methods($dbh); + $response->dbh_attributes(\%dbh_attr_values); } @@ -432,6 +437,22 @@ } +sub _get_default_methods { + my ($dbh) = @_; + # returns a ref to a hash of dbh method names for methods which the driver + # hasn't overridden i.e., quote(). These don't need to be forwarded via gofer. + my $ImplementorClass = $dbh->{ImplementorClass} or die; + my %default_methods; + for my $method (@all_dbh_methods) { + my $dbi_sub = $all_dbh_methods{$method} || 42; + my $imp_sub = $ImplementorClass->can($method) || 42; + next if $imp_sub != $dbi_sub; + #warn("default $method\n"); + $default_methods{$method} = 1; + } + return \%default_methods; +} + 1; __END__ Modified: dbi/trunk/t/85gofer.t ============================================================================== --- dbi/trunk/t/85gofer.t (original) +++ dbi/trunk/t/85gofer.t Tue Mar 27 15:16:45 2007 @@ -169,14 +169,16 @@ ok $go_request_count; ok $dbh->do("DROP TABLE fruit"); - is $go_request_count + 1, $dbh->{go_request_count}; + is ++$go_request_count, $dbh->{go_request_count}; + my $use_remote = ($policy->skip_default_methods) ? 0 : 1; + warn "use_remote=$use_remote (policy=$policy_name, transport=$transport) $dbh->{dbi_default_methods}\n"; $dbh->data_sources({ foo_bar => $go_request_count }); - is $go_request_count + 2, $dbh->{go_request_count}; + is $dbh->{go_request_count}, $go_request_count + 1*$use_remote; $dbh->data_sources({ foo_bar => $go_request_count }); # should use cache - is $go_request_count + 2, $dbh->{go_request_count}; + is $dbh->{go_request_count}, $go_request_count + 1*$use_remote; @_=$dbh->data_sources({ foo_bar => $go_request_count }); # no cached yet due to wantarray - is $go_request_count + 3, $dbh->{go_request_count}; + is $dbh->{go_request_count}, $go_request_count + 2*$use_remote; SKIP: { skip "caching of metadata methods returning sth not yet implemented", 2;
