Author: timbo
Date: Mon Jun  2 03:43:48 2008
New Revision: 11371

Modified:
   dbi/trunk/Changes
   dbi/trunk/DBI.pm
   dbi/trunk/DBI.xs
   dbi/trunk/MANIFEST
   dbi/trunk/lib/DBI/PurePerl.pm
   dbi/trunk/t/05concathash.t

Log:
Fixup some _concat_hash_sorted use_neat inversion issues.
Remove extra_sv arg and logic from _concat_hash_sorted, and tidy it.
Add t/05concathash.t to manifest 
Fix handling of non-printables in DBI::PurePerl neat().
Update DBI::PurePerl _concat_hash_sorted.
Update Changes and tests.
Use _concat_hash_sorted for connect_cached and prepare_cahed.


Modified: dbi/trunk/Changes
==============================================================================
--- dbi/trunk/Changes   (original)
+++ dbi/trunk/Changes   Mon Jun  2 03:43:48 2008
@@ -68,11 +68,16 @@
     inner sth handle when passed a $sth instead of an sql string.
     Drivers will need to be recompiled to pick up this change.
   Fixed leak in neat() for some kinds of values thanks to Rudolf Lippan.
+  Fixed DBI::PurePerl neat() to behave more like XS neat().
+  Fixed the placeholder values reported by ShowErrorStatement
+    to be shown in sorted order.
 
   Increased timeout on tests to accomodate very slow systems.
   Removed the beeps "\a" from Makefile.PL warnings.
   Removed check for PlRPC-modules from Makefile.PL
   Clarified docs re ":N" style placeholders.
