1
/******************************************************************************
2
* $Id: ogrmdblayer.cpp 22156 2011-04-13 20:08:07Z rouault $
4
* Project: OpenGIS Simple Features Reference Implementation
5
* Purpose: Implements OGRMDBLayer class
6
* Author: Even Rouault, <even dot rouault at mines dash paris dot org>
8
******************************************************************************
9
* Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
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:
18
* The above copyright notice and this permission notice shall be included
19
* in all copies or substantial portions of the Software.
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
****************************************************************************/
32
#include "cpl_string.h"
33
#include "ogrpgeogeometry.h"
34
#include "ogrgeomediageometry.h"
36
CPL_CVSID("$Id: ogrmdblayer.cpp 22156 2011-04-13 20:08:07Z rouault $");
38
/************************************************************************/
40
/************************************************************************/
42
OGRMDBLayer::OGRMDBLayer(OGRMDBDataSource* poDS, OGRMDBTable* poMDBTable)
46
this->poMDBTable = poMDBTable;
48
eGeometryType = MDB_GEOM_NONE;
54
panFieldOrdinals = NULL;
61
nSRSId = -2; // we haven't even queried the database for it yet.
66
/************************************************************************/
68
/************************************************************************/
70
OGRMDBLayer::~OGRMDBLayer()
73
if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
75
CPLDebug( "MDB", "%d features read on layer '%s'.",
76
(int) m_nFeaturesRead,
77
poFeatureDefn->GetName() );
80
if( poFeatureDefn != NULL )
82
poFeatureDefn->Release();
86
CPLFree( pszGeomColumn );
87
CPLFree( pszFIDColumn );
89
CPLFree( panFieldOrdinals );
100
/************************************************************************/
101
/* BuildFeatureDefn() */
103
/* Build feature definition from a set of column definitions */
104
/* set on a statement. Sift out geometry and FID fields. */
105
/************************************************************************/
107
CPLErr OGRMDBLayer::BuildFeatureDefn()
110
poFeatureDefn = new OGRFeatureDefn( poMDBTable->GetName() );
112
poFeatureDefn->Reference();
115
int nRawColumns = poMDBTable->GetColumnCount();
116
panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
118
for( int iCol = 0; iCol < nRawColumns; iCol++ )
120
const char* pszColName = poMDBTable->GetColumnName(iCol);
121
OGRFieldDefn oField(pszColName, OFTString );
123
if( pszGeomColumn != NULL
124
&& EQUAL(pszColName,pszGeomColumn) )
127
if( eGeometryType == MDB_GEOM_PGEO
128
&& pszFIDColumn == NULL
129
&& EQUAL(pszColName,"OBJECTID") )
131
pszFIDColumn = CPLStrdup(pszColName);
134
if( eGeometryType == MDB_GEOM_PGEO
135
&& pszGeomColumn == NULL
136
&& EQUAL(pszColName,"Shape") )
138
pszGeomColumn = CPLStrdup(pszColName);
142
switch( poMDBTable->GetColumnType(iCol) )
145
oField.SetType( OFTInteger );
152
oField.SetType( OFTInteger );
157
oField.SetType( OFTBinary );
162
oField.SetType( OFTReal );
166
oField.SetWidth(poMDBTable->GetColumnLength(iCol));
170
/* leave it as OFTString */;
173
poFeatureDefn->AddFieldDefn( &oField );
174
panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol+1;
181
/************************************************************************/
183
/************************************************************************/
185
void OGRMDBLayer::ResetReading()
189
poMDBTable->ResetReading();
192
/************************************************************************/
193
/* GetFeatureCount() */
194
/************************************************************************/
196
int OGRMDBLayer::GetFeatureCount(int bForce)
198
if (m_poFilterGeom != NULL || m_poAttrQuery != NULL)
199
return OGRLayer::GetFeatureCount(bForce);
200
return poMDBTable->GetRowCount();
203
/************************************************************************/
204
/* GetNextFeature() */
205
/************************************************************************/
207
OGRFeature *OGRMDBLayer::GetNextFeature()
212
OGRFeature *poFeature;
214
poFeature = GetNextRawFeature();
215
if( poFeature == NULL )
218
if( (m_poFilterGeom == NULL
219
|| FilterGeometry( poFeature->GetGeometryRef() ) )
220
&& (m_poAttrQuery == NULL
221
|| m_poAttrQuery->Evaluate( poFeature )) )
228
/************************************************************************/
229
/* GetNextRawFeature() */
230
/************************************************************************/
232
OGRFeature *OGRMDBLayer::GetNextRawFeature()
235
OGRErr err = OGRERR_NONE;
237
if( !poMDBTable->GetNextRow() )
240
/* -------------------------------------------------------------------- */
241
/* Create a feature from the current result. */
242
/* -------------------------------------------------------------------- */
244
OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
246
if( pszFIDColumn != NULL && poMDBTable->GetColumnIndex(pszFIDColumn) > -1 )
248
poMDBTable->GetColumnAsInt(poMDBTable->GetColumnIndex(pszFIDColumn)) );
250
poFeature->SetFID( iNextShapeId );
255
/* -------------------------------------------------------------------- */
256
/* Set the fields. */
257
/* -------------------------------------------------------------------- */
258
for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
260
int iSrcField = panFieldOrdinals[iField]-1;
261
char *pszValue = poMDBTable->GetColumnAsString( iSrcField );
262
OGRFieldType eType = poFeature->GetFieldDefnRef(iField)->GetType();
264
if( pszValue == NULL )
266
else if( eType == OFTBinary )
269
GByte* pData = poMDBTable->GetColumnAsBinary( iSrcField, &nBytes);
270
poFeature->SetField( iField,
275
else if ( eType == OFTInteger && EQUAL(pszValue, "true"))
277
poFeature->SetField( iField, 1 );
281
poFeature->SetField( iField, pszValue );
287
/* -------------------------------------------------------------------- */
288
/* Try to extract a geometry. */
289
/* -------------------------------------------------------------------- */
290
if( eGeometryType == MDB_GEOM_PGEO && iGeomColumn >= 0)
293
GByte* pData = poMDBTable->GetColumnAsBinary( iGeomColumn, &nBytes);
294
OGRGeometry *poGeom = NULL;
298
err = OGRCreateFromShapeBin( pData, &poGeom, nBytes );
299
if( OGRERR_NONE != err )
302
"Translation shape binary to OGR geometry failed (FID=%ld)",
303
(long)poFeature->GetFID() );
309
if( poGeom != NULL && OGRERR_NONE == err )
311
poGeom->assignSpatialReference( poSRS );
312
poFeature->SetGeometryDirectly( poGeom );
315
else if( eGeometryType == MDB_GEOM_GEOMEDIA && iGeomColumn >= 0)
318
GByte* pData = poMDBTable->GetColumnAsBinary( iGeomColumn, &nBytes);
319
OGRGeometry *poGeom = NULL;
323
err = OGRCreateFromGeomedia( pData, &poGeom, nBytes );
324
if( OGRERR_NONE != err )
327
"Translation geomedia binary to OGR geometry failed (FID=%ld)",
328
(long)poFeature->GetFID() );
334
if( poGeom != NULL && OGRERR_NONE == err )
336
poGeom->assignSpatialReference( poSRS );
337
poFeature->SetGeometryDirectly( poGeom );
344
/************************************************************************/
346
/************************************************************************/
348
OGRFeature *OGRMDBLayer::GetFeature( long nFeatureId )
351
/* This should be implemented directly! */
353
return OGRLayer::GetFeature( nFeatureId );
356
/************************************************************************/
357
/* TestCapability() */
358
/************************************************************************/
360
int OGRMDBLayer::TestCapability( const char * pszCap )
363
/*if( EQUAL(pszCap,OLCRandomRead) )
367
if( EQUAL(pszCap,OLCFastFeatureCount) ||
368
EQUAL(pszCap,OLCFastGetExtent) )
369
return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
375
/************************************************************************/
376
/* GetSpatialRef() */
377
/************************************************************************/
379
OGRSpatialReference *OGRMDBLayer::GetSpatialRef()
385
/************************************************************************/
387
/************************************************************************/
389
void OGRMDBLayer::LookupSRID( int nSRID )
392
/* -------------------------------------------------------------------- */
393
/* Fetch the corresponding WKT from the SpatialRef table. */
394
/* -------------------------------------------------------------------- */
395
OGRMDBDatabase* poDB = poMDBTable->GetDB();
396
OGRMDBTable* poSRSTable = poDB->GetTable("GDB_SpatialRefs");
397
if (poSRSTable == NULL)
400
int iSRTEXT = poSRSTable->GetColumnIndex("SRTEXT", TRUE);
401
int iSRID = poSRSTable->GetColumnIndex("SRID", TRUE);
403
if (iSRTEXT < 0 || iSRID < 0)
409
char* pszSRText = NULL;
410
while(poSRSTable->GetNextRow())
412
int nTableSRID = poSRSTable->GetColumnAsInt(iSRID);
413
if (nTableSRID == nSRID)
415
pszSRText = poSRSTable->GetColumnAsString(iSRTEXT);
420
if (pszSRText == NULL)
426
/* -------------------------------------------------------------------- */
427
/* Check that it isn't just a GUID. We don't know how to */
428
/* translate those. */
429
/* -------------------------------------------------------------------- */
431
if( pszSRText[0] == '{' )
433
CPLDebug( "MDB", "Ignoreing GUID SRTEXT: %s", pszSRText );
439
/* -------------------------------------------------------------------- */
440
/* Turn it into an OGRSpatialReference. */
441
/* -------------------------------------------------------------------- */
442
poSRS = new OGRSpatialReference();
444
char* pszSRTextPtr = pszSRText;
445
if( poSRS->importFromWkt( &pszSRTextPtr ) != OGRERR_NONE )
447
CPLError( CE_Failure, CPLE_AppDefined,
448
"importFromWKT() failed on SRS '%s'.",
453
else if( poSRS->morphFromESRI() != OGRERR_NONE )
455
CPLError( CE_Failure, CPLE_AppDefined,
456
"morphFromESRI() failed on SRS." );
467
/************************************************************************/
469
/************************************************************************/
471
const char *OGRMDBLayer::GetFIDColumn()
474
if( pszFIDColumn != NULL )
480
/************************************************************************/
481
/* GetGeometryColumn() */
482
/************************************************************************/
484
const char *OGRMDBLayer::GetGeometryColumn()
487
if( pszGeomColumn != NULL )
488
return pszGeomColumn;
494
/************************************************************************/
496
/************************************************************************/
498
CPLErr OGRMDBLayer::Initialize( const char *pszTableName,
499
const char *pszGeomCol,
502
double dfExtentRight,
503
double dfExtentBottom,
510
CPLFree( pszGeomColumn );
512
if( pszGeomCol == NULL )
513
pszGeomColumn = NULL;
516
pszGeomColumn = CPLStrdup( pszGeomCol );
517
iGeomColumn = poMDBTable->GetColumnIndex( pszGeomColumn );
520
CPLFree( pszFIDColumn );
524
sExtent.MinX = dfExtentLeft;
525
sExtent.MaxX = dfExtentRight;
526
sExtent.MinY = dfExtentBottom;
527
sExtent.MaxY = dfExtentTop;
531
eGeometryType = MDB_GEOM_PGEO;
534
eErr = BuildFeatureDefn();
535
if( eErr != CE_None )
538
/* -------------------------------------------------------------------- */
539
/* Setup geometry type. */
540
/* -------------------------------------------------------------------- */
541
OGRwkbGeometryType eOGRType;
545
case ESRI_LAYERGEOMTYPE_NULL:
549
case ESRI_LAYERGEOMTYPE_POINT:
553
case ESRI_LAYERGEOMTYPE_MULTIPOINT:
554
eOGRType = wkbMultiPoint;
557
case ESRI_LAYERGEOMTYPE_POLYLINE:
558
eOGRType = wkbLineString;
561
case ESRI_LAYERGEOMTYPE_POLYGON:
562
case ESRI_LAYERGEOMTYPE_MULTIPATCH:
563
eOGRType = wkbPolygon;
567
CPLDebug("MDB", "Unexpected value for shape type : %d", nShapeType);
568
eOGRType = wkbUnknown;
572
if( eOGRType != wkbUnknown && eOGRType != wkbNone && bHasZ )
573
eOGRType = (OGRwkbGeometryType)(((int) eOGRType) | wkb25DBit);
575
poFeatureDefn->SetGeomType(eOGRType);
581
/************************************************************************/
583
/************************************************************************/
585
CPLErr OGRMDBLayer::Initialize( const char *pszTableName,
586
const char *pszGeomCol,
587
OGRSpatialReference* poSRS )
591
CPLFree( pszGeomColumn );
593
if( pszGeomCol == NULL )
594
pszGeomColumn = NULL;
597
pszGeomColumn = CPLStrdup( pszGeomCol );
598
iGeomColumn = poMDBTable->GetColumnIndex( pszGeomColumn );
601
CPLFree( pszFIDColumn );
604
eGeometryType = MDB_GEOM_GEOMEDIA;
609
eErr = BuildFeatureDefn();
610
if( eErr != CE_None )
616
/************************************************************************/
618
/************************************************************************/
620
OGRErr OGRMDBLayer::GetExtent( OGREnvelope *psExtent, int bForce )
630
return OGRLayer::GetExtent(psExtent, bForce);