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