Re: Toggling dbi attribute within a connection?
by ikegami (Patriarch) on May 12, 2005 at 16:31 UTC
|
Upon creation, a sth inherits the attributes of its dbh. However, changing the attributes of the dbh doesn't change those of a previously created sth. That means if it's a sth method is raising the error, it's the sth's RaiseError you must reset:
$sth->{RaiseError} = 0;
456449 confirms this is your problem.
| [reply] [d/l] |
|
|
Ahh! Yes, of course. This makes complete sense. Problem solved. :)
Thank you.
Matt
| [reply] |
Re: Toggling dbi attribute within a connection?
by Limbic~Region (Chancellor) on May 12, 2005 at 15:11 UTC
|
JupiterCrash,
You are breaking encapsulation. If DBI doesn't provide an mutator method for setting the RaiseError flag then you should expect weird behavior by mucking with the internals. With that said, you might want to try:
delete $dbh->{RaiseError};
Update (30 seconds later) After reading more of TFM, it seems that you are encouraged to muck with internals. I find this odd, but after recently porting Config::Tiny from p5 to p6 it isn't the first time I have seen it. DBI gives the example of limiting the scope as follows:
{
local $h->{RaiseError}; # localize and turn off for this block
}
If you can't limit the scope and need to turn it off/on at will, I suggest using delete which was my first guess anyway.
| [reply] [d/l] [select] |
|
|
Those aren't the internals. It's just a really nasty interface that presents these method calls as hash values using typeglob magic.
| [reply] |
|
|
perrin,
I see. jZed is giving me an education on this in the chatterbox. Thanks.
| [reply] |
|
|
| [reply] [d/l] |
|
|
First, thank you very much for the suggestions.
I had thought that delete $dbh->{RaiseError} might work, too, but it gives this error:
Can't locate object method "DELETE" via package "DBI::db"
I had tried (and just tried again) making it local in scope when setting it, as you suggested, and that does not seem to be working either to turn it on only temporarily. (it stays on outside of the scrope)
This is weird.
Matt
| [reply] |
|
|
Matt,
First, DELETE is not delete. Second, can you provide a minimal example of the code that you can't get to work per the docs (using naked blocks for scopes).
| [reply] |
|
|
|
|
Re: Toggling dbi attribute within a connection?
by jZed (Prior) on May 12, 2005 at 15:41 UTC
|
Are you sure setting RaiseError to 0 isn't working? Did you also unset PrintError? What is the DBD and what is the error? | [reply] |
|
|
I did not also unset PrintError, but I just tried that, and still no luck.
I am using the ODBC DBD at the time, but I believe I had also tried this with Oracle.
Basically, I have code which wants RaiseError on for a prepare and execute. Then, I do NOT want it on for the fetches, because there is a fetch that could potentially throw an error. With RaiseError off (what I want) this code works:
# there is more to fetch, so set this high
if ($sth->fetchrow_arrayref)
{
$extraFetch = 5000000;
}
else
{
$extraFetch = $numRowsDisplayed;
}
This fetch could potentially be outside the boundaries of the rows returned. With RaiseError off, I don't die and the conditiom works fine. With RaiseError on, I get this error:
DBD::ODBC::st fetchrow_arrayref failed: (DBD: no select statement currently executing err=-1)
If RaiseError could be off at this point, all would be good.
However there are other areas in my code where I would have this same problem. Typically I will want to encapsulate a few statements in a transaction (with eval) and want RaiseError on for that. Then I will want it off, as there is code that follows which does things along the lines of
execute($sql) || handle the error
(where a die being thrown would never get into my "handle the error code)
Matt
| [reply] [d/l] |
|
|
This prints "1 error 3" for me with PostgreSQL, as I'd expect. I don't have ODBC handy to check.
#!perl -w
$|=1;
use strict;
use DBI;
my $dbh=DBI->connect('dbi:Pg:dbname=test1');
$dbh->{PrintError}=0;
$dbh->do('junk');
print "1";
eval {
local $dbh->{RaiseError}=1;
$dbh->do('junk');
print "2";
};
print " error " if $@;
$dbh->do('junk');
print "3";
| [reply] [d/l] |
|
|
|
|
|
|
if ($sth->fetchrow_arrayref)
{
$extraFetch = 5000000;
}
else
{
$extraFetch = $numRowsDisplayed;
}
You might want to check for $sth->{Active} instead, it should be true if there is more to fetch and false otherwise. | [reply] [d/l] |