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