Filename | /usr/local/libexec/sympa/Sympa/Database.pm |
Statements | Executed 71694 statements in 464ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
2754 | 1 | 1 | 65.7ms | 985ms | do_prepared_query | Sympa::Database::
8262 | 3 | 1 | 21.9ms | 21.9ms | CORE:subst (opcode) | Sympa::Database::
1 | 1 | 1 | 100µs | 7.59ms | connect | Sympa::Database::
3 | 2 | 2 | 78µs | 102µs | get_id | Sympa::Database::
2 | 2 | 1 | 26µs | 170µs | ping | Sympa::Database::
10 | 6 | 2 | 22µs | 22µs | __dbh | Sympa::Database::
33 | 1 | 1 | 17µs | 17µs | CORE:match (opcode) | Sympa::Database::
1 | 1 | 1 | 16µs | 6.80ms | _connect | Sympa::Database::
6 | 3 | 1 | 9µs | 9µs | CORE:sort (opcode) | Sympa::Database::
0 | 0 | 0 | 0s | 0s | BEGIN@30 | Sympa::Database::
0 | 0 | 0 | 0s | 0s | BEGIN@31 | Sympa::Database::
0 | 0 | 0 | 0s | 0s | BEGIN@32 | Sympa::Database::
0 | 0 | 0 | 0s | 0s | BEGIN@33 | Sympa::Database::
0 | 0 | 0 | 0s | 0s | BEGIN@35 | Sympa::Database::
0 | 0 | 0 | 0s | 0s | BEGIN@36 | Sympa::Database::
0 | 0 | 0 | 0s | 0s | DESTROY | Sympa::Database::
0 | 0 | 0 | 0s | 0s | __ANON__ (xsub) | Sympa::Database::
0 | 0 | 0 | 0s | 0s | _new | Sympa::Database::
0 | 0 | 0 | 0s | 0s | disconnect | Sympa::Database::
0 | 0 | 0 | 0s | 0s | do_operation | Sympa::Database::
0 | 0 | 0 | 0s | 0s | do_query | Sympa::Database::
0 | 0 | 0 | 0s | 0s | error | Sympa::Database::
0 | 0 | 0 | 0s | 0s | new | Sympa::Database::
0 | 0 | 0 | 0s | 0s | prepare_query_log_values | Sympa::Database::
0 | 0 | 0 | 0s | 0s | quote | Sympa::Database::
0 | 0 | 0 | 0s | 0s | set_persistent | Sympa::Database::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # -*- indent-tabs-mode: nil; -*- | ||||
2 | # vim:ft=perl:et:sw=4 | ||||
3 | # $Id$ | ||||
4 | |||||
5 | # Sympa - SYsteme de Multi-Postage Automatique | ||||
6 | # | ||||
7 | # Copyright (c) 1997, 1998, 1999 Institut Pasteur & Christophe Wolfhugel | ||||
8 | # Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, | ||||
9 | # 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites | ||||
10 | # Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 GIP RENATER | ||||
11 | # Copyright 2017, 2018, 2019 The Sympa Community. See the AUTHORS.md file at | ||||
12 | # the top-level directory of this distribution and at | ||||
13 | # <https://github.com/sympa-community/sympa.git>. | ||||
14 | # | ||||
15 | # This program is free software; you can redistribute it and/or modify | ||||
16 | # it under the terms of the GNU General Public License as published by | ||||
17 | # the Free Software Foundation; either version 2 of the License, or | ||||
18 | # (at your option) any later version. | ||||
19 | # | ||||
20 | # This program is distributed in the hope that it will be useful, | ||||
21 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
22 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
23 | # GNU General Public License for more details. | ||||
24 | # | ||||
25 | # You should have received a copy of the GNU General Public License | ||||
26 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
27 | |||||
28 | package Sympa::Database; | ||||
29 | |||||
30 | use strict; | ||||
31 | use warnings; | ||||
32 | use DBI; | ||||
33 | use English qw(-no_match_vars); | ||||
34 | |||||
35 | use Sympa; | ||||
36 | use Sympa::Log; | ||||
37 | |||||
38 | my $log = Sympa::Log->instance; | ||||
39 | |||||
40 | # Structure to keep track of active connections/connection status | ||||
41 | # Keys: unique ID of connection (includes type, server, port, dbname and user). | ||||
42 | # Values: database handler. | ||||
43 | our %connection_of; | ||||
44 | our %persistent_connection_of; | ||||
45 | |||||
46 | # Map to driver names from older format of db_type parameter. | ||||
47 | my %driver_aliases = ( | ||||
48 | mysql => 'Sympa::DatabaseDriver::MySQL', | ||||
49 | Pg => 'Sympa::DatabaseDriver::PostgreSQL', | ||||
50 | ); | ||||
51 | |||||
52 | # Sympa::Database is the proxy class of Sympa::DatabaseDriver subclasses. | ||||
53 | # The constructor may be overridden by _new() method. | ||||
54 | sub new { | ||||
55 | $log->syslog('debug2', '(%s, %s)', @_); | ||||
56 | my $class = shift; | ||||
57 | my $db_type = shift; | ||||
58 | my %params = @_; | ||||
59 | |||||
60 | my $driver = $driver_aliases{$db_type} || $db_type; | ||||
61 | $driver = 'Sympa::DatabaseDriver::' . $driver | ||||
62 | unless $driver =~ /::/; | ||||
63 | unless (eval "require $driver" # spent 0s executing statements in string eval | ||||
64 | and $driver->isa('Sympa::DatabaseDriver')) { | ||||
65 | $log->syslog('err', 'Unable to use %s module: %s', | ||||
66 | $driver, $EVAL_ERROR || 'Not a Sympa::DatabaseDriver class'); | ||||
67 | return undef; | ||||
68 | } | ||||
69 | |||||
70 | return $driver->_new( | ||||
71 | $db_type, | ||||
72 | map { | ||||
73 | (exists $params{$_} and defined $params{$_}) | ||||
74 | ? ($_ => $params{$_}) | ||||
75 | : () | ||||
76 | } ( @{$driver->required_parameters}, @{$driver->optional_parameters} | ||||
77 | ) | ||||
78 | ); | ||||
79 | } | ||||
80 | |||||
81 | sub _new { | ||||
82 | my $class = shift; | ||||
83 | my $db_type = shift; | ||||
84 | my %params = @_; | ||||
85 | |||||
86 | return bless {%params} => $class; | ||||
87 | } | ||||
88 | |||||
89 | ############################################################ | ||||
90 | # connect | ||||
91 | ############################################################ | ||||
92 | # Connect to an SQL database. | ||||
93 | # | ||||
94 | # IN : $options : ref to a hash. Options for the connection process. | ||||
95 | # currently accepts 'keep_trying' : wait and retry until | ||||
96 | # db connection is ok (boolean) ; 'warn' : warn | ||||
97 | # listmaster if connection fails (boolean) | ||||
98 | # OUT : 1 | undef | ||||
99 | # | ||||
100 | ############################################################## | ||||
101 | # spent 7.59ms (100µs+7.49) within Sympa::Database::connect which was called:
# once (100µs+7.49ms) by Sympa::DatabaseDriver::PostgreSQL::connect at line 60 of /usr/local/libexec/sympa/Sympa/DatabaseDriver/PostgreSQL.pm | ||||
102 | 1 | 2µs | 1 | 249µs | $log->syslog('debug3', '(%s)', @_); # spent 249µs making 1 call to Sympa::Log::syslog |
103 | 1 | 800ns | my $self = shift; | ||
104 | |||||
105 | # First check if we have an active connection with this server | ||||
106 | 1 | 5µs | 1 | 52µs | if ($self->ping) { # spent 52µs making 1 call to Sympa::Database::ping |
107 | $log->syslog('debug3', 'Connection to database %s already available', | ||||
108 | $self); | ||||
109 | return 1; | ||||
110 | } | ||||
111 | |||||
112 | # Do we have required parameters? | ||||
113 | 1 | 7µs | 1 | 600ns | foreach my $param (@{$self->required_parameters}) { # spent 600ns making 1 call to Sympa::DatabaseDriver::required_parameters |
114 | 2 | 1µs | unless (defined $self->{$param}) { | ||
115 | $log->syslog('info', 'Missing parameter %s for DBI connection', | ||||
116 | $param); | ||||
117 | return undef; | ||||
118 | } | ||||
119 | } | ||||
120 | |||||
121 | # Check if required module such as DBD is installed. | ||||
122 | 1 | 5µs | 1 | 600ns | foreach my $module (@{$self->required_modules}) { # spent 600ns making 1 call to Sympa::DatabaseDriver::PostgreSQL::required_modules |
123 | 1 | 36µs | unless (eval "require $module") { # spent 0s executing statements in 2 string evals (merged) | ||
124 | $log->syslog( | ||||
125 | 'err', | ||||
126 | 'A module for %s is not installed. You should download and install %s', | ||||
127 | ref($self), | ||||
128 | $module | ||||
129 | ); | ||||
130 | Sympa::send_notify_to_listmaster('*', 'missing_dbd', | ||||
131 | {'db_type' => ref($self), 'db_module' => $module}); | ||||
132 | return undef; | ||||
133 | } | ||||
134 | } | ||||
135 | 1 | 9µs | 1 | 500ns | foreach my $module (@{$self->optional_modules}) { # spent 500ns making 1 call to Sympa::DatabaseDriver::optional_modules |
136 | eval "require $module"; | ||||
137 | } | ||||
138 | |||||
139 | # Set unique ID to determine connection. | ||||
140 | 1 | 3µs | 1 | 27µs | $self->{_id} = $self->get_id; # spent 27µs making 1 call to Sympa::Database::get_id |
141 | |||||
142 | # Establish new connection. | ||||
143 | |||||
144 | # Set environment variables | ||||
145 | # Used by Oracle (ORACLE_HOME) etc. | ||||
146 | 1 | 800ns | if ($self->{'db_env'}) { | ||
147 | foreach my $env (split /;/, $self->{'db_env'}) { | ||||
148 | my ($key, $value) = split /=/, $env, 2; | ||||
149 | $ENV{$key} = $value if ($key); | ||||
150 | } | ||||
151 | } | ||||
152 | |||||
153 | 2 | 15µs | 2 | 6.81ms | $connection_of{$self->{_id}} = eval { $self->_connect }; # spent 6.80ms making 1 call to Sympa::Database::_connect
# spent 1µs making 1 call to DBI::common::DESTROY |
154 | |||||
155 | 1 | 3µs | 1 | 118µs | unless ($self->ping) { # spent 118µs making 1 call to Sympa::Database::ping |
156 | unless ($persistent_connection_of{$self->{_id}}) { | ||||
157 | $log->syslog('err', 'Can\'t connect to Database %s: %s', | ||||
158 | $self, $DBI::errstr); | ||||
159 | $self->{_status} = 'failed'; | ||||
160 | return undef; | ||||
161 | } | ||||
162 | |||||
163 | # Notify listmaster unless the 'failed' status was set earlier. | ||||
164 | $log->syslog('err', 'Can\'t connect to Database %s, still trying...', | ||||
165 | $self); | ||||
166 | unless ($self->{_status} and $self->{_status} eq 'failed') { | ||||
167 | Sympa::send_notify_to_listmaster('*', 'no_db', {}); | ||||
168 | } | ||||
169 | |||||
170 | # Loop until connect works | ||||
171 | my $sleep_delay = 60; | ||||
172 | while (1) { | ||||
173 | sleep $sleep_delay; | ||||
174 | $connection_of{$self->{_id}} = eval { $self->_connect }; | ||||
175 | last if $self->ping; | ||||
176 | $sleep_delay += 10; | ||||
177 | } | ||||
178 | |||||
179 | delete $self->{_status}; | ||||
180 | |||||
181 | $log->syslog('notice', 'Connection to Database %s restored', $self); | ||||
182 | Sympa::send_notify_to_listmaster('*', 'db_restored', {}); | ||||
183 | } | ||||
184 | |||||
185 | 1 | 3µs | 1 | 241µs | $log->syslog('debug2', 'Connected to Database %s', $self); # spent 241µs making 1 call to Sympa::Log::syslog |
186 | |||||
187 | 1 | 3µs | return 1; | ||
188 | } | ||||
189 | |||||
190 | # Merged into connect((). | ||||
191 | #sub establish_connection(); | ||||
192 | |||||
193 | # spent 6.80ms (16µs+6.79) within Sympa::Database::_connect which was called:
# once (16µs+6.79ms) by Sympa::Database::connect at line 153 | ||||
194 | 1 | 400ns | my $self = shift; | ||
195 | |||||
196 | my $connection = DBI->connect( | ||||
197 | $self->build_connect_string, $self->{'db_user'}, | ||||
198 | 1 | 13µs | 2 | 6.79ms | $self->{'db_passwd'}, {PrintError => 0} # spent 6.78ms making 1 call to DBI::connect
# spent 5µs making 1 call to Sympa::DatabaseDriver::PostgreSQL::build_connect_string |
199 | ); | ||||
200 | # Force field names to be lowercased. | ||||
201 | # This has has been added after some problems of field names | ||||
202 | # upercased with Oracle. | ||||
203 | 1 | 5µs | 1 | 1µs | $connection->{FetchHashKeyName} = 'NAME_lc' if $connection; # spent 1µs making 1 call to DBI::common::STORE |
204 | |||||
205 | 1 | 3µs | return $connection; | ||
206 | } | ||||
207 | |||||
208 | # spent 22µs within Sympa::Database::__dbh which was called 10 times, avg 2µs/call:
# 4 times (12µs+0s) by Sympa::Database::do_prepared_query at line 327, avg 3µs/call
# 2 times (5µs+0s) by Sympa::Database::ping at line 448, avg 3µs/call
# once (2µs+0s) by Sympa::DatabaseDriver::PostgreSQL::connect at line 66 of /usr/local/libexec/sympa/Sympa/DatabaseDriver/PostgreSQL.pm
# once (1µs+0s) by Sympa::DatabaseDriver::PostgreSQL::connect at line 68 of /usr/local/libexec/sympa/Sympa/DatabaseDriver/PostgreSQL.pm
# once (1µs+0s) by Sympa::Database::do_prepared_query at line 358
# once (900ns+0s) by Sympa::DatabaseDriver::PostgreSQL::connect at line 67 of /usr/local/libexec/sympa/Sympa/DatabaseDriver/PostgreSQL.pm | ||||
209 | 10 | 3µs | my $self = shift; | ||
210 | 10 | 25µs | return $connection_of{$self->{_id} || ''}; | ||
211 | } | ||||
212 | |||||
213 | sub do_operation { | ||||
214 | die 'Not implemented'; | ||||
215 | } | ||||
216 | |||||
217 | sub do_query { | ||||
218 | my $self = shift; | ||||
219 | my $query = shift; | ||||
220 | my @params = @_; | ||||
221 | |||||
222 | my $sth; | ||||
223 | |||||
224 | $query =~ s/^\s+//; | ||||
225 | $query =~ s/\s+$//; | ||||
226 | my $statement = sprintf $query, @params; | ||||
227 | |||||
228 | my $s = $statement; | ||||
229 | $s =~ s/\n\s*/ /g; | ||||
230 | $log->syslog('debug3', 'Will perform query "%s"', $s); | ||||
231 | |||||
232 | unless ($self->__dbh and $sth = $self->__dbh->prepare($statement)) { | ||||
233 | # Check connection to database in case it would be the cause of the | ||||
234 | # problem. | ||||
235 | unless ($self->connect()) { | ||||
236 | $log->syslog('err', 'Unable to get a handle to %s database', | ||||
237 | $self->{'db_name'}); | ||||
238 | return undef; | ||||
239 | } else { | ||||
240 | unless ($self->__dbh and $sth = $self->__dbh->prepare($statement)) | ||||
241 | { | ||||
242 | my $trace_statement = sprintf $query, | ||||
243 | @{$self->prepare_query_log_values(@params)}; | ||||
244 | $log->syslog('err', 'Unable to prepare SQL statement %s: %s', | ||||
245 | $trace_statement, $self->error); | ||||
246 | return undef; | ||||
247 | } | ||||
248 | } | ||||
249 | } | ||||
250 | unless ($sth->execute) { | ||||
251 | # Check connection to database in case it would be the cause of the | ||||
252 | # problem. | ||||
253 | unless ($self->connect()) { | ||||
254 | $log->syslog('err', 'Unable to get a handle to %s database', | ||||
255 | $self->{'db_name'}); | ||||
256 | return undef; | ||||
257 | } else { | ||||
258 | unless ($sth = $self->__dbh->prepare($statement)) { | ||||
259 | # Check connection to database in case it would be the cause | ||||
260 | # of the problem. | ||||
261 | unless ($self->connect()) { | ||||
262 | $log->syslog('err', | ||||
263 | 'Unable to get a handle to %s database', | ||||
264 | $self->{'db_name'}); | ||||
265 | return undef; | ||||
266 | } else { | ||||
267 | unless ($sth = $self->__dbh->prepare($statement)) { | ||||
268 | my $trace_statement = sprintf $query, | ||||
269 | @{$self->prepare_query_log_values(@params)}; | ||||
270 | $log->syslog('err', | ||||
271 | 'Unable to prepare SQL statement %s: %s', | ||||
272 | $trace_statement, $self->error); | ||||
273 | return undef; | ||||
274 | } | ||||
275 | } | ||||
276 | } | ||||
277 | unless ($sth->execute) { | ||||
278 | my $trace_statement = sprintf $query, | ||||
279 | @{$self->prepare_query_log_values(@params)}; | ||||
280 | $log->syslog('err', | ||||
281 | 'Unable to execute SQL statement "%s": %s', | ||||
282 | $trace_statement, $self->error); | ||||
283 | return undef; | ||||
284 | } | ||||
285 | } | ||||
286 | } | ||||
287 | |||||
288 | return $sth; | ||||
289 | } | ||||
290 | |||||
291 | # spent 985ms (65.7+919) within Sympa::Database::do_prepared_query which was called 2754 times, avg 358µs/call:
# 2754 times (65.7ms+919ms) by Sympa::DatabaseDriver::PostgreSQL::do_prepared_query at line 105 of /usr/local/libexec/sympa/Sympa/DatabaseDriver/PostgreSQL.pm, avg 358µs/call | ||||
292 | 2754 | 572µs | my $self = shift; | ||
293 | 2754 | 819µs | my $query = shift; | ||
294 | 2754 | 850µs | my @params = (); | ||
295 | 2754 | 901µs | my %types = (); | ||
296 | |||||
297 | 2754 | 390µs | my $sth; | ||
298 | |||||
299 | ## get binding types and parameters | ||||
300 | 2754 | 638µs | my $i = 0; | ||
301 | 2754 | 1.19ms | while (scalar @_) { | ||
302 | 8262 | 1.69ms | my $p = shift; | ||
303 | 8262 | 2.91ms | if (ref $p eq 'HASH') { | ||
304 | # a hashref { sql_type => SQL_type } etc. | ||||
305 | $types{$i} = $p; | ||||
306 | push @params, shift; | ||||
307 | } elsif (ref $p) { | ||||
308 | $log->syslog('err', 'Unexpected %s object. Ask developer', | ||||
309 | ref $p); | ||||
310 | return undef; | ||||
311 | } else { | ||||
312 | 8262 | 2.28ms | push @params, $p; | ||
313 | } | ||||
314 | 8262 | 2.90ms | $i++; | ||
315 | } | ||||
316 | |||||
317 | 2754 | 10.5ms | 2754 | 2.19ms | $query =~ s/^\s+//; # spent 2.19ms making 2754 calls to Sympa::Database::CORE:subst, avg 795ns/call |
318 | 2754 | 21.5ms | 2754 | 9.70ms | $query =~ s/\s+$//; # spent 9.70ms making 2754 calls to Sympa::Database::CORE:subst, avg 4µs/call |
319 | 2754 | 18.7ms | 2754 | 10.00ms | $query =~ s/\n\s*/ /g; # spent 10.00ms making 2754 calls to Sympa::Database::CORE:subst, avg 4µs/call |
320 | 2754 | 2.95ms | 2754 | 517ms | $log->syslog('debug3', 'Will perform query "%s"', $query); # spent 517ms making 2754 calls to Sympa::Log::syslog, avg 188µs/call |
321 | |||||
322 | 2754 | 3.59ms | if ($self->{'cached_prepared_statements'}{$query}) { | ||
323 | $sth = $self->{'cached_prepared_statements'}{$query}; | ||||
324 | } else { | ||||
325 | 2 | 3µs | 2 | 290µs | $log->syslog('debug3', # spent 290µs making 2 calls to Sympa::Log::syslog, avg 145µs/call |
326 | 'Did not find prepared statement for %s. Doing it', $query); | ||||
327 | 2 | 40µs | 8 | 233µs | unless ($self->__dbh and $sth = $self->__dbh->prepare($query)) { # spent 121µs making 2 calls to DBI::db::prepare, avg 60µs/call
# spent 101µs making 2 calls to DBD::Pg::db::prepare, avg 50µs/call
# spent 12µs making 4 calls to Sympa::Database::__dbh, avg 3µs/call |
328 | unless ($self->connect()) { | ||||
329 | $log->syslog('err', 'Unable to get a handle to %s database', | ||||
330 | $self->{'db_name'}); | ||||
331 | return undef; | ||||
332 | } else { | ||||
333 | unless ($self->__dbh and $sth = $self->__dbh->prepare($query)) | ||||
334 | { | ||||
335 | $log->syslog('err', 'Unable to prepare SQL statement: %s', | ||||
336 | $self->error); | ||||
337 | return undef; | ||||
338 | } | ||||
339 | } | ||||
340 | } | ||||
341 | |||||
342 | ## bind parameters with special types | ||||
343 | ## this may be done only once when handle is prepared. | ||||
344 | 2 | 11µs | 2 | 1µs | foreach my $i (sort keys %types) { # spent 1µs making 2 calls to Sympa::Database::CORE:sort, avg 550ns/call |
345 | $sth->bind_param($i + 1, $params[$i], $types{$i}); | ||||
346 | } | ||||
347 | |||||
348 | 2 | 4µs | $self->{'cached_prepared_statements'}{$query} = $sth; | ||
349 | } | ||||
350 | 2754 | 379ms | 2754 | 371ms | unless ($sth->execute(@params)) { # spent 371ms making 2754 calls to DBI::st::execute, avg 135µs/call |
351 | # Check database connection in case it would be the cause of the | ||||
352 | # problem. | ||||
353 | 1 | 4µs | 1 | 7.79ms | unless ($self->connect()) { # spent 7.79ms making 1 call to Sympa::DatabaseDriver::PostgreSQL::connect |
354 | $log->syslog('err', 'Unable to get a handle to %s database', | ||||
355 | $self->{'db_name'}); | ||||
356 | return undef; | ||||
357 | } else { | ||||
358 | 1 | 7µs | 3 | 82µs | unless ($sth = $self->__dbh->prepare($query)) { # spent 42µs making 1 call to DBI::db::prepare
# spent 39µs making 1 call to DBD::Pg::db::prepare
# spent 1µs making 1 call to Sympa::Database::__dbh |
359 | unless ($self->connect()) { | ||||
360 | $log->syslog('err', | ||||
361 | 'Unable to get a handle to %s database', | ||||
362 | $self->{'db_name'}); | ||||
363 | return undef; | ||||
364 | } else { | ||||
365 | unless ($sth = $self->__dbh->prepare($query)) { | ||||
366 | $log->syslog('err', | ||||
367 | 'Unable to prepare SQL statement: %s', | ||||
368 | $self->error); | ||||
369 | return undef; | ||||
370 | } | ||||
371 | } | ||||
372 | } | ||||
373 | |||||
374 | ## bind parameters with special types | ||||
375 | ## this may be done only once when handle is prepared. | ||||
376 | 1 | 4µs | 1 | 500ns | foreach my $i (sort keys %types) { # spent 500ns making 1 call to Sympa::Database::CORE:sort |
377 | $sth->bind_param($i + 1, $params[$i], $types{$i}); | ||||
378 | } | ||||
379 | |||||
380 | 1 | 34µs | 3 | 12µs | $self->{'cached_prepared_statements'}{$query} = $sth; # spent 10µs making 2 calls to DBI::common::DESTROY, avg 5µs/call
# spent 1µs making 1 call to DBD::_mem::common::DESTROY |
381 | 1 | 1.18ms | 1 | 1.17ms | unless ($sth->execute(@params)) { # spent 1.17ms making 1 call to DBI::st::execute |
382 | $log->syslog('err', | ||||
383 | 'Unable to execute SQL statement "%s": %s', | ||||
384 | $query, $self->error); | ||||
385 | return undef; | ||||
386 | } | ||||
387 | } | ||||
388 | } | ||||
389 | |||||
390 | 2754 | 11.6ms | return $sth; | ||
391 | } | ||||
392 | |||||
393 | sub prepare_query_log_values { | ||||
394 | my $self = shift; | ||||
395 | my @result; | ||||
396 | foreach my $value (@_) { | ||||
397 | my $cropped = substr($value, 0, 100); | ||||
398 | if ($cropped ne $value) { | ||||
399 | $cropped .= "...[shortened]"; | ||||
400 | } | ||||
401 | push @result, $cropped; | ||||
402 | } | ||||
403 | return \@result; | ||||
404 | } | ||||
405 | |||||
406 | # DEPRECATED: Use tools::eval_in_time() and fetchall_arrayref(). | ||||
407 | #sub fetch(); | ||||
408 | |||||
409 | sub disconnect { | ||||
410 | my $self = shift; | ||||
411 | |||||
412 | my $id = $self->get_id; | ||||
413 | |||||
414 | # Don't disconnect persistent connection. | ||||
415 | return 0 if $persistent_connection_of{$id}; | ||||
416 | |||||
417 | $connection_of{$id}->disconnect if $connection_of{$id}; | ||||
418 | delete $connection_of{$id}; | ||||
419 | return 1; | ||||
420 | } | ||||
421 | |||||
422 | # NOT YET USED. | ||||
423 | #sub create_db; | ||||
424 | |||||
425 | sub error { | ||||
426 | my $self = shift; | ||||
427 | |||||
428 | my $dbh = $self->__dbh; | ||||
429 | return sprintf '(%s) %s', $dbh->state, ($dbh->errstr || '') if $dbh; | ||||
430 | return undef; | ||||
431 | } | ||||
432 | |||||
433 | sub set_persistent { | ||||
434 | my $self = shift; | ||||
435 | my $flag = shift; | ||||
436 | |||||
437 | if ($flag) { | ||||
438 | $persistent_connection_of{$self->get_id} = 1; | ||||
439 | } elsif (defined $flag) { | ||||
440 | delete $persistent_connection_of{$self->get_id}; | ||||
441 | } | ||||
442 | return $self; | ||||
443 | } | ||||
444 | |||||
445 | sub ping { | ||||
446 | 2 | 1µs | my $self = shift; | ||
447 | |||||
448 | 2 | 5µs | 2 | 5µs | my $dbh = $self->__dbh; # spent 5µs making 2 calls to Sympa::Database::__dbh, avg 3µs/call |
449 | |||||
450 | # Disconnected explicitly. | ||||
451 | 2 | 1µs | return undef unless $dbh; | ||
452 | # Some drivers don't have ping(). | ||||
453 | 2 | 13µs | 2 | 7µs | return 1 unless $dbh->can('ping'); # spent 7µs making 2 calls to DBI::common::can, avg 3µs/call |
454 | 2 | 20µs | 4 | 256µs | return $dbh->ping; # spent 132µs making 2 calls to DBI::db::ping, avg 66µs/call
# spent 124µs making 2 calls to DBD::Pg::db::ping, avg 62µs/call |
455 | } | ||||
456 | |||||
457 | sub quote { | ||||
458 | my $self = shift; | ||||
459 | my ($string, $datatype) = @_; | ||||
460 | |||||
461 | # quote() does not need actual connection but driver handle. | ||||
462 | unless ($self->__dbh or $self->connect) { | ||||
463 | return undef; | ||||
464 | } | ||||
465 | return $self->__dbh->quote($string, $datatype); | ||||
466 | } | ||||
467 | |||||
468 | # No longer used. | ||||
469 | #sub set_fetch_timeout($timeout); | ||||
470 | |||||
471 | ## Returns a character string corresponding to the expression to use in | ||||
472 | ## a read query (e.g. SELECT) for the field given as argument. | ||||
473 | ## This sub takes a single argument: the name of the field to be used in | ||||
474 | ## the query. | ||||
475 | ## | ||||
476 | # Moved to Sympa::Upgrade::_get_canonical_write_date(). | ||||
477 | #sub get_canonical_write_date; | ||||
478 | |||||
479 | ## Returns a character string corresponding to the expression to use in | ||||
480 | ## a write query (e.g. UPDATE or INSERT) for the value given as argument. | ||||
481 | ## This sub takes a single argument: the value of the date to be used in | ||||
482 | ## the query. | ||||
483 | ## | ||||
484 | # Moved to Sympa::Upgrade::_get_canonical_read_date(). | ||||
485 | #sub get_canonical_read_date; | ||||
486 | |||||
487 | # We require that user also matches (except SQLite). | ||||
488 | # spent 102µs (78+24) within Sympa::Database::get_id which was called 3 times, avg 34µs/call:
# 2 times (57µs+18µs) by Sympa::Log::syslog at line 112 of /usr/local/libexec/sympa/Sympa/Log.pm, avg 38µs/call
# once (21µs+6µs) by Sympa::Database::connect at line 140 | ||||
489 | 3 | 1µs | my $self = shift; | ||
490 | |||||
491 | return join ';', map {"$_=$self->{$_}"} | ||||
492 | grep { | ||||
493 | 3 | 43µs | 3 | 7µs | !ref($self->{$_}) # spent 7µs making 3 calls to Sympa::Database::CORE:sort, avg 2µs/call |
494 | 21 | 58µs | 33 | 17µs | and defined $self->{$_} # spent 17µs making 33 calls to Sympa::Database::CORE:match, avg 521ns/call |
495 | and !/\A_/ | ||||
496 | and !/passw(or)?d/ | ||||
497 | } | ||||
498 | sort keys %$self; | ||||
499 | } | ||||
500 | |||||
501 | sub DESTROY { | ||||
502 | shift->disconnect; | ||||
503 | } | ||||
504 | |||||
505 | 1; | ||||
506 | __END__ | ||||
# spent 17µs within Sympa::Database::CORE:match which was called 33 times, avg 521ns/call:
# 33 times (17µs+0s) by Sympa::Database::get_id at line 494, avg 521ns/call | |||||
# spent 9µs within Sympa::Database::CORE:sort which was called 6 times, avg 1µs/call:
# 3 times (7µs+0s) by Sympa::Database::get_id at line 493, avg 2µs/call
# 2 times (1µs+0s) by Sympa::Database::do_prepared_query at line 344, avg 550ns/call
# once (500ns+0s) by Sympa::Database::do_prepared_query at line 376 | |||||
# spent 21.9ms within Sympa::Database::CORE:subst which was called 8262 times, avg 3µs/call:
# 2754 times (10.00ms+0s) by Sympa::Database::do_prepared_query at line 319, avg 4µs/call
# 2754 times (9.70ms+0s) by Sympa::Database::do_prepared_query at line 318, avg 4µs/call
# 2754 times (2.19ms+0s) by Sympa::Database::do_prepared_query at line 317, avg 795ns/call |