File Coverage

blib/lib/Dancer2/Plugin/Database.pm
Criterion Covered Total %
statement 12 26 46.1
branch 0 2 0.0
condition 0 5 0.0
subroutine 4 8 50.0
pod n/a
total 16 41 39.0


line stmt bran cond sub pod time code
1             package Dancer2::Plugin::Database;
2              
3 2     2   974512 use strict;
  2         4  
  2         57  
4              
5 2     2   1673 use Dancer::Plugin::Database::Core;
  2         3439  
  2         65  
6 2     2   1746 use Dancer::Plugin::Database::Core::Handle;
  2         46613  
  2         65  
7              
8 2     2   1771 use Dancer2::Plugin;
  2         4701  
  2         14  
9              
10             =encoding utf8
11              
12             =head1 NAME
13              
14             Dancer2::Plugin::Database - easy database connections for Dancer2 applications
15              
16             =cut
17              
18             our $VERSION = '2.14';
19              
20             register_hook qw(database_connected
21             database_connection_lost
22             database_connection_failed
23             database_error);
24              
25              
26             my $settings = {};
27              
28             sub _load_settings {
29 0     0     my $dsl = shift;
30 0           $settings = plugin_setting();
31 0   0       $settings->{charset} ||= $dsl->setting('charset') || 'utf-8';
      0        
32             }
33              
34             register database => sub {
35 0     0     my $dsl = shift;
36              
37             my $logger = sub {
38 0     0     $dsl->log(@_);
39 0           };
40              
41             # wasn't working properly calling the Dancer2::Plugin execute_hook
42             # directly
43             my $hook_exec = sub {
44 0 0   0     if ( $dsl->can('execute_plugin_hook') ) {
45             # Plugin2
46 0           $dsl->execute_plugin_hook(@_);
47             }
48             else {
49             # old behaviour
50 0           $dsl->execute_hook(@_);
51             }
52 0           };
53              
54             ## This is mostly for the case the user uses 'set plugins' and
55             ## changes configuration during runtime. For example in our test suite.
56 0           _load_settings($dsl);
57              
58 0           my ($dbh, $cfg) = Dancer::Plugin::Database::Core::database( arg => $_[0],
59             logger => $logger,
60             hook_exec => $hook_exec,
61             settings => $settings );
62 0           $settings = $cfg;
63 0           return $dbh;
64             };
65              
66             register_plugin;
67              
68             =head1 SYNOPSIS
69              
70             use Dancer2;
71             use Dancer2::Plugin::Database;
72              
73             # Calling the database keyword will get you a connected database handle:
74             get '/widget/view/:id' => sub {
75             my $sth = database->prepare(
76             'select * from widgets where id = ?',
77             );
78             $sth->execute(params->{id});
79             template 'display_widget', { widget => $sth->fetchrow_hashref };
80             };
81              
82             # The handle is a Dancer::Plugin::Database::Core::Handle object, which subclasses
83             # DBI's DBI::db handle and adds a few convenience features, for example:
84             get '/insert/:name' => sub {
85             database->quick_insert('people', { name => params->{name} });
86             };
87              
88             get '/users/:id' => sub {
89             template 'display_user', {
90             person => database->quick_select('users', { id => params->{id} }),
91             };
92             };
93              
94             dance;
95              
96             Database connection details are read from your Dancer2 application config - see
97             below.
98              
99              
100             =head1 DESCRIPTION
101              
102             Provides an easy way to obtain a connected DBI database handle by simply calling
103             the database keyword within your L application
104              
105             Returns a L object, which is a subclass of
106             L's C connection handle object, so it does everything you'd expect
107             to do with DBI, but also adds a few convenience methods. See the documentation
108             for L for full details of those.
109              
110             Takes care of ensuring that the database handle is still connected and valid.
111             If the handle was last asked for more than C seconds
112             ago, it will check that the connection is still alive, using either the
113             C<< $dbh->ping >> method if the DBD driver supports it, or performing a simple
114             no-op query against the database if not. If the connection has gone away, a new
115             connection will be obtained and returned. This avoids any problems for
116             a long-running script where the connection to the database might go away.
117              
118             Care is taken that handles are not shared across processes/threads, so this
119             should be thread-safe with no issues with transactions etc. (Thanks to Matt S
120             Trout for pointing out the previous lack of thread safety. Inspiration was
121             drawn from DBIx::Connector.)
122              
123             =head1 CONFIGURATION
124              
125             Connection details will be taken from your Dancer2 application config file, and
126             should be specified as, for example:
127              
128             plugins:
129             Database:
130             driver: 'mysql'
131             database: 'test'
132             host: 'localhost'
133             port: 3306
134             username: 'myusername'
135             password: 'mypassword'
136             connection_check_threshold: 10
137             dbi_params:
138             RaiseError: 1
139             AutoCommit: 1
140             on_connect_do: ["SET NAMES 'utf8'", "SET CHARACTER SET 'utf8'" ]
141             log_queries: 1
142             handle_class: 'My::Super::Sexy::Database::Handle'
143              
144             The C setting is optional, if not provided, it
145             will default to 30 seconds. If the database keyword was last called more than
146             this number of seconds ago, a quick check will be performed to ensure that we
147             still have a connection to the database, and will reconnect if not. This
148             handles cases where the database handle hasn't been used for a while and the
149             underlying connection has gone away.
150              
151             The C setting is also optional, and if specified, should be settings
152             which can be passed to C<< DBI->connect >> as its fourth argument; see the L
153             documentation for these.
154              
155             The optional C setting is an array of queries which should be
156             performed when a connection is established; if given, each query will be
157             performed using C<< $dbh->do >>. (If using MySQL, you might want to use this to
158             set C to a suitable value to disable MySQL's built-in free data loss
159             'features', for example:
160              
161             on_connect_do: "SET SQL_MODE='TRADITIONAL'"
162              
163             (If you're not familiar with what I mean, I'm talking about the insane default
164             behaviour of "hmm, this bit of data won't fit the column you're trying to put it
165             in.. hmm, I know, I'll just munge it to fit, and throw a warning afterwards -
166             it's not like you're relying on me to, y'know, store what you ask me to store".
167             See L for
168             just one illustration. In hindsight, I wish I'd made a sensible C a
169             default setting, but I don't want to change that now.)
170              
171             The optional C setting enables logging of queries generated by the
172             helper functions C et al in L.
173             If you enable it, generated queries will be logged at 'debug' level. Be aware
174             that they will contain the data you're passing to/from the database, so be
175             careful not to enable this option in production, where you could inadvertently
176             log sensitive information.
177              
178             If you prefer, you can also supply a pre-crafted DSN using the C setting;
179             in that case, it will be used as-is, and the driver/database/host settings will
180             be ignored. This may be useful if you're using some DBI driver which requires
181             a peculiar DSN.
182              
183             The optional C defines your own class into which database handles
184             should be blessed. This should be a subclass of
185             L (or L directly, if you just want to
186             skip the extra features).
187              
188             You will require slightly different options depending on the database engine
189             you're talking to. For instance, for SQLite, you won't need to supply
190             C, C etc, but will need to supply C as the name of the
191             SQLite database file:
192              
193             plugins:
194             Database:
195             driver: SQLite
196             database: 'foo.sqlite'
197              
198             For Oracle, you may want to pass C (system ID) to identify a particular
199             database, e.g.:
200              
201             plugins:
202             Database:
203             driver: Oracle
204             host: localhost
205             sid: ABC12
206              
207              
208             If you have any further connection parameters that need to be appended
209             to the dsn, you can put them in as a hash called dsn_extra. For
210             example, if you're running mysql on a non-standard socket, you could
211             have
212              
213             plugins:
214             Database:
215             driver: mysql
216             host: localhost
217             dsn_extra:
218             mysql_socket: /tmp/mysql_staging.sock
219              
220              
221             =head2 DEFINING MULTIPLE CONNECTIONS
222              
223             If you need to connect to multiple databases, this is easy - just list them in
224             your config under C as shown below:
225              
226             plugins:
227             Database:
228             connections:
229             foo:
230             driver: "SQLite"
231             database: "foo.sqlite"
232             bar:
233             driver: "mysql"
234             host: "localhost"
235             ....
236              
237             Then, you can call the C keyword with the name of the database
238             connection you want, for example:
239              
240             my $foo_dbh = database('foo');
241             my $bar_dbh = database('bar');
242              
243              
244             =head1 RUNTIME CONFIGURATION
245              
246             You can pass a hashref to the C keyword to provide configuration
247             details to override any in the config file at runtime if desired, for instance:
248              
249             my $dbh = database({ driver => 'SQLite', database => $filename });
250              
251             (Thanks to Alan Haggai for this feature.)
252              
253             =head1 AUTOMATIC UTF-8 SUPPORT
254              
255             As of version 1.20, if your application is configured to use UTF-8 (you've
256             defined the C setting in your app config as C) then support for
257             UTF-8 for the database connection will be enabled, if we know how to do so for
258             the database driver in use.
259              
260             If you do not want this behaviour, set C to a false value when
261             providing the connection details.
262              
263              
264              
265             =head1 GETTING A DATABASE HANDLE
266              
267             Calling C will return a connected database handle; the first time it is
268             called, the plugin will establish a connection to the database, and return a
269             reference to the DBI object. On subsequent calls, the same DBI connection
270             object will be returned, unless it has been found to be no longer usable (the
271             connection has gone away), in which case a fresh connection will be obtained.
272              
273             If you have declared named connections as described above in 'DEFINING MULTIPLE
274             CONNECTIONS', then calling the database() keyword with the name of the
275             connection as specified in the config file will get you a database handle
276             connected with those details.
277              
278             You can also pass a hashref of settings if you wish to provide settings at
279             runtime.
280              
281              
282             =head1 CONVENIENCE FEATURES (quick_select, quick_update, quick_insert, quick_delete, quick_count)
283              
284             The handle returned by the C keyword is a
285             L object, which subclasses the C DBI
286             connection handle. This means you can use it just like you'd normally use a DBI
287             handle, but extra convenience methods are provided, as documented in the POD for
288             L.
289              
290             Examples:
291              
292             # Quickly fetch the (first) row whose ID is 42 as a hashref:
293             my $row = database->quick_select($table_name, { id => 42 });
294              
295             # Fetch all badgers as an array of hashrefs:
296             my @badgers = database->quick_select('animals', { genus => 'Mellivora' });
297              
298             # Update the row where the 'id' column is '42', setting the 'foo' column to
299             # 'Bar':
300             database->quick_update($table_name, { id => 42 }, { foo => 'Bar' });
301              
302             # Insert a new row, using a named connection (see above)
303             database('connectionname')->quick_insert($table_name, { foo => 'Bar' });
304              
305             # Delete the row with id 42:
306             database->quick_delete($table_name, { id => 42 });
307              
308             # Fetch all rows from a table (since version 1.30):
309             database->quick_select($table_name, {});
310              
311             # Retrieve a count of rows matching the criteria:
312             database->quick_count($table_name, {});
313              
314             There's more extensive documentation on these features in
315             L, including using the C, C,
316             C options to sort / limit results and include only specific columns.
317              
318             =head1 HOOKS
319              
320             This plugin uses Dancer2's hooks support to allow you to register code that
321             should execute at given times - for example:
322              
323             hook 'database_connected' => sub {
324             my $dbh = shift;
325             # do something with the new DB handle here
326             };
327              
328             Currrently defined hook positions are:
329              
330             =over 4
331              
332             =item C
333              
334             Called when a new database connection has been established, after performing any
335             C statements, but before the handle is returned. Receives the
336             new database handle as a parameter, so that you can do what you need with it.
337              
338             =item C
339              
340             Called when the plugin detects that the database connection has gone away.
341             Receives the no-longer usable handle as a parameter, in case you need to extract
342             some information from it (such as which server it was connected to).
343              
344             =item C
345              
346             Called when an attempt to connect to the database fails. Receives a hashref of
347             connection settings as a parameter, containing the settings the plugin was using
348             to connect (as obtained from the config file).
349              
350             =item C
351              
352             Called when a database error is raised by C. Receives two parameters: the
353             error message being returned by DBI, and the database handle in question.
354              
355             =back
356              
357             If you need other hook positions which would be useful to you, please feel free
358             to suggest them!
359              
360              
361             =head1 AUTHOR
362              
363             David Precious, C<< >>
364              
365              
366              
367             =head1 CONTRIBUTING
368              
369             This module is developed on Github at:
370              
371             L
372              
373             Feel free to fork the repo and submit pull requests! Also, it makes sense to
374             L
375             on GitHub for updates.
376              
377             Feedback and bug reports are always appreciated. Even a quick mail to let me
378             know the module is useful to you would be very nice - it's nice to know if code
379             is being actively used.
380              
381             =head1 ACKNOWLEDGEMENTS
382              
383             Igor Bujna
384              
385             Franck Cuny
386              
387             Alan Haggai
388              
389             Christian Sánchez
390              
391             Michael Stiller
392              
393             Martin J Evans
394              
395             Carlos Sosa
396              
397             Matt S Trout
398              
399             Matthew Vickers
400              
401             Christian Walde
402              
403             Alberto Simões
404              
405             James Aitken (LoonyPandora)
406              
407             Mark Allen (mrallen1)
408              
409             Sergiy Borodych (bor)
410              
411             Mario Domgoergen (mdom)
412              
413             Andrey Inishev (inish777)
414              
415             Nick S. Knutov (knutov)
416              
417             Nicolas Franck (nicolasfranck)
418              
419             mscolly
420              
421             =head1 BUGS
422              
423             Please report any bugs or feature requests to C, or through
424             the web interface at L. I will be notified, and then you'll
425             automatically be notified of progress on your bug as I make changes.
426              
427              
428              
429              
430             =head1 SUPPORT
431              
432             You can find documentation for this module with the perldoc command.
433              
434             perldoc Dancer2::Plugin::Database
435              
436             You can also look for information at:
437              
438             =over 4
439              
440             =item * RT: CPAN's request tracker
441              
442             L
443              
444             =item * AnnoCPAN: Annotated CPAN documentation
445              
446             L
447              
448             =item * CPAN Ratings
449              
450             L
451              
452             =item * Search CPAN
453              
454             L
455              
456             =back
457              
458             You can find the author on IRC in the channel C<#dancer> on .
459              
460              
461             =head1 LICENSE AND COPYRIGHT
462              
463             Copyright 2010-13 David Precious.
464              
465             This program is free software; you can redistribute it and/or modify it
466             under the terms of either: the GNU General Public License as published
467             by the Free Software Foundation; or the Artistic License.
468              
469             See http://dev.perl.org/licenses/ for more information.
470              
471              
472             =head1 SEE ALSO
473              
474             L and L
475              
476             L, L
477              
478             L
479              
480             L
481              
482             =cut
483              
484             1; # End of Dancer2::Plugin::Database