LCOV - code coverage report
Current view: top level - frmts/rasterlite - rasterlitecreatecopy.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 235 324 72.5 %
Date: 2024-11-21 22:18:42 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Rasterlite driver
       4             :  * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
       5             :  * Author:   Even Rouault, <even dot rouault at spatialys.com>
       6             :  *
       7             :  **********************************************************************
       8             :  * Copyright (c) 2009-2012, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "cpl_string.h"
      14             : #include "ogr_api.h"
      15             : #include "ogr_srs_api.h"
      16             : #include "memdataset.h"
      17             : 
      18             : #include "rasterlitedataset.h"
      19             : 
      20             : /************************************************************************/
      21             : /*                  RasterliteGetTileDriverOptions ()                   */
      22             : /************************************************************************/
      23             : 
      24          62 : static char **RasterliteAddTileDriverOptionsForDriver(
      25             :     CSLConstList papszOptions, char **papszTileDriverOptions,
      26             :     const char *pszOptionName, const char *pszExpectedDriverName)
      27             : {
      28          62 :     const char *pszVal = CSLFetchNameValue(papszOptions, pszOptionName);
      29          62 :     if (pszVal)
      30             :     {
      31             :         const char *pszDriverName =
      32           0 :             CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
      33           0 :         if (EQUAL(pszDriverName, pszExpectedDriverName))
      34             :         {
      35             :             papszTileDriverOptions =
      36           0 :                 CSLSetNameValue(papszTileDriverOptions, pszOptionName, pszVal);
      37             :         }
      38             :         else
      39             :         {
      40           0 :             CPLError(CE_Warning, CPLE_NotSupported,
      41             :                      "Unexpected option '%s' for driver '%s'", pszOptionName,
      42             :                      pszDriverName);
      43             :         }
      44             :     }
      45          62 :     return papszTileDriverOptions;
      46             : }
      47             : 
      48          31 : char **RasterliteGetTileDriverOptions(CSLConstList papszOptions)
      49             : {
      50             :     const char *pszDriverName =
      51          31 :         CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
      52             : 
      53          31 :     char **papszTileDriverOptions = nullptr;
      54             : 
      55          31 :     const char *pszQuality = CSLFetchNameValue(papszOptions, "QUALITY");
      56          31 :     if (pszQuality)
      57             :     {
      58           0 :         if (EQUAL(pszDriverName, "GTiff"))
      59             :         {
      60           0 :             papszTileDriverOptions = CSLSetNameValue(
      61             :                 papszTileDriverOptions, "JPEG_QUALITY", pszQuality);
      62             :         }
      63           0 :         else if (EQUAL(pszDriverName, "JPEG") || EQUAL(pszDriverName, "WEBP"))
      64             :         {
      65           0 :             papszTileDriverOptions =
      66           0 :                 CSLSetNameValue(papszTileDriverOptions, "QUALITY", pszQuality);
      67             :         }
      68             :         else
      69             :         {
      70           0 :             CPLError(CE_Warning, CPLE_NotSupported,
      71             :                      "Unexpected option '%s' for driver '%s'", "QUALITY",
      72             :                      pszDriverName);
      73             :         }
      74             :     }
      75             : 
      76          31 :     papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
      77             :         papszOptions, papszTileDriverOptions, "COMPRESS", "GTiff");
      78          31 :     papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
      79             :         papszOptions, papszTileDriverOptions, "PHOTOMETRIC", "GTiff");
      80             : 
      81          31 :     return papszTileDriverOptions;
      82             : }
      83             : 
      84             : /************************************************************************/
      85             : /*                      RasterliteInsertSRID ()                         */
      86             : /************************************************************************/
      87             : 
      88          28 : static int RasterliteInsertSRID(GDALDatasetH hDS, const char *pszWKT)
      89             : {
      90          28 :     int nAuthorityCode = 0;
      91          56 :     CPLString osAuthorityName, osProjCS, osProj4;
      92          28 :     if (pszWKT != nullptr && strlen(pszWKT) != 0)
      93             :     {
      94          28 :         OGRSpatialReferenceH hSRS = OSRNewSpatialReference(pszWKT);
      95          28 :         if (hSRS)
      96             :         {
      97          28 :             OSRSetAxisMappingStrategy(hSRS, OAMS_TRADITIONAL_GIS_ORDER);
      98             : 
      99          28 :             const char *pszAuthorityName = OSRGetAuthorityName(hSRS, nullptr);
     100          28 :             if (pszAuthorityName)
     101           3 :                 osAuthorityName = pszAuthorityName;
     102             : 
     103          28 :             const char *pszProjCS = OSRGetAttrValue(hSRS, "PROJCS", 0);
     104          28 :             if (pszProjCS)
     105           3 :                 osProjCS = pszProjCS;
     106             : 
     107          28 :             const char *pszAuthorityCode = OSRGetAuthorityCode(hSRS, nullptr);
     108          28 :             if (pszAuthorityCode)
     109           3 :                 nAuthorityCode = atoi(pszAuthorityCode);
     110             : 
     111          28 :             char *pszProj4 = nullptr;
     112          28 :             if (OSRExportToProj4(hSRS, &pszProj4) != OGRERR_NONE)
     113             :             {
     114           0 :                 CPLFree(pszProj4);
     115           0 :                 pszProj4 = CPLStrdup("");
     116             :             }
     117          28 :             osProj4 = pszProj4;
     118          28 :             CPLFree(pszProj4);
     119             :         }
     120          28 :         OSRDestroySpatialReference(hSRS);
     121             :     }
     122             : 
     123          28 :     CPLString osSQL;
     124          28 :     int nSRSId = -1;
     125          28 :     if (nAuthorityCode != 0 && !osAuthorityName.empty())
     126             :     {
     127             :         osSQL.Printf("SELECT srid FROM spatial_ref_sys WHERE auth_srid = %d",
     128           3 :                      nAuthorityCode);
     129             :         OGRLayerH hLyr =
     130           3 :             GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     131           3 :         if (hLyr == nullptr)
     132             :         {
     133           0 :             nSRSId = nAuthorityCode;
     134             : 
     135           0 :             if (!osProjCS.empty())
     136             :                 osSQL.Printf(
     137             :                     "INSERT INTO spatial_ref_sys "
     138             :                     "(srid, auth_name, auth_srid, ref_sys_name, proj4text) "
     139             :                     "VALUES (%d, '%s', '%d', '%s', '%s')",
     140             :                     nSRSId, osAuthorityName.c_str(), nAuthorityCode,
     141           0 :                     osProjCS.c_str(), osProj4.c_str());
     142             :             else
     143             :                 osSQL.Printf("INSERT INTO spatial_ref_sys "
     144             :                              "(srid, auth_name, auth_srid, proj4text) "
     145             :                              "VALUES (%d, '%s', '%d', '%s')",
     146             :                              nSRSId, osAuthorityName.c_str(), nAuthorityCode,
     147           0 :                              osProj4.c_str());
     148             : 
     149           0 :             GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     150             :         }
     151             :         else
     152             :         {
     153           3 :             OGRFeatureH hFeat = OGR_L_GetNextFeature(hLyr);
     154           3 :             if (hFeat)
     155             :             {
     156           3 :                 nSRSId = OGR_F_GetFieldAsInteger(hFeat, 0);
     157           3 :                 OGR_F_Destroy(hFeat);
     158             :             }
     159           3 :             GDALDatasetReleaseResultSet(hDS, hLyr);
     160             :         }
     161             :     }
     162             : 
     163          56 :     return nSRSId;
     164             : }
     165             : 
     166             : /************************************************************************/
     167             : /*                     RasterliteCreateTables ()                        */
     168             : /************************************************************************/
     169             : 
     170          28 : static GDALDatasetH RasterliteCreateTables(GDALDatasetH hDS,
     171             :                                            const char *pszTableName, int nSRSId,
     172             :                                            int bWipeExistingData)
     173             : {
     174          56 :     CPLString osSQL;
     175             : 
     176          56 :     const CPLString osDBName = GDALGetDescription(hDS);
     177             : 
     178          56 :     CPLString osRasterLayer;
     179          28 :     osRasterLayer.Printf("%s_rasters", pszTableName);
     180             : 
     181          56 :     CPLString osMetadataLayer;
     182          28 :     osMetadataLayer.Printf("%s_metadata", pszTableName);
     183             : 
     184             :     OGRLayerH hLyr;
     185             : 
     186          28 :     if (GDALDatasetGetLayerByName(hDS, osRasterLayer.c_str()) == nullptr)
     187             :     {
     188             :         /* --------------------------------------------------------------------
     189             :          */
     190             :         /*      The table don't exist. Create them */
     191             :         /* --------------------------------------------------------------------
     192             :          */
     193             : 
     194             :         /* Create _rasters table */
     195             :         osSQL.Printf("CREATE TABLE \"%s\" ("
     196             :                      "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
     197             :                      "raster BLOB NOT NULL)",
     198          28 :                      osRasterLayer.c_str());
     199          28 :         GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     200             : 
     201             :         /* Create _metadata table */
     202             :         osSQL.Printf("CREATE TABLE \"%s\" ("
     203             :                      "id INTEGER NOT NULL PRIMARY KEY,"
     204             :                      "source_name TEXT NOT NULL,"
     205             :                      "tile_id INTEGER NOT NULL,"
     206             :                      "width INTEGER NOT NULL,"
     207             :                      "height INTEGER NOT NULL,"
     208             :                      "pixel_x_size DOUBLE NOT NULL,"
     209             :                      "pixel_y_size DOUBLE NOT NULL)",
     210          28 :                      osMetadataLayer.c_str());
     211          28 :         GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     212             : 
     213             :         /* Add geometry column to _metadata table */
     214             :         osSQL.Printf(
     215             :             "SELECT AddGeometryColumn('%s', 'geometry', %d, 'POLYGON', 2)",
     216          28 :             osMetadataLayer.c_str(), nSRSId);
     217          28 :         if ((hLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr,
     218          28 :                                           nullptr)) == nullptr)
     219             :         {
     220           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     221             :                      "Check that the OGR SQLite driver has Spatialite support");
     222           0 :             GDALClose(hDS);
     223           0 :             return nullptr;
     224             :         }
     225          28 :         GDALDatasetReleaseResultSet(hDS, hLyr);
     226             : 
     227             :         /* Create spatial index on _metadata table */
     228             :         osSQL.Printf("SELECT CreateSpatialIndex('%s', 'geometry')",
     229          28 :                      osMetadataLayer.c_str());
     230          28 :         if ((hLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr,
     231          28 :                                           nullptr)) == nullptr)
     232             :         {
     233           0 :             GDALClose(hDS);
     234           0 :             return nullptr;
     235             :         }
     236          28 :         GDALDatasetReleaseResultSet(hDS, hLyr);
     237             : 
     238             :         /* Create statistics tables */
     239          28 :         osSQL.Printf("SELECT UpdateLayerStatistics()");
     240          28 :         CPLPushErrorHandler(CPLQuietErrorHandler);
     241          28 :         hLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     242          28 :         CPLPopErrorHandler();
     243          28 :         GDALDatasetReleaseResultSet(hDS, hLyr);
     244             : 
     245             :         /* Re-open the DB to take into account the new tables*/
     246          28 :         GDALClose(hDS);
     247             : 
     248          28 :         hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update);
     249             :     }
     250             :     else
     251             :     {
     252             :         /* Check that the existing SRS is consistent with the one of the new */
     253             :         /* data to be inserted */
     254             :         osSQL.Printf(
     255             :             "SELECT srid FROM geometry_columns WHERE f_table_name = '%s'",
     256           0 :             osMetadataLayer.c_str());
     257           0 :         hLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     258           0 :         if (hLyr)
     259             :         {
     260           0 :             int nExistingSRID = -1;
     261           0 :             OGRFeatureH hFeat = OGR_L_GetNextFeature(hLyr);
     262           0 :             if (hFeat)
     263             :             {
     264           0 :                 nExistingSRID = OGR_F_GetFieldAsInteger(hFeat, 0);
     265           0 :                 OGR_F_Destroy(hFeat);
     266             :             }
     267           0 :             GDALDatasetReleaseResultSet(hDS, hLyr);
     268             : 
     269           0 :             if (nExistingSRID != nSRSId)
     270             :             {
     271           0 :                 if (bWipeExistingData)
     272             :                 {
     273             :                     osSQL.Printf("UPDATE geometry_columns SET srid = %d "
     274             :                                  "WHERE f_table_name = \"%s\"",
     275           0 :                                  nSRSId, osMetadataLayer.c_str());
     276           0 :                     GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     277             : 
     278             :                     /* Re-open the DB to take into account the change of SRS */
     279           0 :                     GDALClose(hDS);
     280             : 
     281           0 :                     hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update);
     282             :                 }
     283             :                 else
     284             :                 {
     285           0 :                     CPLError(CE_Failure, CPLE_NotSupported,
     286             :                              "New data has not the same SRS as existing data");
     287           0 :                     GDALClose(hDS);
     288           0 :                     return nullptr;
     289             :                 }
     290             :             }
     291             :         }
     292             : 
     293           0 :         if (bWipeExistingData)
     294             :         {
     295           0 :             osSQL.Printf("DELETE FROM \"%s\"", osRasterLayer.c_str());
     296           0 :             GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     297             : 
     298           0 :             osSQL.Printf("DELETE FROM \"%s\"", osMetadataLayer.c_str());
     299           0 :             GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     300             :         }
     301             :     }
     302             : 
     303          28 :     return hDS;
     304             : }
     305             : 
     306             : /************************************************************************/
     307             : /*                       RasterliteCreateCopy ()                        */
     308             : /************************************************************************/
     309             : 
     310          32 : GDALDataset *RasterliteCreateCopy(const char *pszFilename, GDALDataset *poSrcDS,
     311             :                                   CPL_UNUSED int bStrict, char **papszOptions,
     312             :                                   GDALProgressFunc pfnProgress,
     313             :                                   void *pProgressData)
     314             : {
     315          32 :     const int nBands = poSrcDS->GetRasterCount();
     316          32 :     if (nBands == 0)
     317             :     {
     318           1 :         CPLError(CE_Failure, CPLE_NotSupported, "nBands == 0");
     319           1 :         return nullptr;
     320             :     }
     321             : 
     322             :     const char *pszDriverName =
     323          31 :         CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
     324          31 :     if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT"))
     325             :     {
     326           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     327             :                  "GDAL %s driver cannot be used as underlying driver",
     328             :                  pszDriverName);
     329           0 :         return nullptr;
     330             :     }
     331             : 
     332          31 :     GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName);
     333          31 :     if (hTileDriver == nullptr)
     334             :     {
     335           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver",
     336             :                  pszDriverName);
     337           0 :         return nullptr;
     338             :     }
     339             : 
     340          31 :     GDALDriverH hMemDriver = GDALGetDriverByName("MEM");
     341          31 :     if (hMemDriver == nullptr)
     342             :     {
     343           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver");
     344           0 :         return nullptr;
     345             :     }
     346             : 
     347          31 :     const int nXSize = GDALGetRasterXSize(poSrcDS);
     348          31 :     const int nYSize = GDALGetRasterYSize(poSrcDS);
     349             : 
     350             :     double adfGeoTransform[6];
     351          31 :     if (poSrcDS->GetGeoTransform(adfGeoTransform) != CE_None)
     352             :     {
     353           0 :         adfGeoTransform[0] = 0;
     354           0 :         adfGeoTransform[1] = 1;
     355           0 :         adfGeoTransform[2] = 0;
     356           0 :         adfGeoTransform[3] = 0;
     357           0 :         adfGeoTransform[4] = 0;
     358           0 :         adfGeoTransform[5] = -1;
     359             :     }
     360          31 :     else if (adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0)
     361             :     {
     362           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     363             :                  "Cannot use geotransform with rotational terms");
     364           0 :         return nullptr;
     365             :     }
     366             : 
     367             :     const bool bTiled =
     368          31 :         CPLTestBool(CSLFetchNameValueDef(papszOptions, "TILED", "YES"));
     369             :     int nBlockXSize, nBlockYSize;
     370          31 :     if (bTiled)
     371             :     {
     372             :         nBlockXSize =
     373          31 :             atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256"));
     374             :         nBlockYSize =
     375          31 :             atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256"));
     376          31 :         if (nBlockXSize < 64)
     377           0 :             nBlockXSize = 64;
     378          31 :         else if (nBlockXSize > 4096)
     379           0 :             nBlockXSize = 4096;
     380          31 :         if (nBlockYSize < 64)
     381           0 :             nBlockYSize = 64;
     382          31 :         else if (nBlockYSize > 4096)
     383           0 :             nBlockYSize = 4096;
     384             :     }
     385             :     else
     386             :     {
     387           0 :         nBlockXSize = nXSize;
     388           0 :         nBlockYSize = nYSize;
     389             :     }
     390             : 
     391             :     /* -------------------------------------------------------------------- */
     392             :     /*      Analyze arguments                                               */
     393             :     /* -------------------------------------------------------------------- */
     394             : 
     395             :     /* Skip optional RASTERLITE: prefix */
     396          31 :     const char *pszFilenameWithoutPrefix = pszFilename;
     397          31 :     if (STARTS_WITH_CI(pszFilename, "RASTERLITE:"))
     398           3 :         pszFilenameWithoutPrefix += 11;
     399             : 
     400             :     char **papszTokens =
     401          31 :         CSLTokenizeStringComplex(pszFilenameWithoutPrefix, ",", FALSE, FALSE);
     402          31 :     const int nTokens = CSLCount(papszTokens);
     403          62 :     CPLString osDBName;
     404          62 :     CPLString osTableName;
     405          31 :     if (nTokens == 0)
     406             :     {
     407           0 :         osDBName = pszFilenameWithoutPrefix;
     408           0 :         osTableName = CPLGetBasename(pszFilenameWithoutPrefix);
     409             :     }
     410             :     else
     411             :     {
     412          31 :         osDBName = papszTokens[0];
     413             : 
     414             :         int i;
     415          34 :         for (i = 1; i < nTokens; i++)
     416             :         {
     417           3 :             if (STARTS_WITH_CI(papszTokens[i], "table="))
     418           3 :                 osTableName = papszTokens[i] + 6;
     419             :             else
     420             :             {
     421           0 :                 CPLError(CE_Warning, CPLE_AppDefined, "Invalid option : %s",
     422           0 :                          papszTokens[i]);
     423             :             }
     424             :         }
     425             :     }
     426             : 
     427          31 :     CSLDestroy(papszTokens);
     428          31 :     papszTokens = nullptr;
     429             : 
     430             :     VSIStatBuf sBuf;
     431          31 :     const bool bExists = (VSIStat(osDBName.c_str(), &sBuf) == 0);
     432             : 
     433          31 :     if (osTableName.empty())
     434             :     {
     435          28 :         if (bExists)
     436             :         {
     437           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     438             :                      "Database already exists. Explicit table name must be "
     439             :                      "specified");
     440           0 :             return nullptr;
     441             :         }
     442          28 :         osTableName = CPLGetBasename(osDBName.c_str());
     443             :     }
     444             : 
     445          62 :     CPLString osRasterLayer;
     446          31 :     osRasterLayer.Printf("%s_rasters", osTableName.c_str());
     447             : 
     448          62 :     CPLString osMetadataLayer;
     449          31 :     osMetadataLayer.Printf("%s_metadata", osTableName.c_str());
     450             : 
     451             :     /* -------------------------------------------------------------------- */
     452             :     /*      Create or open the SQLite DB                                    */
     453             :     /* -------------------------------------------------------------------- */
     454             : 
     455          31 :     GDALDriverH hSQLiteDriver = GDALGetDriverByName("SQLite");
     456          31 :     if (hSQLiteDriver == nullptr)
     457             :     {
     458           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot load OGR SQLite driver");
     459           0 :         return nullptr;
     460             :     }
     461             : 
     462             :     GDALDatasetH hDS;
     463             : 
     464          31 :     if (!bExists)
     465             :     {
     466          31 :         char **papszOGROptions = CSLAddString(nullptr, "SPATIALITE=YES");
     467          31 :         hDS = GDALCreate(hSQLiteDriver, osDBName.c_str(), 0, 0, 0, GDT_Unknown,
     468             :                          papszOGROptions);
     469          31 :         CSLDestroy(papszOGROptions);
     470             :     }
     471             :     else
     472             :     {
     473           0 :         hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update);
     474             :     }
     475             : 
     476          31 :     if (hDS == nullptr)
     477             :     {
     478           3 :         CPLError(CE_Failure, CPLE_AppDefined,
     479             :                  "Cannot load or create SQLite database");
     480           3 :         return nullptr;
     481             :     }
     482             : 
     483          56 :     CPLString osSQL;
     484             : 
     485             :     /* -------------------------------------------------------------------- */
     486             :     /*      Get the SRID for the SRS                                        */
     487             :     /* -------------------------------------------------------------------- */
     488          28 :     int nSRSId = RasterliteInsertSRID(hDS, poSrcDS->GetProjectionRef());
     489             : 
     490             :     /* -------------------------------------------------------------------- */
     491             :     /*      Create or wipe existing tables                                  */
     492             :     /* -------------------------------------------------------------------- */
     493             :     const int bWipeExistingData =
     494          28 :         CPLTestBool(CSLFetchNameValueDef(papszOptions, "WIPE", "NO"));
     495             : 
     496          28 :     hDS = RasterliteCreateTables(hDS, osTableName.c_str(), nSRSId,
     497             :                                  bWipeExistingData);
     498          28 :     if (hDS == nullptr)
     499           1 :         return nullptr;
     500             : 
     501             :     OGRLayerH hRasterLayer =
     502          27 :         GDALDatasetGetLayerByName(hDS, osRasterLayer.c_str());
     503             :     OGRLayerH hMetadataLayer =
     504          27 :         GDALDatasetGetLayerByName(hDS, osMetadataLayer.c_str());
     505          27 :     if (hRasterLayer == nullptr || hMetadataLayer == nullptr)
     506             :     {
     507           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     508             :                  "Cannot find metadata and/or raster tables");
     509           0 :         GDALClose(hDS);
     510           0 :         return nullptr;
     511             :     }
     512             : 
     513             :     /* -------------------------------------------------------------------- */
     514             :     /*      Check if there is overlapping data and warn the user            */
     515             :     /* -------------------------------------------------------------------- */
     516          27 :     double minx = adfGeoTransform[0];
     517          27 :     double maxx = adfGeoTransform[0] + nXSize * adfGeoTransform[1];
     518          27 :     double maxy = adfGeoTransform[3];
     519          27 :     double miny = adfGeoTransform[3] + nYSize * adfGeoTransform[5];
     520             : 
     521             :     osSQL.Printf(
     522             :         "SELECT COUNT(geometry) FROM \"%s\" "
     523             :         "WHERE rowid IN "
     524             :         "(SELECT pkid FROM \"idx_%s_metadata_geometry\" "
     525             :         "WHERE %s) AND %s",
     526             :         osMetadataLayer.c_str(), osTableName.c_str(),
     527          54 :         RasterliteGetSpatialFilterCond(minx, miny, maxx, maxy).c_str(),
     528          54 :         RasterliteGetPixelSizeCond(adfGeoTransform[1], -adfGeoTransform[5])
     529          54 :             .c_str());
     530             : 
     531          27 :     int nOverlappingGeoms = 0;
     532             :     OGRLayerH hCountLyr =
     533          27 :         GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     534          27 :     if (hCountLyr)
     535             :     {
     536          18 :         OGRFeatureH hFeat = OGR_L_GetNextFeature(hCountLyr);
     537          18 :         if (hFeat)
     538             :         {
     539          18 :             nOverlappingGeoms = OGR_F_GetFieldAsInteger(hFeat, 0);
     540          18 :             OGR_F_Destroy(hFeat);
     541             :         }
     542          18 :         GDALDatasetReleaseResultSet(hDS, hCountLyr);
     543             :     }
     544             : 
     545          27 :     if (nOverlappingGeoms != 0)
     546             :     {
     547           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     548             :                  "Raster tiles already exist in the %s table within "
     549             :                  "the extent of the data to be inserted in",
     550             :                  osTableName.c_str());
     551             :     }
     552             : 
     553             :     /* -------------------------------------------------------------------- */
     554             :     /*      Iterate over blocks to add data into raster and metadata tables */
     555             :     /* -------------------------------------------------------------------- */
     556          27 :     int nXBlocks = (nXSize + nBlockXSize - 1) / nBlockXSize;
     557          27 :     int nYBlocks = (nYSize + nBlockYSize - 1) / nBlockYSize;
     558             : 
     559          27 :     GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
     560          27 :     int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
     561          27 :     GByte *pabyMEMDSBuffer = reinterpret_cast<GByte *>(VSIMalloc3(
     562          27 :         nBlockXSize, nBlockYSize, cpl::fits_on<int>(nBands * nDataTypeSize)));
     563          27 :     if (pabyMEMDSBuffer == nullptr)
     564             :     {
     565           0 :         GDALClose(hDS);
     566           0 :         return nullptr;
     567             :     }
     568             : 
     569             :     const CPLString osTempFileName(
     570          54 :         VSIMemGenerateHiddenFilename("rasterlite_tile"));
     571             : 
     572          27 :     int nTileId = 0;
     573          27 :     int nBlocks = 0;
     574          27 :     int nTotalBlocks = nXBlocks * nYBlocks;
     575             : 
     576             :     char **papszTileDriverOptions =
     577          27 :         RasterliteGetTileDriverOptions(papszOptions);
     578             : 
     579          27 :     GDALDatasetExecuteSQL(hDS, "BEGIN", nullptr, nullptr);
     580             : 
     581          27 :     CPLErr eErr = CE_None;
     582          54 :     for (int nBlockYOff = 0; eErr == CE_None && nBlockYOff < nYBlocks;
     583             :          nBlockYOff++)
     584             :     {
     585          54 :         for (int nBlockXOff = 0; eErr == CE_None && nBlockXOff < nXBlocks;
     586             :              nBlockXOff++)
     587             :         {
     588             :             /* --------------------------------------------------------------------
     589             :              */
     590             :             /*      Create in-memory tile */
     591             :             /* --------------------------------------------------------------------
     592             :              */
     593          27 :             int nReqXSize = nBlockXSize;
     594          27 :             int nReqYSize = nBlockYSize;
     595          27 :             if ((nBlockXOff + 1) * nBlockXSize > nXSize)
     596          27 :                 nReqXSize = nXSize - nBlockXOff * nBlockXSize;
     597          27 :             if ((nBlockYOff + 1) * nBlockYSize > nYSize)
     598          27 :                 nReqYSize = nYSize - nBlockYOff * nBlockYSize;
     599             : 
     600          27 :             eErr = poSrcDS->RasterIO(
     601             :                 GF_Read, nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize,
     602             :                 nReqXSize, nReqYSize, pabyMEMDSBuffer, nReqXSize, nReqYSize,
     603             :                 eDataType, nBands, nullptr, 0, 0, 0, nullptr);
     604          27 :             if (eErr != CE_None)
     605             :             {
     606           0 :                 break;
     607             :             }
     608             : 
     609             :             auto poMEMDS = std::unique_ptr<MEMDataset>(MEMDataset::Create(
     610          27 :                 "", nReqXSize, nReqYSize, 0, eDataType, nullptr));
     611          64 :             for (int iBand = 0; iBand < nBands; iBand++)
     612             :             {
     613          37 :                 auto hBand = MEMCreateRasterBandEx(
     614          37 :                     poMEMDS.get(), iBand + 1,
     615             :                     pabyMEMDSBuffer +
     616          37 :                         iBand * nDataTypeSize * nReqXSize * nReqYSize,
     617             :                     eDataType, 0, 0, false);
     618          37 :                 poMEMDS->AddMEMBand(hBand);
     619             :             }
     620             : 
     621          27 :             GDALDatasetH hOutDS = GDALCreateCopy(
     622          27 :                 hTileDriver, osTempFileName.c_str(), poMEMDS.get(), FALSE,
     623             :                 papszTileDriverOptions, nullptr, nullptr);
     624             : 
     625          27 :             if (!hOutDS)
     626             :             {
     627           0 :                 eErr = CE_Failure;
     628           0 :                 break;
     629             :             }
     630          27 :             GDALClose(hOutDS);
     631             : 
     632             :             /* --------------------------------------------------------------------
     633             :              */
     634             :             /*      Insert new entry into raster table */
     635             :             /* --------------------------------------------------------------------
     636             :              */
     637          27 :             vsi_l_offset nDataLength = 0;
     638          27 :             GByte *pabyData = VSIGetMemFileBuffer(osTempFileName.c_str(),
     639             :                                                   &nDataLength, FALSE);
     640             : 
     641          27 :             OGRFeatureH hFeat = OGR_F_Create(OGR_L_GetLayerDefn(hRasterLayer));
     642          27 :             OGR_F_SetFieldBinary(hFeat, 0, static_cast<int>(nDataLength),
     643             :                                  pabyData);
     644             : 
     645          27 :             if (OGR_L_CreateFeature(hRasterLayer, hFeat) != OGRERR_NONE)
     646           0 :                 eErr = CE_Failure;
     647             :             /* Query raster ID to set it as the ID of the associated metadata */
     648          27 :             int nRasterID = static_cast<int>(OGR_F_GetFID(hFeat));
     649             : 
     650          27 :             OGR_F_Destroy(hFeat);
     651             : 
     652          27 :             VSIUnlink(osTempFileName.c_str());
     653          27 :             if (eErr == CE_Failure)
     654           0 :                 break;
     655             : 
     656             :             /* --------------------------------------------------------------------
     657             :              */
     658             :             /*      Insert new entry into metadata table */
     659             :             /* --------------------------------------------------------------------
     660             :              */
     661             : 
     662          27 :             hFeat = OGR_F_Create(OGR_L_GetLayerDefn(hMetadataLayer));
     663          27 :             OGR_F_SetFID(hFeat, nRasterID);
     664          27 :             OGR_F_SetFieldString(hFeat, 0, GDALGetDescription(poSrcDS));
     665          27 :             OGR_F_SetFieldInteger(hFeat, 1, nTileId++);
     666          27 :             OGR_F_SetFieldInteger(hFeat, 2, nReqXSize);
     667          27 :             OGR_F_SetFieldInteger(hFeat, 3, nReqYSize);
     668          27 :             OGR_F_SetFieldDouble(hFeat, 4, adfGeoTransform[1]);
     669          27 :             OGR_F_SetFieldDouble(hFeat, 5, -adfGeoTransform[5]);
     670             : 
     671          27 :             minx = adfGeoTransform[0] +
     672          27 :                    (nBlockXSize * nBlockXOff) * adfGeoTransform[1];
     673          27 :             maxx = adfGeoTransform[0] +
     674          27 :                    (nBlockXSize * nBlockXOff + nReqXSize) * adfGeoTransform[1];
     675          27 :             maxy = adfGeoTransform[3] +
     676          27 :                    (nBlockYSize * nBlockYOff) * adfGeoTransform[5];
     677          27 :             miny = adfGeoTransform[3] +
     678          27 :                    (nBlockYSize * nBlockYOff + nReqYSize) * adfGeoTransform[5];
     679             : 
     680          27 :             OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon);
     681          27 :             OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing);
     682          27 :             OGR_G_AddPoint_2D(hLinearRing, minx, miny);
     683          27 :             OGR_G_AddPoint_2D(hLinearRing, minx, maxy);
     684          27 :             OGR_G_AddPoint_2D(hLinearRing, maxx, maxy);
     685          27 :             OGR_G_AddPoint_2D(hLinearRing, maxx, miny);
     686          27 :             OGR_G_AddPoint_2D(hLinearRing, minx, miny);
     687          27 :             OGR_G_AddGeometryDirectly(hRectangle, hLinearRing);
     688             : 
     689          27 :             OGR_F_SetGeometryDirectly(hFeat, hRectangle);
     690             : 
     691          27 :             if (OGR_L_CreateFeature(hMetadataLayer, hFeat) != OGRERR_NONE)
     692           0 :                 eErr = CE_Failure;
     693          27 :             OGR_F_Destroy(hFeat);
     694             : 
     695          27 :             nBlocks++;
     696          27 :             if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks,
     697             :                                             nullptr, pProgressData))
     698           0 :                 eErr = CE_Failure;
     699             :         }
     700             :     }
     701             : 
     702          27 :     VSIUnlink(osTempFileName);
     703          27 :     VSIUnlink((osTempFileName + ".aux.xml").c_str());
     704             : 
     705          27 :     if (eErr == CE_None)
     706          27 :         GDALDatasetExecuteSQL(hDS, "COMMIT", nullptr, nullptr);
     707             :     else
     708           0 :         GDALDatasetExecuteSQL(hDS, "ROLLBACK", nullptr, nullptr);
     709             : 
     710          27 :     CSLDestroy(papszTileDriverOptions);
     711             : 
     712          27 :     VSIFree(pabyMEMDSBuffer);
     713             : 
     714          27 :     GDALClose(hDS);
     715             : 
     716          27 :     if (eErr == CE_Failure)
     717           0 :         return nullptr;
     718             : 
     719          27 :     return GDALDataset::FromHandle(GDALOpen(pszFilename, GA_Update));
     720             : }
     721             : 
     722             : /************************************************************************/
     723             : /*                         RasterliteDelete ()                          */
     724             : /************************************************************************/
     725             : 
     726           3 : CPLErr RasterliteDelete(CPL_UNUSED const char *pszFilename)
     727             : {
     728           3 :     return CE_None;
     729             : }

Generated by: LCOV version 1.14