GRASS 8 Programmer's Manual 8.6.0dev(2026)-56a9afeb9f
Loading...
Searching...
No Matches
db/dbmi_client/select.c
Go to the documentation of this file.
1/*!
2 * \file db/dbmi_client/select.c
3 *
4 * \brief DBMI Library (client) - select records from table
5 *
6 * (C) 1999-2008 by the GRASS Development Team
7 *
8 * This program is free software under the GNU General Public
9 * License (>=v2). Read the file COPYING that comes with GRASS
10 * for details.
11 *
12 * \author Joel Jones (CERL/UIUC), Radim Blazek
13 */
14
15#include <stdlib.h>
16#include <string.h>
17#include <grass/gis.h>
18#include <grass/dbmi.h>
19#include <grass/glocale.h>
20
21static int cmp(const void *pa, const void *pb)
22{
23 int *p1 = (int *)pa;
24 int *p2 = (int *)pb;
25
26 if (*p1 < *p2)
27 return -1;
28 if (*p1 > *p2)
29 return 1;
30 return 0;
31}
32
33static int cmpcat(const void *pa, const void *pb)
34{
35 dbCatVal *p1 = (dbCatVal *)pa;
36 dbCatVal *p2 = (dbCatVal *)pb;
37
38 if (p1->cat < p2->cat)
39 return -1;
40 if (p1->cat > p2->cat)
41 return 1;
42 return 0;
43}
44
45static int cmpcatkey(const void *pa, const void *pb)
46{
47 int *p1 = (int *)pa;
48 dbCatVal *p2 = (dbCatVal *)pb;
49
50 if (*p1 < p2->cat)
51 return -1;
52 if (*p1 > p2->cat)
53 return 1;
54 return 0;
55}
56
57static int cmpvalueint(const void *pa, const void *pb)
58{
59 dbCatVal *p1 = (dbCatVal *)pa;
60 dbCatVal *p2 = (dbCatVal *)pb;
61
62 if (p1->val.i < p2->val.i)
63 return -1;
64 if (p1->val.i > p2->val.i)
65 return 1;
66
67 return 0;
68}
69
70static int cmpvaluedouble(const void *pa, const void *pb)
71{
72 dbCatVal *p1 = (dbCatVal *)pa;
73 dbCatVal *p2 = (dbCatVal *)pb;
74
75 if (p1->val.d < p2->val.d)
76 return -1;
77 if (p1->val.d > p2->val.d)
78 return 1;
79
80 return 0;
81}
82
83static int cmpvaluestring(const void *pa, const void *pb)
84{
85 dbCatVal *const *a = pa;
86 dbCatVal *const *b = pb;
87
88 return strcmp((const char *)a, (const char *)b);
89}
90
91/*!
92 \brief Select array of ordered integers from table/column
93
94 \param driver DB driver
95 \param tab table name
96 \param col column name
97 \param where where statement
98 \param[out] pval array of ordered integer values
99
100 \return number of selected values
101 \return -1 on error
102 */
103int db_select_int(dbDriver *driver, const char *tab, const char *col,
104 const char *where, int **pval)
105{
106 int type, more, alloc, count;
107 int *val;
108 char *buf = NULL;
109 const char *sval;
110 dbString stmt;
113 dbValue *value;
114 dbTable *table;
115
116 G_debug(3, "db_select_int()");
117
118 if (col == NULL || strlen(col) == 0) {
119 G_warning(_("Missing column name"));
120 return -1;
121 }
122
123 /* allocate */
124 alloc = 1000;
125
126 if (where == NULL || strlen(where) == 0)
127 G_asprintf(&buf, "SELECT %s FROM %s", col, tab);
128 else
129 G_asprintf(&buf, "SELECT %s FROM %s WHERE %s", col, tab, where);
130
131 G_debug(3, " SQL: %s", buf);
132
133 db_init_string(&stmt);
134 db_set_string(&stmt, buf);
135 G_free(buf);
136
138 return (-1);
139
140 table = db_get_cursor_table(&cursor);
141 column = db_get_table_column(table, 0); /* first column */
142 if (column == NULL) {
143 return -1;
144 }
147 type = db_sqltype_to_Ctype(type);
148
149 val = (int *)G_malloc(alloc * sizeof(int));
150 /* fetch the data */
151 count = 0;
152 while (1) {
153 if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
154 G_free(val);
155 return (-1);
156 }
157
158 if (!more)
159 break;
160
161 if (count == alloc) {
162 alloc += 1000;
163 val = (int *)G_realloc(val, alloc * sizeof(int));
164 }
165
166 switch (type) {
167 case (DB_C_TYPE_INT):
168 val[count] = db_get_value_int(value);
169 break;
170 case (DB_C_TYPE_STRING):
171 sval = db_get_value_string(value);
172 val[count] = atoi(sval);
173 break;
174 case (DB_C_TYPE_DOUBLE):
175 val[count] = (int)db_get_value_double(value);
176 break;
177 default:
178 G_free(val);
179 return (-1);
180 }
181 count++;
182 }
183
185 db_free_string(&stmt);
186
187 qsort((void *)val, count, sizeof(int), cmp);
188
189 *pval = val;
190
191 return (count);
192}
193
194/*!
195 \brief Select one (first) value from table/column for key/id
196
197 \param driver DB driver
198 \param tab table name
199 \param key key column name
200 \param id identifier in key column
201 \param col name of column to select the value from
202 \param[out] val dbValue to store within
203
204 \return number of selected values
205 \return -1 on error
206 */
207int db_select_value(dbDriver *driver, const char *tab, const char *key, int id,
208 const char *col, dbValue *val)
209{
210 int more, count;
211 char *buf = NULL;
212 dbString stmt;
215 dbValue *value;
216 dbTable *table;
217
218 if (key == NULL || strlen(key) == 0) {
219 G_warning(_("Missing key column name"));
220 return -1;
221 }
222
223 if (col == NULL || strlen(col) == 0) {
224 G_warning(_("Missing column name"));
225 return -1;
226 }
227
228 G_zero(val, sizeof(dbValue));
229 G_asprintf(&buf, "SELECT %s FROM %s WHERE %s = %d", col, tab, key, id);
230 db_init_string(&stmt);
231 db_set_string(&stmt, buf);
232 G_free(buf);
233
235 return (-1);
236
237 table = db_get_cursor_table(&cursor);
238 column = db_get_table_column(table, 0); /* first column */
240
241 /* fetch the data */
242 count = 0;
243 while (1) {
244 if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK)
245 return (-1);
246
247 if (!more)
248 break;
249 if (count == 0)
250 db_copy_value(val, value);
251 count++;
252 }
254 db_free_string(&stmt);
255
256 return (count);
257}
258
259/*!
260 \brief Select pairs key/value to array, values are sorted by key (must be
261 integer)
262
263 \param driver DB driver
264 \param tab table name
265 \param key key column name
266 \param col value column name
267 \param where where statement
268 \param[out] cvarr dbCatValArray to store within
269
270 \return number of selected values
271 \return -1 on error
272 */
273int db_select_CatValArray(dbDriver *driver, const char *tab, const char *key,
274 const char *col, const char *where,
276{
277 int i, type, more, nrows, ncols;
278 char *buf = NULL;
279 dbString stmt;
282 dbValue *value;
283 dbTable *table;
284
285 G_debug(3, "db_select_CatValArray ()");
286
287 if (key == NULL || strlen(key) == 0) {
288 G_warning(_("Missing key column name"));
289 return -1;
290 }
291
292 if (col == NULL || strlen(col) == 0) {
293 G_warning(_("Missing column name"));
294 return -1;
295 }
296 db_init_string(&stmt);
297
298 if (strcmp(key, col) == 0) {
299 ncols = 1;
300 G_asprintf(&buf, "SELECT %s FROM %s", key, tab);
301 }
302 else {
303 ncols = 2;
304 G_asprintf(&buf, "SELECT %s, %s FROM %s", key, col, tab);
305 }
306 db_set_string(&stmt, buf);
307 G_free(buf);
308
309 if (where != NULL && strlen(where) > 0) {
310 db_append_string(&stmt, " WHERE ");
311 db_append_string(&stmt, where);
312 }
313
314 G_debug(3, " SQL: %s", db_get_string(&stmt));
315
317 return (-1);
318
319 nrows = db_get_num_rows(&cursor);
320 G_debug(3, " %d rows selected", nrows);
321 if (nrows < 0) {
322 G_warning(_("Unable select records from table <%s>"), tab);
324 db_free_string(&stmt);
325 return -1;
326 }
327
329
330 table = db_get_cursor_table(&cursor);
331
332 /* Check if key column is integer */
333 column = db_get_table_column(table, 0);
335 G_debug(3, " key type = %d", type);
336
337 if (type != DB_C_TYPE_INT) {
338 G_warning(_("Key column type is not integer"));
340 db_free_string(&stmt);
341 return -1;
342 }
343
344 if (ncols == 2) {
345 column = db_get_table_column(table, 1);
347 G_debug(3, " col type = %d", type);
348
349 /*
350 if ( type != DB_C_TYPE_INT && type != DB_C_TYPE_DOUBLE ) {
351 G_fatal_error ( "Column type not supported by db_select_to_array()"
352 );
353 }
354 */
355 }
356 cvarr->ctype = type;
357
358 /* fetch the data */
359 for (i = 0; i < nrows; i++) {
360 if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK)
361 return (-1);
362
363 column = db_get_table_column(table, 0); /* first column */
365 cvarr->value[i].cat = db_get_value_int(value);
366
367 if (ncols == 2) {
368 column = db_get_table_column(table, 1);
370 }
371 cvarr->value[i].isNull = value->isNull;
372 switch (type) {
373 case (DB_C_TYPE_INT):
374 if (value->isNull)
375 cvarr->value[i].val.i = 0;
376 else
377 cvarr->value[i].val.i = db_get_value_int(value);
378 break;
379
380 case (DB_C_TYPE_DOUBLE):
381 if (value->isNull)
382 cvarr->value[i].val.d = 0.0;
383 else
384 cvarr->value[i].val.d = db_get_value_double(value);
385 break;
386
387 case (DB_C_TYPE_STRING):
388 cvarr->value[i].val.s = (dbString *)malloc(sizeof(dbString));
389 db_init_string(cvarr->value[i].val.s);
390
391 if (!(value->isNull))
392 db_set_string(cvarr->value[i].val.s,
393 db_get_value_string(value));
394 break;
395
396 case (DB_C_TYPE_DATETIME):
397 cvarr->value[i].val.t = (dbDateTime *)calloc(1, sizeof(dbDateTime));
398
399 if (!(value->isNull))
400 memcpy(cvarr->value[i].val.t, &(value->t), sizeof(dbDateTime));
401 break;
402
403 default:
404 return (-1);
405 }
406 }
407 cvarr->n_values = nrows;
408
410 db_free_string(&stmt);
411
413
414 return nrows;
415}
416
417/*!
418 \brief Sort key/value array by key
419 \param[in,out] arr dbCatValArray (key/value array)
420 */
422{
423 qsort((void *)arr->value, arr->n_values, sizeof(dbCatVal), cmpcat);
424}
425
426/*!
427 \brief Sort key/value array by value
428
429 \param[in,out] arr dbCatValArray (key/value array)
430
431 \return DB_OK on success
432 \return DB_FAILED on error
433 */
435{
436 switch (arr->ctype) {
437 case (DB_C_TYPE_INT):
438 qsort((void *)arr->value, arr->n_values, sizeof(dbCatVal), cmpvalueint);
439 break;
440 case (DB_C_TYPE_DOUBLE):
441 qsort((void *)arr->value, arr->n_values, sizeof(dbCatVal),
442 cmpvaluedouble);
443 break;
444 case (DB_C_TYPE_STRING):
445 qsort((void *)arr->value, arr->n_values, sizeof(dbCatVal),
446 cmpvaluestring);
447 break;
448 case (DB_C_TYPE_DATETIME): /* is cmpvaluestring right here ? */
449 qsort((void *)arr->value, arr->n_values, sizeof(dbCatVal),
450 cmpvaluestring);
451 break;
452 default:
453 return (DB_FAILED);
454 }
455
456 return (DB_OK);
457}
458
459/*!
460 \brief Find value by key
461
462 \param arr dbCatValArray (key/value array)
463 \param key key value
464 \param[out] cv dbCatVal structure (key/value) to store within
465
466 \return DB_OK on success
467 \return DB_FAILED on error
468 */
470{
472
473 catval = bsearch((void *)&key, arr->value, arr->n_values, sizeof(dbCatVal),
474 cmpcat);
475 if (catval == NULL) {
476 return DB_FAILED;
477 }
478
479 *cv = catval;
480
481 return DB_OK;
482}
483
484/*!
485 \brief Find value (integer) by key
486
487 \param arr dbCatValArray (key/value array)
488 \param key key value
489 \param[out] val found value (integer)
490
491 \return DB_OK on success
492 \return DB_FAILED on error
493 */
495{
497
498 catval = bsearch((void *)&key, arr->value, arr->n_values, sizeof(dbCatVal),
499 cmpcat);
500 if (catval == NULL) {
501 return DB_FAILED;
502 }
503
504 *val = catval->val.i;
505
506 return DB_OK;
507}
508
509/*!
510 \brief Find value (double) by key
511
512 \param arr dbCatValArray (key/value array)
513 \param key key value
514 \param[out] val found value (double)
515
516 \return DB_OK on success
517 \return DB_FAILED on error
518 */
520{
522
523 G_debug(3, "db_CatValArray_get_value_double(), key = %d", key);
524
525 catval = bsearch((void *)&key, arr->value, arr->n_values, sizeof(dbCatVal),
526 cmpcatkey);
527 if (catval == NULL) {
528 return DB_FAILED;
529 }
530
531 *val = catval->val.d;
532
533 return DB_OK;
534}
#define NULL
Definition ccmath.h:32
int db_CatValArray_get_value_double(dbCatValArray *arr, int key, double *val)
Find value (double) by key.
int db_select_CatValArray(dbDriver *driver, const char *tab, const char *key, const char *col, const char *where, dbCatValArray *cvarr)
Select pairs key/value to array, values are sorted by key (must be integer)
int db_select_int(dbDriver *driver, const char *tab, const char *col, const char *where, int **pval)
Select array of ordered integers from table/column.
int db_select_value(dbDriver *driver, const char *tab, const char *key, int id, const char *col, dbValue *val)
Select one (first) value from table/column for key/id.
int db_CatValArray_get_value_int(dbCatValArray *arr, int key, int *val)
Find value (integer) by key.
void db_CatValArray_sort(dbCatValArray *arr)
Sort key/value array by key.
int db_CatValArray_sort_by_value(dbCatValArray *arr)
Sort key/value array by value.
int db_CatValArray_get_value(dbCatValArray *arr, int key, dbCatVal **cv)
Find value by key.
Main header of GRASS DataBase Management Interface.
struct _db_date_time dbDateTime
#define DB_C_TYPE_INT
Definition dbmi.h:108
#define DB_SEQUENTIAL
Definition dbmi.h:123
#define DB_FAILED
Definition dbmi.h:72
#define DB_C_TYPE_STRING
Definition dbmi.h:107
#define DB_C_TYPE_DOUBLE
Definition dbmi.h:109
#define DB_OK
Definition dbmi.h:71
#define DB_C_TYPE_DATETIME
Definition dbmi.h:110
#define DB_NEXT
Definition dbmi.h:114
void db_copy_value(dbValue *, dbValue *)
Copy value.
Definition value.c:340
int db_CatValArray_alloc(dbCatValArray *, int)
Allocate dbCatValArray.
Definition value.c:401
dbColumn * db_get_table_column(dbTable *, int)
Returns column structure for given table and column number.
double db_get_value_double(dbValue *)
Get double precision value.
Definition value.c:50
int db_sqltype_to_Ctype(int)
Get C data type based on given SQL data type.
Definition sqlCtype.c:24
dbValue * db_get_column_value(dbColumn *)
Returns column value for given column structure.
int db_get_column_sqltype(dbColumn *)
Returns column sqltype for column.
int db_get_num_rows(dbCursor *)
Get number of selected rows.
Definition c_rows.c:26
void db_free_string(dbString *)
Free allocated space for dbString.
Definition string.c:150
char * db_get_string(const dbString *)
Get string.
Definition string.c:140
dbTable * db_get_cursor_table(dbCursor *)
Get table allocated by cursor.
Definition cursor.c:67
int db_set_string(dbString *, const char *)
Inserts string to dbString (enlarge string)
Definition string.c:41
int db_get_value_int(dbValue *)
Get integer value.
Definition value.c:38
void db_init_string(dbString *)
Initialize dbString.
Definition string.c:25
int db_close_cursor(dbCursor *)
Close cursor.
Definition c_close_cur.c:27
int db_open_select_cursor(dbDriver *, dbString *, dbCursor *, int)
Open select cursor.
int db_append_string(dbString *, const char *)
Append string to dbString.
Definition string.c:205
const char * db_get_value_string(dbValue *)
Get string value.
Definition value.c:92
int db_fetch(dbCursor *, int, int *)
Fetch data from open cursor.
Definition c_fetch.c:28
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition gis/zero.c:23
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:147
#define G_realloc(p, n)
Definition defs/gis.h:141
void G_warning(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition defs/gis.h:139
int G_asprintf(char **, const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
#define _(str)
Definition glocale.h:10
int count
double b
Definition r_raster.c:39
void * malloc(unsigned)
dbDateTime t
Definition dbmi.h:192
char isNull
Definition dbmi.h:188
union dbCatVal::@1 val
int cat
Definition dbmi.h:254