ORCA优化器浅析——CFunctionProp function properties_构造函数

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;
}

ORCA优化器浅析——CFunctionProp function properties_SQL_02


而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);
}