LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/sqlite - ogrsqliteviewlayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 201 159 79.1 %
Date: 2012-12-26 Functions: 20 17 85.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrsqliteviewlayer.cpp 25125 2012-10-14 15:55:27Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRSQLiteViewLayer class, access to an existing spatialite view.
       6                 :  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
      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 "cpl_conv.h"
      31                 : #include "cpl_string.h"
      32                 : #include "ogr_sqlite.h"
      33                 : #include <string>
      34                 : 
      35                 : CPL_CVSID("$Id: ogrsqliteviewlayer.cpp 25125 2012-10-14 15:55:27Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                        OGRSQLiteViewLayer()                         */
      39                 : /************************************************************************/
      40                 : 
      41               5 : OGRSQLiteViewLayer::OGRSQLiteViewLayer( OGRSQLiteDataSource *poDSIn )
      42                 : 
      43                 : {
      44               5 :     poDS = poDSIn;
      45                 : 
      46               5 :     iNextShapeId = 0;
      47                 : 
      48               5 :     poFeatureDefn = NULL;
      49               5 :     pszViewName = NULL;
      50               5 :     pszEscapedTableName = NULL;
      51               5 :     pszEscapedUnderlyingTableName = NULL;
      52                 : 
      53               5 :     bHasCheckedSpatialIndexTable = FALSE;
      54                 : 
      55               5 :     bLayerDefnError = FALSE;
      56               5 : }
      57                 : 
      58                 : /************************************************************************/
      59                 : /*                        ~OGRSQLiteViewLayer()                        */
      60                 : /************************************************************************/
      61                 : 
      62               5 : OGRSQLiteViewLayer::~OGRSQLiteViewLayer()
      63                 : 
      64                 : {
      65               5 :     ClearStatement();
      66               5 :     CPLFree(pszViewName);
      67               5 :     CPLFree(pszEscapedTableName);
      68               5 :     CPLFree(pszEscapedUnderlyingTableName);
      69               5 : }
      70                 : 
      71                 : /************************************************************************/
      72                 : /*                             Initialize()                             */
      73                 : /************************************************************************/
      74                 : 
      75               5 : CPLErr OGRSQLiteViewLayer::Initialize( const char *pszViewName,
      76                 :                                        const char *pszViewGeometry,
      77                 :                                        const char *pszViewRowid,
      78                 :                                        const char *pszUnderlyingTableName,
      79                 :                                        const char *pszUnderlyingGeometryColumn)
      80                 : 
      81                 : {
      82               5 :     this->pszViewName = CPLStrdup(pszViewName);
      83                 : 
      84               5 :     osGeomColumn = pszViewGeometry;
      85               5 :     eGeomFormat = OSGF_SpatiaLite;
      86                 : 
      87               5 :     CPLFree( pszFIDColumn );
      88               5 :     pszFIDColumn = CPLStrdup( pszViewRowid );
      89                 : 
      90              10 :     osUnderlyingTableName = pszUnderlyingTableName;
      91              10 :     osUnderlyingGeometryColumn = pszUnderlyingGeometryColumn;
      92               5 :     poUnderlyingLayer = NULL;
      93                 : 
      94                 :     //this->bHasM = bHasM;
      95                 : 
      96              10 :     pszEscapedTableName = CPLStrdup(OGRSQLiteEscape(pszViewName));
      97              10 :     pszEscapedUnderlyingTableName = CPLStrdup(OGRSQLiteEscape(pszUnderlyingTableName));
      98                 : 
      99               5 :     return CE_None;
     100                 : }
     101                 : 
     102                 : /************************************************************************/
     103                 : /*                           GetLayerDefn()                             */
     104                 : /************************************************************************/
     105                 : 
     106              23 : OGRFeatureDefn* OGRSQLiteViewLayer::GetLayerDefn()
     107                 : {
     108              23 :     if (poFeatureDefn)
     109              19 :         return poFeatureDefn;
     110                 : 
     111               4 :     EstablishFeatureDefn();
     112                 : 
     113               4 :     if (poFeatureDefn == NULL)
     114                 :     {
     115               0 :         bLayerDefnError = TRUE;
     116                 : 
     117               0 :         poFeatureDefn = new OGRFeatureDefn( pszViewName );
     118               0 :         poFeatureDefn->Reference();
     119                 :     }
     120                 : 
     121               4 :     return poFeatureDefn;
     122                 : }
     123                 : 
     124                 : /************************************************************************/
     125                 : /*                        GetUnderlyingLayer()                          */
     126                 : /************************************************************************/
     127                 : 
     128               4 : OGRSQLiteLayer* OGRSQLiteViewLayer::GetUnderlyingLayer()
     129                 : {
     130               4 :     if( poUnderlyingLayer == NULL )
     131                 :     {
     132                 :         poUnderlyingLayer =
     133               4 :             (OGRSQLiteLayer*) poDS->GetLayerByName(osUnderlyingTableName);
     134               4 :         if( poUnderlyingLayer == NULL &&
     135                 :             strchr(osUnderlyingTableName, '(') == NULL )
     136                 :         {
     137               2 :             CPLString osNewUnderlyingTableName;
     138                 :             osNewUnderlyingTableName.Printf("%s(%s)",
     139                 :                                             osUnderlyingTableName.c_str(),
     140               2 :                                             osUnderlyingGeometryColumn.c_str());
     141                 :             poUnderlyingLayer =
     142               2 :                 (OGRSQLiteLayer*) poDS->GetLayerByName(osNewUnderlyingTableName);
     143                 :         }
     144                 :     }
     145               4 :     return poUnderlyingLayer;
     146                 : }
     147                 : 
     148                 : /************************************************************************/
     149                 : /*                            GetGeomType()                             */
     150                 : /************************************************************************/
     151                 : 
     152               3 : OGRwkbGeometryType OGRSQLiteViewLayer::GetGeomType()
     153                 : {
     154               3 :     if (poFeatureDefn)
     155               3 :         return poFeatureDefn->GetGeomType();
     156                 : 
     157               0 :     OGRSQLiteLayer* poUnderlyingLayer = GetUnderlyingLayer();
     158               0 :     if (poUnderlyingLayer)
     159               0 :         return poUnderlyingLayer->GetGeomType();
     160                 : 
     161               0 :     return wkbUnknown;
     162                 : }
     163                 : 
     164                 : /************************************************************************/
     165                 : /*                         EstablishFeatureDefn()                       */
     166                 : /************************************************************************/
     167                 : 
     168               4 : CPLErr OGRSQLiteViewLayer::EstablishFeatureDefn()
     169                 : {
     170                 :     int rc;
     171               4 :     sqlite3 *hDB = poDS->GetDB();
     172               4 :     sqlite3_stmt *hColStmt = NULL;
     173                 :     const char *pszSQL;
     174                 : 
     175               4 :     OGRSQLiteLayer* poUnderlyingLayer = GetUnderlyingLayer();
     176               4 :     if (poUnderlyingLayer == NULL)
     177                 :     {
     178                 :         CPLError(CE_Failure, CPLE_AppDefined,
     179                 :                  "Cannot find underlying layer %s for view %s",
     180               0 :                  osUnderlyingTableName.c_str(), pszViewName);
     181               0 :         return CE_Failure;
     182                 :     }
     183               4 :     if ( !poUnderlyingLayer->IsTableLayer() )
     184                 :     {
     185                 :         CPLError(CE_Failure, CPLE_AppDefined,
     186                 :                  "Underlying layer %s for view %s is not a regular table",
     187               0 :                  osUnderlyingTableName.c_str(), pszViewName);
     188               0 :         return CE_Failure;
     189                 :     }
     190                 : 
     191               4 :     const char* pszRealUnderlyingGeometryColumn = poUnderlyingLayer->GetGeometryColumn();
     192               4 :     if ( pszRealUnderlyingGeometryColumn == NULL ||
     193                 :          !EQUAL(pszRealUnderlyingGeometryColumn, osUnderlyingGeometryColumn.c_str()) )
     194                 :     {
     195                 :         CPLError(CE_Failure, CPLE_AppDefined,
     196                 :                  "Underlying layer %s for view %s has not expected geometry column name (%s instead of %s)",
     197                 :                  osUnderlyingTableName.c_str(), pszViewName,
     198                 :                  pszRealUnderlyingGeometryColumn ? pszRealUnderlyingGeometryColumn : "(null)",
     199               0 :                  osUnderlyingGeometryColumn.c_str());
     200               0 :         return CE_Failure;
     201                 :     }
     202                 : 
     203               4 :     poSRS = poUnderlyingLayer->GetSpatialRef();
     204               4 :     if (poSRS)
     205               4 :         poSRS->Reference();
     206                 : 
     207               4 :     this->bHasSpatialIndex = poUnderlyingLayer->HasSpatialIndex();
     208                 : 
     209                 : /* -------------------------------------------------------------------- */
     210                 : /*      Get the column definitions for this table.                      */
     211                 : /* -------------------------------------------------------------------- */
     212               4 :     hColStmt = NULL;
     213                 :     pszSQL = CPLSPrintf( "SELECT \"%s\", * FROM '%s' LIMIT 1",
     214                 :                          OGRSQLiteEscapeName(pszFIDColumn).c_str(),
     215               4 :                          pszEscapedTableName );
     216                 : 
     217               4 :     rc = sqlite3_prepare( hDB, pszSQL, strlen(pszSQL), &hColStmt, NULL ); 
     218               4 :     if( rc != SQLITE_OK )
     219                 :     {
     220                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     221                 :                   "Unable to query table %s for column definitions : %s.",
     222               0 :                   pszViewName, sqlite3_errmsg(hDB) );
     223                 :         
     224               0 :         return CE_Failure;
     225                 :     }
     226                 : 
     227               4 :     rc = sqlite3_step( hColStmt );
     228               4 :     if ( rc != SQLITE_DONE && rc != SQLITE_ROW )
     229                 :     {
     230                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     231                 :                   "In Initialize(): sqlite3_step(%s):\n  %s", 
     232               0 :                   pszSQL, sqlite3_errmsg(hDB) );
     233               0 :         sqlite3_finalize( hColStmt );
     234               0 :         return CE_Failure;
     235                 :     }
     236                 : 
     237                 : /* -------------------------------------------------------------------- */
     238                 : /*      Collect the rest of the fields.                                 */
     239                 : /* -------------------------------------------------------------------- */
     240               4 :     std::set<CPLString> aosEmpty;
     241               4 :     BuildFeatureDefn( pszViewName, hColStmt, aosEmpty );
     242               4 :     sqlite3_finalize( hColStmt );
     243                 : 
     244                 : /* -------------------------------------------------------------------- */
     245                 : /*      Set the geometry type if we know it.                            */
     246                 : /* -------------------------------------------------------------------- */
     247               4 :     poFeatureDefn->SetGeomType( poUnderlyingLayer->GetGeomType() );
     248                 : 
     249               4 :     return CE_None;
     250                 : }
     251                 : 
     252                 : /************************************************************************/
     253                 : /*                           ResetStatement()                           */
     254                 : /************************************************************************/
     255                 : 
     256               4 : OGRErr OGRSQLiteViewLayer::ResetStatement()
     257                 : 
     258                 : {
     259                 :     int rc;
     260               4 :     CPLString osSQL;
     261                 : 
     262               4 :     ClearStatement();
     263                 : 
     264               4 :     iNextShapeId = 0;
     265                 : 
     266                 :     osSQL.Printf( "SELECT \"%s\", * FROM '%s' %s",
     267                 :                   OGRSQLiteEscapeName(pszFIDColumn).c_str(),
     268                 :                   pszEscapedTableName, 
     269               4 :                   osWHERE.c_str() );
     270                 : 
     271                 :     rc = sqlite3_prepare( poDS->GetDB(), osSQL, osSQL.size(),
     272               4 :               &hStmt, NULL );
     273                 : 
     274               4 :     if( rc == SQLITE_OK )
     275                 :     {
     276               4 :   return OGRERR_NONE;
     277                 :     }
     278                 :     else
     279                 :     {
     280                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     281                 :                   "In ResetStatement(): sqlite3_prepare(%s):\n  %s", 
     282               0 :                   osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
     283               0 :         hStmt = NULL;
     284               0 :         return OGRERR_FAILURE;
     285               0 :     }
     286                 : }
     287                 : 
     288                 : /************************************************************************/
     289                 : /*                           GetSpatialRef()                            */
     290                 : /************************************************************************/
     291                 : 
     292               1 : OGRSpatialReference *OGRSQLiteViewLayer::GetSpatialRef()
     293                 : 
     294                 : {
     295               1 :     if (HasLayerDefnError())
     296               0 :         return NULL;
     297                 : 
     298               1 :     return poSRS;
     299                 : }
     300                 : 
     301                 : /************************************************************************/
     302                 : /*                           GetNextFeature()                           */
     303                 : /************************************************************************/
     304                 : 
     305               4 : OGRFeature *OGRSQLiteViewLayer::GetNextFeature()
     306                 : 
     307                 : {
     308               4 :     if (HasLayerDefnError())
     309               0 :         return NULL;
     310                 : 
     311               4 :     return OGRSQLiteLayer::GetNextFeature();
     312                 : }
     313                 : 
     314                 : /************************************************************************/
     315                 : /*                             GetFeature()                             */
     316                 : /************************************************************************/
     317                 : 
     318               3 : OGRFeature *OGRSQLiteViewLayer::GetFeature( long nFeatureId )
     319                 : 
     320                 : {
     321               3 :     if (HasLayerDefnError())
     322               0 :         return NULL;
     323                 : 
     324                 : /* -------------------------------------------------------------------- */
     325                 : /*      If we don't have an explicit FID column, just read through      */
     326                 : /*      the result set iteratively to find our target.                  */
     327                 : /* -------------------------------------------------------------------- */
     328               3 :     if( pszFIDColumn == NULL )
     329               0 :         return OGRSQLiteLayer::GetFeature( nFeatureId );
     330                 : 
     331                 : /* -------------------------------------------------------------------- */
     332                 : /*      Setup explicit query statement to fetch the record we want.     */
     333                 : /* -------------------------------------------------------------------- */
     334               3 :     CPLString osSQL;
     335                 :     int rc;
     336                 : 
     337               3 :     ClearStatement();
     338                 : 
     339               3 :     iNextShapeId = nFeatureId;
     340                 : 
     341                 :     osSQL.Printf( "SELECT \"%s\", * FROM '%s' WHERE \"%s\" = %d",
     342                 :                   OGRSQLiteEscapeName(pszFIDColumn).c_str(),
     343                 :                   pszEscapedTableName, 
     344                 :                   OGRSQLiteEscapeName(pszFIDColumn).c_str(),
     345               3 :                   (int) nFeatureId );
     346                 : 
     347               3 :     CPLDebug( "OGR_SQLITE", "exec(%s)", osSQL.c_str() );
     348                 : 
     349                 :     rc = sqlite3_prepare( poDS->GetDB(), osSQL, osSQL.size(), 
     350               3 :                           &hStmt, NULL );
     351               3 :     if( rc != SQLITE_OK )
     352                 :     {
     353                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     354                 :                   "In GetFeature(): sqlite3_prepare(%s):\n  %s", 
     355               0 :                   osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
     356                 : 
     357               0 :         return NULL;
     358                 :     }
     359                 : /* -------------------------------------------------------------------- */
     360                 : /*      Get the feature if possible.                                    */
     361                 : /* -------------------------------------------------------------------- */
     362               3 :     OGRFeature *poFeature = NULL;
     363                 : 
     364               3 :     poFeature = GetNextRawFeature();
     365                 : 
     366               3 :     ResetReading();
     367                 : 
     368               3 :     return poFeature;
     369                 : }
     370                 : 
     371                 : /************************************************************************/
     372                 : /*                         SetAttributeFilter()                         */
     373                 : /************************************************************************/
     374                 : 
     375               2 : OGRErr OGRSQLiteViewLayer::SetAttributeFilter( const char *pszQuery )
     376                 : 
     377                 : {
     378               2 :     if( pszQuery == NULL )
     379               0 :         osQuery = "";
     380                 :     else
     381               2 :         osQuery = pszQuery;
     382                 : 
     383               2 :     BuildWhere();
     384                 : 
     385               2 :     ResetReading();
     386                 : 
     387               2 :     return OGRERR_NONE;
     388                 : }
     389                 : 
     390                 : 
     391                 : /************************************************************************/
     392                 : /*                          SetSpatialFilter()                          */
     393                 : /************************************************************************/
     394                 : 
     395               4 : void OGRSQLiteViewLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
     396                 : 
     397                 : {
     398               4 :     if( InstallFilter( poGeomIn ) )
     399                 :     {
     400               4 :         BuildWhere();
     401                 : 
     402               4 :         ResetReading();
     403                 :     }
     404               4 : }
     405                 : 
     406                 : /************************************************************************/
     407                 : /*                           GetSpatialWhere()                          */
     408                 : /************************************************************************/
     409                 : 
     410               6 : CPLString OGRSQLiteViewLayer::GetSpatialWhere(OGRGeometry* poFilterGeom)
     411                 : {
     412               6 :     CPLString osSpatialWHERE;
     413                 : 
     414               6 :     if (HasLayerDefnError())
     415               0 :         return "";
     416                 : 
     417               6 :     if( poFilterGeom != NULL && bHasSpatialIndex )
     418                 :     {
     419               3 :         OGREnvelope  sEnvelope;
     420                 : 
     421               3 :         poFilterGeom->getEnvelope( &sEnvelope );
     422                 : 
     423                 :         /* We first check that the spatial index table exists */
     424               3 :         if (!bHasCheckedSpatialIndexTable)
     425                 :         {
     426               3 :             bHasCheckedSpatialIndexTable = TRUE;
     427                 :             char **papszResult;
     428                 :             int nRowCount, nColCount;
     429               3 :             char *pszErrMsg = NULL;
     430                 : 
     431               3 :             CPLString osSQL;
     432                 :             osSQL.Printf("SELECT name FROM sqlite_master "
     433                 :                         "WHERE name='idx_%s_%s'",
     434                 :                         pszEscapedUnderlyingTableName,
     435               3 :                          OGRSQLiteEscape(osUnderlyingGeometryColumn).c_str());
     436                 : 
     437                 :             int  rc = sqlite3_get_table( poDS->GetDB(), osSQL.c_str(),
     438                 :                                         &papszResult, &nRowCount,
     439               3 :                                         &nColCount, &pszErrMsg );
     440                 : 
     441               3 :             if( rc != SQLITE_OK )
     442                 :             {
     443                 :                 CPLError( CE_Failure, CPLE_AppDefined, "Error: %s",
     444               0 :                         pszErrMsg );
     445               0 :                 sqlite3_free( pszErrMsg );
     446               0 :                 bHasSpatialIndex = FALSE;
     447                 :             }
     448                 :             else
     449                 :             {
     450               3 :                 if (nRowCount != 1)
     451                 :                 {
     452               0 :                     bHasSpatialIndex = FALSE;
     453                 :                 }
     454                 : 
     455               3 :                 sqlite3_free_table(papszResult);
     456               3 :             }
     457                 :         }
     458                 : 
     459               3 :         if (bHasSpatialIndex)
     460                 :         {
     461                 :             osSpatialWHERE.Printf("\"%s\" IN ( SELECT pkid FROM 'idx_%s_%s' WHERE "
     462                 :                            "xmax > %.12f AND xmin < %.12f AND ymax > %.12f AND ymin < %.12f)",
     463                 :                             OGRSQLiteEscapeName(pszFIDColumn).c_str(),
     464                 :                             pszEscapedUnderlyingTableName,
     465                 :                             OGRSQLiteEscape(osUnderlyingGeometryColumn).c_str(),
     466                 :                             sEnvelope.MinX - 1e-11, sEnvelope.MaxX + 1e-11,
     467               3 :                             sEnvelope.MinY - 1e-11, sEnvelope.MaxY + 1e-11);
     468                 :         }
     469                 :         else
     470                 :         {
     471                 :             CPLDebug("SQLITE", "Count not find idx_%s_%s layer. Disabling spatial index",
     472               0 :                      pszEscapedUnderlyingTableName, osUnderlyingGeometryColumn.c_str());
     473                 :         }
     474                 : 
     475                 :     }
     476                 : 
     477               6 :     if( poFilterGeom != NULL && OGRSQLiteIsSpatialiteLoaded() && !bHasSpatialIndex )
     478                 :     {
     479               1 :         OGREnvelope  sEnvelope;
     480                 : 
     481               1 :         poFilterGeom->getEnvelope( &sEnvelope );
     482                 : 
     483                 :         /* A bit inefficient but still faster than OGR filtering */
     484                 :         osSpatialWHERE.Printf("MBRIntersects(\"%s\", BuildMBR(%.12f, %.12f, %.12f, %.12f))",
     485                 :                        OGRSQLiteEscapeName(osGeomColumn).c_str(),
     486                 :                        sEnvelope.MinX - 1e-11, sEnvelope.MinY - 1e-11,
     487               1 :                        sEnvelope.MaxX + 1e-11, sEnvelope.MaxY + 1e-11);
     488                 :     }
     489                 : 
     490               6 :     return osSpatialWHERE;
     491                 : }
     492                 : 
     493                 : /************************************************************************/
     494                 : /*                             BuildWhere()                             */
     495                 : /*                                                                      */
     496                 : /*      Build the WHERE statement appropriate to the current set of     */
     497                 : /*      criteria (spatial and attribute queries).                       */
     498                 : /************************************************************************/
     499                 : 
     500               6 : void OGRSQLiteViewLayer::BuildWhere()
     501                 : 
     502                 : {
     503               6 :     osWHERE = "";
     504                 : 
     505               6 :     CPLString osSpatialWHERE = GetSpatialWhere(m_poFilterGeom);
     506              12 :     if (osSpatialWHERE.size() != 0)
     507                 :     {
     508               4 :         osWHERE = "WHERE ";
     509               4 :         osWHERE += osSpatialWHERE;
     510                 :     }
     511                 : 
     512               6 :     if( osQuery.size() > 0 )
     513                 :     {
     514               4 :         if( osWHERE.size() == 0 )
     515                 :         {
     516               2 :             osWHERE = "WHERE ";
     517               2 :             osWHERE += osQuery;
     518                 :         }
     519                 :         else
     520                 :         {
     521               2 :             osWHERE += " AND (";
     522               2 :             osWHERE += osQuery;
     523               2 :             osWHERE += ")";
     524                 :         }
     525               6 :     }
     526               6 : }
     527                 : 
     528                 : /************************************************************************/
     529                 : /*                           TestCapability()                           */
     530                 : /************************************************************************/
     531                 : 
     532               3 : int OGRSQLiteViewLayer::TestCapability( const char * pszCap )
     533                 : 
     534                 : {
     535               3 :     if (HasLayerDefnError())
     536               0 :         return FALSE;
     537                 : 
     538               3 :     if (EQUAL(pszCap,OLCFastFeatureCount))
     539                 :         return m_poFilterGeom == NULL || osGeomColumn.size() == 0 ||
     540               3 :                bHasSpatialIndex;
     541                 : 
     542               0 :     else if (EQUAL(pszCap,OLCFastSpatialFilter))
     543               0 :         return bHasSpatialIndex;
     544                 : 
     545                 :     else 
     546               0 :         return OGRSQLiteLayer::TestCapability( pszCap );
     547                 : }
     548                 : 
     549                 : /************************************************************************/
     550                 : /*                          GetFeatureCount()                           */
     551                 : /*                                                                      */
     552                 : /*      If a spatial filter is in effect, we turn control over to       */
     553                 : /*      the generic counter.  Otherwise we return the total count.      */
     554                 : /*      Eventually we should consider implementing a more efficient     */
     555                 : /*      way of counting features matching a spatial query.              */
     556                 : /************************************************************************/
     557                 : 
     558               3 : int OGRSQLiteViewLayer::GetFeatureCount( int bForce )
     559                 : 
     560                 : {
     561               3 :     if (HasLayerDefnError())
     562               0 :         return 0;
     563                 : 
     564               3 :     if( !TestCapability(OLCFastFeatureCount) )
     565               0 :         return OGRSQLiteLayer::GetFeatureCount( bForce );
     566                 : 
     567                 : /* -------------------------------------------------------------------- */
     568                 : /*      Form count SQL.                                                 */
     569                 : /* -------------------------------------------------------------------- */
     570                 :     const char *pszSQL;
     571                 : 
     572                 :     pszSQL = CPLSPrintf( "SELECT count(*) FROM '%s' %s",
     573               3 :                           pszEscapedTableName, osWHERE.c_str() );
     574                 : 
     575                 : /* -------------------------------------------------------------------- */
     576                 : /*      Execute.                                                        */
     577                 : /* -------------------------------------------------------------------- */
     578                 :     char **papszResult, *pszErrMsg;
     579                 :     int nRowCount, nColCount;
     580               3 :     int nResult = -1;
     581                 : 
     582               3 :     if( sqlite3_get_table( poDS->GetDB(), pszSQL, &papszResult, 
     583                 :                            &nColCount, &nRowCount, &pszErrMsg ) != SQLITE_OK )
     584               0 :         return -1;
     585                 : 
     586               3 :     if( nRowCount == 1 && nColCount == 1 )
     587               3 :         nResult = atoi(papszResult[1]);
     588                 : 
     589               3 :     sqlite3_free_table( papszResult );
     590                 : 
     591               3 :     return nResult;
     592                 : }

Generated by: LCOV version 1.7