| 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 | DBIx::Class::SQLMaker::_quote |
| 45197 | 5 | 2 | 392ms | 1.43s | DBIx::Class::SQLMaker::_recurse_fields (recurses: max depth 2, inclusive time 1.36s) |
| 7330 | 2 | 2 | 258ms | 440ms | DBIx::Class::SQLMaker::_order_by (recurses: max depth 1, inclusive time 106ms) |
| 13706 | 3 | 1 | 231ms | 563ms | DBIx::Class::SQLMaker::_from_chunk_to_sql (recurses: max depth 1, inclusive time 206ms) |
| 6706 | 1 | 1 | 208ms | 4.80s | DBIx::Class::SQLMaker::select |
| 8019 | 4 | 1 | 74.5ms | 1.01s | DBIx::Class::SQLMaker::_table |
| 6706 | 1 | 1 | 69.2ms | 663ms | DBIx::Class::SQLMaker::_gen_from_blocks |
| 100627 | 4 | 1 | 59.4ms | 59.4ms | DBIx::Class::SQLMaker::CORE:match (opcode) |
| 6706 | 1 | 1 | 59.1ms | 59.1ms | DBIx::Class::SQLMaker::_assemble_binds |
| 6706 | 1 | 1 | 49.2ms | 713ms | DBIx::Class::SQLMaker::_recurse_from |
| 6853 | 3 | 3 | 45.3ms | 154ms | DBIx::Class::SQLMaker::_parse_rs_attrs |
| 449 | 1 | 1 | 8.16ms | 431ms | DBIx::Class::SQLMaker::insert |
| 147 | 1 | 1 | 2.61ms | 8.56ms | DBIx::Class::SQLMaker::_where_op_IDENT |
| 147 | 1 | 1 | 1.57ms | 30.7ms | DBIx::Class::SQLMaker::_join_condition |
| 147 | 1 | 1 | 1.13ms | 1.13ms | DBIx::Class::SQLMaker::_quote_chars |
| 147 | 1 | 1 | 982µs | 982µs | DBIx::Class::SQLMaker::_generate_join_clause |
| 5 | 1 | 1 | 144µs | 625µs | DBIx::Class::SQLMaker::new |
| 1 | 1 | 1 | 33µs | 248µs | DBIx::Class::SQLMaker::BEGIN@64 |
| 10 | 1 | 1 | 19µs | 19µs | DBIx::Class::SQLMaker::CORE:qr (opcode) |
| 1 | 1 | 1 | 14µs | 19µs | DBIx::Class::SQLMaker::BEGIN@3 |
| 1 | 1 | 1 | 12µs | 24µs | DBIx::Class::SQLMaker::BEGIN@43 |
| 1 | 1 | 1 | 12µs | 52µs | DBIx::Class::SQLMaker::BEGIN@45 |
| 1 | 1 | 1 | 11µs | 28µs | DBIx::Class::SQLMaker::BEGIN@4 |
| 1 | 1 | 1 | 10µs | 30µs | DBIx::Class::SQLMaker::BEGIN@67 |
| 1 | 1 | 1 | 9µs | 103µs | DBIx::Class::SQLMaker::BEGIN@46 |
| 1 | 1 | 1 | 9µs | 9.28ms | DBIx::Class::SQLMaker::BEGIN@38 |
| 1 | 1 | 1 | 7µs | 180µs | DBIx::Class::SQLMaker::BEGIN@48 |
| 1 | 1 | 1 | 6µs | 6µs | DBIx::Class::SQLMaker::BEGIN@47 |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::SQLMaker::__ANON__[:72] |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::SQLMaker::__ANON__[:77] |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::SQLMaker::_lock_select |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::SQLMaker::_where_op_NEST |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::SQLMaker::_where_op_VALUE |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::SQLMaker::throw_exception |
| 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 | 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 | 3 | 34µ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 | 3 | 37µ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 | 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 | 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 | 25 | 138µ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 | 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 | push @{$self->{special_ops}}, @extra_dbic_syntax; | ||||
| 114 | push @{$self->{unary_ops}}, @extra_dbic_syntax; | ||||
| 115 | |||||
| 116 | $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 | 1029 | 2.19ms | my $self = shift; | ||
| 121 | my ($op, $rhs) = splice @_, -2; | ||||
| 122 | 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 | my $lhs = shift; | ||||
| 128 | |||||
| 129 | 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 | 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 | 73766 | 133ms | my ($self, $table, $fields, $where, $rs_attrs, $limit, $offset) = @_; | ||
| 172 | |||||
| 173 | |||||
| 174 | 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 | 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 | $offset ||= 0; | ||||
| 181 | |||||
| 182 | 5 | 35µs | if (defined $limit) { | ||
| 183 | 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 | my ($sql, @bind); | ||||
| 192 | 6716 | 32.6ms | if ($limit) { | ||
| 193 | # this is legacy code-flow from SQLA::Limit, it is not set in stone | ||||
| 194 | |||||
| 195 | 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 | 10 | 69µs | 5 | 20µs | do { # spent 20µs making 5 calls to UNIVERSAL::can, avg 4µs/call |
| 201 | 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 | 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 | 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 | 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 | push @{$self->{where_bind}}, @bind; | ||||
| 220 | |||||
| 221 | # this *must* be called, otherwise extra binds will remain in the sql-maker | ||||
| 222 | 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 | $sql .= $self->_lock_select ($rs_attrs->{for}) | ||||
| 225 | if $rs_attrs->{for}; | ||||
| 226 | |||||
| 227 | 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 | 13412 | 68.3ms | my $self = shift; | ||
| 232 | 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 | 898 | 5.47ms | 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 | 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 | 153197 | 188ms | my ($self, $fields) = @_; | ||
| 273 | my $ref = ref $fields; | ||||
| 274 | 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 | return $$fields if $ref eq 'SCALAR'; | ||||
| 276 | |||||
| 277 | 20497 | 87.7ms | if ($ref eq 'ARRAY') { | ||
| 278 | 36394 | 75.6ms | 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 | my %hash = %$fields; # shallow copy | ||||
| 282 | |||||
| 283 | my $as = delete $hash{-as}; # if supplied | ||||
| 284 | |||||
| 285 | my ($func, $args, @toomany) = %hash; | ||||
| 286 | |||||
| 287 | # there should be only one pair | ||||
| 288 | if (@toomany) { | ||||
| 289 | $self->throw_exception( "Malformed select argument - too many keys in hash: " . join (',', keys %$fields ) ); | ||||
| 290 | } | ||||
| 291 | |||||
| 292 | 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 | 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 | 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 | 41118 | 51.7ms | my ($self, $arg) = @_; | ||
| 331 | |||||
| 332 | my $sql = ''; | ||||
| 333 | |||||
| 334 | 2 | 4µs | if ($arg->{group_by}) { | ||
| 335 | # horible horrible, waiting for refactor | ||||
| 336 | local $self->{select_bind}; | ||||
| 337 | 2 | 5µ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 | $sql .= $self->_sqlcase(' group by ') . $g; # spent 3µs making 1 call to SQL::Abstract::_sqlcase | ||
| 339 | push @{$self->{group_bind} ||= []}, @{$self->{select_bind}||[]}; | ||||
| 340 | } | ||||
| 341 | } | ||||
| 342 | |||||
| 343 | 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 | 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 | 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 | 14660 | 94.1ms | my ($self, $arg) = @_; | ||
| 358 | |||||
| 359 | # check that we are not called in legacy mode (order_by as 4th argument) | ||||
| 360 | 81362 | 195ms | 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 | 3.44ms | my ($sql, @bind) = $self->next::method($arg); # spent 3.44ms making 629 calls to next::method, avg 5µs/call | ||
| 365 | push @{$self->{order_bind}}, @bind; | ||||
| 366 | 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 | 16038 | 68.9ms | if (my $ref = ref $_[1] ) { | ||
| 374 | 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 | 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 | 441 | 1.18ms | my ($self, $join_type) = @_; | ||
| 391 | |||||
| 392 | $join_type = $self->{_default_jointype} | ||||
| 393 | if ! defined $join_type; | ||||
| 394 | |||||
| 395 | 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 | 13412 | 45.9ms | my $self = shift; | ||
| 402 | |||||
| 403 | 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 | 26824 | 69.3ms | my ($self, $from, @joins) = @_; | ||
| 408 | |||||
| 409 | 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 | for (@joins) { | ||||
| 412 | 1470 | 2.27ms | my ($to, $on) = @$_; | ||
| 413 | |||||
| 414 | # check whether a join type exists | ||||
| 415 | my $to_jt = ref($to) eq 'ARRAY' ? $to->[0] : $to; | ||||
| 416 | my $join_type; | ||||
| 417 | 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 | 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 | 255µs | if (ref $to eq 'ARRAY') { | ||
| 425 | push(@j, '(', $self->_recurse_from(@$to), ')'); | ||||
| 426 | } | ||||
| 427 | else { | ||||
| 428 | 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 | 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 | push(@j, ' ON ', $sql); | ||||
| 433 | push @{$self->{from_bind}}, @bind; | ||||
| 434 | |||||
| 435 | push @fchunks, join '', @j; | ||||
| 436 | } | ||||
| 437 | |||||
| 438 | 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 | 27412 | 62.9ms | my ($self, $fromspec) = @_; | ||
| 443 | |||||
| 444 | 13706 | 33.9ms | return join (' ', do { | ||
| 445 | 20559 | 67.0ms | 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 | 23.3ms | { $_ => $fromspec->{$_} } # spent 23.3ms making 21000 calls to DBIx::Class::SQLMaker::CORE:match, avg 1µs/call | ||
| 458 | 21000 | 76.5ms | ( grep { $_ !~ /^\-/ } keys %$fromspec ) | ||
| 459 | ); | ||||
| 460 | |||||
| 461 | $self->throw_exception( "Only one table/as pair expected in from-spec but an exra '$toomuch' key present" ) | ||||
| 462 | if defined $toomuch; | ||||
| 463 | |||||
| 464 | 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 | 441 | 1.60ms | 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 | 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 | 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 |