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

Generated by: LCOV version 1.14