CQueryMutators.h 7.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
//---------------------------------------------------------------------------
//	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 "gpopt/translate/CMappingVarColId.h"
#include "gpopt/translate/CTranslatorScalarToDXL.h"
#include "gpopt/translate/CTranslatorUtils.h"

#include "gpos/base.h"

26 27 28
#include "naucrates/dxl/operators/CDXLNode.h"
#include "naucrates/md/IMDType.h"
#include "naucrates/md/IMDType.h"
29 30 31 32

// fwd declarations
namespace gpopt
{
J
Jesse Zhang 已提交
33
class CMDAccessor;
34 35 36 37 38 39 40 41 42 43
}

struct Query;
struct RangeTblEntry;
struct Const;
struct List;


namespace gpdxl
{
J
Jesse Zhang 已提交
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
//---------------------------------------------------------------------------
//	@class:
//		CQueryMutators
//
//	@doc:
//		Class providing methods for translating a GPDB Query object into a
//      DXL Tree.
//
//---------------------------------------------------------------------------
class CQueryMutators
{
	typedef Node *(*MutatorWalkerFn)();
	typedef BOOL (*FallbackWalkerFn)();

	typedef struct SContextGrpbyPlMutator
59
	{
J
Jesse Zhang 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
	public:
		// memory pool
		CMemoryPool *m_mp;

		// MD accessor to get the function name
		CMDAccessor *m_mda;

		// original query
		// XXX I don't think this is really needed
		Query *m_query;

		// the new target list of the group by (derived) query
		List *m_derived_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;

		// indice whether we are mutating the argument of a window function
		BOOL m_is_mutating_window_arg;

		// ctor
		SContextGrpbyPlMutator(CMemoryPool *mp, CMDAccessor *mda, Query *query,
							   List *derived_query_tlist)
			: m_mp(mp),
			  m_mda(mda),
			  m_query(query),
			  m_derived_table_tlist(derived_query_tlist),
			  m_current_query_level(0),
			  m_agg_levels_up(gpos::ulong_max),
			  m_is_mutating_agg_arg(false),
			  m_is_mutating_window_arg(false)
		{
		}
99

J
Jesse Zhang 已提交
100 101
		// dtor
		~SContextGrpbyPlMutator()
102
		{
J
Jesse Zhang 已提交
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
		}

	} CContextGrpbyPlMutator;

	typedef 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()
127
		{
J
Jesse Zhang 已提交
128 129 130 131 132 133 134 135 136 137
		}

	} CContextIncLevelsupMutator;

	// context for walker that iterates over the expression in the target entry
	typedef struct SContextTLWalker
	{
	public:
		// list of target list entries in the query
		List *m_target_entries;
138

J
Jesse Zhang 已提交
139 140
		// list of grouping clauses
		List *m_group_clause;
141

J
Jesse Zhang 已提交
142 143 144 145 146
		// ctor
		SContextTLWalker(List *target_entries, List *group_clause)
			: m_target_entries(target_entries), m_group_clause(group_clause)
		{
		}
147

J
Jesse Zhang 已提交
148 149 150 151
		// dtor
		~SContextTLWalker()
		{
		}
152

J
Jesse Zhang 已提交
153
	} CContextTLWalker;
154

J
Jesse Zhang 已提交
155 156 157 158
private:
	// check if the cte levels up needs to be corrected
	static BOOL NeedsLevelsUpCorrection(SContextIncLevelsupMutator *context,
										Index cte_levels_up);
159

J
Jesse Zhang 已提交
160 161 162
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);
163

J
Jesse Zhang 已提交
164 165
	// check if the project list contains expressions on aggregates thereby needing normalization
	static BOOL NeedsProjListNormalization(const Query *query);
166

J
Jesse Zhang 已提交
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
	// 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 *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);

	// make a copy of the window function (minus the arguments)
	static WindowRef *FlatCopyWindowRef(WindowRef *old_windowref);

	// 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 Node *RunFixCTELevelsUpMutator(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 or percentile expression
	static TargetEntry *PteAggregateOrPercentileExpr(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 *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);

	// fix window frame edge boundary when its value is defined by a subquery
	static Query *PqueryFixWindowFrameEdgeBoundary(const Query *pquery);
};
}  // namespace gpdxl
#endif	// GPDXL_CWalkerUtils_H
259 260

//EOF