Re: Is it correct that execute_array does not raise/print an error

2006-07-05 Thread Martin J. Evans
Tim,

Thanks for the clarification and untested patch. I've tried it and it now
fails (returns undef) and the HandleError routine is called. The error I'm
getting now is:

executing ARRAY(0x8ce4c08) generated 1

Changing your patch to:

return $sth-set_err(1, executing  . join(,, @{$tuple_status}) . 
generated $err_count errors)

is every so slightly more useful, since it produces:

executing 1,ARRAY(0x981d698),1,1 generated 1 errors

which makes it obvious which row failed. The error handler gets a
better error message of:

DBD::Oracle::st execute_array failed: executing 1,ARRAY(0x8869c08),1,1
generated 1 errors [for Statement insert into mytest values (?,?) with
ParamValues: :p1=53, :p2='one']

Just one note. This breaks t/15array.t around about line 48 because the test
has RaiseError and PrintError turned on and expects the execute_array to fail.
Turning them off before the test and back on again after fixes.

Thanks again.

Martin
--
Martin J. Evans
Easysoft Ltd, UK
http://www.easysoft.com


On 04-Jul-2006 Tim Bunce wrote:
 On Tue, Jul 04, 2006 at 02:18:33PM +0100, Martin J. Evans wrote:
 
 Thanks for the explanation. You have not however convinced me this behavior
 is
 right. If RaiseError caused a die on error and someone wanted to ignore
 errors
 they could just do what they always do - turn RaiseError off and do the
 checking themselves.
 
 What I was really after was whether not dying on an error in execute_array
 when RaiseError was enabled was by design or a an oversight.
 
 An oversight. Though the oversight is actually in execute_for_fetch()
 which execute_array() array calls to do the real work.
 
 It makes a
 difference to me since I read the DBI docs and saw nothing which said
 RaiseError does not work with execute_array, then discovered it didn't,
 worked around this in my DBIx extension but would like to document why I
 have this workaround.
 
 Try this (untested):
 
 --- DBI.pm  (revision 6604)
 +++ DBI.pm  (working copy)
 @@ -1931,7 +1931,10 @@
 push @$tuple_status, [ $err, $errstr_cache{$err} ||=
 $sth-errstr, $sth-state ];
 }
 }
 -   return ($err_count) ? undef : scalar(@$tuple_status)||0E0;
 +my $tuples = @$tuple_status;
 +return $sth-set_err(1, executing $tuple_status generated
 $err_count errors)
 +if $err_count;
 +   return scalar(@$tuple_status) || 0E0;
  }
  
 Tim.


Re: Is it correct that execute_array does not raise/print an error

2006-07-05 Thread Tim Bunce
On Wed, Jul 05, 2006 at 01:38:04PM +0100, Martin J. Evans wrote:
 Tim,
 
 Thanks for the clarification and untested patch. I've tried it and it now
 fails (returns undef) and the HandleError routine is called. The error I'm
 getting now is:
 
 executing ARRAY(0x8ce4c08) generated 1

D'oh. Thanks.

 Changing your patch to:
 
 return $sth-set_err(1, executing  . join(,, @{$tuple_status}) . 
 generated $err_count errors)
 
 is every so slightly more useful, since it produces:
 
 executing 1,ARRAY(0x981d698),1,1 generated 1 errors
 
 which makes it obvious which row failed.

You might not think it more useful if the batch had 10,000 tuples in it!
I think I'll stick with just a count.

 The error handler gets a better error message of:
 
 DBD::Oracle::st execute_array failed: executing 1,ARRAY(0x8869c08),1,1
 generated 1 errors [for Statement insert into mytest values (?,?) with
 ParamValues: :p1=53, :p2='one']

Um, including ParamValues is somewhat misleading in this situation.

 Just one note. This breaks t/15array.t around about line 48 because the test
 has RaiseError and PrintError turned on and expects the execute_array to fail.
 Turning them off before the test and back on again after fixes.

Thanks.

Try the attached patch on top of the previous one.

Tim.
Index: t/15array.t
===
--- t/15array.t (revision 6474)
+++ t/15array.t (working copy)
@@ -2,7 +2,7 @@
 
 use strict;
 
