I was wrong about 2d12a809 - the crash is real
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / Cursor.pm
CommitLineData
5cf243f6 1package DBIx::Class::Storage::DBI::Cursor;
28927b50 2
28927b50 3use strict;
4use warnings;
5
48a76fcf 6use base qw/DBIx::Class::Cursor/;
a3a526cc 7
9780718f 8use Try::Tiny;
fd323bf1 9use 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
17DBIx::Class::Storage::DBI::Cursor - Object representing a query cursor on a
18resultset.
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
32A Cursor represents a query cursor on a L<DBIx::Class::ResultSet> object. It
33allows for traversing the result set with L</next>, retrieving all results with
34L</all> and resetting the cursor with L</reset>.
35
36Usually, you would use the cursor methods built into L<DBIx::Class::ResultSet>
37to traverse it. See L<DBIx::Class::ResultSet/next>,
38L<DBIx::Class::ResultSet/reset> and L<DBIx::Class::ResultSet/all> for more
39information.
40
41=head1 METHODS
42
43=head2 new
44
5cf243f6 45Returns a new L<DBIx::Class::Storage::DBI::Cursor> object.
46
47=cut
48
28927b50 49sub 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 75Advances the cursor to the next row and returns an array of column
76values (the result of L<DBI/fetchrow_array> method).
5cf243f6 77
78=cut
79
dbaee748 80sub _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 114sub 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 129Returns a list of arrayrefs of column values for all rows in the
130L<DBIx::Class::ResultSet>.
5cf243f6 131
132=cut
133
dbaee748 134sub _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 144sub 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 156Resets the cursor to the beginning of the L<DBIx::Class::ResultSet>.
157
158=cut
159
28927b50 160sub 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
170sub _soft_reset {
171 my ($self) = @_;
172
a3a526cc 173 $self->sth(undef);
dfa92e5e 174 $self->{_done} = 0;
175 $self->{_pos} = 0;
28927b50 176}
177
dbaee748 178sub _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 187sub 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
1951;