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