Author: timbo
Date: Mon Apr 23 08:34:09 2007
New Revision: 9444

Modified:
   dbi/trunk/Changes
   dbi/trunk/DBI.pm
   dbi/trunk/DBI.xs
   dbi/trunk/DBIXS.h
   dbi/trunk/Driver.xst
   dbi/trunk/lib/DBI/PurePerl.pm
   dbi/trunk/t/01basics.t
   dbi/trunk/t/06attrs.t

Log:
Reworked CachedKids. It's now just an ordinary attribute.


Modified: dbi/trunk/Changes
==============================================================================
--- dbi/trunk/Changes   (original)
+++ dbi/trunk/Changes   Mon Apr 23 08:34:09 2007
@@ -41,21 +41,16 @@
 
 =head2 Changes in DBI 1.55 (svn rev XXX),  XXX
 
-XXX DBIc_CACHED_KIDS needs to be an lvalue for Drivers using Driver.xst
-Perl.xs: In function 'XS_DBD__Perl__db_disconnect':
-Perl.xs:277: warning: target of assignment not really an lvalue; this will be 
a hard error in the future
-Perl.xs: In function 'XS_DBD__Perl__db_DESTROY':
-Perl.xs:337: warning: target of assignment not really an lvalue; this will be 
a hard error in the future
-
-
-  Fixed set_err so HandleSetErr hook is executed reliably, if set.
+  Fixed set_err() so HandleSetErr hook is executed reliably, if set.
   Fixed accuracy of profiling when perl configured to use long doubles.
   Fixed 42prof_data.t on fast systems with poor timers thanks to Malcolm 
Nooning.
 
   Changed some handle creation code from perl to C code,
     to reduce handle creation cost by ~20%.
-  Changed connect_cached and prepare_cached to avoid a method call which
-    reduced cost by ~5% for connect_cached and ~30% for prepare_cached.
+  Changed internal implementation of the CachedKids attribute
+    so it's a normal handle attribute (and initially undef).
+  Changed connect_cached and prepare_cached to avoid a FETCH method call,
+    and thereby reduced cost by ~5% and ~30% respectively.
   Changed _set_fbav to not croak when given a wrongly sized array,
     it now warns and adjusts the row buffer to match.
   Changed DBD::NullP to be slightly more useful for testing.

