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

Generated by: LCOV version 1.14