iinq.h
Go to the documentation of this file.
1 /******************************************************************************/
35 /******************************************************************************/
36 
37 /*INDENT-OFF*/
38 
39 #if !defined(IINQ_H_)
40 #define IINQ_H_
41 
42 #if defined(__cplusplus)
43 extern "C" {
44 #endif
45 
46 #include "../dictionary/dictionary_types.h"
47 #include "../dictionary/ion_master_table.h"
48 
49 typedef unsigned int ion_iinq_result_size_t;
50 
51 typedef struct {
52  ion_iinq_result_size_t num_bytes;
53  unsigned char *data;
55 
61 
62 #define IINQ_NEW_PROCESSOR_FUNC(name) \
63 void name(ion_iinq_result_t *result, void* state)
64 
65 typedef struct {
67  void *state;
69 
70 #define IINQ_QUERY_PROCESSOR(execute, state) ((ion_iinq_query_processor_t){ execute, state })
71 
73 
74 typedef struct iinq_cleanup {
76  struct iinq_cleanup *next;
77  struct iinq_cleanup *last;
79 
80 struct iinq_source {
90 };
91 
94  char *schema_file_name,
95  ion_key_type_t key_type,
96  ion_key_size_t key_size,
97  ion_value_size_t value_size
98 );
99 
100 ion_err_t
102  char *schema_file_name,
104  ion_dictionary_handler_t *handler
105 );
106 
109  char *schema_file_name,
110  ion_key_t key,
111  ion_value_t value
112 );
113 
116  char *schema_file_name,
117  ion_key_t key,
118  ion_value_t value
119 );
120 
123  char *schema_file_name,
124  ion_key_t key
125 );
126 
127 ion_err_t
128 iinq_drop(
129  char *schema_file_name
130 );
131 
132 #define CREATE_DICTIONARY(schema_name, key_type, key_size, value_size) \
133 iinq_create_source(#schema_name ".inq", key_type, key_size, value_size)
134 
135 #define INSERT(schema_name, key, value) \
136 iinq_insert(#schema_name ".inq", key, value)
137 
138 #define UPDATE(schema_name, key, value) \
139 iinq_insert(#schema_name ".inq", key, value)
140 
141 #define DELETE_FROM(schema_name, key) \
142 iinq_delete(#schema_name ".inq", key)
143 
144 #define DROP(schema_name)\
145 iinq_drop(#schema_name ".inq")
146 
147 #define SELECT_ALL \
148 ion_iinq_result_size_t result_loc = 0; \
149 ion_iinq_cleanup_t *copyer = first; \
150 while (NULL != copyer) { \
151  memcpy(result.data+(result_loc), copyer->reference->key, copyer->reference->dictionary.instance->record.key_size); \
152  result_loc += copyer->reference->dictionary.instance->record.key_size; \
153  memcpy(result.data+(result_loc), copyer->reference->value, copyer->reference->dictionary.instance->record.value_size); \
154  result_loc += copyer->reference->dictionary.instance->record.value_size; \
155  copyer = copyer->next; \
156 }
157 
158 #define _FROM_SOURCE_SINGLE(source) \
159  ion_iinq_source_t source; \
160  source.cleanup.next = NULL; \
161  source.cleanup.last = last; \
162  source.cleanup.reference = &source; \
163  if (NULL == first) { \
164  first = &source.cleanup; \
165  } \
166  if (NULL != last) { \
167  last->next = &source.cleanup; \
168  } \
169  last = &source.cleanup; \
170  source.cleanup.next = NULL; \
171  source.dictionary.handler = &source.handler; \
172  error = iinq_open_source(#source ".inq", &(source.dictionary), &(source.handler)); \
173  if (err_ok != error) { \
174  break; \
175  } \
176  source.key = alloca(source.dictionary.instance->record.key_size); \
177  source.value = alloca(source.dictionary.instance->record.value_size); \
178  source.ion_record.key = source.key; \
179  source.ion_record.value = source.value; \
180  result.num_bytes += source.dictionary.instance->record.key_size; \
181  result.num_bytes += source.dictionary.instance->record.value_size; \
182  error = dictionary_build_predicate(&(source.predicate), predicate_all_records); \
183  if (err_ok != error) { \
184  break; \
185  } \
186  dictionary_find(&source.dictionary, &source.predicate, &source.cursor);
187 
188 #define _FROM_CHECK_CURSOR_SINGLE(source) \
189  (cs_cursor_active == (source.cursor_status = source.cursor->next(source.cursor, &source.ion_record)) || cs_cursor_initialized == source.cursor_status)
190 
191 #define _FROM_ADVANCE_CURSORS \
192  if (NULL == ref_cursor) { \
193  break; \
194  } \
195  last_cursor = ref_cursor; \
196  /* Keep going backwards through sources until we find one we can advance. If we re-initialize any cursors, reset ref_cursor to last. */ \
197  while (NULL != ref_cursor && (cs_cursor_active != (ref_cursor->reference->cursor_status = ref_cursor->reference->cursor->next(ref_cursor->reference->cursor, &ref_cursor->reference->ion_record)) && cs_cursor_initialized != ref_cursor->reference->cursor_status)) { \
198  ref_cursor->reference->cursor->destroy(&ref_cursor->reference->cursor); \
199  dictionary_find(&ref_cursor->reference->dictionary, &ref_cursor->reference->predicate, &ref_cursor->reference->cursor); \
200  if ((cs_cursor_active != (ref_cursor->reference->cursor_status = ref_cursor->reference->cursor->next(ref_cursor->reference->cursor, &ref_cursor->reference->ion_record)) && cs_cursor_initialized != ref_cursor->reference->cursor_status)) { \
201  goto IINQ_QUERY_CLEANUP; \
202  } \
203  ref_cursor = ref_cursor->last; \
204  } \
205  if (NULL == ref_cursor) { \
206  break; \
207  } \
208  else if (last_cursor != ref_cursor) { \
209  ref_cursor = last; \
210  }
211 
212 /* Here we define a number of FROM macros to facilitate up to 8 sources. */
213 #define _FROM_SOURCE_1(_1) _FROM_SOURCE_SINGLE(_1)
214 #define _FROM_SOURCE_2(_1, _2) _FROM_SOURCE_1(_1) _FROM_SOURCE_1(_2)
215 #define _FROM_SOURCE_3(_1, _2, _3) _FROM_SOURCE_2(_1, _2) _FROM_SOURCE_1(_3)
216 #define _FROM_SOURCE_4(_1, _2, _3, _4) _FROM_SOURCE_3(_1, _2, _3) _FROM_SOURCE_1(_4)
217 #define _FROM_SOURCE_5(_1, _2, _3, _4, _5) _FROM_SOURCE_4(_1, _2, _3, _4) _FROM_SOURCE_1(_5)
218 #define _FROM_SOURCE_6(_1, _2, _3, _4, _5, _6) _FROM_SOURCE_5(_1, _2, _3, _4, _5) _FROM_SOURCE_1(_6)
219 #define _FROM_SOURCE_7(_1, _2, _3, _4, _5, _6, _7) _FROM_SOURCE_6(_1, _2, _3, _4, _5, _6) _FROM_SOURCE_1(_7)
220 #define _FROM_SOURCE_8(_1, _2, _3, _4, _5, _6, _7, _8) _FROM_SOURCE_7(_1, _2, _3, _4, _5, _6, _7) _FROM_SOURCE_1(_8)
221 /*
222  * The last parameter, the variable arguments, is a black whole to swallow unused macro names.
223  */
224 #define _FROM_SOURCE_GET_OVERRIDE(_1, _2, _3, _4, _5, _6, _7, _8, MACRO, ...) MACRO
225 /*
226  * So this one is pretty ugly.
227  *
228  * We "slide" the correct macro based on the number of arguments. At the end, we add a comma so that we don't get a
229  * compiler warning when only passing in only ONE argument into the variable argument list.
230 */
231 #define _FROM_SOURCES(...) _FROM_SOURCE_GET_OVERRIDE(__VA_ARGS__, _FROM_SOURCE_8, _FROM_SOURCE_7, _FROM_SOURCE_6, _FROM_SOURCE_5, _FROM_SOURCE_4, _FROM_SOURCE_3, _FROM_SOURCE_2, _FROM_SOURCE_1, THEBLACKWHOLE)(__VA_ARGS__)
232 
233 #define _FROM_CHECK_CURSOR(sources) \
234  _FROM_CHECK_CURSOR_SINGLE(sources)
235 
236 #define FROM(...) \
237  ion_iinq_cleanup_t *first; \
238  ion_iinq_cleanup_t *last; \
239  ion_iinq_cleanup_t *ref_cursor; \
240  ion_iinq_cleanup_t *last_cursor; \
241  first = NULL; \
242  last = NULL; \
243  ref_cursor = NULL; \
244  last_cursor = NULL; \
245  _FROM_SOURCES(__VA_ARGS__) \
246  result.data = alloca(result.num_bytes); \
247  ref_cursor = first; \
248  /* Initialize all cursors except the last one. */ \
249  while (ref_cursor != last) { \
250  if (NULL == ref_cursor || (cs_cursor_active != (ref_cursor->reference->cursor_status = ref_cursor->reference->cursor->next(ref_cursor->reference->cursor, &ref_cursor->reference->ion_record)) && cs_cursor_initialized != ref_cursor->reference->cursor_status)) { \
251  break; \
252  } \
253  ref_cursor = ref_cursor->next; \
254  } \
255  ref_cursor = last; \
256  while (1) { \
257  _FROM_ADVANCE_CURSORS
258 /*if (!_FROM_CHECK_CURSOR(__VA_ARGS__)) {*/ \
259  /* break; */ \
260  /*}*/
261 
262 #define WHERE(condition) (condition)
263 
264 #define QUERY(select, from, where, groupby, having, orderby, limit, when, p) \
265 do { \
266  ion_err_t error; \
267  ion_iinq_result_t result; \
268  result.num_bytes = 0; \
269  from/* This includes a loop declaration with some other stuff. */ \
270  if (!where) { \
271  continue; \
272  } \
273  select \
274  (p)->execute(&result, (p)->state); \
275  } \
276  IINQ_QUERY_CLEANUP: \
277  while (NULL != first) { \
278  first->reference->cursor->destroy(&first->reference->cursor); \
279  ion_close_dictionary(&first->reference->dictionary); \
280  first = first->next; \
281  }\
282 } while (0);
283 
284 #if defined(__cplusplus)
285 }
286 #endif
287 
288 #endif
289 /*INDENT-ON*/
enum ION_KEY_TYPE ion_key_type_t
This is the available key types for ION_DB. All types will be based on system defines.
ion_err_t iinq_open_source(char *schema_file_name, ion_dictionary_t *dictionary, ion_dictionary_handler_t *handler)
Definition: iinq.c:106
int ion_value_size_t
The size (length) of a dictionary value in bytes.
Definition: kv_system.h:256
ion_dict_cursor_t * cursor
Definition: iinq.h:84
Struct used to maintain key and value.
Definition: kv_system.h:315
#define key(k)
Definition: bpp_tree.c:75
ion_value_t value
Definition: iinq.h:87
struct iinq_cleanup ion_iinq_cleanup_t
ion_iinq_result_size_t num_bytes
Definition: iinq.h:52
char ion_err_t
The error type used to store error codes.
Definition: kv_system.h:226
void * ion_key_t
A dictionary key.
Definition: kv_system.h:241
void * ion_value_t
A dictionary value.
Definition: kv_system.h:246
void(* ion_iinq_query_processor_func_t)(ion_iinq_result_t *, void *)
Function pointer type for processing not data modifying IINQ queries.
Definition: iinq.h:60
ion_iinq_source_t * reference
Definition: iinq.h:75
ion_predicate_t predicate
Definition: iinq.h:83
A dictionary contains information regarding an instance of the storage element and the associated han...
A supertype for dictionary cursor objects.
struct iinq_cleanup * next
Definition: iinq.h:76
unsigned char * data
Definition: iinq.h:53
A supertype for cursor predicate objects.
ion_status_t iinq_insert(char *schema_file_name, ion_key_t key, ion_value_t value)
Definition: iinq.c:156
ion_iinq_cleanup_t cleanup
Definition: iinq.h:89
ion_key_t key
Definition: iinq.h:86
ion_status_t iinq_update(char *schema_file_name, ion_key_t key, ion_value_t value)
Definition: iinq.c:186
ion_err_t iinq_drop(char *schema_file_name)
Definition: iinq.c:245
ion_iinq_query_processor_func_t execute
Definition: iinq.h:66
int ion_key_size_t
The size (length) of a dictionary key in bytes.
Definition: kv_system.h:251
ion_record_t ion_record
Definition: iinq.h:88
unsigned int ion_iinq_result_size_t
Definition: iinq.h:49
ion_err_t iinq_create_source(char *schema_file_name, ion_key_type_t key_type, ion_key_size_t key_size, ion_value_size_t value_size)
Definition: iinq.c:42
ion_dictionary_t dictionary
Definition: iinq.h:82
A dictionary_handler is responsible for dealing with the specific interface for an underlying diction...
ion_cursor_status_t cursor_status
Definition: iinq.h:85
ion_status_t iinq_delete(char *schema_file_name, ion_key_t key)
Definition: iinq.c:216
char ion_cursor_status_t
A type for the status of a cursor.
ion_dictionary_handler_t handler
Definition: iinq.h:81
struct iinq_cleanup * last
Definition: iinq.h:77
A status object that describes the result of a dictionary operation.
Definition: kv_system.h:290