File Coverage

blib/lib/Mojo/MySQL.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Mojo::MySQL;
2 3     3   217313 use Mojo::Base -base;
  3         5  
  3         17  
3              
4 3     3   378 use Carp 'croak';
  3         4  
  3         143  
5 3     3   4190 use DBI;
  3         41351  
  3         257  
6 3     3   1508 use Mojo::MySQL::Database;
  0            
  0            
7             use Mojo::URL;
8              
9             has dsn => 'dbi:mysql:dbname=test';
10             has max_connections => 5;
11             has options => sub { {AutoCommit => 1, PrintError => 0, RaiseError => 1} };
12             has [qw(password username)] => '';
13              
14             our $VERSION = '0.01';
15              
16             sub db {
17             my $self = shift;
18              
19             # Fork safety
20             delete @$self{qw(pid queue)} unless ($self->{pid} //= $$) eq $$;
21              
22             return Mojo::MySQL::Database->new(dbh => $self->_dequeue, mysql => $self);
23             }
24              
25             sub from_string {
26             my ($self, $str) = @_;
27              
28             # Protocol
29             return $self unless $str;
30             my $url = Mojo::URL->new($str);
31             croak qq{Invalid MySQL connection string "$str"} unless $url->protocol eq 'mysql';
32              
33             # Database
34             my $dsn = 'dbi:mysql:dbname=' . $url->path->parts->[0];
35              
36             # Host and port
37             if (my $host = $url->host) { $dsn .= ";host=$host" }
38             if (my $port = $url->port) { $dsn .= ";port=$port" }
39              
40             # Username and password
41             if (($url->userinfo // '') =~ /^([^:]+)(?::([^:]+))?$/) {
42             $self->username($1);
43             $self->password($2) if defined $2;
44             }
45              
46             # Options
47             my $hash = $url->query->to_hash;
48             @{$self->options}{keys %$hash} = values %$hash;
49              
50             return $self->dsn($dsn);
51             }
52              
53             sub new { @_ > 1 ? shift->SUPER::new->from_string(@_) : shift->SUPER::new }
54              
55             sub _dequeue {
56             my $self = shift;
57             while (my $dbh = shift @{$self->{queue} || []}) { return $dbh if $dbh->ping }
58             return DBI->connect(map { $self->$_ } qw(dsn username password options));
59             }
60              
61             sub _enqueue {
62             my ($self, $dbh) = @_;
63             push @{$self->{queue}}, $dbh if $dbh->{Active};
64             shift @{$self->{queue}} while @{$self->{queue}} > $self->max_connections;
65             }
66              
67             1;
68              
69             =encoding utf8
70              
71             =head1 NAME
72              
73             Mojo::MySQL - Mojolicious and Async MySQL
74              
75             =head1 SYNOPSIS
76              
77             use Mojo::MySQL;
78              
79             # Create a table
80             my $mysql = Mojo::MySQL->new('mysql://username@/test');
81             $mysql->db->do('create table if not exists names (name varchar(255))');
82              
83             # Insert a few rows
84             my $db = $mysql->db;
85             $db->query('insert into names values (?)', 'Sara');
86             $db->query('insert into names values (?)', 'Daniel');
87              
88             # Select all rows blocking
89             say for $db->query('select * from names')
90             ->hashes->map(sub { $_->{name} })->each;
91              
92             # Select all rows non-blocking
93             Mojo::IOLoop->delay(
94             sub {
95             my $delay = shift;
96             $db->query('select * from names' => $delay->begin);
97             },
98             sub {
99             my ($delay, $err, $results) = @_;
100             say for $results->hashes->map(sub { $_->{name} })->each;
101             }
102             )->wait;
103              
104             =head1 DESCRIPTION
105              
106             L is a tiny wrapper around L that makes
107             L a lot of fun to use with the
108             L real-time web framework.
109              
110             Database and statement handles are cached automatically, so they can be reused
111             transparently to increase performance. While all I/O operations are performed
112             blocking, you can wait for long running queries asynchronously, allowing the
113             L event loop to perform other tasks in the meantime. Since
114             database connections usually have a very low latency, this often results in
115             very good performance.
116              
117             All cached database handles will be reset automatically if a new process has
118             been forked, this allows multiple processes to share the same L
119             object safely.
120              
121             Note that this whole distribution is EXPERIMENTAL and will change without
122             warning!
123              
124             =head1 ATTRIBUTES
125              
126             L implements the following attributes.
127              
128             =head2 dsn
129              
130             my $dsn = $mysql->dsn;
131             $mysql = $mysql->dsn('dbi:mysql:dbname=foo');
132              
133             Data Source Name, defaults to C.
134              
135             =head2 max_connections
136              
137             my $max = $mysql->max_connections;
138             $mysql = $mysql->max_connections(3);
139              
140             Maximum number of idle database handles to cache for future use, defaults to
141             C<5>.
142              
143             =head2 options
144              
145             my $options = $mysql->options;
146             $mysql = $mysql->options({AutoCommit => 1});
147              
148             Options for database handles, defaults to activating C as well as
149             C and deactivating C.
150              
151             =head2 password
152              
153             my $password = $mysql->password;
154             $mysql = $mysql->password('s3cret');
155              
156             Database password, defaults to an empty string.
157              
158             =head2 username
159              
160             my $username = $mysql->username;
161             $mysql = $mysql->username('batman');
162              
163             Database username, defaults to an empty string.
164              
165             =head1 METHODS
166              
167             L inherits all methods from L and implements the
168             following new ones.
169              
170             =head2 db
171              
172             my $db = $mysql->db;
173              
174             Get L object for a cached or newly created database
175             handle. The database handle will be automatically cached again when that
176             object is destroyed, so you can handle connection timeouts gracefully by
177             holding on to it only for short amounts of time.
178              
179             =head2 from_string
180              
181             $mysql = $mysql->from_string('mysql://user@/test');
182              
183             Parse configuration from connection string.
184              
185             # Just a database
186             $mysql->from_string('mysql:///db1');
187              
188             # Username and database
189             $mysql->from_string('mysql://batman@/db2');
190              
191             # Username, password, host and database
192             $mysql->from_string('mysql://batman:s3cret@localhost/db3');
193              
194             # Username, domain socket and database
195             $mysql->from_string('mysql://batman@%2ftmp%2fmysql.sock/db4');
196              
197             # Username, database and additional options
198             $mysql->from_string('mysql://batman@/db5?PrintError=1&RaiseError=0');
199              
200             =head2 new
201              
202             my $mysql = Mojo::MySQL->new;
203             my $mysql = Mojo::MySQL->new('mysql://user@/test');
204              
205             Construct a new L object and parse connection string with
206             L if necessary.
207              
208             =head1 AUTHOR
209              
210             Jan Henning Thorsen, C.
211              
212             This code is mostly a rip-off from Sebastian Riedel's L.
213              
214             =head1 COPYRIGHT AND LICENSE
215              
216             Copyright (C) 2014, Jan Henning Thorsen.
217              
218             This program is free software, you can redistribute it and/or modify it under
219             the terms of the Artistic License version 2.0.
220              
221             =head1 SEE ALSO
222              
223             L, L,
224             L, L.
225              
226             =cut