GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-f4d8c62acd
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 /*!
629  \brief Free a struct field_info and all memory associated with it.
630 
631  \param[in,out] fi pointer to field_info structure
632  */
634 {
635  if (!fi)
636  return;
637  if (fi->name)
638  G_free(fi->name);
639  G_free(fi->driver);
640  G_free(fi->database);
641  G_free(fi->table);
642  G_free(fi->key);
643  G_free(fi);
644  fi = NULL;
645 }
646 
647 static int read_dblinks_nat(struct Map_info *Map)
648 {
649  FILE *fd;
650  char file[1024], buf[2001];
651  char tab[1024], col[1024], db[1024], drv[1024], fldstr[1024], *fldname;
652  int fld;
653  char *c, path[GPATH_MAX];
654  int row, rule;
655  struct dblinks *dbl;
656  char **tokens;
657  int ntok, i;
658 
659  dbl = Map->dblnk;
660 
661  /* Read dblink for native format */
662  Vect__get_path(path, Map);
663  fd = G_fopen_old(path, GV_DBLN_ELEMENT, Map->mapset);
664  if (fd == NULL) { /* This may be correct, no tables defined */
665  G_debug(1, "Cannot open vector database definition file");
666  return -1;
667  }
668 
669  row = 0;
670  rule = 0;
671  while (G_getl2(buf, 2000, fd)) {
672  row++;
673  G_chop(buf);
674  G_debug(1, "dbln: %s", buf);
675 
676  c = (char *)strchr(buf, '#');
677  if (c != NULL)
678  *c = '\0';
679 
680  if (strlen(buf) == 0)
681  continue;
682 
683 #ifdef NOT_ABLE_TO_READ_GRASS_6
684  int ndef;
685 
686  ndef = sscanf(buf, "%s|%s|%s|%s|%s", fldstr, tab, col, db, drv);
687 
688  if (ndef < 2 || (ndef < 5 && rule < 1)) {
689  G_warning(_("Error in rule on row %d in <%s>"), row, file);
690  continue;
691  }
692 #else
693  tokens = G_tokenize(buf, " |");
694  ntok = G_number_of_tokens(tokens);
695 
696  if (ntok < 2 || (ntok < 5 && rule < 1)) {
697  G_warning(_("Error in rule on row %d in <%s>"), row, file);
698  continue;
699  }
700 
701  strcpy(fldstr, tokens[0]);
702  strcpy(tab, tokens[1]);
703  if (ntok > 2) {
704  strcpy(col, tokens[2]);
705  if (ntok > 3) {
706  strcpy(db, tokens[3]);
707  /* allow for spaces in path names */
708  for (i = 4; i < ntok - 1; i++) {
709  strcat(db, " ");
710  strcat(db, tokens[i]);
711  }
712 
713  strcpy(drv, tokens[ntok - 1]);
714  }
715  }
716  G_free_tokens(tokens);
717 #endif
718 
719  /* get field and field name */
720  fldname = strchr(fldstr, '/');
721  if (fldname != NULL) { /* field has name */
722  fldname[0] = 0;
723  fldname++;
724  }
725  fld = atoi(fldstr);
726 
727  Vect_add_dblink(dbl, fld, fldname, tab, col, db, drv);
728 
729  G_debug(1,
730  "field = %d name = %s, table = %s, key = %s, database = %s, "
731  "driver = %s",
732  fld, fldname, tab, col, db, drv);
733 
734  rule++;
735  }
736  fclose(fd);
737 
738  G_debug(1, "Dblinks read");
739 
740  return rule;
741 }
742 
743 /* return -1 on error */
744 static int read_dblinks_ogr(struct Map_info *Map)
745 {
746  struct dblinks *dbl;
747 
748  dbl = Map->dblnk;
749  G_debug(3, "Searching for FID column in OGR DB");
750 #ifndef HAVE_OGR
751  G_warning(_("GRASS is not compiled with OGR support"));
752 #else
753  int nLayers;
754  char *ogr_fid_col;
755 
756  G_debug(3, "GDAL_VERSION_NUM: %d", GDAL_VERSION_NUM);
757 
758  if (Map->fInfo.ogr.ds == NULL) {
759  /* open the connection to fetch the FID column name */
760  OGRRegisterAll();
761 
762  /* data source handle */
763  Map->fInfo.ogr.ds = OGROpen(Map->fInfo.ogr.dsn, FALSE, NULL);
764  if (Map->fInfo.ogr.ds == NULL) {
765  G_warning(_("Unable to open OGR data source '%s'"),
766  Map->fInfo.ogr.dsn);
767  return -1;
768  }
769  }
770  if (Map->fInfo.ogr.layer == NULL) {
771  /* get layer number */
772  nLayers = OGR_DS_GetLayerCount(
773  Map->fInfo.ogr.ds); /* Layers = Maps in OGR DB */
774 
775  G_debug(3, "%d layers (maps) found in data source", nLayers);
776 
777  G_debug(3, "Trying to open OGR layer: %s", Map->fInfo.ogr.layer_name);
778  if (Map->fInfo.ogr.layer_name) {
779  Map->fInfo.ogr.layer = OGR_DS_GetLayerByName(
780  Map->fInfo.ogr.ds, Map->fInfo.ogr.layer_name);
781  if (Map->fInfo.ogr.layer == NULL) {
782  OGR_DS_Destroy(Map->fInfo.ogr.ds);
783  Map->fInfo.ogr.ds = NULL;
784  G_warning(_("Unable to open OGR layer <%s>"),
785  Map->fInfo.ogr.layer_name);
786  return -1;
787  }
788  }
789  }
790 
791  /* get fid column */
792  ogr_fid_col = G_store(OGR_L_GetFIDColumn(Map->fInfo.ogr.layer));
793  G_debug(3, "Using FID column <%s> in OGR DB", ogr_fid_col);
794  Vect_add_dblink(dbl, 1, Map->fInfo.ogr.layer_name,
795  Map->fInfo.ogr.layer_name, ogr_fid_col, Map->fInfo.ogr.dsn,
796  "ogr");
797  return 1;
798 #endif /* HAVE_GDAL */
799 }
800 
801 static int read_dblinks_pg(struct Map_info *Map NOPG_UNUSED)
802 {
803 #ifdef HAVE_POSTGRES
804  char *name;
805  struct dblinks *dbl;
806  struct Format_info_pg *pg_info;
807 
808  dbl = Map->dblnk;
809  pg_info = &(Map->fInfo.pg);
810 
811  if (!pg_info->fid_column) {
812  G_warning(_("Feature table <%s> has no primary key defined. "
813  "Unable to define DB links."),
814  pg_info->table_name);
815  return -1;
816  }
817  G_debug(3, "Using FID column <%s>", pg_info->fid_column);
818 
819  name = NULL;
820  if (G_strcasecmp(pg_info->schema_name, "public") != 0)
821  G_asprintf(&name, "%s.%s", pg_info->schema_name, pg_info->table_name);
822  else
823  name = pg_info->table_name;
824 
825  Vect_add_dblink(dbl, 1, name, name, pg_info->fid_column, pg_info->db_name,
826  "pg");
827  if (name != pg_info->table_name)
828  G_free(name);
829  return 1;
830 #else
831  G_warning(_("GRASS not compiled with PostgreSQL support"));
832  return -1;
833 #endif
834 }
835 
836 /*!
837  \brief Read dblinks to existing structure.
838 
839  Variables are not substituted by values.
840 
841  \param Map pointer to Map_info structure
842 
843  \return number of links read
844  \return -1 on error
845  */
846 int Vect_read_dblinks(struct Map_info *Map)
847 {
848  G_debug(1, "Vect_read_dblinks(): map = %s, mapset = %s", Map->name,
849  Map->mapset);
850 
852 
853  if (Map->format == GV_FORMAT_NATIVE) {
854  return read_dblinks_nat(Map);
855  }
856  else if (Map->format == GV_FORMAT_OGR ||
857  Map->format == GV_FORMAT_OGR_DIRECT) {
858  return read_dblinks_ogr(Map);
859  }
860  else if (Map->format == GV_FORMAT_POSTGIS) {
861  return read_dblinks_pg(Map);
862  }
863  else {
864  G_fatal_error(_("Unknown vector map format"));
865  }
866 
867  return -1;
868 }
869 
870 /*!
871  \brief Write dblinks to file
872 
873  \param Map pointer to Map_info structure
874 
875  \return 0 on success
876  \return -1 on error
877  */
878 int Vect_write_dblinks(struct Map_info *Map)
879 {
880  int i;
881  FILE *fd;
882  char path[GPATH_MAX], buf[1024];
883  struct dblinks *dbl;
884 
885  if (Map->format != GV_FORMAT_NATIVE)
886  /* nothing to write for non-native formats */
887  return 0;
888 
889  G_debug(1, "Vect_write_dblinks(): map = %s, mapset = %s", Map->name,
890  Map->mapset);
891 
892  dbl = Map->dblnk;
893 
894  Vect__get_path(path, Map);
896  if (fd == NULL) { /* This may be correct, no tables defined */
897  G_warning(
898  _("Unable to create database definition file for vector map <%s>"),
899  Vect_get_name(Map));
900  return -1;
901  }
902 
903  for (i = 0; i < dbl->n_fields; i++) {
904  if (dbl->field[i].name != NULL)
905  sprintf(buf, "%d/%s", dbl->field[i].number, dbl->field[i].name);
906  else
907  sprintf(buf, "%d", dbl->field[i].number);
908 
909  fprintf(fd, "%s|%s|%s|%s|%s\n", buf, dbl->field[i].table,
910  dbl->field[i].key, dbl->field[i].database,
911  dbl->field[i].driver);
912  G_debug(1, "%s|%s|%s|%s|%s", buf, dbl->field[i].table,
913  dbl->field[i].key, dbl->field[i].database,
914  dbl->field[i].driver);
915  }
916  fclose(fd);
917 
918  G_debug(1, "Dblinks written");
919 
920  return 0;
921 }
922 
923 /*!
924  \brief Substitute variable in string
925 
926  \param in current string
927  \param Map pointer to Map_info structure
928 
929  \return pointer to new string
930  */
931 char *Vect_subst_var(const char *in, struct Map_info *Map)
932 {
933  char *c;
934  char buf[1000], str[1000];
935 
936  G_debug(3, "Vect_subst_var(): in = %s, map = %s, mapset = %s", in,
937  Map->name, Map->mapset);
938 
939 #ifdef __MINGW32__
940  char *cin;
941 
942  cin = G_str_replace(in, "/", "\\");
943  strcpy(str, cin);
944  G_free(cin);
945 #else
946  strcpy(str, in);
947 #endif
948 
949  strcpy(buf, str);
950  c = (char *)strstr(buf, "$GISDBASE");
951  if (c != NULL) {
952  *c = '\0';
953  sprintf(str, "%s%s%s", buf, Map->gisdbase, c + 9);
954  }
955 
956  strcpy(buf, str);
957  c = (char *)strstr(buf, "$LOCATION_NAME");
958  if (c != NULL) {
959  *c = '\0';
960  sprintf(str, "%s%s%s", buf, Map->location, c + 14);
961  }
962 
963  strcpy(buf, str);
964  c = (char *)strstr(buf, "$MAPSET");
965  if (c != NULL) {
966  *c = '\0';
967  sprintf(str, "%s%s%s", buf, Map->mapset, c + 7);
968  }
969 
970  strcpy(buf, str);
971  c = (char *)strstr(buf, "$MAP");
972  if (c != NULL) {
973  *c = '\0';
974  sprintf(str, "%s%s%s", buf, Map->name, c + 4);
975  }
976 
977  G_debug(3, " -> %s", str);
978  return (G_store(str));
979 }
980 
981 /*!
982  \brief Rewrite 'dbln' file
983 
984  Should be used by GRASS modules which update database tables, so
985  that other applications know that tables were changed and can reload
986  data.
987 
988  \param Map pointer to Map_info structure
989  */
990 void Vect_set_db_updated(struct Map_info *Map)
991 {
992  if (strcmp(Map->mapset, G_mapset()) != 0 &&
993  G_strcasecmp(Map->mapset, "ogr") != 0) {
995  _("Bug: attempt to update map which is not in current mapset"));
996  }
997 
998  Vect_write_dblinks(Map);
999 }
#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:990
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:846
char * Vect_subst_var(const char *in, struct Map_info *Map)
Substitute variable in string.
Definition: field.c:931
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:878
void Vect_destroy_field_info(struct field_info *fi)
Free a struct field_info and all memory associated with it.
Definition: field.c:633
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)