GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-e5379bbd7
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], buf2[GNAME_MAX];
356  const char *schema;
357  dbConnection connection;
358 
359  G_debug(1, "Vect_default_field_info(): map = %s field = %d", Map->name,
360  field);
361 
362  if (Map->format == GV_FORMAT_OGR_DIRECT) {
363  G_zero(&connection, sizeof(dbConnection));
364  connection.driverName = G_store("ogr");
365  connection.databaseName = G_store(Map->fInfo.ogr.dsn);
366  }
367  else {
368  db_get_connection(&connection);
369  }
370 
371  G_debug(2, "drv = %s db = %s", connection.driverName, connection.databaseName);
372 
373  if (!connection.driverName && !connection.databaseName) {
374  /* Set default values */
376  db_get_connection(&connection);
377 
378  G_important_message(_("Default driver / database set to:\n"
379  "driver: %s\ndatabase: %s"), connection.driverName,
380  connection.databaseName);
381  }
382  /* they must be a matched pair, so if one is set but not the other
383  then give up and let the user figure it out */
384  else if (!connection.driverName) {
385  G_fatal_error(_("Default driver is not set"));
386  }
387  else if (!connection.databaseName) {
388  G_fatal_error(_("Default database is not set"));
389  }
390 
391  fi = (struct field_info *)G_malloc(sizeof(struct field_info));
392 
393  fi->number = field;
394 
395  /* Field name */
396  fi->name = NULL;
397  if (field_name && *field_name) {
398  fi->name = G_store(field_name);
399  if (!name2sql(fi->name)) {
400  G_free(fi->name);
401  fi->name = NULL;
402  }
403  }
404 
405  /* Table name */
406  if (type == GV_1TABLE) {
407  sprintf(buf, "%s", Map->name);
408  }
409  else {
410  if (fi->name != NULL && strlen(fi->name) > 0) {
411  sprintf(buf, "%s_%s", Map->name, fi->name);
412  if (!name2sql(buf)) {
413  sprintf(buf, "%s_%d", Map->name, field);
414  }
415  }
416  else
417  sprintf(buf, "%s_%d", Map->name, field);
418  }
419  schema = connection.schemaName;
420  if (schema && strlen(schema) > 0) {
421  sprintf(buf2, "%s.%s", schema, buf);
422  fi->table = G_store(buf2);
423  }
424  else {
425  fi->table = G_store(buf);
426  }
427 
428  /* Field name still empty */
429  if (!fi->name)
430  fi->name = G_store(buf);
431 
432  fi->key = G_store(GV_KEY_COLUMN); /* Should be: id/fid/gfid/... ? */
433 #ifdef TEMPORARY_MAP_DB
434  if (Map->temporary) {
435  Vect__get_element_path(buf, Map, NULL);
436  if (strcmp(DB_DEFAULT_DRIVER, "sqlite") == 0)
437  strcat(buf, "/sqlite.db");
438  else
439  strcat(buf, "/db.dbf");
440  fi->database = G_store(buf);
442  }
443  else {
444  fi->database = G_store(connection.databaseName);
445  fi->driver = G_store(connection.driverName);
446  }
447 #else
448  fi->database = G_store(connection.databaseName);
449  fi->driver = G_store(connection.driverName);
450 #endif
451 
452  return fi;
453 }
454 
455 /*!
456  \brief Get information about link to database.
457 
458  Variables are substituted by values, link is index to array of
459  dblinks.
460 
461  \param Map pointer to Map_info structure
462  \param link link id
463 
464  \return pointer to new field_info structure
465  */
466 struct field_info *Vect_get_dblink(const struct Map_info *Map, int link)
467 {
468  struct field_info *fi;
469 
470  G_debug(1, "Vect_get_dblink(): link = %d", link);
471 
472  if (link >= Map->dblnk->n_fields) {
473  G_warning(_("Requested dblink %d, maximum link number %d"), link,
474  Map->dblnk->n_fields - 1);
475  return NULL;
476  }
477 
478  fi = (struct field_info *)G_malloc(sizeof(struct field_info));
479  fi->number = Map->dblnk->field[link].number;
480 
481  if (Map->dblnk->field[link].name != NULL)
482  fi->name = G_store(Map->dblnk->field[link].name);
483  else
484  fi->name = NULL;
485 
486  fi->table = G_store(Map->dblnk->field[link].table);
487  fi->key = G_store(Map->dblnk->field[link].key);
488  fi->database = Vect_subst_var(Map->dblnk->field[link].database, Map);
489  fi->driver = G_store(Map->dblnk->field[link].driver);
490 
491  return fi;
492 }
493 
494 /*!
495  \brief Get information about link to database (by layer number)
496 
497  Variables are substituted by values, field is number of requested
498  field.
499 
500  \param Map pointer to Map_info structure
501  \param field layer number
502 
503  \return pointer to new field_info structure
504  \return NULL if not found
505 */
506 struct field_info *Vect_get_field(const struct Map_info *Map, int field)
507 {
508  int i;
509  struct field_info *fi = NULL;
510 
511  G_debug(1, "Vect_get_field(): field = %d", field);
512 
513  for (i = 0; i < Map->dblnk->n_fields; i++) {
514  if (Map->dblnk->field[i].number == field) {
515  fi = Vect_get_dblink(Map, i);
516  break;
517  }
518  }
519 
520  return fi;
521 }
522 
523 /*!
524  \brief Get information about link to database (by layer name)
525 
526  \param Map pointer to Map_info structure
527  \param field layer name
528 
529  \return pointer to new field_info structure
530  \return NULL if not found
531 */
532 struct field_info *Vect_get_field_by_name(const struct Map_info *Map, const char *field)
533 {
534  int i;
535  struct field_info *fi = NULL;
536 
537  G_debug(1, "Vect_get_field_by_name(): field = %s", field);
538 
539  for (i = 0; i < Map->dblnk->n_fields; i++) {
540  if (strcmp(Map->dblnk->field[i].name, field) == 0) {
541  fi = Vect_get_dblink(Map, i);
542  break;
543  }
544  }
545 
546  return fi;
547 }
548 
549 /*!
550  \brief Get information about link to database (by layer number or layer name)
551 
552  Note: if <em>field</em> is -1 then the function returns the first
553  dblink or NULL
554 
555  \param Map pointer to Map_info structure
556  \param field layer number or name
557 
558  \return pointer to new field_info structure
559  \return NULL if not found
560 */
561 struct field_info *Vect_get_field2(const struct Map_info *Map, const char *field)
562 {
563  int ifield;
564  struct field_info *fi;
565 
566  G_debug(1, "Vect_get_field2(): field = %s", field);
567 
568  fi = NULL;
569  ifield = atoi(field);
570 
571  if (ifield > 0) {
572  fi = Vect_get_field(Map, ifield);
573  if (fi)
574  return fi;
575  }
576  else if (ifield == -1) {
577  if (Vect_get_num_dblinks(Map) > 0)
578  return Vect_get_dblink(Map, 0); /* return first */
579  else
580  return NULL;
581  }
582  else if (ifield == 0)
583  return Vect_get_field_by_name(Map, field);
584 
585  return NULL;
586 }
587 
588 /*!
589  \brief Get field number of given field
590 
591  \param Map pointer to Map_info structure
592  \param field layer name
593 
594  \return layer number
595  \return -1 for all layers
596  \return 0 if layer not found
597 */
598 int Vect_get_field_number(const struct Map_info *Map, const char *field)
599 {
600  struct field_info *fi;
601 
602  G_debug(1, "Vect_get_field_number(): field = %s", field);
603 
604  if (strcmp(field, "-1") == 0)
605  return -1;
606 
607  if (Vect_get_num_dblinks(Map) == 0)
608  return atoi(field);
609 
610  fi = Vect_get_field2(Map, field);
611 
612  if (fi)
613  return fi->number;
614 
615  return atoi(field);
616 }
617 
618 static int read_dblinks_nat(struct Map_info *Map)
619 {
620  FILE *fd;
621  char file[1024], buf[2001];
622  char tab[1024], col[1024], db[1024], drv[1024], fldstr[1024], *fldname;
623  int fld;
624  char *c, path[GPATH_MAX];
625  int row, rule;
626  struct dblinks *dbl;
627  char **tokens;
628  int ntok, i;
629 
630  dbl = Map->dblnk;
631 
632  /* Read dblink for native format */
633  Vect__get_path(path, Map);
634  fd = G_fopen_old(path, GV_DBLN_ELEMENT, Map->mapset);
635  if (fd == NULL) { /* This may be correct, no tables defined */
636  G_debug(1, "Cannot open vector database definition file");
637  return -1;
638  }
639 
640  row = 0;
641  rule = 0;
642  while (G_getl2(buf, 2000, fd)) {
643  row++;
644  G_chop(buf);
645  G_debug(1, "dbln: %s", buf);
646 
647  c = (char *)strchr(buf, '#');
648  if (c != NULL)
649  *c = '\0';
650 
651  if (strlen(buf) == 0)
652  continue;
653 
654 #ifdef NOT_ABLE_TO_READ_GRASS_6
655  int ndef;
656  ndef = sscanf(buf, "%s|%s|%s|%s|%s", fldstr, tab, col, db, drv);
657 
658  if (ndef < 2 || (ndef < 5 && rule < 1)) {
659  G_warning(_("Error in rule on row %d in <%s>"), row, file);
660  continue;
661  }
662 #else
663  tokens = G_tokenize(buf, " |");
664  ntok = G_number_of_tokens(tokens);
665 
666  if (ntok < 2 || (ntok < 5 && rule < 1)) {
667  G_warning(_("Error in rule on row %d in <%s>"), row, file);
668  continue;
669  }
670 
671  strcpy(fldstr, tokens[0]);
672  strcpy(tab, tokens[1]);
673  if (ntok > 2) {
674  strcpy(col, tokens[2]);
675  if (ntok > 3) {
676  strcpy(db, tokens[3]);
677  /* allow for spaces in path names */
678  for (i=4; i < ntok-1; i++) {
679  strcat(db, " ");
680  strcat(db, tokens[i]);
681  }
682 
683  strcpy(drv, tokens[ntok-1]);
684  }
685  }
686  G_free_tokens(tokens);
687 #endif
688 
689  /* get field and field name */
690  fldname = strchr(fldstr, '/');
691  if (fldname != NULL) { /* field has name */
692  fldname[0] = 0;
693  fldname++;
694  }
695  fld = atoi(fldstr);
696 
697  Vect_add_dblink(dbl, fld, fldname, tab, col, db, drv);
698 
699  G_debug(1,
700  "field = %d name = %s, table = %s, key = %s, database = %s, driver = %s",
701  fld, fldname, tab, col, db, drv);
702 
703  rule++;
704  }
705  fclose(fd);
706 
707  G_debug(1, "Dblinks read");
708 
709  return rule;
710 }
711 
712 /* return -1 on error */
713 static int read_dblinks_ogr(struct Map_info *Map)
714 {
715  struct dblinks *dbl;
716 
717  dbl = Map->dblnk;
718  G_debug(3, "Searching for FID column in OGR DB");
719 #ifndef HAVE_OGR
720  G_warning(_("GRASS is not compiled with OGR support"));
721 #else
722 #if GDAL_VERSION_NUM > 1320 && HAVE_OGR /* seems to be fixed after 1320 release */
723  int nLayers;
724  char *ogr_fid_col;
725 
726  G_debug(3, "GDAL_VERSION_NUM: %d", GDAL_VERSION_NUM);
727 
728  if (Map->fInfo.ogr.ds == NULL) {
729  /* open the connection to fetch the FID column name */
730  OGRRegisterAll();
731 
732  /* data source handle */
733  Map->fInfo.ogr.ds = OGROpen(Map->fInfo.ogr.dsn, FALSE, NULL);
734  if (Map->fInfo.ogr.ds == NULL) {
735  G_warning(_("Unable to open OGR data source '%s'"),
736  Map->fInfo.ogr.dsn);
737  return -1;
738  }
739  }
740  if (Map->fInfo.ogr.layer == NULL) {
741  /* get layer number */
742  nLayers = OGR_DS_GetLayerCount(Map->fInfo.ogr.ds); /* Layers = Maps in OGR DB */
743 
744  G_debug(3, "%d layers (maps) found in data source", nLayers);
745 
746  G_debug(3, "Trying to open OGR layer: %s", Map->fInfo.ogr.layer_name);
747  if (Map->fInfo.ogr.layer_name) {
748  Map->fInfo.ogr.layer = OGR_DS_GetLayerByName(Map->fInfo.ogr.ds, Map->fInfo.ogr.layer_name);
749  if (Map->fInfo.ogr.layer == NULL) {
750  OGR_DS_Destroy(Map->fInfo.ogr.ds);
751  Map->fInfo.ogr.ds = NULL;
752  G_warning(_("Unable to open OGR layer <%s>"),
753  Map->fInfo.ogr.layer_name);
754  return -1;
755  }
756  }
757  }
758 
759  /* get fid column */
760  ogr_fid_col = G_store(OGR_L_GetFIDColumn(Map->fInfo.ogr.layer));
761  G_debug(3, "Using FID column <%s> in OGR DB", ogr_fid_col);
762  Vect_add_dblink(dbl, 1, Map->fInfo.ogr.layer_name,
763  Map->fInfo.ogr.layer_name, ogr_fid_col,
764  Map->fInfo.ogr.dsn, "ogr");
765 #else
766  dbDriver *driver;
767  dbCursor cursor;
768  dbString sql;
769  int FID = 0, OGC_FID = 0, OGR_FID = 0, GID = 0;
770 
771  G_debug(3, "GDAL_VERSION_NUM: %d", GDAL_VERSION_NUM);
772 
773  /* FID is not available for all OGR drivers */
774  db_init_string(&sql);
775 
776  driver = db_start_driver_open_database("ogr", Map->fInfo.ogr.dsn);
777 
778  if (driver == NULL) {
779  G_warning(_("Unable to open OGR DBMI driver"));
780  return -1;
781  }
782 
783  /* this is a bit stupid, but above FID auto-detection doesn't work yet...: */
785  sprintf(buf, "select FID from %s where FID > 0",
786  Map->fInfo.ogr.layer_name);
787  db_set_string(&sql, buf);
788 
789  if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) !=
790  DB_OK) {
791  /* FID not available, so we try ogc_fid */
792  G_debug(3, "Failed. Now searching for ogc_fid column in OGR DB");
793  sprintf(buf, "select ogc_fid from %s where ogc_fid > 0",
794  Map->fInfo.ogr.layer_name);
795  db_set_string(&sql, buf);
796 
797  if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) !=
798  DB_OK) {
799  /* Neither FID nor ogc_fid available, so we try ogr_fid */
800  G_debug(3,
801  "Failed. Now searching for ogr_fid column in OGR DB");
802  sprintf(buf, "select ogr_fid from %s where ogr_fid > 0",
803  Map->fInfo.ogr.layer_name);
804  db_set_string(&sql, buf);
805 
807  (driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
808  /* Neither FID nor ogc_fid available, so we try gid */
809  G_debug(3,
810  "Failed. Now searching for gid column in OGR DB");
811  sprintf(buf, "select gid from %s where gid > 0",
812  Map->fInfo.ogr.layer_name);
813  db_set_string(&sql, buf);
814 
816  (driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
817  /* neither FID nor ogc_fid nor ogr_fid nor gid available */
818  G_warning(_("All FID tests failed. Neither 'FID' nor 'ogc_fid' "
819  "nor 'ogr_fid' nor 'gid' available in OGR DB table"));
821  return 0;
822  }
823  else
824  GID = 1;
825  }
826  else
827  OGR_FID = 1;
828  }
829  else
830  OGC_FID = 1;
831  }
832  else
833  FID = 1;
834 
835  G_debug(3, "FID: %d, OGC_FID: %d, OGR_FID: %d, GID: %d", FID, OGC_FID,
836  OGR_FID, GID);
837 
838  db_close_cursor(&cursor);
841 
842  if (FID) {
843  G_debug(3, "Using FID column in OGR DB");
844  Vect_add_dblink(dbl, 1, Map->fInfo.ogr.layer_name, Map->fInfo.ogr.layer_name, "FID",
845  Map->fInfo.ogr.dsn, "ogr");
846  }
847  else {
848  if (OGC_FID) {
849  G_debug(3, "Using ogc_fid column in OGR DB");
851  "ogc_fid", Map->fInfo.ogr.dsn, "ogr");
852  }
853  else {
854  if (OGR_FID) {
855  G_debug(3, "Using ogr_fid column in OGR DB");
857  "ogr_fid", Map->fInfo.ogr.dsn, "ogr");
858  }
859  else {
860  if (GID) {
861  G_debug(3, "Using gid column in OGR DB");
862  Vect_add_dblink(dbl, 1, Map->fInfo.ogr.layer_name,
863  Map->fInfo.ogr.layer_name, "gid",
864  Map->fInfo.ogr.dsn, "ogr");
865  }
866  }
867  }
868  }
869 #endif /* GDAL_VERSION_NUM > 1320 && HAVE_OGR */
870  return 1;
871 #endif /* HAVE_GDAL */
872 }
873 
874 static int read_dblinks_pg(struct Map_info *Map)
875 {
876 #ifdef HAVE_POSTGRES
877  char *name;
878  struct dblinks *dbl;
879  struct Format_info_pg *pg_info;
880 
881  dbl = Map->dblnk;
882  pg_info = &(Map->fInfo.pg);
883 
884  if (!pg_info->fid_column) {
885  G_warning(_("Feature table <%s> has no primary key defined. "
886  "Unable to define DB links."), pg_info->table_name);
887  return -1;
888  }
889  G_debug(3, "Using FID column <%s>", pg_info->fid_column);
890 
891  name = NULL;
892  if (G_strcasecmp(pg_info->schema_name, "public") != 0)
893  G_asprintf(&name, "%s.%s", pg_info->schema_name,
894  pg_info->table_name);
895  else
896  name = pg_info->table_name;
897 
898  Vect_add_dblink(dbl, 1, name, name,
899  pg_info->fid_column,
900  pg_info->db_name, "pg");
901  if (name != pg_info->table_name)
902  G_free(name);
903  return 1;
904 #else
905  G_warning(_("GRASS not compiled with PostgreSQL support"));
906  return -1;
907 #endif
908 }
909 
910 /*!
911  \brief Read dblinks to existing structure.
912 
913  Variables are not substituted by values.
914 
915  \param Map pointer to Map_info structure
916 
917  \return number of links read
918  \return -1 on error
919  */
920 int Vect_read_dblinks(struct Map_info *Map)
921 {
922  G_debug(1, "Vect_read_dblinks(): map = %s, mapset = %s", Map->name,
923  Map->mapset);
924 
926 
927  if (Map->format == GV_FORMAT_NATIVE) {
928  return read_dblinks_nat(Map);
929  }
930  else if (Map->format == GV_FORMAT_OGR || Map->format == GV_FORMAT_OGR_DIRECT) {
931  return read_dblinks_ogr(Map);
932  }
933  else if (Map->format == GV_FORMAT_POSTGIS) {
934  return read_dblinks_pg(Map);
935  }
936  else {
937  G_fatal_error(_("Unknown vector map format"));
938  }
939 
940  return -1;
941 }
942 
943 /*!
944  \brief Write dblinks to file
945 
946  \param Map pointer to Map_info structure
947 
948  \return 0 on success
949  \return -1 on error
950  */
951 int Vect_write_dblinks(struct Map_info *Map)
952 {
953  int i;
954  FILE *fd;
955  char path[GPATH_MAX], buf[1024];
956  struct dblinks *dbl;
957 
958  if (Map->format != GV_FORMAT_NATIVE)
959  /* nothing to write for non-native formats */
960  return 0;
961 
962  G_debug(1, "Vect_write_dblinks(): map = %s, mapset = %s", Map->name,
963  Map->mapset);
964 
965  dbl = Map->dblnk;
966 
967  Vect__get_path(path, Map);
968  fd = G_fopen_new(path, GV_DBLN_ELEMENT);
969  if (fd == NULL) { /* This may be correct, no tables defined */
970  G_warning(_("Unable to create database definition file for vector map <%s>"),
971  Vect_get_name(Map));
972  return -1;
973  }
974 
975  for (i = 0; i < dbl->n_fields; i++) {
976  if (dbl->field[i].name != NULL)
977  sprintf(buf, "%d/%s", dbl->field[i].number, dbl->field[i].name);
978  else
979  sprintf(buf, "%d", dbl->field[i].number);
980 
981  fprintf(fd, "%s|%s|%s|%s|%s\n", buf, dbl->field[i].table,
982  dbl->field[i].key, dbl->field[i].database,
983  dbl->field[i].driver);
984  G_debug(1, "%s|%s|%s|%s|%s", buf, dbl->field[i].table,
985  dbl->field[i].key, dbl->field[i].database,
986  dbl->field[i].driver);
987  }
988  fclose(fd);
989 
990  G_debug(1, "Dblinks written");
991 
992  return 0;
993 }
994 
995 /*!
996  \brief Substitute variable in string
997 
998  \param in current string
999  \param Map pointer to Map_info structure
1000 
1001  \return pointer to new string
1002 */
1003 char *Vect_subst_var(const char *in, const struct Map_info *Map)
1004 {
1005  char *c;
1006  char buf[1000], str[1000];
1007 
1008  G_debug(3, "Vect_subst_var(): in = %s, map = %s, mapset = %s", in,
1009  Map->name, Map->mapset);
1010 
1011 #ifdef __MINGW32__
1012  char *cin;
1013  cin = G_str_replace(in, "/", "\\");
1014  strcpy(str, cin);
1015  G_free(cin);
1016 #else
1017  strcpy(str, in);
1018 #endif
1019 
1020  strcpy(buf, str);
1021  c = (char *)strstr(buf, "$GISDBASE");
1022  if (c != NULL) {
1023  *c = '\0';
1024  sprintf(str, "%s%s%s", buf, Map->gisdbase, c + 9);
1025  }
1026 
1027  strcpy(buf, str);
1028  c = (char *)strstr(buf, "$LOCATION_NAME");
1029  if (c != NULL) {
1030  *c = '\0';
1031  sprintf(str, "%s%s%s", buf, Map->location, c + 14);
1032  }
1033 
1034  strcpy(buf, str);
1035  c = (char *)strstr(buf, "$MAPSET");
1036  if (c != NULL) {
1037  *c = '\0';
1038  sprintf(str, "%s%s%s", buf, Map->mapset, c + 7);
1039  }
1040 
1041  strcpy(buf, str);
1042  c = (char *)strstr(buf, "$MAP");
1043  if (c != NULL) {
1044  *c = '\0';
1045  sprintf(str, "%s%s%s", buf, Map->name, c + 4);
1046  }
1047 
1048  G_debug(3, " -> %s", str);
1049  return (G_store(str));
1050 }
1051 
1052 /*!
1053  \brief Rewrite 'dbln' file
1054 
1055  Should be used by GRASS modules which update database tables, so
1056  that other applications know that tables were changed and can reload
1057  data.
1058 
1059  \param Map pointer to Map_info structure
1060 */
1062 {
1063  if (strcmp(Map->mapset, G_mapset()) != 0 &&
1064  G_strcasecmp(Map->mapset, "ogr") != 0) {
1065  G_fatal_error(_("Bug: attempt to update map which is not in current mapset"));
1066  }
1067 
1068  Vect_write_dblinks(Map);
1069 }
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:388
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:1003
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:532
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:170
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:951
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:466
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:167
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:920
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:598
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:506
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:561
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:1061
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