Skip Menu |

This queue is for tickets about the DBI CPAN distribution.

Report information
The Basics
Id: 40210
Status: rejected
Priority: 0/
Queue: DBI

People
Owner: Nobody in particular
Requestors: vitalif [...] mail.ru
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: 1.607
Fixed in: (no value)



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; }
Thanks for the suggestion and patch. However, the way to do this is to pass a prepared statement handle instead of an sql statement.
Show quoted text
> However, the way to do this is to pass a prepared statement handle > instead of an sql statement.
Yeah, I know. But that's a bit less convenient way. :-) Is there any particular reason for DBI to not improve its own performance? i.e. what do you think about this approach, has it any drawbacks? / Ну да, я знаю. Но это чуть менее удобно. :-) Существует ли какая-то конкретная причина, по которой DBI не следует применять prepare_cached? Т.е., что вы думаете об этом подходе, имеет ли он какие-либо недостатки?
You can try to get some popular support for the idea by emailing dbi-users@perl.org. (Please don't reply to this as it'll reopen the ticket again.)