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