1 #ifndef AGGREGATE_PLAN_H_
2 #define AGGREGATE_PLAN_H_
3 #include <value.h>
4 #include <rlookup.h>
5 #include <search_options.h>
6 #include <aggregate/expr/expression.h>
7 #include <util/dllist.h>
8
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12
13 typedef struct AGGPlan AGGPlan, AggregatePlan;
14
15 typedef enum {
16 PLN_T_INVALID = 0,
17 PLN_T_ROOT = 1,
18 PLN_T_GROUP,
19 PLN_T_DISTRIBUTE,
20 PLN_T_FILTER,
21 PLN_T_APPLY,
22 PLN_T_ARRANGE,
23 PLN_T_LOAD,
24 PLN_T__MAX
25 } PLN_StepType;
26
27 #define PLANTYPE_ANY_REDUCER (PLN_T__MAX + 1)
28
29 typedef enum {
30 PLN_F_ALIAS = 0x01, // Plan step has an alias
31
32 // Plan step is a reducer. This does not mean it uses a reduce function, but
33 // rather that it fundamentally modifies the rows.
34 PLN_F_REDUCER = 0x02,
35
36 // Plan to load all fields by RPLoader
37 PLN_F_LOAD_ALL = 0x04,
38 } PlanFlags;
39
40 typedef struct PLN_BaseStep {
41 DLLIST_node llnodePln; // Linked list node for previous/next
42
43 PLN_StepType type : 32;
44 uint32_t flags; // PLN_F_XXX
45
46 const char *alias;
47 // Called to destroy step-specific data
48 void (*dtor)(struct PLN_BaseStep *);
49
50 // Called to yield the lookup structure for the given step. If this object
51 // does not have a lookup, can be set to NULL.
52 RLookup *(*getLookup)(struct PLN_BaseStep *);
53
54 // Type specific stuff goes here..
55 } PLN_BaseStep;
56
57 #define PLN_NEXT_STEP(step) DLLIST_ITEM((step)->llnodePln.next, PLN_BaseStep, llnodePln)
58 #define PLN_PREV_STEP(step) DLLIST_ITEM((step)->llnodePln.prev, PLN_BaseStep, llnodePln)
59
60 /**
61 * JUNCTION/REDUCTION POINTS
62 *
63 * While generally the plan steps are serial, in which they transform rows, some
64 * steps may reduce rows and modify them, so that the rows do not really match
65 * one another.
66 */
67
68 /**
69 * First step. This contains the lookup used for the initial document keys.
70 */
71 typedef struct {
72 PLN_BaseStep base;
73 RLookup lookup;
74 } PLN_FirstStep;
75
76 typedef struct {
77 PLN_BaseStep base;
78 const char *rawExpr;
79 RSExpr *parsedExpr;
80 int shouldFreeRaw; // Whether we own the raw expression, used on coordinator only
81 } PLN_MapFilterStep;
82
83 // Magic value -- will sort by score. For use in SEARCH mode
84 #define PLN_SORTKEYS_DFLSCORE (const char **)0xdeadbeef
85
86 /** ARRANGE covers sort, limit, and so on */
87 typedef struct {
88 PLN_BaseStep base;
89 const RLookupKey **sortkeysLK; // simple array
90 const char **sortKeys; // array_*
91 uint64_t sortAscMap; // Mapping of ascending/descending. Bitwise
92 int isLimited; // Flag if `LIMIT` keyward was used.
93 uint64_t offset; // Seek results. If 0, then no paging is applied
94 uint64_t limit; // Number of rows to output
95 } PLN_ArrangeStep;
96
97 /** LOAD covers any fields not implicitly found within the document */
98 typedef struct {
99 PLN_BaseStep base;
100 ArgsCursor args;
101 const RLookupKey **keys;
102 size_t nkeys;
103 } PLN_LoadStep;
104
105 /* Group step - group by properties and reduce by several reducers */
106 typedef struct {
107 PLN_BaseStep base;
108 RLookup lookup;
109
110 const char **properties;
111 size_t nproperties;
112
113 /* Group step single reducer, a function and its args */
114 struct PLN_Reducer {
115 const char *name; // Name of function
116 char *alias; // Output key
117 ArgsCursor args;
118 } * reducers;
119 int idx;
120 } PLN_GroupStep;
121
122 /**
123 * Returns a new group step with the appropriate constructor
124 */
125 PLN_GroupStep *PLNGroupStep_New(const char **props, size_t nprops);
126
127 /**
128 * Adds a reducer (with its arguments) to the group step
129 * @param gstp the group step
130 * @param name the name of the reducer
131 * @param ac arguments to the reducer; if an alias is used, it is provided
132 * here as well.
133 */
134 int PLNGroupStep_AddReducer(PLN_GroupStep *gstp, const char *name, ArgsCursor *ac,
135 QueryError *status);
136
137 PLN_MapFilterStep *PLNMapFilterStep_New(const char *expr, int mode);
138
139 #ifdef __cplusplus
140 typedef PLN_GroupStep::PLN_Reducer PLN_Reducer;
141 #else
142 typedef struct PLN_Reducer PLN_Reducer;
143 #endif
144
145 /* A plan is a linked list of all steps */
146 struct AGGPlan {
147 DLLIST steps;
148 PLN_ArrangeStep *arrangement;
149 PLN_FirstStep firstStep_s; // Storage for initial plan
150 uint64_t steptypes; // Mask of step-types contained in plan
151 };
152
153 /* Serialize the plan into an array of string args, to create a command to be sent over the network.
154 * The strings need to be freed with free and the array needs to be freed with array_free(). The
155 * length can be extracted with array_len */
156 array_t AGPLN_Serialize(const AGGPlan *plan);
157
158 /* Free the plan resources, not the plan itself */
159 void AGPLN_Free(AGGPlan *plan);
160
161 void AGPLN_Init(AGGPlan *plan);
162
163 /* Frees all the steps within the plan */
164 void AGPLN_FreeSteps(AGGPlan *pln);
165
166 void AGPLN_AddStep(AGGPlan *plan, PLN_BaseStep *step);
167 void AGPLN_AddBefore(AGGPlan *pln, PLN_BaseStep *step, PLN_BaseStep *add);
168 void AGPLN_AddAfter(AGGPlan *pln, PLN_BaseStep *step, PLN_BaseStep *add);
169 void AGPLN_Prepend(AGGPlan *pln, PLN_BaseStep *newstp);
170
171 /* Removes the step from the plan */
172 void AGPLN_PopStep(AGGPlan *pln, PLN_BaseStep *step);
173
174 /** Checks if a step with the given type is contained within the plan */
175 int AGPLN_HasStep(const AGGPlan *pln, PLN_StepType t);
176 /**
177 * Gets the last arrange step for the current pipeline stage. If no arrange
178 * step exists, return NULL.
179 *
180 */
181 PLN_ArrangeStep *AGPLN_GetArrangeStep(AGGPlan *pln);
182
183 /**
184 * Gets the last arrange step for the current pipeline stage. If no arrange
185 * step exists, one is created.
186 *
187 * This function should be used to limit/page through the current step
188 */
189 PLN_ArrangeStep *AGPLN_GetOrCreateArrangeStep(AGGPlan *pln);
190
191 /**
192 * Locate a plan within the given constraints. begin and end are the plan ranges
193 * to check. `end` is considered exclusive while `begin` is inclusive. To search
194 * the entire plan, set `begin` and `end` to NULL.
195 *
196 * @param pln the plan to search
197 * @param begin step to start searching from
198 * @param end step to stop searching at
199 * @param type type of plan to search for. The special PLANTYPE_ANY_REDUCER
200 * can be used for any plan type which creates a new RLookup
201 */
202 const PLN_BaseStep *AGPLN_FindStep(const AGGPlan *pln, const PLN_BaseStep *begin,
203 const PLN_BaseStep *end, PLN_StepType type);
204
205 typedef enum {
206 // Get the root lookup, stopping at stp if provided
207 AGPLN_GETLOOKUP_FIRST,
208
209 // Gets the previous lookup in respect to stp
210 AGPLN_GETLOOKUP_PREV,
211
212 // Get the last lookup, stopping at bstp
213 AGPLN_GETLOOKUP_LAST,
214
215 // Get the next lookup, starting from bstp
216 AGPLN_GETLOOKUP_NEXT
217 } AGPLNGetLookupMode;
218 /**
219 * Get the lookup provided the given mode
220 * @param pln the plan containing the steps
221 * @param bstp - acts as a placeholder for iteration. If mode is FIRST, then
222 * this acts as a barrier and no lookups after this step are returned. If mode
223 * is LAST, then this acts as an initializer, and steps before this (inclusive)
224 * are ignored (NYI).
225 */
226 RLookup *AGPLN_GetLookup(const AGGPlan *pln, const PLN_BaseStep *bstp, AGPLNGetLookupMode mode);
227
228 void AGPLN_Dump(const AGGPlan *pln);
229
230 /**
231 * Determines if the plan is a 'reduce' type. A 'reduce' plan is one which
232 * consumes (in entirety) all of its inputs and produces a new output (and thus
233 * a new 'Lookup' table)
234 */
PLN_IsReduce(const PLN_BaseStep * pln)235 static inline int PLN_IsReduce(const PLN_BaseStep *pln) {
236 switch (pln->type) {
237 case PLN_T_ROOT:
238 case PLN_T_GROUP:
239 return 1;
240 default:
241 return 0;
242 }
243 }
244
245 #ifdef __cplusplus
246 }
247 #endif
248 #endif
249