LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/sqlite - ogrsqliteselectlayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 322 339 95.0 %
Date: 2024-11-25 13:07:18 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        2324 : OGRSQLiteSelectLayerCommonBehaviour::OGRSQLiteSelectLayerCommonBehaviour(
      42             :     OGRSQLiteBaseDataSource *poDSIn, IOGRSQLiteSelectLayer *m_poLayerIn,
      43        2324 :     const CPLString &osSQLIn, bool bEmptyLayerIn)
      44             :     : m_poDS(poDSIn), m_poLayer(m_poLayerIn), m_osSQLBase(osSQLIn),
      45        2324 :       m_bEmptyLayer(bEmptyLayerIn), m_osSQLCurrent(osSQLIn)
      46             : {
      47        2324 : }
      48             : 
      49             : /************************************************************************/
      50             : /*                        OGRSQLiteSelectLayer()                        */
      51             : /************************************************************************/
      52             : 
      53        1565 : OGRSQLiteSelectLayer::OGRSQLiteSelectLayer(
      54             :     OGRSQLiteDataSource *poDSIn, const CPLString &osSQLIn,
      55             :     sqlite3_stmt *m_hStmtIn, bool bUseStatementForGetNextFeature,
      56        1565 :     bool bEmptyLayer, bool bAllowMultipleGeomFieldsIn, bool bCanReopenBaseDS)
      57             :     : OGRSQLiteLayer(poDSIn),
      58             :       m_poBehavior(new OGRSQLiteSelectLayerCommonBehaviour(
      59        1565 :           poDSIn, this, osSQLIn, bEmptyLayer)),
      60        1565 :       m_bCanReopenBaseDS(bCanReopenBaseDS)
      61             : {
      62        1565 :     m_bAllowMultipleGeomFields = bAllowMultipleGeomFieldsIn;
      63             : 
      64        3130 :     std::set<CPLString> aosEmpty;
      65        1565 :     BuildFeatureDefn("SELECT", true, m_hStmtIn, nullptr, aosEmpty);
      66        1565 :     SetDescription("SELECT");
      67             : 
      68        1565 :     if (bUseStatementForGetNextFeature)
      69             :     {
      70        1219 :         m_hStmt = m_hStmtIn;
      71        1219 :         m_bDoStep = false;
      72             : 
      73             :         // Try to extract SRS from first geometry
      74        1516 :         for (int iField = 0;
      75        1516 :              !bEmptyLayer && iField < m_poFeatureDefn->GetGeomFieldCount();
      76             :              iField++)
      77             :         {
      78             :             OGRSQLiteGeomFieldDefn *poGeomFieldDefn =
      79         297 :                 m_poFeatureDefn->myGetGeomFieldDefn(iField);
      80         297 :             if (wkbFlatten(poGeomFieldDefn->GetType()) != wkbUnknown)
      81          15 :                 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        1565 : }
     150             : 
     151             : /************************************************************************/
     152             : /*                       ~OGRSQLiteSelectLayer()                        */
     153             : /************************************************************************/
     154             : 
     155        2534 : OGRSQLiteSelectLayer::~OGRSQLiteSelectLayer()
     156             : {
     157        1564 :     delete m_poBehavior;
     158        2534 : }
     159             : 
     160             : /************************************************************************/
     161             : /*                            ResetReading()                            */
     162             : /************************************************************************/
     163             : 
     164         341 : void OGRSQLiteSelectLayer::ResetReading()
     165             : {
     166         341 :     return m_poBehavior->ResetReading();
     167             : }
     168             : 
     169         804 : void OGRSQLiteSelectLayerCommonBehaviour::ResetReading()
     170             : {
     171         804 :     if (m_poLayer->HasReadFeature() || m_bAllowResetReadingEvenIfIndexAtZero)
     172             :     {
     173         490 :         m_poLayer->BaseResetReading();
     174         490 :         m_bAllowResetReadingEvenIfIndexAtZero = false;
     175             :     }
     176         804 : }
     177             : 
     178             : /************************************************************************/
     179             : /*                           GetNextFeature()                           */
     180             : /************************************************************************/
     181             : 
     182        3427 : OGRFeature *OGRSQLiteSelectLayer::GetNextFeature()
     183             : {
     184        3427 :     return m_poBehavior->GetNextFeature();
     185             : }
     186             : 
     187        5418 : OGRFeature *OGRSQLiteSelectLayerCommonBehaviour::GetNextFeature()
     188             : {
     189        5418 :     if (m_bEmptyLayer)
     190         286 :         return nullptr;
     191             : 
     192        5132 :     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         184 : GIntBig OGRSQLiteSelectLayer::GetFeatureCount(int bForce)
     269             : {
     270         184 :     return m_poBehavior->GetFeatureCount(bForce);
     271             : }
     272             : 
     273         445 : GIntBig OGRSQLiteSelectLayerCommonBehaviour::GetFeatureCount(int bForce)
     274             : {
     275         445 :     if (m_bEmptyLayer)
     276         117 :         return 0;
     277             : 
     278         328 :     if (m_poLayer->GetFeatureQuery() == nullptr &&
     279         328 :         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         658 :         m_osSQLCurrent.ifind(" INTERSECT ") == std::string::npos &&
     283           2 :         m_osSQLCurrent.ifind(" EXCEPT ") == std::string::npos)
     284           2 :         return 1;
     285             : 
     286         326 :     if (m_poLayer->GetFeatureQuery() != nullptr ||
     287         648 :         (m_poLayer->GetFilterGeom() != nullptr && !m_bSpatialFilterInSQL) ||
     288         322 :         STARTS_WITH_CI(m_osSQLCurrent.c_str(), "PRAGMA table_info("))
     289             :     {
     290           5 :         return m_poLayer->BaseGetFeatureCount(bForce);
     291             :     }
     292             : 
     293         642 :     CPLString osFeatureCountSQL("SELECT COUNT(*) FROM (");
     294         321 :     osFeatureCountSQL += m_osSQLCurrent;
     295         321 :     osFeatureCountSQL += ")";
     296             : 
     297         321 :     CPLDebug("SQLITE", "Running %s", osFeatureCountSQL.c_str());
     298             : 
     299             :     /* -------------------------------------------------------------------- */
     300             :     /*      Execute.                                                        */
     301             :     /* -------------------------------------------------------------------- */
     302         321 :     char *pszErrMsg = nullptr;
     303         321 :     char **papszResult = nullptr;
     304         321 :     int nRowCount = 0;
     305         321 :     int nColCount = 0;
     306         321 :     int nResult = -1;
     307             : 
     308         321 :     if (sqlite3_get_table(m_poDS->GetDB(), osFeatureCountSQL, &papszResult,
     309         321 :                           &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         278 :     if (nRowCount == 1 && nColCount == 1)
     317             :     {
     318         278 :         nResult = atoi(papszResult[1]);
     319             :     }
     320             : 
     321         278 :     sqlite3_free_table(papszResult);
     322             : 
     323         278 :     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             : /*                          SetSpatialFilter()                          */
     361             : /************************************************************************/
     362             : 
     363         171 : void OGRSQLiteSelectLayer::SetSpatialFilter(int iGeomField,
     364             :                                             OGRGeometry *poGeomIn)
     365             : 
     366             : {
     367         171 :     if (!m_bCanReopenBaseDS && iGeomField == 0)
     368             :     {
     369           3 :         if (!ValidateGeometryFieldIndexForSetSpatialFilter(iGeomField, poGeomIn,
     370           3 :                                                            true))
     371           1 :             return;
     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 :         OGRLayer::SetSpatialFilter(poGeomIn);
     376             :     }
     377             :     else
     378             :     {
     379         168 :         m_poBehavior->SetSpatialFilter(iGeomField, poGeomIn);
     380             :     }
     381             : }
     382             : 
     383         215 : void OGRSQLiteSelectLayerCommonBehaviour::SetSpatialFilter(
     384             :     int iGeomField, OGRGeometry *poGeomIn)
     385             : 
     386             : {
     387         215 :     if (!m_poLayer->ValidateGeometryFieldIndexForSetSpatialFilter(
     388         215 :             iGeomField, poGeomIn, true))
     389           7 :         return;
     390             : 
     391         208 :     m_bAllowResetReadingEvenIfIndexAtZero = true;
     392             : 
     393         208 :     int &iGeomFieldFilter = m_poLayer->GetIGeomFieldFilter();
     394         208 :     iGeomFieldFilter = iGeomField;
     395         208 :     if (m_poLayer->InstallFilter(poGeomIn))
     396             :     {
     397         147 :         BuildSQL();
     398             : 
     399         147 :         ResetReading();
     400             :     }
     401             : }
     402             : 
     403             : /************************************************************************/
     404             : /*                            GetBaseLayer()                            */
     405             : /************************************************************************/
     406             : 
     407             : std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *>
     408         340 : OGRSQLiteSelectLayerCommonBehaviour::GetBaseLayer(size_t &i)
     409             : {
     410         340 :     char **papszTokens = CSLTokenizeString(m_osSQLBase.c_str());
     411         340 :     bool bCanInsertFilter = true;
     412         340 :     int nCountSelect = 0, nCountFrom = 0, nCountWhere = 0;
     413             : 
     414        2427 :     for (int iToken = 0; papszTokens[iToken] != nullptr; iToken++)
     415             :     {
     416        2087 :         if (EQUAL(papszTokens[iToken], "SELECT"))
     417         341 :             nCountSelect++;
     418        1746 :         else if (EQUAL(papszTokens[iToken], "FROM"))
     419         341 :             nCountFrom++;
     420        1405 :         else if (EQUAL(papszTokens[iToken], "WHERE"))
     421         121 :             nCountWhere++;
     422        1284 :         else if (EQUAL(papszTokens[iToken], "UNION") ||
     423        1283 :                  EQUAL(papszTokens[iToken], "JOIN") ||
     424        1283 :                  EQUAL(papszTokens[iToken], "INTERSECT") ||
     425        1283 :                  EQUAL(papszTokens[iToken], "EXCEPT"))
     426             :         {
     427           1 :             bCanInsertFilter = false;
     428             :         }
     429             :     }
     430         340 :     CSLDestroy(papszTokens);
     431             : 
     432         340 :     if (!(bCanInsertFilter && nCountSelect == 1 && nCountFrom == 1 &&
     433             :           nCountWhere <= 1))
     434             :     {
     435           1 :         CPLDebug("SQLITE", "SQL expression too complex to analyse");
     436           1 :         return std::pair(nullptr, nullptr);
     437             :     }
     438             : 
     439         339 :     size_t nFromPos = m_osSQLBase.ifind(" from ");
     440         339 :     if (nFromPos == std::string::npos)
     441             :     {
     442           0 :         return std::pair(nullptr, nullptr);
     443             :     }
     444             : 
     445             :     /* Remove potential quotes around layer name */
     446         339 :     char chFirst = m_osSQLBase[nFromPos + 6];
     447         339 :     bool bInQuotes = (chFirst == '\'' || chFirst == '"');
     448         678 :     CPLString osBaseLayerName;
     449        2184 :     for (i = nFromPos + 6 + (bInQuotes ? 1 : 0); i < m_osSQLBase.size(); i++)
     450             :     {
     451        2060 :         if (m_osSQLBase[i] == chFirst && bInQuotes)
     452             :         {
     453           9 :             if (i + 1 < m_osSQLBase.size() && m_osSQLBase[i + 1] == chFirst)
     454             :             {
     455           1 :                 osBaseLayerName += m_osSQLBase[i];
     456           1 :                 i++;
     457             :             }
     458             :             else
     459             :             {
     460           8 :                 i++;
     461           8 :                 break;
     462             :             }
     463             :         }
     464        2051 :         else if (m_osSQLBase[i] == ' ' && !bInQuotes)
     465         207 :             break;
     466             :         else
     467        1844 :             osBaseLayerName += m_osSQLBase[i];
     468             :     }
     469             : 
     470         339 :     std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *> oPair;
     471         678 :     if (strchr(osBaseLayerName, '(') == nullptr &&
     472         339 :         m_poLayer->GetLayerDefn()->GetGeomFieldCount() != 0)
     473             :     {
     474         336 :         CPLString osNewUnderlyingTableName;
     475             :         osNewUnderlyingTableName.Printf(
     476             :             "%s(%s)", osBaseLayerName.c_str(),
     477         336 :             m_poLayer->GetLayerDefn()->GetGeomFieldDefn(0)->GetNameRef());
     478             :         oPair =
     479         336 :             m_poDS->GetLayerWithGetSpatialWhereByName(osNewUnderlyingTableName);
     480             :     }
     481         339 :     if (oPair.first == nullptr)
     482         338 :         oPair = m_poDS->GetLayerWithGetSpatialWhereByName(osBaseLayerName);
     483             : 
     484         339 :     if (oPair.first != nullptr && m_poLayer->GetSpatialRef() != nullptr &&
     485          63 :         oPair.first->GetSpatialRef() != nullptr &&
     486         708 :         m_poLayer->GetSpatialRef() != oPair.first->GetSpatialRef() &&
     487          30 :         !m_poLayer->GetSpatialRef()->IsSame(oPair.first->GetSpatialRef()))
     488             :     {
     489           0 :         CPLDebug("SQLITE",
     490             :                  "Result layer and base layer don't have the same SRS.");
     491           0 :         return std::pair(nullptr, nullptr);
     492             :     }
     493             : 
     494         339 :     return oPair;
     495             : }
     496             : 
     497             : /************************************************************************/
     498             : /*                             BuildSQL()                               */
     499             : /************************************************************************/
     500             : 
     501         330 : int OGRSQLiteSelectLayerCommonBehaviour::BuildSQL()
     502             : 
     503             : {
     504         330 :     m_osSQLCurrent = m_osSQLBase;
     505         330 :     m_bSpatialFilterInSQL = true;
     506             : 
     507         330 :     size_t i = 0;
     508         330 :     std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *> oPair = GetBaseLayer(i);
     509         330 :     OGRLayer *poBaseLayer = oPair.first;
     510         330 :     if (poBaseLayer == nullptr)
     511             :     {
     512           1 :         CPLDebug("SQLITE", "Cannot find base layer");
     513           1 :         m_bSpatialFilterInSQL = false;
     514           1 :         return FALSE;
     515             :     }
     516             : 
     517         658 :     CPLString osSpatialWhere;
     518         329 :     if (m_poLayer->GetFilterGeom() != nullptr)
     519             :     {
     520             :         const char *pszGeomCol =
     521         127 :             m_poLayer->GetLayerDefn()
     522         127 :                 ->GetGeomFieldDefn(m_poLayer->GetIGeomFieldFilter())
     523         127 :                 ->GetNameRef();
     524         127 :         int nIdx = poBaseLayer->GetLayerDefn()->GetGeomFieldIndex(pszGeomCol);
     525         127 :         if (nIdx < 0)
     526             :         {
     527           0 :             CPLDebug("SQLITE", "Cannot find field %s in base layer",
     528             :                      pszGeomCol);
     529           0 :             m_bSpatialFilterInSQL = false;
     530             :         }
     531             :         else
     532             :         {
     533             :             osSpatialWhere =
     534         127 :                 oPair.second->GetSpatialWhere(nIdx, m_poLayer->GetFilterGeom());
     535         127 :             if (osSpatialWhere.empty())
     536             :             {
     537          51 :                 CPLDebug("SQLITE", "Cannot get spatial where clause");
     538          51 :                 m_bSpatialFilterInSQL = false;
     539             :             }
     540             :         }
     541             :     }
     542             : 
     543         658 :     CPLString osCustomWhere;
     544         329 :     if (!osSpatialWhere.empty())
     545             :     {
     546          76 :         osCustomWhere = osSpatialWhere;
     547             :     }
     548         455 :     if (m_poLayer->GetAttrQueryString() != nullptr &&
     549         126 :         m_poLayer->GetAttrQueryString()[0] != '\0')
     550             :     {
     551         126 :         if (!osSpatialWhere.empty())
     552          20 :             osCustomWhere += " AND (";
     553         126 :         osCustomWhere += m_poLayer->GetAttrQueryString();
     554         126 :         if (!osSpatialWhere.empty())
     555          20 :             osCustomWhere += ")";
     556             :     }
     557             : 
     558             :     /* Nothing to do */
     559         329 :     if (osCustomWhere.empty())
     560         147 :         return TRUE;
     561             : 
     562         293 :     while (i < m_osSQLBase.size() && m_osSQLBase[i] == ' ')
     563         111 :         i++;
     564             : 
     565         293 :     if (i < m_osSQLBase.size() &&
     566         111 :         STARTS_WITH_CI(m_osSQLBase.c_str() + i, "WHERE "))
     567             :     {
     568          65 :         m_osSQLCurrent = m_osSQLBase.substr(0, i + 6);
     569          65 :         m_osSQLCurrent += osCustomWhere;
     570          65 :         m_osSQLCurrent += " AND (";
     571             : 
     572          65 :         size_t nEndOfWhere = m_osSQLBase.ifind(" GROUP ");
     573          65 :         if (nEndOfWhere == std::string::npos)
     574          50 :             nEndOfWhere = m_osSQLBase.ifind(" ORDER ");
     575          65 :         if (nEndOfWhere == std::string::npos)
     576          34 :             nEndOfWhere = m_osSQLBase.ifind(" LIMIT ");
     577             : 
     578          65 :         if (nEndOfWhere == std::string::npos)
     579             :         {
     580          19 :             m_osSQLCurrent += m_osSQLBase.substr(i + 6);
     581          19 :             m_osSQLCurrent += ")";
     582             :         }
     583             :         else
     584             :         {
     585          46 :             m_osSQLCurrent += m_osSQLBase.substr(i + 6, nEndOfWhere - (i + 6));
     586          46 :             m_osSQLCurrent += ")";
     587          46 :             m_osSQLCurrent += m_osSQLBase.substr(nEndOfWhere);
     588             :         }
     589             :     }
     590         163 :     else if (i < m_osSQLBase.size() &&
     591          46 :              (STARTS_WITH_CI(m_osSQLBase.c_str() + i, "GROUP ") ||
     592          31 :               STARTS_WITH_CI(m_osSQLBase.c_str() + i, "ORDER ") ||
     593          15 :               STARTS_WITH_CI(m_osSQLBase.c_str() + i, "LIMIT ")))
     594             :     {
     595          46 :         m_osSQLCurrent = m_osSQLBase.substr(0, i);
     596          46 :         m_osSQLCurrent += " WHERE ";
     597          46 :         m_osSQLCurrent += osCustomWhere;
     598          46 :         m_osSQLCurrent += " ";
     599          46 :         m_osSQLCurrent += m_osSQLBase.substr(i);
     600             :     }
     601          71 :     else if (i == m_osSQLBase.size())
     602             :     {
     603          71 :         m_osSQLCurrent = m_osSQLBase.substr(0, i);
     604          71 :         m_osSQLCurrent += " WHERE ";
     605          71 :         m_osSQLCurrent += osCustomWhere;
     606             :     }
     607             :     else
     608             :     {
     609           0 :         CPLDebug("SQLITE", "SQL expression too complex for the driver to "
     610             :                            "insert attribute and/or spatial filter in it");
     611           0 :         m_bSpatialFilterInSQL = false;
     612           0 :         return FALSE;
     613             :     }
     614             : 
     615         182 :     return TRUE;
     616             : }
     617             : 
     618             : /************************************************************************/
     619             : /*                           TestCapability()                           */
     620             : /************************************************************************/
     621             : 
     622          58 : int OGRSQLiteSelectLayer::TestCapability(const char *pszCap)
     623             : {
     624          58 :     return m_poBehavior->TestCapability(pszCap);
     625             : }
     626             : 
     627          84 : int OGRSQLiteSelectLayerCommonBehaviour::TestCapability(const char *pszCap)
     628             : 
     629             : {
     630          84 :     if (EQUAL(pszCap, OLCFastSpatialFilter))
     631             :     {
     632          10 :         size_t i = 0;
     633          10 :         const auto oPair = GetBaseLayer(i);
     634          10 :         if (oPair.first == nullptr)
     635             :         {
     636           0 :             CPLDebug("SQLITE", "Cannot find base layer");
     637           0 :             return FALSE;
     638             :         }
     639             : 
     640          10 :         return oPair.second->HasFastSpatialFilter(0);
     641             :     }
     642             :     else
     643          74 :         return m_poLayer->BaseTestCapability(pszCap);
     644             : }
     645             : 
     646             : /************************************************************************/
     647             : /*                             GetExtent()                              */
     648             : /************************************************************************/
     649             : 
     650          18 : OGRErr OGRSQLiteSelectLayer::GetExtent(int iGeomField, OGREnvelope *psExtent,
     651             :                                        int bForce)
     652             : {
     653          18 :     return m_poBehavior->GetExtent(iGeomField, psExtent, bForce);
     654             : }
     655             : 
     656          22 : OGRErr OGRSQLiteSelectLayerCommonBehaviour::GetExtent(int iGeomField,
     657             :                                                       OGREnvelope *psExtent,
     658             :                                                       int bForce)
     659             : {
     660          41 :     if (iGeomField < 0 ||
     661          38 :         iGeomField >= m_poLayer->GetLayerDefn()->GetGeomFieldCount() ||
     662          16 :         m_poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() ==
     663             :             wkbNone)
     664             :     {
     665           6 :         if (iGeomField != 0)
     666             :         {
     667           6 :             CPLError(CE_Failure, CPLE_AppDefined,
     668             :                      "Invalid geometry field index : %d", iGeomField);
     669             :         }
     670           6 :         return OGRERR_FAILURE;
     671             :     }
     672             : 
     673             :     /* Caching of extent by SQL string is interesting to speed-up the */
     674             :     /* establishment of the WFS GetCapabilities document for a MapServer mapfile
     675             :      */
     676             :     /* which has several layers, only differing by scale rules */
     677          16 :     if (iGeomField == 0)
     678             :     {
     679             :         const OGREnvelope *psCachedExtent =
     680          16 :             m_poDS->GetEnvelopeFromSQL(m_osSQLBase);
     681          16 :         if (psCachedExtent)
     682             :         {
     683           5 :             *psExtent = *psCachedExtent;
     684           5 :             return OGRERR_NONE;
     685             :         }
     686             :     }
     687             : 
     688          22 :     CPLString osSQLCommand = m_osSQLBase;
     689             : 
     690             :     /* ORDER BY are costly to evaluate and are not necessary to establish */
     691             :     /* the layer extent. */
     692          11 :     size_t nOrderByPos = osSQLCommand.ifind(" ORDER BY ");
     693          11 :     if (osSQLCommand.ifind("SELECT ") == 0 &&
     694          11 :         osSQLCommand.ifind("SELECT ", 1) ==
     695          11 :             std::string::npos && /* Ensure there's no sub SELECT that could
     696             :                                     confuse our heuristics */
     697           4 :         nOrderByPos != std::string::npos &&
     698           4 :         osSQLCommand.ifind(" LIMIT ") == std::string::npos &&
     699           4 :         osSQLCommand.ifind(" UNION ") == std::string::npos &&
     700          26 :         osSQLCommand.ifind(" INTERSECT ") == std::string::npos &&
     701           4 :         osSQLCommand.ifind(" EXCEPT ") == std::string::npos)
     702             :     {
     703           4 :         osSQLCommand.resize(nOrderByPos);
     704             : 
     705             :         OGRLayer *poTmpLayer =
     706           4 :             m_poDS->ExecuteSQL(osSQLCommand.c_str(), nullptr, nullptr);
     707           4 :         if (poTmpLayer)
     708             :         {
     709           4 :             OGRErr eErr = poTmpLayer->GetExtent(iGeomField, psExtent, bForce);
     710           4 :             m_poDS->ReleaseResultSet(poTmpLayer);
     711           4 :             return eErr;
     712             :         }
     713             :     }
     714             : 
     715             :     OGRErr eErr;
     716           7 :     if (iGeomField == 0)
     717           7 :         eErr = m_poLayer->BaseGetExtent(psExtent, bForce);
     718             :     else
     719           0 :         eErr = m_poLayer->BaseGetExtent(iGeomField, psExtent, bForce);
     720           7 :     if (iGeomField == 0 && eErr == OGRERR_NONE && m_poDS->GetUpdate() == false)
     721           5 :         m_poDS->SetEnvelopeForSQL(m_osSQLBase, *psExtent);
     722           7 :     return eErr;
     723             : }

Generated by: LCOV version 1.14