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

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implements OGRODBCLayer 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) 2003, Frank Warmerdam <warmerdam@pobox.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_odbc.h"
      32             : #include "cpl_string.h"
      33             : 
      34             : /************************************************************************/
      35             : /*                            OGRODBCLayer()                            */
      36             : /************************************************************************/
      37             : 
      38           0 : OGRODBCLayer::OGRODBCLayer()
      39             :     : poFeatureDefn(nullptr), poStmt(nullptr), poSRS(nullptr),
      40             :       nSRSId(-2),  // Have not queried the database for it yet.
      41             :       iNextShapeId(0), poDS(nullptr), bGeomColumnWKB(FALSE),
      42           0 :       pszGeomColumn(nullptr), pszFIDColumn(nullptr), panFieldOrdinals(nullptr)
      43             : {
      44           0 : }
      45             : 
      46             : /************************************************************************/
      47             : /*                            ~OGRODBCLayer()                             */
      48             : /************************************************************************/
      49             : 
      50           0 : OGRODBCLayer::~OGRODBCLayer()
      51             : 
      52             : {
      53           0 :     if (m_nFeaturesRead > 0 && poFeatureDefn != nullptr)
      54             :     {
      55           0 :         CPLDebug("OGR_ODBC", "%d features read on layer '%s'.",
      56           0 :                  (int)m_nFeaturesRead, poFeatureDefn->GetName());
      57             :     }
      58             : 
      59           0 :     if (poStmt)
      60             :     {
      61           0 :         delete poStmt;
      62           0 :         poStmt = nullptr;
      63             :     }
      64             : 
      65           0 :     if (pszGeomColumn)
      66           0 :         CPLFree(pszGeomColumn);
      67             : 
      68           0 :     if (panFieldOrdinals)
      69           0 :         CPLFree(panFieldOrdinals);
      70             : 
      71           0 :     if (poFeatureDefn)
      72             :     {
      73           0 :         poFeatureDefn->Release();
      74           0 :         poFeatureDefn = nullptr;
      75             :     }
      76             : 
      77           0 :     if (poSRS)
      78           0 :         poSRS->Release();
      79           0 : }
      80             : 
      81             : /************************************************************************/
      82             : /*                          BuildFeatureDefn()                          */
      83             : /*                                                                      */
      84             : /*      Build feature definition from a set of column definitions       */
      85             : /*      set on a statement.  Sift out geometry and FID fields.          */
      86             : /************************************************************************/
      87             : 
      88           0 : CPLErr OGRODBCLayer::BuildFeatureDefn(const char *pszLayerName,
      89             :                                       CPLODBCStatement *poStmtIn)
      90             : 
      91             : {
      92           0 :     poFeatureDefn = new OGRFeatureDefn(pszLayerName);
      93           0 :     SetDescription(poFeatureDefn->GetName());
      94           0 :     int nRawColumns = poStmtIn->GetColCount();
      95             : 
      96           0 :     poFeatureDefn->Reference();
      97             : 
      98           0 :     panFieldOrdinals = (int *)CPLMalloc(sizeof(int) * nRawColumns);
      99             : 
     100           0 :     for (int iCol = 0; iCol < nRawColumns; iCol++)
     101             :     {
     102           0 :         OGRFieldDefn oField(poStmtIn->GetColName(iCol), OFTString);
     103             : 
     104           0 :         oField.SetWidth(MAX(0, poStmtIn->GetColSize(iCol)));
     105             : 
     106           0 :         if (pszGeomColumn != nullptr &&
     107           0 :             EQUAL(poStmtIn->GetColName(iCol), pszGeomColumn))
     108           0 :             continue;
     109             : 
     110           0 :         switch (CPLODBCStatement::GetTypeMapping(poStmtIn->GetColType(iCol)))
     111             :         {
     112           0 :             case SQL_C_SSHORT:
     113             :             case SQL_C_USHORT:
     114             :             case SQL_C_SLONG:
     115             :             case SQL_C_ULONG:
     116           0 :                 oField.SetType(OFTInteger);
     117           0 :                 break;
     118             : 
     119           0 :             case SQL_C_SBIGINT:
     120             :             case SQL_C_UBIGINT:
     121           0 :                 oField.SetType(OFTInteger64);
     122           0 :                 break;
     123             : 
     124           0 :             case SQL_C_BINARY:
     125           0 :                 oField.SetType(OFTBinary);
     126           0 :                 break;
     127             : 
     128           0 :             case SQL_C_NUMERIC:
     129           0 :                 oField.SetType(OFTReal);
     130           0 :                 oField.SetPrecision(poStmtIn->GetColPrecision(iCol));
     131           0 :                 break;
     132             : 
     133           0 :             case SQL_C_FLOAT:
     134             :             case SQL_C_DOUBLE:
     135           0 :                 oField.SetType(OFTReal);
     136           0 :                 oField.SetWidth(0);
     137           0 :                 break;
     138             : 
     139           0 :             case SQL_C_DATE:
     140           0 :                 oField.SetType(OFTDate);
     141           0 :                 break;
     142             : 
     143           0 :             case SQL_C_TIME:
     144           0 :                 oField.SetType(OFTTime);
     145           0 :                 break;
     146             : 
     147           0 :             case SQL_C_TIMESTAMP:
     148             :             case SQL_C_TYPE_TIMESTAMP:
     149           0 :                 oField.SetType(OFTDateTime);
     150           0 :                 break;
     151             : 
     152           0 :             default:
     153             :                 /* leave it as OFTString */;
     154             :         }
     155             : 
     156           0 :         poFeatureDefn->AddFieldDefn(&oField);
     157           0 :         panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol + 1;
     158             :     }
     159             : 
     160             :     /* -------------------------------------------------------------------- */
     161             :     /*      If we don't already have an FID, check if there is a special    */
     162             :     /*      FID named column available.                                     */
     163             :     /* -------------------------------------------------------------------- */
     164           0 :     if (pszFIDColumn == nullptr)
     165             :     {
     166           0 :         const char *pszOGR_FID = CPLGetConfigOption("ODBC_OGR_FID", "OGR_FID");
     167           0 :         if (poFeatureDefn->GetFieldIndex(pszOGR_FID) != -1)
     168           0 :             pszFIDColumn = CPLStrdup(pszOGR_FID);
     169             :     }
     170             : 
     171           0 :     if (pszFIDColumn != nullptr)
     172           0 :         CPLDebug("OGR_ODBC", "Using column %s as FID for table %s.",
     173           0 :                  pszFIDColumn, poFeatureDefn->GetName());
     174             :     else
     175           0 :         CPLDebug("OGR_ODBC", "Table %s has no identified FID column.",
     176           0 :                  poFeatureDefn->GetName());
     177             : 
     178           0 :     return CE_None;
     179             : }
     180             : 
     181             : /************************************************************************/
     182             : /*                            ResetReading()                            */
     183             : /************************************************************************/
     184             : 
     185           0 : void OGRODBCLayer::ResetReading()
     186             : 
     187             : {
     188           0 :     iNextShapeId = 0;
     189           0 :     m_bEOF = false;
     190           0 : }
     191             : 
     192             : /************************************************************************/
     193             : /*                           GetNextFeature()                           */
     194             : /************************************************************************/
     195             : 
     196           0 : OGRFeature *OGRODBCLayer::GetNextFeature()
     197             : 
     198             : {
     199             :     while (true)
     200             :     {
     201           0 :         OGRFeature *poFeature = GetNextRawFeature();
     202           0 :         if (poFeature == nullptr)
     203           0 :             return nullptr;
     204             : 
     205           0 :         if ((m_poFilterGeom == nullptr ||
     206           0 :              FilterGeometry(poFeature->GetGeometryRef())) &&
     207           0 :             (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
     208           0 :             return poFeature;
     209             : 
     210           0 :         delete poFeature;
     211           0 :     }
     212             : }
     213             : 
     214             : /************************************************************************/
     215             : /*                         GetNextRawFeature()                          */
     216             : /************************************************************************/
     217             : 
     218           0 : OGRFeature *OGRODBCLayer::GetNextRawFeature()
     219             : 
     220             : {
     221           0 :     if (m_bEOF || GetStatement() == nullptr)
     222           0 :         return nullptr;
     223             : 
     224             :     /* -------------------------------------------------------------------- */
     225             :     /*      If we are marked to restart then do so, and fetch a record.     */
     226             :     /* -------------------------------------------------------------------- */
     227           0 :     if (!poStmt->Fetch())
     228             :     {
     229           0 :         delete poStmt;
     230           0 :         poStmt = nullptr;
     231           0 :         m_bEOF = true;
     232           0 :         return nullptr;
     233             :     }
     234             : 
     235             :     /* -------------------------------------------------------------------- */
     236             :     /*      Create a feature from the current result.                       */
     237             :     /* -------------------------------------------------------------------- */
     238           0 :     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
     239             : 
     240           0 :     if (pszFIDColumn != nullptr && poStmt->GetColId(pszFIDColumn) > -1)
     241           0 :         poFeature->SetFID(
     242           0 :             atoi(poStmt->GetColData(poStmt->GetColId(pszFIDColumn))));
     243             :     else
     244           0 :         poFeature->SetFID(iNextShapeId);
     245             : 
     246           0 :     iNextShapeId++;
     247           0 :     m_nFeaturesRead++;
     248             : 
     249             :     /* -------------------------------------------------------------------- */
     250             :     /*      Set the fields.                                                 */
     251             :     /* -------------------------------------------------------------------- */
     252           0 :     for (int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++)
     253             :     {
     254             :         const OGRFieldType eType =
     255           0 :             poFeatureDefn->GetFieldDefn(iField)->GetType();
     256           0 :         int iSrcField = panFieldOrdinals[iField] - 1;
     257             : 
     258           0 :         if (eType == OFTReal &&
     259           0 :             (poStmt->Flags() &
     260             :              CPLODBCStatement::Flag::RetrieveNumericColumnsAsDouble))
     261             :         {
     262             :             // for OFTReal fields we retrieve the value directly as a double
     263             :             // to avoid loss of precision associated with double/float->string
     264             :             // conversion
     265           0 :             const double dfValue = poStmt->GetColDataAsDouble(iSrcField);
     266           0 :             if (std::isnan(dfValue))
     267             :             {
     268           0 :                 poFeature->SetFieldNull(iField);
     269             :             }
     270             :             else
     271             :             {
     272           0 :                 poFeature->SetField(iField, dfValue);
     273             :             }
     274             :         }
     275             :         else
     276             :         {
     277           0 :             const char *pszValue = poStmt->GetColData(iSrcField);
     278             : 
     279           0 :             if (pszValue == nullptr)
     280           0 :                 poFeature->SetFieldNull(iField);
     281           0 :             else if (poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary)
     282           0 :                 poFeature->SetField(iField, poStmt->GetColDataLength(iSrcField),
     283             :                                     (GByte *)pszValue);
     284             :             else
     285           0 :                 poFeature->SetField(iField, pszValue);
     286             :         }
     287             :     }
     288             : 
     289             :     /* -------------------------------------------------------------------- */
     290             :     /*      Try to extract a geometry.                                      */
     291             :     /* -------------------------------------------------------------------- */
     292           0 :     if (pszGeomColumn != nullptr)
     293             :     {
     294           0 :         int iField = poStmt->GetColId(pszGeomColumn);
     295           0 :         const char *pszGeomText = poStmt->GetColData(iField);
     296           0 :         OGRGeometry *poGeom = nullptr;
     297           0 :         OGRErr eErr = OGRERR_NONE;
     298             : 
     299           0 :         if (pszGeomText != nullptr && !bGeomColumnWKB)
     300             :         {
     301           0 :             eErr = OGRGeometryFactory::createFromWkt(pszGeomText, nullptr,
     302             :                                                      &poGeom);
     303             :         }
     304           0 :         else if (pszGeomText != nullptr && bGeomColumnWKB)
     305             :         {
     306           0 :             int nLength = poStmt->GetColDataLength(iField);
     307             : 
     308           0 :             eErr = OGRGeometryFactory::createFromWkb(pszGeomText, nullptr,
     309             :                                                      &poGeom, nLength);
     310             :         }
     311             : 
     312           0 :         if (eErr != OGRERR_NONE)
     313             :         {
     314           0 :             const char *pszMessage = nullptr;
     315             : 
     316           0 :             switch (eErr)
     317             :             {
     318           0 :                 case OGRERR_NOT_ENOUGH_DATA:
     319           0 :                     pszMessage = "Not enough data to deserialize";
     320           0 :                     break;
     321           0 :                 case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
     322           0 :                     pszMessage = "Unsupported geometry type";
     323           0 :                     break;
     324           0 :                 case OGRERR_CORRUPT_DATA:
     325           0 :                     pszMessage = "Corrupt data";
     326           0 :                     break;
     327           0 :                 default:
     328           0 :                     pszMessage = "Unrecognized error";
     329             :             }
     330           0 :             CPLError(CE_Failure, CPLE_AppDefined, "GetNextRawFeature(): %s",
     331             :                      pszMessage);
     332             :         }
     333             : 
     334           0 :         if (poGeom != nullptr)
     335           0 :             poFeature->SetGeometryDirectly(poGeom);
     336             :     }
     337             : 
     338           0 :     return poFeature;
     339             : }
     340             : 
     341             : /************************************************************************/
     342             : /*                             GetFeature()                             */
     343             : /************************************************************************/
     344             : 
     345           0 : OGRFeature *OGRODBCLayer::GetFeature(GIntBig nFeatureId)
     346             : 
     347             : {
     348             :     /* This should be implemented directly! */
     349             : 
     350           0 :     return OGRLayer::GetFeature(nFeatureId);
     351             : }
     352             : 
     353             : /************************************************************************/
     354             : /*                           TestCapability()                           */
     355             : /************************************************************************/
     356             : 
     357           0 : int OGRODBCLayer::TestCapability(CPL_UNUSED const char *pszCap)
     358             : {
     359           0 :     return FALSE;
     360             : }
     361             : 
     362             : /************************************************************************/
     363             : /*                           GetSpatialRef()                            */
     364             : /************************************************************************/
     365             : 
     366           0 : OGRSpatialReference *OGRODBCLayer::GetSpatialRef()
     367             : 
     368             : {
     369           0 :     return poSRS;
     370             : }

Generated by: LCOV version 1.14