File Coverage

blib/lib/DBD/SQLite.pm
Criterion Covered Total %
statement 352 372 94.6
branch 164 228 71.9
condition 92 147 62.5
subroutine 27 29 93.1
pod 0 1 0.0
total 635 777 81.7


line stmt bran cond sub pod time code
1             package DBD::SQLite;
2              
3 116     116   10604716 use 5.006;
  116         1786  
4 116     116   661 use strict;
  116         253  
  116         3043  
5 116     116   666 use DBI 1.57 ();
  116         2494  
  116         2078  
6 116     116   615 use XSLoader ();
  116         207  
  116         10606  
7              
8             our $VERSION = '1.73_01';
9              
10             # sqlite_version cache (set in the XS bootstrap)
11             our ($sqlite_version, $sqlite_version_number);
12              
13             # not sure if we still need these...
14             our ($err, $errstr);
15              
16             XSLoader::load('DBD::SQLite', $VERSION);
17              
18             # New or old API?
19 116     116   867 use constant NEWAPI => ($DBI::VERSION >= 1.608);
  116         261  
  116         22612  
20              
21             # global registry of collation functions, initialized with 2 builtins
22             our %COLLATION;
23             tie %COLLATION, 'DBD::SQLite::_WriteOnceHash';
24             $COLLATION{perl} = sub { $_[0] cmp $_[1] };
25 116     116   59656 $COLLATION{perllocale} = sub { use locale; $_[0] cmp $_[1] };
  116         73427  
  116         714  
26              
27             our $drh;
28             my $methods_are_installed = 0;
29              
30             sub driver {
31 110 50   110 0 485377 return $drh if $drh;
32              
33 110 50 50     1105 if (!$methods_are_installed && DBD::SQLite::NEWAPI ) {
34 110         594 DBI->setup_driver('DBD::SQLite');
35              
36 110         4630 DBD::SQLite::db->install_method('sqlite_last_insert_rowid');
37 110         7568 DBD::SQLite::db->install_method('sqlite_busy_timeout');
38 110         4274 DBD::SQLite::db->install_method('sqlite_create_function');
39 110         4094 DBD::SQLite::db->install_method('sqlite_create_aggregate');
40 110         3997 DBD::SQLite::db->install_method('sqlite_create_collation');
41 110         4176 DBD::SQLite::db->install_method('sqlite_collation_needed');
42 110         3889 DBD::SQLite::db->install_method('sqlite_progress_handler');
43 110         3910 DBD::SQLite::db->install_method('sqlite_commit_hook');
44 110         4304 DBD::SQLite::db->install_method('sqlite_rollback_hook');
45 110         4045 DBD::SQLite::db->install_method('sqlite_update_hook');
46 110         3925 DBD::SQLite::db->install_method('sqlite_set_authorizer');
47 110         4005 DBD::SQLite::db->install_method('sqlite_backup_from_file');
48 110         4303 DBD::SQLite::db->install_method('sqlite_backup_to_file');
49 110         4552 DBD::SQLite::db->install_method('sqlite_backup_from_dbh');
50 110         4694 DBD::SQLite::db->install_method('sqlite_backup_to_dbh');
51 110         4209 DBD::SQLite::db->install_method('sqlite_enable_load_extension');
52 110         4236 DBD::SQLite::db->install_method('sqlite_load_extension');
53 110         4163 DBD::SQLite::db->install_method('sqlite_register_fts3_perl_tokenizer');
54 110         4449 DBD::SQLite::db->install_method('sqlite_trace', { O => 0x0004 });
55 110         4683 DBD::SQLite::db->install_method('sqlite_profile', { O => 0x0004 });
56 110         4403 DBD::SQLite::db->install_method('sqlite_table_column_metadata', { O => 0x0004 });
57 110         4923 DBD::SQLite::db->install_method('sqlite_db_filename', { O => 0x0004 });
58 110         4360 DBD::SQLite::db->install_method('sqlite_db_status', { O => 0x0004 });
59 110         4926 DBD::SQLite::st->install_method('sqlite_st_status', { O => 0x0004 });
60 110         4405 DBD::SQLite::db->install_method('sqlite_create_module');
61 110         4059 DBD::SQLite::db->install_method('sqlite_limit');
62 110         3996 DBD::SQLite::db->install_method('sqlite_db_config');
63 110         3863 DBD::SQLite::db->install_method('sqlite_get_autocommit');
64 110         3953 DBD::SQLite::db->install_method('sqlite_txn_state');
65 110         5036 DBD::SQLite::db->install_method('sqlite_error_offset');
66              
67 110         3832 $methods_are_installed++;
68             }
69              
70 110         1442 $drh = DBI::_new_drh( "$_[0]::dr", {
71             Name => 'SQLite',
72             Version => $VERSION,
73             Attribution => 'DBD::SQLite by Matt Sergeant et al',
74             } );
75              
76 110         5826 return $drh;
77             }
78              
79             sub CLONE {
80 0     0   0 undef $drh;
81             }
82              
83              
84             package # hide from PAUSE
85             DBD::SQLite::dr;
86              
87             sub connect {
88 313     313   3655510 my ($drh, $dbname, $user, $auth, $attr) = @_;
89              
90             # Default PrintWarn to the value of $^W
91             # unless ( defined $attr->{PrintWarn} ) {
92             # $attr->{PrintWarn} = $^W ? 1 : 0;
93             # }
94              
95 313         1842 my $dbh = DBI::_new_dbh( $drh, {
96             Name => $dbname,
97             } );
98              
99 313         13400 my $real = $dbname;
100 313 100       1859 if ( $dbname =~ /=/ ) {
101 296         1403 foreach my $attrib ( split(/;/, $dbname) ) {
102 298         1116 my ($key, $value) = split(/=/, $attrib, 2);
103 298 100       2195 if ( $key =~ /^(?:db(?:name)?|database)$/ ) {
    100          
104 285         931 $real = $value;
105             } elsif ( $key eq 'uri' ) {
106 6         10 $real = $value;
107 6         23 $attr->{sqlite_open_flags} |= DBD::SQLite::OPEN_URI();
108             } else {
109 7         22 $attr->{$key} = $value;
110             }
111             }
112             }
113              
114 313 100       1350 if (my $flags = $attr->{sqlite_open_flags}) {
115 19 100       103 unless ($flags & (DBD::SQLite::OPEN_READONLY() | DBD::SQLite::OPEN_READWRITE())) {
116 13         40 $attr->{sqlite_open_flags} |= DBD::SQLite::OPEN_READWRITE() | DBD::SQLite::OPEN_CREATE();
117             }
118             }
119              
120             # To avoid unicode and long file name problems on Windows,
121             # convert to the shortname if the file (or parent directory) exists.
122 313 0 33     1948 if ( $^O =~ /MSWin32/ and $real ne ':memory:' and $real ne '' and $real !~ /^file:/ and !-f $real ) {
      33        
      0        
      0        
123 0         0 require File::Basename;
124 0         0 my ($file, $dir, $suffix) = File::Basename::fileparse($real);
125             # We are creating a new file.
126             # Does the directory it's in at least exist?
127 0 0       0 if ( -d $dir ) {
128 0         0 require Win32;
129 0         0 $real = join '', grep { defined } Win32::GetShortPathName($dir), $file, $suffix;
  0         0  
130             } else {
131             # SQLite can't do mkpath anyway.
132             # So let it go through as it and fail.
133             }
134             }
135              
136             # Hand off to the actual login function
137 313 100       112767 DBD::SQLite::db::_login($dbh, $real, $user, $auth, $attr) or return undef;
138              
139             # Register the on-demand collation installer, REGEXP function and
140             # perl tokenizer
141 307         1068 if ( DBD::SQLite::NEWAPI ) {
142 307         4812 $dbh->sqlite_collation_needed( \&install_collation );
143 307         4564 $dbh->sqlite_create_function( "REGEXP", 2, \®exp );
144 307         46350 $dbh->sqlite_register_fts3_perl_tokenizer();
145             } else {
146             $dbh->func( \&install_collation, "collation_needed" );
147             $dbh->func( "REGEXP", 2, \®exp, "create_function" );
148             $dbh->func( "register_fts3_perl_tokenizer" );
149             }
150              
151             # HACK: Since PrintWarn = 0 doesn't seem to actually prevent warnings
152             # in DBD::SQLite we set Warn to false if PrintWarn is false.
153              
154             # NOTE: According to the explanation by timbunce,
155             # "Warn is meant to report on bad practices or problems with
156             # the DBI itself (hence always on by default), while PrintWarn
157             # is meant to report warnings coming from the database."
158             # That is, if you want to disable an ineffective rollback warning
159             # etc (due to bad practices), you should turn off Warn,
160             # and to silence other warnings, turn off PrintWarn.
161             # Warn and PrintWarn are independent, and turning off PrintWarn
162             # does not silence those warnings that should be controlled by
163             # Warn.
164              
165             # unless ( $attr->{PrintWarn} ) {
166             # $attr->{Warn} = 0;
167             # }
168              
169 307         2448 return $dbh;
170             }
171              
172             sub install_collation {
173 12     12   32 my $dbh = shift;
174 12         19 my $name = shift;
175 12         67 my $collation = $DBD::SQLite::COLLATION{$name};
176 12 50       84 unless ($collation) {
177 0 0       0 warn "Can't install unknown collation: $name" if $dbh->{PrintWarn};
178 0         0 return;
179             }
180 12         18 if ( DBD::SQLite::NEWAPI ) {
181 12         116 $dbh->sqlite_create_collation( $name => $collation );
182             } else {
183             $dbh->func( $name => $collation, "create_collation" );
184             }
185             }
186              
187             # default implementation for sqlite 'REGEXP' infix operator.
188             # Note : args are reversed, i.e. "a REGEXP b" calls REGEXP(b, a)
189             # (see https://www.sqlite.org/vtab.html#xfindfunction)
190             sub regexp {
191 116     116   119312 use locale;
  116         331  
  116         569  
192 392 100 66 392   3048 return if !defined $_[0] || !defined $_[1];
193 264         2085 return scalar($_[1] =~ $_[0]);
194             }
195              
196             package # hide from PAUSE
197             DBD::SQLite::db;
198              
199 116     116   12855 use DBI qw/:sql_types/;
  116         313  
  116         605261  
