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

Generated by: LCOV version 1.14