GRASS GIS 8 Programmer's Manual  8.5.0dev(2025)-29009adf5a
open_ogr.c
Go to the documentation of this file.
1 /*!
2  \file lib/vector/Vlib/open_ogr.c
3 
4  \brief Vector library - Open OGR layer as vector map layer
5 
6  Higher level functions for reading/writing/manipulating vectors.
7 
8  (C) 2001-2010 by the GRASS Development Team
9 
10  This program is free software under the GNU General Public License
11  (>=v2). Read the file COPYING that comes with GRASS for details.
12 
13  \author Original author CERL, probably Dave Gerdes or Mike Higgins.
14  \author Update to GRASS 5.7 Radim Blazek and David D. Gray.
15  \author Update to GRASS 7.0 Martin Landa <landa.martin gmail.com> (2009)
16  */
17 
18 #include <unistd.h>
19 #include <string.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 
23 #include <grass/vector.h>
24 #include <grass/dbmi.h>
25 #include <grass/glocale.h>
26 
27 #ifdef HAVE_OGR
28 #include <ogr_api.h>
29 #endif
30 
31 /*!
32  \brief Open existing OGR layer on non-topological level
33 
34  Note: Map->name, Map->mapset, Map->fInfo.ogr.dsn and
35  Map->fInfo.ogr.layer_name must be set before.
36 
37  \param[in,out] Map pointer to Map_info structure
38  \param update TRUE for write mode, otherwise read-only
39 
40  \return 0 success
41  \return -1 error
42  */
43 int V1_open_old_ogr(struct Map_info *Map, int update)
44 {
45 #ifdef HAVE_OGR
46  int i, layer, nLayers;
47 
48  struct Format_info_ogr *ogr_info;
49 
50  OGRDataSourceH Ogr_ds;
51  OGRLayerH Ogr_layer;
52  OGRFeatureDefnH Ogr_featuredefn;
53  OGRwkbGeometryType Ogr_geom_type;
54 
55  Ogr_layer = NULL;
56  Ogr_geom_type = wkbUnknown;
57 
58  ogr_info = &(Map->fInfo.ogr);
59  if (!ogr_info->dsn) {
60  G_fatal_error(_("OGR datasource not defined"));
61  return -1;
62  }
63 
64  if (!ogr_info->layer_name) {
65  G_fatal_error(_("OGR layer not defined"));
66  return -1;
67  }
68 
69  G_debug(2, "V1_open_old_ogr(): dsn = %s layer = %s", ogr_info->dsn,
70  ogr_info->layer_name);
71 
72  OGRRegisterAll();
73 
74  /* open data source handle */
75  Ogr_ds = OGROpen(ogr_info->dsn, FALSE, NULL);
76  if (Ogr_ds == NULL)
77  G_fatal_error(_("Unable to open OGR data source '%s'"), ogr_info->dsn);
78  ogr_info->ds = Ogr_ds;
79 
80  /* get layer number */
81  layer = -1;
82  nLayers = OGR_DS_GetLayerCount(Ogr_ds);
83  G_debug(2, "%d layers found in data source", nLayers);
84 
85  for (i = 0; i < nLayers; i++) {
86  Ogr_layer = OGR_DS_GetLayer(Ogr_ds, i);
87  Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
88  if (strcmp(OGR_FD_GetName(Ogr_featuredefn), ogr_info->layer_name) ==
89  0) {
90  Ogr_geom_type = OGR_FD_GetGeomType(Ogr_featuredefn);
91  layer = i;
92  break;
93  }
94  }
95  if (layer == -1) {
96  OGR_DS_Destroy(Ogr_ds);
97  G_fatal_error(_("OGR layer <%s> not found"), ogr_info->layer_name);
98  }
99  G_debug(2, "OGR layer %d opened", layer);
100 
101  ogr_info->layer = Ogr_layer;
102  if (update && OGR_L_TestCapability(ogr_info->layer, OLCTransactions) &&
103  (OGR_L_StartTransaction(ogr_info->layer) != OGRERR_NONE)) {
104  OGR_DS_Destroy(Ogr_ds);
105  G_warning(_("OGR transaction with layer <%s> failed to start"),
106  ogr_info->layer_name);
107  return -1;
108  }
109 
110  switch (Ogr_geom_type) {
111  case wkbPoint25D:
112  case wkbLineString25D:
113  case wkbPolygon25D:
114  case wkbMultiPoint25D:
115  case wkbMultiLineString25D:
116  case wkbMultiPolygon25D:
117  case wkbGeometryCollection25D:
118  Map->head.with_z = WITH_Z;
119  break;
120  default:
121  Map->head.with_z = WITHOUT_Z;
122  break;
123  }
124 
125  ogr_info->cache.fid = -1; /* FID >= 0 */
126 
127  return 0;
128 #else
129  G_fatal_error(_("GRASS is not compiled with OGR support"));
130  return -1;
131 #endif
132 }
133 
134 /*!
135  \brief Open existing OGR layer on topological level
136 
137  This functions reads feature index (fidx) file required for
138  pseudo-topology.
139 
140  \param[in,out] Map pointer to Map_info structure
141 
142  \return 0 success
143  \return -1 error
144  */
145 int V2_open_old_ogr(struct Map_info *Map)
146 {
147 #ifdef HAVE_OGR
148 
149  G_debug(3, "V2_open_old_ogr(): name = %s mapset = %s", Map->name,
150  Map->mapset);
151 
152  if (Vect_open_fidx(Map, &(Map->fInfo.ogr.offset)) != 0) {
153  const char *map_name = Vect_get_full_name(Map);
154  G_warning(_("Unable to open feature index file for vector map <%s>"),
155  map_name);
156  G_free((void *)map_name);
157  G_zero(&(Map->fInfo.ogr.offset), sizeof(struct Format_info_offset));
158  }
159 
160  Map->fInfo.ogr.next_line = 1; /* reset feature cache */
161 
162  return 0;
163 #else
164  G_fatal_error(_("GRASS is not compiled with OGR support"));
165  return -1;
166 #endif
167 }
168 
169 /*!
170  \brief Prepare OGR datasource for creating new OGR layer (level 1)
171 
172  New OGR layer is created when writing features by
173  Vect_wrile_line().
174 
175  \param[out] Map pointer to Map_info structure
176  \param name name of OGR layer to create
177  \param with_z WITH_Z for 3D vector data otherwise WITHOUT_Z
178 
179  \return 0 success
180  \return -1 error
181  */
182 int V1_open_new_ogr(struct Map_info *Map, const char *name, int with_z)
183 {
184 #ifdef HAVE_OGR
185  int i, nlayers;
186 
187  struct Format_info_ogr *ogr_info;
188 
189  OGRSFDriverH Ogr_driver;
190  OGRDataSourceH Ogr_ds;
191  OGRLayerH Ogr_layer;
192  OGRFeatureDefnH Ogr_featuredefn;
193 
194  OGRRegisterAll();
195 
196  ogr_info = &(Map->fInfo.ogr);
197 
198  G_debug(1, "V1_open_new_ogr(): name = %s with_z = %d", name, with_z);
199  Ogr_driver = OGRGetDriverByName(ogr_info->driver_name);
200  if (!Ogr_driver) {
201  G_warning(_("Unable to get OGR driver <%s>"), ogr_info->driver_name);
202  return -1;
203  }
204  ogr_info->driver = Ogr_driver;
205 
206  /* TODO: creation options */
207  Ogr_ds = OGR_Dr_CreateDataSource(Ogr_driver, ogr_info->dsn, NULL);
208  if (!Ogr_ds) {
209  G_warning(_("Unable to create OGR data source '%s'"), ogr_info->dsn);
210  return -1;
211  }
212  ogr_info->ds = Ogr_ds;
213 
214  nlayers = OGR_DS_GetLayerCount(Ogr_ds);
215  for (i = 0; i < nlayers; i++) {
216  Ogr_layer = OGR_DS_GetLayer(Ogr_ds, i);
217  Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
218  if (strcmp(OGR_FD_GetName(Ogr_featuredefn), name) == 0) {
219  if (G_get_overwrite()) {
220  G_warning(
221  _("OGR layer <%s> already exists and will be overwritten"),
222  ogr_info->layer_name);
223 
224  if (OGR_DS_DeleteLayer(Ogr_ds, i) != OGRERR_NONE) {
225  G_warning(_("Unable to delete OGR layer <%s>"),
226  ogr_info->layer_name);
227  return -1;
228  }
229  }
230  else {
232  _("OGR layer <%s> already exists in datasource '%s'"),
233  ogr_info->layer_name, ogr_info->dsn);
234  }
235  ogr_info->layer = NULL;
236  break;
237  }
238  }
239 
240  return 0;
241 #else
242  G_fatal_error(_("GRASS is not compiled with OGR support"));
243  return -1;
244 #endif
245 }
246 
247 /*!
248  \brief Open feature index file
249 
250  \param[in,out] Map pointer to Map_info struct
251  \param[out] offset pointer to Format_info_offset (OGR or PG)
252 
253  \return 0 on success
254  \return -1 on error
255  */
257 {
258  char elem[GPATH_MAX];
259  char buf[5]; /* used for format version */
260  long length;
261  int Version_Major, Version_Minor, Back_Major, Back_Minor, byte_order;
262 
263  struct gvfile fp;
264  struct Port_info port;
265 
266  G_debug(1, "Vect_open_fidx(): name = %s mapset = %s format = %d", Map->name,
267  Map->mapset, Map->format);
268 
269  sprintf(elem, "%s/%s", GV_DIRECTORY, Map->name);
270  dig_file_init(&fp);
271  fp.file = G_fopen_old(elem, GV_FIDX_ELEMENT, Map->mapset);
272  if (fp.file == NULL) {
273  const char *map_name = Vect_get_full_name(Map);
274  G_debug(1, "unable to open fidx file for vector map <%s>", map_name);
275  G_free((void *)map_name);
276  return -1;
277  }
278 
279  /* Header */
280  if (0 >= dig__fread_port_C(buf, 5, &fp)) {
281  fclose(fp.file);
282  return -1;
283  }
284  Version_Major = buf[0];
285  Version_Minor = buf[1];
286  Back_Major = buf[2];
287  Back_Minor = buf[3];
288  byte_order = buf[4];
289 
290  /* check version numbers */
291  if (Version_Major > 5 || Version_Minor > 0) {
292  if (Back_Major > 5 || Back_Minor > 0) {
293  G_fatal_error(_("Feature index format version %d.%d is not "
294  "supported by this release."
295  " Try to rebuild topology or upgrade GRASS."),
296  Version_Major, Version_Minor);
297  return -1;
298  }
299  G_warning(_("Your GRASS version does not fully support feature index "
300  "format %d.%d of the vector."
301  " Consider to rebuild topology or upgrade GRASS."),
302  Version_Major, Version_Minor);
303  }
304 
306  dig_set_cur_port(&port);
307 
308  /* Body */
309  /* bytes 6 - 9 : header size */
310  if (0 >= dig__fread_port_L(&length, 1, &fp)) {
311  fclose(fp.file);
312  return -1;
313  }
314  G_debug(4, " header size %ld", length);
315 
316  G_fseek(fp.file, length, SEEK_SET);
317 
318  /* number of records */
319  if (0 >= dig__fread_port_I(&(offset->array_num), 1, &fp)) {
320  fclose(fp.file);
321  return -1;
322  }
323 
324  /* alloc space */
325  offset->array = (int *)G_malloc(offset->array_num * sizeof(int));
326  offset->array_alloc = offset->array_num;
327 
328  /* offsets */
329  if (0 >= dig__fread_port_I(offset->array, offset->array_num, &fp)) {
330  fclose(fp.file);
331  return -1;
332  }
333 
334  fclose(fp.file);
335 
336  G_debug(3, "%d records read from fidx", offset->array_num);
337 
338  return 0;
339 }
#define NULL
Definition: ccmath.h:32
FILE * G_fopen_old(const char *, const char *, const char *)
Open a database file for reading.
Definition: gis/open.c:251
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition: gis/zero.c:23
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:150
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 G_fseek(FILE *, off_t, int)
Change the file position of the stream.
Definition: gis/seek.c:50
int G_get_overwrite(void)
Get overwrite value.
Definition: parser.c:957
int G_debug(int, const char *,...) __attribute__((format(printf
const char * Vect_get_full_name(struct Map_info *)
Get fully qualified name of vector map.
#define GV_DIRECTORY
Name of vector directory.
Definition: dig_defines.h:8
#define WITH_Z
Definition: dig_defines.h:172
#define GV_FIDX_ELEMENT
External format (OGR), feature index.
Definition: dig_defines.h:26
#define WITHOUT_Z
2D/3D vector data
Definition: dig_defines.h:171
void dig_init_portable(struct Port_info *, int)
Set Port_info structure to byte order of file.
Definition: portable.c:900
int dig__fread_port_L(long *, size_t, struct gvfile *)
Read longs from the Portable Vector Format.
Definition: portable.c:262
int dig_set_cur_port(struct Port_info *)
Set current Port_info structure.
Definition: portable.c:996
int dig__fread_port_C(char *, size_t, struct gvfile *)
Read chars from the Portable Vector Format.
Definition: portable.c:511
int dig__fread_port_I(int *, size_t, struct gvfile *)
Read integers from the Portable Vector Format.
Definition: portable.c:345
void dig_file_init(struct gvfile *file)
Initialize gvfile structure.
Definition: file.c:171
#define GPATH_MAX
Definition: gis.h:194
#define FALSE
Definition: gis.h:83
#define _(str)
Definition: glocale.h:10
const char * name
Definition: named_colr.c:6
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:182
int Vect_open_fidx(struct Map_info *Map, struct Format_info_offset *offset)
Open feature index file.
Definition: open_ogr.c:256
int V2_open_old_ogr(struct Map_info *Map)
Open existing OGR layer on topological level.
Definition: open_ogr.c:145
int V1_open_old_ogr(struct Map_info *Map, int update)
Open existing OGR layer on non-topological level.
Definition: open_ogr.c:43
long fid
Feature id.
Definition: dig_structs.h:486
Data structure used for building pseudo-topology.
Definition: dig_structs.h:388
int * array
Offset list.
Definition: dig_structs.h:436
int array_alloc
Space allocated for offset list.
Definition: dig_structs.h:444
int array_num
Number of items in offset list.
Definition: dig_structs.h:440
Non-native format info (OGR)
Definition: dig_structs.h:505
char * dsn
OGR datasource name.
Definition: dig_structs.h:513
OGRSFDriverH driver
Pointer to OGRDriver.
Definition: dig_structs.h:526
char * driver_name
OGR driver name.
Definition: dig_structs.h:509
OGRDataSourceH ds
Pointer to OGRDataSource.
Definition: dig_structs.h:530
char * layer_name
OGR layer name.
Definition: dig_structs.h:517
int next_line
Next line to be read.
Definition: dig_structs.h:584
OGRLayerH layer
Pointer to OGRLayer.
Definition: dig_structs.h:534
struct Format_info_offset offset
Offset list used for building pseudo-topology.
Definition: dig_structs.h:577
struct Format_info_cache cache
Lines cache for reading feature.
Definition: dig_structs.h:561
struct Format_info_ogr ogr
OGR info.
Definition: dig_structs.h:708
Vector map info.
Definition: dig_structs.h:1243
char * mapset
Mapset name.
Definition: dig_structs.h:1320
struct dig_head head
Header info.
Definition: dig_structs.h:1388
char * name
Map name (for 4.0)
Definition: dig_structs.h:1316
int format
Map format (native, ogr, postgis)
Definition: dig_structs.h:1255
struct Format_info fInfo
Format info for non-native formats.
Definition: dig_structs.h:1400
Portability info.
Definition: dig_structs.h:181
int byte_order
File byte order.
Definition: dig_structs.h:185
int with_z
2D/3D vector data
Definition: dig_structs.h:339
File definition.
Definition: dig_structs.h:94
FILE * file
File descriptor.
Definition: dig_structs.h:98