blob: b343201e58394719e3049f6e7efa0d314eab7a44 [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 PHYPROP_HDR
#define PHYPROP_HDR
/* -*-C++-*-
**************************************************************************
*
* File: PhyProp.h
* Description: Physical Properties and Cost
* Created: 4/10/94
* Language: C++
*
*
*
*
**************************************************************************
*/
// -----------------------------------------------------------------------
#include "SchemaDB.h"
#include "PartFunc.h"
#include "RelEnforcer.h"
#include "PartReq.h"
#include "RelEnforcer.h"
#include "opt.h"
#include "LookupTable.h"
// -----------------------------------------------------------------------
// The following classes are defined in this file.
// -----------------------------------------------------------------------
class PhysicalProperty;
class ReqdPhysicalProperty;
class InputPhysicalProperty;
class CurrentFragmentBigMemoryProperty;
// -----------------------------------------------------------------------
// forward references
// -----------------------------------------------------------------------
class GroupAttributes;
class CorrName;
class DP2CostDataThatDependsOnSPP;
class PushDownProperty;
class PushDownRequirement;
namespace tmudr {
class UDRPlanInfo;
}
// -----------------------------------------------------------------------
// global defines
// -----------------------------------------------------------------------
// see class ReqdPhysicalProperty
#define DEFAULT_LOCATION EXECUTE_IN_ESP
#define DEFAULT_SINGLETON 1
//#define DEFAULT_DATA_SOURCE SOURCE_PERSISTENT_TABLE /* not used */
// -----------------------------------------------------------------------
// Physical Properties
// ===================
//
// Physical properties are those that can be derived from physical
// expressions. Thus, these are properties that have a dependency
// on the physical strategy/algorithm chosen to implement the
// query.
// -----------------------------------------------------------------------
class PhysicalProperty : public NABasicObject
{
public:
// ---------------------------------------------------------------------
// Constructors and destructor
// ---------------------------------------------------------------------
PhysicalProperty()
: sortOrderType_(NO_SOT),
dp2SortOrderPartFunc_(NULL),
actualPartFunc_(NULL),
location_(DEFAULT_LOCATION),
sourceOfData_(SOURCE_PERSISTENT_TABLE),
indexDesc_(NULL),
partSearchKey_(NULL),
currentCountOfCPUs_(1),
dp2CostInfo_(NULL),
udrPlanInfo_(NULL),
pushDownProperty_(NULL),
memoryNeedsinCurrentFragment_(NULL),
explodedOcbJoin_(FALSE),
accessOnePartition_(FALSE),
insertedDataIsSorted_(FALSE)
{}
PhysicalProperty(const ValueIdList &sortKey,
SortOrderTypeEnum sortOrderType,
PartitioningFunction* dp2SortOrderPartFunc = NULL,
PartitioningFunction * actualPartFunc = NULL,
const PlanExecutionEnum plenum = DEFAULT_LOCATION,
const DataSourceEnum dsenum = SOURCE_PERSISTENT_TABLE,
const IndexDesc * indexDesc = NULL,
const SearchKey * partSearchKey = NULL,
const PushDownProperty* pdp = NULL,
NABoolean explOcbJoin = FALSE
)
: sortKey_(sortKey),
sortOrderType_(sortOrderType),
dp2SortOrderPartFunc_(dp2SortOrderPartFunc),
actualPartFunc_(actualPartFunc),
location_(plenum),
sourceOfData_(dsenum),
indexDesc_(indexDesc),
partSearchKey_(partSearchKey),
currentCountOfCPUs_(1),
dp2CostInfo_(NULL),
udrPlanInfo_(NULL),
pushDownProperty_(pdp),
memoryNeedsinCurrentFragment_(NULL),
explodedOcbJoin_(explOcbJoin),
accessOnePartition_(FALSE),
insertedDataIsSorted_(FALSE)
{}
PhysicalProperty(PartitioningFunction * actualPartFunc,
const PlanExecutionEnum plenum = DEFAULT_LOCATION,
const DataSourceEnum dsenum = SOURCE_PERSISTENT_TABLE
)
: sortOrderType_(NO_SOT),
dp2SortOrderPartFunc_(NULL),
actualPartFunc_(actualPartFunc),
location_(plenum),
sourceOfData_(dsenum),
indexDesc_(NULL),
partSearchKey_(NULL),
currentCountOfCPUs_(1),
dp2CostInfo_(NULL),
udrPlanInfo_(NULL),
pushDownProperty_(NULL),
memoryNeedsinCurrentFragment_(NULL),
explodedOcbJoin_(FALSE),
accessOnePartition_(FALSE),
insertedDataIsSorted_(FALSE)
{}
PhysicalProperty(const PhysicalProperty &other)
: sortKey_(other.sortKey_),
sortOrderType_(other.sortOrderType_),
dp2SortOrderPartFunc_(other.dp2SortOrderPartFunc_),
actualPartFunc_(other.actualPartFunc_),
location_(other.location_),
sourceOfData_(other.sourceOfData_),
indexDesc_(other.indexDesc_),
partSearchKey_(other.partSearchKey_),
currentCountOfCPUs_(other.currentCountOfCPUs_),
dp2CostInfo_(other.dp2CostInfo_),
udrPlanInfo_(other.udrPlanInfo_),
pushDownProperty_(other.pushDownProperty_),
memoryNeedsinCurrentFragment_(other.memoryNeedsinCurrentFragment_),
explodedOcbJoin_(other.explodedOcbJoin_),
accessOnePartition_(other.accessOnePartition_),
insertedDataIsSorted_(other.insertedDataIsSorted_)
{}
PhysicalProperty(const PhysicalProperty &other,
const ValueIdList &sortKey,
SortOrderTypeEnum sortOrderType,
PartitioningFunction* dp2SortOrderPartFunc
)
: sortKey_(sortKey),
sortOrderType_(sortOrderType),
dp2SortOrderPartFunc_(dp2SortOrderPartFunc),
actualPartFunc_(other.actualPartFunc_),
location_(other.location_),
sourceOfData_(other.sourceOfData_),
indexDesc_(other.indexDesc_),
partSearchKey_(other.partSearchKey_),
currentCountOfCPUs_(other.currentCountOfCPUs_),
dp2CostInfo_(other.dp2CostInfo_),
udrPlanInfo_(other.udrPlanInfo_),
pushDownProperty_(other.pushDownProperty_),
memoryNeedsinCurrentFragment_(other.memoryNeedsinCurrentFragment_),
explodedOcbJoin_(other.explodedOcbJoin_),
accessOnePartition_(other.accessOnePartition_),
insertedDataIsSorted_(other.insertedDataIsSorted_)
{}
PhysicalProperty(const PhysicalProperty &other,
const ValueIdList &sortKey,
SortOrderTypeEnum sortOrderType,
PartitioningFunction* dp2SortOrderPartFunc,
DataSourceEnum sourceOfData
)
: sortKey_(sortKey),
sortOrderType_(sortOrderType),
dp2SortOrderPartFunc_(dp2SortOrderPartFunc),
actualPartFunc_(other.actualPartFunc_),
location_(other.location_),
sourceOfData_(sourceOfData),
indexDesc_(other.indexDesc_),
partSearchKey_(other.partSearchKey_),
currentCountOfCPUs_(other.currentCountOfCPUs_),
dp2CostInfo_(other.dp2CostInfo_),
udrPlanInfo_(other.udrPlanInfo_),
pushDownProperty_(other.pushDownProperty_),
memoryNeedsinCurrentFragment_(other.memoryNeedsinCurrentFragment_),
explodedOcbJoin_(other.explodedOcbJoin_),
accessOnePartition_(other.accessOnePartition_),
insertedDataIsSorted_(other.insertedDataIsSorted_)
{}
PhysicalProperty(const PhysicalProperty &other,
const ValueIdList &sortKey,
SortOrderTypeEnum sortOrderType,
PartitioningFunction* dp2SortOrderPartFunc,
PartitioningFunction* actualPartFunc
)
: sortKey_(sortKey),
sortOrderType_(sortOrderType),
dp2SortOrderPartFunc_(dp2SortOrderPartFunc),
actualPartFunc_(actualPartFunc),
location_(other.location_),
sourceOfData_(other.sourceOfData_),
indexDesc_(other.indexDesc_),
partSearchKey_(other.partSearchKey_),
currentCountOfCPUs_(other.currentCountOfCPUs_),
dp2CostInfo_(other.dp2CostInfo_),
udrPlanInfo_(other.udrPlanInfo_),
pushDownProperty_(other.pushDownProperty_),
memoryNeedsinCurrentFragment_(other.memoryNeedsinCurrentFragment_),
explodedOcbJoin_(other.explodedOcbJoin_),
accessOnePartition_(other.accessOnePartition_),
insertedDataIsSorted_(other.insertedDataIsSorted_)
{}
virtual ~PhysicalProperty();
// ---------------------------------------------------------------------
// Accessor/Mutator functions
// ---------------------------------------------------------------------
const NABoolean getexplodedOcbJoinProperty() const
{ return explodedOcbJoin_; }
// For determining if the partitioning key is a prefix of the
// sort key (i.e. the clustering key)
NABoolean isPartKeyPrefixOfSortKey() const;
// --- For sort key
inline NABoolean isSorted() const { return (sortKey_.entries() > 0); }
inline const ValueIdList & getSortKey() const { return sortKey_; }
// accessors
inline SortOrderTypeEnum getSortOrderType() const
{ return sortOrderType_; }
inline PartitioningFunction* getDp2SortOrderPartFunc() const
{ return dp2SortOrderPartFunc_; }
// mutators
void setSortOrderType(SortOrderTypeEnum sortOrderType)
{
// Check that the synthesized sort order type is within the
// allowable range for a synthesized sort order type.
DCMPASSERT((sortOrderType >= NO_SOT) AND
(sortOrderType <= DP2_SOT))
sortOrderType_ = sortOrderType;
}
void setDp2SortOrderPartFunc(
PartitioningFunction* dp2SortOrderPartFunc)
{ dp2SortOrderPartFunc_ = dp2SortOrderPartFunc; }
void setLocation(PlanExecutionEnum location)
{location_ = location;}
// --- For partitioning function
inline NABoolean isPartitioned() const
{ return (actualPartFunc_ AND actualPartFunc_->getCountOfPartitions() > 1); }
inline void scaleNumberOfPartitions(Lng32 npartns)
{
if ( actualPartFunc_ )
actualPartFunc_ = actualPartFunc_->scaleNumberOfPartitions(npartns);
};
inline PartitioningFunction * getPartitioningFunction() const
{ return actualPartFunc_; }
inline Lng32 getCountOfPartitions() const
{
if (actualPartFunc_)
return actualPartFunc_->getCountOfPartitions();
else
return 1;
}
// --- Read-only access to the partitioning key.
inline const ValueIdSet & getPartitioningKey() const
{ return actualPartFunc_->getPartitioningKey(); }
// --- For plan execution
inline NABoolean executeInMasterOrESP() const
{ return (location_ == EXECUTE_IN_MASTER_OR_ESP); }
inline NABoolean executeInMasterOnly() const
{ return (location_ == EXECUTE_IN_MASTER); }
inline NABoolean executeInESPOnly() const
{ return (location_ == EXECUTE_IN_ESP); }
inline NABoolean executeInDP2() const
{ return (location_ == EXECUTE_IN_DP2); }
inline PlanExecutionEnum getPlanExecutionLocation() const
{ return location_; }
// -- For the source of the data
inline DataSourceEnum getDataSourceEnum() const
{ return sourceOfData_; }
inline void setDataSourceEnum(DataSourceEnum s)
{ sourceOfData_ = s; }
// -- Accessor for the table descriptor
inline const IndexDesc * getIndexDesc() const { return indexDesc_; }
inline void setIndexDesc(const IndexDesc * val) { indexDesc_ = val; }
// -- Accessor and Mutator for the partition search key (part. key predicates)
inline const SearchKey * getPartSearchKey() const
{ return partSearchKey_; }
inline void setPartSearchKey(const SearchKey* partSearchKey)
{ partSearchKey_ = partSearchKey; }
// -- Accessor and Mutator for cpuCountInDP2_.
inline Lng32 getCurrentCountOfCPUs() const { return currentCountOfCPUs_; }
inline void setCurrentCountOfCPUs(const Lng32 value)
{ currentCountOfCPUs_ = value; }
// ---------------------------------------------------------------------
// comparison functions (A > B means that A delivers all the
// physical properties that B has plus some more).
// ---------------------------------------------------------------------
inline NABoolean operator > (const PhysicalProperty &other) const
{ return compareProperties(other) == MORE; }
inline NABoolean operator < (const PhysicalProperty &other) const
{ return compareProperties(other) == LESS; }
inline NABoolean operator == (const PhysicalProperty &other) const
{ return compareProperties(other) == SAME; }
// -----------------------------------------------------------------------
// For costing data that gets computed at synthesis time:
// -----------------------------------------------------------------------
const DP2CostDataThatDependsOnSPP * getDP2CostThatDependsOnSPP() const
{ return dp2CostInfo_; }
void setDP2CostThatDependsOnSPP(DP2CostDataThatDependsOnSPP * dp2Cost)
{ dp2CostInfo_ = dp2Cost; }
// for UDRs (only to transfer this info to the code generator)
tmudr::UDRPlanInfo *getUDRPlanInfo() const { return udrPlanInfo_; }
void setUDRPlanInfo(tmudr::UDRPlanInfo *pi) { udrPlanInfo_ = pi; }
// -----------------------------------------------------------------------
// Make sure that all members are covered by the group attributes!
//
// Currently, we only check the sort key. Someday we may check other
// fields, such as the partitioning function.
// -----------------------------------------------------------------------
void enforceCoverageByGroupAttributes (const GroupAttributes * groupAttr) ;
// ---------------------------------------------------------------------
// Utility functions
// ---------------------------------------------------------------------
void print(FILE* ofd = stdout,
const char * prefix = DEFAULT_INDENT,
const char * suffix = "") const;
void setPushDownProperty(const PushDownProperty* pdp)
{ pushDownProperty_ = pdp; };
const PushDownProperty* getPushDownProperty() const
{ return pushDownProperty_; } ;
void setBigMemoryEstimationProperty( CurrentFragmentBigMemoryProperty *c)
{ memoryNeedsinCurrentFragment_ = c;}
const CurrentFragmentBigMemoryProperty * getBigMemoryEstimationProperty()
{ return memoryNeedsinCurrentFragment_; }
void setAccessOnePartition(NABoolean x) { accessOnePartition_ = x; } ;
NABoolean getAccessOnePartition() const { return accessOnePartition_; } ;
void setInsertedDataIsSorted(NABoolean x) { insertedDataIsSorted_ = x; } ;
NABoolean getInsertedDataIsSorted() const { return insertedDataIsSorted_; } ;
private:
// ---------------------------------------------------------------------
// Method for comparing two Physical property vectors.
// ---------------------------------------------------------------------
COMPARE_RESULT compareProperties(const PhysicalProperty & other) const;
// ---------------------------------------------------------------------
// Information about the order of the result rows
// ---------------------------------------------------------------------
ValueIdList sortKey_; // sorted by the specified cols/expressions
// ---------------------------------------------------------------------
// The type of sort order: NO_SOT, ESP_NO_SORT_SOT,
// ESP_VIA_SORT_SOT, DP2_SOT
// ---------------------------------------------------------------------
SortOrderTypeEnum sortOrderType_;
// ---------------------------------------------------------------------
// The physical partitioning function of the access path that generated
// the sort order. NULL if no sort order or if the sort order type is
// not DP2.
// ---------------------------------------------------------------------
PartitioningFunction* dp2SortOrderPartFunc_;
// ---------------------------------------------------------------------
// The partitioning function encapsulates data parallelism.
// When a plan fragment executes within DP2 the degree of operator
// parallelism is equal to the number of partitions, i.e., the degree
// of data parallelism. In contrast, when a plan fragement executes
// in ESP, the number of data streams, i.e., partitions, are expected
// to be equal to the number of operator instances that are expected
// to execute in parallel.
// ---------------------------------------------------------------------
PartitioningFunction * actualPartFunc_;
// ---------------------------------------------------------------------
// Information about where the plan, or plan fragment, should be
// executed.
// ---------------------------------------------------------------------
PlanExecutionEnum location_;
// ---------------------------------------------------------------------
// The source for the data, persistent table, temporary table or esp.
// ---------------------------------------------------------------------
DataSourceEnum sourceOfData_;
// ---------------------------------------------------------------------
// The index which is the source of data. It points
// to a table name only when sourceIsAPersistentTable() is TRUE.
// Otherwise it is NULL.
// This information is preserved until the first Exchange operator
// is reached.
// ---------------------------------------------------------------------
const IndexDesc * indexDesc_;
// ---------------------------------------------------------------------
// The search key to be used to determine partitions for indexDesc_.
// This search key contains artificial predicates, designed to split
// data into different streams when an operator is executed in parallel,
// and any other predicates that may restrict the partititions used.
// All predicates in partSearchKey_ have to be covered by the
// characteristic inputs of the RelExpr that carries this object.
// ---------------------------------------------------------------------
const SearchKey * partSearchKey_;
// ---------------------------------------------------------------------
// No of CPU used if the operator executes in DP2. Meaningless if the
// operator doesn't executes in DP2. This is for informational purpose
// only. Should not be used to determine whether some ReqdPhysProperty
// are satisfied.
// ---------------------------------------------------------------------
// $$$ This member should be moved to class
// $$$ DP2CostDataThatDependsOnSPP!!!!
Lng32 currentCountOfCPUs_;
// -----------------------------------------------------------------------
// The following class should contain all costing data for dp2
// operators that gets computed at synthesis time:
// -----------------------------------------------------------------------
DP2CostDataThatDependsOnSPP * dp2CostInfo_;
tmudr::UDRPlanInfo *udrPlanInfo_;
const PushDownProperty* pushDownProperty_;
CurrentFragmentBigMemoryProperty *memoryNeedsinCurrentFragment_;
NABoolean explodedOcbJoin_;
NABoolean accessOnePartition_;
// set in DP2Insert::synthPhysicalProperty.
// Indicates if the data to be inserted is sorted.
NABoolean insertedDataIsSorted_;
}; // PhysicalProperty
// -----------------------------------------------------------------------
// Performance goals
//
// Optimize for N rows
// Choose a plan that offers the lowest cost for returning the
// first N rows.
//
// Optimize for first row
// Choose a plan that offers that offers the lowest first row cost
//
// Optimize for last row
// Choose a plan that offers that offers the lowest last row cost
//
// Optimize for resource consumption
// Choose a plan that offers that offers the lowest total cost
//
// -----------------------------------------------------------------------
class PerformanceGoal
{
public:
virtual ~PerformanceGoal();
virtual NABoolean isOptimizeForFirstRow() const;
virtual NABoolean isOptimizeForLastRow() const;
virtual NABoolean isOptimizeForResourceConsumption() const;
private:
}; // class PerformanceGoal
// -- Optimize for N rows
class OptimizeForNRows : public PerformanceGoal
{
public:
OptimizeForNRows(Lng32 numberOfRows) : rowCount_(numberOfRows)
{ assert(numberOfRows > 0); }
virtual ~OptimizeForNRows() {}
virtual NABoolean isOptimizeForFirstRow() const;
private:
Lng32 rowCount_;
}; // class OptimizeForNRows
// -- Optimize for first row - not used in SQ
class OptimizeForFirstRow : public OptimizeForNRows
{
public:
OptimizeForFirstRow() : OptimizeForNRows(1) { }
virtual ~OptimizeForFirstRow() {}
}; // class OptimizeForFirstRow
// -- Optimize for last row
class OptimizeForLastRow : public OptimizeForNRows
{
public:
OptimizeForLastRow() : OptimizeForNRows(INT_MAX) { }
virtual ~OptimizeForLastRow() {}
virtual NABoolean isOptimizeForLastRow() const;
virtual NABoolean isOptimizeForFirstRow() const;
}; // class OptimizeForLastRow
// -- Optimize for resource consumption - not used in SQ
class OptimizeForResourceConsumption : public PerformanceGoal
{
public:
virtual ~OptimizeForResourceConsumption() {}
virtual NABoolean isOptimizeForResourceConsumption() const;
}; // class OptimizeForResourceConsumption
// -----------------------------------------------------------------------
// Required physical properties
// -----------------------------------------------------------------------
class ReqdPhysicalProperty : public NABasicObject
{
public:
// ---------------------------------------------------------------------
// Constructor, copy constructor, destructor, and assignment operator
// ---------------------------------------------------------------------
ReqdPhysicalProperty(
const ValueIdSet* const arrangedBy = NULL,
const ValueIdList* const orderedBy = NULL,
SortOrderTypeEnum sortOrderTypeReq = NO_SOT,
PartitioningRequirement* dp2SortOrderPartReq = NULL,
const NABoolean logicalOrderOrArrangement = FALSE,
PartitioningRequirement* partReq = NULL,
LogicalPartitioningRequirement* logicalPartReq = NULL,
const PlanExecutionEnum location = DEFAULT_LOCATION,
const Lng32 availableCPUs = DEFAULT_SINGLETON,
const Lng32 pipelinesPerCPU = DEFAULT_SINGLETON,
const CostWeight* const costWeight = CURRSTMT_OPTDEFAULTS->getDefaultCostWeight(),
const PerformanceGoal* const perfGoal = CURRSTMT_OPTDEFAULTS->getDefaultPerformanceGoal(),
RelExpr* mustMatch = NULL,
PushDownRequirement* pdp = NULL
)
: arrangedBy_(arrangedBy), orderedBy_(orderedBy),
sortOrderTypeReq_(sortOrderTypeReq),
dp2SortOrderPartReq_(dp2SortOrderPartReq),
logicalOrderOrArrangement_(logicalOrderOrArrangement),
partReq_(partReq),
logicalPartReq_(logicalPartReq),
location_(location),
availableCPUs_(availableCPUs),
pipelinesPerCPU_(pipelinesPerCPU),
costWeight_(costWeight),
perfGoal_(perfGoal),
mustMatch_(mustMatch),
pushDownRequirement_(pdp),
noEspExchangeRequirement_(FALSE),
ocbEnabledCostingRequirement_(FALSE)
{
#ifndef NDEBUG
performConsistencyCheck();
#endif
}
// ---------------------------------------------------------------------
// NOTE: mustMatch_ is not propagated from one reqd prop to another
// ---------------------------------------------------------------------
inline ReqdPhysicalProperty(const ReqdPhysicalProperty& other)
: arrangedBy_(other.arrangedBy_), orderedBy_(other.orderedBy_),
sortOrderTypeReq_(other.sortOrderTypeReq_),
dp2SortOrderPartReq_(other.dp2SortOrderPartReq_),
logicalOrderOrArrangement_(other.logicalOrderOrArrangement_),
partReq_(other.partReq_),
logicalPartReq_(other.logicalPartReq_),
location_(other.location_),
availableCPUs_(other.availableCPUs_),
pipelinesPerCPU_(other.pipelinesPerCPU_),
costWeight_(other.costWeight_),
perfGoal_(other.perfGoal_),
mustMatch_(NULL),
pushDownRequirement_(other.pushDownRequirement_),
noEspExchangeRequirement_(other.noEspExchangeRequirement_),
ocbEnabledCostingRequirement_(other.ocbEnabledCostingRequirement_)
{
#ifndef NDEBUG
performConsistencyCheck();
#endif
}
// ---------------------------------------------------------------------
// NOTE: mustMatch_ is not propagated from one reqd prop to another
// ---------------------------------------------------------------------
inline ReqdPhysicalProperty(const ReqdPhysicalProperty& other,
const ValueIdSet* const arrangedBy,
const ValueIdList* const orderedBy,
SortOrderTypeEnum sortOrderTypeReq,
PartitioningRequirement* dp2SortOrderPartReq
)
: arrangedBy_(arrangedBy), orderedBy_(orderedBy),
sortOrderTypeReq_(sortOrderTypeReq),
dp2SortOrderPartReq_(dp2SortOrderPartReq),
logicalOrderOrArrangement_(other.logicalOrderOrArrangement_),
partReq_(other.partReq_),
logicalPartReq_(other.logicalPartReq_),
location_(other.location_),
availableCPUs_(other.availableCPUs_),
pipelinesPerCPU_(other.pipelinesPerCPU_),
costWeight_(other.costWeight_),
perfGoal_(other.perfGoal_),
mustMatch_(NULL),
pushDownRequirement_(other.pushDownRequirement_),
noEspExchangeRequirement_(other.noEspExchangeRequirement_),
ocbEnabledCostingRequirement_(other.ocbEnabledCostingRequirement_)
{
#ifndef NDEBUG
performConsistencyCheck();
#endif
}
// ---------------------------------------------------------------------
// NOTE: mustMatch_ is not propagated from one reqd prop to another
// NOTE: The logicalPartitionBoundariesFlag_ is not propagated from one
// NOTE: required property to another when the partitioning requirement
// NOTE: is changed
// ---------------------------------------------------------------------
ReqdPhysicalProperty(const ReqdPhysicalProperty& other,
const ValueIdSet* const arrangedBy,
const ValueIdList* const orderedBy,
SortOrderTypeEnum sortOrderTypeReq,
PartitioningRequirement* dp2SortOrderPartReq,
PartitioningRequirement* partReq
)
: arrangedBy_(arrangedBy), orderedBy_(orderedBy),
sortOrderTypeReq_(sortOrderTypeReq),
dp2SortOrderPartReq_(dp2SortOrderPartReq),
logicalOrderOrArrangement_(other.logicalOrderOrArrangement_),
partReq_(partReq),
logicalPartReq_(other.logicalPartReq_),
location_(other.location_),
availableCPUs_(other.availableCPUs_),
pipelinesPerCPU_(other.pipelinesPerCPU_),
costWeight_(other.costWeight_),
perfGoal_(other.perfGoal_),
mustMatch_(NULL),
pushDownRequirement_(other.pushDownRequirement_),
noEspExchangeRequirement_(other.noEspExchangeRequirement_),
ocbEnabledCostingRequirement_(other.ocbEnabledCostingRequirement_)
{
#ifndef NDEBUG
performConsistencyCheck();
#endif
}
// ---------------------------------------------------------------------
// NOTE: mustMatch_ is not propagated from one reqd prop to another
// NOTE: The logicalPartitionBoundariesFlag_ is not propagated from one
// NOTE: required property to another when the partitioning requirement
// NOTE: is changed
// ---------------------------------------------------------------------
ReqdPhysicalProperty(const ReqdPhysicalProperty &other,
const ValueIdSet* const arrangedBy,
const ValueIdList* const orderedBy,
SortOrderTypeEnum sortOrderTypeReq,
PartitioningRequirement* dp2SortOrderPartReq,
PartitioningRequirement* partReq,
const PlanExecutionEnum location
)
: arrangedBy_(arrangedBy), orderedBy_(orderedBy),
sortOrderTypeReq_(sortOrderTypeReq),
dp2SortOrderPartReq_(dp2SortOrderPartReq),
logicalOrderOrArrangement_(other.logicalOrderOrArrangement_),
partReq_(partReq),
logicalPartReq_(other.logicalPartReq_),
location_(location),
availableCPUs_(other.availableCPUs_),
pipelinesPerCPU_(other.pipelinesPerCPU_),
costWeight_(other.costWeight_),
perfGoal_(other.perfGoal_),
mustMatch_(NULL),
pushDownRequirement_(other.pushDownRequirement_),
noEspExchangeRequirement_(other.noEspExchangeRequirement_),
ocbEnabledCostingRequirement_(other.ocbEnabledCostingRequirement_)
{
#ifndef NDEBUG
performConsistencyCheck();
#endif
}
// ---------------------------------------------------------------------
// NOTE: mustMatch_ is not propagated from one reqd prop to another
// NOTE: The logicalPartitionBoundariesFlag_ is not propagated from one
// NOTE: required property to another when the partitioning requirement
// NOTE: is changed
// ---------------------------------------------------------------------
ReqdPhysicalProperty(const ReqdPhysicalProperty &other,
const ValueIdSet* const arrangedBy,
const ValueIdList* const orderedBy,
SortOrderTypeEnum sortOrderTypeReq,
PartitioningRequirement* dp2SortOrderPartReq,
PartitioningRequirement* partReq,
const PlanExecutionEnum location,
const Lng32 availableCPUs,
const Lng32 pipelinesPerCPU
)
: arrangedBy_(arrangedBy), orderedBy_(orderedBy),
sortOrderTypeReq_(sortOrderTypeReq),
dp2SortOrderPartReq_(dp2SortOrderPartReq),
logicalOrderOrArrangement_(other.logicalOrderOrArrangement_),
partReq_(partReq),
logicalPartReq_(other.logicalPartReq_),
location_(location),
availableCPUs_(availableCPUs),
pipelinesPerCPU_(pipelinesPerCPU),
costWeight_(other.costWeight_),
perfGoal_(other.perfGoal_),
mustMatch_(NULL),
pushDownRequirement_(other.pushDownRequirement_),
noEspExchangeRequirement_(other.noEspExchangeRequirement_),
ocbEnabledCostingRequirement_(other.ocbEnabledCostingRequirement_)
{
#ifndef NDEBUG
performConsistencyCheck();
#endif
}
// create an empty requirement with only a must match in it
ReqdPhysicalProperty(RelExpr* mustMatch)
: arrangedBy_(NULL), orderedBy_(NULL),
sortOrderTypeReq_(NO_SOT),
dp2SortOrderPartReq_(NULL),
logicalOrderOrArrangement_(FALSE),
partReq_(NULL),
logicalPartReq_(NULL),
location_(DEFAULT_LOCATION),
availableCPUs_(DEFAULT_SINGLETON),
pipelinesPerCPU_(DEFAULT_SINGLETON),
perfGoal_(CURRSTMT_OPTDEFAULTS->getDefaultPerformanceGoal()),
costWeight_(CURRSTMT_OPTDEFAULTS->getDefaultCostWeight()),
mustMatch_(mustMatch),
pushDownRequirement_(NULL),
noEspExchangeRequirement_(FALSE),
ocbEnabledCostingRequirement_(FALSE)
{
#ifndef NDEBUG
performConsistencyCheck();
#endif
}
// ---------------------------------------------------------------------
// NOTE: mustMatch_ is not propagated from one reqd prop to another
// NOTE: This constructor is only used to change the "must match"
// attribute of an operator's rpp. This constructor is never
// used when creating a new rpp for a child.
// ---------------------------------------------------------------------
ReqdPhysicalProperty(const ReqdPhysicalProperty& other,
RelExpr* mustMatch
)
: arrangedBy_(other.arrangedBy_), orderedBy_(other.orderedBy_),
sortOrderTypeReq_(other.sortOrderTypeReq_),
dp2SortOrderPartReq_(other.dp2SortOrderPartReq_),
logicalOrderOrArrangement_(other.logicalOrderOrArrangement_),
partReq_(other.partReq_),
logicalPartReq_(other.logicalPartReq_),
location_(other.location_),
availableCPUs_(other.availableCPUs_),
pipelinesPerCPU_(other.pipelinesPerCPU_),
costWeight_(other.costWeight_),
perfGoal_(other.perfGoal_),
mustMatch_(mustMatch),
pushDownRequirement_(other.pushDownRequirement_),
noEspExchangeRequirement_(other.noEspExchangeRequirement_),
ocbEnabledCostingRequirement_(other.ocbEnabledCostingRequirement_)
{
#ifndef NDEBUG
performConsistencyCheck();
#endif
}
virtual ~ReqdPhysicalProperty();
// --------------------------------------------------------------------
// does a given plan satisfy the required property
// ---------------------------------------------------------------------
NABoolean satisfied(EstLogPropSharedPtr inputLogProp,
const RelExpr * const physExpr,
const PhysicalProperty * const physProp) const;
// ---------------------------------------------------------------------
// Comparison functions between two required phys. properties
//
// Return:
//
// LESS if "this" required physical property requires LESS
// than the "other" required property
// SAME if both properties require the SAME props
// MORE if "this" required physical property requires MORE
// than the "other" required property
// INCOMPATIBLE if the properties are incompatible (A and B are incom-
// patible => no physical property exists that satisfies
// both A and B or the two contexts have incompatible
// optimization goals, such as optimization for n rows
// or statistics for input values)
// UNDEFINED can't tell which requires more or less (properties may
// in some subtle cases still be incompatible)
// ---------------------------------------------------------------------
COMPARE_RESULT compareRequirements(const ReqdPhysicalProperty & other) const;
// ---------------------------------------------------------------------
// Accessor/Mutator functions
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Check whether any requirements are specified at all.
// ---------------------------------------------------------------------
NABoolean isEmpty() const;
// ---------------------------------------------------------------------
// User-specified cost weight.
// ---------------------------------------------------------------------
inline const CostWeight* getCostWeight() const { return costWeight_; }
// ---------------------------------------------------------------------
// User-specified performance goal.
// ---------------------------------------------------------------------
inline const PerformanceGoal* getPerformanceGoal() const
{ return perfGoal_; }
// ---------------------------------------------------------------------
// Requirements related to imposing an order on the result.
// ---------------------------------------------------------------------
inline const ValueIdSet * getArrangedCols() const { return arrangedBy_; }
inline const ValueIdList * getSortKey() const { return orderedBy_; }
static void initSortOrderTypeCompTab();
static void initSortOrderTypeContextCompTab();
//accessors
SortOrderTypeEnum getSortOrderTypeReq() const
{ return sortOrderTypeReq_; }
PartitioningRequirement* getDp2SortOrderPartReq() const
{ return dp2SortOrderPartReq_; }
// mutators
void setSortOrderTypeReq (SortOrderTypeEnum sortOrderTypeReq)
{
// Check that the required sort order type is within the
// allowable range for a required sort order type.
DCMPASSERT((sortOrderTypeReq >= NO_SOT) AND
(sortOrderTypeReq <= DP2_OR_ESP_NO_SORT_SOT))
sortOrderTypeReq_ = sortOrderTypeReq;
}
void setDp2SortOrderPartReq
(PartitioningRequirement* dp2SortOrderPartReq)
{ dp2SortOrderPartReq_ = dp2SortOrderPartReq; }
NABoolean sortOrderTypeReqAndSynthCompatible
(const SortOrderTypeEnum synthesizedSortOrderType) const;
COMPARE_RESULT compareSortOrderTypeReqToReq
(const SortOrderTypeEnum otherSortOrderTypeReq) const;
NABoolean dp2SortOrderPartReqAndSynthCompatible
(const PhysicalProperty* const spp) const;
inline NABoolean getLogicalOrderOrArrangementFlag() const
{ return logicalOrderOrArrangement_; }
inline void setLogicalOrderOrArrangementFlag(const NABoolean newValue)
{ logicalOrderOrArrangement_ = newValue; }
// ---------------------------------------------------------------------
// Location for plan execution
// ---------------------------------------------------------------------
PlanExecutionEnum getPlanExecutionLocation() const
{ return location_; }
NABoolean executeInDP2() const { return (location_ == EXECUTE_IN_DP2); }
// ---------------------------------------------------------------------
// The number of pipelines that can be formed for executing a
// plan fragment in parallel without (outside of) a DP2.
// ---------------------------------------------------------------------
inline Lng32 getCountOfPipelines() const
{ return availableCPUs_ * pipelinesPerCPU_; }
inline Lng32 getCountOfAvailableCPUs() const { return availableCPUs_; }
// ---------------------------------------------------------------------
// The partitions, i.e., the number of data streams that should
// be produced. This is specifed by means of a partitioning requirement.
// ---------------------------------------------------------------------
inline NABoolean requiresPartitioning() const
{ return (partReq_ != NULL); }
inline PartitioningRequirement * getPartitioningRequirement() const
{ return partReq_; }
Lng32 getCountOfPartitions() const
{ return partReq_->getCountOfPartitions(); }
// --- Read-only access to the partitioning key.
inline const ValueIdSet & getPartitioningKey() const
{ return partReq_->getPartitioningKey(); }
// ---------------------------------------------------------------------
// logical partitioning requirement for DP2 fragments
// ---------------------------------------------------------------------
LogicalPartitioningRequirement * getLogicalPartRequirement() const
{ return logicalPartReq_; }
void setLogicalPartRequirement(LogicalPartitioningRequirement *lpr)
{ logicalPartReq_ = lpr; }
// ---------------------------------------------------------------------
// A pattern supplied for enforcing a certain shape on the query
// tree of the plan.
// ---------------------------------------------------------------------
inline const RelExpr * getMustMatch() const { return mustMatch_; }
RelExpr* getInputMustMatch(Lng32 childIndex) const;
void setPushDownRequirement(const PushDownRequirement* pdp)
{ pushDownRequirement_ = pdp; };
const PushDownRequirement* getPushDownRequirement() const
{ return pushDownRequirement_ ; } ;
NABoolean getNoEspExchangeRequirement() const
{ return noEspExchangeRequirement_; } ;
void setNoEspExchangeRequirement(const NABoolean b)
{ noEspExchangeRequirement_ = b; };
NABoolean getOcbEnabledCostingRequirement() const
{ return ocbEnabledCostingRequirement_; } ;
void setOcbEnabledCostingRequirement(const NABoolean b)
{ ocbEnabledCostingRequirement_ = b; };
// ---------------------------------------------------------------------
// Utility functions
// ---------------------------------------------------------------------
void print(FILE* ofd = stdout,
const char * prefix = DEFAULT_INDENT,
const char * suffix = "") const;
private:
// ---------------------------------------------------------------------
// PRIVATE METHODS
// ---------------------------------------------------------------------
void performConsistencyCheck() const
{
DCMPASSERT((availableCPUs_ > 0) AND
(pipelinesPerCPU_ > 0) AND
(costWeight_ != NULL) AND
(perfGoal_ != NULL) );
#ifndef NDEBUG
performSortOrderTypeConsistencyCheck();
#endif
}
void performSortOrderTypeConsistencyCheck() const
{
if ((arrangedBy_ == NULL) AND (orderedBy_ == NULL))
{
DCMPASSERT(sortOrderTypeReq_ == NO_SOT);
DCMPASSERT(dp2SortOrderPartReq_ == NULL);
}
else
{
DCMPASSERT((sortOrderTypeReq_ != NO_SOT) OR
(location_ == EXECUTE_IN_DP2));
}
if ((dp2SortOrderPartReq_ != NULL) OR
(sortOrderTypeReq_ == DP2_OR_ESP_NO_SORT_SOT) OR
(sortOrderTypeReq_ == DP2_SOT))
{
DCMPASSERT(dp2SortOrderPartReq_ != NULL);
DCMPASSERT((location_ == EXECUTE_IN_DP2 AND sortOrderTypeReq_ == NO_SOT) OR (sortOrderTypeReq_ == DP2_OR_ESP_NO_SORT_SOT) OR
(sortOrderTypeReq_ == DP2_SOT));
}
} // performSortOrderTypeConsistencyCheck()
// ---------------------------------------------------------------------
// PRIVATE DATA
// ---------------------------------------------------------------------
static THREAD_P LookupTable<NABoolean>* sortOrderTypeCompTab_;
static THREAD_P LookupTable<COMPARE_RESULT>* sortOrderTypeContextCompTab_;
const CostWeight* const costWeight_; // weight used for comparing costs
const PerformanceGoal* const perfGoal_; // the performance goal
// ---------------------------------------------------------------------
// The output rows are required to be "arranged" such that they are
// sorted and the set of "arrangedBy_" values forms a prefix of the
// sort key.
// ---------------------------------------------------------------------
const ValueIdSet* const arrangedBy_;
// ---------------------------------------------------------------------
// The output rows are required to be ordered by the given columns.
// ---------------------------------------------------------------------
const ValueIdList* const orderedBy_;
// ---------------------------------------------------------------------
// The type of sorted order needed: NO_SOT, ESP_NO_SORT_SOT,
// ESP_VIA_SORT_SOT, DP2_SOT, ESP_SOT, DP2_OR_ESP_NO_SORT_SOT
// ---------------------------------------------------------------------
SortOrderTypeEnum sortOrderTypeReq_;
// ---------------------------------------------------------------------
// The required physical partitioning for a sort order type of DP2 to
// be valid.
// ---------------------------------------------------------------------
PartitioningRequirement* dp2SortOrderPartReq_;
// ---------------------------------------------------------------------
// Indicates whether any required order or arrangement is a logical one.
// This flag will be TRUE if the current location is DP2, and there is
// a required order or arrangement that came from an operator that is
// not in DP2. A logical order or arrangement requirement has
// different rules as to whether the spp satisfies it. See the
// "satisfied" method for details.
// ---------------------------------------------------------------------
NABoolean logicalOrderOrArrangement_;
// ---------------------------------------------------------------------
// The number of instances of a plan fragment that shall execute
// concurrently, in parallel.
// ---------------------------------------------------------------------
const Lng32 availableCPUs_;
const Lng32 pipelinesPerCPU_;
// ---------------------------------------------------------------------
// Specification of the location where the plan must execute.
// ---------------------------------------------------------------------
const PlanExecutionEnum location_;
// ---------------------------------------------------------------------
// The partition requirement describes the characteristics of the
// data streams that are to be produced as output by using a
// built-in (system-defined) partitioning requirement. The destination
// for the data streams could either be a partitioned file set or
// even be a set of ESP's. The absence of a partitioning requirement
// implies that a single output stream must be produced.
//
// partReq_->getCountOfPartitions() specifies the number
// of data streams that must be produced as output. The distribution
// of rows amongst these data streams is dependant upon information
// contained in the partitioning requirement.
//
// partReq_->getPartitioningKey() yields a set of expressions that
// form the partitioning key. The application of the partitioning
// function to the values contained in the partitioning key columns
// decides the data stream (partition number) to which a certain row
// is assigned.
// ---------------------------------------------------------------------
PartitioningRequirement* partReq_;
// ---------------------------------------------------------------------
// The logical partitioning requirement applies to contexts that
// execute in DP2. In this case, logicalPartReq_ describes the
// requirements of the PA or PAPA exchange above. This helps the
// DP2 leaf node (scan, insert, update, delete) to perform "logical
// partitioning", meaning to deal with the fact that multiple PAs or
// ESPs will share the work for the operation.
// ---------------------------------------------------------------------
LogicalPartitioningRequirement *logicalPartReq_;
// ---------------------------------------------------------------------
// Requirement for matching a given tree shape
// ---------------------------------------------------------------------
RelExpr* mustMatch_;
// PushDown requirement, if any.
const PushDownRequirement* pushDownRequirement_;
NABoolean noEspExchangeRequirement_;
NABoolean ocbEnabledCostingRequirement_;
}; // ReqdPhysicalProperty
// this class collects fragment-wise memory related information
class CurrentFragmentBigMemoryProperty : public NABasicObject
{
public:
CurrentFragmentBigMemoryProperty():
currentFileSize_(0),
cumulativeFileSizeofFragment_(0),
noBigMemOpsSoFar_(0),
Op_(NO_OPERATOR_TYPE)
{};
virtual ~CurrentFragmentBigMemoryProperty() {};
void setCurrentFileSize(double d)
{ currentFileSize_=d;
cumulativeFileSizeofFragment_=d;}
double getCumulativeFileSize()
{ return cumulativeFileSizeofFragment_; }
void incrementCumulativeMemSize(double d)
{ cumulativeFileSizeofFragment_+=d;}
void setOperatorType(OperatorTypeEnum op)
{ Op_ = op;}
private:
double currentFileSize_;
double cumulativeFileSizeofFragment_;
Int32 noBigMemOpsSoFar_;
OperatorTypeEnum Op_;
};
// required push down property
class PushDownCSProperty;
class PushDownColocationProperty;
//
// PushDown property abstract class, which defines the interface
// for producing push-down property and generating push-down
// requirement.
//
class PushDownProperty : public NABasicObject
{
public:
PushDownProperty() {};
virtual ~PushDownProperty() {};
// is this propery fully specified?
virtual NABoolean isEmpty() const = 0;
// generating a requirement from a propery.
// used by various createContextForAChild() to echo the
// requirement to the right child, given the push-down
// property from the left child.
virtual const PushDownRequirement* makeRequirement() const = 0;
// dynamic type checking help function for PushDownColocationProperty
virtual const PushDownColocationProperty*
castToPushDownColocationProperty() const { return NULL; };
// dynamic type checking help function for PushDownCSProperty
virtual const
PushDownCSProperty* castToPushDownCSProperty() const { return NULL; };
private:
};
//
// Push-down colocation checking property.
//
class PushDownColocationProperty : public PushDownProperty
{
public:
PushDownColocationProperty(const NodeMap* map = 0) : map_(map) {};
virtual ~PushDownColocationProperty() {};
const NodeMap* getNodeMap() const { return map_; };
NABoolean isEmpty() const { return map_ == 0; };
// generate a PushDownColocationRequirement from the property.
const PushDownRequirement* makeRequirement() const;
const PushDownColocationProperty*
castToPushDownColocationProperty() const { return this; };
private:
const NodeMap* map_;
};
//
// Compound statement push down property.
//
class PushDownCSProperty : public PushDownColocationProperty
{
public:
PushDownCSProperty(const PartitioningFunction* func = 0,
const SearchKey* key = 0) :
PushDownColocationProperty( (func)? func->getNodeMap() : 0),
partFunc_(func), searchKey_(key) {};
~PushDownCSProperty() {};
// get data members
const SearchKey* getSearchKey() const { return searchKey_; };
const PartitioningFunction* getPartFunc() const { return partFunc_; };
// partFunc will never be NULL for a concrete CS push-down
// property. searchKey could be empty (e.g., "select * from t"
// where t is a single partitioned table)
NABoolean isEmpty() const { return partFunc_ == 0; };
// generating a CS push-down requirement.
const PushDownRequirement* makeRequirement() const;
// dynamic type checking help function
const PushDownCSProperty* castToPushDownCSProperty() const { return this; };
private:
const PartitioningFunction* partFunc_;
const SearchKey* searchKey_;
};
// Push down requirement (physical always)
class PushDownCSRequirement;
class PushDownColocationRequirement;
//
// PushDown requirement abstract class, which defines the interface
// for verifying whether a push-down property satisfies a push-down
// requirement.
//
class PushDownRequirement : public NABasicObject
{
public:
PushDownRequirement() {};
virtual ~PushDownRequirement() {};
// check the null state of the requirement (is the requirement fully
// specified?).
virtual NABoolean isEmpty() const = 0;
// verifying a requirement is met by a property.
virtual NABoolean satisfied(const PushDownProperty&) const = 0;
// dynamic type checking on PushDownColocationRequirement.
virtual const PushDownColocationRequirement*
castToPushDownColocationRequirement() const { return NULL; };
// dynamic type checking on PushDownCSRequirement.
virtual const PushDownCSRequirement*
castToPushDownCSRequirement() const { return NULL; };
virtual COMPARE_RESULT compare(const PushDownRequirement &other) const = 0;
private:
};
//
// Colocation requirement class hierarchy.
//
class PushDownColocationRequirement : public PushDownRequirement
{
public:
PushDownColocationRequirement(const NodeMap* map = NULL) : map_(map) {};
~PushDownColocationRequirement() {};
// The data member access function
const NodeMap* getNodeMap() const { return map_; };
NABoolean isEmpty() const { return map_ == NULL; };
NABoolean satisfied(const PushDownProperty&) const;
const PushDownColocationRequirement*
castToPushDownColocationRequirement() const { return this; };
// test whether an instance of PushDownRequirement class is
// actually a PushDownColocationRequirement.
static NABoolean isInstanceOf(const PushDownRequirement* x)
{ return (x AND x->castToPushDownColocationRequirement()); };
COMPARE_RESULT compare(const PushDownRequirement &other) const;
private:
const NodeMap* map_;
};
//
// Compound statement push down requirement class hierarchy.
//
class PushDownCSRequirement : public PushDownColocationRequirement
{
public:
PushDownCSRequirement(const PartitioningFunction* func = NULL,
const SearchKey* key = NULL) :
PushDownColocationRequirement((func)? func->getNodeMap() : NULL),
partFunc_(func), searchKey_(key) {};
~PushDownCSRequirement() {};
// data member access functions
const SearchKey* getSearchKey() const { return searchKey_; };
const PartitioningFunction* getPartFunc() const { return partFunc_; };
// partFunc will never be NULL for a concrete CS push-down
// requirement
NABoolean isEmpty() const { return partFunc_ == NULL; };
NABoolean satisfied(const PushDownProperty&) const;
const PushDownCSRequirement*
castToPushDownCSRequirement() const { return this; };
// test whether an instance of PushDownRequirement class is
// actually a PushDownCSRequirement.
static NABoolean isInstanceOf(const PushDownRequirement* x)
{ return (x AND x->castToPushDownCSRequirement()); };
COMPARE_RESULT compare(const PushDownRequirement &other) const;
private:
const PartitioningFunction* partFunc_;
const SearchKey* searchKey_;
};
// -----------------------------------------------------------------------
// Input physical properties
//
// Used by an operator to specify to its child any physical information
// concerning the parent, ancestors, or siblings that could be helpful
// in costing the current operator. It is currently only used by
// nested join to pass physical information about the left child to the
// right child. If assumeSortedForCosting_ is set then all other fields will be NULL
// and if any of the nj... fields are set assumeSortedForCosting_ is FALSE.
// -----------------------------------------------------------------------
class InputPhysicalProperty : public NABasicObject
{
public:
// default and standard constructor
InputPhysicalProperty(
const ValueIdSet & outerCharOutputs,
const ValueIdList* const outerOrder = NULL,
const PartitioningFunction* const outerOrderPartFunc = NULL,
const PartitioningFunction* const dp2SortOrderPartFunc =NULL,
const NABoolean assumeSortedForCosting = FALSE,
NABoolean explodedOcbJoinForCosting = FALSE)
: njOuterCharOutputs_(outerCharOutputs),
njOuterOrder_(outerOrder),
njOuterOrderPartFunc_(outerOrderPartFunc),
njDp2OuterOrderPartFunc_(dp2SortOrderPartFunc),
assumeSortedForCosting_(assumeSortedForCosting),
njOuterPartFuncForNonUpdates_(outerOrderPartFunc),
explodedOcbJoinForCosting_(explodedOcbJoinForCosting)
{}
// Constructor especially for Exploded Nested Join
InputPhysicalProperty(
const NABoolean assumeSortedProbesForCosting,
NABoolean explodedOcbJoinForCosting = FALSE)
: assumeSortedForCosting_(assumeSortedProbesForCosting),
explodedOcbJoinForCosting_(explodedOcbJoinForCosting),
njOuterCharOutputs_(NULL),
njOuterOrder_(NULL),
njOuterOrderPartFunc_(NULL),
njOuterPartFuncForNonUpdates_(NULL),
njDp2OuterOrderPartFunc_(NULL)
{}
InputPhysicalProperty(
const NABoolean assumeSortedProbesForCosting,
const PartitioningFunction* const njOuterPartFunc,
NABoolean explodedOcbJoinForCosting = FALSE)
: assumeSortedForCosting_(assumeSortedProbesForCosting),
njOuterPartFuncForNonUpdates_(njOuterPartFunc),
explodedOcbJoinForCosting_(explodedOcbJoinForCosting),
njOuterCharOutputs_(NULL),
njOuterOrder_(NULL),
njOuterOrderPartFunc_(NULL),
njDp2OuterOrderPartFunc_(NULL)
{}
// copy constructor
InputPhysicalProperty(const InputPhysicalProperty& other)
: njOuterCharOutputs_(other.njOuterCharOutputs_),
njOuterOrder_(other.njOuterOrder_),
njOuterOrderPartFunc_(other.njOuterOrderPartFunc_),
njDp2OuterOrderPartFunc_(other.njDp2OuterOrderPartFunc_),
assumeSortedForCosting_(other.assumeSortedForCosting_),
njOuterPartFuncForNonUpdates_(other.njOuterPartFuncForNonUpdates_),
explodedOcbJoinForCosting_(other.explodedOcbJoinForCosting_)
{}
// destructor
virtual ~InputPhysicalProperty();
// Accessors
const ValueIdSet& getNjOuterCharOutputs() const
{ return njOuterCharOutputs_; }
const ValueIdList* getNjOuterOrder() const
{ return njOuterOrder_; }
const PartitioningFunction* getNjOuterOrderPartFunc() const
{ return njOuterOrderPartFunc_; }
const PartitioningFunction* getNjDp2OuterOrderPartFunc() const
{ return njDp2OuterOrderPartFunc_; }
NABoolean getAssumeSortedForCosting() const
{ return assumeSortedForCosting_; }
// Comparison method for use when comparing contexts
COMPARE_RESULT compareInputPhysicalProperties(
const InputPhysicalProperty& other) const;
const PartitioningFunction* getNjOuterOrderPartFuncForNonUpdates() const
{ return njOuterPartFuncForNonUpdates_;}
NABoolean getExplodedOcbJoinForCosting() const
{ return explodedOcbJoinForCosting_; }
private:
// Used to pass the characteristic outputs from the left child
// of a nested join to the right child. This is so the right
// child can determine what its equijoin columns are.
const ValueIdSet njOuterCharOutputs_;
// Used to pass the synthesized sort key of the left child of
// a nested join to the right child for costing purposes.
const ValueIdList * njOuterOrder_;
// Used to pass the synthesized logical partitioning function
// of the left child of a nested join to the right child for
// costing purposes.
const PartitioningFunction* njOuterOrderPartFunc_;
// Used to pass the synthesized physical partitioning function
// of the left child access path to the right child, if the
// sort order type of the left child's sort key was "dp2",
// for costing purposes.
const PartitioningFunction* njDp2OuterOrderPartFunc_;
// we want to find partition function even when order is not
// important. See case2 comment for assumeSortedForCosting_ below.
const PartitioningFunction* njOuterPartFuncForNonUpdates_;
// assumeSortedForCosting_ flag is set for two cases:
// case 1: when input is rowset.
// Used to pass information that the left child is an Unpack node
// that is being used to flow input rowsets. We will assume that input rowsets
// are sorted with respect to whatever access path is being considered for the
// right child. This assumption is made only for costing, and not to detrmine the
// plan. This assumption will help us choose "optimistic" plans for rowset input,
// assuming that rowset input is appropriately sorted, even though it may not be,
// as we have no way to infer the sort order of the input rowset.
// In this case njOuterPartFuncForNonUpdates_ will always NULL.
// case 2: when left child partFunc njOuterPartFuncForNonUpdates_ is passed for
// NJ plan 0. This is only for cost estimation of exchange operator.
// In this case njOuterPartFuncForNonUpdates_ will always be non-NULL.
const NABoolean assumeSortedForCosting_ ;
NABoolean explodedOcbJoinForCosting_ ;
}; // InputPhysicalProperty
#endif /* PHYPROP_HDR */