| /********************************************************************** |
| // @@@ 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 _MDAMKEY_H |
| #define _MDAMKEY_H |
| /* -*-C++-*- |
| ***************************************************************************** |
| * |
| * File: mdamkey.h |
| * Description: Handling of disjuncts and costing for mdam |
| * Code location: mdam.C |
| * |
| * Created: //96 |
| * Language: C++ |
| * |
| * |
| * |
| * |
| ***************************************************************************** |
| */ |
| |
| // ----------------------------------------------------------------------- |
| |
| #include "mdam.h" |
| #include "disjuncts.h" |
| #include "keycolumns.h" |
| #include "NABasicObject.h" |
| #include "IndexDesc.h" |
| |
| // ----------------------------------------------------------------------- |
| // Class ScanKey |
| // A ScanKey is an abstract class that represents a set of |
| // of subsets to be read from an index file. |
| // A ScanKey is logically an array of "key disjuncts", |
| // each key disjunct containing a set of key predicates. |
| // These key predicates may be accessed through a data structure |
| // called OrderColumnList (see method getKeyPredicatesByColumn). |
| // |
| // The predicates of the key disjuncts, when applied to the index |
| // table may give raise to several subsets. It is the responsability |
| // of the derived class to enforce the semantics of the key disjunct |
| // generation (for example, the key disjunct generation for |
| // the SearchKey guarantees that the key disjunct represents a single |
| // subset) |
| // |
| // Classes SearchKey (a single subset) and MdamKey (multiple subsets) |
| // inherit from ScanKey. |
| // ----------------------------------------------------------------------- |
| |
| // class Key contains common procedures and declarations |
| // for MdamKey and SearchKey |
| class ScanKey : public NABasicObject |
| { |
| public: |
| // ----------------------------------------------------------------------- |
| // the nonKeyColumnSet is used by the SearchKey when it is |
| // computing the key for an index desc and it is trying to decide |
| // whether to replicate the keys in the executor predicates. |
| // It should be an empty set for the case when search key is used |
| // to compute the partitioning key. |
| // ----------------------------------------------------------------------- |
| |
| ScanKey( |
| const ValueIdList& keyColumnIdList |
| ,const ValueIdSet& operatorInputs |
| ,const Disjuncts& associatedDisjuncts |
| ,const ValueIdSet& nonKeyColumnSet |
| ,const IndexDesc * indexDesc |
| ,const IndexDesc * UDindexDesc = NULL |
| ) : |
| keyColumnIdList_(keyColumnIdList) |
| ,associatedDisjuncts_(associatedDisjuncts) |
| ,operatorInputs_(operatorInputs) |
| ,nonKeyColumnSet_(nonKeyColumnSet) |
| ,iDesc_(indexDesc) |
| ,udiDesc_(UDindexDesc) |
| {} |
| |
| |
| // ----------------------------------------------------------------------- |
| // Accessors: |
| // ----------------------------------------------------------------------- |
| |
| const IndexDesc * getIndexDesc() const |
| { return iDesc_; } |
| |
| const IndexDesc * getUDIndexDesc() const |
| { return udiDesc_; } |
| |
| const ValueIdSet& getExecutorPredicates() const |
| { return executorPredicates_; } |
| |
| void setExecutorPredicates(const ValueIdSet& executorPredicates) |
| { executorPredicates_ = executorPredicates; } |
| |
| // get the number of key disjuncts for this key (the key must |
| // have at least one disjunct) |
| virtual CollIndex getKeyDisjunctEntries() const = 0; |
| |
| // Obtain the key predicates (hashed by column order) |
| // in the key disjunct: |
| virtual void getKeyPredicatesByColumn( |
| ColumnOrderList& keyPredsByCol, /*out*/ |
| CollIndex disjunctNumber = 0) const = 0; |
| |
| // Obtain the set of key predicates in the disjunct: |
| virtual void getKeyPredicates(ValueIdSet &keyPredicates, /* out */ |
| NABoolean * allKeyPredicates = NULL,/*out*/ |
| CollIndex disjunctNumber = 0 /*in*/) const; |
| |
| |
| const ValueIdSet& getNonKeyColumnSet() const |
| { return nonKeyColumnSet_; } |
| |
| const ValueIdSet getAllColumnsReferenced() const; |
| |
| // ----------------------------------------------------------------------- |
| // isAKeyPredicate() |
| // |
| // A predicate is eligible to be used for searching an index when it |
| // satisfies the following requirements: |
| // 1) It should be a unary, binary, or ternary comparison predicate. |
| // 2) One of the key columns must be a child of the root of the |
| // predicate tree. |
| // 3) If the predicate performs binary or ternary comparison, the operand |
| // that is compared with the key column must be a value |
| // belonging to the external inputs. |
| // 4) If the predicate performs a ternary comparison, in addition to |
| // 3), the extra inclusion indicator must also be an external input. |
| // |
| // Parameters: |
| // |
| // const ValueId & predId |
| // IN : A read-only reference to the ValueId of the predicate |
| // to be analyzed. |
| // |
| // |
| // ValueId & referencedInput |
| // OUT: The ValueId of the expression that belongs to externalInputs |
| // and is compared with the keyColumn in the predicate. |
| // It may be set to the NULL_VALUE_ID for an IS NULL predicate. |
| // |
| // ValueId & intervalExclusionExpr |
| // OUT: The value id of a boolean expression that indicates that |
| // the decision whether the predicate is an exclusive or inclusive |
| // key predicate is made at run time. It is set to NULL_VALUE_ID |
| // if this decision can be made at compile time. |
| // |
| // Return value |
| // OUT: TRUE If the given predicate can be used as a key on |
| // a key column |
| // FALSE Otherwise |
| // |
| // ----------------------------------------------------------------------- |
| |
| NABoolean isAKeyPredicate(const ValueId & predId, |
| ValueId & referencedInput, |
| ValueId & intervalExclusionExpr) const; |
| |
| // same semantics as above, but the caller does not need the |
| // referenced input nor the interval exclusion ptr |
| NABoolean isAKeyPredicate(const ValueId& predId) const; |
| |
| // same semantics as above for detecting key predicates |
| // but we need to make sure that the predicate is a key pred |
| // for the column |
| // for instance, for key columns A,B and the pred: |
| // VegRef{A,2} = VegRef{C} |
| // the pred is a key pred. However, it is not a key pred for A. |
| NABoolean |
| isAKeyPredicateForColumn( |
| const ValueId & predId |
| ,ValueId & referencedInput |
| ,ValueId & intervalExclusionExpr |
| ,const ValueId& keyColumn |
| ) const; |
| |
| static NABoolean |
| isAKeyPredicateForColumn( |
| const ValueId & predId |
| ,ValueId & referencedInput |
| ,ValueId & intervalExclusionExpr |
| ,const ValueId& keyColum |
| ,const ValueIdSet& inputValues); |
| |
| NABoolean |
| isAKeyPredicateForColumn( |
| const ValueId& predId |
| ,const ValueId& keyColumn) const; |
| |
| static void createComputedColumnPredicates( |
| ValueIdSet &predicates, /* in/out */ |
| const ValueIdSet &keyColumns, /* in */ |
| const ValueIdSet &operatorInputs, /* in */ |
| ValueIdSet &generatedPredicates /* out */); |
| |
| // ----------------------------------------------------------------------- |
| // Put those key predicates in keyPredicates that need to be |
| // replicated in replicatedKeyPredicates: |
| // ----------------------------------------------------------------------- |
| void |
| replicateNonKeyVEGPredicates( |
| const ValueIdSet& keyPredicates, |
| ValueIdSet& replicatedKeyPredicates /* out */ |
| ) const; |
| |
| // ----------------------------------------------------------------------- |
| // Mutators: |
| // ----------------------------------------------------------------------- |
| |
| // Generate the data structures needed by the generator and |
| // rewrite VEG preds and predicates: |
| virtual void preCodeGen(ValueIdSet& executorPredicates, |
| const ValueIdSet& selectionPredicates, |
| const ValueIdSet & availableValues, |
| const ValueIdSet & inputValues, |
| VEGRewritePairs * vegPairsPtr, |
| NABoolean replicateExpression = FALSE, |
| NABoolean partKeyPredsAdded = FALSE) = 0; |
| |
| |
| |
| const ValueIdList& getKeyColumns() const |
| { return keyColumnIdList_; } |
| |
| const Disjuncts& getDisjuncts() const |
| { return associatedDisjuncts_ ; } |
| |
| |
| const ValueIdSet& getOperatorInputs() const |
| { return operatorInputs_; } |
| |
| protected: |
| |
| // ----------------------------------------------------------------------- |
| // Accessors: |
| // ----------------------------------------------------------------------- |
| |
| // get the selection predicates in MDNF for this key: |
| |
| // construct a key column order from the given set: |
| void getKeyColumnOrderList(ColumnOrderList& keyPredsByCol, /* out*/ |
| const ValueIdSet& predSet) const; |
| |
| |
| static NABoolean expressionContainsColumn( |
| const ItemExpr& iePtr |
| ,const ValueId& keyColumn |
| ); |
| |
| // This is a quick fix: |
| void splitRangeSpecRef(ColumnOrderList& keyPredsByCol, |
| const ValueId& predId, |
| const ValueIdList& columns, |
| NABoolean firstElemInRangeSpec, |
| const ValueId& predIdRange) const; |
| |
| const ValueIdSet& getOperatorInputs() { return operatorInputs_;} |
| |
| |
| // ----------------------------------------------------------------------- |
| // Mutators: |
| // ----------------------------------------------------------------------- |
| |
| |
| private: |
| const IndexDesc *iDesc_; |
| const IndexDesc *udiDesc_; |
| const ValueIdList keyColumnIdList_; |
| const ValueIdSet nonKeyColumnSet_; |
| const ValueIdSet operatorInputs_; |
| const Disjuncts& associatedDisjuncts_; |
| ValueIdSet executorPredicates_; |
| |
| }; // class ScanKey |
| |
| //------------------------------------------------------------- |
| // An MdamKey contains different states at different |
| // times in the optimizer. |
| // |
| // Before optimization it contains data to generate |
| // state for a mdam key with all columns sparse and |
| // all stop columns set to the maximum order. |
| // |
| // After optimization, if the MdamKey survives (i.e. |
| // if a SingleSubset key was not chosen) the |
| // MdamKey may contain a mix. of sparse/dense |
| // columns and not all of the stop columns will be |
| // set to the max (this is chosen by costing) |
| // |
| // After pre-code generation, a data structure |
| // called OrderListPtrArray is created. It contains |
| // An array of key predicates ordered by key column. |
| // There is one entry of this array for each disjunct |
| // present if the MdamKey was generated from the associated |
| // disjuncts. There will be a single array entry, corresponding |
| // to the common predicates of the associated disjuncts, if the |
| // MdamKey was generated from the common predicates. |
| // Also in this phase VEG predicates and references are |
| // rewritten and executor predicates are generated. |
| // |
| // After code generation an Mdam Network is generated from |
| // the OrderListPtrArray. |
| // |
| //-------------------------------------------------------------- |
| |
| |
| class MdamKey : public ScanKey |
| { |
| public: |
| MdamKey( |
| const ValueIdList& keyColumnIdList |
| ,const ValueIdSet& operatorInputs |
| ,const Disjuncts& associatedDisjuncts |
| ,const ValueIdSet& nonKeyColumnSet |
| ,const IndexDesc * indexDesc |
| ); |
| ~MdamKey(); |
| |
| |
| |
| // Return the number of disjuncts that were created |
| // out of the selection predicates: |
| virtual CollIndex getKeyDisjunctEntries() const; |
| |
| // returns the key predicates in those disjuncts |
| virtual void getKeyPredicatesByColumn( |
| ColumnOrderList& keyPredsByCol, /*out*/ |
| CollIndex disjunctNumber = 0) const; |
| |
| |
| void setNoExePred(NABoolean v = TRUE){ noExePred_= v; } |
| |
| NABoolean getNoExePred(){ return noExePred_;} |
| |
| |
| CollIndex getStopColumn(CollIndex disjunctNumber) const; |
| |
| // TRUE means that column is sparse, else it is dense |
| NABoolean getSparseFlag(CollIndex columnOrder) const; |
| |
| NABoolean isColumnSparse(CollIndex columnOrder) const |
| { return getSparseFlag(columnOrder); } |
| NABoolean isColumnDense(CollIndex columnOrder) const |
| { return NOT isColumnSparse(columnOrder); } |
| |
| |
| void setAllStopColumnsToMax(); // all stop columns are the highest |
| void setAllColumnsToSparse(); // all columns are sparse |
| |
| void setStopColumn(CollIndex disjunctNumber, |
| CollIndex columnOrder); |
| void setSparseFlag(CollIndex columnOrder, NABoolean isSparse); |
| |
| void setColumnToDense(CollIndex columnOrder) |
| { setSparseFlag(columnOrder,FALSE); } |
| |
| void setColumnToSparse(CollIndex columnOrder) |
| { setSparseFlag(columnOrder,TRUE); } |
| |
| // This function copies information from 'other' MDAM key |
| // to the current MDAM key: stop columns, starse keys and |
| // noExePred. It is used to share this information when |
| // saving and reusing BasicCost for MDAM key. |
| void reuseMdamKeyInfo(MdamKey * other); |
| |
| // --------------------------------- |
| // ---- Pre-code generation interface: |
| // --------------------------------- |
| // Pre-code gen materializes the columnorderlist |
| // and rewrites the predicates. |
| // It also computes the executor predicates: |
| void preCodeGen(ValueIdSet& executorPredicates, |
| const ValueIdSet& selectionPredicates, |
| const ValueIdSet & availableValues, |
| const ValueIdSet & inputValues, |
| VEGRewritePairs * vegPairsPtr, |
| NABoolean replicateExpression = FALSE, |
| NABoolean partKeyPredsAdded = FALSE); |
| |
| |
| // --------------------------------- |
| // ---- Generator interface: |
| // --------------------------------- |
| const ColumnOrderListPtrArray& getColumnOrderListPtrArray() const; |
| |
| |
| // ----------------------------------------------------------------------- |
| // Utility functions: |
| // ----------------------------------------------------------------------- |
| void display() { print(); } |
| void print( FILE* ofd = stdout, |
| const char* indent = DEFAULT_INDENT, |
| const char* title = "") const; |
| |
| |
| private: |
| |
| // extract key predicates from predicates and append them to |
| // keyPredicates (side-effects keyPredicates): |
| void appendKeyPredicates(ValueIdSet& keyPredicates, |
| const ValueIdSet& predicates, |
| const ValueIdSet& inputValues) const; |
| |
| NABoolean isAPartKeyPredicateForMdam(const ValueId& predId, |
| const ValueIdSet& inputValues) const; |
| |
| |
| |
| // ----------------------------------------------------------------------- |
| // This members are created by the costing. They contain the data |
| // needed to generate the ColumnOrderListArray in preCodeGen. |
| // Also, ScanKey::associatedDisjuncts is used in this generation. |
| // ----------------------------------------------------------------------- |
| NABoolean *sparseFlagArray_; |
| CollIndex *stopColumnArray_; |
| //Boolean that tells us if executor predicates can be empty or not. |
| //It can be empty if all predicates are applied at the dp2. |
| NABoolean noExePred_; |
| |
| // ----------------------------------------------------------------------- |
| // The ColumnOrderListArray contains the data from which the generator |
| // builds the mdam network. |
| // This array is NULL in the optimizer and it is generated by preCodeGen |
| // ----------------------------------------------------------------------- |
| ColumnOrderListPtrArray *columnOrderListPtrArrayPtr_; |
| }; // class MdamKey |
| |
| |
| |
| |
| |
| #endif |
| // eof |