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

Generated by: LCOV version 1.14