1 : /******************************************************************************
2 : * $Id: ogrpgeolayer.cpp 21540 2011-01-22 00:06:04Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements OGRPGeoLayer class, code shared between
6 : * the direct table access, and the generic SQL results.
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "cpl_conv.h"
32 : #include "ogr_pgeo.h"
33 : #include "cpl_string.h"
34 : #include "ogrpgeogeometry.h"
35 :
36 : CPL_CVSID("$Id: ogrpgeolayer.cpp 21540 2011-01-22 00:06:04Z rouault $");
37 :
38 : /************************************************************************/
39 : /* OGRPGeoLayer() */
40 : /************************************************************************/
41 :
42 0 : OGRPGeoLayer::OGRPGeoLayer()
43 :
44 : {
45 0 : poDS = NULL;
46 :
47 0 : pszGeomColumn = NULL;
48 0 : pszFIDColumn = NULL;
49 :
50 0 : poStmt = NULL;
51 :
52 0 : iNextShapeId = 0;
53 :
54 0 : poSRS = NULL;
55 0 : nSRSId = -2; // we haven't even queried the database for it yet.
56 0 : }
57 :
58 : /************************************************************************/
59 : /* ~OGRPGeoLayer() */
60 : /************************************************************************/
61 :
62 0 : OGRPGeoLayer::~OGRPGeoLayer()
63 :
64 : {
65 0 : if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
66 : {
67 : CPLDebug( "PGeo", "%d features read on layer '%s'.",
68 : (int) m_nFeaturesRead,
69 0 : poFeatureDefn->GetName() );
70 : }
71 :
72 0 : if( poStmt != NULL )
73 : {
74 0 : delete poStmt;
75 0 : poStmt = NULL;
76 : }
77 :
78 0 : if( poFeatureDefn != NULL )
79 : {
80 0 : poFeatureDefn->Release();
81 0 : poFeatureDefn = NULL;
82 : }
83 :
84 0 : CPLFree( pszGeomColumn );
85 0 : CPLFree( panFieldOrdinals );
86 0 : CPLFree( pszFIDColumn );
87 :
88 0 : if( poSRS != NULL )
89 : {
90 0 : poSRS->Release();
91 0 : poSRS = NULL;
92 : }
93 0 : }
94 :
95 : /************************************************************************/
96 : /* BuildFeatureDefn() */
97 : /* */
98 : /* Build feature definition from a set of column definitions */
99 : /* set on a statement. Sift out geometry and FID fields. */
100 : /************************************************************************/
101 :
102 0 : CPLErr OGRPGeoLayer::BuildFeatureDefn( const char *pszLayerName,
103 : CPLODBCStatement *poStmt )
104 :
105 : {
106 0 : poFeatureDefn = new OGRFeatureDefn( pszLayerName );
107 0 : int nRawColumns = poStmt->GetColCount();
108 :
109 0 : poFeatureDefn->Reference();
110 :
111 0 : panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
112 :
113 0 : for( int iCol = 0; iCol < nRawColumns; iCol++ )
114 : {
115 0 : OGRFieldDefn oField( poStmt->GetColName(iCol), OFTString );
116 :
117 0 : oField.SetWidth( MAX(0,poStmt->GetColSize( iCol )) );
118 :
119 0 : if( pszGeomColumn != NULL
120 : && EQUAL(poStmt->GetColName(iCol),pszGeomColumn) )
121 0 : continue;
122 :
123 0 : if( pszFIDColumn == NULL
124 : && EQUAL(poStmt->GetColName(iCol),"OBJECTID") )
125 : {
126 0 : pszFIDColumn = CPLStrdup(poStmt->GetColName(iCol));
127 : }
128 :
129 0 : if( pszGeomColumn == NULL
130 : && EQUAL(poStmt->GetColName(iCol),"Shape") )
131 : {
132 0 : pszGeomColumn = CPLStrdup(poStmt->GetColName(iCol));
133 0 : continue;
134 : }
135 :
136 0 : switch( poStmt->GetColType(iCol) )
137 : {
138 : case SQL_INTEGER:
139 : case SQL_SMALLINT:
140 0 : oField.SetType( OFTInteger );
141 0 : break;
142 :
143 : case SQL_BINARY:
144 : case SQL_VARBINARY:
145 : case SQL_LONGVARBINARY:
146 0 : oField.SetType( OFTBinary );
147 0 : break;
148 :
149 : case SQL_DECIMAL:
150 0 : oField.SetType( OFTReal );
151 0 : oField.SetPrecision( poStmt->GetColPrecision(iCol) );
152 0 : break;
153 :
154 : case SQL_FLOAT:
155 : case SQL_REAL:
156 : case SQL_DOUBLE:
157 0 : oField.SetType( OFTReal );
158 0 : oField.SetWidth( 0 );
159 0 : break;
160 :
161 : case SQL_C_DATE:
162 0 : oField.SetType( OFTDate );
163 0 : break;
164 :
165 : case SQL_C_TIME:
166 0 : oField.SetType( OFTTime );
167 0 : break;
168 :
169 : case SQL_C_TIMESTAMP:
170 0 : oField.SetType( OFTDateTime );
171 : break;
172 :
173 : default:
174 : /* leave it as OFTString */;
175 : }
176 :
177 0 : poFeatureDefn->AddFieldDefn( &oField );
178 0 : panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol+1;
179 : }
180 :
181 0 : return CE_None;
182 : }
183 :
184 :
185 : /************************************************************************/
186 : /* ResetReading() */
187 : /************************************************************************/
188 :
189 0 : void OGRPGeoLayer::ResetReading()
190 :
191 : {
192 0 : iNextShapeId = 0;
193 0 : }
194 :
195 : /************************************************************************/
196 : /* GetNextFeature() */
197 : /************************************************************************/
198 :
199 0 : OGRFeature *OGRPGeoLayer::GetNextFeature()
200 :
201 : {
202 0 : for( ; TRUE; )
203 : {
204 : OGRFeature *poFeature;
205 :
206 0 : poFeature = GetNextRawFeature();
207 0 : if( poFeature == NULL )
208 0 : return NULL;
209 :
210 0 : if( (m_poFilterGeom == NULL
211 : || FilterGeometry( poFeature->GetGeometryRef() ) )
212 : && (m_poAttrQuery == NULL
213 : || m_poAttrQuery->Evaluate( poFeature )) )
214 0 : return poFeature;
215 :
216 0 : delete poFeature;
217 : }
218 : }
219 :
220 : /************************************************************************/
221 : /* GetNextRawFeature() */
222 : /************************************************************************/
223 :
224 0 : OGRFeature *OGRPGeoLayer::GetNextRawFeature()
225 :
226 : {
227 0 : OGRErr err = OGRERR_NONE;
228 :
229 0 : if( GetStatement() == NULL )
230 0 : return NULL;
231 :
232 : /* -------------------------------------------------------------------- */
233 : /* If we are marked to restart then do so, and fetch a record. */
234 : /* -------------------------------------------------------------------- */
235 0 : if( !poStmt->Fetch() )
236 : {
237 0 : delete poStmt;
238 0 : poStmt = NULL;
239 0 : return NULL;
240 : }
241 :
242 : /* -------------------------------------------------------------------- */
243 : /* Create a feature from the current result. */
244 : /* -------------------------------------------------------------------- */
245 : int iField;
246 0 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
247 :
248 0 : if( pszFIDColumn != NULL && poStmt->GetColId(pszFIDColumn) > -1 )
249 : poFeature->SetFID(
250 0 : atoi(poStmt->GetColData(poStmt->GetColId(pszFIDColumn))) );
251 : else
252 0 : poFeature->SetFID( iNextShapeId );
253 :
254 0 : iNextShapeId++;
255 0 : m_nFeaturesRead++;
256 :
257 : /* -------------------------------------------------------------------- */
258 : /* Set the fields. */
259 : /* -------------------------------------------------------------------- */
260 0 : for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
261 : {
262 0 : int iSrcField = panFieldOrdinals[iField]-1;
263 0 : const char *pszValue = poStmt->GetColData( iSrcField );
264 :
265 0 : if( pszValue == NULL )
266 : /* no value */;
267 0 : else if( poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary )
268 : poFeature->SetField( iField,
269 : poStmt->GetColDataLength(iSrcField),
270 0 : (GByte *) pszValue );
271 : else
272 0 : poFeature->SetField( iField, pszValue );
273 : }
274 :
275 : /* -------------------------------------------------------------------- */
276 : /* Try to extract a geometry. */
277 : /* -------------------------------------------------------------------- */
278 0 : if( pszGeomColumn != NULL )
279 : {
280 0 : int iField = poStmt->GetColId( pszGeomColumn );
281 0 : GByte *pabyShape = (GByte *) poStmt->GetColData( iField );
282 0 : int nBytes = poStmt->GetColDataLength(iField);
283 0 : OGRGeometry *poGeom = NULL;
284 :
285 0 : if( pabyShape != NULL )
286 : {
287 0 : err = OGRCreateFromShapeBin( pabyShape, &poGeom, nBytes );
288 0 : if( OGRERR_NONE != err )
289 : {
290 : CPLDebug( "PGeo",
291 : "Translation shape binary to OGR geometry failed (FID=%ld)",
292 0 : (long)poFeature->GetFID() );
293 : }
294 : }
295 :
296 0 : if( poGeom != NULL && OGRERR_NONE == err )
297 : {
298 0 : poGeom->assignSpatialReference( poSRS );
299 0 : poFeature->SetGeometryDirectly( poGeom );
300 : }
301 : }
302 :
303 0 : return poFeature;
304 : }
305 :
306 : /************************************************************************/
307 : /* GetFeature() */
308 : /************************************************************************/
309 :
310 0 : OGRFeature *OGRPGeoLayer::GetFeature( long nFeatureId )
311 :
312 : {
313 : /* This should be implemented directly! */
314 :
315 0 : return OGRLayer::GetFeature( nFeatureId );
316 : }
317 :
318 : /************************************************************************/
319 : /* TestCapability() */
320 : /************************************************************************/
321 :
322 0 : int OGRPGeoLayer::TestCapability( const char * pszCap )
323 :
324 : {
325 0 : return FALSE;
326 : }
327 :
328 : /************************************************************************/
329 : /* GetSpatialRef() */
330 : /************************************************************************/
331 :
332 0 : OGRSpatialReference *OGRPGeoLayer::GetSpatialRef()
333 :
334 : {
335 0 : return poSRS;
336 : }
337 :
338 : /************************************************************************/
339 : /* TestCapability() */
340 : /************************************************************************/
341 :
342 0 : void OGRPGeoLayer::LookupSRID( int nSRID )
343 :
344 : {
345 : /* -------------------------------------------------------------------- */
346 : /* Fetch the corresponding WKT from the SpatialRef table. */
347 : /* -------------------------------------------------------------------- */
348 0 : CPLODBCStatement oStmt( poDS->GetSession() );
349 :
350 : oStmt.Appendf( "SELECT srtext FROM GDB_SpatialRefs WHERE srid = %d",
351 0 : nSRID );
352 :
353 0 : if( !oStmt.ExecuteSQL() )
354 : {
355 : CPLError( CE_Failure, CPLE_AppDefined,
356 : "'%s' failed.\n%s",
357 : oStmt.GetCommand(),
358 0 : poDS->GetSession()->GetLastError() );
359 : return;
360 : }
361 :
362 0 : if( !oStmt.Fetch() )
363 : {
364 : CPLError( CE_Warning, CPLE_AppDefined,
365 : "SRID %d lookup failed.\n%s",
366 0 : nSRID, poDS->GetSession()->GetLastError() );
367 : return;
368 : }
369 :
370 : /* -------------------------------------------------------------------- */
371 : /* Check that it isn't just a GUID. We don't know how to */
372 : /* translate those. */
373 : /* -------------------------------------------------------------------- */
374 0 : char *pszSRText = (char *) oStmt.GetColData(0);
375 :
376 0 : if( pszSRText[0] == '{' )
377 : {
378 0 : CPLDebug( "PGEO", "Ignoreing GUID SRTEXT: %s", pszSRText );
379 : return;
380 : }
381 :
382 : /* -------------------------------------------------------------------- */
383 : /* Turn it into an OGRSpatialReference. */
384 : /* -------------------------------------------------------------------- */
385 0 : poSRS = new OGRSpatialReference();
386 :
387 0 : if( poSRS->importFromWkt( &pszSRText ) != OGRERR_NONE )
388 : {
389 : CPLError( CE_Failure, CPLE_AppDefined,
390 : "importFromWKT() failed on SRS '%s'.",
391 0 : pszSRText);
392 0 : delete poSRS;
393 0 : poSRS = NULL;
394 : }
395 0 : else if( poSRS->morphFromESRI() != OGRERR_NONE )
396 : {
397 : CPLError( CE_Failure, CPLE_AppDefined,
398 0 : "morphFromESRI() failed on SRS." );
399 0 : delete poSRS;
400 0 : poSRS = NULL;
401 : }
402 : else
403 0 : nSRSId = nSRID;
404 : }
405 :
406 : /************************************************************************/
407 : /* GetFIDColumn() */
408 : /************************************************************************/
409 :
410 0 : const char *OGRPGeoLayer::GetFIDColumn()
411 :
412 : {
413 0 : if( pszFIDColumn != NULL )
414 0 : return pszFIDColumn;
415 : else
416 0 : return "";
417 : }
418 :
419 : /************************************************************************/
420 : /* GetGeometryColumn() */
421 : /************************************************************************/
422 :
423 0 : const char *OGRPGeoLayer::GetGeometryColumn()
424 :
425 : {
426 0 : if( pszGeomColumn != NULL )
427 0 : return pszGeomColumn;
428 : else
429 0 : return "";
430 : }
|