This file is indexed.

/usr/share/perl5/DBIx/Class/Storage/DBI/SQLite.pm is in libdbix-class-perl 0.082840-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
package DBIx::Class::Storage::DBI::SQLite;

use strict;
use warnings;

use base qw/DBIx::Class::Storage::DBI/;
use mro 'c3';

use SQL::Abstract 'is_plain_value';
use DBIx::Class::_Util qw(modver_gt_or_eq sigwarn_silencer);
use DBIx::Class::Carp;
use Try::Tiny;
use namespace::clean;

__PACKAGE__->sql_maker_class('DBIx::Class::SQLMaker::SQLite');
__PACKAGE__->sql_limit_dialect ('LimitOffset');
__PACKAGE__->sql_quote_char ('"');
__PACKAGE__->datetime_parser_type ('DateTime::Format::SQLite');

=head1 NAME

DBIx::Class::Storage::DBI::SQLite - Automatic primary key class for SQLite

=head1 SYNOPSIS

  # In your table classes
  use base 'DBIx::Class::Core';
  __PACKAGE__->set_primary_key('id');

=head1 DESCRIPTION

This class implements autoincrements for SQLite.

=head2 Known Issues

=over

=item RT79576

 NOTE - This section applies to you only if ALL of these are true:

  * You are or were using DBD::SQLite with a version lesser than 1.38_01

  * You are or were using DBIx::Class versions between 0.08191 and 0.08209
    (inclusive) or between 0.08240-TRIAL and 0.08242-TRIAL (also inclusive)

  * You use objects with overloaded stringification and are feeding them
    to DBIC CRUD methods directly

An unfortunate chain of events led to DBIx::Class silently hitting the problem
described in L<RT#79576|https://rt.cpan.org/Public/Bug/Display.html?id=79576>.

In order to trigger the bug condition one needs to supply B<more than one>
bind value that is an object with overloaded stringification (numification
is not relevant, only stringification is). When this is the case the internal
DBIx::Class call to C<< $sth->bind_param >> would be executed in a way that
triggers the above-mentioned DBD::SQLite bug. As a result all the logs and
tracers will contain the expected values, however SQLite will receive B<all>
these bind positions being set to the value of the B<last> supplied
stringifiable object.

Even if you upgrade DBIx::Class (which works around the bug starting from
version 0.08210) you may still have corrupted/incorrect data in your database.
DBIx::Class warned about this condition for several years, hoping to give
anyone affected sufficient notice of the potential issues. The warning was
removed in 2015/v0.082820.

=back

=head1 METHODS

=cut

sub backup {

  require File::Spec;
  require File::Copy;
  require POSIX;

  my ($self, $dir) = @_;
  $dir ||= './';

  ## Where is the db file?
  my $dsn = $self->_dbi_connect_info()->[0];

  my $dbname = $1 if($dsn =~ /dbname=([^;]+)/);
  if(!$dbname)
  {
    $dbname = $1 if($dsn =~ /^dbi:SQLite:(.+)$/i);
  }
  $self->throw_exception("Cannot determine name of SQLite db file")
    if(!$dbname || !-f $dbname);

#  print "Found database: $dbname\n";
#  my $dbfile = file($dbname);
  my ($vol, $dbdir, $file) = File::Spec->splitpath($dbname);
#  my $file = $dbfile->basename();
  $file = POSIX::strftime("%Y-%m-%d-%H_%M_%S", localtime()) . $file;
  $file = "B$file" while(-f $file);

  mkdir($dir) unless -f $dir;
  my $backupfile = File::Spec->catfile($dir, $file);

  my $res = File::Copy::copy($dbname, $backupfile);
  $self->throw_exception("Backup failed! ($!)") if(!$res);

  return $backupfile;
}

sub _exec_svp_begin {
  my ($self, $name) = @_;

  $self->_dbh->do("SAVEPOINT $name");
}

sub _exec_svp_release {
  my ($self, $name) = @_;

  $self->_dbh->do("RELEASE SAVEPOINT $name");
}

sub _exec_svp_rollback {
  my ($self, $name) = @_;

  $self->_dbh->do("ROLLBACK TO SAVEPOINT $name");

  # resync state for older DBD::SQLite (RT#67843)
  # https://github.com/DBD-SQLite/DBD-SQLite/commit/9b3cdbf
  if (
    ! modver_gt_or_eq('DBD::SQLite', '1.33')
      and
    $self->_dbh->FETCH('AutoCommit')
  ) {
    $self->_dbh->STORE('AutoCommit', 0);
    $self->_dbh->STORE('BegunWork', 1);
  }
}

