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