1 /******************************************************************************
2 *
3 * Project: OpenGIS Simple Features Reference Implementation
4 * Purpose: Implements OGRGeomediaTableLayer class, access to an existing table.
5 * Author: Even Rouault, <even dot rouault at spatialys.com>
6 *
7 ******************************************************************************
8 * Copyright (c) 2011, Even Rouault <even dot rouault at spatialys.com>
9 * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
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_geomedia.h"
32
33 CPL_CVSID("$Id: ogrgeomediatablelayer.cpp 355b41831cd2685c85d1aabe5b95665a2c6e99b7 2019-06-19 17:07:04 +0200 Even Rouault $")
34
35 /************************************************************************/
36 /* OGRGeomediaTableLayer() */
37 /************************************************************************/
38
OGRGeomediaTableLayer(OGRGeomediaDataSource * poDSIn)39 OGRGeomediaTableLayer::OGRGeomediaTableLayer( OGRGeomediaDataSource *poDSIn ) :
40 pszQuery(nullptr)
41 {
42 poDS = poDSIn;
43 iNextShapeId = 0;
44 nSRSId = -1;
45 poFeatureDefn = nullptr;
46 }
47
48 /************************************************************************/
49 /* ~OGRGeomediaTableLayer() */
50 /************************************************************************/
51
~OGRGeomediaTableLayer()52 OGRGeomediaTableLayer::~OGRGeomediaTableLayer()
53
54 {
55 CPLFree( pszQuery );
56 ClearStatement();
57 }
58
59 /************************************************************************/
60 /* Initialize() */
61 /************************************************************************/
62
Initialize(const char * pszTableName,const char * pszGeomCol,OGRSpatialReference * poSRSIn)63 CPLErr OGRGeomediaTableLayer::Initialize( const char *pszTableName,
64 const char *pszGeomCol,
65 OGRSpatialReference* poSRSIn )
66
67 {
68 CPLODBCSession *poSession = poDS->GetSession();
69
70 CPLFree( pszGeomColumn );
71 if( pszGeomCol == nullptr )
72 pszGeomColumn = nullptr;
73 else
74 pszGeomColumn = CPLStrdup( pszGeomCol );
75
76 CPLFree( pszFIDColumn );
77 pszFIDColumn = nullptr;
78
79 poSRS = poSRSIn;
80
81 /* -------------------------------------------------------------------- */
82 /* Do we have a simple primary key? */
83 /* -------------------------------------------------------------------- */
84 {
85 CPLODBCStatement oGetKey( poSession );
86
87 if( oGetKey.GetPrimaryKeys( pszTableName ) && oGetKey.Fetch() )
88 {
89 pszFIDColumn = CPLStrdup(oGetKey.GetColData( 3 ));
90
91 if( oGetKey.Fetch() ) // more than one field in key!
92 {
93 CPLFree( pszFIDColumn );
94 pszFIDColumn = nullptr;
95 CPLDebug( "Geomedia", "%s: Compound primary key, ignoring.",
96 pszTableName );
97 }
98 else
99 CPLDebug( "Geomedia",
100 "%s: Got primary key %s.",
101 pszTableName, pszFIDColumn );
102 }
103 else
104 CPLDebug( "Geomedia", "%s: no primary key", pszTableName );
105 }
106 /* -------------------------------------------------------------------- */
107 /* Get the column definitions for this table. */
108 /* -------------------------------------------------------------------- */
109 CPLODBCStatement oGetCol( poSession );
110 CPLErr eErr;
111
112 if( !oGetCol.GetColumns( pszTableName ) )
113 {
114 CPLError( CE_Failure, CPLE_AppDefined,
115 "GetColumns() failed on %s.\n%s",
116 pszTableName, poSession->GetLastError() );
117 return CE_Failure;
118 }
119
120 eErr = BuildFeatureDefn( pszTableName, &oGetCol );
121 if( eErr != CE_None )
122 return eErr;
123
124 if( poFeatureDefn->GetFieldCount() == 0 )
125 {
126 CPLError( CE_Failure, CPLE_AppDefined,
127 "No column definitions found for table '%s', layer not usable.",
128 pszTableName );
129 return CE_Failure;
130 }
131
132 return CE_None;
133 }
134
135 /************************************************************************/
136 /* ClearStatement() */
137 /************************************************************************/
138
ClearStatement()139 void OGRGeomediaTableLayer::ClearStatement()
140
141 {
142 if( poStmt != nullptr )
143 {
144 delete poStmt;
145 poStmt = nullptr;
146 }
147 }
148
149 /************************************************************************/
150 /* GetStatement() */
151 /************************************************************************/
152
GetStatement()153 CPLODBCStatement *OGRGeomediaTableLayer::GetStatement()
154
155 {
156 if( poStmt == nullptr )
157 ResetStatement();
158
159 return poStmt;
160 }
161
162 /************************************************************************/
163 /* ResetStatement() */
164 /************************************************************************/
165
ResetStatement()166 OGRErr OGRGeomediaTableLayer::ResetStatement()
167
168 {
169 ClearStatement();
170
171 iNextShapeId = 0;
172
173 poStmt = new CPLODBCStatement( poDS->GetSession() );
174 poStmt->Append( "SELECT * FROM " );
175 poStmt->Append( poFeatureDefn->GetName() );
176 if( pszQuery != nullptr )
177 poStmt->Appendf( " WHERE %s", pszQuery );
178
179 if( poStmt->ExecuteSQL() )
180 return OGRERR_NONE;
181 else
182 {
183 delete poStmt;
184 poStmt = nullptr;
185 return OGRERR_FAILURE;
186 }
187 }
188
189 /************************************************************************/
190 /* ResetReading() */
191 /************************************************************************/
192
ResetReading()193 void OGRGeomediaTableLayer::ResetReading()
194
195 {
196 ClearStatement();
197 OGRGeomediaLayer::ResetReading();
198 }
199
200 /************************************************************************/
201 /* GetFeature() */
202 /************************************************************************/
203
GetFeature(GIntBig nFeatureId)204 OGRFeature *OGRGeomediaTableLayer::GetFeature( GIntBig nFeatureId )
205
206 {
207 if( pszFIDColumn == nullptr )
208 return OGRGeomediaLayer::GetFeature( nFeatureId );
209
210 ClearStatement();
211
212 iNextShapeId = nFeatureId;
213
214 poStmt = new CPLODBCStatement( poDS->GetSession() );
215 poStmt->Append( "SELECT * FROM " );
216 poStmt->Append( poFeatureDefn->GetName() );
217 poStmt->Appendf( " WHERE %s = " CPL_FRMT_GIB, pszFIDColumn, nFeatureId );
218
219 if( !poStmt->ExecuteSQL() )
220 {
221 delete poStmt;
222 poStmt = nullptr;
223 return nullptr;
224 }
225
226 return GetNextRawFeature();
227 }
228
229 /************************************************************************/
230 /* SetAttributeFilter() */
231 /************************************************************************/
232
SetAttributeFilter(const char * pszQueryIn)233 OGRErr OGRGeomediaTableLayer::SetAttributeFilter( const char *pszQueryIn )
234
235 {
236 if( (pszQueryIn == nullptr && pszQuery == nullptr)
237 || (pszQueryIn != nullptr && pszQuery != nullptr
238 && EQUAL(pszQueryIn, pszQuery)) )
239 return OGRERR_NONE;
240
241 CPLFree( pszQuery );
242 pszQuery = pszQueryIn ? CPLStrdup( pszQueryIn ) : nullptr;
243
244 ClearStatement();
245
246 return OGRERR_NONE;
247 }
248
249 /************************************************************************/
250 /* TestCapability() */
251 /************************************************************************/
252
TestCapability(const char * pszCap)253 int OGRGeomediaTableLayer::TestCapability( const char * pszCap )
254
255 {
256 if( EQUAL(pszCap,OLCRandomRead) )
257 return TRUE;
258
259 else if( EQUAL(pszCap,OLCFastFeatureCount) )
260 return m_poFilterGeom == nullptr;
261
262 else if( EQUAL(pszCap,OLCFastSpatialFilter) )
263 return FALSE;
264
265 else
266 return OGRGeomediaLayer::TestCapability( pszCap );
267 }
268
269 /************************************************************************/
270 /* GetFeatureCount() */
271 /* */
272 /* If a spatial filter is in effect, we turn control over to */
273 /* the generic counter. Otherwise we return the total count. */
274 /* Eventually we should consider implementing a more efficient */
275 /* way of counting features matching a spatial query. */
276 /************************************************************************/
277
GetFeatureCount(int bForce)278 GIntBig OGRGeomediaTableLayer::GetFeatureCount( int bForce )
279
280 {
281 if( m_poFilterGeom != nullptr )
282 return OGRGeomediaLayer::GetFeatureCount( bForce );
283
284 CPLODBCStatement oStmt( poDS->GetSession() );
285 oStmt.Append( "SELECT COUNT(*) FROM " );
286 oStmt.Append( poFeatureDefn->GetName() );
287
288 if( pszQuery != nullptr )
289 oStmt.Appendf( " WHERE %s", pszQuery );
290
291 if( !oStmt.ExecuteSQL() || !oStmt.Fetch() )
292 {
293 CPLError( CE_Failure, CPLE_AppDefined,
294 "GetFeatureCount() failed on query %s.\n%s",
295 oStmt.GetCommand(), poDS->GetSession()->GetLastError() );
296 return OGRGeomediaLayer::GetFeatureCount(bForce);
297 }
298
299 return atoi(oStmt.GetColData(0));
300 }
301