LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/mssqlspatial - ogrmssqlspatiallayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 322 0.0 %
Date: 2026-03-05 10:33:42 Functions: 0 18 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  MSSQL Spatial driver
       4             :  * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
       5             :  * Author:   Tamas Szekeres, szekerest at gmail.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2010, Tamas Szekeres
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "ogr_mssqlspatial.h"
      14             : 
      15             : #include <algorithm>
      16             : 
      17             : /************************************************************************/
      18             : /*                        OGRMSSQLSpatialLayer()                        */
      19             : /************************************************************************/
      20             : 
      21           0 : OGRMSSQLSpatialLayer::OGRMSSQLSpatialLayer(OGRMSSQLSpatialDataSource *poDSIn)
      22           0 :     : poDS(poDSIn)
      23             : 
      24             : {
      25           0 : }
      26             : 
      27             : /************************************************************************/
      28             : /*                       ~OGRMSSQLSpatialLayer()                        */
      29             : /************************************************************************/
      30             : 
      31           0 : OGRMSSQLSpatialLayer::~OGRMSSQLSpatialLayer()
      32             : 
      33             : {
      34           0 :     if (m_nFeaturesRead > 0 && poFeatureDefn != nullptr)
      35             :     {
      36           0 :         CPLDebug("OGR_MSSQLSpatial", "%d features read on layer '%s'.",
      37           0 :                  static_cast<int>(m_nFeaturesRead), poFeatureDefn->GetName());
      38             :     }
      39             : 
      40           0 :     ClearStatement();
      41             : 
      42           0 :     CPLFree(pszGeomColumn);
      43           0 :     CPLFree(pszFIDColumn);
      44           0 :     CPLFree(panFieldOrdinals);
      45             : 
      46           0 :     if (poFeatureDefn)
      47             :     {
      48           0 :         poFeatureDefn->Release();
      49           0 :         poFeatureDefn = nullptr;
      50             :     }
      51             : 
      52           0 :     if (poSRS)
      53           0 :         poSRS->Release();
      54           0 : }
      55             : 
      56             : /************************************************************************/
      57             : /*                          BuildFeatureDefn()                          */
      58             : /*                                                                      */
      59             : /*      Build feature definition from a set of column definitions       */
      60             : /*      set on a statement.  Sift out geometry and FID fields.          */
      61             : /************************************************************************/
      62             : 
      63           0 : void OGRMSSQLSpatialLayer::BuildFeatureDefn(const char *pszLayerName,
      64             :                                             CPLODBCStatement *poStmtIn)
      65             : 
      66             : {
      67             :     bool bShowFidColumn =
      68           0 :         CPLTestBool(CPLGetConfigOption("MSSQLSPATIAL_SHOW_FID_COLUMN", "NO"));
      69             : 
      70           0 :     if (!poFeatureDefn)
      71             :     {
      72           0 :         poFeatureDefn = new OGRFeatureDefn(pszLayerName);
      73           0 :         poFeatureDefn->Reference();
      74             :     }
      75             :     else
      76             :     {
      77           0 :         for (int iFieldIdx = poFeatureDefn->GetFieldCount() - 1; iFieldIdx >= 0;
      78             :              --iFieldIdx)
      79             :         {
      80           0 :             poFeatureDefn->DeleteFieldDefn(iFieldIdx);
      81             :         }
      82           0 :         for (int iFieldIdx = poFeatureDefn->GetGeomFieldCount() - 1;
      83           0 :              iFieldIdx >= 0; --iFieldIdx)
      84             :         {
      85           0 :             poFeatureDefn->DeleteGeomFieldDefn(iFieldIdx);
      86             :         }
      87           0 :         poFeatureDefn->SetName(pszLayerName);
      88             :     }
      89             : 
      90           0 :     nRawColumns = poStmtIn->GetColCount();
      91             : 
      92           0 :     CPLFree(panFieldOrdinals);
      93           0 :     panFieldOrdinals = static_cast<int *>(CPLMalloc(sizeof(int) * nRawColumns));
      94             : 
      95           0 :     for (int iCol = 0; iCol < nRawColumns; iCol++)
      96             :     {
      97           0 :         if (pszGeomColumn == nullptr)
      98             :         {
      99             :             /* need to identify the geometry column */
     100           0 :             if (EQUAL(poStmtIn->GetColTypeName(iCol), "geometry"))
     101             :             {
     102           0 :                 nGeomColumnType = MSSQLCOLTYPE_GEOMETRY;
     103           0 :                 pszGeomColumn = CPLStrdup(poStmtIn->GetColName(iCol));
     104           0 :                 if (poFeatureDefn->GetGeomFieldCount() == 1)
     105             :                 {
     106           0 :                     poFeatureDefn->GetGeomFieldDefn(0)->SetNullable(
     107           0 :                         poStmtIn->GetColNullable(iCol));
     108           0 :                     poFeatureDefn->GetGeomFieldDefn(0)->SetName(pszGeomColumn);
     109             :                 }
     110           0 :                 nGeomColumnIndex = iCol;
     111           0 :                 continue;
     112             :             }
     113           0 :             else if (EQUAL(poStmtIn->GetColTypeName(iCol), "geography"))
     114             :             {
     115           0 :                 nGeomColumnType = MSSQLCOLTYPE_GEOGRAPHY;
     116           0 :                 pszGeomColumn = CPLStrdup(poStmtIn->GetColName(iCol));
     117           0 :                 if (poFeatureDefn->GetGeomFieldCount() == 1)
     118             :                 {
     119           0 :                     poFeatureDefn->GetGeomFieldDefn(0)->SetNullable(
     120           0 :                         poStmtIn->GetColNullable(iCol));
     121           0 :                     poFeatureDefn->GetGeomFieldDefn(0)->SetName(pszGeomColumn);
     122             :                 }
     123           0 :                 nGeomColumnIndex = iCol;
     124           0 :                 continue;
     125             :             }
     126             :         }
     127             :         else
     128             :         {
     129           0 :             if (EQUAL(poStmtIn->GetColName(iCol), pszGeomColumn))
     130             :             {
     131           0 :                 if (poFeatureDefn->GetGeomFieldCount() == 1)
     132             :                 {
     133           0 :                     poFeatureDefn->GetGeomFieldDefn(0)->SetNullable(
     134           0 :                         poStmtIn->GetColNullable(iCol));
     135           0 :                     poFeatureDefn->GetGeomFieldDefn(0)->SetName(pszGeomColumn);
     136             :                 }
     137           0 :                 nGeomColumnIndex = iCol;
     138           0 :                 continue;
     139             :             }
     140             :         }
     141             : 
     142           0 :         if (pszFIDColumn != nullptr)
     143             :         {
     144           0 :             if (EQUAL(poStmtIn->GetColName(iCol), pszFIDColumn))
     145             :             {
     146           0 :                 bool bIntegerFID = false;
     147           0 :                 switch (CPLODBCStatement::GetTypeMapping(
     148           0 :                     poStmtIn->GetColType(iCol)))
     149             :                 {
     150           0 :                     case SQL_C_SSHORT:
     151             :                     case SQL_C_USHORT:
     152             :                     case SQL_C_SLONG:
     153             :                     case SQL_C_ULONG:
     154             :                     case SQL_C_SBIGINT:
     155             :                     case SQL_C_UBIGINT:
     156           0 :                         bIntegerFID = true;
     157           0 :                         break;
     158           0 :                     default:
     159           0 :                         break;
     160             :                 }
     161           0 :                 if (!bIntegerFID)
     162             :                 {
     163           0 :                     CPLDebug(
     164             :                         "MSSQL",
     165             :                         "Ignoring FID column %s as it is of non integer type",
     166             :                         pszFIDColumn);
     167           0 :                     CPLFree(pszFIDColumn);
     168           0 :                     pszFIDColumn = nullptr;
     169             :                 }
     170             :                 else
     171             :                 {
     172           0 :                     if (STARTS_WITH_CI(poStmtIn->GetColTypeName(iCol),
     173             :                                        "bigint"))
     174           0 :                         SetMetadataItem(OLMD_FID64, "YES");
     175             : 
     176           0 :                     if (EQUAL(poStmtIn->GetColTypeName(iCol), "int identity") ||
     177           0 :                         EQUAL(poStmtIn->GetColTypeName(iCol),
     178             :                               "bigint identity"))
     179           0 :                         bIsIdentityFid = TRUE;
     180             : 
     181           0 :                     nFIDColumnIndex = iCol;
     182             : 
     183           0 :                     if (!bShowFidColumn)
     184           0 :                         continue;
     185             :                 }
     186             :             }
     187             :         }
     188             :         else
     189             :         {
     190           0 :             if (EQUAL(poStmtIn->GetColTypeName(iCol), "int identity"))
     191             :             {
     192           0 :                 pszFIDColumn = CPLStrdup(poStmtIn->GetColName(iCol));
     193           0 :                 bIsIdentityFid = TRUE;
     194           0 :                 nFIDColumnIndex = iCol;
     195             : 
     196           0 :                 if (!bShowFidColumn)
     197           0 :                     continue;
     198             :             }
     199           0 :             else if (EQUAL(poStmtIn->GetColTypeName(iCol), "bigint identity"))
     200             :             {
     201           0 :                 pszFIDColumn = CPLStrdup(poStmtIn->GetColName(iCol));
     202           0 :                 bIsIdentityFid = TRUE;
     203           0 :                 SetMetadataItem(OLMD_FID64, "YES");
     204           0 :                 nFIDColumnIndex = iCol;
     205             : 
     206           0 :                 if (!bShowFidColumn)
     207           0 :                     continue;
     208             :             }
     209             :         }
     210             : 
     211           0 :         OGRFieldDefn oField(poStmtIn->GetColName(iCol), OFTString);
     212             : 
     213           0 :         switch (CPLODBCStatement::GetTypeMapping(poStmtIn->GetColType(iCol)))
     214             :         {
     215           0 :             case SQL_C_SSHORT:
     216           0 :                 oField.SetType(OFTInteger);
     217           0 :                 oField.SetSubType(OFSTInt16);
     218           0 :                 break;
     219             : 
     220           0 :             case SQL_C_USHORT:
     221             :             case SQL_C_SLONG:
     222             :             case SQL_C_ULONG:
     223           0 :                 oField.SetType(OFTInteger);
     224           0 :                 break;
     225             : 
     226           0 :             case SQL_C_SBIGINT:
     227             :             case SQL_C_UBIGINT:
     228           0 :                 oField.SetType(OFTInteger64);
     229           0 :                 break;
     230             : 
     231           0 :             case SQL_C_BINARY:
     232           0 :                 oField.SetType(OFTBinary);
     233           0 :                 oField.SetWidth(std::max<int>(0, poStmtIn->GetColSize(iCol)));
     234           0 :                 break;
     235             : 
     236           0 :             case SQL_C_NUMERIC:
     237           0 :                 oField.SetType(OFTReal);
     238           0 :                 oField.SetPrecision(poStmtIn->GetColPrecision(iCol));
     239           0 :                 oField.SetWidth(std::max<int>(0, poStmtIn->GetColSize(iCol)));
     240           0 :                 if (oField.GetPrecision() == 0 && oField.GetWidth() <= 9)
     241           0 :                     oField.SetType(OFTInteger);
     242           0 :                 else if (oField.GetPrecision() == 0 && oField.GetWidth() <= 18)
     243           0 :                     oField.SetType(OFTInteger64);
     244           0 :                 break;
     245             : 
     246           0 :             case SQL_C_FLOAT:
     247           0 :                 oField.SetType(OFTReal);
     248           0 :                 oField.SetSubType(OFSTFloat32);
     249           0 :                 break;
     250             : 
     251           0 :             case SQL_C_DOUBLE:
     252           0 :                 oField.SetType(OFTReal);
     253           0 :                 break;
     254             : 
     255           0 :             case SQL_C_DATE:
     256           0 :                 oField.SetType(OFTDate);
     257           0 :                 break;
     258             : 
     259           0 :             case SQL_C_TIME:
     260           0 :                 oField.SetType(OFTTime);
     261           0 :                 break;
     262             : 
     263           0 :             case SQL_C_TIMESTAMP:
     264           0 :                 oField.SetType(OFTDateTime);
     265           0 :                 break;
     266             : 
     267           0 :             case SQL_C_GUID:
     268           0 :                 m_bHasUUIDColumn = true;
     269           0 :                 oField.SetType(OFTString);
     270           0 :                 oField.SetSubType(OFSTUUID);
     271           0 :                 break;
     272             : 
     273           0 :             default:
     274           0 :                 oField.SetWidth(std::max<int>(0, poStmtIn->GetColSize(iCol)));
     275             :                 /* leave it as OFTString */;
     276             :         }
     277             : 
     278           0 :         oField.SetNullable(poStmtIn->GetColNullable(iCol));
     279             : 
     280           0 :         if (poStmtIn->GetColColumnDef(iCol))
     281             :         {
     282             :             /* process default value specification */
     283           0 :             if (EQUAL(poStmtIn->GetColColumnDef(iCol), "(getdate())"))
     284           0 :                 oField.SetDefault("CURRENT_TIMESTAMP");
     285           0 :             else if (STARTS_WITH_CI(poStmtIn->GetColColumnDef(iCol),
     286             :                                     "(CONVERT([time],getdate()"))
     287           0 :                 oField.SetDefault("CURRENT_TIME");
     288           0 :             else if (STARTS_WITH_CI(poStmtIn->GetColColumnDef(iCol),
     289             :                                     "(CONVERT([date],getdate()"))
     290           0 :                 oField.SetDefault("CURRENT_DATE");
     291             :             else
     292             :             {
     293           0 :                 char *pszDefault = CPLStrdup(poStmtIn->GetColColumnDef(iCol));
     294           0 :                 int nLen = static_cast<int>(strlen(pszDefault));
     295           0 :                 if (nLen >= 1 && pszDefault[0] == '(' &&
     296           0 :                     pszDefault[nLen - 1] == ')')
     297             :                 {
     298             :                     // All default values are encapsulated in brackets
     299             :                     // by MSSQL server.
     300           0 :                     if (nLen >= 4 && pszDefault[1] == '(' &&
     301           0 :                         pszDefault[nLen - 2] == ')')
     302             :                     {
     303             :                         /* for numeric values double brackets are used */
     304           0 :                         pszDefault[nLen - 2] = '\0';
     305           0 :                         oField.SetDefault(pszDefault + 2);
     306             :                     }
     307             :                     else
     308             :                     {
     309           0 :                         pszDefault[nLen - 1] = '\0';
     310           0 :                         oField.SetDefault(pszDefault + 1);
     311             :                     }
     312             :                 }
     313             :                 else
     314           0 :                     oField.SetDefault(pszDefault);
     315             : 
     316           0 :                 CPLFree(pszDefault);
     317             :             }
     318             :         }
     319             : 
     320           0 :         poFeatureDefn->AddFieldDefn(&oField);
     321           0 :         panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol;
     322             :     }
     323             : 
     324             :     /* -------------------------------------------------------------------- */
     325             :     /*      If we don't already have an FID, check if there is a special    */
     326             :     /*      FID named column available.                                     */
     327             :     /* -------------------------------------------------------------------- */
     328           0 :     if (pszFIDColumn == nullptr)
     329             :     {
     330             :         const char *pszOGR_FID =
     331           0 :             CPLGetConfigOption("MSSQLSPATIAL_OGR_FID", "OGR_FID");
     332           0 :         if (poFeatureDefn->GetFieldIndex(pszOGR_FID) != -1)
     333           0 :             pszFIDColumn = CPLStrdup(pszOGR_FID);
     334             :     }
     335             : 
     336           0 :     if (pszFIDColumn != nullptr)
     337           0 :         CPLDebug("OGR_MSSQLSpatial", "Using column %s as FID for table %s.",
     338           0 :                  pszFIDColumn, poFeatureDefn->GetName());
     339             :     else
     340           0 :         CPLDebug("OGR_MSSQLSpatial", "Table %s has no identified FID column.",
     341           0 :                  poFeatureDefn->GetName());
     342           0 : }
     343             : 
     344             : /************************************************************************/
     345             : /*                           ClearStatement()                           */
     346             : /************************************************************************/
     347             : 
     348           0 : void OGRMSSQLSpatialLayer::ClearStatement()
     349             : 
     350             : {
     351           0 :     if (poStmt != nullptr)
     352             :     {
     353           0 :         delete poStmt;
     354           0 :         poStmt = nullptr;
     355             :     }
     356           0 : }
     357             : 
     358             : /************************************************************************/
     359             : /*                            ResetReading()                            */
     360             : /************************************************************************/
     361             : 
     362           0 : void OGRMSSQLSpatialLayer::ResetReading()
     363             : 
     364             : {
     365           0 :     if (m_bResetNeeded)
     366             :     {
     367           0 :         iNextShapeId = 0;
     368           0 :         ClearStatement();
     369           0 :         m_bEOF = false;
     370           0 :         m_bResetNeeded = false;
     371             :     }
     372           0 : }
     373             : 
     374             : /************************************************************************/
     375             : /*                           GetNextFeature()                           */
     376             : /************************************************************************/
     377             : 
     378           0 : OGRFeature *OGRMSSQLSpatialLayer::GetNextFeature()
     379             : 
     380             : {
     381           0 :     if (m_bEOF)
     382           0 :         return nullptr;
     383             : 
     384             :     while (true)
     385             :     {
     386             :         OGRFeature *poFeature;
     387             : 
     388           0 :         poFeature = GetNextRawFeature();
     389           0 :         if (poFeature == nullptr)
     390             :         {
     391           0 :             m_bEOF = true;
     392           0 :             return nullptr;
     393             :         }
     394             : 
     395           0 :         if ((m_poFilterGeom == nullptr ||
     396           0 :              FilterGeometry(poFeature->GetGeometryRef())) &&
     397           0 :             (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
     398           0 :             return poFeature;
     399             : 
     400           0 :         delete poFeature;
     401           0 :     }
     402             : }
     403             : 
     404             : /************************************************************************/
     405             : /*                         GetNextRawFeature()                          */
     406             : /************************************************************************/
     407             : 
     408           0 : OGRFeature *OGRMSSQLSpatialLayer::GetNextRawFeature()
     409             : 
     410             : {
     411           0 :     m_bResetNeeded = true;
     412           0 :     if (GetStatement() == nullptr)
     413           0 :         return nullptr;
     414             : 
     415             :     /* -------------------------------------------------------------------- */
     416             :     /*      If we are marked to restart then do so, and fetch a record.     */
     417             :     /* -------------------------------------------------------------------- */
     418           0 :     if (!poStmt->Fetch())
     419             :     {
     420           0 :         delete poStmt;
     421           0 :         poStmt = nullptr;
     422           0 :         return nullptr;
     423             :     }
     424             : 
     425             :     /* -------------------------------------------------------------------- */
     426             :     /*      Create a feature from the current result.                       */
     427             :     /* -------------------------------------------------------------------- */
     428           0 :     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
     429             : 
     430             :     const char *pszFID;
     431           0 :     if (pszFIDColumn != nullptr && poStmt->GetColId(pszFIDColumn) > -1 &&
     432           0 :         (pszFID = poStmt->GetColData(poStmt->GetColId(pszFIDColumn))) !=
     433             :             nullptr)
     434           0 :         poFeature->SetFID(CPLAtoGIntBig(pszFID));
     435             :     else
     436           0 :         poFeature->SetFID(iNextShapeId);
     437             : 
     438           0 :     iNextShapeId++;
     439           0 :     m_nFeaturesRead++;
     440             : 
     441             :     /* -------------------------------------------------------------------- */
     442             :     /*      Set the fields.                                                 */
     443             :     /* -------------------------------------------------------------------- */
     444           0 :     for (int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++)
     445             :     {
     446           0 :         if (poFeatureDefn->GetFieldDefn(iField)->IsIgnored())
     447           0 :             continue;
     448             : 
     449           0 :         int iSrcField = panFieldOrdinals[iField];
     450           0 :         const char *pszValue = poStmt->GetColData(iSrcField);
     451             : 
     452           0 :         if (pszValue == nullptr)
     453           0 :             poFeature->SetFieldNull(iField);
     454           0 :         else if (poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary)
     455           0 :             poFeature->SetField(iField, poStmt->GetColDataLength(iSrcField),
     456             :                                 reinterpret_cast<const GByte *>(pszValue));
     457             :         else
     458           0 :             poFeature->SetField(iField, pszValue);
     459             :     }
     460             : 
     461             :     /* -------------------------------------------------------------------- */
     462             :     /*      Try to extract a geometry.                                      */
     463             :     /* -------------------------------------------------------------------- */
     464           0 :     if (pszGeomColumn != nullptr && !poFeatureDefn->IsGeometryIgnored())
     465             :     {
     466           0 :         int iField = poStmt->GetColId(pszGeomColumn);
     467           0 :         const char *pszGeomText = poStmt->GetColData(iField);
     468           0 :         OGRGeometry *poGeom = nullptr;
     469           0 :         OGRErr eErr = OGRERR_NONE;
     470             : 
     471           0 :         if (pszGeomText != nullptr)
     472             :         {
     473           0 :             int nLength = poStmt->GetColDataLength(iField);
     474             : 
     475           0 :             if (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY ||
     476           0 :                 nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY ||
     477           0 :                 nGeomColumnType == MSSQLCOLTYPE_BINARY)
     478             :             {
     479           0 :                 switch (poDS->GetGeometryFormat())
     480             :                 {
     481           0 :                     case MSSQLGEOMETRY_NATIVE:
     482             :                     {
     483           0 :                         OGRMSSQLGeometryParser oParser(nGeomColumnType);
     484           0 :                         eErr = oParser.ParseSqlGeometry(
     485             :                             reinterpret_cast<const unsigned char *>(
     486             :                                 pszGeomText),
     487             :                             nLength, &poGeom);
     488           0 :                         nSRSId = oParser.GetSRSId();
     489             :                     }
     490           0 :                     break;
     491           0 :                     case MSSQLGEOMETRY_WKB:
     492             :                     case MSSQLGEOMETRY_WKBZM:
     493           0 :                         eErr = OGRGeometryFactory::createFromWkb(
     494             :                             pszGeomText, nullptr, &poGeom, nLength);
     495           0 :                         break;
     496           0 :                     case MSSQLGEOMETRY_WKT:
     497           0 :                         eErr = OGRGeometryFactory::createFromWkt(
     498             :                             pszGeomText, nullptr, &poGeom);
     499           0 :                         break;
     500           0 :                 }
     501             :             }
     502           0 :             else if (nGeomColumnType == MSSQLCOLTYPE_TEXT)
     503             :             {
     504           0 :                 eErr = OGRGeometryFactory::createFromWkt(pszGeomText, nullptr,
     505             :                                                          &poGeom);
     506             :             }
     507             :         }
     508             : 
     509           0 :         if (eErr != OGRERR_NONE)
     510             :         {
     511             :             const char *pszMessage;
     512             : 
     513           0 :             switch (eErr)
     514             :             {
     515           0 :                 case OGRERR_NOT_ENOUGH_DATA:
     516           0 :                     pszMessage = "Not enough data to deserialize";
     517           0 :                     break;
     518           0 :                 case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
     519           0 :                     pszMessage = "Unsupported geometry type";
     520           0 :                     break;
     521           0 :                 case OGRERR_CORRUPT_DATA:
     522           0 :                     pszMessage = "Corrupt data";
     523           0 :                     break;
     524           0 :                 default:
     525           0 :                     pszMessage = "Unrecognized error";
     526             :             }
     527           0 :             CPLError(CE_Failure, CPLE_AppDefined, "GetNextRawFeature(): %s",
     528             :                      pszMessage);
     529             :         }
     530             : 
     531           0 :         if (poGeom != nullptr)
     532             :         {
     533           0 :             if (GetSpatialRef())
     534           0 :                 poGeom->assignSpatialReference(poSRS);
     535             : 
     536           0 :             poFeature->SetGeometryDirectly(poGeom);
     537             :         }
     538             :     }
     539             : 
     540           0 :     return poFeature;
     541             : }
     542             : 
     543             : /************************************************************************/
     544             : /*                             GetFeature()                             */
     545             : /************************************************************************/
     546             : 
     547           0 : OGRFeature *OGRMSSQLSpatialLayer::GetFeature(GIntBig nFeatureId)
     548             : 
     549             : {
     550             :     /* This should be implemented directly! */
     551             : 
     552           0 :     return OGRLayer::GetFeature(nFeatureId);
     553             : }
     554             : 
     555             : /************************************************************************/
     556             : /*                           TestCapability()                           */
     557             : /************************************************************************/
     558             : 
     559           0 : int OGRMSSQLSpatialLayer::TestCapability(const char *) const
     560             : {
     561           0 :     return FALSE;
     562             : }
     563             : 
     564             : /************************************************************************/
     565             : /*                          StartTransaction()                          */
     566             : /************************************************************************/
     567             : 
     568           0 : OGRErr OGRMSSQLSpatialLayer::StartTransaction()
     569             : 
     570             : {
     571           0 :     if (!poDS->GetSession()->BeginTransaction())
     572             :     {
     573           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Failed to start transaction: %s",
     574           0 :                  poDS->GetSession()->GetLastError());
     575           0 :         return OGRERR_FAILURE;
     576             :     }
     577           0 :     return OGRERR_NONE;
     578             : }
     579             : 
     580             : /************************************************************************/
     581             : /*                         CommitTransaction()                          */
     582             : /************************************************************************/
     583             : 
     584           0 : OGRErr OGRMSSQLSpatialLayer::CommitTransaction()
     585             : 
     586             : {
     587           0 :     if (!poDS->GetSession()->CommitTransaction())
     588             :     {
     589           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     590             :                  "Failed to commit transaction: %s",
     591           0 :                  poDS->GetSession()->GetLastError());
     592           0 :         return OGRERR_FAILURE;
     593             :     }
     594           0 :     return OGRERR_NONE;
     595             : }
     596             : 
     597             : /************************************************************************/
     598             : /*                        RollbackTransaction()                         */
     599             : /************************************************************************/
     600             : 
     601           0 : OGRErr OGRMSSQLSpatialLayer::RollbackTransaction()
     602             : 
     603             : {
     604           0 :     if (!poDS->GetSession()->RollbackTransaction())
     605             :     {
     606           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     607             :                  "Failed to roll back transaction: %s",
     608           0 :                  poDS->GetSession()->GetLastError());
     609           0 :         return OGRERR_FAILURE;
     610             :     }
     611           0 :     return OGRERR_NONE;
     612             : }
     613             : 
     614             : /************************************************************************/
     615             : /*                           GetSpatialRef()                            */
     616             : /************************************************************************/
     617             : 
     618           0 : const OGRSpatialReference *OGRMSSQLSpatialLayer::GetSpatialRef() const
     619             : 
     620             : {
     621           0 :     if (poSRS == nullptr && nSRSId > 0)
     622             :     {
     623           0 :         poSRS = poDS->FetchSRS(nSRSId);
     624           0 :         if (poSRS != nullptr)
     625           0 :             poSRS->Reference();
     626             :         else
     627           0 :             nSRSId = 0;
     628             :     }
     629             : 
     630           0 :     return poSRS;
     631             : }
     632             : 
     633             : /************************************************************************/
     634             : /*                            GetFIDColumn()                            */
     635             : /************************************************************************/
     636             : 
     637           0 : const char *OGRMSSQLSpatialLayer::GetFIDColumn() const
     638             : 
     639             : {
     640           0 :     GetLayerDefn();
     641             : 
     642           0 :     if (pszFIDColumn != nullptr)
     643           0 :         return pszFIDColumn;
     644             :     else
     645           0 :         return "";
     646             : }
     647             : 
     648             : /************************************************************************/
     649             : /*                         GetGeometryColumn()                          */
     650             : /************************************************************************/
     651             : 
     652           0 : const char *OGRMSSQLSpatialLayer::GetGeometryColumn() const
     653             : 
     654             : {
     655           0 :     GetLayerDefn();
     656             : 
     657           0 :     if (pszGeomColumn != nullptr)
     658           0 :         return pszGeomColumn;
     659             :     else
     660           0 :         return "";
     661             : }
     662             : 
     663             : /************************************************************************/
     664             : /*                       GByteArrayToHexString()                        */
     665             : /************************************************************************/
     666             : 
     667           0 : char *OGRMSSQLSpatialLayer::GByteArrayToHexString(const GByte *pabyData,
     668             :                                                   int nLen)
     669             : {
     670           0 :     const size_t nTextBufLen = nLen * 2 + 3;
     671           0 :     char *pszTextBuf = static_cast<char *>(CPLMalloc(nTextBufLen));
     672             : 
     673           0 :     int iSrc, iDst = 0;
     674             : 
     675           0 :     for (iSrc = 0; iSrc < nLen; iSrc++)
     676             :     {
     677           0 :         if (iSrc == 0)
     678             :         {
     679           0 :             snprintf(pszTextBuf + iDst, nTextBufLen - iDst, "0x%02x",
     680           0 :                      pabyData[iSrc]);
     681           0 :             iDst += 4;
     682             :         }
     683             :         else
     684             :         {
     685           0 :             snprintf(pszTextBuf + iDst, nTextBufLen - iDst, "%02x",
     686           0 :                      pabyData[iSrc]);
     687           0 :             iDst += 2;
     688             :         }
     689             :     }
     690           0 :     pszTextBuf[iDst] = 0;
     691             : 
     692           0 :     return pszTextBuf;
     693             : }
     694             : 
     695             : /************************************************************************/
     696             : /*                             GetDataset()                             */
     697             : /************************************************************************/
     698             : 
     699           0 : GDALDataset *OGRMSSQLSpatialLayer::GetDataset()
     700             : {
     701           0 :     return poDS;
     702             : }

Generated by: LCOV version 1.14