1 /*!
2    \file lib/vector/Vlib/header_finfo.c
3 
4    \brief Vector library - header manipulation (relevant for external
5    formats)
6 
7    Higher level functions for reading/writing/manipulating vectors.
8 
9    (C) 2001-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 (OGR/PostGIS support) by Martin Landa <landa.martin gmail.com>
17 */
18 
19 #include <string.h>
20 
21 #include <grass/vector.h>
22 #include <grass/glocale.h>
23 
24 /*!
25    \brief Get datasource name (relevant only for non-native formats)
26 
27    Returns:
28     - datasource name for OGR format (GV_FORMAT_OGR and GV_FORMAT_OGR_DIRECT)
29     - database name for PostGIS format (GV_FORMAT_POSTGIS)
30 
31    \param Map pointer to Map_info structure
32 
33    \return string containing OGR/PostGIS datasource name
34    \return NULL on error (map format is native)
35  */
Vect_get_finfo_dsn_name(const struct Map_info * Map)36 const char *Vect_get_finfo_dsn_name(const struct Map_info *Map)
37 {
38     if (Map->format == GV_FORMAT_OGR ||
39         Map->format == GV_FORMAT_OGR_DIRECT) {
40 #ifndef HAVE_OGR
41         G_warning(_("GRASS is not compiled with OGR support"));
42 #endif
43         return Map->fInfo.ogr.dsn;
44     }
45     else if (Map->format == GV_FORMAT_POSTGIS) {
46 #ifndef HAVE_POSTGRES
47         G_warning(_("GRASS is not compiled with PostgreSQL support"));
48 #endif
49         return Map->fInfo.pg.db_name;
50     }
51 
52     G_debug(1, "Native vector format detected for <%s>",
53             Vect_get_full_name(Map));
54 
55     return NULL;
56 }
57 
58 /*!
59    \brief Get layer name (relevant only for non-native formats)
60 
61    Returns:
62     - layer name for OGR format (GV_FORMAT_OGR and GV_FORMAT_OGR_DIRECT)
63     - table name for PostGIS format (GV_FORMAT_POSTGIS) including schema (\<schema\>.\<table\>)
64 
65    Note: allocated string should be freed by G_free()
66 
67    \param Map pointer to Map_info structure
68 
69    \return string containing layer name
70    \return NULL on error (map format is native)
71  */
Vect_get_finfo_layer_name(const struct Map_info * Map)72 char *Vect_get_finfo_layer_name(const struct Map_info *Map)
73 {
74     char *name;
75 
76     name = NULL;
77     if (Map->format == GV_FORMAT_OGR ||
78         Map->format == GV_FORMAT_OGR_DIRECT) {
79 #ifndef HAVE_OGR
80         G_warning(_("GRASS is not compiled with OGR support"));
81 #endif
82         name = G_store(Map->fInfo.ogr.layer_name);
83     }
84     else if (Map->format == GV_FORMAT_POSTGIS) {
85 #ifndef HAVE_POSTGRES
86         G_warning(_("GRASS is not compiled with PostgreSQL support"));
87 #endif
88         G_asprintf(&name, "%s.%s", Map->fInfo.pg.schema_name,
89                    Map->fInfo.pg.table_name);
90     }
91     else {
92         G_debug(1, "Native vector format detected for <%s>",
93                   Vect_get_full_name(Map));
94     }
95 
96     return name;
97 }
98 
99 /*!
100   \brief Get format info as string (relevant only for non-native formats)
101 
102   \param Map pointer to Map_info structure
103 
104   \return string containing name of OGR format
105   \return "PostgreSQL" for PostGIS format (GV_FORMAT_POSTGIS)
106   \return NULL on error (or on missing OGR/PostgreSQL support)
107 */
Vect_get_finfo_format_info(const struct Map_info * Map)108 const char *Vect_get_finfo_format_info(const struct Map_info *Map)
109 {
110     if (Map->format == GV_FORMAT_OGR ||
111         Map->format == GV_FORMAT_OGR_DIRECT) {
112 #ifndef HAVE_OGR
113         G_warning(_("GRASS is not compiled with OGR support"));
114 #else
115         if (!Map->fInfo.ogr.ds)
116             return NULL;
117 
118         return OGR_Dr_GetName(OGR_DS_GetDriver(Map->fInfo.ogr.ds));
119 #endif
120     }
121     else if (Map->format == GV_FORMAT_POSTGIS) {
122 #ifndef HAVE_OGR
123         G_warning(_("GRASS is not compiled with PostgreSQL support"));
124 #else
125         return "PostgreSQL";
126 #endif
127     }
128 
129     return NULL;
130 }
131 
132 /*!
133   \brief Get geometry type as string (relevant only for non-native formats)
134 
135   Note: All inner spaces are removed, function returns feature type in
136   lowercase.
137 
138   \param Map pointer to Map_info structure
139 
140   \return allocated string containing geometry type info
141   (point, linestring, polygon, ...)
142   \return NULL on error (map format is native)
143 */
Vect_get_finfo_geometry_type(const struct Map_info * Map)144 const char *Vect_get_finfo_geometry_type(const struct Map_info *Map)
145 {
146     int dim;
147     char *ftype, *ftype_tmp;
148 
149     ftype_tmp = ftype = NULL;
150     if (Map->format == GV_FORMAT_OGR ||
151         Map->format == GV_FORMAT_OGR_DIRECT) {
152 #ifndef HAVE_OGR
153     G_warning(_("GRASS is not compiled with OGR support"));
154 #else
155     OGRwkbGeometryType Ogr_geom_type;
156     OGRFeatureDefnH    Ogr_feature_defn;
157 
158     if (!Map->fInfo.ogr.layer)
159         return NULL;
160 
161     dim = -1;
162 
163     Ogr_feature_defn = OGR_L_GetLayerDefn(Map->fInfo.ogr.layer);
164     Ogr_geom_type = wkbFlatten(OGR_FD_GetGeomType(Ogr_feature_defn));
165 
166     ftype_tmp = G_store(OGRGeometryTypeToName(Ogr_geom_type));
167 #endif
168     }
169     else if (Map->format == GV_FORMAT_POSTGIS) {
170 #ifndef HAVE_POSTGRES
171         G_warning(_("GRASS is not compiled with PostgreSQL support"));
172 #else
173         char stmt[DB_SQL_MAX];
174 
175         const struct Format_info_pg *pg_info;
176 
177         PGresult *res;
178 
179         pg_info = &(Map->fInfo.pg);
180         sprintf(stmt, "SELECT type,coord_dimension FROM geometry_columns "
181                 "WHERE f_table_schema = '%s' AND f_table_name = '%s'",
182                 pg_info->schema_name, pg_info->table_name);
183         G_debug(2, "SQL: %s", stmt);
184 
185         res = PQexec(pg_info->conn, stmt);
186         if (!res || PQresultStatus(res) != PGRES_TUPLES_OK ||
187             PQntuples(res) != 1) {
188             G_debug(1, "Unable to get feature type: %s",
189                     PQresultErrorMessage(res));
190             return NULL;
191         }
192         ftype_tmp = G_store(PQgetvalue(res, 0, 0));
193         dim = atoi(PQgetvalue(res, 0, 1));
194 
195         PQclear(res);
196 #endif
197     }
198 
199     if (!ftype_tmp)
200         return NULL;
201 
202     ftype = G_str_replace(ftype_tmp, " ", "");
203     G_free(ftype_tmp);
204     ftype_tmp = NULL;
205     G_str_to_lower(ftype);
206 
207     if (dim == 3) {
208         ftype_tmp = (char *) G_malloc(3 + strlen(ftype) + 1);
209         sprintf(ftype_tmp, "3D %s", ftype);
210         G_free(ftype);
211         ftype = ftype_tmp;
212     }
213 
214     return ftype;
215 }
216 
217 /*!
218   \brief Get header info for non-native formats
219 
220   \param Map pointer to Map_info structure
221 
222   \return pointer to Format_info structure
223   \return NULL for native format
224 */
Vect_get_finfo(const struct Map_info * Map)225 const struct Format_info* Vect_get_finfo(const struct Map_info *Map)
226 {
227     /* do not check Map-format which is native (see
228      * GRASS_VECTOR_EXTERNAL_IMMEDIATE) */
229 
230     if (Map->fInfo.ogr.driver_name || Map->fInfo.pg.conninfo)
231         return &(Map->fInfo);
232 
233     return NULL;
234 }
235 
236 /*!
237   \brief Get topology type (relevant only for non-native formats)
238 
239   \param Map pointer to Map_info structure
240   \param[out] toposchema Topology schema name or NULL
241   \param[out] topogeom   TopoGeometry column name or NULL
242   \param[out] topo_geo_only TRUE for Topo-Geo data model or NULL
243 
244   \return GV_TOPO_NATIVE for native format
245   \return GV_TOPO_PSEUDO for pseudo-topology
246   \return GV_TOPO_POSTGIS for PostGIS Topology
247 */
Vect_get_finfo_topology_info(const struct Map_info * Map,char ** toposchema,char ** topogeom,int * topo_geo_only)248 int Vect_get_finfo_topology_info(const struct Map_info *Map,
249                                  char **toposchema, char **topogeom, int* topo_geo_only)
250 {
251     if (Map->format == GV_FORMAT_OGR ||
252         Map->format == GV_FORMAT_OGR_DIRECT) {
253 #ifndef HAVE_OGR
254         G_warning(_("GRASS is not compiled with OGR support"));
255 #else
256         return GV_TOPO_PSEUDO;
257 #endif
258     }
259 
260     if (Map->format == GV_FORMAT_POSTGIS) {
261         const struct Format_info_pg *pg_info;
262 
263         pg_info = &(Map->fInfo.pg);
264         if (pg_info->toposchema_name) {
265             if (toposchema)
266                 *toposchema = G_store(pg_info->toposchema_name);
267             if (topogeom)
268                 *topogeom = G_store(pg_info->topogeom_column);
269             if (topo_geo_only)
270                 *topo_geo_only = pg_info->topo_geo_only;
271 
272             return GV_TOPO_POSTGIS;
273         }
274         else {
275             return GV_TOPO_PSEUDO;
276         }
277     }
278 
279     return GV_TOPO_NATIVE;
280 }
281