-use Test::More tests = 50;
+use Test::More tests = 52;
 
 ## 
 ## 15array.t
@@ -45,7 +45,7 @@
 
 # ---
 
-ok(!$sth-execute_array(
+ok(! eval { $sth-execute_array(
{ 
ArrayTupleStatus = $tuple_status 
},
@@ -53,9 +53,11 @@
42,   # scalar 42 treated as array 
of 42's
undef,# scalar undef treated as array 
of undef's
[ qw(A B C) ],# array of strings
-),
-   '... execute_array should return false'
+) },
+'... execute_array should return false'
 );
+ok $@, 'execute_array failure with RaiseError should have died';
+like $sth-errstr, '/executing 3 generated 1 errors/';
 
 cmp_ok(scalar @{$rows}, '==', 2, '... we should have 2 rows');
 cmp_ok(scalar @{$tuple_status}, '==', 3, '... we should have 3 tuple_status');
Index: DBI.pm
===
--- DBI.pm  (revision 6616)
+++ DBI.pm  (working copy)
@@ -1932,7 +1932,7 @@
}
}
 my $tuples = @$tuple_status;
-return $sth-set_err(1, executing $tuple_status generated $err_count 
errors)
+return $sth-set_err(1, executing $tuples generated $err_count 
errors)
 if $err_count;
return scalar(@$tuple_status) || 0E0;
 }


Re: Is it correct that execute_array does not raise/print an error

2006-07-05 Thread Martin J. Evans

On 05-Jul-2006 Tim Bunce wrote:
 On Wed, Jul 05, 2006 at 01:38:04PM +0100, Martin J. Evans wrote:
 Tim,
 
 Thanks for the clarification and untested patch. I've tried it and it now
 fails (returns undef) and the HandleError routine is called. The error I'm
 getting now is:
 
 executing ARRAY(0x8ce4c08) generated 1
 
 D'oh. Thanks.
 
 Changing your patch to:
 
 return $sth-set_err(1, executing  . join(,, @{$tuple_status}) . 
 generated $err_count errors)
 
 is every so slightly more useful, since it produces:
 
 executing 1,ARRAY(0x981d698),1,1 generated 1 errors
 
 which makes it obvious which row failed.
 
 You might not think it more useful if the batch had 10,000 tuples in it!
 I think I'll stick with just a count.

Argh, yes, good point.

 The error handler gets a better error message of:
 
 DBD::Oracle::st execute_array failed: executing 1,ARRAY(0x8869c08),1,1
 generated 1 errors [for Statement insert into mytest values (?,?) with
 ParamValues: :p1=53, :p2='one']
 
 Um, including ParamValues is somewhat misleading in this situation.

Yes, I meant to mention that - the params given are the last ones in the array
and not the failing ones which were :p1=1 and :p2='fiftytwo' in this case.

 Just one note. This breaks t/15array.t around about line 48 because the test
 has RaiseError and PrintError turned on and expects the execute_array to
 fail.
 Turning them off before the test and back on again after fixes.
 
 Thanks.
 
 Try the attached patch on top of the previous one.

Done - works better:

I know get:

executing 4 generated 1 errors

which is correct.

execute_array still returns undef - good.

the two new tests in 15array.t pass and the original one I mentioned passes
although it still throws

t/15arrayok 1/52DBD::Sponge::st execute_array failed: executing
3 generated 1 errors at t/15array.t line 48.

on stdout (PrintError?).

Thanks.

Martin
--
Martin J. Evans
Easysoft Ltd, UK
http://www.easysoft.com



Re: Is it correct that execute_array does not raise/print an error

2006-07-04 Thread John Scoles
It memory serves me correctly I think any errors that are generated is
stored in the ArrayTupleStatus have a parse through that array to see it the
error is stored there.


- Original Message - 
From: Martin J. Evans [EMAIL PROTECTED]
To: dbi-users@perl.org
Sent: Tuesday, July 04, 2006 6:37 AM
Subject: Is it correct that execute_array does not raise/print an error


 Hi,

 I have some code which uses execute_array but it appears when it fails
 my error handler is not called and no error is printed despite setting
 PrintError and RaiseError. The script below illustrates. Is it correct
