1 package DBIx::Class::Storage::DBI::Pg::Sth;
4 use base 'Class::Accessor::Grouped';
6 __PACKAGE__->mk_group_accessors('simple' =>
8 'cursor_id', 'cursor_sql',
10 'cursor_sth', 'fetch_sth',
15 my ($class, $storage, $dbh, $sql, $page_size) = @_;
17 if ($sql =~ /^SELECT\b/i) {
18 my $self=bless {},$class;
19 $self->storage($storage);
21 my $csr_id=$self->_cursor_name_from_number(
22 $storage->_get_next_pg_cursor_number()
24 my $hold= ($sql =~ /\bFOR\s+UPDATE\s*\z/i) ? '' : 'WITH HOLD';
25 $self->cursor_sql("DECLARE $csr_id CURSOR $hold FOR $sql");
26 $self->cursor_id($csr_id);
27 $self->cursor_sth(undef);
28 $self->cursor_created(0);
29 $self->page_size($page_size);
33 die "Can only be used for SELECTs";
37 sub _cursor_name_from_number {
38 return 'dbic_pg_cursor_'.$_[1];
41 sub _prepare_cursor_sth {
44 return if $self->cursor_sth;
46 $self->cursor_sth($self->storage->sth($self->cursor_sql));
52 if ($self->fetch_sth) {
53 $self->fetch_sth->finish();
54 $self->fetch_sth(undef);
56 if ($self->cursor_sth) {
57 $self->cursor_sth->finish();
58 $self->cursor_sth(undef);
59 $self->storage->dbh->do('CLOSE '.$self->cursor_id);
66 eval { $self->_cleanup_sth };
72 my ($self,@bind_args)=@_;
74 $self->_prepare_cursor_sth;
76 return $self->cursor_sth->bind_param(@bind_args);
80 my ($self,@bind_values)=@_;
82 $self->_prepare_cursor_sth;
84 my $ret=$self->cursor_sth->execute(@bind_values);
85 $self->cursor_created(1) if $ret;
89 # bind_param_array & execute_array not used for SELECT statements, so
95 return $self->cursor_sth->errstr;
101 $self->fetch_sth->finish if $self->fetch_sth;
102 return $self->cursor_sth->finish if $self->cursor_sth;
106 sub _check_cursor_end {
109 if ($self->fetch_sth->rows == 0) {
119 if (!$self->cursor_created) {
123 $self->fetch_sth->finish if $self->fetch_sth;
124 $self->fetch_sth($self->storage->sth(
125 sprintf 'fetch %d from %s',
129 $self->fetch_sth->execute;
135 $self->_run_fetch_sth unless $self->fetch_sth;
136 return if $self->_check_cursor_end;
138 my @row = $self->fetch_sth->fetchrow_array;
140 $self->_run_fetch_sth;
141 return if $self->_check_cursor_end;
143 @row = $self->fetch_sth->fetchrow_array;
148 sub fetchall_arrayref {
149 my ($self,$slice,$max_rows) = @_;
152 $self->_run_fetch_sth unless $self->fetch_sth;
153 return if $self->_check_cursor_end;
156 my $batch=$self->fetch_sth->fetchall_arrayref($slice,$max_rows);
160 if (defined($max_rows) && $max_rows >=0) {
161 $max_rows -= @$batch;
162 last if $max_rows <=0;
167 $self->_run_fetch_sth;
168 last if $self->_check_cursor_end;