//--------------------------------------------------------------------------- // Greenplum Database // Copyright (C) 2012 EMC Corp. // // @filename: // CTranslatorUtils.h // // @doc: // Class providing utility methods for translating GPDB's PlannedStmt/Query // into DXL Tree // // @test: // //--------------------------------------------------------------------------- #ifndef GPDXL_CTranslatorUtils_H #define GPDXL_CTranslatorUtils_H #define GPDXL_SYSTEM_COLUMNS 7 extern "C" { #include "postgres.h" #include "access/sdir.h" #include "access/skey.h" #include "nodes/parsenodes.h" } // NOT_EXISTS_SUBLINK is a GPDB extension not present in stock PostgreSQL. // Define it as 100 (matching GPDB's value) so ORCA's subplan translation works. #ifndef NOT_EXISTS_SUBLINK #define NOT_EXISTS_SUBLINK ((SubLinkType) 100) #endif #include "gpos/base.h" #include "gpos/common/CBitSet.h" #include "gpopt/translate/CMappingVarColId.h" #include "naucrates/dxl/CIdGenerator.h" #include "naucrates/dxl/operators/CDXLIndexDescr.h" #include "naucrates/dxl/operators/CDXLLogicalSetOp.h" #include "naucrates/dxl/operators/CDXLLogicalTVF.h" #include "naucrates/dxl/operators/CDXLPhysicalDML.h" #include "naucrates/dxl/operators/CDXLPhysicalMotion.h" #include "naucrates/dxl/operators/CDXLScalarAggref.h" #include "naucrates/dxl/operators/CDXLScalarSubPlan.h" #include "naucrates/md/CMDRelationGPDB.h" #include "naucrates/md/IMDType.h" #include "naucrates/statistics/IStatistics.h" // fwd declarations namespace gpopt { class CMDAccessor; // dynamic array of bitsets using CBitSetArray = CDynamicPtrArray; } // namespace gpopt namespace gpdxl { class CDXLTranslateContext; } namespace gpdxl { using namespace gpopt; enum DistributionHashOpsKind { DistrHashOpsNotDeterminedYet, DistrUseDefaultHashOps, DistrUseLegacyHashOps }; //--------------------------------------------------------------------------- // @class: // CTranslatorUtils // // @doc: // Class providing methods for translating GPDB's PlannedStmt/Query // into DXL Tree // //--------------------------------------------------------------------------- class CTranslatorUtils { private: // Construct a set of column attnos corresponding to a single grouping set // from either a plain GROUP BY or one set in a list of grouping sets static CBitSet *CreateAttnoSetForGroupingSet(CMemoryPool *mp, List *group_elems, ULONG num_cols, UlongToUlongMap *group_col_pos, CBitSet *group_cols, bool use_group_clause); // check if the given mdid array contains any of the polymorphic // types (ANYELEMENT, ANYARRAY) static BOOL ContainsPolymorphicTypes(IMdIdArray *mdid_array); // resolve polymorphic types in the given array of type ids, replacing // them with the actual types obtained from the query static IMdIdArray *ResolvePolymorphicTypes(CMemoryPool *mp, IMdIdArray *return_arg_mdids, List *input_arg_types, FuncExpr *funcexpr); // update grouping col position mappings static void UpdateGrpColMapping(CMemoryPool *mp, UlongToUlongMap *grouping_col_to_pos_map, CBitSet *group_cols, ULONG sort_group_ref); // create a set of grouping sets for a rollup static CBitSetArray *CreateGroupingSetsForRollup( CMemoryPool *mp, const GroupingSet *grouping_set, ULONG num_cols, CBitSet *group_cols, UlongToUlongMap *group_col_pos); // create a set of grouping sets for a cube static CBitSetArray *CreateGroupingSetsForCube( CMemoryPool *mp, const GroupingSet *grouping_set, ULONG num_cols, CBitSet *group_cols, UlongToUlongMap *group_col_pos); // create a set of grouping sets for a grouping sets subclause static CBitSetArray *CreateGroupingSetsForSets( CMemoryPool *mp, const GroupingSet *grouping_set_node, ULONG num_cols, CBitSet *group_cols, UlongToUlongMap *group_col_pos); static CBitSetArray *CreateGroupingSetsForSimple( CMemoryPool *mp, const GroupingSet *grouping_set_node, ULONG num_cols, CBitSet *group_cols, UlongToUlongMap *group_col_pos); public: struct SCmptypeStrategy { IMDType::ECmpType comptype; StrategyNumber strategy_no; }; // get the GPDB scan direction from its corresponding DXL representation static ScanDirection GetScanDirection( EdxlIndexScanDirection idx_scan_direction); // find the n-th column descriptor in the table descriptor static const CDXLColDescr *GetColumnDescrAt( const CDXLTableDescr *table_descr, ULONG pos); // translate the join type from its GPDB representation into the DXL one static EdxlJoinType ConvertToDXLJoinType(JoinType jt); // translate the index scan direction from its GPDB representation into the DXL one static EdxlIndexScanDirection ConvertToDXLIndexScanDirection( ScanDirection sd); // create a DXL index descriptor from an index MD id static CDXLIndexDescr *GetIndexDescr(CMemoryPool *mp, CMDAccessor *md_accessor, IMDId *mdid); // translate a RangeTableEntry into a CDXLTableDescr static CDXLTableDescr *GetTableDescr(CMemoryPool *mp, CMDAccessor *md_accessor, CIdGenerator *id_generator, const RangeTblEntry *rte, const RTEPermissionInfo *perminfo, ULONG assigned_query_id_for_target_rel, BOOL *is_distributed_table = nullptr); // translate a RangeTableEntry into a CDXLLogicalTVF static CDXLLogicalTVF *ConvertToCDXLLogicalTVF(CMemoryPool *mp, CMDAccessor *md_accessor, CIdGenerator *id_generator, const RangeTblEntry *rte); // get column descriptors from a record type static CDXLColDescrArray *GetColumnDescriptorsFromRecord( CMemoryPool *mp, CIdGenerator *id_generator, List *col_names, List *col_types, List *col_type_modifiers); // get column descriptors from a record type static CDXLColDescrArray *GetColumnDescriptorsFromRecord( CMemoryPool *mp, CIdGenerator *id_generator, List *col_names, IMdIdArray *out_arg_types); // get column descriptor from a base type static CDXLColDescrArray *GetColumnDescriptorsFromBase( CMemoryPool *mp, CIdGenerator *id_generator, IMDId *mdid_return_type, INT type_modifier, CMDName *md_name); // get column descriptors from a composite type static CDXLColDescrArray *GetColumnDescriptorsFromComposite( CMemoryPool *mp, CMDAccessor *md_accessor, CIdGenerator *id_generator, const IMDType *md_type); // expand a composite type into an array of IMDColumns static CMDColumnArray *ExpandCompositeType(CMemoryPool *mp, CMDAccessor *md_accessor, const IMDType *md_type); // return the dxl representation of the set operation static EdxlSetOpType GetSetOpType(SetOperation setop, BOOL is_all); // construct a dynamic array of sets of column attnos corresponding // to the group by clause static CBitSetArray *GetColumnAttnosForGroupBy( CMemoryPool *mp, List *group_clause, List *grouping_set_list, bool grouping_distinct, ULONG num_cols, UlongToUlongMap *group_col_pos, CBitSet *group_cold); // return a copy of the query with constant of unknown type being coerced // to the common data type of the output target list static Query *FixUnknownTypeConstant(Query *query, List *target_list); // return the type of the nth non-resjunked target list entry static OID GetTargetListReturnTypeOid(List *target_list, ULONG col_pos); // construct an array of DXL column identifiers for a target list static ULongPtrArray *GenerateColIds(CMemoryPool *mp, List *target_list, IMdIdArray *input_mdids, ULongPtrArray *input_nums, const BOOL *is_outer_ref, CIdGenerator *colid_generator); // construct an array of DXL column descriptors for a target list // using the column ids in the given array static CDXLColDescrArray *GetDXLColumnDescrArray(CMemoryPool *mp, List *target_list, ULongPtrArray *colids, BOOL keep_res_junked); // return the positions of the target list entries included in the output static ULongPtrArray *GetPosInTargetList(CMemoryPool *mp, List *target_list, BOOL keep_res_junked); // construct a column descriptor from the given target entry, column identifier and position in the output static CDXLColDescr *GetColumnDescrAt(CMemoryPool *mp, TargetEntry *target_entry, ULONG colid, ULONG pos); // create a dummy project element to rename the input column identifier static CDXLNode *CreateDummyProjectElem(CMemoryPool *mp, ULONG colid_input, ULONG colid_output, CDXLColDescr *dxl_col_descr); // construct a list of colids corresponding to the given target list // using the given attno->colid map static ULongPtrArray *GetOutputColIdsArray( CMemoryPool *mp, List *target_list, IntToUlongMap *attno_to_colid_map); // construct an array of column ids for the given group by set static ULongPtrArray *GetGroupingColidArray( CMemoryPool *mp, CBitSet *group_by_cols, IntToUlongMap *sort_group_cols_to_colid_map); // return the Colid of column with given index static ULONG GetColId(INT index, IntToUlongMap *index_to_colid_map); // return the corresponding ColId for the given varno, varattno and querylevel static ULONG GetColId(ULONG query_level, INT varno, INT var_attno, IMDId *mdid, CMappingVarColId *var_colid_mapping); // check to see if the target list entry is a sorting column static BOOL IsSortingColumn(const TargetEntry *target_entry, List *sort_clause_list); // check to see if the target list entry is used in the window reference static BOOL IsReferencedInWindowSpec(const TargetEntry *target_entry, List *window_clause_list); // check if the project list contains AggRef with ORDER BY static BOOL HasOrderedAggRefInProjList(CDXLNode *proj_list_dxlnode); // extract a matching target entry that is a window spec static TargetEntry *GetWindowSpecTargetEntry(Node *node, List *window_clause_list, List *target_list); // create a scalar const value expression for the given int8 value static CDXLNode *CreateDXLProjElemFromInt8Const(CMemoryPool *mp, CMDAccessor *md_accessor, INT val); // check to see if the target list entry is a grouping column static BOOL IsGroupingColumn(const TargetEntry *target_entry, List *group_clause_list); // check to see if the target list entry is a grouping column static BOOL IsGroupingColumn(const TargetEntry *target_entry, const SortGroupClause *sort_group_clause); // check if the expression has a matching target entry that is a grouping column static BOOL IsGroupingColumn(Node *node, List *group_clause_list, List *target_list); // extract a matching target entry that is a grouping column static TargetEntry *GetGroupingColumnTargetEntry(Node *node, List *group_clause_list, List *target_list); // convert a list of column ids to a list of attribute numbers using // the provided context with mappings static List *ConvertColidToAttnos(ULongPtrArray *pdrgpul, CDXLTranslateContext *dxl_translate_ctxt); // parse string value into a Long Integer static LINT GetLongFromStr(const CWStringBase *wcstr); // parse string value into an Integer static INT GetIntFromStr(const CWStringBase *wcstr); // check whether the given project list has a project element of the given // operator type static BOOL HasProjElem(CDXLNode *project_list_dxlnode, Edxlopid dxl_op_id); // create a multi-byte character string from a wide character string static CHAR *CreateMultiByteCharStringFromWCString(const WCHAR *wcstr); static UlongToUlongMap *MakeNewToOldColMapping(CMemoryPool *mp, ULongPtrArray *old_colids, ULongPtrArray *new_colids); // check if the given tree contains a subquery static BOOL HasSubquery(Node *node); // check if the given function is a SIRV (single row volatile) that reads // or modifies SQL data static BOOL IsSirvFunc(CMemoryPool *mp, CMDAccessor *md_accessor, OID func_oid); // is this a motion sensitive to duplicates static BOOL IsDuplicateSensitiveMotion( gpdxl::CDXLPhysicalMotion *dxl_motion); // construct a project element with a const NULL expression static CDXLNode *CreateDXLProjElemConstNULL(CMemoryPool *mp, CMDAccessor *md_accessor, IMDId *mdid, ULONG colid, const WCHAR *col_name); // construct a project element with a const NULL expression static CDXLNode *CreateDXLProjElemConstNULL(CMemoryPool *mp, CMDAccessor *md_accessor, IMDId *mdid, ULONG colid, CHAR *alias_name); // create a DXL project element node with a Const NULL of type provided // by the column descriptor static CDXLNode *CreateDXLProjElemConstNULL(CMemoryPool *mp, CMDAccessor *md_accessor, CIdGenerator *colid_generator, const IMDColumn *col); // check required permissions for the range table static void CheckRTEPermissions(List *range_table_list, List *rteperminfos); // check if given column ids are outer references in the tree rooted by given node static void MarkOuterRefs(ULONG *colid, BOOL *is_outer_ref, ULONG num_columns, CDXLNode *node); // map DXL Subplan type to GPDB SubLinkType static SubLinkType MapDXLSubplanToSublinkType( gpdxl::EdxlSubPlanType dxl_subplan_type); // map GPDB SubLinkType to DXL Subplan type static EdxlSubPlanType MapSublinkTypeToDXLSubplan(SubLinkType slink); // check whether there are triggers for the given operation on // the given relation static BOOL RelHasTriggers(CMemoryPool *mp, CMDAccessor *md_accessor, const IMDRelation *mdrel, const gpdxl::EdxlDmlType dml_type_dxl); // check whether the given trigger is applicable to the given DML operation static BOOL IsApplicableTrigger(CMDAccessor *md_accessor, IMDId *trigger_mdid, const gpdxl::EdxlDmlType dml_type_dxl); // check whether there are NOT NULL or CHECK constraints for the given relation static BOOL RelHasConstraints(const IMDRelation *rel); // translate the list of error messages from an assert constraint list static List *GetAssertErrorMsgs(CDXLNode *assert_constraint_list); // return the count of non-system columns in the relation static ULONG GetNumNonSystemColumns(const IMDRelation *mdrel); // return agg kind as an EdxlAggrefKind static EdxlAggrefKind GetAggKind(CHAR aggkind); // return agg kind as a CHAR static CHAR GetAggKind(EdxlAggrefKind aggkind); // check if const func returns composite type static BOOL IsCompositeConst(CMemoryPool *mp, CMDAccessor *md_accessor, const RangeTblFunction *rtfunc); // check if rel contains foreign partitions static BOOL RelContainsForeignPartitions(const IMDRelation *rel, CMDAccessor *md_accessor); }; } // namespace gpdxl #endif // !GPDXL_CTranslatorUtils_H // EOF