Filename | /2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/SQLMaker.pm |
Statements | Executed 648511 statements in 1.68s |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
63788 | 10 | 2 | 423ms | 1.77s | _quote | DBIx::Class::SQLMaker::
45197 | 5 | 2 | 392ms | 1.43s | _recurse_fields (recurses: max depth 2, inclusive time 1.36s) | DBIx::Class::SQLMaker::
7330 | 2 | 2 | 258ms | 440ms | _order_by (recurses: max depth 1, inclusive time 106ms) | DBIx::Class::SQLMaker::
13706 | 3 | 1 | 231ms | 563ms | _from_chunk_to_sql (recurses: max depth 1, inclusive time 206ms) | DBIx::Class::SQLMaker::
6706 | 1 | 1 | 208ms | 4.80s | select | DBIx::Class::SQLMaker::
8019 | 4 | 1 | 74.5ms | 1.01s | _table | DBIx::Class::SQLMaker::
6706 | 1 | 1 | 69.2ms | 663ms | _gen_from_blocks | DBIx::Class::SQLMaker::
100627 | 4 | 1 | 59.4ms | 59.4ms | CORE:match (opcode) | DBIx::Class::SQLMaker::
6706 | 1 | 1 | 59.1ms | 59.1ms | _assemble_binds | DBIx::Class::SQLMaker::
6706 | 1 | 1 | 49.2ms | 713ms | _recurse_from | DBIx::Class::SQLMaker::
6853 | 3 | 3 | 45.3ms | 154ms | _parse_rs_attrs | DBIx::Class::SQLMaker::
449 | 1 | 1 | 8.16ms | 431ms | insert | DBIx::Class::SQLMaker::
147 | 1 | 1 | 2.61ms | 8.56ms | _where_op_IDENT | DBIx::Class::SQLMaker::
147 | 1 | 1 | 1.57ms | 30.7ms | _join_condition | DBIx::Class::SQLMaker::
147 | 1 | 1 | 1.13ms | 1.13ms | _quote_chars | DBIx::Class::SQLMaker::
147 | 1 | 1 | 982µs | 982µs | _generate_join_clause | DBIx::Class::SQLMaker::
5 | 1 | 1 | 144µs | 625µs | new | DBIx::Class::SQLMaker::
1 | 1 | 1 | 33µs | 248µs | BEGIN@64 | DBIx::Class::SQLMaker::
10 | 1 | 1 | 19µs | 19µs | CORE:qr (opcode) | DBIx::Class::SQLMaker::
1 | 1 | 1 | 14µs | 19µs | BEGIN@3 | DBIx::Class::SQLMaker::
1 | 1 | 1 | 12µs | 24µs | BEGIN@43 | DBIx::Class::SQLMaker::
1 | 1 | 1 | 12µs | 52µs | BEGIN@45 | DBIx::Class::SQLMaker::
1 | 1 | 1 | 11µs | 28µs | BEGIN@4 | DBIx::Class::SQLMaker::
1 | 1 | 1 | 10µs | 30µs | BEGIN@67 | DBIx::Class::SQLMaker::
1 | 1 | 1 | 9µs | 103µs | BEGIN@46 | DBIx::Class::SQLMaker::
1 | 1 | 1 | 9µs | 9.28ms | BEGIN@38 | DBIx::Class::SQLMaker::
1 | 1 | 1 | 7µs | 180µs | BEGIN@48 | DBIx::Class::SQLMaker::
1 | 1 | 1 | 6µs | 6µs | BEGIN@47 | DBIx::Class::SQLMaker::
0 | 0 | 0 | 0s | 0s | __ANON__[:72] | DBIx::Class::SQLMaker::
0 | 0 | 0 | 0s | 0s | __ANON__[:77] | DBIx::Class::SQLMaker::
0 | 0 | 0 | 0s | 0s | _lock_select | DBIx::Class::SQLMaker::
0 | 0 | 0 | 0s | 0s | _where_op_NEST | DBIx::Class::SQLMaker::
0 | 0 | 0 | 0s | 0s | _where_op_VALUE | DBIx::Class::SQLMaker::
0 | 0 | 0 | 0s | 0s | throw_exception | DBIx::Class::SQLMaker::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package DBIx::Class::SQLMaker; | ||||
2 | |||||
3 | 3 | 22µs | 2 | 24µs | # spent 19µs (14+5) within DBIx::Class::SQLMaker::BEGIN@3 which was called:
# once (14µs+5µs) by base::import at line 3 # spent 19µs making 1 call to DBIx::Class::SQLMaker::BEGIN@3
# spent 5µs making 1 call to strict::import |
4 | 3 | 38µs | 2 | 45µs | # spent 28µs (11+17) within DBIx::Class::SQLMaker::BEGIN@4 which was called:
# once (11µs+17µs) by base::import at line 4 # spent 28µs making 1 call to DBIx::Class::SQLMaker::BEGIN@4
# spent 17µs making 1 call to warnings::import |
5 | |||||
6 | =head1 NAME | ||||
7 | |||||
8 | DBIx::Class::SQLMaker - An SQL::Abstract-based SQL maker class | ||||
9 | |||||
10 | =head1 DESCRIPTION | ||||
11 | |||||
12 | This module is a subclass of L<SQL::Abstract> and includes a number of | ||||
13 | DBIC-specific workarounds, not yet suitable for inclusion into the | ||||
14 | L<SQL::Abstract> core. It also provides all (and more than) the functionality | ||||
15 | of L<SQL::Abstract::Limit>, see L<DBIx::Class::SQLMaker::LimitDialects> for | ||||
16 | more info. | ||||
17 | |||||
18 | Currently the enhancements to L<SQL::Abstract> are: | ||||
19 | |||||
20 | =over | ||||
21 | |||||
22 | =item * Support for C<JOIN> statements (via extended C<table/from> support) | ||||
23 | |||||
24 | =item * Support of functions in C<SELECT> lists | ||||
25 | |||||
26 | =item * C<GROUP BY>/C<HAVING> support (via extensions to the order_by parameter) | ||||
27 | |||||
28 | =item * Support of C<...FOR UPDATE> type of select statement modifiers | ||||
29 | |||||
30 | =item * The L</-ident> operator | ||||
31 | |||||
32 | =item * The L</-value> operator | ||||
33 | |||||
34 | =back | ||||
35 | |||||
36 | =cut | ||||
37 | |||||
38 | 1 | 6µs | 1 | 0s | # spent 9.28ms (9µs+9.27) within DBIx::Class::SQLMaker::BEGIN@38 which was called:
# once (9µs+9.27ms) by base::import at line 42 # spent 9.27ms making 1 call to base::import, recursion: max depth 1, sum of overlapping time 9.27ms |
39 | DBIx::Class::SQLMaker::LimitDialects | ||||
40 | SQL::Abstract | ||||
41 | DBIx::Class | ||||
42 | 2 | 29µs | 1 | 9.28ms | /; # spent 9.28ms making 1 call to DBIx::Class::SQLMaker::BEGIN@38 |
43 | 3 | 23µs | 2 | 35µs | # spent 24µs (12+11) within DBIx::Class::SQLMaker::BEGIN@43 which was called:
# once (12µs+11µs) by base::import at line 43 # spent 24µs making 1 call to DBIx::Class::SQLMaker::BEGIN@43
# spent 11µs making 1 call to mro::import |
44 | |||||
45 | 3 | 24µs | 2 | 92µs | # spent 52µs (12+40) within DBIx::Class::SQLMaker::BEGIN@45 which was called:
# once (12µs+40µs) by base::import at line 45 # spent 52µs making 1 call to DBIx::Class::SQLMaker::BEGIN@45
# spent 40µs making 1 call to Exporter::import |
46 | 3 | 22µs | 2 | 198µs | # spent 103µs (9+94) within DBIx::Class::SQLMaker::BEGIN@46 which was called:
# once (9µs+94µs) by base::import at line 46 # spent 103µs making 1 call to DBIx::Class::SQLMaker::BEGIN@46
# spent 94µs making 1 call to DBIx::Class::Carp::import |
47 | 3 | 19µs | 1 | 6µs | # spent 6µs within DBIx::Class::SQLMaker::BEGIN@47 which was called:
# once (6µs+0s) by base::import at line 47 # spent 6µs making 1 call to DBIx::Class::SQLMaker::BEGIN@47 |
48 | 3 | 110µs | 2 | 352µs | # spent 180µs (7+173) within DBIx::Class::SQLMaker::BEGIN@48 which was called:
# once (7µs+173µs) by base::import at line 48 # spent 180µs making 1 call to DBIx::Class::SQLMaker::BEGIN@48
# spent 173µs making 1 call to namespace::clean::import |
49 | |||||
50 | 1 | 40µs | 1 | 233µs | __PACKAGE__->mk_group_accessors (simple => qw/quote_char name_sep limit_dialect/); # spent 233µs making 1 call to Class::Accessor::Grouped::mk_group_accessors |
51 | |||||
52 | # for when I need a normalized l/r pair | ||||
53 | # spent 1.13ms within DBIx::Class::SQLMaker::_quote_chars which was called 147 times, avg 8µs/call:
# 147 times (1.13ms+0s) by DBIx::Class::Storage::DBIHacks::_resolve_aliastypes_from_select_args at line 321 of DBIx/Class/Storage/DBIHacks.pm, avg 8µs/call | ||||
54 | map | ||||
55 | { defined $_ ? $_ : '' } | ||||
56 | 147 | 1.14ms | ( ref $_[0]->{quote_char} ? (@{$_[0]->{quote_char}}) : ( ($_[0]->{quote_char}) x 2 ) ) | ||
57 | ; | ||||
58 | } | ||||
59 | |||||
60 | # FIXME when we bring in the storage weaklink, check its schema | ||||
61 | # weaklink and channel through $schema->throw_exception | ||||
62 | sub throw_exception { DBIx::Class::Exception->throw($_[1]) } | ||||
63 | |||||
64 | # spent 248µs (33+214) within DBIx::Class::SQLMaker::BEGIN@64 which was called:
# once (33µs+214µs) by base::import at line 81 | ||||
65 | # reinstall the belch()/puke() functions of SQL::Abstract with custom versions | ||||
66 | # that use DBIx::Class::Carp/DBIx::Class::Exception instead of plain Carp | ||||
67 | 3 | 118µs | 2 | 50µs | # spent 30µs (10+20) within DBIx::Class::SQLMaker::BEGIN@67 which was called:
# once (10µs+20µs) by base::import at line 67 # spent 30µs making 1 call to DBIx::Class::SQLMaker::BEGIN@67
# spent 20µs making 1 call to warnings::unimport |
68 | |||||
69 | *SQL::Abstract::belch = subname 'SQL::Abstract::belch' => sub (@) { | ||||
70 | my($func) = (caller(1))[3]; | ||||
71 | carp "[$func] Warning: ", @_; | ||||
72 | 1 | 19µs | 1 | 3µs | }; # spent 3µs making 1 call to Sub::Name::subname |
73 | |||||
74 | *SQL::Abstract::puke = subname 'SQL::Abstract::puke' => sub (@) { | ||||
75 | my($func) = (caller(1))[3]; | ||||
76 | __PACKAGE__->throw_exception("[$func] Fatal: " . join ('', @_)); | ||||
77 | 1 | 12µs | 1 | 2µs | }; # spent 2µs making 1 call to Sub::Name::subname |
78 | |||||
79 | # Current SQLA pollutes its namespace - clean for the time being | ||||
80 | 1 | 6µs | 1 | 209µs | namespace::clean->clean_subroutines(qw/SQL::Abstract carp croak confess/); # spent 209µs making 1 call to namespace::clean::clean_subroutines |
81 | 1 | 1.73ms | 1 | 248µs | } # spent 248µs making 1 call to DBIx::Class::SQLMaker::BEGIN@64 |
82 | |||||
83 | # the "oh noes offset/top without limit" constant | ||||
84 | # limited to 31 bits for sanity (and consistency, | ||||
85 | # since it may be handed to the like of sprintf %u) | ||||
86 | # | ||||
87 | # Also *some* builds of SQLite fail the test | ||||
88 | # some_column BETWEEN ? AND ?: 1, 4294967295 | ||||
89 | # with the proper integer bind attrs | ||||
90 | # | ||||
91 | # Implemented as a method, since ::Storage::DBI also | ||||
92 | # refers to it (i.e. for the case of software_limit or | ||||
93 | # as the value to abuse with MSSQL ordered subqueries) | ||||
94 | sub __max_int () { 0x7FFFFFFF }; | ||||
95 | |||||
96 | # poor man's de-qualifier | ||||
97 | # spent 1.77s (423ms+1.34) within DBIx::Class::SQLMaker::_quote which was called 63788 times, avg 28µs/call:
# 36394 times (245ms+787ms) by DBIx::Class::SQLMaker::_recurse_fields at line 274, avg 28µs/call
# 7879 times (48.7ms+149ms) by SQL::Abstract::_where_hashpair_SCALAR at line 858 of SQL/Abstract.pm, avg 25µs/call
# 6853 times (38.5ms+127ms) by DBIx::Class::SQLMaker::_from_chunk_to_sql at line 445, avg 24µs/call
# 6853 times (35.7ms+107ms) by DBIx::Class::SQLMaker::_from_chunk_to_sql at line 464, avg 21µs/call
# 1952 times (17.8ms+56.6ms) by SQL::Abstract::_insert_HASHREF at line 175 of SQL/Abstract.pm, avg 38µs/call
# 1313 times (20.1ms+64.8ms) by SQL::Abstract::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/SQL/Abstract.pm:1149] at line 1149 of SQL/Abstract.pm, avg 65µs/call
# 992 times (10.1ms+30.9ms) by SQL::Abstract::update at line 288 of SQL/Abstract.pm, avg 41µs/call
# 781 times (3.58ms+11.1ms) by SQL::Abstract::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/SQL/Abstract.pm:1098] at line 1098 of SQL/Abstract.pm, avg 19µs/call
# 477 times (2.31ms+7.13ms) by SQL::Abstract::__ANON__[/2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/SQL/Abstract.pm:782] at line 778 of SQL/Abstract.pm, avg 20µs/call
# 294 times (1.26ms+4.23ms) by DBIx::Class::SQLMaker::_where_op_IDENT at line 129, avg 19µs/call | ||||
98 | 63788 | 315ms | 63788 | 422ms | $_[0]->next::method( ( $_[0]{_dequalify_idents} and ! ref $_[1] ) # spent 422ms making 63788 calls to next::method, avg 7µs/call |
99 | ? $_[1] =~ / ([^\.]+) $ /x | ||||
100 | : $_[1] | ||||
101 | ); | ||||
102 | } | ||||
103 | |||||
104 | # spent 625µs (144+481) within DBIx::Class::SQLMaker::new which was called 5 times, avg 125µs/call:
# 5 times (144µs+481µs) by DBIx::Class::Storage::DBI::sql_maker at line 985 of DBIx/Class/Storage/DBI.pm, avg 125µs/call | ||||
105 | 5 | 30µs | 5 | 90µs | my $self = shift->next::method(@_); # spent 90µs making 5 calls to next::method, avg 18µs/call |
106 | |||||
107 | # use the same coderefs, they are prepared to handle both cases | ||||
108 | 5 | 73µs | 10 | 19µs | my @extra_dbic_syntax = ( # spent 19µs making 10 calls to DBIx::Class::SQLMaker::CORE:qr, avg 2µs/call |
109 | { regex => qr/^ ident $/xi, handler => '_where_op_IDENT' }, | ||||
110 | { regex => qr/^ value $/xi, handler => '_where_op_VALUE' }, | ||||
111 | ); | ||||
112 | |||||
113 | 5 | 6µs | push @{$self->{special_ops}}, @extra_dbic_syntax; | ||
114 | 5 | 6µs | push @{$self->{unary_ops}}, @extra_dbic_syntax; | ||
115 | |||||
116 | 5 | 23µs | $self; | ||
117 | } | ||||
118 | |||||
119 | # spent 8.56ms (2.61+5.96) within DBIx::Class::SQLMaker::_where_op_IDENT which was called 147 times, avg 58µs/call:
# 147 times (2.61ms+5.96ms) by SQL::Abstract::_where_hashpair_HASHREF at line 735 of SQL/Abstract.pm, avg 58µs/call | ||||
120 | 147 | 96µs | my $self = shift; | ||
121 | 147 | 339µs | my ($op, $rhs) = splice @_, -2; | ||
122 | 147 | 63µs | if (ref $rhs) { | ||
123 | $self->throw_exception("-$op takes a single scalar argument (a quotable identifier)"); | ||||
124 | } | ||||
125 | |||||
126 | # in case we are called as a top level special op (no '=') | ||||
127 | 147 | 114µs | my $lhs = shift; | ||
128 | |||||
129 | 294 | 1.10ms | 588 | 5.96ms | $_ = $self->_convert($self->_quote($_)) for ($lhs, $rhs); # spent 5.49ms making 294 calls to DBIx::Class::SQLMaker::_quote, avg 19µs/call
# spent 463µs making 294 calls to SQL::Abstract::_convert, avg 2µs/call |
130 | |||||
131 | 147 | 481µs | return $lhs | ||
132 | ? "$lhs = $rhs" | ||||
133 | : $rhs | ||||
134 | ; | ||||
135 | } | ||||
136 | |||||
137 | sub _where_op_VALUE { | ||||
138 | my $self = shift; | ||||
139 | my ($op, $rhs) = splice @_, -2; | ||||
140 | |||||
141 | # in case we are called as a top level special op (no '=') | ||||
142 | my $lhs = shift; | ||||
143 | |||||
144 | my @bind = [ | ||||
145 | ($lhs || $self->{_nested_func_lhs} || $self->throw_exception("Unable to find bindtype for -value $rhs") ), | ||||
146 | $rhs | ||||
147 | ]; | ||||
148 | |||||
149 | return $lhs | ||||
150 | ? ( | ||||
151 | $self->_convert($self->_quote($lhs)) . ' = ' . $self->_convert('?'), | ||||
152 | @bind | ||||
153 | ) | ||||
154 | : ( | ||||
155 | $self->_convert('?'), | ||||
156 | @bind, | ||||
157 | ) | ||||
158 | ; | ||||
159 | } | ||||
160 | |||||
161 | sub _where_op_NEST { | ||||
162 | carp_unique ("-nest in search conditions is deprecated, you most probably wanted:\n" | ||||
163 | .q|{..., -and => [ \%cond0, \@cond1, \'cond2', \[ 'cond3', [ col => bind ] ], etc. ], ... }| | ||||
164 | ); | ||||
165 | |||||
166 | shift->next::method(@_); | ||||
167 | } | ||||
168 | |||||
169 | # Handle limit-dialect selection | ||||
170 | # spent 4.80s (208ms+4.59) within DBIx::Class::SQLMaker::select which was called 6706 times, avg 715µs/call:
# 6706 times (208ms+4.59s) by DBIx::Class::Storage::DBI::_gen_sql_bind at line 1428 of DBIx/Class/Storage/DBI.pm, avg 715µs/call | ||||
171 | 6706 | 13.5ms | my ($self, $table, $fields, $where, $rs_attrs, $limit, $offset) = @_; | ||
172 | |||||
173 | |||||
174 | 6706 | 25.1ms | 6706 | 1.42s | $fields = $self->_recurse_fields($fields); # spent 1.42s making 6706 calls to DBIx::Class::SQLMaker::_recurse_fields, avg 212µs/call |
175 | |||||
176 | 6706 | 3.19ms | if (defined $offset) { | ||
177 | $self->throw_exception('A supplied offset must be a non-negative integer') | ||||
178 | if ( $offset =~ /\D/ or $offset < 0 ); | ||||
179 | } | ||||
180 | 6706 | 4.16ms | $offset ||= 0; | ||
181 | |||||
182 | 6706 | 3.56ms | if (defined $limit) { | ||
183 | 5 | 35µs | 5 | 6µs | $self->throw_exception('A supplied limit must be a positive integer') # spent 6µs making 5 calls to DBIx::Class::SQLMaker::CORE:match, avg 1µs/call |
184 | if ( $limit =~ /\D/ or $limit <= 0 ); | ||||
185 | } | ||||
186 | elsif ($offset) { | ||||
187 | $limit = $self->__max_int; | ||||
188 | } | ||||
189 | |||||
190 | |||||
191 | 6706 | 4.63ms | my ($sql, @bind); | ||
192 | 6706 | 6.59ms | if ($limit) { | ||
193 | # this is legacy code-flow from SQLA::Limit, it is not set in stone | ||||
194 | |||||
195 | 5 | 29µs | 5 | 66µs | ($sql, @bind) = $self->next::method ($table, $fields, $where); # spent 66µs making 5 calls to next::method, avg 13µs/call |
196 | |||||
197 | my $limiter = | ||||
198 | $self->can ('emulate_limit') # also backcompat hook from SQLA::Limit | ||||
199 | || | ||||
200 | 5 | 49µs | 5 | 20µs | do { # spent 20µs making 5 calls to UNIVERSAL::can, avg 4µs/call |
201 | 5 | 28µs | 2 | 130µs | my $dialect = $self->limit_dialect # spent 128µs making 1 call to DBIx::Class::SQLMaker::limit_dialect
# spent 3µs making 1 call to DBIx::Class::SQLMaker::SQLite::limit_dialect |
202 | or $self->throw_exception( "Unable to generate SQL-limit - no limit dialect specified on $self, and no emulate_limit method found" ); | ||||
203 | 5 | 41µs | 5 | 13µs | $self->can ("_$dialect") # spent 13µs making 5 calls to UNIVERSAL::can, avg 3µs/call |
204 | or $self->throw_exception(__PACKAGE__ . " does not implement the requested dialect '$dialect'"); | ||||
205 | } | ||||
206 | ; | ||||
207 | |||||
208 | $sql = $self->$limiter ( | ||||
209 | $sql, | ||||
210 | 5 | 87µs | 5 | 2.85ms | { %{$rs_attrs||{}}, _selector_sql => $fields }, # spent 2.85ms making 5 calls to DBIx::Class::SQLMaker::LimitDialects::_LimitOffset, avg 570µs/call |
211 | $limit, | ||||
212 | $offset | ||||
213 | ); | ||||
214 | } | ||||
215 | else { | ||||
216 | 6701 | 32.5ms | 6701 | 44.8ms | ($sql, @bind) = $self->next::method ($table, $fields, $where, $rs_attrs); # spent 44.8ms making 6701 calls to next::method, avg 7µs/call |
217 | } | ||||
218 | |||||
219 | 6706 | 12.3ms | push @{$self->{where_bind}}, @bind; | ||
220 | |||||
221 | # this *must* be called, otherwise extra binds will remain in the sql-maker | ||||
222 | 6706 | 25.7ms | 6706 | 59.1ms | my @all_bind = $self->_assemble_binds; # spent 59.1ms making 6706 calls to DBIx::Class::SQLMaker::_assemble_binds, avg 9µs/call |
223 | |||||
224 | 6706 | 5.09ms | $sql .= $self->_lock_select ($rs_attrs->{for}) | ||
225 | if $rs_attrs->{for}; | ||||
226 | |||||
227 | 6706 | 29.1ms | return wantarray ? ($sql, @all_bind) : $sql; | ||
228 | } | ||||
229 | |||||
230 | # spent 59.1ms within DBIx::Class::SQLMaker::_assemble_binds which was called 6706 times, avg 9µs/call:
# 6706 times (59.1ms+0s) by DBIx::Class::SQLMaker::select at line 222, avg 9µs/call | ||||
231 | 6706 | 4.70ms | my $self = shift; | ||
232 | 6706 | 63.6ms | return map { @{ (delete $self->{"${_}_bind"}) || [] } } (qw/select from where group having order limit/); | ||
233 | } | ||||
234 | |||||
235 | 1 | 2µs | my $for_syntax = { | ||
236 | update => 'FOR UPDATE', | ||||
237 | shared => 'FOR SHARE', | ||||
238 | }; | ||||
239 | sub _lock_select { | ||||
240 | my ($self, $type) = @_; | ||||
241 | my $sql = $for_syntax->{$type} || $self->throw_exception( "Unknown SELECT .. FOR type '$type' requested" ); | ||||
242 | return " $sql"; | ||||
243 | } | ||||
244 | |||||
245 | # Handle default inserts | ||||
246 | # spent 431ms (8.16+423) within DBIx::Class::SQLMaker::insert which was called 449 times, avg 961µs/call:
# 449 times (8.16ms+423ms) by DBIx::Class::Storage::DBI::_gen_sql_bind at line 1428 of DBIx/Class/Storage/DBI.pm, avg 961µs/call | ||||
247 | # optimized due to hotttnesss | ||||
248 | # my ($self, $table, $data, $options) = @_; | ||||
249 | |||||
250 | # SQLA will emit INSERT INTO $table ( ) VALUES ( ) | ||||
251 | # which is sadly understood only by MySQL. Change default behavior here, | ||||
252 | # until SQLA2 comes with proper dialect support | ||||
253 | 449 | 1.79ms | if (! $_[2] or (ref $_[2] eq 'HASH' and !keys %{$_[2]} ) ) { | ||
254 | my @bind; | ||||
255 | my $sql = sprintf( | ||||
256 | 'INSERT INTO %s DEFAULT VALUES', $_[0]->_quote($_[1]) | ||||
257 | ); | ||||
258 | |||||
259 | if ( ($_[3]||{})->{returning} ) { | ||||
260 | my $s; | ||||
261 | ($s, @bind) = $_[0]->_insert_returning ($_[3]); | ||||
262 | $sql .= $s; | ||||
263 | } | ||||
264 | |||||
265 | return ($sql, @bind); | ||||
266 | } | ||||
267 | |||||
268 | 449 | 3.68ms | 449 | 9.18ms | next::method(@_); # spent 9.18ms making 449 calls to next::method, avg 20µs/call |
269 | } | ||||
270 | |||||
271 | # spent 1.43s (392ms+1.04) within DBIx::Class::SQLMaker::_recurse_fields which was called 45197 times, avg 32µs/call:
# 36394 times (201ms+-201ms) by DBIx::Class::SQLMaker::_recurse_fields at line 278, avg 0s/call
# 6706 times (176ms+1.24s) by DBIx::Class::SQLMaker::select at line 174, avg 212µs/call
# 1949 times (13.2ms+-13.2ms) by DBIx::Class::SQLMaker::_recurse_fields at line 300, avg 0s/call
# 147 times (2.35ms+9.60ms) by DBIx::Class::Storage::DBIHacks::_resolve_aliastypes_from_select_args at line 333 of DBIx/Class/Storage/DBIHacks.pm, avg 81µs/call
# once (5µs+21µs) by DBIx::Class::SQLMaker::_parse_rs_attrs at line 337 | ||||
272 | 45197 | 26.9ms | my ($self, $fields) = @_; | ||
273 | 45197 | 19.5ms | my $ref = ref $fields; | ||
274 | 45197 | 131ms | 36394 | 1.03s | return $self->_quote($fields) unless $ref; # spent 1.03s making 36394 calls to DBIx::Class::SQLMaker::_quote, avg 28µs/call |
275 | 8803 | 5.32ms | return $$fields if $ref eq 'SCALAR'; | ||
276 | |||||
277 | 8803 | 5.89ms | if ($ref eq 'ARRAY') { | ||
278 | 43248 | 121ms | 36394 | 0s | return join(', ', map { $self->_recurse_fields($_) } @$fields); # spent 1.25s making 36394 calls to DBIx::Class::SQLMaker::_recurse_fields, avg 34µs/call, recursion: max depth 1, sum of overlapping time 1.25s |
279 | } | ||||
280 | elsif ($ref eq 'HASH') { | ||||
281 | 1949 | 6.45ms | my %hash = %$fields; # shallow copy | ||
282 | |||||
283 | 1949 | 2.45ms | my $as = delete $hash{-as}; # if supplied | ||
284 | |||||
285 | 1949 | 3.46ms | my ($func, $args, @toomany) = %hash; | ||
286 | |||||
287 | # there should be only one pair | ||||
288 | 1949 | 864µs | if (@toomany) { | ||
289 | $self->throw_exception( "Malformed select argument - too many keys in hash: " . join (',', keys %$fields ) ); | ||||
290 | } | ||||
291 | |||||
292 | 1949 | 2.89ms | if (lc ($func) eq 'distinct' && ref $args eq 'ARRAY' && @$args > 1) { | ||
293 | $self->throw_exception ( | ||||
294 | 'The select => { distinct => ... } syntax is not supported for multiple columns.' | ||||
295 | .' Instead please use { group_by => [ qw/' . (join ' ', @$args) . '/ ] }' | ||||
296 | .' or { select => [ qw/' . (join ' ', @$args) . '/ ], distinct => 1 }' | ||||
297 | ); | ||||
298 | } | ||||
299 | |||||
300 | 1949 | 19.2ms | 3898 | 7.40ms | my $select = sprintf ('%s( %s )%s', # spent 7.40ms making 1949 calls to SQL::Abstract::_sqlcase, avg 4µs/call
# spent 112ms making 1949 calls to DBIx::Class::SQLMaker::_recurse_fields, avg 57µs/call, recursion: max depth 2, sum of overlapping time 112ms |
301 | $self->_sqlcase($func), | ||||
302 | $self->_recurse_fields($args), | ||||
303 | $as | ||||
304 | ? sprintf (' %s %s', $self->_sqlcase('as'), $self->_quote ($as) ) | ||||
305 | : '' | ||||
306 | ); | ||||
307 | |||||
308 | 1949 | 7.26ms | return $select; | ||
309 | } | ||||
310 | # Is the second check absolutely necessary? | ||||
311 | elsif ( $ref eq 'REF' and ref($$fields) eq 'ARRAY' ) { | ||||
312 | push @{$self->{select_bind}}, @{$$fields}[1..$#$$fields]; | ||||
313 | return $$fields->[0]; | ||||
314 | } | ||||
315 | else { | ||||
316 | $self->throw_exception( $ref . qq{ unexpected in _recurse_fields()} ); | ||||
317 | } | ||||
318 | } | ||||
319 | |||||
320 | |||||
321 | # this used to be a part of _order_by but is broken out for clarity. | ||||
322 | # What we have been doing forever is hijacking the $order arg of | ||||
323 | # SQLA::select to pass in arbitrary pieces of data (first the group_by, | ||||
324 | # then pretty much the entire resultset attr-hash, as more and more | ||||
325 | # things in the SQLA space need to have mopre info about the $rs they | ||||
326 | # create SQL for. The alternative would be to keep expanding the | ||||
327 | # signature of _select with more and more positional parameters, which | ||||
328 | # is just gross. All hail SQLA2! | ||||
329 | # spent 154ms (45.3+109) within DBIx::Class::SQLMaker::_parse_rs_attrs which was called 6853 times, avg 22µs/call:
# 6701 times (44.4ms+106ms) by DBIx::Class::SQLMaker::_order_by at line 360, avg 22µs/call
# 147 times (814µs+0s) by DBIx::Class::Storage::DBIHacks::_resolve_aliastypes_from_select_args at line 333 of DBIx/Class/Storage/DBIHacks.pm, avg 6µs/call
# 5 times (77µs+2.63ms) by DBIx::Class::SQLMaker::LimitDialects::_LimitOffset at line 53 of DBIx/Class/SQLMaker/LimitDialects.pm, avg 542µs/call | ||||
330 | 6853 | 6.19ms | my ($self, $arg) = @_; | ||
331 | |||||
332 | 6853 | 5.54ms | my $sql = ''; | ||
333 | |||||
334 | 6853 | 5.24ms | if ($arg->{group_by}) { | ||
335 | # horible horrible, waiting for refactor | ||||
336 | 1 | 2µs | local $self->{select_bind}; | ||
337 | 1 | 2µs | 1 | 26µs | if (my $g = $self->_recurse_fields($arg->{group_by}) ) { # spent 26µs making 1 call to DBIx::Class::SQLMaker::_recurse_fields |
338 | 1 | 3µs | 1 | 3µs | $sql .= $self->_sqlcase(' group by ') . $g; # spent 3µs making 1 call to SQL::Abstract::_sqlcase |
339 | 1 | 2µs | push @{$self->{group_bind} ||= []}, @{$self->{select_bind}||[]}; | ||
340 | } | ||||
341 | } | ||||
342 | |||||
343 | 6853 | 5.32ms | if (defined $arg->{having}) { | ||
344 | my ($frag, @bind) = $self->_recurse_where($arg->{having}); | ||||
345 | push(@{$self->{having_bind}}, @bind); | ||||
346 | $sql .= $self->_sqlcase(' having ') . $frag; | ||||
347 | } | ||||
348 | |||||
349 | 6853 | 5.60ms | 629 | 2.63ms | if (defined $arg->{order_by}) { # spent 109ms making 629 calls to DBIx::Class::SQLMaker::_order_by, avg 173µs/call, recursion: max depth 1, sum of overlapping time 106ms |
350 | $sql .= $self->_order_by ($arg->{order_by}); | ||||
351 | } | ||||
352 | |||||
353 | 6853 | 23.8ms | return $sql; | ||
354 | } | ||||
355 | |||||
356 | # spent 440ms (258+182) within DBIx::Class::SQLMaker::_order_by which was called 7330 times, avg 60µs/call:
# 6701 times (251ms+186ms) by SQL::Abstract::where at line 403 of SQL/Abstract.pm, avg 65µs/call
# 629 times (7.20ms+-4.57ms) by DBIx::Class::SQLMaker::_parse_rs_attrs at line 349, avg 4µs/call | ||||
357 | 7330 | 6.23ms | my ($self, $arg) = @_; | ||
358 | |||||
359 | # check that we are not called in legacy mode (order_by as 4th argument) | ||||
360 | 86805 | 278ms | 86176 | 186ms | if (ref $arg eq 'HASH' and not grep { $_ =~ /^-(?:desc|asc)/i } keys %$arg ) { # spent 150ms making 6701 calls to DBIx::Class::SQLMaker::_parse_rs_attrs, avg 22µs/call
# spent 36.0ms making 79475 calls to DBIx::Class::SQLMaker::CORE:match, avg 453ns/call |
361 | return $self->_parse_rs_attrs ($arg); | ||||
362 | } | ||||
363 | else { | ||||
364 | 629 | 1.54ms | 629 | 3.44ms | my ($sql, @bind) = $self->next::method($arg); # spent 3.44ms making 629 calls to next::method, avg 5µs/call |
365 | 629 | 781µs | push @{$self->{order_bind}}, @bind; | ||
366 | 629 | 1.96ms | return $sql; | ||
367 | } | ||||
368 | } | ||||
369 | |||||
370 | # spent 1.01s (74.5ms+932ms) within DBIx::Class::SQLMaker::_table which was called 8019 times, avg 125µs/call:
# 6706 times (53.2ms+713ms) by SQL::Abstract::select at line 354 of SQL/Abstract.pm, avg 114µs/call
# 845 times (13.2ms+135ms) by SQL::Abstract::update at line 276 of SQL/Abstract.pm, avg 175µs/call
# 449 times (7.68ms+80.0ms) by SQL::Abstract::insert at line 137 of SQL/Abstract.pm, avg 195µs/call
# 19 times (460µs+4.38ms) by SQL::Abstract::delete at line 377 of SQL/Abstract.pm, avg 255µs/call | ||||
371 | # optimized due to hotttnesss | ||||
372 | # my ($self, $from) = @_; | ||||
373 | 8019 | 10.4ms | if (my $ref = ref $_[1] ) { | ||
374 | 6706 | 46.8ms | 6706 | 713ms | if ($ref eq 'ARRAY') { # spent 713ms making 6706 calls to DBIx::Class::SQLMaker::_recurse_from, avg 106µs/call |
375 | return $_[0]->_recurse_from(@{$_[1]}); | ||||
376 | } | ||||
377 | elsif ($ref eq 'HASH') { | ||||
378 | return $_[0]->_recurse_from($_[1]); | ||||
379 | } | ||||
380 | elsif ($ref eq 'REF' && ref ${$_[1]} eq 'ARRAY') { | ||||
381 | my ($sql, @bind) = @{ ${$_[1]} }; | ||||
382 | push @{$_[0]->{from_bind}}, @bind; | ||||
383 | return $sql | ||||
384 | } | ||||
385 | } | ||||
386 | 1313 | 11.8ms | 1313 | 14.8ms | return $_[0]->next::method ($_[1]); # spent 14.8ms making 1313 calls to next::method, avg 11µs/call |
387 | } | ||||
388 | |||||
389 | # spent 982µs within DBIx::Class::SQLMaker::_generate_join_clause which was called 147 times, avg 7µs/call:
# 147 times (982µs+0s) by DBIx::Class::SQLMaker::_gen_from_blocks at line 422, avg 7µs/call | ||||
390 | 147 | 81µs | my ($self, $join_type) = @_; | ||
391 | |||||
392 | 147 | 108µs | $join_type = $self->{_default_jointype} | ||
393 | if ! defined $join_type; | ||||
394 | |||||
395 | 147 | 990µs | return sprintf ('%s JOIN ', | ||
396 | $join_type ? $self->_sqlcase($join_type) : '' | ||||
397 | ); | ||||
398 | } | ||||
399 | |||||
400 | # spent 713ms (49.2+663) within DBIx::Class::SQLMaker::_recurse_from which was called 6706 times, avg 106µs/call:
# 6706 times (49.2ms+663ms) by DBIx::Class::SQLMaker::_table at line 374, avg 106µs/call | ||||
401 | 6706 | 3.89ms | my $self = shift; | ||
402 | |||||
403 | 6706 | 42.0ms | 6706 | 663ms | return join (' ', $self->_gen_from_blocks(@_) ); # spent 663ms making 6706 calls to DBIx::Class::SQLMaker::_gen_from_blocks, avg 99µs/call |
404 | } | ||||
405 | |||||
406 | # spent 663ms (69.2+594) within DBIx::Class::SQLMaker::_gen_from_blocks which was called 6706 times, avg 99µs/call:
# 6706 times (69.2ms+594ms) by DBIx::Class::SQLMaker::_recurse_from at line 403, avg 99µs/call | ||||
407 | 6706 | 8.79ms | my ($self, $from, @joins) = @_; | ||
408 | |||||
409 | 6706 | 27.5ms | 6706 | 553ms | my @fchunks = $self->_from_chunk_to_sql($from); # spent 553ms making 6706 calls to DBIx::Class::SQLMaker::_from_chunk_to_sql, avg 83µs/call |
410 | |||||
411 | 6706 | 7.60ms | for (@joins) { | ||
412 | 147 | 123µs | my ($to, $on) = @$_; | ||
413 | |||||
414 | # check whether a join type exists | ||||
415 | 147 | 162µs | my $to_jt = ref($to) eq 'ARRAY' ? $to->[0] : $to; | ||
416 | 147 | 42µs | my $join_type; | ||
417 | 147 | 214µs | if (ref($to_jt) eq 'HASH' and defined($to_jt->{-join_type})) { | ||
418 | $join_type = $to_jt->{-join_type}; | ||||
419 | $join_type =~ s/^\s+ | \s+$//xg; | ||||
420 | } | ||||
421 | |||||
422 | 147 | 509µs | 147 | 982µs | my @j = $self->_generate_join_clause( $join_type ); # spent 982µs making 147 calls to DBIx::Class::SQLMaker::_generate_join_clause, avg 7µs/call |
423 | |||||
424 | 147 | 174µs | if (ref $to eq 'ARRAY') { | ||
425 | push(@j, '(', $self->_recurse_from(@$to), ')'); | ||||
426 | } | ||||
427 | else { | ||||
428 | 147 | 255µs | 147 | 9.10ms | push(@j, $self->_from_chunk_to_sql($to)); # spent 9.10ms making 147 calls to DBIx::Class::SQLMaker::_from_chunk_to_sql, avg 62µs/call |
429 | } | ||||
430 | |||||
431 | 147 | 412µs | 147 | 30.7ms | my ($sql, @bind) = $self->_join_condition($on); # spent 30.7ms making 147 calls to DBIx::Class::SQLMaker::_join_condition, avg 209µs/call |
432 | 147 | 128µs | push(@j, ' ON ', $sql); | ||
433 | 147 | 178µs | push @{$self->{from_bind}}, @bind; | ||
434 | |||||
435 | 147 | 326µs | push @fchunks, join '', @j; | ||
436 | } | ||||
437 | |||||
438 | 6706 | 25.4ms | return @fchunks; | ||
439 | } | ||||
440 | |||||
441 | # spent 563ms (231+332) within DBIx::Class::SQLMaker::_from_chunk_to_sql which was called 13706 times, avg 41µs/call:
# 6853 times (40.3ms+-40.3ms) by DBIx::Class::SQLMaker::_from_chunk_to_sql at line 464, avg 0s/call
# 6706 times (187ms+366ms) by DBIx::Class::SQLMaker::_gen_from_blocks at line 409, avg 83µs/call
# 147 times (3.03ms+6.07ms) by DBIx::Class::SQLMaker::_gen_from_blocks at line 428, avg 62µs/call | ||||
442 | 13706 | 9.55ms | my ($self, $fromspec) = @_; | ||
443 | |||||
444 | 13706 | 53.3ms | return join (' ', do { | ||
445 | 13706 | 33.9ms | 6853 | 166ms | if (! ref $fromspec) { # spent 166ms making 6853 calls to DBIx::Class::SQLMaker::_quote, avg 24µs/call |
446 | $self->_quote($fromspec); | ||||
447 | } | ||||
448 | elsif (ref $fromspec eq 'SCALAR') { | ||||
449 | $$fromspec; | ||||
450 | } | ||||
451 | elsif (ref $fromspec eq 'REF' and ref $$fromspec eq 'ARRAY') { | ||||
452 | push @{$self->{from_bind}}, @{$$fromspec}[1..$#$$fromspec]; | ||||
453 | $$fromspec->[0]; | ||||
454 | } | ||||
455 | elsif (ref $fromspec eq 'HASH') { | ||||
456 | my ($as, $table, $toomuch) = ( map | ||||
457 | 21000 | 76.5ms | 21000 | 23.3ms | { $_ => $fromspec->{$_} } # spent 23.3ms making 21000 calls to DBIx::Class::SQLMaker::CORE:match, avg 1µs/call |
458 | 6853 | 39.1ms | ( grep { $_ !~ /^\-/ } keys %$fromspec ) | ||
459 | ); | ||||
460 | |||||
461 | 6853 | 2.85ms | $self->throw_exception( "Only one table/as pair expected in from-spec but an exra '$toomuch' key present" ) | ||
462 | if defined $toomuch; | ||||
463 | |||||
464 | 6853 | 25.1ms | 13706 | 143ms | ($self->_from_chunk_to_sql($table), $self->_quote($as) ); # spent 143ms making 6853 calls to DBIx::Class::SQLMaker::_quote, avg 21µs/call
# spent 206ms making 6853 calls to DBIx::Class::SQLMaker::_from_chunk_to_sql, avg 30µs/call, recursion: max depth 1, sum of overlapping time 206ms |
465 | } | ||||
466 | else { | ||||
467 | $self->throw_exception('Unsupported from refkind: ' . ref $fromspec ); | ||||
468 | } | ||||
469 | }); | ||||
470 | } | ||||
471 | |||||
472 | # spent 30.7ms (1.57+29.1) within DBIx::Class::SQLMaker::_join_condition which was called 147 times, avg 209µs/call:
# 147 times (1.57ms+29.1ms) by DBIx::Class::SQLMaker::_gen_from_blocks at line 431, avg 209µs/call | ||||
473 | 147 | 112µs | my ($self, $cond) = @_; | ||
474 | |||||
475 | # Backcompat for the old days when a plain hashref | ||||
476 | # { 't1.col1' => 't2.col2' } meant ON t1.col1 = t2.col2 | ||||
477 | # Once things settle we should start warning here so that | ||||
478 | # folks unroll their hacks | ||||
479 | 147 | 964µs | 147 | 114µs | if ( # spent 114µs making 147 calls to DBIx::Class::SQLMaker::CORE:match, avg 776ns/call |
480 | ref $cond eq 'HASH' | ||||
481 | and | ||||
482 | keys %$cond == 1 | ||||
483 | and | ||||
484 | (keys %$cond)[0] =~ /\./ | ||||
485 | and | ||||
486 | ! ref ( (values %$cond)[0] ) | ||||
487 | ) { | ||||
488 | $cond = { keys %$cond => { -ident => values %$cond } } | ||||
489 | } | ||||
490 | elsif ( ref $cond eq 'ARRAY' ) { | ||||
491 | # do our own ORing so that the hashref-shim above is invoked | ||||
492 | my @parts; | ||||
493 | my @binds; | ||||
494 | foreach my $c (@$cond) { | ||||
495 | my ($sql, @bind) = $self->_join_condition($c); | ||||
496 | push @binds, @bind; | ||||
497 | push @parts, $sql; | ||||
498 | } | ||||
499 | return join(' OR ', @parts), @binds; | ||||
500 | } | ||||
501 | |||||
502 | 147 | 523µs | 147 | 29.0ms | return $self->_recurse_where($cond); # spent 29.0ms making 147 calls to SQL::Abstract::_recurse_where, avg 197µs/call |
503 | } | ||||
504 | |||||
505 | 1 | 6µs | 1; | ||
506 | |||||
507 | =head1 OPERATORS | ||||
508 | |||||
509 | =head2 -ident | ||||
510 | |||||
511 | Used to explicitly specify an SQL identifier. Takes a plain string as value | ||||
512 | which is then invariably treated as a column name (and is being properly | ||||
513 | quoted if quoting has been requested). Most useful for comparison of two | ||||
514 | columns: | ||||
515 | |||||
516 | my %where = ( | ||||
517 | priority => { '<', 2 }, | ||||
518 | requestor => { -ident => 'submitter' } | ||||
519 | ); | ||||
520 | |||||
521 | which results in: | ||||
522 | |||||
523 | $stmt = 'WHERE "priority" < ? AND "requestor" = "submitter"'; | ||||
524 | @bind = ('2'); | ||||
525 | |||||
526 | =head2 -value | ||||
527 | |||||
528 | The -value operator signals that the argument to the right is a raw bind value. | ||||
529 | It will be passed straight to DBI, without invoking any of the SQL::Abstract | ||||
530 | condition-parsing logic. This allows you to, for example, pass an array as a | ||||
531 | column value for databases that support array datatypes, e.g.: | ||||
532 | |||||
533 | my %where = ( | ||||
534 | array => { -value => [1, 2, 3] } | ||||
535 | ); | ||||
536 | |||||
537 | which results in: | ||||
538 | |||||
539 | $stmt = 'WHERE array = ?'; | ||||
540 | @bind = ([1, 2, 3]); | ||||
541 | |||||
542 | =head1 AUTHORS | ||||
543 | |||||
544 | See L<DBIx::Class/CONTRIBUTORS>. | ||||
545 | |||||
546 | =head1 LICENSE | ||||
547 | |||||
548 | You may distribute this code under the same terms as Perl itself. | ||||
549 | |||||
550 | 1 | 16µs | 1 | 333µs | =cut # spent 333µs making 1 call to B::Hooks::EndOfScope::__ANON__[B/Hooks/EndOfScope.pm:26] |
# spent 59.4ms within DBIx::Class::SQLMaker::CORE:match which was called 100627 times, avg 591ns/call:
# 79475 times (36.0ms+0s) by DBIx::Class::SQLMaker::_order_by at line 360, avg 453ns/call
# 21000 times (23.3ms+0s) by DBIx::Class::SQLMaker::_from_chunk_to_sql at line 457, avg 1µs/call
# 147 times (114µs+0s) by DBIx::Class::SQLMaker::_join_condition at line 479, avg 776ns/call
# 5 times (6µs+0s) by DBIx::Class::SQLMaker::select at line 183, avg 1µs/call | |||||
# spent 19µs within DBIx::Class::SQLMaker::CORE:qr which was called 10 times, avg 2µs/call:
# 10 times (19µs+0s) by DBIx::Class::SQLMaker::new at line 108, avg 2µs/call |