GRASS 8 Programmer's Manual 8.6.0dev(2026)-1878fdfec5
Loading...
Searching...
No Matches
copy_tab.c
Go to the documentation of this file.
1/*!
2 \file db/dbmi_client/copy_tab.c
3
4 \brief DBMI Library (client) - copy 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/dbmi.h>
15#include <grass/glocale.h>
16#include "macros.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
30/*!
31 \brief Copy table, used by various db_copy_table* (internal use only)
32
33 Use either 'where' or 'select' or 'selcol'+'ivals'+'nvals' but
34 never more than one.
35
36 Warning: driver opened as second must be closed as first, otherwise
37 it hangs, not sure why.
38
39 \param from_dvrname name of driver from table is copied
40 \param from_dbname name of database from table is copied
41 \param from_tbl_name name of table to be copied
42 \param to_dvrname name of driver to - where table is copied to
43 \param to_dbname name of database to - where table is copied to
44 \param to_dbname name of copied table
45 \param where WHERE SQL condition (without where key word) or NULL
46 \param select full select statement
47 \param selcol name of column used to select records by values in ivals or
48 NULL \param ivals pointer to array of integer values or NULL \param nvals
49 number of values in ivals
50
51 \return DB_OK on success
52 \return DB_FAILED on failure
53 */
54static int copy_table(const char *from_drvname, const char *from_dbname,
55 const char *from_tblname, const char *to_drvname,
56 const char *to_dbname, const char *to_tblname,
57 const char *where, const char *select, const char *selcol,
58 int *ivals, int nvals)
59{
60 int col, ncols, sqltype, ctype, more, selcol_found;
61 char buf[1000];
62 int *ivalues;
67 dbTable *table, *out_table;
70 dbValue *value;
71 const char *colname;
73 int count, i;
74
75 G_debug(3,
76 "db_copy_table():\n from driver = %s, db = %s, table = %s\n"
77 " to driver = %s, db = %s, table = %s, where = %s, select = %s",
79 to_tblname, where, select);
80
86
87 if (selcol) {
88 if (!ivals || (ivals && nvals == 0)) {
89 G_warning(_("Array of values to select from column <%s> is empty"),
90 selcol);
91 return DB_FAILED;
92 }
93 /* Make a copy of input values and sort it */
94 if (ivals) {
95 ivalues = (int *)G_malloc(nvals * sizeof(int));
96 memcpy(ivalues, ivals, nvals * sizeof(int));
97 qsort((void *)ivalues, nvals, sizeof(int), cmp);
98 }
99 }
100 else
101 ivalues = NULL;
102
103 /* Open input driver and database */
105 if (from_driver == NULL) {
106 G_warning(_("Unable to start driver <%s>"), from_drvname);
107 return DB_FAILED;
108 }
111 G_warning(_("Unable to open database <%s> by driver <%s>"), from_dbname,
114 return DB_FAILED;
115 }
116
117 /* Open output driver and database */
118 if (strcmp(from_drvname, to_drvname) == 0 &&
120 G_debug(3, "Use the same driver");
122 }
123 else {
125 if (to_driver == NULL) {
126 G_warning(_("Unable to start driver <%s>"), to_drvname);
128 return DB_FAILED;
129 }
132 G_warning(_("Unable to open database <%s> by driver <%s>"),
135 if (from_driver != to_driver) {
137 }
138 return DB_FAILED;
139 }
140 }
141
143
144 /* Because in SQLite3 an opened cursor is no more valid
145 if 'schema' is modified (create table), we have to open
146 cursor twice */
147
148 /* test if the table exists */
149 if (db_list_tables(to_driver, &tblnames, &count, 0) != DB_OK) {
150 G_warning(_("Unable to get list tables in database <%s>"), to_dbname);
152 if (from_driver != to_driver)
154
155 return DB_FAILED;
156 }
157
158 for (i = 0; i < count; i++) {
159 int ret;
160 char *tblname_i;
161
162 tblname_i = NULL;
163 if (strcmp(to_drvname, "pg") == 0) {
164 char *p, *tbl;
166
169 p = strstr(tbl, ".");
170
171 if (p) {
172 char buf[GNAME_MAX];
173
174 snprintf(buf, sizeof(buf), "%s.%s",
175 connection.schemaName ? connection.schemaName
176 : "public",
177 to_tblname);
178 if (strcmp(buf, tbl) == 0)
179 tblname_i = G_store(p + 1); /* skip dot */
180 }
181 }
182 if (!tblname_i) {
184 }
185
186 ret = DB_FAILED;
187 if (strcmp(to_tblname, tblname_i) == 0) {
188 if (G_get_overwrite()) {
189 G_warning(_("Table <%s> already exists in database and will be "
190 "overwritten"),
191 to_tblname);
193 }
194 else {
195 G_warning(_("Table <%s> already exists in database <%s>"),
197 }
198
199 if (ret != DB_OK) {
201 if (from_driver != to_driver)
203
204 return DB_FAILED;
205 }
206 }
207
209 }
210
211 /* Create new table */
212 /* Open cursor for data structure */
213 if (select) {
214 db_set_string(&sql, select);
215
216 /* TODO!: cannot use this because it will not work if a query
217 * ends with 'group by' for example */
218 /*
219 tmp = strdup ( select );
220 G_tolcase ( tmp );
221
222 if ( !strstr( tmp,"where") )
223 {
224 db_append_string ( &sql, " where 0 = 1");
225 }
226 else
227 {
228 db_append_string ( &sql, " and 0 = 1");
229 }
230
231 free (tmp);
232 */
233 }
234 else {
235 db_set_string(&sql, "select * from ");
237 db_append_string(&sql, " where 0 = 1"); /* to get no data */
238 }
239
240 G_debug(3, "db__copy_table: %s", db_get_string(&sql));
242 DB_OK) {
243 G_warning(_("Unable to open select cursor: '%s'"), db_get_string(&sql));
245 if (from_driver != to_driver) {
247 }
248 return DB_FAILED;
249 }
250 G_debug(3, "Select cursor opened");
251
252 table = db_get_cursor_table(&cursor);
253 ncols = db_get_table_number_of_columns(table);
254 G_debug(3, "ncols = %d", ncols);
255
256 out_table = db_alloc_table(ncols);
258
259 selcol_found = 0;
260 for (col = 0; col < ncols; col++) {
262
267
268 G_debug(3, "%s (%s)", colname, db_sqltype_name(sqltype));
269
271
272 if (selcol && G_strcasecmp(colname, selcol) == 0) {
273 if (ctype != DB_C_TYPE_INT)
274 G_fatal_error(_("Column <%s> is not integer"), colname);
275 selcol_found = 1;
276 }
277
285 }
286
288
289 if (selcol && !selcol_found)
290 G_fatal_error(_("Column <%s> not found"), selcol);
291
293 G_warning(_("Unable to create table <%s>"), to_tblname);
295 if (from_driver != to_driver) {
297 }
298 return DB_FAILED;
299 }
300
301 /* Open cursor with data */
302 if (select) {
303 db_set_string(&sql, select);
304 }
305 else {
306 db_set_string(&sql, "select * from ");
308 if (where) {
309 db_append_string(&sql, " where ");
310 db_append_string(&sql, where);
311 }
312 }
313
314 G_debug(3, "db__copy_table: %s", db_get_string(&sql));
316 DB_OK) {
317 G_warning(_("Unable to open select cursor: '%s'"), db_get_string(&sql));
319 if (from_driver != to_driver) {
321 }
322 return DB_FAILED;
323 }
324 G_debug(3, "Select cursor opened");
325
326 table = db_get_cursor_table(&cursor);
327 ncols = db_get_table_number_of_columns(table);
328 G_debug(3, "ncols = %d", ncols);
329
330 /* Copy all rows */
331 while (1) {
332 int select;
333
334 if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
335 G_warning(_("Unable to fetch data from table <%s>"), from_tblname);
338 if (from_driver != to_driver) {
340 }
341 return DB_FAILED;
342 }
343 if (!more)
344 break;
345
346 snprintf(buf, sizeof(buf), "insert into %s values ( ", to_tblname);
347 db_set_string(&sql, buf);
348 select = 1;
349 for (col = 0; col < ncols; col++) {
355
356 if (selcol && G_strcasecmp(colname, selcol) == 0) {
357 if (db_test_value_isnull(value))
358 continue;
359 if (!bsearch(&(value->i), ivalues, nvals, sizeof(int), cmp)) {
360 select = 0;
361 break;
362 }
363 }
364 if (col > 0)
365 db_append_string(&sql, ", ");
367 switch (ctype) {
368 case DB_C_TYPE_STRING:
370 if (db_test_value_isnull(value)) {
371 db_append_string(&sql, "null");
372 }
373 else {
375 db_append_string(&sql, "'");
377 db_append_string(&sql, "'");
378 }
379 break;
380 case DB_C_TYPE_INT:
381 case DB_C_TYPE_DOUBLE:
382 if (db_test_value_isnull(value)) {
383 db_append_string(&sql, "null");
384 }
385 else {
387 }
388 break;
389 default:
390 G_warning(_("Unknown column type (column <%s>)"), colname);
393 if (from_driver != to_driver) {
395 }
396 return DB_FAILED;
397 }
398 }
399 if (!select)
400 continue;
401 db_append_string(&sql, ")");
402 G_debug(3, "db__copy_table: %s", db_get_string(&sql));
404 G_warning("Unable to insert new record: '%s'", db_get_string(&sql));
407 if (from_driver != to_driver) {
409 }
410 return DB_FAILED;
411 }
412 }
413 if (selcol)
415 G_debug(3, "Table copy OK");
416
420 if (from_driver != to_driver) {
422 }
423
424 return DB_OK;
425}
426
427/*!
428 \brief Copy a table
429
430 \param from_drvname name of driver from table is copied
431 \param from_dbname name of database from table is copied
432 \param from_tblname name of table to be copied
433 \param to_drvname name of driver to - where table is copied to
434 \param to_dbname name of database to - where table is copied to
435 \param to_tblname name of copied table
436
437 \return DB_OK on success
438 \return DB_FAILED on failure
439 */
440int db_copy_table(const char *from_drvname, const char *from_dbname,
441 const char *from_tblname, const char *to_drvname,
442 const char *to_dbname, const char *to_tblname)
443{
444 return copy_table(from_drvname, from_dbname, from_tblname, to_drvname,
446}
447
448/*!
449 \brief Copy a table (by where statement)
450
451 \param from_drvname name of driver from table is copied
452 \param from_dbname name of database from table is copied
453 \param from_tblname name of table to be copied
454 \param to_drvname name of driver to - where table is copied to
455 \param to_dbname name of database to - where table is copied to
456 \param to_tblname name of copied table
457 \param where WHERE SQL condition (without where key word)
458
459 \return DB_OK on success
460 \return DB_FAILED on failure
461 */
462int db_copy_table_where(const char *from_drvname, const char *from_dbname,
463 const char *from_tblname, const char *to_drvname,
464 const char *to_dbname, const char *to_tblname,
465 const char *where)
466{
467 return copy_table(from_drvname, from_dbname, from_tblname, to_drvname,
468 to_dbname, to_tblname, where, NULL, NULL, NULL, 0);
469}
470
471/*!
472 \brief Copy a table (by select statement)
473
474 \param from_drvname name of driver from table is copied
475 \param from_dbname name of database from table is copied
476 \param from_tblname name of table to be copied
477 \param to_drvname name of driver to - where table is copied to
478 \param to_dbname name of database to - where table is copied to
479 \param to_tblname name of copied table
480 \param select full select statement
481
482 \return DB_OK on success
483 \return DB_FAILED on failure
484 */
485int db_copy_table_select(const char *from_drvname, const char *from_dbname,
486 const char *from_tblname, const char *to_drvname,
487 const char *to_dbname, const char *to_tblname,
488 const char *select)
489{
490 return copy_table(from_drvname, from_dbname, from_tblname, to_drvname,
491 to_dbname, to_tblname, NULL, select, NULL, NULL, 0);
492}
493
494/*!
495 \brief Copy a table (by keys)
496
497 \param from_drvname name of driver from table is copied
498 \param from_dbname name of database from table is copied
499 \param from_tblname name of table to be copied
500 \param to_drvname name of driver to - where table is copied to
501 \param to_dbname name of database to - where table is copied to
502 \param to_tblname name of copied table
503 \param selcol name of column used to select records by values
504 in ivals or NULL
505 \param ivals pointer to array of integer values or NULL
506 \param nvals number of values in ivals
507
508 \return DB_OK on success
509 \return DB_FAILED on failure
510 */
511int db_copy_table_by_ints(const char *from_drvname, const char *from_dbname,
512 const char *from_tblname, const char *to_drvname,
513 const char *to_dbname, const char *to_tblname,
514 const char *selcol, int *ivals, int nvals)
515{
516 return copy_table(from_drvname, from_dbname, from_tblname, to_drvname,
518}
#define NULL
Definition ccmath.h:32
int db_copy_table_where(const char *from_drvname, const char *from_dbname, const char *from_tblname, const char *to_drvname, const char *to_dbname, const char *to_tblname, const char *where)
Copy a table (by where statement)
Definition copy_tab.c:462
int db_copy_table(const char *from_drvname, const char *from_dbname, const char *from_tblname, const char *to_drvname, const char *to_dbname, const char *to_tblname)
Copy a table.
Definition copy_tab.c:440
int db_copy_table_by_ints(const char *from_drvname, const char *from_dbname, const char *from_tblname, const char *to_drvname, const char *to_dbname, const char *to_tblname, const char *selcol, int *ivals, int nvals)
Copy a table (by keys)
Definition copy_tab.c:511
int db_copy_table_select(const char *from_drvname, const char *from_dbname, const char *from_tblname, const char *to_drvname, const char *to_dbname, const char *to_tblname, const char *select)
Copy a table (by select statement)
Definition copy_tab.c:485
Main header of GRASS DataBase Management Interface.
#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
int db_test_value_isnull(dbValue *)
Check of value is null.
Definition value.c:24
int db_convert_value_to_string(dbValue *, int, dbString *)
Convert value to string.
Definition valuefmt.c:66
int db_commit_transaction(dbDriver *)
Commit transaction.
Definition c_execute.c:79
const char * db_get_column_description(dbColumn *)
Returns column description for given column.
int db_get_column_length(dbColumn *)
Get column's length.
dbColumn * db_get_table_column(dbTable *, int)
Returns column structure for given table and column number.
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.
void db_set_column_length(dbColumn *, int)
Set column's length.
int db_get_column_sqltype(dbColumn *)
Returns column sqltype for column.
void db_set_column_sqltype(dbColumn *, int)
Define column sqltype for column.
void db_set_column_precision(dbColumn *, int)
Set column precision.
int db_open_database(dbDriver *, dbHandle *)
Open database connection.
Definition c_opendb.c:24
int db_close_database_shutdown_driver(dbDriver *)
Close driver/database connection.
Definition db.c:58
int db_begin_transaction(dbDriver *)
Begin transaction.
Definition c_execute.c:53
dbTable * db_alloc_table(int)
Allocate a table with a specific number of columns.
char * db_get_string(const dbString *)
Get string.
Definition string.c:138
int db_drop_table(dbDriver *, dbString *)
Drop table.
Definition c_drop_tab.c:25
int db_get_connection(dbConnection *)
Get default DB connection settings for the current mapset.
int db_set_column_description(dbColumn *, const char *)
Set column description.
dbTable * db_get_cursor_table(dbCursor *)
Get table allocated by cursor.
Definition cursor.c:64
int db_set_table_name(dbTable *, const char *)
Set the name of the table.
int db_set_string(dbString *, const char *)
Inserts string to dbString (enlarge string)
Definition string.c:39
const char * db_get_column_name(dbColumn *)
Returns column name for given column.
int db_set_handle(dbHandle *, const char *, const char *)
Set handle (database and schema name)
Definition handle.c:36
int db_execute_immediate(dbDriver *, dbString *)
Execute SQL statements.
Definition c_execute.c:24
int db_get_column_scale(dbColumn *)
Get column scale.
int db_list_tables(dbDriver *, dbString **, int *, int)
List available tables for given connection.
Definition c_list_tabs.c:36
dbDriver * db_start_driver(const char *)
Initialize a new dbDriver for db transaction.
Definition start.c:48
void db_double_quote_string(dbString *)
Replace each ' is replaced by ''.
Definition string.c:238
void db_init_handle(dbHandle *)
Initialize handle (i.e database/schema)
Definition handle.c:20
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.
const char * db_sqltype_name(int)
Get SQL data type description.
Definition sqltype.c:23
int db_set_column_name(dbColumn *, const char *)
Set column name.
int db_get_column_precision(dbColumn *)
Get column precision.
void db_set_column_scale(dbColumn *, int)
Set column scale.
int db_append_string(dbString *, const char *)
Append string to dbString.
Definition string.c:203
int db_create_table(dbDriver *, dbTable *)
Create table.
int db_fetch(dbCursor *, int, int *)
Fetch data from open cursor.
Definition c_fetch.c:25
int db_get_table_number_of_columns(dbTable *)
Return the number of columns of the table.
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition defs/gis.h:136
int G_get_overwrite(void)
Get overwrite value.
Definition parser.c:957
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
Definition strings.c:45
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:85
int G_debug(int, const char *,...) __attribute__((format(printf
#define GNAME_MAX
Definition gis.h:193
#define _(str)
Definition glocale.h:10
int count
int i
Definition dbmi.h:187