LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/amigocloud - ogramigocloudlayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 220 0.0 %
Date: 2025-07-01 22:47:05 Functions: 0 13 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  AmigoCloud Translator
       4             :  * Purpose:  Implements OGRAmigoCloudLayer class.
       5             :  * Author:   Victor Chernetsky, <victor at amigocloud dot com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2015, Victor Chernetsky, <victor at amigocloud dot com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "ogr_amigocloud.h"
      14             : #include "ogr_p.h"
      15             : #include "ogrlibjsonutils.h"
      16             : 
      17             : OGRAmigoCloudGeomFieldDefn::~OGRAmigoCloudGeomFieldDefn() = default;
      18             : 
      19             : /************************************************************************/
      20             : /*                         OGRAmigoCloudLayer()                            */
      21             : /************************************************************************/
      22             : 
      23           0 : OGRAmigoCloudLayer::OGRAmigoCloudLayer(OGRAmigoCloudDataSource *poDSIn)
      24             :     : poDS(poDSIn), poFeatureDefn(nullptr), osFIDColName("amigo_id"),
      25             :       bEOF(FALSE), nFetchedObjects(-1), iNextInFetchedObjects(0), iNext(0),
      26           0 :       poCachedObj(nullptr)
      27             : {
      28           0 : }
      29             : 
      30             : /************************************************************************/
      31             : /*                         ~OGRAmigoCloudLayer()                           */
      32             : /************************************************************************/
      33             : 
      34           0 : OGRAmigoCloudLayer::~OGRAmigoCloudLayer()
      35             : 
      36             : {
      37           0 :     if (poCachedObj != nullptr)
      38           0 :         json_object_put(poCachedObj);
      39             : 
      40           0 :     if (poFeatureDefn != nullptr)
      41           0 :         poFeatureDefn->Release();
      42           0 : }
      43             : 
      44             : /************************************************************************/
      45             : /*                            ResetReading()                            */
      46             : /************************************************************************/
      47             : 
      48           0 : void OGRAmigoCloudLayer::ResetReading()
      49             : 
      50             : {
      51           0 :     if (poCachedObj != nullptr)
      52           0 :         json_object_put(poCachedObj);
      53           0 :     poCachedObj = nullptr;
      54           0 :     bEOF = FALSE;
      55           0 :     nFetchedObjects = -1;
      56           0 :     iNextInFetchedObjects = 0;
      57           0 :     iNext = 0;
      58           0 : }
      59             : 
      60             : /************************************************************************/
      61             : /*                           GetLayerDefn()                             */
      62             : /************************************************************************/
      63             : 
      64           0 : OGRFeatureDefn *OGRAmigoCloudLayer::GetLayerDefn()
      65             : {
      66           0 :     return GetLayerDefnInternal(nullptr);
      67             : }
      68             : 
      69             : /************************************************************************/
      70             : /*                            BuildFeature()                            */
      71             : /************************************************************************/
      72             : 
      73           0 : OGRFeature *OGRAmigoCloudLayer::BuildFeature(json_object *poRowObj)
      74             : {
      75           0 :     OGRFeature *poFeature = nullptr;
      76           0 :     if (poRowObj != nullptr &&
      77           0 :         json_object_get_type(poRowObj) == json_type_object)
      78             :     {
      79           0 :         poFeature = new OGRFeature(poFeatureDefn);
      80             : 
      81           0 :         if (!osFIDColName.empty())
      82             :         {
      83             :             json_object *poVal =
      84           0 :                 CPL_json_object_object_get(poRowObj, osFIDColName);
      85           0 :             if (poVal != nullptr &&
      86           0 :                 json_object_get_type(poVal) == json_type_string)
      87             :             {
      88           0 :                 std::string amigo_id = json_object_get_string(poVal);
      89           0 :                 OGRAmigoCloudFID aFID(amigo_id, iNext);
      90           0 :                 mFIDs[aFID.iFID] = aFID;
      91           0 :                 poFeature->SetFID(aFID.iFID);
      92             :             }
      93             :         }
      94             : 
      95           0 :         for (int i = 0; i < poFeatureDefn->GetFieldCount(); i++)
      96             :         {
      97           0 :             json_object *poVal = CPL_json_object_object_get(
      98           0 :                 poRowObj, poFeatureDefn->GetFieldDefn(i)->GetNameRef());
      99             : 
     100           0 :             if (poVal == nullptr)
     101             :             {
     102           0 :                 poFeature->SetFieldNull(i);
     103             :             }
     104           0 :             else if (json_object_get_type(poVal) == json_type_string)
     105             :             {
     106           0 :                 poFeature->SetField(i, json_object_get_string(poVal));
     107             :             }
     108           0 :             else if (json_object_get_type(poVal) == json_type_int ||
     109           0 :                      json_object_get_type(poVal) == json_type_boolean)
     110             :             {
     111           0 :                 poFeature->SetField(i, (GIntBig)json_object_get_int64(poVal));
     112             :             }
     113           0 :             else if (json_object_get_type(poVal) == json_type_double)
     114             :             {
     115           0 :                 poFeature->SetField(i, json_object_get_double(poVal));
     116             :             }
     117             :         }
     118             : 
     119           0 :         for (int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
     120             :         {
     121             :             OGRGeomFieldDefn *poGeomFldDefn =
     122           0 :                 poFeatureDefn->GetGeomFieldDefn(i);
     123           0 :             json_object *poVal = CPL_json_object_object_get(
     124             :                 poRowObj, poGeomFldDefn->GetNameRef());
     125           0 :             if (poVal != nullptr &&
     126           0 :                 json_object_get_type(poVal) == json_type_string)
     127             :             {
     128           0 :                 OGRGeometry *poGeom = OGRGeometryFromHexEWKB(
     129             :                     json_object_get_string(poVal), nullptr, FALSE);
     130           0 :                 if (poGeom != nullptr)
     131           0 :                     poGeom->assignSpatialReference(
     132           0 :                         poGeomFldDefn->GetSpatialRef());
     133           0 :                 poFeature->SetGeomFieldDirectly(i, poGeom);
     134             :             }
     135             :         }
     136             :     }
     137           0 :     return poFeature;
     138             : }
     139             : 
     140             : /************************************************************************/
     141             : /*                        FetchNewFeatures()                            */
     142             : /************************************************************************/
     143             : 
     144           0 : json_object *OGRAmigoCloudLayer::FetchNewFeatures(GIntBig iNextIn)
     145             : {
     146           0 :     CPLString osSQL = osBaseSQL;
     147           0 :     if (osSQL.ifind("SELECT") != std::string::npos &&
     148           0 :         osSQL.ifind(" LIMIT ") == std::string::npos)
     149             :     {
     150           0 :         osSQL += " LIMIT ";
     151           0 :         osSQL += CPLSPrintf("%d", GetFeaturesToFetch());
     152           0 :         osSQL += " OFFSET ";
     153           0 :         osSQL += CPLSPrintf(CPL_FRMT_GIB, iNextIn);
     154             :     }
     155           0 :     return poDS->RunSQL(osSQL);
     156             : }
     157             : 
     158             : /************************************************************************/
     159             : /*                       GetNextRawFeature()                            */
     160             : /************************************************************************/
     161             : 
     162           0 : OGRFeature *OGRAmigoCloudLayer::GetNextRawFeature()
     163             : {
     164           0 :     if (bEOF)
     165           0 :         return nullptr;
     166             : 
     167           0 :     if (iNextInFetchedObjects >= nFetchedObjects)
     168             :     {
     169           0 :         if (nFetchedObjects > 0 && nFetchedObjects < GetFeaturesToFetch())
     170             :         {
     171           0 :             bEOF = TRUE;
     172           0 :             return nullptr;
     173             :         }
     174             : 
     175           0 :         if (poFeatureDefn == nullptr && osBaseSQL.empty())
     176             :         {
     177           0 :             GetLayerDefn();
     178             :         }
     179             : 
     180           0 :         json_object *poObj = FetchNewFeatures(iNext);
     181           0 :         if (poObj == nullptr)
     182             :         {
     183           0 :             bEOF = TRUE;
     184           0 :             return nullptr;
     185             :         }
     186             : 
     187           0 :         if (poFeatureDefn == nullptr)
     188             :         {
     189           0 :             GetLayerDefnInternal(poObj);
     190             :         }
     191             : 
     192           0 :         json_object *poRows = CPL_json_object_object_get(poObj, "data");
     193             : 
     194           0 :         if (poRows == nullptr ||
     195           0 :             json_object_get_type(poRows) != json_type_array ||
     196           0 :             json_object_array_length(poRows) == 0)
     197             :         {
     198           0 :             json_object_put(poObj);
     199           0 :             bEOF = TRUE;
     200           0 :             return nullptr;
     201             :         }
     202             : 
     203           0 :         if (poCachedObj != nullptr)
     204           0 :             json_object_put(poCachedObj);
     205           0 :         poCachedObj = poObj;
     206             : 
     207           0 :         nFetchedObjects = static_cast<decltype(nFetchedObjects)>(
     208           0 :             json_object_array_length(poRows));
     209           0 :         iNextInFetchedObjects = 0;
     210             :     }
     211             : 
     212           0 :     json_object *poRows = CPL_json_object_object_get(poCachedObj, "data");
     213             :     json_object *poRowObj =
     214           0 :         json_object_array_get_idx(poRows, iNextInFetchedObjects);
     215             : 
     216           0 :     iNextInFetchedObjects++;
     217             : 
     218           0 :     OGRFeature *poFeature = BuildFeature(poRowObj);
     219             : 
     220             :     std::map<GIntBig, OGRAmigoCloudFID>::iterator it =
     221           0 :         mFIDs.find(poFeature->GetFID());
     222           0 :     if (it != mFIDs.end())
     223             :     {
     224           0 :         iNext = it->second.iIndex + 1;
     225             :     }
     226             : 
     227           0 :     return poFeature;
     228             : }
     229             : 
     230             : /************************************************************************/
     231             : /*                           GetNextFeature()                           */
     232             : /************************************************************************/
     233             : 
     234           0 : OGRFeature *OGRAmigoCloudLayer::GetNextFeature()
     235             : {
     236             :     while (true)
     237             :     {
     238           0 :         OGRFeature *poFeature = GetNextRawFeature();
     239           0 :         if (poFeature == nullptr)
     240           0 :             return nullptr;
     241             : 
     242           0 :         if ((m_poFilterGeom == nullptr ||
     243           0 :              FilterGeometry(poFeature->GetGeometryRef())) &&
     244           0 :             (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
     245             :         {
     246           0 :             return poFeature;
     247             :         }
     248             :         else
     249           0 :             delete poFeature;
     250           0 :     }
     251             : }
     252             : 
     253             : /************************************************************************/
     254             : /*                           TestCapability()                           */
     255             : /************************************************************************/
     256             : 
     257           0 : int OGRAmigoCloudLayer::TestCapability(const char *pszCap)
     258             : 
     259             : {
     260           0 :     if (EQUAL(pszCap, OLCStringsAsUTF8))
     261           0 :         return TRUE;
     262           0 :     else if (EQUAL(pszCap, OLCZGeometries))
     263           0 :         return TRUE;
     264           0 :     return FALSE;
     265             : }
     266             : 
     267             : /************************************************************************/
     268             : /*                          EstablishLayerDefn()                        */
     269             : /************************************************************************/
     270             : 
     271           0 : void OGRAmigoCloudLayer::EstablishLayerDefn(const char *pszLayerName,
     272             :                                             json_object *poObjIn)
     273             : {
     274           0 :     poFeatureDefn = new OGRFeatureDefn(pszLayerName);
     275           0 :     poFeatureDefn->Reference();
     276           0 :     poFeatureDefn->SetGeomType(wkbNone);
     277             : 
     278           0 :     CPLString osSQL;
     279           0 :     size_t nPos = osBaseSQL.ifind(" LIMIT ");
     280           0 :     if (nPos != std::string::npos)
     281             :     {
     282           0 :         osSQL = osBaseSQL;
     283           0 :         size_t nSize = osSQL.size();
     284           0 :         for (size_t i = nPos + strlen(" LIMIT "); i < nSize; i++)
     285             :         {
     286           0 :             if (osSQL[i] == ' ')
     287           0 :                 break;
     288           0 :             osSQL[i] = '0';
     289             :         }
     290             :     }
     291             :     else
     292           0 :         osSQL.Printf("%s LIMIT 0", osBaseSQL.c_str());
     293           0 :     json_object *poObj = poObjIn;
     294           0 :     if (poObj == nullptr)
     295             :     {
     296           0 :         poObj = poDS->RunSQL(osSQL);
     297           0 :         if (poObj == nullptr)
     298             :         {
     299           0 :             return;
     300             :         }
     301             :     }
     302             : 
     303           0 :     json_object *poFields = CPL_json_object_object_get(poObj, "columns");
     304           0 :     if (poFields == nullptr ||
     305           0 :         json_object_get_type(poFields) != json_type_array)
     306             :     {
     307           0 :         if (poObjIn == nullptr)
     308           0 :             json_object_put(poObj);
     309           0 :         return;
     310             :     }
     311             : 
     312           0 :     auto size = json_object_array_length(poFields);
     313             : 
     314           0 :     for (auto i = decltype(size){0}; i < size; i++)
     315             :     {
     316           0 :         json_object *obj = json_object_array_get_idx(poFields, i);
     317             : 
     318           0 :         if (obj != nullptr && json_object_get_type(obj) == json_type_object)
     319             :         {
     320           0 :             std::string fieldName;
     321           0 :             std::string fieldType;
     322             : 
     323             :             json_object_iter it;
     324           0 :             it.key = nullptr;
     325           0 :             it.val = nullptr;
     326           0 :             it.entry = nullptr;
     327           0 :             json_object_object_foreachC(obj, it)
     328             :             {
     329           0 :                 const char *pszColName = it.key;
     330           0 :                 if (it.val != nullptr)
     331             :                 {
     332           0 :                     if (EQUAL(pszColName, "name"))
     333             :                     {
     334           0 :                         fieldName = json_object_get_string(it.val);
     335             :                     }
     336           0 :                     else if (EQUAL(pszColName, "type"))
     337             :                     {
     338           0 :                         fieldType = json_object_get_string(it.val);
     339             :                     }
     340             :                 }
     341             :             }
     342           0 :             if (!fieldName.empty() && !fieldType.empty())
     343             :             {
     344           0 :                 if (EQUAL(fieldType.c_str(), "string") ||
     345           0 :                     EQUAL(fieldType.c_str(), "unknown(19)") /* name */)
     346             :                 {
     347           0 :                     OGRFieldDefn oFieldDefn(fieldName.c_str(), OFTString);
     348           0 :                     poFeatureDefn->AddFieldDefn(&oFieldDefn);
     349             :                 }
     350           0 :                 else if (EQUAL(fieldType.c_str(), "number") ||
     351           0 :                          EQUAL(fieldType.c_str(), "float") ||
     352           0 :                          EQUAL(fieldType.c_str(), "real"))
     353             :                 {
     354           0 :                     OGRFieldDefn oFieldDefn(fieldName.c_str(), OFTReal);
     355           0 :                     poFeatureDefn->AddFieldDefn(&oFieldDefn);
     356             :                 }
     357           0 :                 else if (EQUAL(fieldType.c_str(), "integer"))
     358             :                 {
     359           0 :                     OGRFieldDefn oFieldDefn(fieldName.c_str(), OFTInteger);
     360           0 :                     poFeatureDefn->AddFieldDefn(&oFieldDefn);
     361             :                 }
     362           0 :                 else if (EQUAL(fieldType.c_str(), "bigint"))
     363             :                 {
     364           0 :                     OGRFieldDefn oFieldDefn(fieldName.c_str(), OFTInteger64);
     365           0 :                     poFeatureDefn->AddFieldDefn(&oFieldDefn);
     366             :                 }
     367           0 :                 else if (EQUAL(fieldType.c_str(), "date"))
     368             :                 {
     369           0 :                     OGRFieldDefn oFieldDefn(fieldName.c_str(), OFTDate);
     370           0 :                     poFeatureDefn->AddFieldDefn(&oFieldDefn);
     371             :                 }
     372           0 :                 else if (EQUAL(fieldType.c_str(), "datetime"))
     373             :                 {
     374           0 :                     OGRFieldDefn oFieldDefn(fieldName.c_str(), OFTDateTime);
     375           0 :                     poFeatureDefn->AddFieldDefn(&oFieldDefn);
     376             :                 }
     377           0 :                 else if (EQUAL(fieldType.c_str(), "geometry"))
     378             :                 {
     379             :                     auto poFieldDefn =
     380             :                         std::make_unique<OGRAmigoCloudGeomFieldDefn>(
     381           0 :                             fieldName.c_str(), wkbUnknown);
     382             :                     OGRSpatialReference *poSRS =
     383           0 :                         GetSRS(fieldName.c_str(), &poFieldDefn->nSRID);
     384           0 :                     if (poSRS != nullptr)
     385             :                     {
     386           0 :                         poFieldDefn->SetSpatialRef(poSRS);
     387           0 :                         poSRS->Release();
     388             :                     }
     389           0 :                     poFeatureDefn->AddGeomFieldDefn(std::move(poFieldDefn));
     390             :                 }
     391           0 :                 else if (EQUAL(fieldType.c_str(), "boolean"))
     392             :                 {
     393           0 :                     OGRFieldDefn oFieldDefn(fieldName.c_str(), OFTInteger);
     394           0 :                     oFieldDefn.SetSubType(OFSTBoolean);
     395           0 :                     poFeatureDefn->AddFieldDefn(&oFieldDefn);
     396             :                 }
     397             :                 else
     398             :                 {
     399           0 :                     CPLDebug("AMIGOCLOUD",
     400             :                              "Unhandled type: %s. Defaulting to string",
     401             :                              fieldType.c_str());
     402           0 :                     OGRFieldDefn oFieldDefn(fieldName.c_str(), OFTString);
     403           0 :                     poFeatureDefn->AddFieldDefn(&oFieldDefn);
     404             :                 }
     405             :             }
     406             :         }
     407             :     }
     408           0 :     if (poObjIn == nullptr)
     409           0 :         json_object_put(poObj);
     410             : }
     411             : 
     412             : /************************************************************************/
     413             : /*                               GetSRS()                               */
     414             : /************************************************************************/
     415             : 
     416           0 : OGRSpatialReference *OGRAmigoCloudLayer::GetSRS(const char *pszGeomCol,
     417             :                                                 int *pnSRID)
     418             : {
     419           0 :     json_object *poObj = poDS->RunSQL(GetSRS_SQL(pszGeomCol));
     420           0 :     json_object *poRowObj = OGRAMIGOCLOUDGetSingleRow(poObj);
     421           0 :     if (poRowObj == nullptr)
     422             :     {
     423           0 :         if (poObj != nullptr)
     424           0 :             json_object_put(poObj);
     425           0 :         return nullptr;
     426             :     }
     427             : 
     428           0 :     json_object *poSRID = CPL_json_object_object_get(poRowObj, "srid");
     429           0 :     if (poSRID != nullptr && json_object_get_type(poSRID) == json_type_int)
     430             :     {
     431           0 :         *pnSRID = json_object_get_int(poSRID);
     432             :     }
     433             : 
     434           0 :     json_object *poSRTEXT = CPL_json_object_object_get(poRowObj, "srtext");
     435           0 :     OGRSpatialReference *poSRS = nullptr;
     436           0 :     if (poSRTEXT != nullptr &&
     437           0 :         json_object_get_type(poSRTEXT) == json_type_string)
     438             :     {
     439           0 :         const char *pszSRTEXT = json_object_get_string(poSRTEXT);
     440           0 :         poSRS = new OGRSpatialReference();
     441           0 :         poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     442           0 :         if (poSRS->importFromWkt(pszSRTEXT) != OGRERR_NONE)
     443             :         {
     444           0 :             delete poSRS;
     445           0 :             poSRS = nullptr;
     446             :         }
     447             :     }
     448           0 :     json_object_put(poObj);
     449             : 
     450           0 :     return poSRS;
     451             : }
     452             : 
     453             : /************************************************************************/
     454             : /*                             GetDataset()                             */
     455             : /************************************************************************/
     456             : 
     457           0 : GDALDataset *OGRAmigoCloudLayer::GetDataset()
     458             : {
     459           0 :     return poDS;
     460             : }

Generated by: LCOV version 1.14