LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/sqlite - ogrsqliteselectlayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 315 335 94.0 %
Date: 2025-02-18 14:19:29 Functions: 22 22 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implements OGRSQLiteSelectLayer class, layer access to the results
       5             :  *           of a SELECT statement executed via ExecuteSQL().
       6             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2004, Frank Warmerdam
      10             :  * Copyright (c) 2010-2014, Even Rouault <even dot rouault at spatialys.com>
      11             :  *
      12             :  * SPDX-License-Identifier: MIT
      13             :  ****************************************************************************/
      14             : 
      15             : #include "cpl_port.h"
      16             : #include "ogr_sqlite.h"
      17             : 
      18             : #include <cstddef>
      19             : #include <cstdlib>
      20             : #include <cstring>
      21             : #include <set>
      22             : #include <string>
      23             : #include <utility>
      24             : 
      25             : #include "cpl_conv.h"
      26             : #include "cpl_error.h"
      27             : #include "cpl_string.h"
      28             : #include "ogr_core.h"
      29             : #include "ogr_feature.h"
      30             : #include "ogr_geometry.h"
      31             : #include "ogr_p.h"
      32             : #include "ogr_spatialref.h"
      33             : #include "ogrsf_frmts.h"
      34             : #include "sqlite3.h"
      35             : #include "ogr_swq.h"
      36             : 
      37             : /************************************************************************/
      38             : /*                   OGRSQLiteSelectLayerCommonBehaviour()              */
      39             : /************************************************************************/
      40             : 
      41        2344 : OGRSQLiteSelectLayerCommonBehaviour::OGRSQLiteSelectLayerCommonBehaviour(
      42             :     OGRSQLiteBaseDataSource *poDSIn, IOGRSQLiteSelectLayer *m_poLayerIn,
      43        2344 :     const CPLString &osSQLIn, bool bEmptyLayerIn)
      44             :     : m_poDS(poDSIn), m_poLayer(m_poLayerIn), m_osSQLBase(osSQLIn),
      45        2344 :       m_bEmptyLayer(bEmptyLayerIn), m_osSQLCurrent(osSQLIn)
      46             : {
      47        2344 : }
      48             : 
      49             : /************************************************************************/
      50             : /*                        OGRSQLiteSelectLayer()                        */
      51             : /************************************************************************/
      52             : 
      53        1580 : OGRSQLiteSelectLayer::OGRSQLiteSelectLayer(
      54             :     OGRSQLiteDataSource *poDSIn, const CPLString &osSQLIn,
      55             :     sqlite3_stmt *m_hStmtIn, bool bUseStatementForGetNextFeature,
      56        1580 :     bool bEmptyLayer, bool bAllowMultipleGeomFieldsIn, bool bCanReopenBaseDS)
      57             :     : OGRSQLiteLayer(poDSIn),
      58             :       m_poBehavior(new OGRSQLiteSelectLayerCommonBehaviour(
      59        1580 :           poDSIn, this, osSQLIn, bEmptyLayer)),
      60        1580 :       m_bCanReopenBaseDS(bCanReopenBaseDS)
      61             : {
      62        1580 :     m_bAllowMultipleGeomFields = bAllowMultipleGeomFieldsIn;
      63             : 
      64        3160 :     std::set<CPLString> aosEmpty;
      65        1580 :     BuildFeatureDefn("SELECT", true, m_hStmtIn, nullptr, aosEmpty);
      66        1580 :     SetDescription("SELECT");
      67             : 
      68        1580 :     if (bUseStatementForGetNextFeature)
      69             :     {
      70        1234 :         m_hStmt = m_hStmtIn;
      71        1234 :         m_bDoStep = false;
      72             : 
      73             :         // Try to extract SRS from first geometry
      74        1532 :         for (int iField = 0;
      75        1532 :              !bEmptyLayer && iField < m_poFeatureDefn->GetGeomFieldCount();
      76             :              iField++)
      77             :         {
      78             :             OGRSQLiteGeomFieldDefn *poGeomFieldDefn =
      79         298 :                 m_poFeatureDefn->myGetGeomFieldDefn(iField);
      80         298 :             if (wkbFlatten(poGeomFieldDefn->GetType()) != wkbUnknown)
      81          16 :                 continue;
      82             :             const auto nColType =
      83         282 :                 sqlite3_column_type(m_hStmt, poGeomFieldDefn->m_iCol);
      84         282 :             if (nColType == SQLITE_BLOB)
      85             :             {
      86             :                 // Is it a Spatialite geometry ?
      87             :                 const GByte *pabyBlob = reinterpret_cast<const GByte *>(
      88         171 :                     sqlite3_column_blob(m_hStmt, poGeomFieldDefn->m_iCol));
      89         171 :                 if (sqlite3_column_bytes(m_hStmt, poGeomFieldDefn->m_iCol) >
      90         163 :                         39 &&
      91         163 :                     pabyBlob[0] == 0x00 &&
      92         492 :                     (pabyBlob[1] == wkbNDR || pabyBlob[1] == wkbXDR) &&
      93         158 :                     pabyBlob[38] == 0x7C)
      94             :                 {
      95         158 :                     const int eByteOrder = pabyBlob[1];
      96         158 :                     int nSRSId = 0;
      97         158 :                     memcpy(&nSRSId, pabyBlob + 2, 4);
      98             : #ifdef CPL_LSB
      99         158 :                     if (eByteOrder != wkbNDR)
     100           0 :                         CPL_SWAP32PTR(&nSRSId);
     101             : #else
     102             :                     if (eByteOrder == wkbNDR)
     103             :                         CPL_SWAP32PTR(&nSRSId);
     104             : #endif
     105         158 :                     CPLPushErrorHandler(CPLQuietErrorHandler);
     106         158 :                     OGRSpatialReference *poSRS = m_poDS->FetchSRS(nSRSId);
     107         158 :                     CPLPopErrorHandler();
     108         158 :                     if (poSRS != nullptr)
     109             :                     {
     110         100 :                         poGeomFieldDefn->m_nSRSId = nSRSId;
     111         100 :                         poGeomFieldDefn->SetSpatialRef(poSRS);
     112             :                     }
     113             :                     else
     114          58 :                         CPLErrorReset();
     115             : 
     116         158 :                     continue;
     117             :                 }
     118             :             }
     119             : 
     120             : #ifdef SQLITE_HAS_COLUMN_METADATA
     121         124 :             if (iField == 0 &&
     122          14 :                 (nColType == SQLITE_NULL || nColType == SQLITE_BLOB))
     123             :             {
     124             :                 const char *pszTableName =
     125         123 :                     sqlite3_column_table_name(m_hStmt, poGeomFieldDefn->m_iCol);
     126         123 :                 if (pszTableName != nullptr)
     127             :                 {
     128             :                     CPLErrorStateBackuper oErrorStateBackuper(
     129         230 :                         CPLQuietErrorHandler);
     130             :                     OGRSQLiteLayer *m_poLayer =
     131         115 :                         cpl::down_cast<OGRSQLiteLayer *>(
     132         115 :                             m_poDS->GetLayerByName(pszTableName));
     133         230 :                     if (m_poLayer != nullptr &&
     134         115 :                         m_poLayer->GetLayerDefn()->GetGeomFieldCount() > 0)
     135             :                     {
     136             :                         OGRSQLiteGeomFieldDefn *poSrcGFldDefn =
     137          13 :                             m_poLayer->myGetLayerDefn()->myGetGeomFieldDefn(0);
     138          13 :                         poGeomFieldDefn->m_nSRSId = poSrcGFldDefn->m_nSRSId;
     139          13 :                         poGeomFieldDefn->SetSpatialRef(
     140          13 :                             poSrcGFldDefn->GetSpatialRef());
     141             :                     }
     142             :                 }
     143             :             }
     144             : #endif
     145             :         }
     146             :     }
     147             :     else
     148         346 :         sqlite3_finalize(m_hStmtIn);
     149        1580 : }
     150             : 
     151             : /************************************************************************/
     152             : /*                       ~OGRSQLiteSelectLayer()                        */
     153             : /************************************************************************/
     154             : 
     155        2562 : OGRSQLiteSelectLayer::~OGRSQLiteSelectLayer()
     156             : {
     157        1579 :     delete m_poBehavior;
     158        2562 : }
     159             : 
     160             : /************************************************************************/
     161             : /*                            ResetReading()                            */
     162             : /************************************************************************/
     163             : 
     164         343 : void OGRSQLiteSelectLayer::ResetReading()
     165             : {
     166         343 :     return m_poBehavior->ResetReading();
     167             : }
     168             : 
     169         806 : void OGRSQLiteSelectLayerCommonBehaviour::ResetReading()
     170             : {
     171         806 :     if (m_poLayer->HasReadFeature() || m_bAllowResetReadingEvenIfIndexAtZero)
     172             :     {
     173         490 :         m_poLayer->BaseResetReading();
     174         490 :         m_bAllowResetReadingEvenIfIndexAtZero = false;
     175             :     }
     176         806 : }
     177             : 
     178             : /************************************************************************/
     179             : /*                           GetNextFeature()                           */
     180             : /************************************************************************/
     181             : 
     182        3467 : OGRFeature *OGRSQLiteSelectLayer::GetNextFeature()
     183             : {
     184        3467 :     return m_poBehavior->GetNextFeature();
     185             : }
     186             : 
     187        5460 : OGRFeature *OGRSQLiteSelectLayerCommonBehaviour::GetNextFeature()
     188             : {
     189        5460 :     if (m_bEmptyLayer)
     190         286 :         return nullptr;
     191             : 
     192        5174 :     return m_poLayer->BaseGetNextFeature();
     193             : }
     194             : 
     195             : /************************************************************************/
     196             : /*               OGRGenSQLResultsLayerHasSpecialField()                 */
     197             : /************************************************************************/
     198             : 
     199         287 : static int HasSpecialFields(swq_expr_node *expr, int nMinIndexForSpecialField)
     200             : {
     201         287 :     if (expr->eNodeType == SNT_COLUMN)
     202             :     {
     203          84 :         if (expr->table_index == 0)
     204             :         {
     205          85 :             return expr->field_index >= nMinIndexForSpecialField &&
     206           1 :                    expr->field_index <
     207          85 :                        nMinIndexForSpecialField + SPECIAL_FIELD_COUNT;
     208             :         }
     209             :     }
     210         203 :     else if (expr->eNodeType == SNT_OPERATION)
     211             :     {
     212         286 :         for (int i = 0; i < expr->nSubExprCount; i++)
     213             :         {
     214         191 :             if (HasSpecialFields(expr->papoSubExpr[i],
     215         191 :                                  nMinIndexForSpecialField))
     216           1 :                 return TRUE;
     217             :         }
     218             :     }
     219         202 :     return FALSE;
     220             : }
     221             : 
     222             : /************************************************************************/
     223             : /*                         SetAttributeFilter()                         */
     224             : /************************************************************************/
     225             : 
     226         205 : OGRErr OGRSQLiteSelectLayer::SetAttributeFilter(const char *pszQuery)
     227             : {
     228         205 :     return m_poBehavior->SetAttributeFilter(pszQuery);
     229             : }
     230             : 
     231             : OGRErr
     232         239 : OGRSQLiteSelectLayerCommonBehaviour::SetAttributeFilter(const char *pszQuery)
     233             : 
     234             : {
     235         239 :     char *&m_pszAttrQuertyString = m_poLayer->GetAttrQueryString();
     236         239 :     if (m_pszAttrQuertyString == nullptr && pszQuery == nullptr)
     237          55 :         return OGRERR_NONE;
     238             : 
     239         184 :     CPLFree(m_pszAttrQuertyString);
     240         184 :     m_pszAttrQuertyString = (pszQuery) ? CPLStrdup(pszQuery) : nullptr;
     241             : 
     242         184 :     m_bAllowResetReadingEvenIfIndexAtZero = true;
     243             : 
     244         368 :     OGRFeatureQuery oQuery;
     245             : 
     246         184 :     CPLPushErrorHandler(CPLQuietErrorHandler);
     247             :     const bool bHasSpecialFields =
     248          96 :         (pszQuery != nullptr && pszQuery[0] != '\0' &&
     249         376 :          oQuery.Compile(m_poLayer->GetLayerDefn(), pszQuery) == OGRERR_NONE &&
     250          96 :          HasSpecialFields(static_cast<swq_expr_node *>(oQuery.GetSWQExpr()),
     251          96 :                           m_poLayer->GetLayerDefn()->GetFieldCount()));
     252         184 :     CPLPopErrorHandler();
     253             : 
     254         184 :     if (bHasSpecialFields || !BuildSQL())
     255             :     {
     256           2 :         return m_poLayer->BaseSetAttributeFilter(pszQuery);
     257             :     }
     258             : 
     259         182 :     ResetReading();
     260             : 
     261         182 :     return OGRERR_NONE;
     262             : }
     263             : 
     264             : /************************************************************************/
     265             : /*                           GetNextFeature()                           */
     266             : /************************************************************************/
     267             : 
     268         185 : GIntBig OGRSQLiteSelectLayer::GetFeatureCount(int bForce)
     269             : {
     270         185 :     return m_poBehavior->GetFeatureCount(bForce);
     271             : }
     272             : 
     273         449 : GIntBig OGRSQLiteSelectLayerCommonBehaviour::GetFeatureCount(int bForce)
     274             : {
     275         449 :     if (m_bEmptyLayer)
     276         120 :         return 0;
     277             : 
     278         329 :     if (m_poLayer->GetFeatureQuery() == nullptr &&
     279         329 :         STARTS_WITH_CI(m_osSQLCurrent, "SELECT COUNT(*) FROM") &&
     280           2 :         m_osSQLCurrent.ifind(" GROUP BY ") == std::string::npos &&
     281           2 :         m_osSQLCurrent.ifind(" UNION ") == std::string::npos &&
     282         660 :         m_osSQLCurrent.ifind(" INTERSECT ") == std::string::npos &&
     283           2 :         m_osSQLCurrent.ifind(" EXCEPT ") == std::string::npos)
     284           2 :         return 1;
     285             : 
     286         327 :     if (m_poLayer->GetFeatureQuery() != nullptr ||
     287         650 :         (m_poLayer->GetFilterGeom() != nullptr && !m_bSpatialFilterInSQL) ||
     288         323 :         STARTS_WITH_CI(m_osSQLCurrent.c_str(), "PRAGMA table_info("))
     289             :     {
     290           5 :         return m_poLayer->BaseGetFeatureCount(bForce);
     291             :     }
     292             : 
     293         644 :     CPLString osFeatureCountSQL("SELECT COUNT(*) FROM (");
     294         322 :     osFeatureCountSQL += m_osSQLCurrent;
     295         322 :     osFeatureCountSQL += ")";
     296             : 
     297         322 :     CPLDebug("SQLITE", "Running %s", osFeatureCountSQL.c_str());
     298             : 
     299             :     /* -------------------------------------------------------------------- */
     300             :     /*      Execute.                                                        */
     301             :     /* -------------------------------------------------------------------- */
     302         322 :     char *pszErrMsg = nullptr;
     303         322 :     char **papszResult = nullptr;
     304         322 :     int nRowCount = 0;
     305         322 :     int nColCount = 0;
     306         322 :     int nResult = -1;
     307             : 
     308         322 :     if (sqlite3_get_table(m_poDS->GetDB(), osFeatureCountSQL, &papszResult,
     309         322 :                           &nRowCount, &nColCount, &pszErrMsg) != SQLITE_OK)
     310             :     {
     311          43 :         CPLDebug("SQLITE", "Error: %s", pszErrMsg);
     312          43 :         sqlite3_free(pszErrMsg);
     313          43 :         return m_poLayer->BaseGetFeatureCount(bForce);
     314             :     }
     315             : 
     316         279 :     if (nRowCount == 1 && nColCount == 1)
     317             :     {
     318         279 :         nResult = atoi(papszResult[1]);
     319             :     }
     320             : 
     321         279 :     sqlite3_free_table(papszResult);
     322             : 
     323         279 :     return nResult;
     324             : }
     325             : 
     326             : /************************************************************************/
     327             : /*                           ResetStatement()                           */
     328             : /************************************************************************/
     329             : 
     330         237 : OGRErr OGRSQLiteSelectLayer::ResetStatement()
     331             : 
     332             : {
     333         237 :     ClearStatement();
     334             : 
     335         237 :     m_iNextShapeId = 0;
     336         237 :     m_bDoStep = true;
     337             : 
     338             : #ifdef DEBUG
     339         237 :     CPLDebug("OGR_SQLITE", "prepare_v2(%s)",
     340         237 :              m_poBehavior->m_osSQLCurrent.c_str());
     341             : #endif
     342             : 
     343         237 :     const int rc = sqlite3_prepare_v2(
     344         237 :         m_poDS->GetDB(), m_poBehavior->m_osSQLCurrent,
     345         237 :         static_cast<int>(m_poBehavior->m_osSQLCurrent.size()), &m_hStmt,
     346             :         nullptr);
     347             : 
     348         237 :     if (rc == SQLITE_OK)
     349         237 :         return OGRERR_NONE;
     350             : 
     351           0 :     CPLError(CE_Failure, CPLE_AppDefined,
     352             :              "In ResetStatement(): sqlite3_prepare_v2(%s):\n  %s",
     353           0 :              m_poBehavior->m_osSQLCurrent.c_str(),
     354           0 :              sqlite3_errmsg(m_poDS->GetDB()));
     355           0 :     m_hStmt = nullptr;
     356           0 :     return OGRERR_FAILURE;
     357             : }
     358             : 
     359             : /************************************************************************/
     360             : /*                          ISetSpatialFilter()                         */
     361             : /************************************************************************/
     362             : 
     363         165 : OGRErr OGRSQLiteSelectLayer::ISetSpatialFilter(int iGeomField,
     364             :                                                const OGRGeometry *poGeomIn)
     365             : 
     366             : {
     367         165 :     if (!m_bCanReopenBaseDS && iGeomField == 0)
     368             :     {
     369           2 :         if (!ValidateGeometryFieldIndexForSetSpatialFilter(iGeomField, poGeomIn,
     370           2 :                                                            true))
     371           0 :             return OGRERR_FAILURE;
     372             :         // For a Memory datasource, short-circuit
     373             :         // OGRSQLiteExecuteSQL::SetSpatialFilter()
     374             :         // that would try to re-open the Memory datasource, which would fail.
     375           2 :         return OGRLayer::ISetSpatialFilter(iGeomField, poGeomIn);
     376             :     }
     377             :     else
     378             :     {
     379         163 :         return m_poBehavior->SetSpatialFilter(iGeomField, poGeomIn);
     380             :     }
     381             : }
     382             : 
     383         208 : OGRErr OGRSQLiteSelectLayerCommonBehaviour::SetSpatialFilter(
     384             :     int iGeomField, const OGRGeometry *poGeomIn)
     385             : 
     386             : {
     387         208 :     m_bAllowResetReadingEvenIfIndexAtZero = true;
     388             : 
     389         208 :     int &iGeomFieldFilter = m_poLayer->GetIGeomFieldFilter();
     390         208 :     iGeomFieldFilter = iGeomField;
     391         208 :     if (m_poLayer->InstallFilter(poGeomIn))
     392             :     {
     393         147 :         BuildSQL();
     394             : 
     395         147 :         ResetReading();
     396             :     }
     397             : 
     398         208 :     return OGRERR_NONE;
     399             : }
     400             : 
     401             : /************************************************************************/
     402             : /*                            GetBaseLayer()                            */
     403             : /************************************************************************/
     404             : 
     405             : std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *>
     406         340 : OGRSQLiteSelectLayerCommonBehaviour::GetBaseLayer(size_t &i)
     407             : {
     408         340 :     char **papszTokens = CSLTokenizeString(m_osSQLBase.c_str());
     409         340 :     bool bCanInsertFilter = true;
     410         340 :     int nCountSelect = 0, nCountFrom = 0, nCountWhere = 0;
     411             : 
     412        2427 :     for (int iToken = 0; papszTokens[iToken] != nullptr; iToken++)
     413             :     {
     414        2087 :         if (EQUAL(papszTokens[iToken], "SELECT"))
     415         341 :             nCountSelect++;
     416        1746 :         else if (EQUAL(papszTokens[iToken], "FROM"))
     417         341 :             nCountFrom++;
     418        1405 :         else if (EQUAL(papszTokens[iToken], "WHERE"))
     419         121 :             nCountWhere++;
     420        1284 :         else if (EQUAL(papszTokens[iToken], "UNION") ||
     421        1283 :                  EQUAL(papszTokens[iToken], "JOIN") ||
     422        1283 :                  EQUAL(papszTokens[iToken], "INTERSECT") ||
     423        1283 :                  EQUAL(papszTokens[iToken], "EXCEPT"))
     424             :         {
     425           1 :             bCanInsertFilter = false;
     426             :         }
     427             :     }
     428         340 :     CSLDestroy(papszTokens);
     429             : 
     430         340 :     if (!(bCanInsertFilter && nCountSelect == 1 && nCountFrom == 1 &&
     431             :           nCountWhere <= 1))
     432             :     {
     433           1 :         CPLDebug("SQLITE", "SQL expression too complex to analyse");
     434           1 :         return std::pair(nullptr, nullptr);
     435             :     }
     436             : 
     437         339 :     size_t nFromPos = m_osSQLBase.ifind(" from ");
     438         339 :     if (nFromPos == std::string::npos)
     439             :     {
     440           0 :         return std::pair(nullptr, nullptr);
     441             :     }
     442             : 
     443             :     /* Remove potential quotes around layer name */
     444         339 :     char chFirst = m_osSQLBase[nFromPos + 6];
     445         339 :     bool bInQuotes = (chFirst == '\'' || chFirst == '"');
     446         678 :     CPLString osBaseLayerName;
     447        2184 :     for (i = nFromPos + 6 + (bInQuotes ? 1 : 0); i < m_osSQLBase.size(); i++)
     448             :     {
     449        2060 :         if (m_osSQLBase[i] == chFirst && bInQuotes)
     450             :         {
     451           9 :             if (i + 1 < m_osSQLBase.size() && m_osSQLBase[i + 1] == chFirst)
     452             :             {
     453           1 :                 osBaseLayerName += m_osSQLBase[i];
     454           1 :                 i++;
     455             :             }
     456             :             else
     457             :             {
     458           8 :                 i++;
     459           8 :                 break;
     460             :             }
     461             :         }
     462        2051 :         else if (m_osSQLBase[i] == ' ' && !bInQuotes)
     463         207 :             break;
     464             :         else
     465        1844 :             osBaseLayerName += m_osSQLBase[i];
     466             :     }
     467             : 
     468         339 :     std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *> oPair;
     469         678 :     if (strchr(osBaseLayerName, '(') == nullptr &&
     470         339 :         m_poLayer->GetLayerDefn()->GetGeomFieldCount() != 0)
     471             :     {
     472         336 :         CPLString osNewUnderlyingTableName;
     473             :         osNewUnderlyingTableName.Printf(
     474             :             "%s(%s)", osBaseLayerName.c_str(),
     475         336 :             m_poLayer->GetLayerDefn()->GetGeomFieldDefn(0)->GetNameRef());
     476             :         oPair =
     477         336 :             m_poDS->GetLayerWithGetSpatialWhereByName(osNewUnderlyingTableName);
     478             :     }
     479         339 :     if (oPair.first == nullptr)
     480         338 :         oPair = m_poDS->GetLayerWithGetSpatialWhereByName(osBaseLayerName);
     481             : 
     482         339 :     if (oPair.first != nullptr && m_poLayer->GetSpatialRef() != nullptr &&
     483          63 :         oPair.first->GetSpatialRef() != nullptr &&
     484         708 :         m_poLayer->GetSpatialRef() != oPair.first->GetSpatialRef() &&
     485          30 :         !m_poLayer->GetSpatialRef()->IsSame(oPair.first->GetSpatialRef()))
     486             :     {
     487           0 :         CPLDebug("SQLITE",
     488             :                  "Result layer and base layer don't have the same SRS.");
     489           0 :         return std::pair(nullptr, nullptr);
     490             :     }
     491             : 
     492         339 :     return oPair;
     493             : }
     494             : 
     495             : /************************************************************************/
     496             : /*                             BuildSQL()                               */
     497             : /************************************************************************/
     498             : 
     499         330 : int OGRSQLiteSelectLayerCommonBehaviour::BuildSQL()
     500             : 
     501             : {
     502         330 :     m_osSQLCurrent = m_osSQLBase;
     503         330 :     m_bSpatialFilterInSQL = true;
     504             : 
     505         330 :     size_t i = 0;
     506         330 :     std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *> oPair = GetBaseLayer(i);
     507         330 :     OGRLayer *poBaseLayer = oPair.first;
     508         330 :     if (poBaseLayer == nullptr)
     509             :     {
     510           1 :         CPLDebug("SQLITE", "Cannot find base layer");
     511           1 :         m_bSpatialFilterInSQL = false;
     512           1 :         return FALSE;
     513             :     }
     514             : 
     515         658 :     CPLString osSpatialWhere;
     516         329 :     if (m_poLayer->GetFilterGeom() != nullptr)
     517             :     {
     518             :         const char *pszGeomCol =
     519         127 :             m_poLayer->GetLayerDefn()
     520         127 :                 ->GetGeomFieldDefn(m_poLayer->GetIGeomFieldFilter())
     521         127 :                 ->GetNameRef();
     522         127 :         int nIdx = poBaseLayer->GetLayerDefn()->GetGeomFieldIndex(pszGeomCol);
     523         127 :         if (nIdx < 0)
     524             :         {
     525           0 :             CPLDebug("SQLITE", "Cannot find field %s in base layer",
     526             :                      pszGeomCol);
     527           0 :             m_bSpatialFilterInSQL = false;
     528             :         }
     529             :         else
     530             :         {
     531             :             osSpatialWhere =
     532         127 :                 oPair.second->GetSpatialWhere(nIdx, m_poLayer->GetFilterGeom());
     533         127 :             if (osSpatialWhere.empty())
     534             :             {
     535          51 :                 CPLDebug("SQLITE", "Cannot get spatial where clause");
     536          51 :                 m_bSpatialFilterInSQL = false;
     537             :             }
     538             :         }
     539             :     }
     540             : 
     541         658 :     CPLString osCustomWhere;
     542         329 :     if (!osSpatialWhere.empty())
     543             :     {
     544          76 :         osCustomWhere = osSpatialWhere;
     545             :     }
     546         455 :     if (m_poLayer->GetAttrQueryString() != nullptr &&
     547         126 :         m_poLayer->GetAttrQueryString()[0] != '\0')
     548             :     {
     549         126 :         if (!osSpatialWhere.empty())
     550          20 :             osCustomWhere += " AND (";
     551         126 :         osCustomWhere += m_poLayer->GetAttrQueryString();
     552         126 :         if (!osSpatialWhere.empty())
     553          20 :             osCustomWhere += ")";
     554             :     }
     555             : 
     556             :     /* Nothing to do */
     557         329 :     if (osCustomWhere.empty())
     558         147 :         return TRUE;
     559             : 
     560         293 :     while (i < m_osSQLBase.size() && m_osSQLBase[i] == ' ')
     561         111 :         i++;
     562             : 
     563         293 :     if (i < m_osSQLBase.size() &&
     564         111 :         STARTS_WITH_CI(m_osSQLBase.c_str() + i, "WHERE "))
     565             :     {
     566          65 :         m_osSQLCurrent = m_osSQLBase.substr(0, i + 6);
     567          65 :         m_osSQLCurrent += osCustomWhere;
     568          65 :         m_osSQLCurrent += " AND (";
     569             : 
     570          65 :         size_t nEndOfWhere = m_osSQLBase.ifind(" GROUP ");
     571          65 :         if (nEndOfWhere == std::string::npos)
     572          50 :             nEndOfWhere = m_osSQLBase.ifind(" ORDER ");
     573          65 :         if (nEndOfWhere == std::string::npos)
     574          34 :             nEndOfWhere = m_osSQLBase.ifind(" LIMIT ");
     575             : 
     576          65 :         if (nEndOfWhere == std::string::npos)
     577             :         {
     578          19 :             m_osSQLCurrent += m_osSQLBase.substr(i + 6);
     579          19 :             m_osSQLCurrent += ")";
     580             :         }
     581             :         else
     582             :         {
     583          46 :             m_osSQLCurrent += m_osSQLBase.substr(i + 6, nEndOfWhere - (i + 6));
     584          46 :             m_osSQLCurrent += ")";
     585          46 :             m_osSQLCurrent += m_osSQLBase.substr(nEndOfWhere);
     586             :         }
     587             :     }
     588         163 :     else if (i < m_osSQLBase.size() &&
     589          46 :              (STARTS_WITH_CI(m_osSQLBase.c_str() + i, "GROUP ") ||
     590          31 :               STARTS_WITH_CI(m_osSQLBase.c_str() + i, "ORDER ") ||
     591          15 :               STARTS_WITH_CI(m_osSQLBase.c_str() + i, "LIMIT ")))
     592             :     {
     593          46 :         m_osSQLCurrent = m_osSQLBase.substr(0, i);
     594          46 :         m_osSQLCurrent += " WHERE ";
     595          46 :         m_osSQLCurrent += osCustomWhere;
     596          46 :         m_osSQLCurrent += " ";
     597          46 :         m_osSQLCurrent += m_osSQLBase.substr(i);
     598             :     }
     599          71 :     else if (i == m_osSQLBase.size())
     600             :     {
     601          71 :         m_osSQLCurrent = m_osSQLBase.substr(0, i);
     602          71 :         m_osSQLCurrent += " WHERE ";
     603          71 :         m_osSQLCurrent += osCustomWhere;
     604             :     }
     605             :     else
     606             :     {
     607           0 :         CPLDebug("SQLITE", "SQL expression too complex for the driver to "
     608             :                            "insert attribute and/or spatial filter in it");
     609           0 :         m_bSpatialFilterInSQL = false;
     610           0 :         return FALSE;
     611             :     }
     612             : 
     613         182 :     return TRUE;
     614             : }
     615             : 
     616             : /************************************************************************/
     617             : /*                           TestCapability()                           */
     618             : /************************************************************************/
     619             : 
     620          59 : int OGRSQLiteSelectLayer::TestCapability(const char *pszCap)
     621             : {
     622          59 :     return m_poBehavior->TestCapability(pszCap);
     623             : }
     624             : 
     625          85 : int OGRSQLiteSelectLayerCommonBehaviour::TestCapability(const char *pszCap)
     626             : 
     627             : {
     628          85 :     if (EQUAL(pszCap, OLCFastSpatialFilter))
     629             :     {
     630          10 :         size_t i = 0;
     631          10 :         const auto oPair = GetBaseLayer(i);
     632          10 :         if (oPair.first == nullptr)
     633             :         {
     634           0 :             CPLDebug("SQLITE", "Cannot find base layer");
     635           0 :             return FALSE;
     636             :         }
     637             : 
     638          10 :         return oPair.second->HasFastSpatialFilter(0);
     639             :     }
     640             :     else
     641          75 :         return m_poLayer->BaseTestCapability(pszCap);
     642             : }
     643             : 
     644             : /************************************************************************/
     645             : /*                             GetExtent()                              */
     646             : /************************************************************************/
     647             : 
     648          14 : OGRErr OGRSQLiteSelectLayer::IGetExtent(int iGeomField, OGREnvelope *psExtent,
     649             :                                         bool bForce)
     650             : {
     651          14 :     return m_poBehavior->GetExtent(iGeomField, psExtent, bForce);
     652             : }
     653             : 
     654          16 : OGRErr OGRSQLiteSelectLayerCommonBehaviour::GetExtent(int iGeomField,
     655             :                                                       OGREnvelope *psExtent,
     656             :                                                       bool bForce)
     657             : {
     658          32 :     if (iGeomField < 0 ||
     659          32 :         iGeomField >= m_poLayer->GetLayerDefn()->GetGeomFieldCount() ||
     660          16 :         m_poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() ==
     661             :             wkbNone)
     662             :     {
     663           0 :         if (iGeomField != 0)
     664             :         {
     665           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     666             :                      "Invalid geometry field index : %d", iGeomField);
     667             :         }
     668           0 :         return OGRERR_FAILURE;
     669             :     }
     670             : 
     671             :     /* Caching of extent by SQL string is interesting to speed-up the */
     672             :     /* establishment of the WFS GetCapabilities document for a MapServer mapfile
     673             :      */
     674             :     /* which has several layers, only differing by scale rules */
     675          16 :     if (iGeomField == 0)
     676             :     {
     677             :         const OGREnvelope *psCachedExtent =
     678          16 :             m_poDS->GetEnvelopeFromSQL(m_osSQLBase);
     679          16 :         if (psCachedExtent)
     680             :         {
     681           5 :             *psExtent = *psCachedExtent;
     682           5 :             return OGRERR_NONE;
     683             :         }
     684             :     }
     685             : 
     686          22 :     CPLString osSQLCommand = m_osSQLBase;
     687             : 
     688             :     /* ORDER BY are costly to evaluate and are not necessary to establish */
     689             :     /* the layer extent. */
     690          11 :     size_t nOrderByPos = osSQLCommand.ifind(" ORDER BY ");
     691          11 :     if (osSQLCommand.ifind("SELECT ") == 0 &&
     692          11 :         osSQLCommand.ifind("SELECT ", 1) ==
     693          11 :             std::string::npos && /* Ensure there's no sub SELECT that could
     694             :                                     confuse our heuristics */
     695           4 :         nOrderByPos != std::string::npos &&
     696           4 :         osSQLCommand.ifind(" LIMIT ") == std::string::npos &&
     697           4 :         osSQLCommand.ifind(" UNION ") == std::string::npos &&
     698          26 :         osSQLCommand.ifind(" INTERSECT ") == std::string::npos &&
     699           4 :         osSQLCommand.ifind(" EXCEPT ") == std::string::npos)
     700             :     {
     701           4 :         osSQLCommand.resize(nOrderByPos);
     702             : 
     703             :         OGRLayer *poTmpLayer =
     704           4 :             m_poDS->ExecuteSQL(osSQLCommand.c_str(), nullptr, nullptr);
     705           4 :         if (poTmpLayer)
     706             :         {
     707           4 :             OGRErr eErr = poTmpLayer->GetExtent(iGeomField, psExtent, bForce);
     708           4 :             m_poDS->ReleaseResultSet(poTmpLayer);
     709           4 :             return eErr;
     710             :         }
     711             :     }
     712             : 
     713           7 :     OGRErr eErr = m_poLayer->BaseGetExtent(iGeomField, psExtent, bForce);
     714           7 :     if (iGeomField == 0 && eErr == OGRERR_NONE && m_poDS->GetUpdate() == false)
     715           5 :         m_poDS->SetEnvelopeForSQL(m_osSQLBase, *psExtent);
     716           7 :     return eErr;
     717             : }

Generated by: LCOV version 1.14