GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
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'"),
78  ogr_info->dsn);
79  ogr_info->ds = Ogr_ds;
80 
81  /* get layer number */
82  layer = -1;
83  nLayers = OGR_DS_GetLayerCount(Ogr_ds);
84  G_debug(2, "%d layers found in data source", nLayers);
85 
86  for (i = 0; i < nLayers; i++) {
87  Ogr_layer = OGR_DS_GetLayer(Ogr_ds, i);
88  Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
89  if (strcmp(OGR_FD_GetName(Ogr_featuredefn), ogr_info->layer_name) == 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"),
98  ogr_info->layer_name);
99  }
100  G_debug(2, "OGR layer %d opened", layer);
101 
102  ogr_info->layer = Ogr_layer;
103  if (update && OGR_L_TestCapability(ogr_info->layer, OLCTransactions) &&
104  (OGR_L_StartTransaction(ogr_info->layer) != OGRERR_NONE)) {
105  OGR_DS_Destroy(Ogr_ds);
106  G_warning(_("OGR transaction with layer <%s> failed to start"),
107  ogr_info->layer_name);
108  return -1;
109  }
110 
111  switch(Ogr_geom_type) {
112  case wkbPoint25D: case wkbLineString25D: case wkbPolygon25D:
113  case wkbMultiPoint25D: case wkbMultiLineString25D: case wkbMultiPolygon25D:
114  case wkbGeometryCollection25D:
115  Map->head.with_z = WITH_Z;
116  break;
117  default:
118  Map->head.with_z = WITHOUT_Z;
119  break;
120  }
121 
122  ogr_info->cache.fid = -1; /* FID >= 0 */
123 
124  return 0;
125 #else
126  G_fatal_error(_("GRASS is not compiled with OGR support"));
127  return -1;
128 #endif
129 }
130 
131 /*!
132  \brief Open existing OGR layer on topological level
133 
134  This functions reads feature index (fidx) file required for
135  pseudo-topology.
136 
137  \param[in,out] Map pointer to Map_info structure
138 
139  \return 0 success
140  \return -1 error
141 */
142 int V2_open_old_ogr(struct Map_info *Map)
143 {
144 #ifdef HAVE_OGR
145 
146  G_debug(3, "V2_open_old_ogr(): name = %s mapset = %s", Map->name,
147  Map->mapset);
148 
149  if (Vect_open_fidx(Map, &(Map->fInfo.ogr.offset)) != 0) {
150  G_warning(_("Unable to open feature index file for vector map <%s>"),
151  Vect_get_full_name(Map));
152  G_zero(&(Map->fInfo.ogr.offset), sizeof(struct Format_info_offset));
153  }
154 
155  Map->fInfo.ogr.next_line = 1; /* reset feature cache */
156 
157  return 0;
158 #else
159  G_fatal_error(_("GRASS is not compiled with OGR support"));
160  return -1;
161 #endif
162 }
163 
164 /*!
165  \brief Prepare OGR datasource for creating new OGR layer (level 1)
166 
167  New OGR layer is created when writing features by
168  Vect_wrile_line().
169 
170  \param[out] Map pointer to Map_info structure
171  \param name name of OGR layer to create
172  \param with_z WITH_Z for 3D vector data otherwise WITHOUT_Z
173 
174  \return 0 success
175  \return -1 error
176 */
177 int V1_open_new_ogr(struct Map_info *Map, const char *name, int with_z)
178 {
179 #ifdef HAVE_OGR
180  int i, nlayers;
181 
182  struct Format_info_ogr *ogr_info;
183 
184  OGRSFDriverH Ogr_driver;
185  OGRDataSourceH Ogr_ds;
186  OGRLayerH Ogr_layer;
187  OGRFeatureDefnH Ogr_featuredefn;
188 
189  OGRRegisterAll();
190 
191  ogr_info = &(Map->fInfo.ogr);
192 
193  G_debug(1, "V1_open_new_ogr(): name = %s with_z = %d", name, with_z);
194  Ogr_driver = OGRGetDriverByName(ogr_info->driver_name);
195  if (!Ogr_driver) {
196  G_warning(_("Unable to get OGR driver <%s>"), ogr_info->driver_name);
197  return -1;
198  }
199  ogr_info->driver = Ogr_driver;
200 
201  /* TODO: creation options */
202  Ogr_ds = OGR_Dr_CreateDataSource(Ogr_driver, ogr_info->dsn, NULL);
203  if (!Ogr_ds) {
204  G_warning(_("Unable to create OGR data source '%s'"),
205  ogr_info->dsn);
206  return -1;
207  }
208  ogr_info->ds = Ogr_ds;
209 
210  nlayers = OGR_DS_GetLayerCount(Ogr_ds);
211  for (i = 0; i < nlayers; i++) {
212  Ogr_layer = OGR_DS_GetLayer(Ogr_ds, i);
213  Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
214  if (strcmp(OGR_FD_GetName(Ogr_featuredefn), name) == 0) {
215  if (G_get_overwrite()) {
216  G_warning(_("OGR layer <%s> already exists and will be overwritten"),
217  ogr_info->layer_name);
218 
219  if (OGR_DS_DeleteLayer(Ogr_ds, i) != OGRERR_NONE) {
220  G_warning(_("Unable to delete OGR layer <%s>"),
221  ogr_info->layer_name);
222  return -1;
223  }
224  }
225  else {
226  G_fatal_error(_("OGR layer <%s> already exists in datasource '%s'"),
227  ogr_info->layer_name, ogr_info->dsn);
228  }
229  ogr_info->layer = NULL;
230  break;
231  }
232  }
233 
234  return 0;
235 #else
236  G_fatal_error(_("GRASS is not compiled with OGR support"));
237  return -1;
238 #endif
239 }
240 
241 /*!
242  \brief Open feature index file
243 
244  \param[in,out] Map pointer to Map_info struct
245  \param[out] offset pointer to Format_info_offset (OGR or PG)
246 
247  \return 0 on success
248  \return -1 on error
249 */
251 {
252  char elem[GPATH_MAX];
253  char buf[5]; /* used for format version */
254  long length;
255  int Version_Major, Version_Minor, Back_Major, Back_Minor, byte_order;
256 
257  struct gvfile fp;
258  struct Port_info port;
259 
260  G_debug(1, "Vect_open_fidx(): name = %s mapset = %s format = %d",
261  Map->name, Map->mapset, Map->format);
262 
263  sprintf(elem, "%s/%s", GV_DIRECTORY, Map->name);
264  dig_file_init(&fp);
265  fp.file = G_fopen_old(elem, GV_FIDX_ELEMENT, Map->mapset);
266  if (fp.file == NULL) {
267  G_debug(1, "unable to open fidx file for vector map <%s>",
268  Vect_get_full_name(Map));
269  return -1;
270  }
271 
272  /* Header */
273  if (0 >= dig__fread_port_C(buf, 5, &fp))
274  return -1;
275  Version_Major = buf[0];
276  Version_Minor = buf[1];
277  Back_Major = buf[2];
278  Back_Minor = buf[3];
279  byte_order = buf[4];
280 
281  /* check version numbers */
282  if (Version_Major > 5 || Version_Minor > 0) {
283  if (Back_Major > 5 || Back_Minor > 0) {
284  G_fatal_error(_("Feature index format version %d.%d is not supported by this release."
285  " Try to rebuild topology or upgrade GRASS."),
286  Version_Major, Version_Minor);
287  return -1;
288  }
289  G_warning(_("Your GRASS version does not fully support feature index format %d.%d of the vector."
290  " Consider to rebuild topology or upgrade GRASS."),
291  Version_Major, Version_Minor);
292  }
293 
294  dig_init_portable(&port, byte_order);
295  dig_set_cur_port(&port);
296 
297  /* Body */
298  /* bytes 6 - 9 : header size */
299  if (0 >= dig__fread_port_L(&length, 1, &fp))
300  return -1;
301  G_debug(4, " header size %ld", length);
302 
303  G_fseek(fp.file, length, SEEK_SET);
304 
305  /* number of records */
306  if (0 >= dig__fread_port_I(&(offset->array_num), 1, &fp))
307  return -1;
308 
309  /* alloc space */
310  offset->array = (int *) G_malloc(offset->array_num * sizeof(int));
311  offset->array_alloc = offset->array_num;
312 
313  /* offsets */
314  if (0 >= dig__fread_port_I(offset->array,
315  offset->array_num, &fp))
316  return -1;
317 
318  fclose(fp.file);
319 
320  G_debug(3, "%d records read from fidx", offset->array_num);
321 
322  return 0;
323 }
int * array
Offset list.
Definition: dig_structs.h:446
#define G_malloc(n)
Definition: defs/gis.h:112
int Vect_open_fidx(struct Map_info *Map, struct Format_info_offset *offset)
Open feature index file.
Definition: open_ogr.c:250
char * name
Map name (for 4.0)
Definition: dig_structs.h:1332
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void dig_init_portable(struct Port_info *, int)
Set Port_info structure to byte order of file.
Definition: portable.c:905
#define GV_DIRECTORY
Name of vector directory.
Definition: dig_defines.h:8
OGRSFDriverH driver
Pointer to OGRDriver.
Definition: dig_structs.h:538
OGRDataSourceH ds
Pointer to OGRDataSource.
Definition: dig_structs.h:542
int dig__fread_port_I(int *, size_t, struct gvfile *)
Read integers from the Portable Vector Format.
Definition: portable.c:343
int dig__fread_port_C(char *, size_t, struct gvfile *)
Read chars from the Portable Vector Format.
Definition: portable.c:509
struct Format_info_cache cache
Lines cache for reading feature.
Definition: dig_structs.h:573
struct Format_info_offset offset
Offset list used for building pseudo-topology.
Definition: dig_structs.h:589
long fid
Feature id.
Definition: dig_structs.h:497
char * dsn
OGR datasource name.
Definition: dig_structs.h:525
int dig__fread_port_L(long *, size_t, struct gvfile *)
Read longs from the Portable Vector Format.
Definition: portable.c:260
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
#define NULL
Definition: ccmath.h:32
int G_get_overwrite()
Get overwrite value.
Definition: parser.c:934
int with_z
2D/3D vector data
Definition: dig_structs.h:347
Data structure used for building pseudo-topology.
Definition: dig_structs.h:397
#define FALSE
Definition: gis.h:63
int next_line
Next line to be read.
Definition: dig_structs.h:596
int V2_open_old_ogr(struct Map_info *Map)
Open existing OGR layer on topological level.
Definition: open_ogr.c:142
void G_fseek(FILE *, off_t, int)
Change the file position of the stream.
Definition: gis/seek.c:50
Non-native format info (OGR)
Definition: dig_structs.h:516
void dig_file_init(struct gvfile *file)
Initialize gvfile strcuture.
Definition: file.c:170
struct Format_info_ogr ogr
OGR info.
Definition: dig_structs.h:722
#define GPATH_MAX
Definition: gis.h:180
FILE * G_fopen_old(const char *, const char *, const char *)
Open a database file for reading.
Definition: gis/open.c:253
char * mapset
Mapset name.
Definition: dig_structs.h:1336
#define WITH_Z
Definition: dig_defines.h:171
#define WITHOUT_Z
2D/3D vector data
Definition: dig_defines.h:170
struct dig_head head
Header info.
Definition: dig_structs.h:1403
int array_num
Number of items in offset list.
Definition: dig_structs.h:450
int array_alloc
Space allocated for offset list.
Definition: dig_structs.h:454
Vector map info.
Definition: dig_structs.h:1259
char * layer_name
OGR layer name.
Definition: dig_structs.h:529
FILE * file
File descriptor.
Definition: dig_structs.h:101
const char * Vect_get_full_name(const struct Map_info *)
Get fully qualified name of vector map.
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition: gis/zero.c:23
void G_warning(const char *,...) __attribute__((format(printf
char * driver_name
OGR driver name.
Definition: dig_structs.h:521
Portability info.
Definition: dig_structs.h:186
#define _(str)
Definition: glocale.h:10
int format
Map format (native, ogr, postgis)
Definition: dig_structs.h:1271
int dig_set_cur_port(struct Port_info *)
Set current Port_info structure.
Definition: portable.c:1001
OGRLayerH layer
Pointer to OGRLayer.
Definition: dig_structs.h:546
#define GV_FIDX_ELEMENT
External format (OGR), feature index.
Definition: dig_defines.h:26
const char * name
Definition: named_colr.c:7
File definition.
Definition: dig_structs.h:96
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:177
int G_debug(int, const char *,...) __attribute__((format(printf