GRASS 8 Programmer's Manual 8.6.0dev(2026)-1d1e47ad9d
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 (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/dbmi.h>
18#include <grass/glocale.h>
19#include "macros.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
33/*!
34 \brief Copy table, used by various db_copy_table* (internal use only)
35
36 Use either 'where' or 'select' or 'selcol'+'ivals'+'nvals' but
37 never more than one.
38
39 Warning: driver opened as second must be closed as first, otherwise
40 it hangs, not sure why.
41
42 \param from_dvrname name of driver from table is copied
43 \param from_dbname name of database from table is copied
44 \param from_tbl_name name of table to be copied
45 \param to_dvrname name of driver to - where table is copied to
46 \param to_dbname name of database to - where table is copied to
47 \param to_dbname name of copied table
48 \param where WHERE SQL condition (without where key word) or NULL
49 \param select full select statement
50 \param selcol name of column used to select records by values in ivals or
51 NULL \param ivals pointer to array of integer values or NULL \param nvals
52 number of values in ivals
53
54 \return DB_OK on success
55 \return DB_FAILED on failure
56 */
57static int copy_table(const char *from_drvname, const char *from_dbname,
58 const char *from_tblname, const char *to_drvname,
59 const char *to_dbname, const char *to_tblname,
60 const char *where, const char *select, const char *selcol,
61 int *ivals, int nvals)
62{
63 int col, ncols, sqltype, ctype, more, selcol_found;
64 char buf[1000];
65 int *ivalues;
70 dbTable *table, *out_table;
73 dbValue *value;
74 const char *colname;
76 int count, i;
77
78 G_debug(3,
79 "db_copy_table():\n from driver = %s, db = %s, table = %s\n"
80 " to driver = %s, db = %s, table = %s, where = %s, select = %s",
82 to_tblname, where, select);
83
89
90 if (selcol) {
91 if (!ivals || (ivals && nvals == 0)) {
92 G_warning(_("Array of values to select from column <%s> is empty"),
93 selcol);
94 return DB_FAILED;
95 }
96 /* Make a copy of input values and sort it */
97 if (ivals) {
98 ivalues = (int *)G_malloc(nvals * sizeof(int));
99 memcpy(ivalues, ivals, nvals * sizeof(int));
100 qsort((void *)ivalues, nvals, sizeof(int), cmp);
101 }
102 }
103 else
104 ivalues = NULL;
105
106 /* Open input driver and database */
108 if (from_driver == NULL) {
109 G_warning(_("Unable to start driver <%s>"), from_drvname);
110 return DB_FAILED;
111 }
114 G_warning(_("Unable to open database <%s> by driver <%s>"), from_dbname,
117 return DB_FAILED;
118 }
119
120 /* Open output driver and database */
121 if (strcmp(from_drvname, to_drvname) == 0 &&
123 G_debug(3, "Use the same driver");
125 }
126 else {
128 if (to_driver == NULL) {
129 G_warning(_("Unable to start driver <%s>"), to_drvname);
131 return DB_FAILED;
132 }
135 G_warning(_("Unable to open database <%s> by driver <%s>"),
138 if (from_driver != to_driver) {
140 }
141 return DB_FAILED;
142 }
143 }
144
146
147 /* Because in SQLite3 an opened cursor is no more valid
148 if 'schema' is modified (create table), we have to open
149 cursor twice */
150
151 /* test if the table exists */
152 if (db_list_tables(to_driver, &tblnames, &count, 0) != DB_OK) {
153 G_warning(_("Unable to get list tables in database <%s>"), to_dbname);
155 if (from_driver != to_driver)
157
158 return DB_FAILED;
159 }
160
161 for (i = 0; i < count; i++) {
162 int ret;
163 char *tblname_i;
164
165 tblname_i = NULL;
166 if (strcmp(to_drvname, "pg") == 0) {
167 char *p, *tbl;
169
172 p = strstr(tbl, ".");
173
174 if (p) {
175 char buf[GNAME_MAX];
176
177 snprintf(buf, sizeof(buf), "%s.%s",
178 connection.schemaName ? connection.schemaName
179 : "public",
180 to_tblname);
181 if (strcmp(buf, tbl) == 0)
182 tblname_i = G_store(p + 1); /* skip dot */
183 }
184 }
185 if (!tblname_i) {
187 }
188
189 ret = DB_FAILED;
190 if (strcmp(to_tblname, tblname_i) == 0) {
191 if (G_get_overwrite()) {
192 G_warning(_("Table <%s> already exists in database and will be "
193 "overwritten"),
194 to_tblname);
196 }
197 else {
198 G_warning(_("Table <%s> already exists in database <%s>"),
200 }
201
202 if (ret != DB_OK) {
204 if (from_driver != to_driver)
206
207 return DB_FAILED;
208 }
209 }
210
212 }
213
214 /* Create new table */
215 /* Open cursor for data structure */
216 if (select) {
217 db_set_string(&sql, select);
218
219 /* TODO!: cannot use this because it will not work if a query
220 * ends with 'group by' for example */
221 /*
222 tmp = strdup ( select );
223 G_tolcase ( tmp );
224
225 if ( !strstr( tmp,"where") )
226 {
227 db_append_string ( &sql, " where 0 = 1");
228 }
229 else
230 {
231 db_append_string ( &sql, " and 0 = 1");
232 }
233
234 free (tmp);
235 */
236 }
237 else {
238 db_set_string(&sql, "select * from ");
240 db_append_string(&sql, " where 0 = 1"); /* to get no data */
241 }
242
243 G_debug(3, "db__copy_table: %s", db_get_string(&sql));
245 DB_OK) {
246 G_warning(_("Unable to open select cursor: '%s'"), db_get_string(&sql));
248 if (from_driver != to_driver) {
250 }
251 return DB_FAILED;
252 }
253 G_debug(3, "Select cursor opened");
254
255 table = db_get_cursor_table(&cursor);
256 ncols = db_get_table_number_of_columns(table);
257 G_debug(3, "ncols = %d", ncols);
258
259 out_table = db_alloc_table(ncols);
261
262 selcol_found = 0;
263 for (col = 0; col < ncols; col++) {
265
270
271 G_debug(3, "%s (%s)", colname, db_sqltype_name(sqltype));
272
274
275 if (selcol && G_strcasecmp(colname, selcol) == 0) {
276 if (ctype != DB_C_TYPE_INT)
277 G_fatal_error(_("Column <%s> is not integer"), colname);
278 selcol_found = 1;
279 }
280
288 }
289
291
292 if (selcol && !selcol_found)
293 G_fatal_error(_("Column <%s> not found"), selcol);
294
296 G_warning(_("Unable to create table <%s>"), to_tblname);
298 if (from_driver != to_driver) {
300 }
301 return DB_FAILED;
302 }
303
304 /* Open cursor with data */
305 if (select) {
306 db_set_string(&sql, select);
307 }
308 else {
309 db_set_string(&sql, "select * from ");
311 if (where) {
312 db_append_string(&sql, " where ");
313 db_append_string(&sql, where);
314 }
315 }
316
317 G_debug(3, "db__copy_table: %s", db_get_string(&sql));
319 DB_OK) {
320 G_warning(_("Unable to open select cursor: '%s'"), db_get_string(&sql));
322 if (from_driver != to_driver) {
324 }
325 return DB_FAILED;
326 }
327 G_debug(3, "Select cursor opened");
328
329 table = db_get_cursor_table(&cursor);
330 ncols = db_get_table_number_of_columns(table);
331 G_debug(3, "ncols = %d", ncols);
332
333 /* Copy all rows */
334 while (1) {
335 int select;
336
337 if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
338 G_warning(_("Unable to fetch data from table <%s>"), from_tblname);
341 if (from_driver != to_driver) {
343 }
344 return DB_FAILED;
345 }
346 if (!more)
347 break;
348
349 snprintf(buf, sizeof(buf), "insert into %s values ( ", to_tblname);
350 db_set_string(&sql, buf);
351 select = 1;
352 for (col = 0; col < ncols; col++) {
358
359 if (selcol && G_strcasecmp(colname, selcol) == 0) {
360 if (db_test_value_isnull(value))
361 continue;
362 if (!bsearch(&(value->i), ivalues, nvals, sizeof(int), cmp)) {
363 select = 0;
364 break;
365 }
366 }
367 if (col > 0)
368 db_append_string(&sql, ", ");
370 switch (ctype) {
371 case DB_C_TYPE_STRING:
373 if (db_test_value_isnull(value)) {
374 db_append_string(&sql, "null");
375 }
376 else {
378 db_append_string(&sql, "'");
380 db_append_string(&sql, "'");
381 }
382 break;
383 case DB_C_TYPE_INT:
384 case DB_C_TYPE_DOUBLE:
385 if (db_test_value_isnull(value)) {
386 db_append_string(&sql, "null");
387 }
388 else {
390 }
391 break;
392 default:
393 G_warning(_("Unknown column type (column <%s>)"), colname);
396 if (from_driver != to_driver) {
398 }
399 return DB_FAILED;
400 }
401 }
402 if (!select)
403 continue;
404 db_append_string(&sql, ")");
405 G_debug(3, "db__copy_table: %s", db_get_string(&sql));
407 G_warning("Unable to insert new record: '%s'", db_get_string(&sql));
410 if (from_driver != to_driver) {
412 }
413 return DB_FAILED;
414 }
415 }
416 if (selcol)
418 G_debug(3, "Table copy OK");
419
423 if (from_driver != to_driver) {
425 }
426
427 return DB_OK;
428}
429
430/*!
431 \brief Copy a table
432
433 \param from_drvname name of driver from table is copied
434 \param from_dbname name of database from table is copied
435 \param from_tblname name of table to be copied
436 \param to_drvname name of driver to - where table is copied to
437 \param to_dbname name of database to - where table is copied to
438 \param to_tblname name of copied table
439
440 \return DB_OK on success
441 \return DB_FAILED on failure
442 */
443int db_copy_table(const char *from_drvname, const char *from_dbname,
444 const char *from_tblname, const char *to_drvname,
445 const char *to_dbname, const char *to_tblname)
446{
447 return copy_table(from_drvname, from_dbname, from_tblname, to_drvname,
449}
450
451/*!
452 \brief Copy a table (by where statement)
453
454 \param from_drvname name of driver from table is copied
455 \param from_dbname name of database from table is copied
456 \param from_tblname name of table to be copied
457 \param to_drvname name of driver to - where table is copied to
458 \param to_dbname name of database to - where table is copied to
459 \param to_tblname name of copied table
460 \param where WHERE SQL condition (without where key word)
461
462 \return DB_OK on success
463 \return DB_FAILED on failure
464 */
465int db_copy_table_where(const char *from_drvname, const char *from_dbname,
466 const char *from_tblname, const char *to_drvname,
467 const char *to_dbname, const char *to_tblname,
468 const char *where)
469{
470 return copy_table(from_drvname, from_dbname, from_tblname, to_drvname,
471 to_dbname, to_tblname, where, NULL, NULL, NULL, 0);
472}
473
474/*!
475 \brief Copy a table (by select statement)
476
477 \param from_drvname name of driver from table is copied
478 \param from_dbname name of database from table is copied
479 \param from_tblname name of table to be copied
480 \param to_drvname name of driver to - where table is copied to
481 \param to_dbname name of database to - where table is copied to
482 \param to_tblname name of copied table
483 \param select full select statement
484
485 \return DB_OK on success
486 \return DB_FAILED on failure
487 */
488int db_copy_table_select(const char *from_drvname, const char *from_dbname,
489 const char *from_tblname, const char *to_drvname,
490 const char *to_dbname, const char *to_tblname,
491 const char *select)
492{
493 return copy_table(from_drvname, from_dbname, from_tblname, to_drvname,
494 to_dbname, to_tblname, NULL, select, NULL, NULL, 0);
495}
496
497/*!
498 \brief Copy a table (by keys)
499
500 \param from_drvname name of driver from table is copied
501 \param from_dbname name of database from table is copied
502 \param from_tblname name of table to be copied
503 \param to_drvname name of driver to - where table is copied to
504 \param to_dbname name of database to - where table is copied to
505 \param to_tblname name of copied table
506 \param selcol name of column used to select records by values
507 in ivals or NULL
508 \param ivals pointer to array of integer values or NULL
509 \param nvals number of values in ivals
510
511 \return DB_OK on success
512 \return DB_FAILED on failure
513 */
514int db_copy_table_by_ints(const char *from_drvname, const char *from_dbname,
515 const char *from_tblname, const char *to_drvname,
516 const char *to_dbname, const char *to_tblname,
517 const char *selcol, int *ivals, int nvals)
518{
519 return copy_table(from_drvname, from_dbname, from_tblname, to_drvname,
521}
#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:465
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:443
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:514
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:488
Main header of GRASS DataBase Management Interface.
#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
int db_test_value_isnull(dbValue *)
Check of value is null.
Definition value.c:26
int db_convert_value_to_string(dbValue *, int, dbString *)
Convert value to string.
Definition valuefmt.c:68
int db_commit_transaction(dbDriver *)
Commit transaction.
Definition c_execute.c:82
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:24
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:27
int db_close_database_shutdown_driver(dbDriver *)
Close driver/database connection.
Definition db.c:61
int db_begin_transaction(dbDriver *)
Begin transaction.
Definition c_execute.c:56
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:140
int db_drop_table(dbDriver *, dbString *)
Drop table.
Definition c_drop_tab.c:28
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:67
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:41
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:39
int db_execute_immediate(dbDriver *, dbString *)
Execute SQL statements.
Definition c_execute.c:27
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:39
dbDriver * db_start_driver(const char *)
Initialize a new dbDriver for db transaction.
Definition start.c:51
void db_double_quote_string(dbString *)
Replace each ' is replaced by ''.
Definition string.c:240
void db_init_handle(dbHandle *)
Initialize handle (i.e database/schema)
Definition handle.c:23
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.
const char * db_sqltype_name(int)
Get SQL data type description.
Definition sqltype.c:25
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:205
int db_create_table(dbDriver *, dbTable *)
Create table.
int db_fetch(dbCursor *, int, int *)
Fetch data from open cursor.
Definition c_fetch.c:28
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:147
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:139
int G_get_overwrite(void)
Get overwrite value.
Definition parser.c:959
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
Definition strings.c:47
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:87
int G_debug(int, const char *,...) __attribute__((format(printf
#define GNAME_MAX
Definition gis.h:196
#define _(str)
Definition glocale.h:10
int count
int i
Definition dbmi.h:189