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] = ();