GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-602118adcc
vector/Vlib/copy.c
Go to the documentation of this file.
1 /*!
2  \file lib/vector/Vlib/copy.c
3 
4  \brief Vector library - Copy vector features and attribute tables linked to
5  the map
6 
7  Higher level functions for reading/writing/manipulating vectors.
8 
9  (C) 2001-2009, 2012-2013 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 by Martin Landa <landa.martin gmail.com>
17  (OGR/PostGIS topology support)
18  */
19 
20 #include <grass/vector.h>
21 #include <grass/glocale.h>
22 
23 #include "local_proto.h"
24 
25 /*!
26  \brief Copy topological elements
27 
28  - simple features (None)
29  - native topo (GRASS)
30  - PostGIS Topo
31  */
32 #define TOPO_NONE -1
33 #define TOPO_NATIVE 1
34 #define TOPO_POSTGIS 2
35 
36 #ifdef HAVE_POSTGRES
37 #include "pg_local_proto.h"
38 #define NOPG_UNUSED
39 #else
40 #define NOPG_UNUSED UNUSED
41 #endif
42 
43 static int copy_lines_1(struct Map_info *, int, struct Map_info *);
44 static int copy_lines_2(struct Map_info *, int, int, struct Map_info *);
45 
46 #if 0
47 static int copy_nodes(struct Map_info *, struct Map_info *);
48 #endif
49 static int copy_line_nodes(struct Map_info *, int, int, struct line_pnts *,
50  struct Map_info *);
51 static int is_isle(struct Map_info *, int);
52 
53 /*!
54  \brief Copy all alive vector features from input vector map to
55  output vector map
56 
57  \param In input vector map
58  \param[out] Out output vector map
59 
60  \return 0 on success
61  \return 1 on error
62  */
63 int Vect_copy_map_lines(struct Map_info *In, struct Map_info *Out)
64 {
65  return Vect_copy_map_lines_field(In, -1, Out);
66 }
67 
68 /*!
69  \brief Copy all alive vector features from given layer from input
70  vector map to output vector map
71 
72  Note: Try to copy on level 2 otherwise level 1 is used.
73 
74  \param In input vector map
75  \param field layer number (-1 for all layers)
76  \param[out] Out output vector map
77 
78  \return 0 on success
79  \return 1 on error
80  */
81 int Vect_copy_map_lines_field(struct Map_info *In, int field,
82  struct Map_info *Out)
83 {
84  int ret, format, topo;
85  const char *geometry_type = NULL;
86  const char *map_name = NULL;
87 
88  if (Vect_level(In) < 1)
90  _("Unable to copy features. Input vector map <%s> is not open"),
91  Vect_get_full_name(In));
92 
93  format = Out->format; /* do not use Vect_maptype(), we need native
94  format for temporary maps here */
95  topo = TOPO_NONE;
96  if (format == GV_FORMAT_NATIVE) {
97  topo = TOPO_NATIVE;
98  }
99  else if (format == GV_FORMAT_POSTGIS && Out->fInfo.pg.toposchema_name) {
100  int type;
101 
102  topo = TOPO_POSTGIS;
103 
104  /* get type of first feature from input vector map */
105  Vect_rewind(In);
107  type = Vect_read_next_line(In, NULL, NULL);
108 
109  /* create feature table with given feature type */
110  if (0 > Vect_write_line(Out, type, NULL, NULL)) {
111  G_warning(_("Unable to create PostGIS layer <%s>"),
113  return 1;
114  }
115  }
116 
117  /* Note: sometimes is important to copy on level 2 (pseudotopo
118  centroids) and sometimes on level 1 if build take too long time
119  */
120  ret = 0;
121  if (Vect_level(In) >= 2) {
122  /* -> copy features on level 2 */
123 #if 0
124  if (topo == TOPO_POSTGIS) {
125  /* PostGIS topology - copy also nodes */
126  copy_nodes(In, Out);
127  }
128 #endif
129  /* copy features */
130  ret += copy_lines_2(In, field, topo, Out);
131 
132  if (topo == TOPO_NONE) {
133  /* check output feature type, centroids can be exported as
134  * points; boundaries as linestrings */
135  geometry_type = Vect_get_finfo_geometry_type(Out);
136  if (geometry_type && strcmp(geometry_type, "polygon") == 0) {
137  /* copy areas - external formats and simple features access only
138  */
139  ret += Vect__copy_areas(In, field, Out);
140  }
141  G_free((void *)geometry_type);
142  }
143  }
144  else {
145  /* -> copy features on level 1 */
146  if (topo == TOPO_NONE) {
147  map_name = Vect_get_full_name(In);
148  G_warning(_("Vector map <%s> not open on topological level. "
149  "Areas will be skipped!"),
150  map_name);
151  G_free((void *)map_name);
152  }
153 
154  ret += copy_lines_1(In, field, Out);
155  }
156  return ret > 0 ? 1 : 0;
157 }
158 
159 /*!
160  \brief Copy vector features on level 1
161 
162  \param In input vector map
163  \param field layer number (-1 for all layers)
164  \param Out output vector map
165 
166  \return 0 on success
167  \return 1 on error
168  */
169 int copy_lines_1(struct Map_info *In, int field, struct Map_info *Out)
170 {
171  int ret, type;
172  const char *map_name = NULL;
173 
174  struct line_pnts *Points;
175  struct line_cats *Cats;
176 
177  Points = Vect_new_line_struct();
178  Cats = Vect_new_cats_struct();
179 
180  ret = 0;
181 
182  Vect_rewind(In);
183  while (TRUE) {
184  type = Vect_read_next_line(In, Points, Cats);
185  if (type == -1) {
186  map_name = Vect_get_full_name(In);
187  G_warning(_("Unable to read vector map <%s>"), map_name);
188  G_free((void *)map_name);
189  ret = 1;
190  break;
191  }
192  else if (type == -2) { /* EOF */
193  break; /* free allocated space and return */
194  }
195  else if (type == 0) { /* dead line */
196  continue;
197  }
198 
199  /* don't skip boundaries if field != -1 */
200  if (field != -1 && !(type & GV_BOUNDARY) &&
201  Vect_cat_get(Cats, field, NULL) == 0)
202  continue; /* different layer */
203 
204  Vect_write_line(Out, type, Points, Cats);
205  }
206  Vect_destroy_line_struct(Points);
208 
209  return ret;
210 }
211 
212 /*!
213  \brief Copy vector features on level 2
214 
215  \param In input vector map
216  \param field layer number (-1 for all layers)
217  \param topo topo access (none, native, postgis)
218  \param Out output vector map
219 
220  \return 0 on success
221  \return 1 on error
222  */
223 int copy_lines_2(struct Map_info *In, int field, int topo, struct Map_info *Out)
224 {
225  int i, type, nlines, nskipped;
226  int ret, left, rite, centroid, with_z;
227 
228  struct line_pnts *Points, *CPoints, *NPoints;
229  struct line_cats *Cats, *CCats;
230 
231  const char *ftype = NULL;
232  const char *map_name = NULL;
233 
234  Points = Vect_new_line_struct();
235  CPoints = Vect_new_line_struct();
236  NPoints = Vect_new_line_struct();
237  Cats = Vect_new_cats_struct();
238  CCats = Vect_new_cats_struct();
239 
240  with_z = Vect_is_3d(In);
241 
242  ret = 0;
243  nlines = Vect_get_num_lines(In);
244  if (topo == TOPO_NONE) {
245  ftype = Vect_get_finfo_geometry_type(Out);
246  G_debug(2, "feature type: %s", ftype ? ftype : "?");
247  if (!ftype)
248  G_message(_("Copying features..."));
249  else
250  G_message(_("Copying features (%s)..."), ftype);
251  }
252  else
253  G_message(_("Copying features..."));
254 
255  Vect_append_point(NPoints, 0., 0., 0.);
256  nskipped = 0;
257  for (i = 1; i <= nlines; i++) {
258  if (!Vect_line_alive(In, i))
259  continue;
260 
261  G_percent(i, nlines, 2);
262  type = Vect_read_line(In, Points, Cats, i);
263  if (type == -1) {
264  map_name = Vect_get_full_name(In);
265  G_warning(_("Unable to read vector map <%s>"), map_name);
266  G_free((void *)map_name);
267  ret = 1;
268  break; /* free allocated space and return */
269  }
270  if (type == 0)
271  continue; /* dead line */
272  if (In->constraint.type_flag) {
273  /* skip feature by type */
274  if (!(type & In->constraint.type))
275  continue;
276  }
277 
278  if (topo == TOPO_NONE) {
279  /* OGR/PostGIS layers (simple features) */
280  int skip = FALSE;
281 
282  if (type == GV_BOUNDARY)
283  /* boundaries are written as linestrings when output
284  * feature type is defined as 'linestring', otherwise
285  * they are skipped */
286  if (ftype && strcmp(ftype, "linestring") != 0)
287  skip = TRUE;
288 
289  /* centroids are stored in topo polygon defined by areas
290  (topo required) */
291  if (type == GV_CENTROID) {
292  /* centroids are written as points when output feature
293  * type is defined as 'point', otherwise they are
294  * skipped */
295  if (ftype && strcmp(ftype, "point") != 0)
296  skip = TRUE;
297  }
298 
299  if (skip)
300  continue;
301  }
302 
303  /* don't skips boundaries if field != -1 */
304  if (field != -1) {
305  if (type & GV_BOUNDARY) {
306  if (Vect_cat_get(Cats, field, NULL) == 0) {
307  int skip_bndry = TRUE;
308 
309  Vect_get_line_areas(In, i, &left, &rite);
310  if (left < 0)
311  left = Vect_get_isle_area(In, abs(left));
312  if (left > 0) {
313  if ((centroid = Vect_get_area_centroid(In, left)) > 0) {
314  Vect_read_line(In, CPoints, CCats, centroid);
315  if (Vect_cat_get(CCats, field, NULL) != 0)
316  skip_bndry = FALSE;
317  }
318  }
319  if (skip_bndry) {
320  if (rite < 0)
321  rite = Vect_get_isle_area(In, abs(rite));
322  if (rite > 0) {
323  if ((centroid = Vect_get_area_centroid(In, rite)) >
324  0) {
325  Vect_read_line(In, CPoints, CCats, centroid);
326  if (Vect_cat_get(CCats, field, NULL) != 0)
327  skip_bndry = FALSE;
328  }
329  }
330  }
331  if (skip_bndry)
332  continue;
333  }
334  }
335  else if (Vect_cat_get(Cats, field, NULL) == 0) {
336  nskipped++;
337  continue; /* different layer */
338  }
339  }
340 
341  /* copy also nodes connected to the line (PostGIS Topology
342  * mode only) */
343  if (topo == TOPO_POSTGIS && (type & GV_LINES)) {
344  int n1, n2;
345 
346  struct P_line *Line;
347  struct Format_info_offset *offset;
348 
349  offset = &(Out->fInfo.pg.offset);
350 
351  n1 = n2 = -1;
352  Line = In->plus.Line[i];
353  if (Line) {
354  if (type == GV_LINE) {
355  struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
356 
357  n1 = topo->N1;
358  n2 = topo->N2;
359  }
360  else if (type == GV_BOUNDARY) {
361  struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
362 
363  n1 = topo->N1;
364  n2 = topo->N2;
365  }
366  }
367 
368  if (n1 > 0 &&
369  (n1 > offset->array_num || offset->array[n1 - 1] == 0))
370  copy_line_nodes(In, n1, with_z, NPoints, Out);
371  if (n2 > 0 &&
372  (n2 > offset->array_num || offset->array[n2 - 1] == 0))
373  copy_line_nodes(In, n2, with_z, NPoints, Out);
374  }
375 
376  if (-1 == Vect_write_line(Out, type, Points, Cats)) {
377  G_warning(_("Writing new feature failed"));
378  ret = 1;
379  goto free_exit;
380  }
381  }
382 
383  if (nskipped > 0)
385  _("%d features without category or from different layer skipped"),
386  nskipped);
387 free_exit:
388  Vect_destroy_line_struct(Points);
389  Vect_destroy_line_struct(CPoints);
390  Vect_destroy_line_struct(NPoints);
393  G_free((void *)ftype);
394 
395  return ret;
396 }
397 
398 #if 0
399 /*!
400  \brief Copy nodes as points (PostGIS Topology only)
401 
402  \param In input vector map
403  \param Out output vector map
404 
405  \return 0 on success
406  \return 1 on error
407  */
408 int copy_nodes(struct Map_info *In, struct Map_info *Out)
409 {
410  int nnodes, node, with_z;
411 
412  struct line_pnts *Points;
413 
414  Points = Vect_new_line_struct();
415 
416  with_z = Vect_is_3d(In);
417 
418  nnodes = Vect_get_num_nodes(In);
419  G_message(_("Exporting nodes..."));
420  Vect_append_point(Points, 0., 0., 0.);
421  for (node = 1; node <= nnodes; node++) {
422  G_debug(3, "Exporting GRASS node %d", node);
423 
424  G_percent(node, nnodes, 5);
425  copy_line_nodes(In, node, with_z, Points, Out);
426  }
427 
428  Vect_destroy_line_struct(Points);
429 
430  return 0;
431 }
432 #endif
433 
434 int copy_line_nodes(struct Map_info *In, int node, int with_z,
435  struct line_pnts *Points, struct Map_info *Out NOPG_UNUSED)
436 {
437  double x, y, z;
438 
439  Vect_get_node_coor(In, node, &x, &y, &z);
440  Points->x[0] = x;
441  Points->y[0] = y;
442  if (with_z)
443  Points->z[0] = z;
444 
445 #ifdef HAVE_POSTGRES
446  if (-1 == V2__write_node_pg(Out, Points)) {
447  G_warning(_("Writing node %d failed"), node);
448  return 1;
449  }
450 #else
451  G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
452  return 1;
453 #endif
454 
455  return 0;
456 }
457 
458 /*!
459  \brief Check if area is part of an isle
460 
461  Check for areas that are part of isles which in turn are inside
462  another area.
463 
464  \param Map pointer to Map_info struct
465  \param area area id
466 
467  \return TRUE if area forms an isle otherwise FALSE
468  */
469 int is_isle(struct Map_info *Map, int area)
470 {
471  int i, line, left, right, isle, is_isle;
472 
473  struct ilist *List;
474 
475  List = Vect_new_list();
476  Vect_get_area_boundaries(Map, area, List);
477 
478  is_isle = FALSE;
479  /* do we need to check all boundaries ? no */
480  for (i = 0; i < List->n_values && !is_isle; i++) {
481  line = List->value[i];
482  if (1 != Vect_get_line_areas(Map, abs(line), &left, &right))
483  continue;
484 
485  isle = line > 0 ? left : right;
486 
487  if (isle < 0 && Vect_get_isle_area(Map, abs(isle)) > 0) {
488  is_isle = TRUE;
489  break;
490  }
491  }
492 
493  G_debug(3, "is_isle(): area %d skip? -> %s", area, is_isle ? "yes" : "no");
494  Vect_destroy_list(List);
495 
496  return is_isle;
497 }
498 
499 /*!
500  \brief Copy areas as polygons (OGR/PostGIS simple features access only)
501 
502  \param In input vector map
503  \param field layer number (-1 for all layers)
504  \param Out output vector map
505 
506  \return 0 on success
507  \return 1 on error
508  */
509 int Vect__copy_areas(struct Map_info *In, int field, struct Map_info *Out)
510 {
511  int i, area, nareas, cat, isle, nisles, nparts_alloc, nskipped;
512  int ret = 0;
513  struct line_pnts **Points;
514  struct line_cats *Cats;
515 
516  /* allocate points & cats */
517  Points = (struct line_pnts **)G_malloc(sizeof(struct line_pnts *));
518  Points[0] = Vect_new_line_struct();
519  nparts_alloc = 1;
520  Cats = Vect_new_cats_struct();
521 
522  /* copy areas */
523  nskipped = 0;
524  nareas = Vect_get_num_areas(In);
525  if (nareas > 0)
526  G_message(_("Exporting areas..."));
527  for (area = 1; area <= nareas; area++) {
528  G_debug(2, "area = %d", area);
529  G_percent(area, nareas, 3);
530 
531  /* get category */
532  Vect_reset_cats(Cats);
533  if (field > 0) {
534  cat = Vect_get_area_cat(In, area, field);
535  /* skip area without category in given layer
536  if (cat == -1) {
537  nskipped++;
538  continue;
539  }
540  */
541 
542  if (cat > 0)
543  Vect_cat_set(Cats, field, cat);
544  }
545 
546  /* skip isles */
547  if (Vect_get_area_centroid(In, area) == 0) {
548  /* no centroid - check if area forms an isle */
549  /* this check does not make sense because the area is also
550  * not exported if it is part of an isle inside another
551  * area: the isle gets exported as an inner ring
552  if (!is_isle(In, area))
553  G_warning(_("No centroid defined for area %d. "
554  "Area not exported."),
555  area);
556  */
557  G_debug(3, "Area %d: is_isle() -> %d", area, is_isle(In, area));
558  continue;
559  }
560 
561  /* get outer ring (area) */
562  Vect_get_area_points(In, area, Points[0]);
563 
564  /* get inner rings (isles) */
565  nisles = Vect_get_area_num_isles(In, area);
566  if (nisles + 1 > nparts_alloc) {
567  /* reallocate space for isles */
568  Points = (struct line_pnts **)G_realloc(
569  Points, (nisles + 1) * sizeof(struct line_pnts *));
570  for (i = nparts_alloc; i < nisles + 1; i++)
571  Points[i] = Vect_new_line_struct();
572  nparts_alloc = nisles + 1;
573  }
574  G_debug(3, "\tcat=%d, nisles=%d", cat, nisles);
575  for (i = 0; i < nisles; i++) {
576  isle = Vect_get_area_isle(In, area, i);
577  Vect_get_isle_points(In, isle, Points[i + 1]);
578  }
579 
580  if (In != Out) {
581  if (0 > V2__write_area_sfa(Out, (const struct line_pnts **)Points,
582  nisles + 1, Cats)) {
583  G_warning(_("Writing area %d failed"), area);
584  ret = -1;
585  goto free_exit;
586  }
587  }
588 #ifdef HAVE_POSTGRES
589  else { /* building simple features geometry from topogeometry data */
590  if (0 > V2__update_area_pg(Out, (const struct line_pnts **)Points,
591  nisles + 1, cat)) {
592  G_warning(_("Writing area %d failed"), area);
593  ret = -1;
594  goto free_exit;
595  }
596  }
597 #endif
598  }
599 
600  if (nskipped > 0)
602  _("%d areas without category or from different layer skipped"),
603  nskipped);
604 
605  /* free allocated space for isles */
606 free_exit:
607  for (i = 0; i < nparts_alloc; i++)
608  Vect_destroy_line_struct(Points[i]);
610  G_free(Points);
611 
612  return ret;
613 }
614 
615 /*!
616  \brief Copy attribute tables linked to vector map.
617 
618  Copy all attribute tables linked to the vector map if
619  <em>field</em> is 0, or selected attribute table defined by given
620  field if <em>field</em> > 0.
621 
622  Notice, that if input vector map has no tables defined, it will
623  copy nothing and return 0 (success).
624 
625  \param In input vector map
626  \param[out] Out output vector map
627  \param field layer number (0 for all tables linked to the vector map)
628 
629  \return 0 on success
630  \return -1 on error
631  */
632 int Vect_copy_tables(struct Map_info *In, struct Map_info *Out, int field)
633 {
634  int i, n, type;
635  struct field_info *Fi;
636  const char *map_name = NULL;
637 
638  n = Vect_get_num_dblinks(In);
639 
640  G_debug(2, "Vect_copy_tables(): copying %d tables", n);
641 
642  type = GV_1TABLE;
643  if (field < 1 && n > 1)
644  type = GV_MTABLE;
645 
646  for (i = 0; i < n; i++) {
647  Fi = Vect_get_dblink(In, i);
648  if (Fi == NULL) {
649  G_warning(_("Database connection not defined for layer %d"),
650  In->dblnk->field[i].number);
651  return -1;
652  }
653  if (field > 0 && Fi->number != field) {
655  continue;
656  }
657 
658  if (Vect_copy_table(In, Out, Fi->number, Fi->number, Fi->name, type) !=
659  0) {
660  map_name = Vect_get_full_name(In);
661  G_warning(
662  _("Unable to copy table <%s> for layer %d from <%s> to <%s>"),
663  Fi->table, Fi->number, map_name, Vect_get_name(Out));
664  G_free((void *)map_name);
666  return -1;
667  }
669  }
670  return 0;
671 }
672 
673 /*!
674  \brief Copy attribute table linked to vector map based on type.
675 
676  \param In input vector map
677  \param[out] Out output vector map
678  \param field_in input layer number
679  \param field_out output layer number
680  \param field_name layer name (can be NULL)
681  \param type how many tables are linked to map: GV_1TABLE / GV_MTABLE
682 
683  \return 0 on success
684  \return -1 on error
685  */
686 int Vect_copy_table(struct Map_info *In, struct Map_info *Out, int field_in,
687  int field_out, const char *field_name, int type)
688 {
689  return Vect_copy_table_by_cats(In, Out, field_in, field_out, field_name,
690  type, NULL, 0);
691 }
692 
693 /*!
694  \brief Copy attribute table linked to vector map based on category
695  list.
696 
697  If <em>cat_list</em> is NULL, then Vect_copy_table() is called.
698 
699  \param In input vector map
700  \param[out] Out output vector map
701  \param field_in input layer number
702  \param field_out output layer number
703  \param field_name layer name (can be NULL)
704  \param type how many tables are linked to map: GV_1TABLE / GV_MTABLE
705  \param cat_list pointer to cat_list struct (can be NULL)
706 
707  \return 0 on success
708  \return -1 on error
709  */
710 int Vect_copy_table_by_cat_list(struct Map_info *In, struct Map_info *Out,
711  int field_in, int field_out,
712  const char *field_name, int type,
713  const struct cat_list *cat_list)
714 {
715  int *cats;
716  int ncats, ret;
717 
718  if (cat_list) {
719  if (Vect_cat_list_to_array(cat_list, &cats, &ncats) != 0)
720  return -1;
721 
722  ret = Vect_copy_table_by_cats(In, Out, field_in, field_out, field_name,
723  type, cats, ncats);
724 
725  G_free(cats);
726  }
727  else {
728  ret = Vect_copy_table(In, Out, field_in, field_out, field_name, type);
729  }
730 
731  return ret;
732 }
733 
734 /*!
735  \brief Copy attribute table linked to vector map based on category
736  numbers.
737 
738  \param In input vector map
739  \param[out] Out output vector map
740  \param field_in input layer number
741  \param field_out output layer number
742  \param field_name layer name (can be NULL)
743  \param type how many tables are linked to map: GV_1TABLE / GV_MTABLE
744  \param cats pointer to array of cats or NULL
745  \param ncats number of cats in 'cats'
746 
747  \return 0 on success
748  \return -1 on error
749  */
750 int Vect_copy_table_by_cats(struct Map_info *In, struct Map_info *Out,
751  int field_in, int field_out, const char *field_name,
752  int type, int *cats, int ncats)
753 {
754  int ret = 0;
755  struct field_info *Fi, *Fin;
756  const char *name, *key;
757  dbDriver *driver = NULL;
758 
759  G_debug(2, "Vect_copy_table_by_cats(): field_in = %d field_out = %d",
760  field_in, field_out);
761 
762  Fi = Vect_get_field(In, field_in);
763  if (Fi == NULL) {
764  G_warning(_("Database connection not defined for layer %d"), field_in);
765  return -1;
766  }
767 
768  if (field_name != NULL)
769  name = field_name;
770  else
771  name = Fi->name;
772 
773  Fin = Vect_default_field_info(Out, field_out, name, type);
774  G_debug(3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", Fi->driver,
775  Fi->database, Fi->table, Fin->driver, Fin->database, Fin->table);
776 
777  ret = Vect_map_add_dblink(Out, Fin->number, Fin->name, Fin->table, Fi->key,
778  Fin->database, Fin->driver);
779  if (ret == -1) {
780  G_warning(_("Unable to add database link for vector map <%s>"),
781  Out->name);
782  goto free_exit;
783  }
784 
785  if (cats)
786  key = Fi->key;
787  else
788  key = NULL;
789 
790  ret = db_copy_table_by_ints(Fi->driver, Fi->database, Fi->table,
791  Fin->driver, Vect_subst_var(Fin->database, Out),
792  Fin->table, key, cats, ncats);
793  if (ret == DB_FAILED) {
794  G_warning(_("Unable to copy table <%s>"), Fin->table);
795  ret = -1;
796  goto free_exit;
797  }
798 
800  Vect_subst_var(Fin->database, Out));
801 
802  if (!driver) {
803  G_warning(_("Unable to open database <%s> with driver <%s>"),
804  Fin->database, Fin->driver);
805  ret = -1;
806  goto free_exit;
807  }
808 
809  /* do not allow duplicate keys */
810  if (db_create_index2(driver, Fin->table, Fi->key) != DB_OK) {
811  G_warning(_("Unable to create index"));
812  ret = -1;
813  goto close_db_free_exit;
814  }
815 
817  DB_GROUP | DB_PUBLIC) != DB_OK) {
818  G_warning(_("Unable to grant privileges on table <%s>"), Fin->table);
819  ret = -1;
820  goto close_db_free_exit;
821  }
822 
823 close_db_free_exit:
825 
826 free_exit:
829 
830  return ret;
831 }
#define NULL
Definition: ccmath.h:32
#define DB_FAILED
Definition: dbmi.h:72
#define DB_PUBLIC
Definition: dbmi.h:135
#define DB_GROUP
Definition: dbmi.h:134
#define DB_PRIV_SELECT
Definition: dbmi.h:132
#define DB_OK
Definition: dbmi.h:71
int db_copy_table_by_ints(const char *, const char *, const char *, const char *, const char *, const char *, const char *, int *, int)
Copy a table (by keys)
Definition: copy_tab.c:513
dbDriver * db_start_driver_open_database(const char *, const char *)
Open driver/database connection.
Definition: db.c:28
int db_close_database_shutdown_driver(dbDriver *)
Close driver/database connection.
Definition: db.c:61
int db_create_index2(dbDriver *, const char *, const char *)
Create unique index.
Definition: c_create_idx.c:61
int db_grant_on_table(dbDriver *, const char *, int, int)
Grant privileges on table.
Definition: c_priv.c:29
void G_percent(long, long, int)
Print percent complete messages.
Definition: percent.c:61
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:150
#define G_realloc(p, n)
Definition: defs/gis.h:96
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition: defs/gis.h:94
void void void G_important_message(const char *,...) __attribute__((format(printf
void G_message(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
void Vect_destroy_line_struct(struct line_pnts *)
Frees all memory associated with a line_pnts structure, including the structure itself.
Definition: line.c:77
int Vect_get_node_coor(struct Map_info *, int, double *, double *, double *)
Get node coordinates.
Definition: level_two.c:274
plus_t Vect_get_num_lines(struct Map_info *)
Fetch number of features (points, lines, boundaries, centroids) in vector map.
Definition: level_two.c:75
plus_t Vect_get_num_areas(struct Map_info *)
Get number of areas in vector map.
Definition: level_two.c:87
int Vect_reset_cats(struct line_cats *)
Reset category structure to make sure cats structure is clean to be re-used.
struct field_info * Vect_default_field_info(struct Map_info *, int, const char *, int)
Get default information about link to database for new dblink.
Definition: field.c:358
int Vect_cat_set(struct line_cats *, int, int)
Add new field/cat to category structure if doesn't exist yet.
int Vect_get_area_boundaries(struct Map_info *, int, struct ilist *)
Creates list of boundaries for given area.
const char * Vect_get_full_name(struct Map_info *)
Get fully qualified name of vector map.
int Vect_cat_get(const struct line_cats *, int, int *)
Get first found category of given field.
int Vect_get_isle_points(struct Map_info *, int, struct line_pnts *)
Returns polygon array of points for given isle.
int Vect_get_area_points(struct Map_info *, int, struct line_pnts *)
Returns polygon array of points (outer ring) of given area.
void Vect_destroy_list(struct ilist *)
Frees all memory associated with a struct ilist, including the struct itself.
int Vect_level(struct Map_info *)
Returns level that Map is opened at.
Definition: level.c:29
void Vect_destroy_cats_struct(struct line_cats *)
Frees all memory associated with line_cats structure, including the struct itself.
int Vect_get_area_isle(struct Map_info *, int, int)
Returns isle id for area.
int Vect_read_line(struct Map_info *, struct line_pnts *, struct line_cats *, int)
Read vector feature (topological level required)
struct ilist * Vect_new_list(void)
Creates and initializes a struct ilist.
int Vect_get_area_num_isles(struct Map_info *, int)
Returns number of isles for given area.
char * Vect_subst_var(const char *, struct Map_info *)
Substitute variable in string.
Definition: field.c:931
int Vect_cat_list_to_array(const struct cat_list *, int **, int *)
Convert cat_list struct to ordered array of unique integers.
int Vect_line_alive(struct Map_info *, int)
Check if feature is alive or dead (topological level required)
int Vect_get_num_dblinks(struct Map_info *)
Get number of defined dblinks.
Definition: level_two.c:159
int Vect_get_area_cat(struct Map_info *, int, int)
Find FIRST category of given field and area.
off_t Vect_write_line(struct Map_info *, int, const struct line_pnts *, const struct line_cats *)
Writes a new feature.
struct field_info * Vect_get_field(struct Map_info *, int)
Get information about link to database (by layer number)
Definition: field.c:515
void Vect_destroy_field_info(struct field_info *)
Free a struct field_info and all memory associated with it.
Definition: field.c:633
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition: line.c:45
const char * Vect_get_finfo_geometry_type(struct Map_info *)
Get geometry type as string (relevant only for non-native formats)
Definition: header_finfo.c:143
struct field_info * Vect_get_dblink(struct Map_info *, int)
Get information about link to database.
Definition: field.c:475
plus_t Vect_get_num_nodes(struct Map_info *)
Get number of nodes in vector map.
Definition: level_two.c:34
int Vect_get_area_centroid(struct Map_info *, int)
Returns centroid id for given area.
int Vect_map_add_dblink(struct Map_info *, int, const char *, const char *, const char *, const char *, const char *)
Add new db connection to Map_info structure.
Definition: field.c:120
char * Vect_get_finfo_layer_name(struct Map_info *)
Get layer name (relevant only for non-native formats)
Definition: header_finfo.c:73
int Vect_rewind(struct Map_info *)
Rewind vector map to cause reads to start at beginning.
const char * Vect_get_name(struct Map_info *)
Get name of vector map.
int Vect_read_next_line(struct Map_info *, struct line_pnts *, struct line_cats *)
Read next vector feature.
int Vect_set_constraint_type(struct Map_info *, int)
Set constraint type.
Definition: constraint.c:106
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
int Vect_get_line_areas(struct Map_info *, int, int *, int *)
Get area id on the left and right side of the boundary.
Definition: level_two.c:346
int Vect_is_3d(struct Map_info *)
Check if vector map is 3D.
int Vect_append_point(struct line_pnts *, double, double, double)
Appends one point to the end of a line.
Definition: line.c:148
int Vect_get_isle_area(struct Map_info *, int)
Returns area id for isle.
#define GV_CENTROID
Definition: dig_defines.h:186
#define GV_FORMAT_POSTGIS
PostGIS format.
Definition: dig_defines.h:89
#define GV_LINE
Definition: dig_defines.h:184
#define GV_LINES
Definition: dig_defines.h:193
#define GV_BOUNDARY
Definition: dig_defines.h:185
#define GV_1TABLE
One table linked to vector map.
Definition: dig_defines.h:99
#define GV_MTABLE
More tables linked to vector map.
Definition: dig_defines.h:101
#define GV_POINTS
Definition: dig_defines.h:192
#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 TRUE
Definition: gis.h:79
#define FALSE
Definition: gis.h:83
#define _(str)
Definition: glocale.h:10
const char * name
Definition: named_colr.c:6
Data structure used for building pseudo-topology.
Definition: dig_structs.h:388
int * array
Offset list.
Definition: dig_structs.h:436
int array_num
Number of items in offset list.
Definition: dig_structs.h:440
char * toposchema_name
Topology schema name and id.
Definition: dig_structs.h:686
struct Format_info_offset offset
Offset list used for building pseudo-topology (simple features access)
Definition: dig_structs.h:676
struct Format_info_pg pg
PostGIS info.
Definition: dig_structs.h:712
Vector map info.
Definition: dig_structs.h:1243
char * name
Map name (for 4.0)
Definition: dig_structs.h:1316
int type
Feature type constraint.
Definition: dig_structs.h:1359
int type_flag
Non-zero value to enable feature type constraint.
Definition: dig_structs.h:1355
int format
Map format (native, ogr, postgis)
Definition: dig_structs.h:1255
struct Map_info::@11 constraint
Constraints for sequential feature access.
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
Vector geometry.
Definition: dig_structs.h:1553
void * topo
Topology info.
Definition: dig_structs.h:1577
Boundary topology.
Definition: dig_structs.h:1492
plus_t N1
Start node.
Definition: dig_structs.h:1496
plus_t N2
End node.
Definition: dig_structs.h:1500
Line topology.
Definition: dig_structs.h:1478
plus_t N1
Start node.
Definition: dig_structs.h:1482
plus_t N2
End node.
Definition: dig_structs.h:1486
struct P_line ** Line
Array of vector geometries.
Definition: dig_structs.h:871
Category list.
Definition: dig_structs.h:1697
Definition: driver.h:21
Layer (old: field) information.
Definition: dig_structs.h:131
char * table
Name of DB table.
Definition: dig_structs.h:151
char * driver
Name of DB driver ('sqlite', 'dbf', ...)
Definition: dig_structs.h:143
char * name
Layer name (optional)
Definition: dig_structs.h:139
char * database
Definition: dig_structs.h:147
char * key
Name of key column (usually 'cat')
Definition: dig_structs.h:155
int number
Layer number.
Definition: dig_structs.h:135
List of integers.
Definition: gis.h:709
int n_values
Number of values in the list.
Definition: gis.h:717
int * value
Array of values.
Definition: gis.h:713
Feature category info.
Definition: dig_structs.h:1677
int * field
Array of layers (fields)
Definition: dig_structs.h:1681
Feature geometry info - coordinates.
Definition: dig_structs.h:1651
double * y
Array of Y coordinates.
Definition: dig_structs.h:1659
double * x
Array of X coordinates.
Definition: dig_structs.h:1655
double * z
Array of Z coordinates.
Definition: dig_structs.h:1663
#define TOPO_POSTGIS
#define NOPG_UNUSED
int Vect_copy_table(struct Map_info *In, struct Map_info *Out, int field_in, int field_out, const char *field_name, int type)
Copy attribute table linked to vector map based on type.
int Vect_copy_tables(struct Map_info *In, struct Map_info *Out, int field)
Copy attribute tables linked to vector map.
#define TOPO_NONE
Copy topological elements.
int Vect_copy_table_by_cat_list(struct Map_info *In, struct Map_info *Out, int field_in, int field_out, const char *field_name, int type, const struct cat_list *cat_list)
Copy attribute table linked to vector map based on category list.
int copy_line_nodes(struct Map_info *In, int node, int with_z, struct line_pnts *Points, struct Map_info *Out NOPG_UNUSED)
int Vect_copy_map_lines(struct Map_info *In, struct Map_info *Out)
Copy all alive vector features from input vector map to output vector map.
int Vect_copy_table_by_cats(struct Map_info *In, struct Map_info *Out, int field_in, int field_out, const char *field_name, int type, int *cats, int ncats)
Copy attribute table linked to vector map based on category numbers.
int Vect__copy_areas(struct Map_info *In, int field, struct Map_info *Out)
Copy areas as polygons (OGR/PostGIS simple features access only)
int Vect_copy_map_lines_field(struct Map_info *In, int field, struct Map_info *Out)
Copy all alive vector features from given layer from input vector map to output vector map.
#define TOPO_NATIVE
int V2__update_area_pg(struct Map_info *Map, const struct line_pnts **points, int nparts, int cat)
Updates simple features geometry from GRASS-like topo.
Definition: write_pg.c:557
off_t V2__write_node_pg(struct Map_info *Map, const struct line_pnts *points)
Writes node on topological level (PostGIS Topology interface, internal use only)
Definition: write_pg.c:516
off_t V2__write_area_sfa(struct Map_info *Map, const struct line_pnts **points, int nparts, const struct line_cats *cats)
Writes area on topological level (Simple Features interface, internal use only)
Definition: write_sfa.c:293
#define x