that an
 error can occur in execute_array and it not cause a die when RaiseError is
set?

 use DBI;
 use strict;
 use Data::Dumper;

 sub fred
 {
 print Error Handler called\n;
 print Dumper([EMAIL PROTECTED]);
 }

 my $dbh = DBI-connect(
 'DBI:mysql:mjetest', 'xxx', 'yyy',
 { RaiseError = 1, PrintError = 1, HandleError = \fred});
 $dbh-do(q/drop table if exists mytest/);
 $dbh-do(q/create table mytest (a int primary key, b char(20))/);

 my $sth = $dbh-prepare(q/insert into mytest values (?,?)/);
 $sth-bind_param(1, 1);
 $sth-bind_param(2, 'onetwothree');
 $sth-execute;

 $sth-bind_param_array(1, [51,1,52,53]);
 $sth-bind_param_array(2, ['fiftyone', 'fiftytwo', 'fiftythree', 'one']);
 my @tuple_status;
 my $inserted = $sth-execute_array( { ArrayTupleStatus =
[EMAIL PROTECTED] } );
 print Error from execute_array - $DBI::errstr\n if (!$inserted);

 which produces:

 Error from execute_array -

 even though the trace indicates:

 - prepare('insert into mytest values (?,?)')= DBI::st=HASH(0x82a1b80)
at
 execute_array.pl line 17
 - bind_param(1 1)= 1 at execute_array.pl line 18
 - bind_param(2 'onetwothree')= 1 at execute_array.pl line 19
 - execute= 1 at execute_array.pl line 20
 - bind_param_array(1 ARRAY(0x829d4f8))= 1 at execute_array.pl line 22
 - bind_param_array(2 ARRAY(0x829d534))= 1 at execute_array.pl line 23
 - execute_array(HASH(0x829d5c4))= undef at execute_array.pl line 26


 Thanks

 Martin
 --
 Martin J. Evans
 Easysoft Ltd, UK
 http://www.easysoft.com





Re: Is it correct that execute_array does not raise/print an error

2006-07-04 Thread Martin J. Evans

On 04-Jul-2006 John Scoles wrote:
 It memory serves me correctly I think any errors that are generated is
 stored in the ArrayTupleStatus have a parse through that array to see it the
 error is stored there.

John,

They are stored in the ArrayTupleStatus. I'm not saying I can't get them, but I
rather thought since they were errors that RaiseError would cause a die and
that my HandleError routine would be called - neither seems to occur. Unless
I'm mistaken this seems to make execute_array a special case and thus
RaiseError should say it causes a die for all error in methods except
execute_array (and similarly for HandleError).

Martin
--
Martin J. Evans
Easysoft Ltd, UK
http://www.easysoft.com

 
 - Original Message - 
 From: Martin J. Evans [EMAIL PROTECTED]
 To: dbi-users@perl.org
 Sent: Tuesday, July 04, 2006 6:37 AM
 Subject: Is it correct that execute_array does not raise/print an error
 
 
 Hi,

 I have some code which uses execute_array but it appears when it fails
 my error handler is not called and no error is printed despite setting
 PrintError and RaiseError. The script below illustrates. Is it correct
 that an
 error can occur in execute_array and it not cause a die when RaiseError is
 set?

 use DBI;
 use strict;
 use Data::Dumper;

 sub fred
 {
 print Error Handler called\n;
 print Dumper([EMAIL PROTECTED]);
 }

 my $dbh = DBI-connect(
 'DBI:mysql:mjetest', 'xxx', 'yyy',
 { RaiseError = 1, PrintError = 1, HandleError = \fred});
 $dbh-do(q/drop table if exists mytest/);
 $dbh-do(q/create table mytest (a int primary key, b char(20))/);

 my $sth = $dbh-prepare(q/insert into mytest values (?,?)/);
 $sth-bind_param(1, 1);
 $sth-bind_param(2, 'onetwothree');
 $sth-execute;

 $sth-bind_param_array(1, [51,1,52,53]);
 $sth-bind_param_array(2, ['fiftyone', 'fiftytwo', 'fiftythree', 'one']);
 my @tuple_status;
 my $inserted = $sth-execute_array( { ArrayTupleStatus =
 [EMAIL PROTECTED] } );
 print Error from execute_array - $DBI::errstr\n if (!$inserted);

 which produces:

 Error from execute_array -

 even though the trace indicates:

 - prepare('insert into mytest values (?,?)')= DBI::st=HASH(0x82a1b80)
 at
 execute_array.pl line 17
 - bind_param(1 1)= 1 at execute_array.pl line 18
 - bind_param(2 'onetwothree')= 1 at execute_array.pl line 19
 - execute= 1 at execute_array.pl line 20
 - bind_param_array(1 ARRAY(0x829d4f8))= 1 at execute_array.pl line 22
 - bind_param_array(2 ARRAY(0x829d534))= 1 at execute_array.pl line 23
 - execute_array(HASH(0x829d5c4))= undef at execute_array.pl line 26


 Thanks

 Martin
 --
 Martin J. Evans
 Easysoft Ltd, UK
 http://www.easysoft.com