sub _ping {
  my $self = shift;

  # Be extremely careful what we do here. SQLite is notoriously bad at
  # synchronizing its internal transaction state with {AutoCommit}
  # https://metacpan.org/source/ADAMK/DBD-SQLite-1.37/lib/DBD/SQLite.pm#L921
  # There is a function http://www.sqlite.org/c3ref/get_autocommit.html
  # but DBD::SQLite does not expose it (nor does it seem to properly use it)

  # Therefore only execute a "ping" when we have no other choice *AND*
  # scrutinize the thrown exceptions to make sure we are where we think we are
  my $dbh = $self->_dbh or return undef;
  return undef unless $dbh->FETCH('Active');
  return undef unless $dbh->ping;

  my $ping_fail;

  # older DBD::SQLite does not properly synchronize commit state between
  # the libsqlite and the $dbh
  unless (defined $DBD::SQLite::__DBIC_TXN_SYNC_SANE__) {
    $DBD::SQLite::__DBIC_TXN_SYNC_SANE__ = modver_gt_or_eq('DBD::SQLite', '1.38_02');
  }

  # fallback to travesty
  unless ($DBD::SQLite::__DBIC_TXN_SYNC_SANE__) {
    # since we do not have access to sqlite3_get_autocommit(), do a trick
    # to attempt to *safely* determine what state are we *actually* in.
    # FIXME
    # also using T::T here leads to bizarre leaks - will figure it out later
    my $really_not_in_txn = do {
      local $@;

      # older versions of DBD::SQLite do not properly detect multiline BEGIN/COMMIT
      # statements to adjust their {AutoCommit} state. Hence use such a statement
      # pair here as well, in order to escape from poking {AutoCommit} needlessly
      # https://rt.cpan.org/Public/Bug/Display.html?id=80087
      eval {
        # will fail instantly if already in a txn
        $dbh->do("-- multiline\nBEGIN");
        $dbh->do("-- multiline\nCOMMIT");
        1;
      } or do {
        ($@ =~ /transaction within a transaction/)
          ? 0
          : undef
        ;
      };
    };

    # if we were unable to determine this - we may very well be dead
    if (not defined $really_not_in_txn) {
      $ping_fail = 1;
    }
    # check the AC sync-state
    elsif ($really_not_in_txn xor $dbh->{AutoCommit}) {
      carp_unique (sprintf
        'Internal transaction state of handle %s (apparently %s a transaction) does not seem to '
      . 'match its AutoCommit attribute setting of %s - this is an indication of a '
      . 'potentially serious bug in your transaction handling logic',
        $dbh,
        $really_not_in_txn ? 'NOT in' : 'in',
        $dbh->{AutoCommit} ? 'TRUE' : 'FALSE',
      );

      # it is too dangerous to execute anything else in this state
      # assume everything works (safer - worst case scenario next statement throws)
      return 1;
    }
  }

  # do the actual test and return on no failure
  ( $ping_fail ||= ! try { $dbh->do('SELECT * FROM sqlite_master LIMIT 1'); 1 } )
    or return 1; # the actual RV of _ping()

  # ping failed (or so it seems) - need to do some cleanup
  # it is possible to have a proper "connection", and have "ping" return
  # false anyway (e.g. corrupted file). In such cases DBD::SQLite still
  # keeps the actual file handle open. We don't really want this to happen,
  # so force-close the handle via DBI itself
  #
  local $@; # so that we do not clobber the real error as set above
  eval { $dbh->disconnect }; # if it fails - it fails
  undef; # the actual RV of _ping()
}

sub deployment_statements {
  my $self = shift;
  my ($schema, $type, $version, $dir, $sqltargs, @rest) = @_;

  $sqltargs ||= {};

  if (
    ! exists $sqltargs->{producer_args}{sqlite_version}
      and
    my $dver = $self->_server_info->{normalized_dbms_version}
  ) {
    $sqltargs->{producer_args}{sqlite_version} = $dver;
  }

  $self->next::method($schema, $type, $version, $dir, $sqltargs, @rest);
}

sub bind_attribute_by_data_type {

  # According to http://www.sqlite.org/datatype3.html#storageclasses
  # all numeric types are dynamically allocated up to 8 bytes per
  # individual value
  # Thus it should be safe and non-wasteful to bind everything as
  # SQL_BIGINT and have SQLite deal with storage/comparisons however
  # it deems correct
  $_[1] =~ /^ (?: int(?:[1248]|eger)? | (?:tiny|small|medium|big)int ) $/ix
    ? DBI::SQL_BIGINT()
    : undef
  ;
}

