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