LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/odbc - ogrodbcdatasource.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 28 223 12.6 %
Date: 2024-05-03 15:49:35 Functions: 5 14 35.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implements OGRODBCDataSource class.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
       9             :  * Copyright (c) 2009-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "ogr_odbc.h"
      31             : #include "cpl_conv.h"
      32             : #include "cpl_string.h"
      33             : #include "ogrodbcdrivercore.h"
      34             : 
      35             : /************************************************************************/
      36             : /*                         OGRODBCDataSource()                          */
      37             : /************************************************************************/
      38             : 
      39           2 : OGRODBCDataSource::OGRODBCDataSource()
      40           2 :     : papoLayers(nullptr), nLayers(0), pszName(nullptr)
      41             : {
      42           2 : }
      43             : 
      44             : /************************************************************************/
      45             : /*                         ~OGRODBCDataSource()                         */
      46             : /************************************************************************/
      47             : 
      48           4 : OGRODBCDataSource::~OGRODBCDataSource()
      49             : 
      50             : {
      51           2 :     CPLFree(pszName);
      52             : 
      53           2 :     for (int i = 0; i < nLayers; i++)
      54           0 :         delete papoLayers[i];
      55             : 
      56           2 :     CPLFree(papoLayers);
      57           4 : }
      58             : 
      59             : /************************************************************************/
      60             : /*                  CheckDSNStringTemplate()                            */
      61             : /* The string will be used as the formatting argument of sprintf with   */
      62             : /* a string in vararg. So let's check there's only one '%s', and nothing*/
      63             : /* else                                                                 */
      64             : /************************************************************************/
      65             : 
      66           0 : static int CheckDSNStringTemplate(const char *pszStr)
      67             : {
      68           0 :     int nPercentSFound = FALSE;
      69           0 :     while (*pszStr)
      70             :     {
      71           0 :         if (*pszStr == '%')
      72             :         {
      73           0 :             if (pszStr[1] != 's')
      74             :             {
      75           0 :                 return FALSE;
      76             :             }
      77             :             else
      78             :             {
      79           0 :                 if (nPercentSFound)
      80           0 :                     return FALSE;
      81           0 :                 nPercentSFound = TRUE;
      82             :             }
      83             :         }
      84           0 :         pszStr++;
      85             :     }
      86           0 :     return TRUE;
      87             : }
      88             : 
      89             : /************************************************************************/
      90             : /*                              OpenMDB()                               */
      91             : /************************************************************************/
      92             : 
      93           2 : int OGRODBCDataSource::OpenMDB(GDALOpenInfo *poOpenInfo)
      94             : {
      95             : #ifndef _WIN32
      96             :     // Try to register MDB Tools driver
      97           2 :     CPLODBCDriverInstaller::InstallMdbToolsDriver();
      98             : #endif /* ndef WIN32 */
      99             : 
     100           2 :     const char *pszOptionName = "PGEO_DRIVER_TEMPLATE";
     101             :     const char *pszDSNStringTemplate =
     102           2 :         CPLGetConfigOption(pszOptionName, nullptr);
     103           2 :     if (pszDSNStringTemplate == nullptr)
     104             :     {
     105           2 :         pszOptionName = "MDB_DRIVER_TEMPLATE";
     106           2 :         pszDSNStringTemplate = CPLGetConfigOption(pszOptionName, nullptr);
     107           2 :         if (pszDSNStringTemplate == nullptr)
     108             :         {
     109           2 :             pszOptionName = "";
     110             :         }
     111             :     }
     112           2 :     if (pszDSNStringTemplate && !CheckDSNStringTemplate(pszDSNStringTemplate))
     113             :     {
     114           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Illegal value for %s option",
     115             :                  pszOptionName);
     116           0 :         return FALSE;
     117             :     }
     118             : 
     119           2 :     const char *pszNewName = poOpenInfo->pszFilename;
     120           2 :     if (!oSession.ConnectToMsAccess(pszNewName, pszDSNStringTemplate))
     121             :     {
     122           2 :         return FALSE;
     123             :     }
     124             : 
     125             :     // Retrieve numeric values from MS Access files using ODBC numeric types, to
     126             :     // avoid loss of precision and missing values on Windows (see
     127             :     // https://github.com/OSGeo/gdal/issues/3885)
     128           0 :     m_nStatementFlags |= CPLODBCStatement::Flag::RetrieveNumericColumnsAsDouble;
     129             : 
     130           0 :     pszName = CPLStrdup(pszNewName);
     131             : 
     132             :     // Collate a list of all tables in the data source
     133           0 :     CPLODBCStatement oTableList(&oSession);
     134           0 :     std::vector<CPLString> aosTableNames;
     135           0 :     if (oTableList.GetTables())
     136             :     {
     137           0 :         while (oTableList.Fetch())
     138             :         {
     139           0 :             const char *pszSchema = oTableList.GetColData(1);
     140           0 :             const char *pszTableName = oTableList.GetColData(2);
     141           0 :             if (pszTableName != nullptr)
     142             :             {
     143           0 :                 CPLString osLayerName;
     144             : 
     145           0 :                 if (pszSchema != nullptr && strlen(pszSchema) > 0)
     146             :                 {
     147           0 :                     osLayerName = pszSchema;
     148           0 :                     osLayerName += ".";
     149             :                 }
     150             : 
     151           0 :                 osLayerName += pszTableName;
     152             : 
     153           0 :                 const CPLString osLCTableName(CPLString(osLayerName).tolower());
     154           0 :                 m_aosAllLCTableNames.insert(osLCTableName);
     155             : 
     156           0 :                 aosTableNames.emplace_back(osLayerName);
     157             :             }
     158             :         }
     159             :     }
     160             :     else
     161             :     {
     162           0 :         return FALSE;
     163             :     }
     164             : 
     165             :     /* -------------------------------------------------------------------- */
     166             :     /*      Check if it is a PGeo MDB.                    */
     167             :     /* -------------------------------------------------------------------- */
     168           0 :     for (const CPLString &osTableName : aosTableNames)
     169             :     {
     170           0 :         const CPLString osLCTableName(CPLString(osTableName).tolower());
     171           0 :         if (osLCTableName == "gdb_geomcolumns" /* PGeo */)
     172           0 :             return FALSE;
     173             :     }
     174             : 
     175           0 :     const bool bListAllTables = CPLTestBool(CSLFetchNameValueDef(
     176           0 :         poOpenInfo->papszOpenOptions, "LIST_ALL_TABLES", "NO"));
     177             : 
     178             :     /* -------------------------------------------------------------------- */
     179             :     /*      Return all tables as non-spatial tables.                       */
     180             :     /* -------------------------------------------------------------------- */
     181           0 :     for (const CPLString &osTableName : aosTableNames)
     182             :     {
     183           0 :         const CPLString osLCTableName(CPLString(osTableName).tolower());
     184           0 :         if (bListAllTables || !(osLCTableName.size() >= 4 &&
     185           0 :                                 osLCTableName.substr(0, 4) ==
     186             :                                     "msys")  // MS Access internal tables
     187             :         )
     188             :         {
     189           0 :             OpenTable(osTableName, nullptr);
     190             :         }
     191             :     }
     192             : 
     193           0 :     return TRUE;
     194             : }
     195             : 
     196             : /************************************************************************/
     197             : /*                                Open()                                */
     198             : /************************************************************************/
     199             : 
     200           2 : int OGRODBCDataSource::Open(GDALOpenInfo *poOpenInfo)
     201             : {
     202           2 :     CPLAssert(nLayers == 0);
     203             : 
     204           2 :     const char *pszNewName = poOpenInfo->pszFilename;
     205             : 
     206           2 :     constexpr const char *ODBC_PREFIX = "ODBC:";
     207           4 :     if (!STARTS_WITH_CI(pszNewName, ODBC_PREFIX) &&
     208           2 :         OGRODBCDriverIsSupportedMsAccessFileExtension(
     209             :             CPLGetExtension(pszNewName)))
     210           2 :         return OpenMDB(poOpenInfo);
     211             : 
     212             :     /* -------------------------------------------------------------------- */
     213             :     /*      Start parsing dataset name from the end of string, fetching     */
     214             :     /*      the name of spatial reference table and names for SRID and      */
     215             :     /*      SRTEXT columns first.                                           */
     216             :     /* -------------------------------------------------------------------- */
     217           0 :     char *pszWrkName = CPLStrdup(pszNewName + strlen(ODBC_PREFIX));
     218           0 :     char **papszTables = nullptr;
     219           0 :     char **papszGeomCol = nullptr;
     220           0 :     char *pszSRSTableName = nullptr;
     221           0 :     char *pszSRIDCol = nullptr;
     222           0 :     char *pszSRTextCol = nullptr;
     223           0 :     char *pszDelimiter = nullptr;
     224             : 
     225           0 :     if ((pszDelimiter = strrchr(pszWrkName, ':')) != nullptr)
     226             :     {
     227           0 :         char *pszOBracket = strchr(pszDelimiter + 1, '(');
     228             : 
     229           0 :         if (strchr(pszDelimiter, '\\') != nullptr ||
     230           0 :             strchr(pszDelimiter, '/') != nullptr)
     231             :         {
     232             :             /*
     233             :             ** if there are special tokens then this isn't really
     234             :             ** the srs table name, so avoid further processing.
     235             :             */
     236             :         }
     237           0 :         else if (pszOBracket == nullptr)
     238             :         {
     239           0 :             pszSRSTableName = CPLStrdup(pszDelimiter + 1);
     240           0 :             *pszDelimiter = '\0';
     241             :         }
     242             :         else
     243             :         {
     244           0 :             char *pszCBracket = strchr(pszOBracket, ')');
     245           0 :             if (pszCBracket != nullptr)
     246           0 :                 *pszCBracket = '\0';
     247             : 
     248           0 :             char *pszComma = strchr(pszOBracket, ',');
     249           0 :             if (pszComma != nullptr)
     250             :             {
     251           0 :                 *pszComma = '\0';
     252           0 :                 pszSRIDCol = CPLStrdup(pszComma + 1);
     253             :             }
     254             : 
     255           0 :             *pszOBracket = '\0';
     256           0 :             pszSRSTableName = CPLStrdup(pszDelimiter + 1);
     257           0 :             pszSRTextCol = CPLStrdup(pszOBracket + 1);
     258             : 
     259           0 :             *pszDelimiter = '\0';
     260             :         }
     261             :     }
     262             : 
     263             :     /* -------------------------------------------------------------------- */
     264             :     /*      Strip off any comma delimited set of tables names to access     */
     265             :     /*      from the end of the string first.  Also allow an optional       */
     266             :     /*      bracketed geometry column name after the table name.            */
     267             :     /* -------------------------------------------------------------------- */
     268           0 :     while ((pszDelimiter = strrchr(pszWrkName, ',')) != nullptr)
     269             :     {
     270           0 :         char *pszOBracket = strstr(pszDelimiter + 1, "(");
     271           0 :         if (pszOBracket == nullptr)
     272             :         {
     273           0 :             papszTables = CSLAddString(papszTables, pszDelimiter + 1);
     274           0 :             papszGeomCol = CSLAddString(papszGeomCol, "");
     275             :         }
     276             :         else
     277             :         {
     278           0 :             char *pszCBracket = strstr(pszOBracket, ")");
     279             : 
     280           0 :             if (pszCBracket != nullptr)
     281           0 :                 *pszCBracket = '\0';
     282             : 
     283           0 :             *pszOBracket = '\0';
     284           0 :             papszTables = CSLAddString(papszTables, pszDelimiter + 1);
     285           0 :             papszGeomCol = CSLAddString(papszGeomCol, pszOBracket + 1);
     286             :         }
     287           0 :         *pszDelimiter = '\0';
     288             :     }
     289             : 
     290             :     /* -------------------------------------------------------------------- */
     291             :     /*      Split out userid, password and DSN.  The general form is        */
     292             :     /*      user/password@dsn.  But if there are no @ characters the        */
     293             :     /*      whole thing is assumed to be a DSN.                             */
     294             :     /* -------------------------------------------------------------------- */
     295           0 :     std::string osUserId;
     296           0 :     std::string osPassword;
     297           0 :     std::string osDSN;
     298             : 
     299           0 :     const char *pszAt = strchr(pszWrkName, '@');
     300           0 :     if (pszAt == nullptr)
     301             :     {
     302           0 :         osDSN = pszWrkName;
     303             :     }
     304             :     else
     305             :     {
     306           0 :         osDSN = pszAt + 1;
     307           0 :         osUserId.assign(pszWrkName, pszAt - pszWrkName);
     308           0 :         const auto nSlashPos = osUserId.find('/');
     309           0 :         if (nSlashPos != std::string::npos)
     310             :         {
     311           0 :             osPassword = osUserId.substr(nSlashPos + 1);
     312           0 :             osUserId.resize(nSlashPos);
     313             :         }
     314             :     }
     315             : 
     316           0 :     CPLFree(pszWrkName);
     317             : 
     318             :     /* -------------------------------------------------------------------- */
     319             :     /*      Initialize based on the DSN.                                    */
     320             :     /* -------------------------------------------------------------------- */
     321           0 :     CPLDebug("OGR_ODBC",
     322             :              "EstablishSession(DSN:\"%s\", userid:\"%s\", password:\"%s\")",
     323             :              osDSN.c_str(), osUserId.c_str(), osPassword.c_str());
     324             : 
     325           0 :     if (!oSession.EstablishSession(
     326           0 :             osDSN.c_str(), osUserId.empty() ? nullptr : osUserId.c_str(),
     327           0 :             osPassword.empty() ? nullptr : osPassword.c_str()))
     328             :     {
     329           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     330             :                  "Unable to initialize ODBC connection to DSN for %s,\n"
     331             :                  "%s",
     332             :                  pszNewName + strlen(ODBC_PREFIX), oSession.GetLastError());
     333           0 :         CSLDestroy(papszTables);
     334           0 :         CSLDestroy(papszGeomCol);
     335           0 :         CPLFree(pszSRIDCol);
     336           0 :         CPLFree(pszSRTextCol);
     337           0 :         CPLFree(pszSRSTableName);
     338           0 :         return FALSE;
     339             :     }
     340             : 
     341           0 :     pszName = CPLStrdup(pszNewName);
     342             : 
     343             :     /* -------------------------------------------------------------------- */
     344             :     /*      If no explicit list of tables was given, check for a list in    */
     345             :     /*      a geometry_columns table.                                       */
     346             :     /* -------------------------------------------------------------------- */
     347           0 :     if (papszTables == nullptr)
     348             :     {
     349           0 :         CPLODBCStatement oStmt(&oSession);
     350             : 
     351           0 :         oStmt.Append("SELECT f_table_name, f_geometry_column, geometry_type"
     352             :                      " FROM geometry_columns");
     353           0 :         if (oStmt.ExecuteSQL())
     354             :         {
     355           0 :             while (oStmt.Fetch())
     356             :             {
     357           0 :                 papszTables = CSLAddString(papszTables, oStmt.GetColData(0));
     358           0 :                 papszGeomCol = CSLAddString(papszGeomCol, oStmt.GetColData(1));
     359             :             }
     360             :         }
     361             :     }
     362             : 
     363             :     /* -------------------------------------------------------------------- */
     364             :     /*      Otherwise our final resort is to return all tables as           */
     365             :     /*      non-spatial tables.                                             */
     366             :     /* -------------------------------------------------------------------- */
     367           0 :     if (papszTables == nullptr)
     368             :     {
     369           0 :         CPLODBCStatement oTableList(&oSession);
     370             : 
     371           0 :         if (oTableList.GetTables())
     372             :         {
     373           0 :             while (oTableList.Fetch())
     374             :             {
     375           0 :                 const char *pszSchema = oTableList.GetColData(1);
     376           0 :                 CPLString osLayerName;
     377             : 
     378           0 :                 if (pszSchema != nullptr && strlen(pszSchema) > 0)
     379             :                 {
     380           0 :                     osLayerName = pszSchema;
     381           0 :                     osLayerName += ".";
     382             :                 }
     383             : 
     384           0 :                 osLayerName += oTableList.GetColData(2);
     385             : 
     386           0 :                 papszTables = CSLAddString(papszTables, osLayerName);
     387             : 
     388           0 :                 papszGeomCol = CSLAddString(papszGeomCol, "");
     389             :             }
     390             :         }
     391             :     }
     392             : 
     393             :     /* -------------------------------------------------------------------- */
     394             :     /*      If we have an explicit list of requested tables, use them       */
     395             :     /*      (non-spatial).                                                  */
     396             :     /* -------------------------------------------------------------------- */
     397           0 :     for (int iTable = 0;
     398           0 :          papszTables != nullptr && papszTables[iTable] != nullptr; iTable++)
     399             :     {
     400           0 :         if (strlen(papszGeomCol[iTable]) > 0)
     401           0 :             OpenTable(papszTables[iTable], papszGeomCol[iTable]);
     402             :         else
     403           0 :             OpenTable(papszTables[iTable], nullptr);
     404             :     }
     405             : 
     406           0 :     CSLDestroy(papszTables);
     407           0 :     CSLDestroy(papszGeomCol);
     408             : 
     409             : #if 0
     410             :     // NOTE: nothing uses the SRS cache currently. Hence disabled.
     411             : 
     412             :     /* -------------------------------------------------------------------- */
     413             :     /*      If no explicit list of tables was given, check for a list in    */
     414             :     /*      a geometry_columns table.                                       */
     415             :     /* -------------------------------------------------------------------- */
     416             :     if (pszSRSTableName)
     417             :     {
     418             :         CPLODBCStatement oSRSList(&oSession);
     419             : 
     420             :         if (!pszSRTextCol)
     421             :             pszSRTextCol = CPLStrdup("srtext");
     422             :         if (!pszSRIDCol)
     423             :             pszSRIDCol = CPLStrdup("srid");
     424             : 
     425             :         oSRSList.Append("SELECT ");
     426             :         oSRSList.Append(pszSRIDCol);
     427             :         oSRSList.Append(",");
     428             :         oSRSList.Append(pszSRTextCol);
     429             :         oSRSList.Append(" FROM ");
     430             :         oSRSList.Append(pszSRSTableName);
     431             : 
     432             :         CPLDebug("OGR_ODBC", "ExecuteSQL(%s) to read SRS table",
     433             :                  oSRSList.GetCommand());
     434             :         if (oSRSList.ExecuteSQL())
     435             :         {
     436             :             while (oSRSList.Fetch())
     437             :             {
     438             :                 const char *pszSRID = oSRSList.GetColData(pszSRIDCol);
     439             :                 if (!pszSRID)
     440             :                     continue;
     441             : 
     442             :                 const char *pszSRText = oSRSList.GetColData(pszSRTextCol);
     443             : 
     444             :                 if (pszSRText)
     445             :                 {
     446             :                     std::unique_ptr<OGRSpatialReference, OGRSpatialReferenceReleaser> poSRS(new OGRSpatialReference());
     447             :                     poSRS->SetAxisMappingStrategy(
     448             :                         OAMS_TRADITIONAL_GIS_ORDER);
     449             :                     if (poSRS->importFromWkt(pszSRText) == OGRERR_NONE )
     450             :                     {
     451             :                         m_oSRSCache[atoi(pszSRID)] = std::move(poSRS);
     452             :                     }
     453             :                 }
     454             :             }
     455             :         }
     456             :     }
     457             : #endif
     458             : 
     459           0 :     if (pszSRIDCol)
     460           0 :         CPLFree(pszSRIDCol);
     461           0 :     if (pszSRTextCol)
     462           0 :         CPLFree(pszSRTextCol);
     463           0 :     if (pszSRSTableName)
     464           0 :         CPLFree(pszSRSTableName);
     465             : 
     466           0 :     return TRUE;
     467             : }
     468             : 
     469             : /************************************************************************/
     470             : /*                             OpenTable()                              */
     471             : /************************************************************************/
     472             : 
     473           0 : int OGRODBCDataSource::OpenTable(const char *pszNewName, const char *pszGeomCol)
     474             : {
     475             :     /* -------------------------------------------------------------------- */
     476             :     /*      Create the layer object.                                        */
     477             :     /* -------------------------------------------------------------------- */
     478           0 :     OGRODBCTableLayer *poLayer = new OGRODBCTableLayer(this, m_nStatementFlags);
     479             : 
     480           0 :     if (poLayer->Initialize(pszNewName, pszGeomCol))
     481             :     {
     482           0 :         delete poLayer;
     483           0 :         return FALSE;
     484             :     }
     485             : 
     486             :     /* -------------------------------------------------------------------- */
     487             :     /*      Add layer to data source layer list.                            */
     488             :     /* -------------------------------------------------------------------- */
     489           0 :     papoLayers = (OGRODBCLayer **)CPLRealloc(
     490           0 :         papoLayers, sizeof(OGRODBCLayer *) * (nLayers + 1));
     491           0 :     papoLayers[nLayers++] = poLayer;
     492             : 
     493           0 :     return TRUE;
     494             : }
     495             : 
     496             : /************************************************************************/
     497             : /*                           TestCapability()                           */
     498             : /************************************************************************/
     499             : 
     500           0 : int OGRODBCDataSource::TestCapability(CPL_UNUSED const char *pszCap)
     501             : {
     502           0 :     return FALSE;
     503             : }
     504             : 
     505             : /************************************************************************/
     506             : /*                              GetLayer()                              */
     507             : /************************************************************************/
     508             : 
     509           0 : OGRLayer *OGRODBCDataSource::GetLayer(int iLayer)
     510             : 
     511             : {
     512           0 :     if (iLayer < 0 || iLayer >= nLayers)
     513           0 :         return nullptr;
     514             :     else
     515           0 :         return papoLayers[iLayer];
     516             : }
     517             : 
     518             : /************************************************************************/
     519             : /*                              GetLayerByName()                        */
     520             : /************************************************************************/
     521             : 
     522           0 : OGRLayer *OGRODBCDataSource::GetLayerByName(const char *pszLayerName)
     523             : {
     524           0 :     OGRLayer *poLayer = GDALDataset::GetLayerByName(pszLayerName);
     525           0 :     if (poLayer != nullptr)
     526           0 :         return poLayer;
     527             : 
     528             :     // if table name doesn't exist in database, don't try any further
     529           0 :     const CPLString osLCTableName(CPLString(pszLayerName).tolower());
     530           0 :     if (m_aosAllLCTableNames.find(osLCTableName) == m_aosAllLCTableNames.end())
     531           0 :         return nullptr;
     532             : 
     533             :     // try to open the table -- if successful the table will be added to
     534             :     // papoLayers as the last item
     535           0 :     if (OpenTable(pszLayerName, nullptr))
     536           0 :         return papoLayers[nLayers - 1];
     537             :     else
     538           0 :         return nullptr;
     539             : }
     540             : 
     541             : /************************************************************************/
     542             : /*                    IsPrivateLayerName()                              */
     543             : /************************************************************************/
     544             : 
     545           0 : bool OGRODBCDataSource::IsPrivateLayerName(const CPLString &osName)
     546             : {
     547           0 :     const CPLString osLCTableName(CPLString(osName).tolower());
     548             : 
     549           0 :     return osLCTableName.size() >= 4 &&
     550           0 :            osLCTableName.substr(0, 4) == "msys";  // MS Access internal tables
     551             : }
     552             : 
     553             : /************************************************************************/
     554             : /*                    IsLayerPrivate()                                  */
     555             : /************************************************************************/
     556             : 
     557           0 : bool OGRODBCDataSource::IsLayerPrivate(int iLayer) const
     558             : {
     559           0 :     if (iLayer < 0 || iLayer >= nLayers)
     560           0 :         return false;
     561             : 
     562           0 :     const std::string osName(papoLayers[iLayer]->GetName());
     563           0 :     return IsPrivateLayerName(osName);
     564             : }
     565             : 
     566             : /************************************************************************/
     567             : /*                             ExecuteSQL()                             */
     568             : /************************************************************************/
     569             : 
     570           0 : OGRLayer *OGRODBCDataSource::ExecuteSQL(const char *pszSQLCommand,
     571             :                                         OGRGeometry *poSpatialFilter,
     572             :                                         const char *pszDialect)
     573             : 
     574             : {
     575             :     /* -------------------------------------------------------------------- */
     576             :     /*      Use generic implementation for recognized dialects              */
     577             :     /* -------------------------------------------------------------------- */
     578           0 :     if (IsGenericSQLDialect(pszDialect))
     579           0 :         return OGRDataSource::ExecuteSQL(pszSQLCommand, poSpatialFilter,
     580           0 :                                          pszDialect);
     581             : 
     582             :     /* -------------------------------------------------------------------- */
     583             :     /*      Execute statement.                                              */
     584             :     /* -------------------------------------------------------------------- */
     585             :     CPLODBCStatement *poStmt =
     586           0 :         new CPLODBCStatement(&oSession, m_nStatementFlags);
     587             : 
     588           0 :     CPLDebug("ODBC", "ExecuteSQL(%s) called.", pszSQLCommand);
     589           0 :     poStmt->Append(pszSQLCommand);
     590           0 :     if (!poStmt->ExecuteSQL())
     591             :     {
     592           0 :         CPLError(CE_Failure, CPLE_AppDefined, "%s", oSession.GetLastError());
     593           0 :         delete poStmt;
     594           0 :         return nullptr;
     595             :     }
     596             : 
     597             :     /* -------------------------------------------------------------------- */
     598             :     /*      Are there result columns for this statement?                    */
     599             :     /* -------------------------------------------------------------------- */
     600           0 :     if (poStmt->GetColCount() == 0)
     601             :     {
     602           0 :         delete poStmt;
     603           0 :         CPLErrorReset();
     604           0 :         return nullptr;
     605             :     }
     606             : 
     607             :     /* -------------------------------------------------------------------- */
     608             :     /*      Create a results layer.  It will take ownership of the          */
     609             :     /*      statement.                                                      */
     610             :     /* -------------------------------------------------------------------- */
     611             : 
     612           0 :     OGRODBCSelectLayer *poLayer = new OGRODBCSelectLayer(this, poStmt);
     613             : 
     614           0 :     if (poSpatialFilter != nullptr)
     615           0 :         poLayer->SetSpatialFilter(poSpatialFilter);
     616             : 
     617           0 :     return poLayer;
     618             : }
     619             : 
     620             : /************************************************************************/
     621             : /*                          ReleaseResultSet()                          */
     622             : /************************************************************************/
     623             : 
     624           0 : void OGRODBCDataSource::ReleaseResultSet(OGRLayer *poLayer)
     625             : 
     626             : {
     627           0 :     delete poLayer;
     628           0 : }

Generated by: LCOV version 1.14