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