GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-d6dec75dd4
vector/Vlib/open.c
Go to the documentation of this file.
1 /*!
2  \file lib/vector/Vlib/open.c
3 
4  \brief Vector library - Open existing or create new vector map
5  (native or OGR/PostGIS format)
6 
7  Higher level functions for reading/writing/manipulating vectors.
8 
9  (C) 2001-2015 by the GRASS Development Team
10 
11  This program is free software under the GNU General Public License
12  (>=v2). Read the file COPYING that comes with GRASS for details.
13 
14  \author Original author CERL, probably Dave Gerdes or Mike Higgins.
15  \author Update to GRASS 5.7 Radim Blazek and David D. Gray.
16  \author Update to GRASS 7 Martin Landa <landa.martin gmail.com> (better OGR
17  support and native PostGIS access)
18  */
19 
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 
27 #include <grass/vector.h>
28 #include <grass/glocale.h>
29 
30 #include "local_proto.h"
31 
32 #ifdef HAVE_POSTGRES
33 #include "pg_local_proto.h"
34 #endif
35 
36 /*
37  \brief Number of levels
38 
39  - 1 without topology
40  - 2 with 2D topology
41 
42  \todo Implement
43  - 3 with 3D topology
44  */
45 #define MAX_OPEN_LEVEL 2
46 
47 static int open_old_dummy(struct Map_info *Map UNUSED, int update UNUSED)
48 {
49  return 0;
50 }
51 
52 static int open_new_dummy(struct Map_info *Map UNUSED, const char *name UNUSED,
53  int with_z UNUSED)
54 {
55  return 0;
56 }
57 
58 #if !defined HAVE_OGR || !defined HAVE_POSTGRES
59 static int format_old(struct Map_info *Map UNUSED, int update UNUSED)
60 {
61  G_fatal_error(_("Requested format is not compiled in this version"));
62  return 0;
63 }
64 
65 static int format_new(struct Map_info *Map UNUSED, const char *name UNUSED,
66  int with_z UNUSED)
67 {
68  G_fatal_error(_("Requested format is not compiled in this version"));
69  return 0;
70 }
71 #endif
72 
73 static int Open_level = 0;
74 
75 static int (*Open_old_array[][2])(struct Map_info *,
76  int) = {{open_old_dummy, V1_open_old_nat}
77 #ifdef HAVE_OGR
78  ,
79  {open_old_dummy, V1_open_old_ogr},
80  {open_old_dummy, V1_open_old_ogr}
81 #else
82  ,
83  {open_old_dummy, format_old},
84  {open_old_dummy, format_old}
85 #endif
86 #ifdef HAVE_POSTGRES
87  ,
88  {open_old_dummy, V1_open_old_pg}
89 #else
90  ,
91  {open_old_dummy, format_old}
92 #endif
93 };
94 
95 static int (*Open_new_array[][2])(struct Map_info *Map, const char *name,
96  int with_z) = {
97  {open_new_dummy, V1_open_new_nat}
98 #ifdef HAVE_OGR
99  ,
100  {open_new_dummy, V1_open_new_ogr},
101  {open_new_dummy, V1_open_new_ogr}
102 #else
103  ,
104  {open_new_dummy, format_new},
105  {open_new_dummy, format_new}
106 #endif
107 #ifdef HAVE_POSTGRES
108  ,
109  {open_new_dummy, V1_open_new_pg}
110 #else
111  ,
112  {open_new_dummy, format_new}
113 #endif
114 };
115 
116 static int open_new(struct Map_info *, const char *, int, int);
117 static int map_format(struct Map_info *);
118 
119 /*!
120  \brief Predetermine level at which a vector map will be opened for
121  reading.
122 
123  If it can't open that level, the open will fail. The specified level
124  must be set before any call to open. The default is to try to open
125  the highest level possible, and keep stepping down until success.
126 
127  NOTE: This should only be used to set when you wish to force a lower
128  level open. If you require a higher level, then just check the
129  return to verify the level instead of forcing it. This is because
130  future releases will have higher levels which will be downward
131  compatible and which your programs should support by default.
132 
133  \param level vector access level
134 
135  \return 0 on success
136  \return 1 on error (invalid access level)
137  */
139 {
140  Open_level = level;
141  if (Open_level < 1 || Open_level > MAX_OPEN_LEVEL) {
142  G_warning(_("Programmer requested unknown access level %d"),
143  Open_level);
144  Open_level = 0;
145  return 1;
146  }
147 
148  return 0;
149 }
150 
151 /*!
152  \brief Open existing vector map for reading (internal use only)
153 
154  \param[out] Map pointer to Map_info structure
155  \param name name of vector map to open
156  \param mapset mapset name ("" for search path)
157  \param layer layer name (OGR format only)
158  \param update non-zero to open for update otherwise read-only mode
159  \param head_only read only header info from 'head', 'dbln', 'topo',
160  'cidx' is not opened. The header may be opened on level 2 only.
161  \param is_tmp non-zero code for temporary maps
162 
163  \return level of openness (1, 2)
164  \return -1 in error
165  */
166 int Vect__open_old(struct Map_info *Map, const char *name, const char *mapset,
167  const char *layer, int update, int head_only, int is_tmp)
168 {
169  char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
170  char path[GPATH_MAX];
171  FILE *fp;
172  int level, level_request;
173  int format, ret;
174  int ogr_mapset;
175  const char *fmapset;
176 
177  G_debug(
178  1,
179  "Vect__open_old(): name = %s, mapset = %s, layer = %s, update = %d, "
180  "head_only = %d, is_tmp = %d",
181  name, mapset, layer ? layer : "NULL", update, head_only, is_tmp);
182 
183  if (update && !is_tmp) {
184  is_tmp = getenv("GRASS_VECTOR_TEMPORARY") ? TEMPORARY_MAP_ENV
185  : TEMPORARY_MAP_DISABLED;
186  G_debug(1,
187  "Vect__open_old(): is_tmp = %d (check GRASS_VECTOR_TEMPORARY)",
188  is_tmp);
189  }
190 
191  /* zero Map_info structure */
192  G_zero(Map, sizeof(struct Map_info));
193 
194  /* TODO: Open header for update ('dbln') */
195 
196  level_request = Open_level;
197  Open_level = 0;
198 
199  /* initialize Map->head */
200  Vect__init_head(Map);
201  /* initialize support structures for 2D, update to 3D when reading
202  support files */
203  Map->plus.spidx_with_z = Map->plus.with_z = Map->head.with_z = WITHOUT_Z;
204  /* initialize Map->plus */
205  dig_init_plus(&(Map->plus));
206 
207  /* check OGR mapset */
208  ogr_mapset = FALSE;
209  if (G_name_is_fully_qualified(name, xname, xmapset)) {
210  if (strcasecmp(xmapset, "ogr") == 0) {
211  /* unique OGR mapset detected */
212  G_debug(1, "OGR mapset detected");
213  ogr_mapset = TRUE;
214  Map->fInfo.ogr.dsn = G_store(xname);
215  if (layer) {
216  Map->fInfo.ogr.layer_name =
217  G_store(layer); /* no layer to be open */
218  }
219  }
220  Map->name = G_store(xname);
221  Map->mapset = G_store(xmapset);
222  }
223  else {
224  Map->name = G_store(name);
225 
226  Map->temporary = is_tmp;
227  /* temporary maps can be accessed only in the current mapset */
228  if (mapset)
229  Map->mapset = G_store(mapset);
230  else
231  Map->mapset = G_store("");
232  }
233 
234  Vect__get_path(path, Map);
235 
236  if (!ogr_mapset) {
237  /* try to find vector map (not for OGR mapset) */
238  if (!Map->temporary) {
239  fmapset = G_find_vector2(Map->name, Map->mapset);
240  if (fmapset == NULL) {
241  if (mapset && strcmp(mapset, G_mapset()) == 0)
243  _("Vector map <%s> not found in current mapset"),
244  Vect_get_name(Map));
245  else
246  G_fatal_error(_("Vector map <%s> not found"),
247  Vect_get_full_name(Map));
248  return -1;
249  }
250  Map->mapset = G_store(fmapset);
251  }
252  else {
253  char file_path[GPATH_MAX];
254 
255  /* reduce to current mapset if search path was set */
256  if (strcmp(Map->mapset, "") == 0)
257  Map->mapset = G_store(G_mapset());
258  /* temporary map: reduce to current mapset if search path
259  * was set */
260  if (strcmp(Map->mapset, "") == 0)
261  Map->mapset = G_store(G_mapset());
262  else {
263  if (strcmp(Map->mapset, G_mapset()) != 0) {
264  G_warning(_("Temporary vector maps can be accessed only in "
265  "the current mapset"));
266  return -1;
267  }
268  }
269 
270  Vect__get_element_path(file_path, Map, GV_HEAD_ELEMENT);
271  if (access(file_path, F_OK) != 0) {
272  /* unable to find header file for temporary map, try
273  * to switch to normal mode, useful when updating
274  * existing map */
275  Map->temporary = FALSE;
276  Vect__get_path(path, Map); /* path must be updated for
277  * subsequent operations */
278  Vect__get_element_path(file_path, Map, GV_HEAD_ELEMENT);
279  if (access(file_path, F_OK) != 0)
280  return -1;
281  }
282  }
283  }
284 
285  Map->location = G_store(G_location());
286  Map->gisdbase = G_store(G_gisdbase());
287 
288  if (update && !ogr_mapset && (0 != strcmp(Map->mapset, G_mapset()))) {
289  G_warning(_("Vector map which is not in the current mapset cannot be "
290  "opened for update"));
291  return -1;
292  }
293 
294  G_debug(1, "Map: name = %s, mapset = %s, temporary = %d", Map->name,
295  Map->mapset, Map->temporary);
296 
297  /* read vector format information */
298  if (ogr_mapset) {
300  }
301  else {
302  format = 0;
303  fp = G_fopen_old(path, GV_FRMT_ELEMENT, Map->mapset);
304  if (fp == NULL) {
305  G_debug(1, "Vector format: %d (native)", format);
307  }
308  else {
309  format = dig_read_frmt_ascii(fp, &(Map->fInfo));
310  fclose(fp);
311 
312  G_debug(1, "Vector format: %d (non-native)", format);
313  if (format < 0) {
314  G_fatal_error(_("Unable to open vector map <%s>"),
315  Vect_get_full_name(Map));
316  return -1;
317  }
318  }
319  }
320  Map->format = format;
321 
322  /* read vector head (ignored for OGR mapset) */
323  if (!ogr_mapset && Vect__read_head(Map) != 0) {
324  G_fatal_error(_("Unable to read header file of vector map <%s>"),
325  Vect_get_full_name(Map));
326  }
327 
328  /* projection is not written to head but zone ??? */
329  if (Vect_get_zone(Map) == -1)
330  Vect_set_zone(Map, G_zone());
331  Vect_set_proj(Map, G_projection());
332 
333  G_debug(1, "Level request = %d", level_request);
334 
335  /* There are only 2 possible open levels, 1 and 2. Try first to
336  open 'support' files (topo, sidx, cidx), these files are the same
337  for all formats. If it is not possible and requested level is
338  2, return error, otherwise call Open_old_array[format][1], to
339  open remaining files/sources (level 1)
340  */
341 
342  /* try to open support files if level was not requested or
343  * requested level is 2 (format independent) */
344  if (level_request == 0 || level_request > 1) {
345  level = 2; /* we expect success */
346 
347  /* open topo */
348  ret = -1;
349 #ifdef HAVE_POSTGRES
350  if (Map->format == GV_FORMAT_POSTGIS)
351  /* try to read full-topology for PostGIS links */
352  ret = Vect__open_topo_pg(Map, head_only, update);
353 #endif
354  if (ret != 0) {
355  /* read topology for native format
356  read pseudo-topology for OGR/PostGIS links */
357  ret = Vect_open_topo(Map, head_only);
358 
359  if (ret == 1) { /* topo file is not available */
360  G_debug(1, "topo file for vector '%s' not available.",
361  Vect_get_full_name(Map));
362  level = 1;
363  }
364  else if (ret == -1) {
366  _("Unable to open topology file for vector map <%s>"),
367  Vect_get_full_name(Map));
368  }
369  }
370 
371  /* open spatial index */
372  if (level >= 2) {
373  ret = Vect_open_sidx(Map, (update != 0));
374  if (ret == 1) { /* sidx file is not available */
375  G_debug(1, "sidx file for vector '%s' not available.",
376  Vect_get_full_name(Map));
377  if (!Map->fInfo.pg
378  .toposchema_name) /* optional for PostGIS Topology */
379  level = 1;
380  }
381  else if (ret == -1) {
383  _("Unable to open spatial index file for vector map <%s>"),
384  Vect_get_full_name(Map));
385  }
386  /* check with_z consistency */
387  if ((Map->plus.with_z != 0 && Map->plus.spidx_with_z == 0) ||
388  (Map->plus.with_z == 0 && Map->plus.spidx_with_z != 0)) {
389  G_warning(
390  "Vector map <%s>: topology is %s, but spatial index is %s",
391  Vect_get_full_name(Map),
392  (Map->plus.with_z != 0 ? "3D" : "2D"),
393  (Map->plus.spidx_with_z != 0 ? "3D" : "2D"));
394  level = 1;
395  }
396  }
397 
398  /* open category index */
399  if (level >= 2) {
400  ret = Vect_cidx_open(Map, head_only);
401  if (ret == 1) { /* category index is not available */
402  G_debug(1, "cidx file for vector '%s' not available.",
403  Vect_get_full_name(Map));
404  if (!Map->fInfo.pg
405  .toposchema_name) { /* optional for PostGIS Topology */
406  dig_free_plus(&(Map->plus)); /* free topology */
407  level = 1;
408  }
409  }
410  else if (ret == -1) { /* file exists, but cannot be opened */
412  _("Unable to open category index file for vector map <%s>"),
413  Vect_get_full_name(Map));
414  }
415  }
416 #ifdef HAVE_OGR
417  /* open OGR specific support files */
418  if (level == 2 && Map->format == GV_FORMAT_OGR) {
419  if (V2_open_old_ogr(Map) < 0) {
420  dig_free_plus(&(Map->plus));
421  level = 1;
422  }
423  }
424 #endif
425 #ifdef HAVE_POSTGRES
426  /* open OGR (pseudo-topology access only) specific support
427  * files */
428  if (level == 2 && Map->format == GV_FORMAT_POSTGIS) {
429  if (V2_open_old_pg(Map) < 0) {
430  dig_free_plus(&(Map->plus));
431  level = 1;
432  }
433  }
434 #endif
435  if (level_request == 2 && level < 2) {
436  if (!ogr_mapset) {
437  /* for direct OGR read access is built pseudo-topology on the
438  * fly */
439  G_warning(_("Unable to open vector map <%s> on level %d. "
440  "Try to rebuild vector topology with v.build."),
441  Vect_get_full_name(Map), level_request);
442  return -1;
443  }
444  }
445  }
446  else {
447  level = 1; /* i.e. requested level is 1 */
448  }
449 
450  /* open level 1 files / sources (format specific) */
451  if (!head_only || ogr_mapset || format == GV_FORMAT_POSTGIS) {
452  /* no need to open coordinates */
453  if (0 != (*Open_old_array[format][1])(Map, update)) { /* cannot open */
454  if (level >= 2) { /* support files opened */
455  dig_free_plus(&(Map->plus));
456  }
457  G_fatal_error(_("Unable to open vector map <%s>"),
458  Vect_get_full_name(Map));
459  return -1;
460  }
461  if (ogr_mapset && !head_only && level_request != 1) {
462  /* build pseudo-topology on the fly */
463  int verbose;
464 
465  verbose = G_verbose();
466  G_message(_("Building topology for OGR layer <%s> from datasource "
467  "'%s'..."),
468  Map->fInfo.ogr.layer_name, Map->fInfo.ogr.dsn);
469  G_set_verbose(0);
470  if (Vect_build(Map)) {
471  level = 2;
472  }
473  G_set_verbose(verbose);
474  if (level < level_request)
475  G_fatal_error(_("Unable to open vector map <%s> on level %d"),
476  Map->fInfo.ogr.layer_name, level_request);
477  }
478  if (level < 2 && Map->head.with_z) {
479  /* topo has been initialized as 2D, update to 3D */
480  dig_free_plus(&(Map->plus));
481  dig_init_plus(&(Map->plus));
482  Map->plus.with_z = Map->head.with_z;
483  }
484  }
485  else if (level > 1) {
486  /* take dimension from topo if topo is available */
487  Map->head.with_z = Map->plus.with_z;
488  }
489 
490  /* set status */
491  Map->open = VECT_OPEN_CODE;
492  Map->level = level;
493  Map->head_only = head_only;
494  Map->support_updated = FALSE;
495  if (update) {
496  Map->mode = GV_MODE_RW;
497  Map->plus.mode = GV_MODE_RW;
498  }
499  else {
500  Map->mode = GV_MODE_READ;
501  Map->plus.mode = GV_MODE_READ;
502  }
503  if (head_only) {
504  Map->head_only = TRUE;
505  }
506  else {
507  Map->head_only = FALSE;
508  }
509 
510  G_debug(1, "Vect__open_old(): vector opened on level %d", level);
511 
512  if (level == 1) { /* without topology */
513  Map->plus.built = GV_BUILD_NONE;
514  }
515  else { /* level 2, with topology */
516  Map->plus.built =
517  GV_BUILD_ALL; /* highest level of topology for level 2 */
518  }
519 
520  Map->plus.uplist.do_uplist = FALSE;
521 
522  /* read db links */
524  Vect_read_dblinks(Map);
525 
526  /* open history file */
527  if (update && !ogr_mapset) { /* native only */
529  if (Map->hist_fp == NULL) {
530  G_warning(_("Unable to open history file for vector map <%s>"),
531  Vect_get_full_name(Map));
532  return -1;
533  }
534  G_fseek(Map->hist_fp, (off_t)0, SEEK_END);
535  Vect_hist_write(Map, "-------------------------------------------------"
536  "--------------------------------\n");
537  }
538  else {
539  if (Map->format == GV_FORMAT_NATIVE || Map->format == GV_FORMAT_OGR ||
540  Map->format == GV_FORMAT_POSTGIS) {
542  /* If NULL (does not exist) then Vect_hist_read() handle that */
543  }
544  else {
545  Map->hist_fp = NULL;
546  }
547  }
548 
549  if (!head_only) { /* cannot rewind if not fully opened */
550  Vect_rewind(Map);
551  }
552 
553  /* delete support files if native format was opened for update (not
554  * head_only) */
555  if (update && !head_only) {
556  char file_path[GPATH_MAX];
557 
558  Vect__get_element_path(file_path, Map, GV_TOPO_ELEMENT);
559  if (access(file_path, F_OK) == 0) /* topo file exists? */
560  unlink(file_path);
561 
562  Vect__get_element_path(file_path, Map, GV_SIDX_ELEMENT);
563  if (access(file_path, F_OK) == 0) /* sidx file exists? */
564  unlink(file_path);
565 
566  Vect__get_element_path(file_path, Map, GV_CIDX_ELEMENT);
567  if (access(file_path, F_OK) == 0) /* cidx file exists? */
568  unlink(file_path);
569 
571  Vect__get_element_path(file_path, Map, GV_FIDX_ELEMENT);
572  if (access(file_path, F_OK) == 0) /* fidx file exists? */
573  unlink(file_path);
574  }
575  Map->support_updated = TRUE;
576  }
577 
578  return level;
579 }
580 
581 /*!
582  \brief Open existing vector map for reading
583 
584  This function is replaced by Vect_open_old2() to handle also direct
585  OGR support.
586 
587  Calls G_fatal_error() on failure.
588 
589  \param[out] Map pointer to Map_info structure
590  \param name name of vector map to open
591  \param mapset mapset name ("" for search path)
592 
593  \return 1 open on level 1 (without topology)
594  \return 2 open on level 2 (with topology)
595  \return -1 on error
596  */
597 int Vect_open_old(struct Map_info *Map, const char *name, const char *mapset)
598 {
599  return Vect__open_old(Map, name, mapset, NULL, FALSE, FALSE, FALSE);
600 }
601 
602 /*!
603  \brief Open existing temporary vector map for reading
604 
605  Temporary vector maps are stored in the current mapset (directory
606  <tt>.tmp/<hostname>/vector</tt>).
607 
608  Calls G_fatal_error() on failure.
609 
610  \todo Create new vector map if doesn't exist.
611 
612  \param[out] Map pointer to Map_info structure
613  \param name name of vector map to open
614  \param mapset mapset name ("" for search path)
615 
616  \return 1 open on level 1 (without topology)
617  \return 2 open on level 2 (with topology)
618  \return -1 on error
619  */
620 int Vect_open_tmp_old(struct Map_info *Map, const char *name,
621  const char *mapset)
622 {
623  return Vect__open_old(Map, name, mapset, NULL, FALSE, FALSE, TRUE);
624 }
625 
626 /*!
627  \brief Open existing vector map for reading
628 
629  Calls G_fatal_error() on failure.
630 
631  \param[out] Map pointer to Map_info structure
632  \param name name of vector map to open (datasource for direct OGR access)
633  \param mapset mapset name ("" for search path, "OGR" for direct OGR access)
634  \param layer layer name (OGR layer for direct OGR access)
635 
636  \return 1 open on level 1 (without topology)
637  \return 2 open on level 2 (with topology)
638  \return -1 on error
639  */
640 int Vect_open_old2(struct Map_info *Map, const char *name, const char *mapset,
641  const char *layer)
642 {
643  return Vect__open_old(Map, name, mapset, layer, FALSE, FALSE, FALSE);
644 }
645 
646 /*!
647  \brief Open existing vector map for reading/writing
648 
649  This function is replaced by Vect_open_update2() to handle also
650  direct OGR support.
651 
652  By default list of updated features is not maintained, see
653  Vect_set_updated() for details.
654 
655  Calls G_fatal_error() on failure.
656 
657  \param[out] Map pointer to Map_info structure
658  \param name name of vector map to update
659  \param mapset mapset name
660 
661  \return 1 open on level 1 (without topology)
662  \return 2 open on level 2 (with topology)
663  \return -1 on error
664  */
665 int Vect_open_update(struct Map_info *Map, const char *name, const char *mapset)
666 {
667  return Vect__open_old(Map, name, mapset, NULL, TRUE, FALSE, FALSE);
668 }
669 
670 /*!
671  \brief Open existing temporary vector map for reading/writing
672 
673  Temporary vector maps are stored in the current mapset (directory
674  <tt>.tmp/<hostname>/vector</tt>).
675 
676  By default list of updated features is not maintained, see
677  Vect_set_updated() for details.
678 
679  Calls G_fatal_error() on failure.
680 
681  \todo Create new vector map if doesn't exist.
682 
683  \param[out] Map pointer to Map_info structure
684  \param name name of vector map to update
685  \param mapset mapset name
686 
687  \return 1 open on level 1 (without topology)
688  \return 2 open on level 2 (with topology)
689  \return -1 on error
690  */
691 int Vect_open_tmp_update(struct Map_info *Map, const char *name,
692  const char *mapset)
693 {
694  return Vect__open_old(Map, name, mapset, NULL, TRUE, FALSE, TRUE);
695 }
696 
697 /*!
698  \brief Open existing vector map for reading/writing
699 
700  By default list of updated features is not maintained, see
701  Vect_set_updated() for details.
702 
703  Calls G_fatal_error() on failure.
704 
705  \param[out] Map pointer to Map_info structure
706  \param name name of vector map to open (datasource for direct OGR access)
707  \param mapset mapset name ("" for search path, "OGR" for direct OGR access)
708  \param layer layer name (OGR layer for direct OGR access)
709 
710  \return 1 open on level 1 (without topology)
711  \return 2 open on level 2 (with topology)
712  \return -1 on error
713  */
714 int Vect_open_update2(struct Map_info *Map, const char *name,
715  const char *mapset, const char *layer)
716 {
717  return Vect__open_old(Map, name, mapset, layer, TRUE, FALSE, FALSE);
718 }
719 
720 /*!
721  \brief Reads only info about vector map (headers)
722 
723  Reads from headers of 'head', 'dbln', 'topo' and 'cidx' file.
724 
725  This function is replaced by Vect_open_old_head2() to handle also
726  direct OGR support.
727 
728  Calls G_fatal_error() on failure.
729 
730  \param[out] Map pointer to Map_info structure
731  \param name name of vector map to read
732  \param mapset mapset name ("" for search path)
733 
734  \return 1 open on level 1 (without topology)
735  \return 2 open on level 2 (with topology)
736  \return -1 on error
737  */
738 int Vect_open_old_head(struct Map_info *Map, const char *name,
739  const char *mapset)
740 {
741  return Vect__open_old(Map, name, mapset, NULL, FALSE, TRUE, FALSE);
742 }
743 
744 /*!
745  \brief Reads only info about vector map (headers)
746 
747  Reads from headers of 'head', 'dbln', 'topo' and 'cidx' file.
748 
749  Calls G_fatal_error() on failure.
750 
751  \param[out] Map pointer to Map_info structure
752  \param name name of vector map to read (dsn for OGR)
753  \param mapset mapset name ("" for search path)
754  \param layer layer name (OGR format)
755 
756  \param[out] Map pointer to Map_info structure
757  \param name name of vector map to open (datasource for direct OGR access)
758  \param mapset mapset name ("" for search path, "OGR" for direct OGR access)
759  \param layer layer name (OGR layer for direct OGR access)
760 
761  \return 1 open on level 1 (without topology)
762  \return 2 open on level 2 (with topology)
763  \return -1 on error
764  */
765 int Vect_open_old_head2(struct Map_info *Map, const char *name,
766  const char *mapset, const char *layer)
767 {
768  return Vect__open_old(Map, name, mapset, layer, FALSE, TRUE, FALSE);
769 }
770 
771 /*! \brief Open header file of existing vector map for updating
772  (mostly for database link updates)
773 
774  \param[out] Map pointer to Map_info structure
775  \param name name of vector map to update
776  \param mapset mapset name
777 
778  \return 1 open on level 1 (without topology)
779  \return 2 open on level 2 (with topology)
780  \return -1 on error
781  */
782 int Vect_open_update_head(struct Map_info *Map, const char *name,
783  const char *mapset)
784 {
785  return Vect__open_old(Map, name, mapset, NULL, TRUE, TRUE, FALSE);
786 }
787 
788 int open_new(struct Map_info *Map, const char *name, int with_z, int is_tmp)
789 {
790  int ret;
791  char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
792 
793  G_debug(1, "Vect_open_new(): name = %s with_z = %d is_tmp = %d", name,
794  with_z, is_tmp);
795 
796  /* zero Map_info structure */
797  G_zero(Map, sizeof(struct Map_info));
798 
799  /* init header info */
800  Vect__init_head(Map);
801 
802  /* check for fully-qualified map name */
803  if (G_name_is_fully_qualified(name, xname, xmapset)) {
804  if (strcmp(xmapset, G_mapset()) != 0) {
805  G_warning(_("Unable to create vector map: <%s> is not in the "
806  "current mapset (%s)"),
807  name, G_mapset());
808  return -1;
809  }
810  name = xname;
811  }
812 
813  /* check for [A-Za-z][A-Za-z0-9_]* in name */
814  if (Vect_legal_filename(name) < 0) {
816  _("Unable to create vector map: <%s> is not SQL compliant"), name);
817  return -1;
818  }
819 
820  /* store basic info */
821  Map->name = G_store(name);
822  Map->mapset = G_store(G_mapset());
823  Map->location = G_store(G_location());
824  Map->gisdbase = G_store(G_gisdbase());
825  Map->temporary = is_tmp;
826 
827  /* determine output format */
828  Map->format = map_format(Map);
829 
830  if (Map->format != GV_FORMAT_OGR_DIRECT &&
831  getenv("GRASS_VECTOR_PGFILE") ==
832  NULL) { /* GRASS_VECTOR_PGFILE defined by v.out.postgis */
833  char *env;
834  char path[GPATH_MAX];
835 
836  G_debug(2, " using non-direct format");
837 
838  /* check if map already exists
839  temporary maps are automatically overwritten
840  */
841  if (Map->temporary) {
842  if (-1 == Vect__delete(name, Map->temporary)) {
843  G_warning(_("Unable to delete vector map <%s>"), name);
844  return -1;
845  }
846  }
847 
848  env = getenv("GRASS_VECTOR_TEMPORARY");
849  if (!Map->temporary || (env && strcmp(env, "move") == 0)) {
850  if (G_find_vector2(name, G_mapset()) != NULL) {
851  G_warning(
852  _("Vector map <%s> already exists and will be overwritten"),
853  name);
854 
855  ret = Vect_delete(name);
856  if (ret == -1) {
857  G_warning(_("Unable to delete vector map <%s>"), name);
858  return -1;
859  }
860  }
861  }
862 
863  /* write header file
864 
865  note: header & history file is also written for external
866  formats since vector library create links automatically
867  when closing the map
868  */
869  Map->head.size = 0;
870  Map->head.head_size = GV_COOR_HEAD_SIZE + 4;
871  Vect__write_head(Map);
872 
873  /* create history file */
874  Vect__get_path(path, Map);
876  if (Map->hist_fp == NULL) {
877  G_warning(_("Unable to open history file of vector map <%s>"),
878  name);
879  return -1;
880  }
881  }
882 
883  /* set 2D/3D */
884  Map->plus.spidx_with_z = Map->plus.with_z = Map->head.with_z =
885  (with_z != 0);
886 
887  Map->level = LEVEL_1;
888 
889  if ((*Open_new_array[Map->format][1])(Map, name, with_z) < 0) {
890  if (getenv("GRASS_VECTOR_PGFILE") ==
891  NULL) /* GRASS_VECTOR_PGFILE defined by v.out.postgis */
892  Vect_delete(name); /* clean up */
893  return -1;
894  }
895 
896  Open_level = 0;
897 
898  /* initialize topo */
899  Map->plus.Spidx_file = 0;
900  dig_init_plus(&(Map->plus));
901 
902  /* open new spatial index */
903  if (Vect_open_sidx(Map, 2) < 0)
905  _("Unable to open spatial index file for vector map <%s>"),
906  Vect_get_full_name(Map));
907 
908  Map->open = VECT_OPEN_CODE;
909  Map->head_only = FALSE;
910  Map->support_updated = FALSE;
911  Map->plus.built = GV_BUILD_NONE;
912  Map->mode = GV_MODE_RW;
913  Map->plus.uplist.do_uplist = FALSE;
914 
915  Vect_set_proj(Map, G_projection());
916  Vect_set_zone(Map, G_zone());
917 
919 
920  if (Map->fInfo.ogr.driver_name) {
921  G_verbose_message(_("Using OGR/%s format"), Map->fInfo.ogr.driver_name);
922  }
923  else if (Map->fInfo.pg.conninfo) {
924  if (Map->fInfo.pg.toposchema_name)
925  G_verbose_message(_("Using PostGIS Topology format"));
926  else
927  G_verbose_message(_("Using PostGIS format"));
928  }
929  else {
930  G_verbose_message(_("Using native format"));
931  }
932 
933  return 1;
934 }
935 
936 /*!
937  \brief Create new vector map for reading/writing
938 
939  By default list of updated features is not maintained, see
940  Vect_set_updated() for details.
941 
942  By default map format is native (GV_FORMAT_NATIVE). If OGR file is
943  found in the current mapset then the map (ie. OGR layer) is created
944  in given OGR datasource (GV_FORMAT_OGR). Similarly if PG file exists
945  then the map (ie. PostGIS table) is created using PostGIS interface
946  (GV_FORMAT_POSTGIS). The format of map is stored in Map->format.
947 
948  \param[out] Map pointer to Map_info structure
949  \param name name of vector map to be created
950  \param with_z WITH_Z for 3D vector data otherwise WITHOUT_Z
951 
952  \return 1 on success
953  \return -1 on error
954  */
955 int Vect_open_new(struct Map_info *Map, const char *name, int with_z)
956 {
957  int is_tmp;
958 
959  is_tmp = getenv("GRASS_VECTOR_TEMPORARY") ? TEMPORARY_MAP_ENV
960  : TEMPORARY_MAP_DISABLED;
961  G_debug(1, "Vect_open_new(): is_tmp = %d", is_tmp);
962 
963  return open_new(Map, name, with_z, is_tmp);
964 }
965 
966 /*!
967  \brief Create new temporary vector map
968 
969  Temporary vector maps are stored in the current mapset (directory
970  <tt>.tmp/<hostname>/vector</tt>). If the map already exists, it is
971  overwritten.
972 
973  Temporary vector maps are automatically deleted when closing the map
974  (see Vect_close() for details).
975 
976  If <em>name</em> is not given (is NULL), then the name is determined
977  by process id (<tt>tmp_<pid></tt>).
978 
979  \param[out] Map pointer to output Map_info struct
980  \param name name for new vector map (or NULL)
981  \param with_z WITH_Z for 3D vector data otherwise WITHOUT_Z
982 
983  \return 1 on success
984  \return -1 on error
985  */
986 int Vect_open_tmp_new(struct Map_info *Map, const char *name, int with_z)
987 {
988  char tmp_name[GNAME_MAX];
989 
990  if (!name) {
991  sprintf(tmp_name, "tmp_%d", getpid());
992  }
993  else {
994  sprintf(tmp_name, "%s", name);
995  }
996  G_debug(1, "Vect_open_tmp_new(): name = '%s' with_z = %d", name, with_z);
997 
998  return open_new(Map, tmp_name, with_z, TEMPORARY_MAP); /* temporary map */
999 }
1000 
1001 /*!
1002  \brief Update Coor_info structure
1003 
1004  \param Map pointer to Map_info structure
1005  \param[out] Info pointer to Coor_info structure
1006 
1007  \return 1 on success
1008  \return 0 on error
1009  */
1010 int Vect_coor_info(struct Map_info *Map, struct Coor_info *Info)
1011 {
1012  char file_path[GPATH_MAX];
1013  struct stat stat_buf;
1014 
1015  switch (Map->format) {
1016  case GV_FORMAT_NATIVE:
1017  Vect__get_element_path(file_path, Map, GV_COOR_ELEMENT);
1018  G_debug(1, "get coor info: %s", file_path);
1019  if (0 != stat(file_path, &stat_buf)) {
1020  G_warning(_("Unable to stat file <%s>"), file_path);
1021  Info->size = -1L;
1022  Info->mtime = -1L;
1023  }
1024  else {
1025  Info->size = (off_t)stat_buf.st_size; /* file size */
1026  Info->mtime = (long)stat_buf.st_mtime; /* last modified time */
1027  }
1028 
1029  /* stat does not give correct size on MINGW
1030  * if the file is opened */
1031 #ifdef __MINGW32__
1032  if (Map->open == VECT_OPEN_CODE) {
1033  dig_fseek(&(Map->dig_fp), 0L, SEEK_END);
1034  G_debug(2, "dig_ftell = %d", dig_ftell(&(Map->dig_fp)));
1035  Info->size = dig_ftell(&(Map->dig_fp));
1036  }
1037 #endif
1038  break;
1039  case GV_FORMAT_OGR:
1040  case GV_FORMAT_OGR_DIRECT:
1041  case GV_FORMAT_POSTGIS:
1042  Info->size = 0L;
1043  Info->mtime = 0L;
1044  break;
1045  }
1046  G_debug(1, "Vect_coor_info(): Info->size = %lu, Info->mtime = %ld",
1047  (unsigned long)Info->size, Info->mtime);
1048 
1049  return 1;
1050 }
1051 
1052 /*!
1053  \brief Gets vector map format (as string)
1054 
1055  Note: string is allocated by G_store(). Free allocated memory with
1056  G_free().
1057 
1058  Currently are implemented:
1059  - Native format (native)
1060  - OGR format (ogr)
1061  - PostGIS format (postgis)
1062 
1063  \param Map pointer to Map_info structure
1064 
1065  \return maptype string on success (allocated by G_store())
1066  \return error message on error
1067  */
1068 const char *Vect_maptype_info(struct Map_info *Map)
1069 {
1070  char maptype[1000];
1071 
1072  switch (Map->format) {
1073  case GV_FORMAT_NATIVE:
1074  sprintf(maptype, "native");
1075  break;
1076  case GV_FORMAT_OGR:
1077  case GV_FORMAT_OGR_DIRECT:
1078  sprintf(maptype, "OGR");
1079  break;
1080  case GV_FORMAT_POSTGIS:
1081  sprintf(maptype, "PostGIS");
1082  break;
1083  default:
1084  sprintf(maptype, _("unknown %d (update Vect_maptype_info)"),
1085  Map->format);
1086  }
1087 
1088  return G_store(maptype);
1089 }
1090 
1091 /*!
1092  \brief Gets vector map format
1093 
1094  Currently are implemented:
1095  - Native format (GV_FORMAT_NATIVE)
1096  - OGR format linked via v.external (GV_FORMAT_OGR)
1097  - OGR format (GV_FORMAT_OGR_DIRECT)
1098  - PostGIS format (GV_FORMAT_POSTGIS)
1099 
1100  \param Map pointer to Map_info structure
1101 
1102  \return map format code
1103  */
1104 int Vect_maptype(struct Map_info *Map)
1105 {
1106  if (Map->temporary) {
1107  const struct Format_info *finfo;
1108 
1109  finfo = &(Map->fInfo);
1110  if (finfo->ogr.driver_name) {
1111  return GV_FORMAT_OGR;
1112  }
1113  if (finfo->pg.conninfo) {
1114  return GV_FORMAT_POSTGIS;
1115  }
1116  }
1117 
1118  return Map->format;
1119 }
1120 
1121 /*!
1122  \brief Open topology file ('topo')
1123 
1124  \param[in,out] Map pointer to Map_info structure
1125  \param head_only TRUE to read only header
1126 
1127  \return 0 on success
1128  \return 1 file does not exist
1129  \return -1 on error
1130  */
1131 int Vect_open_topo(struct Map_info *Map, int head_only)
1132 {
1133  int err, ret;
1134  char file_path[GPATH_MAX], path[GPATH_MAX];
1135  struct gvfile fp;
1136  struct Coor_info CInfo;
1137  struct Plus_head *Plus;
1138 
1139  G_debug(1, "Vect_open_topo(): name = %s mapset = %s", Map->name,
1140  Map->mapset);
1141 
1142  Plus = &(Map->plus);
1143 
1144  Vect__get_path(path, Map);
1145  Vect__get_element_path(file_path, Map, GV_TOPO_ELEMENT);
1146  if (access(file_path, F_OK) != 0) { /* does not exist */
1147  return 1;
1148  }
1149 
1150  dig_file_init(&fp);
1152 
1153  if (fp.file == NULL) { /* topo file is not available */
1154  G_debug(1, "Cannot open topo file for vector '%s@%s'.", Map->name,
1155  Map->mapset);
1156  return -1;
1157  }
1158 
1159  /* get coor info */
1160  /* NOTE: coor file not yet opened */
1161  Vect_coor_info(Map, &CInfo);
1162 
1163  /* load head */
1164  if (dig_Rd_Plus_head(&fp, Plus) == -1)
1165  return -1;
1166 
1167  G_debug(1, "Topo head: coor size = %lu, coor mtime = %ld",
1168  (unsigned long)Plus->coor_size, Plus->coor_mtime);
1169 
1170  /* do checks */
1171  err = 0;
1172  if (CInfo.size != Plus->coor_size) {
1173  G_warning(
1174  _("Size of 'coor' file differs from value saved in topology file"));
1175  err = 1;
1176  }
1177  /* Do not check mtime because mtime is changed by copy */
1178  /*
1179  if ( CInfo.mtime != Plus->coor_mtime ) {
1180  G_warning ( "Time of last modification for 'coor' file differs from value
1181  saved in topo file.\n"); err = 1;
1182  }
1183  */
1184  if (err) {
1185  G_warning(_("Please rebuild topology for vector map <%s@%s>"),
1186  Map->name, Map->mapset);
1187  return -1;
1188  }
1189 
1190  /* load file to the memory */
1191  /* dig_file_load ( &fp); */
1192 
1193  /* load topo to memory */
1194  ret = dig_load_plus(Plus, &fp, head_only);
1195 
1196  fclose(fp.file);
1197  /* dig_file_free(&fp); */
1198 
1199  return ret == 0 ? -1 : 0;
1200 }
1201 
1202 /*!
1203  \brief Open spatial index file ('sidx')
1204 
1205  \param[in,out] Map pointer to Map_info
1206  \param mode 0 old, 1 update, 2 new
1207 
1208  \return 1 if sidx file is not available
1209  \return 0 on success
1210  \return -1 on error
1211  */
1212 int Vect_open_sidx(struct Map_info *Map, int mode)
1213 {
1214  int err;
1215  struct Coor_info CInfo;
1216  struct Plus_head *Plus;
1217 
1218  G_debug(1, "Vect_open_sidx(): name = %s mapset= %s mode = %s", Map->name,
1219  Map->mapset, mode == 0 ? "old" : (mode == 1 ? "update" : "new"));
1220 
1221  Plus = &(Map->plus);
1222 
1223  if (Plus->Spidx_built) {
1224  G_debug(1, "Spatial index already opened");
1225  return 0;
1226  }
1227 
1228  dig_file_init(&(Plus->spidx_fp));
1229 
1230  if (mode < 2) {
1231  char path[GPATH_MAX], file_path[GPATH_MAX];
1232 
1233  Vect__get_path(path, Map);
1234  Vect__get_element_path(file_path, Map, GV_SIDX_ELEMENT);
1235  if (access(file_path, F_OK) != 0) /* does not exist */
1236  return 1;
1237 
1239 
1240  if (Plus->spidx_fp.file == NULL) { /* sidx file is not available */
1241  G_debug(1, "Cannot open spatial index file for vector '%s@%s'.",
1242  Map->name, Map->mapset);
1243  return -1;
1244  }
1245 
1246  /* get coor info */
1247  /* NOTE: coor file not yet opened */
1248  Vect_coor_info(Map, &CInfo);
1249 
1250  /* initialize spatial index */
1251  Plus->Spidx_new = FALSE;
1252 
1253  if (mode == 0) {
1254  /* free old indices */
1255  dig_spidx_free(Plus);
1256  /* initialize file based indices */
1257  Plus->Spidx_file = 1;
1258  dig_spidx_init(Plus);
1259  }
1260 
1261  /* load head */
1262  if (dig_Rd_spidx_head(&(Plus->spidx_fp), Plus) == -1) {
1263  fclose(Plus->spidx_fp.file);
1264  return -1;
1265  }
1266 
1267  G_debug(1, "Sidx head: coor size = %lu, coor mtime = %ld",
1268  (unsigned long)Plus->coor_size, Plus->coor_mtime);
1269 
1270  /* do checks */
1271  err = 0;
1272  if (CInfo.size != Plus->coor_size) {
1273  G_warning(
1274  _("Size of 'coor' file differs from value saved in sidx file"));
1275  err = 1;
1276  }
1277  /* Do not check mtime because mtime is changed by copy */
1278  /*
1279  if ( CInfo.mtime != Plus->coor_mtime ) {
1280  G_warning ( "Time of last modification for 'coor' file differs from
1281  value saved in topo file.\n"); err = 1;
1282  }
1283  */
1284  if (err) {
1285  G_warning(_("Please rebuild topology for vector map <%s@%s>"),
1286  Map->name, Map->mapset);
1287  fclose(Plus->spidx_fp.file);
1288  return -1;
1289  }
1290  }
1291 
1292  if (mode) {
1293  /* open new spatial index */
1294  Plus->Spidx_new = TRUE;
1295 
1296  /* file based or memory based */
1297  if (getenv("GRASS_VECTOR_LOWMEM")) {
1298  /* free old indices */
1299  dig_spidx_free(Plus);
1300  /* initialize file based indices */
1301  Plus->Spidx_file = 1;
1302  dig_spidx_init(Plus);
1303  }
1304  G_debug(1, "%s based spatial index",
1305  Plus->Spidx_file == 0 ? "Memory" : "File");
1306 
1307  if (mode == 1) {
1308  /* load spatial index for update */
1309  if (dig_Rd_spidx(&(Plus->spidx_fp), Plus) == -1) {
1310  fclose(Plus->spidx_fp.file);
1311  return -1;
1312  }
1313  }
1314  }
1315 
1316  Plus->Spidx_built = TRUE;
1317 
1318  return 0;
1319 }
1320 
1321 /* check for external formats definition */
1322 int map_format(struct Map_info *Map)
1323 {
1324  int format;
1325  char *def_file;
1326 
1327  format = GV_FORMAT_NATIVE;
1328  /* temporary maps can be stored only in native format */
1329  if (Map->temporary || getenv("GRASS_VECTOR_EXTERNAL_IGNORE"))
1330  return format;
1331 
1332  if (G_find_file2("", "OGR", G_mapset())) {
1333  /* OGR */
1334  FILE *fp;
1335  const char *p;
1336 
1337  struct Key_Value *key_val;
1338  struct Format_info_ogr *ogr_info;
1339 
1340  G_debug(2, " using OGR format");
1341  if (getenv("GRASS_VECTOR_EXTERNAL_IMMEDIATE")) {
1342  /* vector features are written directly to OGR layer */
1343  format = GV_FORMAT_OGR;
1344  }
1345  else {
1346  /* vector features are written to the temporary vector map
1347  * in the native format and when closing the map
1348  * transferred to output OGR layer */
1349  format = GV_FORMAT_NATIVE;
1350  Map->temporary = TEMPORARY_MAP;
1351  }
1352  fp = G_fopen_old("", "OGR", G_mapset());
1353  if (!fp) {
1354  G_fatal_error(_("Unable to open OGR file"));
1355  }
1356  key_val = G_fread_key_value(fp);
1357  fclose(fp);
1358 
1359  ogr_info = &(Map->fInfo.ogr);
1360  /* format */
1361  p = G_find_key_value("format", key_val);
1362  if (p)
1363  ogr_info->driver_name = G_store(p);
1364  /* dsn */
1365  p = G_find_key_value("dsn", key_val);
1366  if (p)
1367  ogr_info->dsn = G_store(p);
1368  /* options */
1369  p = G_find_key_value("options", key_val);
1370  if (p)
1371  ogr_info->layer_options = G_tokenize(p, ",");
1372 
1373  ogr_info->layer_name = G_store(Map->name);
1374  }
1375 
1376  def_file = getenv("GRASS_VECTOR_PGFILE"); /* GRASS_VECTOR_PGFILE defined by
1377  v.out.postgis */
1378  if (G_find_file2("", def_file ? def_file : "PG", G_mapset())) {
1379  /* PostGIS */
1380  if (Map->fInfo.ogr.driver_name) {
1381  G_warning(_("OGR output also detected, using OGR"));
1382  }
1383  else {
1384  FILE *fp;
1385  const char *p;
1386 
1387  struct Key_Value *key_val;
1388  struct Format_info_pg *pg_info;
1389 
1390  G_debug(2, " using PostGIS format");
1391  fp = G_fopen_old("", def_file ? def_file : "PG", G_mapset());
1392  if (!fp) {
1393  G_fatal_error(_("Unable to open PG file"));
1394  }
1395  key_val = G_fread_key_value(fp);
1396  fclose(fp);
1397 
1398  pg_info = &(Map->fInfo.pg);
1399  /* conninfo */
1400  p = G_find_key_value("conninfo", key_val);
1401  if (p) {
1402  pg_info->conninfo = G_store(p);
1403  G_debug(1, "PG: conninfo = '%s'", pg_info->conninfo);
1404  }
1405 
1406  /* schema (default: public) */
1407  p = G_find_key_value("schema", key_val);
1408  if (p)
1409  pg_info->schema_name = G_store(p);
1410  else
1411  pg_info->schema_name = G_store("public");
1412  G_debug(1, "PG: schema_name = '%s'", pg_info->schema_name);
1413 
1414  /* fid column (default: FID_COLUMN) */
1415  p = G_find_key_value("fid", key_val);
1416  if (p)
1417  pg_info->fid_column = G_store(p);
1418  else
1419 #ifdef HAVE_POSTGRES
1420  pg_info->fid_column = G_store(GV_PG_FID_COLUMN);
1421 #endif
1422  G_debug(1, "PG: fid_column = '%s'", pg_info->fid_column);
1423 
1424  /* geometry column (default: GEOMETRY_COLUMN) */
1425  p = G_find_key_value("geometry_name", key_val);
1426  if (p)
1427  pg_info->geom_column = G_store(p);
1428  else
1429 #ifdef HAVE_POSTGRES
1431 #endif
1432  G_debug(1, "PG: geom_column = '%s'", pg_info->geom_column);
1433 
1434  /* srid (default: 0) */
1435  p = G_find_key_value("srid", key_val);
1436  if (p) {
1437  pg_info->srid = atoi(p);
1438  }
1439  else {
1440  /* not defined by v.external.out, so try if EPSG code
1441  * is defined */
1442  p = G_database_epsg_code();
1443  if (p)
1444  pg_info->srid = atoi(p);
1445  }
1446  G_debug(1, "PG: srid = %d", pg_info->srid);
1447 
1448  /* table name */
1449  Map->fInfo.pg.table_name = G_store(Map->name);
1450 
1451  /* PostGIS topology enabled ? */
1452  p = G_find_key_value("topology", key_val);
1453  if (p && G_strcasecmp(p, "yes") == 0) {
1454  /* define topology name */
1455  p = G_find_key_value("toposchema_name", key_val);
1456  if (p)
1457  pg_info->toposchema_name = G_store(p);
1458  else
1459  G_asprintf(&(pg_info->toposchema_name), "topo_%s",
1460  pg_info->table_name);
1461 
1462  G_debug(1, "PG: topology = yes, schema_name = %s",
1463  pg_info->toposchema_name);
1464  }
1465  G_debug(1, "PG: topology = no");
1466 
1467  if (getenv("GRASS_VECTOR_EXTERNAL_IMMEDIATE")) {
1468  /* vector features are written directly to PostGIS layer */
1469  format = GV_FORMAT_POSTGIS;
1470  }
1471  else {
1472  /* vector features are written to the temporary vector map
1473  * in the native format and when closing the map
1474  * transferred to output PostGIS layer */
1475  format = GV_FORMAT_NATIVE;
1476  Map->temporary = TEMPORARY_MAP;
1477  }
1478  }
1479  }
1480 
1481  G_debug(2, "map_format = %d", format);
1482  return format;
1483 }
1484 
1485 /*!
1486  \brief Get map directory name (internal use only)
1487 
1488  \param file_path path string buffer
1489  \param Map pointer to Map_info struct
1490 
1491  \return buffer containing path
1492  */
1493 char *Vect__get_path(char *path, struct Map_info *Map)
1494 {
1495  if (Map->temporary) {
1496  char path_tmp[GPATH_MAX];
1497 
1498  G__temp_element(path_tmp, TRUE);
1499  sprintf(path, "%s/%s/%s", path_tmp, GV_DIRECTORY, Map->name);
1500  }
1501  else {
1502  sprintf(path, "%s/%s", GV_DIRECTORY, Map->name);
1503  }
1504 
1505  return path;
1506 }
1507 
1508 /*!
1509  \brief Get map element full path (internal use only)
1510 
1511  Allocate string should be freed by G_free().
1512 
1513  \param Map pointer to Map_info struct
1514  \param element element name, eg. GV_TOPO_ELEMENT
1515 
1516  \return allocated buffer containing path
1517  */
1518 char *Vect__get_element_path(char *file_path, struct Map_info *Map,
1519  const char *element)
1520 {
1521  char path[GPATH_MAX];
1522 
1523  Vect__get_path(path, Map);
1524  if (Map->temporary)
1525  G_file_name_tmp(file_path, path, element, Map->mapset);
1526  else
1527  G_file_name(file_path, path, element, Map->mapset);
1528 
1529  return file_path;
1530 }
#define NULL
Definition: ccmath.h:32
int G_name_is_fully_qualified(const char *, char *, char *)
Check if map name is fully qualified (map @ mapset)
Definition: nme_in_mps.c:36
FILE * G_fopen_old(const char *, const char *, const char *)
Open a database file for reading.
Definition: gis/open.c:251
const char * G_find_vector2(const char *, const char *)
Find a vector map (look but don't touch)
Definition: find_vect.c:62
const char * G_database_epsg_code(void)
Get EPGS code for the current location.
Definition: proj3.c:236
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition: gis/zero.c:23
const char * G_find_file2(const char *, const char *, const char *)
Searches for a file from the mapset search list or in a specified mapset. (look but don't touch)
Definition: find_file.c:234
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
char * G_file_name(char *, const char *, const char *, const char *)
Builds full path names to GIS data files.
Definition: file_name.c:61
const char * G_gisdbase(void)
Get name of top level database directory.
Definition: gisdbase.c:26
const char * G_find_key_value(const char *, const struct Key_Value *)
Find given key (case sensitive)
Definition: key_value1.c:85
void G__temp_element(char *, int)
Populates element with a path string (internal use only!)
Definition: tempfile.c:159
void G_fseek(FILE *, off_t, int)
Change the file position of the stream.
Definition: gis/seek.c:50
void void G_verbose_message(const char *,...) __attribute__((format(printf
const char * G_mapset(void)
Get current mapset name.
Definition: gis/mapset.c:33
char * G_file_name_tmp(char *, const char *, const char *, const char *)
Builds full path names to GIS data files in temporary directory (for internal use only)
Definition: file_name.c:125
FILE * G_fopen_modify(const char *, const char *)
Open a database file for update (r+ mode)
Definition: gis/open.c:306
struct Key_Value * G_fread_key_value(FILE *)
Read key/values pairs from file.
Definition: key_value2.c:49
int G_verbose(void)
Get current verbosity level.
Definition: verbose.c:60
int G_asprintf(char **, const char *,...) __attribute__((format(printf
int G_zone(void)
Query cartographic zone.
Definition: zone.c:24
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
Definition: strings.c:47
int G_set_verbose(int)
Set verbosity level.
Definition: verbose.c:125
const char * G_location(void)
Get current location name.
Definition: location.c:32
void G_message(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
char * G_store(const char *)
Copy string to allocated memory.
Definition: strings.c:87
FILE * G_fopen_new(const char *, const char *)
Open a new database file.
Definition: gis/open.c:219
char ** G_tokenize(const char *, const char *)
Tokenize string.
Definition: gis/token.c:47
int G_projection(void)
Query cartographic projection.
Definition: proj1.c:32
int V1_open_old_ogr(struct Map_info *, int)
Open existing OGR layer on non-topological level.
Definition: open_ogr.c:43
int Vect_cidx_open(struct Map_info *, int)
Read category index from cidx file if exists.
Definition: Vlib/cindex.c:522
int Vect_set_proj(struct Map_info *, int)
Set projection in map header.
int V1_open_new_pg(struct Map_info *, const char *, int)
int Vect_read_dblinks(struct Map_info *)
Read dblinks to existing structure.
Definition: field.c:846
struct dblinks * Vect_new_dblinks_struct(void)
Create and init new dblinks structure.
Definition: field.c:52
int Vect_set_zone(struct Map_info *, int)
Set projection zone in map header.
int V1_open_new_nat(struct Map_info *, const char *, int)
Create new vector map (level 1)
Definition: open_nat.c:96
int V1_open_old_nat(struct Map_info *, int)
Open existing vector map (level 1)
Definition: open_nat.c:40
int V2_open_old_pg(struct Map_info *)
const char * Vect_get_full_name(struct Map_info *)
Get fully qualified name of vector map.
int Vect_get_zone(struct Map_info *)
int Vect_delete(const char *)
Delete vector map including attribute tables.
Definition: map.c:367
int Vect_legal_filename(const char *)
Check if output is legal vector name.
Definition: legal_vname.c:32
int Vect__read_head(struct Map_info *)
Reads head information from text file (GV_HEAD_ELEMENT) - for internal use only.
int Vect_build(struct Map_info *)
Build topology for vector map.
Definition: build.c:586
void Vect__init_head(struct Map_info *)
Initialize Map_info head structure (dig_head)
Definition: init_head.c:29
int Vect_rewind(struct Map_info *)
Rewind vector map to cause reads to start at beginning.
int V1_open_new_ogr(struct Map_info *, const char *, int)
Prepare OGR datasource for creating new OGR layer (level 1)
Definition: open_ogr.c:180
const char * Vect_get_name(struct Map_info *)
Get name of vector map.
int Vect__write_head(struct Map_info *)
Writes head information to text file (GV_HEAD_ELEMENT)
int Vect_hist_write(struct Map_info *, const char *)
Write string to history file.
Definition: hist.c:65
int V2_open_old_ogr(struct Map_info *)
Open existing OGR layer on topological level.
Definition: open_ogr.c:145
int V1_open_old_pg(struct Map_info *, int)
#define GV_FRMT_ELEMENT
Format description, data location (OGR)
Definition: dig_defines.h:10
#define GV_BUILD_NONE
Topology levels - nothing to build.
Definition: dig_defines.h:123
#define VECT_OPEN_CODE
Vector map open code.
Definition: dig_defines.h:111
#define GV_FORMAT_POSTGIS
PostGIS format.
Definition: dig_defines.h:89
#define GV_DIRECTORY
Name of vector directory.
Definition: dig_defines.h:8
#define GV_SIDX_ELEMENT
Native format, spatial index.
Definition: dig_defines.h:22
#define GV_MODE_READ
Read-only vector map open mode.
Definition: dig_defines.h:104
#define LEVEL_1
Vector level - without topology.
Definition: dig_defines.h:116
#define GV_BUILD_ALL
Topology levels - build everything (currently same as GV_BUILD_CENTROIDS)
Definition: dig_defines.h:134
#define GV_COOR_ELEMENT
Native format, coordinates.
Definition: dig_defines.h:12
#define GV_FIDX_ELEMENT
External format (OGR), feature index.
Definition: dig_defines.h:26
#define GV_COOR_HEAD_SIZE
Coordinates file head size.
Definition: dig_defines.h:145
#define GV_FORMAT_OGR_DIRECT
OGR format (direct access)
Definition: dig_defines.h:87
#define WITHOUT_Z
2D/3D vector data
Definition: dig_defines.h:171
#define GV_CIDX_ELEMENT
Native format, category index.
Definition: dig_defines.h:24
#define GV_TOPO_ELEMENT
Native format, topology file.
Definition: dig_defines.h:20
#define GV_PG_GEOMETRY_COLUMN
GRASS-PostGIS data provider - default geometry column.
Definition: dig_defines.h:273
#define GV_HEAD_ELEMENT
Native format, header information.
Definition: dig_defines.h:14
#define GV_FORMAT_OGR
OGR format.
Definition: dig_defines.h:85
#define GV_MODE_RW
Read-write vector map open mode.
Definition: dig_defines.h:108
#define GV_PG_FID_COLUMN
GRASS-PostGIS data provider - default fid column.
Definition: dig_defines.h:271
#define GV_FORMAT_NATIVE
Geometry data formats supported by lib Don't change GV_FORMAT_* values, this order is hardcoded in li...
Definition: dig_defines.h:83
#define GV_HIST_ELEMENT
Native format, history file.
Definition: dig_defines.h:18
int dig_load_plus(struct Plus_head *, struct gvfile *, int)
Reads topo file to topo structure.
Definition: plus.c:195
void dig_free_plus(struct Plus_head *)
Free Plus structure.
Definition: plus.c:173
int dig_init_plus(struct Plus_head *)
Initialize Plus_head structure.
Definition: plus.c:30
int dig_read_frmt_ascii(FILE *, struct Format_info *)
Read external vector format file.
Definition: frmt.c:33
off_t dig_ftell(struct gvfile *file)
Get struct gvfile position.
Definition: file.c:36
int dig_Rd_spidx(struct gvfile *, struct Plus_head *)
Read spatial index from sidx file Only needed when old vector is opened in update mode.
Definition: spindex_rw.c:1223
int dig_Rd_Plus_head(struct gvfile *, struct Plus_head *)
Read Plus_head from file.
Definition: plus_struct.c:531
int dig_fseek(struct gvfile *file, off_t offset, int whence)
Set struct gvfile position.
Definition: file.c:60
int dig_Rd_spidx_head(struct gvfile *, struct Plus_head *)
Read spatial index header from sidx file.
Definition: spindex_rw.c:262
void dig_spidx_free(struct Plus_head *)
Free spatial index (nodes, lines, areas, isles)
Definition: spindex.c:243
void dig_file_init(struct gvfile *file)
Initialize gvfile structure.
Definition: file.c:171
int dig_spidx_init(struct Plus_head *)
Initit spatial index (nodes, lines, areas, isles)
Definition: spindex.c:35
#define GMAPSET_MAX
Definition: gis.h:192
#define GPATH_MAX
Definition: gis.h:194
#define TRUE
Definition: gis.h:79
#define FALSE
Definition: gis.h:83
#define GNAME_MAX
Definition: gis.h:191
#define UNUSED
A macro for an attribute, if attached to a variable, indicating that the variable is not used.
Definition: gis.h:47
#define _(str)
Definition: glocale.h:10
int Vect__delete(const char *map, int is_tmp)
Delete vector map (internal use only)
Definition: map.c:381
const char * name
Definition: named_colr.c:6
int Vect__open_topo_pg(struct Map_info *Map NOPG_UNUSED, int head_only NOPG_UNUSED, int update NOPG_UNUSED)
Read full-topology for PostGIS links.
Definition: open_pg.c:326
Coor file info.
Definition: dig_structs.h:371
off_t size
Total size (in bytes)
Definition: dig_structs.h:375
long mtime
Time of last modification.
Definition: dig_structs.h:379
Non-native format info (OGR)
Definition: dig_structs.h:505
char * dsn
OGR datasource name.
Definition: dig_structs.h:513
char * driver_name
OGR driver name.
Definition: dig_structs.h:509
char * layer_name
OGR layer name.
Definition: dig_structs.h:517
char ** layer_options
Array of OGR layer options.
Definition: dig_structs.h:556
Non-native format info (PostGIS)
Definition: dig_structs.h:590
char * fid_column
FID column.
Definition: dig_structs.h:614
char * schema_name
Schema name.
Definition: dig_structs.h:602
char * toposchema_name
Topology schema name and id.
Definition: dig_structs.h:686
char * conninfo
Connection string.
Definition: dig_structs.h:594
int srid
Spatial reference system id (see spatial_ref_sys table)
Definition: dig_structs.h:631
char * geom_column
Geometry column (simple feature access)
Definition: dig_structs.h:618
char * table_name
Table name.
Definition: dig_structs.h:606
Non-native format info (currently only OGR is implemented)
Definition: dig_structs.h:700
struct Format_info_pg pg
PostGIS info.
Definition: dig_structs.h:712
struct Format_info_ogr ogr
OGR info.
Definition: dig_structs.h:708
Definition: gis.h:528
Vector map info.
Definition: dig_structs.h:1243
char * mapset
Mapset name.
Definition: dig_structs.h:1320
int temporary
Temporary map flag.
Definition: dig_structs.h:1260
struct gvfile dig_fp
GV file pointer (native format only)
Definition: dig_structs.h:1395
struct dig_head head
Header info.
Definition: dig_structs.h:1388
int support_updated
Support files were updated.
Definition: dig_structs.h:1311
char * gisdbase
GISDBASE path.
Definition: dig_structs.h:1331
int level
Topology level.
Definition: dig_structs.h:1297
char * name
Map name (for 4.0)
Definition: dig_structs.h:1316
FILE * hist_fp
History file.
Definition: dig_structs.h:1378
int open
Open indicator.
Definition: dig_structs.h:1280
char * location
Location name.
Definition: dig_structs.h:1327
int head_only
Open only header.
Definition: dig_structs.h:1304
int format
Map format (native, ogr, postgis)
Definition: dig_structs.h:1255
struct dblinks * dblnk
Array of DB links.
Definition: dig_structs.h:1265
struct Format_info fInfo
Format info for non-native formats.
Definition: dig_structs.h:1400
struct Plus_head plus
Plus info (topology, version, ...)
Definition: dig_structs.h:1270
Basic topology-related info.
Definition: dig_structs.h:769
int do_uplist
Indicates if the list of updated features is maintained.
Definition: dig_structs.h:1161
struct gvfile spidx_fp
Spatial index file pointer.
Definition: dig_structs.h:1054
int Spidx_built
Spatial index built?
Definition: dig_structs.h:1037
int with_z
2D/3D vector data
Definition: dig_structs.h:786
off_t coor_size
Size of coor file.
Definition: dig_structs.h:1145
int Spidx_new
Build new spatial index.
Definition: dig_structs.h:1043
int Spidx_file
Build new spatial index in file.
Definition: dig_structs.h:1049
int spidx_with_z
2D/3D spatial index
Definition: dig_structs.h:793
struct Plus_head::@10 uplist
List of updated lines/nodes.
long coor_mtime
Time of last coor modification.
Definition: dig_structs.h:1149
int mode
Access mode.
Definition: dig_structs.h:845
int built
Highest level of topology currently available.
Definition: dig_structs.h:857
off_t size
Coor file size.
Definition: dig_structs.h:344
int with_z
2D/3D vector data
Definition: dig_structs.h:339
long head_size
Coor header size.
Definition: dig_structs.h:348
Definition: lidar.h:85
File definition.
Definition: dig_structs.h:94
FILE * file
File descriptor.
Definition: dig_structs.h:98
Definition: path.h:15
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
Definition: symbol/read.c:216
int Vect__open_old(struct Map_info *Map, const char *name, const char *mapset, const char *layer, int update, int head_only, int is_tmp)
Open existing vector map for reading (internal use only)
const char * Vect_maptype_info(struct Map_info *Map)
Gets vector map format (as string)
int Vect_open_tmp_new(struct Map_info *Map, const char *name, int with_z)
Create new temporary vector map.
int Vect_open_old(struct Map_info *Map, const char *name, const char *mapset)
Open existing vector map for reading.
int Vect_set_open_level(int level)
Predetermine level at which a vector map will be opened for reading.
int Vect_open_tmp_update(struct Map_info *Map, const char *name, const char *mapset)
Open existing temporary vector map for reading/writing.
char * Vect__get_path(char *path, struct Map_info *Map)
Get map directory name (internal use only)
char * Vect__get_element_path(char *file_path, struct Map_info *Map, const char *element)
Get map element full path (internal use only)
int Vect_open_update_head(struct Map_info *Map, const char *name, const char *mapset)
Open header file of existing vector map for updating (mostly for database link updates)
int Vect_open_old2(struct Map_info *Map, const char *name, const char *mapset, const char *layer)
Open existing vector map for reading.
int Vect_open_old_head2(struct Map_info *Map, const char *name, const char *mapset, const char *layer)
Reads only info about vector map (headers)
int Vect_coor_info(struct Map_info *Map, struct Coor_info *Info)
Update Coor_info structure.
int Vect_open_topo(struct Map_info *Map, int head_only)
Open topology file ('topo')
#define MAX_OPEN_LEVEL
int Vect_open_new(struct Map_info *Map, const char *name, int with_z)
Create new vector map for reading/writing.
int Vect_open_sidx(struct Map_info *Map, int mode)
Open spatial index file ('sidx')
int Vect_open_old_head(struct Map_info *Map, const char *name, const char *mapset)
Reads only info about vector map (headers)
int Vect_maptype(struct Map_info *Map)
Gets vector map format.
int Vect_open_update(struct Map_info *Map, const char *name, const char *mapset)
Open existing vector map for reading/writing.
int Vect_open_tmp_old(struct Map_info *Map, const char *name, const char *mapset)
Open existing temporary vector map for reading.
int Vect_open_update2(struct Map_info *Map, const char *name, const char *mapset, const char *layer)
Open existing vector map for reading/writing.