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

Generated by: LCOV version 1.14