LCOV - code coverage report
Current view: top level - apps - gdalalg_materialize.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 144 155 92.9 %
Date: 2025-09-10 17:48:50 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  gdal "materialize" pipeline step
       5             :  * Author:   Even Rouault <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2025, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "gdalalg_materialize.h"
      14             : #include "gdal_utils.h"
      15             : #include "gdal_priv.h"
      16             : #include "ogrsf_frmts.h"
      17             : 
      18             : //! @cond Doxygen_Suppress
      19             : 
      20             : #ifndef _
      21             : #define _(x) (x)
      22             : #endif
      23             : 
      24             : /************************************************************************/
      25             : /*                     GDALMaterializeRasterAlgorithm()                 */
      26             : /************************************************************************/
      27             : 
      28          56 : GDALMaterializeRasterAlgorithm::GDALMaterializeRasterAlgorithm()
      29             :     : GDALMaterializeStepAlgorithm<GDALRasterPipelineStepAlgorithm,
      30          56 :                                    GDAL_OF_RASTER>(HELP_URL)
      31             : {
      32             :     AddOutputDatasetArg(&m_outputDataset, GDAL_OF_RASTER,
      33             :                         /* positionalAndRequired = */ false,
      34          56 :                         _("Materialized dataset name"))
      35          56 :         .SetDatasetInputFlags(GADV_NAME);
      36             : 
      37          56 :     AddOutputFormatArg(&m_format)
      38             :         .AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES,
      39             :                          {GDAL_DCAP_RASTER, GDAL_DCAP_CREATECOPY,
      40         336 :                           GDAL_DCAP_OPEN, GDAL_DMD_EXTENSIONS})
      41         224 :         .AddMetadataItem(GAAMDI_ALLOWED_FORMATS, {"MEM", "COG"})
      42         112 :         .AddMetadataItem(GAAMDI_EXCLUDED_FORMATS, {"VRT"});
      43             : 
      44          56 :     AddCreationOptionsArg(&m_creationOptions);
      45          56 :     AddOverwriteArg(&m_overwrite);
      46          56 : }
      47             : 
      48             : /************************************************************************/
      49             : /*               GDALMaterializeRasterAlgorithm::RunStep()              */
      50             : /************************************************************************/
      51             : 
      52           6 : bool GDALMaterializeRasterAlgorithm::RunStep(GDALPipelineStepRunContext &ctxt)
      53             : {
      54           6 :     auto pfnProgress = ctxt.m_pfnProgress;
      55           6 :     auto pProgressData = ctxt.m_pProgressData;
      56             : 
      57           6 :     auto poSrcDS = m_inputDataset[0].GetDatasetRef();
      58           6 :     CPLAssert(poSrcDS);
      59           6 :     CPLAssert(!m_outputDataset.GetDatasetRef());
      60             : 
      61           6 :     if (m_format.empty())
      62           3 :         m_format = "GTiff";
      63             : 
      64           6 :     auto poDrv = GetGDALDriverManager()->GetDriverByName(m_format.c_str());
      65           6 :     if (!poDrv)
      66             :     {
      67           0 :         ReportError(CE_Failure, CPLE_AppDefined, "Driver %s does not exist",
      68             :                     m_format.c_str());
      69           0 :         return false;
      70             :     }
      71             : 
      72          12 :     std::string filename = m_outputDataset.GetName();
      73             :     const bool autoDeleteFile =
      74           6 :         filename.empty() && !EQUAL(m_format.c_str(), "MEM");
      75           6 :     if (autoDeleteFile)
      76             :     {
      77           4 :         filename = CPLGenerateTempFilenameSafe(nullptr);
      78             : 
      79           4 :         const char *pszExt = poDrv->GetMetadataItem(GDAL_DMD_EXTENSIONS);
      80           4 :         if (pszExt)
      81             :         {
      82           4 :             filename += '.';
      83           4 :             filename += CPLStringList(CSLTokenizeString(pszExt))[0];
      84             :         }
      85             :     }
      86             : 
      87          12 :     CPLStringList aosOptions(m_creationOptions);
      88           6 :     if (EQUAL(m_format.c_str(), "GTiff"))
      89             :     {
      90           3 :         if (aosOptions.FetchNameValue("TILED") == nullptr)
      91             :         {
      92           3 :             aosOptions.SetNameValue("TILED", "YES");
      93             :         }
      94           3 :         if (aosOptions.FetchNameValue("COPY_SRC_OVERVIEWS") == nullptr)
      95             :         {
      96           3 :             aosOptions.SetNameValue("COPY_SRC_OVERVIEWS", "YES");
      97             :         }
      98           3 :         if (aosOptions.FetchNameValue("COMPRESS") == nullptr)
      99             :         {
     100             :             const char *pszCOList =
     101           3 :                 poDrv->GetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST);
     102             :             aosOptions.SetNameValue(
     103             :                 "COMPRESS",
     104           3 :                 pszCOList && strstr(pszCOList, "ZSTD") ? "ZSTD" : "DEFLATE");
     105             :         }
     106             :     }
     107             : 
     108           6 :     if (autoDeleteFile)
     109             :     {
     110           4 :         aosOptions.SetNameValue("@SUPPRESS_ASAP", "YES");
     111             :     }
     112             : 
     113             :     auto poOutDS = std::unique_ptr<GDALDataset>(
     114           6 :         poDrv->CreateCopy(filename.c_str(), poSrcDS, false, aosOptions.List(),
     115           6 :                           pfnProgress, pProgressData));
     116           6 :     bool ok = poOutDS != nullptr && poOutDS->FlushCache() == CE_None;
     117           6 :     if (poOutDS)
     118             :     {
     119           6 :         if (poDrv->GetMetadataItem(GDAL_DCAP_REOPEN_AFTER_WRITE_REQUIRED))
     120             :         {
     121           0 :             ok = poOutDS->Close() == CE_None;
     122           0 :             poOutDS.reset();
     123           0 :             if (ok)
     124             :             {
     125           0 :                 const char *const apszAllowedDrivers[] = {m_format.c_str(),
     126           0 :                                                           nullptr};
     127           0 :                 poOutDS.reset(GDALDataset::Open(
     128             :                     filename.c_str(), GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR,
     129             :                     apszAllowedDrivers));
     130           0 :                 ok = poOutDS != nullptr;
     131             :             }
     132             :         }
     133           6 :         if (ok)
     134             :         {
     135           6 :             if (autoDeleteFile)
     136             :             {
     137             : #if !defined(_WIN32)
     138           4 :                 if (poDrv->GetMetadataItem(GDAL_DCAP_CAN_READ_AFTER_DELETE))
     139             :                 {
     140           4 :                     CPLErrorStateBackuper oBackuper(CPLQuietErrorHandler);
     141           4 :                     poDrv->Delete(poOutDS.get(),
     142           8 :                                   CPLStringList(poOutDS->GetFileList()).List());
     143             :                 }
     144             : #endif
     145           4 :                 poOutDS->MarkSuppressOnClose();
     146             :             }
     147             : 
     148           6 :             m_outputDataset.Set(std::move(poOutDS));
     149             :         }
     150             :     }
     151           6 :     return ok;
     152             : }
     153             : 
     154             : /************************************************************************/
     155             : /*                     GDALMaterializeVectorAlgorithm()                 */
     156             : /************************************************************************/
     157             : 
     158          54 : GDALMaterializeVectorAlgorithm::GDALMaterializeVectorAlgorithm()
     159             :     : GDALMaterializeStepAlgorithm<GDALVectorPipelineStepAlgorithm,
     160          54 :                                    GDAL_OF_VECTOR>(HELP_URL)
     161             : {
     162             :     AddOutputDatasetArg(&m_outputDataset, GDAL_OF_VECTOR,
     163             :                         /* positionalAndRequired = */ false,
     164          54 :                         _("Materialized dataset name"))
     165          54 :         .SetDatasetInputFlags(GADV_NAME);
     166             : 
     167          54 :     AddOutputFormatArg(&m_format)
     168             :         .AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES,
     169             :                          {GDAL_DCAP_VECTOR, GDAL_DCAP_CREATE, GDAL_DCAP_OPEN,
     170         324 :                           GDAL_DMD_EXTENSIONS})
     171         162 :         .AddMetadataItem(GAAMDI_ALLOWED_FORMATS, {"MEM"})
     172             :         .AddMetadataItem(GAAMDI_EXCLUDED_FORMATS,
     173         270 :                          {"MBTiles", "MVT", "PMTiles", "JP2ECW"});
     174             : 
     175          54 :     AddCreationOptionsArg(&m_creationOptions);
     176          54 :     AddLayerCreationOptionsArg(&m_layerCreationOptions);
     177          54 :     AddOverwriteArg(&m_overwrite);
     178          54 : }
     179             : 
     180             : /************************************************************************/
     181             : /*               GDALMaterializeVectorAlgorithm::RunStep()              */
     182             : /************************************************************************/
     183             : 
     184           8 : bool GDALMaterializeVectorAlgorithm::RunStep(GDALPipelineStepRunContext &ctxt)
     185             : {
     186           8 :     auto pfnProgress = ctxt.m_pfnProgress;
     187           8 :     auto pProgressData = ctxt.m_pProgressData;
     188             : 
     189           8 :     auto poSrcDS = m_inputDataset[0].GetDatasetRef();
     190           8 :     CPLAssert(poSrcDS);
     191           8 :     CPLAssert(!m_outputDataset.GetDatasetRef());
     192             : 
     193           8 :     if (m_format.empty())
     194             :     {
     195           4 :         bool bSeveralGeomFields = false;
     196           8 :         for (const auto *poLayer : poSrcDS->GetLayers())
     197             :         {
     198           4 :             if (!bSeveralGeomFields)
     199           4 :                 bSeveralGeomFields =
     200           4 :                     poLayer->GetLayerDefn()->GetGeomFieldCount() > 1;
     201           7 :             if (!bSeveralGeomFields &&
     202           3 :                 poLayer->GetLayerDefn()->GetGeomFieldCount() > 0)
     203             :             {
     204           7 :                 for (const auto *poFieldDefn :
     205          17 :                      poLayer->GetLayerDefn()->GetFields())
     206             :                 {
     207           7 :                     const auto eType = poFieldDefn->GetType();
     208           7 :                     if (eType == OFTStringList || eType == OFTIntegerList ||
     209           6 :                         eType == OFTRealList || eType == OFTInteger64List)
     210             :                     {
     211           1 :                         bSeveralGeomFields = true;
     212             :                     }
     213             :                 }
     214             :             }
     215             :         }
     216           4 :         m_format = bSeveralGeomFields ? "SQLite" : "GPKG";
     217             :     }
     218             : 
     219           8 :     auto poDrv = GetGDALDriverManager()->GetDriverByName(m_format.c_str());
     220           8 :     if (!poDrv)
     221             :     {
     222           0 :         ReportError(CE_Failure, CPLE_AppDefined, "Driver %s does not exist",
     223             :                     m_format.c_str());
     224           0 :         return false;
     225             :     }
     226             : 
     227          16 :     std::string filename = m_outputDataset.GetName();
     228             :     const bool autoDeleteFile =
     229           8 :         filename.empty() && !EQUAL(m_format.c_str(), "MEM");
     230           8 :     if (autoDeleteFile)
     231             :     {
     232           7 :         filename = CPLGenerateTempFilenameSafe(nullptr);
     233             : 
     234           7 :         const char *pszExt = poDrv->GetMetadataItem(GDAL_DMD_EXTENSIONS);
     235           7 :         if (pszExt)
     236             :         {
     237           7 :             filename += '.';
     238           7 :             filename += CPLStringList(CSLTokenizeString(pszExt))[0];
     239             :         }
     240             :     }
     241             : 
     242          16 :     CPLStringList aosOptions;
     243           8 :     aosOptions.AddString("--invoked-from-gdal-vector-convert");
     244           8 :     if (!m_overwrite)
     245             :     {
     246           8 :         aosOptions.AddString("--no-overwrite");
     247             :     }
     248             : 
     249           8 :     aosOptions.AddString("-of");
     250           8 :     aosOptions.AddString(m_format.c_str());
     251           9 :     for (const auto &co : m_creationOptions)
     252             :     {
     253           1 :         aosOptions.AddString("-dsco");
     254           1 :         aosOptions.AddString(co.c_str());
     255             :     }
     256           8 :     if (EQUAL(m_format.c_str(), "SQLite"))
     257             :     {
     258             :         const char *pszCOList =
     259           2 :             poDrv->GetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST);
     260           4 :         if (pszCOList && strstr(pszCOList, "SPATIALITE") &&
     261           4 :             CPLStringList(m_creationOptions).FetchNameValue("SPATIALITE") ==
     262             :                 nullptr)
     263             :         {
     264           1 :             aosOptions.AddString("-dsco");
     265           1 :             aosOptions.AddString("SPATIALITE=YES");
     266             :         }
     267             :     }
     268           9 :     for (const auto &co : m_layerCreationOptions)
     269             :     {
     270           1 :         aosOptions.AddString("-lco");
     271           1 :         aosOptions.AddString(co.c_str());
     272             :     }
     273           8 :     if (pfnProgress && pfnProgress != GDALDummyProgress)
     274             :     {
     275           1 :         aosOptions.AddString("-progress");
     276             :     }
     277             : 
     278           8 :     if (autoDeleteFile)
     279             :     {
     280           7 :         aosOptions.AddString("-dsco");
     281           7 :         aosOptions.AddString("@SUPPRESS_ASAP=YES");
     282             :     }
     283             : 
     284             :     GDALVectorTranslateOptions *psOptions =
     285           8 :         GDALVectorTranslateOptionsNew(aosOptions.List(), nullptr);
     286           8 :     GDALVectorTranslateOptionsSetProgress(psOptions, pfnProgress,
     287             :                                           pProgressData);
     288             : 
     289           8 :     GDALDatasetH hSrcDS = GDALDataset::ToHandle(poSrcDS);
     290             :     auto poOutDS = std::unique_ptr<GDALDataset>(
     291             :         GDALDataset::FromHandle(GDALVectorTranslate(
     292           8 :             filename.c_str(), nullptr, 1, &hSrcDS, psOptions, nullptr)));
     293           8 :     GDALVectorTranslateOptionsFree(psOptions);
     294             : 
     295           8 :     bool ok = poOutDS != nullptr && poOutDS->FlushCache() == CE_None;
     296           8 :     if (poOutDS)
     297             :     {
     298           8 :         if (poDrv->GetMetadataItem(GDAL_DCAP_REOPEN_AFTER_WRITE_REQUIRED))
     299             :         {
     300           2 :             ok = poOutDS->Close() == CE_None;
     301           2 :             poOutDS.reset();
     302           2 :             if (ok)
     303             :             {
     304           2 :                 const char *const apszAllowedDrivers[] = {m_format.c_str(),
     305           2 :                                                           nullptr};
     306           2 :                 poOutDS.reset(GDALDataset::Open(
     307             :                     filename.c_str(), GDAL_OF_VECTOR | GDAL_OF_VERBOSE_ERROR,
     308             :                     apszAllowedDrivers));
     309           2 :                 ok = poOutDS != nullptr;
     310             :             }
     311             :         }
     312           8 :         if (ok)
     313             :         {
     314           8 :             if (autoDeleteFile)
     315             :             {
     316             : #if !defined(_WIN32)
     317           7 :                 if (poDrv->GetMetadataItem(GDAL_DCAP_CAN_READ_AFTER_DELETE))
     318             :                 {
     319           6 :                     CPLErrorStateBackuper oBackuper(CPLQuietErrorHandler);
     320           6 :                     poDrv->Delete(poOutDS.get(),
     321          12 :                                   CPLStringList(poOutDS->GetFileList()).List());
     322             :                 }
     323             : #endif
     324           7 :                 poOutDS->MarkSuppressOnClose();
     325             :             }
     326             : 
     327           8 :             m_outputDataset.Set(std::move(poOutDS));
     328             :         }
     329             :     }
     330           8 :     return ok;
     331             : }
     332             : 
     333             : //! @endcond

Generated by: LCOV version 1.14