Removed old stuff, and done some cleanup in the documentation, and
authorpop <pop>
Fri, 28 Feb 2003 18:38:28 +0000 (18:38 +0000)
committerpop <pop>
Fri, 28 Feb 2003 18:38:28 +0000 (18:38 +0000)
around resultsets

perl/IDZebra_wrap.c
perl/lib/IDZebra/Repository.pm [deleted file]
perl/lib/IDZebra/Resultset.pm
perl/lib/IDZebra/Service.pm [deleted file]
perl/lib/IDZebra/Session.pm
perl/test.pl
perl/zebra_api_ext.c
perl/zebra_perl.h

index 342b0a1..127e0a6 100644 (file)
@@ -212,7 +212,7 @@ SWIG_TypeClientData(swig_type_info *ti, void *clientdata) {
  * perl5.swg
  *
  * Perl5 runtime library
- * $Header: /home/cvsroot/idis/perl/Attic/IDZebra_wrap.c,v 1.6 2003-02-28 16:17:42 pop Exp $
+ * $Header: /home/cvsroot/idis/perl/Attic/IDZebra_wrap.c,v 1.7 2003-02-28 18:38:28 pop Exp $
  * ----------------------------------------------------------------------------- */
 
 #define SWIGPERL
diff --git a/perl/lib/IDZebra/Repository.pm b/perl/lib/IDZebra/Repository.pm
deleted file mode 100644 (file)
index ff1a4a4..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-#!/usr/bin/perl
-# ============================================================================
-# Zebra perl API header
-# =============================================================================
-use strict;
-# ============================================================================
-package IDZebra::Repository;
-use IDZebra;
-use IDZebra::Logger qw(:flags :calls);
-use Carp;
-use Scalar::Util qw(weaken);
-1;
-
-
-# -----------------------------------------------------------------------------
-# Repository stuff
-# -----------------------------------------------------------------------------
-
-sub new {
-    my ($proto,$session,%args) = @_;
-    my $class = ref($proto) || $proto;
-    my $self = {};
-    $self->{session} = $session;
-    weaken ($self->{session});
-    $self->{rg} = IDZebra::recordGroup->new();
-    IDZebra::init_recordGroup($self->{rg});
-    bless ($self, $class);
-    unless ($self->_set_options(%args)) {
-       $self->_prepare;
-    }
-    return ($self);
-}
-
-sub modify {
-    my ($self,%args) = @_;
-    if ($args{name}) {
-       if ($args{name} ne $self->{rg}{groupName}) {
-           $self->readConfig($args{name},"");
-       }
-       delete($args{name});
-    }
-    $self->_set_options(%args);
-}
-
-sub readConfig {
-    my ($self, $groupName, $ext) = @_;
-    if ($#_ > 0) { 
-      IDZebra::init_recordGroup($self->{rg});
-       $self->{rg}{groupName} = $groupName;  
-    }
-    $ext = "" unless ($ext);
-    IDZebra::res_get_recordGroup($self->{session}{zh}, $self->{rg}, $ext);
-    $self->_prepare();
-}
-
-sub _set_options {
-    my ($self, %args) = @_; 
-    my $i = 0;
-    foreach my $key (keys(%args)) {
-       $self->{rg}{$key} = $args{$key};
-       $i++;
-    }    
-    if ($i > 0) {
-       $self->_prepare();
-    }
-    return ($i);
-}
-
-sub _prepare {
-    my ($self) = @_;
-
-    IDZebra::set_group($self->{session}{zh}, $self->{rg});
-
-    my $dbName;
-    unless ($dbName = $self->{rg}{databaseName}) {
-       $dbName = 'Default';
-    }
-    if (my $res = IDZebra::select_database($self->{session}{zh}, $dbName)) {
-       logf(LOG_FATAL, 
-            "Could not select database %s errCode=%d",
-            $self->{rg}{databaseName},
-            $self->{session}->errCode());
-       croak("Fatal error opening/selecting database (record group)");
-    } else {
-       logf(LOG_LOG,"Database %s selected",$dbName);
-    }
-}
-
-sub DEBUG {
-    my ($self) = @_;
-    foreach my $key qw (groupName databaseName path recordId recordType flagStoreData flagStoreKeys flagRw fileVerboseLimit databaseNamePath explainDatabase followLinks) {
-       print STDERR "RG:$key:",$self->{rg}{$key},"\n";
-    }
-}
-
-sub init {
-    my ($self, %args) = @_;
-    $self->_set_options(%args);
-    IDZebra::init($self->{session}{zh});
-}
-
-sub compact {
-    my ($self, %args) = @_;
-    $self->_set_options(%args);
-    IDZebra::compact($self->{session}{zh});
-}
-
-sub update {
-    my ($self, %args) = @_;
-    $self->_set_options(%args);
-    IDZebra::repository_update($self->{session}{zh});
-}
-
-sub delete {
-    my ($self, %args) = @_;
-    $self->_set_options(%args);
-    IDZebra::repository_delete($self->{session}{zh});
-}
-
-sub show {
-    my ($self, %args) = @_;
-    $self->_set_options(%args);
-    IDZebra::repository_show($self->{session}{zh});
-}
-
-sub update_record {
-    my ($self, %args) = @_;
-    return(IDZebra::update_record($self->{session}{zh},
-                                 $self->{rg},
-                                 $self->update_args(%args)));
-}
-
-sub delete_record {
-    my ($self, %args) = @_;
-    return(IDZebra::delete_record($self->{session}{zh},
-                                 $self->{rg},
-                                 $self->update_args(%args)));
-}
-
-sub update_args {
-    my ($self, %args) = @_;
-
-    my $sysno   = $args{sysno}      ? $args{sysno}      : 0;
-    my $match   = $args{match}      ? $args{match}      : "";
-    my $rectype = $args{recordType} ? $args{recordType} : "";
-    my $fname   = $args{file}       ? $args{file}       : "<no file>";
-
-    my $buff;
-
-    if ($args{data}) {
-       $buff = $args{data};
-    } 
-    elsif ($args{file}) {
-       open (F, $args{file}) || warn ("Cannot open $args{file}");
-       $buff = join('',(<F>));
-       close (F);
-    }
-    my $len = length($buff);
-
-    # If no record type is given, then try to find it out from the
-    # file extension;
-
-    unless ($rectype) {
-       my ($ext) = $fname =~ /\.(\w+)$/;
-       $self->readConfig( $self->{rg}{groupName},$ext);
-    }
-
-    return ($rectype, $sysno, $match, $fname, $buff, $len);
-}
-
-sub DESTROY {
-    my ($self) = @_;
-}
-
-__END__
-
-=head1 NAME
-
-IDZebra::Repository - 
-
-=head1 SYNOPSIS
-
-=head1 DESCRIPTION
-
-=head1 COPYRIGHT
-
-Fill in
-
-=head1 AUTHOR
-
-Peter Popovics, pop@technomat.hu
-
-=head1 SEE ALSO
-
-IDZebra, IDZebra::Data1, Zebra documentation
-
-=cut
index dd40ad1..0831d9d 100644 (file)
@@ -37,6 +37,21 @@ sub new {
     return ($self);
 }
 
+sub count {
+    my ($self) = @_;
+    return ($self->{recordCount});
+}
+
+sub errCode {
+    my ($self) = @_;
+    return ($self->{errCode});
+}
+
+sub errString {
+    my ($self) = @_;
+    return ($self->{errCode});
+}
+
 sub DESTROY {
     my ($self) = @_;
 
@@ -102,16 +117,30 @@ sub sort {
     }
 }
 
+# ============================================================================
 __END__
 
 =head1 NAME
 
-IDZebra::Session - 
+IDZebra::Resultset - Representation of Zebra search results
 
 =head1 SYNOPSIS
 
 =head1 DESCRIPTION
 
+The I<Resultset> object represents results of a Zebra search. Contains number of hits, search status, and can be used to sort and retrieve the records.
+
+=head1 PROPERTIES
+
+  $count = $rs->count;
+
+  printf ("RS Status is %d (%s)\n", $rs->errCode, $rs->errString);
+
+I<$rs-E<gt>errCode> is 0, if there were no errors during search.
+
+=head1 RETRIEVING RECORDS
+
+
 =head1 COPYRIGHT
 
 Fill in
diff --git a/perl/lib/IDZebra/Service.pm b/perl/lib/IDZebra/Service.pm
deleted file mode 100644 (file)
index 4ac41a8..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/perl
-# ============================================================================
-# Zebra perl API header
-# =============================================================================
-use strict;
-use Carp;
-# ============================================================================
-package IDZebra::Service;
-use IDZebra;
-use IDZebra::Session;
-use IDZebra::Logger qw(:flags :calls);
-use Scalar::Util qw(weaken);
-
-our @ISA = qw(IDZebra::Logger);
-
-1;
-# -----------------------------------------------------------------------------
-# Class constructors, destructor
-# -----------------------------------------------------------------------------
-sub new {
-    my ($proto,$configName) = @_;
-    my $class = ref($proto) || $proto;
-    my $self = {};
-    $self->{configName} = $configName;
-    $self->{sessions} = {};
-    $self->{sessc} = 0;
-    bless ($self, $class);
-    return ($self);
-}
-
-sub start {
-    my ($proto,$configName) = @_;
-    my $self = {};
-    if (ref($proto)) { $self = $proto; } else { 
-       $self = $proto->new($configName);
-    }
-    unless (defined($self->{zs})) {
-       $self->{zs} = IDZebra::start($self->{configName});
-    }
-    return ($self);
-}
-
-sub stop {
-    my ($self) = @_;
-    foreach my $sess (values(%{$self->{sessions}})) {
-       $sess->close;
-    }
-    IDZebra::stop($self->{zs}) if ($self->{zs});    
-    $self->{zs} = undef;
-}
-
-sub DESTROY {
-    my ($self) = @_;
-    $self->stop; 
-}
-# -----------------------------------------------------------------------------
-# Session management
-# -----------------------------------------------------------------------------
-sub createSession {
-    my ($self) = @_;
-    my $session = IDZebra::Session->new($self);
-    $self->{sessions}{$self->{sessc}} = $session;
-    weaken ($self->{sessions}{$self->{sessc}});
-    $self->{sessc}++;
-    return($session);
-}
-
-sub openSession {
-    my ($self) = @_;
-    my $session = IDZebra::Session->open($self);
-    $self->{sessions}{$self->{sessc}} = $session;
-    weaken ($self->{sessions}{$self->{sessc}});
-    $self->{sessc}++;
-    return($session);
-}
-
-__END__
-
-=head1 NAME
-
-IDZebra::Service - 
-
-=head1 SYNOPSIS
-
-=head1 DESCRIPTION
-
-=head1 COPYRIGHT
-
-Fill in
-
-=head1 AUTHOR
-
-Peter Popovics, pop@technomat.hu
-
-=head1 SEE ALSO
-
-IDZebra, IDZebra::Data1, Zebra documentation
-
-=cut
index 1a395f0..f68df57 100644 (file)
@@ -1,13 +1,11 @@
-#!/usr/bin/perl
-# ============================================================================
+# $Id: Session.pm,v 1.5 2003-02-28 18:38:29 pop Exp $
+# 
 # Zebra perl API header
 # =============================================================================
 use strict;
-# ============================================================================
 package IDZebra::Session;
 use IDZebra;
 use IDZebra::Logger qw(:flags :calls);
-#use IDZebra::Repository;
 use IDZebra::Resultset;
 use Scalar::Util;
 use Carp;
@@ -79,7 +77,7 @@ sub open {
     $self->{rscount} = 0;
 
     # This is needed in order to somehow initialize the service
-    $self->select_databases("Default");
+    $self->databases("Default");
 
     # Load the default configuration
     $self->group(%args);
@@ -238,22 +236,33 @@ sub _selectRecordGroup {
     unless ($dbName = $rg->{databaseName}) {
        $dbName = 'Default';
     }
-    if ($self->select_databases($dbName)) {
+    unless ($self->databases($dbName)) {
        croak("Fatal error selecting database $dbName");
     }
 }
 # -----------------------------------------------------------------------------
 # Selecting databases for search (and also for updating - internally)
 # -----------------------------------------------------------------------------
-sub select_databases {
+sub databases {
     my ($self, @databases) = @_;
 
+    unless ($#_ >0) {
+       return (keys(%{$self->{databases}}));
+    }
+
+    my %tmp;
+
     my $changed = 0;
     foreach my $db (@databases) {
        next if ($self->{databases}{$db});
+       $tmp{$db}++;
        $changed++;
     }
 
+    foreach my $db (keys (%{$self->{databases}})) {
+       $changed++ unless ($tmp{$db});
+    }
+
     if ($changed) {
 
        delete ($self->{databases});
@@ -261,19 +270,19 @@ sub select_databases {
            $self->{databases}{$db}++;
        }
 
-       if (my $res = IDZebra::select_databases($self->{zh}, 
+       if (IDZebra::select_databases($self->{zh}, 
                                                ($#databases + 1), 
                                                \@databases)) {
            logf(LOG_FATAL, 
                 "Could not select database(s) %s errCode=%d",
                 join(",",@databases),
                 $self->errCode());
-           return ($res);
+           return (0);
        } else {
            logf(LOG_LOG,"Database(s) selected: %s",join(",",@databases));
        }
     }
-    return (0);
+    return (keys(%{$self->{databases}}));
 }
 
 # -----------------------------------------------------------------------------
@@ -507,9 +516,22 @@ sub search {
        croak ("No query given to search");
     }
 
+    my @origdbs;
+
+    if ($args{databases}) {
+       @origdbs = $self->databases;
+       $self->databases(@{$args{databases}});
+    }
+
     my $rsname = $args{rsname} ? $args{rsname} : $self->_new_setname;
 
-    return ($self->_search_pqf($query, $rsname));
+    my $rs = $self->_search_pqf($query, $rsname);
+
+    if ($args{databases}) {
+       $self->databases(@origdbs);
+    }
+
+    return ($rs);
 }
 
 sub _new_setname {
@@ -534,15 +556,6 @@ sub _search_pqf {
     return($rs);
 }
 
-sub search_cql {
-    my ($self, $query, $transfile) = @_;
-}
-
-
-sub search_ccl {
-    my ($self, $query, $transfile) = @_;
-}
-
 # -----------------------------------------------------------------------------
 # Sort
 #
@@ -580,6 +593,8 @@ sub sortResultsets {
     return ($rs);
 }
 
+# ============================================================================
+
 
 __END__
 
@@ -592,8 +607,29 @@ IDZebra::Session - A Zebra database server session for update and retrieval
   $sess = IDZebra::Session->new(configFile => 'demo/zebra.cfg');
   $sess->open();
 
-  $sess = IDZebra::Session->open(configFile => 'demo/zebra.cfg');
+  $sess = IDZebra::Session->open(configFile => 'demo/zebra.cfg',
+                                groupName  => 'demo1');
+
+  $sess->group(groupName => 'demo2');
+
+  $sess->init();
 
+  $sess->begin_trans;
+
+  $sess->update(path      =>  'lib');
+
+  my $s1=$sess->update_record(data       => $rec1,
+                             recordType => 'grs.perl.pod',
+                             groupName  => "demo1",
+                             );
+
+  my $stat = $sess->end_trans;
+
+  $sess->databases('demo1','demo2');
+
+  my $rs1 = $sess->search(cqlmap    => 'demo/cql.map',
+                         cql       => 'dc.title=IDZebra',
+                         databases => [qw(demo1 demo2)]);
   $sess->close;
 
 =head1 DESCRIPTION
@@ -651,7 +687,7 @@ This will select the named record group, and load the corresponding settings fro
 
 =item B<databaseName>
 
-The name of the (logical) database the updated records will belong to.
+The name of the (logical) database the updated records will belong to. 
 
 =item B<path>
 
@@ -777,8 +813,60 @@ Don't try this at home! This case, the record identifier string (which is normal
 
 B<Important:> Note, that one record can be updated only once within a transaction - all subsequent updates are skipped. 
 
+=head1 DATABASE SELECTION
+
+Within a zebra repository you can define logical databases. You can either do this by record groups, or by providing the databaseName argument for update methods. For each record the database name it belongs to is stored. 
+
+For searching, you can select databases by calling:
+
+  $sess->databases('db1','db2');
+
+This will not do anything if the given and only the given databases are already selected. You can get the list of the actually selected databases, by calling:
+  
+  @dblist = $sess->databases();
+
 =head1 SEARCHING
 
+It's nice to be able to store data in your repository... But it's useful to reach it as well. So this is how to do searching:
+
+  $rs = $sess->search(databases => [qw(demo1,demo2)], # optional
+                      pqf       => '@attr 1=4 computer');
+
+This is going to execute a search in databases demo1 and demo2, for title 'com,puter'. This is a PQF (Prefix Query Format) search, see YAZ documentation for details. The database selection is optional: if it's provided, the given list of databases is selected for this particular search, then the original selection is restored.
+
+=head2 CCL searching
+
+Not all users enjoy typing in prefix query structures and numerical attribute values, even in a minimalistic test client. In the library world, the more intuitive Common Command Language (or ISO 8777) has enjoyed some popularity - especially before the widespread availability of graphical interfaces. It is still useful in applications where you for some reason or other need to provide a symbolic language for expressing boolean query structures. 
+
+The CCL searching is not currently supported by this API.
+
+=head2 CQL searching
+
+CQL - Common Query Language - was defined for the SRW protocol. In many ways CQL has a similar syntax to CCL. The objective of CQL is different. Where CCL aims to be an end-user language, CQL is the protocol query language for SRW. 
+
+In order to map CQL queries to Zebra internal search structures, you have to define a mapping, the way it is described in YAZ documentation: I<Specification of CQL to RPN mapping>. The mapping is interpreted by the method:
+
+  $sess->cqlmap($mapfile);
+
+Or, you can directly provide the I<mapfile> parameter for the search:
+
+  my $rs1 = $sess->search(cqlmap    => 'demo/cql.map',
+                         cql       => 'dc.title=IDZebra');
+
+As you see, CQL searching is so simple: just give the query in the I<cql> parameter.
+
+=head1 RESULTSETS
+
+As you have seen, the result of the search request is a I<Resultset> object.
+It contains number of hits, and search status, and can be used to sort and retrieve the resulting records.
+
+  $count = $rs->count;
+
+  printf ("RS Status is %d (%s)\n", $rs->errCode, $rs->errString);
+
+I<$rs-E<gt>errCode> is 0, if there were no errors during search. Read the I<IDZebra::Resultset> manpage for more details.
+
+=head1 MISC FUNCTIONS
 
 =head1 COPYRIGHT
 
index 592a316..9fec1e2 100755 (executable)
@@ -1,16 +1,16 @@
 #!/usr/bin/perl
-
+# =============================================================================
+# $Id: test.pl,v 1.7 2003-02-28 18:38:28 pop Exp $
+#
+# Perl API header
+# =============================================================================
 BEGIN {
+    use Test::More tests => 15;
     push (@INC,'demo','blib/lib','blib/arch');
+    use_ok('IDZebra::Session'); 
 }
-
 use pod;
 
-use Test::More tests => 15;
-
-BEGIN { 
-  use_ok('IDZebra::Session'); 
-}
 
 IDZebra::logFile("test.log");
 
@@ -33,6 +33,7 @@ my $sess = IDZebra::Session->open(configFile => 'demo/zebra.cfg',
                                  groupName  => 'demo1');
 isa_ok($sess,"IDZebra::Session");
 ok(defined($sess->{zh}), "Zebra handle opened");
+#use IDZebra::Repository;
 
 # ----------------------------------------------------------------------------
 # Record group tests
@@ -50,7 +51,7 @@ $sess->init();
 # ----------------------------------------------------------------------------
 # repository upadte
 
-our $filecount = 6;
+our $filecount = 5;
 
 $sess->begin_trans;
 $sess->update(path      =>  'lib');
@@ -65,7 +66,7 @@ $sess->update(groupName => 'demo1',
 
 my $stat = $sess->end_trans;
 ok(($stat->{inserted} == $filecount), 
-   "Inserted $stat->{updated}/$filecount records");
+   "Inserted $stat->{inserted}/$filecount records");
 
 $sess->begin_trans;
 $sess->delete(groupName => 'demo1',
@@ -97,13 +98,13 @@ my $s1=$sess->update_record(data       => $rec2,
 my $stat = $sess->end_trans;
 ok(($stat->{updated} == 1), "Updated 1 records");
 
-#exit;
 # ----------------------------------------------------------------------------
 # search
-$sess->select_databases('demo2');
-$sess->begin_read;
-my $rs1 = $sess->search(cqlmap => 'demo/cql.map',
-                       cql    => 'IDZebra');
+$sess->databases('demo2');
+#$sess->begin_read;
+my $rs1 = $sess->search(cqlmap    => 'demo/cql.map',
+                       cql       => 'IDZebra',
+                       databases => [qw(demo1 demo2)]);
 
 print STDERR "$rs1->{recordCount} hits.\n";
 
index 94f65ed..0712d5f 100644 (file)
@@ -318,6 +318,8 @@ void record_retrieve(RetrievalObj *ro,
   res->buf        = buf;
   res->buf->len   = ro->records[i].len;
   res->buf->buf   = ro->records[i].buf;
+  res->score      = ro->records[i].score;
+  res->sysno      = ro->records[i].sysno;
 
 }
 
@@ -489,6 +491,7 @@ void api_records_retrieve (ZebraHandle zh, ODR stream,
                recs[i].len = strlen(poset[i].term);
                recs[i].buf = poset[i].term;
                recs[i].base = poset[i].db;
+               recs[i].sysno = 0;
            
            }
            else if (poset[i].sysno)
@@ -505,6 +508,8 @@ void api_records_retrieve (ZebraHandle zh, ODR stream,
                recs[i].buf = (char *) odr_malloc(stream,recs[i].len);
                memcpy(recs[i].buf, b, recs[i].len);
                recs[i].errString = NULL;
+               recs[i].sysno = poset[i].sysno;
+               recs[i].score = poset[i].score;
            }
            else
            {
index 9b49303..7020563 100644 (file)
@@ -29,6 +29,8 @@ typedef struct {
   char *errString;     /* error string */
   int  position;       /* position of record in result set (1,2,..) */
   char *base; 
+  int  sysno;
+  int  score;
   oid_value format;    /* record syntax */
   RetrievalRecordBuf *buf;
 } RetrievalRecord;