1 : /******************************************************************************
2 : * $Id: ogrinfo.cpp 25582 2013-01-29 21:13:43Z 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 : #include "commonutils.h"
37 :
38 : CPL_CVSID("$Id: ogrinfo.cpp 25582 2013-01-29 21:13:43Z rouault $");
39 :
40 : int bReadOnly = FALSE;
41 : int bVerbose = TRUE;
42 : int bSummaryOnly = FALSE;
43 : int nFetchFID = OGRNullFID;
44 : char** papszOptions = NULL;
45 :
46 : static void Usage(const char* pszErrorMsg = NULL);
47 :
48 : static void ReportOnLayer( OGRLayer *, const char *, OGRGeometry * );
49 :
50 : /************************************************************************/
51 : /* main() */
52 : /************************************************************************/
53 :
54 : #define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
55 : do { if (iArg + nExtraArg >= nArgc) \
56 : Usage(CPLSPrintf("%s option requires %d argument(s)", papszArgv[iArg], nExtraArg)); } while(0)
57 :
58 32 : int main( int nArgc, char ** papszArgv )
59 :
60 : {
61 32 : const char *pszWHERE = NULL;
62 32 : const char *pszDataSource = NULL;
63 32 : char **papszLayers = NULL;
64 32 : OGRGeometry *poSpatialFilter = NULL;
65 32 : int nRepeatCount = 1, bAllLayers = FALSE;
66 32 : const char *pszSQLStatement = NULL;
67 32 : const char *pszDialect = NULL;
68 32 : int nRet = 0;
69 :
70 : /* Check strict compilation and runtime library version as we use C++ API */
71 32 : if (! GDAL_CHECK_VERSION(papszArgv[0]))
72 0 : exit(1);
73 :
74 32 : EarlySetConfigOptions(nArgc, papszArgv);
75 :
76 : /* -------------------------------------------------------------------- */
77 : /* Register format(s). */
78 : /* -------------------------------------------------------------------- */
79 32 : OGRRegisterAll();
80 :
81 : /* -------------------------------------------------------------------- */
82 : /* Processing command line arguments. */
83 : /* -------------------------------------------------------------------- */
84 32 : nArgc = OGRGeneralCmdLineProcessor( nArgc, &papszArgv, 0 );
85 :
86 32 : if( nArgc < 1 )
87 8 : exit( -nArgc );
88 :
89 73 : for( int iArg = 1; iArg < nArgc; iArg++ )
90 : {
91 50 : if( EQUAL(papszArgv[iArg], "--utility_version") )
92 : {
93 : printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
94 1 : papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
95 1 : return 0;
96 : }
97 49 : else if( EQUAL(papszArgv[iArg],"--help") )
98 0 : Usage();
99 49 : else if( EQUAL(papszArgv[iArg],"-ro") )
100 2 : bReadOnly = TRUE;
101 47 : else if( EQUAL(papszArgv[iArg],"-q") || EQUAL(papszArgv[iArg],"-quiet"))
102 0 : bVerbose = FALSE;
103 47 : else if( EQUAL(papszArgv[iArg],"-fid") )
104 : {
105 1 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
106 1 : nFetchFID = atoi(papszArgv[++iArg]);
107 : }
108 46 : else if( EQUAL(papszArgv[iArg],"-spat") )
109 : {
110 1 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4);
111 1 : OGRLinearRing oRing;
112 :
113 1 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
114 1 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+4]) );
115 1 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+4]) );
116 1 : oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+2]) );
117 1 : oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
118 :
119 1 : poSpatialFilter = new OGRPolygon();
120 1 : ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
121 1 : iArg += 4;
122 : }
123 45 : else if( EQUAL(papszArgv[iArg],"-where") )
124 : {
125 1 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
126 1 : pszWHERE = papszArgv[++iArg];
127 : }
128 44 : else if( EQUAL(papszArgv[iArg],"-sql") )
129 : {
130 9 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
131 9 : pszSQLStatement = papszArgv[++iArg];
132 : }
133 35 : else if( EQUAL(papszArgv[iArg],"-dialect") )
134 : {
135 0 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
136 0 : pszDialect = papszArgv[++iArg];
137 : }
138 35 : else if( EQUAL(papszArgv[iArg],"-rc") )
139 : {
140 0 : CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
141 0 : nRepeatCount = atoi(papszArgv[++iArg]);
142 : }
143 35 : else if( EQUAL(papszArgv[iArg],"-al") )
144 : {
145 2 : bAllLayers = TRUE;
146 : }
147 66 : else if( EQUAL(papszArgv[iArg],"-so")
148 33 : || EQUAL(papszArgv[iArg],"-summary") )
149 : {
150 0 : bSummaryOnly = TRUE;
151 : }
152 33 : else if( EQUALN(papszArgv[iArg],"-fields=", strlen("-fields=")) )
153 : {
154 1 : char* pszTemp = (char*)CPLMalloc(32 + strlen(papszArgv[iArg]));
155 1 : sprintf(pszTemp, "DISPLAY_FIELDS=%s", papszArgv[iArg] + strlen("-fields="));
156 1 : papszOptions = CSLAddString(papszOptions, pszTemp);
157 1 : CPLFree(pszTemp);
158 : }
159 32 : else if( EQUALN(papszArgv[iArg],"-geom=", strlen("-geom=")) )
160 : {
161 2 : char* pszTemp = (char*)CPLMalloc(32 + strlen(papszArgv[iArg]));
162 2 : sprintf(pszTemp, "DISPLAY_GEOMETRY=%s", papszArgv[iArg] + strlen("-geom="));
163 2 : papszOptions = CSLAddString(papszOptions, pszTemp);
164 2 : CPLFree(pszTemp);
165 : }
166 30 : else if( papszArgv[iArg][0] == '-' )
167 : {
168 0 : Usage(CPLSPrintf("Unkown option name '%s'", papszArgv[iArg]));
169 : }
170 30 : else if( pszDataSource == NULL )
171 23 : pszDataSource = papszArgv[iArg];
172 : else
173 : {
174 7 : papszLayers = CSLAddString( papszLayers, papszArgv[iArg] );
175 7 : bAllLayers = FALSE;
176 : }
177 : }
178 :
179 23 : if( pszDataSource == NULL )
180 0 : Usage("No datasource specified.");
181 :
182 : /* -------------------------------------------------------------------- */
183 : /* Open data source. */
184 : /* -------------------------------------------------------------------- */
185 23 : OGRDataSource *poDS = NULL;
186 23 : OGRSFDriver *poDriver = NULL;
187 :
188 23 : poDS = OGRSFDriverRegistrar::Open( pszDataSource, !bReadOnly, &poDriver );
189 23 : if( poDS == NULL && !bReadOnly )
190 : {
191 0 : poDS = OGRSFDriverRegistrar::Open( pszDataSource, FALSE, &poDriver );
192 0 : if( poDS != NULL && bVerbose )
193 : {
194 0 : printf( "Had to open data source read-only.\n" );
195 0 : bReadOnly = TRUE;
196 : }
197 : }
198 :
199 : /* -------------------------------------------------------------------- */
200 : /* Report failure */
201 : /* -------------------------------------------------------------------- */
202 23 : if( poDS == NULL )
203 : {
204 0 : OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
205 :
206 : printf( "FAILURE:\n"
207 : "Unable to open datasource `%s' with the following drivers.\n",
208 0 : pszDataSource );
209 :
210 0 : for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
211 : {
212 0 : printf( " -> %s\n", poR->GetDriver(iDriver)->GetName() );
213 : }
214 :
215 0 : nRet = 1;
216 0 : goto end;
217 : }
218 :
219 23 : CPLAssert( poDriver != NULL);
220 :
221 : /* -------------------------------------------------------------------- */
222 : /* Some information messages. */
223 : /* -------------------------------------------------------------------- */
224 23 : if( bVerbose )
225 : printf( "INFO: Open of `%s'\n"
226 : " using driver `%s' successful.\n",
227 23 : pszDataSource, poDriver->GetName() );
228 :
229 23 : if( bVerbose && !EQUAL(pszDataSource,poDS->GetName()) )
230 : {
231 : printf( "INFO: Internal data source name `%s'\n"
232 : " different from user name `%s'.\n",
233 1 : poDS->GetName(), pszDataSource );
234 : }
235 :
236 : /* -------------------------------------------------------------------- */
237 : /* Special case for -sql clause. No source layers required. */
238 : /* -------------------------------------------------------------------- */
239 23 : if( pszSQLStatement != NULL )
240 : {
241 9 : OGRLayer *poResultSet = NULL;
242 :
243 9 : nRepeatCount = 0; // skip layer reporting.
244 :
245 9 : if( CSLCount(papszLayers) > 0 )
246 0 : printf( "layer names ignored in combination with -sql.\n" );
247 :
248 : poResultSet = poDS->ExecuteSQL( pszSQLStatement, poSpatialFilter,
249 9 : pszDialect );
250 :
251 9 : if( poResultSet != NULL )
252 : {
253 1 : if( pszWHERE != NULL )
254 : {
255 0 : if (poResultSet->SetAttributeFilter( pszWHERE ) != OGRERR_NONE )
256 : {
257 0 : printf( "FAILURE: SetAttributeFilter(%s) failed.\n", pszWHERE );
258 0 : exit(1);
259 : }
260 : }
261 :
262 1 : ReportOnLayer( poResultSet, NULL, NULL );
263 1 : poDS->ReleaseResultSet( poResultSet );
264 : }
265 : }
266 :
267 23 : CPLDebug( "OGR", "GetLayerCount() = %d\n", poDS->GetLayerCount() );
268 :
269 37 : for( int iRepeat = 0; iRepeat < nRepeatCount; iRepeat++ )
270 : {
271 14 : if ( CSLCount(papszLayers) == 0 )
272 : {
273 : /* -------------------------------------------------------------------- */
274 : /* Process each data source layer. */
275 : /* -------------------------------------------------------------------- */
276 14 : for( int iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++ )
277 : {
278 7 : OGRLayer *poLayer = poDS->GetLayer(iLayer);
279 :
280 7 : if( poLayer == NULL )
281 : {
282 : printf( "FAILURE: Couldn't fetch advertised layer %d!\n",
283 0 : iLayer );
284 0 : exit( 1 );
285 : }
286 :
287 7 : if (!bAllLayers)
288 : {
289 : printf( "%d: %s",
290 : iLayer+1,
291 5 : poLayer->GetName() );
292 :
293 5 : if( poLayer->GetGeomType() != wkbUnknown )
294 : printf( " (%s)",
295 : OGRGeometryTypeToName(
296 5 : poLayer->GetGeomType() ) );
297 :
298 5 : printf( "\n" );
299 : }
300 : else
301 : {
302 2 : if( iRepeat != 0 )
303 0 : poLayer->ResetReading();
304 :
305 2 : ReportOnLayer( poLayer, pszWHERE, poSpatialFilter );
306 : }
307 : }
308 : }
309 : else
310 : {
311 : /* -------------------------------------------------------------------- */
312 : /* Process specified data source layers. */
313 : /* -------------------------------------------------------------------- */
314 7 : char** papszIter = papszLayers;
315 14 : for( ; *papszIter != NULL; papszIter++ )
316 : {
317 7 : OGRLayer *poLayer = poDS->GetLayerByName(*papszIter);
318 :
319 7 : if( poLayer == NULL )
320 : {
321 : printf( "FAILURE: Couldn't fetch requested layer %s!\n",
322 0 : *papszIter );
323 0 : exit( 1 );
324 : }
325 :
326 7 : if( iRepeat != 0 )
327 0 : poLayer->ResetReading();
328 :
329 7 : ReportOnLayer( poLayer, pszWHERE, poSpatialFilter );
330 : }
331 : }
332 : }
333 :
334 : /* -------------------------------------------------------------------- */
335 : /* Close down. */
336 : /* -------------------------------------------------------------------- */
337 : end:
338 23 : CSLDestroy( papszArgv );
339 23 : CSLDestroy( papszLayers );
340 23 : CSLDestroy( papszOptions );
341 23 : OGRDataSource::DestroyDataSource( poDS );
342 23 : if (poSpatialFilter)
343 1 : OGRGeometryFactory::destroyGeometry( poSpatialFilter );
344 :
345 23 : OGRCleanupAll();
346 :
347 23 : return nRet;
348 : }
349 :
350 : /************************************************************************/
351 : /* Usage() */
352 : /************************************************************************/
353 :
354 0 : static void Usage(const char* pszErrorMsg)
355 :
356 : {
357 : printf( "Usage: ogrinfo [--help-general] [-ro] [-q] [-where restricted_where]\n"
358 : " [-spat xmin ymin xmax ymax] [-fid fid]\n"
359 : " [-sql statement] [-dialect sql_dialect] [-al] [-so] [-fields={YES/NO}]\n"
360 : " [-geom={YES/NO/SUMMARY}][--formats]\n"
361 0 : " datasource_name [layer [layer ...]]\n");
362 :
363 0 : if( pszErrorMsg != NULL )
364 0 : fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
365 :
366 0 : exit( 1 );
367 : }
368 :
369 : /************************************************************************/
370 : /* ReportOnLayer() */
371 : /************************************************************************/
372 :
373 10 : static void ReportOnLayer( OGRLayer * poLayer, const char *pszWHERE,
374 : OGRGeometry *poSpatialFilter )
375 :
376 : {
377 10 : OGRFeatureDefn *poDefn = poLayer->GetLayerDefn();
378 :
379 : /* -------------------------------------------------------------------- */
380 : /* Set filters if provided. */
381 : /* -------------------------------------------------------------------- */
382 10 : if( pszWHERE != NULL )
383 : {
384 1 : if (poLayer->SetAttributeFilter( pszWHERE ) != OGRERR_NONE )
385 : {
386 0 : printf( "FAILURE: SetAttributeFilter(%s) failed.\n", pszWHERE );
387 0 : exit(1);
388 : }
389 : }
390 :
391 10 : if( poSpatialFilter != NULL )
392 1 : poLayer->SetSpatialFilter( poSpatialFilter );
393 :
394 : /* -------------------------------------------------------------------- */
395 : /* Report various overall information. */
396 : /* -------------------------------------------------------------------- */
397 10 : printf( "\n" );
398 :
399 10 : printf( "Layer name: %s\n", poLayer->GetName() );
400 :
401 10 : if( bVerbose )
402 : {
403 : printf( "Geometry: %s\n",
404 10 : OGRGeometryTypeToName( poLayer->GetGeomType() ) );
405 :
406 10 : printf( "Feature Count: %d\n", poLayer->GetFeatureCount() );
407 :
408 10 : OGREnvelope oExt;
409 10 : if (poLayer->GetExtent(&oExt, TRUE) == OGRERR_NONE)
410 : {
411 : printf("Extent: (%f, %f) - (%f, %f)\n",
412 10 : oExt.MinX, oExt.MinY, oExt.MaxX, oExt.MaxY);
413 : }
414 :
415 : char *pszWKT;
416 :
417 10 : if( poLayer->GetSpatialRef() == NULL )
418 0 : pszWKT = CPLStrdup( "(unknown)" );
419 : else
420 : {
421 10 : poLayer->GetSpatialRef()->exportToPrettyWkt( &pszWKT );
422 : }
423 :
424 10 : printf( "Layer SRS WKT:\n%s\n", pszWKT );
425 10 : CPLFree( pszWKT );
426 :
427 10 : if( strlen(poLayer->GetFIDColumn()) > 0 )
428 : printf( "FID Column = %s\n",
429 0 : poLayer->GetFIDColumn() );
430 :
431 10 : if( strlen(poLayer->GetGeometryColumn()) > 0 )
432 : printf( "Geometry Column = %s\n",
433 0 : poLayer->GetGeometryColumn() );
434 :
435 37 : for( int iAttr = 0; iAttr < poDefn->GetFieldCount(); iAttr++ )
436 : {
437 27 : OGRFieldDefn *poField = poDefn->GetFieldDefn( iAttr );
438 :
439 : printf( "%s: %s (%d.%d)\n",
440 : poField->GetNameRef(),
441 : poField->GetFieldTypeName( poField->GetType() ),
442 : poField->GetWidth(),
443 27 : poField->GetPrecision() );
444 : }
445 : }
446 :
447 : /* -------------------------------------------------------------------- */
448 : /* Read, and dump features. */
449 : /* -------------------------------------------------------------------- */
450 10 : OGRFeature *poFeature = NULL;
451 :
452 19 : if( nFetchFID == OGRNullFID && !bSummaryOnly )
453 : {
454 84 : while( (poFeature = poLayer->GetNextFeature()) != NULL )
455 : {
456 66 : poFeature->DumpReadable( NULL, papszOptions );
457 66 : OGRFeature::DestroyFeature( poFeature );
458 : }
459 : }
460 1 : else if( nFetchFID != OGRNullFID )
461 : {
462 1 : poFeature = poLayer->GetFeature( nFetchFID );
463 1 : if( poFeature == NULL )
464 : {
465 : printf( "Unable to locate feature id %d on this layer.\n",
466 0 : nFetchFID );
467 : }
468 : else
469 : {
470 1 : poFeature->DumpReadable( NULL, papszOptions );
471 1 : OGRFeature::DestroyFeature( poFeature );
472 : }
473 : }
474 10 : }
|