Modified: dbi/trunk/DBI.pm
==============================================================================
--- dbi/trunk/DBI.pm    (original)
+++ dbi/trunk/DBI.pm    Mon Apr 23 08:34:09 2007
@@ -369,7 +369,7 @@
 %DBI::DBI_methods = ( # Define the DBI interface methods per class:
 
     common => {                # Interface methods common to all DBI handle 
classes
-       'DESTROY'       => $keeperr,
+       'DESTROY'       => { O=>0x004|0x10000 },
        'CLEAR'         => $keeperr,
        'EXISTS'        => $keeperr,
        'FETCH'         => { O=>0x0404 },
@@ -402,7 +402,7 @@
     },
     db => {            # Database Session Class Interface
        data_sources    => { U =>[1,2,'[\%attr]' ], O=>0x0200 },
-       take_imp_data   => { U =>[1,1], },
+       take_imp_data   => { U =>[1,1], O=>0x10000 },
        clone           => { U =>[1,2,'[\%attr]'] },
        connected       => { U =>[1,0], O => 0x0004 },
        begin_work      => { U =>[1,2,'[ \%attr ]'], O=>0x0400 },
@@ -420,7 +420,7 @@
        selectall_hashref=>{ U =>[3,0,'$statement, $keyfield [, \%attr [, 
@bind_params ] ]'], O=>0x2000 },
        selectcol_arrayref=>{U =>[2,0,'$statement [, \%attr [, @bind_params ] 
]'], O=>0x2000 },
        ping            => { U =>[1,1], O=>0x0404 },
-       disconnect      => { U =>[1,1], O=>0x0400|0x0800 },
+       disconnect      => { U =>[1,1], O=>0x0400|0x0800|0x10000 },
        quote           => { U =>[2,3, '$string [, $data_type ]' ], O=>0x0430 },
        quote_identifier=> { U =>[2,6, '$name [, ...] [, \%attr ]' ],    
O=>0x0430 },
        rows            => $keeperr,

Modified: dbi/trunk/DBI.xs
==============================================================================
--- dbi/trunk/DBI.xs    (original)
+++ dbi/trunk/DBI.xs    Mon Apr 23 08:34:09 2007
@@ -120,6 +120,7 @@
 #define IMA_SHOW_ERR_STMT      0x2000  /* dbh meth relates to Statement*/
 #define IMA_HIDE_ERR_PARAMVALUES 0x4000        /* ParamValues are not relevant 
*/
 #define IMA_IS_FACTORY          0x8000 /* new h ie connect and prepare */
+#define IMA_CLEAR_CACHED_KIDS  0x10000 /* clear CachedKids before call */
 
 #define DBIc_STATE_adjust(imp_xxh, state)                               \
     (SvOK(state)       /* SQLSTATE is implemented by driver   */        \
@@ -1147,16 +1148,6 @@
        }
     }
 
-    /* setup CachedKids */
-    if (DBIc_TYPE(imp) < DBIt_ST) {
-        SV **tmp_svp = hv_fetch((HV*)SvRV(h), "CachedKids", 10, 1);
-        imp_dbh_t *imp_dbh = (imp_dbh_t*)imp; /* also drh */
-        if (!SvROK(*tmp_svp) || SvTYPE(SvRV(*tmp_svp)) != SVt_PVHV) {
-           sv_setsv(*tmp_svp, newRV_noinc((SV*)newHV()));
-        }
-        DBIc_CACHED_KIDS_SVP(imp_dbh) = tmp_svp;
-    }
-
     /* Use DBI magic on inner handle to carry handle attributes        */
     sv_magic(SvRV(h), dbih_imp_sv, DBI_MAGIC, Nullch, 0);
     SvREFCNT_dec(dbih_imp_sv); /* since sv_magic() incremented it      */
@@ -1244,12 +1235,6 @@
     if (DBIc_LongReadLen(imp_xxh) != DBIc_LongReadLen_init)
        PerlIO_printf(DBILOGFP,"%s LongReadLen %ld\n", pad, 
(long)DBIc_LongReadLen(imp_xxh));
 
-    if (DBIc_TYPE(imp_xxh) <= DBIt_DB) {
-       const imp_dbh_t *imp_dbh = (imp_dbh_t*)imp_xxh;
-       HV *hv = DBIc_CACHED_KIDS(imp_dbh);
-       if (hv && HvKEYS(hv))
-           PerlIO_printf(DBILOGFP,"%s CachedKids %d\n", pad, (int)HvKEYS(hv));
-    }
     if (DBIc_TYPE(imp_xxh) == DBIt_ST) {
        const imp_sth_t *imp_sth = (imp_sth_t*)imp_xxh;
        PerlIO_printf(DBILOGFP,"%s NUM_OF_FIELDS %d\n", pad, 
DBIc_NUM_FIELDS(imp_sth));
@@ -1258,6 +1243,13 @@
     inner = dbih_inner((SV*)DBIc_MY_H(imp_xxh), msg);
     if (!inner || !SvROK(inner))
         return 1;
+    if (DBIc_TYPE(imp_xxh) <= DBIt_DB) {
+        SV **svp = hv_fetch((HV*)SvRV(inner), "CachedKids", 10, 0);
+       if (svp && SvROK(*svp) && SvTYPE(SvRV(*svp)) == SVt_PVHV) {
+            HV *hv = (HV*)SvRV(*svp);
+           PerlIO_printf(DBILOGFP,"%s CachedKids %d\n", pad, (int)HvKEYS(hv));
+        }
+    }
     if (level > 0) {
         SV* value;
        char *key;
@@ -1317,16 +1309,6 @@
        dbih_dumpcom(imp_xxh,"DESTROY (dbih_clearcom)", 0);
 
     if (!dirty) {
-       if (DBIc_TYPE(imp_xxh) <= DBIt_DB) {
-            HV *hv;
-           imp_dbh_t *imp_dbh = (imp_dbh_t*)imp_xxh; /* works for DRH also */
-           if ((hv=DBIc_CACHED_KIDS(imp_dbh)) && HvKEYS(hv)>0) {
-               warn("DBI %s handle 0x%lx cleared whilst still holding %d 
cached kids",
-                        dbih_htype_name(DBIc_TYPE(imp_xxh)),
-                       (unsigned long)DBIc_MY_H(imp_xxh), (int)HvKEYS(hv) );
-               hv_clear(hv); /* may recurse */
-           }
-       }
 
        if (DBIc_ACTIVE(imp_xxh)) {     /* bad news, potentially        */
             /* warn for sth, warn for dbh only if it has active sth or isn't 
AutoCommit */
@@ -2251,29 +2233,30 @@
 
 
 static void
-clear_cached_kids(SV *h, imp_xxh_t *imp_xxh, const char *meth_name, int 
trace_level)
+clear_cached_kids(pTHX_ SV *h, imp_xxh_t *imp_xxh, const char *meth_name, int 
trace_level)
 {
-    HV *hv;
-
-    if (DBIc_TYPE(imp_xxh) > DBIt_DB)
-        return;
-    hv = DBIc_CACHED_KIDS((imp_drh_t*)imp_xxh);
-    if (hv && HvKEYS(hv)) {
-        dTHX;
-        dPERINTERP;
-        if (DBIc_TRACE_LEVEL(imp_xxh) > trace_level)
-            trace_level = DBIc_TRACE_LEVEL(imp_xxh);
-        if (trace_level >= 2) {
-            PerlIO_printf(DBILOGFP,"    >> %s %s clearing %d CachedKids\n",
-                meth_name, neatsvpv(h,0), (int)HvKEYS(hv));
-            PerlIO_flush(DBILOGFP);
+    if (DBIc_TYPE(imp_xxh) <= DBIt_DB) {
+        SV **svp = hv_fetch((HV*)SvRV(h), "CachedKids", 10, 0);
+        if (svp && SvROK(*svp) && SvTYPE(SvRV(*svp)) == SVt_PVHV) {
+            HV *hv = (HV*)SvRV(*svp);
+            if (HvKEYS(hv)) {
+                dPERINTERP;
+                if (DBIc_TRACE_LEVEL(imp_xxh) > trace_level)
+                    trace_level = DBIc_TRACE_LEVEL(imp_xxh);
+                if (trace_level >= 2) {
+                    PerlIO_printf(DBILOGFP,"    >> %s %s clearing %d 
CachedKids\n",
+                        meth_name, neatsvpv(h,0), (int)HvKEYS(hv));
+                    PerlIO_flush(DBILOGFP);
+                }
+                /* This will probably recurse through dispatch to DESTROY the 
kids */
+                /* For drh we should probably explicitly do dbh disconnects */
+                hv_clear(hv);
+            }
         }
-        /* This will probably recurse through dispatch to DESTROY the kids */
-        /* For drh we should probably explicitly do dbh disconnects */
-        hv_clear(hv);
     }
 }
 
+
 static NV
 dbi_time() {
 # ifdef HAS_GETTIMEOFDAY
@@ -2710,7 +2693,7 @@
            }
 #endif
            if (imp_xxh && DBIc_TYPE(imp_xxh) <= DBIt_DB)
-               clear_cached_kids(mg->mg_obj, imp_xxh, meth_name, trace_level);
+               clear_cached_kids(aTHX_ mg->mg_obj, imp_xxh, meth_name, 
trace_level);
            if (trace_level >= 3) {
                 /* XXX might be better to move this down to after call_depth 
has been
                  * incremented and then also SvREFCNT_dec(mg->mg_obj) to force 
an immediate
@@ -2859,6 +2842,7 @@
                XSRETURN(0);
            }
            if (ima_flags & IMA_FUNC_REDIRECT) {
+                /* XXX this doesn't redispatch, nor consider the IMA of the 
new method */
                SV *meth_name_sv = POPs;
                PUTBACK;
                --items;
@@ -2882,6 +2866,9 @@
                /* don't use SvOK_off: dbh's Statement may be ref to sth's */
                hv_store((HV*)SvRV(h), "Statement", 9, &sv_undef, 0);
            }
+           if (ima_flags & IMA_CLEAR_CACHED_KIDS)
+                clear_cached_kids(aTHX_ h, imp_xxh, meth_name, trace_flags);
+
        }
 
        if (ima_flags & IMA_HAS_USAGE) {
@@ -2936,8 +2923,6 @@
                sv_setsv(DBIc_ERRSTR(parent_imp), DBIc_ERRSTR(imp_xxh));
                sv_setsv(DBIc_STATE(parent_imp),  DBIc_STATE(imp_xxh));
            }
-
-            clear_cached_kids(h, imp_xxh, meth_name, trace_flags);
        }
 
        if (DBIc_IADESTROY(imp_xxh)) { /* want's ineffective destroy    */
@@ -4324,8 +4309,6 @@
      * destroyed they may need to interact with the 'zombie' parent dbh.
      * So we do our best to neautralize them (finish & rebless)
      */
-    if (DBIc_TYPE(imp_xxh) <= DBIt_DB)
-       clear_cached_kids(h, imp_xxh, "take_imp_data", 0);
     if ((tmp_svp = hv_fetch((HV*)SvRV(h), "ChildHandles", 12, FALSE)) && 
SvROK(*tmp_svp)) {
        AV *av = (AV*)SvRV(*tmp_svp);
        HV *zombie_stash = gv_stashpv("DBI::zombie", GV_ADDWARN);

Modified: dbi/trunk/DBIXS.h
==============================================================================
--- dbi/trunk/DBIXS.h   (original)
+++ dbi/trunk/DBIXS.h   Mon Apr 23 08:34:09 2007
@@ -133,13 +133,13 @@
 typedef struct {               /* -- DRIVER --                         */
     dbih_com_std_t     std;
     dbih_com_attr_t    attr;
-    SV          **cached_kids_svp;      /* \($h->{CachedKids}) */
+    HV          *_old_cached_kids; /* not used, here for binary compat */
 } dbih_drc_t;
 
 typedef struct {               /* -- DATABASE --                       */
     dbih_com_std_t     std;    /* \__ standard structure               */
     dbih_com_attr_t    attr;   /* /   plus... (nothing else right now) */
-    SV          **cached_kids_svp;     /* \($h->{CachedKids}) */
+    HV          *_old_cached_kids; /* not used, here for binary compat */
 } dbih_dbc_t;
 
 typedef struct {               /* -- STATEMENT --                      */
@@ -232,8 +232,7 @@
 
 /* handle sub-type specific fields                                             
*/
 /*     dbh & drh       */
-#define DBIc_CACHED_KIDS_SVP(imp) _imp2com(imp, cached_kids_svp)
-#define DBIc_CACHED_KIDS(imp)          ((HV*)SvRV( *DBIc_CACHED_KIDS_SVP(imp) 
))
+#define DBIc_CACHED_KIDS(imp)          Nullhv /* no longer used, here for src 
compat */
 /*     sth     */
 #define DBIc_NUM_FIELDS(imp)   _imp2com(imp, num_fields)
 #define DBIc_NUM_PARAMS(imp)   _imp2com(imp, num_params)

Modified: dbi/trunk/Driver.xst
==============================================================================
--- dbi/trunk/Driver.xst        (original)
+++ dbi/trunk/Driver.xst        Mon Apr 23 08:34:09 2007
@@ -271,11 +271,6 @@
     if ( !DBIc_ACTIVE(imp_dbh) ) {
        XSRETURN_YES;
     }
-    /* pre-disconnect checks and tidy-ups */
-    if (DBIc_CACHED_KIDS(imp_dbh)) {
-       SvREFCNT_dec(DBIc_CACHED_KIDS(imp_dbh));      /* cast them to the winds 
*/
-       DBIc_CACHED_KIDS(imp_dbh) = Nullhv;
-    }
     /* Check for disconnect() being called whilst refs to cursors      */
     /* still exists. This possibly needs some more thought.            */
     if (DBIc_ACTIVE_KIDS(imp_dbh) && DBIc_WARN(imp_dbh) && !dirty) {
@@ -331,11 +326,6 @@
                    SvPV(dbh,lna));
     }
     else {
-       /* pre-disconnect checks and tidy-ups */
-       if (DBIc_CACHED_KIDS(imp_dbh)) {
-           SvREFCNT_dec(DBIc_CACHED_KIDS(imp_dbh));  /* cast them to the winds 
*/
-           DBIc_CACHED_KIDS(imp_dbh) = Nullhv;
-       }
         if (DBIc_IADESTROY(imp_dbh)) {           /* want's ineffective destroy 
*/
             DBIc_ACTIVE_off(imp_dbh);
            if (DBIc_DBISTATE(imp_dbh)->debug)

Modified: dbi/trunk/lib/DBI/PurePerl.pm
==============================================================================
--- dbi/trunk/lib/DBI/PurePerl.pm       (original)
+++ dbi/trunk/lib/DBI/PurePerl.pm       Mon Apr 23 08:34:09 2007
@@ -128,6 +128,7 @@
 use constant IMA_SHOW_ERR_STMT  => 0x2000; #/* dbh meth relates to Statement*/
 use constant IMA_HIDE_ERR_PARAMVALUES => 0x4000; #/* ParamValues are not 
relevant */
 use constant IMA_IS_FACTORY     => 0x8000; #/* new h ie connect & prepare */
+use constant IMA_CLEAR_CACHED_KIDS    => 0x10000; #/* clear CachedKids before 
call */
 
 my %is_flag_attribute = map {$_ =>1 } qw(
        Active
@@ -248,6 +249,10 @@
        $parent_dbh->{Executed} = 1 if $parent_dbh;
     } if IMA_EXECUTE & $bitmask;
 
+    push @pre_call_frag, q{
+       %{ $h->{CachedKids} } = () if $h->{CachedKids};
+    } if IMA_CLEAR_CACHED_KIDS & $bitmask;
+
     if (IMA_KEEP_ERR & $bitmask) {
        push @pre_call_frag, q{
            my $keep_error = 1;
@@ -484,7 +489,6 @@
        }
        elsif (ref($parent) =~ /::dr$/){
            $h_inner->{Driver} = $parent;
-            $h_inner->{CachedKids} ||= {};
        }
        $h_inner->{_parent} = $parent;
 
@@ -509,7 +513,6 @@
        $h_inner->{FetchHashKeyName}    ||= 'NAME';
        $h_inner->{LongReadLen}         ||= 80;
        $h_inner->{ChildHandles}        ||= [] if $HAS_WEAKEN;
-       $h_inner->{CachedKids}          ||= {};
        $h_inner->{Type}                ||= 'dr';
     }
     $h_inner->{"_call_depth"} = 0;

Modified: dbi/trunk/t/01basics.t
==============================================================================
--- dbi/trunk/t/01basics.t      (original)
+++ dbi/trunk/t/01basics.t      Mon Apr 23 08:34:09 2007
@@ -2,7 +2,7 @@
 
 use strict;
 
-use Test::More tests => 131;
+use Test::More tests => 130;
 use File::Spec;
 
 $|=1;
@@ -176,8 +176,7 @@
 cmp_ok(($switch->{private_test1} = 1), '==', 1, '... this should work and 
return 1');
 cmp_ok($switch->{private_test1},       '==', 1, '... this should equal 1');
 
-is(ref($switch->{CachedKids}), 'HASH', '... CachedKids should be a HASH 
reference');
-ok(!keys %{ $switch->{CachedKids} },   '... CachedKids should be empty');
+is($switch->{CachedKids}, undef, '... CachedKids should be undef initially');
 my $cache = {};
 $switch->{CachedKids} = $cache;
 is($switch->{CachedKids}, $cache,      '... CachedKids should be our ref');

Modified: dbi/trunk/t/06attrs.t
==============================================================================
--- dbi/trunk/t/06attrs.t       (original)
+++ dbi/trunk/t/06attrs.t       Mon Apr 23 08:34:09 2007
@@ -61,7 +61,7 @@
     cmp_ok($dbh->{ActiveKids}, '==', 0, '... checking ActiveKids attribute for 
dbh');;
 }
 
-is(ref $dbh->{CachedKids},'HASH', '... checking CachedKids attribute for dbh');
+is($dbh->{CachedKids}, undef,     '... checking CachedKids attribute for dbh');
 ok(!defined $dbh->{HandleError},  '... checking HandleError attribute for 
dbh');
 ok(!defined $dbh->{Profile},      '... checking Profile attribute for dbh');
 ok(!defined $dbh->{Statement},    '... checking Statement attribute for dbh');
@@ -128,7 +128,7 @@
     cmp_ok($drh->{ActiveKids}, '==', 1, '... checking ActiveKids attribute for 
drh');
 }
 
-is(ref $drh->{CachedKids},'HASH','... checking CachedKids attribute for drh');
+is($drh->{CachedKids}, undef,    '... checking CachedKids attribute for drh');
 ok(!defined $drh->{HandleError}, '... checking HandleError attribute for drh');
 ok(!defined $drh->{Profile},     '... checking Profile attribute for drh');
 

Reply via email to