cleanup, moved Pg::Sth to separate file
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / Pg / Sth.pm
CommitLineData
8c194608 1package DBIx::Class::Storage::DBI::Pg::Sth;
2use strict;
3use warnings;
4use base 'Class::Accessor::Grouped';
5
6__PACKAGE__->mk_group_accessors('simple' =>
7 'storage',
8 'cursor_id', 'cursor_created',
9 'cursor_sth', 'fetch_sth',
10 );
11
12sub new {
13 my ($class, $storage, $dbh, $sql) = @_;
14
15 if ($sql =~ /^SELECT\b/i) {
16 my $self=bless {},$class;
17 $self->storage($storage);
18
19 my $csr_id=$self->_cursor_name_from_number(
20 $storage->_get_next_pg_cursor_number()
21 );
22 my $hold= ($sql =~ /\bFOR\s+UPDATE\s*\z/i) ? '' : 'WITH HOLD';
23 $sql="DECLARE $csr_id CURSOR $hold FOR $sql";
24 $self->cursor_id($csr_id);
25 $self->cursor_sth($storage->_dbh_sth($dbh,$sql));
26 $self->cursor_created(0);
27 return $self;
28 }
29 else {
30 die "Can only be used for SELECTS";
31 }
32}
33
34sub _cursor_name_from_number {
35 return 'dbic_pg_cursor_'.$_[1];
36}
37
38sub _cleanup_sth {
39 my ($self)=@_;
40
41 if ($self->fetch_sth) {
42 $self->fetch_sth->finish();
43 $self->fetch_sth(undef);
44 }
45 if ($self->cursor_sth) {
46 $self->cursor_sth->finish();
47 $self->cursor_sth(undef);
48 $self->storage->dbh->do('CLOSE '.$self->cursor_id);
49 }
50}
51
52sub DESTROY {
53 my ($self) = @_;
54
55 eval { $self->_cleanup_sth };
56
57 return;
58}
59
60sub bind_param {
61 my ($self,@bind_args)=@_;
62
63 return $self->cursor_sth->bind_param(@bind_args);
64}
65
66sub execute {
67 my ($self,@bind_values)=@_;
68
69 $self->cursor_created(1);
70 return $self->cursor_sth->execute(@bind_values);
71}
72
73# bind_param_array & execute_array not used for SELECT statements, so
74# we'll ignore them
75
76sub errstr {
77 my ($self)=@_;
78
79 return $self->cursor_sth->errstr;
80}
81
82sub finish {
83 my ($self)=@_;
84
85 $self->fetch_sth->finish if $self->fetch_sth;
86 return $self->cursor_sth->finish if $self->cursor_sth;
87 return 0;
88}
89
90sub _check_cursor_end {
91 my ($self) = @_;
92
93 if ($self->fetch_sth->rows == 0) {
94 $self->_cleanup_sth;
95 return 1;
96 }
97 return;
98}
99
100sub _run_fetch_sth {
101 my ($self)=@_;
102
103 if (!$self->cursor_created) {
104 $self->cursor_sth->execute();
105 }
106
107 $self->fetch_sth->finish if $self->fetch_sth;
108 $self->fetch_sth($self->storage->sth("fetch 1000 from ".$self->cursor_id));
109 $self->fetch_sth->execute;
110}
111
112sub fetchrow_array {
113 my ($self) = @_;
114
115 $self->_run_fetch_sth unless $self->fetch_sth;
116 return if $self->_check_cursor_end;
117
118 my @row = $self->fetch_sth->fetchrow_array;
119 if (!@row) {
120 $self->_run_fetch_sth;
121 return if $self->_check_cursor_end;
122
123 @row = $self->fetch_sth->fetchrow_array;
124 }
125 return @row;
126}
127
128sub fetchall_arrayref {
129 my ($self,$slice,$max_rows) = @_;
130
131 my $ret=[];
132 $self->_run_fetch_sth unless $self->fetch_sth;
133 return if $self->_check_cursor_end;
134
135 while (1) {
136 my $batch=$self->fetch_sth->fetchall_arrayref($slice,$max_rows);
137
138 push @$ret,@$batch;
139
140 if (defined($max_rows) && $max_rows >=0) {
141 $max_rows -= @$batch;
142 last if $max_rows <=0;
143 }
144
145 last if @$batch ==0;
146
147 $self->_run_fetch_sth;
148 last if $self->_check_cursor_end;
149 }
150
151 return $ret;
152}
153
1541;