LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/pg - ogrpgresultlayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 102 96 94.1 %
Date: 2012-04-28 Functions: 13 10 76.9 %

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

Generated by: LCOV version 1.7