File Coverage

blib/lib/Mojo/mysql/Results.pm
Criterion Covered Total %
statement 12 64 18.7
branch 0 22 0.0
condition 0 14 0.0
subroutine 4 29 13.7
pod 16 16 100.0
total 32 145 22.0


line stmt bran cond sub pod time code
1             package Mojo::mysql::Results;
2 18     18   108 use Mojo::Base -base;
  18         33  
  18         105  
3              
4 18     18   2779 use Mojo::Collection;
  18         29  
  18         616  
5 18     18   84 use Mojo::JSON 'from_json';
  18         26  
  18         687  
6 18     18   87 use Mojo::Util 'tablify';
  18         38  
  18         25149  
7              
8             has [qw(db sth)];
9              
10 0     0 1   sub array { ($_[0]->_expand({list => 0, type => 'array'}))[0] }
11              
12 0     0 1   sub arrays { _c($_[0]->_expand({list => 1, type => 'array'})) }
13              
14 0     0 1   sub columns { shift->sth->{NAME} }
15              
16 0 0   0 1   sub expand { $_[0]{expand} = defined $_[1] ? 2 : 1 and return $_[0] }
    0          
17              
18 0     0 1   sub finish { shift->sth->finish }
19              
20 0     0 1   sub hash { ($_[0]->_expand({list => 0, type => 'hash'}))[0] }
21              
22 0     0 1   sub hashes { _c($_[0]->_expand({list => 1, type => 'hash'})) }
23              
24 0     0 1   sub rows { shift->sth->rows }
25              
26 0     0 1   sub text { tablify shift->arrays }
27              
28 0     0 1   sub more_results { shift->sth->more_results }
29              
30 0     0 1   sub affected_rows { shift->{affected_rows} }
31              
32 0     0 1   sub err { shift->sth->err }
33              
34 0     0 1   sub errstr { shift->sth->errstr }
35              
36 0     0 1   sub last_insert_id { shift->_sth_attr('mysql_insertid') }
37              
38 0     0 1   sub state { shift->sth->state }
39              
40 0     0 1   sub warnings_count { shift->_sth_attr('mysql_warning_count') }
41              
42 0     0     sub _c { Mojo::Collection->new(@_) }
43              
44             sub _expand {
45 0     0     my ($self, $to) = @_;
46              
47             # Get field names and types, needs to be done before reading from sth
48 0   0       my $mode = $self->{expand} || 0;
49 0 0         my ($idx, $names) = $mode == 1 ? $self->_types : ();
50              
51             # Fetch sql data
52 0           my $hash = $to->{type} eq 'hash';
53             my $sql_data
54             = $to->{list} && $hash ? $self->sth->fetchall_arrayref({})
55 0 0 0       : $to->{list} ? $self->sth->fetchall_arrayref
    0          
    0          
56             : $hash ? [$self->sth->fetchrow_hashref]
57             : [$self->sth->fetchrow_arrayref];
58              
59             # Optionally expand
60 0 0         if ($mode) {
61 0           my $from_json = __PACKAGE__->can(sprintf '_from_json_mode_%s_%s', $mode, $to->{type});
62 0           $from_json->($_, $idx, $names) for @$sql_data;
63             }
64              
65 0           return @$sql_data;
66             }
67              
68             sub _from_json_mode_1_array {
69 0     0     my ($r, $idx, $names) = @_;
70 0           $r->[$_] = from_json $r->[$_] for grep { defined $r->[$_] } @$idx;
  0            
71             }
72              
73             sub _from_json_mode_1_hash {
74 0     0     my ($r, $idx, $names) = @_;
75 0           $r->{$_} = from_json $r->{$_} for grep { defined $r->{$_} } @$names;
  0            
76             }
77              
78             sub _from_json_mode_2_array {
79 0     0     my ($r, $idx, $names) = @_;
80 0   0       $_ = from_json $_ for grep defined && /^[\[{].*[}\]]$/, @$r;
81             }
82              
83             sub _from_json_mode_2_hash {
84 0     0     my ($r, $idx, $names) = @_;
85 0   0       $_ = from_json $_ for grep defined && /^[\[{].*[}\]]$/, values %$r;
86             }
87              
88             sub _sth_attr {
89 0     0     my ($self, $name) = @_;
90 0           $name =~ s!^mysql!{lc $self->db->dbh->{Driver}{Name}}!e;
  0            
  0            
91 0           return $self->sth->{$name};
92             }
93              
94             sub _types {
95 0     0     my $self = shift;
96 0 0         return @$self{qw(idx names)} if $self->{idx};
97              
98 0           my $types = $self->_sth_attr('mysql_type');
99 0 0         my @idx = grep { $types->[$_] == 245 or $types->[$_] == 252 } 0 .. $#$types; # 245 = MySQL, 252 = MariaDB
  0            
100              
101 0           return ($self->{idx} = \@idx, $self->{names} = [@{$self->columns}[@idx]]);
  0            
102             }
103              
104             sub DESTROY {
105 0     0     my $self = shift;
106 0 0 0       return unless my $db = $self->{db} and my $sth = $self->{sth};
107 0 0         push @{$db->{done_sth}}, $sth unless $self->{is_blocking};
  0            
108             }
109              
110             1;
111              
112             =encoding utf8
113              
114             =head1 NAME
115              
116             Mojo::mysql::Results - Results
117              
118             =head1 SYNOPSIS
119              
120             use Mojo::mysql::Results;
121              
122             my $results = Mojo::mysql::Results->new(db => $db, sth => $sth);
123              
124             =head1 DESCRIPTION
125              
126             L is a container for statement handles used by
127             L.
128              
129             =head1 ATTRIBUTES
130              
131             L implements the following attributes.
132              
133             =head2 db
134              
135             my $db = $results->db;
136             $results = $results->db(Mojo::mysql::Database->new);
137              
138             L object these results belong to.
139              
140             =head2 sth
141              
142             my $sth = $results->sth;
143             $results = $results->sth($sth);
144              
145             Statement handle results are fetched from.
146              
147             =head1 METHODS
148              
149             L inherits all methods from L and implements
150             the following new ones.
151              
152             =head2 array
153              
154             my $array = $results->array;
155              
156             Fetch next row from L and return it as an array reference. Note that
157             L needs to be called if you are not fetching all the possible rows.
158              
159             # Process one row at a time
160             while (my $next = $results->array) {
161             say $next->[3];
162             }
163              
164             =head2 arrays
165              
166             my $collection = $results->arrays;
167              
168             Fetch all rows and return them as a L object containing
169             array references.
170              
171             # Process all rows at once
172             say $results->arrays->reduce(sub { $a->[3] + $b->[3] });
173              
174             =head2 columns
175              
176             my $columns = $results->columns;
177              
178             Return column names as an array reference.
179              
180             =head2 expand
181              
182             $results = $results->expand;
183             $results = $results->expand(1)
184              
185             Decode C fields automatically to Perl values for all rows. Passing in "1"
186             as an argument will force expanding all columns that looks like a JSON array or
187             object.
188              
189             # Expand JSON
190             $results->expand->hashes->map(sub { $_->{foo}{bar} })->join("\n")->say;
191              
192             Note that this method is EXPERIMENTAL.
193              
194             See also L for more details
195             on how to work with JSON in MySQL.
196              
197             =head2 finish
198              
199             $results->finish;
200              
201             Indicate that you are finished with L and will not be fetching all the
202             remaining rows.
203              
204             =head2 hash
205              
206             my $hash = $results->hash;
207              
208             Fetch next row from L and return it as a hash reference. Note that
209             L needs to be called if you are not fetching all the possible rows.
210              
211             # Process one row at a time
212             while (my $next = $results->hash) {
213             say $next->{money};
214             }
215              
216             =head2 hashes
217              
218             my $collection = $results->hashes;
219              
220             Fetch all rows and return them as a L object containing hash
221             references.
222              
223             # Process all rows at once
224             say $results->hashes->reduce(sub { $a->{money} + $b->{money} });
225              
226             =head2 new
227              
228             my $results = Mojo::mysql::Results->new(db => $db, sth => $sth);
229             my $results = Mojo::mysql::Results->new({db => $db, sth => $sth});
230              
231             Construct a new L object.
232              
233             =head2 rows
234              
235             my $num = $results->rows;
236              
237             Number of rows.
238              
239             =head2 text
240              
241             my $text = $results->text;
242              
243             Fetch all rows and turn them into a table with L.
244              
245             =head2 more_results
246              
247             do {
248             my $columns = $results->columns;
249             my $arrays = $results->arrays;
250             } while ($results->more_results);
251              
252             Handle multiple results.
253              
254             =head2 affected_rows
255              
256             my $affected = $results->affected_rows;
257              
258             Number of affected rows by the query. The number reported is dependant from
259             C or C option in
260             L. For example
261              
262             UPDATE $table SET id = 1 WHERE id = 1
263              
264             would return 1 if C or L is
265             set, and 0 otherwise.
266              
267             =head2 last_insert_id
268              
269             my $last_id = $results->last_insert_id;
270              
271             That value of C column if executed query was C in a table with
272             C column.
273              
274             =head2 warnings_count
275              
276             my $warnings = $results->warnings_count;
277              
278             Number of warnings raised by the executed query.
279              
280             =head2 err
281              
282             my $err = $results->err;
283              
284             Error code receieved.
285              
286             =head2 state
287              
288             my $state = $results->state;
289              
290             Error state receieved.
291              
292             =head2 errstr
293              
294             my $errstr = $results->errstr;
295              
296             Error message receieved.
297              
298             =head1 SEE ALSO
299              
300             L.
301              
302             =cut