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