#
# IPtoLL
#
# Robert Olson
# olson@mcs.anl.gov
# Argonne National Laboratory
# September, 1996
#
# Please keep this heading attached to the file it heads.
#

package DBQuery;

use Carp;
use strict;
#use vars qw(@ISA);

=head1 NAME
MTk::DBQuery - db query obj

=head1 DESCRIPTION

A MTK::DBQuery object encapsulates the result of a query against
a databsae. It is intended to be database-independent.

=cut

=head2 $dbq = new MTk::DBQuery($query, $vars, $rows)

DBQuery constructor, intended to be called from the layer-1 database
interface. $vars is a ref to an array of column names for the query
result.  $rows is a ref to an array of array-refs representing the
result of the query. $query is the text of the query itself.

=cut

sub new
{
    my($class, $query, $vars, $rows) = @_;
    my($self, $i);

    $self = {
	vars => $vars,
	rows => $rows,
	query => $query,
	name_idx => {},
    };

    for ($i = 0; $i < @$vars; $i++)
    {
	$self->{name_idx}->{$vars->[$i]} = $i;
    }

    bless($self, $class);
    return $self;
}

=head2 $query->n_rows()

Returns the number of rows in the query result.

=cut

sub n_rows
{
    my($self) = @_;

    return int(@{$self->{rows}});
}

=head2 $val = $query->item($row_idx, $col_id)

Retrieve a specific item from the query. $row_idx is the index of the
row from which to retrieve the value. $col_id is the column identifier
for the item. The column identifier can be either a number, in which
case it is treated as a column index, or a string, in which case it is
treated as the name of a column.

=cut

sub item
{
    my($self, $row_idx, $col_idx) = @_;
    my($row);

    #
    # If we're accessing a named column...
    #
    if ($col_idx !~ /^\d+$/)
    {
	my $i = $self->{name_idx}->{$col_idx};
	if (!defined($i))
	{
	    carp "no item for $col_idx";
	    return undef;
	}
	$col_idx = $i;
    }

    if ($row_idx < 0 or $row_idx >= @{$self->{rows}})
    {
	Carp::carp "invalid row_idx $row_idx";
	return undef;
    }

    $row = $self->{rows}->[$row_idx];

    return $row->[$col_idx];
}

=head2 $row = $query->row_list($row_idx)

Return the values in row $row_idx. Return value is a reference to an
array. 

=cut

sub row_list
{
    my($self, $row_idx) = @_;
    my($h);

    if ($row_idx < 0 or $row_idx >= @{$self->{rows}})
    {
	carp "invalid row_idx $row_idx";
	return undef;
    }

    return $self->{rows}->[$row_idx];
}

=head2 $row = $query->row_hash($row_idx)

Return the values in row $row_idx. Return value is a reference to a
hash whose keys are column names.

=cut

sub row_hash
{
    my($self, $row_idx) = @_;
    
    if ($row_idx < 0 or $row_idx >= @{$self->{rows}})
    {
	carp "invalid row_idx $row_idx";
	return undef;
    }

    my($h, $n);
    $h = {};
    for $n (keys %{$self->{name_idx}})
    {
	$h->{$n} = $self->item($row_idx, $n);
    }
    return $h;
}

=head2 $row_lists = $query->row_lists()

Return all rows. The return value is a reference to an array of
rows. Each row in that array is itself a reference to an array of
column values.

=cut

sub row_lists
{
    my($self) = @_;
    my($i, $n);
    my($rc);

    $n = $self->n_rows();

    $rc = [];

    for ($i = 0; $i < $n; $i++)
    {
	push(@$rc, $self->row_list($i));
    }

    return $rc;
}

=head2 $row_hashes = $query->row_hashes()

Return all rows. The return value is a reference to an array of
rows. Each row in that array is a reference to a hash whose key is the
column name.

=cut

sub row_hashes
{
    my($self) = @_;
    my($i, $n);
    my($rc);

    $n = $self->n_rows();

    $rc = [];

    for ($i = 0; $i < $n; $i++)
    {
	push(@$rc, $self->row_hash($i));
    }

    return $rc;
}

1;
