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

Generated by: LCOV version 1.14