LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/sqlite - ogrsqliteviewlayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 171 213 80.3 %
Date: 2024-11-25 13:07:18 Functions: 17 17 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implements OGRSQLiteViewLayer class, access to an existing
       5             :  *spatialite view. Author:   Even Rouault, <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2011-2013, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "cpl_port.h"
      14             : #include "ogr_sqlite.h"
      15             : #include "ogrsqliteutility.h"
      16             : 
      17             : #include <cstdlib>
      18             : #include <cstring>
      19             : #include <set>
      20             : #include <string>
      21             : 
      22             : #include "cpl_conv.h"
      23             : #include "cpl_error.h"
      24             : #include "cpl_string.h"
      25             : #include "ogr_core.h"
      26             : #include "ogr_feature.h"
      27             : #include "ogr_geometry.h"
      28             : #include "sqlite3.h"
      29             : 
      30             : /************************************************************************/
      31             : /*                        OGRSQLiteViewLayer()                         */
      32             : /************************************************************************/
      33             : 
      34           5 : OGRSQLiteViewLayer::OGRSQLiteViewLayer(OGRSQLiteDataSource *poDSIn)
      35           5 :     : OGRSQLiteLayer(poDSIn)
      36             : {
      37           5 : }
      38             : 
      39             : /************************************************************************/
      40             : /*                        ~OGRSQLiteViewLayer()                        */
      41             : /************************************************************************/
      42             : 
      43          10 : OGRSQLiteViewLayer::~OGRSQLiteViewLayer()
      44             : 
      45             : {
      46           5 :     ClearStatement();
      47           5 :     CPLFree(m_pszViewName);
      48           5 :     CPLFree(m_pszEscapedTableName);
      49           5 :     CPLFree(m_pszEscapedUnderlyingTableName);
      50          10 : }
      51             : 
      52             : /************************************************************************/
      53             : /*                             Initialize()                             */
      54             : /************************************************************************/
      55             : 
      56           5 : CPLErr OGRSQLiteViewLayer::Initialize(const char *pszViewNameIn,
      57             :                                       const char *pszViewGeometry,
      58             :                                       const char *pszViewRowid,
      59             :                                       const char *pszUnderlyingTableName,
      60             :                                       const char *pszUnderlyingGeometryColumn)
      61             : 
      62             : {
      63           5 :     m_pszViewName = CPLStrdup(pszViewNameIn);
      64           5 :     SetDescription(m_pszViewName);
      65             : 
      66           5 :     m_osGeomColumn = pszViewGeometry;
      67           5 :     m_eGeomFormat = OSGF_SpatiaLite;
      68             : 
      69           5 :     CPLFree(m_pszFIDColumn);
      70           5 :     m_pszFIDColumn = CPLStrdup(pszViewRowid);
      71             : 
      72           5 :     m_osUnderlyingTableName = pszUnderlyingTableName;
      73           5 :     m_osUnderlyingGeometryColumn = pszUnderlyingGeometryColumn;
      74           5 :     m_poUnderlyingLayer = nullptr;
      75             : 
      76           5 :     m_pszEscapedTableName = CPLStrdup(SQLEscapeLiteral(m_pszViewName));
      77           5 :     m_pszEscapedUnderlyingTableName =
      78           5 :         CPLStrdup(SQLEscapeLiteral(pszUnderlyingTableName));
      79             : 
      80           5 :     return CE_None;
      81             : }
      82             : 
      83             : /************************************************************************/
      84             : /*                           GetLayerDefn()                             */
      85             : /************************************************************************/
      86             : 
      87          31 : OGRFeatureDefn *OGRSQLiteViewLayer::GetLayerDefn()
      88             : {
      89          31 :     if (m_poFeatureDefn)
      90          27 :         return m_poFeatureDefn;
      91             : 
      92           4 :     EstablishFeatureDefn();
      93             : 
      94           4 :     if (m_poFeatureDefn == nullptr)
      95             :     {
      96           0 :         m_bLayerDefnError = true;
      97             : 
      98           0 :         m_poFeatureDefn = new OGRSQLiteFeatureDefn(m_pszViewName);
      99           0 :         m_poFeatureDefn->Reference();
     100             :     }
     101             : 
     102           4 :     return m_poFeatureDefn;
     103             : }
     104             : 
     105             : /************************************************************************/
     106             : /*                        GetUnderlyingLayer()                          */
     107             : /************************************************************************/
     108             : 
     109           4 : OGRSQLiteLayer *OGRSQLiteViewLayer::GetUnderlyingLayer()
     110             : {
     111           4 :     if (m_poUnderlyingLayer == nullptr)
     112             :     {
     113           4 :         if (strchr(m_osUnderlyingTableName, '(') == nullptr)
     114             :         {
     115           4 :             CPLString osNewUnderlyingTableName;
     116             :             osNewUnderlyingTableName.Printf(
     117             :                 "%s(%s)", m_osUnderlyingTableName.c_str(),
     118           4 :                 m_osUnderlyingGeometryColumn.c_str());
     119           4 :             m_poUnderlyingLayer = cpl::down_cast<OGRSQLiteLayer *>(
     120           4 :                 m_poDS->GetLayerByNameNotVisible(osNewUnderlyingTableName));
     121             :         }
     122           4 :         if (m_poUnderlyingLayer == nullptr)
     123           0 :             m_poUnderlyingLayer = cpl::down_cast<OGRSQLiteLayer *>(
     124           0 :                 m_poDS->GetLayerByNameNotVisible(m_osUnderlyingTableName));
     125             :     }
     126           4 :     return m_poUnderlyingLayer;
     127             : }
     128             : 
     129             : /************************************************************************/
     130             : /*                            GetGeomType()                             */
     131             : /************************************************************************/
     132             : 
     133           3 : OGRwkbGeometryType OGRSQLiteViewLayer::GetGeomType()
     134             : {
     135           3 :     if (m_poFeatureDefn)
     136           3 :         return m_poFeatureDefn->GetGeomType();
     137             : 
     138           0 :     OGRSQLiteLayer *l_m_poUnderlyingLayer = GetUnderlyingLayer();
     139           0 :     if (l_m_poUnderlyingLayer)
     140           0 :         return l_m_poUnderlyingLayer->GetGeomType();
     141             : 
     142           0 :     return wkbUnknown;
     143             : }
     144             : 
     145             : /************************************************************************/
     146             : /*                         EstablishFeatureDefn()                       */
     147             : /************************************************************************/
     148             : 
     149           4 : CPLErr OGRSQLiteViewLayer::EstablishFeatureDefn()
     150             : {
     151           4 :     sqlite3 *hDB = m_poDS->GetDB();
     152           4 :     sqlite3_stmt *hColStmt = nullptr;
     153             : 
     154           4 :     OGRSQLiteLayer *l_m_poUnderlyingLayer = GetUnderlyingLayer();
     155           4 :     if (l_m_poUnderlyingLayer == nullptr)
     156             :     {
     157           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     158             :                  "Cannot find underlying layer %s for view %s",
     159             :                  m_osUnderlyingTableName.c_str(), m_pszViewName);
     160           0 :         return CE_Failure;
     161             :     }
     162           4 :     if (!l_m_poUnderlyingLayer->IsTableLayer())
     163             :     {
     164           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     165             :                  "Underlying layer %s for view %s is not a regular table",
     166             :                  m_osUnderlyingTableName.c_str(), m_pszViewName);
     167           0 :         return CE_Failure;
     168             :     }
     169             : 
     170             :     int nUnderlyingLayerGeomFieldIndex =
     171           8 :         l_m_poUnderlyingLayer->GetLayerDefn()->GetGeomFieldIndex(
     172           4 :             m_osUnderlyingGeometryColumn);
     173           4 :     if (nUnderlyingLayerGeomFieldIndex < 0)
     174             :     {
     175           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     176             :                  "Underlying layer %s for view %s has not expected geometry "
     177             :                  "column name %s",
     178             :                  m_osUnderlyingTableName.c_str(), m_pszViewName,
     179             :                  m_osUnderlyingGeometryColumn.c_str());
     180           0 :         return CE_Failure;
     181             :     }
     182             : 
     183           4 :     m_bHasSpatialIndex =
     184           4 :         l_m_poUnderlyingLayer->HasSpatialIndex(nUnderlyingLayerGeomFieldIndex);
     185             : 
     186             :     /* -------------------------------------------------------------------- */
     187             :     /*      Get the column definitions for this table.                      */
     188             :     /* -------------------------------------------------------------------- */
     189           4 :     hColStmt = nullptr;
     190           4 :     const char *pszSQL = CPLSPrintf("SELECT \"%s\", * FROM '%s' LIMIT 1",
     191           8 :                                     SQLEscapeName(m_pszFIDColumn).c_str(),
     192             :                                     m_pszEscapedTableName);
     193             : 
     194           4 :     int rc = sqlite3_prepare_v2(hDB, pszSQL, -1, &hColStmt, nullptr);
     195           4 :     if (rc != SQLITE_OK)
     196             :     {
     197           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     198             :                  "Unable to query table %s for column definitions : %s.",
     199             :                  m_pszViewName, sqlite3_errmsg(hDB));
     200             : 
     201           0 :         return CE_Failure;
     202             :     }
     203             : 
     204           4 :     rc = sqlite3_step(hColStmt);
     205           4 :     if (rc != SQLITE_DONE && rc != SQLITE_ROW)
     206             :     {
     207           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     208             :                  "In Initialize(): sqlite3_step(%s):\n  %s", pszSQL,
     209             :                  sqlite3_errmsg(hDB));
     210           0 :         sqlite3_finalize(hColStmt);
     211           0 :         return CE_Failure;
     212             :     }
     213             : 
     214             :     /* -------------------------------------------------------------------- */
     215             :     /*      Collect the rest of the fields.                                 */
     216             :     /* -------------------------------------------------------------------- */
     217           8 :     std::set<CPLString> aosGeomCols;
     218           4 :     std::set<CPLString> aosIgnoredCols;
     219           4 :     aosGeomCols.insert(m_osGeomColumn);
     220           4 :     BuildFeatureDefn(m_pszViewName, false, hColStmt, &aosGeomCols,
     221             :                      aosIgnoredCols);
     222           4 :     sqlite3_finalize(hColStmt);
     223             : 
     224             :     /* -------------------------------------------------------------------- */
     225             :     /*      Set the properties of the geometry column.                      */
     226             :     /* -------------------------------------------------------------------- */
     227           4 :     if (m_poFeatureDefn->GetGeomFieldCount() != 0)
     228             :     {
     229             :         OGRSQLiteGeomFieldDefn *poSrcGeomFieldDefn =
     230           4 :             l_m_poUnderlyingLayer->myGetLayerDefn()->myGetGeomFieldDefn(
     231             :                 nUnderlyingLayerGeomFieldIndex);
     232             :         OGRSQLiteGeomFieldDefn *poGeomFieldDefn =
     233           4 :             m_poFeatureDefn->myGetGeomFieldDefn(0);
     234           4 :         poGeomFieldDefn->SetType(poSrcGeomFieldDefn->GetType());
     235           4 :         poGeomFieldDefn->SetSpatialRef(poSrcGeomFieldDefn->GetSpatialRef());
     236           4 :         poGeomFieldDefn->m_nSRSId = poSrcGeomFieldDefn->m_nSRSId;
     237           4 :         if (m_eGeomFormat != OSGF_None)
     238           4 :             poGeomFieldDefn->m_eGeomFormat = m_eGeomFormat;
     239             :     }
     240             : 
     241           4 :     return CE_None;
     242             : }
     243             : 
     244             : /************************************************************************/
     245             : /*                           ResetStatement()                           */
     246             : /************************************************************************/
     247             : 
     248           4 : OGRErr OGRSQLiteViewLayer::ResetStatement()
     249             : 
     250             : {
     251           8 :     CPLString osSQL;
     252             : 
     253           4 :     ClearStatement();
     254             : 
     255           4 :     m_iNextShapeId = 0;
     256             : 
     257             :     osSQL.Printf("SELECT \"%s\", * FROM '%s' %s",
     258           4 :                  SQLEscapeName(m_pszFIDColumn).c_str(), m_pszEscapedTableName,
     259           4 :                  m_osWHERE.c_str());
     260             : 
     261             :     const int rc =
     262           4 :         sqlite3_prepare_v2(m_poDS->GetDB(), osSQL,
     263           4 :                            static_cast<int>(osSQL.size()), &m_hStmt, nullptr);
     264             : 
     265           4 :     if (rc == SQLITE_OK)
     266             :     {
     267           4 :         return OGRERR_NONE;
     268             :     }
     269             : 
     270           0 :     CPLError(CE_Failure, CPLE_AppDefined,
     271             :              "In ResetStatement(): sqlite3_prepare_v2(%s):\n  %s",
     272           0 :              osSQL.c_str(), sqlite3_errmsg(m_poDS->GetDB()));
     273           0 :     m_hStmt = nullptr;
     274           0 :     return OGRERR_FAILURE;
     275             : }
     276             : 
     277             : /************************************************************************/
     278             : /*                           GetNextFeature()                           */
     279             : /************************************************************************/
     280             : 
     281           4 : OGRFeature *OGRSQLiteViewLayer::GetNextFeature()
     282             : 
     283             : {
     284           4 :     if (HasLayerDefnError())
     285           0 :         return nullptr;
     286             : 
     287           4 :     return OGRSQLiteLayer::GetNextFeature();
     288             : }
     289             : 
     290             : /************************************************************************/
     291             : /*                             GetFeature()                             */
     292             : /************************************************************************/
     293             : 
     294           3 : OGRFeature *OGRSQLiteViewLayer::GetFeature(GIntBig nFeatureId)
     295             : 
     296             : {
     297           3 :     if (HasLayerDefnError())
     298           0 :         return nullptr;
     299             : 
     300             :     /* -------------------------------------------------------------------- */
     301             :     /*      If we don't have an explicit FID column, just read through      */
     302             :     /*      the result set iteratively to find our target.                  */
     303             :     /* -------------------------------------------------------------------- */
     304           3 :     if (m_pszFIDColumn == nullptr)
     305           0 :         return OGRSQLiteLayer::GetFeature(nFeatureId);
     306             : 
     307             :     /* -------------------------------------------------------------------- */
     308             :     /*      Setup explicit query statement to fetch the record we want.     */
     309             :     /* -------------------------------------------------------------------- */
     310           6 :     CPLString osSQL;
     311             : 
     312           3 :     ClearStatement();
     313             : 
     314           3 :     m_iNextShapeId = nFeatureId;
     315             : 
     316             :     osSQL.Printf("SELECT \"%s\", * FROM '%s' WHERE \"%s\" = " CPL_FRMT_GIB,
     317           3 :                  SQLEscapeName(m_pszFIDColumn).c_str(), m_pszEscapedTableName,
     318           6 :                  SQLEscapeName(m_pszFIDColumn).c_str(), nFeatureId);
     319             : 
     320           3 :     CPLDebug("OGR_SQLITE", "exec(%s)", osSQL.c_str());
     321             : 
     322             :     const int rc =
     323           3 :         sqlite3_prepare_v2(m_poDS->GetDB(), osSQL,
     324           3 :                            static_cast<int>(osSQL.size()), &m_hStmt, nullptr);
     325           3 :     if (rc != SQLITE_OK)
     326             :     {
     327           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     328             :                  "In GetFeature(): sqlite3_prepare_v2(%s):\n  %s",
     329           0 :                  osSQL.c_str(), sqlite3_errmsg(m_poDS->GetDB()));
     330             : 
     331           0 :         return nullptr;
     332             :     }
     333             :     /* -------------------------------------------------------------------- */
     334             :     /*      Get the feature if possible.                                    */
     335             :     /* -------------------------------------------------------------------- */
     336           3 :     OGRFeature *poFeature = GetNextRawFeature();
     337             : 
     338           3 :     ResetReading();
     339             : 
     340           3 :     return poFeature;
     341             : }
     342             : 
     343             : /************************************************************************/
     344             : /*                         SetAttributeFilter()                         */
     345             : /************************************************************************/
     346             : 
     347           2 : OGRErr OGRSQLiteViewLayer::SetAttributeFilter(const char *pszQuery)
     348             : 
     349             : {
     350           2 :     if (pszQuery == nullptr)
     351           0 :         m_osQuery = "";
     352             :     else
     353           2 :         m_osQuery = pszQuery;
     354             : 
     355           2 :     BuildWhere();
     356             : 
     357           2 :     ResetReading();
     358             : 
     359           2 :     return OGRERR_NONE;
     360             : }
     361             : 
     362             : /************************************************************************/
     363             : /*                          SetSpatialFilter()                          */
     364             : /************************************************************************/
     365             : 
     366           4 : void OGRSQLiteViewLayer::SetSpatialFilter(OGRGeometry *poGeomIn)
     367             : 
     368             : {
     369           4 :     if (InstallFilter(poGeomIn))
     370             :     {
     371           4 :         BuildWhere();
     372             : 
     373           4 :         ResetReading();
     374             :     }
     375           4 : }
     376             : 
     377             : /************************************************************************/
     378             : /*                           GetSpatialWhere()                          */
     379             : /************************************************************************/
     380             : 
     381           6 : CPLString OGRSQLiteViewLayer::GetSpatialWhere(int iGeomCol,
     382             :                                               OGRGeometry *poFilterGeom)
     383             : {
     384          12 :     if (HasLayerDefnError() || m_poFeatureDefn == nullptr || iGeomCol < 0 ||
     385           6 :         iGeomCol >= m_poFeatureDefn->GetGeomFieldCount())
     386           0 :         return "";
     387             : 
     388           6 :     if (poFilterGeom != nullptr && m_bHasSpatialIndex)
     389             :     {
     390           3 :         OGREnvelope sEnvelope;
     391             : 
     392           3 :         poFilterGeom->getEnvelope(&sEnvelope);
     393             : 
     394             :         /* We first check that the spatial index table exists */
     395           3 :         if (!m_bHasCheckedSpatialIndexTable)
     396             :         {
     397           3 :             m_bHasCheckedSpatialIndexTable = true;
     398           3 :             char **papszResult = nullptr;
     399           3 :             int nRowCount = 0;
     400           3 :             int nColCount = 0;
     401           3 :             char *pszErrMsg = nullptr;
     402             : 
     403           6 :             CPLString osSQL;
     404             :             osSQL.Printf(
     405             :                 "SELECT name FROM sqlite_master "
     406             :                 "WHERE name='idx_%s_%s'",
     407             :                 m_pszEscapedUnderlyingTableName,
     408           3 :                 SQLEscapeLiteral(m_osUnderlyingGeometryColumn).c_str());
     409             : 
     410             :             int rc =
     411           3 :                 sqlite3_get_table(m_poDS->GetDB(), osSQL.c_str(), &papszResult,
     412             :                                   &nRowCount, &nColCount, &pszErrMsg);
     413             : 
     414           3 :             if (rc != SQLITE_OK)
     415             :             {
     416           0 :                 CPLError(CE_Failure, CPLE_AppDefined, "Error: %s", pszErrMsg);
     417           0 :                 sqlite3_free(pszErrMsg);
     418           0 :                 m_bHasSpatialIndex = false;
     419             :             }
     420             :             else
     421             :             {
     422           3 :                 if (nRowCount != 1)
     423             :                 {
     424           1 :                     m_bHasSpatialIndex = false;
     425             :                 }
     426             : 
     427           3 :                 sqlite3_free_table(papszResult);
     428             :             }
     429             :         }
     430             : 
     431           3 :         if (m_bHasSpatialIndex)
     432             :         {
     433             :             return FormatSpatialFilterFromRTree(
     434             :                 poFilterGeom,
     435           2 :                 CPLSPrintf("\"%s\"", SQLEscapeName(m_pszFIDColumn).c_str()),
     436           2 :                 m_pszEscapedUnderlyingTableName,
     437           6 :                 SQLEscapeLiteral(m_osUnderlyingGeometryColumn).c_str());
     438             :         }
     439             :         else
     440             :         {
     441           1 :             CPLDebug("SQLITE",
     442             :                      "Count not find idx_%s_%s layer. Disabling spatial index",
     443             :                      m_pszEscapedUnderlyingTableName,
     444             :                      m_osUnderlyingGeometryColumn.c_str());
     445             :         }
     446             :     }
     447             : 
     448           4 :     if (poFilterGeom != nullptr && m_poDS->IsSpatialiteLoaded())
     449             :     {
     450             :         return FormatSpatialFilterFromMBR(
     451             :             poFilterGeom,
     452           4 :             SQLEscapeName(
     453           2 :                 m_poFeatureDefn->GetGeomFieldDefn(iGeomCol)->GetNameRef())
     454           2 :                 .c_str());
     455             :     }
     456             : 
     457           2 :     return "";
     458             : }
     459             : 
     460             : /************************************************************************/
     461             : /*                             BuildWhere()                             */
     462             : /*                                                                      */
     463             : /*      Build the WHERE statement appropriate to the current set of     */
     464             : /*      criteria (spatial and attribute queries).                       */
     465             : /************************************************************************/
     466             : 
     467           6 : void OGRSQLiteViewLayer::BuildWhere()
     468             : 
     469             : {
     470           6 :     m_osWHERE = "";
     471             : 
     472             :     CPLString osSpatialWHERE =
     473          12 :         GetSpatialWhere(m_iGeomFieldFilter, m_poFilterGeom);
     474           6 :     if (!osSpatialWHERE.empty())
     475             :     {
     476           4 :         m_osWHERE = "WHERE ";
     477           4 :         m_osWHERE += osSpatialWHERE;
     478             :     }
     479             : 
     480           6 :     if (!m_osQuery.empty())
     481             :     {
     482           4 :         if (m_osWHERE.empty())
     483             :         {
     484           2 :             m_osWHERE = "WHERE ";
     485           2 :             m_osWHERE += m_osQuery;
     486             :         }
     487             :         else
     488             :         {
     489           2 :             m_osWHERE += " AND (";
     490           2 :             m_osWHERE += m_osQuery;
     491           2 :             m_osWHERE += ")";
     492             :         }
     493             :     }
     494           6 : }
     495             : 
     496             : /************************************************************************/
     497             : /*                           TestCapability()                           */
     498             : /************************************************************************/
     499             : 
     500           3 : int OGRSQLiteViewLayer::TestCapability(const char *pszCap)
     501             : 
     502             : {
     503           3 :     if (HasLayerDefnError())
     504           0 :         return FALSE;
     505             : 
     506           3 :     if (EQUAL(pszCap, OLCFastFeatureCount))
     507           3 :         return m_poFilterGeom == nullptr || m_osGeomColumn.empty() ||
     508           3 :                m_bHasSpatialIndex;
     509             : 
     510           0 :     else if (EQUAL(pszCap, OLCFastSpatialFilter))
     511           0 :         return m_bHasSpatialIndex;
     512             : 
     513             :     else
     514           0 :         return OGRSQLiteLayer::TestCapability(pszCap);
     515             : }
     516             : 
     517             : /************************************************************************/
     518             : /*                          GetFeatureCount()                           */
     519             : /*                                                                      */
     520             : /*      If a spatial filter is in effect, we turn control over to       */
     521             : /*      the generic counter.  Otherwise we return the total count.      */
     522             : /*      Eventually we should consider implementing a more efficient     */
     523             : /*      way of counting features matching a spatial query.              */
     524             : /************************************************************************/
     525             : 
     526           3 : GIntBig OGRSQLiteViewLayer::GetFeatureCount(int bForce)
     527             : 
     528             : {
     529           3 :     if (HasLayerDefnError())
     530           0 :         return 0;
     531             : 
     532           3 :     if (!TestCapability(OLCFastFeatureCount))
     533           0 :         return OGRSQLiteLayer::GetFeatureCount(bForce);
     534             : 
     535             :     /* -------------------------------------------------------------------- */
     536             :     /*      Form count SQL.                                                 */
     537             :     /* -------------------------------------------------------------------- */
     538           3 :     const char *pszSQL = CPLSPrintf("SELECT count(*) FROM '%s' %s",
     539             :                                     m_pszEscapedTableName, m_osWHERE.c_str());
     540             : 
     541             :     /* -------------------------------------------------------------------- */
     542             :     /*      Execute.                                                        */
     543             :     /* -------------------------------------------------------------------- */
     544             :     char **papszResult, *pszErrMsg;
     545             :     int nRowCount, nColCount;
     546           3 :     int nResult = -1;
     547             : 
     548           3 :     if (sqlite3_get_table(m_poDS->GetDB(), pszSQL, &papszResult, &nColCount,
     549           3 :                           &nRowCount, &pszErrMsg) != SQLITE_OK)
     550           0 :         return -1;
     551             : 
     552           3 :     if (nRowCount == 1 && nColCount == 1)
     553           3 :         nResult = atoi(papszResult[1]);
     554             : 
     555           3 :     sqlite3_free_table(papszResult);
     556             : 
     557           3 :     return nResult;
     558             : }

Generated by: LCOV version 1.14