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