Fix multiple savepointing transactions on DBD::SQLite
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / SQLite.pm
CommitLineData
843f8ecd 1package DBIx::Class::Storage::DBI::SQLite;
2
3use strict;
4use warnings;
2ad62d97 5
6use base qw/DBIx::Class::Storage::DBI/;
7use mro 'c3';
8
04ab4eb1 9use DBIx::Class::_Util qw(modver_gt_or_eq sigwarn_silencer);
632d1e0f 10use DBIx::Class::Carp;
8d1fb3e2 11use Try::Tiny;
632d1e0f 12use namespace::clean;
13
d5dedbd6 14__PACKAGE__->sql_maker_class('DBIx::Class::SQLMaker::SQLite');
6a247f33 15__PACKAGE__->sql_limit_dialect ('LimitOffset');
2b8cc2f2 16__PACKAGE__->sql_quote_char ('"');
6f7a118e 17__PACKAGE__->datetime_parser_type ('DateTime::Format::SQLite');
09cedb88 18
2fa97c7d 19=head1 NAME
20
21DBIx::Class::Storage::DBI::SQLite - Automatic primary key class for SQLite
22
23=head1 SYNOPSIS
24
25 # In your table classes
26 use base 'DBIx::Class::Core';
27 __PACKAGE__->set_primary_key('id');
28
29=head1 DESCRIPTION
30
31This class implements autoincrements for SQLite.
32
75a1d824 33=head2 Known Issues
34
35=over
36
37=item RT79576
38
39 NOTE - This section applies to you only if ALL of these are true:
40
41 * You are or were using DBD::SQLite with a version lesser than 1.38_01
42
43 * You are or were using DBIx::Class versions between 0.08191 and 0.08209
44 (inclusive) or between 0.08240-TRIAL and 0.08242-TRIAL (also inclusive)
45
46 * You use objects with overloaded stringification and are feeding them
47 to DBIC CRUD methods directly
48
49An unfortunate chain of events led to DBIx::Class silently hitting the problem
50described in L<RT#79576|https://rt.cpan.org/Public/Bug/Display.html?id=79576>.
51
52In order to trigger the bug condition one needs to supply B<more than one>
4a0eed52 53bind value that is an object with overloaded stringification (numification
75a1d824 54is not relevant, only stringification is). When this is the case the internal
55DBIx::Class call to C<< $sth->bind_param >> would be executed in a way that
56triggers the above-mentioned DBD::SQLite bug. As a result all the logs and
57tracers will contain the expected values, however SQLite will receive B<all>
58these bind positions being set to the value of the B<last> supplied
59stringifiable object.
60
61Even if you upgrade DBIx::Class (which works around the bug starting from
62version 0.08210) you may still have corrupted/incorrect data in your database.
63DBIx::Class will currently detect when this condition (more than one
64stringifiable object in one CRUD call) is encountered and will issue a warning
65pointing to this section. This warning will be removed 2 years from now,
66around April 2015, You can disable it after you've audited your data by
67setting the C<DBIC_RT79576_NOWARN> environment variable. Note - the warning
4a0eed52 68is emitted only once per callsite per process and only when the condition in
69question is encountered. Thus it is very unlikely that your logsystem will be
75a1d824 70flooded as a result of this.
71
72=back
73
2fa97c7d 74=head1 METHODS
75
76=cut
77
357eb92c 78sub backup {
79
80 require File::Spec;
81 require File::Copy;
82 require POSIX;
83
8795fefb 84 my ($self, $dir) = @_;
85 $dir ||= './';
c9d2e0a2 86
87 ## Where is the db file?
12c9beea 88 my $dsn = $self->_dbi_connect_info()->[0];
c9d2e0a2 89
90 my $dbname = $1 if($dsn =~ /dbname=([^;]+)/);
91 if(!$dbname)
92 {
93 $dbname = $1 if($dsn =~ /^dbi:SQLite:(.+)$/i);
94 }
357eb92c 95 $self->throw_exception("Cannot determine name of SQLite db file")
c9d2e0a2 96 if(!$dbname || !-f $dbname);
97
98# print "Found database: $dbname\n";
79923569 99# my $dbfile = file($dbname);
8795fefb 100 my ($vol, $dbdir, $file) = File::Spec->splitpath($dbname);
79923569 101# my $file = $dbfile->basename();
357eb92c 102 $file = POSIX::strftime("%Y-%m-%d-%H_%M_%S", localtime()) . $file;
c9d2e0a2 103 $file = "B$file" while(-f $file);
8795fefb 104
105 mkdir($dir) unless -f $dir;
106 my $backupfile = File::Spec->catfile($dir, $file);
107
357eb92c 108 my $res = File::Copy::copy($dbname, $backupfile);
c9d2e0a2 109 $self->throw_exception("Backup failed! ($!)") if(!$res);
110
8795fefb 111 return $backupfile;
c9d2e0a2 112}
113
86a51471 114sub _exec_svp_begin {
115 my ($self, $name) = @_;
116
117 $self->_dbh->do("SAVEPOINT $name");
118}
119
120sub _exec_svp_release {
121 my ($self, $name) = @_;
122
123 $self->_dbh->do("RELEASE SAVEPOINT $name");
124}
125
126sub _exec_svp_rollback {
127 my ($self, $name) = @_;
128
398215b1 129 $self->_dbh->do("ROLLBACK TO SAVEPOINT $name");
130}
131
132# older SQLite has issues here too - both of these are in fact
133# completely benign warnings (or at least so say the tests)
134sub _exec_txn_rollback {
135 local $SIG{__WARN__} = sigwarn_silencer( qr/rollback ineffective/ )
136 unless $DBD::SQLite::__DBIC_TXN_SYNC_SANE__;
137
138 shift->next::method(@_);
139}
140
141sub _exec_txn_commit {
142 local $SIG{__WARN__} = sigwarn_silencer( qr/commit ineffective/ )
143 unless $DBD::SQLite::__DBIC_TXN_SYNC_SANE__;
86a51471 144
398215b1 145 shift->next::method(@_);
86a51471 146}
147
8d1fb3e2 148sub _ping {
149 my $self = shift;
2aeb3c7f 150
151 # Be extremely careful what we do here. SQLite is notoriously bad at
152 # synchronizing its internal transaction state with {AutoCommit}
153 # https://metacpan.org/source/ADAMK/DBD-SQLite-1.37/lib/DBD/SQLite.pm#L921
154 # There is a function http://www.sqlite.org/c3ref/get_autocommit.html
155 # but DBD::SQLite does not expose it (nor does it seem to properly use it)
156
157 # Therefore only execute a "ping" when we have no other choice *AND*
158 # scrutinize the thrown exceptions to make sure we are where we think we are
159 my $dbh = $self->_dbh or return undef;
160 return undef unless $dbh->FETCH('Active');
161 return undef unless $dbh->ping;
162
ab0b0a09 163 my $ping_fail;
164
165 # older DBD::SQLite does not properly synchronize commit state between
166 # the libsqlite and the $dbh
167 unless (defined $DBD::SQLite::__DBIC_TXN_SYNC_SANE__) {
b1dbf716 168 $DBD::SQLite::__DBIC_TXN_SYNC_SANE__ = modver_gt_or_eq('DBD::SQLite', '1.38_02');
ab0b0a09 169 }
2aeb3c7f 170
ab0b0a09 171 # fallback to travesty
172 unless ($DBD::SQLite::__DBIC_TXN_SYNC_SANE__) {
173 # since we do not have access to sqlite3_get_autocommit(), do a trick
174 # to attempt to *safely* determine what state are we *actually* in.
175 # FIXME
176 # also using T::T here leads to bizarre leaks - will figure it out later
177 my $really_not_in_txn = do {
178 local $@;
179
180 # older versions of DBD::SQLite do not properly detect multiline BEGIN/COMMIT
181 # statements to adjust their {AutoCommit} state. Hence use such a statement
182 # pair here as well, in order to escape from poking {AutoCommit} needlessly
183 # https://rt.cpan.org/Public/Bug/Display.html?id=80087
184 eval {
185 # will fail instantly if already in a txn
186 $dbh->do("-- multiline\nBEGIN");
187 $dbh->do("-- multiline\nCOMMIT");
188 1;
189 } or do {
190 ($@ =~ /transaction within a transaction/)
191 ? 0
192 : undef
193 ;
194 };
2aeb3c7f 195 };
2aeb3c7f 196
ab0b0a09 197 # if we were unable to determine this - we may very well be dead
198 if (not defined $really_not_in_txn) {
199 $ping_fail = 1;
200 }
201 # check the AC sync-state
202 elsif ($really_not_in_txn xor $dbh->{AutoCommit}) {
203 carp_unique (sprintf
204 'Internal transaction state of handle %s (apparently %s a transaction) does not seem to '
205 . 'match its AutoCommit attribute setting of %s - this is an indication of a '
206 . 'potentially serious bug in your transaction handling logic',
207 $dbh,
208 $really_not_in_txn ? 'NOT in' : 'in',
209 $dbh->{AutoCommit} ? 'TRUE' : 'FALSE',
210 );
211
212 # it is too dangerous to execute anything else in this state
213 # assume everything works (safer - worst case scenario next statement throws)
214 return 1;
215 }
2aeb3c7f 216 }
217
ab0b0a09 218 # do the actual test and return on no failure
219 ( $ping_fail ||= ! try { $dbh->do('SELECT * FROM sqlite_master LIMIT 1'); 1 } )
220 or return 1; # the actual RV of _ping()
221
222 # ping failed (or so it seems) - need to do some cleanup
223 # it is possible to have a proper "connection", and have "ping" return
224 # false anyway (e.g. corrupted file). In such cases DBD::SQLite still
225 # keeps the actual file handle open. We don't really want this to happen,
226 # so force-close the handle via DBI itself
227 #
4a0eed52 228 local $@; # so that we do not clobber the real error as set above
ab0b0a09 229 eval { $dbh->disconnect }; # if it fails - it fails
230 undef; # the actual RV of _ping()
8d1fb3e2 231}
232
2361982d 233sub deployment_statements {
96736321 234 my $self = shift;
2361982d 235 my ($schema, $type, $version, $dir, $sqltargs, @rest) = @_;
236
237 $sqltargs ||= {};
238
96736321 239 if (
240 ! exists $sqltargs->{producer_args}{sqlite_version}
241 and
242 my $dver = $self->_server_info->{normalized_dbms_version}
243 ) {
244 $sqltargs->{producer_args}{sqlite_version} = $dver;
6d766626 245 }
2361982d 246
f9b5239a 247 $sqltargs->{quote_identifiers}
248 = !!$self->sql_maker->_quote_chars
249 if ! exists $sqltargs->{quote_identifiers};
250
2361982d 251 $self->next::method($schema, $type, $version, $dir, $sqltargs, @rest);
252}
253
0e773352 254sub bind_attribute_by_data_type {
04ab4eb1 255
256 # According to http://www.sqlite.org/datatype3.html#storageclasses
257 # all numeric types are dynamically allocated up to 8 bytes per
258 # individual value
259 # Thus it should be safe and non-wasteful to bind everything as
260 # SQL_BIGINT and have SQLite deal with storage/comparisons however
261 # it deems correct
262 $_[1] =~ /^ (?: int(?:[1248]|eger)? | (?:tiny|small|medium|big)int ) $/ix
263 ? DBI::SQL_BIGINT()
0e773352 264 : undef
265 ;
266}
267
04ab4eb1 268# FIXME - what the flying fuck... work around RT#76395
269# DBD::SQLite warns on binding >32 bit values with 32 bit IVs
270sub _dbh_execute {
1363f0f5 271 if (
00882d2c 272 (
273 DBIx::Class::_ENV_::IV_SIZE < 8
274 or
275 DBIx::Class::_ENV_::OS_NAME eq 'MSWin32'
276 )
1363f0f5 277 and
278 ! defined $DBD::SQLite::__DBIC_CHECK_dbd_mishandles_bound_BIGINT
279 ) {
280 $DBD::SQLite::__DBIC_CHECK_dbd_mishandles_bound_BIGINT = (
281 modver_gt_or_eq('DBD::SQLite', '1.37')
282 ) ? 1 : 0;
04ab4eb1 283 }
284
1363f0f5 285 local $SIG{__WARN__} = sigwarn_silencer( qr/
286 \Qdatatype mismatch: bind\E \s (?:
287 param \s+ \( \d+ \) \s+ [-+]? \d+ (?: \. 0*)? \Q as integer\E
288 |
289 \d+ \s type \s @{[ DBI::SQL_BIGINT() ]} \s as \s [-+]? \d+ (?: \. 0*)?
290 )
00882d2c 291 /x ) if (
292 (
293 DBIx::Class::_ENV_::IV_SIZE < 8
294 or
295 DBIx::Class::_ENV_::OS_NAME eq 'MSWin32'
296 )
297 and
298 $DBD::SQLite::__DBIC_CHECK_dbd_mishandles_bound_BIGINT
299 );
1363f0f5 300
04ab4eb1 301 shift->next::method(@_);
302}
303
632d1e0f 304# DBD::SQLite (at least up to version 1.31 has a bug where it will
4a0eed52 305# non-fatally numify a string value bound as an integer, resulting
632d1e0f 306# in insertions of '0' into supposed-to-be-numeric fields
307# Since this can result in severe data inconsistency, remove the
4a0eed52 308# bind attr if such a situation is detected
632d1e0f 309#
310# FIXME - when a DBD::SQLite version is released that eventually fixes
4a0eed52 311# this situation (somehow) - no-op this override once a proper DBD
632d1e0f 312# version is detected
313sub _dbi_attrs_for_bind {
314 my ($self, $ident, $bind) = @_;
75a1d824 315
632d1e0f 316 my $bindattrs = $self->next::method($ident, $bind);
317
04ab4eb1 318 if (! defined $DBD::SQLite::__DBIC_CHECK_dbd_can_bind_bigint_values) {
215102b9 319 $DBD::SQLite::__DBIC_CHECK_dbd_can_bind_bigint_values
320 = modver_gt_or_eq('DBD::SQLite', '1.37') ? 1 : 0;
04ab4eb1 321 }
322
75a1d824 323 # an attempt to detect former effects of RT#79576, bug itself present between
324 # 0.08191 and 0.08209 inclusive (fixed in 0.08210 and higher)
325 my $stringifiable = 0;
326
49f7b6c7 327 for my $i (0.. $#$bindattrs) {
75a1d824 328
49f7b6c7 329 $stringifiable++ if ( length ref $bind->[$i][1] and overload::Method($bind->[$i][1], '""') );
75a1d824 330
632d1e0f 331 if (
49f7b6c7 332 defined $bindattrs->[$i]
632d1e0f 333 and
49f7b6c7 334 defined $bind->[$i][1]
632d1e0f 335 and
d830d9f4 336 grep { $bindattrs->[$i] eq $_ } (
337 DBI::SQL_INTEGER(), DBI::SQL_TINYINT(), DBI::SQL_SMALLINT(), DBI::SQL_BIGINT()
338 )
632d1e0f 339 ) {
04ab4eb1 340 if ( $bind->[$i][1] !~ /^ [\+\-]? [0-9]+ (?: \. 0* )? $/x ) {
341 carp_unique( sprintf (
342 "Non-integer value supplied for column '%s' despite the integer datatype",
343 $bind->[$i][0]{dbic_colname} || "# $i"
344 ) );
345 undef $bindattrs->[$i];
346 }
347 elsif (
348 ! $DBD::SQLite::__DBIC_CHECK_dbd_can_bind_bigint_values
215102b9 349 ) {
04ab4eb1 350 # unsigned 32 bit ints have a range of −2,147,483,648 to 2,147,483,647
351 # alternatively expressed as the hexadecimal numbers below
352 # the comparison math will come out right regardless of ivsize, since
353 # we are operating within 31 bits
354 # P.S. 31 because one bit is lost for the sign
215102b9 355 if ($bind->[$i][1] > 0x7fff_ffff or $bind->[$i][1] < -0x8000_0000) {
356 carp_unique( sprintf (
357 "An integer value occupying more than 32 bits was supplied for column '%s' "
358 . 'which your version of DBD::SQLite (%s) can not bind properly so DBIC '
359 . 'will treat it as a string instead, consider upgrading to at least '
360 . 'DBD::SQLite version 1.37',
361 $bind->[$i][0]{dbic_colname} || "# $i",
362 DBD::SQLite->VERSION,
363 ) );
364 undef $bindattrs->[$i];
365 }
366 else {
367 $bindattrs->[$i] = DBI::SQL_INTEGER()
368 }
04ab4eb1 369 }
632d1e0f 370 }
371 }
372
75a1d824 373 carp_unique(
374 'POSSIBLE *PAST* DATA CORRUPTION detected - see '
375 . 'DBIx::Class::Storage::DBI::SQLite/RT79576 or '
376 . 'http://v.gd/DBIC_SQLite_RT79576 for further details or set '
377 . '$ENV{DBIC_RT79576_NOWARN} to disable this warning. Trigger '
378 . 'condition encountered'
379 ) if (!$ENV{DBIC_RT79576_NOWARN} and $stringifiable > 1);
380
632d1e0f 381 return $bindattrs;
382}
383
732e4282 384=head2 connect_call_use_foreign_keys
385
386Used as:
387
388 on_connect_call => 'use_foreign_keys'
389
8384a713 390In L<connect_info|DBIx::Class::Storage::DBI/connect_info> to turn on foreign key
391(including cascading) support for recent versions of SQLite and L<DBD::SQLite>.
732e4282 392
393Executes:
394
8273e845 395 PRAGMA foreign_keys = ON
732e4282 396
397See L<http://www.sqlite.org/foreignkeys.html> for more information.
398
399=cut
400
401sub connect_call_use_foreign_keys {
402 my $self = shift;
403
404 $self->_do_query(
405 'PRAGMA foreign_keys = ON'
406 );
407}
408
843f8ecd 4091;
410
0c11ad0e 411=head1 AUTHOR AND CONTRIBUTORS
843f8ecd 412
0c11ad0e 413See L<AUTHOR|DBIx::Class/AUTHOR> and L<CONTRIBUTORS|DBIx::Class/CONTRIBUTORS> in DBIx::Class
843f8ecd 414
415=head1 LICENSE
416
417You may distribute this code under the same terms as Perl itself.
418
419=cut