Line data Source code
1 : /***********************************************************************
2 : * File : postgisraster.h
3 : * Project: PostGIS Raster driver
4 : * Purpose: Main header file for PostGIS Raster Driver
5 : * Author: Jorge Arevalo, jorge.arevalo@deimos-space.com
6 : * jorgearevalo@libregis.org
7 : *
8 : * Author: David Zwarg, dzwarg@azavea.com
9 : *
10 : * Last changes: $Id$
11 : *
12 : ***********************************************************************
13 : * Copyright (c) 2009 - 2013, Jorge Arevalo, David Zwarg
14 : * Copyright (c) 2013, Even Rouault
15 : *
16 : * SPDX-License-Identifier: MIT
17 : **********************************************************************/
18 :
19 : #ifndef POSTGISRASTER_H_INCLUDED
20 : #define POSTGISRASTER_H_INCLUDED
21 :
22 : #include "gdal_priv.h"
23 : #include "libpq-fe.h"
24 : #include "vrtdataset.h"
25 : #include "cpl_mem_cache.h"
26 : #include "cpl_quad_tree.h"
27 : #include <float.h>
28 : #include <map>
29 :
30 : // #define DEBUG_VERBOSE
31 : // #define DEBUG_QUERY
32 :
33 : #if defined(DEBUG_VERBOSE) && !defined(DEBUG_QUERY)
34 : #define DEBUG_QUERY
35 : #endif
36 :
37 : /**
38 : * The block size for the cache will be the minimum between the tile
39 : * size from sources and this value. So, please keep it at 2048 or
40 : * lower
41 : **/
42 : #define MAX_BLOCK_SIZE 2048
43 :
44 : #define NO_VALID_RES "-1234.56"
45 :
46 : /**
47 : * To move over the data return by queries
48 : **/
49 : #define POSTGIS_RASTER_VERSION static_cast<GUInt16>(0)
50 : #define RASTER_HEADER_SIZE 61
51 : #define RASTER_BAND_HEADER_FIXED_SIZE 1
52 :
53 : #define BAND_SIZE(nodatasize, datasize) \
54 : (RASTER_BAND_HEADER_FIXED_SIZE + (nodatasize) + (datasize))
55 :
56 : #define GET_BAND_DATA(raster, nband, nodatasize, datasize) \
57 : ((raster) + RASTER_HEADER_SIZE + (nband)*BAND_SIZE(nodatasize, datasize) - \
58 : (datasize))
59 :
60 : #define GEOTRSFRM_TOPLEFT_X 0
61 : #define GEOTRSFRM_WE_RES 1
62 : #define GEOTRSFRM_ROTATION_PARAM1 2
63 : #define GEOTRSFRM_TOPLEFT_Y 3
64 : #define GEOTRSFRM_ROTATION_PARAM2 4
65 : #define GEOTRSFRM_NS_RES 5
66 :
67 : // Number of results return by ST_Metadata PostGIS function
68 : #define ELEMENTS_OF_METADATA_RECORD 10
69 :
70 : // Positions of elements of ST_Metadata PostGIS function
71 : #define POS_UPPERLEFTX 0
72 : #define POS_UPPERLEFTY 1
73 : #define POS_WIDTH 2
74 : #define POS_HEIGHT 3
75 : #define POS_SCALEX 4
76 : #define POS_SCALEY 5
77 : #define POS_SKEWX 6
78 : #define POS_SKEWY 7
79 : #define POS_SRID 8
80 : #define POS_NBANDS 9
81 :
82 : // Number of results return by ST_BandMetadata PostGIS function
83 : #define ELEMENTS_OF_BAND_METADATA_RECORD 4
84 :
85 : // Positions of elements of ST_BandMetadata PostGIS function
86 : #define POS_PIXELTYPE 0
87 : #define POS_NODATAVALUE 1
88 : #define POS_ISOUTDB 2
89 : #define POS_PATH 3
90 :
91 : /**
92 : * The driver can work in these modes:
93 : * - NO_MODE: Error case
94 : * - ONE_RASTER_PER_ROW: Each row of the requested table is considered
95 : * as a separated raster object. This is the default mode, if
96 : * database and table name are provided, and no mode is specified.
97 : * - ONE_RASTER_PER_TABLE: All the rows of the requested table are
98 : * considered as tiles of a bigger raster coverage (the whole
99 : * table). If database and table name are specified and mode = 2
100 : * is present in the connection string, this is the selected mode.
101 : * - BROWSE_SCHEMA: If no table name is specified, just database and
102 : * schema names, the driver will yell of the schema's raster tables
103 : * as possible datasets.
104 : * - BROWSE_DATABASE: If no table name is specified, just database name,
105 : * the driver will yell of the database's raster tables as possible
106 : * datasets.
107 : **/
108 : typedef enum
109 : {
110 : NO_MODE,
111 : ONE_RASTER_PER_ROW,
112 : ONE_RASTER_PER_TABLE,
113 : BROWSE_SCHEMA,
114 : BROWSE_DATABASE
115 : } WorkingMode;
116 :
117 : enum class OutDBResolution
118 : {
119 : SERVER_SIDE,
120 : CLIENT_SIDE,
121 : CLIENT_SIDE_IF_POSSIBLE
122 : };
123 :
124 : /**
125 : * Important metadata of a PostGIS Raster band
126 : **/
127 : typedef struct
128 : {
129 : GDALDataType eDataType;
130 : int nBitsDepth;
131 : GBool bHasNoDataValue;
132 : GBool bIsOffline;
133 : char *path;
134 : double dfNoDataValue;
135 : } BandMetadata;
136 :
137 : typedef struct
138 : {
139 : char *pszSchema;
140 : char *pszTable;
141 : char *pszColumn;
142 : int nFactor;
143 : } PROverview;
144 :
145 : // Some tools definitions
146 : char *ReplaceQuotes(const char *, int);
147 : GBool TranslateDataType(const char *, GDALDataType *, int *);
148 :
149 : class PostGISRasterRasterBand;
150 : class PostGISRasterTileDataset;
151 :
152 : /***********************************************************************
153 : * PostGISRasterDriver: extends GDALDriver to support PostGIS Raster
154 : * connect.
155 : **********************************************************************/
156 : class PostGISRasterDriver final : public GDALDriver
157 : {
158 :
159 : private:
160 : CPLMutex *hMutex = nullptr;
161 : std::map<CPLString, PGconn *> oMapConnection{};
162 :
163 : CPL_DISALLOW_COPY_ASSIGN(PostGISRasterDriver)
164 : public:
165 : PostGISRasterDriver();
166 : virtual ~PostGISRasterDriver();
167 : PGconn *GetConnection(const char *pszConnectionString,
168 : const char *pszServiceIn, const char *pszDbnameIn,
169 : const char *pszHostIn, const char *pszPortIn,
170 : const char *pszUserIn);
171 :
172 : static PostGISRasterDriver *gpoPostGISRasterDriver;
173 : };
174 :
175 : /***********************************************************************
176 : * PostGISRasterDataset: extends VRTDataset to support PostGIS Raster
177 : * datasets
178 : **********************************************************************/
179 : class PostGISRasterDataset final : public VRTDataset
180 : {
181 : friend class PostGISRasterRasterBand;
182 : friend class PostGISRasterTileRasterBand;
183 :
184 : private:
185 : typedef enum
186 : {
187 : LOWEST_RESOLUTION,
188 : HIGHEST_RESOLUTION,
189 : AVERAGE_RESOLUTION,
190 : USER_RESOLUTION,
191 : AVERAGE_APPROX_RESOLUTION
192 : } ResolutionStrategy;
193 :
194 : char **papszSubdatasets;
195 : double adfGeoTransform[6];
196 : int nSrid;
197 : int nOverviewFactor;
198 : int nBandsToCreate;
199 : PGconn *poConn;
200 : GBool bRegularBlocking;
201 : GBool bAllTilesSnapToSameGrid;
202 : GBool bCheckAllTiles;
203 : char *pszSchema;
204 : char *pszTable;
205 : char *pszColumn;
206 : char *pszWhere;
207 : char *pszPrimaryKeyName;
208 : GBool bIsFastPK;
209 : int bHasTriedFetchingPrimaryKeyName;
210 : mutable OGRSpatialReference m_oSRS{};
211 : ResolutionStrategy resolutionStrategy;
212 : WorkingMode nMode;
213 : OutDBResolution eOutDBResolution{OutDBResolution::SERVER_SIDE};
214 : bool bHasStBandFileSize = false;
215 : int m_nTiles;
216 : double xmin;
217 : double ymin;
218 : double xmax;
219 : double ymax;
220 : PostGISRasterTileDataset **papoSourcesHolders;
221 : CPLQuadTree *hQuadTree;
222 :
223 : GBool bHasBuiltOverviews;
224 : int nOverviewCount;
225 : PostGISRasterDataset *poParentDS;
226 : PostGISRasterDataset **papoOverviewDS;
227 :
228 : std::map<CPLString, PostGISRasterTileDataset *> oMapPKIDToRTDS{};
229 :
230 : GBool bAssumeMultiBandReadPattern;
231 : int nNextExpectedBand;
232 : int nXOffPrev;
233 : int nYOffPrev;
234 : int nXSizePrev;
235 : int nYSizePrev;
236 :
237 : GBool bHasTriedHasSpatialIndex;
238 : GBool bHasSpatialIndex;
239 :
240 : GBool bBuildQuadTreeDynamically;
241 :
242 : GBool bTilesSameDimension;
243 : int nTileWidth;
244 : int nTileHeight;
245 :
246 : int m_nLastLoadSourcesXOff = 0;
247 : int m_nLastLoadSourcesYOff = 0;
248 : int m_nLastLoadSourcesXSize = 0;
249 : int m_nLastLoadSourcesYSize = 0;
250 : int m_nLastLoadSourcesBand = 0;
251 :
252 : lru11::Cache<std::string, std::shared_ptr<GDALDataset>> oOutDBDatasetCache{
253 : 8, 0};
254 : lru11::Cache<std::string, bool> oOutDBFilenameUsable{100, 0};
255 :
256 : GBool ConstructOneDatasetFromTiles(PGresult *);
257 : GBool YieldSubdatasets(PGresult *, const char *);
258 : GBool SetRasterProperties(const char *);
259 : GBool BrowseDatabase(const char *, const char *);
260 : void AddComplexSource(PostGISRasterTileDataset *poRTDS);
261 : void GetDstWin(PostGISRasterTileDataset *, int *, int *, int *, int *);
262 : BandMetadata *GetBandsMetadata(int *);
263 : PROverview *GetOverviewTables(int *);
264 :
265 : PostGISRasterTileDataset *
266 : BuildRasterTileDataset(const char *pszMetadata, const char *pszPKID,
267 : int nBandsFetched, BandMetadata *poBandMetaData);
268 : void UpdateGlobalResolutionWithTileResolution(double tilePixelSizeX,
269 : double tilePixelSizeY);
270 : void BuildOverviews();
271 : void BuildBands(BandMetadata *poBandMetaData, int nBandsFetched);
272 :
273 0 : PostGISRasterTileDataset *GetMatchingSourceRef(const char *pszPKID)
274 : {
275 0 : return oMapPKIDToRTDS[pszPKID];
276 : }
277 :
278 : PostGISRasterTileDataset *GetMatchingSourceRef(double dfUpperLeftX,
279 : double dfUpperLeftY);
280 :
281 : bool CanUseClientSideOutDB(bool bAllBandCaching, int nBand,
282 : const CPLString &osWHERE);
283 :
284 : bool LoadOutdbRaster(int &nCurOffset, GDALDataType eDT, int nBand,
285 : const GByte *pbyData, int nWKBLength, void *pImage,
286 : double dfTileUpperLeftX, double dfTileUpperLeftY,
287 : double dfTileResX, double dfTileResY, int nTileXSize,
288 : int nTileYSize);
289 :
290 : CPL_DISALLOW_COPY_ASSIGN(PostGISRasterDataset)
291 :
292 : protected:
293 : virtual int CloseDependentDatasets() override;
294 : virtual CPLErr FlushCache(bool bAtClosing) override;
295 :
296 : public:
297 : PostGISRasterDataset();
298 : virtual ~PostGISRasterDataset();
299 : static GDALDataset *Open(GDALOpenInfo *);
300 : static GDALDataset *CreateCopy(const char *, GDALDataset *, int, char **,
301 : GDALProgressFunc, void *);
302 : static GBool InsertRaster(PGconn *, PostGISRasterDataset *, const char *,
303 : const char *, const char *);
304 : static CPLErr Delete(const char *);
305 : virtual char **GetMetadataDomainList() override;
306 : char **GetMetadata(const char *) override;
307 :
308 : const OGRSpatialReference *GetSpatialRef() const override;
309 : CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override;
310 :
311 : CPLErr SetGeoTransform(double *) override;
312 : CPLErr GetGeoTransform(double *) override;
313 : char **GetFileList() override;
314 :
315 : int GetOverviewCount();
316 : PostGISRasterDataset *GetOverviewDS(int iOvr);
317 :
318 : const char *GetPrimaryKeyRef();
319 : GBool HasSpatialIndex();
320 : GBool LoadSources(int nXOff, int nYOff, int nXSize, int nYSize, int nBand);
321 : GBool PolygonFromCoords(int nXOff, int nYOff, int nXEndOff, int nYEndOff,
322 : double adfProjWin[8]);
323 : void CacheTile(const char *pszMetadata, const char *pszRaster,
324 : const char *pszPKID, int nBand, bool bAllBandCaching);
325 : };
326 :
327 : /***********************************************************************
328 : * PostGISRasterRasterBand: extends VRTSourcedRasterBand to support
329 : * PostGIS Raster bands
330 : **********************************************************************/
331 : class PostGISRasterTileRasterBand;
332 :
333 : class PostGISRasterRasterBand final : public VRTSourcedRasterBand
334 : {
335 : friend class PostGISRasterDataset;
336 :
337 : CPL_DISALLOW_COPY_ASSIGN(PostGISRasterRasterBand)
338 : protected:
339 : const char *pszSchema;
340 : const char *pszTable;
341 : const char *pszColumn;
342 :
343 : void NullBuffer(void *pData, int nBufXSize, int nBufYSize,
344 : GDALDataType eBufType, int nPixelSpace, int nLineSpace);
345 :
346 : public:
347 : PostGISRasterRasterBand(PostGISRasterDataset *poDSIn, int nBandIn,
348 : GDALDataType eDataTypeIn, GBool bNoDataValueSetIn,
349 : double dfNodata);
350 :
351 : virtual ~PostGISRasterRasterBand();
352 :
353 : virtual double GetNoDataValue(int *pbSuccess = nullptr) override;
354 : virtual CPLErr SetNoDataValue(double) override;
355 : virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
356 : GDALDataType, GSpacing nPixelSpace,
357 : GSpacing nLineSpace,
358 : GDALRasterIOExtraArg *psExtraArg) override;
359 :
360 : virtual int GetOverviewCount() override;
361 : virtual GDALRasterBand *GetOverview(int) override;
362 : virtual GDALColorInterp GetColorInterpretation() override;
363 :
364 : virtual double GetMinimum(int *pbSuccess) override;
365 : virtual double GetMaximum(int *pbSuccess) override;
366 : virtual CPLErr ComputeRasterMinMax(int bApproxOK,
367 : double *adfMinMax) override;
368 : };
369 :
370 : /***********************************************************************
371 : * PostGISRasterTileDataset: it holds just a raster tile
372 : **********************************************************************/
373 : class PostGISRasterTileRasterBand;
374 :
375 : class PostGISRasterTileDataset final : public GDALDataset
376 : {
377 : friend class PostGISRasterDataset;
378 : friend class PostGISRasterRasterBand;
379 : friend class PostGISRasterTileRasterBand;
380 :
381 : private:
382 : PostGISRasterDataset *poRDS;
383 : char *pszPKID;
384 : double adfGeoTransform[6];
385 :
386 : CPL_DISALLOW_COPY_ASSIGN(PostGISRasterTileDataset)
387 :
388 : public:
389 : PostGISRasterTileDataset(PostGISRasterDataset *poRDS, int nXSize,
390 : int nYSize);
391 : ~PostGISRasterTileDataset();
392 : CPLErr GetGeoTransform(double *) override;
393 : void GetExtent(double *pdfMinX, double *pdfMinY, double *pdfMaxX,
394 : double *pdfMaxY) const;
395 :
396 0 : const char *GetPKID() const
397 : {
398 0 : return pszPKID;
399 : }
400 : };
401 :
402 : /***********************************************************************
403 : * PostGISRasterTileRasterBand: it holds a raster tile band, that will
404 : * be used as a source for PostGISRasterRasterBand
405 : **********************************************************************/
406 : class PostGISRasterTileRasterBand final : public GDALRasterBand
407 : {
408 : friend class PostGISRasterRasterBand;
409 : friend class PostGISRasterDataset;
410 :
411 : private:
412 : GBool IsCached();
413 :
414 : VRTSource *poSource;
415 :
416 : CPL_DISALLOW_COPY_ASSIGN(PostGISRasterTileRasterBand)
417 :
418 : public:
419 : PostGISRasterTileRasterBand(PostGISRasterTileDataset *poRTDS, int nBand,
420 : GDALDataType eDataType);
421 : virtual ~PostGISRasterTileRasterBand();
422 : virtual CPLErr IReadBlock(int, int, void *) override;
423 : };
424 :
425 : #endif // POSTGISRASTER_H_INCLUDED
|