// @file queryoptimizercursor.h - Interface for a cursor interleaving multiple candidate cursors. /** * Copyright (C) 2011 10gen Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #pragma once #include "cursor.h" #include "diskloc.h" #include "projection.h" namespace mongo { class QueryPlan; /** * An interface for policies overriding the query optimizer's default query plan selection * behavior. */ class QueryPlanSelectionPolicy { public: virtual ~QueryPlanSelectionPolicy() {} virtual string name() const = 0; virtual bool permitOptimalNaturalPlan() const { return true; } virtual bool permitOptimalIdPlan() const { return true; } virtual bool permitPlan( const QueryPlan &plan ) const { return true; } virtual BSONObj planHint( const char *ns ) const { return BSONObj(); } /** Allow any query plan selection, permitting the query optimizer's default behavior. */ static const QueryPlanSelectionPolicy &any(); /** Prevent unindexed collection scans. */ static const QueryPlanSelectionPolicy &indexOnly(); /** * Generally hints to use the _id plan, falling back to the $natural plan. However, the * $natural plan will always be used if optimal for the query. */ static const QueryPlanSelectionPolicy &idElseNatural(); private: class Any; static Any __any; class IndexOnly; static IndexOnly __indexOnly; class IdElseNatural; static IdElseNatural __idElseNatural; }; class QueryPlanSelectionPolicy::Any : public QueryPlanSelectionPolicy { public: virtual string name() const { return "any"; } }; class QueryPlanSelectionPolicy::IndexOnly : public QueryPlanSelectionPolicy { public: virtual string name() const { return "indexOnly"; } virtual bool permitOptimalNaturalPlan() const { return false; } virtual bool permitPlan( const QueryPlan &plan ) const; }; class QueryPlanSelectionPolicy::IdElseNatural : public QueryPlanSelectionPolicy { public: virtual string name() const { return "idElseNatural"; } virtual bool permitPlan( const QueryPlan &plan ) const; virtual BSONObj planHint( const char *ns ) const; }; class FieldRangeSet; class ExplainQueryInfo; /** * Adds functionality to Cursor for running multiple plans, running out of order plans, * utilizing covered indexes, and generating explain output. */ class QueryOptimizerCursor : public Cursor { public: /** Summarizes the candidate plans that may run for a query. */ class CandidatePlans { public: CandidatePlans( bool mayRunInOrderPlan, bool mayRunOutOfOrderPlan ) : _mayRunInOrderPlan( mayRunInOrderPlan ), _mayRunOutOfOrderPlan( mayRunOutOfOrderPlan ) { } CandidatePlans() : _mayRunInOrderPlan(), _mayRunOutOfOrderPlan() { } bool mayRunInOrderPlan() const { return _mayRunInOrderPlan; } bool mayRunOutOfOrderPlan() const { return _mayRunOutOfOrderPlan; } bool valid() const { return mayRunInOrderPlan() || mayRunOutOfOrderPlan(); } bool hybridPlanSet() const { return mayRunInOrderPlan() && mayRunOutOfOrderPlan(); } private: bool _mayRunInOrderPlan; bool _mayRunOutOfOrderPlan; }; /** Candidate plans for the query before it begins running. */ virtual CandidatePlans initialCandidatePlans() const = 0; /** FieldRangeSet for the query before it begins running. */ virtual const FieldRangeSet *initialFieldRangeSet() const = 0; /** @return true if the plan for the current iterate is out of order. */ virtual bool currentPlanScanAndOrderRequired() const = 0; /** @return the covered index projector for the current iterate (may be 0). */ virtual const Projection::KeyOnly *keyFieldsOnly() const = 0; /** @return true when there may be multiple plans running and some are in order. */ virtual bool runningInitialInOrderPlan() const = 0; /** * @return true when a cached plan is running, but it has not been selected for the * remainder of the query. */ virtual bool runningInitialCachedPlan() const = 0; /** * @return true when both in order and out of order candidate plans were available, and * an out of order candidate plan completed iteration. */ virtual bool completePlanOfHybridSetScanAndOrderRequired() const = 0; /** Clear recorded indexes for the current clause's query patterns. */ virtual void clearIndexesForPatterns() = 0; /** Stop returning results from out of order plans and do not allow them to complete. */ virtual void abortOutOfOrderPlans() = 0; /** Note match information for the current iterate, to generate explain output. */ virtual void noteIterate( bool match, bool loadedDocument, bool chunkSkip ) = 0; /** @return explain output for the query run by this cursor. */ virtual shared_ptr explainQueryInfo() const = 0; }; } // namespace mongo