Subject: | Prepare caching in do(), selectall_arrayref() and similar / Кэширование объектов запроса при вызовах do(), selectall_arrayref() и подобных |
I think DBI should use prepare_cached() instead of prepare() in all
$dbh->do(), $dbh->selectall_arrayref(), $dbh->selectall_hashref() and
similar method calls. These methods don't return statement object, so
the situation described in prepare_cached "Caveat emptor" section of
DBI perldoc, is impossible. A patch for DBI 1.607 is attached.
Я думаю, что в DBI в методах $dbh->do(), $dbh->selectall_arrayref(),
$dbh->selectall_hashref() и подобных нужно использовать не prepare, а
prepare_cached, т.е. использовать один и тот же объект запроса вместо
создания каждый раз нового. Эти методы не возвращают нам объект
запроса, таким образом, ошибочная ситуация с двумя вложенными циклами
по одному и тому же запросу, описанная в секции "Caveat emptor"
описания prepare_cached, в perldoc'е по DBI, невозможна.
Производительность же - улучшится. Прилагаю патч к версии DBI 1.607.
Subject: | DBI-1.607-prepare-cached.patch |
diff -Nurap DBI-1.607-tHlTB9/DBI.pm DBI-1.607-tHlTB9-orig/DBI.pm
--- DBI-1.607-tHlTB9/DBI.pm 2008-10-21 03:19:25.132210296 +0400
+++ DBI-1.607-tHlTB9-orig/DBI.pm 2008-07-23 01:45:17.000000000 +0400
@@ -1558,7 +1558,7 @@ sub _new_sth { # called by DBD::<drivern
sub do {
my($dbh, $statement, $attr, @params) = @_;
- my $sth = $dbh->prepare_cached($statement, $attr) or return undef;
+ my $sth = $dbh->prepare($statement, $attr) or return undef;
$sth->execute(@params) or return undef;
my $rows = $sth->rows;
($rows == 0) ? "0E0" : $rows;
@@ -1566,7 +1566,7 @@ sub _new_sth { # called by DBD::<drivern
sub _do_selectrow {
my ($method, $dbh, $stmt, $attr, @bind) = @_;
- my $sth = ((ref $stmt) ? $stmt : $dbh->prepare_cached($stmt, $attr))
+ my $sth = ((ref $stmt) ? $stmt : $dbh->prepare($stmt, $attr))
or return;
$sth->execute(@bind)
or return;
@@ -1589,7 +1589,7 @@ sub _new_sth { # called by DBD::<drivern
# which fallsback to this if a slice is given
sub selectall_arrayref {
my ($dbh, $stmt, $attr, @bind) = @_;
- my $sth = (ref $stmt) ? $stmt : $dbh->prepare_cached($stmt, $attr)
+ my $sth = (ref $stmt) ? $stmt : $dbh->prepare($stmt, $attr)
or return;
$sth->execute(@bind) || return;
my $slice = $attr->{Slice}; # typically undef, else hash or array ref
@@ -1606,7 +1606,7 @@ sub _new_sth { # called by DBD::<drivern
sub selectall_hashref {
my ($dbh, $stmt, $key_field, $attr, @bind) = @_;
- my $sth = (ref $stmt) ? $stmt : $dbh->prepare_cached($stmt, $attr);
+ my $sth = (ref $stmt) ? $stmt : $dbh->prepare($stmt, $attr);
return unless $sth;
$sth->execute(@bind) || return;
return $sth->fetchall_hashref($key_field);
@@ -1614,7 +1614,7 @@ sub _new_sth { # called by DBD::<drivern
sub selectcol_arrayref {
my ($dbh, $stmt, $attr, @bind) = @_;
- my $sth = (ref $stmt) ? $stmt : $dbh->prepare_cached($stmt, $attr);
+ my $sth = (ref $stmt) ? $stmt : $dbh->prepare($stmt, $attr);
return unless $sth;
$sth->execute(@bind) || return;
my @columns = ($attr->{Columns}) ? @{$attr->{Columns}} : (1);
diff -Nurap DBI-1.607-tHlTB9/Driver.xst DBI-1.607-tHlTB9-orig/Driver.xst
--- DBI-1.607-tHlTB9/Driver.xst 2008-10-21 03:18:40.732718204 +0400
+++ DBI-1.607-tHlTB9-orig/Driver.xst 2008-05-27 16:27:15.000000000 +0400
@@ -132,7 +132,7 @@ selectall_arrayref(...)
sth = mg->mg_obj;
}
else {
- sth = dbixst_bounce_method("prepare_cached", 3);
+ sth = dbixst_bounce_method("prepare", 3);
SPAGAIN; SP -= items; /* because stack might have been realloc'd */
if (!SvROK(sth))
XSRETURN_UNDEF;
@@ -175,7 +175,7 @@ selectrow_arrayref(...)
}
else {
/* --- prepare --- */
- sth = dbixst_bounce_method("prepare_cached", 3);
+ sth = dbixst_bounce_method("prepare", 3);
SPAGAIN; SP -= items; /* because stack might have been realloc'd */
if (!SvROK(sth)) {
if (is_selectrow_array) { XSRETURN_EMPTY; } else { XSRETURN_UNDEF; }