Skip Menu |

This queue is for tickets about the KiokuDB-Backend-BDB CPAN distribution.

Report information
The Basics
Id: 46377
Status: new
Priority: 0/
Queue: KiokuDB-Backend-BDB

People
Owner: Nobody in particular
Requestors: j.borevich [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.14
Fixed in: (no value)



Subject: Wrong (?) beahavour of search using KiokuDB::Backend::BDB::GIN
perl version: 5.8.8 os version: Linux fireball 2.6.18-6-686 #1 SMP Tue Jun 17 21:31:27 UTC 2008 i686 GNU/Linux KiokuDB version: 0.27 KiokiDB::Backend::BDB version: 0.14 BerkeleyDB (perl package) version: 0.38 BerkeleyDB version: 4.7.25 I found some issues using manual GIN search with KiojuDB::Backend::DBD::GIN : 1. Warns like 'Reference is already weak at /home/self/lib/KiokuDB/LiveObjects.pm line 324' 2. OR-like result set while make search with multi-keyed query (waitng AND-like result set) 3. Duplicated objects in result set while make search with multy-keyed query 4. Re-deserializing entries, that are already exists in live objects How to reproduce: execute attached script, look at warnigns and test. Patch (attached): Simplest way i found to fix this bug is to rewrite search method in KiokuDB::Backend::BDB::GIN. Main idea is to use BerkeleyDB equlity joins, wich take all heavy work on itself.
Subject: KiokuDB-Backend-BDB-GIN-patch.pm
# i'm sory for possible negative-style design of this patch; # there is my first public patch # there is only search method redefined package KiokuDB::Backend::BDB::GIN; use Moose; use BerkeleyDB; sub search { my ( $self, $query, @args ) = @_; my %args = ( distinct => $self->distinct, @args, ); my $live_objects = $args{live_objects}; my %spec = $query->extract_values($self); my @cursors; # create cursor for each requested field foreach my $key (@{ $spec{values} }){ my $cur = $self->secondary_db->db_cursor; my $data = ''; my $ret = $cur->c_get($key, $data, DB_SET); if ($ret == DB_NOTFOUND){ return new Data::Stream::Bulk::Nil; } confess "Can't join tables: $ret" unless $ret == 0; push @cursors, $cur; } # we want retrieve all records if no fields requested my $cursor = scalar @cursors ? $self->primary_db->db_join(\@cursors) : $self->secondary_db->db_cursor; my $flags = scalar @cursors ? 0 : DB_NEXT; return new Data::Stream::Bulk::Callback callback => sub { my ($id, $data) = ('', ''); my $ret = $cursor->c_get($id, $data, $flags); if ($ret == 0){ # wan't desereilize fetched objects, use exited my ($entry) = $live_objects->ids_to_entries($id); unless (defined $entry){ $entry = $self->deserialize($data); } return [$entry]; } elsif ($ret == DB_NOTFOUND){ $cursor->c_close; return; } else { throw LGame::Err "Error while fetching db: $ret"; } } } __PACKAGE__->meta->make_immutable; 1;
Subject: kioku-test_search.pl
{ package App::Object; use Moose; has indexed_field => ( is => 'rw', isa => 'Int' ); __PACKAGE__->meta->make_immutable; 1; } package main; use KiokuDB; use Search::GIN::Extract::Callback; use Search::GIN::Query::Manual; use Test::Simple tests => 2; my $dir = KiokuDB->connect( "bdb-gin:dir=/home/self/tmp/db/", create => 1, extract => Search::GIN::Extract::Callback->new(extract => sub { my ( $object, $extractor, @args) = @_; my $index = { class => ref $object }; if ( $object->isa('App::Object') ){ $index->{indexed_field} = $object->indexed_field; } return $index; }) ); { my $scope = $dir->new_scope; $dir->store(App::Object->new(indexed_field => 123)); $dir->store(App::Object->new(indexed_field => 777)); } { my $scope = $dir->new_scope; my $query = Search::GIN::Query::Manual->new( values => { class => 'App::Object', indexed_field => 123 }, ); # i'm waiting here to recieve 1 object # that will be an instance of App::Object AND # have indexed_field == 123 @result = $dir->search($query)->all; ok @result == 1; # not ok, @result == 3 here, looks good with patch }