1 : /******************************************************************************
2 : * $Id: ogrpgeotablelayer.cpp 22155 2011-04-13 19:52:57Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements OGRPGeoTableLayer class, access to an existing table.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2005, 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 "cpl_conv.h"
31 : #include "ogr_pgeo.h"
32 : #include "ogrpgeogeometry.h"
33 :
34 : CPL_CVSID("$Id: ogrpgeotablelayer.cpp 22155 2011-04-13 19:52:57Z rouault $");
35 :
36 : /************************************************************************/
37 : /* OGRPGeoTableLayer() */
38 : /************************************************************************/
39 :
40 0 : OGRPGeoTableLayer::OGRPGeoTableLayer( OGRPGeoDataSource *poDSIn )
41 :
42 : {
43 0 : poDS = poDSIn;
44 0 : pszQuery = NULL;
45 0 : bUpdateAccess = TRUE;
46 0 : iNextShapeId = 0;
47 0 : nSRSId = -1;
48 0 : poFeatureDefn = NULL;
49 0 : memset( &sExtent, 0, sizeof(sExtent) );
50 0 : }
51 :
52 : /************************************************************************/
53 : /* ~OGRPGeoTableLayer() */
54 : /************************************************************************/
55 :
56 0 : OGRPGeoTableLayer::~OGRPGeoTableLayer()
57 :
58 : {
59 0 : CPLFree( pszQuery );
60 0 : ClearStatement();
61 0 : }
62 :
63 : /************************************************************************/
64 : /* Initialize() */
65 : /************************************************************************/
66 :
67 0 : CPLErr OGRPGeoTableLayer::Initialize( const char *pszTableName,
68 : const char *pszGeomCol,
69 : int nShapeType,
70 : double dfExtentLeft,
71 : double dfExtentRight,
72 : double dfExtentBottom,
73 : double dfExtentTop,
74 : int nSRID,
75 : int bHasZ )
76 :
77 :
78 : {
79 0 : CPLODBCSession *poSession = poDS->GetSession();
80 :
81 0 : CPLFree( pszGeomColumn );
82 0 : if( pszGeomCol == NULL )
83 0 : pszGeomColumn = NULL;
84 : else
85 0 : pszGeomColumn = CPLStrdup( pszGeomCol );
86 :
87 0 : CPLFree( pszFIDColumn );
88 0 : pszFIDColumn = NULL;
89 :
90 0 : sExtent.MinX = dfExtentLeft;
91 0 : sExtent.MaxX = dfExtentRight;
92 0 : sExtent.MinY = dfExtentBottom;
93 0 : sExtent.MaxY = dfExtentTop;
94 :
95 0 : LookupSRID( nSRID );
96 :
97 : /* -------------------------------------------------------------------- */
98 : /* Setup geometry type. */
99 : /* -------------------------------------------------------------------- */
100 : OGRwkbGeometryType eOGRType;
101 :
102 0 : switch( nShapeType )
103 : {
104 : case ESRI_LAYERGEOMTYPE_NULL:
105 0 : eOGRType = wkbNone;
106 0 : break;
107 :
108 : case ESRI_LAYERGEOMTYPE_POINT:
109 0 : eOGRType = wkbPoint;
110 0 : break;
111 :
112 : case ESRI_LAYERGEOMTYPE_MULTIPOINT:
113 0 : eOGRType = wkbMultiPoint;
114 0 : break;
115 :
116 : case ESRI_LAYERGEOMTYPE_POLYLINE:
117 0 : eOGRType = wkbLineString;
118 0 : break;
119 :
120 : case ESRI_LAYERGEOMTYPE_POLYGON:
121 : case ESRI_LAYERGEOMTYPE_MULTIPATCH:
122 0 : eOGRType = wkbPolygon;
123 0 : break;
124 :
125 : default:
126 0 : CPLDebug("PGeo", "Unexpected value for shape type : %d", nShapeType);
127 0 : eOGRType = wkbUnknown;
128 : break;
129 : }
130 :
131 0 : if( eOGRType != wkbUnknown && eOGRType != wkbNone && bHasZ )
132 0 : eOGRType = (OGRwkbGeometryType)(((int) eOGRType) | wkb25DBit);
133 :
134 : /* -------------------------------------------------------------------- */
135 : /* Do we have a simple primary key? */
136 : /* -------------------------------------------------------------------- */
137 0 : CPLODBCStatement oGetKey( poSession );
138 :
139 0 : if( oGetKey.GetPrimaryKeys( pszTableName ) && oGetKey.Fetch() )
140 : {
141 0 : pszFIDColumn = CPLStrdup(oGetKey.GetColData( 3 ));
142 :
143 0 : if( oGetKey.Fetch() ) // more than one field in key!
144 : {
145 0 : CPLFree( pszFIDColumn );
146 0 : pszFIDColumn = NULL;
147 : CPLDebug( "PGeo", "%s: Compound primary key, ignoring.",
148 0 : pszTableName );
149 : }
150 : else
151 : CPLDebug( "PGeo",
152 : "%s: Got primary key %s.",
153 0 : pszTableName, pszFIDColumn );
154 : }
155 : else
156 0 : CPLDebug( "PGeo", "%s: no primary key", pszTableName );
157 :
158 : /* -------------------------------------------------------------------- */
159 : /* Get the column definitions for this table. */
160 : /* -------------------------------------------------------------------- */
161 0 : CPLODBCStatement oGetCol( poSession );
162 : CPLErr eErr;
163 :
164 0 : if( !oGetCol.GetColumns( pszTableName ) )
165 : {
166 : CPLError( CE_Failure, CPLE_AppDefined,
167 : "GetColumns() failed on %s.\n%s",
168 0 : pszTableName, poSession->GetLastError() );
169 0 : return CE_Failure;
170 : }
171 :
172 0 : eErr = BuildFeatureDefn( pszTableName, &oGetCol );
173 0 : if( eErr != CE_None )
174 0 : return eErr;
175 :
176 0 : if( poFeatureDefn->GetFieldCount() == 0 )
177 : {
178 : CPLError( CE_Failure, CPLE_AppDefined,
179 : "No column definitions found for table '%s', layer not usable.",
180 0 : pszTableName );
181 0 : return CE_Failure;
182 : }
183 :
184 : /* -------------------------------------------------------------------- */
185 : /* Set geometry type. */
186 : /* */
187 : /* NOTE: per reports from Craig Miller, it seems we cannot really */
188 : /* trust the ShapeType value. At the very least "line" tables */
189 : /* sometimes have multilinestrings. So for now we just always */
190 : /* return wkbUnknown. */
191 : /* */
192 : /* TODO - mloskot: Similar issue has been reported in Ticket #1484 */
193 : /* -------------------------------------------------------------------- */
194 : #ifdef notdef
195 : poFeatureDefn->SetGeomType( eOGRType );
196 : #endif
197 :
198 0 : return CE_None;
199 : }
200 :
201 : /************************************************************************/
202 : /* ClearStatement() */
203 : /************************************************************************/
204 :
205 0 : void OGRPGeoTableLayer::ClearStatement()
206 :
207 : {
208 0 : if( poStmt != NULL )
209 : {
210 0 : delete poStmt;
211 0 : poStmt = NULL;
212 : }
213 0 : }
214 :
215 : /************************************************************************/
216 : /* GetStatement() */
217 : /************************************************************************/
218 :
219 0 : CPLODBCStatement *OGRPGeoTableLayer::GetStatement()
220 :
221 : {
222 0 : if( poStmt == NULL )
223 0 : ResetStatement();
224 :
225 0 : return poStmt;
226 : }
227 :
228 : /************************************************************************/
229 : /* ResetStatement() */
230 : /************************************************************************/
231 :
232 0 : OGRErr OGRPGeoTableLayer::ResetStatement()
233 :
234 : {
235 0 : ClearStatement();
236 :
237 0 : iNextShapeId = 0;
238 :
239 0 : poStmt = new CPLODBCStatement( poDS->GetSession() );
240 0 : poStmt->Append( "SELECT * FROM " );
241 0 : poStmt->Append( poFeatureDefn->GetName() );
242 0 : if( pszQuery != NULL )
243 0 : poStmt->Appendf( " WHERE %s", pszQuery );
244 :
245 0 : if( poStmt->ExecuteSQL() )
246 0 : return OGRERR_NONE;
247 : else
248 : {
249 0 : delete poStmt;
250 0 : poStmt = NULL;
251 0 : return OGRERR_FAILURE;
252 : }
253 : }
254 :
255 : /************************************************************************/
256 : /* ResetReading() */
257 : /************************************************************************/
258 :
259 0 : void OGRPGeoTableLayer::ResetReading()
260 :
261 : {
262 0 : ClearStatement();
263 0 : OGRPGeoLayer::ResetReading();
264 0 : }
265 :
266 : /************************************************************************/
267 : /* GetFeature() */
268 : /************************************************************************/
269 :
270 0 : OGRFeature *OGRPGeoTableLayer::GetFeature( long nFeatureId )
271 :
272 : {
273 0 : if( pszFIDColumn == NULL )
274 0 : return OGRPGeoLayer::GetFeature( nFeatureId );
275 :
276 0 : ClearStatement();
277 :
278 0 : iNextShapeId = nFeatureId;
279 :
280 0 : poStmt = new CPLODBCStatement( poDS->GetSession() );
281 0 : poStmt->Append( "SELECT * FROM " );
282 0 : poStmt->Append( poFeatureDefn->GetName() );
283 0 : poStmt->Appendf( " WHERE %s = %ld", pszFIDColumn, nFeatureId );
284 :
285 0 : if( !poStmt->ExecuteSQL() )
286 : {
287 0 : delete poStmt;
288 0 : poStmt = NULL;
289 0 : return NULL;
290 : }
291 :
292 0 : return GetNextRawFeature();
293 : }
294 :
295 : /************************************************************************/
296 : /* SetAttributeFilter() */
297 : /************************************************************************/
298 :
299 0 : OGRErr OGRPGeoTableLayer::SetAttributeFilter( const char *pszQuery )
300 :
301 : {
302 0 : if( (pszQuery == NULL && this->pszQuery == NULL)
303 : || (pszQuery != NULL && this->pszQuery != NULL
304 : && EQUAL(pszQuery,this->pszQuery)) )
305 0 : return OGRERR_NONE;
306 :
307 0 : CPLFree( this->pszQuery );
308 0 : this->pszQuery = pszQuery ? CPLStrdup( pszQuery ) : NULL;
309 :
310 0 : ClearStatement();
311 :
312 0 : return OGRERR_NONE;
313 : }
314 :
315 :
316 : /************************************************************************/
317 : /* TestCapability() */
318 : /************************************************************************/
319 :
320 0 : int OGRPGeoTableLayer::TestCapability( const char * pszCap )
321 :
322 : {
323 0 : if( EQUAL(pszCap,OLCRandomRead) )
324 0 : return TRUE;
325 :
326 0 : else if( EQUAL(pszCap,OLCFastFeatureCount) )
327 0 : return m_poFilterGeom == NULL;
328 :
329 0 : else if( EQUAL(pszCap,OLCFastSpatialFilter) )
330 0 : return FALSE;
331 :
332 : else
333 0 : return OGRPGeoLayer::TestCapability( pszCap );
334 : }
335 :
336 : /************************************************************************/
337 : /* GetFeatureCount() */
338 : /* */
339 : /* If a spatial filter is in effect, we turn control over to */
340 : /* the generic counter. Otherwise we return the total count. */
341 : /* Eventually we should consider implementing a more efficient */
342 : /* way of counting features matching a spatial query. */
343 : /************************************************************************/
344 :
345 0 : int OGRPGeoTableLayer::GetFeatureCount( int bForce )
346 :
347 : {
348 0 : if( m_poFilterGeom != NULL )
349 0 : return OGRPGeoLayer::GetFeatureCount( bForce );
350 :
351 0 : CPLODBCStatement oStmt( poDS->GetSession() );
352 0 : oStmt.Append( "SELECT COUNT(*) FROM " );
353 0 : oStmt.Append( poFeatureDefn->GetName() );
354 :
355 0 : if( pszQuery != NULL )
356 0 : oStmt.Appendf( " WHERE %s", pszQuery );
357 :
358 0 : if( !oStmt.ExecuteSQL() || !oStmt.Fetch() )
359 : {
360 : CPLError( CE_Failure, CPLE_AppDefined,
361 : "GetFeatureCount() failed on query %s.\n%s",
362 0 : oStmt.GetCommand(), poDS->GetSession()->GetLastError() );
363 0 : return OGRPGeoLayer::GetFeatureCount(bForce);
364 : }
365 :
366 0 : return atoi(oStmt.GetColData(0));
367 : }
368 :
369 : /************************************************************************/
370 : /* GetExtent() */
371 : /************************************************************************/
372 :
373 0 : OGRErr OGRPGeoTableLayer::GetExtent( OGREnvelope *psExtent, int bForce )
374 :
375 : {
376 0 : *psExtent = sExtent;
377 0 : return OGRERR_NONE;
378 : }
|