# ====================================================================
# Gossamer Threads Module Library - http://gossamer-threads.com/
#
#   GT::SQL::Search::STH
#   Author: Aki Mimoto
#   CVS Info : 087,071,086,086,085      
#   CVS Info : 087,071,086,086,085      
#   $Id: STH.pm,v 1.1 2006/12/07 07:04:51 aki Exp $
#
# Copyright (c) 2004 Gossamer Threads Inc.  All Rights Reserved.
# ====================================================================
#

package GT::SQL::Search::LUCENE::STH;
#--------------------------------------------------------------------------------
use strict;
use vars qw/@ISA $ATTRIBS $VERSION $DEBUG $ERRORS $ERROR_MESSAGE /;
require GT::SQL::Search::Base::STH;

@ISA = ('GT::SQL::Search::STH');
$ATTRIBS = {
    'db_sort' => 1,
    'hits'    => undef
};
$ERROR_MESSAGE = 'GT::SQL::Search::STH';



sub init {
#--------------------------------------------------------------------------------
# GT::SQL::Search::STH expects a full set of results in $self->{results}. For
# Lucene the only time a full set of results is there is when we are sorting
# on a field that is not weighted, otherwise the results in $self->{results} is
# the proper page and number of results.
    my $self    = shift;

    $self->set(@_);

    --$self->{nh} if $self->{nh};

    # Here we allow hits to override our concept of rows. This is only useful
    # when !$self->{db_sort}
    $self->{rows} = $self->{hits}
        ? $self->{hits}
        : $self->{results}
            ? scalar(keys %{$self->{results}})
            : 0;

    if ($self->{db_sort}) {
        $self->get_db_sorted_results;
    }
    else {
        $self->get_sorted_results;
    }
}

sub get_sorted_results {
# Just sorts the results out of $self->{results} which should have been setup
# by a search driver
    my ($self) = @_;
    my $results = $self->{results};
    $self->{index} = 0;
    $self->{max_index} = $self->{mh} - 1;
    $self->{'order'}  = [ sort { 
                                    ( $results->{$b} || return 0 ) <=> ( $results->{$a} || 0 )
                              } keys %{$results} ];
    $self->debug_dumper( "Results will be presented in the following order: ", $self->{'order'} ) if ($self->{_debug});
}

sub get_db_sorted_results {
# This assumes $self->{results} has a full result set, i.e. without any LIMIT
# It then selects the result set using the SQL driver to do the sorting. This
# is for Search modules which can not handle their own sorting
    my ($self) = @_;

    my $sb = GT::SQL::Search::Base::Search->clean_sb($self->{sb}, $self->{so});
    $self->{index}  = $self->{nh} * $self->{mh} || 0;
    $self->{max_index} = $self->{index} + $self->{mh} - 1; # index + mh is the first record which should not be returned.
    if ($self->{max_index} > $self->{rows}) {
        $self->{max_index}  = $self->{rows};
        $self->{rows}       = $self->{rows} - $self->{index};
        $self->{rows} < 0 ? $self->{rows} = 0 : 0;
    }

    else {
        $self->{rows}       = $self->{mh};
    }
    my ( $table, $pk ) = $self->_table_info();
    my ( $query, $where, $st, $limit );

    $where      = qq!$pk in(! . join( ",", keys %{$self->{results}}) . ')';
    $self->{mh} and $limit = qq!LIMIT $self->{index}, $self->{rows}!;
    $query      = qq!
        SELECT $pk
        FROM   $table
        WHERE  $where
        $sb
        $limit
    !;
    $self->debug( "Row fetch query: $query" ) if ($self->{_debug});
    my $sth        = $self->{table}->{driver}->prepare( $query );
    $sth->execute();

    $self->{index}    = 0;
    $self->{max_hits} = $self->{rows};

    # Fetch the results in sorted order
    my $order = $sth->fetchall_arrayref();
    $sth->finish();

    $self->{'order'}  = [ map { $_->[0] } @{$order} ];
}

1;

