Author: timbo
Date: Fri Feb 13 16:30:25 2004
New Revision: 58
Modified:
dbi/trunk/Changes
dbi/trunk/DBI.pm
dbi/trunk/DBI.xs
dbi/trunk/DBIXS.h
dbi/trunk/Driver.xst
Log:
Add new $h->{Executed} attribute and use it to control the
rollback warning issued when an active non-autocommit dbh is destroyed.
Modified: dbi/trunk/Changes
==============================================================================
--- dbi/trunk/Changes (original)
+++ dbi/trunk/Changes Fri Feb 13 16:30:25 2004
@@ -6,9 +6,9 @@
=head1 CHANGES
-Change to let drivers use set_err to record errors
Drivers to change how they get debug level (with masked bits).
Extra hooks in Driver.xst for bind_col etc
+Add tests for $h->{Executed}
Fixed execute_for_array() so tuple_status parameter is optional
as per docs, thanks to Ed Avis.
@@ -33,6 +33,7 @@
point that an error, warn, or info state is recorded.
The code can alter the err, errstr, and state values
(e.g., to promote an error to a warning, or the reverse).
+ Added $h->{Executed} attribute set if do()/execute() called.
Added details of DBI::Const::GetInfoType module to get_info() docs.
Added ref count of inner handle to "DESTROY ignored for outer" msg.
Added Win32 build config checks to DBI::DBD thanks to Andy Hassall.
Modified: dbi/trunk/DBI.pm
==============================================================================
--- dbi/trunk/DBI.pm (original)
+++ dbi/trunk/DBI.pm Fri Feb 13 16:30:25 2004
@@ -389,7 +389,7 @@
begin_work => { U =>[1,2,'[ \%attr ]'], O=>0x0400 },
commit => { U =>[1,1], O=>0x0480|0x0800 },
rollback => { U =>[1,1], O=>0x0480|0x0800 },
- 'do' => { U =>[2,0,'$statement [, \%attr [, @bind_params ] ]'],
O=>0x0200 },
+ 'do' => { U =>[2,0,'$statement [, \%attr [, @bind_params ] ]'],
O=>0x1200 },
last_insert_id => { U =>[3,4,'$table_name, $field_name [, \%attr ]'],
O=>0x0100 },
preparse => { }, # XXX
prepare => { U =>[2,3,'$statement [, \%attr]'], O=>0x0200 },
@@ -423,12 +423,12 @@
bind_columns => { U =>[2,0,'\\$var1 [, \\$var2, ...]'] },
bind_param => { U =>[3,4,'$parameter, $var [, \%attr]'] },
bind_param_inout=> { U =>[4,5,'$parameter, \\$var, $maxlen, [, \%attr]'] },
- execute => { U =>[1,0,'[EMAIL PROTECTED]'], O=>0x40 },
+ execute => { U =>[1,0,'[EMAIL PROTECTED]'], O=>0x1040 },
bind_param_array => { U =>[3,4,'$parameter, $var [, \%attr]'] },
bind_param_inout_array => { U =>[4,5,'$parameter, [EMAIL PROTECTED], $maxlen,
[, \%attr]'] },
- execute_array => { U =>[2,0,'\\%attribs [, @args]'] },
- execute_for_fetch => { U =>[2,3,'$fetch_sub [, $tuple_status]'] },
+ execute_array => { U =>[2,0,'\\%attribs [, @args]'], O=>0x1040 },
+ execute_for_fetch => { U =>[2,3,'$fetch_sub [, $tuple_status]'], O=>0x1040 },
fetch => undef, # alias for fetchrow_arrayref
fetchrow_arrayref => undef,
@@ -2815,6 +2815,20 @@
that may have more data to fetch. (Fetching all the data or calling
C<$sth-E<gt>finish>
sets C<Active> off.)
+=item C<Executed> (boolean)
+
+The C<Executed> attribute is true if the handle object has been "executed".
+Currently only the $dbh do() method and the $sth execute(), execute_array(),
+and execute_for_fetch() methods set the C<Executed> attribute.
+
+When it's on a handle it is also set on the parent handle at the
+same time. So calling execute() on a $sth also sets the C<Executed>
+attribute on the parent $dbh.
+
+The C<Executed> attribute for a $dbh is cleared by the commit() and
+rollback() methods. (The C<Executed> attribute of any child statement
+handles are not cleared.)
+
=item C<Kids> (integer, read-only)
For a driver handle, C<Kids> is the number of currently existing database
Modified: dbi/trunk/DBI.xs
==============================================================================
--- dbi/trunk/DBI.xs (original)
+++ dbi/trunk/DBI.xs Fri Feb 13 16:30:25 2004
@@ -110,6 +110,7 @@
#define IMA_CLEAR_STMT 0x0200 /* clear Statement before call */
#define IMA_PROF_EMPTY_STMT 0x0400 /* profile as empty Statement */
#define IMA_NOT_FOUND_OKAY 0x0800 /* no error if not found */
+#define IMA_EXECUTE 0x1000 /* do/execute: DBIcf_Executed */
#define DBIc_STATE_adjust(imp_xxh, state) \
(SvOK(state) /* SQLSTATE is implemented by driver */ \
@@ -1298,13 +1299,7 @@
PerlIO_printf(DBILOGFP," STORE %s %s => %s\n",
neatsvpv(h,0), neatsvpv(keysv,0), neatsvpv(valuesv,0));
- if (strEQ(key, "CompatMode")) {
- (on) ? DBIc_COMPAT_on(imp_xxh) : DBIc_COMPAT_off(imp_xxh);
- }
- else if (strEQ(key, "Warn")) {
- (on) ? DBIc_WARN_on(imp_xxh) : DBIc_WARN_off(imp_xxh);
- }
- else if (internal && strEQ(key, "Active")) {
+ if (internal && strEQ(key, "Active")) {
if (on) {
D_imp_sth(h);
DBIc_ACTIVE_on(imp_xxh);
@@ -1317,22 +1312,31 @@
DBIc_ACTIVE_off(imp_xxh);
}
}
- else if (strEQ(key, "InactiveDestroy")) {
- (on) ? DBIc_IADESTROY_on(imp_xxh) : DBIc_IADESTROY_off(imp_xxh);
- }
else if (strEQ(key, "FetchHashKeyName")) {
if (htype >= DBIt_ST)
croak("Can't set FetchHashKeyName for a statement handle, set in parent
before prepare()");
cacheit = 1; /* just save it */
}
+ else if (strEQ(key, "CompatMode")) {
+ (on) ? DBIc_COMPAT_on(imp_xxh) : DBIc_COMPAT_off(imp_xxh);
+ }
+ else if (strEQ(key, "Warn")) {
+ (on) ? DBIc_WARN_on(imp_xxh) : DBIc_WARN_off(imp_xxh);
+ }
+ else if (strEQ(key, "InactiveDestroy")) {
+ (on) ? DBIc_IADESTROY_on(imp_xxh) : DBIc_IADESTROY_off(imp_xxh);
+ }
else if (strEQ(key, "RootClass")) {
cacheit = 1; /* just save it */
}
else if (strEQ(key, "RowCacheSize")) {
cacheit = 0; /* ignore it */
}
+ else if (strEQ(key, "Executed")) {
+ DBIc_set(imp_xxh, DBIcf_Executed, on);
+ }
else if (strEQ(key, "ChopBlanks")) {
- DBIc_set(imp_xxh,DBIcf_ChopBlanks, on);
+ DBIc_set(imp_xxh, DBIcf_ChopBlanks, on);
}
else if (strEQ(key, "LongReadLen")) {
if (SvNV(valuesv) < 0 || SvNV(valuesv) > MAX_LongReadLen)
@@ -1661,6 +1665,12 @@
}
break;
+ case 'E':
+ if (strEQ(key, "Executed")) {
+ valuesv = boolSV(DBIc_is(imp_xxh, DBIcf_Executed));
+ }
+ break;
+
case 'I':
if (strEQ(key, "InactiveDestroy")) {
valuesv = boolSV(DBIc_IADESTROY(imp_xxh));
@@ -2295,7 +2305,7 @@
/* Check method call against Internal Method Attributes */
if (ima) {
- if (ima->flags &
(IMA_STUB|IMA_FUNC_REDIRECT|IMA_KEEP_ERR|IMA_KEEP_ERR_SUB|IMA_CLEAR_STMT)) {
+ if (ima->flags &
(IMA_STUB|IMA_FUNC_REDIRECT|IMA_KEEP_ERR|IMA_KEEP_ERR_SUB|IMA_CLEAR_STMT|IMA_EXECUTE))
{
if (ima->flags & IMA_STUB) {
if (*meth_name == 'c' && strEQ(meth_name,"can")) {
@@ -2328,6 +2338,12 @@
neatsvpv(h,0), meth_name, neatsvpv(meth_name_sv,0));
meth_name = SvPV(meth_name_sv, lna);
}
+ if (ima->flags & IMA_EXECUTE) {
+ imp_xxh_t *parent = DBIc_PARENT_COM(imp_xxh);
+ DBIc_on(imp_xxh, DBIcf_Executed);
+ if (parent)
+ DBIc_on(parent, DBIcf_Executed);
+ }
if (ima->flags & IMA_KEEP_ERR)
keep_error = TRUE;
if (ima->flags & IMA_KEEP_ERR_SUB
@@ -2648,6 +2664,8 @@
}
if (ima && ima->flags & IMA_END_WORK) { /* commit() or rollback() */
+ DBIc_off(imp_xxh, DBIcf_Executed);
+
if (DBIc_has(imp_xxh, DBIcf_BegunWork)) {
DBIc_off(imp_xxh, DBIcf_BegunWork);
if (!DBIc_has(imp_xxh, DBIcf_AutoCommit)) {
Modified: dbi/trunk/DBIXS.h
==============================================================================
--- dbi/trunk/DBIXS.h (original)
+++ dbi/trunk/DBIXS.h Fri Feb 13 16:30:25 2004
@@ -239,12 +239,13 @@
#define DBIcf_Profile 0x010000 /* profile activity on this handle */
#define DBIcf_TaintIn 0x020000 /* check inputs for taintedness */
#define DBIcf_TaintOut 0x040000 /* taint outgoing data */
+#define DBIcf_Executed 0x080000 /* do/execute called since commit/rollb */
/* NOTE: new flags may require clone() to be updated */
#define DBIcf_INHERITMASK /* what NOT to pass on to children */ \
(U32)( DBIcf_COMSET | DBIcf_IMPSET | DBIcf_ACTIVE | DBIcf_IADESTROY \
/* These are for dbh only: */ \
- | DBIcf_AutoCommit | DBIcf_BegunWork )
+ | DBIcf_AutoCommit | DBIcf_BegunWork | DBIcf_Executed )
/* general purpose bit setting and testing macros */
#define DBIbf_is( bitset,flag) ((bitset) & (flag))
Modified: dbi/trunk/Driver.xst
==============================================================================
--- dbi/trunk/Driver.xst (original)
+++ dbi/trunk/Driver.xst Fri Feb 13 16:30:25 2004
@@ -345,7 +345,10 @@
/* Perl will call DESTROY on the dbh and, if we don't rollback, */
/* the server may automatically commit! Bham! Corrupt database! */
if (!DBIc_has(imp_dbh,DBIcf_AutoCommit)) {
- if (DBIc_WARN(imp_dbh) && (!dirty || DBIc_DBISTATE(imp_dbh)->debug >=
3))
+ if (DBIc_WARN(imp_dbh)
+ && DBIc_is(imp_dbh, DBIcf_Executed)
+ && (!dirty || DBIc_DBISTATE(imp_dbh)->debug >= 3)
+ )
warn("Issuing rollback() for database handle being DESTROY'd
without explicit disconnect()");
dbd_db_rollback(dbh, imp_dbh); /* ROLLBACK! */
}