X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2FCursor.pm;h=d94151fed0b58e59870ec3432b410cf351bbcdf4;hb=6793561f9463f93c211917cc6f5bd57ab8d1ca5e;hp=f3bc1e23d5d83713cbe5947707a38f4c03a37966;hpb=b205131f91a5cdb5d1fe113518f6212d32c91d88;p=freeside.git diff --git a/FS/FS/Cursor.pm b/FS/FS/Cursor.pm index f3bc1e23d..d94151fed 100644 --- a/FS/FS/Cursor.pm +++ b/FS/FS/Cursor.pm @@ -2,12 +2,12 @@ package FS::Cursor; use strict; use vars qw($DEBUG $buffer); -use base qw( Exporter ); -use FS::Record qw(qsearch dbdef dbh); -use Data::Dumper; +use FS::Record; +use FS::UID qw(myconnect); use Scalar::Util qw(refaddr); -$DEBUG = 0; +$DEBUG = 2; + # this might become a parameter at some point, but right now, you can # "local $FS::Cursor::buffer = X;" $buffer = 200; @@ -39,24 +39,28 @@ and returns an FS::Cursor object to fetch the rows one at a time. sub new { my $class = shift; my $q = FS::Record::_query(@_); # builds the statement and parameter list + my $dbh = myconnect(); my $self = { query => $q, class => 'FS::' . ($q->{table} || 'Record'), buffer => [], + dbh => $dbh, }; bless $self, $class; # the class of record object to return $self->{class} = "FS::".($q->{table} || 'Record'); + # save for later, so forked children will not destroy me when they exit + $self->{pid} = $$; + $self->{id} = sprintf('cursor%08x', refaddr($self)); my $statement = "DECLARE ".$self->{id}." CURSOR FOR ".$q->{statement}; - my $dbh = dbh; my $sth = $dbh->prepare($statement) or die $dbh->errstr; - my $bind = 0; + my $bind = 1; foreach my $value ( @{ $q->{value} } ) { my $bind_type = shift @{ $q->{bind_type} }; $sth->bind_param($bind++, $value, $bind_type ); @@ -101,6 +105,15 @@ sub refill { scalar @$result; } +sub DESTROY { + my $self = shift; + return unless $self->{pid} eq $$; + $self->{dbh}->do('CLOSE '. $self->{id}) + or die $self->{dbh}->errstr; # clean-up the cursor in Pg + $self->{dbh}->rollback; + $self->{dbh}->disconnect; +} + =back =head1 TO DO @@ -111,6 +124,12 @@ Replace all uses of qsearch with this. Doesn't support MySQL. +The cursor will close prematurely if any code issues a rollback/commit. If +you need protection against this use qsearch or fork and get a new dbh +handle. +Normally this issue will represent itself this message. +ERROR: cursor "cursorXXXXXXX" does not exist. + =head1 SEE ALSO L