1 : /******************************************************************************
2 : * $Id: ogrvrtlayer.cpp 25311 2012-12-15 12:48:14Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements OGRVRTLayer class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2003, 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_vrt.h"
32 : #include "cpl_string.h"
33 : #include "ogrpgeogeometry.h"
34 : #include <string>
35 :
36 : CPL_CVSID("$Id: ogrvrtlayer.cpp 25311 2012-12-15 12:48:14Z rouault $");
37 :
38 : #define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
39 :
40 : /************************************************************************/
41 : /* OGRVRTLayer() */
42 : /************************************************************************/
43 :
44 472 : OGRVRTLayer::OGRVRTLayer(OGRVRTDataSource* poDSIn)
45 :
46 : {
47 472 : poDS = poDSIn;
48 :
49 472 : bHasFullInitialized = FALSE;
50 472 : eGeomType = wkbUnknown;
51 472 : psLTree = NULL;
52 :
53 472 : poFeatureDefn = NULL;
54 472 : poSrcLayer = NULL;
55 472 : poSRS = NULL;
56 472 : poSrcDS = NULL;
57 472 : poSrcFeatureDefn = NULL;
58 :
59 472 : bUseSpatialSubquery = FALSE;
60 472 : iFIDField = -1;
61 472 : iStyleField = -1;
62 :
63 472 : eGeometryStyle = VGS_Direct;
64 472 : iGeomField = iGeomXField = iGeomYField = iGeomZField = -1;
65 :
66 472 : pszAttrFilter = NULL;
67 :
68 472 : bNeedReset = TRUE;
69 472 : bSrcLayerFromSQL = FALSE;
70 :
71 472 : bSrcClip = FALSE;
72 472 : poSrcRegion = NULL;
73 472 : bUpdate = FALSE;
74 472 : bAttrFilterPassThrough = FALSE;
75 :
76 472 : nFeatureCount = -1;
77 472 : }
78 :
79 : /************************************************************************/
80 : /* ~OGRVRTLayer() */
81 : /************************************************************************/
82 :
83 472 : OGRVRTLayer::~OGRVRTLayer()
84 :
85 : {
86 472 : if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
87 : {
88 : CPLDebug( "VRT", "%d features read on layer '%s'.",
89 : (int) m_nFeaturesRead,
90 62 : poFeatureDefn->GetName() );
91 : }
92 :
93 472 : if( poSRS != NULL )
94 207 : poSRS->Release();
95 :
96 472 : if( poSrcDS != NULL )
97 : {
98 233 : if( bSrcLayerFromSQL && poSrcLayer )
99 2 : poSrcDS->ReleaseResultSet( poSrcLayer );
100 :
101 233 : if( bSrcDSShared )
102 28 : OGRSFDriverRegistrar::GetRegistrar()->ReleaseDataSource( poSrcDS );
103 : else
104 205 : delete poSrcDS;
105 : }
106 :
107 472 : if( poFeatureDefn )
108 292 : poFeatureDefn->Release();
109 :
110 472 : CPLFree( pszAttrFilter );
111 :
112 472 : if( poSrcRegion != NULL )
113 3 : delete poSrcRegion;
114 472 : }
115 :
116 : /************************************************************************/
117 : /* GetSrcLayerDefn() */
118 : /************************************************************************/
119 :
120 797 : OGRFeatureDefn* OGRVRTLayer::GetSrcLayerDefn()
121 : {
122 797 : if (poSrcFeatureDefn)
123 572 : return poSrcFeatureDefn;
124 :
125 225 : if (poSrcLayer)
126 225 : poSrcFeatureDefn = poSrcLayer->GetLayerDefn();
127 :
128 225 : return poSrcFeatureDefn;
129 : }
130 :
131 : /************************************************************************/
132 : /* FastInitialize() */
133 : /************************************************************************/
134 :
135 472 : int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTree, const char *pszVRTDirectory,
136 : int bUpdate)
137 :
138 : {
139 472 : this->psLTree = psLTree;
140 472 : this->bUpdate = bUpdate;
141 472 : osVRTDirectory = pszVRTDirectory;
142 :
143 472 : if( !EQUAL(psLTree->pszValue,"OGRVRTLayer") )
144 0 : return FALSE;
145 :
146 : /* -------------------------------------------------------------------- */
147 : /* Get layer name. */
148 : /* -------------------------------------------------------------------- */
149 472 : const char *pszLayerName = CPLGetXMLValue( psLTree, "name", NULL );
150 :
151 472 : if( pszLayerName == NULL )
152 : {
153 : CPLError( CE_Failure, CPLE_AppDefined,
154 1 : "Missing name attribute on OGRVRTLayer" );
155 1 : return FALSE;
156 : }
157 :
158 471 : osName = pszLayerName;
159 :
160 : /* -------------------------------------------------------------------- */
161 : /* Do we have a fixed geometry type? If so use it */
162 : /* -------------------------------------------------------------------- */
163 471 : const char *pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
164 471 : if( pszGType != NULL )
165 : {
166 : int bError;
167 198 : eGeomType = OGRVRTGetGeometryType(pszGType, &bError);
168 198 : if( bError )
169 : {
170 : CPLError( CE_Failure, CPLE_AppDefined,
171 : "GeometryType %s not recognised.",
172 1 : pszGType );
173 1 : return FALSE;
174 : }
175 : }
176 :
177 : /* -------------------------------------------------------------------- */
178 : /* Apply a spatial reference system if provided */
179 : /* -------------------------------------------------------------------- */
180 470 : const char* pszLayerSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
181 470 : if( pszLayerSRS != NULL )
182 : {
183 114 : if( EQUAL(pszLayerSRS,"NULL") )
184 0 : poSRS = NULL;
185 : else
186 : {
187 114 : OGRSpatialReference oSRS;
188 :
189 114 : if( oSRS.SetFromUserInput( pszLayerSRS ) != OGRERR_NONE )
190 : {
191 : CPLError( CE_Failure, CPLE_AppDefined,
192 1 : "Failed to import LayerSRS `%s'.", pszLayerSRS );
193 1 : return FALSE;
194 : }
195 113 : poSRS = oSRS.Clone();
196 : }
197 : }
198 :
199 : /* -------------------------------------------------------------------- */
200 : /* Set FeatureCount if provided */
201 : /* -------------------------------------------------------------------- */
202 469 : const char* pszFeatureCount = CPLGetXMLValue( psLTree, "FeatureCount", NULL );
203 469 : if( pszFeatureCount != NULL )
204 : {
205 0 : nFeatureCount = atoi(pszFeatureCount);
206 : }
207 :
208 : /* -------------------------------------------------------------------- */
209 : /* Set Extent if provided */
210 : /* -------------------------------------------------------------------- */
211 469 : const char* pszExtentXMin = CPLGetXMLValue( psLTree, "ExtentXMin", NULL );
212 469 : const char* pszExtentYMin = CPLGetXMLValue( psLTree, "ExtentYMin", NULL );
213 469 : const char* pszExtentXMax = CPLGetXMLValue( psLTree, "ExtentXMax", NULL );
214 469 : const char* pszExtentYMax = CPLGetXMLValue( psLTree, "ExtentYMax", NULL );
215 469 : if( pszExtentXMin != NULL && pszExtentYMin != NULL &&
216 : pszExtentXMax != NULL && pszExtentYMax != NULL )
217 : {
218 0 : sStaticEnvelope.MinX = CPLAtof(pszExtentXMin);
219 0 : sStaticEnvelope.MinY = CPLAtof(pszExtentYMin);
220 0 : sStaticEnvelope.MaxX = CPLAtof(pszExtentXMax);
221 0 : sStaticEnvelope.MaxY = CPLAtof(pszExtentYMax);
222 : }
223 :
224 469 : return TRUE;
225 : }
226 :
227 : /************************************************************************/
228 : /* FullInitialize() */
229 : /************************************************************************/
230 :
231 292 : int OGRVRTLayer::FullInitialize()
232 :
233 : {
234 292 : const char *pszSharedSetting = NULL;
235 292 : const char *pszSQL = NULL;
236 292 : const char *pszSrcRegion = NULL;
237 292 : const char *pszGType = NULL;
238 292 : const char *pszLayerSRS = NULL;
239 292 : const char *pszEncoding = NULL;
240 292 : const char *pszFIDFieldName = NULL;
241 292 : const char *pszStyleFieldName = NULL;
242 292 : CPLXMLNode *psChild = NULL;
243 :
244 292 : if (bHasFullInitialized)
245 0 : return TRUE;
246 :
247 292 : bHasFullInitialized = TRUE;
248 :
249 292 : poFeatureDefn = new OGRFeatureDefn( osName );
250 292 : poFeatureDefn->Reference();
251 :
252 292 : if (poDS->GetRecursionDetected())
253 34 : return FALSE;
254 :
255 : /* -------------------------------------------------------------------- */
256 : /* Figure out the data source name. It may be treated relative */
257 : /* to vrt filename, but normally it is used directly. */
258 : /* -------------------------------------------------------------------- */
259 258 : OGRSFDriverRegistrar *poReg = OGRSFDriverRegistrar::GetRegistrar();
260 258 : char *pszSrcDSName = (char *) CPLGetXMLValue(psLTree,"SrcDataSource",NULL);
261 :
262 258 : if( pszSrcDSName == NULL )
263 : {
264 : CPLError( CE_Failure, CPLE_AppDefined,
265 19 : "Missing SrcDataSource for layer %s.", osName.c_str() );
266 19 : goto error;
267 : }
268 :
269 239 : if( CSLTestBoolean(CPLGetXMLValue( psLTree, "SrcDataSource.relativetoVRT",
270 : "0")) )
271 : {
272 : pszSrcDSName = CPLStrdup(
273 130 : CPLProjectRelativeFilename( osVRTDirectory, pszSrcDSName ) );
274 : }
275 : else
276 : {
277 109 : pszSrcDSName = CPLStrdup(pszSrcDSName);
278 : }
279 :
280 : /* -------------------------------------------------------------------- */
281 : /* Are we accessing this datasource in shared mode? We default */
282 : /* to shared for SrcSQL requests, but we also allow the XML to */
283 : /* control our shared setting with an attribute on the */
284 : /* datasource element. */
285 : /* -------------------------------------------------------------------- */
286 : pszSharedSetting = CPLGetXMLValue( psLTree,
287 : "SrcDataSource.shared",
288 239 : NULL );
289 239 : if( pszSharedSetting == NULL )
290 : {
291 210 : if( CPLGetXMLValue( psLTree, "SrcSQL", NULL ) == NULL )
292 207 : pszSharedSetting = "OFF";
293 : else
294 3 : pszSharedSetting = "ON";
295 : }
296 :
297 239 : bSrcDSShared = CSLTestBoolean( pszSharedSetting );
298 :
299 : // update mode doesn't make sense if we have a SrcSQL element
300 239 : if (CPLGetXMLValue( psLTree, "SrcSQL", NULL ) != NULL)
301 3 : bUpdate = FALSE;
302 :
303 : /* -------------------------------------------------------------------- */
304 : /* Try to access the datasource. */
305 : /* -------------------------------------------------------------------- */
306 : try_again:
307 239 : CPLErrorReset();
308 239 : if( EQUAL(pszSrcDSName,"@dummy@") )
309 : {
310 0 : OGRSFDriver *poMemDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("Memory");
311 0 : if (poMemDriver != NULL)
312 : {
313 0 : poSrcDS = poMemDriver->CreateDataSource( "@dummy@" );
314 0 : poSrcDS->CreateLayer( "@dummy@" );
315 : }
316 : }
317 239 : else if( bSrcDSShared )
318 : {
319 31 : if (poDS->IsInForbiddenNames(pszSrcDSName))
320 : {
321 3 : CPLError(CE_Failure, CPLE_AppDefined, "Cyclic VRT opening detected !");
322 3 : poDS->SetRecursionDetected();
323 : }
324 : else
325 : {
326 28 : poSrcDS = poReg->OpenShared( pszSrcDSName, bUpdate, NULL );
327 : /* Is it a VRT datasource ? */
328 28 : if (poSrcDS != NULL && poSrcDS->GetDriver() == poDS->GetDriver())
329 : {
330 4 : OGRVRTDataSource* poVRTSrcDS = (OGRVRTDataSource*)poSrcDS;
331 4 : poVRTSrcDS->AddForbiddenNames(poDS->GetName());
332 : }
333 : }
334 : }
335 : else
336 : {
337 208 : if (poDS->GetCallLevel() < 32)
338 : {
339 206 : poSrcDS = poReg->Open( pszSrcDSName, bUpdate, NULL );
340 : /* Is it a VRT datasource ? */
341 206 : if (poSrcDS != NULL && poSrcDS->GetDriver() == poDS->GetDriver())
342 : {
343 64 : OGRVRTDataSource* poVRTSrcDS = (OGRVRTDataSource*)poSrcDS;
344 64 : poVRTSrcDS->SetCallLevel(poDS->GetCallLevel() + 1);
345 64 : poVRTSrcDS->SetParentDS(poDS);
346 : }
347 : }
348 : else
349 : {
350 : CPLError(CE_Failure, CPLE_AppDefined,
351 2 : "Trying to open a VRT from a VRT from a VRT from ... [32 times] a VRT !");
352 :
353 2 : poDS->SetRecursionDetected();
354 :
355 2 : OGRVRTDataSource* poParent = poDS->GetParentDS();
356 68 : while(poParent != NULL)
357 : {
358 64 : poParent->SetRecursionDetected();
359 64 : poParent = poParent->GetParentDS();
360 : }
361 : }
362 : }
363 :
364 239 : if( poSrcDS == NULL )
365 : {
366 6 : if (bUpdate)
367 : {
368 : CPLError( CE_Warning, CPLE_AppDefined,
369 : "Cannot open datasource `%s' in update mode. Trying again in read-only mode",
370 0 : pszSrcDSName );
371 0 : bUpdate = FALSE;
372 0 : goto try_again;
373 : }
374 6 : if( strlen(CPLGetLastErrorMsg()) == 0 )
375 : CPLError( CE_Failure, CPLE_AppDefined,
376 : "Failed to open datasource `%s'.",
377 1 : pszSrcDSName );
378 6 : goto error;
379 : }
380 :
381 : /* -------------------------------------------------------------------- */
382 : /* Is this layer derived from an SQL query result? */
383 : /* -------------------------------------------------------------------- */
384 233 : pszSQL = CPLGetXMLValue( psLTree, "SrcSQL", NULL );
385 :
386 233 : if( pszSQL != NULL )
387 : {
388 3 : const char* pszDialect = CPLGetXMLValue( psLTree, "SrcSQL.dialect", NULL );
389 3 : if( pszDialect != NULL && pszDialect[0] == '\0' )
390 0 : pszDialect = NULL;
391 3 : poSrcLayer = poSrcDS->ExecuteSQL( pszSQL, NULL, pszDialect );
392 3 : if( poSrcLayer == NULL )
393 : {
394 : CPLError( CE_Failure, CPLE_AppDefined,
395 : "SQL statement failed, or returned no layer result:\n%s",
396 1 : pszSQL );
397 1 : goto error;
398 : }
399 2 : bSrcLayerFromSQL = TRUE;
400 : }
401 :
402 : /* -------------------------------------------------------------------- */
403 : /* Fetch the layer if it is a regular layer. */
404 : /* -------------------------------------------------------------------- */
405 232 : if( poSrcLayer == NULL )
406 : {
407 : const char *pszSrcLayerName = CPLGetXMLValue( psLTree, "SrcLayer",
408 230 : osName );
409 :
410 230 : poSrcLayer = poSrcDS->GetLayerByName( pszSrcLayerName );
411 230 : if( poSrcLayer == NULL )
412 : {
413 : CPLError( CE_Failure, CPLE_AppDefined,
414 : "Failed to find layer '%s' on datasource '%s'.",
415 2 : pszSrcLayerName, pszSrcDSName );
416 2 : goto error;
417 : }
418 : }
419 :
420 230 : CPLFree( pszSrcDSName );
421 230 : pszSrcDSName = NULL;
422 :
423 : /* -------------------------------------------------------------------- */
424 : /* Do we have a fixed geometry type? If not derive from the */
425 : /* source layer. */
426 : /* -------------------------------------------------------------------- */
427 230 : pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
428 230 : if( pszGType == NULL )
429 : {
430 178 : eGeomType = poSrcLayer->GetGeomType();
431 : }
432 230 : poFeatureDefn->SetGeomType(eGeomType);
433 :
434 : /* -------------------------------------------------------------------- */
435 : /* Copy spatial reference system from source if not provided */
436 : /* -------------------------------------------------------------------- */
437 230 : pszLayerSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
438 230 : if( pszLayerSRS == NULL )
439 : {
440 183 : CPLAssert(poSRS == NULL);
441 183 : if( poSrcLayer->GetSpatialRef() != NULL )
442 94 : poSRS = poSrcLayer->GetSpatialRef()->Clone();
443 : else
444 89 : poSRS = NULL;
445 : }
446 :
447 : /* -------------------------------------------------------------------- */
448 : /* Handle GeometryField. */
449 : /* -------------------------------------------------------------------- */
450 :
451 230 : pszEncoding = CPLGetXMLValue( psLTree,"GeometryField.encoding", "direct");
452 :
453 230 : if( EQUAL(pszEncoding,"Direct") )
454 170 : eGeometryStyle = VGS_Direct;
455 60 : else if( EQUAL(pszEncoding,"None") )
456 0 : eGeometryStyle = VGS_None;
457 60 : else if( EQUAL(pszEncoding,"WKT") )
458 23 : eGeometryStyle = VGS_WKT;
459 37 : else if( EQUAL(pszEncoding,"WKB") )
460 1 : eGeometryStyle = VGS_WKB;
461 36 : else if( EQUAL(pszEncoding,"Shape") )
462 1 : eGeometryStyle = VGS_Shape;
463 35 : else if( EQUAL(pszEncoding,"PointFromColumns") )
464 : {
465 34 : eGeometryStyle = VGS_PointFromColumns;
466 : bUseSpatialSubquery =
467 : CSLTestBoolean(
468 : CPLGetXMLValue(psLTree,
469 : "GeometryField.useSpatialSubquery",
470 34 : "TRUE"));
471 :
472 : iGeomXField = GetSrcLayerDefn()->GetFieldIndex(
473 34 : CPLGetXMLValue( psLTree, "GeometryField.x", "missing" ) );
474 : iGeomYField = GetSrcLayerDefn()->GetFieldIndex(
475 34 : CPLGetXMLValue( psLTree, "GeometryField.y", "missing" ) );
476 : iGeomZField = GetSrcLayerDefn()->GetFieldIndex(
477 34 : CPLGetXMLValue( psLTree, "GeometryField.z", "missing" ) );
478 :
479 34 : if( iGeomXField == -1 || iGeomYField == -1 )
480 : {
481 : CPLError( CE_Failure, CPLE_AppDefined,
482 1 : "Unable to identify source X or Y field for PointFromColumns encoding." );
483 1 : goto error;
484 : }
485 : }
486 : else
487 : {
488 : CPLError( CE_Failure, CPLE_AppDefined,
489 1 : "encoding=\"%s\" not recognised.", pszEncoding );
490 1 : goto error;
491 : }
492 :
493 228 : if( eGeometryStyle == VGS_WKT
494 : || eGeometryStyle == VGS_WKB
495 : || eGeometryStyle == VGS_Shape )
496 : {
497 : const char *pszFieldName =
498 25 : CPLGetXMLValue( psLTree, "GeometryField.field", "missing" );
499 :
500 25 : iGeomField = GetSrcLayerDefn()->GetFieldIndex(pszFieldName);
501 :
502 25 : if( iGeomField == -1 )
503 : {
504 : CPLError( CE_Failure, CPLE_AppDefined,
505 : "Unable to identify source field '%s' for geometry.",
506 1 : pszFieldName );
507 1 : goto error;
508 : }
509 : }
510 :
511 : /* -------------------------------------------------------------------- */
512 : /* Figure out what should be used as an FID. */
513 : /* -------------------------------------------------------------------- */
514 227 : pszFIDFieldName = CPLGetXMLValue( psLTree, "FID", NULL );
515 :
516 227 : if( pszFIDFieldName != NULL )
517 : {
518 : iFIDField =
519 20 : GetSrcLayerDefn()->GetFieldIndex( pszFIDFieldName );
520 20 : if( iFIDField == -1 )
521 : {
522 : CPLError( CE_Failure, CPLE_AppDefined,
523 : "Unable to identify FID field '%s'.",
524 1 : pszFIDFieldName );
525 1 : goto error;
526 : }
527 : }
528 :
529 : /* -------------------------------------------------------------------- */
530 : /* Figure out what should be used as a Style */
531 : /* -------------------------------------------------------------------- */
532 226 : pszStyleFieldName = CPLGetXMLValue( psLTree, "Style", NULL );
533 :
534 226 : if( pszStyleFieldName != NULL )
535 : {
536 : iStyleField =
537 2 : GetSrcLayerDefn()->GetFieldIndex( pszStyleFieldName );
538 2 : if( iStyleField == -1 )
539 : {
540 : CPLError( CE_Failure, CPLE_AppDefined,
541 : "Unable to identify Style field '%s'.",
542 1 : pszStyleFieldName );
543 1 : goto error;
544 : }
545 : }
546 :
547 : /* ==================================================================== */
548 : /* Search for schema definitions in the VRT. */
549 : /* ==================================================================== */
550 225 : bAttrFilterPassThrough = TRUE;
551 970 : for( psChild = psLTree->psChild; psChild != NULL; psChild=psChild->psNext )
552 : {
553 750 : if( psChild->eType == CXT_Element && EQUAL(psChild->pszValue,"Field") )
554 : {
555 : /* -------------------------------------------------------------------- */
556 : /* Field name. */
557 : /* -------------------------------------------------------------------- */
558 19 : const char *pszName = CPLGetXMLValue( psChild, "name", NULL );
559 19 : if( pszName == NULL )
560 : {
561 : CPLError( CE_Failure, CPLE_AppDefined,
562 1 : "Unable to identify Field name." );
563 1 : goto error;
564 : }
565 :
566 18 : OGRFieldDefn oFieldDefn( pszName, OFTString );
567 :
568 : /* -------------------------------------------------------------------- */
569 : /* Type */
570 : /* -------------------------------------------------------------------- */
571 18 : const char *pszArg = CPLGetXMLValue( psChild, "type", NULL );
572 :
573 18 : if( pszArg != NULL )
574 : {
575 : int iType;
576 :
577 36 : for( iType = 0; iType <= (int) OFTMaxType; iType++ )
578 : {
579 35 : if( EQUAL(pszArg,OGRFieldDefn::GetFieldTypeName(
580 : (OGRFieldType)iType)) )
581 : {
582 9 : oFieldDefn.SetType( (OGRFieldType) iType );
583 9 : break;
584 : }
585 : }
586 :
587 10 : if( iType > (int) OFTMaxType )
588 : {
589 : CPLError( CE_Failure, CPLE_AppDefined,
590 : "Unable to identify Field type '%s'.",
591 1 : pszArg );
592 : goto error;
593 : }
594 : }
595 :
596 : /* -------------------------------------------------------------------- */
597 : /* Width and precision. */
598 : /* -------------------------------------------------------------------- */
599 17 : int nWidth = atoi(CPLGetXMLValue( psChild, "width", "0" ));
600 17 : if (nWidth < 0)
601 : {
602 : CPLError( CE_Failure, CPLE_IllegalArg,
603 : "Invalid width for field %s.",
604 1 : pszName );
605 : goto error;
606 : }
607 16 : oFieldDefn.SetWidth(nWidth);
608 :
609 16 : int nPrecision = atoi(CPLGetXMLValue( psChild, "precision", "0" ));
610 16 : if (nPrecision < 0 || nPrecision > 1024)
611 : {
612 : CPLError( CE_Failure, CPLE_IllegalArg,
613 : "Invalid precision for field %s.",
614 1 : pszName );
615 : goto error;
616 : }
617 15 : oFieldDefn.SetPrecision(nPrecision);
618 :
619 : /* -------------------------------------------------------------------- */
620 : /* Create the field. */
621 : /* -------------------------------------------------------------------- */
622 15 : poFeatureDefn->AddFieldDefn( &oFieldDefn );
623 :
624 15 : abDirectCopy.push_back( FALSE );
625 :
626 : /* -------------------------------------------------------------------- */
627 : /* Source field. */
628 : /* -------------------------------------------------------------------- */
629 : int iSrcField =
630 15 : GetSrcLayerDefn()->GetFieldIndex( pszName );
631 :
632 15 : pszArg = CPLGetXMLValue( psChild, "src", NULL );
633 :
634 15 : if( pszArg != NULL )
635 : {
636 : iSrcField =
637 9 : GetSrcLayerDefn()->GetFieldIndex( pszArg );
638 9 : if( iSrcField == -1 )
639 : {
640 : CPLError( CE_Failure, CPLE_AppDefined,
641 : "Unable to find source field '%s'.",
642 1 : pszArg );
643 : goto error;
644 : }
645 : }
646 :
647 20 : if (iSrcField < 0 || (pszArg != NULL && strcmp(pszArg, pszName) != 0))
648 6 : bAttrFilterPassThrough = FALSE;
649 : else
650 : {
651 8 : OGRFieldDefn* poSrcFieldDefn = GetSrcLayerDefn()->GetFieldDefn(iSrcField);
652 8 : if (poSrcFieldDefn->GetType() != oFieldDefn.GetType())
653 4 : bAttrFilterPassThrough = FALSE;
654 : }
655 :
656 14 : anSrcField.push_back( iSrcField );
657 : }
658 : }
659 :
660 220 : CPLAssert( poFeatureDefn->GetFieldCount() == (int) anSrcField.size() );
661 :
662 : /* -------------------------------------------------------------------- */
663 : /* Create the schema, if it was not explicitly in the VRT. */
664 : /* -------------------------------------------------------------------- */
665 220 : if( poFeatureDefn->GetFieldCount() == 0 )
666 : {
667 : int bReportSrcColumn =
668 213 : CSLTestBoolean(CPLGetXMLValue( psLTree, "GeometryField.reportSrcColumn", "YES" ));
669 :
670 : int iSrcField;
671 : int iDstField;
672 213 : int nSrcFieldCount = GetSrcLayerDefn()->GetFieldCount();
673 213 : int nDstFieldCount = nSrcFieldCount;
674 213 : if (bReportSrcColumn == FALSE)
675 : {
676 2 : if (iGeomXField != -1) nDstFieldCount --;
677 2 : if (iGeomYField != -1) nDstFieldCount --;
678 2 : if (iGeomZField != -1) nDstFieldCount --;
679 2 : if (iGeomField != -1) nDstFieldCount --;
680 : }
681 :
682 617 : for( iSrcField = 0, iDstField = 0; iSrcField < nSrcFieldCount; iSrcField++ )
683 : {
684 404 : if (bReportSrcColumn == FALSE &&
685 : (iSrcField == iGeomXField || iSrcField == iGeomYField ||
686 : iSrcField == iGeomZField || iSrcField == iGeomField))
687 4 : continue;
688 :
689 400 : poFeatureDefn->AddFieldDefn( GetSrcLayerDefn()->GetFieldDefn( iSrcField ) );
690 400 : anSrcField.push_back( iSrcField );
691 400 : abDirectCopy.push_back( TRUE );
692 400 : iDstField++;
693 : }
694 213 : bAttrFilterPassThrough = TRUE;
695 : }
696 :
697 : /* -------------------------------------------------------------------- */
698 : /* Do we have a SrcRegion? */
699 : /* -------------------------------------------------------------------- */
700 220 : pszSrcRegion = CPLGetXMLValue( psLTree, "SrcRegion", NULL );
701 220 : if( pszSrcRegion != NULL )
702 : {
703 5 : OGRGeometryFactory::createFromWkt( (char**) &pszSrcRegion, NULL, &poSrcRegion );
704 5 : if( poSrcRegion == NULL || wkbFlatten(poSrcRegion->getGeometryType()) != wkbPolygon)
705 : {
706 : CPLError(CE_Warning, CPLE_AppDefined,
707 2 : "Ignoring SrcRegion. It must be a valid WKT polygon");
708 2 : delete poSrcRegion;
709 2 : poSrcRegion = NULL;
710 : }
711 :
712 5 : bSrcClip = CSLTestBoolean(CPLGetXMLValue( psLTree, "SrcRegion.clip", "FALSE" ));
713 : }
714 :
715 : /* -------------------------------------------------------------------- */
716 : /* Is VRT layer definition identical to the source layer defn ? */
717 : /* If so, use it directly, and save the translation of features. */
718 : /* -------------------------------------------------------------------- */
719 220 : if (poSrcFeatureDefn != NULL && iFIDField == -1 && iStyleField == -1 &&
720 : eGeometryStyle == VGS_Direct &&
721 : poSrcFeatureDefn->IsSame(poFeatureDefn))
722 : {
723 119 : CPLDebug("VRT", "Source feature definition is identical to VRT feature definition. Use optimized path");
724 119 : poFeatureDefn->Release();
725 119 : poFeatureDefn = poSrcFeatureDefn;
726 119 : poFeatureDefn->Reference();
727 : }
728 :
729 : /* -------------------------------------------------------------------- */
730 : /* Allow vrt to override whether attribute filters should be */
731 : /* passed through. */
732 : /* -------------------------------------------------------------------- */
733 220 : if( CPLGetXMLValue( psLTree, "attrFilterPassThrough", NULL ) != NULL )
734 : bAttrFilterPassThrough =
735 : CSLTestBoolean(
736 : CPLGetXMLValue(psLTree, "attrFilterPassThrough",
737 0 : "TRUE") );
738 :
739 220 : SetIgnoredFields(NULL);
740 :
741 220 : return TRUE;
742 :
743 : error:
744 38 : CPLFree( pszSrcDSName );
745 38 : if( poFeatureDefn )
746 38 : poFeatureDefn->Release();
747 38 : poFeatureDefn = new OGRFeatureDefn( osName );
748 38 : poFeatureDefn->Reference();
749 38 : return FALSE;
750 : }
751 :
752 : /************************************************************************/
753 : /* ResetReading() */
754 : /************************************************************************/
755 :
756 559 : void OGRVRTLayer::ResetReading()
757 :
758 : {
759 559 : bNeedReset = TRUE;
760 559 : }
761 :
762 : /************************************************************************/
763 : /* ResetSourceReading() */
764 : /************************************************************************/
765 :
766 271 : int OGRVRTLayer::ResetSourceReading()
767 :
768 : {
769 271 : int bSuccess = TRUE;
770 :
771 : /* -------------------------------------------------------------------- */
772 : /* Do we want to let source layer do spatial restriction? */
773 : /* -------------------------------------------------------------------- */
774 271 : char *pszFilter = NULL;
775 271 : if( (m_poFilterGeom || poSrcRegion) && bUseSpatialSubquery &&
776 : eGeometryStyle == VGS_PointFromColumns )
777 : {
778 : const char *pszXField, *pszYField;
779 :
780 9 : pszXField = poSrcLayer->GetLayerDefn()->GetFieldDefn(iGeomXField)->GetNameRef();
781 9 : pszYField = poSrcLayer->GetLayerDefn()->GetFieldDefn(iGeomYField)->GetNameRef();
782 9 : if (bUseSpatialSubquery)
783 : {
784 9 : OGRFieldType xType = poSrcLayer->GetLayerDefn()->GetFieldDefn(iGeomXField)->GetType();
785 9 : OGRFieldType yType = poSrcLayer->GetLayerDefn()->GetFieldDefn(iGeomYField)->GetType();
786 9 : if (!((xType == OFTReal || xType == OFTInteger) && (yType == OFTReal || yType == OFTInteger)))
787 : {
788 : CPLError(CE_Warning, CPLE_AppDefined,
789 : "The '%s' and/or '%s' fields of the source layer are not declared as numeric fields,\n"
790 : "so the spatial filter cannot be turned into an attribute filter on them",
791 1 : pszXField, pszYField);
792 1 : bUseSpatialSubquery = FALSE;
793 : }
794 : }
795 9 : if (bUseSpatialSubquery)
796 : {
797 8 : OGREnvelope sEnvelope;
798 :
799 : pszFilter = (char *)
800 8 : CPLMalloc(2*strlen(pszXField)+2*strlen(pszYField) + 100);
801 :
802 8 : if (poSrcRegion != NULL)
803 : {
804 5 : if (m_poFilterGeom == NULL)
805 3 : poSrcRegion->getEnvelope( &sEnvelope );
806 : else
807 : {
808 2 : OGRGeometry* poIntersection = poSrcRegion->Intersection(m_poFilterGeom);
809 2 : if (poIntersection)
810 : {
811 2 : poIntersection->getEnvelope( &sEnvelope );
812 2 : delete poIntersection;
813 : }
814 : else
815 : {
816 0 : sEnvelope.MinX = 0;
817 0 : sEnvelope.MaxX = 0;
818 0 : sEnvelope.MinY = 0;
819 0 : sEnvelope.MaxY = 0;
820 : }
821 : }
822 : }
823 : else
824 3 : m_poFilterGeom->getEnvelope( &sEnvelope );
825 :
826 : sprintf( pszFilter,
827 : "%s > %.15g AND %s < %.15g AND %s > %.15g AND %s < %.15g",
828 : pszXField, sEnvelope.MinX,
829 : pszXField, sEnvelope.MaxX,
830 : pszYField, sEnvelope.MinY,
831 8 : pszYField, sEnvelope.MaxY );
832 : char* pszComma;
833 16 : while((pszComma = strchr(pszFilter, ',')) != NULL)
834 0 : *pszComma = '.';
835 : }
836 : }
837 :
838 : /* -------------------------------------------------------------------- */
839 : /* Install spatial + attr filter query on source layer. */
840 : /* -------------------------------------------------------------------- */
841 514 : if( pszFilter == NULL && pszAttrFilter == NULL )
842 243 : bSuccess = (poSrcLayer->SetAttributeFilter( NULL ) == CE_None);
843 :
844 34 : else if( pszFilter != NULL && pszAttrFilter == NULL )
845 6 : bSuccess = (poSrcLayer->SetAttributeFilter( pszFilter ) == CE_None);
846 :
847 42 : else if( pszFilter == NULL && pszAttrFilter != NULL )
848 20 : bSuccess = (poSrcLayer->SetAttributeFilter( pszAttrFilter ) == CE_None);
849 :
850 : else
851 : {
852 2 : CPLString osMerged = pszFilter;
853 :
854 2 : osMerged += " AND (";
855 2 : osMerged += pszAttrFilter;
856 2 : osMerged += ")";
857 :
858 2 : bSuccess = (poSrcLayer->SetAttributeFilter(osMerged) == CE_None);
859 : }
860 :
861 271 : CPLFree( pszFilter );
862 :
863 : /* -------------------------------------------------------------------- */
864 : /* Clear spatial filter (to be safe) for non direct geometries */
865 : /* and reset reading. */
866 : /* -------------------------------------------------------------------- */
867 271 : if (eGeometryStyle == VGS_Direct)
868 : {
869 205 : if (poSrcRegion == NULL)
870 200 : poSrcLayer->SetSpatialFilter( m_poFilterGeom );
871 5 : else if (m_poFilterGeom == NULL)
872 3 : poSrcLayer->SetSpatialFilter( poSrcRegion );
873 : else
874 : {
875 2 : if( wkbFlatten(m_poFilterGeom->getGeometryType()) != wkbPolygon )
876 : {
877 : CPLError(CE_Failure, CPLE_AppDefined,
878 0 : "Spatial filter should be polygon when a SrcRegion is defined. Ignoring it");
879 0 : poSrcLayer->SetSpatialFilter( poSrcRegion );
880 : }
881 : else
882 : {
883 2 : OGRGeometry* poIntersection = m_poFilterGeom->Intersection(poSrcRegion);
884 2 : poSrcLayer->SetSpatialFilter( poIntersection );
885 2 : delete poIntersection;
886 : }
887 : }
888 : }
889 : else
890 66 : poSrcLayer->SetSpatialFilter( NULL );
891 271 : poSrcLayer->ResetReading();
892 271 : bNeedReset = FALSE;
893 :
894 271 : return bSuccess;
895 : }
896 :
897 : /************************************************************************/
898 : /* GetNextFeature() */
899 : /************************************************************************/
900 :
901 12284 : OGRFeature *OGRVRTLayer::GetNextFeature()
902 :
903 : {
904 12284 : if (!bHasFullInitialized) FullInitialize();
905 12284 : if (!poSrcLayer || poDS->GetRecursionDetected()) return NULL;
906 :
907 12277 : if( bNeedReset )
908 : {
909 201 : if( !ResetSourceReading() )
910 0 : return NULL;
911 : }
912 :
913 7 : for( ; TRUE; )
914 : {
915 : OGRFeature *poSrcFeature, *poFeature;
916 :
917 12284 : poSrcFeature = poSrcLayer->GetNextFeature();
918 12284 : if( poSrcFeature == NULL )
919 144 : return NULL;
920 :
921 12140 : if (poFeatureDefn == poSrcFeatureDefn)
922 : {
923 1572 : poFeature = poSrcFeature;
924 1572 : ClipAndAssignSRS(poFeature);
925 : }
926 : else
927 : {
928 10568 : poFeature = TranslateFeature( poSrcFeature, TRUE );
929 10568 : delete poSrcFeature;
930 : }
931 :
932 12140 : if( poFeature == NULL )
933 4 : return NULL;
934 :
935 12136 : if( (eGeometryStyle == VGS_Direct || m_poFilterGeom == NULL
936 : || FilterGeometry( poFeature->GetGeometryRef() ) )
937 : && (m_poAttrQuery == NULL
938 : || m_poAttrQuery->Evaluate( poFeature )) )
939 12129 : return poFeature;
940 :
941 7 : delete poFeature;
942 : }
943 : }
944 :
945 : /************************************************************************/
946 : /* ClipAndAssignSRS() */
947 : /************************************************************************/
948 :
949 12147 : void OGRVRTLayer::ClipAndAssignSRS(OGRFeature* poFeature)
950 : {
951 : /* Clip the geometry to the SrcRegion if asked */
952 12147 : if (poSrcRegion != NULL && bSrcClip && poFeature->GetGeometryRef() != NULL)
953 : {
954 0 : OGRGeometry* poClippedGeom = poFeature->GetGeometryRef()->Intersection(poSrcRegion);
955 0 : poFeature->SetGeometryDirectly(poClippedGeom);
956 : }
957 :
958 12147 : if (poFeature->GetGeometryRef() != NULL && poSRS != NULL)
959 11946 : poFeature->GetGeometryRef()->assignSpatialReference(poSRS);
960 12147 : }
961 :
962 : /************************************************************************/
963 : /* TranslateFeature() */
964 : /* */
965 : /* Translate a source feature into a feature for this layer. */
966 : /************************************************************************/
967 :
968 10585 : OGRFeature *OGRVRTLayer::TranslateFeature( OGRFeature*& poSrcFeat, int bUseSrcRegion )
969 :
970 : {
971 : retry:
972 10585 : OGRFeature *poDstFeat = new OGRFeature( poFeatureDefn );
973 :
974 10585 : m_nFeaturesRead++;
975 :
976 : /* -------------------------------------------------------------------- */
977 : /* Handle FID. */
978 : /* -------------------------------------------------------------------- */
979 10585 : if( iFIDField == -1 )
980 10561 : poDstFeat->SetFID( poSrcFeat->GetFID() );
981 : else
982 24 : poDstFeat->SetFID( poSrcFeat->GetFieldAsInteger( iFIDField ) );
983 :
984 : /* -------------------------------------------------------------------- */
985 : /* Handle style string. */
986 : /* -------------------------------------------------------------------- */
987 10585 : if( iStyleField != -1 )
988 : {
989 3 : if( poSrcFeat->IsFieldSet(iStyleField) )
990 : poDstFeat->SetStyleString(
991 3 : poSrcFeat->GetFieldAsString(iStyleField) );
992 : }
993 : else
994 : {
995 10582 : if( poSrcFeat->GetStyleString() != NULL )
996 0 : poDstFeat->SetStyleString(poSrcFeat->GetStyleString());
997 : }
998 :
999 : /* -------------------------------------------------------------------- */
1000 : /* Handle the geometry. Eventually there will be several more */
1001 : /* supported options. */
1002 : /* -------------------------------------------------------------------- */
1003 10585 : if( eGeometryStyle == VGS_None || GetLayerDefn()->IsGeometryIgnored() )
1004 : {
1005 : /* do nothing */
1006 : }
1007 10618 : else if( eGeometryStyle == VGS_WKT && iGeomField != -1 )
1008 : {
1009 43 : char *pszWKT = (char *) poSrcFeat->GetFieldAsString( iGeomField );
1010 :
1011 43 : if( pszWKT != NULL )
1012 : {
1013 43 : OGRGeometry *poGeom = NULL;
1014 :
1015 43 : OGRGeometryFactory::createFromWkt( &pszWKT, NULL, &poGeom );
1016 43 : if( poGeom == NULL )
1017 : CPLDebug( "OGR_VRT", "Did not get geometry from %s",
1018 0 : pszWKT );
1019 :
1020 43 : poDstFeat->SetGeometryDirectly( poGeom );
1021 : }
1022 : }
1023 10533 : else if( eGeometryStyle == VGS_WKB && iGeomField != -1 )
1024 : {
1025 : int nBytes;
1026 : GByte *pabyWKB;
1027 1 : int bNeedFree = FALSE;
1028 :
1029 1 : if( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
1030 : {
1031 0 : pabyWKB = poSrcFeat->GetFieldAsBinary( iGeomField, &nBytes );
1032 : }
1033 : else
1034 : {
1035 1 : const char *pszWKT = poSrcFeat->GetFieldAsString( iGeomField );
1036 :
1037 1 : pabyWKB = CPLHexToBinary( pszWKT, &nBytes );
1038 1 : bNeedFree = TRUE;
1039 : }
1040 :
1041 1 : if( pabyWKB != NULL )
1042 : {
1043 1 : OGRGeometry *poGeom = NULL;
1044 :
1045 1 : if( OGRGeometryFactory::createFromWkb( pabyWKB, NULL, &poGeom,
1046 : nBytes ) == OGRERR_NONE )
1047 1 : poDstFeat->SetGeometryDirectly( poGeom );
1048 : }
1049 :
1050 1 : if( bNeedFree )
1051 1 : CPLFree( pabyWKB );
1052 : }
1053 10534 : else if( eGeometryStyle == VGS_Shape && iGeomField != -1 )
1054 : {
1055 : int nBytes;
1056 : GByte *pabyWKB;
1057 3 : int bNeedFree = FALSE;
1058 :
1059 3 : if( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
1060 : {
1061 0 : pabyWKB = poSrcFeat->GetFieldAsBinary( iGeomField, &nBytes );
1062 : }
1063 : else
1064 : {
1065 3 : const char *pszWKT = poSrcFeat->GetFieldAsString( iGeomField );
1066 :
1067 3 : pabyWKB = CPLHexToBinary( pszWKT, &nBytes );
1068 3 : bNeedFree = TRUE;
1069 : }
1070 :
1071 3 : if( pabyWKB != NULL )
1072 : {
1073 3 : OGRGeometry *poGeom = NULL;
1074 :
1075 3 : if( OGRCreateFromShapeBin( pabyWKB, &poGeom, nBytes ) == OGRERR_NONE )
1076 3 : poDstFeat->SetGeometryDirectly( poGeom );
1077 : }
1078 :
1079 3 : if( bNeedFree )
1080 3 : CPLFree( pabyWKB );
1081 : }
1082 10528 : else if( eGeometryStyle == VGS_Direct )
1083 : {
1084 97 : poDstFeat->SetGeometry( poSrcFeat->GetGeometryRef() );
1085 : }
1086 10431 : else if( eGeometryStyle == VGS_PointFromColumns )
1087 : {
1088 10430 : if( iGeomZField != -1 )
1089 : poDstFeat->SetGeometryDirectly(
1090 : new OGRPoint( poSrcFeat->GetFieldAsDouble( iGeomXField ),
1091 : poSrcFeat->GetFieldAsDouble( iGeomYField ),
1092 10410 : poSrcFeat->GetFieldAsDouble( iGeomZField ) ) );
1093 : else
1094 : poDstFeat->SetGeometryDirectly(
1095 : new OGRPoint( poSrcFeat->GetFieldAsDouble( iGeomXField ),
1096 20 : poSrcFeat->GetFieldAsDouble( iGeomYField ) ) );
1097 : }
1098 : else
1099 : /* add other options here. */;
1100 :
1101 : /* In the non direct case, we need to check that the geometry intersects the source */
1102 : /* region before an optionnal clipping */
1103 10585 : if( bUseSrcRegion && eGeometryStyle != VGS_Direct && poSrcRegion != NULL )
1104 : {
1105 23 : OGRGeometry* poGeom = poDstFeat->GetGeometryRef();
1106 23 : if (poGeom != NULL && !poGeom->Intersects(poSrcRegion))
1107 : {
1108 14 : delete poSrcFeat;
1109 14 : delete poDstFeat;
1110 :
1111 : /* Fetch next source feature and retry translating it */
1112 14 : poSrcFeat = poSrcLayer->GetNextFeature();
1113 14 : if (poSrcFeat == NULL)
1114 4 : return NULL;
1115 :
1116 10 : goto retry;
1117 : }
1118 : }
1119 :
1120 10571 : ClipAndAssignSRS(poDstFeat);
1121 :
1122 : /* -------------------------------------------------------------------- */
1123 : /* Copy fields. */
1124 : /* -------------------------------------------------------------------- */
1125 : int iVRTField;
1126 :
1127 42315 : for( iVRTField = 0; iVRTField < poFeatureDefn->GetFieldCount(); iVRTField++ )
1128 : {
1129 31744 : if( anSrcField[iVRTField] == -1 )
1130 8 : continue;
1131 :
1132 31736 : OGRFieldDefn *poDstDefn = poFeatureDefn->GetFieldDefn( iVRTField );
1133 31736 : OGRFieldDefn *poSrcDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( anSrcField[iVRTField] );
1134 :
1135 31736 : if( !poSrcFeat->IsFieldSet( anSrcField[iVRTField] ) || poDstDefn->IsIgnored() )
1136 11 : continue;
1137 :
1138 31725 : if( abDirectCopy[iVRTField]
1139 : && poDstDefn->GetType() == poSrcDefn->GetType() )
1140 : {
1141 : poDstFeat->SetField( iVRTField,
1142 31698 : poSrcFeat->GetRawFieldRef( anSrcField[iVRTField] ) );
1143 : }
1144 : else
1145 : {
1146 : /* Eventually we need to offer some more sophisticated translation
1147 : options here for more esoteric types. */
1148 27 : if (poDstDefn->GetType() == OFTReal)
1149 : poDstFeat->SetField( iVRTField,
1150 1 : poSrcFeat->GetFieldAsDouble(anSrcField[iVRTField]));
1151 : else
1152 : poDstFeat->SetField( iVRTField,
1153 26 : poSrcFeat->GetFieldAsString(anSrcField[iVRTField]));
1154 : }
1155 : }
1156 :
1157 10571 : return poDstFeat;
1158 : }
1159 :
1160 :
1161 : /************************************************************************/
1162 : /* GetFeature() */
1163 : /************************************************************************/
1164 :
1165 18 : OGRFeature *OGRVRTLayer::GetFeature( long nFeatureId )
1166 :
1167 : {
1168 18 : if (!bHasFullInitialized) FullInitialize();
1169 18 : if (!poSrcLayer || poDS->GetRecursionDetected()) return NULL;
1170 :
1171 17 : bNeedReset = TRUE;
1172 :
1173 : /* -------------------------------------------------------------------- */
1174 : /* If the FID is directly mapped, we can do a simple */
1175 : /* GetFeature() to get our target feature. Otherwise we need */
1176 : /* to setup an appropriate query to get it. */
1177 : /* -------------------------------------------------------------------- */
1178 : OGRFeature *poSrcFeature, *poFeature;
1179 :
1180 17 : if( iFIDField == -1 )
1181 : {
1182 15 : poSrcFeature = poSrcLayer->GetFeature( nFeatureId );
1183 : }
1184 : else
1185 : {
1186 2 : const char* pszFID = poSrcLayer->GetLayerDefn()->GetFieldDefn(iFIDField)->GetNameRef();
1187 2 : char* pszFIDQuery = (char*)CPLMalloc(strlen(pszFID) + 64);
1188 :
1189 2 : poSrcLayer->ResetReading();
1190 2 : sprintf( pszFIDQuery, "%s = %ld", pszFID, nFeatureId );
1191 2 : poSrcLayer->SetSpatialFilter( NULL );
1192 2 : poSrcLayer->SetAttributeFilter( pszFIDQuery );
1193 2 : CPLFree(pszFIDQuery);
1194 :
1195 2 : poSrcFeature = poSrcLayer->GetNextFeature();
1196 : }
1197 :
1198 17 : if( poSrcFeature == NULL )
1199 6 : return NULL;
1200 :
1201 : /* -------------------------------------------------------------------- */
1202 : /* Translate feature and return it. */
1203 : /* -------------------------------------------------------------------- */
1204 11 : if (poFeatureDefn == poSrcFeatureDefn)
1205 : {
1206 4 : poFeature = poSrcFeature;
1207 4 : ClipAndAssignSRS(poFeature);
1208 : }
1209 : else
1210 : {
1211 7 : poFeature = TranslateFeature( poSrcFeature, FALSE );
1212 7 : delete poSrcFeature;
1213 : }
1214 :
1215 11 : return poFeature;
1216 : }
1217 :
1218 : /************************************************************************/
1219 : /* SetNextByIndex() */
1220 : /************************************************************************/
1221 :
1222 14 : OGRErr OGRVRTLayer::SetNextByIndex( long nIndex )
1223 : {
1224 14 : if (!bHasFullInitialized) FullInitialize();
1225 14 : if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
1226 :
1227 13 : if( bNeedReset )
1228 : {
1229 4 : if( !ResetSourceReading() )
1230 0 : return OGRERR_FAILURE;
1231 : }
1232 :
1233 13 : if (TestCapability(OLCFastSetNextByIndex))
1234 13 : return poSrcLayer->SetNextByIndex(nIndex);
1235 :
1236 0 : return OGRLayer::SetNextByIndex(nIndex);
1237 : }
1238 :
1239 : /************************************************************************/
1240 : /* TranslateVRTFeatureToSrcFeature() */
1241 : /* */
1242 : /* Translate a VRT feature into a feature for the source layer */
1243 : /************************************************************************/
1244 :
1245 3 : OGRFeature* OGRVRTLayer::TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeature)
1246 : {
1247 3 : OGRFeature *poSrcFeat = new OGRFeature( poSrcLayer->GetLayerDefn() );
1248 :
1249 3 : poSrcFeat->SetFID( poVRTFeature->GetFID() );
1250 :
1251 : /* -------------------------------------------------------------------- */
1252 : /* Handle style string. */
1253 : /* -------------------------------------------------------------------- */
1254 3 : if( iStyleField != -1 )
1255 : {
1256 0 : if( poVRTFeature->GetStyleString() != NULL )
1257 0 : poSrcFeat->SetField( iStyleField, poVRTFeature->GetStyleString() );
1258 : }
1259 : else
1260 : {
1261 3 : if( poVRTFeature->GetStyleString() != NULL )
1262 0 : poSrcFeat->SetStyleString(poVRTFeature->GetStyleString());
1263 : }
1264 :
1265 : /* -------------------------------------------------------------------- */
1266 : /* Handle the geometry. Eventually there will be several more */
1267 : /* supported options. */
1268 : /* -------------------------------------------------------------------- */
1269 3 : if( eGeometryStyle == VGS_None )
1270 : {
1271 : /* do nothing */
1272 : }
1273 3 : else if( eGeometryStyle == VGS_WKT )
1274 : {
1275 1 : OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
1276 1 : if (poGeom != NULL)
1277 : {
1278 1 : char* pszWKT = NULL;
1279 1 : if (poGeom->exportToWkt(&pszWKT) == OGRERR_NONE)
1280 : {
1281 1 : poSrcFeat->SetField(iGeomField, pszWKT);
1282 : }
1283 1 : CPLFree(pszWKT);
1284 : }
1285 : }
1286 2 : else if( eGeometryStyle == VGS_WKB )
1287 : {
1288 1 : OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
1289 1 : if (poGeom != NULL)
1290 : {
1291 1 : int nSize = poGeom->WkbSize();
1292 1 : GByte* pabyData = (GByte*)CPLMalloc(nSize);
1293 1 : if (poGeom->exportToWkb(wkbNDR, pabyData) == OGRERR_NONE)
1294 : {
1295 1 : if ( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
1296 : {
1297 0 : poSrcFeat->SetField(iGeomField, nSize, pabyData);
1298 : }
1299 : else
1300 : {
1301 1 : char* pszHexWKB = CPLBinaryToHex(nSize, pabyData);
1302 1 : poSrcFeat->SetField(iGeomField, pszHexWKB);
1303 1 : CPLFree(pszHexWKB);
1304 : }
1305 : }
1306 1 : CPLFree(pabyData);
1307 : }
1308 : }
1309 1 : else if( eGeometryStyle == VGS_Shape )
1310 : {
1311 0 : CPLDebug("OGR_VRT", "Update of VGS_Shape geometries not supported");
1312 : }
1313 1 : else if( eGeometryStyle == VGS_Direct )
1314 : {
1315 0 : poSrcFeat->SetGeometry( poVRTFeature->GetGeometryRef() );
1316 : }
1317 1 : else if( eGeometryStyle == VGS_PointFromColumns )
1318 : {
1319 1 : OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
1320 1 : if (poGeom != NULL)
1321 : {
1322 1 : if (wkbFlatten(poGeom->getGeometryType()) != wkbPoint)
1323 : {
1324 : CPLError(CE_Warning, CPLE_NotSupported,
1325 0 : "Cannot set a non ponctual geometry for PointFromColumns geometry");
1326 : }
1327 : else
1328 : {
1329 1 : poSrcFeat->SetField( iGeomXField, ((OGRPoint*)poGeom)->getX() );
1330 1 : poSrcFeat->SetField( iGeomYField, ((OGRPoint*)poGeom)->getY() );
1331 1 : if( iGeomZField != -1 )
1332 : {
1333 0 : poSrcFeat->SetField( iGeomZField, ((OGRPoint*)poGeom)->getZ() );
1334 : }
1335 : }
1336 : }
1337 : }
1338 : else
1339 : /* add other options here. */;
1340 :
1341 3 : if (poSrcFeat->GetGeometryRef() != NULL && poSRS != NULL)
1342 0 : poSrcFeat->GetGeometryRef()->assignSpatialReference(poSRS);
1343 :
1344 : /* -------------------------------------------------------------------- */
1345 : /* Copy fields. */
1346 : /* -------------------------------------------------------------------- */
1347 :
1348 : int iVRTField;
1349 :
1350 11 : for( iVRTField = 0; iVRTField < poFeatureDefn->GetFieldCount(); iVRTField++ )
1351 : {
1352 : /* Do not set source geometry columns. Have been set just above */
1353 8 : if (anSrcField[iVRTField] == iGeomField || anSrcField[iVRTField] == iGeomXField ||
1354 : anSrcField[iVRTField] == iGeomYField || anSrcField[iVRTField] == iGeomZField)
1355 2 : continue;
1356 :
1357 6 : OGRFieldDefn *poVRTDefn = poFeatureDefn->GetFieldDefn( iVRTField );
1358 6 : OGRFieldDefn *poSrcDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( anSrcField[iVRTField] );
1359 :
1360 6 : if( abDirectCopy[iVRTField]
1361 : && poVRTDefn->GetType() == poSrcDefn->GetType() )
1362 : {
1363 : poSrcFeat->SetField( anSrcField[iVRTField],
1364 6 : poVRTFeature->GetRawFieldRef( iVRTField ) );
1365 : }
1366 : else
1367 : {
1368 : /* Eventually we need to offer some more sophisticated translation
1369 : options here for more esoteric types. */
1370 : poSrcFeat->SetField( anSrcField[iVRTField],
1371 0 : poVRTFeature->GetFieldAsString(iVRTField));
1372 : }
1373 : }
1374 :
1375 3 : return poSrcFeat;
1376 : }
1377 :
1378 : /************************************************************************/
1379 : /* CreateFeature() */
1380 : /************************************************************************/
1381 :
1382 8 : OGRErr OGRVRTLayer::CreateFeature( OGRFeature* poVRTFeature )
1383 : {
1384 8 : if (!bHasFullInitialized) FullInitialize();
1385 8 : if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
1386 :
1387 7 : if(!bUpdate)
1388 : {
1389 : CPLError( CE_Failure, CPLE_NotSupported,
1390 : UNSUPPORTED_OP_READ_ONLY,
1391 1 : "CreateFeature");
1392 1 : return OGRERR_FAILURE;
1393 : }
1394 :
1395 6 : if( iFIDField != -1 )
1396 : {
1397 : CPLError( CE_Failure, CPLE_AppDefined,
1398 0 : "The CreateFeature() operation is not supported if the FID option is specified." );
1399 0 : return OGRERR_FAILURE;
1400 : }
1401 :
1402 6 : if( poSrcFeatureDefn == poFeatureDefn )
1403 3 : return poSrcLayer->CreateFeature(poVRTFeature);
1404 :
1405 3 : OGRFeature* poSrcFeature = TranslateVRTFeatureToSrcFeature(poVRTFeature);
1406 3 : poSrcFeature->SetFID(OGRNullFID);
1407 3 : OGRErr eErr = poSrcLayer->CreateFeature(poSrcFeature);
1408 3 : if (eErr == OGRERR_NONE)
1409 : {
1410 3 : poVRTFeature->SetFID(poSrcFeature->GetFID());
1411 : }
1412 3 : delete poSrcFeature;
1413 3 : return eErr;
1414 : }
1415 :
1416 : /************************************************************************/
1417 : /* SetFeature() */
1418 : /************************************************************************/
1419 :
1420 4 : OGRErr OGRVRTLayer::SetFeature( OGRFeature* poVRTFeature )
1421 : {
1422 4 : if (!bHasFullInitialized) FullInitialize();
1423 4 : if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
1424 :
1425 3 : if(!bUpdate)
1426 : {
1427 : CPLError( CE_Failure, CPLE_NotSupported,
1428 : UNSUPPORTED_OP_READ_ONLY,
1429 1 : "SetFeature");
1430 1 : return OGRERR_FAILURE;
1431 : }
1432 :
1433 2 : if( iFIDField != -1 )
1434 : {
1435 : CPLError( CE_Failure, CPLE_AppDefined,
1436 0 : "The SetFeature() operation is not supported if the FID option is specified." );
1437 0 : return OGRERR_FAILURE;
1438 : }
1439 :
1440 2 : if( poSrcFeatureDefn == poFeatureDefn )
1441 2 : return poSrcLayer->SetFeature(poVRTFeature);
1442 :
1443 0 : OGRFeature* poSrcFeature = TranslateVRTFeatureToSrcFeature(poVRTFeature);
1444 0 : OGRErr eErr = poSrcLayer->SetFeature(poSrcFeature);
1445 0 : delete poSrcFeature;
1446 0 : return eErr;
1447 : }
1448 :
1449 : /************************************************************************/
1450 : /* DeleteFeature() */
1451 : /************************************************************************/
1452 :
1453 2 : OGRErr OGRVRTLayer::DeleteFeature( long nFID )
1454 :
1455 : {
1456 2 : if (!bHasFullInitialized) FullInitialize();
1457 2 : if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
1458 :
1459 1 : if(!bUpdate )
1460 : {
1461 : CPLError( CE_Failure, CPLE_NotSupported,
1462 : UNSUPPORTED_OP_READ_ONLY,
1463 1 : "DeleteFeature");
1464 1 : return OGRERR_FAILURE;
1465 : }
1466 :
1467 0 : if( iFIDField != -1 )
1468 : {
1469 : CPLError( CE_Failure, CPLE_AppDefined,
1470 0 : "The DeleteFeature() operation is not supported if the FID option is specified." );
1471 0 : return OGRERR_FAILURE;
1472 : }
1473 :
1474 0 : return poSrcLayer->DeleteFeature(nFID);
1475 : }
1476 :
1477 : /************************************************************************/
1478 : /* SetAttributeFilter() */
1479 : /************************************************************************/
1480 :
1481 230 : OGRErr OGRVRTLayer::SetAttributeFilter( const char *pszNewQuery )
1482 :
1483 : {
1484 230 : if (!bHasFullInitialized) FullInitialize();
1485 230 : if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
1486 :
1487 217 : if( bAttrFilterPassThrough )
1488 : {
1489 216 : CPLFree( pszAttrFilter );
1490 401 : if( pszNewQuery == NULL || strlen(pszNewQuery) == 0 )
1491 185 : pszAttrFilter = NULL;
1492 : else
1493 31 : pszAttrFilter = CPLStrdup( pszNewQuery );
1494 :
1495 216 : ResetReading();
1496 216 : return OGRERR_NONE;
1497 : }
1498 : else
1499 : {
1500 : /* setup m_poAttrQuery */
1501 1 : return OGRLayer::SetAttributeFilter( pszNewQuery );
1502 : }
1503 : }
1504 :
1505 : /************************************************************************/
1506 : /* TestCapability() */
1507 : /************************************************************************/
1508 :
1509 201 : int OGRVRTLayer::TestCapability( const char * pszCap )
1510 :
1511 : {
1512 201 : if ( EQUAL(pszCap,OLCFastFeatureCount) &&
1513 : nFeatureCount >= 0 &&
1514 : m_poFilterGeom == NULL && m_poAttrQuery == NULL )
1515 0 : return TRUE;
1516 :
1517 201 : if ( EQUAL(pszCap,OLCFastGetExtent) &&
1518 : sStaticEnvelope.IsInit() )
1519 0 : return TRUE;
1520 :
1521 201 : if (!bHasFullInitialized) FullInitialize();
1522 201 : if (!poSrcLayer || poDS->GetRecursionDetected()) return FALSE;
1523 :
1524 194 : if ( EQUAL(pszCap,OLCFastFeatureCount) ||
1525 : EQUAL(pszCap,OLCFastSetNextByIndex) )
1526 : return (eGeometryStyle == VGS_Direct ||
1527 : (poSrcRegion == NULL && m_poFilterGeom == NULL)) &&
1528 : m_poAttrQuery == NULL &&
1529 24 : poSrcLayer->TestCapability(pszCap);
1530 :
1531 170 : else if( EQUAL(pszCap,OLCFastSpatialFilter) )
1532 : return eGeometryStyle == VGS_Direct && m_poAttrQuery == NULL &&
1533 8 : poSrcLayer->TestCapability(pszCap);
1534 :
1535 162 : else if ( EQUAL(pszCap,OLCFastGetExtent) )
1536 : return eGeometryStyle == VGS_Direct &&
1537 : m_poAttrQuery == NULL &&
1538 : (poSrcRegion == NULL || bSrcClip) &&
1539 5 : poSrcLayer->TestCapability(pszCap);
1540 :
1541 157 : else if( EQUAL(pszCap,OLCRandomRead) )
1542 4 : return iFIDField == -1 && poSrcLayer->TestCapability(pszCap);
1543 :
1544 153 : else if( EQUAL(pszCap,OLCSequentialWrite)
1545 : || EQUAL(pszCap,OLCRandomWrite)
1546 : || EQUAL(pszCap,OLCDeleteFeature) )
1547 13 : return bUpdate && iFIDField == -1 && poSrcLayer->TestCapability(pszCap);
1548 :
1549 140 : else if( EQUAL(pszCap,OLCStringsAsUTF8) )
1550 11 : return poSrcLayer->TestCapability(pszCap);
1551 :
1552 129 : else if( EQUAL(pszCap,OLCTransactions) )
1553 1 : return bUpdate && poSrcLayer->TestCapability(pszCap);
1554 :
1555 128 : else if( EQUAL(pszCap,OLCIgnoreFields) )
1556 125 : return poSrcLayer->TestCapability(pszCap);
1557 :
1558 3 : return FALSE;
1559 : }
1560 :
1561 : /************************************************************************/
1562 : /* GetSpatialRef() */
1563 : /************************************************************************/
1564 :
1565 772 : OGRSpatialReference *OGRVRTLayer::GetSpatialRef()
1566 :
1567 : {
1568 772 : if (CPLGetXMLValue( psLTree, "LayerSRS", NULL ) != NULL)
1569 33 : return poSRS;
1570 :
1571 739 : if (!bHasFullInitialized) FullInitialize();
1572 739 : if (!poSrcLayer || poDS->GetRecursionDetected()) return NULL;
1573 :
1574 659 : return poSRS;
1575 : }
1576 :
1577 : /************************************************************************/
1578 : /* GetExtent() */
1579 : /************************************************************************/
1580 :
1581 17 : OGRErr OGRVRTLayer::GetExtent( OGREnvelope *psExtent, int bForce )
1582 : {
1583 17 : if( sStaticEnvelope.IsInit() )
1584 : {
1585 0 : memcpy(psExtent, &sStaticEnvelope, sizeof(OGREnvelope));
1586 0 : return OGRERR_NONE;
1587 : }
1588 :
1589 17 : if (!bHasFullInitialized) FullInitialize();
1590 17 : if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
1591 :
1592 16 : if ( eGeometryStyle == VGS_Direct &&
1593 : m_poAttrQuery == NULL &&
1594 : (poSrcRegion == NULL || bSrcClip) )
1595 : {
1596 12 : if( bNeedReset )
1597 10 : ResetSourceReading();
1598 :
1599 12 : OGRErr eErr = poSrcLayer->GetExtent(psExtent, bForce);
1600 12 : if( eErr != OGRERR_NONE || poSrcRegion == NULL )
1601 12 : return eErr;
1602 :
1603 0 : OGREnvelope sSrcRegionEnvelope;
1604 0 : poSrcRegion->getEnvelope(&sSrcRegionEnvelope);
1605 :
1606 0 : psExtent->Intersect(sSrcRegionEnvelope);
1607 0 : return eErr;
1608 : }
1609 :
1610 4 : return OGRLayer::GetExtent(psExtent, bForce);
1611 : }
1612 :
1613 : /************************************************************************/
1614 : /* GetFeatureCount() */
1615 : /************************************************************************/
1616 :
1617 93 : int OGRVRTLayer::GetFeatureCount( int bForce )
1618 :
1619 : {
1620 93 : if (nFeatureCount >= 0 &&
1621 : m_poFilterGeom == NULL && m_poAttrQuery == NULL)
1622 : {
1623 0 : return nFeatureCount;
1624 : }
1625 :
1626 93 : if (!bHasFullInitialized) FullInitialize();
1627 93 : if (!poSrcLayer || poDS->GetRecursionDetected()) return 0;
1628 :
1629 84 : if ((eGeometryStyle == VGS_Direct ||
1630 : (poSrcRegion == NULL && m_poFilterGeom == NULL)) &&
1631 : m_poAttrQuery == NULL )
1632 : {
1633 72 : if( bNeedReset )
1634 56 : ResetSourceReading();
1635 :
1636 72 : return poSrcLayer->GetFeatureCount( bForce );
1637 : }
1638 : else
1639 12 : return OGRLayer::GetFeatureCount( bForce );
1640 : }
1641 :
1642 :
1643 : /************************************************************************/
1644 : /* SetSpatialFilter() */
1645 : /************************************************************************/
1646 :
1647 245 : void OGRVRTLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
1648 : {
1649 245 : if (!bHasFullInitialized) FullInitialize();
1650 245 : if (!poSrcLayer || poDS->GetRecursionDetected()) return;
1651 :
1652 232 : if (eGeometryStyle == VGS_Direct)
1653 221 : bNeedReset = TRUE;
1654 232 : OGRLayer::SetSpatialFilter(poGeomIn);
1655 : }
1656 :
1657 : /************************************************************************/
1658 : /* SyncToDisk() */
1659 : /************************************************************************/
1660 :
1661 3 : OGRErr OGRVRTLayer::SyncToDisk()
1662 : {
1663 3 : if (!bHasFullInitialized) FullInitialize();
1664 3 : if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
1665 :
1666 2 : return poSrcLayer->SyncToDisk();
1667 : }
1668 :
1669 : /************************************************************************/
1670 : /* GetLayerDefn() */
1671 : /************************************************************************/
1672 :
1673 12228 : OGRFeatureDefn *OGRVRTLayer::GetLayerDefn()
1674 : {
1675 12228 : if (!bHasFullInitialized) FullInitialize();
1676 :
1677 12228 : return poFeatureDefn;
1678 : }
1679 :
1680 : /************************************************************************/
1681 : /* GetGeomType() */
1682 : /************************************************************************/
1683 :
1684 129 : OGRwkbGeometryType OGRVRTLayer::GetGeomType()
1685 : {
1686 129 : if (CPLGetXMLValue( psLTree, "GeometryType", NULL ) != NULL)
1687 3 : return eGeomType;
1688 :
1689 126 : return GetLayerDefn()->GetGeomType();
1690 : }
1691 :
1692 : /************************************************************************/
1693 : /* GetFIDColumn() */
1694 : /************************************************************************/
1695 :
1696 5 : const char * OGRVRTLayer::GetFIDColumn()
1697 : {
1698 5 : if (!bHasFullInitialized) FullInitialize();
1699 5 : if (!poSrcLayer || poDS->GetRecursionDetected()) return "";
1700 :
1701 : const char* pszFIDColumn;
1702 4 : if (iFIDField == -1)
1703 : {
1704 : /* If pass-through, then query the source layer FID column */
1705 1 : pszFIDColumn = poSrcLayer->GetFIDColumn();
1706 1 : if (pszFIDColumn == NULL || EQUAL(pszFIDColumn, ""))
1707 1 : return "";
1708 : }
1709 : else
1710 : {
1711 : /* Otherwise get the name from the index in the source layer definition */
1712 3 : OGRFieldDefn* poFDefn = GetSrcLayerDefn()->GetFieldDefn(iFIDField);
1713 3 : pszFIDColumn = poFDefn->GetNameRef();
1714 : }
1715 :
1716 : /* Check that the FIDColumn is actually reported in the VRT layer definition */
1717 3 : if (GetLayerDefn()->GetFieldIndex(pszFIDColumn) != -1)
1718 2 : return pszFIDColumn;
1719 : else
1720 1 : return "";
1721 : }
1722 :
1723 : /************************************************************************/
1724 : /* StartTransaction() */
1725 : /************************************************************************/
1726 :
1727 3 : OGRErr OGRVRTLayer::StartTransaction()
1728 : {
1729 3 : if (!bHasFullInitialized) FullInitialize();
1730 3 : if (!poSrcLayer || !bUpdate || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
1731 :
1732 2 : return poSrcLayer->StartTransaction();
1733 : }
1734 :
1735 : /************************************************************************/
1736 : /* CommitTransaction() */
1737 : /************************************************************************/
1738 :
1739 2 : OGRErr OGRVRTLayer::CommitTransaction()
1740 : {
1741 2 : if (!bHasFullInitialized) FullInitialize();
1742 2 : if (!poSrcLayer || !bUpdate || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
1743 :
1744 1 : return poSrcLayer->CommitTransaction();
1745 : }
1746 :
1747 : /************************************************************************/
1748 : /* RollbackTransaction() */
1749 : /************************************************************************/
1750 :
1751 2 : OGRErr OGRVRTLayer::RollbackTransaction()
1752 : {
1753 2 : if (!bHasFullInitialized) FullInitialize();
1754 2 : if (!poSrcLayer || !bUpdate || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
1755 :
1756 1 : return poSrcLayer->RollbackTransaction();
1757 : }
1758 :
1759 : /************************************************************************/
1760 : /* SetIgnoredFields() */
1761 : /************************************************************************/
1762 :
1763 364 : OGRErr OGRVRTLayer::SetIgnoredFields( const char **papszFields )
1764 : {
1765 364 : if (!bHasFullInitialized) FullInitialize();
1766 364 : if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
1767 :
1768 300 : if( !poSrcLayer->TestCapability(OLCIgnoreFields) )
1769 45 : return OGRERR_FAILURE;
1770 :
1771 255 : OGRErr eErr = OGRLayer::SetIgnoredFields(papszFields);
1772 255 : if( eErr != OGRERR_NONE )
1773 0 : return eErr;
1774 :
1775 255 : const char** papszIter = papszFields;
1776 255 : char** papszFieldsSrc = NULL;
1777 255 : OGRFeatureDefn* poSrcFeatureDefn = poSrcLayer->GetLayerDefn();
1778 548 : while ( papszIter != NULL && *papszIter != NULL )
1779 : {
1780 38 : const char* pszFieldName = *papszIter;
1781 45 : if ( EQUAL(pszFieldName, "OGR_GEOMETRY") ||
1782 : EQUAL(pszFieldName, "OGR_STYLE") )
1783 : {
1784 7 : papszFieldsSrc = CSLAddString(papszFieldsSrc, pszFieldName);
1785 : }
1786 : else
1787 : {
1788 31 : int iVRTField = GetLayerDefn()->GetFieldIndex(pszFieldName);
1789 31 : if( iVRTField >= 0 )
1790 : {
1791 31 : int iSrcField = anSrcField[iVRTField];
1792 31 : if (iSrcField >= 0)
1793 : {
1794 31 : OGRFieldDefn *poSrcDefn = poSrcFeatureDefn->GetFieldDefn( iSrcField );
1795 31 : papszFieldsSrc = CSLAddString(papszFieldsSrc, poSrcDefn->GetNameRef());
1796 : }
1797 : }
1798 : }
1799 38 : papszIter++;
1800 : }
1801 :
1802 255 : int* panSrcFieldsUsed = (int*) CPLCalloc(sizeof(int), poSrcFeatureDefn->GetFieldCount());
1803 832 : for(int iVRTField = 0; iVRTField < GetLayerDefn()->GetFieldCount(); iVRTField++)
1804 : {
1805 577 : int iSrcField = anSrcField[iVRTField];
1806 577 : if (iSrcField >= 0)
1807 577 : panSrcFieldsUsed[iSrcField] = TRUE;
1808 : }
1809 837 : for(int iSrcField = 0; iSrcField < poSrcFeatureDefn->GetFieldCount(); iSrcField ++)
1810 : {
1811 582 : if( !panSrcFieldsUsed[iSrcField] )
1812 : {
1813 5 : OGRFieldDefn *poSrcDefn = poSrcFeatureDefn->GetFieldDefn( iSrcField );
1814 5 : papszFieldsSrc = CSLAddString(papszFieldsSrc, poSrcDefn->GetNameRef());
1815 : }
1816 : }
1817 255 : CPLFree(panSrcFieldsUsed);
1818 :
1819 255 : eErr = poSrcLayer->SetIgnoredFields((const char**)papszFieldsSrc);
1820 :
1821 255 : CSLDestroy(papszFieldsSrc);
1822 :
1823 255 : return eErr;
1824 : }
|