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