1 /*
2  * (C) Copyright 2005- ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  *
7  * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
8  * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
9  */
10 
11 /*
12  *
13  * Description: grib database routines
14  *
15  */
16 #include "grib_api_internal.h"
17 #define GRIB_START_ARRAY_SIZE 5000
18 #define GRIB_ARRAY_INCREMENT 1000
19 
20 #define SWAP(a, b) \
21     temp = (a);    \
22     (a)  = (b);    \
23     (b)  = temp;
24 
25 #define GRIB_ORDER_BY_ASC 1
26 #define GRIB_ORDER_BY_DESC -1
27 
28 /* Note: A fast cut-down version of strcmp which does NOT return -1 */
29 /* 0 means input strings are equal and 1 means not equal */
grib_inline_strcmp(const char * a,const char * b)30 GRIB_INLINE static int grib_inline_strcmp(const char* a, const char* b)
31 {
32     if (*a != *b)
33         return 1;
34     while ((*a != 0 && *b != 0) && *(a) == *(b)) {
35         a++;
36         b++;
37     }
38     return (*a == 0 && *b == 0) ? 0 : 1;
39 }
40 
41 static int grib_db_new_column(grib_db* db, int id, char* key, int type);
42 static void grib_db_delete_columns(grib_db* db);
43 static int grib_db_columns_resize(grib_db* db, size_t newsize);
44 static int grib_db_column_copy_from_handle(grib_handle* h, grib_db* db, int i);
45 static grib_db* grib_db_create_from_keys(grib_context* c, char** keys, int nkeys, int* err);
46 static void grib_fieldset* grib_db_fieldset_create(grib_db* db, int* err);
47 static int grib_fieldset_compare(grib_fieldset* set, int* i, int* j);
48 static void grib_db_sort(grib_set* set, int beg, int theEnd);
49 static grib_order_by* grib_db_new_order_by(grib_context* c, char* obstr);
50 static void grib_db_delete_order_by(grib_context* c, grib_order_by* order_by);
51 static int grib_db_resize(grib_db* db, size_t newsize);
52 static int grib_db_resize_fields(grib_db* db, size_t newsize);
53 
54 
55 /* --------------- grib_column functions ------------------*/
grib_db_new_column(grib_db * db,int id,char * key,int type)56 static int grib_db_new_column(grib_db* db, int id, char* key, int type)
57 {
58     grib_column* column = 0;
59     grib_context* c;
60     int err = 0;
61 
62     if (!db)
63         return GRIB_INVALID_ARGUMENT;
64 
65     c = db->context;
66 
67     db->columns[id].errors = (int*)grib_context_malloc(c,
68                                                        sizeof(int) * GRIB_START_ARRAY_SIZE);
69 
70     switch (type) {
71         case GRIB_TYPE_LONG:
72             db->columns[id].long_values = (long*)grib_context_malloc(c,
73                                                                      sizeof(long) * GRIB_START_ARRAY_SIZE);
74             if (!db->columns[id].long_values) {
75                 grib_context_log(c, GRIB_LOG_ERROR,
76                                  "grib_db_new_column : Cannot malloc %d bytes",
77                                  sizeof(long) * GRIB_START_ARRAY_SIZE);
78                 err = GRIB_OUT_OF_MEMORY;
79                 return err;
80             }
81             break;
82         case GRIB_TYPE_DOUBLE:
83             db->columns[id].double_values = (double*)grib_context_malloc(c,
84                                                                          sizeof(double) * GRIB_START_ARRAY_SIZE);
85             if (!db->columns[id].double_values) {
86                 grib_context_log(c, GRIB_LOG_ERROR,
87                                  "grib_db_new_column : Cannot malloc %d bytes",
88                                  sizeof(double) * GRIB_START_ARRAY_SIZE);
89                 err = GRIB_OUT_OF_MEMORY;
90                 return err;
91             }
92             break;
93         case GRIB_TYPE_STRING:
94             db->columns[id].string_values = (char**)grib_context_malloc(c,
95                                                                         sizeof(char*) * GRIB_START_ARRAY_SIZE);
96             if (!db->columns[id].string_values) {
97                 grib_context_log(c, GRIB_LOG_ERROR,
98                                  "grib_db_new_column : Cannot malloc %d bytes",
99                                  sizeof(char*) * GRIB_START_ARRAY_SIZE);
100                 err = GRIB_OUT_OF_MEMORY;
101                 return err;
102             }
103             break;
104         default:
105             grib_context_log(c, GRIB_LOG_ERROR,
106                              "grib_db_new_column : unknown column type %d", type);
107             grib_context_free(c, column);
108             return err;
109     }
110 
111     db->columns[id].context           = c;
112     db->columns[id].name              = strdup(key);
113     db->columns[id].type              = type;
114     db->columns[id].values_array_size = GRIB_START_ARRAY_SIZE;
115     db->columns[id].size              = 0;
116     return err;
117 }
118 
grib_db_delete_columns(grib_db * db)119 static void grib_db_delete_columns(grib_db* db)
120 {
121     int i = 0;
122     grib_context* c;
123 
124     if (!set)
125         return;
126     c = db->context;
127 
128     for (i = 0; i < db->columns_size; i++) {
129         switch (db->columns[i].type) {
130             case GRIB_TYPE_LONG:
131                 grib_context_free(c, db->columns[i].long_values);
132                 break;
133             case GRIB_TYPE_DOUBLE:
134                 grib_context_free(c, db->columns[i].double_values);
135                 break;
136             case GRIB_TYPE_STRING:
137                 for (i = 0; i < db->columns[i].size; i++)
138                     grib_context_free(c, db->columns[i].string_values[i]);
139                 grib_context_free(c, db->columns[i].string_values);
140                 break;
141             default:
142                 grib_context_log(c, GRIB_LOG_ERROR,
143                                  "grib_db_new_column : unknown column type %d", db->columns[i].type);
144         }
145         grib_context_free(c, db->columns[i].errors);
146         free(db->columns[i].name);
147     }
148     grib_context_free(c, db->columns);
149 }
150 
grib_db_columns_resize(grib_db * db,size_t newsize)151 static int grib_db_columns_resize(grib_db* db, size_t newsize)
152 {
153     double* newdoubles;
154     long* newlongs;
155     char** newstrings;
156     int* newerrors;
157     int i = 0;
158     grib_context* c;
159 
160     if (!db || !db->columns)
161         return GRIB_INVALID_ARGUMENT;
162 
163     c = db->context;
164 
165     if (newsize <= db->columns[0].values_array_size)
166         return 0;
167 
168     for (i = 0; i < db->columns_size; i++) {
169         switch (db->columns[i].type) {
170             case GRIB_TYPE_LONG:
171                 newlongs = (long*)grib_context_realloc(c, db->columns[i].long_values,
172                                                        newsize * sizeof(long));
173                 if (!newlongs) {
174                     grib_context_log(c, GRIB_LOG_ERROR,
175                                      "grib_db_columns_resize : Cannot malloc %d bytes", newsize - db->columns[i].values_array_size);
176                     return GRIB_OUT_OF_MEMORY;
177                 }
178                 else
179                     db->columns[i].long_values = newlongs;
180                 break;
181             case GRIB_TYPE_DOUBLE:
182                 newdoubles = (double*)grib_context_realloc(c, db->columns[i].double_values,
183                                                            newsize * sizeof(double));
184                 if (!newdoubles) {
185                     grib_context_log(c, GRIB_LOG_ERROR,
186                                      "grib_db_columns_resize : Cannot malloc %d bytes", newsize - db->columns[i].values_array_size);
187                     return GRIB_OUT_OF_MEMORY;
188                 }
189                 else
190                     db->columns[i].double_values = newdoubles;
191                 break;
192             case GRIB_TYPE_STRING:
193                 newstrings = (char**)grib_context_realloc(c, db->columns[i].string_values,
194                                                           newsize * sizeof(char*));
195                 if (!newstrings) {
196                     grib_context_log(c, GRIB_LOG_ERROR,
197                                      "grib_db_columns_resize : Cannot malloc %d bytes", newsize - db->columns[i].values_array_size);
198                     return GRIB_OUT_OF_MEMORY;
199                 }
200                 else
201                     db->columns[i].string_values = newstrings;
202                 break;
203         }
204         newerrors = (int*)grib_context_realloc(c, db->columns[i].errors, newsize * sizeof(int));
205         if (!newerrors) {
206             grib_context_log(c, GRIB_LOG_ERROR,
207                              "grib_db_columns_resize : Cannot malloc %d bytes",
208                              db->columns[i].errors, newsize * sizeof(int));
209             return GRIB_OUT_OF_MEMORY;
210         }
211         else
212             db->columns[i].errors = newerrors;
213 
214         db->columns[i].values_array_size = newsize;
215     }
216 
217     return GRIB_SUCCESS;
218 }
219 
grib_db_column_copy_from_handle(grib_handle * h,grib_db * db,int i)220 static int grib_db_column_copy_from_handle(grib_handle* h, grib_db* db, int i)
221 {
222     int err     = 0;
223     long lval   = 0;
224     double dval = 0;
225     char sval[1024];
226     size_t slen = 1024;
227     if (!db || !h || db->columns[i].type == 0)
228         return GRIB_INVALID_ARGUMENT;
229 
230     if (db->columns[i].size >= db->columns[i].values_array_size)
231         grib_db_columns_resize(db, db->columns[i].values_array_size + GRIB_ARRAY_INCREMENT);
232 
233     switch (db->columns[i].type) {
234         case GRIB_TYPE_LONG:
235             err                                             = grib_get_long(h, db->columns[i].name, &lval);
236             db->columns[i].long_values[db->columns[i].size] = lval;
237             break;
238         case GRIB_TYPE_DOUBLE:
239             err                                               = grib_get_double(h, db->columns[i].name, &dval);
240             db->columns[i].double_values[db->columns[i].size] = dval;
241             break;
242         case GRIB_TYPE_STRING:
243             err                                               = grib_get_string(h, db->columns[i].name, sval, &slen);
244             db->columns[i].string_values[db->columns[i].size] = strdup(sval);
245             break;
246     }
247 
248     db->columns[i].errors[db->columns[i].size] = err;
249     db->columns[i].size++;
250 
251     return err;
252 }
253 
254 /* --------------- grib_db functions ------------------*/
255 #if 0
256 grib_db* grib_db_new_from_files(grib_context* c, char* filenames[],
257                                 int nfiles, char** keys, int nkeys, int* err)
258 {
259     int i   = 0;
260     int ret = GRIB_SUCCESS;
261 
262     grib_db* db = 0;
263 
264     if (!c)
265         c = grib_context_get_default();
266 
267     if (((!keys || nkeys == 0)) || !filenames) {
268         *err = GRIB_INVALID_ARGUMENT;
269         return NULL;
270     }
271 
272     db = grib_db_new_from_file(c, filenames[0], keys, nkeys, err);
273     if (!db || *err != GRIB_SUCCESS)
274         return db;
275 
276     *err = GRIB_SUCCESS;
277     for (i = 1; i < nfiles; i++) {
278         ret = grib_db_load(db, filenames[i]);
279         if (ret != GRIB_SUCCESS)
280             *err = ret;
281     }
282 
283     return db;
284 }
285 
286 grib_db* grib_db_new_from_file(grib_context* c, char* filename,
287                                char** keys, int nkeys, int* err)
288 {
289     int i   = 0;
290     int ret = GRIB_SUCCESS;
291 
292     grib_db* db = 0;
293 
294     if (!c)
295         c = grib_context_get_default();
296 
297     if (((!keys || nkeys == 0)) || !filename) {
298         *err = GRIB_INVALID_ARGUMENT;
299         return NULL;
300     }
301 
302     db = grib_db_create_from_keys(c, keys, nkeys, err);
303 
304     *err = GRIB_SUCCESS;
305     ret  = grib_db_load(db, filename);
306     if (ret != GRIB_SUCCESS)
307         *err = ret;
308 
309     return db;
310 }
311 #endif
312 
grib_db_create_from_keys(grib_context * c,char ** keys,int nkeys,int * err)313 static grib_db* grib_db_create_from_keys(grib_context* c, char** keys, int nkeys, int* err)
314 {
315     grib_db* db  = 0;
316     size_t msize = 0, size = 0;
317     int i            = 0;
318     int type         = 0;
319     int default_type = GRIB_TYPE_DOUBLE;
320 
321     if (!c)
322         c = grib_context_get_default();
323 
324     size = GRIB_START_ARRAY_SIZE;
325 
326     msize = sizeof(grib_db);
327     db    = (grib_db*)grib_context_malloc(c, msize);
328     if (!db) {
329         grib_context_log(c, GRIB_LOG_ERROR,
330                          "grib_db_create : Cannot malloc %d bytes", msize);
331         return NULL;
332     }
333 
334     db->context           = c;
335     db->size              = 0;
336     db->fields_array_size = size;
337     db->fields            = 0;
338     db->columns           = 0;
339 
340     db->fields = grib_db_create_fields(db->context, size);
341 
342     db->columns = (grib_column*)grib_context_malloc(c, sizeof(grib_column) * nkeys);
343     if (!set->columns) {
344         grib_context_log(c, GRIB_LOG_ERROR, "grib_db_new_query: memory allocation error");
345         *err = GRIB_OUT_OF_MEMORY;
346         return NULL;
347     }
348     for (i = 0; i < nkeys; i++) {
349         char* key = strdup(keys[i]);
350         char* p   = key;
351         while (*p != ':' && *p != '\0')
352             p++;
353         if (*p == ':') {
354             type = grib_type_to_int(*(p + 1));
355             *p   = '\0';
356         }
357         else {
358             type = default_type;
359         }
360         *err = grib_db_new_column(db, i, key, type);
361         free(key);
362     }
363 
364     db->columns_size = nkeys;
365 
366     return db;
367 }
368 
grib_db_delete(grib_db * db)369 void grib_db_delete(grib_db* db)
370 {
371     grib_context* c = 0;
372     if (!db)
373         return;
374 
375     c = set->context;
376 
377     grib_db_delete_columns(db);
378 
379     grib_db_delete_fields(db);
380 
381     grib_context_free(c, db);
382 }
383 
grib_db_new_query(grib_context * c,const char * where_string,const char * order_by_string)384 grib_query* grib_db_new_query(grib_context* c, const char* where_string,
385                               const char* order_by_string)
386 {
387     grib_query* q = 0;
388 
389     if (!c)
390         c = grib_context_get_default();
391 
392     q = (grib_query*)grib_context_malloc(c, sizeof(grib_query));
393 
394     q->where_string = 0;
395     q->order_by     = 0;
396 
397     if (where_string)
398         q->where_string = strdup(where_string);
399 
400     if (order_by_string) {
401         q->order_by = grib_db_new_order_by(set->context, (char*)order_by_string);
402         if ((err = grib_db_set_order_by(set, ob)) != GRIB_SUCCESS)
403             return q;
404     }
405 
406     return q;
407 }
408 
grib_db_execute(grib_db * db,grib_query * query,int * err)409 grib_fieldset* grib_db_execute(grib_db* db, grib_query* query, int* err)
410 {
411     grib_fieldset* set = NULL;
412 
413     if (!db) {
414         *err = GRIB_INVALID_ARGUMENT;
415         return NULL;
416     }
417     set = grib_db_fieldset_create(db, err);
418     if (*err != GRIB_SUCCESS)
419         return set;
420 
421     set->query = query;
422 
423     *err = grib_db_apply_where(set, query->where_string);
424     if (*err != GRIB_SUCCESS)
425         return set;
426 
427     *err = grib_db_apply_order_by(set, query->order_by);
428     if (*err != GRIB_SUCCESS)
429         return set;
430 
431     return set;
432 }
433 
grib_db_fieldset_create(grib_db * db,int * err)434 static void grib_fieldset* grib_db_fieldset_create(grib_db* db, int* err)
435 {
436     grib_fieldset* set = (grib_fieldset*)grib_context_malloc(db->context,
437                                                              sizeof(grib_fieldset));
438 
439     if (!set) {
440         *err = GRIB_OUT_OF_MEMORY;
441         return NULL;
442     }
443 
444     set->db         = db;
445     set->context    = db->context;
446     set->grib_query = NULL;
447     set->size       = 0;
448     set->filter     = NULL;
449     set->order      = NULL;
450 
451     return set;
452 }
453 
grib_db_apply_where(grib_fieldset * set)454 int grib_db_apply_where(grib_fieldset* set)
455 {
456     int err      = GRIB_SUCCESS;
457     grib_math* m = 0;
458 
459     if (!set)
460         return GRIB_INVALID_ARGUMENT;
461 
462     /*
463   m=grib_math_new(set->context,where_string,&err);
464 
465   print_math(m);
466   printf("\n");
467   */
468 
469     if (set->filter)
470         grib_db_delete_int_array(set->filter);
471     set->filter = grib_db_create_int_array(set->context, db->size);
472 
473     if (set->order)
474         grib_db_delete_int_array(set->order);
475     set->order = grib_db_create_int_array(set->context, db->size);
476 
477     for (i = 0; i < db->size; i++)
478         set->filter[i] = i;
479 
480     return err;
481 }
482 
grib_db_apply_order_by(grib_fieldset * set)483 int grib_db_apply_order_by(grib_fieldset* set)
484 {
485     int err           = 0;
486     grib_order_by* ob = NULL;
487 
488     if (!set || !set->query)
489         return GRIB_INVALID_ARGUMENT;
490 
491     if (set->query->order_by)
492         grib_db_sort(set, 0, set->size - 1);
493 
494     grib_db_rewind(set);
495 
496     return err;
497 }
498 
grib_fieldset_compare(grib_fieldset * set,int * i,int * j)499 static int grib_fieldset_compare(grib_fieldset* set, int* i, int* j)
500 {
501     int ret           = 0;
502     double d          = 0;
503     int idkey         = 0;
504     grib_order_by* ob = 0;
505     int ii = 0, jj = 0;
506     int *order = 0, *filter = 0;
507 
508     if (!set || !set->order_by)
509         return GRIB_INVALID_ARGUMENT;
510     ob     = set->query->order_by;
511     order  = set->order->el;
512     filter = set->filter->el;
513 
514     ii = *(set->filter->el + *(order + *i));
515     jj = *(set->filter->el + *(order + *j));
516 
517     while (ob) {
518         idkey = ob->idkey;
519         switch (set->db->columns[idkey].type) {
520             case GRIB_TYPE_STRING:
521                 ret = grib_inline_strcmp(set->db->columns[idkey].string_values[ii],
522                                          set->db->columns[idkey].string_values[jj]);
523                 break;
524 
525             case GRIB_TYPE_DOUBLE:
526                 d = set->db->columns[idkey].double_values[ii] -
527                     set->db->columns[idkey].double_values[jj];
528                 if (d > 0)
529                     ret = 1;
530                 else if (d == 0)
531                     ret = 0;
532                 else
533                     ret = -1;
534                 break;
535 
536             case GRIB_TYPE_LONG:
537                 ret = set->db->columns[idkey].long_values[ii] -
538                       set->db->columns[idkey].long_values[jj];
539                 break;
540             default:
541                 return GRIB_INVALID_TYPE;
542         }
543         if (ret != 0) {
544             ret *= ob->mode;
545             break;
546         }
547         ob = ob->next;
548     }
549 
550     return ret;
551 }
552 
grib_db_sort(grib_set * set,int beg,int theEnd)553 static void grib_db_sort(grib_set* set, int beg, int theEnd)
554 {
555     double temp;
556     int l = 0, r = 0;
557     if (theEnd > beg) {
558         l = beg + 1;
559         r = theEnd;
560         while (l < r) {
561             if (grib_db_compare(set, &l, &beg) <= 0) {
562                 l++;
563             }
564             else if (grib_db_compare(set, &r, &beg) >= 0) {
565                 r--;
566             }
567             else {
568                 SWAP(set->order->el[l], set->order->el[r])
569             }
570         }
571 
572         if (grib_db_compare(set, &l, &beg) < 0) {
573             SWAP(set->order->el[l], set->order->el[beg])
574             l--;
575         }
576         else {
577             l--;
578             SWAP(set->order->el[l], set->order->el[beg])
579         }
580 
581         grib_db_sort(set, beg, l);
582         grib_db_sort(set, r, theEnd);
583     }
584 }
585 
grib_db_delete_order_by(grib_context * c,grib_order_by * order_by)586 static void grib_db_delete_order_by(grib_context* c, grib_order_by* order_by)
587 {
588     grib_order_by* ob = order_by;
589 
590     if (!c)
591         c = grib_context_get_default();
592 
593     while (order_by) {
594         if (order_by->key)
595             free(order_by->key);
596         ob       = order_by;
597         order_by = order_by->next;
598         grib_context_free(c, ob);
599     }
600 
601     return;
602 }
603 
grib_db_new_order_by(grib_context * c,char * obstr)604 static grib_order_by* grib_db_new_order_by(grib_context* c, char* obstr)
605 {
606     char *t1 = 0, *t2 = 0, *p = 0;
607     int id  = 0;
608     char *z = 0, *zs       = 0;
609     int mode, mode_default = GRIB_ORDER_BY_ASC;
610     grib_order_by *ob, *sob;
611 
612     if (!obstr)
613         return NULL;
614 
615     z  = strdup(obstr);
616     zs = z;
617     grib_trim(&z);
618 
619     if (strlen(z) == 0) {
620         return 0;
621     }
622 
623     ob        = (grib_order_by*)grib_context_malloc(c, sizeof(grib_order_by));
624     sob       = ob;
625     ob->key   = 0;
626     ob->idkey = 0;
627     ob->mode  = 0;
628     ob->next  = 0;
629 
630     if (z)
631         t1 = strtok(z, ",");
632 
633     while (t1) {
634         grib_trim(&t1);
635         t2 = strdup(t1);
636         p  = t2;
637         while (*p != ' ' && *p != '\0')
638             p++;
639         mode = mode_default;
640         if (p != t2) {
641             while (*p == ' ' && *p != '\0')
642                 p++;
643             if (*p != '\0') {
644                 *(p - 1) = '\0';
645                 if (!grib_inline_strcmp(p, "asc"))
646                     mode = GRIB_ORDER_BY_ASC;
647                 if (!grib_inline_strcmp(p, "desc"))
648                     mode = GRIB_ORDER_BY_DESC;
649             }
650             grib_trim(&p);
651         }
652         grib_trim(&t2);
653         id = -1;
654         t1 = strtok(NULL, ",");
655 
656         if (ob->key) {
657             ob->next = (grib_order_by*)grib_context_malloc(c, sizeof(grib_order_by));
658             ob       = ob->next;
659             ob->key  = 0;
660             ob->next = 0;
661         }
662         ob->mode  = mode;
663         ob->key   = t2;
664         ob->idkey = id;
665     }
666 
667     free(zs);
668     return sob;
669 }
670 
grib_db_load(grib_db * db,char * filename)671 int grib_db_load(grib_db* db, char* filename)
672 {
673     int ret        = GRIB_SUCCESS;
674     int err        = 0;
675     int i          = 0;
676     grib_handle* h = 0;
677     int nkeys;
678     grib_file* file;
679     double offset   = 0;
680     long length     = 0;
681     grib_context* c = 0;
682 
683     if (!db || !filename)
684         return GRIB_INVALID_ARGUMENT;
685     c = db->context;
686 
687     nkeys = db->columns_size;
688 
689     file = grib_file_open(filename, "r", &err);
690     if (!file || !file->handle)
691         return err;
692 
693     while ((h = grib_handle_new_from_file(c, file->handle, &err)) != NULL || ret != GRIB_SUCCESS) {
694         if (!h)
695             return ret;
696 
697         err = GRIB_SUCCESS;
698         for (i = 0; i < db->columns_size; i++) {
699             err = grib_db_column_copy_from_handle(h, db, i);
700             if (err != GRIB_SUCCESS)
701                 ret = err;
702         }
703         if (err == GRIB_SUCCESS || err == GRIB_NOT_FOUND) {
704             if (db->fields_array_size < db->columns[0].values_array_size) {
705                 ret = grib_db_resize(db, db->columns[0].values_array_size);
706                 if (ret != GRIB_SUCCESS)
707                     return ret;
708             }
709             offset                     = 0;
710             ret                        = grib_get_double(h, "offset", &offset);
711             db->fields[db->size]       = (grib_field*)grib_context_malloc(c, sizeof(grib_field));
712             db->fields[db->size]->file = file;
713             file->refcount++;
714             db->fields[db->size]->offset = (off_t)offset;
715             ret                          = grib_get_long(h, "totalLength", &length);
716             db->fields[db->size]->length = length;
717             db->size                     = set->columns[0].size;
718         }
719         grib_handle_delete(h);
720     }
721     if (h)
722         grib_handle_delete(h);
723 
724     grib_file_close(file->name, 0, &err);
725 
726     return ret;
727 }
728 
grib_db_resize(grib_db * db,size_t newsize)729 static int grib_db_resize(grib_db* db, size_t newsize)
730 {
731     int err = 0;
732 
733     err = grib_db_resize_fields(db, newsize);
734     if (err != 0)
735         return err;
736 
737     set->fields_array_size = newsize;
738 
739     return GRIB_SUCCESS;
740 }
741 
grib_db_rewind(grib_fieldset * set)742 void grib_db_rewind(grib_fieldset* set)
743 {
744     if (set)
745         set->current = 0;
746 }
747 
grib_db_next_handle(grib_fieldset * set,int * err)748 grib_handle* grib_db_next_handle(grib_fieldset* set, int* err)
749 {
750     grib_handle* h;
751     *err = GRIB_SUCCESS;
752     h    = grib_db_retrieve(set, set->current, err);
753     if (*err == GRIB_SUCCESS) {
754         set->current++;
755     }
756     return h;
757 }
758 
grib_db_count(grib_fieldset * set)759 int grib_db_count(grib_fieldset* set)
760 {
761     return set->size;
762 }
763 
grib_db_retrieve(grib_fieldset * set,int i,int * err)764 grib_handle* grib_db_retrieve(grib_fieldset* set, int i, int* err)
765 {
766     grib_handle* h    = 0;
767     grib_field* field = 0;
768     *err              = GRIB_SUCCESS;
769     if (!set) {
770         *err = GRIB_INVALID_ARGUMENT;
771         return NULL;
772     }
773     if (i >= set->size)
774         return NULL;
775 
776     field = set->db->fields[set->filter->el[set->order->el[i]]];
777     grib_file_open(field->file->name, "r", err);
778     if (*err != GRIB_SUCCESS)
779         return NULL;
780 
781     fseeko(field->file->handle, field->offset, SEEK_SET);
782     h = grib_handle_new_from_file(set->context, field->file->handle, err);
783     if (*err != GRIB_SUCCESS)
784         return NULL;
785 
786     grib_file_close(field->file->name, 0, err);
787 
788     return h;
789 }
790 
grib_db_create_int_array(grib_context * c,size_t size)791 static grib_int_array* grib_db_create_int_array(grib_context* c, size_t size)
792 {
793     grib_int_array* a;
794     int i = 0;
795 
796     if (!c)
797         c = grib_context_get_default();
798 
799     a = (grib_int_array*)grib_context_malloc(c, sizeof(grib_int_array));
800 
801     if (!a) {
802         grib_context_log(c, GRIB_LOG_ERROR,
803                          "grib_db_create_int_array : Cannot malloc %d bytes",
804                          sizeof(grib_int_array));
805         return NULL;
806     }
807 
808     a->el = (int*)grib_context_malloc(c, sizeof(int) * size);
809     if (!a->el) {
810         grib_context_log(c, GRIB_LOG_ERROR,
811                          "grib_db_create_int_array : Cannot malloc %d bytes",
812                          sizeof(int) * size);
813         return NULL;
814     }
815 
816     a->size    = size;
817     a->context = c;
818     for (i = 0; i < size; i++)
819         a->el[i] = i;
820 
821     return a;
822 }
823 
grib_db_resize_int_array(grib_int_array * a,size_t newsize)824 static int grib_db_resize_int_array(grib_int_array* a, size_t newsize)
825 {
826     int* el;
827     int err = 0;
828     if (!a)
829         return GRIB_INVALID_ARGUMENT;
830 
831     newsize = newsize * sizeof(int);
832 
833     el = (int*)grib_context_realloc(a->context, a->el, newsize);
834     if (!el) {
835         grib_context_log(a->context, GRIB_LOG_ERROR,
836                          "grib_db_resize_int_array : Cannot malloc %d bytes",
837                          newsize);
838         return GRIB_OUT_OF_MEMORY;
839     }
840     else
841         a->el = el;
842     a->size = newsize;
843     return err;
844 }
845 
grib_db_delete_int_array(grib_int_array * f)846 static void grib_db_delete_int_array(grib_int_array* f)
847 {
848     grib_context* c = NULL;
849 
850     if (!f)
851         return;
852     c = f->context;
853 
854     grib_context_free(c, f->el);
855     grib_context_free(c, f);
856 }
857 
grib_db_create_fields(grib_context * c,size_t size)858 static grib_field** grib_db_create_fields(grib_context* c, size_t size)
859 {
860     int i               = 0;
861     grib_field** fields = (grib_field**)grib_context_malloc(c, size * sizeof(grib_field*));
862     if (!fields)
863         return NULL;
864     for (i = 0; i < size; i++)
865         fields[i] = 0;
866     return fields;
867 }
868 
grib_db_resize_fields(grib_db * db,size_t newsize)869 static int grib_db_resize_fields(grib_db* db, size_t newsize)
870 {
871     int err = 0;
872     int i;
873     grib_field** fields;
874     if (!db)
875         return GRIB_INVALID_ARGUMENT;
876 
877     fields = (grib_field**)grib_context_realloc(set->context, set->fields, newsize * sizeof(grib_field*));
878     if (!fields) {
879         grib_context_log(set->context, GRIB_LOG_ERROR,
880                          "grib_db_resize_fields : Cannot malloc %d bytes",
881                          newsize * sizeof(grib_field*));
882         return GRIB_OUT_OF_MEMORY;
883     }
884     else
885         db->fields = fields;
886 
887     for (i = set->fields_array_size; i < newsize; i++)
888         db->fields[i] = 0;
889 
890     db->fields_array_size = newsize;
891     return err;
892 }
893 
grib_db_delete_fields(grib_fieldset * set)894 static void grib_db_delete_fields(grib_fieldset* set)
895 {
896     int i;
897     for (i = 0; i < set->size; i++) {
898         if (!set->fields[i])
899             continue;
900         set->fields[i]->file->refcount--;
901         grib_context_free(set->context, set->fields[i]);
902     }
903     grib_context_free(set->context, set->fields);
904 }
905 
grib_trim(char ** x)906 static void grib_trim(char** x)
907 {
908     char* p = 0;
909     while (**x == ' ' && **x != '\0')
910         (*x)++;
911     if (**x == '\0')
912         return;
913     p = (*x) + strlen(*x) - 1;
914     while (*p == ' ') {
915         *p = '\0';
916         p--;
917     }
918     if (*p == ' ')
919         *p = '\0';
920 }
921 
grib_db_set_order_by(grib_fieldset * set,grib_order_by * ob)922 static int grib_db_set_order_by(grib_fieldset* set, grib_order_by* ob)
923 {
924     grib_order_by* next = ob;
925     int i               = 0;
926 
927     while (next) {
928         next->idkey = -1;
929         for (i = 0; i < set->columns_size; i++) {
930             if (!grib_inline_strcmp(next->key, set->columns[i].name)) {
931                 next->idkey = i;
932                 break;
933             }
934         }
935         if (next->idkey == -1) {
936             grib_context_log(set->context, GRIB_LOG_ERROR,
937                              "Unable to apply the order by. Key missing from the fieldset.\n");
938             return GRIB_MISSING_KEY;
939         }
940         next = next->next;
941     }
942 
943     set->order_by = ob;
944 
945     return GRIB_SUCCESS;
946 }
947