| RDF-Query documentation | Contained in the RDF-Query distribution. |
RDF::Query::Plan::Sort - Executable query plan for Sorts.
This document describes RDF::Query::Plan::Sort version 2.907.
Beyond the methods documented below, this class inherits methods from the RDF::Query::Plan class.
new ( $pattern, [ $expr1, $rev1 ], ... )execute ( $execution_context )nextclosepatternReturns the query plan that will be used to produce the data to be sorted.
distinctReturns true if the pattern is guaranteed to return distinct results.
orderedReturns true if the pattern is guaranteed to return ordered results.
plan_node_nameReturns the string name of this plan node, suitable for use in serialization.
plan_prototypeReturns a list of scalar identifiers for the type of the content (children) nodes of this plan node. See RDF::Query::Plan for a list of the allowable identifiers.
plan_node_dataReturns the data for this plan node that corresponds to the values described by
the signature returned by plan_prototype.
graph ( $g )explainReturns a string serialization of the plan appropriate for display on the command line.
Gregory Todd Williams <gwilliams@cpan.org>
| RDF-Query documentation | Contained in the RDF-Query distribution. |
# RDF::Query::Plan::Sort # -----------------------------------------------------------------------------
package RDF::Query::Plan::Sort; use strict; use warnings; use base qw(RDF::Query::Plan); ###################################################################### our ($VERSION); BEGIN { $VERSION = '2.907'; } ######################################################################
sub new { my $class = shift; my $plan = shift; my @exprs = @_; foreach my $e (@exprs) { $e->[1] ||= 0; } my $self = $class->SUPER::new( $plan, \@exprs ); $self->[0]{referenced_variables} = [ $plan->referenced_variables ]; return $self; }
sub execute ($) { my $self = shift; my $context = shift; if ($self->state == $self->OPEN) { throw RDF::Query::Error::ExecutionError -text => "SORT plan can't be executed while already open"; } my $plan = $self->[1]; $plan->execute( $context ); my $l = Log::Log4perl->get_logger("rdf.query.plan.sort"); $l->trace("executing sort"); if ($plan->state == $self->OPEN) { my $exprs = $self->[2]; my @rows = $plan->get_all; if ($l->is_trace) { $l->trace("sorting result list:"); $l->trace("- $_") foreach (@rows); } my $query = $context->query; use sort 'stable'; my @sorted = sort { _cmp_rows( $context, $exprs, $a, $b ) } @rows; if ($l->is_trace) { $l->trace("sorted list:"); $l->trace("- $_") foreach (@sorted); } $self->[0]{rows} = \@sorted; $self->state( $self->OPEN ); } else { warn "could not execute plan in distinct"; } $self; }
sub next { my $self = shift; unless ($self->state == $self->OPEN) { throw RDF::Query::Error::ExecutionError -text => "next() cannot be called on an un-open SORT"; } return shift(@{ $self->[0]{rows} }); }
sub close { my $self = shift; unless ($self->state == $self->OPEN) { throw RDF::Query::Error::ExecutionError -text => "close() cannot be called on an un-open SORT"; } delete $self->[0]{rows}; $self->[1]->close(); $self->SUPER::close(); } sub _cmp_rows { my $context = shift; my $exprs = shift; my $a = shift; my $b = shift; my $l = Log::Log4perl->get_logger("rdf.query.plan.sort"); my $query = $context->query || 'RDF::Query'; my $bridge = $context->model; no warnings 'numeric'; no warnings 'uninitialized'; foreach my $data (@$exprs) { my ($expr, $rev) = @$data; my $a_val = $query->var_or_expr_value( $a, $expr, $context ); my $b_val = $query->var_or_expr_value( $b, $expr, $context ); local($RDF::Query::Node::Literal::LAZY_COMPARISONS) = 1; $l->trace("comparing $a_val <=> $b_val"); my $cmp = $a_val <=> $b_val; if ($cmp != 0) { if ($rev) { $cmp *= -1; } $l->trace("==> $cmp"); return $cmp; } else { } } $l->trace("==> 0"); return 0; }
sub pattern { my $self = shift; return $self->[1]; }
sub distinct { my $self = shift; return $self->pattern->distinct; }
sub ordered { my $self = shift; my $sort = $self->[2]; return [ map { [ $_->[0], ($_->[1] ? 'DESC' : 'ASC') ] } @$sort ]; }
sub plan_node_name { return 'order'; }
sub plan_prototype { my $self = shift; return qw(P *\wE); }
sub plan_node_data { my $self = shift; my $exprs = $self->[2]; return ($self->pattern, map { [ ($_->[1] == 0 ? 'asc' : 'desc'), $_->[0] ] } @$exprs); }
sub graph { my $self = shift; my $g = shift; my $c = $self->pattern->graph( $g ); my $expr = join(' ', map { $_->sse( {}, "" ) } @{ $self->[2] }); $g->add_node( "$self", label => "Sort ($expr)" . $self->graph_labels ); $g->add_edge( "$self", $c ); return "$self"; }
sub explain { my $self = shift; my $s = shift; my $count = shift; my $indent = $s x $count; my $type = $self->plan_node_name; my $string = "${indent}${type}\n"; $string .= "${indent}${s}sory by:\n"; my $exprs = $self->[2]; foreach my $e (@$exprs) { my $dir = ($e->[1] == 0 ? 'asc ' : 'desc '); $string .= "${indent}${s}${s}${dir}" . $e->[0] . "\n"; } $string .= $self->pattern->explain( $s, $count+1 ); return $string; } 1; __END__