← Index
NYTProf Performance Profile   « line view »
For svc/members/upsert
  Run on Tue Jan 13 11:50:22 2015
Reported on Tue Jan 13 12:09:46 2015

Filename/mnt/catalyst/koha/svc/members/upsert
StatementsExecuted 74 statements in 15.3ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
11110.2ms642msmain::::BEGIN@73 main::BEGIN@73
1115.97ms223msmain::::BEGIN@72 main::BEGIN@72
1113.10ms346msmain::::BEGIN@75 main::BEGIN@75
3322.72ms2.72msDBI::db::::do DBI::db::do (xsub)
1112.50ms40.4msmain::::BEGIN@70 main::BEGIN@70
7741.84ms1.84msDBI::st::::execute DBI::st::execute (xsub)
43584431µs431µsUNIVERSAL::::isa UNIVERSAL::isa (xsub)
611426µs713µsDBI::db::::selectrow_array DBI::db::selectrow_array (xsub)
111171µs2.47msmain::::get_borrower_fields main::get_borrower_fields
111150µs31.0msmain::::process_upsert main::process_upsert
22731147µs147µsInternals::::SvREADONLY Internals::SvREADONLY (xsub)
942210127µs127µsUNIVERSAL::::can UNIVERSAL::can (xsub)
6922120µs1.13msDBI::st::::fetchrow_hashref DBI::st::fetchrow_hashref (xsub)
7564113µs113µsDBI::common::::FETCH DBI::common::FETCH (xsub)
1010987µs87µsUNIVERSAL::::VERSION UNIVERSAL::VERSION (xsub)
722278µs78µsDBI::st::::fetch DBI::st::fetch (xsub)
138577µs670µsDBI::db::::prepare DBI::db::prepare (xsub)
212160µs60µsDBI::st::::fetchrow DBI::st::fetchrow (xsub)
247358µs58µsDBI::common::::DESTROY DBI::common::DESTROY (xsub)
691145µs45µsDBI::st::::mysql_async_ready DBI::st::mysql_async_ready (xsub)
172144µs44µsDBI::common::::func DBI::common::func (xsub)
118238µs38µsDBI::common::::STORE DBI::common::STORE (xsub)
11133µs112µsmain::::find_borrower main::find_borrower
11125µs25µsDBI::db::::ping DBI::db::ping (xsub)
11122µs23µsFcntl::::O_NOINHERIT Fcntl::O_NOINHERIT
11119µs133µsDBI::db::::prepare_cached DBI::db::prepare_cached (xsub)
127316µs16µsDBD::_mem::common::::DESTROYDBD::_mem::common::DESTROY (xsub)
44214µs14µsmain::::CORE:pack main::CORE:pack (opcode)
11113µs198µsDBI::st::::fetchall_arrayref DBI::st::fetchall_arrayref (xsub)
11112µs12µsDBI::dr::::disconnect_all DBI::dr::disconnect_all (xsub)
11112µs1.44msDBI::dr::::connect DBI::dr::connect (xsub)
31111µs52µsDBI::st::::bind_col DBI::st::bind_col (xsub)
11110µs36µsmain::::BEGIN@77 main::BEGIN@77
11110µs10µsmain::::create_borrower main::create_borrower
1119µs10µsFcntl::::O_EXLOCK Fcntl::O_EXLOCK
1118µs9µsFcntl::::O_TEMPORARY Fcntl::O_TEMPORARY
1118µs366µsmain::::get_extended_attribs main::get_extended_attribs
1118µs8µsmain::::BEGIN@74 main::BEGIN@74
1118µs8µsDBI::st::::fetchrow_array DBI::st::fetchrow_array (xsub)
2226µs6µsDBI::st::::finish DBI::st::finish (xsub)
1115µs5µsDBI::db::::connected DBI::db::connected (xsub)
1114µs124µsDBI::st::::bind_columns DBI::st::bind_columns (xsub)
1114µs4µsmain::::CORE:match main::CORE:match (opcode)
1113µs3µsDBI::st::::fetchrow_arrayref DBI::st::fetchrow_arrayref (xsub)
0000s0smain::::RUNTIME main::RUNTIME
0000s0smain::::find_borrower_from_ext main::find_borrower_from_ext
0000s0smain::::update_borrower main::update_borrower
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1#!/usr/bin/perl
2
3# Copyright 2015 Catalyst IT
4#
5# This file is part of Koha.
6#
7# Koha is free software; you can redistribute it and/or modify it under the
8# terms of the GNU General Public License as published by the Free Software
9# Foundation; either version 3 of the License, or (at your option) any later
10# version.
11#
12# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with Koha; if not, write to the Free Software Foundation, Inc.,
18# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20=head1 NAME
21
22svc/members/upsert - web service for inserting and updating user details
23
24=head1 SYNOPSIS
25
26 POST /svc/members/upsert
27
28The request paramters go in the POST body.
29
30=head1 DESCRIPTION
31
32This allows user data to be added and updated on a Koha system from another
33service. User data is supplied, and if it matches an existing user, that user
34is updated. If not, then a new user is created. A field to match on must be
35provided. For example, this might be an ID of the user in an employee
36management system. It may be an extended attribute.
37
38=head1 PARAMETERS
39
40The request can contain any field from the borrowers table, and any extended
41attribute name. It must also contain 'matchField' which specifies the field
42to use to see if the user already exists.
43
44To clear a field, provide an empty parameter for it. If the parameter doesn't
45exist, then the field will be left alone.
46
47Dates must be in YYYY-MM-DD form.
48
49Boolean values must be 1 (for true) or 0 (for false.)
50
51A borrowernumber field may be provided and used for matching. It will be
52ignored when it comes to creating or updating however.
53
54If the matchField parameters returns more than one value, an error will be
55raised. Care should be taken to ensure that it is unique.
56
57=head2 Results
58
59On success, this will return a result in XML form containing the
60borrowernumber of the record (whether it's newly created or just updated) and
61a 'createOrUpdate' element that contains either 'create' or 'update',
62depending on what operation ended up happening.
63
64On error, an error response is returned. This may be because a matchField
65was provided that didn't match anything, or because the matchField
66produced multiple results. Or probably many other things.
67
68=cut
69
7021.87ms240.5ms
# spent 40.4ms (2.50+37.9) within main::BEGIN@70 which was called: # once (2.50ms+37.9ms) by main::NULL at line 70
use Modern::Perl;
# spent 40.4ms making 1 call to main::BEGIN@70 # spent 120µs making 1 call to Modern::Perl::import
71
7223.52ms2272ms
# spent 223ms (5.97+217) within main::BEGIN@72 which was called: # once (5.97ms+217ms) by main::NULL at line 72
use C4::Context;
# spent 223ms making 1 call to main::BEGIN@72 # spent 49.5ms making 1 call to C4::Context::import
7322.71ms2643ms
# spent 642ms (10.2+632) within main::BEGIN@73 which was called: # once (10.2ms+632ms) by main::NULL at line 73
use C4::Members;
# spent 642ms making 1 call to main::BEGIN@73 # spent 326µs making 1 call to Exporter::import
74222µs18µs
# spent 8µs within main::BEGIN@74 which was called: # once (8µs+0s) by main::NULL at line 74
use C4::Members::AttributeTypes;
# spent 8µs making 1 call to main::BEGIN@74
7522.68ms1346ms
# spent 346ms (3.10+343) within main::BEGIN@75 which was called: # once (3.10ms+343ms) by main::NULL at line 75
use C4::Service;
# spent 346ms making 1 call to main::BEGIN@75
76
7722.81ms261µs
# spent 36µs (10+25) within main::BEGIN@77 which was called: # once (10µs+25µs) by main::NULL at line 77
use Data::Dumper; # TODO remove
# spent 36µs making 1 call to main::BEGIN@77 # spent 25µs making 1 call to Exporter::import
78
7912µs131.0msprocess_upsert();
# spent 31.0ms making 1 call to main::process_upsert
80
81
# spent 31.0ms (150µs+30.8) within main::process_upsert which was called: # once (150µs+30.8ms) by main::RUNTIME at line 79
sub process_upsert {
8216µs124.5ms my $service = C4::Service->new( { needed_flags => { borrowers => 1 } } );
# spent 24.5ms making 1 call to C4::Service::new
83
8412µs14µs my $query = $service->query();
# spent 4µs making 1 call to C4::Service::query
8513µs121µs my @supplied_fields = $query->param();
# spent 21µs making 1 call to CGI::param
8616µs42.47ms my @borrower_fields = get_borrower_fields();
# spent 2.47ms making 1 call to main::get_borrower_fields # spent 2µs making 2 calls to DBI::common::DESTROY, avg 1µs/call # spent 900ns making 1 call to DBD::_mem::common::DESTROY
8713µs1366µs my @attrib_types = get_extended_attribs();
# spent 366µs making 1 call to main::get_extended_attribs
8812µs114µs my $match_field = $query->param('matchField');
# spent 14µs making 1 call to CGI::param
89
90 # Make a mapping of these so we can do fast lookups
91143µs my %borrower_fields = map { $_ => 1 } @borrower_fields;
9212µs my %attrib_types = map { $_ => 1 } @attrib_types;
93
941300ns $service->return_error( 'parameters', 'No matchField provided' )
95 unless $match_field;
961500ns my $is_borrower_field; # for matchField, as opposed to an ext attribute
971600ns $is_borrower_field = $borrower_fields{$match_field} // 0;
981300ns if ( !$is_borrower_field ) {
99 $service->return_error( 'parameters',
100 'Provided matchField doesn\'t match a valid field' )
101 unless $attrib_types{$match_field};
102 }
10312µs17µs my $match_value = $query->param($match_field);
# spent 7µs making 1 call to CGI::param
1041200ns $service->return_error( 'parameters',
105 'The field specified by matchField wasn\'t provided.' )
106 unless $match_value;
107
108 # verify we are only given valid fields, at the same time make a mapping
109 # of them.
1101300ns my ( %supplied_data_borr, %supplied_data_ext );
11111µs foreach my $f (@supplied_fields) {
11251µs next if $f eq 'matchField';
11341µs $service->return_error( 'parameters', "Invalid parameter provided: $f" )
114 unless $borrower_fields{$f} || $attrib_types{$f};
11546µs314µs if ( $borrower_fields{$f} ) {
# spent 14µs making 3 calls to CGI::param, avg 5µs/call
116 $supplied_data_borr{$f} = $query->param($f);
117 }
118 else {
11911µs15µs $supplied_data_ext{$f} = $query->param($f);
# spent 5µs making 1 call to CGI::param
120 }
121 }
122
123 # Sanity checks and data extraction over, find our borrower.
1241200ns my $borr_num;
1251600ns eval {
12612µs4114µs if ($is_borrower_field) {
# spent 112µs making 1 call to main::find_borrower # spent 2µs making 2 calls to DBI::common::DESTROY, avg 1µs/call # spent 700ns making 1 call to DBD::_mem::common::DESTROY
127 $borr_num = find_borrower( $match_field, $match_value );
128 }
129 else {
130 $borr_num = find_borrower_from_ext( $match_field, $match_value );
131 }
132 };
1331200ns if ($@) {
134 $service->return_error( 'borrower', $@ );
135 }
136
137 # Now we know if we're creating a new user, or updating an existing one.
1381100ns my $change_type;
1391400ns eval {
1401600ns if ($borr_num) {
141 update_borrower( $borr_num, \%supplied_data_borr,
142 \%supplied_data_ext );
143 $change_type = 'update';
144 }
145 else {
14612µs110µs $borr_num =
# spent 10µs making 1 call to main::create_borrower
147 create_borrower( \%supplied_data_borr, \%supplied_data_ext );
148 $change_type = 'create';
149 }
150 };
1511300ns if ($@) {
15212µs13.28ms $service->return_error( 'data', $@ );
# spent 3.28ms making 1 call to C4::Service::return_error
153 }
154
155 $service->output_stream->param( 'borrowernumber', $borr_num );
156 $service->output_stream->param( 'createOrUpdate', $change_type );
157 $service->return_success();
158}
159
160=head2 get_borrower_fields
161
162Fetches the list of columns from the borrower table. Returns a list.
163
164=cut
165
166
# spent 2.47ms (171µs+2.29) within main::get_borrower_fields which was called: # once (171µs+2.29ms) by main::process_upsert at line 86
sub get_borrower_fields {
16712µs14µs my $dbh = C4::Context->dbh();
# spent 4µs making 1 call to C4::Context::dbh
168
1691200ns my @fields;
1701400ns my $q = 'SHOW COLUMNS FROM borrowers';
17115µs263µs my $sth = $dbh->prepare($q);
# spent 34µs making 1 call to DBI::db::prepare # spent 30µs making 1 call to DBD::mysql::db::prepare
17211.22ms11.21ms $sth->execute();
# spent 1.21ms making 1 call to DBI::st::execute
1731212µs1361.97ms while ( my $row = $sth->fetchrow_hashref() ) {
# spent 1.04ms making 68 calls to DBI::st::fetchrow_hashref, avg 15µs/call # spent 930µs making 68 calls to DBD::mysql::st::__ANON__[DBD/mysql.pm:799], avg 14µs/call
174 push @fields, $row->{Field};
175 }
176122µs return @fields;
177}
178
179=head2 get_extended_attribs
180
181Fetch all the extended attributes from the system. Returns a list.
182
183=cut
184
185
# spent 366µs (8+358) within main::get_extended_attribs which was called: # once (8µs+358µs) by main::process_upsert at line 87
sub get_extended_attribs {
18619µs4361µs return map { $_->{code} } C4::Members::AttributeTypes::GetAttributeTypes();
# spent 358µs making 1 call to C4::Members::AttributeTypes::GetAttributeTypes # spent 2µs making 2 calls to DBI::common::DESTROY, avg 1µs/call # spent 1µs making 1 call to DBD::_mem::common::DESTROY
187}
188
189=head2 find_borrower
190
191 $borr_num = find_borrower($field, $value);
192
193Given a field and value, this will look up a borrower by that name. If none
194is found, C<undef> is returned. If more than one is found, an exception is
195raised.
196
197It performs some basic validation to ensure the field is safe for searching.
198
199=cut
200
201
# spent 112µs (33+78) within main::find_borrower which was called: # once (33µs+78µs) by main::process_upsert at line 126
sub find_borrower {
2021500ns my ( $field, $value ) = @_;
203
204 # We could use C4::Members::GetMember here, however it doesn't quite
205 # allow us to do what we need.
206 # TODO for upstreaming: move this into Koha::Borrowers
207
20818µs14µs die "Field value may not be safe for SQL" if $field =~ /[^A-Za-z0-9]/;
# spent 4µs making 1 call to main::CORE:match
20912µs14µs my $dbh = C4::Context->dbh();
# spent 4µs making 1 call to C4::Context::dbh
21011µs my $q = "SELECT borrowernumber FROM borrowers WHERE $field=?";
21115µs254µs my $sth = $dbh->prepare($q);
# spent 29µs making 1 call to DBI::db::prepare # spent 25µs making 1 call to DBD::mysql::db::prepare
212140µs135µs $sth->execute($value);
# spent 35µs making 1 call to DBI::st::execute
21319µs13µs my $row = $sth->fetchrow_arrayref();
# spent 3µs making 1 call to DBI::st::fetchrow_arrayref
214115µs return undef unless $row;
215 my $bib = $row->[0];
216 die "Multiple borrowers match provided values\n"
217 if $sth->fetchrow_arrayref();
218 return $bib;
219}
220
221=head2 find_borrower_from_ext
222
223 $borr_num = find_borrower_from_ext($field, $value);
224
225Given an extended attribute code and a value, this finds the borrower with the
226matching attribute. If none is found, C<undef> is returned. If more than one
227is found, an exception is raised.
228
229=cut
230
231sub find_borrower_from_ext {
232 my ( $code, $value ) = @_;
233
234 # TODO for upstreaming: move this somewhere under Koha::Borrowers
235
236 my $dbh = C4::Context->dbh();
237 my $q =
238'SELECT DISTINCT borrowernumber FROM borrower_attributes WHERE code=? AND attribute=?';
239 my $sth = $dbh->prepare($q);
240 $sth->execute( $code, $value );
241 my $row = $sth->fetchrow_arrayref();
242 return undef unless $row;
243 my $bib = $row->[0];
244 die "Multiple borrowers match provided values\n"
245 if $sth->fetchrow_arrayref();
246 return $bib;
247}
248
249=head2 update_borrower
250
251 update_borrower($borr_num, \%borrower_fields, \%ext_attrib_fields);
252
253This takes a borrower number, a hashref containing the fields and values for
254the borrower, and a hashref containing the fields and values for the extended
255attributes. It will update the borrower to set its fields to the values
256supplied.
257
258A supplied borrowernumber will be ignored.
259
260=cut
261
262sub update_borrower {
263 my ( $borr_num, $borr_fields, $ext_fields ) = @_;
264
265 # For the first phase, we build an update query for the borrower
266 my ( @f_borr, @v_borr );
267 while ( my ( $f, $v ) = each %$borr_fields ) {
268 next if $f =~ /^borrowernumber$/i;
269 die "Invalid fieldname provided (update): $f\n" if $f =~ /[^A-Za-z0-9]/;
270 push @f_borr, $f;
271 push @v_borr, $v;
272 }
273 my $q_borr =
274 'UPDATE borrowers SET '
275 . ( join ',', map { $_ . '=?' } @f_borr )
276 . ' WHERE borrowernumber=?';
277
278 # Now queries to sort out the extended fields
279 my @f_ext = keys %$ext_fields;
280 my @v_ext = values %$ext_fields;
281 my $q_ext_del =
282 'DELETE FROM borrower_attributes WHERE borrowernumber=? AND code IN ('
283 . ( join ',', map { '?' } @f_ext ) . ')';
284 my $q_ext_add =
285'INSERT INTO borrower_attributes (borrowernumber, code, attribute) VALUES (?, ?, ?)';
286
287 my $dbh = C4::Context->dbh();
288
289 # Finally, run these all inside a transaction.
290 eval {
291 $dbh->begin_work;
292
293 my $sth;
294
295 if (@f_borr) {
296 $sth = $dbh->prepare($q_borr);
297 $sth->execute( @v_borr, $borr_num );
298 }
299
300 $sth = $dbh->prepare($q_ext_del);
301 $sth->execute( $borr_num, @f_ext );
302
303 $sth = $dbh->prepare($q_ext_add);
304 while ( my ( $f, $v ) = each %$ext_fields ) {
305 next if $v eq '';
306 $sth->execute( $borr_num, $f, $v );
307 }
308
309 $dbh->commit;
310 };
311 if ($@) {
312 $dbh->rollback;
313 die "Failed to update borrower record: $@\n";
314 }
315 return $borr_num;
316}
317
318=head2 create_borrower
319
320 my $borr_num = create_borrower(\%borrower_fields, \%ext_attrib_fields);
321
322This creates a new borrower using the supplied data.
323
324A supplied borrowernumber will be ignored.
325
326The borrowernumber of the new borrower will be returned.
327
328=cut
329
330
# spent 10µs within main::create_borrower which was called: # once (10µs+0s) by main::process_upsert at line 146
sub create_borrower {
3311600ns my ( $borr_fields, $ext_fields ) = @_;
332
33311µs my @criticals = qw(surname branchcode categorycode);
334
335 # Check we have the ones we need
3361500ns foreach my $c (@criticals) {
337211µs die "Critical field missing (create): $c\n" unless $borr_fields->{$c};
338 }
339
340 # Borrower fields
341 my ( @f_borr, @v_borr );
342 while ( my ( $f, $v ) = each %$borr_fields ) {
343 die "Invalid fieldname provided: $f\n" if $f =~ /[^A-Za-z0-9]/;
344 push @f_borr, $f;
345 push @v_borr, $v;
346 }
347 my $q_borr =
348 'INSERT INTO borrowers ('
349 . ( join ',', @f_borr )
350 . ') VALUES ('
351 . join ',', map { '?' } @f_borr . ')';
352
353 # Extended attributes
354 my @f_ext = keys %$ext_fields;
355 my @v_ext = values %$ext_fields;
356 my $q_ext_add =
357'INSERT INTO borrower_attributes (borrowernumber, code, attribute) VALUES (?, ?, ?)';
358
359 my $dbh = C4::Context->dbh();
360
361 # Finally, run these all inside a transaction.
362 my $borr_num;
363 eval {
364 $dbh->begin_work;
365
366 my $sth = $dbh->prepare($q_borr);
367 $sth->execute(@v_borr);
368 my $borr_num = $dbh->last_insert_id( undef, undef, undef, undef );
369
370 $sth = $dbh->prepare($q_ext_add);
371 while ( my ( $f, $v ) = each %$ext_fields ) {
372 $sth->execute( $borr_num, $f, $v );
373 }
374
375 $dbh->commit;
376 };
377 if ($@) {
378 $dbh->rollback;
379 die "Failed to create borrower record: $@\n";
380 }
381 return $borr_num;
382}
 
# spent 16µs within DBD::_mem::common::DESTROY which was called 12 times, avg 1µs/call: # 6 times (9µs+0s) by C4::Context::preference at line 566 of C4/Context.pm, avg 2µs/call # once (2µs+0s) by C4::Auth::get_user_subpermissions at line 1652 of C4/Auth.pm # once (2µs+0s) by C4::Auth::getuserflags at line 1747 of C4/Auth.pm # once (1µs+0s) by C4::Auth::haspermission at line 1232 of C4/Auth.pm # once (1µs+0s) by C4::Members::AttributeTypes::GetAttributeTypes at line 186 # once (900ns+0s) by main::get_borrower_fields at line 86 # once (700ns+0s) by main::find_borrower at line 126
sub DBD::_mem::common::DESTROY; # xsub
# spent 58µs within DBI::common::DESTROY which was called 24 times, avg 2µs/call: # 12 times (23µs+0s) by C4::Context::preference at line 566 of C4/Context.pm, avg 2µs/call # 2 times (18µs+0s) by C4::Auth::haspermission at line 1232 of C4/Auth.pm, avg 9µs/call # 2 times (6µs+0s) by C4::Auth::get_user_subpermissions at line 1652 of C4/Auth.pm, avg 3µs/call # 2 times (4µs+0s) by C4::Auth::getuserflags at line 1747 of C4/Auth.pm, avg 2µs/call # 2 times (2µs+0s) by main::get_borrower_fields at line 86, avg 1µs/call # 2 times (2µs+0s) by C4::Members::AttributeTypes::GetAttributeTypes at line 186, avg 1µs/call # 2 times (2µs+0s) by main::find_borrower at line 126, avg 1µs/call
sub DBI::common::DESTROY; # xsub
# spent 113µs within DBI::common::FETCH which was called 75 times, avg 2µs/call: # 69 times (76µs+0s) by DBD::_::st::fetchrow_hashref at line 798 of DBD/mysql.pm, avg 1µs/call # 2 times (7µs+0s) by DBD::_::st::fetchall_arrayref at line 2064 of DBI.pm, avg 4µs/call # once (17µs+0s) by DBD::_::st::bind_columns at line 1888 of DBI.pm # once (7µs+0s) by C4::Context::_new_dbh at line 819 of C4/Context.pm # once (3µs+0s) by CGI::Session::Driver::DBI::DESTROY at line 141 of CGI/Session/Driver/DBI.pm # once (2µs+0s) by C4::Context::_new_dbh at line 820 of C4/Context.pm
sub DBI::common::FETCH; # xsub
# spent 38µs within DBI::common::STORE which was called 11 times, avg 3µs/call: # 3 times (14µs+0s) by DBI::__ANON__[/usr/lib/x86_64-linux-gnu/perl5/5.20/DBI.pm:738] at line 723 of DBI.pm, avg 5µs/call # 2 times (6µs+0s) by C4::Context::_new_dbh at line 818 of C4/Context.pm, avg 3µs/call # once (7µs+0s) by DBI::connect at line 742 of DBI.pm # once (4µs+0s) by DBI::__ANON__[/usr/lib/x86_64-linux-gnu/perl5/5.20/DBI.pm:738] at line 726 of DBI.pm # once (2µs+0s) by C4::Context::_new_dbh at line 819 of C4/Context.pm # once (2µs+0s) by C4::Context::_new_dbh at line 820 of C4/Context.pm # once (2µs+0s) by C4::Context::_new_dbh at line 828 of C4/Context.pm # once (1µs+0s) by C4::Context::_new_dbh at line 836 of C4/Context.pm
sub DBI::common::STORE; # xsub
# spent 44µs within DBI::common::func which was called 17 times, avg 3µs/call: # 13 times (38µs+0s) by DBD::mysql::db::prepare at line 232 of DBD/mysql.pm, avg 3µs/call # 4 times (6µs+0s) by DBD::mysql::st::__ANON__[/usr/lib/x86_64-linux-gnu/perl5/5.20/DBD/mysql.pm:810] at line 808 of DBD/mysql.pm, avg 2µs/call
sub DBI::common::func; # xsub
# spent 5µs within DBI::db::connected which was called: # once (5µs+0s) by DBI::__ANON__[/usr/lib/x86_64-linux-gnu/perl5/5.20/DBI.pm:738] at line 733 of DBI.pm
sub DBI::db::connected; # xsub
# spent 2.72ms within DBI::db::do which was called 3 times, avg 908µs/call: # once (2.56ms+0s) by CGI::Session::Driver::mysql::store at line 50 of CGI/Session/Driver/mysql.pm # once (93µs+0s) by C4::Context::_new_dbh at line 821 of C4/Context.pm # once (70µs+0s) by C4::Context::_new_dbh at line 837 of C4/Context.pm
sub DBI::db::do; # xsub
# spent 25µs within DBI::db::ping which was called: # once (25µs+0s) by CGI::Session::Driver::DBI::DESTROY at line 136 of CGI/Session/Driver/DBI.pm
sub DBI::db::ping; # xsub
# spent 670µs (77+593) within DBI::db::prepare which was called 13 times, avg 52µs/call: # 6 times (26µs+261µs) by DBI::db::selectrow_array at line 563 of C4/Context.pm, avg 48µs/call # once (9µs+67µs) by DBD::_::db::prepare_cached at line 1717 of DBI.pm # once (10µs+57µs) by C4::Auth::haspermission at line 1744 of C4/Auth.pm # once (9µs+56µs) by C4::Auth::getuserflags at line 1640 of C4/Auth.pm # once (9µs+56µs) by C4::Auth::get_user_subpermissions at line 1690 of C4/Auth.pm # once (6µs+41µs) by C4::Members::AttributeTypes::GetAttributeTypes at line 86 of C4/Members/AttributeTypes.pm # once (4µs+30µs) by main::get_borrower_fields at line 171 # once (4µs+25µs) by main::find_borrower at line 211
sub DBI::db::prepare; # xsub
# spent 133µs (19+114) within DBI::db::prepare_cached which was called: # once (19µs+114µs) by CGI::Session::Driver::DBI::retrieve at line 68 of CGI/Session/Driver/DBI.pm
sub DBI::db::prepare_cached; # xsub
# spent 713µs (426+286) within DBI::db::selectrow_array which was called 6 times, avg 119µs/call: # 6 times (426µs+286µs) by C4::Context::preference at line 563 of C4/Context.pm, avg 119µs/call
sub DBI::db::selectrow_array; # xsub
# spent 1.44ms (12µs+1.43) within DBI::dr::connect which was called: # once (12µs+1.43ms) by DBI::__ANON__[/usr/lib/x86_64-linux-gnu/perl5/5.20/DBI.pm:738] at line 671 of DBI.pm
sub DBI::dr::connect; # xsub
# spent 12µs within DBI::dr::disconnect_all which was called: # once (12µs+0s) by DBI::disconnect_all at line 750 of DBI.pm
sub DBI::dr::disconnect_all; # xsub
# spent 52µs (11+40) within DBI::st::bind_col which was called 3 times, avg 17µs/call: # 3 times (11µs+40µs) by DBD::_::st::bind_columns at line 1899 of DBI.pm, avg 17µs/call
sub DBI::st::bind_col; # xsub
# spent 124µs (4+120) within DBI::st::bind_columns which was called: # once (4µs+120µs) by DBD::_::st::fetchall_arrayref at line 2064 of DBI.pm
sub DBI::st::bind_columns; # xsub
# spent 1.84ms within DBI::st::execute which was called 7 times, avg 262µs/call: # once (1.21ms+0s) by main::get_borrower_fields at line 172 # once (347µs+0s) by CGI::Session::Driver::DBI::retrieve at line 72 of CGI/Session/Driver/DBI.pm # once (67µs+0s) by C4::Auth::haspermission at line 1745 of C4/Auth.pm # once (64µs+0s) by C4::Auth::get_user_subpermissions at line 1696 of C4/Auth.pm # once (60µs+0s) by C4::Auth::getuserflags at line 1641 of C4/Auth.pm # once (52µs+0s) by C4::Members::AttributeTypes::GetAttributeTypes at line 87 of C4/Members/AttributeTypes.pm # once (35µs+0s) by main::find_borrower at line 212
sub DBI::st::execute; # xsub
# spent 78µs within DBI::st::fetch which was called 72 times, avg 1µs/call: # 69 times (74µs+0s) by DBD::_::st::fetchrow_hashref at line 798 of DBD/mysql.pm, avg 1µs/call # 3 times (5µs+0s) by DBD::_::st::fetchall_arrayref at line 2071 of DBI.pm, avg 2µs/call
sub DBI::st::fetch; # xsub
# spent 198µs (13+185) within DBI::st::fetchall_arrayref which was called: # once (13µs+185µs) by C4::Members::AttributeTypes::GetAttributeTypes at line 88 of C4/Members/AttributeTypes.pm
sub DBI::st::fetchall_arrayref; # xsub
# spent 60µs within DBI::st::fetchrow which was called 21 times, avg 3µs/call: # 20 times (47µs+0s) by C4::Auth::getuserflags at line 1643 of C4/Auth.pm, avg 2µs/call # once (13µs+0s) by C4::Auth::haspermission at line 1746 of C4/Auth.pm
sub DBI::st::fetchrow; # xsub
# spent 8µs within DBI::st::fetchrow_array which was called: # once (8µs+0s) by CGI::Session::Driver::DBI::retrieve at line 74 of CGI/Session/Driver/DBI.pm
sub DBI::st::fetchrow_array; # xsub
# spent 3µs within DBI::st::fetchrow_arrayref which was called: # once (3µs+0s) by main::find_borrower at line 213
sub DBI::st::fetchrow_arrayref; # xsub
# spent 1.13ms (120µs+1.01) within DBI::st::fetchrow_hashref which was called 69 times, avg 16µs/call: # 68 times (112µs+930µs) by main::get_borrower_fields at line 173, avg 15µs/call # once (9µs+81µs) by C4::Auth::get_user_subpermissions at line 1699 of C4/Auth.pm
sub DBI::st::fetchrow_hashref; # xsub
# spent 6µs within DBI::st::finish which was called 2 times, avg 3µs/call: # once (5µs+0s) by CGI::Session::Driver::DBI::retrieve at line 76 of CGI/Session/Driver/DBI.pm # once (1µs+0s) by C4::Members::AttributeTypes::GetAttributeTypes at line 89 of C4/Members/AttributeTypes.pm
sub DBI::st::finish; # xsub
# spent 45µs within DBI::st::mysql_async_ready which was called 69 times, avg 652ns/call: # 69 times (45µs+0s) by DBD::mysql::st::__ANON__[/usr/lib/x86_64-linux-gnu/perl5/5.20/DBD/mysql.pm:799] at line 795 of DBD/mysql.pm, avg 652ns/call
sub DBI::st::mysql_async_ready; # xsub
# spent 147µs within Internals::SvREADONLY which was called 227 times, avg 648ns/call: # 225 times (145µs+0s) by constant::import at line 149 of constant.pm, avg 646ns/call # once (1µs+0s) by constant::BEGIN@24 at line 32 of constant.pm # once (500ns+0s) by constant::BEGIN@24 at line 33 of constant.pm
sub Internals::SvREADONLY; # xsub
# spent 87µs within UNIVERSAL::VERSION which was called 10 times, avg 9µs/call: # once (12µs+0s) by Module::Implementation::BEGIN@8 at line 8 of Module/Implementation.pm # once (11µs+0s) by Try::Tiny::BEGIN@12 at line 12 of Try/Tiny.pm # once (10µs+0s) by DateTime::TimeZone::BEGIN@15 at line 15 of DateTime/TimeZone.pm # once (9µs+0s) by Data::OptList::BEGIN@11 at line 11 of Data/OptList.pm # once (9µs+0s) by Class::Load::XS::BEGIN@11 at line 11 of Class/Load/XS.pm # once (8µs+0s) by Class::Load::BEGIN@11 at line 11 of Class/Load.pm # once (8µs+0s) by Sub::Name::BEGIN@58 at line 58 of Sub/Name.pm # once (7µs+0s) by Class::Load::BEGIN@12 at line 17 of Class/Load.pm # once (7µs+0s) by Package::Stash::BEGIN@13 at line 13 of Package/Stash.pm # once (6µs+0s) by Module::Runtime::use_module at line 349 of Module/Runtime.pm
sub UNIVERSAL::VERSION; # xsub
# spent 127µs within UNIVERSAL::can which was called 94 times, avg 1µs/call: # 44 times (38µs+0s) by Math::BigInt::import at line 2842 of Math/BigInt.pm, avg 868ns/call # 10 times (18µs+0s) by DateTime::Format::Builder::Parser::create_single_parser at line 181 of DateTime/Format/Builder/Parser.pm, avg 2µs/call # 4 times (5µs+0s) by XML::SAX::Base::comment at line 2354 of XML/SAX/Base.pm, avg 1µs/call # 4 times (5µs+0s) by XML::SAX::Base::start_prefix_mapping at line 1112 of XML/SAX/Base.pm, avg 1µs/call # 4 times (4µs+0s) by XML::SAX::Base::end_prefix_mapping at line 54 of XML/SAX/Base.pm, avg 925ns/call # 3 times (12µs+0s) by Math::BigInt::import at line 2903 of Math/BigInt.pm, avg 4µs/call # 3 times (7µs+0s) by if::work at line 14 of if.pm, avg 2µs/call # 2 times (7µs+0s) by XML::SAX::ParserFactory::parser at line 36 of XML/SAX/ParserFactory.pm, avg 3µs/call # 2 times (2µs+0s) by XML::SAX::Base::start_document at line 1250 of XML/SAX/Base.pm, avg 1µs/call # 2 times (2µs+0s) by XML::SAX::Base::parse at line 2608 of XML/SAX/Base.pm, avg 1µs/call # 2 times (2µs+0s) by XML::SAX::Base::start_element at line 284 of XML/SAX/Base.pm, avg 1µs/call # 2 times (2µs+0s) by XML::SAX::Base::characters at line 192 of XML/SAX/Base.pm, avg 1µs/call # 2 times (2µs+0s) by XML::SAX::Base::end_document at line 1434 of XML/SAX/Base.pm, avg 950ns/call # 2 times (2µs+0s) by XML::SAX::Base::end_element at line 2193 of XML/SAX/Base.pm, avg 900ns/call # once (5µs+0s) by attributes::import at line 59 of attributes.pm # once (3µs+0s) by CGI::Session::Serialize::yaml::freeze at line 18 of CGI/Session/Serialize/yaml.pm # once (3µs+0s) by CGI::Session::Serialize::yaml::thaw at line 24 of CGI/Session/Serialize/yaml.pm # once (2µs+0s) by Math::BigInt::import at line 2826 of Math/BigInt.pm # once (2µs+0s) by autouse::vet_import at line 75 of autouse.pm # once (2µs+0s) by DateTime::Locale::_load_class_from_id at line 279 of DateTime/Locale.pm # once (1µs+0s) by Sub::Install::__ANON__[/usr/share/perl5/Sub/Install.pm:118] at line 106 of Sub/Install.pm # once (1µs+0s) by DateTime::Locale::_load_class_from_id at line 292 of DateTime/Locale.pm
sub UNIVERSAL::can; # xsub
# spent 431µs within UNIVERSAL::isa which was called 435 times, avg 990ns/call: # 192 times (141µs+0s) by XML::Simple::collapse at line 1114 of XML/Simple.pm, avg 734ns/call # 168 times (162µs+0s) by XML::Simple::collapse at line 1076 of XML/Simple.pm, avg 963ns/call # 38 times (82µs+0s) by base::import at line 89 of base.pm, avg 2µs/call # 20 times (8µs+0s) by XML::Simple::array_to_hash at line 1281 of XML/Simple.pm, avg 420ns/call # 6 times (15µs+0s) by DBI::setup_driver at line 845 of DBI.pm, avg 2µs/call # 6 times (12µs+0s) by DBI::setup_driver at line 850 of DBI.pm, avg 2µs/call # 4 times (9µs+0s) by XML::Simple::_get_object at line 162 of XML/Simple.pm, avg 2µs/call # once (2µs+0s) by CGI::header at line 17 of (eval 81)[CGI.pm:932]
sub UNIVERSAL::isa; # xsub
# spent 4µs within main::CORE:match which was called: # once (4µs+0s) by main::find_borrower at line 208
sub main::CORE:match; # opcode
# spent 14µs within main::CORE:pack which was called 4 times, avg 4µs/call: # once (11µs+0s) by MARC::Charset::BEGIN@11 at line 4 of Unicode/Normalize.pm # once (2µs+0s) by charnames::BEGIN@6 at line 88 of _charnames.pm # once (1µs+0s) by MARC::Charset::BEGIN@11 at line 48 of Unicode/Normalize.pm # once (600ns+0s) by charnames::BEGIN@6 at line 89 of _charnames.pm
sub main::CORE:pack; # opcode