| /********************************************************************** |
| // @@@ 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 @@@ |
| **********************************************************************/ |
| #ifndef RELEXPR_H |
| #define RELEXPR_H |
| /* -*-C++-*- |
| ****************************************************************************** |
| * |
| * File: RelExpr.h |
| * Description: Relational expression base class |
| * Created: 4/28/94 |
| * Language: C++ |
| * Status: $State: Exp $ |
| * |
| * |
| * |
| * |
| ****************************************************************************** |
| */ |
| |
| #include "ObjectNames.h" |
| #include "CmpContext.h" |
| #include "CmpStatement.h" |
| #include "RETDesc.h" |
| #include "ValueDesc.h" |
| #include "Rule.h" |
| #include "ExprNode.h" |
| #include "ComTransInfo.h" |
| #include "mdam.h" |
| #include "DefaultConstants.h" |
| #include "Inlining.h" |
| #include "NADefaults.h" |
| #include "OptUtilIncludes.h" |
| #include "ExplainTupleMaster.h" |
| |
| // ----------------------------------------------------------------------- |
| // contents of this file |
| // ----------------------------------------------------------------------- |
| class ExprGroupId; |
| class RelExpr; |
| class RelExprList; |
| class CutOp; |
| class SubtreeOp; |
| class WildCardOp; |
| class ScanForceWildCard; |
| class UDFForceWildCard; |
| class RequiredResources; |
| |
| // ----------------------------------------------------------------------- |
| // forward references |
| // ----------------------------------------------------------------------- |
| class BindWA; |
| class CacheWA; |
| class CascadesPlan; |
| class Context; |
| class ContextList; |
| class Cost; |
| class CostLimit; |
| class CostMethod; |
| class EstLogProp; |
| class Generator; |
| class ComTdb; |
| class ExplainTuple; |
| class GroupAttibutes; |
| class Guidance; |
| class NormWA; |
| class PhysicalProperty; |
| class InputPhysicalProperty; |
| class ReqdPhysicalProperty; |
| class PlanWorkSpace; |
| class PartitioningRequirement; |
| class FileScan; |
| class Scan; |
| class SubTreeAccessSet; |
| class SearchKey; |
| class ScanKey; |
| class MVInfoForDDL; |
| class PlanPriority; |
| class Hint; |
| class TableMappingUDF; |
| class RelSequence; |
| class CSEInfo; |
| |
| |
| //////////////////// |
| class CANodeIdSet; |
| class QueryAnalysis; |
| class GroupAnalysis; |
| //////////////////// |
| |
| // used in heuristics to limit VSBB and SIDETREE inserts only if number rows |
| // being inserted is larger than this constant. Used in ImplRule.cpp and |
| // GenPreCode.cpp |
| const Lng32 MIN_ROWS_FOR_VSBB = 100; |
| |
| // used to defined input partitioning type of a TMUDF table input (its child) |
| enum TMUDFInputPartReq |
| { |
| ANY_PARTITIONING, |
| SPECIFIED_PARTITIONING, |
| REPLICATE_PARTITIONING, |
| NO_PARTITIONING |
| }; |
| |
| // ----------------------------------------------------------------------- |
| // An ExprGroupId object is a pointer to a logical or a physical RelExpr |
| // object or to a Cascades group. It is used to point to the child |
| // nodes (subtrees) of an ExprNode object. Different modes of addressing |
| // are available, depending on whether the tree is a standalone object |
| // outside of Cascades, a materialized binding in Cascades, or a memoized |
| // expression (a member of the CascadesMemo structure). |
| // ----------------------------------------------------------------------- |
| class ExprGroupId : public NABasicObject |
| { |
| public: |
| |
| // state of the object |
| enum GroupIdMode |
| { |
| STANDALONE, |
| BINDING, |
| MEMOIZED |
| }; |
| |
| // constructors |
| |
| ExprGroupId(); |
| ExprGroupId(const ExprGroupId & other); |
| ExprGroupId(RelExpr *node); |
| ExprGroupId(CascadesGroupId groupId); |
| |
| // assignment operators |
| ExprGroupId & operator = (const ExprGroupId & other); |
| ExprGroupId & operator = (RelExpr * other); |
| ExprGroupId & operator = (CascadesGroupId other); |
| |
| // compare an ExprGroupId with another ExprGroupId or a RelExpr * |
| NABoolean operator == (const ExprGroupId &other) const; |
| NABoolean operator != (const ExprGroupId &other) const |
| { return NOT operator == (other); } |
| NABoolean operator == (const RelExpr *other) const; |
| NABoolean operator != (const RelExpr *other) const |
| { return NOT operator == (other); } |
| |
| // dereferencing operator, this class works like a pointer |
| inline RelExpr * operator ->() const; // defined below class Rexpr |
| |
| // same as a "normal" method |
| inline RelExpr * getPtr() const; // defined below class RelExpr |
| |
| // cast into a RelExpr * |
| inline operator RelExpr *() const; // defined below class RelExpr |
| |
| // return a group number instead of a pointer |
| CascadesGroupId getGroupId() const; |
| |
| // return the mode of the pointer |
| GroupIdMode getMode() const { return groupIdMode_; } |
| |
| // change a binding back to mode MEMOIZED |
| void releaseBinding(); |
| void convertBindingToStandalone(); // use after optimization |
| |
| // The Group Attributes contains certain attributes that are |
| // characteristics for a relational operator. |
| void setGroupAttr(GroupAttributes *gaPtr); |
| GroupAttributes *getGroupAttr() const; |
| |
| // shortcut to get the estimated output log props out of the group |
| // given the corresponding input estimated logical property. |
| // NOTE: If the OLP has not yet been synthesized, this method |
| // will synthesize the OLP on demand. |
| // (This means that no const version of this function is |
| // possible) |
| EstLogPropSharedPtr outputLogProp(const EstLogPropSharedPtr& inputLogProp); |
| |
| // A shortcut to get the bound expression (if it exists) ... |
| // or the first logical expression in the Cascades Group. |
| RelExpr * getLogExpr() const; |
| |
| RelExpr * getFirstLogExpr() const; |
| |
| private: |
| |
| enum GroupIdMode groupIdMode_; |
| RelExpr * node_; // used for all modes but MEMOIZED |
| CascadesGroupId groupId_; // used for the MEMOIZED and BINDING mode |
| |
| }; // class ExprGroupId |
| |
| // ----------------------------------------------------------------------- |
| // A generic relational expression node. This class is a base class for |
| // any relational operator in the system. Every relational operator has |
| // a selection predicate associated with it. This base class also |
| // maintains all the data members describing the output row of a |
| // relational operator and its outer references. |
| // ----------------------------------------------------------------------- |
| |
| class RelExpr : public ExprNode |
| { |
| |
| public: |
| |
| // --------------------------------------------------------------------- |
| // default constructor |
| // --------------------------------------------------------------------- |
| RelExpr(OperatorTypeEnum otype, |
| RelExpr *leftChild = NULL, |
| RelExpr *rightChild = NULL, |
| CollHeap *outHeap = CmpCommon::statementHeap()); |
| |
| // operator== required for use in templates |
| NABoolean operator==(const RelExpr &other) const |
| { |
| if(&other == this) |
| return TRUE; |
| else |
| return FALSE; |
| } |
| |
| // --------------------------------------------------------------------- |
| // virtual destructor |
| // --------------------------------------------------------------------- |
| virtual ~RelExpr(); |
| |
| virtual Int32 getArity() const; |
| |
| NABoolean isAnyJoin() const; |
| |
| virtual const NAString getText() const {return NAString("RelExpr"); } |
| |
| // are RelExpr's kids cacheable after this phase? |
| NABoolean cacheableKids(CacheWA& cwa); |
| |
| // is this entire expression cacheable after this phase? |
| virtual NABoolean isCacheableExpr(CacheWA& cwa); |
| |
| // is this single ExprNode cacheable after this phase? |
| NABoolean isCacheableNode(CmpPhase phase) const; |
| |
| // mark this ExprNode as cacheable for this and later phases |
| void setCacheableNode(CmpPhase phase); |
| |
| // append an ascii-version of RelExpr into cachewa.qryText_ |
| virtual void generateCacheKey(CacheWA& cachewa) const; |
| |
| // change literals of a cacheable query into ConstantParameters |
| virtual RelExpr* normalizeForCache(CacheWA& cachewa, BindWA& bindWA); |
| |
| // helper function on CQS Tree |
| virtual RelExpr *generateMatchingExpr(CANodeIdSet &, |
| CANodeIdSet &, |
| RelExpr *); |
| |
| // helper function on Normalized tree (CQS project) |
| virtual RelExpr * generateLogicalExpr (CANodeIdSet &, |
| CANodeIdSet &); |
| |
| Hint *getHint() const { return hint_; } |
| |
| void setHint(Hint *h) { hint_ = h; } |
| |
| static const CorrName invalid; |
| virtual inline const CorrName& getTableName()const { return invalid;} |
| |
| |
| |
| protected: |
| // append an ascii-version of RelExpr node into cachewa.qryText_ |
| void generateCacheKeyNode(CacheWA& cwa) const; |
| |
| // append an ascii-version of RelExpr's kids into cachewa.qryText_ |
| void generateCacheKeyForKids(CacheWA& cachewa) const; |
| |
| // change literals in cacheable query's kids into ConstantParameters |
| void normalizeKidsForCache(CacheWA& cachewa, BindWA& bindWA); |
| |
| // How much memory do we expect this operator's executor to be able to use |
| // per ESP/master fragment ? |
| Lng32 getExeMemoryAvailable(NABoolean inMaster) const; |
| |
| // compute the memory quota |
| double computeMemoryQuota(NABoolean inMaster, |
| NABoolean perNode, |
| double BMOsMemoryLimit, |
| UInt16 totalNumBMOs, |
| double totalBMOsMemoryUsage, |
| UInt16 numBMOsPerFragment, |
| double BMOMemoryUsage, |
| Lng32 numStreams, |
| double &memQuotaRatio |
| ); |
| |
| |
| public: |
| // --------------------------------------------------------------------- |
| // perform a safe type cast (return NULL ptr for illegal casts) |
| // --------------------------------------------------------------------- |
| virtual RelExpr *castToRelExpr(); |
| const RelExpr * castToRelExpr() const; |
| |
| // This method clears all logical expressions uptill the leaf node |
| // for multi-join. The methid should be called only before optimization phases |
| // Reason for that is (1)it is very expensive to synthLogProp and should be avoided |
| // (2) we are resetting number of joined tables, which should not be done once it is |
| // set during optimization phases |
| |
| void clearLogExprForSynthDuringAnalysis(); |
| |
| virtual NABoolean isAControlStatement() const { return FALSE; } |
| virtual StaticOnly isAStaticOnlyStatement() const { return NOT_STATIC_ONLY; } |
| |
| NABoolean isParHeuristic4Feasible(Context* myContext, |
| const ReqdPhysicalProperty* rppForMe); |
| |
| // safe casting to derived classes |
| virtual TableMappingUDF *castToTableMappingUDF(); |
| |
| // --------------------------------------------------------------------- |
| // method required for traversing an ExprNode tree |
| // access a child of an ExprNode |
| // --------------------------------------------------------------------- |
| virtual ExprNode * getChild(Lng32 index); |
| |
| // Method for replacing a particular child |
| virtual void setChild(Lng32 index, ExprNode *); |
| |
| // --------------------------------------------------------------------- |
| // Delete this node without deleting its subtree. |
| // --------------------------------------------------------------------- |
| void deleteInstance(); |
| |
| // --------------------------------------------------------------------- |
| // methods for traversing the tree |
| // --------------------------------------------------------------------- |
| |
| // operator [] is used to access the children of a tree |
| virtual ExprGroupId & operator[] (Lng32 index) |
| { |
| CMPASSERT(index >= 0 AND index < MAX_REL_ARITY); |
| return child_[index]; |
| } |
| |
| virtual const ExprGroupId & operator[] (Lng32 index) const |
| { |
| CMPASSERT(index >= 0 AND index < MAX_REL_ARITY); |
| return child_[index]; |
| } |
| |
| // for cases where a named method is more convenient than operator [] |
| inline ExprGroupId & child(Lng32 index) |
| { return operator[](index); } |
| // const version of the above |
| inline const ExprGroupId & child(Lng32 index) const |
| { return operator[](index); } |
| |
| // --------------------------------------------------------------------- |
| // manipulate the selection predicate of the node |
| // (read and set the entire predicate, add and remove |
| // predicates that are ANDed together). |
| // Predicates that are passed through this interface change |
| // ownership, meaning that the new "owner" is responsible |
| // for deallocation. No copies are made by these methods. |
| // --------------------------------------------------------------------- |
| |
| // add a new selection predicate (new pred = child pred AND existing pred) |
| void addSelPredTree(ItemExpr *selpred); |
| |
| // remove the selection predicate tree from this node and return its pointer |
| ItemExpr * removeSelPredTree(); |
| |
| // non-destructive read of the selection predicates |
| ItemExpr * selPredTree() const { return selection_; } |
| const ItemExpr * getSelPredTree() const { return selection_; } |
| |
| // return a (short-lived) read/write reference to the selection predicates |
| ValueIdSet & selectionPred() { CMPASSERT(NOT isCutOp()); return predicates_; } |
| |
| // return a constant reference to the selection predicates |
| const ValueIdSet & getSelectionPred() const { return predicates_; } |
| const ValueIdSet & getSelectionPredicates() const { return predicates_; } |
| |
| void setSelectionPredicates(const ValueIdSet& p) { predicates_ = p; } |
| |
| //++MV |
| // Used by inlining mechanism for adding optimizer constraints |
| void addUniqueColumnsTree(ItemExpr *uniqueColumnsTree); |
| ItemExpr * removeUniqueColumnsTree(); |
| |
| inline ValueIdSet& getUniqueColumns() { return uniqueColumns_; } |
| inline void setUniqueColumns(const ValueIdSet& uniqueColumns) |
| { |
| uniqueColumns_ = uniqueColumns; |
| } |
| |
| CardConstraint * getCardConstraint() const { return cardConstraint_; } |
| void addCardConstraint(Cardinality lowerBound, Cardinality upperBound) |
| { |
| cardConstraint_ = new(CmpCommon::statementHeap()) |
| CardConstraint(lowerBound,upperBound); |
| } |
| //--MV |
| |
| |
| // --------------------------------------------------------------------- |
| // The Group Attributes contains certain attributes that are |
| // characteristics for this relational operator, namely, |
| // 1) the values that it requires as external inputs, which are |
| // outer references such as a column from an outer scope, |
| // a host variable, a dynamic parameter or a constant. |
| // 2) the values that it produces as output. |
| // 3) the logical properties such as constraints, statistics, etc. |
| // --------------------------------------------------------------------- |
| void setGroupAttr(GroupAttributes *gaPtr); |
| inline GroupAttributes *getGroupAttr() const { return groupAttr_; } |
| virtual NABoolean reconcileGroupAttr(GroupAttributes *newGroupAttr); |
| |
| // ********************************************************************* |
| // Common interfaces for processing DML statements. |
| // Each interface implements one phase of query processing. |
| // ********************************************************************* |
| enum AtomicityType |
| {UNSPECIFIED_ = 0, ATOMIC_ = 1, NOT_ATOMIC_ = 2}; |
| |
| // Rowsets processing does some transformations after parsing but before |
| // binding. For example, it transforms a query Q that has an input rowset |
| // array A into a TSJ that feeds each element of A into the query Q. The argument |
| // inputArrayMaxsize is used to set the length of input arrays for ODBC |
| // insert queries. |
| virtual RelExpr *xformRowsetsInTree(BindWA& wa, |
| const ULng32 inputArrayMaxsize = 0, |
| const AtomicityType atomicity = UNSPECIFIED_); |
| |
| // -------------------------------------------------------------------- |
| // The name binding and semantics checking phase is implemented |
| // by the virtual function bindNode(). |
| // -------------------------------------------------------------------- |
| virtual RelExpr * bindNode(BindWA *bindWAPtr); |
| |
| // -------------------------------------------------------------------- |
| // Unconditional query transformations such as the transformation of |
| // a subquery to a semijoin are implemented by the virtual function |
| // transformNode(). The aim of such transformations is to bring the |
| // query tree to a canonical form. transformNode() also ensures |
| // that the "required" (or characteristic) input values are "minimal" |
| // and the "required" (or characteristic) outputs values are |
| // "maximal" for each operator. |
| // |
| // transformNode() is an overloaded name, which is used for a set |
| // of methods that implement the transformation phase of query |
| // normalization. |
| // |
| // We use the term query tree for a tree of relational operators, |
| // each of which can contain none or more scalar expression trees. |
| // The transformations performed by transformNode() brings scalar |
| // expressions into a canonical form. The effect of most such |
| // transformations is local to the scalar expression tree. |
| // However, the transformation of a subquery requires a semijoin |
| // to be performed between the relational operator that contains |
| // the subquery and the query tree for the subquery. The effect |
| // of such a subquery transformation is therefore visible not |
| // only in the scalar expression tree but also in the relational |
| // expression tree. |
| // |
| // Originally, transformNode() was a virtual method on ExprNode. |
| // The relational as well as scalar expressions are derived from |
| // ExprNode and used to provide proprietary implementations for it. |
| // However, relational and scalar expressions have different |
| // processing requirements during the transformation phase. Hence, |
| // each of them now support a virtual transformNode() method that |
| // differ in their interfaces. |
| // |
| // Parameters: |
| // |
| // NormWA & normWARef |
| // IN : a pointer to the normalizer work area |
| // |
| // ExprGroupId & locationOfPointerToMe |
| // IN : a reference to the location that contains a pointer to |
| // the RelExpr that is currently being processed. |
| // |
| // -------------------------------------------------------------------- |
| virtual void transformNode(NormWA & normWARef, |
| ExprGroupId & locationOfPointerToMe); |
| |
| // -------------------------------------------------------------------- |
| // rewriteNode() is the virtual function that computes |
| // the transitive closure for "=" predicates and rewrites value |
| // expressions. |
| // -------------------------------------------------------------------- |
| virtual void rewriteNode(NormWA & normWARef); |
| |
| // QSTUFF |
| |
| // -------------------------------------------------------------------- |
| // This routine checks whether a table is both read and updated |
| // -------------------------------------------------------------------- |
| enum rwErrorStatus |
| { |
| RWERROR, |
| RWOKAY |
| }; |
| |
| virtual rwErrorStatus checkReadWriteConflicts(NormWA & normWARef); |
| |
| // QSTUFF |
| |
| // -------------------------------------------------------------------- |
| // normalizeNode() performs predicate pushdown and also ensures |
| // that the characteristic input as well as characteristic output |
| // values are both "minimal". |
| // -------------------------------------------------------------------- |
| virtual RelExpr * normalizeNode(NormWA & normWARef); |
| |
| // -------------------------------------------------------------------- |
| // getEssentialOutputsFromChildren() is a helper method used by the |
| // classifyChildOutputs() method. This method will have a set containing |
| // all Essential Outputs out a node's direct children in essOutputs, |
| // upon completion. |
| // -------------------------------------------------------------------- |
| void getEssentialOutputsFromChildren(ValueIdSet & essOutputs); |
| |
| // -------------------------------------------------------------------- |
| // fixEssentialCharacteristicOutputs() is a used during the bottom-up of |
| // normalizeNode(). This method collects the essential outputs of the |
| // children nodes and if any nonessential outputs of the cureent node |
| // overlap with those essential outputs, then the overlapping nonessential |
| // outputs are set to be essential too. In other words this method implements |
| // the rule that states if an output is essential in my child, it is |
| // essential for me too (if the valueid is part of my output). |
| // -------------------------------------------------------------------- |
| void fixEssentialCharacteristicOutputs(); |
| |
| // -------------------------------------------------------------------- |
| // semanticQueryOptimizeNode() performs sematic query optimization |
| // In Neo R2.2 this includes only subquery unnesting |
| // semantic query optimization is defined as a sematics preserving |
| // tranformation on a query tree that uses the logical constraints |
| // computed for the query. |
| // -------------------------------------------------------------------- |
| virtual RelExpr * semanticQueryOptimizeNode(NormWA & normWARef); |
| |
| // used during SemanticQueryOptimize to remove filter nodes introduced |
| // in previous phases, if the subquery is not going to be unnested. |
| // The objective is to push predicates as far down as possible so that |
| // cardinality can be estimated correctly for all nodes during Analyzer |
| // phase |
| void eliminateFilterChild(); |
| |
| // used duirng SQO, to check if the child or grandchild of current |
| // node is a filter. Two acceptable patterns are (a) child(0) is filter |
| // child(0) is groupby an child(0)->child(0) is filter |
| NABoolean hasFilterChild(); |
| |
| // used during SQO phase to make the left sub tree of the join |
| // being unnested produce the extra outputs that is necessary to |
| // group by a set of unique columns of of the left sub tree |
| NABoolean getMoreOutputsIfPossible(ValueIdSet& outputsNeeded) ; |
| |
| // calls pushDownCoveredExpr recursively. Used at the end of the |
| // SQO phase to get outputs at every node to be minimal |
| void recursivePushDownCoveredExpr(NormWA * normWAPtr, |
| NABoolean doSynthLogProp = TRUE) ; |
| |
| // synthesizes (in Scan's implemenation), matches (in Join's implementation) |
| // and flows CompRefOpt constraints up the query tree. |
| virtual void processCompRefOptConstraints(NormWA * normWAPtr) ; |
| |
| // Used during SQO to prepare the child tree of a CommonSubExprRef |
| // for sharing between multiple consumers. This basically undoes |
| // some of the normalizations, like eliminating unneeded outputs |
| // and pushing predicates down. This is a recursive tree walk |
| // method, most nodes don't override this one. |
| // Returns TRUE for success, FALSE if it was unable to prepare |
| // (diags will be set). |
| // Tree remains unchanged if testRun is TRUE. |
| virtual NABoolean prepareTreeForCSESharing( |
| const ValueIdSet &outputsToAdd, |
| const ValueIdSet &predicatesToRemove, |
| const ValueIdSet &commonPredicatesToAdd, |
| const ValueIdSet &inputsToRemove, |
| ValueIdSet &valuesForVEGRewrite, |
| ValueIdSet &keyColumns, |
| CSEInfo *info); |
| |
| // A virtual method called on every node from prepareTreeForCSESharing(), |
| // use this to do the actual work of removing predicates other than |
| // selection predicates, and to indicate that the node supports this |
| // method (the default implementation returns FALSE). |
| // |
| // This method needs to |
| // - make sure no changes are done to the node when testRun is TRUE |
| // - add any required new outputs to the char. outputs, unless they |
| // are produced by a child |
| // - make sure no local expression reference any of the inputs to |
| // be removed |
| // - indicate in its return value whether it was successful doing so |
| // |
| // This method doesn't need to take care of the following, since the |
| // caller of this method already does it: |
| // - removing predicates from selectionPred() |
| // - adding new common predicates to selectionPred(), unless |
| // they are covered by the children's group attributes |
| // - adding required outputs that are produced by children |
| // - removing char. inputs that are requested to be removed |
| virtual NABoolean prepareMeForCSESharing( |
| const ValueIdSet &outputsToAdd, |
| const ValueIdSet &predicatesToRemove, |
| const ValueIdSet &commonPredicatesToAdd, |
| const ValueIdSet &inputsToRemove, |
| ValueIdSet &valuesForVEGRewrite, |
| ValueIdSet &keyColumns, |
| CSEInfo *info); |
| |
| // -------------------------------------------------------------------- |
| // Create a query execution plan. |
| // -------------------------------------------------------------------- |
| virtual RelExpr * optimizeNode(); |
| |
| // -------------------------------------------------------------------- |
| // Perform local query rewrites such as for the creation and |
| // population of intermediate tables, for accessing partitioned |
| // data. Rewrite the value expressions after minimizing the dataflow |
| // using the transitive closure of equality predicates. |
| // -------------------------------------------------------------------- |
| virtual RelExpr * preCodeGen(Generator * generator, |
| const ValueIdSet & externalInputs, |
| ValueIdSet &pulledNewInputs); |
| |
| // -------------------------------------------------------------------- |
| // Perform DoP reduction. Called during preCodeGen(). |
| // -------------------------------------------------------------------- |
| virtual void prepareDopReduction(Generator*); |
| virtual void doDopReduction(); |
| virtual void doDopReductionWithinFragment(Lng32 newDoP); |
| |
| // -------------------------------------------------------------------- |
| // Generate executor task definition blocks (ComTdb's). |
| // -------------------------------------------------------------------- |
| virtual short codeGen(Generator *); |
| |
| // ----------------------------------------------------- |
| // generate CONTROL QUERY SHAPE fragment for this node. |
| // ----------------------------------------------------- |
| virtual short generateShape(CollHeap * space, char * buf, NAString * shapeStr = NULL); |
| |
| // ********************************************************************* |
| // Helper functions and methods used by the binder. |
| // ********************************************************************* |
| |
| void bindChildren(BindWA *bindWAPtr); |
| |
| RelExpr *bindSelf(BindWA *bindWAPtr); |
| |
| void setRETDesc(RETDesc *retdesc) { RETDesc_ = retdesc; } |
| RETDesc *getRETDesc() const; |
| CollIndex getDegree() const |
| { |
| RETDesc *rd = getRETDesc(); |
| return rd ? rd->getDegree() : (CollIndex)0; |
| } |
| |
| Scan *getScanNode(NABoolean assertExactlyOneScanNode = TRUE) const; |
| Scan *getLeftmostScanNode() const; |
| Scan *getAnyScanNode() const; |
| Join *getLeftJoinChild() const; |
| RelSequence *getOlapChild() const; |
| void getAllTableDescs(TableDescList &tableDescs); |
| |
| TableDesc *findFirstTableDescAndValueIdMap(RelExpr *currentNode, |
| ValueIdMap &valueIdMap); |
| |
| |
| // QSTUFF |
| // we must pushdown the outputs of a genericupdate root to its |
| // descendants to ensure that only those required output values are |
| // tested against indexes when selecting an index for a stream scan |
| // followed by an embedded update. Since we may allow for unions and |
| // for inner updates we just follow the isEmbeddedUpdate() thread once |
| // we reach a generic update root. |
| |
| void pushDownGenericUpdateRootOutputs(const ValueIdSet &outputs); |
| |
| // in order to bind constraints for views with the check option we |
| // have to locate the respective view scan scope. In case of a simple |
| // view the scope is associated with the leaf scan node; in case of |
| // stacked views the scope is associated with the rename node inserted |
| // by view expansion. |
| |
| RelExpr *getViewScanNode(NABoolean isTopLevelUpdateInView = FALSE) const; |
| // QSTUFF |
| |
| // a virtual function to get addressability to the list of output values |
| virtual ItemExpr * selectList(); // in the external form |
| |
| // Triggers -- |
| // get/set the InliningInfo object. |
| inline InliningInfo& getInliningInfo() { return inliningInfo_; } |
| inline const InliningInfo& getInliningInfo() const { return inliningInfo_; } |
| inline void setInliningInfo(InliningInfo *info) { inliningInfo_ = *info; } |
| |
| // Access set handling methods |
| inline SubTreeAccessSet *getAccessSet0() { return accessSet0_;} |
| inline SubTreeAccessSet *getAccessSet1() { return accessSet1_;} |
| inline void setAccessSet0(SubTreeAccessSet *as) { accessSet0_ = as; } |
| inline void setAccessSet1(SubTreeAccessSet *as) { accessSet1_ = as; } |
| |
| virtual SubTreeAccessSet *calcAccessSets(CollHeap *heap); |
| |
| // MV -- |
| virtual NABoolean isIncrementalMV() { return FALSE; } |
| virtual void collectMVInformation(MVInfoForDDL *mvInfo, |
| NABoolean isNormalized); |
| |
| // determine whether an IUD operation has been seen |
| virtual NABoolean seenIUD() { return seenIUD_; } |
| virtual void setSeenIUD() { seenIUD_ = TRUE; } |
| |
| // ********************************************************************* |
| // Helper functions and methods used by the normalizer. |
| // ********************************************************************* |
| |
| // procedure to do the common processing of the select predicate |
| void transformSelectPred(NormWA & normWARef, |
| ExprGroupId & locationOfPointerToMe); |
| |
| // --------------------------------------------------------------------- |
| // Inputs and Ouptuts. |
| // |
| // Each relational operator in the dataflow tree can receive some |
| // external dataflow inputs such as constant values or values in |
| // host variables or dynamic parameters, for evaluating some scalar |
| // expression. Each operator can also produce one or more output |
| // values that are either "raw" values from columns or values that |
| // result from the evaluation of an expression. |
| // |
| // An operator can receive more values as inputs than it requires |
| // for its own expressions because it passes them down to its |
| // children. It is also capable of producing a large number of |
| // values as outputs: potentially all those values that its children |
| // can produce as well as those that do not require any new external |
| // children. For example, if the children can produce values a, b, |
| // then the operator is capable of producing a, b, a + b and so on. |
| // |
| // The Group Attributes that are associated with each relational |
| // operator contain its Charcateristic Input and Outputs. The |
| // following methods are used for priming the Group Attributes |
| // with an set of values that provide the basis for computing |
| // the Characteristic Input and Outputs. |
| // -------------------------------------------------------------------- |
| void primeGroupAttributes(); |
| void allocateAndPrimeGroupAttributes(); // used after a rule-based transformation |
| virtual void primeGroupAnalysis(); |
| |
| // -------------------------------------------------------------------- |
| // A method that provides the set of values that can potentially be |
| // produced as output by this operator. These are values over and |
| // above those that are prodcued as Characteristic Outputs. |
| // -------------------------------------------------------------------- |
| virtual void getPotentialOutputValues(ValueIdSet & vs) const; |
| |
| virtual void getPotentialOutputValuesAsVEGs(ValueIdSet& outputs) const; |
| |
| // --------------------------------------------------------------------- |
| // pullUpPreds() |
| // |
| // This method is used during subquery transformation. |
| // It moves predicates from transformed children of the node to the |
| // appropriate place in the node. |
| // If a child loses some predicates then recomputeOuterReferences() |
| // must be called on it. |
| // |
| // --------------------------------------------------------------------- |
| virtual void pullUpPreds(); |
| |
| // --------------------------------------------------------------------- |
| // recomputeOuterReferences() |
| // |
| // This method is used by the normalizer for recomputing the |
| // outer references (external dataflow input values) that are |
| // still referenced by each operator in the subquery tree |
| // after the predicate pull up is complete. |
| // |
| // --------------------------------------------------------------------- |
| virtual void recomputeOuterReferences(); |
| |
| // -------------------------------------------------------------------- |
| // pushdownCoveredExpr() |
| // |
| // In order to compute the Group Attributes for a relational operator |
| // an analysis of all the scalar expressions associated with it is |
| // performed. The purpose of this analysis is to identify the sources |
| // of the values that each expression requires. As a result of this |
| // analysis values are categorized as external dataflow inputs or |
| // those that can be produced completely by a certain child of the |
| // relational operator. |
| // |
| // This method is invoked on each relational operator. It causes |
| // a) the pushdown of predicates and |
| // b) the recomputation of the Group Attributes of each child. |
| // The recomputation is required either because the child is |
| // assigned new predicates or is expected to compute some of |
| // expressions that are required by its parent. |
| // c) Classification of outputs into essential and non-essential outputs |
| // |
| // Parameters: |
| // |
| // const ValueIdSet & outputExprOnOperator |
| // IN: a read-only reference to the outputs of a node. This will |
| // be used to classify the child outputs into essential & |
| // non-essential outputs. Ideally this argument is not needed |
| // as a relExpr is capable of finding out what its outputs are. |
| // This argument is being kept so that many callers do not |
| // have to change. |
| // |
| // ValueIdSet & newExternalInputs |
| // IN : a reference to a set of new external inputs (ValueIds) |
| // that are provided by this operator for evaluating the |
| // the above expressions. |
| // |
| // ValueIdSet & predOnOperator |
| // IN : the set of predicates existing on the operator |
| // OUT: a subset of the original predicates. Some of the |
| // predicate factors may have been pushed down to |
| // the operator's children. |
| // |
| // ValueIdSet & nonPredNonOutputExprOnOperator |
| // IN: A pointer to a set of expressions that are |
| // associated with this operator. Typically, they do not |
| // include the selection predicates. For example this will |
| // include the group and aggregate expr of a GroupBy, any |
| // order requirement on a Root node |
| // |
| // short childId |
| // IN : This is an optional parameter. |
| // If supplied, it is a zero-based index for a specific child |
| // on which the predicate pushdown should be attempted. |
| // If not supplied, or a null pointer is supplied, then |
| // the pushdown is attempted on all the children. |
| // |
| // --------------------------------------------------------------------- |
| virtual void pushdownCoveredExpr( |
| const ValueIdSet & outputExprOnOperator, |
| const ValueIdSet & newExternalInputs, |
| ValueIdSet& predOnOperator, |
| const ValueIdSet * |
| nonPredNonOutputExprOnOperator = NULL, |
| Lng32 childId = (-MAX_REL_ARITY)); |
| |
| |
| // ----------------------------------------------------------------------- |
| // RelExpr::computeValuesReqdForPredicates() |
| // This function obtains the values required to evaluate the predicates |
| // contained in setOfExpr (first argument). The |
| // computed list of values is returned in the second argument |
| // ----------------------------------------------------------------------- |
| static void computeValuesReqdForPredicates(const ValueIdSet& setOfExpr, |
| ValueIdSet& reqdValues, |
| NABoolean addInstNull = FALSE); |
| |
| // ----------------------------------------------------------------------- |
| // RelExpr::computeValuesReqdForOutput() |
| // This function obtains the values required to evaluate the predicates |
| // contained in setOfExpr (first argument). The |
| // computed list of values is returned in the third argument. |
| // ----------------------------------------------------------------------- |
| static void computeValuesReqdForOutput(const ValueIdSet& setOfExpr, |
| const ValueIdSet& newExternalInputs, |
| ValueIdSet& outputsOnOperator); |
| |
| // ----------------------------------------------------------------------- |
| // RelExpr::preventPushDownPartReq() |
| // This function returns TRUE if both children have plans, are small and |
| // not partitioned. Looking through all group's plans could be expensive, |
| // especially at the end of the compilation process when we have lots of |
| // plans in the memo. The idea of heuristic4, implemented here, is to check |
| // just the first plan's partitioning properties for the child's group. |
| // Under SYSTEM option we try to create parallel plan first. So if this |
| // first plan happend to be non-parallel because we couldn't create a |
| // parallel one we don't want to try parallelism again. |
| // SO, if this is the only child and the child is small and non-partitioned |
| // then the function returns TRUE preventing creation of parallel plan. If |
| // the child is partitioned the function will return FALSE allowing creation |
| // of parallel plan for the child's group. If the current expression has two |
| // children they should be both "small" and have their first plans non- |
| // parallel and succeeded in the current pass to prevent attempt to create |
| // another parallel plan. |
| |
| NABoolean preventPushDownPartReq |
| (const ReqdPhysicalProperty* rppForMe, |
| const EstLogPropSharedPtr& inLogProp ); |
| // ********************************************************************* |
| // Helper functions and methods used by the optimizer. |
| // ********************************************************************* |
| |
| // synthesize logical properties |
| virtual void synthLogProp(NormWA * normWAPtr = NULL); |
| |
| // finish the synthesis of logical properties by setting various cardinality |
| // related attributes |
| virtual void finishSynthEstLogProp(); |
| |
| // synthesize estimated logical properties given a specific set of |
| // input log. properties |
| virtual void synthEstLogProp(const EstLogPropSharedPtr& inputLP); |
| |
| // synthesize estimated logical properties for unary and leaf ops |
| EstLogPropSharedPtr synthEstLogPropForUnaryLeafOp |
| (const EstLogPropSharedPtr& inputEstLogProp, |
| const ColStatDescList & childStats, |
| CostScalar initialRowcount = 1, |
| CostScalar *childMaxCardEst = NULL) const; |
| |
| // call the optimizer with requirements |
| RelExpr * optimize(NABoolean exception = FALSE, |
| Guidance* guidance = NULL, |
| ReqdPhysicalProperty * rpp = NULL, |
| CostLimit* costLimit = NULL); |
| |
| RelExpr * optimize2(); |
| |
| RelExpr * checkAndReorderTree(); |
| |
| void clearAllEstLogProp(); |
| |
| // clear logical properties of me and mine children |
| void clearAllLogProp(); |
| |
| virtual RelExpr * reorderTree(NABoolean & treeModified, |
| NABoolean doReorderJoin); |
| |
| // added for trigger project, to activate after trigger transformation |
| virtual RelExpr * fixupTriggers(NABoolean & treeModified); |
| |
| // --------------------------------------------------------------------- |
| // comparison, hash, and copy methods |
| // --------------------------------------------------------------------- |
| |
| virtual SimpleHashValue hash(); // from ExprNode |
| virtual HashValue topHash(); |
| HashValue treeHash(); |
| virtual NABoolean patternMatch(const RelExpr & other) const; |
| virtual NABoolean duplicateMatch(const RelExpr & other) const; |
| |
| // "virtual copy constructor", provides a generic method to duplicate |
| // the top node of an expression tree or an entire tree. |
| virtual RelExpr * copyTopNode(RelExpr *derivedNode = NULL, |
| CollHeap* outHeap = NULL); |
| RelExpr * copyTree(CollHeap* heap = NULL); |
| RelExpr * copyRelExprTree(CollHeap* outHeap = NULL); |
| const RelExpr * getOriginalExpr(NABoolean transitive = TRUE) const; |
| RelExpr * getOriginalExpr(NABoolean transitive = TRUE); |
| |
| // -------------------------------------------------------------------- |
| // Methods used internally by Cascades |
| // -------------------------------------------------------------------- |
| |
| virtual NABoolean isLogical() const; |
| virtual NABoolean isPhysical() const; |
| |
| // these functions must not be redefined, except for Cut, Subtree, |
| // or Wildcard nodes |
| virtual NABoolean isCutOp() const; |
| virtual NABoolean isSubtreeOp() const; |
| virtual NABoolean isWildcard() const; |
| |
| // get/set the Cascades internal data of a RelExpr |
| // NOTE: these methods are not really intended for general use!!! |
| inline CascadesGroupId getGroupId() const { return groupId_; } |
| inline void setGroupId(CascadesGroupId g) { groupId_ = g; } |
| |
| inline RelExpr * getNextInGroup() { return groupNext_; } |
| inline void setNextInGroup(RelExpr * v) { groupNext_ = v; } |
| inline RelExpr * getNextInBucket() { return bucketNext_; } |
| inline void setNextInBucket(RelExpr * v) { bucketNext_ = v; } |
| |
| inline const RuleSubset &getContextInsensRules() const { return contextInsensRules_; } |
| inline RuleSubset &contextInsensRules() { return contextInsensRules_; } |
| inline const RulesPerContextList &getContextSensRules() const { return contextSensRules_; } |
| inline RulesPerContextList &contextSensRules() { return contextSensRules_; } |
| |
| // --------------------------------------------------------------------- |
| // methods needed by Cascades iff an operator is logical |
| // --------------------------------------------------------------------- |
| |
| // determine how many promising moves to pursue in exploration |
| virtual Int32 computeExploreExprCutoff(RuleWithPromise promisingMoves [], |
| Int32 numberOfMoves, |
| RelExpr* pattern, |
| Guidance* myGuidance); |
| |
| // determine how many promising moves to pursue in optimization |
| virtual Int32 computeOptimizeExprCutoff(RuleWithPromise promisingMoves [], |
| Int32 numberOfMoves, |
| Guidance* myGuidance, |
| Context* myContext); |
| |
| // --------------------------------------------------------------------- |
| // Methods needed by Cascades iff an operator is physical |
| // --------------------------------------------------------------------- |
| |
| // --------------------------------------------------------------------- |
| // A virtual function to permit the allocation of an operator-specific |
| // work space that is used during plan generation. |
| // --------------------------------------------------------------------- |
| virtual PlanWorkSpace* allocateWorkSpace() const; |
| |
| // --------------------------------------------------------------------- |
| // Obtain a pointer to a CostMethod object that provides access |
| // to the cost estimation functions for nodes of this type. |
| // --------------------------------------------------------------------- |
| virtual CostMethod* costMethod() const; |
| |
| // --------------------------------------------------------------------- |
| // The main driver for plan generation. |
| // Generate a context for optimizing a child of this operator, |
| // given the optimization context and an operator-specific |
| // work space that is used during plan generation. |
| // The (implementation) rule and the guidance that was used |
| // for creating this instance of the operator are also supplied. |
| // They are used for creating a new guidance that is used for |
| // optimizing the child. |
| // --------------------------------------------------------------------- |
| virtual Context* createPlan(Context* myContext, |
| PlanWorkSpace* pws, |
| Rule* rule, |
| Guidance* myGuidance, |
| Guidance* & childGuidance); |
| |
| // --------------------------------------------------------------------- |
| // Create a Context for a specific child and store it in the |
| // PlanWorkSpace. |
| // This method is called from within the implementation |
| // of createPlan(). |
| // --------------------------------------------------------------------- |
| virtual Context* createContextForAChild(Context* myContext, |
| PlanWorkSpace* pws, |
| Lng32& childIndex); |
| |
| // --------------------------------------------------------------------- |
| // Create a Context for a specific child, given a sortkey and |
| // arranged columns. |
| // This method should be called from within the implementation |
| // of createContextForAChild() for operators that require the dataflow |
| // produced by their child to be sorted. |
| // --------------------------------------------------------------------- |
| Context * generateContext(Context* myContext, |
| PlanWorkSpace* pws, |
| Lng32 childIndex, |
| const ValueIdSet* const arrangedCols, |
| const ValueIdList* const sortKey, |
| PartitioningRequirement* partReq); |
| |
| // --------------------------------------------------------------------- |
| // A virtual function for computing the cost limit to be imposed |
| // on the child that is about to be optimized. |
| // --------------------------------------------------------------------- |
| virtual CostLimit* computeCostLimit(const Context* myContext, |
| PlanWorkSpace* pws); |
| |
| // --------------------------------------------------------------------- |
| // A virtual function that determines if the current plan is |
| // compatible with any forced plan constraints and is viable. |
| // --------------------------------------------------------------------- |
| virtual NABoolean currentPlanIsAcceptable(Lng32 planNo, |
| const ReqdPhysicalProperty* const rppForMe) const; |
| |
| // --------------------------------------------------------------------- |
| // A virtual function for associating one of the Contexts |
| // that was created for each child of this operator |
| // with the Context for this operator. |
| // --------------------------------------------------------------------- |
| virtual NABoolean findOptimalSolution(Context* myContext, |
| PlanWorkSpace* pws); |
| |
| // --------------------------------------------------------------------- |
| // calculate physical properties from child's phys properties |
| // (assuming the children are already optimized and have physical properties) |
| // (used in the implementation of createPlan) |
| // --------------------------------------------------------------------- |
| virtual PhysicalProperty* synthPhysicalProperty(const Context* myContext, |
| const Lng32 planNumber, |
| PlanWorkSpace *pws); |
| |
| // --------------------------------------------------------------------- |
| // A helper method for synthesizing the physical properties for the leaf |
| // operators scan, cursor insert, cursor update, and cursor delete. |
| // --------------------------------------------------------------------- |
| PhysicalProperty* synthDP2PhysicalProperty( |
| const Context* myContext, |
| const ValueIdList& sortOrder, |
| const IndexDesc* indexDesc, |
| const SearchKey* partSearchKey); |
| |
| // --------------------------------------------------------------------- |
| // create or share an optimization goal for a child group |
| // --------------------------------------------------------------------- |
| Context* shareContext(Lng32 childIndex, |
| const ReqdPhysicalProperty* const reqdPhys, |
| const InputPhysicalProperty* const inputPhys, |
| CostLimit* costLimit, |
| Context* parentContext, |
| const EstLogPropSharedPtr& inputLogProp, |
| RelExpr *explicitlyRequiredShape = NULL) const; |
| |
| // --------------------------------------------------------------------- |
| // release a binding that was created by means other than using a |
| // BINDING object (e.g. a binding created by Context::bindSolutionTree() |
| // --------------------------------------------------------------------- |
| void releaseBindingTree(NABoolean memoIsMoribund = FALSE); |
| |
| // --------------------------------------------------------------------- |
| // A virtual function that decides if ESP parallelism is allowed |
| // by the settings in the defaults table, or if the number of |
| // ESPs is being forced. |
| // --------------------------------------------------------------------- |
| virtual DefaultToken getParallelControlSettings ( |
| const ReqdPhysicalProperty* const rppForMe, /*IN*/ |
| Lng32& numOfESPs, /*OUT*/ |
| float& allowedDeviation, /*OUT*/ |
| NABoolean& numOfESPsForced /*OUT*/) const; |
| |
| // --------------------------------------------------------------------- |
| // A virtual function that decides if ESP parallelism is worth it |
| // for the operator. |
| // --------------------------------------------------------------------- |
| virtual NABoolean okToAttemptESPParallelism ( |
| const Context* myContext, /*IN*/ |
| PlanWorkSpace* pws, /*IN*/ |
| Lng32& numOfESPs, /*OUT*/ |
| float& allowedDeviation, /*OUT*/ |
| NABoolean& numOfESPsForced /*OUT*/) ; |
| |
| // --------------------------------------------------------------------- |
| // Checks the required physical properties to see if they require |
| // something that only an enforcer (i.e. sort or exchange) can provide. |
| // This method is called by all implementations of the |
| // method topMatch() except the enforcer rule implementations. |
| // --------------------------------------------------------------------- |
| NABoolean rppRequiresEnforcer |
| (const ReqdPhysicalProperty* const rppForMe) const; |
| |
| // --------------------------------------------------------------------- |
| // Compares the pivs of this node to those of its children. |
| // If they are different, they are made the same. |
| // --------------------------------------------------------------------- |
| virtual void replacePivs(); |
| |
| // --------------------------------------------------------------------- |
| // Performs mapping on the partitioning function, from this |
| // operator to the designated child, if the operator has/requires mapping. |
| // Note that this default implementation does no mapping. |
| // --------------------------------------------------------------------- |
| virtual PartitioningFunction* mapPartitioningFunction( |
| const PartitioningFunction* partFunc, |
| NABoolean rewriteForChild0) ; |
| |
| virtual void addPartKeyPredsToSelectionPreds( |
| const ValueIdSet& partKeyPreds, |
| const ValueIdSet& pivs) |
| {} |
| |
| // ********************************************************************* |
| // Helper functions and methods during the pre code generation phase. |
| // ********************************************************************* |
| |
| // --------------------------------------------------------------------- |
| // get... methods for the code generator. |
| // --------------------------------------------------------------------- |
| void getOutputValuesOfMyChildren(ValueIdSet & vs) const; |
| virtual void getInputValuesFromParentAndChildren(ValueIdSet & vs) const; |
| void getInputAndPotentialOutputValues(ValueIdSet& vs) const; |
| |
| ULng32 getDefault(DefaultConstants); |
| |
| // cleanup after the generator phase |
| virtual void cleanupAfterCompilation(); |
| |
| // --------------------------------------------------------------------- |
| // This method is used to propagate to all Sort nodes in the query |
| // if the top N sorted rows are needed. Called when the user |
| // has specified [first <N>] in their select statement. The actual |
| // value of <N> is sent to the operator at runtime via a GET_N request. |
| // See executor queue structure for details about GET_N request. |
| // The value of 'val' is used to set or reset this in the Sort node. |
| // --------------------------------------------------------------------- |
| virtual void needSortedNRows(NABoolean val); |
| |
| // --------------------------------------------------------------------- |
| // Methods for retrieving information from the best plan. |
| // NOTE: The following set of methods should be used ONLY AFTER |
| // optimization is complete, at which point physical property, |
| // cost, and estimated # rows are transferred from the optimal plan. |
| // --------------------------------------------------------------------- |
| |
| inline const PhysicalProperty* getPhysicalProperty() const |
| { return physProp_; } |
| inline void setPhysicalProperty (const PhysicalProperty* physProp) |
| { physProp_ = physProp; } |
| |
| inline const Cost * getOperatorCost() const |
| { return operatorCost_; } |
| |
| inline void setOperatorCost (const Cost * cost) |
| { operatorCost_ = cost; } |
| |
| inline const Cost * getRollUpCost() const |
| { return rollUpCost_; } |
| |
| inline void setRollUpCost (const Cost * cost) |
| { rollUpCost_ = cost; } |
| |
| inline const CostScalar getEstRowsUsed() const { return estRowsUsed_; } |
| inline void setEstRowsUsed(CostScalar r) { estRowsUsed_ = r; } |
| |
| inline const CostScalar getInputCardinality() const { return inputCardinality_; } |
| inline void setInputCardinality(CostScalar r) { inputCardinality_ = r; } |
| |
| inline const CostScalar getMaxCardEst() const { return maxCardEst_; } |
| inline void setMaxCardEst(CostScalar r) { maxCardEst_ = r; } |
| |
| static short bmoGrowthPercent(CostScalar e, CostScalar m); |
| // --------------------------------------------------------------------- |
| // for debugging |
| // --------------------------------------------------------------------- |
| |
| // add all the expressions that are local to this |
| // node to an existing list of expressions |
| virtual void addLocalExpr(LIST(ExprNode *) &xlist, |
| LIST(NAString) &llist) const; |
| |
| void addExplainPredicates(ExplainTupleMaster * explainTuple, |
| Generator * generator); |
| |
| ExplainTuple *addExplainInfo(ComTdb *tdb, |
| ExplainTuple *leftChild, |
| ExplainTuple *rightChild, |
| Generator *generator); |
| |
| virtual ExplainTuple *addSpecificExplainInfo(ExplainTupleMaster *explainTuple, |
| ComTdb * tdb, |
| Generator *generator); |
| |
| |
| virtual void print(FILE * f = stdout, |
| const char * prefix = "", |
| const char * suffix = "") const; |
| |
| virtual void unparse(NAString &result, |
| PhaseEnum phase = DEFAULT_PHASE, |
| UnparseFormatEnum form = USER_FORMAT, |
| TableDesc * tabId = NULL) const; |
| |
| |
| // -- Triggers |
| // Count the number of nodes in the tree. |
| Int32 nodeCount() const; |
| |
| // Determine whether a node of the given type exists in the tree. |
| NABoolean containsNode(OperatorTypeEnum nodeType); |
| |
| // --------------------------------------------------------------------- |
| // isBigMemoryOperator() returns TRUE for operators which intend to use |
| // an amount of memory per cpu that is greater than the limit. It is |
| // used during costing. The context is needed because we need the number of |
| // CPU the operator can execute on to estimate its memory needs on each |
| // CPU, and we also need the input logical properties to estimate the |
| // size of the table the operator is handling. Both of them are stored |
| // in the Context object. We also need to know the plan number, |
| // since different plans for the same operator may consume different |
| // quantities of memory. For example, a Type-2 parallel hash join vs. |
| // a Type-1 parallel hash join. |
| // --------------------------------------------------------------------- |
| virtual NABoolean isBigMemoryOperator(const PlanWorkSpace* pws, |
| const Lng32 planNumber); |
| |
| virtual CostScalar getEstimatedRunTimeMemoryUsage(Generator *generator, NABoolean perNode, Lng32 *numStreams = NULL) {return 0;} |
| virtual double getEstimatedRunTimeMemoryUsage(Generator *generator, ComTdb * tdb) {return 0;} |
| |
| inline NABoolean isinBlockStmt() const |
| { return isinBlockStmt_; } |
| inline NABoolean isinBlockStmt() |
| { return isinBlockStmt_; } |
| inline void setBlockStmt(NABoolean cs) |
| { isinBlockStmt_ = cs; } |
| |
| // set the isinBlockStmt_ flag to x for the entire tree rooted |
| // at this RelExpr. |
| void setBlockStmtRecursively(NABoolean x); |
| |
| double calculateNoOfLogPlans(Lng32& numOfMergedExprs); |
| |
| double calculateSubTreeComplexity(NABoolean& antiSemiJoinQuery); |
| |
| // calculate a query's MJ complexity, |
| // shoud be called after MJ rewrite |
| double calculateQueryMJComplexity(double &n,double &n2,double &n3,double &n4); |
| |
| void makeListBySize(LIST(CostScalar) & orderedList, |
| NABoolean recompute); |
| |
| void setFirstNRows(Int64 firstNRows) { firstNRows_ = firstNRows; } |
| Int64 getFirstNRows() { return firstNRows_; } |
| |
| virtual PlanPriority computeOperatorPriority |
| (const Context* context, |
| PlanWorkSpace *pws=NULL, |
| Lng32 planNumber=0); |
| |
| NABoolean oltOpt() { return oltOptInfo_.oltAnyOpt(); }; |
| NABoolean oltOptLean() { return oltOptInfo_.oltEidLeanOpt(); }; |
| |
| OltOptInfo &oltOptInfo() { return oltOptInfo_; }; |
| |
| // get TableDesc from the expression. It could be directly |
| // attached to the expression, as in Scan, or could be a |
| // part of GroupAnalysis, as in cut-opp. For expressions |
| // which do not have a tableDesc attached to them, like Join |
| // it would be NULL |
| TableDesc* getTableDescForExpr(); |
| |
| NABoolean treeContainsEspExchange(); |
| |
| /////////////////////////////////////////////////////////// |
| |
| virtual NABoolean pilotAnalysis(QueryAnalysis* qa); |
| virtual void jbbAnalysis(QueryAnalysis* qa); |
| virtual void jbbJoinDependencyAnalysis(ValueIdSet & predsWithDependencies); |
| virtual void predAnalysis(QueryAnalysis* qa); |
| virtual RelExpr* convertToMultiJoinSubtree(QueryAnalysis* qa); |
| virtual EstLogPropSharedPtr setJBBInput(EstLogPropSharedPtr & inLP = (*GLOBAL_EMPTY_INPUT_LOGPROP)); |
| virtual RelExpr* expandMultiJoinSubtree(); |
| GroupAnalysis* getGroupAnalysis(); |
| |
| /////////////////////////////////////////////////////////// |
| |
| // do some analysis on the initial plan |
| // this is called at the end of the analysis phase |
| virtual void analyzeInitialPlan(); |
| |
| virtual void computeRequiredResources(RequiredResources & reqResources, |
| EstLogPropSharedPtr & inLP = (*GLOBAL_EMPTY_INPUT_LOGPROP)); |
| |
| virtual void computeMyRequiredResources(RequiredResources & reqResources, |
| EstLogPropSharedPtr & inLP); |
| |
| // Accessor for the rowsetIterator flag. |
| NABoolean isRowsetIterator() const { return rowsetIterator_; } |
| // Mutator for the rowsetIterator flag. |
| void setRowsetIterator(NABoolean rowsetIterator) |
| { rowsetIterator_ = rowsetIterator; } |
| |
| // Accessor for the tolerateNonFatalError flag. |
| AtomicityType getTolerateNonFatalError() const { return tolerateNonFatalError_; } |
| // Mutator for the tolerateNonFatalError flag. |
| void setTolerateNonFatalError(AtomicityType tolerateNonFatalError) |
| { tolerateNonFatalError_ = tolerateNonFatalError; } |
| |
| // method used by generator to detrmine if rowsAffected needs to be set in PA. |
| // The base class implementaion returns FALSE. FirstN and GenericUpdate are the only |
| // classes that return true currently. |
| virtual NABoolean computeRowsAffected() const |
| {return FALSE;} ; |
| |
| inline NABoolean markedForElimination() const |
| { return markedForElimination_; } |
| inline void setMarkedForElimination(NABoolean b) |
| { markedForElimination_ = b; } |
| |
| inline NABoolean isExtraHub() const |
| { return isExtraHub_; } |
| inline void setIsExtraHub(NABoolean b) |
| { isExtraHub_ = b; } |
| |
| // methods to set, get and update substitute potential |
| void setPotential(Int32 potential) { potential_ = potential; }; |
| Int32 getPotential() const { return potential_;}; |
| Int32 updatePotential(Int32 potential) |
| { |
| if ((potential != -1) && |
| (potential_ == -1)) |
| { |
| potential_ = potential; |
| } |
| |
| return potential_; |
| }; |
| |
| void setExpandShortRows(NABoolean val) |
| { (val ? (flags_ |= EXPAND_SHORT_ROWS) : (flags_ &= ~EXPAND_SHORT_ROWS)); } |
| |
| NABoolean expandShortRows() |
| { return ((flags_ & EXPAND_SHORT_ROWS) != 0); } |
| |
| // For compressed internal format. |
| // At codegen some nodes will switch from compressed internal format to |
| // the exploded format when they are directly beneath the root node. |
| void setParentIsRoot(NABoolean val) |
| { (val ? (flags_ |= PARENT_IS_ROOT) : (flags_ &= ~PARENT_IS_ROOT)); } |
| |
| NABoolean isParentRoot() |
| { return ((flags_ & PARENT_IS_ROOT) != 0); } |
| |
| virtual int getCifBMOWeight() |
| { |
| return 1; |
| } |
| |
| NABoolean dopReduced() const { return dopReduced_; }; |
| void setDopReduced(NABoolean x) { dopReduced_ = x; }; |
| |
| void adjustTopPartFunc(Lng32 newDop); |
| |
| protected: |
| |
| void synthPropForBindChecks(); |
| |
| private: |
| |
| enum Flags { |
| EXPAND_SHORT_ROWS = 0x00000001 // expand short rows when added columns |
| ,PARENT_IS_ROOT = 0x00000002 // compressed internal format |
| }; |
| |
| // every relational expression node has the ability to perform |
| // a selection on its result and to project some of its output |
| // columns (or expressions on its output columns). |
| |
| ItemExpr * selection_; // generated by the parser |
| ValueIdSet predicates_; // predicates represented as a set |
| |
| // A descriptor for the table derived from the RelExpr. |
| RETDesc * RETDesc_; |
| |
| // During the bind and normalization phase, each relational |
| // operator has a private set of Group Attributes. Within |
| // Cascades, once the operator is memoized, it shares the |
| // Group Attributes for the Cascades Group. |
| GroupAttributes * groupAttr_; |
| |
| // Cascades-specific part of a relational expression |
| CascadesGroupId groupId_; // pointer back to eq. class |
| |
| RelExpr * groupNext_; // list within group |
| RelExpr * bucketNext_; // list within hash bucket |
| RuleSubset contextInsensRules_; // context insensitive rules tried |
| // on this expression |
| |
| RulesPerContextList contextSensRules_; // context sensitive rules tried |
| // per context |
| |
| // The children of an expression (its operands). Only a fixed number of |
| // children can be stored here (could use a virtual operator[] to |
| // overcome this, if it ever becomes necessary). |
| ExprGroupId child_[MAX_REL_ARITY]; |
| |
| // The following fields are applicable only after optimization is complete. |
| // After the optimal plan is selected, the following properties are transferred |
| // from the CascadesPlan structure to the following placeholders for the |
| // purposes of code generation. |
| |
| const PhysicalProperty * physProp_; // physical properties for the optimal plan |
| |
| // --------------------------------------------------------------------- |
| // The operator cost is the cost for this operator independent |
| // of its children. |
| // --------------------------------------------------------------------- |
| const Cost * operatorCost_; // operator cost for the optimal plan |
| |
| // --------------------------------------------------------------------- |
| // The roll-up cost is the cost of the sub-plan rooted at |
| // this operator (operator cost of this operator combined with |
| // the operator's children cost) |
| // --------------------------------------------------------------------- |
| const Cost * rollUpCost_; // roll up cost for the optimal plan |
| CostScalar estRowsUsed_; // est. # rows produced from this plan per probe |
| CostScalar inputCardinality_; // est. # of probes |
| // (cardinality of input logical prop.) for this plan |
| CostScalar maxCardEst_; // maximum cardinality estimate |
| |
| // Triggers -- |
| // Information for Triggers, RI and IM. |
| InliningInfo inliningInfo_; |
| |
| //++MV |
| // Used by inlining mechanism for adding optimizer constraints |
| ItemExpr *uniqueColumnsTree_; |
| ValueIdSet uniqueColumns_; |
| |
| CardConstraint *cardConstraint_; |
| |
| //--MV |
| |
| SubTreeAccessSet *accessSet0_; |
| SubTreeAccessSet *accessSet1_; |
| |
| // An object counter for debugging purpose only |
| static THREAD_P ObjectCounter *counter_; |
| |
| NABoolean isinBlockStmt_; // is this operator inside a compound statement? |
| |
| // if set to -1, return all rows. |
| // Otherwise, return firstNRows_ at runtime. |
| Int64 firstNRows_; |
| |
| UInt32 flags_; |
| |
| // various olt type optimizations. See OptUtilIncludes.h. |
| // Set during preCodeGen phase. |
| OltOptInfo oltOptInfo_; |
| |
| // Should this node be enabled for counting rowset rownumber counting? |
| // Currently only UnPack, TupleFlow and NestedJoin nodes will have this attribute |
| // set to TRUE for rowset IUD statements |
| NABoolean rowsetIterator_; |
| |
| // Should this node continue execution after a Nonfatal error has been seen? |
| // Currently only UnPack & Insert & NestedJoin have this attribute set to NOT_ATOMIC for NOT ATOMIC |
| // rowset insert statements. Root, PA & TupleFlow also have a similar flag set |
| // in their TDBs during codegen. |
| AtomicityType tolerateNonFatalError_; |
| |
| // optimizer hint |
| Hint *hint_; |
| |
| // if TRUE, this join can be eliminated because |
| // (a) it is guaranteed to match one and only one row |
| // (b) no outputs from the inner child are used beyond this join |
| // The marking is done during Join::synthLogProp() and the actual |
| // removal during Join::SemanticQueryOptimization() |
| NABoolean markedForElimination_ ; |
| |
| // if TRUE, this join can be placed at the top of the join chain because |
| // (a) it is guaranteed to match one and only one row |
| // (therefore does not increase/decrease dataflow) |
| // (b) no outputs from the inner child are used beyond this join, |
| // excepts as outputs of the root node (part of select list) |
| // The marking is done during Join::synthLogProp() and the actual |
| // reordering is done during Join::leftLinearizeTree() |
| |
| NABoolean isExtraHub_; |
| |
| // potential of the substitute |
| Int32 potential_; |
| |
| // Used to help determine whether hash join |
| // optimizations may be turned on |
| // This flag is set to true when an Insert/Update/Delete has been |
| // seen |
| NABoolean seenIUD_; |
| |
| // the following data members were added solely for the cascades display gui |
| // so we can trace each relexpr to its creator and source |
| // begin relexpr tracking info |
| Lng32 parentTaskId_; // {parentTaskId_,stride_} of the CascadesTask |
| short stride_; // that created this RelExpr |
| |
| CascadesGroupId sourceGroupId_; // GroupId of creator task of this relexpr |
| Int32 birthId_; // TaskCount when this relexpr was created |
| |
| ULng32 memoExprId_; // MemoExprId of this relexpr |
| ULng32 sourceMemoExprId_; // MemoExprId of the source of this relexpr |
| |
| double costLimit_; // CostLimit of task's context that created this relexpr |
| // end relexpr tracking info |
| |
| ExpTupleDesc::TupleDataFormat cachedTupleFormat_; |
| NABoolean cachedResizeCIFRecord_; |
| NABoolean cachedDefrag_; |
| |
| // Record the status whether my dop has been reduced. That is, whether |
| // the partfunc pointed by my spp has a dop reduction. |
| NABoolean dopReduced_; |
| |
| // if we copy an expression with copyTopNode() then |
| // remember the original here, e.g. to find VEG regions |
| RelExpr *originalExpr_; |
| |
| NAString operKey_; |
| |
| public: |
| |
| // begin: accessors & mutators for relexpr tracking info |
| Lng32 getParentTaskId() { return parentTaskId_; } |
| short getSubTaskId() { return stride_; } |
| Int32 getBirthId() { return birthId_; } |
| |
| const NAString getCascadesTraceInfoStr(); |
| void setCascadesTraceInfo(RelExpr *src); |
| // end: accessors & mutators for relexpr tracking info |
| enum CifUseOptions |
| { |
| CIF_ON, |
| CIF_OFF, |
| CIF_SYSTEM |
| }; |
| |
| |
| void cacheTupleFormatAndResizeFlag(ExpTupleDesc::TupleDataFormat tf, NABoolean r, NABoolean d) |
| { |
| cachedTupleFormat_ = tf; |
| cachedResizeCIFRecord_ = r; |
| cachedDefrag_ = d; |
| } |
| |
| ExpTupleDesc::TupleDataFormat getCachedTupleFormat() |
| { |
| return cachedTupleFormat_; |
| } |
| |
| NABoolean getCachedResizeCIFRecord() |
| { |
| return cachedResizeCIFRecord_; |
| } |
| |
| NABoolean getCachedDefrag() |
| { |
| return cachedDefrag_; |
| } |
| |
| CostScalar getChild0Cardinality(const Context*); |
| |
| NAString *getKey(); |
| }; // class RelExpr |
| |
| // ----------------------------------------------------------------------- |
| // List of RelExprs. |
| // ----------------------------------------------------------------------- |
| class RelExprList : public LIST (RelExpr *) |
| { |
| public: |
| |
| RelExprList(CollHeap* h) : LIST (RelExpr *)(h) {} |
| |
| // copy ctor |
| RelExprList (const RelExprList & rlist, CollHeap * h=0) : |
| LIST (RelExpr *)(rlist, h) {} |
| |
| // --------------------------------------------------------------------- |
| // Insert RelExpr into list order by estimated rowcount (of the logical |
| // properties). |
| // --------------------------------------------------------------------- |
| void insertOrderByRowcount (RelExpr * expr); |
| |
| NABoolean operator== (const RelExprList &other) const; |
| NABoolean operator!= (const RelExprList &other) const; |
| |
| }; // RelExprList |
| |
| // ----------------------------------------------------------------------- |
| // Leaf Operator (for use in rule patterns and substitutes only). |
| // A leaf operator in a pattern matches any logical expression. When |
| // firing the rule, the binding presented to the rule contains the |
| // leaf operator as its leaf. |
| // ----------------------------------------------------------------------- |
| class CutOp : public RelExpr |
| { |
| |
| public: |
| |
| CutOp (Int32 index, |
| CollHeap *oHeap = CmpCommon::statementHeap()) : |
| RelExpr(REL_CUT_OP, NULL, NULL, oHeap) |
| { index_ = index; expr_ = NULL; } |
| |
| virtual ~CutOp(); |
| |
| virtual void print(FILE * f = stdout, |
| const char * prefix = "", |
| const char * suffix = "") const; |
| virtual Int32 getArity () const; |
| virtual NABoolean isCutOp () const; |
| virtual RelExpr * copyTopNode(RelExpr *, |
| CollHeap* outHeap = 0); |
| inline Int32 getIndex() { return index_; } |
| void setGroupIdAndAttr(CascadesGroupId groupId); |
| inline RelExpr * getExpr() const { return expr_; } |
| void setExpr(RelExpr *e); |
| |
| virtual void synthLogProp(NormWA * normWAPtr = NULL); |
| |
| virtual const NAString getText() const; |
| |
| private: |
| |
| Int32 index_; // in rules, used to distinguish multiple children |
| RelExpr *expr_; // only for bindings fixed to a particular expression |
| |
| }; // CutOp |
| |
| // ----------------------------------------------------------------------- |
| // Tree operator (for use in rule patterns and substitutes only). |
| // A tree operator in a pattern matches any logical expression. When |
| // firing the rule, the binding is materialized beyond the tree operator |
| // all the way down to leaf nodes. Depending on whether the "all" |
| // data member is set to TRUE, all possible bindings for the tree node are |
| // or just one (randomly selected) binding is presented to the rule. |
| // Rules using a tree node must redefine their nextSubstitute() method |
| // since the generic method can not handle tree nodes. |
| // ----------------------------------------------------------------------- |
| class SubtreeOp : public RelExpr |
| { |
| |
| public: |
| |
| inline SubtreeOp (NABoolean all) : RelExpr(REL_TREE_OP) {all_ = all;} |
| virtual ~SubtreeOp(); |
| virtual Int32 getArity() const; |
| virtual NABoolean isSubtreeOp() const; |
| virtual const NAString getText() const; |
| virtual RelExpr * copyTopNode(RelExpr *, |
| CollHeap* outHeap = 0); |
| inline NABoolean all_bindings() const { return all_; } |
| |
| private: |
| |
| NABoolean all_; // find all bindings? |
| |
| }; // SubtreeOp |
| |
| // ----------------------------------------------------------------------- |
| // A wildcard node can appear in rule patterns and rule substitutes. |
| // When used in a substitute, the designator of a wildcard must match |
| // a designator in the pattern. The wildcard is then replaced with |
| // the child node that matched the corresponding wildcard in the pattern. |
| // ----------------------------------------------------------------------- |
| class WildCardOp: public RelExpr |
| { |
| |
| public: |
| |
| WildCardOp(OperatorType otype, |
| Int32 designator = 0, |
| RelExpr *child0 = NULL, |
| RelExpr *child1 = NULL, |
| CollHeap *outHeap = CmpCommon::statementHeap()) |
| : RelExpr(otype,child0,child1,outHeap) |
| { designator_ = designator; corrNode_ = NULL; } |
| |
| virtual ~WildCardOp(); |
| |
| virtual Int32 getArity() const; |
| |
| inline Int32 getDesignator() { return designator_; } |
| virtual NABoolean isWildcard() const; |
| virtual RelExpr * copyTopNode(RelExpr *derivedNode = NULL, |
| CollHeap* outHeap = 0); |
| |
| inline void setCorrespondingNode(RelExpr *corr) { corrNode_ = corr; } |
| inline RelExpr * getCorrespondingNode() { return corrNode_; } |
| |
| virtual const NAString getText() const; |
| |
| private: |
| |
| Int32 designator_; |
| RelExpr *corrNode_; |
| |
| }; // WildCardOp |
| |
| // ----------------------------------------------------------------------- |
| // A special form of a wildcard op, used to force scans on specific |
| // tables and indexes |
| // ----------------------------------------------------------------------- |
| |
| class ScanForceWildCard : public WildCardOp |
| { |
| // to be used with operator type REL_FORCE_ANY_SCAN |
| |
| public: |
| |
| enum scanOptionEnum |
| { |
| UNDEFINED, |
| INDEX_SYSTEM, |
| MDAM_SYSTEM, |
| MDAM_FORCED, |
| MDAM_OFF, |
| MDAM_COLUMNS_REST_BY_SYSTEM, |
| MDAM_COLUMNS_NO_MORE, |
| MDAM_COLUMNS_ALL, |
| COLUMN_SYSTEM, |
| COLUMN_SPARSE, |
| COLUMN_DENSE, |
| DIRECTION_SYSTEM, |
| DIRECTION_FORWARD, |
| DIRECTION_REVERSED |
| }; |
| |
| // either use any scan on the table with a given exposed name |
| // or only use an index scan on the specified index |
| ScanForceWildCard(CollHeap *outHeap = CmpCommon::statementHeap()); |
| ScanForceWildCard(const NAString& exposedName, |
| CollHeap *outHeap = CmpCommon::statementHeap()); |
| ScanForceWildCard(const NAString& exposedName, |
| const NAString& indexName, |
| CollHeap *outHeap = CmpCommon::statementHeap()); |
| |
| virtual ~ScanForceWildCard(); |
| |
| virtual void initializeScanOptions(); |
| virtual const NAString getText() const; |
| virtual RelExpr * copyTopNode(RelExpr *derivedNode = NULL, |
| CollHeap* outHeap = 0); |
| |
| virtual NABoolean setScanOptions(ScanForceWildCard::scanOptionEnum option); |
| virtual NABoolean setIndexName(const NAString& value); |
| virtual NABoolean setColumnOptions(CollIndex numColumns, |
| ScanForceWildCard::scanOptionEnum* columnAlgos, |
| ScanForceWildCard::scanOptionEnum mdamColumnsStatus); |
| virtual NABoolean setColumnOptions(CollIndex numColumns, |
| ScanForceWildCard::scanOptionEnum mdamColumnsStatus); |
| virtual NABoolean mergeScanOptions(const ScanForceWildCard& other); |
| virtual void prepare(); |
| |
| virtual NABoolean doesThisCoflictMasterSwitch() const; |
| inline const NAString& getExposedName() const { return exposedName_; } |
| inline const NAString& getIndexName() const { return indexName_; } |
| inline CollIndex getNumMdamColumns() const { return numMdamColumns_;} |
| inline scanOptionEnum getIndexStatus() const { return indexStatus_;} |
| inline scanOptionEnum getDirection() const { return direction_;} |
| inline scanOptionEnum getMdamStatus() const { return mdamStatus_;} |
| inline scanOptionEnum getMdamColumnsStatus() const |
| { return mdamColumnsStatus_;} |
| scanOptionEnum getEnumAlgorithmForColumn(CollIndex column) const; |
| |
| void setNumberOfBlocksToReadPerAccess(const Lng32& blocks) |
| { |
| DCMPASSERT(blocks > -1); |
| numberOfBlocksToReadPerAccess_ = blocks; |
| } |
| |
| // If this returns -1 it indicates that we are not forcing blocks per access... |
| Lng32 getNumberOfBlocksToReadPerAccess() const |
| { |
| return numberOfBlocksToReadPerAccess_; |
| } |
| |
| // helper function on CQS Tree |
| virtual RelExpr *generateMatchingExpr(CANodeIdSet &, |
| CANodeIdSet &, |
| RelExpr *); |
| private: |
| |
| NAString exposedName_; |
| NAString indexName_; |
| scanOptionEnum indexStatus_; // UNDEFINED or INDEX_SYSTEM |
| scanOptionEnum mdamStatus_; // MDAM_OFF, _FORCED, _SYSTEM, or UNDEFINED |
| scanOptionEnum direction_; // .._FORWARD, _REVERSE, _SYSTEM, or UNDEFINED |
| scanOptionEnum mdamColumnsStatus_; // .._REST_BY_SYSTEM, _NO_MORE, _ALL |
| CollIndex numMdamColumns_; |
| scanOptionEnum* enumAlgorithms_; // array of enumeration algorithms |
| // for each column |
| // To force the FileScan member of the same name |
| Lng32 numberOfBlocksToReadPerAccess_; |
| |
| }; |
| |
| // ----------------------------------------------------------------------- |
| // A special form of a wildcard op, used to force joins and parallel join |
| // plan2 (any plan, plan1 or plan2, number of ESPs used) |
| // ----------------------------------------------------------------------- |
| |
| class JoinForceWildCard : public WildCardOp |
| { |
| // to be used with operator types REL_FORCE_JOIN, REL_FORCE_NESTED_JOIN, |
| // REL_FORCE_MERGE_JOIN, REL_FORCE_HASH_JOIN |
| |
| public: |
| |
| enum forcedPlanEnum { ANY_PLAN, // don't care which plan |
| FORCED_PLAN0, // plan # 0 |
| FORCED_PLAN1, // plan # 1 |
| FORCED_PLAN2, // plan # 2 |
| FORCED_PLAN3, // plan # 3 |
| FORCED_TYPE1, // join matching partitions |
| FORCED_TYPE2, |
| FORCED_INDEXJOIN }; // replicate one child |
| |
| // either use any scan on the table with a given exposed name |
| // or only use an index scan on the specified index |
| JoinForceWildCard(OperatorTypeEnum type, |
| RelExpr *child0, |
| RelExpr *child1, |
| forcedPlanEnum plan = ANY_PLAN, |
| Int32 numOfEsps = 0, |
| CollHeap *outHeap = CmpCommon::statementHeap()); |
| |
| virtual ~JoinForceWildCard(); |
| |
| virtual RelExpr * copyTopNode(RelExpr *derivedNode = NULL, |
| CollHeap* outHeap = 0); |
| |
| inline forcedPlanEnum getPlan() const { return plan_; } |
| inline Int32 getNumOfEsps() const { return numOfEsps_; } |
| |
| virtual const NAString getText() const; |
| |
| // helper function on CQS Tree |
| virtual RelExpr *generateMatchingExpr(CANodeIdSet &, |
| CANodeIdSet &, |
| RelExpr *); |
| |
| private: |
| |
| forcedPlanEnum plan_; // ANY_PLAN means don't force the plan type |
| Int32 numOfEsps_; // 0 means don't force number of ESPs |
| |
| }; |
| |
| // ----------------------------------------------------------------------- |
| // A special form of a wildcard op, used to force specific Exchange |
| // nodes (3 forms are distinguished, ESP exchange, PA node and PAPA node). |
| // ----------------------------------------------------------------------- |
| |
| class ExchangeForceWildCard : public WildCardOp |
| { |
| // to be used with operator type REL_FORCE_EXCHANGE |
| |
| public: |
| |
| enum forcedExchEnum |
| { |
| ANY_EXCH, // don't care which exchange |
| FORCED_PA, // single PA node |
| FORCED_PAPA, // PAPA on top of PA node |
| FORCED_ESP_EXCHANGE // split/send nodes with ESPs |
| }; |
| |
| enum forcedLogPartEnum |
| { |
| ANY_LOGPART, // don't care which form of logical partitioning |
| FORCED_GROUP, // PA partition grouping |
| FORCED_SPLIT, // subpartitioning or partition slicing |
| FORCED_REPART // PA grouped repartitioning |
| }; |
| |
| // either use any scan on the table with a given exposed name |
| // or only use an index scan on the specified index |
| ExchangeForceWildCard(RelExpr *child0, |
| forcedExchEnum which = ANY_EXCH, |
| forcedLogPartEnum whatLogPart = ANY_LOGPART, |
| Lng32 numBottomEsps = -1, |
| CollHeap *outHeap = CmpCommon::statementHeap()); |
| |
| virtual ~ExchangeForceWildCard(); |
| |
| virtual RelExpr * copyTopNode(RelExpr *derivedNode = NULL, |
| CollHeap* outHeap = 0); |
| |
| inline forcedExchEnum getWhich() const { return which_; } |
| inline forcedLogPartEnum getWhichLogPart() const { return whatLogPart_;} |
| inline Lng32 getHowMany() const { return howMany_; } |
| |
| virtual const NAString getText() const; |
| |
| // helper function on CQS Tree |
| virtual RelExpr *generateMatchingExpr(CANodeIdSet &, |
| CANodeIdSet &, |
| RelExpr *); |
| |
| private: |
| |
| forcedExchEnum which_; // which of the flavors of Exchange we want |
| |
| forcedLogPartEnum whatLogPart_; // which flavor of logical partitioning |
| |
| Lng32 howMany_; // how many exchanges on the bottom |
| |
| }; // ExchangeForceWildCard |
| |
| // ----------------------------------------------------------------------- |
| // A special form of a wildcard op, used to force the use of UDFs via CQS. |
| // ----------------------------------------------------------------------- |
| |
| class UDFForceWildCard : public WildCardOp |
| { |
| // to be used with operator type REL_FORCE_ANY_SCLAR_UDF. |
| public: |
| |
| // Constructor used when parsing ISOLATED_SCALAR_UDF in controlDB.cpp. |
| // op used is REL_FORCE_ANY_SCALAR_UDF. |
| UDFForceWildCard(OperatorTypeEnum op, |
| CollHeap *outHeap = CmpCommon::statementHeap()); |
| // Instantiated when parsing 'SCALAR_UDF' or 'UDF_ACTION' followed by name. |
| // Uses 'FORCE_ANY_SCALAR_UDF' as operator. |
| UDFForceWildCard(const NAString& functionName, |
| const NAString& actionName, |
| CollHeap *outHeap = CmpCommon::statementHeap()); |
| |
| virtual ~UDFForceWildCard(); |
| |
| virtual const NAString getText() const; |
| virtual RelExpr * copyTopNode(RelExpr *derivedNode = NULL, |
| CollHeap* outHeap = 0); |
| |
| virtual NABoolean mergeUDFOptions(const UDFForceWildCard& other); |
| |
| inline const NAString& getFunctionName() const { return functionName_; } |
| inline const NAString& getActionName() const { return actionName_; } |
| |
| // helper function on CQS Tree - this is never called. Not implemented |
| //virtual RelExpr *generateMatchingExpr(CANodeIdSet &, |
| // CANodeIdSet &, |
| // RelExpr *); |
| private: |
| |
| NAString functionName_; |
| NAString actionName_; |
| }; // UDFForceWildCard |
| |
| |
| class RequiredResources : public NABasicObject { |
| public: |
| RequiredResources() : memoryResources_(0), |
| cpuResources_(0), |
| dataAccessCost_(0), |
| maxOperMemReq_(0), |
| maxOperCPUReq_(0), |
| maxOperDataAccessCost_(0), |
| maxMaxCardinality_(0){}; |
| void accumulate(CostScalar memRsrcs, CostScalar cpuRsrcs, CostScalar dataAccessCost, CostScalar maxCard = csZero); |
| CostScalar getMemoryResources(){ return memoryResources_; }; |
| CostScalar getCpuResources(){ return cpuResources_; }; |
| CostScalar getDataAccessCost() { return dataAccessCost_;} |
| CostScalar getMaxOperMemoryResources(){ return maxOperMemReq_; }; |
| CostScalar getMaxOperCpuReq(){ return maxOperCPUReq_; }; |
| CostScalar getMaxOperDataAccessCost() { return maxOperDataAccessCost_;} |
| CostScalar getMaxMaxCardinality() { return maxMaxCardinality_;} |
| |
| void setMemoryResources(CostScalar memRes) { memoryResources_ = memRes; }; |
| void setCpuResources(CostScalar cpuRes) { cpuResources_ = cpuRes; }; |
| void setDataAccessCost(CostScalar dataAccessCost) { dataAccessCost_ = dataAccessCost; }; |
| |
| private: |
| CostScalar memoryResources_; |
| CostScalar cpuResources_; |
| CostScalar dataAccessCost_; |
| CostScalar maxOperMemReq_; |
| CostScalar maxOperCPUReq_; |
| CostScalar maxOperDataAccessCost_; |
| CostScalar maxMaxCardinality_; |
| }; // RequiredResources |
| |
| // ********************************************************************* |
| // The following five enumerated types are specific to plan generation. |
| // They are housed in this file so that many derived classes of |
| // RelExpr can use them. Another alternative is to create a separate |
| // ".h" file for them. |
| // ********************************************************************* |
| |
| // --------------------------------------------------------------------- |
| // Location where a plan or a plan fragment should be executed. |
| // |
| // EXECUTE_IN_MASTER_AND_ESP |
| // Can execute in the master and also can execute in an ESP |
| // EXECUTE_IN_MASTER_OR_ESP |
| // Used for requirements only: require EXECUTE_IN_MASTER_AND_ESP |
| // or EXECUTE_IN_MASTER or EXECUTE_IN_ESP |
| // EXECUTE_IN_MASTER |
| // Execute ONLY in the root exector server process that is at |
| // thr root of the tree of processes. |
| // EXECUTE_IN_ESP |
| // Execute in an executor server process (ESP) only |
| // EXECUTE_IN_DP2 |
| // Execute in a disk server process. |
| // --------------------------------------------------------------------- |
| enum PlanExecutionEnum |
| { |
| EXECUTE_IN_MASTER_AND_ESP, |
| EXECUTE_IN_MASTER_OR_ESP, |
| EXECUTE_IN_MASTER, |
| EXECUTE_IN_ESP, |
| EXECUTE_IN_DP2 |
| }; |
| |
| // --------------------------------------------------------------------- |
| // Source for the data. |
| // 1) A persistent table. |
| // 2) An SQL temporary table. |
| // 3) A table that is materialized transiently at the optimizer's behest. |
| // 4) A virtual table, that is, a table-values stored procedure. |
| // 5) A tuple provided by the user. |
| // 6) An ESP where the different data streams are dependent on each |
| // other in the sense that if one were to read only from some of |
| // them and not from others one could run into a deadlock |
| // (this is true for repartitioned data) |
| // 7) An ESP where the individual data streams can be read independently |
| // from each other without causing a deadlock |
| // --------------------------------------------------------------------- |
| enum DataSourceEnum |
| { |
| SOURCE_PERSISTENT_TABLE, |
| SOURCE_TEMPORARY_TABLE, |
| SOURCE_TRANSIENT_TABLE, |
| SOURCE_VIRTUAL_TABLE, |
| SOURCE_TUPLE, |
| SOURCE_ESP_DEPENDENT, |
| SOURCE_ESP_INDEPENDENT |
| }; |
| |
| // --------------------------------------------------------------------- |
| // The next enum is used for both synthesized and required sort |
| // order types. Only the first four are valid as a synthesized |
| // sort order type. The meaning of each literal is slightly |
| // different depending on whether it is being used as a requirement |
| // or a synthesized value. |
| // --------------------------------------------------------------------- |
| // Synthesized Sort Order Type (SOT) |
| // |
| // NO_SOT |
| // The spp contains no sort order, or we are in DP2 and the |
| // sort order type is irrelevant. |
| // ESP_NO_SORT_SOT |
| // The sort order in the spp was generated naturally via a disk |
| // process access path. If necessary, a merge of sorted streams |
| // or synchronous access will be done to maintain the order. |
| // ESP_VIA_SORT_SOT |
| // The sort order in the spp was generated by a sort operator. |
| // If necessary, a merge of sorted streams will be done to |
| // maintain the order. |
| // DP2_SOT |
| // The sort order in the spp is only valid in DP2. Synchronous |
| // access or a merge of sorted streams will not be done. The |
| // sort order is only usable by another operator if it is also |
| // in DP2 and the physical partitioning function of it's access |
| // path matches exactly the physical partitioning function in |
| // this operator's spp. |
| // --------------------------------------------------------------------- |
| // --------------------------------------------------------------------- |
| // Sort Order Type (SOT) Requirement |
| // |
| // NO_SOT |
| // There is no required sort order or arrangement in the rpp, or we |
| // are in DP2 and the sort order type is irrelevant. |
| // ESP_NO_SORT_SOT |
| // A complete executor process order is required, and the child is |
| // is not allowed to sort to satisfy the requirement. |
| // ESP_VIA_SORT_SOT |
| // A complete executor process order is required, and the child must |
| // utilize sort to satisfy the requirement. |
| // DP2_SOT |
| // The required sort order or arrangement must only be valid in |
| // DP2. A complete executor process order is not necessary and does |
| // NOT satisfy the requirement. This means a merge of sorted |
| // streams or synchronous access cannot be done. |
| // ESP_SOT |
| // A complete executor process order is required. This can be |
| // achieved naturally or via a sort. |
| // DP2_OR_ESP_NO_SORT_SOT |
| // A synthesized sort order type of ESP_NO_SORT or DP2 satisfies |
| // this sort order type requirement. |
| // INCOMPATIBLE_SOT |
| // Used to signify that two required sort order types are not |
| // compatible with each other. |
| // --------------------------------------------------------------------- |
| enum SortOrderTypeEnum |
| { |
| NO_SOT, |
| ESP_NO_SORT_SOT, |
| ESP_VIA_SORT_SOT, |
| DP2_SOT, |
| ESP_SOT, |
| DP2_OR_ESP_NO_SORT_SOT, |
| INCOMPATIBLE_SOT |
| }; |
| |
| // ----------------------------------------------------------------------- |
| // Inlines that couldn't be defined till now due to dependencies |
| // ----------------------------------------------------------------------- |
| inline RelExpr * ExprGroupId::getPtr() const |
| { |
| // part of fix to genesis case: 10-981030-4975 |
| if (node_) node_->checkInvalidObject(this); |
| // else plan is not valid |
| return node_; |
| } |
| |
| inline RelExpr * ExprGroupId::operator ->() const { return getPtr(); } |
| inline ExprGroupId::operator RelExpr *() const { return getPtr(); } |
| |
| #endif /* RELEXPR_H */ |