Re: Is it correct that execute_array does not raise/print an error

2006-07-04 Thread John Scoles
Yes execute_array is a special case.

What DBI does is pass the Array of  Tuples off to the native array interface
of the database for processing and expects back a Tuple of results.
Not sure what the exact call is in MYSQL but I know for Oracle this is what
OCI (the native Oracle interface) is doing. So it is a case of DBI::DBD
mimicking what the native driver is doing.

As execute_array is normally use to inserts/update of millions of records
and with this volume you would not want your process to choke on just one
bad record so it makes sense to look for errors after the process has run
rather that stopping at each one.

This being said if the DBD driver does not support an array interface DBI
simply mimics this behaviour by iterating though the array. Not real time
saving there it just follows the array interface model.

Cheers

John Scoles

- Original Message - 
From: Martin J. Evans [EMAIL PROTECTED]
To: dbi-users@perl.org
Sent: Tuesday, July 04, 2006 8:03 AM
Subject: Re: Is it correct that execute_array does not raise/print an error



 On 04-Jul-2006 John Scoles wrote:
  It memory serves me correctly I think any errors that are generated is
  stored in the ArrayTupleStatus have a parse through that array to see it
the
  error is stored there.

 John,

 They are stored in the ArrayTupleStatus. I'm not saying I can't get them,
but I
 rather thought since they were errors that RaiseError would cause a die
and
 that my HandleError routine would be called - neither seems to occur.
Unless
 I'm mistaken this seems to make execute_array a special case and thus
 RaiseError should say it causes a die for all error in methods except
 execute_array (and similarly for HandleError).

 Martin
 --
 Martin J. Evans
 Easysoft Ltd, UK
 http://www.easysoft.com

 
  - Original Message - 
  From: Martin J. Evans [EMAIL PROTECTED]
  To: dbi-users@perl.org
  Sent: Tuesday, July 04, 2006 6:37 AM
  Subject: Is it correct that execute_array does not raise/print an error
 
 
  Hi,
 
  I have some code which uses execute_array but it appears when it fails
  my error handler is not called and no error is printed despite setting
  PrintError and RaiseError. The script below illustrates. Is it correct
  that an
  error can occur in execute_array and it not cause a die when RaiseError
is
  set?
 
  use DBI;
  use strict;
  use Data::Dumper;
 
  sub fred
  {
  print Error Handler called\n;
  print Dumper([EMAIL PROTECTED]);
  }
 
  my $dbh = DBI-connect(
  'DBI:mysql:mjetest', 'xxx', 'yyy',
  { RaiseError = 1, PrintError = 1, HandleError = \fred});
  $dbh-do(q/drop table if exists mytest/);
  $dbh-do(q/create table mytest (a int primary key, b char(20))/);
 
  my $sth = $dbh-prepare(q/insert into mytest values (?,?)/);
  $sth-bind_param(1, 1);
  $sth-bind_param(2, 'onetwothree');
  $sth-execute;
 
  $sth-bind_param_array(1, [51,1,52,53]);
  $sth-bind_param_array(2, ['fiftyone', 'fiftytwo', 'fiftythree',
'one']);
  my @tuple_status;
  my $inserted = $sth-execute_array( { ArrayTupleStatus =
  [EMAIL PROTECTED] } );
  print Error from execute_array - $DBI::errstr\n if (!$inserted);
 
  which produces:
 
  Error from execute_array -
 
  even though the trace indicates:
 
  - prepare('insert into mytest values (?,?)')=
