Perl DBI when to close prepared statements

怎甘沉沦 提交于 2019-12-11 09:27:24

问题


I have an odd problem. On my dev computer I am getting errors. However on the live system the errors do not happen. If I fix the issues on dev the fixes cause problems in production.

It has to do with when I am closing prepared statements. On production I have to call finish after every fetch. If I do this on my dev system then the next execute of the statement will return undef, and there is nothing $dbh->errstr or in $DBI::errstr.

Any Idea where to even start with this one?

Here is a simple test:

#!/usr/bin/perl

use strict;
use warnings;

use DBI;
use DateTime;
use DateTime::Format::Strptime;
use Data::Dumper;

# Debug flag.
my $debug = 1;

#helper
sub getLoggingTime {

    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
    my $nice_timestamp = sprintf ( "%04d/%02d/%02d %02d:%02d:%02d",
                               $year+1900,$mon+1,$mday,$hour,$min,$sec);
    return $nice_timestamp;
}

# Debug function.
sub dbg { if (! $debug) { return }; my $str = getLoggingTime() . " " . shift ; print STDERR $str }

# These are *the* date and time formats we use.
my $dateFormat = new DateTime::Format::Strptime('pattern' => '%F', 'locale' => 'en_NZ',             'time_zone' => 'Pacific/Auckland');
my $timeFormat = new DateTime::Format::Strptime('pattern' => '%T', 'locale' => 'en_NZ', 'time_zone' => 'Pacific/Auckland');

# Connect to the database.
my $dbconnect = *****removed**** || die 'No dbi_connection configured.';
my $dbusername = *****removed**** || die 'No dbi_username configured.';
my $dbpassword = *****removed**** || die 'No dbi_password configured.';

my $dbh = DBI->connect ($dbconnect, $dbusername, $dbpassword, { RaiseError => 1, PrintError => 1, AutoCommit => 1 }) ||
    die 'Cannot connect to database. ' . DBI::errstr;
my $test_sth = $dbh->prepare('
    SELECT 
        ? as teststring, 
        GETDATE() as testdate
    ') || die 'Cannot prepare franchise name statement: ' . ($dbh->errstr ||$DBI::errstr || "")  . "\n";


##Attempt One
$test_sth->execute("Test string") || die "Could not execute test statement: " . ($dbh->errstr ||$DBI::errstr || "") . "\n";

my $result = $test_sth->fetchrow_hashref()
|| die "Cannot get result: " . ($dbh->errstr ||$DBI::errstr || "") . "\n";
$test_sth->finish();

my $testString = $result->{'teststring'};
my $testDate =  $result->{'testdate'};

dbg("testString = $testString, testDate = $testDate\n");


##Attempt Two 
$test_sth->execute("Test string") || die "Could not execute test statement: " . ($dbh->errstr ||$DBI::errstr || "") . "\n";

$result = $test_sth->fetchrow_hashref()
|| die "Cannot get result: " . ($dbh->errstr ||$DBI::errstr || "") . "\n";
$test_sth->finish();

$testString = $result->{'teststring'};
$testDate =  $result->{'testdate'};

dbg("testString = $testString, testDate = $testDate\n");

$dbh->disconnect();
1;

On dev I get :

perl dbiTest.pl 2014/03/13 11:15:51 testString = Test string, testDate = Mar 13 2014 11:15AM Could not execute test statement:

on Prod I get:

dbiTest.pl 2014/03/13 11:17:20 testString = Test string, testDate = Mar 13 2014 11:17AM 2014/03/13 11:17:20 testString = Test string, testDate = Mar 13 2014 11:17AM

If I comment the first $test_sth->finish(); On dev I get:

perl dbiTest.pl 2014/03/13 11:24:44 testString = Test string, testDate = Mar 13 2014 11:24AM 2014/03/13 11:24:44 testString = Test string, testDate = Mar 13 2014 11:24AM on Prod I get: perl dbiTest.pl 2014/03/13 11:18:06 testString = Test string, testDate = Mar 13 2014 11:18AM DBD::Sybase::st execute failed: OpenClient message: LAYER = (0) ORIGIN = (0) SEVERITY = (78) NUMBER = (51) Message String: Attempt to initiate a new Adaptive Server operation with results pending DBD::Sybase::st execute failed: OpenClient message: LAYER = (0) ORIGIN = (0) SEVERITY = (78) NUMBER = (51) Message String: Attempt to initiate a new Adaptive Server operation with results pending

UPDATE: Setting $dbh->{syb_flush_finish} = 1; allows the dev system to run finish and not break. This does fix my problem, but does not explain what is happening.


回答1:


Your version of DBD::Sysbase is way out of date. According to the changelog, a fix was added in v1.01 (released all the way back in September, 2003!) to

Automatically finish() statement handles if they are re-executed before all the rows have been fetched.

There was another fix in v1.06 (August, 2005) because finish sometimes failed to clean up the associated database handle. There have been many, many changes since v1.00, so upgrade to the latest version and drop the calls to finish.



来源:https://stackoverflow.com/questions/22364932/perl-dbi-when-to-close-prepared-statements

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!