[Bio] / Sprout / DBQuery.pm Repository:
ViewVC logotype

View of /Sprout/DBQuery.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.5 - (download) (as text) (annotate)
Sun Mar 26 17:24:55 2006 UTC (13 years, 8 months ago) by parrello
Branch: MAIN
Changes since 1.4: +10 -4 lines
Enhanced to enable objects to appear more than once in a single Get call.

package DBQuery;

    use strict;
    use DBKernel;
    use DBObject;
    use DBI;
    use Tracer;

=head1 Entity-Relationship Database Package Query Iterator

=head2 Introduction

This package defines the Iteration object for an Entity-Relationship Database. The iteration object
represents a filtered SELECT statement against an Entity-Relationship Database, and provides
methods for getting the appropriate records.

There are two common ways an iteration object can be created. An I<entity iterator> is created when the
client asks for objects of a given entity type. A I<relationship iterator> is created when the
client asks for objects across a relationship starting from a specific entity instance. The
entity iterator returns a single object at each position; the relationship iterator returns two 
objects at each position-- one for the target entity, and one for the relationship instance
that connects it to the source entity.

For example, a client could ask for all B<Feature> instances that are marked active. This would 
return an entity iterator. Each position in the iteration would consist of a single
B<Feature> instance. From a specific B<Feature> instance, the client could decide to cross the
B<IsLocatedIn> relationship to get all the B<Contig> instances which contain residues that
participate in the feature. This would return a relationship iterator. Each position in the
iterator would contain a single B<IsLocatedIn> instance and a single B<Contig> instance.

At each point in the result set, the iterator returns a B<DBObject>. The DBObject allows the
client to access the fields of the current entity or relationship instance.

It is also possible to ask for many different objects in a single iterator by chaining long
sequences of entities together by relationships. This is discussed in the documentation for the 
B<ERDB> object's C<Get> method.

Finally, objects of this type should never by created directly. Instead, they are created
by the aforementioned C<Get> method and the B<DBObject>'s C<Cross> method.

=head2 Public Methods

=head3 Fetch

C<< my $dbObject = $dbQuery->Fetch(); >>

Retrieve a record from this query. The record returned will be a B<DBObject>, which
may represent a single entity instance or a list of entity instances joined by relationships.
The first time this method is called it will return the first result from query. After that it
will continue sequentially. It will return an undefined value if we've reached the end of the
result set. 

=cut

sub Fetch {
    # Get the parameters;
    my ($self) = @_;
    # Declare the return variable.
    my $retVal;
    # Fetch the next row in the query result set.
    my $sth = $self->{_sth};
    my @row = $sth->fetchrow;
    # Check to see if we got any results.
    if (@row == 0) {
        Trace("No result from query.") if T(3);
        # Here we have no result. If we're at the end of the result set, this is okay, because
        # we'll be returning an undefined value in $retVal. If an error occurred, we need to abort.
        if ($sth->err) {
            Confess("FETCH error");
        }
    } else {
        # Here we have a result, so we need to turn it into an instance object.
        $retVal = DBObject::_new($self->{_db}, $self->{_objectNames}, @row);
        Trace("Row returned from query.") if T(4);
    }
    # Return the result.
    return $retVal;
}

=head2 Utility Methods

=head3 new (internal)

Create a new query object.

This is a static method.

=over 4

=item database

ERDB object for the relevant database.

=item sth

Statement handle for the SELECT clause generated by the query.

=item relationMap

Reference to a list of 2-tuples. Each tuple consists of an object name as used in the
query followed by the actual name of that object. This enables the B<DBObject> to
determine the order of the tables in the query and which object name belongs to each
mapped object name. Most of the time these two values are the same; however, if a
relation occurs twice in the query, the relation name in the field list and WHERE
clause will use a mapped name (generally the actual relation name with a numeric
suffix) that does not match the actual relation name.

=back

=cut

sub _new {
    # Get the parameters.
    my ($database, $sth, $relationMap) = @_;
    # Create this object.
    my $self = { _db => $database, _sth => $sth, _objectNames => $relationMap};
    # Bless and return it.
    bless $self;
    return $self;
}

1;

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3