LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/pgeo - ogrpgeolayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 173 0.0 %
Date: 2024-05-03 15:49:35 Functions: 0 12 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implements OGRPGeoLayer class, code shared between
       5             :  *           the direct table access, and the generic SQL results.
       6             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
      10             :  * Copyright (c) 2008-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_conv.h"
      32             : #include "ogr_pgeo.h"
      33             : #include "cpl_string.h"
      34             : #include "ogrpgeogeometry.h"
      35             : 
      36             : #include <algorithm>
      37             : 
      38             : /************************************************************************/
      39             : /*                            OGRPGeoLayer()                            */
      40             : /************************************************************************/
      41             : 
      42           0 : OGRPGeoLayer::OGRPGeoLayer()
      43             :     : poFeatureDefn(nullptr), poStmt(nullptr), poSRS(nullptr),
      44             :       nSRSId(-2),  // we haven't even queried the database for it yet.
      45             :       iNextShapeId(0), poDS(nullptr), pszGeomColumn(nullptr),
      46           0 :       pszFIDColumn(nullptr), panFieldOrdinals(nullptr)
      47             : {
      48           0 : }
      49             : 
      50             : /************************************************************************/
      51             : /*                            ~OGRPGeoLayer()                             */
      52             : /************************************************************************/
      53             : 
      54           0 : OGRPGeoLayer::~OGRPGeoLayer()
      55             : 
      56             : {
      57           0 :     if (m_nFeaturesRead > 0 && poFeatureDefn != nullptr)
      58             :     {
      59           0 :         CPLDebug("PGeo", "%d features read on layer '%s'.",
      60           0 :                  static_cast<int>(m_nFeaturesRead), poFeatureDefn->GetName());
      61             :     }
      62             : 
      63           0 :     if (poStmt != nullptr)
      64             :     {
      65           0 :         delete poStmt;
      66           0 :         poStmt = nullptr;
      67             :     }
      68             : 
      69           0 :     if (poFeatureDefn != nullptr)
      70             :     {
      71           0 :         poFeatureDefn->Release();
      72           0 :         poFeatureDefn = nullptr;
      73             :     }
      74             : 
      75           0 :     CPLFree(pszGeomColumn);
      76           0 :     CPLFree(panFieldOrdinals);
      77           0 :     CPLFree(pszFIDColumn);
      78             : 
      79           0 :     if (poSRS != nullptr)
      80             :     {
      81           0 :         poSRS->Release();
      82           0 :         poSRS = nullptr;
      83             :     }
      84           0 : }
      85             : 
      86             : /************************************************************************/
      87             : /*                          BuildFeatureDefn()                          */
      88             : /*                                                                      */
      89             : /*      Build feature definition from a set of column definitions       */
      90             : /*      set on a statement.  Sift out geometry and FID fields.          */
      91             : /************************************************************************/
      92             : 
      93           0 : CPLErr OGRPGeoLayer::BuildFeatureDefn(const char *pszLayerName,
      94             :                                       CPLODBCStatement *poStmtIn)
      95             : 
      96             : {
      97           0 :     poFeatureDefn = new OGRFeatureDefn(pszLayerName);
      98           0 :     SetDescription(poFeatureDefn->GetName());
      99           0 :     int nRawColumns = poStmtIn->GetColCount();
     100             : 
     101           0 :     poFeatureDefn->Reference();
     102           0 :     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
     103             : 
     104           0 :     panFieldOrdinals = (int *)CPLMalloc(sizeof(int) * nRawColumns);
     105             : 
     106           0 :     for (int iCol = 0; iCol < nRawColumns; iCol++)
     107             :     {
     108           0 :         OGRFieldDefn oField(poStmtIn->GetColName(iCol), OFTString);
     109             : 
     110           0 :         oField.SetWidth(
     111           0 :             std::max(static_cast<short>(0), poStmtIn->GetColSize(iCol)));
     112             : 
     113           0 :         if (pszGeomColumn != nullptr &&
     114           0 :             EQUAL(poStmtIn->GetColName(iCol), pszGeomColumn))
     115           0 :             continue;
     116             : 
     117           0 :         if (pszFIDColumn == nullptr &&
     118           0 :             EQUAL(poStmtIn->GetColName(iCol), "OBJECTID"))
     119             :         {
     120           0 :             pszFIDColumn = CPLStrdup(poStmtIn->GetColName(iCol));
     121             :         }
     122             : 
     123           0 :         if (pszGeomColumn == nullptr &&
     124           0 :             EQUAL(poStmtIn->GetColName(iCol), "Shape"))
     125             :         {
     126           0 :             pszGeomColumn = CPLStrdup(poStmtIn->GetColName(iCol));
     127           0 :             continue;
     128             :         }
     129             : 
     130           0 :         switch (poStmtIn->GetColType(iCol))
     131             :         {
     132           0 :             case SQL_INTEGER:
     133             :             case SQL_SMALLINT:
     134           0 :                 oField.SetType(OFTInteger);
     135           0 :                 break;
     136             : 
     137           0 :             case SQL_BINARY:
     138             :             case SQL_VARBINARY:
     139             :             case SQL_LONGVARBINARY:
     140           0 :                 oField.SetType(OFTBinary);
     141           0 :                 break;
     142             : 
     143           0 :             case SQL_DECIMAL:
     144           0 :                 oField.SetType(OFTReal);
     145           0 :                 oField.SetPrecision(poStmtIn->GetColPrecision(iCol));
     146           0 :                 break;
     147             : 
     148           0 :             case SQL_FLOAT:
     149             :             case SQL_REAL:
     150             :             case SQL_DOUBLE:
     151           0 :                 oField.SetType(OFTReal);
     152           0 :                 oField.SetWidth(0);
     153           0 :                 break;
     154             : 
     155           0 :             case SQL_C_DATE:
     156           0 :                 oField.SetType(OFTDate);
     157           0 :                 break;
     158             : 
     159           0 :             case SQL_C_TIME:
     160           0 :                 oField.SetType(OFTTime);
     161           0 :                 break;
     162             : 
     163           0 :             case SQL_C_TIMESTAMP:
     164             :             case SQL_C_TYPE_TIMESTAMP:
     165           0 :                 oField.SetType(OFTDateTime);
     166           0 :                 break;
     167             : 
     168           0 :             default:
     169             :                 /* leave it as OFTString */;
     170             :         }
     171             : 
     172           0 :         poFeatureDefn->AddFieldDefn(&oField);
     173           0 :         panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol + 1;
     174             :     }
     175             : 
     176           0 :     if (pszGeomColumn != nullptr)
     177           0 :         poFeatureDefn->GetGeomFieldDefn(0)->SetName(pszGeomColumn);
     178             :     else
     179           0 :         poFeatureDefn->SetGeomType(wkbNone);
     180             : 
     181           0 :     return CE_None;
     182             : }
     183             : 
     184             : /************************************************************************/
     185             : /*                            ResetReading()                            */
     186             : /************************************************************************/
     187             : 
     188           0 : void OGRPGeoLayer::ResetReading()
     189             : 
     190             : {
     191           0 :     iNextShapeId = 0;
     192           0 :     m_bEOF = false;
     193           0 : }
     194             : 
     195             : /************************************************************************/
     196             : /*                           GetNextFeature()                           */
     197             : /************************************************************************/
     198             : 
     199           0 : OGRFeature *OGRPGeoLayer::GetNextFeature()
     200             : 
     201             : {
     202             :     while (true)
     203             :     {
     204           0 :         OGRFeature *poFeature = GetNextRawFeature();
     205           0 :         if (poFeature == nullptr)
     206           0 :             return nullptr;
     207             : 
     208           0 :         if ((m_poFilterGeom == nullptr ||
     209           0 :              FilterGeometry(poFeature->GetGeometryRef())) &&
     210           0 :             (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
     211           0 :             return poFeature;
     212             : 
     213           0 :         delete poFeature;
     214           0 :     }
     215             : }
     216             : 
     217             : /************************************************************************/
     218             : /*                         GetNextRawFeature()                          */
     219             : /************************************************************************/
     220             : 
     221           0 : OGRFeature *OGRPGeoLayer::GetNextRawFeature()
     222             : 
     223             : {
     224           0 :     OGRErr err = OGRERR_NONE;
     225             : 
     226           0 :     if (m_bEOF || GetStatement() == nullptr)
     227           0 :         return nullptr;
     228             : 
     229             :     /* -------------------------------------------------------------------- */
     230             :     /*      If we are marked to restart then do so, and fetch a record.     */
     231             :     /* -------------------------------------------------------------------- */
     232           0 :     if (!poStmt->Fetch())
     233             :     {
     234           0 :         delete poStmt;
     235           0 :         poStmt = nullptr;
     236           0 :         m_bEOF = true;
     237           0 :         return nullptr;
     238             :     }
     239             : 
     240             :     /* -------------------------------------------------------------------- */
     241             :     /*      Create a feature from the current result.                       */
     242             :     /* -------------------------------------------------------------------- */
     243           0 :     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
     244             : 
     245           0 :     if (pszFIDColumn != nullptr && poStmt->GetColId(pszFIDColumn) > -1)
     246           0 :         poFeature->SetFID(
     247           0 :             atoi(poStmt->GetColData(poStmt->GetColId(pszFIDColumn))));
     248             :     else
     249           0 :         poFeature->SetFID(iNextShapeId);
     250             : 
     251           0 :     iNextShapeId++;
     252           0 :     m_nFeaturesRead++;
     253             : 
     254             :     /* -------------------------------------------------------------------- */
     255             :     /*      Set the fields.                                                 */
     256             :     /* -------------------------------------------------------------------- */
     257           0 :     for (int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++)
     258             :     {
     259             :         const OGRFieldType eType =
     260           0 :             poFeatureDefn->GetFieldDefn(iField)->GetType();
     261           0 :         int iSrcField = panFieldOrdinals[iField] - 1;
     262             : 
     263           0 :         if (eType == OFTReal &&
     264           0 :             (poStmt->Flags() &
     265             :              CPLODBCStatement::Flag::RetrieveNumericColumnsAsDouble))
     266             :         {
     267             :             // for OFTReal fields we retrieve the value directly as a double
     268             :             // to avoid loss of precision associated with double/float->string
     269             :             // conversion
     270           0 :             const double dfValue = poStmt->GetColDataAsDouble(iSrcField);
     271           0 :             if (std::isnan(dfValue))
     272             :             {
     273           0 :                 poFeature->SetFieldNull(iField);
     274             :             }
     275             :             else
     276             :             {
     277           0 :                 poFeature->SetField(iField, dfValue);
     278             :             }
     279             :         }
     280             :         else
     281             :         {
     282           0 :             const char *pszValue = poStmt->GetColData(iSrcField);
     283             : 
     284           0 :             if (pszValue == nullptr)
     285           0 :                 poFeature->SetFieldNull(iField);
     286           0 :             else if (poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary)
     287           0 :                 poFeature->SetField(iField, poStmt->GetColDataLength(iSrcField),
     288             :                                     (GByte *)pszValue);
     289             :             else
     290           0 :                 poFeature->SetField(iField, pszValue);
     291             :         }
     292             :     }
     293             : 
     294             :     /* -------------------------------------------------------------------- */
     295             :     /*      Try to extract a geometry.                                      */
     296             :     /* -------------------------------------------------------------------- */
     297           0 :     if (pszGeomColumn != nullptr)
     298             :     {
     299           0 :         int iField = poStmt->GetColId(pszGeomColumn);
     300           0 :         GByte *pabyShape = (GByte *)poStmt->GetColData(iField);
     301           0 :         int nBytes = poStmt->GetColDataLength(iField);
     302           0 :         OGRGeometry *poGeom = nullptr;
     303             : 
     304           0 :         if (pabyShape != nullptr)
     305             :         {
     306           0 :             err = OGRCreateFromShapeBin(pabyShape, &poGeom, nBytes);
     307           0 :             if (OGRERR_NONE != err)
     308             :             {
     309           0 :                 CPLDebug(
     310             :                     "PGeo",
     311             :                     "Translation shape binary to OGR geometry failed (FID=%ld)",
     312           0 :                     (long)poFeature->GetFID());
     313             :             }
     314             :         }
     315             : 
     316           0 :         if (poGeom != nullptr && OGRERR_NONE == err)
     317             :         {
     318             :             // always promote polygon/linestring geometries to
     319             :             // multipolygon/multilinestring, so that the geometry types returned
     320             :             // for the layer are predictable and match the advertised layer
     321             :             // geometry type. See more details in OGRPGeoTableLayer::Initialize
     322             :             const OGRwkbGeometryType eFlattenType =
     323           0 :                 wkbFlatten(poGeom->getGeometryType());
     324           0 :             if (eFlattenType == wkbPolygon || eFlattenType == wkbLineString)
     325           0 :                 poGeom = OGRGeometryFactory::forceTo(
     326           0 :                     poGeom, OGR_GT_GetCollection(poGeom->getGeometryType()));
     327             : 
     328           0 :             poGeom->assignSpatialReference(poSRS);
     329           0 :             poFeature->SetGeometryDirectly(poGeom);
     330             :         }
     331             :     }
     332             : 
     333           0 :     return poFeature;
     334             : }
     335             : 
     336             : /************************************************************************/
     337             : /*                             GetFeature()                             */
     338             : /************************************************************************/
     339             : 
     340           0 : OGRFeature *OGRPGeoLayer::GetFeature(GIntBig nFeatureId)
     341             : 
     342             : {
     343             :     /* This should be implemented directly! */
     344             : 
     345           0 :     return OGRLayer::GetFeature(nFeatureId);
     346             : }
     347             : 
     348             : /************************************************************************/
     349             : /*                           TestCapability()                           */
     350             : /************************************************************************/
     351             : 
     352           0 : int OGRPGeoLayer::TestCapability(CPL_UNUSED const char *pszCap)
     353             : {
     354           0 :     if (EQUAL(pszCap, OLCZGeometries))
     355           0 :         return true;
     356           0 :     if (EQUAL(pszCap, OLCMeasuredGeometries))
     357           0 :         return true;
     358             : 
     359           0 :     return false;
     360             : }
     361             : 
     362             : /************************************************************************/
     363             : /*                           TestCapability()                           */
     364             : /************************************************************************/
     365             : 
     366           0 : void OGRPGeoLayer::LookupSRID(int nSRID)
     367             : 
     368             : {
     369             :     /* -------------------------------------------------------------------- */
     370             :     /*      Fetch the corresponding WKT from the SpatialRef table.          */
     371             :     /* -------------------------------------------------------------------- */
     372           0 :     CPLODBCStatement oStmt(poDS->GetSession());
     373             : 
     374           0 :     oStmt.Appendf("SELECT srtext FROM GDB_SpatialRefs WHERE srid = %d", nSRID);
     375             : 
     376           0 :     if (!oStmt.ExecuteSQL())
     377             :     {
     378           0 :         CPLError(CE_Failure, CPLE_AppDefined, "'%s' failed.\n%s",
     379           0 :                  oStmt.GetCommand(), poDS->GetSession()->GetLastError());
     380           0 :         return;
     381             :     }
     382             : 
     383           0 :     if (!oStmt.Fetch())
     384             :     {
     385           0 :         CPLError(CE_Warning, CPLE_AppDefined, "SRID %d lookup failed.\n%s",
     386           0 :                  nSRID, poDS->GetSession()->GetLastError());
     387           0 :         return;
     388             :     }
     389             : 
     390             :     /* -------------------------------------------------------------------- */
     391             :     /*      Check that it isn't just a GUID.  We don't know how to          */
     392             :     /*      translate those.                                                */
     393             :     /* -------------------------------------------------------------------- */
     394           0 :     const char *pszSRText = oStmt.GetColData(0);
     395             : 
     396           0 :     if (pszSRText[0] == '{')
     397             :     {
     398           0 :         CPLDebug("PGEO", "Ignoring GUID SRTEXT: %s", pszSRText);
     399           0 :         return;
     400             :     }
     401             : 
     402             :     /* -------------------------------------------------------------------- */
     403             :     /*      Turn it into an OGRSpatialReference.                            */
     404             :     /* -------------------------------------------------------------------- */
     405           0 :     poSRS = new OGRSpatialReference();
     406           0 :     poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     407             : 
     408           0 :     if (poSRS->importFromWkt(pszSRText) != OGRERR_NONE)
     409             :     {
     410           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     411             :                  "importFromWKT() failed on SRS '%s'.", pszSRText);
     412           0 :         delete poSRS;
     413           0 :         poSRS = nullptr;
     414             :     }
     415             :     else
     416           0 :         nSRSId = nSRID;
     417             : }
     418             : 
     419             : /************************************************************************/
     420             : /*                            GetFIDColumn()                            */
     421             : /************************************************************************/
     422             : 
     423           0 : const char *OGRPGeoLayer::GetFIDColumn()
     424             : 
     425             : {
     426           0 :     if (pszFIDColumn != nullptr)
     427           0 :         return pszFIDColumn;
     428             :     else
     429           0 :         return "";
     430             : }
     431             : 
     432             : /************************************************************************/
     433             : /*                         GetGeometryColumn()                          */
     434             : /************************************************************************/
     435             : 
     436           0 : const char *OGRPGeoLayer::GetGeometryColumn()
     437             : 
     438             : {
     439           0 :     if (pszGeomColumn != nullptr)
     440           0 :         return pszGeomColumn;
     441             :     else
     442           0 :         return "";
     443             : }

Generated by: LCOV version 1.14