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

Generated by: LCOV version 1.14