//--------------------------------------------------------------------------- // Greenplum Database // Copyright (C) 2012 EMC Corp. // // @filename: // CQueryMutators.h // // @doc: // Class providing methods for translating a GPDB Query object into a // DXL Tree // // @test: // // //--------------------------------------------------------------------------- #ifndef GPDXL_CWalkerUtils_H #define GPDXL_CWalkerUtils_H #include "gpos/base.h" #include "gpopt/translate/CMappingVarColId.h" #include "gpopt/translate/CTranslatorScalarToDXL.h" #include "gpopt/translate/CTranslatorUtils.h" #include "naucrates/dxl/operators/CDXLNode.h" #include "naucrates/md/IMDType.h" // fwd declarations namespace gpopt { class CMDAccessor; } struct Query; struct RangeTblEntry; struct Const; struct List; namespace gpdxl { //--------------------------------------------------------------------------- // @class: // CQueryMutators // // @doc: // Class providing methods for translating a GPDB Query object into a // DXL Tree. // //--------------------------------------------------------------------------- class CQueryMutators { using MutatorWalkerFn = Node *(*)(Node*, void*); using ExprWalkerFn = BOOL (*)(Node*, void*); using CContextGrpbyPlMutator = struct SContextGrpbyPlMutator { public: // memory pool CMemoryPool *m_mp; // MD accessor to get the function name CMDAccessor *m_mda; // original query Query *m_query; // the new target list of the group by or window (lower) query List *m_lower_table_tlist; // the current query level ULONG m_current_query_level; // indicate the levels up of the aggregate we are mutating ULONG m_agg_levels_up; // indicate whether we are mutating the argument of an aggregate BOOL m_is_mutating_agg_arg; // ctor SContextGrpbyPlMutator(CMemoryPool *mp, CMDAccessor *mda, Query *query, List *derived_table_tlist) : m_mp(mp), m_mda(mda), m_query(query), m_lower_table_tlist(derived_table_tlist), m_current_query_level(0), m_agg_levels_up(gpos::ulong_max), m_is_mutating_agg_arg(false) { } // dtor ~SContextGrpbyPlMutator() = default; }; using CContextIncLevelsupMutator = struct SContextIncLevelsupMutator { public: // the current query level ULONG m_current_query_level; // fix target list entry of the top level BOOL m_should_fix_top_level_target_list; // ctor SContextIncLevelsupMutator(ULONG current_query_level, BOOL should_fix_top_level_target_list) : m_current_query_level(current_query_level), m_should_fix_top_level_target_list( should_fix_top_level_target_list) { } // dtor ~SContextIncLevelsupMutator() = default; }; // context for walker that iterates over the expression in the target entry using CContextTLWalker = struct SContextTLWalker { public: // list of target list entries in the query List *m_target_entries; // list of grouping clauses List *m_group_clause; // ctor SContextTLWalker(List *target_entries, List *group_clause) : m_target_entries(target_entries), m_group_clause(group_clause) { } // dtor ~SContextTLWalker() = default; }; public: // fall back during since the target list refers to a attribute which algebrizer at this point cannot resolve static BOOL ShouldFallback(Node *node, SContextTLWalker *context); // check if the project list contains expressions on aggregates thereby needing normalization static BOOL NeedsProjListNormalization(const Query *query); // normalize query static Query *NormalizeQuery(CMemoryPool *mp, CMDAccessor *md_accessor, const Query *query, ULONG query_level); // check if the project list contains expressions on window operators thereby needing normalization static BOOL NeedsProjListWindowNormalization(const Query *query); // flatten expressions in window operation project list static Query *NormalizeWindowProjList(CMemoryPool *mp, CMDAccessor *md_accessor, const Query *original_query); // traverse the project list to extract all window functions in an arbitrarily complex project element static Node *RunWindowProjListMutator(Node *node, SContextGrpbyPlMutator *context); // flatten expressions in project list static Query *NormalizeGroupByProjList(CMemoryPool *mp, CMDAccessor *md_accessor, const Query *query); // make a copy of the aggref (minus the arguments) static Aggref *FlatCopyAggref(Aggref *aggref); // create a new entry in the derived table and return its corresponding var static Var *MakeVarInDerivedTable(Node *node, SContextGrpbyPlMutator *context); // check if a matching node exists in the list of target entries static Node *FindNodeInGroupByTargetList(Node *node, SContextGrpbyPlMutator *context); // increment the levels up of outer references static Var *IncrLevelsUpIfOuterRef(Var *var); // pull up having clause into a select static Query *NormalizeHaving(CMemoryPool *mp, CMDAccessor *md_accessor, const Query *query); // traverse the expression and fix the levels up of any outer reference static Node *RunIncrLevelsUpMutator(Node *node, SContextIncLevelsupMutator *context); // traverse the expression and fix the levels up of any CTE static BOOL RunFixCTELevelsUpWalker(Node *node, SContextIncLevelsupMutator *context); // mutate the grouping columns, fix levels up when necessary static Node *RunGroupingColMutator(Node *node, SContextGrpbyPlMutator *context); // fix the level up of grouping columns when necessary static Node *FixGroupingCols(Node *node, TargetEntry *original, SContextGrpbyPlMutator *context); // return a target entry for the aggregate expression static TargetEntry *GetTargetEntryForAggExpr(CMemoryPool *mp, CMDAccessor *md_accessor, Node *node, ULONG attno); // traverse the having qual to extract all aggregate functions, // fix correlated vars and return the modified having qual static Node *RunExtractAggregatesMutator(Node *node, SContextGrpbyPlMutator *context); // for a given an TE in the derived table, create a new TE to be added to the top level query static TargetEntry *MakeTopLevelTargetEntry(TargetEntry *target_entry, ULONG attno); // return the column name of the target entry static CHAR *GetTargetEntryColName(TargetEntry *target_entry, Query *query); // make the input query into a derived table and return a new root query static Query *ConvertToDerivedTable(const Query *original_query, BOOL should_fix_target_list, BOOL should_fix_having_qual); // eliminate distinct clause static Query *EliminateDistinctClause(const Query *query); // reassign the sorting clause from the derived table to the new top-level query static void ReassignSortClause(Query *top_level_query, Query *derive_table_query); }; } // namespace gpdxl #endif // GPDXL_CWalkerUtils_H //EOF