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

Generated by: LCOV version 1.14