LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/pg - ogrpgresultlayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 98 92 93.9 %
Date: 2011-12-18 Functions: 12 9 75.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrpgresultlayer.cpp 23565 2011-12-13 20:33:20Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRPGResultLayer class, access the resultset from
       6                 :  *           a particular select query done via ExecuteSQL().
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2002, Frank Warmerdam
      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_conv.h"
      32                 : #include "ogr_pg.h"
      33                 : 
      34                 : CPL_CVSID("$Id: ogrpgresultlayer.cpp 23565 2011-12-13 20:33:20Z rouault $");
      35                 : 
      36                 : #define PQexec this_is_an_error
      37                 : 
      38                 : /************************************************************************/
      39                 : /*                          OGRPGResultLayer()                          */
      40                 : /************************************************************************/
      41                 : 
      42              34 : OGRPGResultLayer::OGRPGResultLayer( OGRPGDataSource *poDSIn, 
      43                 :                                     const char * pszRawQueryIn,
      44              34 :                                     PGresult *hInitialResultIn )
      45                 : {
      46              34 :     poDS = poDSIn;
      47                 : 
      48              34 :     iNextShapeId = 0;
      49                 : 
      50              34 :     pszRawStatement = CPLStrdup(pszRawQueryIn);
      51                 : 
      52              34 :     osWHERE = "";
      53                 : 
      54              34 :     BuildFullQueryStatement();
      55                 : 
      56              34 :     poFeatureDefn = ReadResultDefinition(hInitialResultIn);
      57                 : 
      58                 :     /* We have to get the SRID of the geometry column, so to be able */
      59                 :     /* to do spatial filtering */
      60              34 :     if (bHasPostGISGeometry)
      61                 :     {
      62              10 :         CPLString osGetSRID;
      63              10 :         osGetSRID += "SELECT getsrid(";
      64              10 :         osGetSRID += OGRPGEscapeColumnName(pszGeomColumn);
      65              10 :         osGetSRID += ") FROM (";
      66              10 :         osGetSRID += pszRawStatement;
      67              10 :         osGetSRID += ") AS ogrpggetsrid LIMIT 1";
      68                 : 
      69              10 :         PGresult* hSRSIdResult = OGRPG_PQexec(poDS->GetPGConn(), osGetSRID );
      70                 : 
      71              10 :         if( hSRSIdResult && PQresultStatus(hSRSIdResult) == PGRES_TUPLES_OK)
      72                 :         {
      73              10 :             if ( PQntuples(hSRSIdResult) > 0 )
      74              10 :                 nSRSId = atoi(PQgetvalue(hSRSIdResult, 0, 0));
      75                 :         }
      76                 :         else
      77                 :         {
      78                 :             CPLError( CE_Failure, CPLE_AppDefined,
      79               0 :                         "%s", PQerrorMessage(poDS->GetPGConn()) );
      80                 :         }
      81                 : 
      82              10 :         OGRPGClearResult(hSRSIdResult);
      83                 :     }
      84              24 :     else if (bHasPostGISGeography)
      85                 :     {
      86                 :         // FIXME? But for the moment, PostGIS 1.5 only handles SRID:4326.
      87               1 :         nSRSId = 4326;
      88                 :     }
      89              34 : }
      90                 : 
      91                 : /************************************************************************/
      92                 : /*                          ~OGRPGResultLayer()                          */
      93                 : /************************************************************************/
      94                 : 
      95              34 : OGRPGResultLayer::~OGRPGResultLayer()
      96                 : 
      97                 : {
      98              34 :     CPLFree( pszRawStatement );
      99              34 : }
     100                 : 
     101                 : 
     102                 : /************************************************************************/
     103                 : /*                      BuildFullQueryStatement()                       */
     104                 : /************************************************************************/
     105                 : 
     106              39 : void OGRPGResultLayer::BuildFullQueryStatement()
     107                 : 
     108                 : {
     109              39 :     if( pszQueryStatement != NULL )
     110                 :     {
     111               5 :         CPLFree( pszQueryStatement );
     112               5 :         pszQueryStatement = NULL;
     113                 :     }
     114                 : 
     115              39 :     pszQueryStatement = (char*) CPLMalloc(strlen(pszRawStatement) + strlen(osWHERE) + 40);
     116                 : 
     117              39 :     if (strlen(osWHERE) == 0)
     118              35 :         strcpy(pszQueryStatement, pszRawStatement);
     119                 :     else
     120                 :         sprintf(pszQueryStatement, "SELECT * FROM (%s) AS ogrpgsubquery %s",
     121               4 :                 pszRawStatement, osWHERE.c_str());
     122              39 : }
     123                 : 
     124                 : /************************************************************************/
     125                 : /*                            ResetReading()                            */
     126                 : /************************************************************************/
     127                 : 
     128              64 : void OGRPGResultLayer::ResetReading()
     129                 : 
     130                 : {
     131              64 :     OGRPGLayer::ResetReading();
     132              64 : }
     133                 : 
     134                 : /************************************************************************/
     135                 : /*                          GetFeatureCount()                           */
     136                 : /************************************************************************/
     137                 : 
     138              24 : int OGRPGResultLayer::GetFeatureCount( int bForce )
     139                 : 
     140                 : {
     141              24 :     if( TestCapability(OLCFastFeatureCount) == FALSE )
     142               8 :         return OGRPGLayer::GetFeatureCount( bForce );
     143                 : 
     144              16 :     PGconn              *hPGConn = poDS->GetPGConn();
     145              16 :     PGresult            *hResult = NULL;
     146              16 :     CPLString           osCommand;
     147              16 :     int                 nCount = 0;
     148                 : 
     149                 :     osCommand.Printf(
     150                 :         "SELECT count(*) FROM (%s) AS ogrpgcount",
     151              16 :         pszQueryStatement );
     152                 : 
     153              16 :     hResult = OGRPG_PQexec(hPGConn, osCommand);
     154              16 :     if( hResult != NULL && PQresultStatus(hResult) == PGRES_TUPLES_OK )
     155              16 :         nCount = atoi(PQgetvalue(hResult,0,0));
     156                 :     else
     157               0 :         CPLDebug( "PG", "%s; failed.", osCommand.c_str() );
     158              16 :     OGRPGClearResult( hResult );
     159                 : 
     160              16 :     return nCount;
     161                 : }
     162                 : 
     163                 : 
     164                 : /************************************************************************/
     165                 : /*                           TestCapability()                           */
     166                 : /************************************************************************/
     167                 : 
     168              48 : int OGRPGResultLayer::TestCapability( const char * pszCap )
     169                 : 
     170                 : {
     171              48 :     if( EQUAL(pszCap,OLCFastFeatureCount) ||
     172                 :         EQUAL(pszCap,OLCFastSetNextByIndex) )
     173                 :         return (m_poFilterGeom == NULL || 
     174              32 :                 ((bHasPostGISGeometry || bHasPostGISGeography) && nSRSId != UNDETERMINED_SRID)) && m_poAttrQuery == NULL;
     175                 : 
     176              16 :     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
     177               0 :         return ((bHasPostGISGeometry || bHasPostGISGeography) && nSRSId != UNDETERMINED_SRID) && m_poAttrQuery == NULL;
     178                 : 
     179              16 :     else if( EQUAL(pszCap,OLCFastGetExtent) )
     180              10 :         return (bHasPostGISGeometry && nSRSId != UNDETERMINED_SRID) && m_poAttrQuery == NULL;
     181                 :         
     182               6 :     else if( EQUAL(pszCap,OLCStringsAsUTF8) )
     183               2 :         return TRUE;
     184                 : 
     185                 :     else
     186               4 :         return FALSE;
     187                 : }
     188                 : 
     189                 : 
     190                 : /************************************************************************/
     191                 : /*                           GetNextFeature()                           */
     192                 : /************************************************************************/
     193                 : 
     194            2529 : OGRFeature *OGRPGResultLayer::GetNextFeature()
     195                 : 
     196                 : {
     197                 : 
     198              98 :     for( ; TRUE; )
     199                 :     {
     200                 :         OGRFeature      *poFeature;
     201                 : 
     202            2529 :         poFeature = GetNextRawFeature();
     203            2529 :         if( poFeature == NULL )
     204              31 :             return NULL;
     205                 : 
     206            2498 :         if( (m_poFilterGeom == NULL
     207                 :             || ((bHasPostGISGeometry || bHasPostGISGeography) && nSRSId != UNDETERMINED_SRID)
     208                 :             || FilterGeometry( poFeature->GetGeometryRef() ) )
     209                 :             && (m_poAttrQuery == NULL
     210                 :                 || m_poAttrQuery->Evaluate( poFeature )) )
     211            2400 :             return poFeature;
     212                 : 
     213              98 :         delete poFeature;
     214                 :     }
     215                 : }
     216                 : 
     217                 : /************************************************************************/
     218                 : /*                          SetSpatialFilter()                          */
     219                 : /************************************************************************/
     220                 : 
     221              16 : void OGRPGResultLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
     222                 : 
     223                 : {
     224              16 :     if( InstallFilter( poGeomIn ) )
     225                 :     {
     226              10 :         if ((bHasPostGISGeometry || bHasPostGISGeography) && nSRSId != UNDETERMINED_SRID)
     227                 :         {
     228               5 :             if( m_poFilterGeom != NULL)
     229                 :             {
     230                 :                 char szBox3D_1[128];
     231                 :                 char szBox3D_2[128];
     232                 :                 char* pszComma;
     233               4 :                 OGREnvelope  sEnvelope;
     234                 : 
     235               4 :                 m_poFilterGeom->getEnvelope( &sEnvelope );
     236               4 :                 snprintf(szBox3D_1, sizeof(szBox3D_1), "%.12f %.12f", sEnvelope.MinX, sEnvelope.MinY);
     237               8 :                 while((pszComma = strchr(szBox3D_1, ',')) != NULL)
     238               0 :                     *pszComma = '.';
     239               4 :                 snprintf(szBox3D_2, sizeof(szBox3D_2), "%.12f %.12f", sEnvelope.MaxX, sEnvelope.MaxY);
     240               8 :                 while((pszComma = strchr(szBox3D_2, ',')) != NULL)
     241               0 :                     *pszComma = '.';
     242                 :                 osWHERE.Printf("WHERE %s && SetSRID('BOX3D(%s, %s)'::box3d,%d) ",
     243               4 :                             OGRPGEscapeColumnName(pszGeomColumn).c_str(), szBox3D_1, szBox3D_2, nSRSId );
     244                 :             }
     245                 :             else
     246                 :             {
     247               1 :                 osWHERE = "";
     248                 :             }
     249                 : 
     250               5 :             BuildFullQueryStatement();
     251                 :         }
     252                 : 
     253              10 :         ResetReading();
     254                 :     }
     255                 : 
     256              16 : }
     257                 : 
     258                 : /************************************************************************/
     259                 : /*                             GetExtent()                              */
     260                 : /*                                                                      */
     261                 : /*      For PostGIS use internal Extend(geometry) function              */
     262                 : /*      in other cases we use standard OGRLayer::GetExtent()            */
     263                 : /************************************************************************/
     264                 : 
     265               5 : OGRErr OGRPGResultLayer::GetExtent( OGREnvelope *psExtent, int bForce )
     266                 : {
     267               5 :     CPLString   osCommand;
     268                 : 
     269                 :     const char* pszExtentFct;
     270               5 :     if (poDS->sPostGISVersion.nMajor >= 2)
     271               0 :         pszExtentFct = "ST_Extent";
     272                 :     else
     273               5 :         pszExtentFct = "Extent";
     274                 : 
     275               5 :     if ( TestCapability(OLCFastGetExtent) )
     276                 :     {
     277                 :         /* Do not take the spatial filter into account */
     278                 :         osCommand.Printf( "SELECT %s(%s) FROM (%s) AS ogrpgextent",
     279                 :                           pszExtentFct, OGRPGEscapeColumnName(pszGeomColumn).c_str(),
     280               2 :                           pszRawStatement );
     281                 :     }
     282               3 :     else if ( bHasPostGISGeography )
     283                 :     {
     284                 :         /* Probably not very efficient, but more efficient than client-side implementation */
     285                 :         osCommand.Printf( "SELECT %s(ST_GeomFromWKB(ST_AsBinary(%s))) FROM (%s) AS ogrpgextent",
     286                 :                           pszExtentFct, OGRPGEscapeColumnName(pszGeomColumn).c_str(),
     287               1 :                           pszRawStatement );
     288                 :     }
     289                 :     
     290               5 :     return RunGetExtentRequest(psExtent, bForce, osCommand);
     291                 : }

Generated by: LCOV version 1.7