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-05-04 12:52:34 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             :  * Permission is hereby granted, free of charge, to any person obtaining
      15             :  * a copy of this software and associated documentation files (the
      16             :  * "Software"), to deal in the Software without restriction, including
      17             :  * without limitation the rights to use, copy, modify, merge, publish,
      18             :  * distribute, sublicense, and/or sell copies of the Software, and to
      19             :  * permit persons to whom the Software is furnished to do so, subject to
      20             :  * the following conditions:
      21             :  *
      22             :  * The above copyright notice and this permission notice shall be
      23             :  * included in all copies or substantial portions of the Software.
      24             :  *
      25             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      26             :  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      27             :  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      28             :  * NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      29             :  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
      30             :  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
      31             :  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      32             :  * SOFTWARE.
      33             :  **********************************************************************/
      34             : #include "postgisraster.h"
      35             : #include <memory>
      36             : 
      37             : /************************
      38             :  * \brief Constructor
      39             :  ************************/
      40           0 : PostGISRasterTileRasterBand::PostGISRasterTileRasterBand(
      41           0 :     PostGISRasterTileDataset *poRTDSIn, int nBandIn, GDALDataType eDataTypeIn)
      42           0 :     : poSource(nullptr)
      43             : {
      44             :     // Basic properties.
      45           0 :     poDS = poRTDSIn;
      46           0 :     nBand = nBandIn;
      47             : 
      48             : #if 0
      49             :     CPLDebug("PostGIS_Raster",
      50             :         "PostGISRasterTileRasterBand::Constructor: Raster tile dataset "
      51             :         "of dimensions %dx%d", poRTDS->GetRasterXSize(),
      52             :         poRTDS->GetRasterYSize());
      53             : #endif
      54             : 
      55           0 :     eDataType = eDataTypeIn;
      56             : 
      57           0 :     nRasterXSize = poRTDSIn->GetRasterXSize();
      58           0 :     nRasterYSize = poRTDSIn->GetRasterYSize();
      59             : 
      60           0 :     nBlockXSize = nRasterXSize;
      61           0 :     nBlockYSize = nRasterYSize;
      62           0 : }
      63             : 
      64             : /************************
      65             :  * \brief Destructor
      66             :  ************************/
      67           0 : PostGISRasterTileRasterBand::~PostGISRasterTileRasterBand()
      68             : {
      69           0 : }
      70             : 
      71             : /***********************************************************************
      72             :  * \brief Returns true if the (only) block is stored in the cache
      73             :  **********************************************************************/
      74           0 : GBool PostGISRasterTileRasterBand::IsCached()
      75             : {
      76           0 :     GDALRasterBlock *poBlock = TryGetLockedBlockRef(0, 0);
      77           0 :     if (poBlock != nullptr)
      78             :     {
      79           0 :         poBlock->DropLock();
      80           0 :         return true;
      81             :     }
      82             : 
      83           0 :     return false;
      84             : }
      85             : 
      86             : /*****************************************************
      87             :  * \brief Read a natural block of raster band data
      88             :  *****************************************************/
      89           0 : CPLErr PostGISRasterTileRasterBand::IReadBlock(int /*nBlockXOff*/,
      90             :                                                int /*nBlockYOff*/, void *pImage)
      91             : {
      92           0 :     CPLString osCommand;
      93           0 :     PGresult *poResult = nullptr;
      94           0 :     int nWKBLength = 0;
      95             : 
      96           0 :     const int nPixelSize = GDALGetDataTypeSizeBytes(eDataType);
      97             : 
      98             :     PostGISRasterTileDataset *poRTDS =
      99           0 :         cpl::down_cast<PostGISRasterTileDataset *>(poDS);
     100             : 
     101           0 :     const double dfTileUpperLeftX =
     102             :         poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X];
     103           0 :     const double dfTileUpperLeftY =
     104             :         poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y];
     105           0 :     const double dfTileResX = poRTDS->adfGeoTransform[1];
     106           0 :     const double dfTileResY = poRTDS->adfGeoTransform[5];
     107           0 :     const int nTileXSize = nBlockXSize;
     108           0 :     const int nTileYSize = nBlockYSize;
     109             : 
     110           0 :     CPLString osSchemaI(CPLQuotedSQLIdentifier(poRTDS->poRDS->pszSchema));
     111           0 :     CPLString osTableI(CPLQuotedSQLIdentifier(poRTDS->poRDS->pszTable));
     112           0 :     CPLString osColumnI(CPLQuotedSQLIdentifier(poRTDS->poRDS->pszColumn));
     113             : 
     114           0 :     CPLString osRasterToFetch;
     115           0 :     osRasterToFetch.Printf("ST_Band(%s, %d)", osColumnI.c_str(), nBand);
     116             :     // We don't honour CLIENT_SIDE_IF_POSSIBLE since it would be likely too
     117             :     // costly in that context.
     118           0 :     if (poRTDS->poRDS->eOutDBResolution != OutDBResolution::CLIENT_SIDE)
     119             :     {
     120             :         osRasterToFetch =
     121           0 :             "encode(ST_AsBinary(" + osRasterToFetch + ",TRUE),'hex')";
     122             :     }
     123             : 
     124             :     osCommand.Printf("SELECT %s FROM %s.%s WHERE ", osRasterToFetch.c_str(),
     125           0 :                      osSchemaI.c_str(), osTableI.c_str());
     126             : 
     127             :     // Get by PKID
     128           0 :     if (poRTDS->poRDS->pszPrimaryKeyName)
     129             :     {
     130             :         CPLString osPrimaryKeyNameI(
     131           0 :             CPLQuotedSQLIdentifier(poRTDS->poRDS->pszPrimaryKeyName));
     132             :         osCommand +=
     133           0 :             CPLSPrintf("%s = '%s'", osPrimaryKeyNameI.c_str(), poRTDS->pszPKID);
     134             :     }
     135             : 
     136             :     // Get by upperleft
     137             :     else
     138             :     {
     139             :         osCommand += CPLSPrintf("abs(ST_UpperLeftX(%s) - %.8f) < 1e-8 and "
     140             :                                 "abs(ST_UpperLeftY(%s) - %.8f) < 1e-8",
     141             :                                 osColumnI.c_str(), dfTileUpperLeftX,
     142           0 :                                 osColumnI.c_str(), dfTileUpperLeftY);
     143             :     }
     144             : 
     145           0 :     poResult = PQexec(poRTDS->poRDS->poConn, osCommand.c_str());
     146             : 
     147             : #ifdef DEBUG_QUERY
     148             :     CPLDebug("PostGIS_Raster",
     149             :              "PostGISRasterTileRasterBand::IReadBlock(): "
     150             :              "Query = \"%s\" --> number of rows = %d",
     151             :              osCommand.c_str(), poResult ? PQntuples(poResult) : 0);
     152             : #endif
     153             : 
     154           0 :     if (poResult == nullptr || PQresultStatus(poResult) != PGRES_TUPLES_OK ||
     155           0 :         PQntuples(poResult) <= 0)
     156             :     {
     157             : 
     158           0 :         CPLString osError;
     159           0 :         if (PQresultStatus(poResult) == PGRES_FATAL_ERROR)
     160             :         {
     161           0 :             const char *pszError = PQerrorMessage(poRTDS->poRDS->poConn);
     162           0 :             if (pszError)
     163           0 :                 osError = pszError;
     164             :         }
     165           0 :         if (poResult)
     166           0 :             PQclear(poResult);
     167             : 
     168           0 :         ReportError(CE_Failure, CPLE_AppDefined,
     169             :                     "Error getting block of data (upperpixel = %f, %f): %s",
     170             :                     dfTileUpperLeftX, dfTileUpperLeftY, osError.c_str());
     171             : 
     172           0 :         return CE_Failure;
     173             :     }
     174             : 
     175             :     /* Copy only data size, without payload */
     176           0 :     int nExpectedDataSize = nBlockXSize * nBlockYSize * nPixelSize;
     177             : 
     178             :     struct CPLFreer
     179             :     {
     180           0 :         void operator()(GByte *x) const
     181             :         {
     182           0 :             CPLFree(x);
     183           0 :         }
     184             :     };
     185             : 
     186             :     std::unique_ptr<GByte, CPLFreer> pbyDataAutoFreed(
     187           0 :         CPLHexToBinary(PQgetvalue(poResult, 0, 0), &nWKBLength));
     188           0 :     GByte *pbyData = pbyDataAutoFreed.get();
     189           0 :     PQclear(poResult);
     190             : 
     191           0 :     const int nMinimumWKBLength = RASTER_HEADER_SIZE + BAND_SIZE(1, nPixelSize);
     192           0 :     if (nWKBLength < nMinimumWKBLength)
     193             :     {
     194           0 :         CPLDebug("PostGIS_Raster",
     195             :                  "nWKBLength=%d. too short. Expected at least %d", nWKBLength,
     196             :                  nMinimumWKBLength);
     197           0 :         return CE_Failure;
     198             :     }
     199             : 
     200             :     // Is it indb-raster ?
     201           0 :     if ((pbyData[RASTER_HEADER_SIZE] & 0x80) == 0)
     202             :     {
     203           0 :         int nExpectedWKBLength =
     204           0 :             RASTER_HEADER_SIZE + BAND_SIZE(nPixelSize, nExpectedDataSize);
     205           0 :         if (nWKBLength != nExpectedWKBLength)
     206             :         {
     207           0 :             CPLDebug("PostGIS_Raster", "nWKBLength=%d, nExpectedWKBLength=%d",
     208             :                      nWKBLength, nExpectedWKBLength);
     209           0 :             return CE_Failure;
     210             :         }
     211             : 
     212           0 :         GByte *pbyDataToRead =
     213           0 :             GET_BAND_DATA(pbyData, 1, nPixelSize, nExpectedDataSize);
     214             : 
     215             :         // Do byte-swapping if necessary */
     216           0 :         const bool bIsLittleEndian = (pbyData[0] == 1);
     217             : #ifdef CPL_LSB
     218           0 :         const bool bSwap = !bIsLittleEndian;
     219             : #else
     220             :         const bool bSwap = bIsLittleEndian;
     221             : #endif
     222             : 
     223           0 :         if (bSwap && nPixelSize > 1)
     224             :         {
     225           0 :             GDALSwapWords(pbyDataToRead, nPixelSize, nBlockXSize * nBlockYSize,
     226             :                           nPixelSize);
     227             :         }
     228             : 
     229           0 :         memcpy(pImage, pbyDataToRead, nExpectedDataSize);
     230             :     }
     231             :     else
     232             :     {
     233           0 :         int nCurOffset = RASTER_HEADER_SIZE;
     234           0 :         if (!poRTDS->poRDS->LoadOutdbRaster(
     235             :                 nCurOffset, eDataType, nBand, pbyData, nWKBLength, pImage,
     236             :                 dfTileUpperLeftX, dfTileUpperLeftY, dfTileResX, dfTileResY,
     237             :                 nTileXSize, nTileYSize))
     238             :         {
     239           0 :             return CE_Failure;
     240             :         }
     241             :     }
     242             : 
     243           0 :     return CE_None;
     244             : }

Generated by: LCOV version 1.14