blob: cd9b42be8f6fead53aba384b9916308c1bd481ad [file] [log] [blame]
/**********************************************************************
// @@@ 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