LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/vrt - ogrvrtlayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 732 666 91.0 %
Date: 2012-12-26 Functions: 33 30 90.9 %

       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                 : }

Generated by: LCOV version 1.7