CFunctionProp
CFunctionProp代表了function properties函数属性,主要由function stability函数易变性( enum EFuncStbl { EfsImmutable, /* never changes for given input */ EfsStable, /* does not change within a scan */ EfsVolatile, /* can change even within a scan */ EfsSentinel };
)、表达式是否含有volatile函数扫描标志m_fHasVolatileFunctionScan、函数是否用作scan operator标志m_fScan成员组成。其中函数易变性EFuncStbl是最关键的function properties。
//---------------------------------------------------------------------------
// @class:
// CFunctionProp
// @doc:
// Representation of function properties
//---------------------------------------------------------------------------
class CFunctionProp : public CRefCount {
private:
IMDFunction::EFuncStbl m_efs; // function stability
BOOL m_fHasVolatileFunctionScan; // does this expression have a volatile Function Scan
BOOL m_fScan; // is this function used as a scan operator
CFunctionProp(const CFunctionProp &); // hidden copy ctor
public:
CFunctionProp(IMDFunction::EFuncStbl func_stability, BOOL fHasVolatileFunctionScan, BOOL fScan); // ctor
virtual ~CFunctionProp(); // dtor
IMDFunction::EFuncStbl Efs() const { return m_efs; } // function stability
virtual BOOL FHasVolatileFunctionScan() const { return m_fHasVolatileFunctionScan; } // does this expression have a volatile Function Scan
BOOL NeedsSingletonExecution() const; // check if must execute on a single host
IOstream &OsPrint(IOstream &os) const; // print
}; // class CFunctionProp
//---------------------------------------------------------------------------
// @function:
// CFunctionProp::SingletonExecution
// @doc:
// Check if must execute on a single host based on function properties
//---------------------------------------------------------------------------
BOOL CFunctionProp::NeedsSingletonExecution() const {
// a function needs to execute on a single host if any of the following holds:
// a) it reads or modifies SQL data
// b) it is volatile and used as a scan operator (i.e. in the from clause)
// TODO: - Feb 10, 2014; enable the following line instead of the
// current return statement once all function properties are fixed
//return (IMDFunction::EfdaContainsSQL < m_efda || (m_fScan && IMDFunction::EfsVolatile == m_efs));
return m_fScan && (IMDFunction::EfsVolatile == m_efs || IMDFunction::EfsStable == m_efs);
}
其中NeedsSingletonExecution函数用于检查function properties指明该函数只能在single host上执行。这种函数有如下之一的特征:a) it reads or modifies SQL data b) it is volatile and used as a scan operator (i.e. in the from clause)。
COperator
COperator作为Base class for all operators: logical, physical, scalar, patterns。其提供了两个protected的静态函数和function properties相关的函数,定义如下所示。
class COperator : public CRefCount
{
private:
// private copy ctor
COperator(COperator &);
protected:
// operator id that is unique over all instances of all operator types
// for the current query
ULONG m_ulOpId;
// memory pool for internal allocations
CMemoryPool *m_mp;
// is pattern of xform
BOOL m_fPattern;
// return an addref'ed copy of the operator
virtual COperator *PopCopyDefault();
// derive stability function property from children
static IMDFunction::EFuncStbl EfsDeriveFromChildren(
CExpressionHandle &exprhdl, IMDFunction::EFuncStbl efsDefault);
// derive function properties from children
static CFunctionProp *PfpDeriveFromChildren(
CMemoryPool *mp, CExpressionHandle &exprhdl,
IMDFunction::EFuncStbl efsDefault, BOOL fHasVolatileFunctionScan,
BOOL fScan);
// generate unique operator ids
static ULONG m_aulOpIdCounter;
...
}
COperator::EfsDeriveFromChildren函数用于从子表达式中提取stability function property函数易变属性。从代码实现可以看出其也是通过CExpressionHandle接口来获取对应子表达式的CFunctionProp function properties,从而获取其易变属性值的。从逻辑实现来看EfsImmutable, /* never changes for given input */ EfsStable, /* does not change within a scan */ EfsVolatile, /* can change even within a scan */ EfsSentinel
只要子表达式中的函数出现易变属性,将会掩盖其他函数的非易变属性。
//---------------------------------------------------------------------------
// @function:
// COperator::EfsDeriveFromChildren
// @doc:
// Derive stability function property from child expressions
//---------------------------------------------------------------------------
IMDFunction::EFuncStbl COperator::EfsDeriveFromChildren(CExpressionHandle &exprhdl, IMDFunction::EFuncStbl efsDefault) {
IMDFunction::EFuncStbl efs = efsDefault;
const ULONG arity = exprhdl.Arity();
for (ULONG ul = 0; ul < arity; ul++){
IMDFunction::EFuncStbl efsChild = exprhdl.PfpChild(ul)->Efs();
if (efsChild > efs){
efs = efsChild;
}
}
return efs;
}
而COperator::PfpDeriveFromChildren则是调用EfsDeriveFromChildren函数获取易变属性,然后调用CFunctionProp构造函数创建函数属性变量。
//---------------------------------------------------------------------------
// @function:
// COperator::PfpDeriveFromChildren
// @doc:
// Derive function properties from child expressions
//---------------------------------------------------------------------------
CFunctionProp *COperator::PfpDeriveFromChildren(CMemoryPool *mp, CExpressionHandle &exprhdl, IMDFunction::EFuncStbl efsDefault, BOOL fHasVolatileFunctionScan, BOOL fScan){
IMDFunction::EFuncStbl efs = EfsDeriveFromChildren(exprhdl, efsDefault);
return GPOS_NEW(mp) CFunctionProp(
efs,
fHasVolatileFunctionScan || exprhdl.FChildrenHaveVolatileFuncScan(),
fScan);
}