Algorithm-SpatialIndex
view release on metacpan or search on metacpan
lib/Algorithm/SpatialIndex/Storage/DBI.pm view on Meta::CPAN
);
warn $sql if DEBUG;
$dbh->do($sql);
my $bsql = $self->{buckets_create_sql};
warn $bsql if DEBUG;
$dbh->do($bsql);
}
=head2 _write_config
Writes the index's configuration to the
configuration table.
=cut
sub _write_config {
my $self = shift;
my $dbh = $self->dbh_rw;
my $table_prefix = $self->table_prefix;
my $sql_struct = $self->{_write_config_sql};
my $is_sub = ref($sql_struct) eq 'CODE';
my $sth;
$sth = $dbh->prepare_cached($sql_struct->[0]) if not $is_sub;
my $success = eval {
foreach my $key (keys %{$self->{config}}) {
if ($is_sub) {
$sql_struct->($key, $self->{config}{$key});
} else {
my $d = [$key, $self->{config}{$key}];
$sth->execute(map $d->[$_], @{$sql_struct}[1..$#$sql_struct]);
my $err = $sth->errstr; die $err if $err;
}
}
1;
};
$sth->finish;
}
sub fetch_node {
my $self = shift;
my $index = shift;
my $dbh = $self->dbh_ro;
my $str = $self->{_fetch_node_sql};
my $sth = $dbh->prepare_cached($str);
$sth->execute($index);
my $struct = $sth->fetchrow_arrayref;
$sth->finish;
return if not defined $struct;
my $coords = $self->no_of_coords;
my $snodes = [@{$struct}[1+$coords..$coords+$self->no_of_subnodes]];
$snodes = [] if not defined $snodes->[0];
my $node = Algorithm::SpatialIndex::Node->new(
id => $struct->[0],
coords => [@{$struct}[1..$coords]],
subnode_ids => $snodes,
);
#use Data::Dumper; warn "FETCH: " . Dumper($node);
return $node;
}
sub store_node {
my $self = shift;
my $node = shift;
#use Data::Dumper;
#use Data::Dumper; warn "STORE: " . Dumper($node);
my $id = $node->id;
my $dbh = $self->dbh_rw;
my $tname = $self->table_prefix . '_nodes';
my $sth;
if (not defined $id) {
$sth = $dbh->prepare_cached($self->{_write_new_node_sql});
my $coords = $node->coords;
my $snids = $node->subnode_ids;
my @args = (
@$coords,
((undef) x ($self->no_of_coords - @$coords)),
@$snids,
((undef) x ($self->no_of_subnodes - @$snids))
);
$sth->execute(@args);
$id = $dbh->last_insert_id('', '', '', ''); # FIXME NOT PORTABLE LIKE THAT
$node->id($id);
}
else {
$sth = $dbh->prepare_cached($self->{_write_node_sql});
$sth->execute($id, @{$node->coords}, @{$node->subnode_ids}, $id);
}
$sth->finish();
return $id;
}
sub get_option {
my $self = shift;
return $self->{config}->{shift()}; # We assume this data changes RARELY
}
sub set_option {
my $self = shift;
my $key = shift;
my $value = shift;
$self->{config}->{$key} = $value;
$self->_write_config(); # FIXME wasteful
}
sub store_bucket {
my $self = shift;
my $bucket = shift;
my $dbh = $self->dbh_rw;
my $id = $bucket->node_id;
my $sql = $self->{buckets_insert_sql};
my $is_sub = ref($sql) eq 'CODE';
if (!$is_sub) {
my $sth = $dbh->prepare_cached($sql->[0]);
my $d = [$id, map {@$_} @{$bucket->items}];
$sth->execute(map $d->[$_], @{$sql}[1..$#$sql]);
my $err = $sth->errstr; die $err if $err;
$sth->finish;
}
else {
$sql->($id, map {@$_} @{$bucket->items});
}
}
sub fetch_bucket {
lib/Algorithm/SpatialIndex/Storage/DBI.pm view on Meta::CPAN
my $self = shift;
my $bsize = $self->bucket_size;
my $tname = $self->table_prefix . '_buckets';
my %types = (
float => 'FLOAT',
double => 'DOUBLE',
integer => 'INTEGER',
unsigned => 'INTEGER UNSIGNED',
);
my $item_coord_types = [map $types{$_}, @{$self->item_coord_types}];
# i0 INTEGER, i0c0 DOUBLE, i0c1 DOUBLE, ...
$self->{buckets_create_sql} = qq{CREATE TABLE IF NOT EXISTS $tname ( node_id INTEGER PRIMARY KEY, }
. join(
', ',
map {
my $i = $_;
my $c = 0;
("i$i INTEGER", map "i${i}c".$c++." $_", @$item_coord_types)
} 0..$bsize-1
)
. ')';
$self->{buckets_select_sql} = qq{SELECT * FROM $tname WHERE node_id=?};
my $insert_id_list = join(
', ',
map {
my $i = $_;
"i$i", map "i${i}c$_", 0..$#$item_coord_types
} 0..$bsize-1
);
my $nentries = 1 + $bsize * (1+@$item_coord_types);
#my $idlist = join(', ', map "i$_" 0..$bsize-1);
my $qlist = '?,' x $nentries;
$qlist =~ s/,$//;
if ($self->is_mysql) {
$self->{buckets_insert_sql} = [
qq{
INSERT INTO $tname
VALUES ($qlist)
ON DUPLICATE KEY UPDATE $insert_id_list
}, 0..$nentries-1
];
}
elsif ($self->is_sqlite) {
$self->{buckets_insert_sql} = [qq{INSERT OR REPLACE INTO $tname VALUES($qlist)}, 0..$nentries-1 ];
}
else {
my $insert_sql = qq{INSERT INTO $tname VALUES(?, $qlist)};
my $update_sql = qq{UPDATE $tname SET id=?, $insert_id_list};
$self->{buckets_insert_sql} = sub {
my $dbh = shift;
eval {
$dbh->do($insert_sql, {}, @_, (undef) x ($nentries-@_));
$dbh->do($update_sql, {}, @_, (undef) x ($nentries-@_));
1;
};
};
}
#use Data::Dumper;
#warn Dumper $self->{buckets_insert_sql};
}
1;
__END__
=head1 AUTHOR
Steffen Mueller, E<lt>smueller@cpan.orgE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2010, 2011 by Steffen Mueller
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.10.1 or,
at your option, any later version of Perl 5 you may have available.
=cut
( run in 1.333 second using v1.01-cache-2.11-cpan-39bf76dae61 )