DBI::st=HASH(0x82a1b80)
  at
  execute_array.pl line 17
  - bind_param(1 1)= 1 at execute_array.pl line 18
  - bind_param(2 'onetwothree')= 1 at execute_array.pl line 19
  - execute= 1 at execute_array.pl line 20
  - bind_param_array(1 ARRAY(0x829d4f8))= 1 at execute_array.pl line
22
  - bind_param_array(2 ARRAY(0x829d534))= 1 at execute_array.pl line
23
  - execute_array(HASH(0x829d5c4))= undef at execute_array.pl line
26
 
 
  Thanks
 
  Martin
  --
  Martin J. Evans
  Easysoft Ltd, UK
  http://www.easysoft.com
 
 





Re: Is it correct that execute_array does not raise/print an error

2006-07-04 Thread Martin J. Evans
John,

On 04-Jul-2006 John Scoles wrote:
 Yes execute_array is a special case.
 
 What DBI does is pass the Array of  Tuples off to the native array interface
 of the database for processing and expects back a Tuple of results.

As an aside, I'm not sure this is always the case. I'm sure I read in the DBI
docs you could pass a function reference in which would be used to retrieve the
tuples.

 Not sure what the exact call is in MYSQL but I know for Oracle this is what
 OCI (the native Oracle interface) is doing. So it is a case of DBI::DBD
 mimicking what the native driver is doing.
 
 As execute_array is normally use to inserts/update of millions of records
 and with this volume you would not want your process to choke on just one
 bad record so it makes sense to look for errors after the process has run
 rather that stopping at each one.
 
 This being said if the DBD driver does not support an array interface DBI
 simply mimics this behaviour by iterating though the array. Not real time
 saving there it just follows the array interface model.
 
 Cheers
 
 John Scoles

Thanks for the explanation. You have not however convinced me this behavior is
right. If RaiseError caused a die on error and someone wanted to ignore errors
they could just do what they always do - turn RaiseError off and do the
checking themselves.

What I was really after was whether not dying on an error in execute_array
when RaiseError was enabled was by design or a an oversight. It makes a
difference to me since I read the DBI docs and saw nothing which said
RaiseError does not work with execute_array, then discovered it didn't,
worked around this in my DBIx extension but would like to document why I
have this workaround.

