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

Generated by: LCOV version 1.14