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

Generated by: LCOV version 1.14