200              
201             sub prepare {
202 1380     1380   3340393 my $dbh = shift;
203 1380         2342 my $sql = shift;
204 1380 50       3397 $sql = '' unless defined $sql;
205              
206 1380         5522 my $sth = DBI::_new_sth( $dbh, {
207             Statement => $sql,
208             } );
209              
210 1380 100       114937 DBD::SQLite::st::_prepare($sth, $sql, @_) or return undef;
211              
212 1359         20377 return $sth;
213             }
214              
215             sub do {
216 2978     2978   3057791 my ($dbh, $statement, $attr, @bind_values) = @_;
217              
218             # shortcut
219 2978         10963 my $allow_multiple_statements = $dbh->FETCH('sqlite_allow_multiple_statements');
220 2978 100 100     16555 if (defined $statement && !defined $attr && !@bind_values) {
      100        
221             # _do() (i.e. sqlite3_exec()) runs semicolon-separate SQL
222             # statements, which is handy but insecure sometimes.
223             # Use this only when it's safe or explicitly allowed.
224 2870 100 66     8666 if (index($statement, ';') == -1 or $allow_multiple_statements) {
225 2847         8488028 return DBD::SQLite::db::_do($dbh, $statement);
226             }
227             }
228              
229 131         264 my @copy = @{[@bind_values]};
  131         391  
230 131         269 my $rows = 0;
231              
232 131         362 while ($statement) {
233 136 100       536 my $sth = $dbh->prepare($statement, $attr) or return undef;
234 123 100       10805 $sth->execute(splice @copy, 0, $sth->{NUM_OF_PARAMS}) or return undef;
235 119         1048 $rows += $sth->rows;
236             # XXX: not sure why but $dbh->{sqlite...} wouldn't work here
237 119 100       1729 last unless $allow_multiple_statements;
238 8         124 $statement = $sth->{sqlite_unprepared_statements};
239             }
240              
241             # always return true if no error
242 114 100       796 return ($rows == 0) ? "0E0" : $rows;
243             }
244              
245             sub ping {
246 1     1   912 my $dbh = shift;
247              
248             # $file may be undef (ie. in-memory/temporary database)
249 1         25 my $file = DBD::SQLite::NEWAPI ? $dbh->sqlite_db_filename
250             : $dbh->func("db_filename");
251              
252 1 50 33     9 return 0 if $file && !-f $file;
253 1 50       12 return $dbh->FETCH('Active') ? 1 : 0;
254             }
255              
256             sub quote {
257 8     8   3402 my ($self, $value, $data_type) = @_;
258 8 100       31 return "NULL" unless defined $value;
259 7 50 66     81 if (defined $data_type and (
      66        
260             $data_type == DBI::SQL_BIT ||
261             $data_type == DBI::SQL_BLOB ||
262             $data_type == DBI::SQL_BINARY ||
263             $data_type == DBI::SQL_VARBINARY ||
264             $data_type == DBI::SQL_LONGVARBINARY)) {
265 6         1006 return q(X') . unpack('H*', $value) . q(');
266             }
267 1         6 $value =~ s/'/''/g;
268 1         7 return "'$value'";
269             }
270              
271             sub get_info {
272 79     79   9746 my ($dbh, $info_type) = @_;
273              
274 79         6063 require DBD::SQLite::GetInfo;
275 79         223 my $v = $DBD::SQLite::GetInfo::info{int($info_type)};
276 79 100       216 $v = $v->($dbh) if ref $v eq 'CODE';
277 79         216 return $v;
278             }
279              
280             sub _attached_database_list {
281 21     21   39 my $dbh = shift;
282 21         30 my @attached;
283              
284 21 50       68 my $sth_databases = $dbh->prepare( 'PRAGMA database_list' ) or return;
285 21 50       195 $sth_databases->execute or return;
286 21         489 while ( my $db_info = $sth_databases->fetchrow_hashref ) {
287 47 100       660 push @attached, $db_info->{name} if $db_info->{seq} >= 2;
288             }
289 21         324 return @attached;
290             }
291              
292             # SQL/CLI (ISO/IEC JTC 1/SC 32 N 0595), 6.63 Tables
293             # Based on DBD::Oracle's
294             # See also http://www.ch-werner.de/sqliteodbc/html/sqlite3odbc_8c.html#a213
295             sub table_info {
296 16     16   11990 my ($dbh, $cat_val, $sch_val, $tbl_val, $typ_val, $attr) = @_;
297              
298 16         33 my @where = ();
299 16         28 my $sql;
300 16 100 100     176 if ( defined($cat_val) && $cat_val eq '%'
    100 66        
    100 66        
      33        
      33        
      66        
      66        
      66        
      66        
      66        
      66        
      66        
      33        
      33        
      33        
      33        
      33        
301             && defined($sch_val) && $sch_val eq ''
302             && defined($tbl_val) && $tbl_val eq '') { # Rule 19a
303 1         4 $sql = <<'END_SQL';
304             SELECT NULL TABLE_CAT
305             , NULL TABLE_SCHEM
306             , NULL TABLE_NAME
307             , NULL TABLE_TYPE
308             , NULL REMARKS
309             END_SQL
310             }
311             elsif ( defined($cat_val) && $cat_val eq ''
312             && defined($sch_val) && $sch_val eq '%'
313             && defined($tbl_val) && $tbl_val eq '') { # Rule 19b
314 1         2 $sql = <<'END_SQL';
315             SELECT NULL TABLE_CAT
316             , t.tn TABLE_SCHEM
317             , NULL TABLE_NAME
318             , NULL TABLE_TYPE
319             , NULL REMARKS
320             FROM (
321             SELECT 'main' tn
322             UNION SELECT 'temp' tn
323             END_SQL
324 1         4 for my $db_name (_attached_database_list($dbh)) {
325 0         0 $sql .= " UNION SELECT '$db_name' tn\n";
326             }
327 1         5 $sql .= ") t\n";
328             }
329             elsif ( defined($cat_val) && $cat_val eq ''
330             && defined($sch_val) && $sch_val eq ''
331             && defined($tbl_val) && $tbl_val eq ''
332             && defined($typ_val) && $typ_val eq '%') { # Rule 19c
333 1         3 $sql = <<'END_SQL';
334             SELECT NULL TABLE_CAT
335             , NULL TABLE_SCHEM
336             , NULL TABLE_NAME
337             , t.tt TABLE_TYPE
338             , NULL REMARKS
339             FROM (
340             SELECT 'TABLE' tt UNION
341             SELECT 'VIEW' tt UNION
342             SELECT 'LOCAL TEMPORARY' tt UNION
343             SELECT 'SYSTEM TABLE' tt
344             ) t
345             ORDER BY TABLE_TYPE
346             END_SQL
347             }
348             else {
349 13         26 $sql = <<'END_SQL';
350             SELECT *
351             FROM
352             (
353             SELECT NULL TABLE_CAT
354             , TABLE_SCHEM
355             , tbl_name TABLE_NAME
356             , TABLE_TYPE
357             , NULL REMARKS
358             , sql sqlite_sql
359             FROM (
360             SELECT 'main' TABLE_SCHEM, tbl_name, upper(type) TABLE_TYPE, sql
361             FROM sqlite_master
362             UNION ALL
363             SELECT 'temp' TABLE_SCHEM, tbl_name, 'LOCAL TEMPORARY' TABLE_TYPE, sql
364             FROM sqlite_temp_master
365             END_SQL
366              
367 13         29 for my $db_name (_attached_database_list($dbh)) {
368 9         34 $sql .= <<"END_SQL";
369             UNION ALL
370             SELECT '$db_name' TABLE_SCHEM, tbl_name, upper(type) TABLE_TYPE, sql
371             FROM "$db_name".sqlite_master
372             END_SQL
373             }
374              
375 13         32 $sql .= <<'END_SQL';
376             UNION ALL
377             SELECT 'main' TABLE_SCHEM, 'sqlite_master' tbl_name, 'SYSTEM TABLE' TABLE_TYPE, NULL sql
378             UNION ALL
379             SELECT 'temp' TABLE_SCHEM, 'sqlite_temp_master' tbl_name, 'SYSTEM TABLE' TABLE_TYPE, NULL sql
380             )
381             )
382             END_SQL
383 13 50       50 $attr = {} unless ref $attr eq 'HASH';
384 13 50       40 my $escape = defined $attr->{Escape} ? " ESCAPE '$attr->{Escape}'" : '';
385 13 100       31 if ( defined $sch_val ) {
386 3         9 push @where, "TABLE_SCHEM LIKE '$sch_val'$escape";
387             }
388 13 100       27 if ( defined $tbl_val ) {
389 11         33 push @where, "TABLE_NAME LIKE '$tbl_val'$escape";
390             }
391 13 100       28 if ( defined $typ_val ) {
392 1         2 my $table_type_list;
393 1         6 $typ_val =~ s/^\s+//;
394 1         5 $typ_val =~ s/\s+$//;
395 1         5 my @ttype_list = split (/\s*,\s*/, $typ_val);
396 1         4 foreach my $table_type (@ttype_list) {
397 1 50       5 if ($table_type !~ /^'.*'$/) {
398 1         4 $table_type = "'" . $table_type . "'";
399             }
400             }
401 1         4 $table_type_list = join(', ', @ttype_list);
402 1 50       6 push @where, "TABLE_TYPE IN (\U$table_type_list)" if $table_type_list;
403             }
404 13 100       54 $sql .= ' WHERE ' . join("\n AND ", @where ) . "\n" if @where;
405 13         29 $sql .= " ORDER BY TABLE_TYPE, TABLE_SCHEM, TABLE_NAME\n";
406             }
407 16 50       68 my $sth = $dbh->prepare($sql) or return undef;
408 16 50       883 $sth->execute or return undef;
409 16         358 $sth;
410             }
411              
412             sub primary_key_info {
413 33     33   20102 my ($dbh, $catalog, $schema, $table, $attr) = @_;
414              
415 33         344 my $databases = $dbh->selectall_arrayref("PRAGMA database_list", {Slice => {}});
416              
417 33         4171 my @pk_info;
418 33         105 for my $database (@$databases) {
419 49         131 my $dbname = $database->{name};
420 49 100 66     174 next if defined $schema && $schema ne '%' && $schema ne $dbname;
      100        
421              
422 43         203 my $quoted_dbname = $dbh->quote_identifier($dbname);
423              
424 43 100       1387 my $master_table =
    100          
425             ($dbname eq 'main') ? 'sqlite_master' :
426             ($dbname eq 'temp') ? 'sqlite_temp_master' :
427             $quoted_dbname.'.sqlite_master';
428              
429 43 50       190 my $sth = $dbh->prepare("SELECT name, sql FROM $master_table WHERE type = ?") or return;
430 43 50       1277 $sth->execute("table") or return;
431 43         1175 while(my $row = $sth->fetchrow_hashref) {
432 55         185 my $tbname = $row->{name};
433 55 100 66     964 next if defined $table && $table ne '%' && $table ne $tbname;
      100        
434              
435 33         162 my $quoted_tbname = $dbh->quote_identifier($tbname);
436 33 50       1110 my $t_sth = $dbh->prepare("PRAGMA $quoted_dbname.table_info($quoted_tbname)") or return;
437 33 50       517 $t_sth->execute or return;
438 33         97 my @pk;
439 33         795 while(my $col = $t_sth->fetchrow_hashref) {
440 52 100       1006 push @pk, $col->{name} if $col->{pk};
441             }
442              
443             # If there're multiple primary key columns, we need to
444             # find their order from one of the auto-generated unique
445             # indices (note that single column integer primary key
446             # doesn't create an index).
447 33 100 66     266 if (@pk > 1 and $row->{sql} =~ /\bPRIMARY\s+KEY\s*\(\s*
448             (
449             (?:
450             (
451             [a-z_][a-z0-9_]*
452             | (["'`])(?:\3\3|(?!\3).)+?\3(?!\3)
453             | \[[^\]]+\]
454             )
455             \s*,\s*
456             )+
457             (
458             [a-z_][a-z0-9_]*
459             | (["'`])(?:\5\5|(?!\5).)+?\5(?!\5)
460             | \[[^\]]+\]
461             )
462             )
463             \s*\)/six) {
464 4         21 my $pk_sql = $1;
465 4         39 @pk = ();
466 4         42 while($pk_sql =~ /
467             (
468             [a-z_][a-z0-9_]*
469             | (["'`])(?:\2\2|(?!\2).)+?\2(?!\2)
470             | \[([^\]]+)\]
471             )
472             (?:\s*,\s*|$)
473             /sixg) {
474 9         43 my($col, $quote, $brack) = ($1, $2, $3);
475 9 100       36 if ( defined $quote ) {
    100          
476             # Dequote "'`
477 2         5 $col = substr $col, 1, -1;
478 2         29 $col =~ s/$quote$quote/$quote/g;
479             } elsif ( defined $brack ) {
480             # Dequote []
481 1         2 $col = $brack;
482             }
483 9         48 push @pk, $col;
484             }
485             }
486              
487 33 100       220 my $key_name = $row->{sql} =~ /\bCONSTRAINT\s+(\S+|"[^"]+")\s+PRIMARY\s+KEY\s*\(/i ? $1 : 'PRIMARY KEY';
488 33         56 my $key_seq = 0;
489 33         78 foreach my $pk_field (@pk) {
490 38         1126 push @pk_info, {
491             TABLE_SCHEM => $dbname,
492             TABLE_NAME => $tbname,
493             COLUMN_NAME => $pk_field,
494             KEY_SEQ => ++$key_seq,
495             PK_NAME => $key_name,
496             };
497             }
498             }
499             }
500              
501 33 50       190 my $sponge = DBI->connect("DBI:Sponge:", '','')
502             or return $dbh->DBI::set_err($DBI::err, "DBI::Sponge: $DBI::errstr");
503 33         19742 my @names = qw(TABLE_CAT TABLE_SCHEM TABLE_NAME COLUMN_NAME KEY_SEQ PK_NAME);
504             my $sth = $sponge->prepare( "primary_key_info", {
505 33 50       118 rows => [ map { [ @{$_}{@names} ] } @pk_info ],
  38         65  
  38         347  
506             NUM_OF_FIELDS => scalar @names,
507             NAME => \@names,
508             }) or return $dbh->DBI::set_err(
509             $sponge->err,
510             $sponge->errstr,
511             );
512 33         3123 return $sth;
513             }
514              
515              
516             our %DBI_code_for_rule = ( # from DBI doc; curiously, they are not exported
517             # by the DBI module.
518             # codes for update/delete constraints
519             'CASCADE' => 0,
520             'RESTRICT' => 1,
521             'SET NULL' => 2,
522             'NO ACTION' => 3,
523             'SET DEFAULT' => 4,
524              
525             # codes for deferrability
526             'INITIALLY DEFERRED' => 5,
527             'INITIALLY IMMEDIATE' => 6,
528             'NOT DEFERRABLE' => 7,
529             );
530              
531              
532             my @FOREIGN_KEY_INFO_ODBC = (
533             'PKTABLE_CAT', # The primary (unique) key table catalog identifier.
534             'PKTABLE_SCHEM', # The primary (unique) key table schema identifier.
535             'PKTABLE_NAME', # The primary (unique) key table identifier.
536             'PKCOLUMN_NAME', # The primary (unique) key column identifier.
537             'FKTABLE_CAT', # The foreign key table catalog identifier.
538             'FKTABLE_SCHEM', # The foreign key table schema identifier.
539             'FKTABLE_NAME', # The foreign key table identifier.
540             'FKCOLUMN_NAME', # The foreign key column identifier.
541             'KEY_SEQ', # The column sequence number (starting with 1).
542             'UPDATE_RULE', # The referential action for the UPDATE rule.
543             'DELETE_RULE', # The referential action for the DELETE rule.
544             'FK_NAME', # The foreign key name.
545             'PK_NAME', # The primary (unique) key name.
546             'DEFERRABILITY', # The deferrability of the foreign key constraint.
547             'UNIQUE_OR_PRIMARY', # qualifies the key referenced by the foreign key
548             );
549              
550             # Column names below are not used, but listed just for completeness's sake.
551             # Maybe we could add an option so that the user can choose which field
552             # names will be returned; the DBI spec is not very clear about ODBC vs. CLI.
553             my @FOREIGN_KEY_INFO_SQL_CLI = qw(
554             UK_TABLE_CAT
555             UK_TABLE_SCHEM
556             UK_TABLE_NAME
557             UK_COLUMN_NAME
558             FK_TABLE_CAT
559             FK_TABLE_SCHEM
560             FK_TABLE_NAME
561             FK_COLUMN_NAME
562             ORDINAL_POSITION
563             UPDATE_RULE
564             DELETE_RULE
565             FK_NAME
566             UK_NAME
567             DEFERABILITY
568             UNIQUE_OR_PRIMARY
569             );
570              
571             my $DEFERRABLE_RE = qr/
572             (?:(?:
573             on \s+ (?:delete|update) \s+ (?:set \s+ null|set \s+ default|cascade|restrict|no \s+ action)
574             |
575             match \s* (?:\S+|".+?(?
576             ) \s*)*
577             ((?:not)? \s* deferrable (?: \s* initially \s* (?: immediate | deferred))?)?
578             /sxi;
579              
580             sub foreign_key_info {
581 10     10   15641 my ($dbh, $pk_catalog, $pk_schema, $pk_table, $fk_catalog, $fk_schema, $fk_table) = @_;
582              
583 10 50       97 my $databases = $dbh->selectall_arrayref("PRAGMA database_list", {Slice => {}}) or return;
584              
585 10         1129 my @fk_info;
586             my %table_info;
587 10         34 for my $database (@$databases) {
588 20         47 my $dbname = $database->{name};
589 20 100 66     63 next if defined $fk_schema && $fk_schema ne '%' && $fk_schema ne $dbname;
      100        
590              
591 19         93 my $quoted_dbname = $dbh->quote_identifier($dbname);
592 19 100       621 my $master_table =
    100          
593             ($dbname eq 'main') ? 'sqlite_master' :
594             ($dbname eq 'temp') ? 'sqlite_temp_master' :
595             $quoted_dbname.'.sqlite_master';
596              
597 19 50       139 my $tables = $dbh->selectall_arrayref("SELECT name, sql FROM $master_table WHERE type = ?", undef, "table") or return;
598 19         286 for my $table (@$tables) {
599 34         70 my $tbname = $table->[0];
600 34         47 my $ddl = $table->[1];
601 34         51 my (@rels, %relid2rels);
602 34 100 66     168 next if defined $fk_table && $fk_table ne '%' && $fk_table ne $tbname;
      100        
603              
604 14         83 my $quoted_tbname = $dbh->quote_identifier($tbname);
605 14 50       475 my $sth = $dbh->prepare("PRAGMA $quoted_dbname.foreign_key_list($quoted_tbname)") or return;
606 14 50       156 $sth->execute or return;
607 14         388 while(my $row = $sth->fetchrow_hashref) {
608 18 100 66     145 next if defined $pk_table && $pk_table ne '%' && $pk_table ne $row->{table};
      100        
609              
610 15 100       46 unless ($table_info{$row->{table}}) {
611 13         54 my $quoted_tb = $dbh->quote_identifier($row->{table});
612 13         400 for my $db (@$databases) {
613 15         58 my $quoted_db = $dbh->quote_identifier($db->{name});
614 15 50       381 my $t_sth = $dbh->prepare("PRAGMA $quoted_db.table_info($quoted_tb)") or return;
615 15 50       194 $t_sth->execute or return;
616 15         44 my $cols = {};
617 15         345 while(my $r = $t_sth->fetchrow_hashref) {
618 30         535 $cols->{$r->{name}} = $r->{pk};
619             }
620 15 100       132 if (keys %$cols) {
621             $table_info{$row->{table}} = {
622             schema => $db->{name},
623 13         77 columns => $cols,
624             };
625 13         148 last;
626             }
627             }
628             }
629              
630 15 100 66     117 next if defined $pk_schema && $pk_schema ne '%' && $pk_schema ne $table_info{$row->{table}}{schema};
      100        
631              
632             # cribbed from DBIx::Class::Schema::Loader::DBI::SQLite
633             my $rel = $rels[ $row->{id} ] ||= {
634             local_columns => [],
635             remote_columns => undef,
636             remote_table => $row->{table},
637 13   100     96 };
638 13         25 push @{ $rel->{local_columns} }, $row->{from};
  13         33  
639 13         34 push @{ $rel->{remote_columns} }, $row->{to}
640 13 50       36 if defined $row->{to};
641              
642             my $fk_row = {
643             PKTABLE_CAT => undef,
644             PKTABLE_SCHEM => $table_info{$row->{table}}{schema},
645             PKTABLE_NAME => $row->{table},
646             PKCOLUMN_NAME => $row->{to},
647             FKTABLE_CAT => undef,
648             FKTABLE_SCHEM => $dbname,
649             FKTABLE_NAME => $tbname,
650             FKCOLUMN_NAME => $row->{from},
651             KEY_SEQ => $row->{seq} + 1,
652             UPDATE_RULE => $DBI_code_for_rule{$row->{on_update}},
653             DELETE_RULE => $DBI_code_for_rule{$row->{on_delete}},
654             FK_NAME => undef,
655             PK_NAME => undef,
656             DEFERRABILITY => undef,
657 13 100       216 UNIQUE_OR_PRIMARY => $table_info{$row->{table}}{columns}{$row->{to}} ? 'PRIMARY' : 'UNIQUE',
658             };
659 13         34 push @fk_info, $fk_row;
660 13         16 push @{ $relid2rels{$row->{id}} }, $fk_row; # keep so can fixup
  13         261  
661             }
662              
663             # cribbed from DBIx::Class::Schema::Loader::DBI::SQLite
664             # but with additional parsing of which kind of deferrable
665 14         107 REL: for my $relid (keys %relid2rels) {
666 11         27 my $rel = $rels[$relid];
667 11         19 my $deferrable = $DBI_code_for_rule{'NOT DEFERRABLE'};
668 11         20 my $local_cols = '"?' . (join '"? \s* , \s* "?', map quotemeta, @{ $rel->{local_columns} }) . '"?';
  11         62  
669 11 50       21 my $remote_cols = '"?' . (join '"? \s* , \s* "?', map quotemeta, @{ $rel->{remote_columns} || [] }) . '"?';
  11         51  
670 11     1   1137 my ($deferrable_clause) = $ddl =~ /
  1         668  
  1         15  
  1         19  
671             foreign \s+ key \s* \( \s* $local_cols \s* \) \s* references \s* (?:\S+|".+?(?
672             (?:\( \s* $remote_cols \s* \) \s*)?
673             $DEFERRABLE_RE
674             /sxi;
675 11 50       28335 if (!$deferrable_clause) {
676             # check for inline constraint if 1 local column
677 11 100       18 if (@{ $rel->{local_columns} } == 1) {
  11         35  
678 9         16 my ($local_col) = @{ $rel->{local_columns} };
  9         27  
679 9 50       17 my ($remote_col) = @{ $rel->{remote_columns} || [] };
  9         35  
680 9   50     23 $remote_col ||= '';
681 9         7582 ($deferrable_clause) = $ddl =~ /
682             "?\Q$local_col\E"? \s* (?:\w+\s*)* (?: \( \s* \d\+ (?:\s*,\s*\d+)* \s* \) )? \s*
683             references \s+ (?:\S+|".+?(?
684             $DEFERRABLE_RE
685             /sxi;
686             }
687             }
688 11 100       55 if ($deferrable_clause) {
689             # default is already NOT
690 3 50       12 if ($deferrable_clause !~ /not/i) {
691             $deferrable = $deferrable_clause =~ /deferred/i
692             ? $DBI_code_for_rule{'INITIALLY DEFERRED'}
693 3 50       12 : $DBI_code_for_rule{'INITIALLY IMMEDIATE'};
694             }
695             }
696 11         17 $_->{DEFERRABILITY} = $deferrable for @{ $relid2rels{$relid} };
  11         225  
697             }
698             }
699             }
700              
701 10 50       90 my $sponge_dbh = DBI->connect("DBI:Sponge:", "", "")
702             or return $dbh->DBI::set_err($DBI::err, "DBI::Sponge: $DBI::errstr");
703             my $sponge_sth = $sponge_dbh->prepare("foreign_key_info", {
704             NAME => \@FOREIGN_KEY_INFO_ODBC,
705 10 50       4301 rows => [ map { [@{$_}{@FOREIGN_KEY_INFO_ODBC} ] } @fk_info ],
  13         23  
  13         131  
706             NUM_OF_FIELDS => scalar(@FOREIGN_KEY_INFO_ODBC),
707             }) or return $dbh->DBI::set_err(
708             $sponge_dbh->err,
709             $sponge_dbh->errstr,
710             );
711 10         1200 return $sponge_sth;
712             }
713              
714             my @STATISTICS_INFO_ODBC = (
715             'TABLE_CAT', # The catalog identifier.
716             'TABLE_SCHEM', # The schema identifier.
717             'TABLE_NAME', # The table identifier.
718             'NON_UNIQUE', # Unique index indicator.
719             'INDEX_QUALIFIER', # Index qualifier identifier.
720             'INDEX_NAME', # The index identifier.
721             'TYPE', # The type of information being returned.
722             'ORDINAL_POSITION', # Column sequence number (starting with 1).
723             'COLUMN_NAME', # The column identifier.
724             'ASC_OR_DESC', # Column sort sequence.
725             'CARDINALITY', # Cardinality of the table or index.
726             'PAGES', # Number of storage pages used by this table or index.
727             'FILTER_CONDITION', # The index filter condition as a string.
728             );
729              
730             sub statistics_info {
731 4     4   39193 my ($dbh, $catalog, $schema, $table, $unique_only, $quick) = @_;
732              
733 4 50       44 my $databases = $dbh->selectall_arrayref("PRAGMA database_list", {Slice => {}}) or return;
734              
735 4         502 my @statistics_info;
736 4         14 for my $database (@$databases) {
737 8         23 my $dbname = $database->{name};
738 8 0 33     24 next if defined $schema && $schema ne '%' && $schema ne $dbname;
      33        
739              
740 8         32 my $quoted_dbname = $dbh->quote_identifier($dbname);
741 8 50       298 my $master_table =
    100          
742             ($dbname eq 'main') ? 'sqlite_master' :
743             ($dbname eq 'temp') ? 'sqlite_temp_master' :
744             $quoted_dbname.'.sqlite_master';
745              
746 8 50       56 my $tables = $dbh->selectall_arrayref("SELECT name FROM $master_table WHERE type = ?", undef, "table") or return;
747 8         121 for my $table_ref (@$tables) {
748 8         19 my $tbname = $table_ref->[0];
749 8 100 33     64 next if defined $table && $table ne '%' && uc($table) ne uc($tbname);
      66        
750              
751 4         18 my $quoted_tbname = $dbh->quote_identifier($tbname);
752 4 50       132 my $sth = $dbh->prepare("PRAGMA $quoted_dbname.index_list($quoted_tbname)") or return;
753 4 50       45 $sth->execute or return;
754 4         93 while(my $row = $sth->fetchrow_hashref) {
755              
756 16 100 100     114 next if $unique_only && !$row->{unique};
757 12         45 my $quoted_idx = $dbh->quote_identifier($row->{name});
758 12         338 for my $db (@$databases) {
759 24         87 my $quoted_db = $dbh->quote_identifier($db->{name});
760 24 50       640 my $i_sth = $dbh->prepare("PRAGMA $quoted_db.index_info($quoted_idx)") or return;
761 24 50       194 $i_sth->execute or return;
762 24         58 my $cols = {};
763 24         658 while(my $info = $i_sth->fetchrow_hashref) {
764             push @statistics_info, {
765             TABLE_CAT => undef,
766             TABLE_SCHEM => $db->{name},
767             TABLE_NAME => $tbname,
768             NON_UNIQUE => $row->{unique} ? 0 : 1,
769             INDEX_QUALIFIER => undef,
770             INDEX_NAME => $row->{name},
771             TYPE => 'btree', # see https://www.sqlite.org/version3.html esp. "Traditional B-trees are still used for indices"
772             ORDINAL_POSITION => $info->{seqno} + 1,
773             COLUMN_NAME => $info->{name},
774 16 100       491 ASC_OR_DESC => undef,
775             CARDINALITY => undef,
776             PAGES => undef,
777             FILTER_CONDITION => undef,
778             };
779             }
780             }
781             }
782             }
783             }
784              
785 4 50       21 my $sponge_dbh = DBI->connect("DBI:Sponge:", "", "")
786             or return $dbh->DBI::set_err($DBI::err, "DBI::Sponge: $DBI::errstr");
787             my $sponge_sth = $sponge_dbh->prepare("statistics_info", {
788             NAME => \@STATISTICS_INFO_ODBC,
789 4 50       3057 rows => [ map { [@{$_}{@STATISTICS_INFO_ODBC} ] } @statistics_info ],
  16         26  
  16         110  
790             NUM_OF_FIELDS => scalar(@STATISTICS_INFO_ODBC),
791             }) or return $dbh->DBI::set_err(
792             $sponge_dbh->err,
793             $sponge_dbh->errstr,
794             );
795 4         508 return $sponge_sth;
796             }
797              
798             my @TypeInfoKeys = qw/
799             TYPE_NAME
800             DATA_TYPE
801             COLUMN_SIZE
802             LITERAL_PREFIX
803             LITERAL_SUFFIX
804             CREATE_PARAMS
805             NULLABLE
806             CASE_SENSITIVE
807             SEARCHABLE
808             UNSIGNED_ATTRIBUTE
809             FIXED_PREC_SCALE
810             AUTO_UNIQUE_VALUE
811             LOCAL_TYPE_NAME
812             MINIMUM_SCALE
813             MAXIMUM_SCALE
814             SQL_DATA_TYPE
815             SQL_DATETIME_SUB
816             NUM_PREC_RADIX
817             INTERVAL_PRECISION
818             /;
819              
820             my %TypeInfo = (
821             SQL_INTEGER ,=> {
822             TYPE_NAME => 'INTEGER',
823             DATA_TYPE => SQL_INTEGER,
824             NULLABLE => 2, # no for integer primary key, otherwise yes
825             SEARCHABLE => 3,
826             },
827             SQL_DOUBLE ,=> {
828             TYPE_NAME => 'REAL',
829             DATA_TYPE => SQL_DOUBLE,
830             NULLABLE => 1,
831             SEARCHABLE => 3,
832             },
833             SQL_VARCHAR ,=> {
834             TYPE_NAME => 'TEXT',
835             DATA_TYPE => SQL_VARCHAR,
836             LITERAL_PREFIX => "'",
837             LITERAL_SUFFIX => "'",
838             NULLABLE => 1,
839             SEARCHABLE => 3,
840             },
841             SQL_BLOB ,=> {
842             TYPE_NAME => 'BLOB',
843             DATA_TYPE => SQL_BLOB,
844             NULLABLE => 1,
845             SEARCHABLE => 3,
846             },
847             SQL_UNKNOWN_TYPE ,=> {
848             DATA_TYPE => SQL_UNKNOWN_TYPE,
849             },
850             );
851              
852             sub type_info_all {
853 0     0   0 my $idx = 0;
854              
855 0         0 my @info = ({map {$_ => $idx++} @TypeInfoKeys});
  0         0  
856 0         0 for my $id (sort {$a <=> $b} keys %TypeInfo) {
  0         0  
857 0         0 push @info, [map {$TypeInfo{$id}{$_}} @TypeInfoKeys];
  0         0  
858             }
859 0         0 return \@info;
860             }
861              
862             my @COLUMN_INFO = qw(
863             TABLE_CAT
864             TABLE_SCHEM
865             TABLE_NAME
866             COLUMN_NAME
867             DATA_TYPE
868             TYPE_NAME
869             COLUMN_SIZE
870             BUFFER_LENGTH
871             DECIMAL_DIGITS
872             NUM_PREC_RADIX
873             NULLABLE
874             REMARKS
875             COLUMN_DEF
876             SQL_DATA_TYPE
877             SQL_DATETIME_SUB
878             CHAR_OCTET_LENGTH
879             ORDINAL_POSITION
880             IS_NULLABLE
881             );
882              
883             sub column_info {
884 7     7   5508 my ($dbh, $cat_val, $sch_val, $tbl_val, $col_val) = @_;
885              
886 7 100 100     67 if ( defined $col_val and $col_val eq '%' ) {
887 1         3 $col_val = undef;
888             }
889              
890             # Get a list of all tables ordered by TABLE_SCHEM, TABLE_NAME
891 7         41 my $sql = <<'END_SQL';
892             SELECT TABLE_SCHEM, tbl_name TABLE_NAME
893             FROM (
894             SELECT 'main' TABLE_SCHEM, tbl_name
895             FROM sqlite_master
896             WHERE type IN ('table','view')
897             UNION ALL
898             SELECT 'temp' TABLE_SCHEM, tbl_name
899             FROM sqlite_temp_master
900             WHERE type IN ('table','view')
901             END_SQL
902              
903 7         24 for my $db_name (_attached_database_list($dbh)) {
904 2         10 $sql .= <<"END_SQL";
905             UNION ALL
906             SELECT '$db_name' TABLE_SCHEM, tbl_name
907             FROM "$db_name".sqlite_master
908             WHERE type IN ('table','view')
909             END_SQL
910             }
911              
912 7         29 $sql .= <<'END_SQL';
913             UNION ALL
914             SELECT 'main' TABLE_SCHEM, 'sqlite_master' tbl_name
915             UNION ALL
916             SELECT 'temp' TABLE_SCHEM, 'sqlite_temp_master' tbl_name
917             )
918             END_SQL
919              
920 7         18 my @where;
921 7 50       24 if ( defined $sch_val ) {
922 0         0 push @where, "TABLE_SCHEM LIKE '$sch_val'";
923             }
924 7 50       19 if ( defined $tbl_val ) {
925 7         24 push @where, "TABLE_NAME LIKE '$tbl_val'";
926             }
927 7 50       38 $sql .= ' WHERE ' . join("\n AND ", @where ) . "\n" if @where;
928 7         18 $sql .= " ORDER BY TABLE_SCHEM, TABLE_NAME\n";
929 7 50       25 my $sth_tables = $dbh->prepare($sql) or return undef;
930 7 50       581 $sth_tables->execute or return undef;
931              
932             # Taken from Fey::Loader::SQLite
933 7         27 my @cols;
934 7         165 while ( my ($schema, $table) = $sth_tables->fetchrow_array ) {
935 9 50       65 my $sth_columns = $dbh->prepare(qq{PRAGMA "$schema".table_info("$table")}) or return;
936 9 50       104 $sth_columns->execute or return;
937              
938 9         263 for ( my $position = 1; my $col_info = $sth_columns->fetchrow_hashref; $position++ ) {
939 20 100       67 if ( defined $col_val ) {
940             # This must do a LIKE comparison
941 14 50       91 my $sth = $dbh->prepare("SELECT '$col_info->{name}' LIKE '$col_val'") or return undef;
942 14 50       137 $sth->execute or return undef;
943             # Skip columns that don't match $col_val
944 14 100       397 next unless ($sth->fetchrow_array)[0];
945             }
946              
947             my %col = (
948             TABLE_SCHEM => $schema,
949             TABLE_NAME => $table,
950             COLUMN_NAME => $col_info->{name},
951 13         95 ORDINAL_POSITION => $position,
952             );
953              
954 13         32 my $type = $col_info->{type};
955 13 100       130 if ( $type =~ s/(\w+)\s*\(\s*(\d+)(?:\s*,\s*(\d+))?\s*\)/$1/ ) {
956 7         21 $col{COLUMN_SIZE} = $2;
957 7         27 $col{DECIMAL_DIGITS} = $3;
958             }
959              
960 13         32 $col{TYPE_NAME} = $type;
961              
962 13 50       32 if ( defined $col_info->{dflt_value} ) {
963             $col{COLUMN_DEF} = $col_info->{dflt_value}
964 0         0 }
965              
966 13 100       33 if ( $col_info->{notnull} ) {
967 2         9 $col{NULLABLE} = 0;
968 2         9 $col{IS_NULLABLE} = 'NO';
969             } else {
970 11         36 $col{NULLABLE} = 1;
971 11         25 $col{IS_NULLABLE} = 'YES';
972             }
973              
974 13         258 push @cols, \%col;
975             }
976 9         195 $sth_columns->finish;
977             }
978 7         71 $sth_tables->finish;
979              
980 7 50       51 my $sponge = DBI->connect("DBI:Sponge:", '','')
981             or return $dbh->DBI::set_err($DBI::err, "DBI::Sponge: $DBI::errstr");
982             $sponge->prepare( "column_info", {
983 7 50       8514 rows => [ map { [ @{$_}{@COLUMN_INFO} ] } @cols ],
  13         23  
  13         168  
984             NUM_OF_FIELDS => scalar @COLUMN_INFO,
985             NAME => [ @COLUMN_INFO ],
986             } ) or return $dbh->DBI::set_err(
987             $sponge->err,
988             $sponge->errstr,
989             );
990             }
991              
992             #======================================================================
993             # An internal tied hash package used for %DBD::SQLite::COLLATION, to
994             # prevent people from unintentionally overriding globally registered collations.
995              
996             package # hide from PAUSE
997             DBD::SQLite::_WriteOnceHash;
998              
999             require Tie::Hash;
1000              
1001             our @ISA = qw(Tie::StdHash);
1002              
1003             sub TIEHASH {
1004 116     116   505 bless {}, $_[0];
1005             }
1006              
1007             sub STORE {
1008 237 100   237   2383 ! exists $_[0]->{$_[1]} or die "entry $_[1] already registered";
1009 235         833 $_[0]->{$_[1]} = $_[2];
1010             }
1011              
1012             sub DELETE {
1013 1     1   568 die "deletion of entry $_[1] is forbidden";
1014             }
1015              
1016             1;
1017              
1018             __END__