1 : /******************************************************************************
2 : * $Id: ogrinfo.cpp 18306 2009-12-15 18:57:11Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Simple client for viewing OGR driver data.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogr_api.h"
31 : #include "ogrsf_frmts.h"
32 : #include "ogr_p.h"
33 : #include "cpl_conv.h"
34 : #include "cpl_string.h"
35 : #include "cpl_multiproc.h"
36 :
37 : CPL_CVSID("$Id: ogrinfo.cpp 18306 2009-12-15 18:57:11Z rouault $");
38 :
39 : int bReadOnly = FALSE;
40 : int bVerbose = TRUE;
41 : int bSummaryOnly = FALSE;
42 : int nFetchFID = OGRNullFID;
43 : char** papszOptions = NULL;
44 :
45 : static void Usage();
46 :
47 : static void ReportOnLayer( OGRLayer *, const char *, OGRGeometry * );
48 :
49 : /************************************************************************/
50 : /* main() */
51 : /************************************************************************/
52 :
53 15 : int main( int nArgc, char ** papszArgv )
54 :
55 : {
56 15 : const char *pszWHERE = NULL;
57 15 : const char *pszDataSource = NULL;
58 15 : char **papszLayers = NULL;
59 15 : OGRGeometry *poSpatialFilter = NULL;
60 15 : int nRepeatCount = 1, bAllLayers = FALSE;
61 15 : const char *pszSQLStatement = NULL;
62 15 : const char *pszDialect = NULL;
63 :
64 : /* Check strict compilation and runtime library version as we use C++ API */
65 15 : if (! GDAL_CHECK_VERSION(papszArgv[0]))
66 0 : exit(1);
67 : /* -------------------------------------------------------------------- */
68 : /* Register format(s). */
69 : /* -------------------------------------------------------------------- */
70 15 : OGRRegisterAll();
71 :
72 : /* -------------------------------------------------------------------- */
73 : /* Processing command line arguments. */
74 : /* -------------------------------------------------------------------- */
75 15 : nArgc = OGRGeneralCmdLineProcessor( nArgc, &papszArgv, 0 );
76 :
77 15 : if( nArgc < 1 )
78 0 : exit( -nArgc );
79 :
80 47 : for( int iArg = 1; iArg < nArgc; iArg++ )
81 : {
82 33 : if( EQUAL(papszArgv[iArg], "--utility_version") )
83 : {
84 : printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
85 1 : papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
86 1 : return 0;
87 : }
88 32 : else if( EQUAL(papszArgv[iArg],"-ro") )
89 1 : bReadOnly = TRUE;
90 31 : else if( EQUAL(papszArgv[iArg],"-q") || EQUAL(papszArgv[iArg],"-quiet"))
91 0 : bVerbose = FALSE;
92 32 : else if( EQUAL(papszArgv[iArg],"-fid") && iArg < nArgc-1 )
93 1 : nFetchFID = atoi(papszArgv[++iArg]);
94 35 : else if( EQUAL(papszArgv[iArg],"-spat")
95 1 : && papszArgv[iArg+1] != NULL
96 1 : && papszArgv[iArg+2] != NULL
97 1 : && papszArgv[iArg+3] != NULL
98 1 : && papszArgv[iArg+4] != NULL )
99 : {
100 1 : OGRLinearRing oRing;
101 :
102 1 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
103 1 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+4]) );
104 1 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+4]) );
105 1 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+2]) );
106 1 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
107 :
108 1 : poSpatialFilter = new OGRPolygon();
109 1 : ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
110 1 : iArg += 4;
111 : }
112 30 : else if( EQUAL(papszArgv[iArg],"-where") && papszArgv[iArg+1] != NULL )
113 : {
114 1 : pszWHERE = papszArgv[++iArg];
115 : }
116 33 : else if( EQUAL(papszArgv[iArg],"-sql") && papszArgv[iArg+1] != NULL )
117 : {
118 5 : pszSQLStatement = papszArgv[++iArg];
119 : }
120 23 : else if( EQUAL(papszArgv[iArg],"-dialect")
121 0 : && papszArgv[iArg+1] != NULL )
122 : {
123 0 : pszDialect = papszArgv[++iArg];
124 : }
125 23 : else if( EQUAL(papszArgv[iArg],"-rc") && papszArgv[iArg+1] != NULL )
126 : {
127 0 : nRepeatCount = atoi(papszArgv[++iArg]);
128 : }
129 23 : else if( EQUAL(papszArgv[iArg],"-al") )
130 : {
131 1 : bAllLayers = TRUE;
132 : }
133 44 : else if( EQUAL(papszArgv[iArg],"-so")
134 22 : || EQUAL(papszArgv[iArg],"-summary") )
135 : {
136 0 : bSummaryOnly = TRUE;
137 : }
138 22 : else if( EQUALN(papszArgv[iArg],"-fields=", strlen("-fields=")) )
139 : {
140 1 : char* pszTemp = (char*)CPLMalloc(32 + strlen(papszArgv[iArg]));
141 1 : sprintf(pszTemp, "DISPLAY_FIELDS=%s", papszArgv[iArg] + strlen("-fields="));
142 1 : papszOptions = CSLAddString(papszOptions, pszTemp);
143 1 : CPLFree(pszTemp);
144 : }
145 21 : else if( EQUALN(papszArgv[iArg],"-geom=", strlen("-geom=")) )
146 : {
147 1 : char* pszTemp = (char*)CPLMalloc(32 + strlen(papszArgv[iArg]));
148 1 : sprintf(pszTemp, "DISPLAY_GEOMETRY=%s", papszArgv[iArg] + strlen("-geom="));
149 1 : papszOptions = CSLAddString(papszOptions, pszTemp);
150 1 : CPLFree(pszTemp);
151 : }
152 20 : else if( papszArgv[iArg][0] == '-' )
153 : {
154 0 : Usage();
155 : }
156 20 : else if( pszDataSource == NULL )
157 14 : pszDataSource = papszArgv[iArg];
158 : else
159 : {
160 6 : papszLayers = CSLAddString( papszLayers, papszArgv[iArg] );
161 6 : bAllLayers = FALSE;
162 : }
163 : }
164 :
165 14 : if( pszDataSource == NULL )
166 0 : Usage();
167 :
168 : /* -------------------------------------------------------------------- */
169 : /* Open data source. */
170 : /* -------------------------------------------------------------------- */
171 14 : OGRDataSource *poDS = NULL;
172 14 : OGRSFDriver *poDriver = NULL;
173 :
174 14 : poDS = OGRSFDriverRegistrar::Open( pszDataSource, !bReadOnly, &poDriver );
175 14 : if( poDS == NULL && !bReadOnly )
176 : {
177 0 : poDS = OGRSFDriverRegistrar::Open( pszDataSource, FALSE, &poDriver );
178 0 : if( poDS != NULL && bVerbose )
179 : {
180 0 : printf( "Had to open data source read-only.\n" );
181 0 : bReadOnly = TRUE;
182 : }
183 : }
184 :
185 : /* -------------------------------------------------------------------- */
186 : /* Report failure */
187 : /* -------------------------------------------------------------------- */
188 14 : if( poDS == NULL )
189 : {
190 0 : OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
191 :
192 : printf( "FAILURE:\n"
193 : "Unable to open datasource `%s' with the following drivers.\n",
194 0 : pszDataSource );
195 :
196 0 : for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
197 : {
198 0 : printf( " -> %s\n", poR->GetDriver(iDriver)->GetName() );
199 : }
200 :
201 0 : exit( 1 );
202 : }
203 :
204 : CPLAssert( poDriver != NULL);
205 :
206 : /* -------------------------------------------------------------------- */
207 : /* Some information messages. */
208 : /* -------------------------------------------------------------------- */
209 14 : if( bVerbose )
210 : printf( "INFO: Open of `%s'\n"
211 : " using driver `%s' successful.\n",
212 14 : pszDataSource, poDriver->GetName() );
213 :
214 14 : if( bVerbose && !EQUAL(pszDataSource,poDS->GetName()) )
215 : {
216 : printf( "INFO: Internal data source name `%s'\n"
217 : " different from user name `%s'.\n",
218 0 : poDS->GetName(), pszDataSource );
219 : }
220 :
221 : /* -------------------------------------------------------------------- */
222 : /* Special case for -sql clause. No source layers required. */
223 : /* -------------------------------------------------------------------- */
224 14 : if( pszSQLStatement != NULL )
225 : {
226 5 : OGRLayer *poResultSet = NULL;
227 :
228 5 : nRepeatCount = 0; // skip layer reporting.
229 :
230 5 : if( CSLCount(papszLayers) > 0 )
231 0 : printf( "layer names ignored in combination with -sql.\n" );
232 :
233 : poResultSet = poDS->ExecuteSQL( pszSQLStatement, poSpatialFilter,
234 5 : pszDialect );
235 :
236 5 : if( poResultSet != NULL )
237 : {
238 1 : if( pszWHERE != NULL )
239 0 : poResultSet->SetAttributeFilter( pszWHERE );
240 :
241 1 : ReportOnLayer( poResultSet, NULL, NULL );
242 1 : poDS->ReleaseResultSet( poResultSet );
243 : }
244 : }
245 :
246 14 : CPLDebug( "OGR", "GetLayerCount() = %d\n", poDS->GetLayerCount() );
247 :
248 23 : for( int iRepeat = 0; iRepeat < nRepeatCount; iRepeat++ )
249 : {
250 9 : if ( CSLCount(papszLayers) == 0 )
251 : {
252 : /* -------------------------------------------------------------------- */
253 : /* Process each data source layer. */
254 : /* -------------------------------------------------------------------- */
255 6 : for( int iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++ )
256 : {
257 3 : OGRLayer *poLayer = poDS->GetLayer(iLayer);
258 :
259 3 : if( poLayer == NULL )
260 : {
261 : printf( "FAILURE: Couldn't fetch advertised layer %d!\n",
262 0 : iLayer );
263 0 : exit( 1 );
264 : }
265 :
266 3 : if (!bAllLayers)
267 : {
268 : printf( "%d: %s",
269 : iLayer+1,
270 2 : poLayer->GetLayerDefn()->GetName() );
271 :
272 2 : if( poLayer->GetLayerDefn()->GetGeomType() != wkbUnknown )
273 : printf( " (%s)",
274 : OGRGeometryTypeToName(
275 2 : poLayer->GetLayerDefn()->GetGeomType() ) );
276 :
277 2 : printf( "\n" );
278 : }
279 : else
280 : {
281 1 : if( iRepeat != 0 )
282 0 : poLayer->ResetReading();
283 :
284 1 : ReportOnLayer( poLayer, pszWHERE, poSpatialFilter );
285 : }
286 : }
287 : }
288 : else
289 : {
290 : /* -------------------------------------------------------------------- */
291 : /* Process specified data source layers. */
292 : /* -------------------------------------------------------------------- */
293 6 : char** papszIter = papszLayers;
294 12 : for( ; *papszIter != NULL; papszIter++ )
295 : {
296 6 : OGRLayer *poLayer = poDS->GetLayerByName(*papszIter);
297 :
298 6 : if( poLayer == NULL )
299 : {
300 : printf( "FAILURE: Couldn't fetch requested layer %s!\n",
301 0 : *papszIter );
302 0 : exit( 1 );
303 : }
304 :
305 6 : if( iRepeat != 0 )
306 0 : poLayer->ResetReading();
307 :
308 6 : ReportOnLayer( poLayer, pszWHERE, poSpatialFilter );
309 : }
310 : }
311 : }
312 :
313 : /* -------------------------------------------------------------------- */
314 : /* Close down. */
315 : /* -------------------------------------------------------------------- */
316 14 : CSLDestroy( papszArgv );
317 14 : CSLDestroy( papszLayers );
318 14 : CSLDestroy( papszOptions );
319 14 : OGRDataSource::DestroyDataSource( poDS );
320 14 : if (poSpatialFilter)
321 1 : OGRGeometryFactory::destroyGeometry( poSpatialFilter );
322 :
323 14 : OGRCleanupAll();
324 :
325 14 : return 0;
326 : }
327 :
328 : /************************************************************************/
329 : /* Usage() */
330 : /************************************************************************/
331 :
332 0 : static void Usage()
333 :
334 : {
335 : printf( "Usage: ogrinfo [--help-general] [-ro] [-q] [-where restricted_where]\n"
336 : " [-spat xmin ymin xmax ymax] [-fid fid]\n"
337 : " [-sql statement] [-al] [-so] [-fields={YES/NO}]\n"
338 : " [-geom={YES/NO/SUMMARY}][--formats]\n"
339 0 : " datasource_name [layer [layer ...]]\n");
340 0 : exit( 1 );
341 : }
342 :
343 : /************************************************************************/
344 : /* ReportOnLayer() */
345 : /************************************************************************/
346 :
347 8 : static void ReportOnLayer( OGRLayer * poLayer, const char *pszWHERE,
348 : OGRGeometry *poSpatialFilter )
349 :
350 : {
351 8 : OGRFeatureDefn *poDefn = poLayer->GetLayerDefn();
352 :
353 : /* -------------------------------------------------------------------- */
354 : /* Set filters if provided. */
355 : /* -------------------------------------------------------------------- */
356 8 : if( pszWHERE != NULL )
357 1 : poLayer->SetAttributeFilter( pszWHERE );
358 :
359 8 : if( poSpatialFilter != NULL )
360 1 : poLayer->SetSpatialFilter( poSpatialFilter );
361 :
362 : /* -------------------------------------------------------------------- */
363 : /* Report various overall information. */
364 : /* -------------------------------------------------------------------- */
365 8 : printf( "\n" );
366 :
367 8 : printf( "Layer name: %s\n", poDefn->GetName() );
368 :
369 8 : if( bVerbose )
370 : {
371 : printf( "Geometry: %s\n",
372 8 : OGRGeometryTypeToName( poDefn->GetGeomType() ) );
373 :
374 8 : printf( "Feature Count: %d\n", poLayer->GetFeatureCount() );
375 :
376 8 : OGREnvelope oExt;
377 8 : if (poLayer->GetExtent(&oExt, TRUE) == OGRERR_NONE)
378 : {
379 : printf("Extent: (%f, %f) - (%f, %f)\n",
380 8 : oExt.MinX, oExt.MinY, oExt.MaxX, oExt.MaxY);
381 : }
382 :
383 : char *pszWKT;
384 :
385 8 : if( poLayer->GetSpatialRef() == NULL )
386 0 : pszWKT = CPLStrdup( "(unknown)" );
387 : else
388 : {
389 8 : poLayer->GetSpatialRef()->exportToPrettyWkt( &pszWKT );
390 : }
391 :
392 8 : printf( "Layer SRS WKT:\n%s\n", pszWKT );
393 8 : CPLFree( pszWKT );
394 :
395 8 : if( strlen(poLayer->GetFIDColumn()) > 0 )
396 : printf( "FID Column = %s\n",
397 0 : poLayer->GetFIDColumn() );
398 :
399 8 : if( strlen(poLayer->GetGeometryColumn()) > 0 )
400 : printf( "Geometry Column = %s\n",
401 0 : poLayer->GetGeometryColumn() );
402 :
403 32 : for( int iAttr = 0; iAttr < poDefn->GetFieldCount(); iAttr++ )
404 : {
405 24 : OGRFieldDefn *poField = poDefn->GetFieldDefn( iAttr );
406 :
407 : printf( "%s: %s (%d.%d)\n",
408 : poField->GetNameRef(),
409 : poField->GetFieldTypeName( poField->GetType() ),
410 : poField->GetWidth(),
411 24 : poField->GetPrecision() );
412 : }
413 : }
414 :
415 : /* -------------------------------------------------------------------- */
416 : /* Read, and dump features. */
417 : /* -------------------------------------------------------------------- */
418 8 : OGRFeature *poFeature = NULL;
419 :
420 15 : if( nFetchFID == OGRNullFID && !bSummaryOnly )
421 : {
422 69 : while( (poFeature = poLayer->GetNextFeature()) != NULL )
423 : {
424 55 : poFeature->DumpReadable( NULL, papszOptions );
425 55 : OGRFeature::DestroyFeature( poFeature );
426 : }
427 : }
428 1 : else if( nFetchFID != OGRNullFID )
429 : {
430 1 : poFeature = poLayer->GetFeature( nFetchFID );
431 1 : if( poFeature == NULL )
432 : {
433 : printf( "Unable to locate feature id %d on this layer.\n",
434 0 : nFetchFID );
435 : }
436 : else
437 : {
438 1 : poFeature->DumpReadable( NULL, papszOptions );
439 1 : OGRFeature::DestroyFeature( poFeature );
440 : }
441 : }
442 8 : }
|