1
0
Fork 0
mirror of https://github.com/DBD-SQLite/DBD-SQLite synced 2025-06-07 22:28:47 -04:00

applied a patch from VLYON on #81536

This commit is contained in:
Kenichi Ishigaki 2012-11-30 02:34:14 +00:00
parent 8c43ef029f
commit 0cabcee217
2 changed files with 61 additions and 25 deletions

View file

@ -392,7 +392,7 @@ sub primary_key_info {
($dbname eq 'temp') ? 'sqlite_temp_master' : ($dbname eq 'temp') ? 'sqlite_temp_master' :
$quoted_dbname.'.sqlite_master'; $quoted_dbname.'.sqlite_master';
my $sth = $dbh->prepare("SELECT name FROM $master_table WHERE type = ?"); my $sth = $dbh->prepare("SELECT name, sql FROM $master_table WHERE type = ?");
$sth->execute("table"); $sth->execute("table");
while(my $row = $sth->fetchrow_hashref) { while(my $row = $sth->fetchrow_hashref) {
my $tbname = $row->{name}; my $tbname = $row->{name};
@ -403,40 +403,60 @@ sub primary_key_info {
$t_sth->execute; $t_sth->execute;
my @pk; my @pk;
while(my $col = $t_sth->fetchrow_hashref) { while(my $col = $t_sth->fetchrow_hashref) {
next unless $col->{pk}; push @pk, $col->{name} if $col->{pk};
push @pk, $col->{name};
} }
# If there're multiple primary key columns, we need to # If there're multiple primary key columns, we need to
# find their order from one of the auto-generated unique # find their order from one of the auto-generated unique
# indices (note that single column integer primary key # indices (note that single column integer primary key
# doesn't create an index). # doesn't create an index).
if (@pk > 1) { if (@pk > 1 and $row->{sql} =~ /\bPRIMARY\s+KEY\s*\(\s*
my $indices = $dbh->selectall_arrayref("PRAGMA $quoted_dbname.index_list($quoted_tbname)", {Slice => +{}}); (
for my $index (@$indices) { (?:
next unless $index->{unique}; (
my $quoted_idxname = $dbh->quote_identifier($index->{name}); [a-z_][a-z0-9_]*
my $cols = $dbh->selectall_arrayref("PRAGMA $quoted_dbname.index_info($quoted_idxname)", {Slice => +{}}); | (["'`])(?:\3\3|(?!\3).)+?\3(?!\3)
my %seen; | \[[^\]]+\]
if (@pk == grep { !$seen{$_}++ } (@pk, map { $_->{name} } @$cols)) { )
for (@$cols) { \s*,\s*
push @pk_info, { )+
TABLE_SCHEM => $dbname, (
TABLE_NAME => $tbname, [a-z_][a-z0-9_]*
COLUMN_NAME => $_->{name}, | (["'`])(?:\5\5|(?!\5).)+?\5(?!\5)
KEY_SEQ => scalar @pk_info + 1, | \[[^\]]+\]
PK_NAME => 'PRIMARY KEY', )
}; )
} \s*\)/six) {
my $pk_sql = $1;
@pk = ();
while($pk_sql =~ /
(
[a-z_][a-z0-9_]*
| (["'`])(?:\2\2|(?!\2).)+?\2(?!\2)
| \[([^\]]+)\]
)
(?:\s*,\s*|$)
/sixg) {
my($col, $quote, $brack) = ($1, $2, $3);
if ( defined $quote ) {
# Dequote "'`
$col = substr $col, 1, -1;
$col =~ s/$quote$quote/$quote/g;
} elsif ( defined $brack ) {
# Dequote []
$col = $brack;
} }
push @pk, $col;
} }
} }
else {
my $key_seq = 0;
foreach my $pk_field (@pk) {
push @pk_info, { push @pk_info, {
TABLE_SCHEM => $dbname, TABLE_SCHEM => $dbname,
TABLE_NAME => $tbname, TABLE_NAME => $tbname,
COLUMN_NAME => $pk[0], COLUMN_NAME => $pk_field,
KEY_SEQ => scalar @pk_info + 1, KEY_SEQ => ++$key_seq,
PK_NAME => 'PRIMARY KEY', PK_NAME => 'PRIMARY KEY',
}; };
} }

View file

@ -10,7 +10,7 @@ use t::lib::Test qw/connect_ok/;
use Test::More; use Test::More;
use Test::NoWarnings; use Test::NoWarnings;
plan tests => 10 + 1; plan tests => 15 + 1;
# single column integer primary key # single column integer primary key
{ {
@ -44,7 +44,23 @@ plan tests => 10 + 1;
my $sth = $dbh->primary_key_info(undef, undef, 'foo'); my $sth = $dbh->primary_key_info(undef, undef, 'foo');
my @pk_info; my @pk_info;
while(my $row = $sth->fetchrow_hashref) { push @pk_info, $row }; while(my $row = $sth->fetchrow_hashref) { push @pk_info, $row };
is @pk_info => 2, "found 1 pks"; is @pk_info => 2, "found 2 pks";
is $pk_info[0]{COLUMN_NAME} => 'type', "first pk name is type"; is $pk_info[0]{COLUMN_NAME} => 'type', "first pk name is type";
is $pk_info[1]{COLUMN_NAME} => 'id', "second pk name is id"; is $pk_info[1]{COLUMN_NAME} => 'id', "second pk name is id";
} }
# multi-column primary key with quotes
{
my $dbh = connect_ok();
$dbh->do('create table foo (a, b, "c""d", unique(a, b, "c""d"), primary key( "c""d", [b], `a` ))');
my $sth = $dbh->primary_key_info(undef, undef, 'foo');
my @pk_info;
while(my $row = $sth->fetchrow_hashref) { push @pk_info, $row };
is @pk_info => 3, "found 3 pks";
my @pk = map $_->{COLUMN_NAME}, @pk_info;
is join(' ', sort @pk) => 'a b c"d', 'all pks are correct';
is join(' ', @pk) => 'c"d b a', 'pk order is correct';
@pk = map $_->{COLUMN_NAME}, sort {$a->{KEY_SEQ} <=> $b->{KEY_SEQ}} @pk_info;
is join(' ', @pk) => 'c"d b a', 'pk KEY_SEQ is correct';
}