LCOV - code coverage report
Current view: top level - frmts/postgisraster - postgisrastertilerasterband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 83 0.0 %
Date: 2025-01-18 12:42:00 Functions: 0 6 0.0 %

          Line data    Source code
       1             : /***********************************************************************
       2             :  * File :    postgisrastertilerasterband.cpp
       3             :  * Project:  PostGIS Raster driver
       4             :  * Purpose:  GDAL Tile RasterBand implementation for PostGIS Raster
       5             :  * driver
       6             :  * Author:   Jorge Arevalo, jorge.arevalo@deimos-space.com
       7             :  *                          jorgearevalo@libregis.org
       8             :  *
       9             :  ***********************************************************************
      10             :  * Copyright (c) 2009 - 2013, Jorge Arevalo
      11             :  * Copyright (c) 2013-2018, Even Rouault
      12             :  *
      13             :  * SPDX-License-Identifier: MIT
      14             :  **********************************************************************/
      15             : #include "postgisraster.h"
      16             : #include <memory>
      17             : 
      18             : /************************
      19             :  * \brief Constructor
      20             :  ************************/
      21           0 : PostGISRasterTileRasterBand::PostGISRasterTileRasterBand(
      22           0 :     PostGISRasterTileDataset *poRTDSIn, int nBandIn, GDALDataType eDataTypeIn)
      23           0 :     : poSource(nullptr)
      24             : {
      25             :     // Basic properties.
      26           0 :     poDS = poRTDSIn;
      27           0 :     nBand = nBandIn;
      28             : 
      29             : #if 0
      30             :     CPLDebug("PostGIS_Raster",
      31             :         "PostGISRasterTileRasterBand::Constructor: Raster tile dataset "
      32             :         "of dimensions %dx%d", poRTDS->GetRasterXSize(),
      33             :         poRTDS->GetRasterYSize());
      34             : #endif
      35             : 
      36           0 :     eDataType = eDataTypeIn;
      37             : 
      38           0 :     nRasterXSize = poRTDSIn->GetRasterXSize();
      39           0 :     nRasterYSize = poRTDSIn->GetRasterYSize();
      40             : 
      41           0 :     nBlockXSize = nRasterXSize;
      42           0 :     nBlockYSize = nRasterYSize;
      43           0 : }
      44             : 
      45             : /************************
      46             :  * \brief Destructor
      47             :  ************************/
      48           0 : PostGISRasterTileRasterBand::~PostGISRasterTileRasterBand()
      49             : {
      50           0 : }
      51             : 
      52             : /***********************************************************************
      53             :  * \brief Returns true if the (only) block is stored in the cache
      54             :  **********************************************************************/
      55           0 : GBool PostGISRasterTileRasterBand::IsCached()
      56             : {
      57           0 :     GDALRasterBlock *poBlock = TryGetLockedBlockRef(0, 0);
      58           0 :     if (poBlock != nullptr)
      59             :     {
      60           0 :         poBlock->DropLock();
      61           0 :         return true;
      62             :     }
      63             : 
      64           0 :     return false;
      65             : }
      66             : 
      67             : /*****************************************************
      68             :  * \brief Read a natural block of raster band data
      69             :  *****************************************************/
      70           0 : CPLErr PostGISRasterTileRasterBand::IReadBlock(int /*nBlockXOff*/,
      71             :                                                int /*nBlockYOff*/, void *pImage)
      72             : {
      73           0 :     CPLString osCommand;
      74           0 :     PGresult *poResult = nullptr;
      75           0 :     int nWKBLength = 0;
      76             : 
      77           0 :     const int nPixelSize = GDALGetDataTypeSizeBytes(eDataType);
      78             : 
      79             :     PostGISRasterTileDataset *poRTDS =
      80           0 :         cpl::down_cast<PostGISRasterTileDataset *>(poDS);
      81             : 
      82           0 :     const double dfTileUpperLeftX =
      83             :         poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X];
      84           0 :     const double dfTileUpperLeftY =
      85             :         poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y];
      86           0 :     const double dfTileResX = poRTDS->adfGeoTransform[1];
      87           0 :     const double dfTileResY = poRTDS->adfGeoTransform[5];
      88           0 :     const int nTileXSize = nBlockXSize;
      89           0 :     const int nTileYSize = nBlockYSize;
      90             : 
      91           0 :     CPLString osSchemaI(CPLQuotedSQLIdentifier(poRTDS->poRDS->pszSchema));
      92           0 :     CPLString osTableI(CPLQuotedSQLIdentifier(poRTDS->poRDS->pszTable));
      93           0 :     CPLString osColumnI(CPLQuotedSQLIdentifier(poRTDS->poRDS->pszColumn));
      94             : 
      95           0 :     CPLString osRasterToFetch;
      96           0 :     osRasterToFetch.Printf("ST_Band(%s, %d)", osColumnI.c_str(), nBand);
      97             :     // We don't honour CLIENT_SIDE_IF_POSSIBLE since it would be likely too
      98             :     // costly in that context.
      99           0 :     if (poRTDS->poRDS->eOutDBResolution != OutDBResolution::CLIENT_SIDE)
     100             :     {
     101             :         osRasterToFetch =
     102           0 :             "encode(ST_AsBinary(" + osRasterToFetch + ",TRUE),'hex')";
     103             :     }
     104             : 
     105             :     osCommand.Printf("SELECT %s FROM %s.%s WHERE ", osRasterToFetch.c_str(),
     106           0 :                      osSchemaI.c_str(), osTableI.c_str());
     107             : 
     108             :     // Get by PKID
     109           0 :     if (poRTDS->poRDS->pszPrimaryKeyName)
     110             :     {
     111             :         CPLString osPrimaryKeyNameI(
     112           0 :             CPLQuotedSQLIdentifier(poRTDS->poRDS->pszPrimaryKeyName));
     113             :         osCommand +=
     114           0 :             CPLSPrintf("%s = '%s'", osPrimaryKeyNameI.c_str(), poRTDS->pszPKID);
     115             :     }
     116             : 
     117             :     // Get by upperleft
     118             :     else
     119             :     {
     120             :         osCommand += CPLSPrintf("abs(ST_UpperLeftX(%s) - %.8f) < 1e-8 and "
     121             :                                 "abs(ST_UpperLeftY(%s) - %.8f) < 1e-8",
     122             :                                 osColumnI.c_str(), dfTileUpperLeftX,
     123           0 :                                 osColumnI.c_str(), dfTileUpperLeftY);
     124             :     }
     125             : 
     126           0 :     poResult = PQexec(poRTDS->poRDS->poConn, osCommand.c_str());
     127             : 
     128             : #ifdef DEBUG_QUERY
     129             :     CPLDebug("PostGIS_Raster",
     130             :              "PostGISRasterTileRasterBand::IReadBlock(): "
     131             :              "Query = \"%s\" --> number of rows = %d",
     132             :              osCommand.c_str(), poResult ? PQntuples(poResult) : 0);
     133             : #endif
     134             : 
     135           0 :     if (poResult == nullptr || PQresultStatus(poResult) != PGRES_TUPLES_OK ||
     136           0 :         PQntuples(poResult) <= 0)
     137             :     {
     138             : 
     139           0 :         CPLString osError;
     140           0 :         if (PQresultStatus(poResult) == PGRES_FATAL_ERROR)
     141             :         {
     142           0 :             const char *pszError = PQerrorMessage(poRTDS->poRDS->poConn);
     143           0 :             if (pszError)
     144           0 :                 osError = pszError;
     145             :         }
     146           0 :         if (poResult)
     147           0 :             PQclear(poResult);
     148             : 
     149           0 :         ReportError(CE_Failure, CPLE_AppDefined,
     150             :                     "Error getting block of data (upperpixel = %f, %f): %s",
     151             :                     dfTileUpperLeftX, dfTileUpperLeftY, osError.c_str());
     152             : 
     153           0 :         return CE_Failure;
     154             :     }
     155             : 
     156             :     /* Copy only data size, without payload */
     157           0 :     int nExpectedDataSize = nBlockXSize * nBlockYSize * nPixelSize;
     158             : 
     159             :     struct CPLFreer
     160             :     {
     161           0 :         void operator()(GByte *x) const
     162             :         {
     163           0 :             CPLFree(x);
     164           0 :         }
     165             :     };
     166             : 
     167             :     std::unique_ptr<GByte, CPLFreer> pbyDataAutoFreed(
     168           0 :         CPLHexToBinary(PQgetvalue(poResult, 0, 0), &nWKBLength));
     169           0 :     GByte *pbyData = pbyDataAutoFreed.get();
     170           0 :     PQclear(poResult);
     171             : 
     172           0 :     const int nMinimumWKBLength = RASTER_HEADER_SIZE + BAND_SIZE(1, nPixelSize);
     173           0 :     if (nWKBLength < nMinimumWKBLength)
     174             :     {
     175           0 :         CPLDebug("PostGIS_Raster",
     176             :                  "nWKBLength=%d. too short. Expected at least %d", nWKBLength,
     177             :                  nMinimumWKBLength);
     178           0 :         return CE_Failure;
     179             :     }
     180             : 
     181             :     // Is it indb-raster ?
     182           0 :     if ((pbyData[RASTER_HEADER_SIZE] & 0x80) == 0)
     183             :     {
     184           0 :         int nExpectedWKBLength =
     185           0 :             RASTER_HEADER_SIZE + BAND_SIZE(nPixelSize, nExpectedDataSize);
     186           0 :         if (nWKBLength != nExpectedWKBLength)
     187             :         {
     188           0 :             CPLDebug("PostGIS_Raster", "nWKBLength=%d, nExpectedWKBLength=%d",
     189             :                      nWKBLength, nExpectedWKBLength);
     190           0 :             return CE_Failure;
     191             :         }
     192             : 
     193           0 :         GByte *pbyDataToRead =
     194           0 :             GET_BAND_DATA(pbyData, 1, nPixelSize, nExpectedDataSize);
     195             : 
     196             :         // Do byte-swapping if necessary */
     197           0 :         const bool bIsLittleEndian = (pbyData[0] == 1);
     198             : #ifdef CPL_LSB
     199           0 :         const bool bSwap = !bIsLittleEndian;
     200             : #else
     201             :         const bool bSwap = bIsLittleEndian;
     202             : #endif
     203             : 
     204           0 :         if (bSwap && nPixelSize > 1)
     205             :         {
     206           0 :             GDALSwapWords(pbyDataToRead, nPixelSize, nBlockXSize * nBlockYSize,
     207             :                           nPixelSize);
     208             :         }
     209             : 
     210           0 :         memcpy(pImage, pbyDataToRead, nExpectedDataSize);
     211             :     }
     212             :     else
     213             :     {
     214           0 :         int nCurOffset = RASTER_HEADER_SIZE;
     215           0 :         if (!poRTDS->poRDS->LoadOutdbRaster(
     216             :                 nCurOffset, eDataType, nBand, pbyData, nWKBLength, pImage,
     217             :                 dfTileUpperLeftX, dfTileUpperLeftY, dfTileResX, dfTileResY,
     218             :                 nTileXSize, nTileYSize))
     219             :         {
     220           0 :             return CE_Failure;
     221             :         }
     222             :     }
     223             : 
     224           0 :     return CE_None;
     225             : }

Generated by: LCOV version 1.14