line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mojo::SQLite; |
2
|
6
|
|
|
6
|
|
1385712
|
use Mojo::Base 'Mojo::EventEmitter'; |
|
6
|
|
|
|
|
80
|
|
|
6
|
|
|
|
|
49
|
|
3
|
|
|
|
|
|
|
|
4
|
6
|
|
|
6
|
|
9339
|
use Carp 'croak'; |
|
6
|
|
|
|
|
12
|
|
|
6
|
|
|
|
|
234
|
|
5
|
6
|
|
|
6
|
|
6578
|
use DBI; |
|
6
|
|
|
|
|
75891
|
|
|
6
|
|
|
|
|
321
|
|
6
|
6
|
|
|
6
|
|
3639
|
use DBD::SQLite; |
|
6
|
|
|
|
|
46449
|
|
|
6
|
|
|
|
|
208
|
|
7
|
6
|
|
|
6
|
|
2204
|
use DBD::SQLite::Constants qw(:database_connection_configuration_options :dbd_sqlite_string_mode); |
|
6
|
|
|
|
|
4177
|
|
|
6
|
|
|
|
|
1524
|
|
8
|
6
|
|
|
6
|
|
2053
|
use File::Spec::Functions 'catfile'; |
|
6
|
|
|
|
|
3923
|
|
|
6
|
|
|
|
|
340
|
|
9
|
6
|
|
|
6
|
|
3094
|
use File::Temp; |
|
6
|
|
|
|
|
50467
|
|
|
6
|
|
|
|
|
409
|
|
10
|
6
|
|
|
6
|
|
2518
|
use Mojo::SQLite::Database; |
|
6
|
|
|
|
|
17
|
|
|
6
|
|
|
|
|
48
|
|
11
|
6
|
|
|
6
|
|
2514
|
use Mojo::SQLite::Migrations; |
|
6
|
|
|
|
|
17
|
|
|
6
|
|
|
|
|
60
|
|
12
|
6
|
|
|
6
|
|
222
|
use Scalar::Util qw(blessed weaken); |
|
6
|
|
|
|
|
12
|
|
|
6
|
|
|
|
|
286
|
|
13
|
6
|
|
|
6
|
|
2609
|
use SQL::Abstract::Pg; |
|
6
|
|
|
|
|
115141
|
|
|
6
|
|
|
|
|
353
|
|
14
|
6
|
|
|
6
|
|
3244
|
use URI; |
|
6
|
|
|
|
|
24194
|
|
|
6
|
|
|
|
|
227
|
|
15
|
6
|
|
|
6
|
|
2629
|
use URI::db; |
|
6
|
|
|
|
|
57600
|
|
|
6
|
|
|
|
|
7779
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
our $VERSION = '3.009'; |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
has abstract => sub { SQL::Abstract::Pg->new(name_sep => '.', quote_char => '"') }; |
20
|
|
|
|
|
|
|
has 'auto_migrate'; |
21
|
|
|
|
|
|
|
has database_class => 'Mojo::SQLite::Database'; |
22
|
|
|
|
|
|
|
has dsn => sub { _url_from_file(shift->_tempfile)->dbi_dsn }; |
23
|
|
|
|
|
|
|
has max_connections => 1; |
24
|
|
|
|
|
|
|
has migrations => sub { Mojo::SQLite::Migrations->new(sqlite => shift) }; |
25
|
|
|
|
|
|
|
has options => sub { |
26
|
|
|
|
|
|
|
{ |
27
|
|
|
|
|
|
|
AutoCommit => 1, |
28
|
|
|
|
|
|
|
AutoInactiveDestroy => 1, |
29
|
|
|
|
|
|
|
PrintError => 0, |
30
|
|
|
|
|
|
|
RaiseError => 1, |
31
|
|
|
|
|
|
|
sqlite_string_mode => DBD_SQLITE_STRING_MODE_UNICODE_FALLBACK, |
32
|
|
|
|
|
|
|
wal_mode => 1, |
33
|
|
|
|
|
|
|
}; |
34
|
|
|
|
|
|
|
}; |
35
|
|
|
|
|
|
|
has 'parent'; |
36
|
|
|
|
|
|
|
|
37
|
21
|
100
|
|
21
|
1
|
33096
|
sub new { @_ > 1 ? shift->SUPER::new->from_string(@_) : shift->SUPER::new } |
38
|
|
|
|
|
|
|
|
39
|
123
|
|
|
123
|
1
|
115567
|
sub db { $_[0]->database_class->new(dbh => $_[0]->_prepare, sqlite => $_[0]) } |
40
|
|
|
|
|
|
|
|
41
|
5
|
|
|
5
|
1
|
44
|
sub from_filename { shift->from_string(_url_from_file(shift, shift)) } |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
sub from_string { |
44
|
14
|
|
|
14
|
1
|
90
|
my ($self, $str) = @_; |
45
|
14
|
50
|
|
|
|
49
|
return $self unless $str; |
46
|
14
|
100
|
100
|
|
|
286
|
return $self->parent($str) if blessed $str and $str->isa('Mojo::SQLite'); |
47
|
|
|
|
|
|
|
|
48
|
12
|
|
|
|
|
50
|
my $url = URI->new($str); |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# Options |
51
|
12
|
|
|
|
|
2140
|
my %options = $url->query_form; |
52
|
12
|
|
|
|
|
595
|
$url->query(undef); |
53
|
|
|
|
|
|
|
# don't set default string_mode if sqlite_unicode legacy option is set |
54
|
12
|
100
|
|
|
|
191
|
delete $self->options->{sqlite_string_mode} if exists $options{sqlite_unicode}; |
55
|
12
|
|
|
|
|
34
|
@{$self->options}{keys %options} = values %options; |
|
12
|
|
|
|
|
36
|
|
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
# Parse URL based on scheme |
58
|
12
|
100
|
|
|
|
81
|
$url->scheme('file') unless $url->has_recognized_scheme; |
59
|
12
|
100
|
|
|
|
482
|
if ($url->scheme eq 'file') { |
|
|
100
|
|
|
|
|
|
60
|
5
|
|
|
|
|
130
|
$url = _url_from_file($url->file); |
61
|
|
|
|
|
|
|
} elsif ($url->scheme ne 'db') { |
62
|
2
|
|
|
|
|
80
|
$url = URI::db->new($url); |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
12
|
50
|
66
|
|
|
439
|
croak qq{Invalid SQLite connection string "$str"} |
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
66
|
|
|
|
|
|
|
unless $url->has_recognized_engine and $url->canonical_engine eq 'sqlite' |
67
|
|
|
|
|
|
|
and (($url->host // '') eq '' or $url->host eq 'localhost'); |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
# Temp database file |
70
|
11
|
50
|
|
|
|
645
|
$url->dbname($self->_tempfile) if $url->dbname eq ':temp:'; |
71
|
|
|
|
|
|
|
|
72
|
11
|
|
|
|
|
724
|
return $self->dsn($url->dbi_dsn); |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub _dequeue { |
76
|
123
|
|
|
123
|
|
166
|
my $self = shift; |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# Fork-safety |
79
|
123
|
100
|
66
|
|
|
684
|
delete @$self{qw(pid queue)} unless ($self->{pid} //= $$) eq $$; |
80
|
|
|
|
|
|
|
|
81
|
123
|
50
|
|
|
|
159
|
while (my $dbh = shift @{$self->{queue} || []}) { return $dbh if $dbh->ping } |
|
96
|
100
|
|
|
|
396
|
|
|
123
|
|
|
|
|
385
|
|
82
|
|
|
|
|
|
|
|
83
|
27
|
|
33
|
|
|
73
|
my $dbh = DBI->connect($self->dsn, undef, undef, $self->options) |
84
|
0
|
|
|
|
|
0
|
// croak "DBI connection to @{[$self->dsn]} failed: $DBI::errstr"; # RaiseError disabled |
85
|
27
|
|
|
|
|
18706
|
$dbh->sqlite_db_config(SQLITE_DBCONFIG_DQS_DDL, 0); |
86
|
27
|
|
|
|
|
82
|
$dbh->sqlite_db_config(SQLITE_DBCONFIG_DQS_DML, 0); |
87
|
27
|
100
|
66
|
|
|
81
|
if ($self->options->{wal_mode} and !$self->options->{no_wal}) { |
88
|
26
|
|
|
|
|
436
|
$dbh->do('pragma journal_mode=WAL'); |
89
|
26
|
|
|
|
|
107275
|
$dbh->do('pragma synchronous=NORMAL'); |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
# Cache the last insert rowid on inserts |
93
|
27
|
|
|
|
|
751
|
weaken(my $weakdbh = $dbh); |
94
|
|
|
|
|
|
|
$dbh->sqlite_update_hook(sub { |
95
|
43
|
100
|
|
43
|
|
1126
|
$weakdbh->{private_mojo_last_insert_id} = $_[3] if $_[0] == DBD::SQLite::INSERT; |
96
|
27
|
|
|
|
|
220
|
}); |
97
|
|
|
|
|
|
|
|
98
|
27
|
|
|
|
|
168
|
$self->emit(connection => $dbh); |
99
|
|
|
|
|
|
|
|
100
|
27
|
|
|
|
|
493
|
return $dbh; |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
sub _enqueue { |
104
|
129
|
|
|
129
|
|
225
|
my ($self, $dbh) = @_; |
105
|
|
|
|
|
|
|
|
106
|
129
|
100
|
|
|
|
283
|
if (my $parent = $self->parent) { return $parent->_enqueue($dbh) } |
|
6
|
|
|
|
|
33
|
|
107
|
|
|
|
|
|
|
|
108
|
123
|
|
100
|
|
|
597
|
my $queue = $self->{queue} ||= []; |
109
|
123
|
100
|
|
|
|
882
|
push @$queue, $dbh if $dbh->{Active}; |
110
|
123
|
|
|
|
|
405
|
shift @$queue while @$queue > $self->max_connections; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub _prepare { |
114
|
129
|
|
|
129
|
|
605
|
my $self = shift; |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
# Automatic migrations |
117
|
|
|
|
|
|
|
++$self->{migrated} and $self->migrations->migrate |
118
|
129
|
100
|
33
|
|
|
408
|
if !$self->{migrated} && $self->auto_migrate; |
|
|
|
100
|
|
|
|
|
119
|
|
|
|
|
|
|
|
120
|
129
|
|
|
|
|
632
|
my $parent = $self->parent; |
121
|
129
|
100
|
|
|
|
525
|
return $parent ? $parent->_prepare : $self->_dequeue; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
7
|
|
|
7
|
|
57
|
sub _tempfile { catfile(shift->{tempdir} = File::Temp->newdir, 'sqlite.db') } |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub _url_from_file { |
127
|
17
|
|
|
17
|
|
6720
|
my $url = URI::db->new; |
128
|
17
|
|
|
|
|
1908
|
$url->engine('sqlite'); |
129
|
17
|
|
|
|
|
7133
|
$url->dbname(shift); |
130
|
17
|
100
|
|
|
|
1411
|
if (my $options = shift) { $url->query_form($options) } |
|
1
|
|
|
|
|
9
|
|
131
|
17
|
|
|
|
|
161
|
return $url; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
1; |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=head1 NAME |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
Mojo::SQLite - A tiny Mojolicious wrapper for SQLite |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=head1 SYNOPSIS |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
use Mojo::SQLite; |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
# Select the library version |
145
|
|
|
|
|
|
|
my $sql = Mojo::SQLite->new('sqlite:test.db'); |
146
|
|
|
|
|
|
|
say $sql->db->query('select sqlite_version() as version')->hash->{version}; |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# Use migrations to create a table |
149
|
|
|
|
|
|
|
$sql->migrations->name('my_names_app')->from_string(<migrate; |
150
|
|
|
|
|
|
|
-- 1 up |
151
|
|
|
|
|
|
|
create table names (id integer primary key autoincrement, name text); |
152
|
|
|
|
|
|
|
-- 1 down |
153
|
|
|
|
|
|
|
drop table names; |
154
|
|
|
|
|
|
|
EOF |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
# Use migrations to drop and recreate the table |
157
|
|
|
|
|
|
|
$sql->migrations->migrate(0)->migrate; |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# Get a database handle from the cache for multiple queries |
160
|
|
|
|
|
|
|
my $db = $sql->db; |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# Use SQL::Abstract to generate simple CRUD queries for you |
163
|
|
|
|
|
|
|
$db->insert('names', {name => 'Isabel'}); |
164
|
|
|
|
|
|
|
my $id = $db->select('names', ['id'], {name => 'Isabel'})->hash->{id}; |
165
|
|
|
|
|
|
|
$db->update('names', {name => 'Bel'}, {id => $id}); |
166
|
|
|
|
|
|
|
$db->delete('names', {name => 'Bel'}); |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
# Insert a few rows in a transaction with SQL and placeholders |
169
|
|
|
|
|
|
|
eval { |
170
|
|
|
|
|
|
|
my $tx = $db->begin; |
171
|
|
|
|
|
|
|
$db->query('insert into names (name) values (?)', 'Sara'); |
172
|
|
|
|
|
|
|
$db->query('insert into names (name) values (?)', 'Stefan'); |
173
|
|
|
|
|
|
|
$tx->commit; |
174
|
|
|
|
|
|
|
}; |
175
|
|
|
|
|
|
|
say $@ if $@; |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# Insert another row with SQL::Abstract and return the generated id |
178
|
|
|
|
|
|
|
say $db->insert('names', {name => 'Daniel'})->last_insert_id; |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
# JSON roundtrip |
181
|
|
|
|
|
|
|
say $db->query('select ? as foo', {json => {bar => 'baz'}}) |
182
|
|
|
|
|
|
|
->expand(json => 'foo')->hash->{foo}{bar}; |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
# Select one row at a time |
185
|
|
|
|
|
|
|
my $results = $db->query('select * from names'); |
186
|
|
|
|
|
|
|
while (my $next = $results->hash) { |
187
|
|
|
|
|
|
|
say $next->{name}; |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
# Select all rows with SQL::Abstract |
191
|
|
|
|
|
|
|
say $_->{name} for $db->select('names')->hashes->each; |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=head1 DESCRIPTION |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
L is a tiny wrapper around L that makes |
196
|
|
|
|
|
|
|
L a lot of fun to use with the |
197
|
|
|
|
|
|
|
L real-time web framework. Use all |
198
|
|
|
|
|
|
|
L SQLite has to offer, generate CRUD |
199
|
|
|
|
|
|
|
queries from data structures, and manage your database schema with migrations. |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=head1 BASICS |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
Database and statement handles are cached automatically, so they can be reused |
204
|
|
|
|
|
|
|
transparently to increase performance. And you can handle connection timeouts |
205
|
|
|
|
|
|
|
gracefully by holding on to them only for short amounts of time. |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
use Mojolicious::Lite; |
208
|
|
|
|
|
|
|
use Mojo::SQLite; |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
helper sqlite => sub { state $sql = Mojo::SQLite->new('sqlite:test.db') }; |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
get '/' => sub ($c) { |
213
|
|
|
|
|
|
|
my $db = $c->sqlite->db; |
214
|
|
|
|
|
|
|
$c->render(json => $db->query(q{select datetime('now','localtime') as now})->hash); |
215
|
|
|
|
|
|
|
}; |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
app->start; |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
In this example application, we create a C helper to store a |
220
|
|
|
|
|
|
|
L object. Our action calls that helper and uses the method |
221
|
|
|
|
|
|
|
L to dequeue a L object from the |
222
|
|
|
|
|
|
|
connection pool. Then we use the method L to |
223
|
|
|
|
|
|
|
execute an L |
224
|
|
|
|
|
|
|
statement, which returns a L object. And finally we call |
225
|
|
|
|
|
|
|
the method L to retrieve the first row as a hash |
226
|
|
|
|
|
|
|
reference. |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
All I/O and queries are performed synchronously, and SQLite's default journal |
229
|
|
|
|
|
|
|
mode only supports concurrent reads from multiple processes while the database |
230
|
|
|
|
|
|
|
is not being written. The "Write-Ahead Log" journal mode allows multiple |
231
|
|
|
|
|
|
|
processes to read and write concurrently to the same database file (but only |
232
|
|
|
|
|
|
|
one can write at a time). WAL mode is enabled by the C option, |
233
|
|
|
|
|
|
|
currently enabled by default, and persists when opening that same database in |
234
|
|
|
|
|
|
|
the future. |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
# Performed concurrently (concurrent with writing only with WAL journaling mode) |
237
|
|
|
|
|
|
|
my $pid = fork || die $!; |
238
|
|
|
|
|
|
|
say $sql->db->query(q{select datetime('now','localtime') as time})->hash->{time}; |
239
|
|
|
|
|
|
|
exit unless $pid; |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
The C option prevents WAL mode from being enabled in new databases but |
242
|
|
|
|
|
|
|
doesn't affect databases where it has already been enabled. C may not |
243
|
|
|
|
|
|
|
be set by default in a future release. See L and |
244
|
|
|
|
|
|
|
L for more information. |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
The L
|
247
|
|
|
|
|
|
|
|https://sqlite.org/quirks.html#double_quoted_string_literals_are_accepted> is |
248
|
|
|
|
|
|
|
disabled for all connections since Mojo::SQLite 3.003; use single quotes for |
249
|
|
|
|
|
|
|
string literals and double quotes for identifiers, as is normally recommended. |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
All cached database handles will be reset automatically if a new process has |
252
|
|
|
|
|
|
|
been forked, this allows multiple processes to share the same L |
253
|
|
|
|
|
|
|
object safely. |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
Any database errors will throw an exception as C is automatically |
256
|
|
|
|
|
|
|
enabled, so use C or L to catch them. This makes transactions |
257
|
|
|
|
|
|
|
with L easy. |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
While passing a file path of C<:memory:> (or a custom L"dsn"> with |
260
|
|
|
|
|
|
|
C) will create a temporary database, in-memory databases cannot be |
261
|
|
|
|
|
|
|
shared between connections, so subsequent calls to L"db"> may return |
262
|
|
|
|
|
|
|
connections to completely different databases. For a temporary database that |
263
|
|
|
|
|
|
|
can be shared between connections and processes, pass a file path of C<:temp:> |
264
|
|
|
|
|
|
|
to store the database in a temporary directory (this is the default), or |
265
|
|
|
|
|
|
|
consider constructing a temporary directory yourself with L if you |
266
|
|
|
|
|
|
|
need to reuse the filename. A temporary directory allows SQLite to create |
267
|
|
|
|
|
|
|
L safely. |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
use File::Spec::Functions 'catfile'; |
270
|
|
|
|
|
|
|
use File::Temp; |
271
|
|
|
|
|
|
|
use Mojo::SQLite; |
272
|
|
|
|
|
|
|
my $tempdir = File::Temp->newdir; # Deleted when object goes out of scope |
273
|
|
|
|
|
|
|
my $tempfile = catfile $tempdir, 'test.db'; |
274
|
|
|
|
|
|
|
my $sql = Mojo::SQLite->new->from_filename($tempfile); |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
=head1 EXAMPLES |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
This distribution also contains a well-structured example |
279
|
|
|
|
|
|
|
L |
280
|
|
|
|
|
|
|
you can use for inspiration. This application shows how to apply the MVC design |
281
|
|
|
|
|
|
|
pattern in practice. |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
=head1 EVENTS |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
L inherits all events from L and can emit the |
286
|
|
|
|
|
|
|
following new ones. |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
=head2 connection |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
$sql->on(connection => sub ($sql, $dbh) { |
291
|
|
|
|
|
|
|
$dbh->do('pragma journal_size_limit=1000000'); |
292
|
|
|
|
|
|
|
}); |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
Emitted when a new database connection has been established. |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
L implements the following attributes. |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
=head2 abstract |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
my $abstract = $sql->abstract; |
303
|
|
|
|
|
|
|
$sql = $sql->abstract(SQL::Abstract->new); |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
L object used to generate CRUD queries for |
306
|
|
|
|
|
|
|
L, defaults to a L object with |
307
|
|
|
|
|
|
|
C set to C<.> and C set to C<">. |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
# Generate WHERE clause and bind values |
310
|
|
|
|
|
|
|
my($stmt, @bind) = $sql->abstract->where({foo => 'bar', baz => 'yada'}); |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
L provides additional features to the L |
313
|
|
|
|
|
|
|
query methods in L such as C<-json> and |
314
|
|
|
|
|
|
|
C/C. The C feature is not applicable to SQLite queries. |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
$sql->db->select(['some_table', ['other_table', foo_id => 'id']], |
317
|
|
|
|
|
|
|
['foo', [bar => 'baz'], \q{datetime('now') as dt}], |
318
|
|
|
|
|
|
|
{foo => 'value'}, |
319
|
|
|
|
|
|
|
{order_by => 'foo', limit => 10, offset => 5, group_by => ['foo'], having => {baz => 'value'}}); |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
# Upsert supported since SQLite 3.24.0 |
322
|
|
|
|
|
|
|
$sql->db->insert('some_table', {name => $name, value => $value}, |
323
|
|
|
|
|
|
|
{on_conflict => [name => {value => \'"excluded"."value"'}]}); |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
=head2 auto_migrate |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
my $bool = $sql->auto_migrate; |
328
|
|
|
|
|
|
|
$sql = $sql->auto_migrate($bool); |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
Automatically migrate to the latest database schema with L"migrations">, as |
331
|
|
|
|
|
|
|
soon as L"db"> has been called for the first time. |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
=head2 database_class |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
my $class = $sql->database_class; |
336
|
|
|
|
|
|
|
$sql = $sql->database_class('MyApp::Database'); |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
Class to be used by L"db">, defaults to L. Note that |
339
|
|
|
|
|
|
|
this class needs to have already been loaded before L"db"> is called. |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
=head2 dsn |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
my $dsn = $sql->dsn; |
344
|
|
|
|
|
|
|
$sql = $sql->dsn('dbi:SQLite:uri=file:foo.db'); |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
Data source name, defaults to C followed by a path to a |
347
|
|
|
|
|
|
|
temporary file. |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
=head2 max_connections |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
my $max = $sql->max_connections; |
352
|
|
|
|
|
|
|
$sql = $sql->max_connections(3); |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
Maximum number of idle database handles to cache for future use, defaults to |
355
|
|
|
|
|
|
|
C<1>. |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
=head2 migrations |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
my $migrations = $sql->migrations; |
360
|
|
|
|
|
|
|
$sql = $sql->migrations(Mojo::SQLite::Migrations->new); |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
L object you can use to change your database schema |
363
|
|
|
|
|
|
|
more easily. |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
# Load migrations from file and migrate to latest version |
366
|
|
|
|
|
|
|
$sql->migrations->from_file('/home/dbook/migrations.sql')->migrate; |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
=head2 options |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
my $options = $sql->options; |
371
|
|
|
|
|
|
|
$sql = $sql->options({AutoCommit => 1, RaiseError => 1}); |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
Options for database handles, defaults to setting C to |
374
|
|
|
|
|
|
|
C, setting C, |
375
|
|
|
|
|
|
|
C and C, and deactivating C. |
376
|
|
|
|
|
|
|
Note that C and C are considered mandatory, so |
377
|
|
|
|
|
|
|
deactivating them would be very dangerous. See |
378
|
|
|
|
|
|
|
L and |
379
|
|
|
|
|
|
|
L for more information on available |
380
|
|
|
|
|
|
|
options. |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
=head2 parent |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
my $parent = $sql->parent; |
385
|
|
|
|
|
|
|
$sql = $sql->parent(Mojo::SQLite->new); |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
Another L object to use for connection management, instead of |
388
|
|
|
|
|
|
|
establishing and caching our own database connections. |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
=head1 METHODS |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
L inherits all methods from L and implements |
393
|
|
|
|
|
|
|
the following new ones. |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
=head2 new |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
my $sql = Mojo::SQLite->new; |
398
|
|
|
|
|
|
|
my $sql = Mojo::SQLite->new('file:test.db); |
399
|
|
|
|
|
|
|
my $sql = Mojo::SQLite->new('sqlite:test.db'); |
400
|
|
|
|
|
|
|
my $sql = Mojo::SQLite->new(Mojo::SQLite->new); |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
Construct a new L object and parse connection string with |
403
|
|
|
|
|
|
|
L"from_string"> if necessary. |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
# Customize configuration further |
406
|
|
|
|
|
|
|
my $sql = Mojo::SQLite->new->dsn('dbi:SQLite:dbname=test.db'); |
407
|
|
|
|
|
|
|
my $sql = Mojo::SQLite->new->dsn('dbi:SQLite:uri=file:test.db?mode=memory'); |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
# Pass filename directly |
410
|
|
|
|
|
|
|
my $sql = Mojo::SQLite->new->from_filename($filename); |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
=head2 db |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
my $db = $sql->db; |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
Get a database object based on L"database_class"> (which is usually |
417
|
|
|
|
|
|
|
L) for a cached or newly established database |
418
|
|
|
|
|
|
|
connection. The L database handle will be automatically cached |
419
|
|
|
|
|
|
|
again when that object is destroyed, so you can handle problems like connection |
420
|
|
|
|
|
|
|
timeouts gracefully by holding on to it only for short amounts of time. |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
# Add up all the money |
423
|
|
|
|
|
|
|
say $sql->db->select('accounts') |
424
|
|
|
|
|
|
|
->hashes->reduce(sub { $a->{money} + $b->{money} }); |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
=head2 from_filename |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
$sql = $sql->from_filename('C:\\Documents and Settings\\foo & bar.db', $options); |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
Parse database filename directly. Unlike L"from_string">, the filename is |
431
|
|
|
|
|
|
|
parsed as a local filename and not a URL. A hashref of L"options"> may be |
432
|
|
|
|
|
|
|
passed as the second argument. |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
# Absolute filename |
435
|
|
|
|
|
|
|
$sql->from_filename('/home/fred/data.db'); |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
# Relative to current directory |
438
|
|
|
|
|
|
|
$sql->from_filename('data.db'); |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
# Temporary file database (default) |
441
|
|
|
|
|
|
|
$sql->from_filename(':temp:'); |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
# In-memory temporary database (single connection only) |
444
|
|
|
|
|
|
|
my $db = $sql->from_filename(':memory:')->db; |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
# Additional options |
447
|
|
|
|
|
|
|
$sql->from_filename($filename, { PrintError => 1 }); |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
# Readonly connection without WAL mode |
450
|
|
|
|
|
|
|
$sql->from_filename($filename, { ReadOnly => 1, no_wal => 1 }); |
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
# Strict unicode strings and WAL mode |
453
|
|
|
|
|
|
|
use DBD::SQLite::Constants ':dbd_sqlite_string_mode'; |
454
|
|
|
|
|
|
|
$sql->from_filename($filename, { sqlite_string_mode => DBD_SQLITE_STRING_MODE_UNICODE_STRICT, wal_mode => 1 }); |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
=head2 from_string |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
$sql = $sql->from_string('test.db'); |
459
|
|
|
|
|
|
|
$sql = $sql->from_string('file:test.db'); |
460
|
|
|
|
|
|
|
$sql = $sql->from_string('file:///C:/foo/bar.db'); |
461
|
|
|
|
|
|
|
$sql = $sql->from_string('sqlite:C:%5Cfoo%5Cbar.db'); |
462
|
|
|
|
|
|
|
$sql = $sql->from_string(Mojo::SQLite->new); |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
Parse configuration from connection string or use another L |
465
|
|
|
|
|
|
|
object as L"parent">. Connection strings are parsed as URLs, so you should |
466
|
|
|
|
|
|
|
construct them using a module like L, L, or L. |
467
|
|
|
|
|
|
|
For portability on non-Unix-like systems, either construct the URL with the |
468
|
|
|
|
|
|
|
C scheme, or use L to construct a URL with the C |
469
|
|
|
|
|
|
|
scheme. A URL with no scheme will be parsed as a C URL, and C URLs |
470
|
|
|
|
|
|
|
are parsed according to the current operating system. If specified, the |
471
|
|
|
|
|
|
|
hostname must be C. If the URL has a query string, it will be parsed |
472
|
|
|
|
|
|
|
and applied to L"options">. |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
# Absolute filename |
475
|
|
|
|
|
|
|
$sql->from_string('sqlite:////home/fred/data.db'); |
476
|
|
|
|
|
|
|
$sql->from_string('sqlite://localhost//home/fred/data.db'); |
477
|
|
|
|
|
|
|
$sql->from_string('sqlite:/home/fred/data.db'); |
478
|
|
|
|
|
|
|
$sql->from_string('file:///home/fred/data.db'); |
479
|
|
|
|
|
|
|
$sql->from_string('file://localhost/home/fred/data.db'); |
480
|
|
|
|
|
|
|
$sql->from_string('file:/home/fred/data.db'); |
481
|
|
|
|
|
|
|
$sql->from_string('///home/fred/data.db'); |
482
|
|
|
|
|
|
|
$sql->from_string('//localhost/home/fred/data.db'); |
483
|
|
|
|
|
|
|
$sql->from_string('/home/fred/data.db'); |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
# Relative to current directory |
486
|
|
|
|
|
|
|
$sql->from_string('sqlite:data.db'); |
487
|
|
|
|
|
|
|
$sql->from_string('file:data.db'); |
488
|
|
|
|
|
|
|
$sql->from_string('data.db'); |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
# Connection string must be a valid URL |
491
|
|
|
|
|
|
|
$sql->from_string(Mojo::URL->new->scheme('sqlite')->path($filename)); |
492
|
|
|
|
|
|
|
$sql->from_string(URI::db->new->Mojo::Base::tap(engine => 'sqlite')->Mojo::Base::tap(dbname => $filename)); |
493
|
|
|
|
|
|
|
$sql->from_string(URI::file->new($filename)); |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
# Temporary file database (default) |
496
|
|
|
|
|
|
|
$sql->from_string(':temp:'); |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
# In-memory temporary database (single connection only) |
499
|
|
|
|
|
|
|
my $db = $sql->from_string(':memory:')->db; |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
# Additional options |
502
|
|
|
|
|
|
|
$sql->from_string('data.db?PrintError=1&sqlite_allow_multiple_statements=1'); |
503
|
|
|
|
|
|
|
$sql->from_string(Mojo::URL->new->scheme('sqlite')->path($filename)->query(sqlite_see_if_its_a_number => 1)); |
504
|
|
|
|
|
|
|
$sql->from_string(URI::file->new($filename)->Mojo::Base::tap(query_form => {PrintError => 1})); |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
# Readonly connection without WAL mode |
507
|
|
|
|
|
|
|
$sql->from_string('data.db?ReadOnly=1&no_wal=1'); |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
# String unicode strings and WAL mode |
510
|
|
|
|
|
|
|
use DBD::SQLite::Constants ':dbd_sqlite_string_mode'; |
511
|
|
|
|
|
|
|
$sql->from_string(Mojo::URL->new->scheme('sqlite')->path('data.db') |
512
|
|
|
|
|
|
|
->query(sqlite_string_mode => DBD_SQLITE_STRING_MODE_UNICODE_STRICT, wal_mode => 1)); |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
=head1 DEBUGGING |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
You can set the C environment variable to get some advanced |
517
|
|
|
|
|
|
|
diagnostics information printed by L. |
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
DBI_TRACE=1 |
520
|
|
|
|
|
|
|
DBI_TRACE=15 |
521
|
|
|
|
|
|
|
DBI_TRACE=SQL |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
=head1 REFERENCE |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
This is the class hierarchy of the L distribution. |
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
=over 2 |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
=item * L |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
=item * L |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
=item * L |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
=item * L |
536
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
=item * L |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
=back |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
=head1 BUGS |
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
Report any issues on the public bugtracker. |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
=head1 AUTHOR |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
Dan Book, C |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
=head1 CREDITS |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
Sebastian Riedel, author of L, which this distribution is based on. |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
Copyright 2015, Dan Book. |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
This library is free software; you may redistribute it and/or modify it under |
558
|
|
|
|
|
|
|
the terms of the Artistic License version 2.0. |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
=head1 SEE ALSO |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
L, L, L |