LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/pgeo - ogrpgeotablelayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 178 0.0 %
Date: 2024-11-21 22:18:42 Functions: 0 13 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implements OGRPGeoTableLayer class, access to an existing table.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2005, Frank Warmerdam
       9             :  * Copyright (c) 2008-2011, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_conv.h"
      15             : #include "ogr_pgeo.h"
      16             : #include "ogrpgeogeometry.h"
      17             : 
      18             : /************************************************************************/
      19             : /*                          OGRPGeoTableLayer()                         */
      20             : /************************************************************************/
      21             : 
      22           0 : OGRPGeoTableLayer::OGRPGeoTableLayer(OGRPGeoDataSource *poDSIn,
      23           0 :                                      int nODBCStatementFlags)
      24           0 :     : pszQuery(nullptr)
      25             : {
      26           0 :     m_nStatementFlags = nODBCStatementFlags;
      27           0 :     poDS = poDSIn;
      28           0 :     iNextShapeId = 0;
      29           0 :     nSRSId = -1;
      30           0 :     poFeatureDefn = nullptr;
      31           0 : }
      32             : 
      33             : /************************************************************************/
      34             : /*                          ~OGRPGeoTableLayer()                          */
      35             : /************************************************************************/
      36             : 
      37           0 : OGRPGeoTableLayer::~OGRPGeoTableLayer()
      38             : 
      39             : {
      40           0 :     CPLFree(pszQuery);
      41           0 :     ClearStatement();
      42           0 : }
      43             : 
      44             : /************************************************************************/
      45             : /*                             Initialize()                             */
      46             : /************************************************************************/
      47             : 
      48           0 : CPLErr OGRPGeoTableLayer::Initialize(const char *pszTableName,
      49             :                                      const char *pszGeomCol, int nShapeType,
      50             :                                      double dfExtentLeft, double dfExtentRight,
      51             :                                      double dfExtentBottom, double dfExtentTop,
      52             :                                      int nSRID, int bHasZ, int bHasM)
      53             : 
      54             : {
      55           0 :     CPLODBCSession *poSession = poDS->GetSession();
      56             : 
      57           0 :     SetDescription(pszTableName);
      58             : 
      59           0 :     CPLFree(pszGeomColumn);
      60           0 :     if (pszGeomCol == nullptr)
      61           0 :         pszGeomColumn = nullptr;
      62             :     else
      63           0 :         pszGeomColumn = CPLStrdup(pszGeomCol);
      64             : 
      65           0 :     CPLFree(pszFIDColumn);
      66           0 :     pszFIDColumn = nullptr;
      67             : 
      68           0 :     sExtent.MinX = dfExtentLeft;
      69           0 :     sExtent.MaxX = dfExtentRight;
      70           0 :     sExtent.MinY = dfExtentBottom;
      71           0 :     sExtent.MaxY = dfExtentTop;
      72             : 
      73           0 :     if (pszGeomCol)
      74           0 :         LookupSRID(nSRID);
      75             : 
      76             :     // Setup geometry type.
      77             : 
      78             :     // The PGeo format has a similar approach to multi-part handling as
      79             :     // Shapefiles, where polygon and multipolygon geometries or line and
      80             :     // multiline geometries will co-exist in a layer reported as just polygon or
      81             :     // line type respectively. To handle this in a predictable way for clients
      82             :     // we always promote the polygon/line types to multitypes, and
      83             :     // correspondingly ALWAYS return multi polygon/line geometry objects for
      84             :     // features (even if strictly speaking the original feature had a
      85             :     // polygon/line geometry object)
      86             :     OGRwkbGeometryType eOGRType;
      87             : 
      88           0 :     switch (nShapeType)
      89             :     {
      90           0 :         case ESRI_LAYERGEOMTYPE_NULL:
      91           0 :             eOGRType = wkbNone;
      92           0 :             break;
      93             : 
      94           0 :         case ESRI_LAYERGEOMTYPE_POINT:
      95           0 :             eOGRType = wkbPoint;
      96           0 :             break;
      97             : 
      98           0 :         case ESRI_LAYERGEOMTYPE_MULTIPOINT:
      99           0 :             eOGRType = wkbMultiPoint;
     100           0 :             break;
     101             : 
     102           0 :         case ESRI_LAYERGEOMTYPE_POLYLINE:
     103           0 :             eOGRType = wkbMultiLineString;  // see comment above
     104           0 :             break;
     105             : 
     106           0 :         case ESRI_LAYERGEOMTYPE_POLYGON:
     107             :         case ESRI_LAYERGEOMTYPE_MULTIPATCH:
     108           0 :             eOGRType = wkbMultiPolygon;  // see comment above
     109           0 :             break;
     110             : 
     111           0 :         default:
     112           0 :             CPLDebug("PGeo", "Unexpected value for shape type : %d",
     113             :                      nShapeType);
     114           0 :             eOGRType = wkbUnknown;
     115           0 :             break;
     116             :     }
     117             : 
     118           0 :     if (eOGRType != wkbUnknown && eOGRType != wkbNone)
     119             :     {
     120           0 :         if (bHasZ)
     121           0 :             eOGRType = wkbSetZ(eOGRType);
     122           0 :         if (bHasM)
     123           0 :             eOGRType = wkbSetM(eOGRType);
     124             :     }
     125           0 :     CPL_IGNORE_RET_VAL(eOGRType);
     126             : 
     127             :     /* -------------------------------------------------------------------- */
     128             :     /*      Do we have a simple primary key?                                */
     129             :     /* -------------------------------------------------------------------- */
     130           0 :     CPLODBCStatement oGetKey(poSession);
     131             : 
     132           0 :     if (oGetKey.GetPrimaryKeys(pszTableName) && oGetKey.Fetch())
     133             :     {
     134           0 :         pszFIDColumn = CPLStrdup(oGetKey.GetColData(3));
     135             : 
     136           0 :         if (oGetKey.Fetch())  // more than one field in key!
     137             :         {
     138           0 :             CPLFree(pszFIDColumn);
     139           0 :             pszFIDColumn = nullptr;
     140           0 :             CPLDebug("PGeo", "%s: Compound primary key, ignoring.",
     141             :                      pszTableName);
     142             :         }
     143             :         else
     144           0 :             CPLDebug("PGeo", "%s: Got primary key %s.", pszTableName,
     145             :                      pszFIDColumn);
     146             :     }
     147             :     else
     148           0 :         CPLDebug("PGeo", "%s: no primary key", pszTableName);
     149             : 
     150             :     /* -------------------------------------------------------------------- */
     151             :     /*      Get the column definitions for this table.                      */
     152             :     /* -------------------------------------------------------------------- */
     153           0 :     CPLODBCStatement oGetCol(poSession);
     154             :     CPLErr eErr;
     155             : 
     156           0 :     if (!oGetCol.GetColumns(pszTableName))
     157             :     {
     158           0 :         CPLError(CE_Failure, CPLE_AppDefined, "GetColumns() failed on %s.\n%s",
     159             :                  pszTableName, poSession->GetLastError());
     160           0 :         return CE_Failure;
     161             :     }
     162             : 
     163           0 :     eErr = BuildFeatureDefn(pszTableName, &oGetCol);
     164           0 :     if (eErr != CE_None)
     165           0 :         return eErr;
     166             : 
     167           0 :     if (poFeatureDefn->GetFieldCount() == 0)
     168             :     {
     169           0 :         CPLError(
     170             :             CE_Failure, CPLE_AppDefined,
     171             :             "No column definitions found for table '%s', layer not usable.",
     172             :             pszTableName);
     173           0 :         return CE_Failure;
     174             :     }
     175             : 
     176           0 :     poFeatureDefn->SetGeomType(eOGRType);
     177             : 
     178             :     // Where possible, retrieve useful metadata information from the GDB_Items
     179             :     // table
     180           0 :     if (poDS->HasGdbItemsTable())
     181             :     {
     182           0 :         CPLODBCStatement oItemsStmt(poSession);
     183           0 :         oItemsStmt.Append(
     184             :             "SELECT Definition, Documentation FROM GDB_Items WHERE Name='");
     185           0 :         oItemsStmt.Append(pszTableName);
     186           0 :         oItemsStmt.Append("'");
     187           0 :         if (oItemsStmt.ExecuteSQL())
     188             :         {
     189           0 :             while (oItemsStmt.Fetch())
     190             :             {
     191             :                 const CPLString osDefinition =
     192           0 :                     CPLString(oItemsStmt.GetColData(0, ""));
     193           0 :                 if (strstr(osDefinition, "DEFeatureClassInfo") != nullptr)
     194             :                 {
     195           0 :                     m_osDefinition = osDefinition;
     196             : 
     197             :                     // try to retrieve field domains
     198             :                     CPLXMLTreeCloser oTree(
     199           0 :                         CPLParseXMLString(osDefinition.c_str()));
     200           0 :                     if (oTree.get())
     201             :                     {
     202           0 :                         if (const CPLXMLNode *psFieldInfoExs = CPLGetXMLNode(
     203             :                                 oTree.get(),
     204             :                                 "=DEFeatureClassInfo.GPFieldInfoExs"))
     205             :                         {
     206           0 :                             for (const CPLXMLNode *psFieldInfoEx =
     207           0 :                                      CPLGetXMLNode(psFieldInfoExs,
     208             :                                                    "GPFieldInfoEx");
     209           0 :                                  psFieldInfoEx != nullptr;
     210           0 :                                  psFieldInfoEx = psFieldInfoEx->psNext)
     211             :                             {
     212             :                                 const CPLString osName =
     213           0 :                                     CPLGetXMLValue(psFieldInfoEx, "Name", "");
     214             :                                 const CPLString osDomainName = CPLGetXMLValue(
     215           0 :                                     psFieldInfoEx, "DomainName", "");
     216           0 :                                 if (!osDomainName.empty())
     217             :                                 {
     218             :                                     const int fieldIndex =
     219           0 :                                         poFeatureDefn->GetFieldIndex(osName);
     220           0 :                                     if (fieldIndex != -1)
     221           0 :                                         poFeatureDefn->GetFieldDefn(fieldIndex)
     222           0 :                                             ->SetDomainName(osDomainName);
     223             :                                 }
     224             :                             }
     225             :                         }
     226             :                     }
     227             : 
     228             :                     // try to retrieve layer medata
     229           0 :                     m_osDocumentation = CPLString(oItemsStmt.GetColData(1, ""));
     230           0 :                     break;
     231             :                 }
     232             :             }
     233             :         }
     234             :     }
     235             : 
     236           0 :     return CE_None;
     237             : }
     238             : 
     239             : /************************************************************************/
     240             : /*                           ClearStatement()                           */
     241             : /************************************************************************/
     242             : 
     243           0 : void OGRPGeoTableLayer::ClearStatement()
     244             : 
     245             : {
     246           0 :     if (poStmt != nullptr)
     247             :     {
     248           0 :         delete poStmt;
     249           0 :         poStmt = nullptr;
     250             :     }
     251           0 : }
     252             : 
     253             : /************************************************************************/
     254             : /*                            GetStatement()                            */
     255             : /************************************************************************/
     256             : 
     257           0 : CPLODBCStatement *OGRPGeoTableLayer::GetStatement()
     258             : 
     259             : {
     260           0 :     if (poStmt == nullptr)
     261           0 :         ResetStatement();
     262             : 
     263           0 :     return poStmt;
     264             : }
     265             : 
     266             : /************************************************************************/
     267             : /*                           ResetStatement()                           */
     268             : /************************************************************************/
     269             : 
     270           0 : OGRErr OGRPGeoTableLayer::ResetStatement()
     271             : 
     272             : {
     273           0 :     ClearStatement();
     274             : 
     275           0 :     iNextShapeId = 0;
     276             : 
     277           0 :     poStmt = new CPLODBCStatement(poDS->GetSession(), m_nStatementFlags);
     278           0 :     poStmt->Append("SELECT * FROM ");
     279           0 :     poStmt->Append(poFeatureDefn->GetName());
     280           0 :     if (pszQuery != nullptr)
     281           0 :         poStmt->Appendf(" WHERE %s", pszQuery);
     282             : 
     283           0 :     if (poStmt->ExecuteSQL())
     284           0 :         return OGRERR_NONE;
     285             :     else
     286             :     {
     287           0 :         delete poStmt;
     288           0 :         poStmt = nullptr;
     289           0 :         return OGRERR_FAILURE;
     290             :     }
     291             : }
     292             : 
     293             : /************************************************************************/
     294             : /*                            ResetReading()                            */
     295             : /************************************************************************/
     296             : 
     297           0 : void OGRPGeoTableLayer::ResetReading()
     298             : 
     299             : {
     300           0 :     ClearStatement();
     301           0 :     OGRPGeoLayer::ResetReading();
     302           0 : }
     303             : 
     304             : /************************************************************************/
     305             : /*                             GetFeature()                             */
     306             : /************************************************************************/
     307             : 
     308           0 : OGRFeature *OGRPGeoTableLayer::GetFeature(GIntBig nFeatureId)
     309             : 
     310             : {
     311           0 :     if (pszFIDColumn == nullptr)
     312           0 :         return OGRPGeoLayer::GetFeature(nFeatureId);
     313             : 
     314           0 :     ClearStatement();
     315             : 
     316           0 :     iNextShapeId = nFeatureId;
     317             : 
     318           0 :     poStmt = new CPLODBCStatement(poDS->GetSession(), m_nStatementFlags);
     319           0 :     poStmt->Append("SELECT * FROM ");
     320           0 :     poStmt->Append(poFeatureDefn->GetName());
     321           0 :     poStmt->Appendf(" WHERE %s = " CPL_FRMT_GIB, pszFIDColumn, nFeatureId);
     322             : 
     323           0 :     if (!poStmt->ExecuteSQL())
     324             :     {
     325           0 :         delete poStmt;
     326           0 :         poStmt = nullptr;
     327           0 :         return nullptr;
     328             :     }
     329             : 
     330           0 :     return GetNextRawFeature();
     331             : }
     332             : 
     333             : /************************************************************************/
     334             : /*                         SetAttributeFilter()                         */
     335             : /************************************************************************/
     336             : 
     337           0 : OGRErr OGRPGeoTableLayer::SetAttributeFilter(const char *pszQueryIn)
     338             : 
     339             : {
     340           0 :     CPLFree(m_pszAttrQueryString);
     341           0 :     m_pszAttrQueryString = (pszQueryIn) ? CPLStrdup(pszQueryIn) : nullptr;
     342             : 
     343           0 :     if ((pszQueryIn == nullptr && pszQuery == nullptr) ||
     344           0 :         (pszQueryIn != nullptr && pszQuery != nullptr &&
     345           0 :          EQUAL(pszQueryIn, pszQuery)))
     346           0 :         return OGRERR_NONE;
     347             : 
     348           0 :     CPLFree(pszQuery);
     349           0 :     pszQuery = pszQueryIn ? CPLStrdup(pszQueryIn) : nullptr;
     350             : 
     351           0 :     ClearStatement();
     352             : 
     353           0 :     return OGRERR_NONE;
     354             : }
     355             : 
     356             : /************************************************************************/
     357             : /*                           TestCapability()                           */
     358             : /************************************************************************/
     359             : 
     360           0 : int OGRPGeoTableLayer::TestCapability(const char *pszCap)
     361             : 
     362             : {
     363           0 :     if (EQUAL(pszCap, OLCRandomRead))
     364           0 :         return TRUE;
     365             : 
     366           0 :     else if (EQUAL(pszCap, OLCFastFeatureCount))
     367           0 :         return m_poFilterGeom == nullptr && poDS->CountStarWorking();
     368             : 
     369           0 :     else if (EQUAL(pszCap, OLCFastSpatialFilter))
     370           0 :         return FALSE;
     371             : 
     372             :     else
     373           0 :         return OGRPGeoLayer::TestCapability(pszCap);
     374             : }
     375             : 
     376             : /************************************************************************/
     377             : /*                          GetFeatureCount()                           */
     378             : /*                                                                      */
     379             : /*      If a spatial filter is in effect, we turn control over to       */
     380             : /*      the generic counter.  Otherwise we return the total count.      */
     381             : /*      Eventually we should consider implementing a more efficient     */
     382             : /*      way of counting features matching a spatial query.              */
     383             : /************************************************************************/
     384             : 
     385           0 : GIntBig OGRPGeoTableLayer::GetFeatureCount(int bForce)
     386             : 
     387             : {
     388           0 :     if (m_poFilterGeom != nullptr || !poDS->CountStarWorking())
     389           0 :         return OGRPGeoLayer::GetFeatureCount(bForce);
     390             : 
     391           0 :     CPLODBCStatement oStmt(poDS->GetSession());
     392           0 :     oStmt.Append("SELECT COUNT(*) FROM ");
     393           0 :     oStmt.Append(poFeatureDefn->GetName());
     394             : 
     395           0 :     if (pszQuery != nullptr)
     396           0 :         oStmt.Appendf(" WHERE %s", pszQuery);
     397             : 
     398           0 :     if (!oStmt.ExecuteSQL() || !oStmt.Fetch())
     399             :     {
     400           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     401             :                  "GetFeatureCount() failed on query %s.\n%s",
     402           0 :                  oStmt.GetCommand(), poDS->GetSession()->GetLastError());
     403           0 :         return OGRPGeoLayer::GetFeatureCount(bForce);
     404             :     }
     405             : 
     406           0 :     return CPLAtoGIntBig(oStmt.GetColData(0));
     407             : }
     408             : 
     409             : /************************************************************************/
     410             : /*                             GetExtent()                              */
     411             : /************************************************************************/
     412             : 
     413           0 : OGRErr OGRPGeoTableLayer::GetExtent(OGREnvelope *psExtent,
     414             :                                     CPL_UNUSED int bForce)
     415             : {
     416           0 :     if (pszGeomColumn == nullptr)
     417             :     {
     418           0 :         return OGRERR_FAILURE;
     419             :     }
     420             : 
     421           0 :     *psExtent = sExtent;
     422           0 :     return OGRERR_NONE;
     423             : }

Generated by: LCOV version 1.14