File Coverage

blib/lib/DBIx/Class/Helper/ResultSet/Explain.pm
Criterion Covered Total %
statement 21 21 100.0
branch n/a
condition 1 3 33.3
subroutine 6 6 100.0
pod 0 1 0.0
total 28 31 90.3


line stmt bran cond sub pod time code
1             package DBIx::Class::Helper::ResultSet::Explain;
2             $DBIx::Class::Helper::ResultSet::Explain::VERSION = '2.034002';
3             # ABSTRACT: Get query plan for a ResultSet
4              
5 55     55   21971 use strict;
  55         107  
  55         1426  
6 55     55   262 use warnings;
  55         92  
  55         1183  
7              
8 55     55   229 use parent 'DBIx::Class::ResultSet';
  55         92  
  55         237  
9              
10 55     55   3222 use DBIx::Introspector;
  55         121  
  55         16322  
11              
12             sub _introspector {
13             my $d = DBIx::Introspector->new(drivers => '2013-12.01');
14              
15             $d->decorate_driver_connected(MSSQL => splain => 'GETUTCDATE()');
16             $d->decorate_driver_connected(
17             SQLite => splain => sub {
18             sub {
19             my ($dbh, $query) = @_;
20             my ($sql, @bind) = @{$$query};
21              
22             $sql =~ s/\s*\((.*)\)\s*/$1/;
23              
24             shift->selectall_arrayref("EXPLAIN $sql", undef, @bind)
25             },
26             },
27             );
28             $d->decorate_driver_connected(
29             Pg => splain => sub {
30             sub {
31             my ($dbh, $query) = @_;
32             my ($sql, @bind) = @{$$query};
33             shift->selectall_arrayref("EXPLAIN ANALYZE $sql", undef, @bind)
34             },
35             },
36             );
37              
38             $d->decorate_driver_connected(
39             mysql => splain => sub {
40             sub {
41             my ($dbh, $query) = @_;
42             my ($sql, @bind) = @{$$query};
43             shift->selectall_arrayref("EXPLAIN EXTENDED $sql", undef, @bind)
44             },
45             },
46             );
47              
48             return $d;
49             }
50              
51 55     55   381 use namespace::clean;
  55         108  
  55         351  
52              
53             my $i;
54              
55             sub explain {
56 1   33 1 0 750 $i ||= _introspector();
57              
58 1         2 my $self = shift;
59              
60 1         11 my $storage = $self->result_source->storage;
61 1         232 $storage->ensure_connected;
62 1         209 my $dbh = $storage->dbh;
63              
64 1         138 $i->get($dbh, undef, 'splain')->($dbh, $self->as_query)
65             }
66              
67             1;
68              
69             __END__
70              
71             =pod
72              
73             =head1 NAME
74              
75             DBIx::Class::Helper::ResultSet::Explain - Get query plan for a ResultSet
76              
77             =head1 SYNOPSIS
78              
79             This module mostly makes sense to be used without setting as a component:
80              
81             use Devel::Dwarn;
82             Dwarn DBIx::Class::ResultSet::Explain::explain($rs)
83              
84             But as usual, if you prefer to use it as a component here's how:
85              
86             package MyApp::Schema::ResultSet::Foo;
87              
88             __PACKAGE__->load_components(qw{Helper::ResultSet::Explain});
89              
90             ...
91              
92             1;
93              
94             And then in a script or something:
95              
96             use Devel::Dwarn;
97             Dwarn $rs->explain;
98              
99             =head1 DESCRIPTION
100              
101             This is just a handy little tool that gives you the query plan for a given
102             ResultSet. The output is in no way normalized, so just treat it as a debug tool
103             or something. The only supported DB's are those listed below. Have fun!
104              
105             See L<DBIx::Class::Helper::ResultSet/NOTE> for a nice way to apply it
106             to your entire schema.
107              
108             =head1 EXAMPLE OUTPUT FROM SUPPORTED DB's
109              
110             =head2 SQlite
111              
112             [
113             [
114             0,
115             "Init",
116             0,
117             10,
118             0,
119             "",
120             "00",
121             undef,
122             ],
123             [
124             1,
125             "OpenRead",
126             0,
127             3,
128             0,
129             4,
130             "00",
131             undef,
132             ],
133             [
134             2,
135             "Rewind",
136             0,
137             9,
138             0,
139             "",
140             "00",
141             undef,
142             ],
143             [
144             3,
145             "Rowid",
146             0,
147             1,
148             0,
149             "",
150             "00",
151             undef,
152             ],
153             [
154             4,
155             "Column",
156             0,
157             1,
158             2,
159             "",
160             "00",
161             undef,
162             ],
163             [
164             5,
165             "Column",
166             0,
167             2,
168             3,
169             "",
170             "00",
171             undef,
172             ],
173             [
174             6,
175             "Column",
176             0,
177             3,
178             4,
179             "",
180             "00",
181             undef,
182             ],
183             [
184             7,
185             "ResultRow",
186             1,
187             4,
188             0,
189             "",
190             "00",
191             undef,
192             ],
193             [
194             8,
195             "Next",
196             0,
197             3,
198             0,
199             "",
200             "01",
201             undef,
202             ],
203             [
204             9,
205             "Halt",
206             0,
207             0,
208             0,
209             "",
210             "00",
211             undef,
212             ],
213             [
214             10,
215             "Transaction",
216             0,
217             0,
218             17,
219             0,
220             "01",
221             undef,
222             ],
223             [
224             11,
225             "Goto",
226             0,
227             1,
228             0,
229             "",
230             "00",
231             undef,
232             ],
233             ]
234              
235             =head2 Pg
236              
237             [
238             [
239             "Seq Scan on \"Gnarly\" me (cost=0.00..16.20 rows=620 width=100) (actual time=0.001..0.001 rows=0 loops=1)",
240             ],
241             [
242             "Planning time: 0.126 ms",
243             ],
244             [
245             "Execution time: 0.025 ms",
246             ],
247             ]
248              
249             =head2 mysql
250              
251             [
252             [
253             1,
254             "SIMPLE",
255             "me",
256             "ALL",
257             undef,
258             undef,
259             undef,
260             undef,
261             1,
262             100,
263             "",
264             ],
265             ]
266              
267             =head1 AUTHOR
268              
269             Arthur Axel "fREW" Schmidt <frioux+cpan@gmail.com>
270              
271             =head1 COPYRIGHT AND LICENSE
272              
273             This software is copyright (c) 2019 by Arthur Axel "fREW" Schmidt.
274              
275             This is free software; you can redistribute it and/or modify it under
276             the same terms as the Perl 5 programming language system itself.
277              
278             =cut