# FIXME - what the flying fuck... work around RT#76395
# DBD::SQLite warns on binding >32 bit values with 32 bit IVs
sub _dbh_execute {
  if (
    (
      DBIx::Class::_ENV_::IV_SIZE < 8
        or
      DBIx::Class::_ENV_::OS_NAME eq 'MSWin32'
    )
      and
    ! defined $DBD::SQLite::__DBIC_CHECK_dbd_mishandles_bound_BIGINT
  ) {
    $DBD::SQLite::__DBIC_CHECK_dbd_mishandles_bound_BIGINT = (
      modver_gt_or_eq('DBD::SQLite', '1.37')
    ) ? 1 : 0;
  }

  local $SIG{__WARN__} = sigwarn_silencer( qr/
    \Qdatatype mismatch: bind\E \s (?:
      param \s+ \( \d+ \) \s+ [-+]? \d+ (?: \. 0*)? \Q as integer\E
        |
      \d+ \s type \s @{[ DBI::SQL_BIGINT() ]} \s as \s [-+]? \d+ (?: \. 0*)?
    )
  /x ) if (
    (
      DBIx::Class::_ENV_::IV_SIZE < 8
        or
      DBIx::Class::_ENV_::OS_NAME eq 'MSWin32'
    )
      and
    $DBD::SQLite::__DBIC_CHECK_dbd_mishandles_bound_BIGINT
  );

  shift->next::method(@_);
}

# DBD::SQLite (at least up to version 1.31 has a bug where it will
# non-fatally numify a string value bound as an integer, resulting
# in insertions of '0' into supposed-to-be-numeric fields
# Since this can result in severe data inconsistency, remove the
# bind attr if such a situation is detected
#
# FIXME - when a DBD::SQLite version is released that eventually fixes
# this situation (somehow) - no-op this override once a proper DBD
# version is detected
sub _dbi_attrs_for_bind {
  my ($self, $ident, $bind) = @_;

  my $bindattrs = $self->next::method($ident, $bind);

  if (! defined $DBD::SQLite::__DBIC_CHECK_dbd_can_bind_bigint_values) {
    $DBD::SQLite::__DBIC_CHECK_dbd_can_bind_bigint_values
      = modver_gt_or_eq('DBD::SQLite', '1.37') ? 1 : 0;
  }

  for my $i (0.. $#$bindattrs) {
    if (
      defined $bindattrs->[$i]
        and
      defined $bind->[$i][1]
        and
      grep { $bindattrs->[$i] eq $_ } (
        DBI::SQL_INTEGER(), DBI::SQL_TINYINT(), DBI::SQL_SMALLINT(), DBI::SQL_BIGINT()
      )
    ) {
      if ( $bind->[$i][1] !~ /^ [\+\-]? [0-9]+ (?: \. 0* )? $/x ) {
        carp_unique( sprintf (
          "Non-integer value supplied for column '%s' despite the integer datatype",
          $bind->[$i][0]{dbic_colname} || "# $i"
        ) );
        undef $bindattrs->[$i];
      }
      elsif (
        ! $DBD::SQLite::__DBIC_CHECK_dbd_can_bind_bigint_values
      ) {
        # unsigned 32 bit ints have a range of −2,147,483,648 to 2,147,483,647
        # alternatively expressed as the hexadecimal numbers below
        # the comparison math will come out right regardless of ivsize, since
        # we are operating within 31 bits
        # P.S. 31 because one bit is lost for the sign
        if ($bind->[$i][1] > 0x7fff_ffff or $bind->[$i][1] < -0x8000_0000) {
          carp_unique( sprintf (
            "An integer value occupying more than 32 bits was supplied for column '%s' "
          . 'which your version of DBD::SQLite (%s) can not bind properly so DBIC '
          . 'will treat it as a string instead, consider upgrading to at least '
          . 'DBD::SQLite version 1.37',
            $bind->[$i][0]{dbic_colname} || "# $i",
            DBD::SQLite->VERSION,
          ) );
          undef $bindattrs->[$i];
        }
        else {
          $bindattrs->[$i] = DBI::SQL_INTEGER()
        }
      }
    }
  }

  return $bindattrs;
}

=head2 connect_call_use_foreign_keys

Used as:

    on_connect_call => 'use_foreign_keys'

In L<connect_info|DBIx::Class::Storage::DBI/connect_info> to turn on foreign key
(including cascading) support for recent versions of SQLite and L<DBD::SQLite>.

Executes:

  PRAGMA foreign_keys = ON

See L<http://www.sqlite.org/foreignkeys.html> for more information.

=cut

sub connect_call_use_foreign_keys {
  my $self = shift;

  $self->_do_query(
    'PRAGMA foreign_keys = ON'
  );
}

=head1 FURTHER QUESTIONS?

Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.

=head1 COPYRIGHT AND LICENSE

This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
redistribute it and/or modify it under the same terms as the
L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.

=cut

1;