Martin
--
Martin J. Evans
Easysoft Ltd, UK
http://www.easysoft.com


 - Original Message - 
 From: Martin J. Evans [EMAIL PROTECTED]
 To: dbi-users@perl.org
 Sent: Tuesday, July 04, 2006 8:03 AM
 Subject: Re: Is it correct that execute_array does not raise/print an error
 
 

 On 04-Jul-2006 John Scoles wrote:
  It memory serves me correctly I think any errors that are generated is
  stored in the ArrayTupleStatus have a parse through that array to see it
 the
  error is stored there.

 John,

 They are stored in the ArrayTupleStatus. I'm not saying I can't get them,
 but I
 rather thought since they were errors that RaiseError would cause a die
 and
 that my HandleError routine would be called - neither seems to occur.
 Unless
 I'm mistaken this seems to make execute_array a special case and thus
 RaiseError should say it causes a die for all error in methods except
 execute_array (and similarly for HandleError).

 Martin
 --
 Martin J. Evans
 Easysoft Ltd, UK
 http://www.easysoft.com

 
  - Original Message - 
  From: Martin J. Evans [EMAIL PROTECTED]
  To: dbi-users@perl.org
  Sent: Tuesday, July 04, 2006 6:37 AM
  Subject: Is it correct that execute_array does not raise/print an error
 
 
  Hi,
 
  I have some code which uses execute_array but it appears when it fails
  my error handler is not called and no error is printed despite setting
  PrintError and RaiseError. The script below illustrates. Is it correct
  that an
  error can occur in execute_array and it not cause a die when RaiseError
 is
  set?
 
  use DBI;
  use strict;
  use Data::Dumper;
 
  sub fred
  {
  print Error Handler called\n;
  print Dumper([EMAIL PROTECTED]);
  }
 
  my $dbh = DBI-connect(
  'DBI:mysql:mjetest', 'xxx', 'yyy',
  { RaiseError = 1, PrintError = 1, HandleError = \fred});
  $dbh-do(q/drop table if exists mytest/);
  $dbh-do(q/create table mytest (a int primary key, b char(20))/);
 
  my $sth = $dbh-prepare(q/insert into mytest values (?,?)/);
  $sth-bind_param(1, 1);
  $sth-bind_param(2, 'onetwothree');
  $sth-execute;
 
  $sth-bind_param_array(1, [51,1,52,53]);
  $sth-bind_param_array(2, ['fiftyone', 'fiftytwo', 'fiftythree',
 'one']);
  my @tuple_status;
  my $inserted = $sth-execute_array( { ArrayTupleStatus =
  [EMAIL PROTECTED] } );
  print Error from execute_array - $DBI::errstr\n if (!$inserted);
 
  which produces:
 
  Error from execute_array -
 
  even though the trace indicates:
 
  - prepare('insert into mytest values (?,?)')=
 DBI::st=HASH(0x82a1b80)
  at
  execute_array.pl line 17
  - bind_param(1 1)= 1 at execute_array.pl line 18
  - bind_param(2 'onetwothree')= 1 at execute_array.pl line 19
  - execute= 1 at execute_array.pl line 20
  - bind_param_array(1 ARRAY(0x829d4f8))= 1 at execute_array.pl line
 22
  - bind_param_array(2 ARRAY(0x829d534))= 1 at execute_array.pl line
 23
  - execute_array(HASH(0x829d5c4))= undef at execute_array.pl line
 26
 
 
  Thanks
 
  Martin
  --
  Martin J. Evans
  Easysoft Ltd, UK
  http://www.easysoft.com
 
 




Re: Is it correct that execute_array does not raise/print an error

2006-07-04 Thread Dr.Ruud
John Scoles schreef:

 As execute_array is normally use to inserts/update of millions of
 records and with this volume you would not want your process to choke
 on just one bad record

Huh? It is fine if you can deliberately turn it off, but by default such
a feature should abort and roll back.

If non-fatal warnings occur, see perllexwarn about FATAL.

-- 
Affijn, Ruud

Gewoon is een tijger.




Re: Is it correct that execute_array does not raise/print an error

2006-07-04 Thread Tim Bunce
On Tue, Jul 04, 2006 at 02:18:33PM +0100, Martin J. Evans wrote:
 
 Thanks for the explanation. You have not however convinced me this behavior is
 right. If RaiseError caused a die on error and someone wanted to ignore errors
 they could just do what they always do - turn RaiseError off and do the
 checking themselves.
 
 What I was really after was whether not dying on an error in execute_array
 when RaiseError was enabled was by design or a an oversight.

An oversight. Though the oversight is actually in execute_for_fetch()
which execute_array() array calls to do the real work.

 It makes a
 difference to me since I read the DBI docs and saw nothing which said
 RaiseError does not work with execute_array, then discovered it didn't,
 worked around this in my DBIx extension but would like to document why I
 have this workaround.

Try this (untested):

--- DBI.pm  (revision 6604)
+++ DBI.pm  (working copy)
@@ -1931,7 +1931,10 @@
push @$tuple_status, [ $err, $errstr_cache{$err} ||= 
$sth-errstr, $sth-state ];
}
}
-   return ($err_count) ? undef : scalar(@$tuple_status)||0E0;
+my $tuples = @$tuple_status;
+return $sth-set_err(1, executing $tuple_status generated $err_count 
errors)
+if $err_count;
+   return scalar(@$tuple_status) || 0E0;
 }
 
Tim.