GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-7413740dd8
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  }
576 
577  return level;
578 }
579 
580 /*!
581  \brief Open existing vector map for reading
582 
583  This function is replaced by Vect_open_old2() to handle also direct
584  OGR support.
585 
586  Calls G_fatal_error() on failure.
587 
588  \param[out] Map pointer to Map_info structure
589  \param name name of vector map to open
590  \param mapset mapset name ("" for search path)
591 
592  \return 1 open on level 1 (without topology)
593  \return 2 open on level 2 (with topology)
594  \return -1 on error
595  */
596 int Vect_open_old(struct Map_info *Map, const char *name, const char *mapset)
597 {
598  return Vect__open_old(Map, name, mapset, NULL, FALSE, FALSE, FALSE);
599 }
600 
601 /*!
602  \brief Open existing temporary vector map for reading
603 
604  Temporary vector maps are stored in the current mapset (directory
605  <tt>.tmp/<hostname>/vector</tt>).
606 
607  Calls G_fatal_error() on failure.
608 
609  \todo Create new vector map if doesn't exist.
610 
611  \param[out] Map pointer to Map_info structure
612  \param name name of vector map to open
613  \param mapset mapset name ("" for search path)
614 
615  \return 1 open on level 1 (without topology)
616  \return 2 open on level 2 (with topology)
617  \return -1 on error
618  */
619 int Vect_open_tmp_old(struct Map_info *Map, const char *name,
620  const char *mapset)
621 {
622  return Vect__open_old(Map, name, mapset, NULL, FALSE, FALSE, TRUE);
623 }
624 
625 /*!
626  \brief Open existing vector map for reading
627 
628  Calls G_fatal_error() on failure.
629 
630  \param[out] Map pointer to Map_info structure
631  \param name name of vector map to open (datasource for direct OGR access)
632  \param mapset mapset name ("" for search path, "OGR" for direct OGR access)
633  \param layer layer name (OGR layer for direct OGR access)
634 
635  \return 1 open on level 1 (without topology)
636  \return 2 open on level 2 (with topology)
637  \return -1 on error
638  */
639 int Vect_open_old2(struct Map_info *Map, const char *name, const char *mapset,
640  const char *layer)
641 {
642  return Vect__open_old(Map, name, mapset, layer, FALSE, FALSE, FALSE);
643 }
644 
645 /*!
646  \brief Open existing vector map for reading/writing
647 
648  This function is replaced by Vect_open_update2() to handle also
649  direct OGR support.
650 
651  By default list of updated features is not maintained, see
652  Vect_set_updated() for details.
653 
654  Calls G_fatal_error() on failure.
655 
656  \param[out] Map pointer to Map_info structure
657  \param name name of vector map to update
658  \param mapset mapset name
659 
660  \return 1 open on level 1 (without topology)
661  \return 2 open on level 2 (with topology)
662  \return -1 on error
663  */
664 int Vect_open_update(struct Map_info *Map, const char *name, const char *mapset)
665 {
666  return Vect__open_old(Map, name, mapset, NULL, TRUE, FALSE, FALSE);
667 }
668 
669 /*!
670  \brief Open existing temporary vector map for reading/writing
671 
672  Temporary vector maps are stored in the current mapset (directory
673  <tt>.tmp/<hostname>/vector</tt>).
674 
675  By default list of updated features is not maintained, see
676  Vect_set_updated() for details.
677 
678  Calls G_fatal_error() on failure.
679 
680  \todo Create new vector map if doesn't exist.
681 
682  \param[out] Map pointer to Map_info structure
683  \param name name of vector map to update
684  \param mapset mapset name
685 
686  \return 1 open on level 1 (without topology)
687  \return 2 open on level 2 (with topology)
688  \return -1 on error
689  */
690 int Vect_open_tmp_update(struct Map_info *Map, const char *name,
691  const char *mapset)
692 {
693  return Vect__open_old(Map, name, mapset, NULL, TRUE, FALSE, TRUE);
694 }
695 
696 /*!
697  \brief Open existing vector map for reading/writing
698 
699  By default list of updated features is not maintained, see
700  Vect_set_updated() for details.
701 
702  Calls G_fatal_error() on failure.
703 
704  \param[out] Map pointer to Map_info structure
705  \param name name of vector map to open (datasource for direct OGR access)
706  \param mapset mapset name ("" for search path, "OGR" for direct OGR access)
707  \param layer layer name (OGR layer for direct OGR access)
708 
709  \return 1 open on level 1 (without topology)
710  \return 2 open on level 2 (with topology)
711  \return -1 on error
712  */
713 int Vect_open_update2(struct Map_info *Map, const char *name,
714  const char *mapset, const char *layer)
715 {
716  return Vect__open_old(Map, name, mapset, layer, TRUE, FALSE, FALSE);
717 }
718 
719 /*!
720  \brief Reads only info about vector map (headers)
721 
722  Reads from headers of 'head', 'dbln', 'topo' and 'cidx' file.
723 
724  This function is replaced by Vect_open_old_head2() to handle also
725  direct OGR support.
726 
727  Calls G_fatal_error() on failure.
728 
729  \param[out] Map pointer to Map_info structure
730  \param name name of vector map to read
731  \param mapset mapset name ("" for search path)
732 
733  \return 1 open on level 1 (without topology)
734  \return 2 open on level 2 (with topology)
735  \return -1 on error
736  */
737 int Vect_open_old_head(struct Map_info *Map, const char *name,
738  const char *mapset)
739 {
740  return Vect__open_old(Map, name, mapset, NULL, FALSE, TRUE, FALSE);
741 }
742 
743 /*!
744  \brief Reads only info about vector map (headers)
745 
746  Reads from headers of 'head', 'dbln', 'topo' and 'cidx' file.
747 
748  Calls G_fatal_error() on failure.
749 
750  \param[out] Map pointer to Map_info structure
751  \param name name of vector map to read (dsn for OGR)
752  \param mapset mapset name ("" for search path)
753  \param layer layer name (OGR format)
754 
755  \param[out] Map pointer to Map_info structure
756  \param name name of vector map to open (datasource for direct OGR access)
757  \param mapset mapset name ("" for search path, "OGR" for direct OGR access)
758  \param layer layer name (OGR layer for direct OGR access)
759 
760  \return 1 open on level 1 (without topology)
761  \return 2 open on level 2 (with topology)
762  \return -1 on error
763  */
764 int Vect_open_old_head2(struct Map_info *Map, const char *name,
765  const char *mapset, const char *layer)
766 {
767  return Vect__open_old(Map, name, mapset, layer, FALSE, TRUE, FALSE);
768 }
769 
770 /*! \brief Open header file of existing vector map for updating
771  (mostly for database link updates)
772 
773  \param[out] Map pointer to Map_info structure
774  \param name name of vector map to update
775  \param mapset mapset name
776 
777  \return 1 open on level 1 (without topology)
778  \return 2 open on level 2 (with topology)
779  \return -1 on error
780  */
781 int Vect_open_update_head(struct Map_info *Map, const char *name,
782  const char *mapset)
783 {
784  return Vect__open_old(Map, name, mapset, NULL, TRUE, TRUE, FALSE);
785 }
786 
787 int open_new(struct Map_info *Map, const char *name, int with_z, int is_tmp)
788 {
789  int ret;
790  char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
791 
792  G_debug(1, "Vect_open_new(): name = %s with_z = %d is_tmp = %d", name,
793  with_z, is_tmp);
794 
795  /* zero Map_info structure */
796  G_zero(Map, sizeof(struct Map_info));
797 
798  /* init header info */
799  Vect__init_head(Map);
800 
801  /* check for fully-qualified map name */
802  if (G_name_is_fully_qualified(name, xname, xmapset)) {
803  if (strcmp(xmapset, G_mapset()) != 0) {
804  G_warning(_("Unable to create vector map: <%s> is not in the "
805  "current mapset (%s)"),
806  name, G_mapset());
807  return -1;
808  }
809  name = xname;
810  }
811 
812  /* check for [A-Za-z][A-Za-z0-9_]* in name */
813  if (Vect_legal_filename(name) < 0) {
815  _("Unable to create vector map: <%s> is not SQL compliant"), name);
816  return -1;
817  }
818 
819  /* store basic info */
820  Map->name = G_store(name);
821  Map->mapset = G_store(G_mapset());
822  Map->location = G_store(G_location());
823  Map->gisdbase = G_store(G_gisdbase());
824  Map->temporary = is_tmp;
825 
826  /* determine output format */
827  Map->format = map_format(Map);
828 
829  if (Map->format != GV_FORMAT_OGR_DIRECT &&
830  getenv("GRASS_VECTOR_PGFILE") ==
831  NULL) { /* GRASS_VECTOR_PGFILE defined by v.out.postgis */
832  char *env;
833  char path[GPATH_MAX];
834 
835  G_debug(2, " using non-direct format");
836 
837  /* check if map already exists
838  temporary maps are automatically overwritten
839  */
840  if (Map->temporary) {
841  if (-1 == Vect__delete(name, Map->temporary)) {
842  G_warning(_("Unable to delete vector map <%s>"), name);
843  return -1;
844  }
845  }
846 
847  env = getenv("GRASS_VECTOR_TEMPORARY");
848  if (!Map->temporary || (env && strcmp(env, "move") == 0)) {
849  if (G_find_vector2(name, G_mapset()) != NULL) {
850  G_warning(
851  _("Vector map <%s> already exists and will be overwritten"),
852  name);
853 
854  ret = Vect_delete(name);
855  if (ret == -1) {
856  G_warning(_("Unable to delete vector map <%s>"), name);
857  return -1;
858  }
859  }
860  }
861 
862  /* write header file
863 
864  note: header & history file is also written for external
865  formats since vector library create links automatically
866  when closing the map
867  */
868  Map->head.size = 0;
869  Map->head.head_size = GV_COOR_HEAD_SIZE + 4;
870  Vect__write_head(Map);
871 
872  /* create history file */
873  Vect__get_path(path, Map);
875  if (Map->hist_fp == NULL) {
876  G_warning(_("Unable to open history file of vector map <%s>"),
877  name);
878  return -1;
879  }
880  }
881 
882  /* set 2D/3D */
883  Map->plus.spidx_with_z = Map->plus.with_z = Map->head.with_z =
884  (with_z != 0);
885 
886  Map->level = LEVEL_1;
887 
888  if ((*Open_new_array[Map->format][1])(Map, name, with_z) < 0) {
889  if (getenv("GRASS_VECTOR_PGFILE") ==
890  NULL) /* GRASS_VECTOR_PGFILE defined by v.out.postgis */
891  Vect_delete(name); /* clean up */
892  return -1;
893  }
894 
895  Open_level = 0;
896 
897  /* initialize topo */
898  Map->plus.Spidx_file = 0;
899  dig_init_plus(&(Map->plus));
900 
901  /* open new spatial index */
902  if (Vect_open_sidx(Map, 2) < 0)
904  _("Unable to open spatial index file for vector map <%s>"),
905  Vect_get_full_name(Map));
906 
907  Map->open = VECT_OPEN_CODE;
908  Map->head_only = FALSE;
909  Map->support_updated = FALSE;
910  Map->plus.built = GV_BUILD_NONE;
911  Map->mode = GV_MODE_RW;
912  Map->plus.uplist.do_uplist = FALSE;
913 
914  Vect_set_proj(Map, G_projection());
915  Vect_set_zone(Map, G_zone());
916 
918 
919  if (Map->fInfo.ogr.driver_name) {
920  G_verbose_message(_("Using OGR/%s format"), Map->fInfo.ogr.driver_name);
921  }
922  else if (Map->fInfo.pg.conninfo) {
923  if (Map->fInfo.pg.toposchema_name)
924  G_verbose_message(_("Using PostGIS Topology format"));
925  else
926  G_verbose_message(_("Using PostGIS format"));
927  }
928  else {
929  G_verbose_message(_("Using native format"));
930  }
931 
932  return 1;
933 }
934 
935 /*!
936  \brief Create new vector map for reading/writing
937 
938  By default list of updated features is not maintained, see
939  Vect_set_updated() for details.
940 
941  By default map format is native (GV_FORMAT_NATIVE). If OGR file is
942  found in the current mapset then the map (ie. OGR layer) is created
943  in given OGR datasource (GV_FORMAT_OGR). Similarly if PG file exists
944  then the map (ie. PostGIS table) is created using PostGIS interface
945  (GV_FORMAT_POSTGIS). The format of map is stored in Map->format.
946 
947  \param[out] Map pointer to Map_info structure
948  \param name name of vector map to be created
949  \param with_z WITH_Z for 3D vector data otherwise WITHOUT_Z
950 
951  \return 1 on success
952  \return -1 on error
953  */
954 int Vect_open_new(struct Map_info *Map, const char *name, int with_z)
955 {
956  int is_tmp;
957 
958  is_tmp = getenv("GRASS_VECTOR_TEMPORARY") ? TEMPORARY_MAP_ENV
959  : TEMPORARY_MAP_DISABLED;
960  G_debug(1, "Vect_open_new(): is_tmp = %d", is_tmp);
961 
962  return open_new(Map, name, with_z, is_tmp);
963 }
964 
965 /*!
966  \brief Create new temporary vector map
967 
968  Temporary vector maps are stored in the current mapset (directory
969  <tt>.tmp/<hostname>/vector</tt>). If the map already exists, it is
970  overwritten.
971 
972  Temporary vector maps are automatically deleted when closing the map
973  (see Vect_close() for details).
974 
975  If <em>name</em> is not given (is NULL), then the name is determined
976  by process id (<tt>tmp_<pid></tt>).
977 
978  \param[out] Map pointer to output Map_info struct
979  \param name name for new vector map (or NULL)
980  \param with_z WITH_Z for 3D vector data otherwise WITHOUT_Z
981 
982  \return 1 on success
983  \return -1 on error
984  */
985 int Vect_open_tmp_new(struct Map_info *Map, const char *name, int with_z)
986 {
987  char tmp_name[GNAME_MAX];
988 
989  if (!name) {
990  sprintf(tmp_name, "tmp_%d", getpid());
991  }
992  else {
993  sprintf(tmp_name, "%s", name);
994  }
995  G_debug(1, "Vect_open_tmp_new(): name = '%s' with_z = %d", name, with_z);
996 
997  return open_new(Map, tmp_name, with_z, TEMPORARY_MAP); /* temporary map */
998 }
999 
1000 /*!
1001  \brief Update Coor_info structure
1002 
1003  \param Map pointer to Map_info structure
1004  \param[out] Info pointer to Coor_info structure
1005 
1006  \return 1 on success
1007  \return 0 on error
1008  */
1009 int Vect_coor_info(struct Map_info *Map, struct Coor_info *Info)
1010 {
1011  char file_path[GPATH_MAX];
1012  struct stat stat_buf;
1013 
1014  switch (Map->format) {
1015  case GV_FORMAT_NATIVE:
1016  Vect__get_element_path(file_path, Map, GV_COOR_ELEMENT);
1017  G_debug(1, "get coor info: %s", file_path);
1018  if (0 != stat(file_path, &stat_buf)) {
1019  G_warning(_("Unable to stat file <%s>"), file_path);
1020  Info->size = -1L;
1021  Info->mtime = -1L;
1022  }
1023  else {
1024  Info->size = (off_t)stat_buf.st_size; /* file size */
1025  Info->mtime = (long)stat_buf.st_mtime; /* last modified time */
1026  }
1027 
1028  /* stat does not give correct size on MINGW
1029  * if the file is opened */
1030 #ifdef __MINGW32__
1031  if (Map->open == VECT_OPEN_CODE) {
1032  dig_fseek(&(Map->dig_fp), 0L, SEEK_END);
1033  G_debug(2, "dig_ftell = %d", dig_ftell(&(Map->dig_fp)));
1034  Info->size = dig_ftell(&(Map->dig_fp));
1035  }
1036 #endif
1037  break;
1038  case GV_FORMAT_OGR:
1039  case GV_FORMAT_OGR_DIRECT:
1040  case GV_FORMAT_POSTGIS:
1041  Info->size = 0L;
1042  Info->mtime = 0L;
1043  break;
1044  }
1045  G_debug(1, "Vect_coor_info(): Info->size = %lu, Info->mtime = %ld",
1046  (unsigned long)Info->size, Info->mtime);
1047 
1048  return 1;
1049 }
1050 
1051 /*!
1052  \brief Gets vector map format (as string)
1053 
1054  Note: string is allocated by G_store(). Free allocated memory with
1055  G_free().
1056 
1057  Currently are implemented:
1058  - Native format (native)
1059  - OGR format (ogr)
1060  - PostGIS format (postgis)
1061 
1062  \param Map pointer to Map_info structure
1063 
1064  \return maptype string on success (allocated by G_store())
1065  \return error message on error
1066  */
1067 const char *Vect_maptype_info(struct Map_info *Map)
1068 {
1069  char maptype[1000];
1070 
1071  switch (Map->format) {
1072  case GV_FORMAT_NATIVE:
1073  sprintf(maptype, "native");
1074  break;
1075  case GV_FORMAT_OGR:
1076  case GV_FORMAT_OGR_DIRECT:
1077  sprintf(maptype, "OGR");
1078  break;
1079  case GV_FORMAT_POSTGIS:
1080  sprintf(maptype, "PostGIS");
1081  break;
1082  default:
1083  sprintf(maptype, _("unknown %d (update Vect_maptype_info)"),
1084  Map->format);
1085  }
1086 
1087  return G_store(maptype);
1088 }
1089 
1090 /*!
1091  \brief Gets vector map format
1092 
1093  Currently are implemented:
1094  - Native format (GV_FORMAT_NATIVE)
1095  - OGR format linked via v.external (GV_FORMAT_OGR)
1096  - OGR format (GV_FORMAT_OGR_DIRECT)
1097  - PostGIS format (GV_FORMAT_POSTGIS)
1098 
1099  \param Map pointer to Map_info structure
1100 
1101  \return map format code
1102  */
1103 int Vect_maptype(struct Map_info *Map)
1104 {
1105  if (Map->temporary) {
1106  const struct Format_info *finfo;
1107 
1108  finfo = &(Map->fInfo);
1109  if (finfo->ogr.driver_name) {
1110  return GV_FORMAT_OGR;
1111  }
1112  if (finfo->pg.conninfo) {
1113  return GV_FORMAT_POSTGIS;
1114  }
1115  }
1116 
1117  return Map->format;
1118 }
1119 
1120 /*!
1121  \brief Open topology file ('topo')
1122 
1123  \param[in,out] Map pointer to Map_info structure
1124  \param head_only TRUE to read only header
1125 
1126  \return 0 on success
1127  \return 1 file does not exist
1128  \return -1 on error
1129  */
1130 int Vect_open_topo(struct Map_info *Map, int head_only)
1131 {
1132  int err, ret;
1133  char file_path[GPATH_MAX], path[GPATH_MAX];
1134  struct gvfile fp;
1135  struct Coor_info CInfo;
1136  struct Plus_head *Plus;
1137 
1138  G_debug(1, "Vect_open_topo(): name = %s mapset = %s", Map->name,
1139  Map->mapset);
1140 
1141  Plus = &(Map->plus);
1142 
1143  Vect__get_path(path, Map);
1144  Vect__get_element_path(file_path, Map, GV_TOPO_ELEMENT);
1145  if (access(file_path, F_OK) != 0) { /* does not exist */
1146  return 1;
1147  }
1148 
1149  dig_file_init(&fp);
1151 
1152  if (fp.file == NULL) { /* topo file is not available */
1153  G_debug(1, "Cannot open topo file for vector '%s@%s'.", Map->name,
1154  Map->mapset);
1155  return -1;
1156  }
1157 
1158  /* get coor info */
1159  /* NOTE: coor file not yet opened */
1160  Vect_coor_info(Map, &CInfo);
1161 
1162  /* load head */
1163  if (dig_Rd_Plus_head(&fp, Plus) == -1)
1164  return -1;
1165 
1166  G_debug(1, "Topo head: coor size = %lu, coor mtime = %ld",
1167  (unsigned long)Plus->coor_size, Plus->coor_mtime);
1168 
1169  /* do checks */
1170  err = 0;
1171  if (CInfo.size != Plus->coor_size) {
1172  G_warning(
1173  _("Size of 'coor' file differs from value saved in topology file"));
1174  err = 1;
1175  }
1176  /* Do not check mtime because mtime is changed by copy */
1177  /*
1178  if ( CInfo.mtime != Plus->coor_mtime ) {
1179  G_warning ( "Time of last modification for 'coor' file differs from value
1180  saved in topo file.\n"); err = 1;
1181  }
1182  */
1183  if (err) {
1184  G_warning(_("Please rebuild topology for vector map <%s@%s>"),
1185  Map->name, Map->mapset);
1186  return -1;
1187  }
1188 
1189  /* load file to the memory */
1190  /* dig_file_load ( &fp); */
1191 
1192  /* load topo to memory */
1193  ret = dig_load_plus(Plus, &fp, head_only);
1194 
1195  fclose(fp.file);
1196  /* dig_file_free(&fp); */
1197 
1198  return ret == 0 ? -1 : 0;
1199 }
1200 
1201 /*!
1202  \brief Open spatial index file ('sidx')
1203 
1204  \param[in,out] Map pointer to Map_info
1205  \param mode 0 old, 1 update, 2 new
1206 
1207  \return 1 if sidx file is not available
1208  \return 0 on success
1209  \return -1 on error
1210  */
1211 int Vect_open_sidx(struct Map_info *Map, int mode)
1212 {
1213  int err;
1214  struct Coor_info CInfo;
1215  struct Plus_head *Plus;
1216 
1217  G_debug(1, "Vect_open_sidx(): name = %s mapset= %s mode = %s", Map->name,
1218  Map->mapset, mode == 0 ? "old" : (mode == 1 ? "update" : "new"));
1219 
1220  Plus = &(Map->plus);
1221 
1222  if (Plus->Spidx_built) {
1223  G_debug(1, "Spatial index already opened");
1224  return 0;
1225  }
1226 
1227  dig_file_init(&(Plus->spidx_fp));
1228 
1229  if (mode < 2) {
1230  char path[GPATH_MAX], file_path[GPATH_MAX];
1231 
1232  Vect__get_path(path, Map);
1233  Vect__get_element_path(file_path, Map, GV_SIDX_ELEMENT);
1234  if (access(file_path, F_OK) != 0) /* does not exist */
1235  return 1;
1236 
1238 
1239  if (Plus->spidx_fp.file == NULL) { /* sidx file is not available */
1240  G_debug(1, "Cannot open spatial index file for vector '%s@%s'.",
1241  Map->name, Map->mapset);
1242  return -1;
1243  }
1244 
1245  /* get coor info */
1246  /* NOTE: coor file not yet opened */
1247  Vect_coor_info(Map, &CInfo);
1248 
1249  /* initialize spatial index */
1250  Plus->Spidx_new = FALSE;
1251 
1252  if (mode == 0) {
1253  /* free old indices */
1254  dig_spidx_free(Plus);
1255  /* initialize file based indices */
1256  Plus->Spidx_file = 1;
1257  dig_spidx_init(Plus);
1258  }
1259 
1260  /* load head */
1261  if (dig_Rd_spidx_head(&(Plus->spidx_fp), Plus) == -1) {
1262  fclose(Plus->spidx_fp.file);
1263  return -1;
1264  }
1265 
1266  G_debug(1, "Sidx head: coor size = %lu, coor mtime = %ld",
1267  (unsigned long)Plus->coor_size, Plus->coor_mtime);
1268 
1269  /* do checks */
1270  err = 0;
1271  if (CInfo.size != Plus->coor_size) {
1272  G_warning(
1273  _("Size of 'coor' file differs from value saved in sidx file"));
1274  err = 1;
1275  }
1276  /* Do not check mtime because mtime is changed by copy */
1277  /*
1278  if ( CInfo.mtime != Plus->coor_mtime ) {
1279  G_warning ( "Time of last modification for 'coor' file differs from
1280  value saved in topo file.\n"); err = 1;
1281  }
1282  */
1283  if (err) {
1284  G_warning(_("Please rebuild topology for vector map <%s@%s>"),
1285  Map->name, Map->mapset);
1286  fclose(Plus->spidx_fp.file);
1287  return -1;
1288  }
1289  }
1290 
1291  if (mode) {
1292  /* open new spatial index */
1293  Plus->Spidx_new = TRUE;
1294 
1295  /* file based or memory based */
1296  if (getenv("GRASS_VECTOR_LOWMEM")) {
1297  /* free old indices */
1298  dig_spidx_free(Plus);
1299  /* initialize file based indices */
1300  Plus->Spidx_file = 1;
1301  dig_spidx_init(Plus);
1302  }
1303  G_debug(1, "%s based spatial index",
1304  Plus->Spidx_file == 0 ? "Memory" : "File");
1305 
1306  if (mode == 1) {
1307  /* load spatial index for update */
1308  if (dig_Rd_spidx(&(Plus->spidx_fp), Plus) == -1) {
1309  fclose(Plus->spidx_fp.file);
1310  return -1;
1311  }
1312  }
1313  }
1314 
1315  Plus->Spidx_built = TRUE;
1316 
1317  return 0;
1318 }
1319 
1320 /* check for external formats definition */
1321 int map_format(struct Map_info *Map)
1322 {
1323  int format;
1324  char *def_file;
1325 
1326  format = GV_FORMAT_NATIVE;
1327  /* temporary maps can be stored only in native format */
1328  if (Map->temporary || getenv("GRASS_VECTOR_EXTERNAL_IGNORE"))
1329  return format;
1330 
1331  if (G_find_file2("", "OGR", G_mapset())) {
1332  /* OGR */
1333  FILE *fp;
1334  const char *p;
1335 
1336  struct Key_Value *key_val;
1337  struct Format_info_ogr *ogr_info;
1338 
1339  G_debug(2, " using OGR format");
1340  if (getenv("GRASS_VECTOR_EXTERNAL_IMMEDIATE")) {
1341  /* vector features are written directly to OGR layer */
1342  format = GV_FORMAT_OGR;
1343  }
1344  else {
1345  /* vector features are written to the temporary vector map
1346  * in the native format and when closing the map
1347  * transferred to output OGR layer */
1348  format = GV_FORMAT_NATIVE;
1349  Map->temporary = TEMPORARY_MAP;
1350  }
1351  fp = G_fopen_old("", "OGR", G_mapset());
1352  if (!fp) {
1353  G_fatal_error(_("Unable to open OGR file"));
1354  }
1355  key_val = G_fread_key_value(fp);
1356  fclose(fp);
1357 
1358  ogr_info = &(Map->fInfo.ogr);
1359  /* format */
1360  p = G_find_key_value("format", key_val);
1361  if (p)
1362  ogr_info->driver_name = G_store(p);
1363  /* dsn */
1364  p = G_find_key_value("dsn", key_val);
1365  if (p)
1366  ogr_info->dsn = G_store(p);
1367  /* options */
1368  p = G_find_key_value("options", key_val);
1369  if (p)
1370  ogr_info->layer_options = G_tokenize(p, ",");
1371 
1372  ogr_info->layer_name = G_store(Map->name);
1373  }
1374 
1375  def_file = getenv("GRASS_VECTOR_PGFILE"); /* GRASS_VECTOR_PGFILE defined by
1376  v.out.postgis */
1377  if (G_find_file2("", def_file ? def_file : "PG", G_mapset())) {
1378  /* PostGIS */
1379  if (Map->fInfo.ogr.driver_name) {
1380  G_warning(_("OGR output also detected, using OGR"));
1381  }
1382  else {
1383  FILE *fp;
1384  const char *p;
1385 
1386  struct Key_Value *key_val;
1387  struct Format_info_pg *pg_info;
1388 
1389  G_debug(2, " using PostGIS format");
1390  fp = G_fopen_old("", def_file ? def_file : "PG", G_mapset());
1391  if (!fp) {
1392  G_fatal_error(_("Unable to open PG file"));
1393  }
1394  key_val = G_fread_key_value(fp);
1395  fclose(fp);
1396 
1397  pg_info = &(Map->fInfo.pg);
1398  /* conninfo */
1399  p = G_find_key_value("conninfo", key_val);
1400  if (p) {
1401  pg_info->conninfo = G_store(p);
1402  G_debug(1, "PG: conninfo = '%s'", pg_info->conninfo);
1403  }
1404 
1405  /* schema (default: public) */
1406  p = G_find_key_value("schema", key_val);
1407  if (p)
1408  pg_info->schema_name = G_store(p);
1409  else
1410  pg_info->schema_name = G_store("public");
1411  G_debug(1, "PG: schema_name = '%s'", pg_info->schema_name);
1412 
1413  /* fid column (default: FID_COLUMN) */
1414  p = G_find_key_value("fid", key_val);
1415  if (p)
1416  pg_info->fid_column = G_store(p);
1417  else
1418 #ifdef HAVE_POSTGRES
1419  pg_info->fid_column = G_store(GV_PG_FID_COLUMN);
1420 #endif
1421  G_debug(1, "PG: fid_column = '%s'", pg_info->fid_column);
1422 
1423  /* geometry column (default: GEOMETRY_COLUMN) */
1424  p = G_find_key_value("geometry_name", key_val);
1425  if (p)
1426  pg_info->geom_column = G_store(p);
1427  else
1428 #ifdef HAVE_POSTGRES
1430 #endif
1431  G_debug(1, "PG: geom_column = '%s'", pg_info->geom_column);
1432 
1433  /* srid (default: 0) */
1434  p = G_find_key_value("srid", key_val);
1435  if (p) {
1436  pg_info->srid = atoi(p);
1437  }
1438  else {
1439  /* not defined by v.external.out, so try if EPSG code
1440  * is defined */
1441  p = G_database_epsg_code();
1442  if (p)
1443  pg_info->srid = atoi(p);
1444  }
1445  G_debug(1, "PG: srid = %d", pg_info->srid);
1446 
1447  /* table name */
1448  Map->fInfo.pg.table_name = G_store(Map->name);
1449 
1450  /* PostGIS topology enabled ? */
1451  p = G_find_key_value("topology", key_val);
1452  if (p && G_strcasecmp(p, "yes") == 0) {
1453  /* define topology name */
1454  p = G_find_key_value("toposchema_name", key_val);
1455  if (p)
1456  pg_info->toposchema_name = G_store(p);
1457  else
1458  G_asprintf(&(pg_info->toposchema_name), "topo_%s",
1459  pg_info->table_name);
1460 
1461  G_debug(1, "PG: topology = yes, schema_name = %s",
1462  pg_info->toposchema_name);
1463  }
1464  G_debug(1, "PG: topology = no");
1465 
1466  if (getenv("GRASS_VECTOR_EXTERNAL_IMMEDIATE")) {
1467  /* vector features are written directly to PostGIS layer */
1468  format = GV_FORMAT_POSTGIS;
1469  }
1470  else {
1471  /* vector features are written to the temporary vector map
1472  * in the native format and when closing the map
1473  * transferred to output PostGIS layer */
1474  format = GV_FORMAT_NATIVE;
1475  Map->temporary = TEMPORARY_MAP;
1476  }
1477  }
1478  }
1479 
1480  G_debug(2, "map_format = %d", format);
1481  return format;
1482 }
1483 
1484 /*!
1485  \brief Get map directory name (internal use only)
1486 
1487  \param file_path path string buffer
1488  \param Map pointer to Map_info struct
1489 
1490  \return buffer containing path
1491  */
1492 char *Vect__get_path(char *path, struct Map_info *Map)
1493 {
1494  if (Map->temporary) {
1495  char path_tmp[GPATH_MAX];
1496 
1497  G__temp_element(path_tmp, TRUE);
1498  sprintf(path, "%s/%s/%s", path_tmp, GV_DIRECTORY, Map->name);
1499  }
1500  else {
1501  sprintf(path, "%s/%s", GV_DIRECTORY, Map->name);
1502  }
1503 
1504  return path;
1505 }
1506 
1507 /*!
1508  \brief Get map element full path (internal use only)
1509 
1510  Allocate string should be freed by G_free().
1511 
1512  \param Map pointer to Map_info struct
1513  \param element element name, eg. GV_TOPO_ELEMENT
1514 
1515  \return allocated buffer containing path
1516  */
1517 char *Vect__get_element_path(char *file_path, struct Map_info *Map,
1518  const char *element)
1519 {
1520  char path[GPATH_MAX];
1521 
1522  Vect__get_path(path, Map);
1523  if (Map->temporary)
1524  G_file_name_tmp(file_path, path, element, Map->mapset);
1525  else
1526  G_file_name(file_path, path, element, Map->mapset);
1527 
1528  return file_path;
1529 }
#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:32
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:493
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:235
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:525
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.