All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bigdata.bop.join.NestedLoopJoinOp Maven / Gradle / Ivy

/**

Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016.  All rights reserved.

Contact:
     SYSTAP, LLC DBA Blazegraph
     2501 Calvert ST NW #106
     Washington, DC 20008
     [email protected]

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
/*
 * Created on Aug 25, 2010
 */

package com.bigdata.bop.join;

import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

import com.bigdata.bop.BOp;
import com.bigdata.bop.BOpContext;
import com.bigdata.bop.BOpUtility;
import com.bigdata.bop.IBindingSet;
import com.bigdata.bop.IConstraint;
import com.bigdata.bop.IVariable;
import com.bigdata.bop.NV;
import com.bigdata.bop.PipelineOp;
import com.bigdata.bop.controller.INamedSolutionSetRef;
import com.bigdata.bop.controller.NamedSetAnnotations;
import com.bigdata.bop.engine.BOpStats;
import com.bigdata.relation.accesspath.IBlockingBuffer;
import com.bigdata.relation.accesspath.UnsyncLocalOutputBuffer;

import cutthecrap.utils.striterators.ICloseableIterator;

/**
 * This operator performs a nested loop join for solutions. Intermediate
 * solutions read from the pipeline are joined against a scan of some other
 * solution set. This operator is useful when the cardinality of the source
 * solutions in the pipeline is low (typically one empty source solution which
 * is exogenous to the query, but it is also cost efficient when there is a
 * small set of source solutions to be tested for each solution drained from the
 * named solution set). As the number of source solutions to be drained from the
 * pipeline grows, it eventually becomes cheaper to build a hash index over the
 * named solution set and perform a hash join with the source solutions.
 * 

* Note: This operator MUST NOT reorder the solutions which are being scanned * from the named solution set. The query planner relies on that behavior to * optimize a SLICE from a pre-computed named solution set. *

* * @see * SPARQL Update * * @see SPARQL * UPDATE for SOLUTION SETS * * @author Bryan Thompson * @version $Id: CopyOp.java 6010 2012-02-10 20:11:20Z thompsonbry $ * * TODO This join does not implement optional semantics. If a use case * for a nested loop join with optional semantics is identified at some * point, then we will have to add support for optional here (and in * the test suite). */ public class NestedLoopJoinOp extends PipelineOp { /** * */ private static final long serialVersionUID = 1L; public interface Annotations extends JoinAnnotations, NamedSetAnnotations { // /** // * The name of the pre-existing named solution set to be scanned. // */ // String NAME = NestedLoopJoinOp.class.getName() + ".name"; } /** * Deep copy constructor. * * @param op */ public NestedLoopJoinOp(final NestedLoopJoinOp op) { super(op); } /** * Shallow copy constructor. * * @param args * @param annotations */ public NestedLoopJoinOp(final BOp[] args, final Map annotations) { super(args, annotations); // MUST be given. getRequiredProperty(Annotations.NAMED_SET_REF); } public NestedLoopJoinOp(final BOp[] args, final NV... annotations) { this(args, NV.asMap(annotations)); } // /** // * @see Annotations#NAME // */ // protected String getName() { // // return (String) getRequiredProperty(Annotations.NAME); // // } /** * @see Annotations#SELECT */ protected IVariable[] getSelect() { return getProperty(Annotations.SELECT, null/* defaultValue */); } /** * @see Annotations#CONSTRAINTS */ protected IConstraint[] constraints() { return getProperty(Annotations.CONSTRAINTS, null/* defaultValue */); } public FutureTask eval(final BOpContext context) { return new FutureTask(new ChunkTask(this, context)); } /** * Copy the source to the sink. */ static private class ChunkTask implements Callable { private final NestedLoopJoinOp op; private final BOpContext context; ChunkTask(final NestedLoopJoinOp op, final BOpContext context) { this.op = op; this.context = context; } @Override public Void call() throws Exception { final BOpStats stats = context.getStats(); // Convert source solutions to array (assumes low cardinality). final IBindingSet[] leftSolutions = BOpUtility.toArray( context.getSource(), stats); // default sink final IBlockingBuffer sink = context.getSink(); final UnsyncLocalOutputBuffer unsyncBuffer = new UnsyncLocalOutputBuffer( op.getChunkCapacity(), sink); final IVariable[] selectVars = op.getSelect(); final IConstraint[] constraints = op.constraints(); final ICloseableIterator ritr = getRightSolutions(); try { while (ritr.hasNext()) { final IBindingSet[] a = ritr.next(); for (IBindingSet right : a) { for (IBindingSet left : leftSolutions) { // See if the solutions join. final IBindingSet outSolution = BOpContext.bind(// right,// left,// constraints,// selectVars// ); if (outSolution != null) { // Output the solution. unsyncBuffer.add(outSolution); } } } } // flush the unsync buffer. unsyncBuffer.flush(); // flush the sink. sink.flush(); // Done. return null; } finally { sink.close(); context.getSource().close(); if (ritr != null) ritr.close(); } } /** * Return the right solutions. */ protected ICloseableIterator getRightSolutions() { final INamedSolutionSetRef namedSetRef = (INamedSolutionSetRef) op .getRequiredProperty(Annotations.NAMED_SET_REF); return context.getAlternateSource(namedSetRef); } } // class ChunkTask }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy