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