On Sun, Feb 25, 2007 at 03:36:07PM +0000, Tim Bunce wrote:
> On Sat, Feb 24, 2007 at 09:20:35PM +0000, Will Parsons wrote:
> > I'm trying to change the text of error messages, for example the following:
> > 
> > DBD::SQLite::db do failed: table X already exists(1) at dbdimp.c line 269
> > 
> > >From the user's point of view, "table X already exists" is valuable
> > information, but "at dbdimp.c line 269" is useless.
> > 
> > I've attempted to do this using the HandleError attribute with a function:
> > 
> > sub handle_error {
> >    $_[0] =~ s/ at dbdimp.c line \d+//;
> >    print STDERR "db error: $_[0]\n";   # for debug
> >    return 0;
> > }
> > 
> > The print statement shows the handler is changing the error text, but
> > the contents of $DBI:errstr on return from an offending statement show
> > the original text.
> > 
> > How can I do this?
> 
> Umm. I'd expect it to work. $_[0] is the same SV that's passed to
> warn/croak for PrintError/RaiseError.
> 
> If you send me a patch that moves the HandleError tests from t/10examp.t
> into a separate file and adds a new test for this problem, then I'll
> try to fix it :)
> 
> Having said that, I don't see any value in the _sqlite_error() function
> in DBD::SQLite adding the file and line number into the error message.
> 
> In fact the code needs changing anyway to use the newer way to record
> errors. That'll mean you could use the DBI's SetErrHandler hook.
> I'll do that and post a patch including the above change.

Here's the patch.

Matt, I hope you approve.

Funnily enough, adding the tests found a bug in the way the DBI set_err
function handles HandleSetErr (fixed in the next release).

Tim.

diff -ru DBD-SQLite-1.13/dbdimp.c DBD-SQLite-1.13.tim1/dbdimp.c
--- DBD-SQLite-1.13/dbdimp.c    2006-09-08 05:50:50.000000000 +0100
+++ DBD-SQLite-1.13.tim1/dbdimp.c       2007-02-25 22:02:19.000000000 +0000
@@ -36,11 +36,7 @@
 _sqlite_error(char *file, int line, SV *h, imp_xxh_t *imp_xxh, int rc, char 
*what)
 {
     dTHR;
-
-    SV *errstr = DBIc_ERRSTR(imp_xxh);
-    sv_setiv(DBIc_ERR(imp_xxh), (IV)rc);
-    sv_setpv(errstr, what);
-    sv_catpvf(errstr, "(%d) at %s line %d", rc, file, line);
+    DBIh_SET_ERR_CHAR(h, imp_xxh, NULL, rc, what, NULL, NULL);
     
     if (DBIS->debug >= 3) {
         PerlIO_printf(DBILOGFP, "sqlite error %d recorded: %s at %s line %d\n",
@@ -441,7 +437,7 @@
 {
     int pos;
     if (!SvIOK(param)) {
-        int len;
+        STRLEN len;
         char *paramstring;
         paramstring = SvPV(param, len);
         if( paramstring[len] == 0 && strlen(paramstring) == len) {
diff -ru DBD-SQLite-1.13/t/06error.t DBD-SQLite-1.13.tim1/t/06error.t
--- DBD-SQLite-1.13/t/06error.t 2002-09-08 13:18:46.000000000 +0100
+++ DBD-SQLite-1.13.tim1/t/06error.t    2007-02-25 22:26:03.000000000 +0000
@@ -1,20 +1,37 @@
 use Test;
-BEGIN { plan tests => 2 }
+BEGIN { plan tests => 8 }
 use DBI;
 
+my @set_err;
+
 unlink('foo');
-my $db = DBI->connect('dbi:SQLite:foo', '', '', { RaiseError => 1, PrintError 
=> 0 });
+my $db = DBI->connect('dbi:SQLite:foo', '', '', {
+    RaiseError => 1,
+    PrintError => 0,
+    HandleSetErr => sub { push @set_err,$_[2]; return 0; },
+});
+
 eval {
   $db->do('ssdfsdf sdf sd sdfsdfdsf sdfsdf');
 };
-ok($@);
+my $err = $@;
+ok($err);
+ok($err, qr/syntax error/);
+ok($DBI::err);
+ok($DBI::errstr);
 
 $db->do('create table testerror (a, b)');
 $db->do('insert into testerror values (1, 2)');
 $db->do('insert into testerror values (3, 4)');
 
 $db->do('create unique index testerror_idx on testerror (a)');
[EMAIL PROTECTED] = ();
 eval {
   $db->do('insert into testerror values (1, 5)');
 };
-ok($@);
+$err = $@;
+ok($err);
+ok($err, qr/column a is not unique/);
+ok(scalar @set_err, 1);
+ok("@set_err", qr/column a is not unique/);
[EMAIL PROTECTED] = ();

Reply via email to