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: 218 244 89.3 %
Date: 2025-01-18 12:42:00 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        3010 : 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        3010 :       m_nBlockSize(512)
      36             : {
      37        3010 : }
      38             : 
      39             : /************************************************************************/
      40             : /*                         ~OGRTABDataSource()                          */
      41             : /************************************************************************/
      42             : 
      43        6020 : OGRTABDataSource::~OGRTABDataSource()
      44             : 
      45             : {
      46        3010 :     CPLFree(m_pszDirectory);
      47             : 
      48        5321 :     for (int i = 0; i < m_nLayerCount; i++)
      49        2311 :         delete m_papoLayers[i];
      50             : 
      51        3010 :     CPLFree(m_papoLayers);
      52        3010 :     CSLDestroy(m_papszOptions);
      53        6020 : }
      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         479 :     else if (EQUAL(CPLGetExtensionSafe(pszName).c_str(), "mif") ||
      72         293 :              EQUAL(CPLGetExtensionSafe(pszName).c_str(), "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(CPLGetExtensionSafe(pszName).c_str()) == 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(CPLGetPathSafe(pszName).c_str());
     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        2817 : int OGRTABDataSource::Open(GDALOpenInfo *poOpenInfo, int bTestOpen)
     162             : 
     163             : {
     164        2817 :     SetDescription(poOpenInfo->pszFilename);
     165        2817 :     eAccess = poOpenInfo->eAccess;
     166             : 
     167             :     // If it is a file, try to open as a Mapinfo file.
     168        2817 :     if (!poOpenInfo->bIsDirectory)
     169             :     {
     170        4226 :         IMapInfoFile *poFile = IMapInfoFile::SmartOpen(
     171        2113 :             this, poOpenInfo->pszFilename, GetUpdate(), bTestOpen);
     172        2113 :         if (poFile == nullptr)
     173          58 :             return FALSE;
     174             : 
     175        2055 :         poFile->SetDescription(poFile->GetName());
     176             : 
     177        2055 :         m_nLayerCount = 1;
     178        2055 :         m_papoLayers = static_cast<IMapInfoFile **>(CPLMalloc(sizeof(void *)));
     179        2055 :         m_papoLayers[0] = poFile;
     180             : 
     181        2055 :         m_pszDirectory =
     182        2055 :             CPLStrdup(CPLGetPathSafe(poOpenInfo->pszFilename).c_str());
     183             : 
     184        2055 :         m_bSingleFile = TRUE;
     185        2055 :         m_bSingleLayerAlreadyCreated = TRUE;
     186             :     }
     187             : 
     188             :     // Otherwise, we need to scan the whole directory for files
     189             :     // ending in .tab or .mif.
     190             :     else
     191             :     {
     192         704 :         char **papszFileList = VSIReadDir(poOpenInfo->pszFilename);
     193             : 
     194         704 :         m_pszDirectory = CPLStrdup(poOpenInfo->pszFilename);
     195             : 
     196       27826 :         for (int iFile = 0;
     197       27826 :              papszFileList != nullptr && papszFileList[iFile] != nullptr;
     198             :              iFile++)
     199             :         {
     200             :             const std::string osExtension =
     201       27140 :                 CPLGetExtensionSafe(papszFileList[iFile]);
     202             : 
     203       54221 :             if (!EQUAL(osExtension.c_str(), "tab") &&
     204       27081 :                 !EQUAL(osExtension.c_str(), "mif"))
     205       27075 :                 continue;
     206             : 
     207             :             char *pszSubFilename =
     208          65 :                 CPLStrdup(CPLFormFilenameSafe(m_pszDirectory,
     209          65 :                                               papszFileList[iFile], nullptr)
     210             :                               .c_str());
     211             : 
     212          65 :             IMapInfoFile *poFile = IMapInfoFile::SmartOpen(
     213          65 :                 this, pszSubFilename, GetUpdate(), bTestOpen);
     214          65 :             CPLFree(pszSubFilename);
     215             : 
     216          65 :             if (poFile == nullptr)
     217             :             {
     218          18 :                 CSLDestroy(papszFileList);
     219          18 :                 return FALSE;
     220             :             }
     221          47 :             poFile->SetDescription(poFile->GetName());
     222             : 
     223          47 :             m_nLayerCount++;
     224          47 :             m_papoLayers = static_cast<IMapInfoFile **>(
     225          47 :                 CPLRealloc(m_papoLayers, sizeof(void *) * m_nLayerCount));
     226          47 :             m_papoLayers[m_nLayerCount - 1] = poFile;
     227             :         }
     228             : 
     229         686 :         CSLDestroy(papszFileList);
     230             : 
     231         686 :         if (m_nLayerCount == 0)
     232             :         {
     233         657 :             if (!bTestOpen)
     234           0 :                 CPLError(CE_Failure, CPLE_OpenFailed,
     235             :                          "No mapinfo files found in directory %s.",
     236             :                          m_pszDirectory);
     237             : 
     238         657 :             return FALSE;
     239             :         }
     240             :     }
     241             : 
     242        2084 :     return TRUE;
     243             : }
     244             : 
     245             : /************************************************************************/
     246             : /*                           GetLayerCount()                            */
     247             : /************************************************************************/
     248             : 
     249        2347 : int OGRTABDataSource::GetLayerCount()
     250             : 
     251             : {
     252        2347 :     if (m_bSingleFile && !m_bSingleLayerAlreadyCreated)
     253          12 :         return 0;
     254             :     else
     255        2335 :         return m_nLayerCount;
     256             : }
     257             : 
     258             : /************************************************************************/
     259             : /*                              GetLayer()                              */
     260             : /************************************************************************/
     261             : 
     262        2176 : OGRLayer *OGRTABDataSource::GetLayer(int iLayer)
     263             : 
     264             : {
     265        2176 :     if (iLayer < 0 || iLayer >= GetLayerCount())
     266           8 :         return nullptr;
     267             :     else
     268        2168 :         return m_papoLayers[iLayer];
     269             : }
     270             : 
     271             : /************************************************************************/
     272             : /*                           ICreateLayer()                             */
     273             : /************************************************************************/
     274             : 
     275             : OGRLayer *
     276         209 : OGRTABDataSource::ICreateLayer(const char *pszLayerName,
     277             :                                const OGRGeomFieldDefn *poGeomFieldDefnIn,
     278             :                                CSLConstList papszOptions)
     279             : 
     280             : {
     281         209 :     if (!GetUpdate())
     282             :     {
     283           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     284             :                  "Cannot create layer on read-only dataset.");
     285           0 :         return nullptr;
     286             :     }
     287             : 
     288             :     const auto poSRSIn =
     289         209 :         poGeomFieldDefnIn ? poGeomFieldDefnIn->GetSpatialRef() : nullptr;
     290             : 
     291             :     // If it is a single file mode file, then we may have already
     292             :     // instantiated the low level layer.   We would just need to
     293             :     // reset the coordinate system and (potentially) bounds.
     294         209 :     IMapInfoFile *poFile = nullptr;
     295         209 :     char *pszFullFilename = nullptr;
     296             : 
     297         209 :     const char *pszEncoding = CSLFetchNameValue(papszOptions, "ENCODING");
     298         209 :     const char *pszCharset(IMapInfoFile::EncodingToCharset(pszEncoding));
     299         209 :     const char *pszDescription(CSLFetchNameValue(papszOptions, "DESCRIPTION"));
     300             :     const char *pszStrictLaundering =
     301         209 :         CSLFetchNameValue(papszOptions, "STRICT_FIELDS_NAME_LAUNDERING");
     302         209 :     if (pszStrictLaundering == nullptr)
     303             :     {
     304         207 :         pszStrictLaundering = CSLFetchNameValueDef(
     305         207 :             m_papszOptions, "STRICT_FIELDS_NAME_LAUNDERING", "YES");
     306             :     }
     307         209 :     bool bStrictLaundering = CPLTestBool(pszStrictLaundering);
     308             : 
     309         209 :     if (m_bSingleFile)
     310             :     {
     311         151 :         if (m_bSingleLayerAlreadyCreated)
     312             :         {
     313           0 :             CPLError(
     314             :                 CE_Failure, CPLE_AppDefined,
     315             :                 "Unable to create new layers in this single file dataset.");
     316           0 :             return nullptr;
     317             :         }
     318             : 
     319         151 :         m_bSingleLayerAlreadyCreated = TRUE;
     320             : 
     321         151 :         poFile = m_papoLayers[0];
     322         151 :         if (pszEncoding)
     323           3 :             poFile->SetCharset(pszCharset);
     324             : 
     325         151 :         if (poFile->GetFileClass() == TABFC_TABFile)
     326          67 :             poFile->SetMetadataItem("DESCRIPTION", pszDescription);
     327             :     }
     328             : 
     329             :     else
     330             :     {
     331          58 :         if (m_bCreateMIF)
     332             :         {
     333           3 :             pszFullFilename = CPLStrdup(
     334           6 :                 CPLFormFilenameSafe(m_pszDirectory, pszLayerName, "mif")
     335             :                     .c_str());
     336             : 
     337           3 :             poFile = new MIFFile(this);
     338             : 
     339           3 :             if (poFile->Open(pszFullFilename, TABWrite, FALSE, pszCharset) != 0)
     340             :             {
     341           0 :                 CPLFree(pszFullFilename);
     342           0 :                 delete poFile;
     343           0 :                 return nullptr;
     344             :             }
     345             :         }
     346             :         else
     347             :         {
     348          55 :             pszFullFilename = CPLStrdup(
     349         110 :                 CPLFormFilenameSafe(m_pszDirectory, pszLayerName, "tab")
     350             :                     .c_str());
     351             : 
     352          55 :             TABFile *poTABFile = new TABFile(this);
     353             : 
     354          55 :             if (poTABFile->Open(pszFullFilename, TABWrite, FALSE, m_nBlockSize,
     355          55 :                                 pszCharset) != 0)
     356             :             {
     357           0 :                 CPLFree(pszFullFilename);
     358           0 :                 delete poTABFile;
     359           0 :                 return nullptr;
     360             :             }
     361          55 :             poFile = poTABFile;
     362          55 :             poFile->SetMetadataItem("DESCRIPTION", pszDescription);
     363             :         }
     364             : 
     365          58 :         m_nLayerCount++;
     366          58 :         m_papoLayers = static_cast<IMapInfoFile **>(
     367          58 :             CPLRealloc(m_papoLayers, sizeof(void *) * m_nLayerCount));
     368          58 :         m_papoLayers[m_nLayerCount - 1] = poFile;
     369             : 
     370          58 :         CPLFree(pszFullFilename);
     371             :     }
     372             : 
     373         209 :     poFile->SetDescription(poFile->GetName());
     374         209 :     poFile->SetStrictLaundering(bStrictLaundering);
     375             : 
     376             :     // Assign the coordinate system (if provided) and set
     377             :     // reasonable bounds.
     378         209 :     if (poSRSIn != nullptr)
     379             :     {
     380         100 :         auto poSRSClone = poSRSIn->Clone();
     381         100 :         poSRSClone->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     382         100 :         poFile->SetSpatialRef(poSRSClone);
     383         100 :         poSRSClone->Release();
     384             :         // SetSpatialRef() has cloned the passed geometry
     385         100 :         auto poGeomFieldDefn = poFile->GetLayerDefn()->GetGeomFieldDefn(0);
     386         200 :         auto oTemporaryUnsealer(poGeomFieldDefn->GetTemporaryUnsealer());
     387         100 :         poGeomFieldDefn->SetSpatialRef(poFile->GetSpatialRef());
     388             :     }
     389             : 
     390             :     // Pull out the bounds if supplied
     391         209 :     const char *pszOpt = nullptr;
     392         209 :     if ((pszOpt = CSLFetchNameValue(papszOptions, "BOUNDS")) != nullptr)
     393             :     {
     394             :         double dfBounds[4];
     395           5 :         if (CPLsscanf(pszOpt, "%lf,%lf,%lf,%lf", &dfBounds[0], &dfBounds[1],
     396           5 :                       &dfBounds[2], &dfBounds[3]) != 4)
     397             :         {
     398           0 :             CPLError(
     399             :                 CE_Failure, CPLE_IllegalArg,
     400             :                 "Invalid BOUNDS parameter, expected min_x,min_y,max_x,max_y");
     401             :         }
     402             :         else
     403             :         {
     404           5 :             poFile->SetBounds(dfBounds[0], dfBounds[1], dfBounds[2],
     405           5 :                               dfBounds[3]);
     406             :         }
     407             :     }
     408             : 
     409         209 :     if (!poFile->IsBoundsSet() && !m_bCreateMIF)
     410             :     {
     411         103 :         if (poSRSIn != nullptr && poSRSIn->IsGeographic())
     412           0 :             poFile->SetBounds(-1000, -1000, 1000, 1000);
     413         103 :         else if (poSRSIn != nullptr && poSRSIn->IsProjected())
     414             :         {
     415          11 :             const double FE = poSRSIn->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);
     416          11 :             const double FN = poSRSIn->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     417          11 :             poFile->SetBounds(-30000000 + FE, -15000000 + FN, 30000000 + FE,
     418          11 :                               15000000 + FN);
     419             :         }
     420             :         else
     421          92 :             poFile->SetBounds(-30000000, -15000000, 30000000, 15000000);
     422             :     }
     423             : 
     424         209 :     if (m_bQuickSpatialIndexMode == TRUE &&
     425           0 :         poFile->SetQuickSpatialIndexMode(TRUE) != 0)
     426             :     {
     427           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     428             :                  "Setting Quick Spatial Index Mode failed.");
     429             :     }
     430         209 :     else if (m_bQuickSpatialIndexMode == FALSE &&
     431           0 :              poFile->SetQuickSpatialIndexMode(FALSE) != 0)
     432             :     {
     433           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     434             :                  "Setting Normal Spatial Index Mode failed.");
     435             :     }
     436             : 
     437         209 :     return poFile;
     438             : }
     439             : 
     440             : /************************************************************************/
     441             : /*                           TestCapability()                           */
     442             : /************************************************************************/
     443             : 
     444          92 : int OGRTABDataSource::TestCapability(const char *pszCap)
     445             : 
     446             : {
     447          92 :     if (EQUAL(pszCap, ODsCCreateLayer))
     448          42 :         return GetUpdate() && (!m_bSingleFile || !m_bSingleLayerAlreadyCreated);
     449          50 :     else if (EQUAL(pszCap, ODsCRandomLayerWrite))
     450           0 :         return GetUpdate();
     451             :     else
     452          50 :         return FALSE;
     453             : }
     454             : 
     455             : /************************************************************************/
     456             : /*                            GetFileList()                             */
     457             : /************************************************************************/
     458             : 
     459          36 : char **OGRTABDataSource::GetFileList()
     460             : {
     461             :     VSIStatBufL sStatBuf;
     462          72 :     CPLStringList osList;
     463             : 
     464          72 :     if (VSIStatL(GetDescription(), &sStatBuf) == 0 &&
     465          36 :         VSI_ISDIR(sStatBuf.st_mode))
     466             :     {
     467             :         static const char *const apszExtensions[] = {
     468             :             "mif", "mid", "tab", "map", "ind", "dat", "id", nullptr};
     469          18 :         char **papszDirEntries = VSIReadDir(GetDescription());
     470             : 
     471         156 :         for (int iFile = 0;
     472         156 :              papszDirEntries != nullptr && papszDirEntries[iFile] != nullptr;
     473             :              iFile++)
     474             :         {
     475         138 :             if (CSLFindString(
     476             :                     apszExtensions,
     477         276 :                     CPLGetExtensionSafe(papszDirEntries[iFile]).c_str()) != -1)
     478             :             {
     479         134 :                 osList.push_back(CPLFormFilenameSafe(
     480         134 :                     GetDescription(), papszDirEntries[iFile], nullptr));
     481             :             }
     482             :         }
     483             : 
     484          18 :         CSLDestroy(papszDirEntries);
     485             :     }
     486             :     else
     487             :     {
     488             :         static const char *const apszMIFExtensions[] = {"mif", "mid", nullptr};
     489             :         static const char *const apszTABExtensions[] = {"tab", "map", "ind",
     490             :                                                         "dat", "id",  nullptr};
     491          18 :         const char *const *papszExtensions = nullptr;
     492          50 :         if (EQUAL(CPLGetExtensionSafe(GetDescription()).c_str(), "mif") ||
     493          32 :             EQUAL(CPLGetExtensionSafe(GetDescription()).c_str(), "mid"))
     494             :         {
     495           4 :             papszExtensions = apszMIFExtensions;
     496             :         }
     497             :         else
     498             :         {
     499          14 :             papszExtensions = apszTABExtensions;
     500             :         }
     501          18 :         const char *const *papszIter = papszExtensions;
     502          96 :         while (*papszIter)
     503             :         {
     504             :             std::string osFile =
     505          78 :                 CPLResetExtensionSafe(GetDescription(), *papszIter);
     506          78 :             if (VSIStatL(osFile.c_str(), &sStatBuf) != 0)
     507             :             {
     508          28 :                 osFile = CPLResetExtensionSafe(GetDescription(),
     509          42 :                                                CPLString(*papszIter).toupper());
     510          14 :                 if (VSIStatL(osFile.c_str(), &sStatBuf) != 0)
     511             :                 {
     512          14 :                     osFile.clear();
     513             :                 }
     514             :             }
     515          78 :             if (!osFile.empty())
     516          64 :                 osList.AddString(osFile.c_str());
     517          78 :             papszIter++;
     518             :         }
     519             :     }
     520          72 :     return osList.StealList();
     521             : }
     522             : 
     523             : /************************************************************************/
     524             : /*                            ExecuteSQL()                              */
     525             : /************************************************************************/
     526             : 
     527          35 : OGRLayer *OGRTABDataSource::ExecuteSQL(const char *pszStatement,
     528             :                                        OGRGeometry *poSpatialFilter,
     529             :                                        const char *pszDialect)
     530             : {
     531          35 :     char **papszTokens = CSLTokenizeString(pszStatement);
     532          40 :     if (CSLCount(papszTokens) == 6 && EQUAL(papszTokens[0], "CREATE") &&
     533          45 :         EQUAL(papszTokens[1], "INDEX") && EQUAL(papszTokens[2], "ON") &&
     534           5 :         EQUAL(papszTokens[4], "USING"))
     535             :     {
     536             :         IMapInfoFile *poLayer =
     537           5 :             dynamic_cast<IMapInfoFile *>(GetLayerByName(papszTokens[3]));
     538           5 :         if (poLayer == nullptr)
     539             :         {
     540           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     541             :                      "`%s' failed failed, no such layer as `%s'.", pszStatement,
     542           1 :                      papszTokens[3]);
     543           1 :             CSLDestroy(papszTokens);
     544           1 :             return nullptr;
     545             :         }
     546           4 :         int nFieldIdx = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
     547           4 :         CSLDestroy(papszTokens);
     548           4 :         if (nFieldIdx < 0)
     549             :         {
     550           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     551             :                      "`%s' failed, field not found.", pszStatement);
     552           1 :             return nullptr;
     553             :         }
     554           3 :         poLayer->SetFieldIndexed(nFieldIdx);
     555           3 :         return nullptr;
     556             :     }
     557             : 
     558          30 :     CSLDestroy(papszTokens);
     559          30 :     return GDALDataset::ExecuteSQL(pszStatement, poSpatialFilter, pszDialect);
     560             : }

Generated by: LCOV version 1.14