+  Changed the format of the key used for $h->{CachedKids}
+    (which is undocumented so you shouldn't depend on it anyway)
 
   Added cache miss trace message to DBD::Gofer transport class.
   Added $drh->dbixs_revision method.

Modified: dbi/trunk/DBI.pm
==============================================================================
--- dbi/trunk/DBI.pm    (original)
+++ dbi/trunk/DBI.pm    Mon Jun  2 03:43:48 2008
@@ -1428,14 +1428,13 @@
        my ($dsn, $user, $auth, $attr) = @_;
 
        my $cache = $drh->{CachedKids} ||= {};
-
-       my @attr_keys = $attr ? sort keys %$attr : ();
-       my $key = do { local $^W; # silence undef warnings
-           join "~~", $dsn, $user, $auth, $attr ? (@attr_keys,@[EMAIL 
PROTECTED]) : ()
+       my $key = do { local $^W;
+           join "!\001", $dsn, $user, $auth, DBI::_concat_hash_sorted($attr, 
"=\001", ",\001", 0, 0)
        };
        my $dbh = $cache->{$key};
         $drh->trace_msg(sprintf("    connect_cached: key '$key', cached dbh 
$dbh\n", DBI::neat($key), DBI::neat($dbh)))
             if $DBI::dbi_debug >= 4;
+
         my $cb = $attr->{Callbacks}; # take care not to autovivify
        if ($dbh && $dbh->FETCH('Active') && eval { $dbh->ping }) {
             # If the caller has provided a callback then call it
@@ -1636,13 +1635,16 @@
 
     sub prepare_cached {
        my ($dbh, $statement, $attr, $if_active) = @_;
+
        # Needs support at dbh level to clear cache before complaining about
        # active children. The XS template code does this. Drivers not using
        # the template must handle clearing the cache themselves.
        my $cache = $dbh->{CachedKids} ||= {};
-       my @attr_keys = ($attr) ? sort keys %$attr : ();
-       my $key = ($attr) ? join("~~", $statement, @attr_keys, @[EMAIL 
PROTECTED]) : $statement;
+       my $key = do { local $^W;
+           join "!\001", $statement, DBI::_concat_hash_sorted($attr, "=\001", 
",\001", 0, 0)
+       };
        my $sth = $cache->{$key};
+
        if ($sth) {
            return $sth unless $sth->FETCH('Active');
            Carp::carp("prepare_cached($statement) statement handle $sth still 
Active")
@@ -1650,8 +1652,10 @@
            $sth->finish if $if_active <= 1;
            return $sth  if $if_active <= 2;
        }
+
        $sth = $dbh->prepare($statement, $attr);
        $cache->{$key} = $sth if $sth;
+
        return $sth;
     }
 

Modified: dbi/trunk/DBI.xs
==============================================================================
--- dbi/trunk/DBI.xs    (original)
+++ dbi/trunk/DBI.xs    Mon Jun  2 03:43:48 2008
@@ -331,6 +331,9 @@
             }
 
             if (use_neat) {
+                sv_catpv(return_sv, neatsvpv(*hash_svp,0));
+            }
+            else {
                 if (SvOK(*hash_svp)) {
                      STRLEN hv_val_len;
                      char *hv_val = SvPV(*hash_svp, hv_val_len);
@@ -340,7 +343,6 @@
                 }
                 else sv_catpvn(return_sv, "undef", 5);
             }
-            else     sv_catpv(return_sv, neatsvpv(*hash_svp,0));
 
             if (i < hv_len-1)
                 sv_catpvn(return_sv, pair_sep, pair_sep_len);
@@ -4388,44 +4390,31 @@
 
 
 SV *
-_concat_hash_sorted(hash_sv, kv_sep_sv, pair_sep_sv, use_neat_sv, num_sort_sv, 
extra_sv=Nullsv)
+_concat_hash_sorted(hash_sv, kv_sep_sv, pair_sep_sv, use_neat_sv, num_sort_sv)
     SV *hash_sv
     SV *kv_sep_sv
     SV *pair_sep_sv
     SV *use_neat_sv
     SV *num_sort_sv
-    SV *extra_sv
     PREINIT:
-    STRLEN kv_sep_len, pair_sep_len;
     char *kv_sep, *pair_sep;
-    int use_neat, num_sort;
+    STRLEN kv_sep_len, pair_sep_len;
     CODE:
         if (!SvOK(hash_sv))
             XSRETURN_UNDEF;
         if (!SvROK(hash_sv) || SvTYPE(SvRV(hash_sv))!=SVt_PVHV)
             croak("hash is not a hash reference");
+
         kv_sep   = SvPV(kv_sep_sv,   kv_sep_len);
         pair_sep = SvPV(pair_sep_sv, pair_sep_len);
-        /* use_neat should be undef, 0 or 1, may allow sprintf format strings 
later */
-        use_neat = (SvOK(use_neat_sv)) ? SvIV(use_neat_sv) : 0;
-        num_sort = (SvOK(num_sort_sv)) ? SvIV(num_sort_sv) : -1;
-
-        RETVAL = _join_hash_sorted((HV*)SvRV(hash_sv), kv_sep, kv_sep_len, 
pair_sep, pair_sep_len, use_neat, num_sort);
-
-        /* efficient way for the caller to tack extra info onto the return 
string */
-        if (extra_sv && SvOK(extra_sv) && SvROK(extra_sv) && 
SvTYPE(SvRV(extra_sv))==SVt_PVAV) {
-            AV *extra_av = (AV*)SvRV(extra_sv);
-            int i, items = AvFILL(extra_av)+1;
-            for (i=0; i < items; ++i) {
-                SV *e_sv = *av_fetch(extra_av, i, 1);
-                if (SvTRUE(RETVAL))
-                    sv_catsv(RETVAL, kv_sep_sv);
-                if (SvOK(e_sv))
-                     sv_catsv(RETVAL, *av_fetch(extra_av, i, 1));
-                else sv_catpvn(RETVAL, "undef", 5);
-            }
-        }
 
+        RETVAL = _join_hash_sorted( (HV*)SvRV(hash_sv),
+            kv_sep,   kv_sep_len,
+            pair_sep, pair_sep_len,
+            /* use_neat should be undef, 0 or 1, may allow sprintf format 
strings later */
+            (SvOK(use_neat_sv)) ? SvIV(use_neat_sv) :  0,
+            (SvOK(num_sort_sv)) ? SvIV(num_sort_sv) : -1
+        );
     OUTPUT:
         RETVAL
 

Modified: dbi/trunk/MANIFEST
==============================================================================
--- dbi/trunk/MANIFEST  (original)
+++ dbi/trunk/MANIFEST  Mon Jun  2 03:43:48 2008
@@ -70,6 +70,7 @@
 t/02dbidrv.t
 t/03handle.t
 t/04mods.t
+t/05concathash.t
 t/06attrs.t
 t/07kids.t
 t/08keeperr.t

Modified: dbi/trunk/lib/DBI/PurePerl.pm
==============================================================================
--- dbi/trunk/lib/DBI/PurePerl.pm       (original)
+++ dbi/trunk/lib/DBI/PurePerl.pm       Mon Jun  2 03:43:48 2008
@@ -664,6 +664,7 @@
        $v = substr($v,0,$maxlen-5);
        $v .= '...';
     }
+    $v =~ s/[^[:print:]]/./g;
     return "$quote$v$quote";
 }
 
@@ -674,21 +675,21 @@
 sub DBI::st::TIEHASH { bless $_[1] => $_[0] };
 
 sub _concat_hash_sorted {
-    my ( $hash_ref, $kv_separator, $pair_separator, $value_format, $sort_type 
) = @_;
-    # $value_format: false=use neat(), true=dumb quotes
-    # $sort_type: 0=lexical, 1=numeric, undef=try to guess
+    my ( $hash_ref, $kv_separator, $pair_separator, $use_neat, $num_sort ) = 
@_;
+    # $num_sort: 0=lexical, 1=numeric, undef=try to guess
 
+    return undef unless defined $hash_ref;
     die "hash is not a hash reference" unless ref $hash_ref eq 'HASH';
-    my $keys = _get_sorted_hash_keys($hash_ref, $sort_type);
+    my $keys = _get_sorted_hash_keys($hash_ref, $num_sort);
     my $string = '';
     for my $key (@$keys) {
         $string .= $pair_separator if length $string > 0;
         my $value = $hash_ref->{$key};
-        if ($value_format) {
-            $value = (defined $value) ? "'$value'" : 'undef';
+        if ($use_neat) {
+            $value = DBI::neat($value, 0);
         }
         else {
-            $value = DBI::neat($value,0);
+            $value = (defined $value) ? "'$value'" : 'undef';
         }
         $string .= $key . $kv_separator . $value;
     }
@@ -696,20 +697,19 @@
 }
 
 sub _get_sorted_hash_keys {
-    my ($hash_ref, $sort_type) = @_;
-    if (not defined $sort_type) {
+    my ($hash_ref, $num_sort) = @_;
+    if (not defined $num_sort) {
         my $sort_guess = 1;
         $sort_guess = (not looks_like_number($_)) ? 0 : $sort_guess
             for keys %$hash_ref;
-        $sort_type = $sort_guess;
+        $num_sort = $sort_guess;
     }
     
     my @keys = keys %$hash_ref;
     no warnings 'numeric';
-    my @sorted = ($sort_type)
+    my @sorted = ($num_sort)
         ? sort { $a <=> $b or $a cmp $b } @keys
         : sort    @keys;
-    #warn "$sort_type = @sorted\n";
     return [EMAIL PROTECTED];
 }
 

Modified: dbi/trunk/t/05concathash.t
==============================================================================
--- dbi/trunk/t/05concathash.t  (original)
+++ dbi/trunk/t/05concathash.t  Mon Jun  2 03:43:48 2008
@@ -29,9 +29,9 @@
 # (nul byte in hash not supported)
 is DBI::_concat_hash_sorted({ 1=>"a", 2=>"b" }, "=\000=", ":\000:", undef, 
undef),
     "1=\000='a':\000:2=\000='b'", 'should work with nul bytes in kv_sep and 
pair_sep';
-is DBI::_concat_hash_sorted({ 1=>"a\000a", 2=>"b" }, "=", ":", 0, undef),
-    "1='a.a':2='b'", 'should work with nul bytes in hash value (neat)';
 is DBI::_concat_hash_sorted({ 1=>"a\000a", 2=>"b" }, "=", ":", 1, undef),
+    "1='a.a':2='b'", 'should work with nul bytes in hash value (neat)';
+is DBI::_concat_hash_sorted({ 1=>"a\000a", 2=>"b" }, "=", ":", 0, undef),
     "1='a\000a':2='b'", 'should work with nul bytes in hash value (not neat)';
 
 # Simple stress tests
@@ -144,22 +144,22 @@
 #CatHash::_concat_hash_values({ }, ":-",,"::",1,1);
 
 
-sub _concat_hash_sorted {
-    my ( $hash_ref, $kv_separator, $pair_separator, $value_format, $sort_type 
) = @_;
-    # $value_format: false=use neat(), true=dumb quotes
-    # $sort_type: 0=lexical, 1=numeric, undef=try to guess
-
+sub _concat_hash_sorted { 
+    my ( $hash_ref, $kv_separator, $pair_separator, $use_neat, $num_sort ) = 
@_;
+    # $num_sort: 0=lexical, 1=numeric, undef=try to guess
+        
+    return undef unless defined $hash_ref;
     die "hash is not a hash reference" unless ref $hash_ref eq 'HASH';
-    my $keys = _get_sorted_hash_keys($hash_ref, $sort_type);
+    my $keys = _get_sorted_hash_keys($hash_ref, $num_sort);
     my $string = '';
     for my $key (@$keys) {
         $string .= $pair_separator if length $string > 0;
         my $value = $hash_ref->{$key};
-        if ($value_format) {
-            $value = (defined $value) ? "'$value'" : 'undef';
-        }
+        if ($use_neat) {
+            $value = DBI::neat($value, 0); 
+        } 
         else {
-            $value = DBI::neat($value,0);
+            $value = (defined $value) ? "'$value'" : 'undef';
         }
         $string .= $key . $kv_separator . $value;
     }

Reply via email to