Commit | Line | Data |
5cf243f6 |
1 | package DBIx::Class::Storage::DBI::Cursor; |
28927b50 |
2 | |
28927b50 |
3 | use strict; |
4 | use warnings; |
5 | |
48a76fcf |
6 | use base qw/DBIx::Class::Cursor/; |
a3a526cc |
7 | |
9780718f |
8 | use Try::Tiny; |
fd323bf1 |
9 | use namespace::clean; |
9780718f |
10 | |
a3a526cc |
11 | __PACKAGE__->mk_group_accessors('simple' => |
dfa92e5e |
12 | qw/sth storage args attrs/ |
a3a526cc |
13 | ); |
2ad62d97 |
14 | |
5cf243f6 |
15 | =head1 NAME |
16 | |
17 | DBIx::Class::Storage::DBI::Cursor - Object representing a query cursor on a |
18 | resultset. |
19 | |
20 | =head1 SYNOPSIS |
21 | |
22 | my $cursor = $schema->resultset('CD')->cursor(); |
c564f8c3 |
23 | |
24 | # raw values off the database handle in resultset columns/select order |
25 | my @next_cd_column_values = $cursor->next; |
26 | |
27 | # list of all raw values as arrayrefs |
28 | my @all_cds_column_values = $cursor->all; |
5cf243f6 |
29 | |
30 | =head1 DESCRIPTION |
31 | |
32 | A Cursor represents a query cursor on a L<DBIx::Class::ResultSet> object. It |
33 | allows for traversing the result set with L</next>, retrieving all results with |
34 | L</all> and resetting the cursor with L</reset>. |
35 | |
36 | Usually, you would use the cursor methods built into L<DBIx::Class::ResultSet> |
37 | to traverse it. See L<DBIx::Class::ResultSet/next>, |
38 | L<DBIx::Class::ResultSet/reset> and L<DBIx::Class::ResultSet/all> for more |
39 | information. |
40 | |
41 | =head1 METHODS |
42 | |
43 | =head2 new |
44 | |
5cf243f6 |
45 | Returns a new L<DBIx::Class::Storage::DBI::Cursor> object. |
46 | |
47 | =cut |
48 | |
28927b50 |
49 | sub new { |
cb5f2eea |
50 | my ($class, $storage, $args, $attrs) = @_; |
cb5f2eea |
51 | $class = ref $class if ref $class; |
2007929b |
52 | |
28927b50 |
53 | my $new = { |
cb5f2eea |
54 | storage => $storage, |
28927b50 |
55 | args => $args, |
1346e22d |
56 | attrs => $attrs, |
dbaee748 |
57 | _dbh_gen => $storage->{_dbh_gen}, |
dfa92e5e |
58 | _pos => 0, |
59 | _done => 0, |
1346e22d |
60 | }; |
61 | |
cb5f2eea |
62 | return bless ($new, $class); |
28927b50 |
63 | } |
64 | |
5cf243f6 |
65 | =head2 next |
66 | |
21b5c39d |
67 | =over 4 |
68 | |
ebc77b53 |
69 | =item Arguments: none |
21b5c39d |
70 | |
d601dc88 |
71 | =item Return Value: \@row_columns |
21b5c39d |
72 | |
5cf243f6 |
73 | =back |
74 | |
685dad64 |
75 | Advances the cursor to the next row and returns an array of column |
76 | values (the result of L<DBI/fetchrow_array> method). |
5cf243f6 |
77 | |
78 | =cut |
79 | |
dbaee748 |
80 | sub _dbh_next { |
81 | my ($storage, $dbh, $self) = @_; |
1346e22d |
82 | |
dbaee748 |
83 | $self->_check_dbh_gen; |
22ed9526 |
84 | if ( |
85 | $self->{attrs}{software_limit} |
86 | && $self->{attrs}{rows} |
dfa92e5e |
87 | && $self->{_pos} >= $self->{attrs}{rows} |
22ed9526 |
88 | ) { |
a3a526cc |
89 | $self->sth->finish if $self->sth->{Active}; |
90 | $self->sth(undef); |
dfa92e5e |
91 | $self->{_done} = 1; |
cb5f2eea |
92 | } |
dfa92e5e |
93 | |
94 | return if $self->{_done}; |
95 | |
a3a526cc |
96 | unless ($self->sth) { |
97 | $self->sth(($storage->_select(@{$self->{args}}))[1]); |
5c91499f |
98 | if ($self->{attrs}{software_limit}) { |
99 | if (my $offset = $self->{attrs}{offset}) { |
a3a526cc |
100 | $self->sth->fetch for 1 .. $offset; |
5c91499f |
101 | } |
102 | } |
28927b50 |
103 | } |
a3a526cc |
104 | my @row = $self->sth->fetchrow_array; |
cb5f2eea |
105 | if (@row) { |
dfa92e5e |
106 | $self->{_pos}++; |
cb5f2eea |
107 | } else { |
a3a526cc |
108 | $self->sth(undef); |
dfa92e5e |
109 | $self->{_done} = 1; |
cb5f2eea |
110 | } |
28927b50 |
111 | return @row; |
112 | } |
113 | |
dbaee748 |
114 | sub next { |
115 | my ($self) = @_; |
116 | $self->{storage}->dbh_do($self->can('_dbh_next'), $self); |
117 | } |
118 | |
5cf243f6 |
119 | =head2 all |
120 | |
21b5c39d |
121 | =over 4 |
122 | |
ebc77b53 |
123 | =item Arguments: none |
21b5c39d |
124 | |
d601dc88 |
125 | =item Return Value: \@row_columns+ |
21b5c39d |
126 | |
5cf243f6 |
127 | =back |
128 | |
21b5c39d |
129 | Returns a list of arrayrefs of column values for all rows in the |
130 | L<DBIx::Class::ResultSet>. |
5cf243f6 |
131 | |
132 | =cut |
133 | |
dbaee748 |
134 | sub _dbh_all { |
135 | my ($storage, $dbh, $self) = @_; |
1346e22d |
136 | |
dbaee748 |
137 | $self->_check_dbh_gen; |
b4ad6d39 |
138 | $self->sth->finish if $self->sth && $self->sth->{Active}; |
a3a526cc |
139 | $self->sth(undef); |
dbaee748 |
140 | my ($rv, $sth) = $storage->_select(@{$self->{args}}); |
1a14aa3f |
141 | return @{$sth->fetchall_arrayref}; |
142 | } |
143 | |
dbaee748 |
144 | sub all { |
145 | my ($self) = @_; |
6296f45b |
146 | if ($self->{attrs}{software_limit} |
147 | && ($self->{attrs}{offset} || $self->{attrs}{rows})) { |
c3515436 |
148 | return $self->next::method; |
6296f45b |
149 | } |
22ed9526 |
150 | |
dbaee748 |
151 | $self->{storage}->dbh_do($self->can('_dbh_all'), $self); |
152 | } |
153 | |
5cf243f6 |
154 | =head2 reset |
155 | |
5cf243f6 |
156 | Resets the cursor to the beginning of the L<DBIx::Class::ResultSet>. |
157 | |
158 | =cut |
159 | |
28927b50 |
160 | sub reset { |
161 | my ($self) = @_; |
1346e22d |
162 | |
dbaee748 |
163 | # No need to care about failures here |
52b420dd |
164 | try { $self->sth->finish } |
165 | if $self->sth && $self->sth->{Active}; |
1346e22d |
166 | $self->_soft_reset; |
b7c79955 |
167 | return undef; |
1346e22d |
168 | } |
169 | |
170 | sub _soft_reset { |
171 | my ($self) = @_; |
172 | |
a3a526cc |
173 | $self->sth(undef); |
dfa92e5e |
174 | $self->{_done} = 0; |
175 | $self->{_pos} = 0; |
28927b50 |
176 | } |
177 | |
dbaee748 |
178 | sub _check_dbh_gen { |
1346e22d |
179 | my ($self) = @_; |
180 | |
dbaee748 |
181 | if($self->{_dbh_gen} != $self->{storage}->{_dbh_gen}) { |
182 | $self->{_dbh_gen} = $self->{storage}->{_dbh_gen}; |
183 | $self->_soft_reset; |
1346e22d |
184 | } |
185 | } |
186 | |
28927b50 |
187 | sub DESTROY { |
dbaee748 |
188 | # None of the reasons this would die matter if we're in DESTROY anyways |
05b22e33 |
189 | if (my $sth = $_[0]->sth) { |
25d3127d |
190 | local $SIG{__WARN__} = sub {}; |
380b6ea1 |
191 | try { $sth->finish } if $sth->FETCH('Active'); |
05b22e33 |
192 | } |
28927b50 |
193 | } |
194 | |
195 | 1; |