All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
as_query.h
Go to the documentation of this file.
1 /*
2  * Copyright 2008-2017 Aerospike, Inc.
3  *
4  * Portions may be licensed to Aerospike, Inc. under one or more contributor
5  * license agreements.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8  * use this file except in compliance with the License. You may obtain a copy of
9  * the License at http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14  * License for the specific language governing permissions and limitations under
15  * the License.
16  */
17 #pragma once
18 #pragma GCC diagnostic ignored "-Waddress"
19 
21 #include <aerospike/as_bin.h>
22 #include <aerospike/as_key.h>
23 #include <aerospike/as_list.h>
24 #include <aerospike/as_predexp.h>
25 #include <aerospike/as_udf.h>
26 
27 #include <stdarg.h>
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 /******************************************************************************
34  * MACROS
35  *****************************************************************************/
36 
37 /**
38  * Macro for setting setting the STRING_EQUAL predicate.
39  *
40  * ~~~~~~~~~~{.c}
41  * as_query_where(query, "bin1", as_string_equals("abc"));
42  * ~~~~~~~~~~
43  *
44  * @relates as_query
45  */
46 #define as_string_equals(__val) AS_PREDICATE_EQUAL, AS_INDEX_TYPE_DEFAULT, AS_INDEX_STRING, __val
47 
48 /**
49  * Macro for setting setting the INTEGER_EQUAL predicate.
50  *
51  * ~~~~~~~~~~{.c}
52  * as_query_where(query, "bin1", as_integer_equals(123));
53  * ~~~~~~~~~~
54  *
55  * @relates as_query
56  */
57 #define as_integer_equals(__val) AS_PREDICATE_EQUAL, AS_INDEX_TYPE_DEFAULT, AS_INDEX_NUMERIC, (int64_t)__val
58 
59 /**
60  * Macro for setting setting the INTEGER_RANGE predicate.
61  *
62  * ~~~~~~~~~~{.c}
63  * as_query_where(query, "bin1", as_integer_range(1,100));
64  * ~~~~~~~~~~
65  *
66  * @relates as_query
67  * @ingroup query_object
68  */
69 #define as_integer_range(__min, __max) AS_PREDICATE_RANGE, AS_INDEX_TYPE_DEFAULT, AS_INDEX_NUMERIC, (int64_t)__min, (int64_t)__max
70 
71 /**
72  * Macro for setting setting the RANGE predicate.
73  *
74  * ~~~~~~~~~~{.c}
75  * as_query_where(query, "bin1", as_range(LIST,NUMERIC,1,100));
76  * ~~~~~~~~~~
77  *
78  * @relates as_query
79  * @ingroup query_object
80  */
81 #define as_range(indextype, datatype, __min, __max) AS_PREDICATE_RANGE, AS_INDEX_TYPE_ ##indextype, AS_INDEX_ ##datatype, __min, __max
82 
83 /**
84  * Macro for setting setting the CONTAINS predicate.
85  *
86  * ~~~~~~~~~~{.c}
87  * as_query_where(query, "bin1", as_contains(LIST,STRING,"val"));
88  * ~~~~~~~~~~
89  *
90  * @relates as_query
91  * @ingroup query_object
92  */
93 #define as_contains(indextype, datatype, __val) AS_PREDICATE_EQUAL, AS_INDEX_TYPE_ ##indextype, AS_INDEX_ ##datatype, __val
94 
95 /**
96  * Macro for setting setting the EQUALS predicate.
97  *
98  * ~~~~~~~~~~{.c}
99  * as_query_where(query, "bin1", as_equals(NUMERIC,5));
100  * ~~~~~~~~~~
101  *
102  * @relates as_query
103  * @ingroup query_object
104  */
105 #define as_equals(datatype, __val) AS_PREDICATE_EQUAL, AS_INDEX_TYPE_DEFAULT, AS_INDEX_ ##datatype, __val
106 
107 #define as_geo_within(__val) AS_PREDICATE_RANGE, AS_INDEX_TYPE_DEFAULT, AS_INDEX_GEO2DSPHERE, __val
108 
109 #define as_geo_contains(__val) AS_PREDICATE_RANGE, AS_INDEX_TYPE_DEFAULT, AS_INDEX_GEO2DSPHERE, __val
110 
111 
112 /******************************************************************************
113  * TYPES
114  *****************************************************************************/
115 
116 /**
117  * Union of supported predicates
118  */
119 typedef union as_predicate_value_u {
120 
121  /**
122  * String Value
123  */
124  char * string;
125 
126  /**
127  * Integer Value
128  */
129  int64_t integer;
130 
131  /**
132  * Integer Range Value
133  */
134  struct {
135 
136  /**
137  * Minimum value
138  */
139  int64_t min;
140 
141  /**
142  * Maximum value
143  */
144  int64_t max;
145 
146  } integer_range;
147 
149 
150 /**
151  * The types of predicates supported.
152  */
153 typedef enum as_predicate_type_e {
154 
155  /**
156  * String Equality Predicate.
157  * Requires as_predicate_value.string to be set.
158  */
160 
163 
164 /**
165  * Defines a predicate, including the bin, type of predicate and the value
166  * for the predicate.
167  */
168 typedef struct as_predicate_s {
169 
170  /**
171  * Bin to apply the predicate to
172  */
174 
175  /**
176  * The predicate type, dictates which values to use from the union
177  */
179 
180  /**
181  * The value for the predicate.
182  */
184 
185  /*
186  * The type of data user wants to query
187  */
188 
190 
191  /*
192  * The type of index predicate is on
193  */
195 } as_predicate;
196 
197 /**
198  * Enumerations defining the direction of an ordering.
199  */
200 typedef enum as_order_e {
201 
202  /**
203  * Ascending order
204  */
206 
207  /**
208  * bin should be in ascending order
209  */
211 
212 } as_order;
213 
214 
215 /**
216  * Defines the direction a bin should be ordered by.
217  */
218 typedef struct as_ordering_s {
219 
220  /**
221  * Name of the bin to sort by
222  */
224 
225  /**
226  * Direction of the sort
227  */
229 
230 } as_ordering;
231 
232 /**
233  * Sequence of bins which should be selected during a query.
234  *
235  * Entries can either be initialized on the stack or on the heap.
236  *
237  * Initialization should be performed via a query object, using:
238  * - as_query_select_init()
239  * - as_query_select_inita()
240  */
241 typedef struct as_query_bins_s {
242 
243  /**
244  * @private
245  * If true, then as_query_destroy() will free this instance.
246  */
247  bool _free;
248 
249  /**
250  * Number of entries allocated
251  */
252  uint16_t capacity;
253 
254  /**
255  * Number of entries used
256  */
257  uint16_t size;
258 
259  /**
260  * Sequence of entries
261  */
263 
264 } as_query_bins;
265 
266 /**
267  * Sequence of predicates to be applied to a query.
268  *
269  * Entries can either be initialized on the stack or on the heap.
270  *
271  * Initialization should be performed via a query object, using:
272  * - as_query_where_init()
273  * - as_query_where_inita()
274  */
275 typedef struct as_query_predicates_s {
276 
277  /**
278  * @private
279  * If true, then as_query_destroy() will free this instance.
280  */
281  bool _free;
282 
283  /**
284  * Number of entries allocated
285  */
286  uint16_t capacity;
287 
288  /**
289  * Number of entries used
290  */
291  uint16_t size;
292 
293  /**
294  * Sequence of entries
295  */
297 
299 
300 /**
301  * Sequence of predicate expressions to be applied to a query.
302  *
303  * Entries can either be initialized on the stack or on the heap.
304  *
305  * Initialization should be performed via a query object, using:
306  * - as_query_predexp_init()
307  * - as_query_predexp_inita()
308  */
309 typedef struct as_query_predexp_s {
310 
311  /**
312  * @private
313  * If true, then as_query_destroy() will free this instance.
314  */
315  bool _free;
316 
317  /**
318  * Number of entries allocated
319  */
320  uint16_t capacity;
321 
322  /**
323  * Number of entries used
324  */
325  uint16_t size;
326 
327  /**
328  * Sequence of entries
329  */
331 
333 
334 /**
335  * Sequence of ordering to be applied to a query results.
336  *
337  * Entries can either be initialized on the stack or on the heap.
338  *
339  * Initialization should be performed via a query object, using:
340  * - as_query_orderby_init()
341  * - as_query_orderby_inita()
342  */
343 typedef struct as_query_sort_s {
344 
345  /**
346  * @private
347  * If true, then as_query_destroy() will free this instance.
348  */
349  bool _free;
350 
351  /**
352  * Number of entries allocated
353  */
354  uint16_t capacity;
355 
356  /**
357  * Number of entries used
358  */
359  uint16_t size;
360 
361  /**
362  * Sequence of entries
363  */
365 
367 
368 
369 /**
370  * The as_query object is used define a query to be executed in the datasbase.
371  *
372  * ## Initialization
373  *
374  * Before using an as_query, it must be initialized via either:
375  * - as_query_init()
376  * - as_query_new()
377  *
378  * as_query_init() should be used on a stack allocated as_query. It will
379  * initialize the as_query with the given namespace and set. On success,
380  * it will return a pointer to the initialized as_query. Otherwise, NULL
381  * is returned.
382  *
383  * ~~~~~~~~~~{.c}
384  * as_query query;
385  * as_query_init(&query, "namespace", "set");
386  * ~~~~~~~~~~
387  *
388  * as_query_new() should be used to allocate and initialize a heap allocated
389  * as_query. It will allocate the as_query, then initialized it with the
390  * given namespace and set. On success, it will return a pointer to the
391  * initialized as_query. Otherwise, NULL is returned.
392  *
393  * ~~~~~~~~~~{.c}
394  * as_query * query = as_query_new("namespace", "set");
395  * ~~~~~~~~~~
396  *
397  * ## Destruction
398  *
399  * When you are finished with the as_query, you can destroy it and associated
400  * resources:
401  *
402  * ~~~~~~~~~~{.c}
403  * as_query_destroy(query);
404  * ~~~~~~~~~~
405  *
406  * ## Usage
407  *
408  * The following explains how to use an as_query to build a query.
409  *
410  * ### Selecting Bins
411  *
412  * as_query_select() is used to specify the bins to be selected by the query.
413  *
414  * ~~~~~~~~~~{.c}
415  * as_query_select(query, "bin1");
416  * as_query_select(query, "bin2");
417  * ~~~~~~~~~~
418  *
419  * Before adding bins to select, the select structure must be initialized via
420  * either:
421  * - as_query_select_inita() - Initializes the structure on the stack.
422  * - as_query_select_init() - Initializes the structure on the heap.
423  *
424  * Both functions are given the number of bins to be selected.
425  *
426  * A complete example using as_query_select_inita()
427  *
428  * ~~~~~~~~~~{.c}
429  * as_query_select_inita(query, 2);
430  * as_query_select(query, "bin1");
431  * as_query_select(query, "bin2");
432  * ~~~~~~~~~~
433  *
434  *
435  * ### Predicates on Bins
436  *
437  * as_query_where() is used to specify predicates to be added to the the query.
438  *
439  * **Note:** Currently, a single where predicate is supported. To do more advanced filtering,
440  * you will want to use a UDF to process the result set on the server.
441  *
442  * ~~~~~~~~~~{.c}
443  * as_query_where(query, "bin1", as_string_equals("abc"));
444  * ~~~~~~~~~~
445  *
446  * The predicates that you can apply to a bin include:
447  * - as_string_equals() - Test for string equality.
448  * - as_integer_equals() - Test for integer equality.
449  * - as_integer_range() - Test for integer within a range.
450  *
451  * Before adding predicates, the where structure must be initialized. To
452  * initialize the where structure, you can choose to use one of the following:
453  * - as_query_where_inita() - Initializes the structure on the stack.
454  * - as_query_where_init() - Initializes the structure on the heap.
455  *
456  * Both functions are given the number of predicates to be added.
457  *
458  * A complete example using as_query_where_inita():
459  *
460  * ~~~~~~~~~~{.c}
461  * as_query_where_inita(query, 1);
462  * as_query_where(query, "bin1", as_string_equals("abc"));
463  * ~~~~~~~~~~
464  *
465  *
466  * ### Sorting Results
467  *
468  * as_query_orderby() is used to specify ordering of results of a query.
469  *
470  * ~~~~~~~~~~{.c}
471  * as_query_orderby(query, "bin1", AS_ORDER_ASCENDING);
472  * ~~~~~~~~~~
473  *
474  * The sort order can be:
475  * - `AS_ORDER_ASCENDING`
476  * - `AS_ORDER_DESCENDING`
477  *
478  * Before adding ordering, the orderby structure must be initialized via
479  * either:
480  * - as_query_orderby_inita() - Initializes the structure on the stack.
481  * - as_query_orderby_init() - Initializes the structure on the heap.
482  *
483  * Both functions are given the number of orderings to be added.
484  *
485  * A complete example using as_query_orderby_inita():
486  *
487  * ~~~~~~~~~~{.c}
488  * as_query_orderby_inita(query, 2);
489  * as_query_orderby(query, "bin1", AS_ORDER_ASCENDING);
490  * as_query_orderby(query, "bin2", AS_ORDER_ASCENDING);
491  * ~~~~~~~~~~
492  *
493  * ### Applying a UDF to Query Results
494  *
495  * A UDF can be applied to the results of a query.
496  *
497  * To define the UDF for the query, use as_query_apply().
498  *
499  * ~~~~~~~~~~{.c}
500  * as_query_apply(query, "udf_module", "udf_function", arglist);
501  * ~~~~~~~~~~
502  *
503  * @ingroup client_objects
504  */
505 typedef struct as_query_s {
506 
507  /**
508  * @private
509  * If true, then as_query_destroy() will free this instance.
510  */
511  bool _free;
512 
513  /**
514  * Namespace to be queried.
515  *
516  * Should be initialized via either:
517  * - as_query_init() - To initialize a stack allocated query.
518  * - as_query_new() - To heap allocate and initialize a query.
519  */
521 
522  /**
523  * Set to be queried.
524  *
525  * Should be initialized via either:
526  * - as_query_init() - To initialize a stack allocated query.
527  * - as_query_new() - To heap allocate and initialize a query.
528  */
530 
531  /**
532  * Name of bins to select.
533  *
534  * Use either of the following function to initialize:
535  * - as_query_select_init() - To initialize on the heap.
536  * - as_query_select_inita() - To initialize on the stack.
537  *
538  * Use as_query_select() to populate.
539  */
541 
542  /**
543  * Predicates for filtering.
544  *
545  * Use either of the following function to initialize:
546  * - as_query_where_init() - To initialize on the heap.
547  * - as_query_where_inita() - To initialize on the stack.
548  *
549  * Use as_query_where() to populate.
550  */
552 
553  /**
554  * Predicate Expressions for filtering.
555  *
556  * Use either of the following function to initialize:
557  * - as_query_predexp_init() - To initialize on the heap.
558  * - as_query_predexp_inita() - To initialize on the stack.
559  *
560  * Use as_query_predexp() to populate.
561  */
563 
564  /**
565  * Bins to order by.
566  *
567  * Use either of the following function to initialize:
568  * - as_query_orderby_init() - To initialize on the heap.
569  * - as_query_orderby_inita() - To initialize on the stack.
570  *
571  * Use as_query_orderby() to populate.
572  */
574 
575  /**
576  * UDF to apply to results of the query
577  *
578  * Should be set via `as_query_apply()`.
579  */
581 
582 } as_query;
583 
584 /******************************************************************************
585  * INSTANCE FUNCTIONS
586  *****************************************************************************/
587 
588 /**
589  * Initialize a stack allocated as_query.
590  *
591  * ~~~~~~~~~~{.c}
592  * as_query query;
593  * as_query_init(&query, "test", "demo");
594  * ~~~~~~~~~~
595  *
596  * @param query The query to initialize.
597  * @param ns The namespace to query.
598  * @param set The set to query.
599  *
600  * @return On success, the initialized query. Otherwise NULL.
601  *
602  * @relates as_query
603  */
604 as_query * as_query_init(as_query * query, const as_namespace ns, const as_set set);
605 
606 /**
607  * Create and initialize a new heap allocated as_query.
608  *
609  * ~~~~~~~~~~{.c}
610  * as_query * query = as_query_new("test", "demo");
611  * ~~~~~~~~~~
612  *
613  * @param ns The namespace to query.
614  * @param set The set to query.
615  *
616  * @return On success, the new query. Otherwise NULL.
617  *
618  * @relates as_query
619  * @ingroup query_object
620  */
621 as_query * as_query_new(const as_namespace ns, const as_set set);
622 
623 /**
624  * Destroy the query and associated resources.
625  *
626  * ~~~~~~~~~~{.c}
627  * as_query_destroy(scan);
628  * ~~~~~~~~~~
629  *
630  * @param query The query to destroy.
631  *
632  * @relates as_query
633  */
634 void as_query_destroy(as_query * query);
635 
636 /******************************************************************************
637  * SELECT FUNCTIONS
638  *****************************************************************************/
639 
640 /**
641  * Initializes `as_query.select` with a capacity of `n` using `alloca`
642  *
643  * For heap allocation, use `as_query_select_init()`.
644  *
645  * ~~~~~~~~~~{.c}
646  * as_query_select_inita(&query, 2);
647  * as_query_select(&query, "bin1");
648  * as_query_select(&query, "bin2");
649  * ~~~~~~~~~~
650  *
651  * @param __query The query to initialize.
652  * @param __n The number of bins to allocate.
653  *
654  * @relates as_query
655  * @ingroup query_object
656  */
657 #define as_query_select_inita(__query, __n) \
658  do { \
659  if ( (__query) != NULL && (__query)->select.entries == NULL ) {\
660  (__query)->select.entries = (as_bin_name*) alloca(sizeof(as_bin_name) * (__n));\
661  if ( (__query)->select.entries ) { \
662  (__query)->select._free = false;\
663  (__query)->select.capacity = (__n);\
664  (__query)->select.size = 0;\
665  }\
666  } \
667  } while(0)
668 
669 /**
670  * Initializes `as_query.select` with a capacity of `n` using `malloc()`.
671  *
672  * For stack allocation, use `as_query_select_inita()`.
673  *
674  * ~~~~~~~~~~{.c}
675  * as_query_select_init(&query, 2);
676  * as_query_select(&query, "bin1");
677  * as_query_select(&query, "bin2");
678  * ~~~~~~~~~~
679  *
680  * @param query The query to initialize.
681  * @param n The number of bins to allocate.
682  *
683  * @return On success, the initialized. Otherwise an error occurred.
684  *
685  * @relates as_query
686  * @ingroup query_object
687  */
688 bool as_query_select_init(as_query * query, uint16_t n);
689 
690 /**
691  * Select bins to be projected from matching records.
692  *
693  * You have to ensure as_query.select has sufficient capacity, prior to
694  * adding a bin. If capacity is sufficient then false is returned.
695  *
696  * ~~~~~~~~~~{.c}
697  * as_query_select_init(&query, 2);
698  * as_query_select(&query, "bin1");
699  * as_query_select(&query, "bin2");
700  * ~~~~~~~~~~
701  *
702  * @param query The query to modify.
703  * @param bin The name of the bin to select.
704  *
705  * @return On success, true. Otherwise an error occurred.
706  *
707  * @relates as_query
708  * @ingroup query_object
709  */
710 bool as_query_select(as_query * query, const char * bin);
711 
712 /******************************************************************************
713  * WHERE FUNCTIONS
714  *****************************************************************************/
715 
716 /**
717  * Initializes `as_query.where` with a capacity of `n` using `alloca()`.
718  *
719  * For heap allocation, use `as_query_where_init()`.
720  *
721  * ~~~~~~~~~~{.c}
722  * as_query_where_inita(&query, 3);
723  * as_query_where(&query, "bin1", as_string_equals("abc"));
724  * as_query_where(&query, "bin2", as_integer_equals(123));
725  * as_query_where(&query, "bin3", as_integer_range(0,123));
726  * ~~~~~~~~~~
727  *
728  * @param __query The query to initialize.
729  * @param __n The number of as_predicate to allocate.
730  *
731  * @return On success, true. Otherwise an error occurred.
732  *
733  * @relates as_query
734  */
735 #define as_query_where_inita(__query, __n) \
736  do { \
737  if ( (__query) != NULL && (__query)->where.entries == NULL ) {\
738  (__query)->where.entries = (as_predicate*) alloca(sizeof(as_predicate) * (__n));\
739  if ( (__query)->where.entries ) { \
740  (__query)->where._free = false;\
741  (__query)->where.capacity = (__n);\
742  (__query)->where.size = 0;\
743  }\
744  } \
745  } while(0)
746 
747 /**
748  * Initializes `as_query.where` with a capacity of `n` using `malloc()`.
749  *
750  * For stack allocation, use `as_query_where_inita()`.
751  *
752  * ~~~~~~~~~~{.c}
753  * as_query_where_init(&query, 3);
754  * as_query_where(&query, "bin1", as_string_equals("abc"));
755  * as_query_where(&query, "bin1", as_integer_equals(123));
756  * as_query_where(&query, "bin1", as_integer_range(0,123));
757  * ~~~~~~~~~~
758  *
759  * @param query The query to initialize.
760  * @param n The number of as_predicate to allocate.
761  *
762  * @return On success, true. Otherwise an error occurred.
763  *
764  * @relates as_query
765  */
766 bool as_query_where_init(as_query * query, uint16_t n);
767 
768 /**
769  * Add a predicate to the query.
770  *
771  * You have to ensure as_query.where has sufficient capacity, prior to
772  * adding a predicate. If capacity is insufficient then false is returned.
773  *
774  * String predicates are not owned by as_query. If the string is allocated
775  * on the heap, the caller is responsible for freeing the string after the query
776  * has been executed. as_query_destroy() will not free this string predicate.
777  *
778  * ~~~~~~~~~~{.c}
779  * as_query_where_init(&query, 3);
780  * as_query_where(&query, "bin1", as_string_equals("abc"));
781  * as_query_where(&query, "bin1", as_integer_equals(123));
782  * as_query_where(&query, "bin1", as_integer_range(0,123));
783  * ~~~~~~~~~~
784  *
785  * @param query The query add the predicate to.
786  * @param bin The name of the bin the predicate will apply to.
787  * @param type The type of predicate.
788  * @param itype The type of index.
789  * @param dtype The underlying data type that the index is based on.
790  * @param ... The values for the predicate.
791  *
792  * @return On success, true. Otherwise an error occurred.
793  *
794  * @relates as_query
795  */
796 bool as_query_where(as_query * query, const char * bin, as_predicate_type type, as_index_type itype, as_index_datatype dtype, ... );
797 
798 /******************************************************************************
799  * PREDEXP FUNCTIONS
800  *****************************************************************************/
801 
802 /**
803  * Initializes `as_query.predexp` with a capacity of `n` using `alloca`
804  *
805  * For heap allocation, use `as_query_predexp_init()`.
806  *
807  * ~~~~~~~~~~{.c}
808  * as_query_predexp_inita(&query, 3);
809  * as_query_predexp_add(&query, as_predexp_string_value("apple"));
810  * as_query_predexp_add(&query, as_predexp_string_bin("fruit"));
811  * as_query_predexp_add(&query, as_predexp_string_equal());
812  * ~~~~~~~~~~
813  *
814  * @param __query The query to initialize.
815  * @param __n The number of predicate expression slots to allocate.
816  *
817  * @relates as_query
818  * @ingroup query_object
819  */
820 #define as_query_predexp_inita(__query, __n) \
821  if ( (__query) != NULL && (__query)->predexp.entries == NULL ) { \
822  (__query)->predexp.entries = \
823  (as_predexp_base **) \
824  alloca(__n * sizeof(as_predexp_base *)); \
825  if ( (__query)->predexp.entries ) { \
826  (__query)->predexp._free = false; \
827  (__query)->predexp.capacity = __n; \
828  (__query)->predexp.size = 0; \
829  } \
830  }
831 
832 /**
833  * Initializes `as_query.predexp` with a capacity of `n` using `malloc()`.
834  *
835  * For stack allocation, use `as_query_predexp_inita()`.
836  *
837  * ~~~~~~~~~~{.c}
838  * as_query_predexp_init(&query, 3);
839  * as_query_predexp_add(&query, as_predexp_string_value("apple"));
840  * as_query_predexp_add(&query, as_predexp_string_bin("fruit"));
841  * as_query_predexp_add(&query, as_predexp_string_equal());
842  * ~~~~~~~~~~
843  *
844  * @param query The query to initialize.
845  * @param n The number of predicate expression slots to allocate.
846  *
847  * @return On success, the initialized. Otherwise an error occurred.
848  *
849  * @relates as_query
850  * @ingroup query_object
851  */
852 bool as_query_predexp_init(as_query * query, uint16_t n);
853 
854 /**
855  * Adds predicate expressions to a query.
856  *
857  * You have to ensure as_query.predexp has sufficient capacity, prior to
858  * adding a predexp. If capacity is sufficient then false is returned.
859  *
860  * ~~~~~~~~~~{.c}
861  * as_query_predexp_inita(&query, 3);
862  * as_query_predexp_add(&query, as_predexp_string_value("apple"));
863  * as_query_predexp_add(&query, as_predexp_string_bin("fruit"));
864  * as_query_predexp_add(&query, as_predexp_string_equal());
865  * ~~~~~~~~~~
866  *
867  * @param query The query to modify.
868  * @param predexp Pointer to a constructed predicate expression.
869  *
870  * @return On success, true. Otherwise an error occurred.
871  *
872  * @relates as_query
873  * @ingroup query_object
874  */
875 bool as_query_predexp_add(as_query * query, as_predexp_base * predexp);
876 
877 /******************************************************************************
878  * ORDERBY FUNCTIONS
879  *****************************************************************************/
880 
881 /**
882  * Initializes `as_query.where` with a capacity of `n` using `alloca()`.
883  *
884  * For heap allocation, use `as_query_where_init()`.
885  *
886  * ~~~~~~~~~~{.c}
887  * as_query_orderby_inita(&query, 1);
888  * as_query_orderby(&query, "bin1", AS_ORDER_ASCENDING);
889  * ~~~~~~~~~~
890  *
891  * @param __query The query to initialize.
892  * @param __n The number of as_orders to allocate.
893  *
894  * @return On success, true. Otherwise an error occurred.
895  *
896  * @relates as_query
897  */
898 #define as_query_orderby_inita(__query, __n) \
899  do { \
900  if ( (__query) != NULL && (__query)->orderby.entries == NULL ) {\
901  (__query)->orderby.entries = (as_ordering*) alloca(sizeof(as_ordering) * (__n));\
902  if ( (__query)->orderby.entries ) { \
903  (__query)->orderby._free = false;\
904  (__query)->orderby.capacity = (__n);\
905  (__query)->orderby.size = 0;\
906  }\
907  } \
908  } while(0)
909 
910 /**
911  * Initializes `as_query.orderby` with a capacity of `n` using `malloc()`.
912  *
913  * For stack allocation, use `as_query_orderby_inita()`.
914  *
915  * ~~~~~~~~~~{.c}
916  * as_query_orderby_init(&query, 1);
917  * as_query_orderby(&query, "bin1", AS_ORDER_ASCENDING);
918  * ~~~~~~~~~~
919  *
920  * @param query The query to initialize.
921  * @param n The number of as_orders to allocate.
922  *
923  * @return On success, true. Otherwise an error occurred.
924  *
925  * @relates as_query
926  */
927 bool as_query_orderby_init(as_query * query, uint16_t n);
928 
929 /**
930  * Add a bin to sort by to the query.
931  *
932  * You have to ensure as_query.orderby has sufficient capacity, prior to
933  * adding an ordering. If capacity is insufficient then false is returned.
934  *
935  * ~~~~~~~~~~{.c}
936  * as_query_orderby_init(&query, 1);
937  * as_query_orderby(&query, "bin1", AS_ORDER_ASCENDING);
938  * ~~~~~~~~~~
939  *
940  * @param query The query to modify.
941  * @param bin The name of the bin to sort by.
942  * @param order The sort order: `AS_ORDER_ASCENDING` or `AS_ORDER_DESCENDING`.
943  *
944  * @return On success, true. Otherwise an error occurred.
945  *
946  * @relates as_query
947  */
948 bool as_query_orderby(as_query * query, const char * bin, as_order order);
949 
950 /******************************************************************************
951  * QUERY MODIFIER FUNCTIONS
952  *****************************************************************************/
953 
954 /**
955  * Apply a function to the results of the query.
956  *
957  * ~~~~~~~~~~{.c}
958  * as_query_apply(&query, "my_module", "my_function", NULL);
959  * ~~~~~~~~~~
960  *
961  * @param query The query to apply the function to.
962  * @param module The module containing the function to invoke.
963  * @param function The function in the module to invoke.
964  * @param arglist The arguments to use when calling the function.
965  *
966  * @return On success, true. Otherwise an error occurred.
967  *
968  * @relates as_query
969  */
970 bool as_query_apply(as_query * query, const char * module, const char * function, const as_list * arglist);
971 
972 #ifdef __cplusplus
973 } // end extern "C"
974 #endif