| // ********************************************************************** |
| // @@@ START COPYRIGHT @@@ |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| // @@@ END COPYRIGHT @@@ |
| // ********************************************************************** |
| |
| // *********************************************************************** |
| // |
| // File: MatchOutput.h |
| // Description: |
| // |
| // |
| // |
| // |
| // Created: 08/26/08 |
| // *********************************************************************** |
| |
| #include "QRSharedPtr.h" |
| |
| // Forward declarations |
| class RewriteInstructionsItem; |
| class compositeMatchingResults; |
| class MatchTest; |
| class MatchOutput; |
| class MatchRangePredicates; |
| class MatchResidualPredicates; |
| class MatchGroupingColumns; |
| class MatchJoinPreds; |
| class MatchOuterJoins; |
| class AggregateCollectorVisitor; |
| |
| #ifdef _MEMSHAREDPTR |
| typedef QRIntrusiveSharedPtr<RewriteInstructionsItem> RewriteInstructionsItemPtr; |
| typedef QRIntrusiveSharedPtr<compositeMatchingResults> compositeMatchingResultsPtr; |
| typedef QRIntrusiveSharedPtr<MatchOutput> MatchOutputPtr; |
| typedef QRIntrusiveSharedPtr<MatchRangePredicates> MatchRangePredicatesPtr; |
| typedef QRIntrusiveSharedPtr<MatchResidualPredicates> MatchResidualPredicatesPtr; |
| typedef QRIntrusiveSharedPtr<MatchGroupingColumns> MatchGroupingColumnsPtr; |
| typedef QRIntrusiveSharedPtr<MatchJoinPreds> MatchJoinPredsPtr; |
| typedef QRIntrusiveSharedPtr<MatchOuterJoins> MatchOuterJoinsPtr; |
| typedef QRIntrusiveSharedPtr<AggregateCollectorVisitor> AggregateCollectorVisitorPtr; |
| #else |
| typedef RewriteInstructionsItem* RewriteInstructionsItemPtr; |
| typedef compositeMatchingResults* compositeMatchingResultsPtr; |
| typedef MatchOutput* MatchOutputPtr; |
| typedef MatchRangePredicates* MatchRangePredicatesPtr; |
| typedef MatchResidualPredicates* MatchResidualPredicatesPtr; |
| typedef MatchGroupingColumns* MatchGroupingColumnsPtr; |
| typedef MatchJoinPreds* MatchJoinPredsPtr; |
| typedef MatchOuterJoins* MatchOuterJoinsPtr; |
| typedef AggregateCollectorVisitor* AggregateCollectorVisitorPtr; |
| #endif |
| |
| typedef StringPtrSet IDSet; |
| typedef NAPtrList<RewriteInstructionsItemPtr> RewriteInstructionsItemList; |
| typedef NAPtrList<QRFunctionPtr> FunctionNodesList; |
| typedef NAPtrList<QRColumnPtr> ColumnNodesList; |
| typedef NAPtrList<QRJoinPredPtr> JoinPredNodesList; |
| typedef SharedPtrValueHash<const NAString, RewriteInstructionsItem> OutputsHash; |
| typedef NAHashDictionary<const NAString, const NAString> IDHash; |
| |
| #ifndef _MATCHOUTPUT_H_ |
| #define _MATCHOUTPUT_H_ |
| |
| #include "QRDescriptor.h" |
| #include "QmsMVCandidate.h" |
| |
| // Add a few intermediate result codes to QRElement::ExprResult |
| enum ResultCode { |
| RC_OUTSIDE = QRElement::Outside, |
| RC_PROVIDED = QRElement::Provided, |
| RC_NOTPROVIDED = QRElement::NotProvided, |
| RC_REJECT, // MV was disqualified |
| RC_CONTINUE, // Not found yet, continue matching. |
| RC_EXTRAHUB, // Used by output list |
| RC_BACKJOIN, // Used by output list |
| RC_INDIRECT, // Used by output list |
| RC_INPUTS_PROVIDED, // Secondary: The expression inputs are provided. |
| RC_EXPR_REWRITE, // Secondary: The expression should be rewritten using an alternative expression. |
| RC_MATCH_RANGE, // Match range preds in Pass 2. |
| RC_SKIP_ME, // This element has already been handled so ignore it (but don't reject it). |
| RC_ROLLUP, // Rollup of an aggregate function. |
| RC_ROLLUP_EXPR, // Rollup of an aggregate expression. |
| RC_AGGR_EXPR, // Complex aggregate expression. |
| RC_ROLLUP_ON_GROUPING, // Rollup over a grouping column. |
| RC_NO_INPUTS, // An expression with no input columns |
| RC_INVALID_RESULT |
| }; |
| |
| enum ResultStatus { |
| RS_FINAL, |
| RS_INTERMEDIATE |
| }; |
| |
| /** |
| * This class is used to store intermediate rewrite instructions, that are |
| * produced by the matching algorithms, for elements such as an output expression, |
| * a range or residual predicate. Each object contains the following: |
| * - The element from the query descriptor that is rewritten. |
| * - The element from the MV descriptor that is used for this rewrite (optional) |
| * - The result code (Provided, NotProvided, Outside etc.) |
| * - Is the rewrite for this query element final. |
| * - Expression rewrites may have sub-elements. |
| * For final rewrites, the result code must be one of the QRElement results, |
| * and no further matching is needed. |
| * For non-final rewrites, another pass of matching is required to finalize it. |
| ***************************************************************************** |
| */ |
| class RewriteInstructionsItem : public NAIntrusiveSharedPtrObject |
| { |
| public: |
| /** |
| * RewriteInstructionsItem constructor |
| * @param queryElement The query element to be rewritten |
| * @param mvElement The (optional) MV element used for the rewrite |
| * @param resultCode The result code |
| * @param status Is the rewrite final or intermediate. |
| * @param heap The heap from which to allocate memory. |
| */ |
| RewriteInstructionsItem(const QRElementPtr queryElement, |
| const QRElementPtr mvElement, |
| ResultCode resultCode, |
| ResultStatus status, |
| ADD_MEMCHECK_ARGS_DECL(CollHeap* heap)); |
| |
| |
| /** |
| * Copy constructor |
| */ |
| RewriteInstructionsItem(const RewriteInstructionsItem& other, |
| ADD_MEMCHECK_ARGS_DECL(CollHeap* heap)); |
| |
| virtual ~RewriteInstructionsItem(); |
| |
| NABoolean operator==(const RewriteInstructionsItem& other) |
| { |
| // Do a pointer comparison. |
| return this == &other; |
| } |
| |
| /** |
| * Get the query element that is rewritten |
| * @return |
| */ |
| const QRElementPtr getQueryElement() |
| { |
| return queryElement_; |
| } |
| |
| /** |
| * Get the query element that is rewritten |
| * If its an Output element, return the output item inside it. |
| * @return |
| */ |
| const QRElementPtr getActualQueryElement() |
| { |
| QRElementPtr queryElem = getQueryElement(); |
| if (queryElem->getElementType()== ET_Output) |
| queryElem = queryElem->downCastToQROutput()->getOutputItem()->getReferencedElement(); |
| return queryElem; |
| } |
| |
| /** |
| * Get the MV element that is used to rewrite the query element. |
| * @return |
| */ |
| const QRElementPtr getMvElement() |
| { |
| return mvElement_; |
| } |
| |
| /** |
| * Get the result code |
| * @return |
| */ |
| ResultCode getResultCode() |
| { |
| return resultCode_; |
| } |
| |
| /** |
| * Return a string corresponding to the result code. |
| * Used for debugging only. |
| * @return A pointer to the name of the result code. |
| */ |
| static const char* getResultString(ResultCode rc); |
| |
| const char* getResultString(); |
| |
| /** |
| * Is the rewrite final? |
| * @return |
| */ |
| NABoolean isFinal() |
| { |
| return status_ == RS_FINAL; |
| } |
| |
| /** |
| * Get the result status (Final ot Intermediate) |
| * @return |
| */ |
| ResultStatus getResultStatus() |
| { |
| return status_; |
| } |
| |
| /** |
| * Set the result status (Final ot Intermediate) |
| * @param status |
| */ |
| void setResultStatus(ResultStatus status) |
| { |
| status_ = status; |
| } |
| |
| /** |
| * Get the secondary result code |
| * @return |
| */ |
| ResultCode getSecondaryResultCode() |
| { |
| return secondaryResultCode_; |
| } |
| |
| /** |
| * Get the list of rewrite instructions for sub-elements |
| * @return |
| */ |
| compositeMatchingResultsPtr getSubElements() |
| { |
| return subElements_; |
| } |
| |
| /** |
| * Does this object include any rewrite instructions for sub-elements? |
| * @return |
| */ |
| NABoolean hasSpecialSubElement() |
| { |
| return extraHubTables_.entries()>0 || backJoinTables_.entries()>0; |
| } |
| |
| /** |
| * Set the secondary result code |
| * @param rc |
| */ |
| void setSecondaryResultCode(ResultCode rc) |
| { |
| secondaryResultCode_ = rc; |
| } |
| |
| /** |
| * Add an optional sub-element. |
| * @param subElement |
| */ |
| void addSubElement(RewriteInstructionsItemPtr subElement); |
| |
| /** |
| * Add a list of rewrite instructions for sub-elements. |
| * @param subElements |
| * @param isSpecial Are these of a type that requires special consideration |
| * such as Back-Join or Extra-Hub? |
| */ |
| void addSubElements(const RewriteInstructionsItemList& subElements, NABoolean isSpecial); |
| |
| |
| /** |
| * Add a list of rewrite instructions for sub-elements. |
| * @param subElements |
| */ |
| void addSubElements(compositeMatchingResultsPtr other); |
| |
| /** |
| * Set the query element of the rewrite instructions |
| * @param queryElement |
| */ |
| void setQueryElement(const QRElementPtr queryElement) |
| { |
| queryElement_ = queryElement; |
| } |
| |
| /** |
| * Set the query element of the rewrite instructions |
| * @param queryElement |
| */ |
| void setMvElement(const QRElementPtr mvElement) |
| { |
| mvElement_ = mvElement; |
| } |
| |
| /** |
| * Set the result code. |
| * @param rc |
| */ |
| void setResultCode(ResultCode rc) |
| { |
| resultCode_ = rc; |
| } |
| |
| /** |
| * Get the final result code for use in the descriptor. |
| * @return |
| */ |
| QRElement::ExprResult getDescriptorResultCode() |
| { |
| switch (resultCode_) |
| { |
| case RC_PROVIDED: |
| return QRElement::Provided; |
| |
| case RC_NOTPROVIDED: |
| case RC_BACKJOIN: |
| return QRElement::NotProvided; |
| |
| case RC_OUTSIDE: |
| return QRElement::Outside; |
| |
| default: |
| // These are the only result codes allowed for final rewrite instructions. |
| assertLogAndThrow(CAT_MATCHTST_MVDETAILS, LL_MVQR_FAIL, |
| FALSE, QRLogicException, |
| "Not a final result code."); |
| return QRElement::INVALID_EXPR_RESULT; |
| } |
| } |
| |
| /** |
| * Add a table ID to the list of extra-hub tables used |
| * @param tableID |
| */ |
| void addExtraHubTable(const NAString* tableID) |
| { |
| extraHubTables_.insert(tableID); |
| } |
| |
| /** |
| * Add a table ID to the list of back-join tables used |
| * @param tableID |
| */ |
| void addBackJoinTable(const NAString* tableID) |
| { |
| backJoinTables_.insert(tableID); |
| } |
| |
| /** |
| * Get the list of extra-hub tables used |
| * @return |
| */ |
| IDSet& getExtraHubTables() |
| { |
| return extraHubTables_; |
| } |
| |
| /** |
| * Get the list of back-join tables used |
| * @return |
| */ |
| IDSet& getBackJoinTables() |
| { |
| return backJoinTables_; |
| } |
| |
| private: |
| QRElementPtr queryElement_; |
| QRElementPtr mvElement_; |
| ResultCode resultCode_; |
| ResultCode secondaryResultCode_; |
| ResultStatus status_; |
| compositeMatchingResultsPtr subElements_; |
| IDSet extraHubTables_; // Query descriptor IDs of needed extra-hub tables. |
| IDSet backJoinTables_; // Query descriptor IDs of needed back-join tables. |
| }; // class RewriteInstructionsItem |
| |
| /** |
| * Intermediate results of matching a list of input columns to expressions. |
| ***************************************************************************** |
| */ |
| class compositeMatchingResults : public NAIntrusiveSharedPtrObject |
| { |
| public: |
| compositeMatchingResults(ADD_MEMCHECK_ARGS_DECL(CollHeap* heap)) |
| : NAIntrusiveSharedPtrObject(ADD_MEMCHECK_ARGS_PASS(heap)) |
| ,providedInputs_(heap) |
| ,notProvidedInputs_(heap) |
| ,outsideInputs_(heap) |
| ,extrahubInputs_(heap) |
| ,backJoinInputs_(heap) |
| ,indirectInputs_(heap) |
| ,wasBlockedColumn_(FALSE) |
| {} |
| |
| virtual ~compositeMatchingResults(); |
| |
| /** |
| * Get the number of rewrite instructions objects contained here. |
| * @return |
| */ |
| CollIndex entries() |
| { |
| return providedInputs_.entries() + |
| notProvidedInputs_.entries() + |
| outsideInputs_.entries() + |
| extrahubInputs_.entries() + |
| backJoinInputs_.entries() + |
| indirectInputs_.entries(); |
| } |
| |
| void clear() |
| { |
| providedInputs_.clear(); |
| notProvidedInputs_.clear(); |
| outsideInputs_.clear(); |
| extrahubInputs_.clear(); |
| backJoinInputs_.clear(); |
| indirectInputs_.clear(); |
| } |
| |
| /** |
| * Insert a single rewrite instructions object. |
| * @param item |
| */ |
| void insert(RewriteInstructionsItemPtr item); |
| |
| /** |
| * Insert a list of rewrite instructions objects. |
| * @param itemList |
| */ |
| void insert(const RewriteInstructionsItemList& itemList); |
| |
| // A blocked column is one that is not provoded by the MV, and cannot be |
| // accesed through a back-join, because its table is not back-joinable. |
| NABoolean wasBlockedColumn_; |
| |
| // Lists of sub-elements by their result code. |
| RewriteInstructionsItemList providedInputs_; |
| RewriteInstructionsItemList notProvidedInputs_; |
| RewriteInstructionsItemList outsideInputs_; |
| RewriteInstructionsItemList extrahubInputs_; |
| RewriteInstructionsItemList backJoinInputs_; |
| RewriteInstructionsItemList indirectInputs_; |
| }; // class compositeMatchingResults |
| |
| /** |
| * The \c MatchTest class is an abstract superclass to all the specific matching |
| * tests, such as range, residual and output list. |
| * It provides these main functions: |
| * - The definition of a standard interface for calling the Pass 1 and Pass 2 |
| * matching tests, as well as for generating the result descriptor. |
| * - Implementation of common methods for reusing code. |
| * - Storing intermediate and final rewrite instructions. |
| ***************************************************************************** |
| */ |
| class MatchTest : public NAIntrusiveSharedPtrObject |
| { |
| public: |
| /** |
| * RewriteInstructions constructor |
| * @param heap The heap from which to allocate memory. |
| */ |
| MatchTest(ADD_MEMCHECK_ARGS_DECL(CollHeap* heap)) |
| : NAIntrusiveSharedPtrObject(ADD_MEMCHECK_ARGS_PASS(heap)) |
| ,listOfFinalInstructions_(heap) |
| ,listOfPendingWork_(heap) |
| ,heap_(heap) |
| { |
| } |
| |
| virtual ~MatchTest(); |
| |
| /** |
| * Run the Pass 1 algorithm. |
| * Pure virtual method to be implemented by subclasses. |
| * @return TRUE if the MV passed this test, FALSE if it was disqualified. |
| */ |
| virtual NABoolean matchPass1() = 0; |
| |
| /** |
| * Run the Pass 2 algorithm. |
| * This method goes over the remaining intermediate rewrite instructions, |
| * and calls the pure virtual method \c matchPass2OnElement() for each. |
| * @return TRUE if the MV passed this test, FALSE if it was disqualified. |
| */ |
| NABoolean matchPass2(); |
| |
| /** |
| * Generate the relevant section of the MV candidate in the result descriptor. |
| * @return TRUE if result descriptor was generated, FALSE if MV was rejected. |
| */ |
| NABoolean generateDescriptor(QRCandidatePtr resultDesc); |
| |
| /** |
| * Set a pointer to the MVCandidate object. |
| * @param candidate |
| */ |
| void setCandidate(MVCandidatePtr candidate) |
| { |
| candidate_ = candidate; |
| } |
| |
| /** |
| * Add an item of rewrite instructions to the collection. |
| * @param rewrite the item to add. |
| */ |
| virtual void addRewriteInstructions(RewriteInstructionsItemPtr rewrite); |
| |
| protected: |
| |
| /** |
| * Is the matching work done for this MV candidate, for a particular match test? |
| * @return TRUE if done, FALSE if more matching work is needed. |
| */ |
| NABoolean isFinal() |
| { |
| return (listOfPendingWork_.entries() == 0); |
| } |
| |
| /** |
| * Get the list of final rewrite instructions for the result descriptor. |
| * @return |
| */ |
| RewriteInstructionsItemList& getListOfFinalInstructions() |
| { |
| return listOfFinalInstructions_; |
| } |
| |
| /** |
| * Get the list of output items that still need some work. |
| * @return |
| */ |
| RewriteInstructionsItemList& getListOfPendingWork() |
| { |
| return listOfPendingWork_; |
| } |
| |
| /** |
| * Generate the QRMVColumn element for a provided column. |
| * @param rewrite |
| * @return |
| */ |
| QRMVColumnPtr generateProvidedMvColumn(RewriteInstructionsItemPtr rewrite); |
| |
| /** |
| * Generate the QRColumn element for a NotProvided column. |
| * @param rewrite |
| * @return |
| */ |
| QRColumnPtr generateNotProvidedColumn(RewriteInstructionsItemPtr rewrite); |
| |
| /** |
| * Run Pass 2 matching test for a particular element. |
| * Pure virtual method to be implemented by subclasses. |
| * @param pending The rewrite instructions prepared by the Pass 1 code. |
| * @return TRUE if the MV passed this test, FALSE if it was disqualified. |
| */ |
| virtual NABoolean matchPass2OnElement(RewriteInstructionsItemPtr pending) = 0; |
| |
| /** |
| * Generate a Provided result descriptor element. |
| * Pure virtual method to be implemented by subclasses. |
| * @param resultDesc |
| * @param rewrite |
| * @return TRUE if the MV passed this test, FALSE if it was disqualified. |
| */ |
| virtual NABoolean generateProvidedElement (QRCandidatePtr resultDesc, RewriteInstructionsItemPtr rewrite) = 0; |
| |
| /** |
| * Generate a NotProvided result descriptor element. |
| * Pure virtual method to be implemented by subclasses. |
| * @param resultDesc |
| * @param rewrite |
| * @return TRUE if the MV passed this test, FALSE if it was disqualified. |
| */ |
| virtual NABoolean generateNotProvidedElement(QRCandidatePtr resultDesc, RewriteInstructionsItemPtr rewrite) = 0; |
| |
| RewriteInstructionsItemPtr matchColumn(const QRColumnPtr colElem, |
| NABoolean fromExpr, |
| NABoolean isAnEqualitySet = FALSE); |
| |
| /** |
| * Match a single, full (not referencing) output column (Pass 1) |
| * @param colElem The query column element |
| * @param fromExpr Is this method called from the expression matching algorithm |
| * @return The rewrite instructions for matching the query column, |
| * or NULL if it is not covered by the MV. |
| */ |
| RewriteInstructionsItemPtr matchSingleColumn(const QRColumnPtr colElem, |
| NABoolean fromExpr); |
| |
| /** |
| * Match an Equality set (Pass 1). |
| * @param joinPred The join predicate element |
| * @return The rewrite instructions for matching the query equality set, |
| or NULL if it is not covered by the MV. |
| */ |
| RewriteInstructionsItemPtr matchEqualitySet(const QRJoinPredPtr joinPred); |
| |
| |
| /** |
| * Check if \c colElem is an Outside column (from a table that is not covered |
| * by the MV. There are three possible results: |
| * - FALSE, no extraHubID - The column is from an MV hub table, need to check if its provided. |
| * - FALSE, extraHubID set - The column is from an MV extra hub table |
| * - TRUE - the table is not covered by the MV at all. |
| * \par |
| * @param colElem The column to check |
| * @param extraHubID [OUT] When the table is detected as an extra-hub table, |
| * this returns its descriptor ID. |
| */ |
| NABoolean isOutsideColumn(const QRColumnPtr colElem, const NAString*& extraHubID); |
| |
| /** |
| * Is this column provided by the MV? |
| * @param colElem The column to check |
| * @param mvCol [OUT] A pointer to the MV output column that provides it. |
| * @return TRUE if the column is Provided, FALSE otherwise. |
| */ |
| NABoolean isProvidedColumn(const QRColumnPtr colElem, QROutputPtr& mvCol); |
| |
| /** |
| * Can the column be provided by using a back-join? |
| * @param colElem The column to check |
| * @return TRUE if this column is back-joinable, FALSE otherwise. |
| */ |
| NABoolean isBackJoinableColumn(const QRColumnPtr colElem); |
| |
| /** |
| * This method is called only for columns that are inputs of query |
| * output expressions. It checks if this column is an input of an |
| * MV output expression, so there is a chance that the MV provides |
| * a sub-expression of the needed query expression. |
| * @param colElem The column to check |
| * @return The rewrite instructions for matching the query output column, |
| * or NULL if it is not covered by the MV. |
| */ |
| RewriteInstructionsItemPtr isIndirectColumn(const QRColumnPtr colElem); |
| |
| /** |
| * Match an expression (Pass 1). |
| * @param expr The query expression. |
| * @return The rewrite instructions for matching the query expression, |
| * or NULL if it is not covered by the MV. |
| */ |
| RewriteInstructionsItemPtr matchExpression(const QRExprPtr expr); |
| |
| /** |
| * Check if the MV provides a matching output expression, including its |
| * input columns. |
| * @param expr The expression to find |
| * @return The rewrite instructions for matching the query expression, |
| * or NULL if it is not provided directly. |
| */ |
| RewriteInstructionsItemPtr findMatchingMvExpression(const QRExplicitExprPtr expr); |
| |
| /** |
| * Find MV columns that correspond to the input columns of the expression. |
| * @param queryColList The list of expression input columns. |
| * @return Rewrite instructions or NULL if no matching MV columns found. |
| */ |
| RewriteInstructionsItemPtr findExpressionInputs(const ElementPtrList& queryColList, |
| const QRElementPtr queryElement); |
| /** |
| * For a list of columns that can be either the list od exprerssion inputs, |
| * or an equality set list of members, match every member of the list, and |
| * sort it according to the result code in separate lists. |
| * @param queryColList The list of columns to sort out. |
| * @param matchingResults [OUT] The results are returned here. |
| * @param isAnEqualitySet Is this an equality set (TRUE) or an expression |
| * input list (FALSE) |
| */ |
| void MatchInputColumnList(const ElementPtrList& queryColList, |
| compositeMatchingResultsPtr matchingResults, |
| NABoolean isAnEqualitySet); |
| |
| /** |
| * Match the input column lists of a query expression from a range or |
| * residual predicate, with a corresponding MV expression that has the same |
| * expression text, in order to make sure its the same predicate. |
| * @param queryExpr The query expression. |
| * @param mvExpr The MV expression. |
| * @return TRUE if the column lists match, FALSE otherwise. |
| */ |
| NABoolean matchExpressionInputs(const ElementPtrList& queryInputColumns, |
| const ElementPtrList& mvInputColumns); |
| |
| /** |
| * Check if the queryColumn matches the mvColumn, not only by the column |
| * name, but also that its from the same instance of the same table. |
| * @param queryColumn Column element from the query descriptor. |
| * @param mvColumn Column element from the MV descriptor. |
| * @return TRUE if there is a match, FALSE otherwise. |
| */ |
| NABoolean matchColumnsByNameAndID(const QRColumnPtr queryColumn, |
| const QRColumnPtr mvColumn); |
| |
| |
| NABoolean verifyExtraHubAndBackJoinColumns(RewriteInstructionsItemPtr pending); |
| NABoolean verifyExtraHubColumn(RewriteInstructionsItemPtr pending); |
| |
| void addInputsToOutputList(RewriteInstructionsItemPtr rewrite); |
| |
| RewriteInstructionsItemPtr findInternalAggregateFunctions(QRExplicitExprPtr treeExpr); |
| RewriteInstructionsItemPtr findAggregateFunction(QRFunctionPtr func); |
| QRExprPtr generateAggregateExpressionOutput(RewriteInstructionsItemPtr rewrite); |
| QRFunctionPtr generateRollupAggregateFunction(RewriteInstructionsItemPtr rewrite); |
| QRFunctionPtr generateRollupOverGroupingAggregateFunction(RewriteInstructionsItemPtr rewrite); |
| NABoolean isExtraGroupingColumn(QRColumnPtr col); |
| NABoolean areAllInputsGroupingColumns(QRFunctionPtr func, ElementPtrList& inputList); |
| void cleanupSubExprHash(subExpressionRewriteHash& subExprHash); |
| |
| protected: |
| CollHeap* heap_; |
| MVCandidatePtr candidate_; |
| |
| private: |
| // List of final rewrite instructions |
| RewriteInstructionsItemList listOfFinalInstructions_; |
| |
| // List of intermediate rewrite instructions. |
| RewriteInstructionsItemList listOfPendingWork_; |
| |
| }; // class MatchTest |
| |
| /** |
| * Matching test for the output list. |
| ***************************************************************************** |
| */ |
| class MatchOutput : public MatchTest |
| { |
| public: |
| /** |
| * MatchOutput constructor |
| * @param heap The heap from which to allocate memory. |
| */ |
| MatchOutput(ADD_MEMCHECK_ARGS_DECL(CollHeap* heap)) |
| : MatchTest(ADD_MEMCHECK_ARGS_PASS(heap)) |
| ,OutputRewriteInstructionsByID_(hashKey, INIT_HASH_SIZE_SMALL, TRUE, heap) |
| ,OutputRewriteInstructionsByMvColName_(hashKey, INIT_HASH_SIZE_SMALL, TRUE, heap) |
| ,OutputsToAvoidByID_(hashKey, INIT_HASH_SIZE_SMALL, TRUE, heap) |
| {} |
| |
| virtual ~MatchOutput() |
| { |
| OutputRewriteInstructionsByID_.clear(); |
| OutputRewriteInstructionsByMvColName_.clear(); |
| OutputsToAvoidByID_.clear(); |
| } |
| |
| /** |
| * Run the Pass 1 algorithm of the output list test. |
| * Implementation of superclass pure virtual method. |
| * @return TRUE if the MV passed this test, FALSE if it was disqualified. |
| */ |
| virtual NABoolean matchPass1(); |
| |
| /** |
| * Override superclass implementation in order to filter duplicates |
| * @param rewrite |
| */ |
| virtual void addRewriteInstructions(RewriteInstructionsItemPtr rewrite); |
| |
| /** |
| * Add an IDto the list of outputs to avoid. |
| * @param id |
| */ |
| void addOutputToAvoid(const NAString& id); |
| |
| protected: |
| |
| virtual NABoolean matchPass2OnElement(RewriteInstructionsItemPtr pending); |
| |
| NABoolean matchAggregateExpressions(RewriteInstructionsItemPtr pending); |
| |
| // Implementation of virtual methods. |
| QROutputPtr createNewResultElement(RewriteInstructionsItemPtr rewrite); |
| |
| virtual NABoolean generateProvidedElement (QRCandidatePtr resultDesc, RewriteInstructionsItemPtr rewrite); |
| virtual NABoolean generateNotProvidedElement(QRCandidatePtr resultDesc, RewriteInstructionsItemPtr rewrite); |
| |
| QROutputPtr generateRollupAggregateOutput(RewriteInstructionsItemPtr rewrite); |
| |
| NABoolean isFromOutside(RewriteInstructionsItemPtr rewrite); |
| void switchRewrites(RewriteInstructionsItemPtr newRewrite, |
| RewriteInstructionsItemPtr firstRewrite, |
| const NAString& MVColName); |
| |
| private: |
| OutputsHash OutputRewriteInstructionsByID_; |
| OutputsHash OutputRewriteInstructionsByMvColName_; |
| IDHash OutputsToAvoidByID_; |
| }; // class MatchOutput |
| |
| |
| /** |
| * Matching test for range predicates. |
| ***************************************************************************** |
| */ |
| class MatchRangePredicates : public MatchTest |
| { |
| public: |
| /** |
| * Constructor |
| * @param heap The heap from which to allocate memory. |
| */ |
| MatchRangePredicates(ADD_MEMCHECK_ARGS_DECL(CollHeap* heap)) |
| : MatchTest(ADD_MEMCHECK_ARGS_PASS(heap)), |
| mvFullPredList_(heap) |
| {} |
| |
| virtual ~MatchRangePredicates() |
| {} |
| |
| /** |
| * Run the Pass 1 algorithm of range predicate test. |
| * Implementation of superclass pure virtual method. |
| * @return TRUE if the MV passed this test, FALSE if it was disqualified. |
| */ |
| virtual NABoolean matchPass1(); |
| |
| /** |
| * Used for Workload Analysis, to match a range predicate between two MVs. |
| * @param querySidePred the range predicate from the first MV. |
| * @return if the second MV has a matching predicate, return it, or NULL otherwise. |
| */ |
| QRRangePredPtr checkPredicate(QRRangePredPtr querySidePred); |
| |
| protected: |
| /** |
| * Check if the query predicate bitmaps are a superset of the MV predicate bitmaps. |
| * This method checks the bitmaps for both range and residual predicates, |
| * because the algorithm is the same for both, and it doesn't make sense to |
| * repeat the entire loop for the residual predicates in the MatchResidualPredicates |
| * class for the sake of organized code. |
| * If the query range predicate bitmap is not a superset of the MV bitmap for |
| * all the involved tables, then the MV has predicates that are not covered by |
| * the query, and is very quickly disqualified. |
| * @return TRUE if the MV passed, and FALSE if it is disqualified. |
| */ |
| NABoolean matchPredicateBitmaps(); |
| |
| /** |
| * Match a range predicate on an expression |
| * @param queryRangePred The range predicate element. |
| * @return FALSE is the MVCandidate should be disqualified. |
| */ |
| NABoolean matchPredOnExpr(const QRRangePredPtr queryRangePred); |
| |
| /** |
| * Match a range predicate on a column |
| * @param queryRangePred The range predicate element. |
| * @return FALSE is the MVCandidate should be disqualified. |
| */ |
| NABoolean matchPredOnColumn(const QRRangePredPtr queryRangePred, const QRColumnPtr rangeColumn); |
| |
| /** |
| * Match a range predicate on an equality set. |
| * @param queryRangePred The range predicate element. |
| * @param joinPred The join predicate element. |
| * @return FALSE is the MVCandidate should be disqualified. |
| */ |
| NABoolean matchPredOnEqualitySet(const QRRangePredPtr queryRangePred, const QRJoinPredPtr joinPred); |
| |
| // Implementation of virtual methods. |
| virtual NABoolean matchPass2OnElement(RewriteInstructionsItemPtr pending); |
| |
| QRRangePredPtr createNewResultElement(RewriteInstructionsItemPtr rewrite); |
| |
| virtual NABoolean generateProvidedElement (QRCandidatePtr resultDesc, RewriteInstructionsItemPtr rewrite); |
| virtual NABoolean generateNotProvidedElement(QRCandidatePtr resultDesc, RewriteInstructionsItemPtr rewrite); |
| |
| private: |
| // Used to track if all the range predicates of the MV have been matched. |
| RangePredPtrList mvFullPredList_; |
| }; // class MatchRangePredicates |
| |
| /** |
| * Matching test for residual predicates. |
| ***************************************************************************** |
| */ |
| class MatchResidualPredicates : public MatchTest |
| { |
| public: |
| /** |
| * Constructor |
| * @param heap The heap from which to allocate memory. |
| */ |
| MatchResidualPredicates(ADD_MEMCHECK_ARGS_DECL(CollHeap* heap)) |
| : MatchTest(ADD_MEMCHECK_ARGS_PASS(heap)), |
| mvFullPredList_(heap) |
| {} |
| |
| virtual ~MatchResidualPredicates() |
| {} |
| |
| /** |
| * Run the Pass 1 algorithm of residual predicate test. |
| * Implementation of superclass pure virtual method. |
| * @return TRUE if the MV passed this test, FALSE if it was disqualified. |
| */ |
| virtual NABoolean matchPass1(); |
| |
| /** |
| * Used for Workload Analysis, to match a residual predicate between two MVs. |
| * @param querySidePred the residual predicate from the first MV. |
| * @return if the second MV has a matching predicate, return it, or NULL otherwise. |
| */ |
| QRExprPtr checkPredicate(QRExprPtr querySidePred); |
| |
| protected: |
| // Implementation of virtual methods. |
| virtual NABoolean matchPass2OnElement(RewriteInstructionsItemPtr pending); |
| |
| QRExprPtr createNewResultElement(RewriteInstructionsItemPtr rewrite); |
| |
| /** |
| * Match a query residual predicate |
| * @param queryResidualPred The residual predicate element |
| * @param usedDupMvPreds List of preds that have been matched, and share the |
| * same text with 1 or more others. |
| * @return The rewrite instructions, or NULL if the MV candidate should be disqualified. |
| */ |
| RewriteInstructionsItemPtr matchResidualPredicate(const QRExprPtr queryResidualPred, |
| ResidualPredPtrList& usedDupMvPreds); |
| |
| virtual NABoolean generateProvidedElement (QRCandidatePtr resultDesc, RewriteInstructionsItemPtr rewrite); |
| virtual NABoolean generateNotProvidedElement(QRCandidatePtr resultDesc, RewriteInstructionsItemPtr rewrite); |
| |
| private: |
| // Used to track if all the residual predicates of the MV have been matched. |
| ResidualPredPtrList mvFullPredList_; |
| }; // class MatchResidualPredicates |
| |
| /** |
| * Matching test for grouping columns. |
| ***************************************************************************** |
| */ |
| class MatchGroupingColumns : public MatchTest |
| { |
| public: |
| /** |
| * Constructor |
| * @param heap The heap from which to allocate memory. |
| */ |
| MatchGroupingColumns(ADD_MEMCHECK_ARGS_DECL(CollHeap* heap)) |
| : MatchTest(ADD_MEMCHECK_ARGS_PASS(heap)) |
| {} |
| |
| virtual ~MatchGroupingColumns() |
| {} |
| |
| /** |
| * Run the Pass 1 algorithm of residual predicate test. |
| * Implementation of superclass pure virtual method. |
| * @return TRUE if the MV passed this test, FALSE if it was disqualified. |
| */ |
| virtual NABoolean matchPass1(); |
| |
| /** |
| * Override MatchTest method, because the GroupBy element is different. |
| * @param resultDesc The result descriptor being generated. |
| * @return FALSE if the MV candidate has been disqualified. |
| */ |
| virtual NABoolean generateDescriptor(QRCandidatePtr resultDesc); |
| |
| protected: |
| // Implementation of virtual methods from parent class. |
| /////////////////////////////////////////////////////////// |
| |
| // No Pass 2 functionality needed. |
| virtual NABoolean matchPass2OnElement(RewriteInstructionsItemPtr pending) |
| { |
| return TRUE; |
| } |
| |
| // Not used. |
| virtual NABoolean generateProvidedElement(QRCandidatePtr resultDesc, RewriteInstructionsItemPtr rewrite) |
| { |
| return TRUE; |
| } |
| |
| // Not used. |
| virtual NABoolean generateNotProvidedElement(QRCandidatePtr resultDesc, RewriteInstructionsItemPtr rewrite) |
| { |
| return TRUE; |
| } |
| |
| // Internal methods. |
| ////////////////////// |
| |
| NABoolean VerifyGroupingColumns(); |
| NABoolean verifyGroupingElement(const QRElementPtr groupingElem, NABoolean isRecursive = FALSE); |
| |
| }; // class MatchGroupingColumns |
| |
| /** |
| * Matching test for Equi-Join predicates. |
| * This test checks all the equi-join predicates in the query hub and extrahub, |
| * to find any that involve both tables used by the MV, and tables outside |
| * the MV. For these predicates, we check if the needed columns from the MV |
| * tables are Provided by the MV. If not - the MV is disqualified. Otherwise |
| * the needed columns are added to the result descriptor Output list. |
| * The PASS 1 method is the last PASS 1 method being called, so it knows the |
| * needed extrahub tables. Any join predicates that involve needed extrahub |
| * tables are postponed to PASS 2, when the extrahub tables have already been |
| * verified. |
| * This test does not create any JoinPred elements in the result descriptor, |
| * but rather, just adds MV columns to the Output list. Therefore the |
| * descriptor generation methods are not used. |
| ***************************************************************************** |
| */ |
| class MatchJoinPreds : public MatchTest |
| { |
| public: |
| /** |
| * Constructor |
| * @param heap The heap from which to allocate memory. |
| */ |
| MatchJoinPreds(ADD_MEMCHECK_ARGS_DECL(CollHeap* heap)) |
| : MatchTest(ADD_MEMCHECK_ARGS_PASS(heap)) |
| {} |
| |
| virtual ~MatchJoinPreds() |
| {} |
| |
| /** |
| * Run the Pass 1 algorithm of equi-join predicates test. |
| * Implementation of superclass pure virtual method. |
| * @return TRUE if the MV passed this test, FALSE if it was disqualified. |
| */ |
| virtual NABoolean matchPass1(); |
| |
| /** |
| * Override MatchTest method, because the JoinPred element is different. |
| * @param resultDesc The result descriptor being generated. |
| * @return FALSE if the MV candidate has been disqualified. |
| */ |
| virtual NABoolean generateDescriptor(QRCandidatePtr resultDesc); |
| |
| protected: |
| // Implementation of virtual methods from parent class. |
| /////////////////////////////////////////////////////////// |
| |
| /** |
| * Check again any predicate that involves needed extrahub tables. |
| * @param pending |
| * @return |
| */ |
| virtual NABoolean matchPass2OnElement(RewriteInstructionsItemPtr pending); |
| |
| NABoolean addBackJoinPredsForTable(const QRTablePtr table, QRCandidatePtr resultDesc); |
| |
| // Not used. |
| virtual NABoolean generateProvidedElement(QRCandidatePtr resultDesc, RewriteInstructionsItemPtr rewrite) |
| { |
| return TRUE; |
| } |
| |
| // Not used |
| virtual NABoolean generateNotProvidedElement(QRCandidatePtr resultDesc, RewriteInstructionsItemPtr rewrite) |
| { |
| return TRUE; |
| } |
| |
| protected: |
| // Internal methods. |
| ////////////////////// |
| |
| NABoolean analyzeJoinPredicate(const QRJoinPredPtr joinPred, NABoolean isPass1); |
| |
| void analyzeEQMember(QRElementPtr elem, |
| Int32& mvTables, |
| Int32& ehTables, |
| Int32& outTables, |
| ColumnNodesList& mvColumns, |
| NAPtrList<QRExprPtr>& mvExprs, |
| NABoolean isPass1); |
| |
| NABoolean analyzeProvidedExpression(const QRExprPtr expr); |
| |
| }; // class MatchJoinPreds |
| |
| /** |
| * |
| * |
| * |
| * |
| * |
| ***************************************************************************** |
| */ |
| class MatchOuterJoins : public MatchTest |
| { |
| public: |
| /** |
| * Constructor |
| * @param heap The heap from which to allocate memory. |
| */ |
| MatchOuterJoins(ADD_MEMCHECK_ARGS_DECL(CollHeap* heap)) |
| : MatchTest(ADD_MEMCHECK_ARGS_PASS(heap)) |
| {} |
| |
| virtual ~MatchOuterJoins() |
| {} |
| |
| /** |
| * Run the Pass 1 algorithm of equi-join predicates test. |
| * Implementation of superclass pure virtual method. |
| * @return TRUE if the MV passed this test, FALSE if it was disqualified. |
| */ |
| virtual NABoolean matchPass1(); |
| |
| /** |
| * Override MatchTest method, because the JoinPred element is different. |
| * @param resultDesc The result descriptor being generated. |
| * @return FALSE if the MV candidate has been disqualified. |
| */ |
| virtual NABoolean generateDescriptor(QRCandidatePtr resultDesc); |
| |
| protected: |
| // Implementation of virtual methods from parent class. |
| /////////////////////////////////////////////////////////// |
| |
| /** |
| * Check again any predicate that involves needed extrahub tables. |
| * @param pending |
| * @return |
| */ |
| virtual NABoolean matchPass2OnElement(RewriteInstructionsItemPtr pending); |
| |
| // Not used. |
| virtual NABoolean generateProvidedElement(QRCandidatePtr resultDesc, RewriteInstructionsItemPtr rewrite) |
| { |
| return TRUE; |
| } |
| |
| // Not used |
| virtual NABoolean generateNotProvidedElement(QRCandidatePtr resultDesc, RewriteInstructionsItemPtr rewrite) |
| { |
| return TRUE; |
| } |
| |
| protected: |
| // Internal methods. |
| ////////////////////// |
| |
| NABoolean addTheNotNullPred(const QRTablePtr queryTable, const BaseTableDetailsPtr mvTableDetails); |
| |
| }; // class MatchOuterJoins |
| |
| /** |
| * |
| * |
| * |
| * |
| * |
| ***************************************************************************** |
| */ |
| class AggregateCollectorVisitor : public Visitor |
| { |
| public: |
| AggregateCollectorVisitor(ADD_MEMCHECK_ARGS_DECL(CollHeap* heap)) |
| : Visitor(ADD_MEMCHECK_ARGS_PASS(heap)) |
| ,aggregateFunctions_(heap) |
| ,simpleColumns_(heap) |
| ,joinedColumns_(heap) |
| {} |
| |
| virtual ~AggregateCollectorVisitor() |
| { |
| aggregateFunctions_.clear(); |
| simpleColumns_.clear(); |
| joinedColumns_.clear(); |
| } |
| |
| virtual VisitResult visit(QRElementPtr caller); |
| |
| FunctionNodesList& getAggregateFunctionList() |
| { |
| return aggregateFunctions_; |
| } |
| |
| ColumnNodesList& getSimpleColumnList() |
| { |
| return simpleColumns_; |
| } |
| |
| JoinPredNodesList& getJoinedColumnList() |
| { |
| return joinedColumns_; |
| } |
| |
| private: |
| FunctionNodesList aggregateFunctions_; |
| ColumnNodesList simpleColumns_; |
| JoinPredNodesList joinedColumns_; |
| }; // class AggregateCollectorVisitor |
| |
| |
| #endif |