mirror of
https://github.com/DBD-SQLite/DBD-SQLite
synced 2025-06-07 22:28:47 -04:00
reimplemented foreign_key_info; fk_table is not mandatory anymore
This commit is contained in:
parent
4f721b7880
commit
fe3e0e3236
3 changed files with 58 additions and 78 deletions
2
Changes
2
Changes
|
@ -9,7 +9,7 @@ Changes for Perl extension DBD-SQLite
|
||||||
to false explicitly. (ISHIGAKI)
|
to false explicitly. (ISHIGAKI)
|
||||||
|
|
||||||
- Updated to SQLite 3.17.14 (ISHIGAKI)
|
- Updated to SQLite 3.17.14 (ISHIGAKI)
|
||||||
- Added support for foreign_key_info (DAMI)
|
- Added support for foreign_key_info (DAMI/ISHIGAKI)
|
||||||
- Added several methods to retrieve internal information such as
|
- Added several methods to retrieve internal information such as
|
||||||
table_column_metadata/db_filename/*_status (ISHIGAKI)
|
table_column_metadata/db_filename/*_status (ISHIGAKI)
|
||||||
- Resolved #77617: atoll () sometimes just is atol () (GAAS)
|
- Resolved #77617: atoll () sometimes just is atol () (GAAS)
|
||||||
|
|
|
@ -478,62 +478,65 @@ my @FOREIGN_KEY_INFO_SQL_CLI = qw(
|
||||||
);
|
);
|
||||||
|
|
||||||
sub foreign_key_info {
|
sub foreign_key_info {
|
||||||
my $dbh = shift;
|
my ($dbh, $pk_catalog, $pk_schema, $pk_table, $fk_catalog, $fk_schema, $fk_table) = @_;
|
||||||
my %arg;
|
|
||||||
@arg{qw/PK_CATALOG PK_SCHEMA PK_TABLE
|
|
||||||
FK_CATALOG FK_SCHEMA FK_TABLE/} = @_;
|
|
||||||
|
|
||||||
# check arguments
|
my $databases = $dbh->selectall_arrayref("PRAGMA database_list", {Slice => {}});
|
||||||
$arg{FK_TABLE}
|
|
||||||
or return $dbh->DBI::set_err($DBI::stderr, '6th arg FK_TABLE is mandatory');
|
|
||||||
foreach my $arg_name (qw/PK_CATALOG PK_SCHEMA FK_CATALOG FK_SCHEMA/) {
|
|
||||||
!$arg{$arg_name} || $arg{$arg_name} eq '%'
|
|
||||||
or $dbh->DBI::set_err(0, "arg $arg_name will be ignored");
|
|
||||||
}
|
|
||||||
|
|
||||||
# get info from a PRAGMA statement
|
my @fk_info;
|
||||||
my $fk_sth = $dbh->prepare("PRAGMA foreign_key_list($arg{FK_TABLE})");
|
for my $database (@$databases) {
|
||||||
$fk_sth->execute;
|
my $dbname = $database->{name};
|
||||||
|
next if defined $fk_schema && $fk_schema ne '%' && $fk_schema ne $dbname;
|
||||||
|
|
||||||
# accumulate results (create rows of appropriate structure)
|
my $quoted_dbname = $dbh->quote_identifier($dbname);
|
||||||
my @rows;
|
my $master_table =
|
||||||
while (my $row = $fk_sth->fetchrow_hashref) {
|
($dbname eq 'main') ? 'sqlite_master' :
|
||||||
next if $arg{PK_TABLE} && $arg{PK_TABLE} ne $row->{table};
|
($dbname eq 'temp') ? 'sqlite_temp_master' :
|
||||||
push @rows, [
|
$quoted_dbname.'.sqlite_master';
|
||||||
undef, # PKTABLE_CAT
|
|
||||||
undef, # PKTABLE_SCHEM
|
|
||||||
$row->{table}, # PKTABLE_NAME
|
|
||||||
$row->{to}, # PKCOLUMN_NAME
|
|
||||||
undef, # FKTABLE_CAT
|
|
||||||
undef, # FKTABLE_SCHEM
|
|
||||||
$arg{FK_TABLE}, # FKTABLE_NAME
|
|
||||||
$row->{from}, # FKCOLUMN_NAME
|
|
||||||
$row->{seq} + 1, # KEY_SEQ
|
|
||||||
$DBI_code_for_rule{$row->{on_update}}, # UPDATE_RULE
|
|
||||||
$DBI_code_for_rule{$row->{on_delete}}, # DELETE_RULE
|
|
||||||
undef, # FK_NAME
|
|
||||||
undef, # PK_NAME
|
|
||||||
undef, # DEFERRABILITY
|
|
||||||
undef, # UNIQUE_OR_PRIMARY
|
|
||||||
];
|
|
||||||
# not used: $row->{id}, $row->{match}
|
|
||||||
# CAVEAT : the PRAGMA does not report about DEFERRABILITY clauses
|
|
||||||
}
|
|
||||||
|
|
||||||
# return rows as a 'sponge' statement handle
|
my $tables = $dbh->selectall_arrayref("SELECT name FROM $master_table WHERE type = ?", undef, "table");
|
||||||
my $sponge_dbh = DBI->connect("DBI:Sponge:", '','')
|
for my $table (@$tables) {
|
||||||
or return $dbh->DBI::set_err($DBI::err, "DBI::Sponge: $DBI::errstr");
|
my $tbname = $table->[0];
|
||||||
my $sponge_sth = $sponge_dbh->prepare( "foreign_key_info $arg{FK_TABLE}", {
|
next if defined $fk_table && $fk_table ne '%' && $fk_table ne $tbname;
|
||||||
NAME => \@FOREIGN_KEY_INFO_ODBC,
|
|
||||||
rows => \@rows,
|
|
||||||
NUM_OF_FIELDS => scalar(@FOREIGN_KEY_INFO_ODBC),
|
|
||||||
}) or return $dbh->DBI::set_err(
|
|
||||||
$sponge_dbh->err,
|
|
||||||
$sponge_dbh->errstr,
|
|
||||||
);
|
|
||||||
return $sponge_sth;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
my $quoted_tbname = $dbh->quote_identifier($tbname);
|
||||||
|
my $sth = $dbh->prepare("PRAGMA $quoted_dbname.foreign_key_list($quoted_tbname)") or die $dbh->errstr;
|
||||||
|
$sth->execute;
|
||||||
|
while(my $row = $sth->fetchrow_hashref) {
|
||||||
|
next if defined $pk_table && $pk_table ne '%' && $pk_table ne $row->{table};
|
||||||
|
|
||||||
|
push @fk_info, {
|
||||||
|
PKTABLE_CAT => undef,
|
||||||
|
PKTABLE_SCHEM => undef,
|
||||||
|
PKTABLE_NAME => $row->{table},
|
||||||
|
PKCOLUMN_NAME => $row->{to},
|
||||||
|
FKTABLE_CAT => undef,
|
||||||
|
FKTABLE_SCHEM => $dbname,
|
||||||
|
FKTABLE_NAME => $tbname,
|
||||||
|
FKCOLUMN_NAME => $row->{from},
|
||||||
|
KEY_SEQ => $row->{seq} + 1,
|
||||||
|
UPDATE_RULE => $DBI_code_for_rule{$row->{on_update}},
|
||||||
|
DELETE_RULE => $DBI_code_for_rule{$row->{on_delete}},
|
||||||
|
FK_NAME => undef,
|
||||||
|
PK_NAME => undef,
|
||||||
|
DEFERRABILITY => undef,
|
||||||
|
UNIQUE_OR_PRIMARY => undef,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $sponge_dbh = DBI->connect("DBI:Sponge:", "", "")
|
||||||
|
or return $dbh->DBI::set_err($DBI::err, "DBI::Sponge: $DBI::errstr");
|
||||||
|
my $sponge_sth = $sponge_dbh->prepare("foreign_key_info", {
|
||||||
|
NAME => \@FOREIGN_KEY_INFO_ODBC,
|
||||||
|
rows => [ map { [@{$_}{@FOREIGN_KEY_INFO_ODBC} ] } @fk_info ],
|
||||||
|
NUM_OF_FIELDS => scalar(@FOREIGN_KEY_INFO_ODBC),
|
||||||
|
}) or return $dbh->DBI::set_err(
|
||||||
|
$sponge_dbh->err,
|
||||||
|
$sponge_dbh->errstr,
|
||||||
|
);
|
||||||
|
return $sponge_sth;
|
||||||
|
}
|
||||||
|
|
||||||
sub type_info_all {
|
sub type_info_all {
|
||||||
return; # XXX code just copied from DBD::Oracle, not yet thought about
|
return; # XXX code just copied from DBD::Oracle, not yet thought about
|
||||||
|
@ -1263,8 +1266,8 @@ keys of temporary tables).
|
||||||
|
|
||||||
=head2 foreign_key_info
|
=head2 foreign_key_info
|
||||||
|
|
||||||
$sth = $dbh->foreign_key_info(undef, undef, $optional_pk_table,
|
$sth = $dbh->foreign_key_info(undef, $pk_schema, $pk_table,
|
||||||
undef, undef, $fk_table);
|
undef, $fk_schema, $fk_table);
|
||||||
|
|
||||||
Returns information about foreign key constraints, as specified in
|
Returns information about foreign key constraints, as specified in
|
||||||
L<DBI/foreign_key_info>, but with some limitations :
|
L<DBI/foreign_key_info>, but with some limitations :
|
||||||
|
@ -1273,18 +1276,6 @@ L<DBI/foreign_key_info>, but with some limitations :
|
||||||
|
|
||||||
=item *
|
=item *
|
||||||
|
|
||||||
argument C<$fk_table> is mandatory (this is name of the table that contains
|
|
||||||
the foreign key(s))
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
all other arguments are unused, except the optional C<$pk_table>
|
|
||||||
that may act as an additional filter (the result will only contain
|
|
||||||
the foreign keys in C<$fk_table> which correspond to C<$pk_table>'s
|
|
||||||
primary key).
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
information in rows returned by the C<$sth> is incomplete with
|
information in rows returned by the C<$sth> is incomplete with
|
||||||
respect to the L<DBI/foreign_key_info> specification. All requested fields
|
respect to the L<DBI/foreign_key_info> specification. All requested fields
|
||||||
are present, but the content is C<undef> for some of them.
|
are present, but the content is C<undef> for some of them.
|
||||||
|
|
|
@ -55,7 +55,7 @@ CREATE TABLE song(
|
||||||
__EOSQL__
|
__EOSQL__
|
||||||
|
|
||||||
|
|
||||||
plan tests => @sql_statements + 17;
|
plan tests => @sql_statements + 16;
|
||||||
|
|
||||||
my $dbh = connect_ok( RaiseError => 1, PrintError => 0, AutoCommit => 1 );
|
my $dbh = connect_ok( RaiseError => 1, PrintError => 0, AutoCommit => 1 );
|
||||||
my $sth;
|
my $sth;
|
||||||
|
@ -106,14 +106,3 @@ for ($fk_data->{songartist}) {
|
||||||
for ($fk_data->{songalbum}) {
|
for ($fk_data->{songalbum}) {
|
||||||
is($_->{KEY_SEQ}, 2, "FK song, key seq 2");
|
is($_->{KEY_SEQ}, 2, "FK song, key seq 2");
|
||||||
}
|
}
|
||||||
|
|
||||||
dies(sub {$dbh->foreign_key_info(undef, undef, 'artist',
|
|
||||||
undef, undef, undef)}, qr/mandatory/,
|
|
||||||
"6th arg is mandatory");
|
|
||||||
|
|
||||||
# use YAML;
|
|
||||||
# print STDERR Dump $fk_data;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue