greenplumn CDXLOperatorFactory 源码

  • 2022-08-18
  • 浏览 (296)

greenplumn CDXLOperatorFactory 代码

文件路径:/src/backend/gporca/libnaucrates/src/operators/CDXLOperatorFactory.cpp

//---------------------------------------------------------------------------
//	Greenplum Database
//	Copyright (C) 2010 Greenplum, Inc.
//
//	@filename:
//		CDXLOperatorFactory.cpp
//
//	@doc:
//		Implementation of the factory methods for creation of DXL elements.
//---------------------------------------------------------------------------

#include "naucrates/dxl/operators/CDXLOperatorFactory.h"

#include <xercesc/util/NumberFormatException.hpp>

#include "gpos/common/clibwrapper.h"
#include "gpos/string/CWStringConst.h"
#include "gpos/string/CWStringDynamic.h"

#include "naucrates/dxl/CDXLUtils.h"
#include "naucrates/dxl/operators/CDXLDatumBool.h"
#include "naucrates/dxl/operators/CDXLDatumGeneric.h"
#include "naucrates/dxl/operators/CDXLDatumInt2.h"
#include "naucrates/dxl/operators/CDXLDatumInt4.h"
#include "naucrates/dxl/operators/CDXLDatumInt8.h"
#include "naucrates/dxl/operators/CDXLDatumOid.h"
#include "naucrates/dxl/operators/CDXLDatumStatsDoubleMappable.h"
#include "naucrates/dxl/operators/CDXLDatumStatsLintMappable.h"
#include "naucrates/dxl/operators/CDXLLogicalJoin.h"
#include "naucrates/dxl/operators/CDXLPhysicalAgg.h"
#include "naucrates/dxl/operators/CDXLPhysicalAppend.h"
#include "naucrates/dxl/operators/CDXLPhysicalBroadcastMotion.h"
#include "naucrates/dxl/operators/CDXLPhysicalGatherMotion.h"
#include "naucrates/dxl/operators/CDXLPhysicalHashJoin.h"
#include "naucrates/dxl/operators/CDXLPhysicalLimit.h"
#include "naucrates/dxl/operators/CDXLPhysicalMaterialize.h"
#include "naucrates/dxl/operators/CDXLPhysicalMergeJoin.h"
#include "naucrates/dxl/operators/CDXLPhysicalNLJoin.h"
#include "naucrates/dxl/operators/CDXLPhysicalRandomMotion.h"
#include "naucrates/dxl/operators/CDXLPhysicalRedistributeMotion.h"
#include "naucrates/dxl/operators/CDXLPhysicalResult.h"
#include "naucrates/dxl/operators/CDXLPhysicalRoutedDistributeMotion.h"
#include "naucrates/dxl/operators/CDXLPhysicalSort.h"
#include "naucrates/dxl/operators/CDXLPhysicalSubqueryScan.h"
#include "naucrates/dxl/operators/CDXLPhysicalTableScan.h"
#include "naucrates/dxl/operators/CDXLScalarAggref.h"
#include "naucrates/dxl/operators/CDXLScalarArray.h"
#include "naucrates/dxl/operators/CDXLScalarArrayCoerceExpr.h"
#include "naucrates/dxl/operators/CDXLScalarArrayComp.h"
#include "naucrates/dxl/operators/CDXLScalarCast.h"
#include "naucrates/dxl/operators/CDXLScalarCoerceToDomain.h"
#include "naucrates/dxl/operators/CDXLScalarCoerceViaIO.h"
#include "naucrates/dxl/operators/CDXLScalarComp.h"
#include "naucrates/dxl/operators/CDXLScalarDistinctComp.h"
#include "naucrates/dxl/operators/CDXLScalarFuncExpr.h"
#include "naucrates/dxl/operators/CDXLScalarHashExpr.h"
#include "naucrates/dxl/operators/CDXLScalarIdent.h"
#include "naucrates/dxl/operators/CDXLScalarIfStmt.h"
#include "naucrates/dxl/operators/CDXLScalarLimitCount.h"
#include "naucrates/dxl/operators/CDXLScalarLimitOffset.h"
#include "naucrates/dxl/operators/CDXLScalarNullTest.h"
#include "naucrates/dxl/operators/CDXLScalarOpExpr.h"
#include "naucrates/dxl/operators/CDXLScalarProjElem.h"
#include "naucrates/dxl/operators/CDXLScalarSortCol.h"
#include "naucrates/dxl/operators/CDXLScalarWindowRef.h"
#include "naucrates/exception.h"
#include "naucrates/md/CMDIdCast.h"
#include "naucrates/md/CMDIdColStats.h"
#include "naucrates/md/CMDIdGPDB.h"
#include "naucrates/md/CMDIdGPDBCtas.h"
#include "naucrates/md/CMDIdRelStats.h"
#include "naucrates/md/CMDIdScCmp.h"

using namespace gpos;
using namespace gpdxl;


XERCES_CPP_NAMESPACE_USE

#define GPDXL_GPDB_MDID_COMPONENTS 3
#define GPDXL_DEFAULT_USERID 0

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLTblScan
//
//	@doc:
//		Construct a table scan operator
//
//---------------------------------------------------------------------------
CDXLPhysical *
CDXLOperatorFactory::MakeDXLTblScan(CDXLMemoryManager *dxl_memory_manager,
									const Attributes &	// attrs
)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	return GPOS_NEW(mp) CDXLPhysicalTableScan(mp);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLSubqScan
//
//	@doc:
//		Construct a subquery scan operator
//
//---------------------------------------------------------------------------
CDXLPhysical *
CDXLOperatorFactory::MakeDXLSubqScan(CDXLMemoryManager *dxl_memory_manager,
									 const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// parse subquery name from attributes
	const XMLCh *subquery_name_xml =
		ExtractAttrValue(attrs, EdxltokenAlias, EdxltokenPhysicalSubqueryScan);

	CWStringDynamic *subquery_name_str =
		CDXLUtils::CreateDynamicStringFromXMLChArray(dxl_memory_manager,
													 subquery_name_xml);


	// create a copy of the string in the CMDName constructor
	CMDName *subquery_name = GPOS_NEW(mp) CMDName(mp, subquery_name_str);

	GPOS_DELETE(subquery_name_str);

	return GPOS_NEW(mp) CDXLPhysicalSubqueryScan(mp, subquery_name);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLResult
//
//	@doc:
//		Construct a result operator
//
//---------------------------------------------------------------------------
CDXLPhysical *
CDXLOperatorFactory::MakeDXLResult(CDXLMemoryManager *dxl_memory_manager)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	return GPOS_NEW(mp) CDXLPhysicalResult(mp);
}

//		Construct a hashjoin operator
CDXLPhysical *
CDXLOperatorFactory::MakeDXLHashJoin(CDXLMemoryManager *dxl_memory_manager,
									 const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	const XMLCh *join_type_xml =
		ExtractAttrValue(attrs, EdxltokenJoinType, EdxltokenPhysicalHashJoin);

	EdxlJoinType join_type = ParseJoinType(
		join_type_xml, CDXLTokens::GetDXLTokenStr(EdxltokenPhysicalHashJoin));

	return GPOS_NEW(mp) CDXLPhysicalHashJoin(mp, join_type);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLNLJoin
//
//	@doc:
//		Construct a nested loop join operator
//
//---------------------------------------------------------------------------
CDXLPhysical *
CDXLOperatorFactory::MakeDXLNLJoin(CDXLMemoryManager *dxl_memory_manager,
								   const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	const XMLCh *join_type_xml =
		ExtractAttrValue(attrs, EdxltokenJoinType, EdxltokenPhysicalNLJoin);

	BOOL is_index_nlj = false;
	const XMLCh *index_nlj_xml =
		attrs.getValue(CDXLTokens::XmlstrToken(EdxltokenPhysicalNLJoinIndex));
	if (nullptr != index_nlj_xml)
	{
		is_index_nlj = ConvertAttrValueToBool(dxl_memory_manager, index_nlj_xml,
											  EdxltokenPhysicalNLJoinIndex,
											  EdxltokenPhysicalNLJoin);
	}

	// identify if nest params are expected in dxl
	BOOL nest_params_exists = false;
	const XMLCh *nest_param_exists_xml = attrs.getValue(
		CDXLTokens::XmlstrToken(EdxltokenNLJIndexOuterRefAsParam));
	if (nullptr != nest_param_exists_xml)
	{
		nest_params_exists = ConvertAttrValueToBool(
			dxl_memory_manager, nest_param_exists_xml,
			EdxltokenNLJIndexOuterRefAsParam, EdxltokenPhysicalNLJoin);
	}

	EdxlJoinType join_type = ParseJoinType(
		join_type_xml, CDXLTokens::GetDXLTokenStr(EdxltokenPhysicalNLJoin));

	return GPOS_NEW(mp)
		CDXLPhysicalNLJoin(mp, join_type, is_index_nlj, nest_params_exists);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLMergeJoin
//
//	@doc:
//		Construct a merge join operator
//
//---------------------------------------------------------------------------
CDXLPhysical *
CDXLOperatorFactory::MakeDXLMergeJoin(CDXLMemoryManager *dxl_memory_manager,
									  const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	const XMLCh *join_type_xml =
		ExtractAttrValue(attrs, EdxltokenJoinType, EdxltokenPhysicalMergeJoin);

	EdxlJoinType join_type = ParseJoinType(
		join_type_xml, CDXLTokens::GetDXLTokenStr(EdxltokenPhysicalMergeJoin));

	BOOL is_unique_outer = ExtractConvertAttrValueToBool(
		dxl_memory_manager, attrs, EdxltokenMergeJoinUniqueOuter,
		EdxltokenPhysicalMergeJoin);

	return GPOS_NEW(mp) CDXLPhysicalMergeJoin(mp, join_type, is_unique_outer);
}

//		Construct a gather motion operator
CDXLPhysical *
CDXLOperatorFactory::MakeDXLGatherMotion(CDXLMemoryManager *dxl_memory_manager,
										 const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	CDXLPhysicalGatherMotion *dxl_op =
		GPOS_NEW(mp) CDXLPhysicalGatherMotion(mp);
	SetSegmentInfo(dxl_memory_manager, dxl_op, attrs,
				   EdxltokenPhysicalGatherMotion);

	return dxl_op;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLBroadcastMotion
//
//	@doc:
//		Construct a broadcast motion operator
//
//---------------------------------------------------------------------------
CDXLPhysical *
CDXLOperatorFactory::MakeDXLBroadcastMotion(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	CDXLPhysicalBroadcastMotion *dxl_op =
		GPOS_NEW(mp) CDXLPhysicalBroadcastMotion(mp);
	SetSegmentInfo(dxl_memory_manager, dxl_op, attrs,
				   EdxltokenPhysicalBroadcastMotion);

	return dxl_op;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLRedistributeMotion
//
//	@doc:
//		Construct a redistribute motion operator
//
//---------------------------------------------------------------------------
CDXLPhysical *
CDXLOperatorFactory::MakeDXLRedistributeMotion(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	BOOL is_duplicate_sensitive = false;

	const XMLCh *duplicate_sensitive_xml =
		attrs.getValue(CDXLTokens::XmlstrToken(EdxltokenDuplicateSensitive));
	if (nullptr != duplicate_sensitive_xml)
	{
		is_duplicate_sensitive = ConvertAttrValueToBool(
			dxl_memory_manager, duplicate_sensitive_xml,
			EdxltokenDuplicateSensitive, EdxltokenPhysicalRedistributeMotion);
	}

	CDXLPhysicalRedistributeMotion *dxl_op =
		GPOS_NEW(mp) CDXLPhysicalRedistributeMotion(mp, is_duplicate_sensitive);
	SetSegmentInfo(dxl_memory_manager, dxl_op, attrs,
				   EdxltokenPhysicalRedistributeMotion);

	return dxl_op;
}


//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLRoutedMotion
//
//	@doc:
//		Construct a routed motion operator
//
//---------------------------------------------------------------------------
CDXLPhysical *
CDXLOperatorFactory::MakeDXLRoutedMotion(CDXLMemoryManager *dxl_memory_manager,
										 const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	ULONG segment_colid = CDXLOperatorFactory::ExtractConvertAttrValueToUlong(
		dxl_memory_manager, attrs, EdxltokenSegmentIdCol,
		EdxltokenPhysicalRoutedDistributeMotion);

	CDXLPhysicalRoutedDistributeMotion *dxl_op =
		GPOS_NEW(mp) CDXLPhysicalRoutedDistributeMotion(mp, segment_colid);
	SetSegmentInfo(dxl_memory_manager, dxl_op, attrs,
				   EdxltokenPhysicalRoutedDistributeMotion);

	return dxl_op;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLRandomMotion
//
//	@doc:
//		Construct a random motion operator
//
//---------------------------------------------------------------------------
CDXLPhysical *
CDXLOperatorFactory::MakeDXLRandomMotion(CDXLMemoryManager *dxl_memory_manager,
										 const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	BOOL is_duplicate_sensitive = false;

	const XMLCh *duplicate_sensitive_xml =
		attrs.getValue(CDXLTokens::XmlstrToken(EdxltokenDuplicateSensitive));
	if (nullptr != duplicate_sensitive_xml)
	{
		is_duplicate_sensitive = ConvertAttrValueToBool(
			dxl_memory_manager, duplicate_sensitive_xml,
			EdxltokenDuplicateSensitive, EdxltokenPhysicalRandomMotion);
	}

	CDXLPhysicalRandomMotion *dxl_op =
		GPOS_NEW(mp) CDXLPhysicalRandomMotion(mp, is_duplicate_sensitive);
	SetSegmentInfo(dxl_memory_manager, dxl_op, attrs,
				   EdxltokenPhysicalRandomMotion);

	return dxl_op;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLAppend
//	@doc:
//		Construct an Append operator
//
//---------------------------------------------------------------------------
CDXLPhysical *
CDXLOperatorFactory::MakeDXLAppend(CDXLMemoryManager *dxl_memory_manager,
								   const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	BOOL is_target = ExtractConvertAttrValueToBool(dxl_memory_manager, attrs,
												   EdxltokenAppendIsTarget,
												   EdxltokenPhysicalAppend);

	BOOL is_zapped = ExtractConvertAttrValueToBool(dxl_memory_manager, attrs,
												   EdxltokenAppendIsZapped,
												   EdxltokenPhysicalAppend);

	ULONG scan_id = ExtractConvertAttrValueToUlong(
		dxl_memory_manager, attrs, EdxltokenPartIndexId,
		EdxltokenPhysicalAppend, true /* is_optional */,
		gpos::ulong_max /* default_value */);

	ULongPtrArray *selector_ids = nullptr;
	if (scan_id != gpos::ulong_max)
	{
		selector_ids = ExtractConvertValuesToArray(dxl_memory_manager, attrs,
												   EdxltokenSelectorIds,
												   EdxltokenPhysicalAppend);
	}

	return GPOS_NEW(mp) CDXLPhysicalAppend(mp, is_target, is_zapped, scan_id,
										   nullptr, selector_ids);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLLimit
//	@doc:
//		Construct a Limit operator
//
//---------------------------------------------------------------------------
CDXLPhysical *
CDXLOperatorFactory::MakeDXLLimit(CDXLMemoryManager *dxl_memory_manager,
								  const Attributes &  // attrs
)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	return GPOS_NEW(mp) CDXLPhysicalLimit(mp);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLLimitCount
//
//	@doc:
//		Construct a Limit Count operator
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLLimitCount(CDXLMemoryManager *dxl_memory_manager,
									   const Attributes &  // attrs
)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	return GPOS_NEW(mp) CDXLScalarLimitCount(mp);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLLimitOffset
//
//	@doc:
//		Construct a Limit Offset operator
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLLimitOffset(CDXLMemoryManager *dxl_memory_manager,
										const Attributes &	// attrs
)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	return GPOS_NEW(mp) CDXLScalarLimitOffset(mp);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLAgg
//
//	@doc:
//		Construct an aggregate operator
//
//---------------------------------------------------------------------------
CDXLPhysical *
CDXLOperatorFactory::MakeDXLAgg(CDXLMemoryManager *dxl_memory_manager,
								const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	const XMLCh *agg_strategy_xml = ExtractAttrValue(
		attrs, EdxltokenAggStrategy, EdxltokenPhysicalAggregate);

	EdxlAggStrategy dxl_agg_strategy = EdxlaggstrategySentinel;

	if (0 == XMLString::compareString(
				 CDXLTokens::XmlstrToken(EdxltokenAggStrategyPlain),
				 agg_strategy_xml))
	{
		dxl_agg_strategy = EdxlaggstrategyPlain;
	}
	else if (0 == XMLString::compareString(
					  CDXLTokens::XmlstrToken(EdxltokenAggStrategySorted),
					  agg_strategy_xml))
	{
		dxl_agg_strategy = EdxlaggstrategySorted;
	}
	else if (0 == XMLString::compareString(
					  CDXLTokens::XmlstrToken(EdxltokenAggStrategyHashed),
					  agg_strategy_xml))
	{
		dxl_agg_strategy = EdxlaggstrategyHashed;
	}
	else
	{
		GPOS_RAISE(
			gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
			CDXLTokens::GetDXLTokenStr(EdxltokenAggStrategy)->GetBuffer(),
			CDXLTokens::GetDXLTokenStr(EdxltokenPhysicalAggregate)
				->GetBuffer());
	}

	BOOL stream_safe = false;

	const XMLCh *stream_safe_xml =
		attrs.getValue(CDXLTokens::XmlstrToken(EdxltokenAggStreamSafe));
	if (nullptr != stream_safe_xml)
	{
		stream_safe = ConvertAttrValueToBool(
			dxl_memory_manager, stream_safe_xml, EdxltokenAggStreamSafe,
			EdxltokenPhysicalAggregate);
	}

	return GPOS_NEW(mp) CDXLPhysicalAgg(mp, dxl_agg_strategy, stream_safe);
}


//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLSort
//
//	@doc:
//		Construct a sort operator
//
//---------------------------------------------------------------------------
CDXLPhysical *
CDXLOperatorFactory::MakeDXLSort(CDXLMemoryManager *dxl_memory_manager,
								 const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// parse discard duplicates and nulls first properties from the attributes
	BOOL discard_duplicates = ExtractConvertAttrValueToBool(
		dxl_memory_manager, attrs, EdxltokenSortDiscardDuplicates,
		EdxltokenPhysicalSort);

	return GPOS_NEW(mp) CDXLPhysicalSort(mp, discard_duplicates);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLMaterialize
//
//	@doc:
//		Construct a materialize operator
//
//---------------------------------------------------------------------------
CDXLPhysical *
CDXLOperatorFactory::MakeDXLMaterialize(CDXLMemoryManager *dxl_memory_manager,
										const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// parse spooling info from the attributes

	CDXLPhysicalMaterialize *materialize_dxlnode = nullptr;

	// is this a multi-slice spool
	BOOL eager_materialize = ExtractConvertAttrValueToBool(
		dxl_memory_manager, attrs, EdxltokenMaterializeEager,
		EdxltokenPhysicalMaterialize);

	if (1 == attrs.getLength())
	{
		// no spooling info specified -> create a non-spooling materialize operator
		materialize_dxlnode =
			GPOS_NEW(mp) CDXLPhysicalMaterialize(mp, eager_materialize);
	}
	else
	{
		// parse spool id
		ULONG spool_id = ExtractConvertAttrValueToUlong(
			dxl_memory_manager, attrs, EdxltokenSpoolId,
			EdxltokenPhysicalMaterialize);

		// parse id of executor slice
		INT executor_slice = ExtractConvertAttrValueToInt(
			dxl_memory_manager, attrs, EdxltokenExecutorSliceId,
			EdxltokenPhysicalMaterialize);

		ULONG num_consumer_slices = ExtractConvertAttrValueToUlong(
			dxl_memory_manager, attrs, EdxltokenConsumerSliceCount,
			EdxltokenPhysicalMaterialize);

		materialize_dxlnode = GPOS_NEW(mp)
			CDXLPhysicalMaterialize(mp, eager_materialize, spool_id,
									executor_slice, num_consumer_slices);
	}

	return materialize_dxlnode;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLScalarCmp
//
//	@doc:
//		Construct a scalar comparison operator
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLScalarCmp(CDXLMemoryManager *dxl_memory_manager,
									  const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// get comparison operator from attributes
	const XMLCh *scalar_cmp_xml =
		ExtractAttrValue(attrs, EdxltokenComparisonOp, EdxltokenScalarComp);

	// parse op no and function id
	IMDId *op_id = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenOpNo, EdxltokenScalarComp);

	// parse comparison operator from string
	CWStringDynamic *comp_op_name =
		CDXLUtils::CreateDynamicStringFromXMLChArray(dxl_memory_manager,
													 scalar_cmp_xml);

	// copy dynamic string into const string
	CWStringConst *comp_op_name_copy =
		GPOS_NEW(mp) CWStringConst(mp, comp_op_name->GetBuffer());

	// cleanup
	GPOS_DELETE(comp_op_name);

	return GPOS_NEW(mp) CDXLScalarComp(mp, op_id, comp_op_name_copy);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLDistinctCmp
//
//	@doc:
//		Construct a scalar distinct comparison operator
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLDistinctCmp(CDXLMemoryManager *dxl_memory_manager,
										const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// parse operator and function id
	IMDId *op_id = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenOpNo, EdxltokenScalarDistinctComp);

	return GPOS_NEW(mp) CDXLScalarDistinctComp(mp, op_id);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLOpExpr
//
//	@doc:
//		Construct a scalar OpExpr
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLOpExpr(CDXLMemoryManager *dxl_memory_manager,
								   const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// get scalar OpExpr from attributes
	const XMLCh *op_expr_xml =
		ExtractAttrValue(attrs, EdxltokenOpName, EdxltokenScalarOpExpr);

	IMDId *op_id = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenOpNo, EdxltokenScalarOpExpr);

	IMDId *return_type_mdid = nullptr;
	const XMLCh *return_type_xml =
		attrs.getValue(CDXLTokens::XmlstrToken(EdxltokenOpType));

	if (nullptr != return_type_xml)
	{
		return_type_mdid = ExtractConvertAttrValueToMdId(
			dxl_memory_manager, attrs, EdxltokenOpType, EdxltokenScalarOpExpr);
	}

	CWStringDynamic *value = CDXLUtils::CreateDynamicStringFromXMLChArray(
		dxl_memory_manager, op_expr_xml);
	CWStringConst *value_copy =
		GPOS_NEW(mp) CWStringConst(mp, value->GetBuffer());
	GPOS_DELETE(value);

	return GPOS_NEW(mp)
		CDXLScalarOpExpr(mp, op_id, return_type_mdid, value_copy);
}


//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLArrayComp
//
//	@doc:
//		Construct a scalar array comparison
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLArrayComp(CDXLMemoryManager *dxl_memory_manager,
									  const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// get attributes
	const XMLCh *op_expr_xml =
		ExtractAttrValue(attrs, EdxltokenOpName, EdxltokenScalarArrayComp);

	const XMLCh *op_type_xml =
		ExtractAttrValue(attrs, EdxltokenOpType, EdxltokenScalarArrayComp);

	// parse operator no and function id
	IMDId *op_id = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenOpNo, EdxltokenScalarArrayComp);

	EdxlArrayCompType array_comp_type = Edxlarraycomptypeany;

	if (0 == XMLString::compareString(
				 CDXLTokens::XmlstrToken(EdxltokenOpTypeAll), op_type_xml))
	{
		array_comp_type = Edxlarraycomptypeall;
	}
	else if (0 != XMLString::compareString(
					  CDXLTokens::XmlstrToken(EdxltokenOpTypeAny), op_type_xml))
	{
		GPOS_RAISE(
			gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
			CDXLTokens::GetDXLTokenStr(EdxltokenOpType)->GetBuffer(),
			CDXLTokens::GetDXLTokenStr(EdxltokenScalarArrayComp)->GetBuffer());
	}

	CWStringDynamic *opname = CDXLUtils::CreateDynamicStringFromXMLChArray(
		dxl_memory_manager, op_expr_xml);
	CWStringConst *opname_copy =
		GPOS_NEW(mp) CWStringConst(mp, opname->GetBuffer());
	GPOS_DELETE(opname);

	return GPOS_NEW(mp)
		CDXLScalarArrayComp(mp, op_id, opname_copy, array_comp_type);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLBoolExpr
//
//	@doc:
//		Construct a scalar BoolExpr
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLBoolExpr(CDXLMemoryManager *dxl_memory_manager,
									 const EdxlBoolExprType edxlboolexprType)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	return GPOS_NEW(mp) CDXLScalarBoolExpr(mp, edxlboolexprType);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLBooleanTest
//
//	@doc:
//		Construct a scalar BooleanTest
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLBooleanTest(
	CDXLMemoryManager *dxl_memory_manager,
	const EdxlBooleanTestType edxlbooleantesttype)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	return GPOS_NEW(mp) CDXLScalarBooleanTest(mp, edxlbooleantesttype);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLSubPlan
//
//	@doc:
//		Construct a SubPlan node
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLSubPlan(CDXLMemoryManager *dxl_memory_manager,
									IMDId *mdid,
									CDXLColRefArray *dxl_colref_array,
									EdxlSubPlanType dxl_subplan_type,
									CDXLNode *dxlnode_test_expr)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	return GPOS_NEW(mp) CDXLScalarSubPlan(mp, mdid, dxl_colref_array,
										  dxl_subplan_type, dxlnode_test_expr);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLNullTest
//
//	@doc:
//		Construct a scalar NullTest
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLNullTest(CDXLMemoryManager *dxl_memory_manager,
									 const BOOL is_null)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	return GPOS_NEW(mp) CDXLScalarNullTest(mp, is_null);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLCast
//
//	@doc:
//		Construct a scalar RelabelType
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLCast(CDXLMemoryManager *dxl_memory_manager,
								 const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// parse type id and function id
	IMDId *mdid_type = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenTypeId, EdxltokenScalarCast);

	IMDId *mdid_func = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenFuncId, EdxltokenScalarCast);

	return GPOS_NEW(mp) CDXLScalarCast(mp, mdid_type, mdid_func);
}


//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLCoerceToDomain
//
//	@doc:
//		Construct a scalar coerce
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLCoerceToDomain(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// parse type id and function id
	IMDId *mdid_type = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenTypeId,
		EdxltokenScalarCoerceToDomain);
	INT type_modifier = ExtractConvertAttrValueToInt(
		dxl_memory_manager, attrs, EdxltokenTypeMod,
		EdxltokenScalarCoerceToDomain, true, default_type_modifier);
	ULONG coercion_form = ExtractConvertAttrValueToUlong(
		dxl_memory_manager, attrs, EdxltokenCoercionForm,
		EdxltokenScalarCoerceToDomain);
	INT location = ExtractConvertAttrValueToInt(dxl_memory_manager, attrs,
												EdxltokenLocation,
												EdxltokenScalarCoerceToDomain);

	return GPOS_NEW(mp)
		CDXLScalarCoerceToDomain(mp, mdid_type, type_modifier,
								 (EdxlCoercionForm) coercion_form, location);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLCoerceViaIO
//
//	@doc:
//		Construct a scalar coerce
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLCoerceViaIO(CDXLMemoryManager *dxl_memory_manager,
										const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// parse type id and function id
	IMDId *mdid_type = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenTypeId, EdxltokenScalarCoerceViaIO);
	INT type_modifier = ExtractConvertAttrValueToInt(
		dxl_memory_manager, attrs, EdxltokenTypeMod, EdxltokenScalarCoerceViaIO,
		true, default_type_modifier);
	ULONG coercion_form = ExtractConvertAttrValueToUlong(
		dxl_memory_manager, attrs, EdxltokenCoercionForm,
		EdxltokenScalarCoerceViaIO);
	INT location = ExtractConvertAttrValueToInt(dxl_memory_manager, attrs,
												EdxltokenLocation,
												EdxltokenScalarCoerceViaIO);

	return GPOS_NEW(mp)
		CDXLScalarCoerceViaIO(mp, mdid_type, type_modifier,
							  (EdxlCoercionForm) coercion_form, location);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLArrayCoerceExpr
//
//	@doc:
//		Construct a scalar array coerce expression
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLArrayCoerceExpr(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs)
{
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	IMDId *element_func = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenElementFunc,
		EdxltokenScalarArrayCoerceExpr);
	IMDId *mdid_type = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenTypeId,
		EdxltokenScalarArrayCoerceExpr);
	INT type_modifier = ExtractConvertAttrValueToInt(
		dxl_memory_manager, attrs, EdxltokenTypeMod,
		EdxltokenScalarArrayCoerceExpr, true, default_type_modifier);
	BOOL is_explicit = ExtractConvertAttrValueToBool(
		dxl_memory_manager, attrs, EdxltokenIsExplicit,
		EdxltokenScalarArrayCoerceExpr);
	ULONG coercion_form = ExtractConvertAttrValueToUlong(
		dxl_memory_manager, attrs, EdxltokenCoercionForm,
		EdxltokenScalarArrayCoerceExpr);
	INT location = ExtractConvertAttrValueToInt(dxl_memory_manager, attrs,
												EdxltokenLocation,
												EdxltokenScalarArrayCoerceExpr);

	return GPOS_NEW(mp) CDXLScalarArrayCoerceExpr(
		mp, element_func, mdid_type, type_modifier, is_explicit,
		(EdxlCoercionForm) coercion_form, location);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLConstValue
//
//	@doc:
//		Construct a scalar Const
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLConstValue(CDXLMemoryManager *dxl_memory_manager,
									   const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();
	CDXLDatum *dxl_datum =
		GetDatumVal(dxl_memory_manager, attrs, EdxltokenScalarConstValue);

	return GPOS_NEW(mp) CDXLScalarConstValue(mp, dxl_datum);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLIfStmt
//
//	@doc:
//		Construct an if statement operator
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLIfStmt(CDXLMemoryManager *dxl_memory_manager,
								   const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// get the type id
	IMDId *mdid_type = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenTypeId, EdxltokenScalarIfStmt);

	return GPOS_NEW(mp) CDXLScalarIfStmt(mp, mdid_type);
}


//		Construct an funcexpr operator
CDXLScalar *
CDXLOperatorFactory::MakeDXLFuncExpr(CDXLMemoryManager *dxl_memory_manager,
									 const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	IMDId *mdid_func = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenFuncId, EdxltokenScalarFuncExpr);

	BOOL is_retset = ExtractConvertAttrValueToBool(dxl_memory_manager, attrs,
												   EdxltokenFuncRetSet,
												   EdxltokenScalarFuncExpr);

	IMDId *mdid_return_type = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenTypeId, EdxltokenScalarFuncExpr);

	INT type_modifier = ExtractConvertAttrValueToInt(
		dxl_memory_manager, attrs, EdxltokenTypeMod, EdxltokenScalarCast, true,
		default_type_modifier);

	return GPOS_NEW(mp) CDXLScalarFuncExpr(mp, mdid_func, mdid_return_type,
										   type_modifier, is_retset);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLAggFunc
//
//	@doc:
//		Construct an AggRef operator
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLAggFunc(CDXLMemoryManager *dxl_memory_manager,
									const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	IMDId *agg_mdid = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenAggrefOid, EdxltokenScalarAggref);

	const XMLCh *agg_stage_xml =
		ExtractAttrValue(attrs, EdxltokenAggrefStage, EdxltokenScalarAggref);

	BOOL is_distinct = ExtractConvertAttrValueToBool(dxl_memory_manager, attrs,
													 EdxltokenAggrefDistinct,
													 EdxltokenScalarAggref);

	const XMLCh *agg_kind_xml =
		ExtractAttrValue(attrs, EdxltokenAggrefKind, EdxltokenScalarAggref);

	ULongPtrArray *argtypelist = ExtractConvertValuesToArray(
		dxl_memory_manager, attrs, EdxltokenAggrefArgTypes,
		EdxltokenScalarAggref);

	EdxlAggrefStage agg_stage = EdxlaggstageFinal;

	if (0 ==
		XMLString::compareString(
			CDXLTokens::XmlstrToken(EdxltokenAggrefStageNormal), agg_stage_xml))
	{
		agg_stage = EdxlaggstageNormal;
	}
	else if (0 == XMLString::compareString(
					  CDXLTokens::XmlstrToken(EdxltokenAggrefStagePartial),
					  agg_stage_xml))
	{
		agg_stage = EdxlaggstagePartial;
	}
	else if (0 == XMLString::compareString(
					  CDXLTokens::XmlstrToken(EdxltokenAggrefStageIntermediate),
					  agg_stage_xml))
	{
		agg_stage = EdxlaggstageIntermediate;
	}
	else if (0 == XMLString::compareString(
					  CDXLTokens::XmlstrToken(EdxltokenAggrefStageFinal),
					  agg_stage_xml))
	{
		agg_stage = EdxlaggstageFinal;
	}
	else
	{
		// turn Xerces exception in optimizer exception
		GPOS_RAISE(
			gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
			CDXLTokens::GetDXLTokenStr(EdxltokenAggrefStage)->GetBuffer(),
			CDXLTokens::GetDXLTokenStr(EdxltokenScalarAggref)->GetBuffer());
	}

	EdxlAggrefKind agg_kind = EdxlaggkindNormal;
	if (0 ==
		XMLString::compareString(
			CDXLTokens::XmlstrToken(EdxltokenAggrefKindNormal), agg_kind_xml))
	{
		agg_kind = EdxlaggkindNormal;
	}
	else if (0 == XMLString::compareString(
					  CDXLTokens::XmlstrToken(EdxltokenAggrefKindOrderedSet),
					  agg_kind_xml))
	{
		agg_kind = EdxlaggkindOrderedSet;
	}
	else if (0 == XMLString::compareString(
					  CDXLTokens::XmlstrToken(EdxltokenAggrefKindHypothetical),
					  agg_kind_xml))
	{
		agg_kind = EdxlaggkindHypothetical;
	}
	else
	{
		// turn Xerces exception in optimizer exception
		GPOS_RAISE(
			gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
			CDXLTokens::GetDXLTokenStr(EdxltokenAggrefKind)->GetBuffer(),
			CDXLTokens::GetDXLTokenStr(EdxltokenScalarAggref)->GetBuffer());
	}

	IMDId *resolved_rettype = nullptr;
	const XMLCh *return_type_xml =
		attrs.getValue(CDXLTokens::XmlstrToken(EdxltokenTypeId));
	if (nullptr != return_type_xml)
	{
		resolved_rettype = ExtractConvertAttrValueToMdId(
			dxl_memory_manager, attrs, EdxltokenTypeId, EdxltokenScalarAggref);
	}

	return GPOS_NEW(mp)
		CDXLScalarAggref(mp, agg_mdid, resolved_rettype, is_distinct, agg_stage,
						 agg_kind, argtypelist);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ParseDXLFrameBoundary
//
//	@doc:
//		Parse the frame boundary
//
//---------------------------------------------------------------------------
EdxlFrameBoundary
CDXLOperatorFactory::ParseDXLFrameBoundary(const Attributes &attrs,
										   Edxltoken token_type)
{
	const XMLCh *frame_boundary_xml =
		ExtractAttrValue(attrs, token_type, EdxltokenWindowFrame);

	EdxlFrameBoundary frame_boundary = EdxlfbSentinel;
	ULONG window_frame_boundary_to_frame_boundary_mapping[][2] = {
		{EdxlfbUnboundedPreceding, EdxltokenWindowBoundaryUnboundedPreceding},
		{EdxlfbBoundedPreceding, EdxltokenWindowBoundaryBoundedPreceding},
		{EdxlfbCurrentRow, EdxltokenWindowBoundaryCurrentRow},
		{EdxlfbUnboundedFollowing, EdxltokenWindowBoundaryUnboundedFollowing},
		{EdxlfbBoundedFollowing, EdxltokenWindowBoundaryBoundedFollowing},
		{EdxlfbDelayedBoundedPreceding,
		 EdxltokenWindowBoundaryDelayedBoundedPreceding},
		{EdxlfbDelayedBoundedFollowing,
		 EdxltokenWindowBoundaryDelayedBoundedFollowing}};

	const ULONG arity =
		GPOS_ARRAY_SIZE(window_frame_boundary_to_frame_boundary_mapping);
	for (ULONG ul = 0; ul < arity; ul++)
	{
		ULONG *current = window_frame_boundary_to_frame_boundary_mapping[ul];
		Edxltoken current_window = (Edxltoken) current[1];
		if (0 ==
			XMLString::compareString(CDXLTokens::XmlstrToken(current_window),
									 frame_boundary_xml))
		{
			frame_boundary = (EdxlFrameBoundary) current[0];
			break;
		}
	}

	if (EdxlfbSentinel == frame_boundary)
	{
		// turn Xerces exception in optimizer exception
		GPOS_RAISE(
			gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
			CDXLTokens::GetDXLTokenStr(token_type)->GetBuffer(),
			CDXLTokens::GetDXLTokenStr(EdxltokenWindowFrame)->GetBuffer());
	}

	return frame_boundary;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ParseDXLFrameSpec
//
//	@doc:
//		Parse the frame specification
//
//---------------------------------------------------------------------------
EdxlFrameSpec
CDXLOperatorFactory::ParseDXLFrameSpec(const Attributes &attrs)
{
	const XMLCh *frame_spec_xml =
		ExtractAttrValue(attrs, EdxltokenWindowFrameSpec, EdxltokenWindowFrame);

	EdxlFrameSpec frame_spec = EdxlfsSentinel;
	if (0 == XMLString::compareString(
				 CDXLTokens::XmlstrToken(EdxltokenWindowFSRow), frame_spec_xml))
	{
		frame_spec = EdxlfsRow;
	}
	else if (0 == XMLString::compareString(
					  CDXLTokens::XmlstrToken(EdxltokenWindowFSRange),
					  frame_spec_xml))
	{
		frame_spec = EdxlfsRange;
	}
	else
	{
		// turn Xerces exception in optimizer exception
		GPOS_RAISE(
			gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
			CDXLTokens::GetDXLTokenStr(EdxltokenWindowFrameSpec)->GetBuffer(),
			CDXLTokens::GetDXLTokenStr(EdxltokenWindowFrame)->GetBuffer());
	}

	return frame_spec;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ParseFrameExclusionStrategy
//
//	@doc:
//		Parse the frame exclusion strategy
//
//---------------------------------------------------------------------------
EdxlFrameExclusionStrategy
CDXLOperatorFactory::ParseFrameExclusionStrategy(const Attributes &attrs)
{
	const XMLCh *frame_exc_strategy_xml = ExtractAttrValue(
		attrs, EdxltokenWindowExclusionStrategy, EdxltokenWindowFrame);

	ULONG window_frame_boundary_to_frame_boundary_mapping[][2] = {
		{EdxlfesNone, EdxltokenWindowESNone},
		{EdxlfesNulls, EdxltokenWindowESNulls},
		{EdxlfesCurrentRow, EdxltokenWindowESCurrentRow},
		{EdxlfesGroup, EdxltokenWindowESGroup},
		{EdxlfesTies, EdxltokenWindowESTies}};

	EdxlFrameExclusionStrategy frame_exc_strategy = EdxlfesSentinel;
	const ULONG arity =
		GPOS_ARRAY_SIZE(window_frame_boundary_to_frame_boundary_mapping);
	for (ULONG ul = 0; ul < arity; ul++)
	{
		ULONG *current = window_frame_boundary_to_frame_boundary_mapping[ul];
		Edxltoken current_window = (Edxltoken) current[1];
		if (0 ==
			XMLString::compareString(CDXLTokens::XmlstrToken(current_window),
									 frame_exc_strategy_xml))
		{
			frame_exc_strategy = (EdxlFrameExclusionStrategy) current[0];
			break;
		}
	}

	if (EdxlfesSentinel == frame_exc_strategy)
	{
		// turn Xerces exception in optimizer exception
		GPOS_RAISE(
			gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
			CDXLTokens::GetDXLTokenStr(EdxltokenWindowExclusionStrategy)
				->GetBuffer(),
			CDXLTokens::GetDXLTokenStr(EdxltokenWindowFrame)->GetBuffer());
	}

	return frame_exc_strategy;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLArray
//
//	@doc:
//		Construct an array operator
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLArray(CDXLMemoryManager *dxl_memory_manager,
								  const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	IMDId *elem_type_mdid = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenArrayElementType,
		EdxltokenScalarArray);
	IMDId *array_type_mdid = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenArrayType, EdxltokenScalarArray);
	BOOL is_multidimenstional = ExtractConvertAttrValueToBool(
		dxl_memory_manager, attrs, EdxltokenArrayMultiDim,
		EdxltokenScalarArray);

	return GPOS_NEW(mp) CDXLScalarArray(mp, elem_type_mdid, array_type_mdid,
										is_multidimenstional);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLScalarIdent
//
//	@doc:
//		Construct a scalar identifier operator
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLScalarIdent(CDXLMemoryManager *dxl_memory_manager,
										const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	CDXLColRef *dxl_colref =
		MakeDXLColRef(dxl_memory_manager, attrs, EdxltokenScalarIdent);

	return GPOS_NEW(mp) CDXLScalarIdent(mp, dxl_colref);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLProjElem
//
//	@doc:
//		Construct a proj elem operator
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLProjElem(CDXLMemoryManager *dxl_memory_manager,
									 const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// parse alias from attributes
	const XMLCh *xml_alias =
		ExtractAttrValue(attrs, EdxltokenAlias, EdxltokenScalarProjElem);

	// parse column id
	ULONG id = ExtractConvertAttrValueToUlong(
		dxl_memory_manager, attrs, EdxltokenColId, EdxltokenScalarProjElem);

	CWStringDynamic *alias = CDXLUtils::CreateDynamicStringFromXMLChArray(
		dxl_memory_manager, xml_alias);

	// create a copy of the string in the CMDName constructor
	CMDName *mdname = GPOS_NEW(mp) CMDName(mp, alias);

	GPOS_DELETE(alias);

	return GPOS_NEW(mp) CDXLScalarProjElem(mp, id, mdname);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLHashExpr
//
//	@doc:
//		Construct a hash expr operator
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLHashExpr(CDXLMemoryManager *dxl_memory_manager,
									 const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// get column type id and type name from attributes

	IMDId *mdid_type = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenOpfamily, EdxltokenScalarHashExpr,
		true /* is_optional */, nullptr /* default_val */
	);

	return GPOS_NEW(mp) CDXLScalarHashExpr(mp, mdid_type);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLSortCol
//
//	@doc:
//		Construct a sorting column description
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeDXLSortCol(CDXLMemoryManager *dxl_memory_manager,
									const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// get column id from attributes
	ULONG colid = ExtractConvertAttrValueToUlong(
		dxl_memory_manager, attrs, EdxltokenColId, EdxltokenScalarSortCol);

	// get sorting operator name
	const XMLCh *sort_op_xml =
		ExtractAttrValue(attrs, EdxltokenSortOpName, EdxltokenScalarSortCol);
	CWStringDynamic *sort_op_name =
		CDXLUtils::CreateDynamicStringFromXMLChArray(dxl_memory_manager,
													 sort_op_xml);

	// get null first property
	BOOL nulls_first = ExtractConvertAttrValueToBool(dxl_memory_manager, attrs,
													 EdxltokenSortNullsFirst,
													 EdxltokenPhysicalSort);

	// parse sorting operator id
	IMDId *sort_op_id = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenSortOpId, EdxltokenPhysicalSort);

	// copy dynamic string into const string
	CWStringConst *sort_op_name_copy =
		GPOS_NEW(mp) CWStringConst(mp, sort_op_name->GetBuffer());

	GPOS_DELETE(sort_op_name);

	return GPOS_NEW(mp) CDXLScalarSortCol(mp, colid, sort_op_id,
										  sort_op_name_copy, nulls_first);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLOperatorCost
//
//	@doc:
//		Construct a cost estimates element
//
//---------------------------------------------------------------------------
CDXLOperatorCost *
CDXLOperatorFactory::MakeDXLOperatorCost(CDXLMemoryManager *dxl_memory_manager,
										 const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	const XMLCh *startup_cost_xml =
		ExtractAttrValue(attrs, EdxltokenStartupCost, EdxltokenCost);

	const XMLCh *total_cost_xml =
		ExtractAttrValue(attrs, EdxltokenTotalCost, EdxltokenCost);

	const XMLCh *rows_xml =
		ExtractAttrValue(attrs, EdxltokenRows, EdxltokenCost);

	const XMLCh *width_xml =
		ExtractAttrValue(attrs, EdxltokenWidth, EdxltokenCost);

	CWStringDynamic *startup_cost_str =
		CDXLUtils::CreateDynamicStringFromXMLChArray(dxl_memory_manager,
													 startup_cost_xml);
	CWStringDynamic *total_cost_str =
		CDXLUtils::CreateDynamicStringFromXMLChArray(dxl_memory_manager,
													 total_cost_xml);
	CWStringDynamic *rows_out_str =
		CDXLUtils::CreateDynamicStringFromXMLChArray(dxl_memory_manager,
													 rows_xml);
	CWStringDynamic *width_str = CDXLUtils::CreateDynamicStringFromXMLChArray(
		dxl_memory_manager, width_xml);

	return GPOS_NEW(mp) CDXLOperatorCost(startup_cost_str, total_cost_str,
										 rows_out_str, width_str);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLTableDescr
//
//	@doc:
//		Construct a table descriptor
//
//---------------------------------------------------------------------------
CDXLTableDescr *
CDXLOperatorFactory::MakeDXLTableDescr(CDXLMemoryManager *dxl_memory_manager,
									   const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// parse table descriptor from attributes
	const XMLCh *xml_str_table_name =
		ExtractAttrValue(attrs, EdxltokenTableName, EdxltokenTableDescr);

	CMDName *mdname = CDXLUtils::CreateMDNameFromXMLChar(dxl_memory_manager,
														 xml_str_table_name);

	// parse metadata id
	IMDId *mdid = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenMdid, EdxltokenTableDescr);

	// parse execute as user value if the attribute is specified
	ULONG user_id = GPDXL_DEFAULT_USERID;
	const XMLCh *execute_as_user_xml =
		attrs.getValue(CDXLTokens::XmlstrToken(EdxltokenExecuteAsUser));

	INT lockmode = ExtractConvertAttrValueToInt(
		dxl_memory_manager, attrs, EdxltokenLockMode, EdxltokenTableDescr,
		true /* is_optional */, -1);

	if (nullptr != execute_as_user_xml)
	{
		user_id = ConvertAttrValueToUlong(
			dxl_memory_manager, execute_as_user_xml, EdxltokenExecuteAsUser,
			EdxltokenTableDescr);
	}

	return GPOS_NEW(mp) CDXLTableDescr(mp, mdid, mdname, user_id, lockmode);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLIndexDescr
//
//	@doc:
//		Construct an index descriptor
//
//---------------------------------------------------------------------------
CDXLIndexDescr *
CDXLOperatorFactory::MakeDXLIndexDescr(CDXLMemoryManager *dxl_memory_manager,
									   const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// parse index descriptor from attributes
	const XMLCh *index_name_xml =
		ExtractAttrValue(attrs, EdxltokenIndexName, EdxltokenIndexDescr);

	CWStringDynamic *index_name = CDXLUtils::CreateDynamicStringFromXMLChArray(
		dxl_memory_manager, index_name_xml);

	// parse metadata id
	IMDId *mdid = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenMdid, EdxltokenIndexDescr);

	// create a copy of the string in the CMDName constructor
	CMDName *mdname = GPOS_NEW(mp) CMDName(mp, index_name);
	GPOS_DELETE(index_name);

	return GPOS_NEW(mp) CDXLIndexDescr(mdid, mdname);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeColumnDescr
//
//	@doc:
//		Construct a column descriptor
//
//---------------------------------------------------------------------------
CDXLColDescr *
CDXLOperatorFactory::MakeColumnDescr(CDXLMemoryManager *dxl_memory_manager,
									 const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// parse column name from attributes
	const XMLCh *column_name_xml =
		ExtractAttrValue(attrs, EdxltokenColName, EdxltokenColDescr);

	// parse column id
	ULONG id = ExtractConvertAttrValueToUlong(
		dxl_memory_manager, attrs, EdxltokenColId, EdxltokenColDescr);

	// parse attno
	INT attno = ExtractConvertAttrValueToInt(dxl_memory_manager, attrs,
											 EdxltokenAttno, EdxltokenColDescr);

	if (0 == attno)
	{
		GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
				   CDXLTokens::GetDXLTokenStr(EdxltokenAttno)->GetBuffer(),
				   CDXLTokens::GetDXLTokenStr(EdxltokenColDescr)->GetBuffer());
	}

	// parse column type id
	IMDId *mdid_type = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenTypeId, EdxltokenColDescr);

	// parse optional type modifier from attributes
	INT type_modifier = ExtractConvertAttrValueToInt(
		dxl_memory_manager, attrs, EdxltokenTypeMod, EdxltokenColDescr, true,
		default_type_modifier);

	BOOL col_dropped = false;

	const XMLCh *col_dropped_xml =
		attrs.getValue(CDXLTokens::XmlstrToken(EdxltokenColDropped));

	if (nullptr != col_dropped_xml)
	{
		// attribute is present: get value
		col_dropped =
			ConvertAttrValueToBool(dxl_memory_manager, col_dropped_xml,
								   EdxltokenColDropped, EdxltokenColDescr);
	}

	ULONG col_len = gpos::ulong_max;

	// parse column length from attributes
	const XMLCh *col_len_xml =
		attrs.getValue(CDXLTokens::XmlstrToken(EdxltokenColWidth));

	if (nullptr != col_len_xml)
	{
		col_len = ConvertAttrValueToUlong(dxl_memory_manager, col_len_xml,
										  EdxltokenColWidth, EdxltokenColDescr);
	}

	CWStringDynamic *col_name = CDXLUtils::CreateDynamicStringFromXMLChArray(
		dxl_memory_manager, column_name_xml);

	// create a copy of the string in the CMDName constructor
	CMDName *mdname = GPOS_NEW(mp) CMDName(mp, col_name);

	GPOS_DELETE(col_name);

	return GPOS_NEW(mp) CDXLColDescr(mdname, id, attno, mdid_type,
									 type_modifier, col_dropped, col_len);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeDXLColRef
//
//	@doc:
//		Construct a column reference
//
//---------------------------------------------------------------------------
CDXLColRef *
CDXLOperatorFactory::MakeDXLColRef(CDXLMemoryManager *dxl_memory_manager,
								   const Attributes &attrs,
								   Edxltoken target_elem)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	// parse column name from attributes
	const XMLCh *column_name_xml =
		ExtractAttrValue(attrs, EdxltokenColName, target_elem);

	// parse column id
	ULONG id = 0;
	const XMLCh *colid_xml =
		attrs.getValue(CDXLTokens::XmlstrToken(EdxltokenColId));
	if (nullptr == colid_xml)
	{
		GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLMissingAttribute,
				   CDXLTokens::GetDXLTokenStr(EdxltokenColRef)->GetBuffer(),
				   CDXLTokens::GetDXLTokenStr(target_elem)->GetBuffer());
	}

	id = XMLString::parseInt(colid_xml, dxl_memory_manager);

	CWStringDynamic *col_name = CDXLUtils::CreateDynamicStringFromXMLChArray(
		dxl_memory_manager, column_name_xml);

	// create a copy of the string in the CMDName constructor
	CMDName *mdname = GPOS_NEW(mp) CMDName(mp, col_name);

	GPOS_DELETE(col_name);

	IMDId *mdid_type = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenTypeId, target_elem);

	// parse optional type modifier
	INT type_modifier = ExtractConvertAttrValueToInt(
		dxl_memory_manager, attrs, EdxltokenTypeMod, target_elem, true,
		default_type_modifier);

	return GPOS_NEW(mp) CDXLColRef(mdname, id, mdid_type, type_modifier);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ParseOutputSegId
//
//	@doc:
//		Parse an output segment index
//
//---------------------------------------------------------------------------
INT
CDXLOperatorFactory::ParseOutputSegId(CDXLMemoryManager *dxl_memory_manager,
									  const Attributes &attrs)
{
	// get output segment index from attributes
	const XMLCh *seg_id_xml =
		ExtractAttrValue(attrs, EdxltokenSegId, EdxltokenSegment);

	// parse segment id from string
	INT segment_id = -1;
	try
	{
		segment_id = XMLString::parseInt(seg_id_xml, dxl_memory_manager);
	}
	catch (const NumberFormatException &toCatch)
	{
		// turn Xerces exception into GPOS exception
		GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
				   CDXLTokens::GetDXLTokenStr(EdxltokenSegId)->GetBuffer(),
				   CDXLTokens::GetDXLTokenStr(EdxltokenSegment)->GetBuffer());
	}

	return segment_id;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractAttrValue
//
//	@doc:
//    	Extracts the value for the given attribute.
// 		If there is no such attribute defined, and the given optional
// 		flag is set to false then it will raise an exception
//---------------------------------------------------------------------------
const XMLCh *
CDXLOperatorFactory::ExtractAttrValue(const Attributes &attrs,
									  Edxltoken target_attr,
									  Edxltoken target_elem, BOOL is_optional)
{
	const XMLCh *attribute_val_xml =
		attrs.getValue(CDXLTokens::XmlstrToken(target_attr));

	if (nullptr == attribute_val_xml && !is_optional)
	{
		GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLMissingAttribute,
				   CDXLTokens::GetDXLTokenStr(target_attr)->GetBuffer(),
				   CDXLTokens::GetDXLTokenStr(target_elem)->GetBuffer());
	}

	return attribute_val_xml;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ConvertAttrValueToUlong
//
//	@doc:
//	  	Converts the attribute value to ULONG
//
//---------------------------------------------------------------------------
ULONG
CDXLOperatorFactory::ConvertAttrValueToUlong(
	CDXLMemoryManager *dxl_memory_manager, const XMLCh *attribute_val_xml,
	Edxltoken target_attr, Edxltoken target_elem)
{
	GPOS_ASSERT(attribute_val_xml != nullptr);
	ULONG attr = 0;
	try
	{
		attr = XMLString::parseInt(attribute_val_xml, dxl_memory_manager);
	}
	catch (const NumberFormatException &toCatch)
	{
		// turn Xerces exception into GPOS exception
		GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
				   CDXLTokens::GetDXLTokenStr(target_attr)->GetBuffer(),
				   CDXLTokens::GetDXLTokenStr(target_elem)->GetBuffer());
	}
	return attr;
}


//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ConvertAttrValueToUllong
//
//	@doc:
//	  	Converts the attribute value to ULLONG
//
//---------------------------------------------------------------------------
ULLONG
CDXLOperatorFactory::ConvertAttrValueToUllong(
	CDXLMemoryManager *dxl_memory_manager, const XMLCh *attribute_val_xml,
	Edxltoken target_attr, Edxltoken target_elem)
{
	GPOS_ASSERT(attribute_val_xml != nullptr);

	CHAR *attr = XMLString::transcode(attribute_val_xml, dxl_memory_manager);
	GPOS_ASSERT(nullptr != attr);

	CHAR **end = nullptr;
	LINT converted_val = clib::Strtoll(attr, end, 10 /*ulBase*/);

	if ((nullptr != end && attr == *end) || gpos::lint_max == converted_val ||
		gpos::lint_min == converted_val || 0 > converted_val)
	{
		GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
				   CDXLTokens::GetDXLTokenStr(target_attr)->GetBuffer(),
				   CDXLTokens::GetDXLTokenStr(target_elem)->GetBuffer());
	}

	XMLString::release(&attr, dxl_memory_manager);

	return (ULLONG) converted_val;
}


//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ConvertAttrValueToBool
//
//	@doc:
//	  	Converts the attribute value to BOOL
//
//---------------------------------------------------------------------------
BOOL
CDXLOperatorFactory::ConvertAttrValueToBool(
	CDXLMemoryManager *dxl_memory_manager, const XMLCh *attribute_val_xml,
	Edxltoken target_attr, Edxltoken target_elem)
{
	GPOS_ASSERT(attribute_val_xml != nullptr);
	BOOL flag = false;
	CHAR *attr = XMLString::transcode(attribute_val_xml, dxl_memory_manager);

	if (0 == strncasecmp(attr, "true", 4))
	{
		flag = true;
	}
	else if (0 != strncasecmp(attr, "false", 5))
	{
		GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
				   CDXLTokens::GetDXLTokenStr(target_attr)->GetBuffer(),
				   CDXLTokens::GetDXLTokenStr(target_elem)->GetBuffer());
	}

	XMLString::release(&attr, dxl_memory_manager);
	return flag;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ConvertAttrValueToInt
//
//	@doc:
//	  	Converts the attribute value from xml string to INT
//
//---------------------------------------------------------------------------
INT
CDXLOperatorFactory::ConvertAttrValueToInt(
	CDXLMemoryManager *dxl_memory_manager, const XMLCh *attribute_val_xml,
	Edxltoken target_attr, Edxltoken target_elem)
{
	GPOS_ASSERT(attribute_val_xml != nullptr);
	INT attr = 0;
	try
	{
		attr = XMLString::parseInt(attribute_val_xml, dxl_memory_manager);
	}
	catch (const NumberFormatException &toCatch)
	{
		// turn Xerces exception into GPOS exception
		GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
				   CDXLTokens::GetDXLTokenStr(target_attr)->GetBuffer(),
				   CDXLTokens::GetDXLTokenStr(target_elem)->GetBuffer());
	}
	return attr;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractConvertAttrValueToInt
//
//	@doc:
//	  	Extracts the value for the given attribute and converts it into INT
//
//---------------------------------------------------------------------------
INT
CDXLOperatorFactory::ExtractConvertAttrValueToInt(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs,
	Edxltoken target_attr, Edxltoken target_elem, BOOL is_optional,
	INT default_val)
{
	const XMLCh *attr_val_xml = CDXLOperatorFactory::ExtractAttrValue(
		attrs, target_attr, target_elem, is_optional);

	if (nullptr == attr_val_xml)
	{
		return default_val;
	}

	return ConvertAttrValueToInt(dxl_memory_manager, attr_val_xml, target_attr,
								 target_elem);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ConvertAttrValueToShortInt
//
//	@doc:
//	  	Converts the attribute value from xml string to short int
//
//---------------------------------------------------------------------------
SINT
CDXLOperatorFactory::ConvertAttrValueToShortInt(
	CDXLMemoryManager *dxl_memory_manager, const XMLCh *attribute_val_xml,
	Edxltoken target_attr, Edxltoken target_elem)
{
	GPOS_ASSERT(attribute_val_xml != nullptr);
	SINT attr = 0;
	try
	{
		attr =
			(SINT) XMLString::parseInt(attribute_val_xml, dxl_memory_manager);
	}
	catch (const NumberFormatException &toCatch)
	{
		// turn Xerces exception into GPOS exception
		GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
				   CDXLTokens::GetDXLTokenStr(target_attr)->GetBuffer(),
				   CDXLTokens::GetDXLTokenStr(target_elem)->GetBuffer());
	}
	return attr;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractConvertAttrValueToShortInt
//
//	@doc:
//	  	Extracts the value for the given attribute and converts it into short
//		int
//
//---------------------------------------------------------------------------
SINT
CDXLOperatorFactory::ExtractConvertAttrValueToShortInt(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs,
	Edxltoken target_attr, Edxltoken target_elem, BOOL is_optional,
	SINT default_val)
{
	const XMLCh *attr_val_xml = CDXLOperatorFactory::ExtractAttrValue(
		attrs, target_attr, target_elem, is_optional);

	if (nullptr == attr_val_xml)
	{
		return default_val;
	}

	return ConvertAttrValueToShortInt(dxl_memory_manager, attr_val_xml,
									  target_attr, target_elem);
}

// Converts the attribute value from xml string to char
CHAR
CDXLOperatorFactory::ConvertAttrValueToChar(
	CDXLMemoryManager *dxl_memory_manager, const XMLCh *xml_val,
	Edxltoken,	// target_attr,
	Edxltoken	// target_elem
)
{
	GPOS_ASSERT(xml_val != nullptr);
	CHAR *attr = XMLString::transcode(xml_val, dxl_memory_manager);
	CHAR val = *attr;
	XMLString::release(&attr, dxl_memory_manager);
	return val;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ConvertAttrValueToOid
//
//	@doc:
//	  	Converts the attribute value to OID
//
//---------------------------------------------------------------------------
OID
CDXLOperatorFactory::ConvertAttrValueToOid(
	CDXLMemoryManager *dxl_memory_manager, const XMLCh *attribute_val_xml,
	Edxltoken target_attr, Edxltoken target_elem)
{
	GPOS_ASSERT(attribute_val_xml != nullptr);
	OID oid = 0;
	try
	{
		oid = XMLString::parseInt(attribute_val_xml, dxl_memory_manager);
	}
	catch (const NumberFormatException &toCatch)
	{
		// turn Xerces exception into GPOS exception
		GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
				   CDXLTokens::GetDXLTokenStr(target_attr)->GetBuffer(),
				   CDXLTokens::GetDXLTokenStr(target_elem)->GetBuffer());
	}
	return oid;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractConvertAttrValueToOid
//
//	@doc:
//	  	Extracts the value for the given attribute and converts it into OID
//
//---------------------------------------------------------------------------
OID
CDXLOperatorFactory::ExtractConvertAttrValueToOid(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs,
	Edxltoken target_attr, Edxltoken target_elem, BOOL is_optional,
	OID OidDefaultValue)
{
	const XMLCh *attr_val_xml = CDXLOperatorFactory::ExtractAttrValue(
		attrs, target_attr, target_elem, is_optional);

	if (nullptr == attr_val_xml)
	{
		return OidDefaultValue;
	}

	return ConvertAttrValueToOid(dxl_memory_manager, attr_val_xml, target_attr,
								 target_elem);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ConvertAttrValueToSz
//
//	@doc:
//	  	Converts the string attribute value
//
//---------------------------------------------------------------------------
CHAR *
CDXLOperatorFactory::ConvertAttrValueToSz(CDXLMemoryManager *dxl_memory_manager,
										  const XMLCh *xml_val,
										  Edxltoken,  // target_attr,
										  Edxltoken	  // target_elem
)
{
	GPOS_ASSERT(nullptr != xml_val);
	return XMLString::transcode(xml_val, dxl_memory_manager);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractConvertAttrValueToSz
//
//	@doc:
//	  	Extracts the value for the given attribute and converts it into CHAR*
//
//---------------------------------------------------------------------------
CHAR *
CDXLOperatorFactory::ExtractConvertAttrValueToSz(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs,
	Edxltoken target_attr, Edxltoken target_elem, BOOL is_optional,
	CHAR *default_value)
{
	const XMLCh *attr_val_xml = CDXLOperatorFactory::ExtractAttrValue(
		attrs, target_attr, target_elem, is_optional);

	if (nullptr == attr_val_xml)
	{
		return default_value;
	}

	return CDXLOperatorFactory::ConvertAttrValueToSz(
		dxl_memory_manager, attr_val_xml, target_attr, target_elem);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractConvertAttrValueToStr
//
//	@doc:
//	  	Extracts the string value for the given attribute
//
//---------------------------------------------------------------------------
CWStringDynamic *
CDXLOperatorFactory::ExtractConvertAttrValueToStr(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs,
	Edxltoken target_attr, Edxltoken target_elem)
{
	const XMLCh *attr_val_xml =
		CDXLOperatorFactory::ExtractAttrValue(attrs, target_attr, target_elem);
	return CDXLUtils::CreateDynamicStringFromXMLChArray(dxl_memory_manager,
														attr_val_xml);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractConvertAttrValueToBool
//
//	@doc:
//	  	Extracts the value for the given attribute and converts it into BOOL
//
//---------------------------------------------------------------------------
BOOL
CDXLOperatorFactory::ExtractConvertAttrValueToBool(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs,
	Edxltoken target_attr, Edxltoken target_elem, BOOL is_optional,
	BOOL default_value)
{
	const XMLCh *attr_val_xml = CDXLOperatorFactory::ExtractAttrValue(
		attrs, target_attr, target_elem, is_optional);

	if (nullptr == attr_val_xml)
	{
		return default_value;
	}

	return ConvertAttrValueToBool(dxl_memory_manager, attr_val_xml, target_attr,
								  target_elem);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractConvertAttrValueToUlong
//
//	@doc:
//	  	Extracts the value for the given attribute and converts it into ULONG
//
//---------------------------------------------------------------------------
ULONG
CDXLOperatorFactory::ExtractConvertAttrValueToUlong(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs,
	Edxltoken target_attr, Edxltoken target_elem, BOOL is_optional,
	ULONG default_value)
{
	const XMLCh *attr_val_xml = CDXLOperatorFactory::ExtractAttrValue(
		attrs, target_attr, target_elem, is_optional);

	if (nullptr == attr_val_xml)
	{
		return default_value;
	}

	return ConvertAttrValueToUlong(dxl_memory_manager, attr_val_xml,
								   target_attr, target_elem);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractConvertAttrValueToUllong
//
//	@doc:
//	  	Extracts the value for the given attribute and converts it into ULLONG
//
//---------------------------------------------------------------------------
ULLONG
CDXLOperatorFactory::ExtractConvertAttrValueToUllong(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs,
	Edxltoken target_attr, Edxltoken target_elem, BOOL is_optional,
	ULLONG default_value)
{
	const XMLCh *attr_val_xml = CDXLOperatorFactory::ExtractAttrValue(
		attrs, target_attr, target_elem, is_optional);

	if (nullptr == attr_val_xml)
	{
		return default_value;
	}

	return ConvertAttrValueToUllong(dxl_memory_manager, attr_val_xml,
									target_attr, target_elem);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ParseGroupingColId
//
//	@doc:
//		Parse a grouping column id
//
//---------------------------------------------------------------------------
ULONG
CDXLOperatorFactory::ParseGroupingColId(CDXLMemoryManager *dxl_memory_manager,
										const Attributes &attrs)
{
	const CWStringConst *grouping_colid_str =
		CDXLTokens::GetDXLTokenStr(EdxltokenGroupingCol);
	const CWStringConst *colid_str = CDXLTokens::GetDXLTokenStr(EdxltokenColId);

	// get grouping column id from attributes
	INT colid = ExtractConvertAttrValueToInt(
		dxl_memory_manager, attrs, EdxltokenColId, EdxltokenGroupingCol);

	if (colid < 0)
	{
		GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
				   colid_str->GetBuffer(), grouping_colid_str->GetBuffer());
	}

	return (ULONG) colid;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractConvertAttrValueToMdId
//
//	@doc:
//		Parse a metadata id object from the XML attributes of the specified element.
//
//---------------------------------------------------------------------------
IMDId *
CDXLOperatorFactory::ExtractConvertAttrValueToMdId(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs,
	Edxltoken target_attr, Edxltoken target_elem, BOOL is_optional,
	IMDId *default_val)
{
	// extract mdid
	const XMLCh *mdid_xml =
		ExtractAttrValue(attrs, target_attr, target_elem, is_optional);

	if (nullptr == mdid_xml)
	{
		if (nullptr != default_val)
		{
			default_val->AddRef();
		}

		return default_val;
	}

	return MakeMdIdFromStr(dxl_memory_manager, mdid_xml, target_attr,
						   target_elem);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeMdIdFromStr
//
//	@doc:
//		Parse a metadata id object from the XML attributes of the specified element.
//
//---------------------------------------------------------------------------
IMDId *
CDXLOperatorFactory::MakeMdIdFromStr(CDXLMemoryManager *dxl_memory_manager,
									 const XMLCh *mdid_xml,
									 Edxltoken target_attr,
									 Edxltoken target_elem)
{
	// extract mdid's components: MdidType.Oid.Major.Minor
	XMLStringTokenizer mdid_components(
		mdid_xml, CDXLTokens::XmlstrToken(EdxltokenDotSemicolon));

	GPOS_ASSERT(1 < mdid_components.countTokens());

	// get mdid type from first component
	XMLCh *mdid_type = mdid_components.nextToken();

	// collect the remaining tokens in an array
	XMLChArray *remaining_tokens = GPOS_NEW(dxl_memory_manager->Pmp())
		XMLChArray(dxl_memory_manager->Pmp());

	XMLCh *xml_val = nullptr;
	while (nullptr != (xml_val = mdid_components.nextToken()))
	{
		remaining_tokens->Append(xml_val);
	}

	IMDId::EMDIdType typ = (IMDId::EMDIdType) ConvertAttrValueToUlong(
		dxl_memory_manager, mdid_type, target_attr, target_elem);

	IMDId *mdid = nullptr;
	switch (typ)
	{
		case IMDId::EmdidGPDB:
			mdid = GetGPDBMdId(dxl_memory_manager, remaining_tokens,
							   target_attr, target_elem);
			break;

		case IMDId::EmdidGPDBCtas:
			mdid = GetGPDBCTASMdId(dxl_memory_manager, remaining_tokens,
								   target_attr, target_elem);
			break;

		case IMDId::EmdidColStats:
			mdid = GetColStatsMdId(dxl_memory_manager, remaining_tokens,
								   target_attr, target_elem);
			break;

		case IMDId::EmdidRelStats:
			mdid = GetRelStatsMdId(dxl_memory_manager, remaining_tokens,
								   target_attr, target_elem);
			break;

		case IMDId::EmdidCastFunc:
			mdid = GetCastFuncMdId(dxl_memory_manager, remaining_tokens,
								   target_attr, target_elem);
			break;

		case IMDId::EmdidScCmp:
			mdid = GetScCmpMdId(dxl_memory_manager, remaining_tokens,
								target_attr, target_elem);
			break;

		default:
			GPOS_ASSERT(!"Unrecognized mdid type");
	}

	remaining_tokens->Release();

	return mdid;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::GetGPDBMdId
//
//	@doc:
//		Construct a GPDB mdid from an array of XML string components.
//
//---------------------------------------------------------------------------
CMDIdGPDB *
CDXLOperatorFactory::GetGPDBMdId(CDXLMemoryManager *dxl_memory_manager,
								 XMLChArray *remaining_tokens,
								 Edxltoken target_attr, Edxltoken target_elem)
{
	GPOS_ASSERT(GPDXL_GPDB_MDID_COMPONENTS <= remaining_tokens->Size());

	XMLCh *xml_oid = (*remaining_tokens)[0];
	ULONG oid_colid = ConvertAttrValueToUlong(dxl_memory_manager, xml_oid,
											  target_attr, target_elem);

	XMLCh *version_major_xml = (*remaining_tokens)[1];
	ULONG version_major = ConvertAttrValueToUlong(
		dxl_memory_manager, version_major_xml, target_attr, target_elem);

	XMLCh *xmlszVersionMinor = (*remaining_tokens)[2];
	;
	ULONG version_minor = ConvertAttrValueToUlong(
		dxl_memory_manager, xmlszVersionMinor, target_attr, target_elem);

	// construct metadata id object
	return GPOS_NEW(dxl_memory_manager->Pmp())
		CMDIdGPDB(oid_colid, version_major, version_minor);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::GetGPDBCTASMdId
//
//	@doc:
//		Construct a GPDB CTAS mdid from an array of XML string components.
//
//---------------------------------------------------------------------------
CMDIdGPDB *
CDXLOperatorFactory::GetGPDBCTASMdId(CDXLMemoryManager *dxl_memory_manager,
									 XMLChArray *remaining_tokens,
									 Edxltoken target_attr,
									 Edxltoken target_elem)
{
	GPOS_ASSERT(GPDXL_GPDB_MDID_COMPONENTS <= remaining_tokens->Size());

	XMLCh *xml_oid = (*remaining_tokens)[0];
	ULONG oid_colid = ConvertAttrValueToUlong(dxl_memory_manager, xml_oid,
											  target_attr, target_elem);

	// construct metadata id object
	return GPOS_NEW(dxl_memory_manager->Pmp()) CMDIdGPDBCtas(oid_colid);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::GetColStatsMdId
//
//	@doc:
//		Construct a column stats mdid from an array of XML string components.
//
//---------------------------------------------------------------------------
CMDIdColStats *
CDXLOperatorFactory::GetColStatsMdId(CDXLMemoryManager *dxl_memory_manager,
									 XMLChArray *remaining_tokens,
									 Edxltoken target_attr,
									 Edxltoken target_elem)
{
	GPOS_ASSERT(GPDXL_GPDB_MDID_COMPONENTS + 1 == remaining_tokens->Size());

	CMDIdGPDB *rel_mdid = GetGPDBMdId(dxl_memory_manager, remaining_tokens,
									  target_attr, target_elem);

	XMLCh *attno_xml = (*remaining_tokens)[3];
	ULONG attno = ConvertAttrValueToUlong(dxl_memory_manager, attno_xml,
										  target_attr, target_elem);

	// construct metadata id object
	return GPOS_NEW(dxl_memory_manager->Pmp()) CMDIdColStats(rel_mdid, attno);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::GetRelStatsMdId
//
//	@doc:
//		Construct a relation stats mdid from an array of XML string components.
//
//---------------------------------------------------------------------------
CMDIdRelStats *
CDXLOperatorFactory::GetRelStatsMdId(CDXLMemoryManager *dxl_memory_manager,
									 XMLChArray *remaining_tokens,
									 Edxltoken target_attr,
									 Edxltoken target_elem)
{
	GPOS_ASSERT(GPDXL_GPDB_MDID_COMPONENTS == remaining_tokens->Size());

	CMDIdGPDB *rel_mdid = GetGPDBMdId(dxl_memory_manager, remaining_tokens,
									  target_attr, target_elem);

	// construct metadata id object
	return GPOS_NEW(dxl_memory_manager->Pmp()) CMDIdRelStats(rel_mdid);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::GetCastFuncMdId
//
//	@doc:
//		Construct a cast function mdid from the array of XML string components.
//
//---------------------------------------------------------------------------
CMDIdCast *
CDXLOperatorFactory::GetCastFuncMdId(CDXLMemoryManager *dxl_memory_manager,
									 XMLChArray *remaining_tokens,
									 Edxltoken target_attr,
									 Edxltoken target_elem)
{
	GPOS_ASSERT(2 * GPDXL_GPDB_MDID_COMPONENTS == remaining_tokens->Size());

	CMDIdGPDB *mdid_src = GetGPDBMdId(dxl_memory_manager, remaining_tokens,
									  target_attr, target_elem);
	XMLChArray *dest_xml = GPOS_NEW(dxl_memory_manager->Pmp())
		XMLChArray(dxl_memory_manager->Pmp());

	for (ULONG ul = GPDXL_GPDB_MDID_COMPONENTS;
		 ul < GPDXL_GPDB_MDID_COMPONENTS * 2; ul++)
	{
		dest_xml->Append((*remaining_tokens)[ul]);
	}

	CMDIdGPDB *mdid_dest =
		GetGPDBMdId(dxl_memory_manager, dest_xml, target_attr, target_elem);
	dest_xml->Release();

	return GPOS_NEW(dxl_memory_manager->Pmp()) CMDIdCast(mdid_src, mdid_dest);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::GetScCmpMdId
//
//	@doc:
//		Construct a scalar comparison operator mdid from the array of XML string components.
//
//---------------------------------------------------------------------------
CMDIdScCmp *
CDXLOperatorFactory::GetScCmpMdId(CDXLMemoryManager *dxl_memory_manager,
								  XMLChArray *remaining_tokens,
								  Edxltoken target_attr, Edxltoken target_elem)
{
	GPOS_ASSERT(2 * GPDXL_GPDB_MDID_COMPONENTS + 1 == remaining_tokens->Size());

	CMDIdGPDB *left_mdid = GetGPDBMdId(dxl_memory_manager, remaining_tokens,
									   target_attr, target_elem);
	XMLChArray *right_xml = GPOS_NEW(dxl_memory_manager->Pmp())
		XMLChArray(dxl_memory_manager->Pmp());

	for (ULONG ul = GPDXL_GPDB_MDID_COMPONENTS;
		 ul < GPDXL_GPDB_MDID_COMPONENTS * 2 + 1; ul++)
	{
		right_xml->Append((*remaining_tokens)[ul]);
	}

	CMDIdGPDB *right_mdid =
		GetGPDBMdId(dxl_memory_manager, right_xml, target_attr, target_elem);

	// parse the comparison type from the last component of the mdid
	XMLCh *xml_str_comp_type = (*right_xml)[right_xml->Size() - 1];
	IMDType::ECmpType cmp_type = (IMDType::ECmpType) ConvertAttrValueToUlong(
		dxl_memory_manager, xml_str_comp_type, target_attr, target_elem);
	GPOS_ASSERT(IMDType::EcmptOther > cmp_type);

	right_xml->Release();

	return GPOS_NEW(dxl_memory_manager->Pmp())
		CMDIdScCmp(left_mdid, right_mdid, cmp_type);
}


//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::GetDatumVal
//
//	@doc:
//		Parses a DXL datum from the given attributes
//
//---------------------------------------------------------------------------
CDXLDatum *
CDXLOperatorFactory::GetDatumVal(CDXLMemoryManager *dxl_memory_manager,
								 const Attributes &attrs, Edxltoken target_elem)
{
	// get the type id and value of the datum from attributes
	IMDId *mdid = ExtractConvertAttrValueToMdId(dxl_memory_manager, attrs,
												EdxltokenTypeId, target_elem);
	GPOS_ASSERT(IMDId::EmdidGPDB == mdid->MdidType());
	CMDIdGPDB *gpdb_mdid = CMDIdGPDB::CastMdid(mdid);

	// get the type id from string
	BOOL is_const_null = ExtractConvertAttrValueToBool(
		dxl_memory_manager, attrs, EdxltokenIsNull, target_elem, true, false);

	switch (gpdb_mdid->Oid())
	{
		default:
		{
			const XMLCh *attr_val_xml =
				attrs.getValue(CDXLTokens::XmlstrToken(EdxltokenLintValue));
			if (attr_val_xml)
			{
				return GetDatumStatsLintMappable(dxl_memory_manager, attrs,
												 target_elem, mdid,
												 is_const_null);
			}
			// generate a datum of generic type
			return GetDatumGeneric(dxl_memory_manager, attrs, target_elem, mdid,
								   is_const_null);
		}
		// native support
		case GPDB_INT2:
		{
			return GetDatumInt2(dxl_memory_manager, attrs, target_elem, mdid,
								is_const_null);
		}
		case GPDB_INT4:
		{
			return GetDatumInt4(dxl_memory_manager, attrs, target_elem, mdid,
								is_const_null);
		}
		case GPDB_INT8:
		{
			return GetDatumInt8(dxl_memory_manager, attrs, target_elem, mdid,
								is_const_null);
		}
		case GPDB_BOOL:
		{
			return GetDatumBool(dxl_memory_manager, attrs, target_elem, mdid,
								is_const_null);
		}
		case GPDB_OID:
		{
			return GetDatumOid(dxl_memory_manager, attrs, target_elem, mdid,
							   is_const_null);
		}
		// types with long int mapping
		case GPDB_CHAR:
		case GPDB_VARCHAR:
		case GPDB_TEXT:
		case GPDB_CASH:
		case GPDB_UUID:
		case GPDB_DATE:
		{
			return GetDatumStatsLintMappable(dxl_memory_manager, attrs,
											 target_elem, mdid, is_const_null);
		}
		// non-integer numeric types
		case GPDB_NUMERIC:
		case GPDB_FLOAT4:
		case GPDB_FLOAT8:
		// network-related types
		case GPDB_INET:
		case GPDB_CIDR:
		case GPDB_MACADDR:
		// time-related types
		case GPDB_TIME:
		case GPDB_TIMETZ:
		case GPDB_TIMESTAMP:
		case GPDB_TIMESTAMPTZ:
		case GPDB_ABSTIME:
		case GPDB_RELTIME:
		case GPDB_INTERVAL:
		case GPDB_TIMEINTERVAL:
		{
			return GetDatumStatsDoubleMappable(
				dxl_memory_manager, attrs, target_elem, mdid, is_const_null);
		}
	}
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::GetDatumOid
//
//	@doc:
//		Parses a DXL datum of oid type
//
//---------------------------------------------------------------------------
CDXLDatum *
CDXLOperatorFactory::GetDatumOid(CDXLMemoryManager *dxl_memory_manager,
								 const Attributes &attrs, Edxltoken target_elem,
								 IMDId *mdid, BOOL is_const_null)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	OID val = 0;
	if (!is_const_null)
	{
		val = ExtractConvertAttrValueToOid(dxl_memory_manager, attrs,
										   EdxltokenValue, target_elem);
	}

	return GPOS_NEW(mp) CDXLDatumOid(mp, mdid, is_const_null, val);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::GetDatumInt2
//
//	@doc:
//		Parses a DXL datum of int2 type
//
//---------------------------------------------------------------------------
CDXLDatum *
CDXLOperatorFactory::GetDatumInt2(CDXLMemoryManager *dxl_memory_manager,
								  const Attributes &attrs,
								  Edxltoken target_elem, IMDId *mdid,
								  BOOL is_const_null)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	SINT val = 0;
	if (!is_const_null)
	{
		val = ExtractConvertAttrValueToShortInt(dxl_memory_manager, attrs,
												EdxltokenValue, target_elem);
	}

	return GPOS_NEW(mp) CDXLDatumInt2(mp, mdid, is_const_null, val);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::GetDatumInt4
//
//	@doc:
//		Parses a DXL datum of int4 type
//
//---------------------------------------------------------------------------
CDXLDatum *
CDXLOperatorFactory::GetDatumInt4(CDXLMemoryManager *dxl_memory_manager,
								  const Attributes &attrs,
								  Edxltoken target_elem, IMDId *mdid,
								  BOOL is_const_null)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	INT val = 0;
	if (!is_const_null)
	{
		val = ExtractConvertAttrValueToInt(dxl_memory_manager, attrs,
										   EdxltokenValue, target_elem);
	}

	return GPOS_NEW(mp) CDXLDatumInt4(mp, mdid, is_const_null, val);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::GetDatumInt8
//
//	@doc:
//		Parses a DXL datum of int8 type
//
//---------------------------------------------------------------------------
CDXLDatum *
CDXLOperatorFactory::GetDatumInt8(CDXLMemoryManager *dxl_memory_manager,
								  const Attributes &attrs,
								  Edxltoken target_elem, IMDId *mdid,
								  BOOL is_const_null)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	LINT val = 0;
	if (!is_const_null)
	{
		val = ExtractConvertAttrValueToLint(dxl_memory_manager, attrs,
											EdxltokenValue, target_elem);
	}

	return GPOS_NEW(mp) CDXLDatumInt8(mp, mdid, is_const_null, val);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::GetDatumBool
//
//	@doc:
//		Parses a DXL datum of boolean type
//
//---------------------------------------------------------------------------
CDXLDatum *
CDXLOperatorFactory::GetDatumBool(CDXLMemoryManager *dxl_memory_manager,
								  const Attributes &attrs,
								  Edxltoken target_elem, IMDId *mdid,
								  BOOL is_const_null)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	BOOL value = false;
	if (!is_const_null)
	{
		value = ExtractConvertAttrValueToBool(dxl_memory_manager, attrs,
											  EdxltokenValue, target_elem);
	}

	return GPOS_NEW(mp) CDXLDatumBool(mp, mdid, is_const_null, value);
}


//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::GetDatumGeneric
//
//	@doc:
//		Parses a DXL datum of generic type
//
//---------------------------------------------------------------------------
CDXLDatum *
CDXLOperatorFactory::GetDatumGeneric(CDXLMemoryManager *dxl_memory_manager,
									 const Attributes &attrs,
									 Edxltoken target_elem, IMDId *mdid,
									 BOOL is_const_null)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	ULONG len = 0;
	BYTE *data = nullptr;

	if (!is_const_null)
	{
		data = GetByteArray(dxl_memory_manager, attrs, target_elem, &len);
		if (nullptr == data)
		{
			// unable to decode value. probably not Base64 encoded.
			GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
					   CDXLTokens::XmlstrToken(EdxltokenValue),
					   CDXLTokens::GetDXLTokenStr(target_elem));
		}
	}

	INT type_modifier = ExtractConvertAttrValueToInt(
		dxl_memory_manager, attrs, EdxltokenTypeMod, EdxltokenScalarCast, true,
		default_type_modifier);

	return GPOS_NEW(mp)
		CDXLDatumGeneric(mp, mdid, type_modifier, is_const_null, data, len);
}


//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::GetDatumStatsLintMappable
//
//	@doc:
//		Parses a DXL datum of types having lint mapping
//
//---------------------------------------------------------------------------
CDXLDatum *
CDXLOperatorFactory::GetDatumStatsLintMappable(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs,
	Edxltoken target_elem, IMDId *mdid, BOOL is_const_null)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	ULONG len = 0;
	BYTE *data = nullptr;

	LINT value = 0;
	if (!is_const_null)
	{
		data = GetByteArray(dxl_memory_manager, attrs, target_elem, &len);
		value = Value(dxl_memory_manager, attrs, target_elem, data);
	}

	INT type_modifier = ExtractConvertAttrValueToInt(
		dxl_memory_manager, attrs, EdxltokenTypeMod, EdxltokenScalarCast, true,
		-1 /* default_val value */
	);

	return GPOS_NEW(mp) CDXLDatumStatsLintMappable(
		mp, mdid, type_modifier, is_const_null, data, len, value);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::Value
//
//	@doc:
//		Return the LINT value of byte array
//
//---------------------------------------------------------------------------
LINT
CDXLOperatorFactory::Value(CDXLMemoryManager *dxl_memory_manager,
						   const Attributes &attrs, Edxltoken target_elem,
						   const BYTE *data)
{
	if (nullptr == data)
	{
		// unable to decode value. probably not Base64 encoded.
		GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
				   CDXLTokens::XmlstrToken(EdxltokenValue),
				   CDXLTokens::GetDXLTokenStr(target_elem));
	}

	return ExtractConvertAttrValueToLint(dxl_memory_manager, attrs,
										 EdxltokenLintValue, target_elem);
}


//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::GetByteArray
//
//	@doc:
//		Parses a byte array representation of the datum
//
//---------------------------------------------------------------------------
BYTE *
CDXLOperatorFactory::GetByteArray(CDXLMemoryManager *dxl_memory_manager,
								  const Attributes &attrs,
								  Edxltoken target_elem, ULONG *length)
{
	const XMLCh *attr_val_xml =
		ExtractAttrValue(attrs, EdxltokenValue, target_elem);

	return CDXLUtils::CreateStringFrom64XMLStr(dxl_memory_manager, attr_val_xml,
											   length);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::GetDatumStatsDoubleMappable
//
//	@doc:
//		Parses a DXL datum of types that need double mapping
//
//---------------------------------------------------------------------------
CDXLDatum *
CDXLOperatorFactory::GetDatumStatsDoubleMappable(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs,
	Edxltoken target_elem, IMDId *mdid, BOOL is_const_null)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	ULONG len = 0;
	BYTE *data = nullptr;
	CDouble value = 0;

	if (!is_const_null)
	{
		data = GetByteArray(dxl_memory_manager, attrs, target_elem, &len);

		if (nullptr == data)
		{
			// unable to decode value. probably not Base64 encoded.
			GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
					   CDXLTokens::XmlstrToken(EdxltokenValue),
					   CDXLTokens::GetDXLTokenStr(target_elem));
		}

		value = ExtractConvertAttrValueToDouble(
			dxl_memory_manager, attrs, EdxltokenDoubleValue, target_elem);
	}
	INT type_modifier = ExtractConvertAttrValueToInt(
		dxl_memory_manager, attrs, EdxltokenTypeMod, EdxltokenScalarCast, true,
		-1 /* default_val value */
	);
	return GPOS_NEW(mp) CDXLDatumStatsDoubleMappable(
		mp, mdid, type_modifier, is_const_null, data, len, value);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractConvertValuesToArray
//
//	@doc:
//		Parse a comma-separated list of unsigned long integers ids into a dynamic array.
//		Will raise an exception if list is not well-formed
//
//---------------------------------------------------------------------------
ULongPtrArray *
CDXLOperatorFactory::ExtractConvertValuesToArray(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs,
	Edxltoken target_attr, Edxltoken target_elem)
{
	const XMLCh *xml_val =
		CDXLOperatorFactory::ExtractAttrValue(attrs, target_attr, target_elem);

	return ExtractIntsToUlongArray(dxl_memory_manager, xml_val, target_attr,
								   target_elem);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractConvertMdIdsToArray
//
//	@doc:
//		Parse a comma-separated list of MDids into a dynamic array.
//		Will raise an exception if list is not well-formed
//
//---------------------------------------------------------------------------
IMdIdArray *
CDXLOperatorFactory::ExtractConvertMdIdsToArray(
	CDXLMemoryManager *dxl_memory_manager, const XMLCh *mdid_list_xml,
	Edxltoken target_attr, Edxltoken target_elem)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	IMdIdArray *mdid_array = GPOS_NEW(mp) IMdIdArray(mp);

	XMLStringTokenizer mdid_components(mdid_list_xml,
									   CDXLTokens::XmlstrToken(EdxltokenComma));
	const ULONG num_tokens = mdid_components.countTokens();

	for (ULONG ul = 0; ul < num_tokens; ul++)
	{
		XMLCh *mdid_xml = mdid_components.nextToken();
		GPOS_ASSERT(nullptr != mdid_xml);

		IMDId *mdid = MakeMdIdFromStr(dxl_memory_manager, mdid_xml, target_attr,
									  target_elem);
		mdid_array->Append(mdid);
	}

	return mdid_array;
}

// Parse a comma-separated list of CHAR partition types into a dynamic array.
// Will raise an exception if list is not well-formed
CharPtrArray *
CDXLOperatorFactory::ExtractConvertPartitionTypeToArray(
	CDXLMemoryManager *dxl_memory_manager, const XMLCh *xml_val,
	Edxltoken target_attr, Edxltoken target_elem)
{
	return ExtractIntsToArray<CHAR, CleanupDelete, ConvertAttrValueToChar>(
		dxl_memory_manager, xml_val, target_attr, target_elem);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractConvertUlongTo2DArray
//
//	@doc:
//		Parse a semicolon-separated list of comma-separated unsigned long
//		integers into a dynamic array.
//		Will raise an exception if list is not well-formed
//
//---------------------------------------------------------------------------
ULongPtr2dArray *
CDXLOperatorFactory::ExtractConvertUlongTo2DArray(
	CDXLMemoryManager *dxl_memory_manager, const XMLCh *xml_val,
	Edxltoken target_attr, Edxltoken target_elem)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	ULongPtr2dArray *array_2D = GPOS_NEW(mp) ULongPtr2dArray(mp);

	XMLStringTokenizer mdid_components(
		xml_val, CDXLTokens::XmlstrToken(EdxltokenSemicolon));
	const ULONG num_tokens = mdid_components.countTokens();

	for (ULONG ul = 0; ul < num_tokens; ul++)
	{
		XMLCh *comp_xml = mdid_components.nextToken();

		GPOS_ASSERT(nullptr != comp_xml);

		ULongPtrArray *array_1D = ExtractIntsToUlongArray(
			dxl_memory_manager, comp_xml, target_attr, target_elem);
		array_2D->Append(array_1D);
	}

	return array_2D;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractConvertSegmentIdsToArray
//
//	@doc:
//		Parse a comma-separated list of segment ids into a dynamic array.
//		Will raise an exception if list is not well-formed
//
//---------------------------------------------------------------------------
IntPtrArray *
CDXLOperatorFactory::ExtractConvertSegmentIdsToArray(
	CDXLMemoryManager *dxl_memory_manager, const XMLCh *seg_id_list_xml,
	Edxltoken target_attr, Edxltoken target_elem)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	GPOS_ASSERT(nullptr != seg_id_list_xml);

	IntPtrArray *seg_ids = GPOS_NEW(mp) IntPtrArray(mp);

	XMLStringTokenizer mdid_components(seg_id_list_xml,
									   CDXLTokens::XmlstrToken(EdxltokenComma));

	const ULONG num_of_segments = mdid_components.countTokens();
	GPOS_ASSERT(0 < num_of_segments);

	for (ULONG ul = 0; ul < num_of_segments; ul++)
	{
		XMLCh *seg_id_xml = mdid_components.nextToken();

		GPOS_ASSERT(nullptr != seg_id_xml);

		INT *seg_id = GPOS_NEW(mp) INT(ConvertAttrValueToInt(
			dxl_memory_manager, seg_id_xml, target_attr, target_elem));
		seg_ids->Append(seg_id);
	}

	return seg_ids;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractConvertStrsToArray
//
//	@doc:
//		Parse a semicolon-separated list of strings into a dynamic array.
//
//---------------------------------------------------------------------------
StringPtrArray *
CDXLOperatorFactory::ExtractConvertStrsToArray(
	CDXLMemoryManager *dxl_memory_manager, const XMLCh *xml_val)
{
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	StringPtrArray *array_strs = GPOS_NEW(mp) StringPtrArray(mp);

	XMLStringTokenizer mdid_components(
		xml_val, CDXLTokens::XmlstrToken(EdxltokenSemicolon));
	const ULONG num_tokens = mdid_components.countTokens();

	for (ULONG ul = 0; ul < num_tokens; ul++)
	{
		XMLCh *current_str = mdid_components.nextToken();
		GPOS_ASSERT(nullptr != current_str);

		CWStringDynamic *str = CDXLUtils::CreateDynamicStringFromXMLChArray(
			dxl_memory_manager, current_str);
		array_strs->Append(str);
	}

	return array_strs;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::SetSegmentInfo
//
//	@doc:
//		Parses the input and output segment ids from Xerces attributes and
//		stores them in the provided DXL Motion operator.
//		Will raise an exception if lists are not well-formed
//
//---------------------------------------------------------------------------
void
CDXLOperatorFactory::SetSegmentInfo(CDXLMemoryManager *dxl_memory_manager,
									CDXLPhysicalMotion *motion,
									const Attributes &attrs,
									Edxltoken target_elem)
{
	const XMLCh *input_seglist_xml =
		ExtractAttrValue(attrs, EdxltokenInputSegments, target_elem);
	IntPtrArray *input_segments =
		ExtractConvertSegmentIdsToArray(dxl_memory_manager, input_seglist_xml,
										EdxltokenInputSegments, target_elem);
	motion->SetInputSegIds(input_segments);

	const XMLCh *output_seglist_xml =
		ExtractAttrValue(attrs, EdxltokenOutputSegments, target_elem);
	IntPtrArray *output_segments =
		ExtractConvertSegmentIdsToArray(dxl_memory_manager, output_seglist_xml,
										EdxltokenOutputSegments, target_elem);
	motion->SetOutputSegIds(output_segments);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ParseJoinType
//
//	@doc:
//		Parse a join type from the attribute value.
//		Raise an exception if join type value is invalid.
//
//---------------------------------------------------------------------------
EdxlJoinType
CDXLOperatorFactory::ParseJoinType(const XMLCh *join_type_xml,
								   const CWStringConst *join_name)
{
	EdxlJoinType join_type = EdxljtSentinel;

	if (0 == XMLString::compareString(
				 CDXLTokens::XmlstrToken(EdxltokenJoinInner), join_type_xml))
	{
		join_type = EdxljtInner;
	}
	else if (0 ==
			 XMLString::compareString(
				 CDXLTokens::XmlstrToken(EdxltokenJoinLeft), join_type_xml))
	{
		join_type = EdxljtLeft;
	}
	else if (0 ==
			 XMLString::compareString(
				 CDXLTokens::XmlstrToken(EdxltokenJoinFull), join_type_xml))
	{
		join_type = EdxljtFull;
	}
	else if (0 ==
			 XMLString::compareString(
				 CDXLTokens::XmlstrToken(EdxltokenJoinRight), join_type_xml))
	{
		join_type = EdxljtRight;
	}
	else if (0 == XMLString::compareString(
					  CDXLTokens::XmlstrToken(EdxltokenJoinIn), join_type_xml))
	{
		join_type = EdxljtIn;
	}
	else if (0 == XMLString::compareString(
					  CDXLTokens::XmlstrToken(EdxltokenJoinLeftAntiSemiJoin),
					  join_type_xml))
	{
		join_type = EdxljtLeftAntiSemijoin;
	}
	else if (0 ==
			 XMLString::compareString(
				 CDXLTokens::XmlstrToken(EdxltokenJoinLeftAntiSemiJoinNotIn),
				 join_type_xml))
	{
		join_type = EdxljtLeftAntiSemijoinNotIn;
	}
	else
	{
		GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
				   CDXLTokens::GetDXLTokenStr(EdxltokenJoinType)->GetBuffer(),
				   join_name->GetBuffer());
	}

	return join_type;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ParseIndexScanDirection
//
//	@doc:
//		Parse the index scan direction from the attribute value. Raise
//		exception if it is invalid
//
//---------------------------------------------------------------------------
EdxlIndexScanDirection
CDXLOperatorFactory::ParseIndexScanDirection(const XMLCh *direction_xml,
											 const CWStringConst *index_scan)
{
	if (0 == XMLString::compareString(
				 CDXLTokens::XmlstrToken(EdxltokenIndexScanDirectionBackward),
				 direction_xml))
	{
		return EdxlisdBackward;
	}
	else if (0 ==
			 XMLString::compareString(
				 CDXLTokens::XmlstrToken(EdxltokenIndexScanDirectionForward),
				 direction_xml))
	{
		return EdxlisdForward;
	}
	else if (0 ==
			 XMLString::compareString(
				 CDXLTokens::XmlstrToken(EdxltokenIndexScanDirectionNoMovement),
				 direction_xml))
	{
		return EdxlisdNoMovement;
	}
	else
	{
		GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
				   CDXLTokens::GetDXLTokenStr(EdxltokenIndexScanDirection)
					   ->GetBuffer(),
				   index_scan->GetBuffer());
	}

	return EdxlisdSentinel;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeLogicalJoin
//
//	@doc:
//		Construct a logical join operator
//
//---------------------------------------------------------------------------
CDXLLogical *
CDXLOperatorFactory::MakeLogicalJoin(CDXLMemoryManager *dxl_memory_manager,
									 const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();

	const XMLCh *join_type_xml =
		ExtractAttrValue(attrs, EdxltokenJoinType, EdxltokenLogicalJoin);
	EdxlJoinType join_type = ParseJoinType(
		join_type_xml, CDXLTokens::GetDXLTokenStr(EdxltokenLogicalJoin));

	return GPOS_NEW(mp) CDXLLogicalJoin(mp, join_type);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ConvertAttrValueToDouble
//
//	@doc:
//	  Converts the attribute value to CDouble
//
//---------------------------------------------------------------------------
CDouble
CDXLOperatorFactory::ConvertAttrValueToDouble(
	CDXLMemoryManager *dxl_memory_manager, const XMLCh *attribute_val_xml,
	Edxltoken,	//target_attr,
	Edxltoken	//target_elem
)
{
	GPOS_ASSERT(attribute_val_xml != nullptr);
	CHAR *sz = XMLString::transcode(attribute_val_xml, dxl_memory_manager);

	CDouble value(clib::Strtod(sz));

	XMLString::release(&sz, dxl_memory_manager);
	return value;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractConvertAttrValueToDouble
//
//	@doc:
//	  Extracts the value for the given attribute and converts it into CDouble
//
//---------------------------------------------------------------------------
CDouble
CDXLOperatorFactory::ExtractConvertAttrValueToDouble(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs,
	Edxltoken target_attr, Edxltoken target_elem)
{
	const XMLCh *attr_val_xml =
		CDXLOperatorFactory::ExtractAttrValue(attrs, target_attr, target_elem);
	return ConvertAttrValueToDouble(dxl_memory_manager, attr_val_xml,
									target_attr, target_elem);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ConvertAttrValueToLint
//
//	@doc:
//	  Converts the attribute value to LINT
//
//---------------------------------------------------------------------------
LINT
CDXLOperatorFactory::ConvertAttrValueToLint(
	CDXLMemoryManager *dxl_memory_manager, const XMLCh *attribute_val_xml,
	Edxltoken,	//target_attr,
	Edxltoken	//target_elem
)
{
	GPOS_ASSERT(nullptr != attribute_val_xml);
	CHAR *sz = XMLString::transcode(attribute_val_xml, dxl_memory_manager);
	CHAR *szEnd = nullptr;

	LINT value = clib::Strtoll(sz, &szEnd, 10);
	XMLString::release(&sz, dxl_memory_manager);

	return value;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ExtractConvertAttrValueToLint
//
//	@doc:
//	  Extracts the value for the given attribute and converts it into LINT
//
//---------------------------------------------------------------------------
LINT
CDXLOperatorFactory::ExtractConvertAttrValueToLint(
	CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs,
	Edxltoken target_attr, Edxltoken target_elem, BOOL is_optional,
	LINT default_value)
{
	const XMLCh *attr_val_xml = CDXLOperatorFactory::ExtractAttrValue(
		attrs, target_attr, target_elem, is_optional);

	if (nullptr == attr_val_xml)
	{
		return default_value;
	}

	return ConvertAttrValueToLint(dxl_memory_manager, attr_val_xml, target_attr,
								  target_elem);
}


CSystemId
CDXLOperatorFactory::Sysid(CDXLMemoryManager *dxl_memory_manager,
						   const Attributes &attrs, Edxltoken target_attr,
						   Edxltoken target_elem)
{
	// extract systemids
	const XMLCh *xml_val = ExtractAttrValue(attrs, target_attr, target_elem);

	// get sysid components
	XMLStringTokenizer sys_id_components(xml_val,
										 CDXLTokens::XmlstrToken(EdxltokenDot));
	GPOS_ASSERT(2 == sys_id_components.countTokens());

	XMLCh *sys_id_comp = sys_id_components.nextToken();
	ULONG type = CDXLOperatorFactory::ConvertAttrValueToUlong(
		dxl_memory_manager, sys_id_comp, target_attr, target_elem);

	XMLCh *xml_str_name = sys_id_components.nextToken();
	CWStringDynamic *str_name = CDXLUtils::CreateDynamicStringFromXMLChArray(
		dxl_memory_manager, xml_str_name);

	CSystemId sys_id((IMDId::EMDIdType) type, str_name->GetBuffer(),
					 str_name->Length());
	GPOS_DELETE(str_name);

	return sys_id;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::MakeWindowRef
//
//	@doc:
//		Construct an WindowRef operator
//
//---------------------------------------------------------------------------
CDXLScalar *
CDXLOperatorFactory::MakeWindowRef(CDXLMemoryManager *dxl_memory_manager,
								   const Attributes &attrs)
{
	// get the memory pool from the memory manager
	CMemoryPool *mp = dxl_memory_manager->Pmp();
	IMDId *mdid_func = ExtractConvertAttrValueToMdId(dxl_memory_manager, attrs,
													 EdxltokenWindowrefOid,
													 EdxltokenScalarWindowref);
	IMDId *mdid_return_type = ExtractConvertAttrValueToMdId(
		dxl_memory_manager, attrs, EdxltokenTypeId, EdxltokenScalarWindowref);
	BOOL is_distinct = ExtractConvertAttrValueToBool(dxl_memory_manager, attrs,
													 EdxltokenWindowrefDistinct,
													 EdxltokenScalarWindowref);
	BOOL is_star_arg = ExtractConvertAttrValueToBool(dxl_memory_manager, attrs,
													 EdxltokenWindowrefStarArg,
													 EdxltokenScalarWindowref);
	BOOL is_simple_agg = ExtractConvertAttrValueToBool(
		dxl_memory_manager, attrs, EdxltokenWindowrefSimpleAgg,
		EdxltokenScalarWindowref);
	ULONG win_spec_pos = ExtractConvertAttrValueToUlong(
		dxl_memory_manager, attrs, EdxltokenWindowrefWinSpecPos,
		EdxltokenScalarWindowref);

	const XMLCh *agg_stage_xml = ExtractAttrValue(
		attrs, EdxltokenWindowrefStrategy, EdxltokenScalarWindowref);
	EdxlWinStage dxl_win_stage = EdxlwinstageSentinel;

	ULONG window_frame_boundary_to_frame_boundary_mapping[][2] = {
		{EdxlwinstageImmediate, EdxltokenWindowrefStageImmediate},
		{EdxlwinstagePreliminary, EdxltokenWindowrefStagePreliminary},
		{EdxlwinstageRowKey, EdxltokenWindowrefStageRowKey}};

	const ULONG arity =
		GPOS_ARRAY_SIZE(window_frame_boundary_to_frame_boundary_mapping);
	for (ULONG ul = 0; ul < arity; ul++)
	{
		ULONG *mapping = window_frame_boundary_to_frame_boundary_mapping[ul];
		Edxltoken frame_bound = (Edxltoken) mapping[1];
		if (0 == XMLString::compareString(CDXLTokens::XmlstrToken(frame_bound),
										  agg_stage_xml))
		{
			dxl_win_stage = (EdxlWinStage) mapping[0];
			break;
		}
	}
	GPOS_ASSERT(EdxlwinstageSentinel != dxl_win_stage);

	return GPOS_NEW(mp) CDXLScalarWindowRef(
		mp, mdid_func, mdid_return_type, is_distinct, is_star_arg,
		is_simple_agg, dxl_win_stage, win_spec_pos);
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ParseCmpType
//
//	@doc:
//		Parse comparison type
//
//---------------------------------------------------------------------------
IMDType::ECmpType
CDXLOperatorFactory::ParseCmpType(const XMLCh *xml_str_comp_type)
{
	ULONG parse_cmp_type_mapping[][2] = {
		{EdxltokenCmpEq, IMDType::EcmptEq},
		{EdxltokenCmpNeq, IMDType::EcmptNEq},
		{EdxltokenCmpLt, IMDType::EcmptL},
		{EdxltokenCmpLeq, IMDType::EcmptLEq},
		{EdxltokenCmpGt, IMDType::EcmptG},
		{EdxltokenCmpGeq, IMDType::EcmptGEq},
		{EdxltokenCmpIDF, IMDType::EcmptIDF},
		{EdxltokenCmpOther, IMDType::EcmptOther}};

	for (ULONG ul = 0; ul < GPOS_ARRAY_SIZE(parse_cmp_type_mapping); ul++)
	{
		ULONG *mapping = parse_cmp_type_mapping[ul];
		Edxltoken cmp_type = (Edxltoken) mapping[0];

		if (0 == XMLString::compareString(CDXLTokens::XmlstrToken(cmp_type),
										  xml_str_comp_type))
		{
			return (IMDType::ECmpType) mapping[1];
		}
	}

	GPOS_RAISE(
		gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
		CDXLTokens::GetDXLTokenStr(EdxltokenGPDBScalarOpCmpType)->GetBuffer(),
		CDXLTokens::GetDXLTokenStr(EdxltokenGPDBScalarOp)->GetBuffer());
	return (IMDType::ECmpType) IMDType::EcmptOther;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ParseRelationDistPolicy
//
//	@doc:
//		Parse relation distribution policy from XML string
//
//---------------------------------------------------------------------------
IMDRelation::Ereldistrpolicy
CDXLOperatorFactory::ParseRelationDistPolicy(const XMLCh *xml_val)
{
	GPOS_ASSERT(nullptr != xml_val);
	IMDRelation::Ereldistrpolicy rel_distr_policy =
		IMDRelation::EreldistrSentinel;

	if (0 == XMLString::compareString(
				 xml_val, CDXLTokens::XmlstrToken(EdxltokenRelDistrMasterOnly)))
	{
		rel_distr_policy = IMDRelation::EreldistrMasterOnly;
	}
	else if (0 == XMLString::compareString(
					  xml_val, CDXLTokens::XmlstrToken(EdxltokenRelDistrHash)))
	{
		rel_distr_policy = IMDRelation::EreldistrHash;
	}
	else if (0 ==
			 XMLString::compareString(
				 xml_val, CDXLTokens::XmlstrToken(EdxltokenRelDistrRandom)))
	{
		rel_distr_policy = IMDRelation::EreldistrRandom;
	}
	else if (0 ==
			 XMLString::compareString(
				 xml_val, CDXLTokens::XmlstrToken(EdxltokenRelDistrReplicated)))
	{
		rel_distr_policy = IMDRelation::EreldistrReplicated;
	}

	return rel_distr_policy;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ParseRelationStorageType
//
//	@doc:
//		Parse relation storage type from XML string
//
//---------------------------------------------------------------------------
IMDRelation::Erelstoragetype
CDXLOperatorFactory::ParseRelationStorageType(const XMLCh *xml_val)
{
	GPOS_ASSERT(nullptr != xml_val);

	if (0 == XMLString::compareString(
				 xml_val, CDXLTokens::XmlstrToken(EdxltokenRelStorageHeap)))
	{
		return IMDRelation::ErelstorageHeap;
	}

	if (0 == XMLString::compareString(
				 xml_val,
				 CDXLTokens::XmlstrToken(EdxltokenRelStorageAppendOnlyCols)))
	{
		return IMDRelation::ErelstorageAppendOnlyCols;
	}

	if (0 == XMLString::compareString(
				 xml_val,
				 CDXLTokens::XmlstrToken(EdxltokenRelStorageAppendOnlyRows)))
	{
		return IMDRelation::ErelstorageAppendOnlyRows;
	}

	if (0 == XMLString::compareString(
				 xml_val, CDXLTokens::XmlstrToken(EdxltokenRelStorageExternal)))
	{
		return IMDRelation::ErelstorageExternal;
	}

	if (0 == XMLString::compareString(
				 xml_val,
				 CDXLTokens::XmlstrToken(EdxltokenRelStorageMixedPartitioned)))
	{
		return IMDRelation::ErelstorageMixedPartitioned;
	}

	GPOS_ASSERT(!"Unrecognized storage type");

	return IMDRelation::ErelstorageSentinel;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ParseOnCommitActionSpec
//
//	@doc:
//		Parse on commit action spec from XML attributes
//
//---------------------------------------------------------------------------
CDXLCtasStorageOptions::ECtasOnCommitAction
CDXLOperatorFactory::ParseOnCommitActionSpec(const Attributes &attrs)
{
	const XMLCh *xml_val =
		attrs.getValue(CDXLTokens::XmlstrToken(EdxltokenOnCommitAction));

	if (nullptr == xml_val)
	{
		GPOS_RAISE(
			gpdxl::ExmaDXL, gpdxl::ExmiDXLMissingAttribute,
			CDXLTokens::GetDXLTokenStr(EdxltokenOnCommitAction)->GetBuffer(),
			CDXLTokens::GetDXLTokenStr(EdxltokenCTASOptions)->GetBuffer());
	}

	if (0 == XMLString::compareString(
				 xml_val, CDXLTokens::XmlstrToken(EdxltokenOnCommitPreserve)))
	{
		return CDXLCtasStorageOptions::EctascommitPreserve;
	}

	if (0 == XMLString::compareString(
				 xml_val, CDXLTokens::XmlstrToken(EdxltokenOnCommitDelete)))
	{
		return CDXLCtasStorageOptions::EctascommitDelete;
	}

	if (0 == XMLString::compareString(
				 xml_val, CDXLTokens::XmlstrToken(EdxltokenOnCommitDrop)))
	{
		return CDXLCtasStorageOptions::EctascommitDrop;
	}

	if (0 != XMLString::compareString(
				 xml_val, CDXLTokens::XmlstrToken(EdxltokenOnCommitNOOP)))
	{
		GPOS_RAISE(
			gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
			CDXLTokens::GetDXLTokenStr(EdxltokenOnCommitAction)->GetBuffer(),
			CDXLTokens::GetDXLTokenStr(EdxltokenCTASOptions)->GetBuffer());
	}

	return CDXLCtasStorageOptions::EctascommitNOOP;
}

//---------------------------------------------------------------------------
//	@function:
//		CDXLOperatorFactory::ParseIndexType
//
//	@doc:
//		Parse index type from XML attributes
//
//---------------------------------------------------------------------------
IMDIndex::EmdindexType
CDXLOperatorFactory::ParseIndexType(const Attributes &attrs)
{
	const XMLCh *xml_val =
		attrs.getValue(CDXLTokens::XmlstrToken(EdxltokenIndexType));

	if (nullptr == xml_val ||
		0 == XMLString::compareString(
				 xml_val, CDXLTokens::XmlstrToken(EdxltokenIndexTypeBtree)))
	{
		// default_val is btree
		return IMDIndex::EmdindBtree;
	}


	if (0 == XMLString::compareString(
				 xml_val, CDXLTokens::XmlstrToken(EdxltokenIndexTypeBitmap)))
	{
		return IMDIndex::EmdindBitmap;
	}
	else if (0 == XMLString::compareString(
					  xml_val, CDXLTokens::XmlstrToken(EdxltokenIndexTypeGist)))
	{
		return IMDIndex::EmdindGist;
	}
	else if (0 == XMLString::compareString(
					  xml_val, CDXLTokens::XmlstrToken(EdxltokenIndexTypeGin)))
	{
		return IMDIndex::EmdindGin;
	}
	else if (0 == XMLString::compareString(
					  xml_val, CDXLTokens::XmlstrToken(EdxltokenIndexTypeBrin)))
	{
		return IMDIndex::EmdindBrin;
	}

	GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLInvalidAttributeValue,
			   CDXLTokens::GetDXLTokenStr(EdxltokenIndexType)->GetBuffer(),
			   CDXLTokens::GetDXLTokenStr(EdxltokenIndex)->GetBuffer());

	return IMDIndex::EmdindSentinel;
}

// EOF

相关信息

greenplumn 源码目录

相关文章

greenplumn CDXLColDescr 源码

greenplumn CDXLColRef 源码

greenplumn CDXLCtasStorageOptions 源码

greenplumn CDXLDatum 源码

greenplumn CDXLDatumBool 源码

greenplumn CDXLDatumGeneric 源码

greenplumn CDXLDatumInt2 源码

greenplumn CDXLDatumInt4 源码

greenplumn CDXLDatumInt8 源码

greenplumn CDXLDatumOid 源码

0  赞