GRASS 8 Programmer's Manual 8.6.0dev(2026)-1878fdfec5
Loading...
Searching...
No Matches
field.c
Go to the documentation of this file.
1/*!
2 \file lib/vector/Vlib/field.c
3
4 \brief Vector library - field (layer) related fns.
5
6 Higher level functions for reading/writing/manipulating vectors.
7
8 \todo see Vect_read_dblinks(); activate auto-FID detection once
9 OGR_L_GetFIDColumn() is working or solution found if FID not
10 available
11
12 SPDX-FileCopyrightText: 2001-2009, 2011-2012 GRASS Development Team
13 SPDX-License-Identifier: GPL-2.0-or-later
14
15 \author Original author CERL, probably Dave Gerdes or Mike Higgins.
16 \author Update to GRASS 5.7 by Radim Blazek and David D. Gray.
17 \author Various updates by Martin Landa <landa.martin gmail.com>, 2009-2011
18 */
19
20#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
23#include <grass/gis.h>
24#include <grass/glocale.h>
25#include <grass/dbmi.h>
26#include <grass/vector.h>
27
28#include "local_proto.h"
29
30#include <gdal_version.h> /* needed for FID detection */
31#include <ogr_api.h>
32
33#ifdef HAVE_POSTGRES
34#define NOPG_UNUSED
35#else
36#define NOPG_UNUSED G_UNUSED
37#endif
38
39/*!
40 \brief Create and init new dblinks structure
41
42 \return pointer to new dblinks structure
43 \return NULL on failure
44 */
46{
47 struct dblinks *p;
48
49 p = (struct dblinks *)G_malloc(sizeof(struct dblinks));
50
51 if (p) {
52 /* initialize members */
53 G_zero(p, sizeof(struct dblinks));
54 }
55
56 return p;
57}
58
59static int name2sql(char *name)
60{
61 char *s = name;
62 int ret;
63
64 if (!s)
65 return 0;
66
67 /* sql-compliant name must start with letter */
68 if (!((*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z'))) {
70 _("Name <%s> is not SQL compliant. Must start with a letter."),
71 name);
72 return 0;
73 }
74
75 ret = 1;
76 /* convert illegal characters to underscore */
77 for (s++; *s; s++) {
78 if (!((*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z') ||
79 (*s >= '0' && *s <= '9') || *s == '_')) {
80 G_debug(2, "Character '%c' not allowed.", *s);
81 *s = '_';
82 ret++;
83 }
84 }
85
86 return ret;
87}
88
89/*!
90 \brief Reset dblinks structure (number of fields)
91
92 \param p pointer to existing dblinks structure
93 */
95{
96 p->n_fields = 0;
97}
98
99/*!
100 \brief Add new db connection to Map_info structure
101
102 \param Map pointer to Map_info structure
103 \param number layer number
104 \param name layer name (if not given use table name)
105 \param table table name
106 \param key key name
107 \param db database name
108 \param driver driver name
109
110 \return 0 on success
111 \return -1 on failure
112 */
113int Vect_map_add_dblink(struct Map_info *Map, int number, const char *name,
114 const char *table, const char *key, const char *db,
115 const char *driver)
116{
117 int ret;
118
119 if (number < 1) {
120 G_warning(_("Layer number must be 1 or greater"));
121 return -1;
122 }
123
124 if (Map->mode != GV_MODE_WRITE && Map->mode != GV_MODE_RW) {
125 G_warning(_("Unable to add attribute link, vector map is "
126 "not opened in WRITE mode"));
127 return -1;
128 }
129
130 ret = Vect_add_dblink(Map->dblnk, number, name, table, key, db, driver);
131 if (ret == -1) {
132 G_warning(_("Unable to add attribute link"));
133 return -1;
134 }
135 /* write it immediately otherwise it is lost if module crashes */
137 if (ret == -1) {
138 G_warning(_("Unable to write attribute links"));
139 return -1;
140 }
141 return 0;
142}
143
144/*!
145 \brief Delete db connection from Map_info structure
146
147 \param Map pointer to Map_info structure
148 \param field layer number (-1 to delete all dblinks)
149
150 \return 0 deleted
151 \return -1 error
152 */
154{
155 int i, j, ret;
156 struct dblinks *links;
157
158 G_debug(4, "Vect_map_del_dblink() field = %d", field);
159 links = Map->dblnk;
160
161 ret = -1;
162 for (i = 0; i < links->n_fields; i++) {
163 if (field < 0 || links->field[i].number == field) { /* field found */
164 for (j = i; j < links->n_fields - 1; j++) {
165 links->field[j].number = links->field[j + 1].number;
166 links->field[j].name = links->field[j + 1].name;
167 links->field[j].table = links->field[j + 1].table;
168 links->field[j].key = links->field[j + 1].key;
169 links->field[j].database = links->field[j + 1].database;
170 links->field[j].driver = links->field[j + 1].driver;
171 }
172 ret = 0;
173 links->n_fields--;
174 }
175 }
176
177 if (ret == -1)
178 return -1;
179
180 /* write it immediately otherwise it is lost if module crashes */
182 if (ret == -1) {
183 G_warning(_("Unable to write database links"));
184 return -1;
185 }
186
187 return 0;
188}
189
190/*!
191 \brief Copy DB links from input vector map to output vector map
192
193 \param In pointer to Map_info structure (input)
194 \param Out pointer to Map_info structure (output)
195 \param first_only TRUE to copy only first link otherwise all DB links are
196 copied
197 */
198void Vect_copy_map_dblinks(struct Map_info *In, struct Map_info *Out,
199 int first_only)
200{
201 int i, ndblinks;
202 struct field_info *Fi;
203
205 for (i = 0; i < ndblinks; i++) {
206 Fi = Vect_get_dblink(In, 0);
207 if (!Fi) {
208 G_warning(_("Database connection not defined. Skipping."));
209 continue;
210 }
211 Vect_map_add_dblink(Out, Fi->number, Fi->name, Fi->table, Fi->key,
212 Fi->database, Fi->driver);
213
214 if (first_only && ndblinks > 1)
215 G_warning(_("More DB links defined for input vector map. "
216 "Using only first DB link for output."));
217 }
218}
219
220/*!
221 \brief Check if DB connection exists in dblinks structure
222
223 \param Map pointer to Map_info structure
224 \param field layer number
225 \param name layer name
226
227 \return 1 dblink for field exists
228 \return 0 dblink does not exist for field
229 */
230int Vect_map_check_dblink(struct Map_info *Map, int field, const char *name)
231{
232 return Vect_check_dblink(Map->dblnk, field, name);
233}
234
235/*!
236 \brief Check if DB connection exists in dblinks structure
237
238 \param p pointer to existing dblinks structure
239 \param field layer number
240 \param name layer name
241
242 \return 1 dblink for field exists
243 \return 0 dblink does not exist for field
244 */
245int Vect_check_dblink(const struct dblinks *p, int field, const char *name)
246{
247 int i;
248
249 G_debug(3, "Vect_check_dblink: field %d, name %s", field,
250 (name != NULL ? name : "not given"));
251
252 for (i = 0; i < p->n_fields; i++) {
253 if (p->field[i].number == field) {
254 return 1;
255 }
256 if (name != NULL && p->field[i].name != NULL) {
257 if (strcmp(p->field[i].name, name) == 0)
258 return 1;
259 }
260 }
261 return 0;
262}
263
264/*!
265 \brief Add new DB connection to dblinks structure
266
267 \param[in,out] p pointer to existing dblinks structure
268 \param number layer number (1 for OGR)
269 \param name layer name (layer for OGR) - if not given use table name
270 \param table table name (layer for OGR)
271 \param key key name
272 \param db database name (datasource for OGR)
273 \param driver driver name (dbf, postgresql, ogr, ...)
274
275 \return 0 on success
276 \return -1 error
277 */
278int Vect_add_dblink(struct dblinks *p, int number, const char *name,
279 const char *table, const char *key, const char *db,
280 const char *driver)
281{
282 int ret;
283
284 G_debug(3, "Field number <%d>, name <%s>", number, name);
285 if (!name) {
286 /* if name is not given, use table name */
287 name = table;
288 }
290 if (ret == 1) {
291 G_warning(_("Layer number %d or name <%s> already exists"), number,
292 name);
293 return -1;
294 }
295
296 if (p->n_fields == p->alloc_fields) {
297 p->alloc_fields += 10;
298 p->field = (struct field_info *)G_realloc(
299 (void *)p->field, p->alloc_fields * sizeof(struct field_info));
300 }
301
302 p->field[p->n_fields].number = number;
303
304 if (name != NULL) {
305 p->field[p->n_fields].name = G_store(name);
306 /* replace all spaces with underscore, otherwise dbln can't be read */
307 /* G_strchg(p->field[p->n_fields].name, ' ', '_'); */
308 if (!name2sql(p->field[p->n_fields].name)) {
309 G_free(p->field[p->n_fields].name);
310 p->field[p->n_fields].name = NULL;
311 }
312 }
313 else
314 p->field[p->n_fields].name = NULL;
315
316 if (table != NULL)
317 p->field[p->n_fields].table = G_store(table);
318 else
319 p->field[p->n_fields].table = NULL;
320
321 if (key != NULL)
322 p->field[p->n_fields].key = G_store(key);
323 else
324 p->field[p->n_fields].key = NULL;
325
326 if (db != NULL)
327 p->field[p->n_fields].database = G_store(db);
328 else
329 p->field[p->n_fields].database = NULL;
330
331 if (driver != NULL)
332 p->field[p->n_fields].driver = G_store(driver);
333 else
334 p->field[p->n_fields].driver = NULL;
335
336 p->n_fields++;
337
338 return 0;
339}
340
341/*!
342 \brief Get default information about link to database for new dblink
343
344 \param Map pointer to Map_info structure
345 \param field layer number
346 \param field_name layer name
347 \param type how many tables are linked to map: GV_1TABLE / GV_MTABLE
348
349 \return pointer to allocated field_info structure
350 */
352 const char *field_name, int type)
353{
354 struct field_info *fi;
355 char buf[GNAME_MAX];
356 char *buf2;
357 const char *schema;
359
360 G_debug(1, "Vect_default_field_info(): map = %s field = %d", Map->name,
361 field);
362
363 if (Map->format == GV_FORMAT_OGR_DIRECT) {
364 G_zero(&connection, sizeof(dbConnection));
365 connection.driverName = G_store("ogr");
366 connection.databaseName = G_store(Map->fInfo.ogr.dsn);
367 }
368 else {
370 }
371
372 G_debug(2, "drv = %s db = %s", connection.driverName,
373 connection.databaseName);
374
375 if (!connection.driverName && !connection.databaseName) {
376 /* Set default values */
379
380 G_important_message(_("Default driver / database set to:\n"
381 "driver: %s\ndatabase: %s"),
382 connection.driverName, connection.databaseName);
383 }
384 /* they must be a matched pair, so if one is set but not the other
385 then give up and let the user figure it out */
386 else if (!connection.driverName) {
387 G_fatal_error(_("Default driver is not set"));
388 }
389 else if (!connection.databaseName) {
390 G_fatal_error(_("Default database is not set"));
391 }
392
393 fi = (struct field_info *)G_malloc(sizeof(struct field_info));
394
395 fi->number = field;
396
397 /* Field name */
398 fi->name = NULL;
399 if (field_name && *field_name) {
400 fi->name = G_store(field_name);
401 if (!name2sql(fi->name)) {
402 G_free(fi->name);
403 fi->name = NULL;
404 }
405 }
406
407 /* Table name */
408 if (type == GV_1TABLE) {
409 snprintf(buf, sizeof(buf), "%s", Map->name);
410 }
411 else {
412 if (fi->name != NULL && strlen(fi->name) > 0) {
413 snprintf(buf, sizeof(buf), "%s_%s", Map->name, fi->name);
414 if (!name2sql(buf)) {
415 snprintf(buf, sizeof(buf), "%s_%d", Map->name, field);
416 }
417 }
418 else
419 snprintf(buf, sizeof(buf), "%s_%d", Map->name, field);
420 }
421 schema = connection.schemaName;
422 if (schema && strlen(schema) > 0) {
423 G_asprintf(&buf2, "%s.%s", schema, buf);
424 fi->table = buf2;
425 }
426 else {
427 fi->table = G_store(buf);
428 }
429
430 /* Field name still empty */
431 if (!fi->name)
432 fi->name = G_store(buf);
433
434 fi->key = G_store(GV_KEY_COLUMN); /* Should be: id/fid/gfid/... ? */
435#ifdef TEMPORARY_MAP_DB
436 if (Map->temporary) {
438 if (strcmp(DB_DEFAULT_DRIVER, "sqlite") == 0)
439 strcat(buf, "/sqlite.db");
440 else
441 strcat(buf, "/db.dbf");
442 fi->database = G_store(buf);
444 }
445 else {
446 fi->database = G_store(connection.databaseName);
447 fi->driver = G_store(connection.driverName);
448 }
449#else
450 fi->database = G_store(connection.databaseName);
451 fi->driver = G_store(connection.driverName);
452#endif
453
454 return fi;
455}
456
457/*!
458 \brief Get information about link to database.
459
460 Variables are substituted by values, link is index to array of
461 dblinks.
462
463 \param Map pointer to Map_info structure
464 \param link link id
465
466 \return pointer to new field_info structure
467 */
468struct field_info *Vect_get_dblink(struct Map_info *Map, int link)
469{
470 struct field_info *fi;
471
472 G_debug(1, "Vect_get_dblink(): link = %d", link);
473
474 if (link >= Map->dblnk->n_fields) {
475 G_warning(_("Requested dblink %d, maximum link number %d"), link,
476 Map->dblnk->n_fields - 1);
477 return NULL;
478 }
479
480 fi = (struct field_info *)G_malloc(sizeof(struct field_info));
481 fi->number = Map->dblnk->field[link].number;
482
483 if (Map->dblnk->field[link].name != NULL)
484 fi->name = G_store(Map->dblnk->field[link].name);
485 else
486 fi->name = NULL;
487
488 fi->table = G_store(Map->dblnk->field[link].table);
489 fi->key = G_store(Map->dblnk->field[link].key);
490 fi->database = Vect_subst_var(Map->dblnk->field[link].database, Map);
491 fi->driver = G_store(Map->dblnk->field[link].driver);
492
493 return fi;
494}
495
496/*!
497 \brief Get information about link to database (by layer number)
498
499 Variables are substituted by values, field is number of requested
500 field.
501
502 \param Map pointer to Map_info structure
503 \param field layer number
504
505 \return pointer to new field_info structure
506 \return NULL if not found
507 */
508struct field_info *Vect_get_field(struct Map_info *Map, int field)
509{
510 int i;
511 struct field_info *fi = NULL;
512
513 G_debug(1, "Vect_get_field(): field = %d", field);
514
515 for (i = 0; i < Map->dblnk->n_fields; i++) {
516 if (Map->dblnk->field[i].number == field) {
517 fi = Vect_get_dblink(Map, i);
518 break;
519 }
520 }
521
522 return fi;
523}
524
525/*!
526 \brief Get information about link to database (by layer name)
527
528 \param Map pointer to Map_info structure
529 \param field layer name
530
531 \return pointer to new field_info structure
532 \return NULL if not found
533 */
535 const char *field)
536{
537 int i;
538 struct field_info *fi = NULL;
539
540 G_debug(1, "Vect_get_field_by_name(): field = %s", field);
541
542 for (i = 0; i < Map->dblnk->n_fields; i++) {
543 if (strcmp(Map->dblnk->field[i].name, field) == 0) {
544 fi = Vect_get_dblink(Map, i);
545 break;
546 }
547 }
548
549 return fi;
550}
551
552/*!
553 \brief Get information about link to database (by layer number or layer name)
554
555 Note: if <em>field</em> is -1 then the function returns the first
556 dblink or NULL
557
558 \param Map pointer to Map_info structure
559 \param field layer number or name
560
561 \return pointer to new field_info structure
562 \return NULL if not found
563 */
564struct field_info *Vect_get_field2(struct Map_info *Map, const char *field)
565{
566 int ifield;
567 struct field_info *fi;
568
569 G_debug(1, "Vect_get_field2(): field = %s", field);
570
571 fi = NULL;
572 ifield = atoi(field);
573
574 if (ifield > 0) {
576 if (fi)
577 return fi;
578 }
579 else if (ifield == -1) {
580 if (Vect_get_num_dblinks(Map) > 0)
581 return Vect_get_dblink(Map, 0); /* return first */
582 else
583 return NULL;
584 }
585 else if (ifield == 0)
586 return Vect_get_field_by_name(Map, field);
587
588 return NULL;
589}
590
591/*!
592 \brief Get field number of given field
593
594 \param Map pointer to Map_info structure
595 \param field layer name
596
597 \return layer number
598 \return -1 for all layers
599 \return 0 if layer not found
600 */
601int Vect_get_field_number(struct Map_info *Map, const char *field)
602{
603 struct field_info *fi;
604
605 G_debug(1, "Vect_get_field_number(): field = %s", field);
606
607 if (strcmp(field, "-1") == 0)
608 return -1;
609
610 if (Vect_get_num_dblinks(Map) == 0)
611 return atoi(field);
612
613 fi = Vect_get_field2(Map, field);
614
615 if (fi)
616 return fi->number;
617
618 return atoi(field);
619}
620
621/*!
622 \brief Free a struct field_info and all memory associated with it.
623
624 \param[in,out] fi pointer to field_info structure
625 */
627{
628 if (!fi)
629 return;
630 if (fi->name)
631 G_free(fi->name);
632 G_free(fi->driver);
633 G_free(fi->database);
634 G_free(fi->table);
635 G_free(fi->key);
636 G_free(fi);
637 fi = NULL;
638}
639
640static int read_dblinks_nat(struct Map_info *Map)
641{
642 FILE *fd;
643 char file[1024], buf[2001];
644 char tab[1024], col[1024], db[1024], drv[1024], fldstr[1024], *fldname;
645 int fld;
646 char *c, path[GPATH_MAX];
647 int row, rule;
648 struct dblinks *dbl;
649 char **tokens;
650 int ntok, i;
651
652 dbl = Map->dblnk;
653
654 /* Read dblink for native format */
656 fd = G_fopen_old(path, GV_DBLN_ELEMENT, Map->mapset);
657 if (fd == NULL) { /* This may be correct, no tables defined */
658 G_debug(1, "Cannot open vector database definition file");
659 return -1;
660 }
661
662 row = 0;
663 rule = 0;
664 while (G_getl2(buf, 2000, fd)) {
665 row++;
666 G_chop(buf);
667 G_debug(1, "dbln: %s", buf);
668
669 c = (char *)strchr(buf, '#');
670 if (c != NULL)
671 *c = '\0';
672
673 if (strlen(buf) == 0)
674 continue;
675
676#ifdef NOT_ABLE_TO_READ_GRASS_6
677 int ndef;
678
679 ndef = sscanf(buf, "%s|%s|%s|%s|%s", fldstr, tab, col, db, drv);
680
681 if (ndef < 2 || (ndef < 5 && rule < 1)) {
682 G_warning(_("Error in rule on row %d in <%s>"), row, file);
683 continue;
684 }
685#else
686 tokens = G_tokenize(buf, " |");
688
689 if (ntok < 2 || (ntok < 5 && rule < 1)) {
690 G_warning(_("Error in rule on row %d in <%s>"), row, file);
691 continue;
692 }
693
694 strcpy(fldstr, tokens[0]);
695 strcpy(tab, tokens[1]);
696 if (ntok > 2) {
697 strcpy(col, tokens[2]);
698 if (ntok > 3) {
699 strcpy(db, tokens[3]);
700 /* allow for spaces in path names */
701 for (i = 4; i < ntok - 1; i++) {
702 strcat(db, " ");
703 strcat(db, tokens[i]);
704 }
705
706 strcpy(drv, tokens[ntok - 1]);
707 }
708 }
710#endif
711
712 /* get field and field name */
713 fldname = strchr(fldstr, '/');
714 if (fldname != NULL) { /* field has name */
715 fldname[0] = 0;
716 fldname++;
717 }
718 fld = atoi(fldstr);
719
721
722 G_debug(1,
723 "field = %d name = %s, table = %s, key = %s, database = %s, "
724 "driver = %s",
725 fld, fldname, tab, col, db, drv);
726
727 rule++;
728 }
729 fclose(fd);
730
731 G_debug(1, "Dblinks read");
732
733 return rule;
734}
735
736/* return -1 on error */
737static int read_dblinks_ogr(struct Map_info *Map)
738{
739 struct dblinks *dbl;
740
741 dbl = Map->dblnk;
742 G_debug(3, "Searching for FID column in OGR DB");
743 int nLayers;
744 char *ogr_fid_col;
745
746 G_debug(3, "GDAL_VERSION_NUM: %d", GDAL_VERSION_NUM);
747
748 if (Map->fInfo.ogr.ds == NULL) {
749 /* open the connection to fetch the FID column name */
751
752 /* data source handle */
753 Map->fInfo.ogr.ds = OGROpen(Map->fInfo.ogr.dsn, FALSE, NULL);
754 if (Map->fInfo.ogr.ds == NULL) {
755 G_warning(_("Unable to open OGR data source '%s'"),
756 Map->fInfo.ogr.dsn);
757 return -1;
758 }
759 }
760 if (Map->fInfo.ogr.layer == NULL) {
761 /* get layer number */
763 Map->fInfo.ogr.ds); /* Layers = Maps in OGR DB */
764
765 G_debug(3, "%d layers (maps) found in data source", nLayers);
766
767 G_debug(3, "Trying to open OGR layer: %s", Map->fInfo.ogr.layer_name);
768 if (Map->fInfo.ogr.layer_name) {
769 Map->fInfo.ogr.layer = OGR_DS_GetLayerByName(
770 Map->fInfo.ogr.ds, Map->fInfo.ogr.layer_name);
771 if (Map->fInfo.ogr.layer == NULL) {
772 OGR_DS_Destroy(Map->fInfo.ogr.ds);
773 Map->fInfo.ogr.ds = NULL;
774 G_warning(_("Unable to open OGR layer <%s>"),
775 Map->fInfo.ogr.layer_name);
776 return -1;
777 }
778 }
779 }
780
781 /* get fid column */
782 ogr_fid_col = G_store(OGR_L_GetFIDColumn(Map->fInfo.ogr.layer));
783 G_debug(3, "Using FID column <%s> in OGR DB", ogr_fid_col);
784 Vect_add_dblink(dbl, 1, Map->fInfo.ogr.layer_name,
785 Map->fInfo.ogr.layer_name, ogr_fid_col, Map->fInfo.ogr.dsn,
786 "ogr");
787 return 1;
788}
789
790static int read_dblinks_pg(struct Map_info *Map NOPG_UNUSED)
791{
792#ifdef HAVE_POSTGRES
793 char *name;
794 struct dblinks *dbl;
795 struct Format_info_pg *pg_info;
796
797 dbl = Map->dblnk;
798 pg_info = &(Map->fInfo.pg);
799
800 if (!pg_info->fid_column) {
801 G_warning(_("Feature table <%s> has no primary key defined. "
802 "Unable to define DB links."),
803 pg_info->table_name);
804 return -1;
805 }
806 G_debug(3, "Using FID column <%s>", pg_info->fid_column);
807
808 name = NULL;
809 if (G_strcasecmp(pg_info->schema_name, "public") != 0)
810 G_asprintf(&name, "%s.%s", pg_info->schema_name, pg_info->table_name);
811 else
812 name = pg_info->table_name;
813
814 Vect_add_dblink(dbl, 1, name, name, pg_info->fid_column, pg_info->db_name,
815 "pg");
816 if (name != pg_info->table_name)
817 G_free(name);
818 return 1;
819#else
820 G_warning(_("GRASS not compiled with PostgreSQL support"));
821 return -1;
822#endif
823}
824
825/*!
826 \brief Read dblinks to existing structure.
827
828 Variables are not substituted by values.
829
830 \param Map pointer to Map_info structure
831
832 \return number of links read
833 \return -1 on error
834 */
836{
837 G_debug(1, "Vect_read_dblinks(): map = %s, mapset = %s", Map->name,
838 Map->mapset);
839
840 Vect_reset_dblinks(Map->dblnk);
841
842 if (Map->format == GV_FORMAT_NATIVE) {
843 return read_dblinks_nat(Map);
844 }
845 else if (Map->format == GV_FORMAT_OGR ||
846 Map->format == GV_FORMAT_OGR_DIRECT) {
847 return read_dblinks_ogr(Map);
848 }
849 else if (Map->format == GV_FORMAT_POSTGIS) {
850 return read_dblinks_pg(Map);
851 }
852 else {
853 G_fatal_error(_("Unknown vector map format"));
854 }
855
856 return -1;
857}
858
859/*!
860 \brief Write dblinks to file
861
862 \param Map pointer to Map_info structure
863
864 \return 0 on success
865 \return -1 on error
866 */
868{
869 int i;
870 FILE *fd;
871 char path[GPATH_MAX], buf[1024];
872 struct dblinks *dbl;
873
874 if (Map->format != GV_FORMAT_NATIVE)
875 /* nothing to write for non-native formats */
876 return 0;
877
878 G_debug(1, "Vect_write_dblinks(): map = %s, mapset = %s", Map->name,
879 Map->mapset);
880
881 dbl = Map->dblnk;
882
885 if (fd == NULL) { /* This may be correct, no tables defined */
886 G_warning(
887 _("Unable to create database definition file for vector map <%s>"),
889 return -1;
890 }
891
892 for (i = 0; i < dbl->n_fields; i++) {
893 if (dbl->field[i].name != NULL)
894 snprintf(buf, sizeof(buf), "%d/%s", dbl->field[i].number,
895 dbl->field[i].name);
896 else
897 snprintf(buf, sizeof(buf), "%d", dbl->field[i].number);
898
899 fprintf(fd, "%s|%s|%s|%s|%s\n", buf, dbl->field[i].table,
900 dbl->field[i].key, dbl->field[i].database,
901 dbl->field[i].driver);
902 G_debug(1, "%s|%s|%s|%s|%s", buf, dbl->field[i].table,
903 dbl->field[i].key, dbl->field[i].database,
904 dbl->field[i].driver);
905 }
906 fclose(fd);
907
908 G_debug(1, "Dblinks written");
909
910 return 0;
911}
912
913/*!
914 \brief Substitute variable in string
915
916 \param in current string
917 \param Map pointer to Map_info structure
918
919 \return pointer to new string
920 */
921char *Vect_subst_var(const char *in, struct Map_info *Map)
922{
923 char *c;
924 char buf[1000], str[1000];
925
926 G_debug(3, "Vect_subst_var(): in = %s, map = %s, mapset = %s", in,
927 Map->name, Map->mapset);
928
929#ifdef __MINGW32__
930 char *cin;
931
932 cin = G_str_replace(in, "/", "\\");
933 strcpy(str, cin);
934 G_free(cin);
935#else
936 strcpy(str, in);
937#endif
938
939 strcpy(buf, str);
940 c = (char *)strstr(buf, "$GISDBASE");
941 if (c != NULL) {
942 *c = '\0';
943 snprintf(str, sizeof(str), "%s%s%s", buf, Map->gisdbase, c + 9);
944 }
945
946 strcpy(buf, str);
947 c = (char *)strstr(buf, "$LOCATION_NAME");
948 if (c != NULL) {
949 *c = '\0';
950 snprintf(str, sizeof(str), "%s%s%s", buf, Map->location, c + 14);
951 }
952
953 strcpy(buf, str);
954 c = (char *)strstr(buf, "$MAPSET");
955 if (c != NULL) {
956 *c = '\0';
957 snprintf(str, sizeof(str), "%s%s%s", buf, Map->mapset, c + 7);
958 }
959
960 strcpy(buf, str);
961 c = (char *)strstr(buf, "$MAP");
962 if (c != NULL) {
963 *c = '\0';
964 snprintf(str, sizeof(str), "%s%s%s", buf, Map->name, c + 4);
965 }
966
967 G_debug(3, " -> %s", str);
968 return (G_store(str));
969}
970
971/*!
972 \brief Rewrite 'dbln' file
973
974 Should be used by GRASS modules which update database tables, so
975 that other applications know that tables were changed and can reload
976 data.
977
978 \param Map pointer to Map_info structure
979 */
981{
982 if (strcmp(Map->mapset, G_mapset()) != 0 &&
983 G_strcasecmp(Map->mapset, "ogr") != 0) {
985 _("Bug: attempt to update map which is not in current mapset"));
986 }
987
989}
#define NULL
Definition ccmath.h:32
AMI_err name(char **stream_name)
Definition ami_stream.h:426
Main header of GRASS DataBase Management Interface.
#define DB_DEFAULT_DRIVER
Definition dbmi.h:19
int db_get_connection(dbConnection *)
Get default DB connection settings for the current mapset.
int db_set_default_connection(void)
Sets up database connection settings using GRASS default from dbmi.h.
int G_getl2(char *, int, FILE *)
Gets a line of text from a file of any pedigree.
Definition getl.c:58
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 void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
FILE * G_fopen_new(const char *, const char *)
Open a new database file.
Definition gis/open.c:218
#define G_malloc(n)
Definition defs/gis.h:136
FILE * G_fopen_old(const char *, const char *, const char *)
Open a database file for reading.
Definition gis/open.c:250
char ** G_tokenize(const char *, const char *)
Tokenize string.
Definition gis/token.c:45
void G_free_tokens(char **)
Free memory allocated to tokens.
Definition gis/token.c:195
void void void G_important_message(const char *,...) __attribute__((format(printf
int G_asprintf(char **, const char *,...) __attribute__((format(printf
int G_number_of_tokens(char **)
Return number of tokens.
Definition gis/token.c:176
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
Definition strings.c:45
char * G_chop(char *)
Chop leading and trailing white spaces.
Definition strings.c:330
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:85
char * G_str_replace(const char *, const char *, const char *)
Replace all occurrences of old_str in buffer with new_str.
Definition strings.c:187
int G_debug(int, const char *,...) __attribute__((format(printf
const char * G_mapset(void)
Get current mapset name.
Definition gis/mapset.c:31
const char * Vect_get_name(struct Map_info *)
Get name of vector map.
int Vect_get_num_dblinks(struct Map_info *)
Get number of defined dblinks.
Definition level_two.c:157
#define GV_FORMAT_POSTGIS
PostGIS format.
Definition dig_defines.h:89
#define GV_1TABLE
One table linked to vector map.
Definition dig_defines.h:99
#define GV_MODE_WRITE
Write vector map open mode.
#define GV_DBLN_ELEMENT
Native format, link to database.
Definition dig_defines.h:16
#define GV_FORMAT_OGR_DIRECT
OGR format (direct access)
Definition dig_defines.h:87
#define GV_FORMAT_OGR
OGR format.
Definition dig_defines.h:85
#define GV_MODE_RW
Read-write vector map open mode.
#define GV_FORMAT_NATIVE
Geometry data formats supported by lib Don't change GV_FORMAT_* values, this order is hardcoded in li...
Definition dig_defines.h:83
struct dblinks * Vect_new_dblinks_struct(void)
Create and init new dblinks structure.
Definition field.c:45
#define NOPG_UNUSED
Definition field.c:34
void Vect_set_db_updated(struct Map_info *Map)
Rewrite 'dbln' file.
Definition field.c:980
int Vect_map_del_dblink(struct Map_info *Map, int field)
Delete db connection from Map_info structure.
Definition field.c:153
int Vect_get_field_number(struct Map_info *Map, const char *field)
Get field number of given field.
Definition field.c:601
void Vect_reset_dblinks(struct dblinks *p)
Reset dblinks structure (number of fields)
Definition field.c:94
struct field_info * Vect_get_field2(struct Map_info *Map, const char *field)
Get information about link to database (by layer number or layer name)
Definition field.c:564
struct field_info * Vect_default_field_info(struct Map_info *Map, int field, const char *field_name, int type)
Get default information about link to database for new dblink.
Definition field.c:351
struct field_info * Vect_get_dblink(struct Map_info *Map, int link)
Get information about link to database.
Definition field.c:468
int Vect_add_dblink(struct dblinks *p, int number, const char *name, const char *table, const char *key, const char *db, const char *driver)
Add new DB connection to dblinks structure.
Definition field.c:278
int Vect_check_dblink(const struct dblinks *p, int field, const char *name)
Check if DB connection exists in dblinks structure.
Definition field.c:245
int Vect_read_dblinks(struct Map_info *Map)
Read dblinks to existing structure.
Definition field.c:835
char * Vect_subst_var(const char *in, struct Map_info *Map)
Substitute variable in string.
Definition field.c:921
int Vect_map_add_dblink(struct Map_info *Map, int number, const char *name, const char *table, const char *key, const char *db, const char *driver)
Add new db connection to Map_info structure.
Definition field.c:113
int Vect_write_dblinks(struct Map_info *Map)
Write dblinks to file.
Definition field.c:867
struct field_info * Vect_get_field_by_name(struct Map_info *Map, const char *field)
Get information about link to database (by layer name)
Definition field.c:534
void Vect_destroy_field_info(struct field_info *fi)
Free a struct field_info and all memory associated with it.
Definition field.c:626
int Vect_map_check_dblink(struct Map_info *Map, int field, const char *name)
Check if DB connection exists in dblinks structure.
Definition field.c:230
struct field_info * Vect_get_field(struct Map_info *Map, int field)
Get information about link to database (by layer number)
Definition field.c:508
void Vect_copy_map_dblinks(struct Map_info *In, struct Map_info *Out, int first_only)
Copy DB links from input vector map to output vector map.
Definition field.c:198
#define GV_KEY_COLUMN
Name of default key column.
Definition gis.h:420
#define GPATH_MAX
Definition gis.h:196
#define FALSE
Definition gis.h:79
#define GNAME_MAX
Definition gis.h:193
#define _(str)
Definition glocale.h:10
#define file
const char * name
Definition named_colr.c:6
#define strcpy
Definition parson.c:66
Non-native format info (PostGIS)
Vector map info.
Layer (old: field) information.
char * table
Name of DB table.
char * driver
Name of DB driver ('sqlite', 'dbf', ...)
char * name
Layer name (optional)
char * database
char * key
Name of key column (usually 'cat')
int number
Layer number.
Definition path.h:15
char * Vect__get_element_path(char *file_path, struct Map_info *Map, const char *element)
Get map element full path (internal use only)
char * Vect__get_path(char *path, struct Map_info *Map)
Get map directory name (internal use only)