LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/mitab - mitab_ogr_datasource.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 213 239 89.1 %
Date: 2024-11-21 22:18:42 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /**********************************************************************
       2             :  *
       3             :  * Name:     mitab_ogr_datasource.cpp
       4             :  * Project:  MapInfo Mid/Mif, Tab ogr support
       5             :  * Language: C++
       6             :  * Purpose:  Implementation of OGRTABDataSource.
       7             :  * Author:   Stephane Villeneuve, stephane.v@videotron.ca
       8             :  *           and Frank Warmerdam, warmerdam@pobox.com
       9             :  *
      10             :  **********************************************************************
      11             :  * Copyright (c) 1999, 2000, Stephane Villeneuve
      12             :  * Copyright (c) 2014, Even Rouault <even.rouault at spatialys.com>
      13             :  *
      14             :  * SPDX-License-Identifier: MIT
      15             :  **********************************************************************/
      16             : 
      17             : #include "mitab_ogr_driver.h"
      18             : 
      19             : /*=======================================================================
      20             :  *                 OGRTABDataSource
      21             :  *
      22             :  * We need one single OGRDataSource/Driver set of classes to handle all
      23             :  * the MapInfo file types.  They all deal with the IMapInfoFile abstract
      24             :  * class.
      25             :  *=====================================================================*/
      26             : 
      27             : /************************************************************************/
      28             : /*                         OGRTABDataSource()                           */
      29             : /************************************************************************/
      30             : 
      31        3006 : OGRTABDataSource::OGRTABDataSource()
      32             :     : m_pszDirectory(nullptr), m_nLayerCount(0), m_papoLayers(nullptr),
      33             :       m_papszOptions(nullptr), m_bCreateMIF(FALSE), m_bSingleFile(FALSE),
      34             :       m_bSingleLayerAlreadyCreated(FALSE), m_bQuickSpatialIndexMode(-1),
      35        3006 :       m_nBlockSize(512)
      36             : {
      37        3006 : }
      38             : 
      39             : /************************************************************************/
      40             : /*                         ~OGRTABDataSource()                          */
      41             : /************************************************************************/
      42             : 
      43        6012 : OGRTABDataSource::~OGRTABDataSource()
      44             : 
      45             : {
      46        3006 :     CPLFree(m_pszDirectory);
      47             : 
      48        5316 :     for (int i = 0; i < m_nLayerCount; i++)
      49        2310 :         delete m_papoLayers[i];
      50             : 
      51        3006 :     CPLFree(m_papoLayers);
      52        3006 :     CSLDestroy(m_papszOptions);
      53        6012 : }
      54             : 
      55             : /************************************************************************/
      56             : /*                               Create()                               */
      57             : /*                                                                      */
      58             : /*      Create a new dataset (directory or file).                       */
      59             : /************************************************************************/
      60             : 
      61         193 : int OGRTABDataSource::Create(const char *pszName, char **papszOptions)
      62             : 
      63             : {
      64         193 :     SetDescription(pszName);
      65         193 :     m_papszOptions = CSLDuplicate(papszOptions);
      66         193 :     eAccess = GA_Update;
      67             : 
      68         193 :     const char *pszOpt = CSLFetchNameValue(papszOptions, "FORMAT");
      69         193 :     if (pszOpt != nullptr && EQUAL(pszOpt, "MIF"))
      70           7 :         m_bCreateMIF = TRUE;
      71         293 :     else if (EQUAL(CPLGetExtension(pszName), "mif") ||
      72         107 :              EQUAL(CPLGetExtension(pszName), "mid"))
      73          79 :         m_bCreateMIF = TRUE;
      74             : 
      75         193 :     if ((pszOpt = CSLFetchNameValue(papszOptions, "SPATIAL_INDEX_MODE")) !=
      76             :         nullptr)
      77             :     {
      78           0 :         if (EQUAL(pszOpt, "QUICK"))
      79           0 :             m_bQuickSpatialIndexMode = TRUE;
      80           0 :         else if (EQUAL(pszOpt, "OPTIMIZED"))
      81           0 :             m_bQuickSpatialIndexMode = FALSE;
      82             :     }
      83             : 
      84         193 :     m_nBlockSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKSIZE", "512"));
      85             : 
      86             :     // Create a new empty directory.
      87             :     VSIStatBufL sStat;
      88             : 
      89         193 :     if (strlen(CPLGetExtension(pszName)) == 0)
      90             :     {
      91          41 :         if (VSIStatL(pszName, &sStat) == 0)
      92             :         {
      93           6 :             if (!VSI_ISDIR(sStat.st_mode))
      94             :             {
      95           0 :                 CPLError(CE_Failure, CPLE_OpenFailed,
      96             :                          "Attempt to create dataset named %s,\n"
      97             :                          "but that is an existing file.",
      98             :                          pszName);
      99           0 :                 return FALSE;
     100             :             }
     101             :         }
     102             :         else
     103             :         {
     104          35 :             if (VSIMkdir(pszName, 0755) != 0)
     105             :             {
     106           1 :                 CPLError(CE_Failure, CPLE_AppDefined,
     107             :                          "Unable to create directory %s.", pszName);
     108           1 :                 return FALSE;
     109             :             }
     110             :         }
     111             : 
     112          40 :         m_pszDirectory = CPLStrdup(pszName);
     113             :     }
     114             : 
     115             :     // Create a new single file.
     116             :     else
     117             :     {
     118         152 :         IMapInfoFile *poFile = nullptr;
     119         152 :         const char *pszEncoding(CSLFetchNameValue(papszOptions, "ENCODING"));
     120         152 :         const char *pszCharset(IMapInfoFile::EncodingToCharset(pszEncoding));
     121         152 :         bool bStrictLaundering = CPLTestBool(CSLFetchNameValueDef(
     122             :             papszOptions, "STRICT_FIELDS_NAME_LAUNDERING", "YES"));
     123         152 :         if (m_bCreateMIF)
     124             :         {
     125          84 :             poFile = new MIFFile(this);
     126          84 :             if (poFile->Open(pszName, TABWrite, FALSE, pszCharset) != 0)
     127             :             {
     128           0 :                 delete poFile;
     129           0 :                 return FALSE;
     130             :             }
     131             :         }
     132             :         else
     133             :         {
     134          68 :             TABFile *poTabFile = new TABFile(this);
     135          68 :             if (poTabFile->Open(pszName, TABWrite, FALSE, m_nBlockSize,
     136          68 :                                 pszCharset) != 0)
     137             :             {
     138           1 :                 delete poTabFile;
     139           1 :                 return FALSE;
     140             :             }
     141          67 :             poFile = poTabFile;
     142             :         }
     143         151 :         poFile->SetStrictLaundering(bStrictLaundering);
     144         151 :         m_nLayerCount = 1;
     145         151 :         m_papoLayers = static_cast<IMapInfoFile **>(CPLMalloc(sizeof(void *)));
     146         151 :         m_papoLayers[0] = poFile;
     147             : 
     148         151 :         m_pszDirectory = CPLStrdup(CPLGetPath(pszName));
     149         151 :         m_bSingleFile = TRUE;
     150             :     }
     151             : 
     152         191 :     return TRUE;
     153             : }
     154             : 
     155             : /************************************************************************/
     156             : /*                                Open()                                */
     157             : /*                                                                      */
     158             : /*      Open an existing file, or directory of files.                   */
     159             : /************************************************************************/
     160             : 
     161        2813 : int OGRTABDataSource::Open(GDALOpenInfo *poOpenInfo, int bTestOpen)
     162             : 
     163             : {
     164        2813 :     SetDescription(poOpenInfo->pszFilename);
     165        2813 :     eAccess = poOpenInfo->eAccess;
     166             : 
     167             :     // If it is a file, try to open as a Mapinfo file.
     168        2813 :     if (!poOpenInfo->bIsDirectory)
     169             :     {
     170        4224 :         IMapInfoFile *poFile = IMapInfoFile::SmartOpen(
     171        2112 :             this, poOpenInfo->pszFilename, GetUpdate(), bTestOpen);
     172        2112 :         if (poFile == nullptr)
     173          58 :             return FALSE;
     174             : 
     175        2054 :         poFile->SetDescription(poFile->GetName());
     176             : 
     177        2054 :         m_nLayerCount = 1;
     178        2054 :         m_papoLayers = static_cast<IMapInfoFile **>(CPLMalloc(sizeof(void *)));
     179        2054 :         m_papoLayers[0] = poFile;
     180             : 
     181        2054 :         m_pszDirectory = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
     182             : 
     183        2054 :         m_bSingleFile = TRUE;
     184        2054 :         m_bSingleLayerAlreadyCreated = TRUE;
     185             :     }
     186             : 
     187             :     // Otherwise, we need to scan the whole directory for files
     188             :     // ending in .tab or .mif.
     189             :     else
     190             :     {
     191         701 :         char **papszFileList = VSIReadDir(poOpenInfo->pszFilename);
     192             : 
     193         701 :         m_pszDirectory = CPLStrdup(poOpenInfo->pszFilename);
     194             : 
     195       27643 :         for (int iFile = 0;
     196       27643 :              papszFileList != nullptr && papszFileList[iFile] != nullptr;
     197             :              iFile++)
     198             :         {
     199       26960 :             const char *pszExtension = CPLGetExtension(papszFileList[iFile]);
     200             : 
     201       26960 :             if (!EQUAL(pszExtension, "tab") && !EQUAL(pszExtension, "mif"))
     202       26895 :                 continue;
     203             : 
     204          65 :             char *pszSubFilename = CPLStrdup(
     205          65 :                 CPLFormFilename(m_pszDirectory, papszFileList[iFile], nullptr));
     206             : 
     207          65 :             IMapInfoFile *poFile = IMapInfoFile::SmartOpen(
     208          65 :                 this, pszSubFilename, GetUpdate(), bTestOpen);
     209          65 :             CPLFree(pszSubFilename);
     210             : 
     211          65 :             if (poFile == nullptr)
     212             :             {
     213          18 :                 CSLDestroy(papszFileList);
     214          18 :                 return FALSE;
     215             :             }
     216          47 :             poFile->SetDescription(poFile->GetName());
     217             : 
     218          47 :             m_nLayerCount++;
     219          47 :             m_papoLayers = static_cast<IMapInfoFile **>(
     220          47 :                 CPLRealloc(m_papoLayers, sizeof(void *) * m_nLayerCount));
     221          47 :             m_papoLayers[m_nLayerCount - 1] = poFile;
     222             :         }
     223             : 
     224         683 :         CSLDestroy(papszFileList);
     225             : 
     226         683 :         if (m_nLayerCount == 0)
     227             :         {
     228         654 :             if (!bTestOpen)
     229           0 :                 CPLError(CE_Failure, CPLE_OpenFailed,
     230             :                          "No mapinfo files found in directory %s.",
     231             :                          m_pszDirectory);
     232             : 
     233         654 :             return FALSE;
     234             :         }
     235             :     }
     236             : 
     237        2083 :     return TRUE;
     238             : }
     239             : 
     240             : /************************************************************************/
     241             : /*                           GetLayerCount()                            */
     242             : /************************************************************************/
     243             : 
     244        2346 : int OGRTABDataSource::GetLayerCount()
     245             : 
     246             : {
     247        2346 :     if (m_bSingleFile && !m_bSingleLayerAlreadyCreated)
     248          12 :         return 0;
     249             :     else
     250        2334 :         return m_nLayerCount;
     251             : }
     252             : 
     253             : /************************************************************************/
     254             : /*                              GetLayer()                              */
     255             : /************************************************************************/
     256             : 
     257        2175 : OGRLayer *OGRTABDataSource::GetLayer(int iLayer)
     258             : 
     259             : {
     260        2175 :     if (iLayer < 0 || iLayer >= GetLayerCount())
     261           8 :         return nullptr;
     262             :     else
     263        2167 :         return m_papoLayers[iLayer];
     264             : }
     265             : 
     266             : /************************************************************************/
     267             : /*                           ICreateLayer()                             */
     268             : /************************************************************************/
     269             : 
     270             : OGRLayer *
     271         209 : OGRTABDataSource::ICreateLayer(const char *pszLayerName,
     272             :                                const OGRGeomFieldDefn *poGeomFieldDefnIn,
     273             :                                CSLConstList papszOptions)
     274             : 
     275             : {
     276         209 :     if (!GetUpdate())
     277             :     {
     278           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     279             :                  "Cannot create layer on read-only dataset.");
     280           0 :         return nullptr;
     281             :     }
     282             : 
     283             :     const auto poSRSIn =
     284         209 :         poGeomFieldDefnIn ? poGeomFieldDefnIn->GetSpatialRef() : nullptr;
     285             : 
     286             :     // If it is a single file mode file, then we may have already
     287             :     // instantiated the low level layer.   We would just need to
     288             :     // reset the coordinate system and (potentially) bounds.
     289         209 :     IMapInfoFile *poFile = nullptr;
     290         209 :     char *pszFullFilename = nullptr;
     291             : 
     292         209 :     const char *pszEncoding = CSLFetchNameValue(papszOptions, "ENCODING");
     293         209 :     const char *pszCharset(IMapInfoFile::EncodingToCharset(pszEncoding));
     294         209 :     const char *pszDescription(CSLFetchNameValue(papszOptions, "DESCRIPTION"));
     295             :     const char *pszStrictLaundering =
     296         209 :         CSLFetchNameValue(papszOptions, "STRICT_FIELDS_NAME_LAUNDERING");
     297         209 :     if (pszStrictLaundering == nullptr)
     298             :     {
     299         207 :         pszStrictLaundering = CSLFetchNameValueDef(
     300         207 :             m_papszOptions, "STRICT_FIELDS_NAME_LAUNDERING", "YES");
     301             :     }
     302         209 :     bool bStrictLaundering = CPLTestBool(pszStrictLaundering);
     303             : 
     304         209 :     if (m_bSingleFile)
     305             :     {
     306         151 :         if (m_bSingleLayerAlreadyCreated)
     307             :         {
     308           0 :             CPLError(
     309             :                 CE_Failure, CPLE_AppDefined,
     310             :                 "Unable to create new layers in this single file dataset.");
     311           0 :             return nullptr;
     312             :         }
     313             : 
     314         151 :         m_bSingleLayerAlreadyCreated = TRUE;
     315             : 
     316         151 :         poFile = m_papoLayers[0];
     317         151 :         if (pszEncoding)
     318           3 :             poFile->SetCharset(pszCharset);
     319             : 
     320         151 :         if (poFile->GetFileClass() == TABFC_TABFile)
     321          67 :             poFile->SetMetadataItem("DESCRIPTION", pszDescription);
     322             :     }
     323             : 
     324             :     else
     325             :     {
     326          58 :         if (m_bCreateMIF)
     327             :         {
     328             :             pszFullFilename =
     329           3 :                 CPLStrdup(CPLFormFilename(m_pszDirectory, pszLayerName, "mif"));
     330             : 
     331           3 :             poFile = new MIFFile(this);
     332             : 
     333           3 :             if (poFile->Open(pszFullFilename, TABWrite, FALSE, pszCharset) != 0)
     334             :             {
     335           0 :                 CPLFree(pszFullFilename);
     336           0 :                 delete poFile;
     337           0 :                 return nullptr;
     338             :             }
     339             :         }
     340             :         else
     341             :         {
     342             :             pszFullFilename =
     343          55 :                 CPLStrdup(CPLFormFilename(m_pszDirectory, pszLayerName, "tab"));
     344             : 
     345          55 :             TABFile *poTABFile = new TABFile(this);
     346             : 
     347          55 :             if (poTABFile->Open(pszFullFilename, TABWrite, FALSE, m_nBlockSize,
     348          55 :                                 pszCharset) != 0)
     349             :             {
     350           0 :                 CPLFree(pszFullFilename);
     351           0 :                 delete poTABFile;
     352           0 :                 return nullptr;
     353             :             }
     354          55 :             poFile = poTABFile;
     355          55 :             poFile->SetMetadataItem("DESCRIPTION", pszDescription);
     356             :         }
     357             : 
     358          58 :         m_nLayerCount++;
     359          58 :         m_papoLayers = static_cast<IMapInfoFile **>(
     360          58 :             CPLRealloc(m_papoLayers, sizeof(void *) * m_nLayerCount));
     361          58 :         m_papoLayers[m_nLayerCount - 1] = poFile;
     362             : 
     363          58 :         CPLFree(pszFullFilename);
     364             :     }
     365             : 
     366         209 :     poFile->SetDescription(poFile->GetName());
     367         209 :     poFile->SetStrictLaundering(bStrictLaundering);
     368             : 
     369             :     // Assign the coordinate system (if provided) and set
     370             :     // reasonable bounds.
     371         209 :     if (poSRSIn != nullptr)
     372             :     {
     373         100 :         auto poSRSClone = poSRSIn->Clone();
     374         100 :         poSRSClone->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     375         100 :         poFile->SetSpatialRef(poSRSClone);
     376         100 :         poSRSClone->Release();
     377             :         // SetSpatialRef() has cloned the passed geometry
     378         100 :         auto poGeomFieldDefn = poFile->GetLayerDefn()->GetGeomFieldDefn(0);
     379         200 :         auto oTemporaryUnsealer(poGeomFieldDefn->GetTemporaryUnsealer());
     380         100 :         poGeomFieldDefn->SetSpatialRef(poFile->GetSpatialRef());
     381             :     }
     382             : 
     383             :     // Pull out the bounds if supplied
     384         209 :     const char *pszOpt = nullptr;
     385         209 :     if ((pszOpt = CSLFetchNameValue(papszOptions, "BOUNDS")) != nullptr)
     386             :     {
     387             :         double dfBounds[4];
     388           5 :         if (CPLsscanf(pszOpt, "%lf,%lf,%lf,%lf", &dfBounds[0], &dfBounds[1],
     389           5 :                       &dfBounds[2], &dfBounds[3]) != 4)
     390             :         {
     391           0 :             CPLError(
     392             :                 CE_Failure, CPLE_IllegalArg,
     393             :                 "Invalid BOUNDS parameter, expected min_x,min_y,max_x,max_y");
     394             :         }
     395             :         else
     396             :         {
     397           5 :             poFile->SetBounds(dfBounds[0], dfBounds[1], dfBounds[2],
     398           5 :                               dfBounds[3]);
     399             :         }
     400             :     }
     401             : 
     402         209 :     if (!poFile->IsBoundsSet() && !m_bCreateMIF)
     403             :     {
     404         103 :         if (poSRSIn != nullptr && poSRSIn->IsGeographic())
     405           0 :             poFile->SetBounds(-1000, -1000, 1000, 1000);
     406         103 :         else if (poSRSIn != nullptr && poSRSIn->IsProjected())
     407             :         {
     408          11 :             const double FE = poSRSIn->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);
     409          11 :             const double FN = poSRSIn->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     410          11 :             poFile->SetBounds(-30000000 + FE, -15000000 + FN, 30000000 + FE,
     411          11 :                               15000000 + FN);
     412             :         }
     413             :         else
     414          92 :             poFile->SetBounds(-30000000, -15000000, 30000000, 15000000);
     415             :     }
     416             : 
     417         209 :     if (m_bQuickSpatialIndexMode == TRUE &&
     418           0 :         poFile->SetQuickSpatialIndexMode(TRUE) != 0)
     419             :     {
     420           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     421             :                  "Setting Quick Spatial Index Mode failed.");
     422             :     }
     423         209 :     else if (m_bQuickSpatialIndexMode == FALSE &&
     424           0 :              poFile->SetQuickSpatialIndexMode(FALSE) != 0)
     425             :     {
     426           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     427             :                  "Setting Normal Spatial Index Mode failed.");
     428             :     }
     429             : 
     430         209 :     return poFile;
     431             : }
     432             : 
     433             : /************************************************************************/
     434             : /*                           TestCapability()                           */
     435             : /************************************************************************/
     436             : 
     437          92 : int OGRTABDataSource::TestCapability(const char *pszCap)
     438             : 
     439             : {
     440          92 :     if (EQUAL(pszCap, ODsCCreateLayer))
     441          42 :         return GetUpdate() && (!m_bSingleFile || !m_bSingleLayerAlreadyCreated);
     442          50 :     else if (EQUAL(pszCap, ODsCRandomLayerWrite))
     443           0 :         return GetUpdate();
     444             :     else
     445          50 :         return FALSE;
     446             : }
     447             : 
     448             : /************************************************************************/
     449             : /*                            GetFileList()                             */
     450             : /************************************************************************/
     451             : 
     452          36 : char **OGRTABDataSource::GetFileList()
     453             : {
     454             :     VSIStatBufL sStatBuf;
     455          72 :     CPLStringList osList;
     456             : 
     457          72 :     if (VSIStatL(GetDescription(), &sStatBuf) == 0 &&
     458          36 :         VSI_ISDIR(sStatBuf.st_mode))
     459             :     {
     460             :         static const char *const apszExtensions[] = {
     461             :             "mif", "mid", "tab", "map", "ind", "dat", "id", nullptr};
     462          18 :         char **papszDirEntries = VSIReadDir(GetDescription());
     463             : 
     464         156 :         for (int iFile = 0;
     465         156 :              papszDirEntries != nullptr && papszDirEntries[iFile] != nullptr;
     466             :              iFile++)
     467             :         {
     468         138 :             if (CSLFindString(apszExtensions,
     469         276 :                               CPLGetExtension(papszDirEntries[iFile])) != -1)
     470             :             {
     471             :                 osList.AddString(CPLFormFilename(
     472         134 :                     GetDescription(), papszDirEntries[iFile], nullptr));
     473             :             }
     474             :         }
     475             : 
     476          18 :         CSLDestroy(papszDirEntries);
     477             :     }
     478             :     else
     479             :     {
     480             :         static const char *const apszMIFExtensions[] = {"mif", "mid", nullptr};
     481             :         static const char *const apszTABExtensions[] = {"tab", "map", "ind",
     482             :                                                         "dat", "id",  nullptr};
     483          18 :         const char *const *papszExtensions = nullptr;
     484          32 :         if (EQUAL(CPLGetExtension(GetDescription()), "mif") ||
     485          14 :             EQUAL(CPLGetExtension(GetDescription()), "mid"))
     486             :         {
     487           4 :             papszExtensions = apszMIFExtensions;
     488             :         }
     489             :         else
     490             :         {
     491          14 :             papszExtensions = apszTABExtensions;
     492             :         }
     493          18 :         const char *const *papszIter = papszExtensions;
     494          96 :         while (*papszIter)
     495             :         {
     496             :             const char *pszFile =
     497          78 :                 CPLResetExtension(GetDescription(), *papszIter);
     498          78 :             if (VSIStatL(pszFile, &sStatBuf) != 0)
     499             :             {
     500          14 :                 pszFile = CPLResetExtension(GetDescription(),
     501          28 :                                             CPLString(*papszIter).toupper());
     502          14 :                 if (VSIStatL(pszFile, &sStatBuf) != 0)
     503             :                 {
     504          14 :                     pszFile = nullptr;
     505             :                 }
     506             :             }
     507          78 :             if (pszFile)
     508          64 :                 osList.AddString(pszFile);
     509          78 :             papszIter++;
     510             :         }
     511             :     }
     512          72 :     return osList.StealList();
     513             : }
     514             : 
     515             : /************************************************************************/
     516             : /*                            ExecuteSQL()                              */
     517             : /************************************************************************/
     518             : 
     519          35 : OGRLayer *OGRTABDataSource::ExecuteSQL(const char *pszStatement,
     520             :                                        OGRGeometry *poSpatialFilter,
     521             :                                        const char *pszDialect)
     522             : {
     523          35 :     char **papszTokens = CSLTokenizeString(pszStatement);
     524          40 :     if (CSLCount(papszTokens) == 6 && EQUAL(papszTokens[0], "CREATE") &&
     525          45 :         EQUAL(papszTokens[1], "INDEX") && EQUAL(papszTokens[2], "ON") &&
     526           5 :         EQUAL(papszTokens[4], "USING"))
     527             :     {
     528             :         IMapInfoFile *poLayer =
     529           5 :             dynamic_cast<IMapInfoFile *>(GetLayerByName(papszTokens[3]));
     530           5 :         if (poLayer == nullptr)
     531             :         {
     532           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     533             :                      "`%s' failed failed, no such layer as `%s'.", pszStatement,
     534           1 :                      papszTokens[3]);
     535           1 :             CSLDestroy(papszTokens);
     536           1 :             return nullptr;
     537             :         }
     538           4 :         int nFieldIdx = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
     539           4 :         CSLDestroy(papszTokens);
     540           4 :         if (nFieldIdx < 0)
     541             :         {
     542           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     543             :                      "`%s' failed, field not found.", pszStatement);
     544           1 :             return nullptr;
     545             :         }
     546           3 :         poLayer->SetFieldIndexed(nFieldIdx);
     547           3 :         return nullptr;
     548             :     }
     549             : 
     550          30 :     CSLDestroy(papszTokens);
     551          30 :     return GDALDataset::ExecuteSQL(pszStatement, poSpatialFilter, pszDialect);
     552             : }

Generated by: LCOV version 1.14