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: 223 249 89.6 %
Date: 2025-09-10 17:48:50 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        3073 : 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        3073 :       m_nBlockSize(512)
      36             : {
      37        3073 : }
      38             : 
      39             : /************************************************************************/
      40             : /*                         ~OGRTABDataSource()                          */
      41             : /************************************************************************/
      42             : 
      43        6146 : OGRTABDataSource::~OGRTABDataSource()
      44             : 
      45             : {
      46        3073 :     CPLFree(m_pszDirectory);
      47             : 
      48        5384 :     for (int i = 0; i < m_nLayerCount; i++)
      49        2311 :         delete m_papoLayers[i];
      50             : 
      51        3073 :     CPLFree(m_papoLayers);
      52        3073 :     CSLDestroy(m_papszOptions);
      53        6146 : }
      54             : 
      55             : /************************************************************************/
      56             : /*                               Create()                               */
      57             : /*                                                                      */
      58             : /*      Create a new dataset (directory or file).                       */
      59             : /************************************************************************/
      60             : 
      61         194 : int OGRTABDataSource::Create(const char *pszName, char **papszOptions)
      62             : 
      63             : {
      64         194 :     SetDescription(pszName);
      65         194 :     m_papszOptions = CSLDuplicate(papszOptions);
      66         194 :     eAccess = GA_Update;
      67             : 
      68         194 :     const char *pszOpt = CSLFetchNameValue(papszOptions, "FORMAT");
      69         194 :     if (pszOpt != nullptr && EQUAL(pszOpt, "MIF"))
      70           7 :         m_bCreateMIF = TRUE;
      71         482 :     else if (EQUAL(CPLGetExtensionSafe(pszName).c_str(), "mif") ||
      72         295 :              EQUAL(CPLGetExtensionSafe(pszName).c_str(), "mid"))
      73          79 :         m_bCreateMIF = TRUE;
      74             : 
      75         194 :     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         194 :     m_nBlockSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKSIZE", "512"));
      85             : 
      86             :     // Create a new empty directory.
      87             :     VSIStatBufL sStat;
      88             : 
      89         194 :     if (strlen(CPLGetExtensionSafe(pszName).c_str()) == 0)
      90             :     {
      91          42 :         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          36 :             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          41 :         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         192 :     return TRUE;
     153             : }
     154             : 
     155             : /************************************************************************/
     156             : /*                                Open()                                */
     157             : /*                                                                      */
     158             : /*      Open an existing file, or directory of files.                   */
     159             : /************************************************************************/
     160             : 
     161        2879 : int OGRTABDataSource::Open(GDALOpenInfo *poOpenInfo, int bTestOpen)
     162             : 
     163             : {
     164        2879 :     SetDescription(poOpenInfo->pszFilename);
     165        2879 :     eAccess = poOpenInfo->eAccess;
     166             : 
     167             :     // If it is a file, try to open as a Mapinfo file.
     168        2879 :     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         766 :         char **papszFileList = VSIReadDir(poOpenInfo->pszFilename);
     193             : 
     194         766 :         m_pszDirectory = CPLStrdup(poOpenInfo->pszFilename);
     195             : 
     196       26663 :         for (int iFile = 0;
     197       26663 :              papszFileList != nullptr && papszFileList[iFile] != nullptr;
     198             :              iFile++)
     199             :         {
     200             :             const std::string osExtension =
     201       25915 :                 CPLGetExtensionSafe(papszFileList[iFile]);
     202             : 
     203       51771 :             if (!EQUAL(osExtension.c_str(), "tab") &&
     204       25856 :                 !EQUAL(osExtension.c_str(), "mif"))
     205       25850 :                 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         748 :         CSLDestroy(papszFileList);
     230             : 
     231         748 :         if (m_nLayerCount == 0)
     232             :         {
     233         719 :             if (!bTestOpen)
     234           0 :                 CPLError(CE_Failure, CPLE_OpenFailed,
     235             :                          "No mapinfo files found in directory %s.",
     236             :                          m_pszDirectory);
     237             : 
     238         719 :             return FALSE;
     239             :         }
     240             :     }
     241             : 
     242        2084 :     return TRUE;
     243             : }
     244             : 
     245             : /************************************************************************/
     246             : /*                           GetLayerCount()                            */
     247             : /************************************************************************/
     248             : 
     249        2350 : int OGRTABDataSource::GetLayerCount() const
     250             : 
     251             : {
     252        2350 :     if (m_bSingleFile && !m_bSingleLayerAlreadyCreated)
     253          12 :         return 0;
     254             :     else
     255        2338 :         return m_nLayerCount;
     256             : }
     257             : 
     258             : /************************************************************************/
     259             : /*                              GetLayer()                              */
     260             : /************************************************************************/
     261             : 
     262        2176 : const OGRLayer *OGRTABDataSource::GetLayer(int iLayer) const
     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         210 : OGRTABDataSource::ICreateLayer(const char *pszLayerName,
     277             :                                const OGRGeomFieldDefn *poGeomFieldDefnIn,
     278             :                                CSLConstList papszOptions)
     279             : 
     280             : {
     281         210 :     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         210 :         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         210 :     IMapInfoFile *poFile = nullptr;
     295         210 :     char *pszFullFilename = nullptr;
     296             : 
     297         210 :     const char *pszEncoding = CSLFetchNameValue(papszOptions, "ENCODING");
     298         210 :     const char *pszCharset(IMapInfoFile::EncodingToCharset(pszEncoding));
     299         210 :     const char *pszDescription(CSLFetchNameValue(papszOptions, "DESCRIPTION"));
     300             :     const char *pszStrictLaundering =
     301         210 :         CSLFetchNameValue(papszOptions, "STRICT_FIELDS_NAME_LAUNDERING");
     302         210 :     if (pszStrictLaundering == nullptr)
     303             :     {
     304         208 :         pszStrictLaundering = CSLFetchNameValueDef(
     305         208 :             m_papszOptions, "STRICT_FIELDS_NAME_LAUNDERING", "YES");
     306             :     }
     307         210 :     bool bStrictLaundering = CPLTestBool(pszStrictLaundering);
     308             : 
     309         210 :     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          59 :         if (CPLLaunderForFilenameSafe(pszLayerName, nullptr) != pszLayerName)
     332             :         {
     333           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     334             :                      "Illegal characters in '%s' to form a valid filename",
     335             :                      pszLayerName);
     336           1 :             return nullptr;
     337             :         }
     338             : 
     339          58 :         if (m_bCreateMIF)
     340             :         {
     341           3 :             pszFullFilename = CPLStrdup(
     342           6 :                 CPLFormFilenameSafe(m_pszDirectory, pszLayerName, "mif")
     343             :                     .c_str());
     344             : 
     345           3 :             poFile = new MIFFile(this);
     346             : 
     347           3 :             if (poFile->Open(pszFullFilename, TABWrite, FALSE, pszCharset) != 0)
     348             :             {
     349           0 :                 CPLFree(pszFullFilename);
     350           0 :                 delete poFile;
     351           0 :                 return nullptr;
     352             :             }
     353             :         }
     354             :         else
     355             :         {
     356          55 :             pszFullFilename = CPLStrdup(
     357         110 :                 CPLFormFilenameSafe(m_pszDirectory, pszLayerName, "tab")
     358             :                     .c_str());
     359             : 
     360          55 :             TABFile *poTABFile = new TABFile(this);
     361             : 
     362          55 :             if (poTABFile->Open(pszFullFilename, TABWrite, FALSE, m_nBlockSize,
     363          55 :                                 pszCharset) != 0)
     364             :             {
     365           0 :                 CPLFree(pszFullFilename);
     366           0 :                 delete poTABFile;
     367           0 :                 return nullptr;
     368             :             }
     369          55 :             poFile = poTABFile;
     370          55 :             poFile->SetMetadataItem("DESCRIPTION", pszDescription);
     371             :         }
     372             : 
     373          58 :         m_nLayerCount++;
     374          58 :         m_papoLayers = static_cast<IMapInfoFile **>(
     375          58 :             CPLRealloc(m_papoLayers, sizeof(void *) * m_nLayerCount));
     376          58 :         m_papoLayers[m_nLayerCount - 1] = poFile;
     377             : 
     378          58 :         CPLFree(pszFullFilename);
     379             :     }
     380             : 
     381         209 :     poFile->SetDescription(poFile->GetName());
     382         209 :     poFile->SetStrictLaundering(bStrictLaundering);
     383             : 
     384             :     // Assign the coordinate system (if provided) and set
     385             :     // reasonable bounds.
     386         209 :     if (poSRSIn != nullptr)
     387             :     {
     388         100 :         auto poSRSClone = poSRSIn->Clone();
     389         100 :         poSRSClone->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     390         100 :         poFile->SetSpatialRef(poSRSClone);
     391         100 :         poSRSClone->Release();
     392             :         // SetSpatialRef() has cloned the passed geometry
     393         100 :         OGRLayer *poFileAsLayer = poFile;
     394             :         auto poGeomFieldDefn =
     395         100 :             poFileAsLayer->GetLayerDefn()->GetGeomFieldDefn(0);
     396         200 :         whileUnsealing(poGeomFieldDefn)
     397         200 :             ->SetSpatialRef(
     398         100 :                 const_cast<OGRSpatialReference *>(poFile->GetSpatialRef()));
     399             :     }
     400             : 
     401             :     // Pull out the bounds if supplied
     402         209 :     const char *pszOpt = nullptr;
     403         209 :     if ((pszOpt = CSLFetchNameValue(papszOptions, "BOUNDS")) != nullptr)
     404             :     {
     405             :         double dfBounds[4];
     406           5 :         if (CPLsscanf(pszOpt, "%lf,%lf,%lf,%lf", &dfBounds[0], &dfBounds[1],
     407           5 :                       &dfBounds[2], &dfBounds[3]) != 4)
     408             :         {
     409           0 :             CPLError(
     410             :                 CE_Failure, CPLE_IllegalArg,
     411             :                 "Invalid BOUNDS parameter, expected min_x,min_y,max_x,max_y");
     412             :         }
     413             :         else
     414             :         {
     415           5 :             poFile->SetBounds(dfBounds[0], dfBounds[1], dfBounds[2],
     416           5 :                               dfBounds[3]);
     417             :         }
     418             :     }
     419             : 
     420         209 :     if (!poFile->IsBoundsSet() && !m_bCreateMIF)
     421             :     {
     422         103 :         if (poSRSIn != nullptr && poSRSIn->IsGeographic())
     423           0 :             poFile->SetBounds(-1000, -1000, 1000, 1000);
     424         103 :         else if (poSRSIn != nullptr && poSRSIn->IsProjected())
     425             :         {
     426          11 :             const double FE = poSRSIn->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);
     427          11 :             const double FN = poSRSIn->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     428          11 :             poFile->SetBounds(-30000000 + FE, -15000000 + FN, 30000000 + FE,
     429          11 :                               15000000 + FN);
     430             :         }
     431             :         else
     432          92 :             poFile->SetBounds(-30000000, -15000000, 30000000, 15000000);
     433             :     }
     434             : 
     435         209 :     if (m_bQuickSpatialIndexMode == TRUE &&
     436           0 :         poFile->SetQuickSpatialIndexMode(TRUE) != 0)
     437             :     {
     438           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     439             :                  "Setting Quick Spatial Index Mode failed.");
     440             :     }
     441         209 :     else if (m_bQuickSpatialIndexMode == FALSE &&
     442           0 :              poFile->SetQuickSpatialIndexMode(FALSE) != 0)
     443             :     {
     444           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     445             :                  "Setting Normal Spatial Index Mode failed.");
     446             :     }
     447             : 
     448         209 :     return poFile;
     449             : }
     450             : 
     451             : /************************************************************************/
     452             : /*                           TestCapability()                           */
     453             : /************************************************************************/
     454             : 
     455          92 : int OGRTABDataSource::TestCapability(const char *pszCap) const
     456             : 
     457             : {
     458          92 :     if (EQUAL(pszCap, ODsCCreateLayer))
     459          42 :         return GetUpdate() && (!m_bSingleFile || !m_bSingleLayerAlreadyCreated);
     460          50 :     else if (EQUAL(pszCap, ODsCRandomLayerWrite))
     461           0 :         return GetUpdate();
     462             :     else
     463          50 :         return FALSE;
     464             : }
     465             : 
     466             : /************************************************************************/
     467             : /*                            GetFileList()                             */
     468             : /************************************************************************/
     469             : 
     470          36 : char **OGRTABDataSource::GetFileList()
     471             : {
     472             :     VSIStatBufL sStatBuf;
     473          72 :     CPLStringList osList;
     474             : 
     475          72 :     if (VSIStatL(GetDescription(), &sStatBuf) == 0 &&
     476          36 :         VSI_ISDIR(sStatBuf.st_mode))
     477             :     {
     478             :         static const char *const apszExtensions[] = {
     479             :             "mif", "mid", "tab", "map", "ind", "dat", "id", nullptr};
     480          18 :         char **papszDirEntries = VSIReadDir(GetDescription());
     481             : 
     482         156 :         for (int iFile = 0;
     483         156 :              papszDirEntries != nullptr && papszDirEntries[iFile] != nullptr;
     484             :              iFile++)
     485             :         {
     486         138 :             if (CSLFindString(
     487             :                     apszExtensions,
     488         276 :                     CPLGetExtensionSafe(papszDirEntries[iFile]).c_str()) != -1)
     489             :             {
     490         134 :                 osList.push_back(CPLFormFilenameSafe(
     491         134 :                     GetDescription(), papszDirEntries[iFile], nullptr));
     492             :             }
     493             :         }
     494             : 
     495          18 :         CSLDestroy(papszDirEntries);
     496             :     }
     497             :     else
     498             :     {
     499             :         static const char *const apszMIFExtensions[] = {"mif", "mid", nullptr};
     500             :         static const char *const apszTABExtensions[] = {"tab", "map", "ind",
     501             :                                                         "dat", "id",  nullptr};
     502          18 :         const char *const *papszExtensions = nullptr;
     503          50 :         if (EQUAL(CPLGetExtensionSafe(GetDescription()).c_str(), "mif") ||
     504          32 :             EQUAL(CPLGetExtensionSafe(GetDescription()).c_str(), "mid"))
     505             :         {
     506           4 :             papszExtensions = apszMIFExtensions;
     507             :         }
     508             :         else
     509             :         {
     510          14 :             papszExtensions = apszTABExtensions;
     511             :         }
     512          18 :         const char *const *papszIter = papszExtensions;
     513          96 :         while (*papszIter)
     514             :         {
     515             :             std::string osFile =
     516          78 :                 CPLResetExtensionSafe(GetDescription(), *papszIter);
     517          78 :             if (VSIStatL(osFile.c_str(), &sStatBuf) != 0)
     518             :             {
     519          28 :                 osFile = CPLResetExtensionSafe(GetDescription(),
     520          42 :                                                CPLString(*papszIter).toupper());
     521          14 :                 if (VSIStatL(osFile.c_str(), &sStatBuf) != 0)
     522             :                 {
     523          14 :                     osFile.clear();
     524             :                 }
     525             :             }
     526          78 :             if (!osFile.empty())
     527          64 :                 osList.AddString(osFile.c_str());
     528          78 :             papszIter++;
     529             :         }
     530             :     }
     531          72 :     return osList.StealList();
     532             : }
     533             : 
     534             : /************************************************************************/
     535             : /*                            ExecuteSQL()                              */
     536             : /************************************************************************/
     537             : 
     538          35 : OGRLayer *OGRTABDataSource::ExecuteSQL(const char *pszStatement,
     539             :                                        OGRGeometry *poSpatialFilter,
     540             :                                        const char *pszDialect)
     541             : {
     542          35 :     char **papszTokens = CSLTokenizeString(pszStatement);
     543          40 :     if (CSLCount(papszTokens) == 6 && EQUAL(papszTokens[0], "CREATE") &&
     544          45 :         EQUAL(papszTokens[1], "INDEX") && EQUAL(papszTokens[2], "ON") &&
     545           5 :         EQUAL(papszTokens[4], "USING"))
     546             :     {
     547             :         IMapInfoFile *poLayer =
     548           5 :             dynamic_cast<IMapInfoFile *>(GetLayerByName(papszTokens[3]));
     549           5 :         if (poLayer == nullptr)
     550             :         {
     551           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     552             :                      "`%s' failed failed, no such layer as `%s'.", pszStatement,
     553           1 :                      papszTokens[3]);
     554           1 :             CSLDestroy(papszTokens);
     555           1 :             return nullptr;
     556             :         }
     557           4 :         int nFieldIdx = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
     558           4 :         CSLDestroy(papszTokens);
     559           4 :         if (nFieldIdx < 0)
     560             :         {
     561           1 :             CPLError(CE_Failure, CPLE_AppDefined,
     562             :                      "`%s' failed, field not found.", pszStatement);
     563           1 :             return nullptr;
     564             :         }
     565           3 :         poLayer->SetFieldIndexed(nFieldIdx);
     566           3 :         return nullptr;
     567             :     }
     568             : 
     569          30 :     CSLDestroy(papszTokens);
     570          30 :     return GDALDataset::ExecuteSQL(pszStatement, poSpatialFilter, pszDialect);
     571             : }

Generated by: LCOV version 1.14