1 /******************************************************************************
2 *
3 * Project: GDAL Core
4 * Purpose: Base class for raster file formats.
5 * Author: Frank Warmerdam, warmerdam@pobox.com
6 *
7 ******************************************************************************
8 * Copyright (c) 1998, 2003, Frank Warmerdam
9 * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE.
28 ****************************************************************************/
29
30 #include "cpl_port.h"
31 #include "gdal.h"
32 #include "gdal_priv.h"
33
34 #include <climits>
35 #include <cstdarg>
36 #include <cstdio>
37 #include <cstdlib>
38 #include <cstring>
39 #include <algorithm>
40 #include <map>
41 #include <new>
42 #include <set>
43 #include <string>
44 #include <utility>
45
46 #include "cpl_conv.h"
47 #include "cpl_error.h"
48 #include "cpl_hash_set.h"
49 #include "cpl_multiproc.h"
50 #include "cpl_progress.h"
51 #include "cpl_string.h"
52 #include "cpl_vsi.h"
53 #include "cpl_vsi_error.h"
54 #include "ogr_api.h"
55 #include "ogr_attrind.h"
56 #include "ogr_core.h"
57 #include "ogr_feature.h"
58 #include "ogr_featurestyle.h"
59 #include "ogr_gensql.h"
60 #include "ogr_geometry.h"
61 #include "ogr_p.h"
62 #include "ogr_spatialref.h"
63 #include "ogr_srs_api.h"
64 #include "ograpispy.h"
65 #include "ogrsf_frmts.h"
66 #include "ogrunionlayer.h"
67 #include "ogr_swq.h"
68
69 #include "../frmts/derived/derivedlist.h"
70
71 #ifdef SQLITE_ENABLED
72 #include "../sqlite/ogrsqliteexecutesql.h"
73 #endif
74
75 CPL_CVSID("$Id: gdaldataset.cpp a89f31543fbe6c7d738a6405c099ba82fdb3c326 2021-08-22 19:38:03 +0200 Even Rouault $")
76
77 CPL_C_START
78 GDALAsyncReader *
79 GDALGetDefaultAsyncReader( GDALDataset *poDS,
80 int nXOff, int nYOff,
81 int nXSize, int nYSize,
82 void *pBuf,
83 int nBufXSize, int nBufYSize,
84 GDALDataType eBufType,
85 int nBandCount, int* panBandMap,
86 int nPixelSpace, int nLineSpace,
87 int nBandSpace, char **papszOptions );
88 CPL_C_END
89
90 enum class GDALAllowReadWriteMutexState
91 {
92 RW_MUTEX_STATE_UNKNOWN,
93 RW_MUTEX_STATE_ALLOWED,
94 RW_MUTEX_STATE_DISABLED
95 };
96
97 const GIntBig TOTAL_FEATURES_NOT_INIT = -2;
98 const GIntBig TOTAL_FEATURES_UNKNOWN = -1;
99
100 class GDALDataset::Private
101 {
102 CPL_DISALLOW_COPY_ASSIGN(Private)
103
104 public:
105 CPLMutex *hMutex = nullptr;
106 std::map<GIntBig, int> oMapThreadToMutexTakenCount{};
107 #ifdef DEBUG_EXTRA
108 std::map<GIntBig, int> oMapThreadToMutexTakenCountSaved{};
109 #endif
110 GDALAllowReadWriteMutexState eStateReadWriteMutex = GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN;
111 int nCurrentLayerIdx = 0;
112 int nLayerCount = -1;
113 GIntBig nFeatureReadInLayer = 0;
114 GIntBig nFeatureReadInDataset = 0;
115 GIntBig nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
116 GIntBig nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
117 OGRLayer *poCurrentLayer = nullptr;
118
119 char *m_pszWKTCached = nullptr;
120 OGRSpatialReference *m_poSRSCached = nullptr;
121 char *m_pszWKTGCPCached = nullptr;
122 OGRSpatialReference *m_poSRSGCPCached = nullptr;
123
124 GDALDataset* poParentDataset = nullptr;
125
126 bool m_bOverviewsEnabled = true;
127
128 Private() = default;
129 };
130
131 struct SharedDatasetCtxt
132 {
133 // PID of the thread that mark the dataset as shared
134 // This may not be the actual PID, but the responsiblePID.
135 GIntBig nPID;
136 char *pszDescription;
137 GDALAccess eAccess;
138
139 GDALDataset *poDS;
140 };
141
142 // Set of datasets opened as shared datasets (with GDALOpenShared)
143 // The values in the set are of type SharedDatasetCtxt.
144 static CPLHashSet *phSharedDatasetSet = nullptr;
145
146 // Set of all datasets created in the constructor of GDALDataset.
147 // In the case of a shared dataset, memorize the PID of the thread
148 // that marked the dataset as shared, so that we can remove it from
149 // the phSharedDatasetSet in the destructor of the dataset, even
150 // if GDALClose is called from a different thread.
151 static std::map<GDALDataset *, GIntBig> *poAllDatasetMap = nullptr;
152
153 static CPLMutex *hDLMutex = nullptr;
154
155 // Static array of all datasets. Used by GDALGetOpenDatasets.
156 // Not thread-safe. See GDALGetOpenDatasets.
157 static GDALDataset **ppDatasets = nullptr;
158
GDALSharedDatasetHashFunc(const void * elt)159 static unsigned long GDALSharedDatasetHashFunc( const void *elt )
160 {
161 const SharedDatasetCtxt *psStruct =
162 static_cast<const SharedDatasetCtxt *>(elt);
163 return static_cast<unsigned long>(
164 CPLHashSetHashStr(psStruct->pszDescription) ^ psStruct->eAccess ^
165 psStruct->nPID);
166 }
167
GDALSharedDatasetEqualFunc(const void * elt1,const void * elt2)168 static int GDALSharedDatasetEqualFunc( const void* elt1, const void* elt2 )
169 {
170 const SharedDatasetCtxt *psStruct1 =
171 static_cast<const SharedDatasetCtxt *>(elt1);
172 const SharedDatasetCtxt *psStruct2 =
173 static_cast<const SharedDatasetCtxt *>(elt2);
174 return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
175 psStruct1->nPID == psStruct2->nPID &&
176 psStruct1->eAccess == psStruct2->eAccess;
177 }
178
GDALSharedDatasetFreeFunc(void * elt)179 static void GDALSharedDatasetFreeFunc( void* elt )
180 {
181 SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
182 CPLFree(psStruct->pszDescription);
183 CPLFree(psStruct);
184 }
185
186 /************************************************************************/
187 /* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
188 /************************************************************************/
189
190 // The open-shared mutex must be used by the ProxyPool too.
GDALGetphDLMutex()191 CPLMutex **GDALGetphDLMutex() { return &hDLMutex; }
192
193 // The current thread will act in the behalf of the thread of PID
194 // responsiblePID.
GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)195 void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
196 {
197 GIntBig *pResponsiblePID =
198 static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
199 if(pResponsiblePID == nullptr)
200 {
201 pResponsiblePID = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
202 CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
203 }
204 *pResponsiblePID = responsiblePID;
205 }
206
207 // Get the PID of the thread that the current thread will act in the behalf of
208 // By default : the current thread acts in the behalf of itself.
GDALGetResponsiblePIDForCurrentThread()209 GIntBig GDALGetResponsiblePIDForCurrentThread()
210 {
211 GIntBig *pResponsiblePID =
212 static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
213 if( pResponsiblePID == nullptr )
214 return CPLGetPID();
215 return *pResponsiblePID;
216 }
217
218 /************************************************************************/
219 /* ==================================================================== */
220 /* GDALDataset */
221 /* ==================================================================== */
222 /************************************************************************/
223
224 /**
225 * \class GDALDataset "gdal_priv.h"
226 *
227 * A dataset encapsulating one or more raster bands. Details are
228 * further discussed in the <a href="gdal_datamodel.html#GDALDataset">GDAL
229 * Data Model</a>.
230 *
231 * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,
232 * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new
233 * dataset.
234 */
235
236 /************************************************************************/
237 /* GDALDataset() */
238 /************************************************************************/
239
240 //! @cond Doxygen_Suppress
GDALDataset()241 GDALDataset::GDALDataset():
242 GDALDataset(CPLTestBool(CPLGetConfigOption("GDAL_FORCE_CACHING", "NO")))
243 {
244 }
245
GDALDataset(int bForceCachedIOIn)246 GDALDataset::GDALDataset(int bForceCachedIOIn):
247 bForceCachedIO(CPL_TO_BOOL(bForceCachedIOIn)),
248 m_poPrivate(new(std::nothrow) GDALDataset::Private)
249 {
250 }
251 //! @endcond
252
253 /************************************************************************/
254 /* ~GDALDataset() */
255 /************************************************************************/
256
257 /**
258 * \brief Destroy an open GDALDataset.
259 *
260 * This is the accepted method of closing a GDAL dataset and deallocating
261 * all resources associated with it.
262 *
263 * Equivalent of the C callable GDALClose(). Except that GDALClose() first
264 * decrements the reference count, and then closes only if it has dropped to
265 * zero.
266 *
267 * For Windows users, it is not recommended to use the delete operator on the
268 * dataset object because of known issues when allocating and freeing memory
269 * across module boundaries. Calling GDALClose() is then a better option.
270 */
271
~GDALDataset()272 GDALDataset::~GDALDataset()
273
274 {
275 // we don't want to report destruction of datasets that
276 // were never really open or meant as internal
277 if( !bIsInternal && (nBands != 0 || !EQUAL(GetDescription(), "")) )
278 {
279 if( CPLGetPID() != GDALGetResponsiblePIDForCurrentThread() )
280 CPLDebug("GDAL",
281 "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)",
282 GetDescription(), this, static_cast<int>(CPLGetPID()),
283 static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
284 else
285 CPLDebug("GDAL", "GDALClose(%s, this=%p)", GetDescription(), this);
286 }
287
288 if( bSuppressOnClose )
289 VSIUnlink(GetDescription());
290
291 /* -------------------------------------------------------------------- */
292 /* Remove dataset from the "open" dataset list. */
293 /* -------------------------------------------------------------------- */
294 if( !bIsInternal )
295 {
296 CPLMutexHolderD(&hDLMutex);
297 if( poAllDatasetMap )
298 {
299 std::map<GDALDataset *, GIntBig>::iterator oIter =
300 poAllDatasetMap->find(this);
301 CPLAssert(oIter != poAllDatasetMap->end());
302 GIntBig nPIDCreatorForShared = oIter->second;
303 poAllDatasetMap->erase(oIter);
304
305 if( bShared && phSharedDatasetSet != nullptr )
306 {
307 SharedDatasetCtxt sStruct;
308 sStruct.nPID = nPIDCreatorForShared;
309 sStruct.eAccess = eAccess;
310 sStruct.pszDescription = const_cast<char *>(GetDescription());
311 SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
312 CPLHashSetLookup(phSharedDatasetSet, &sStruct));
313 if( psStruct && psStruct->poDS == this )
314 {
315 CPLHashSetRemove(phSharedDatasetSet, psStruct);
316 }
317 else
318 {
319 CPLDebug("GDAL", "Should not happen. Cannot find %s, "
320 "this=%p in phSharedDatasetSet",
321 GetDescription(), this);
322 }
323 }
324
325 if (poAllDatasetMap->empty())
326 {
327 delete poAllDatasetMap;
328 poAllDatasetMap = nullptr;
329 if (phSharedDatasetSet)
330 {
331 CPLHashSetDestroy(phSharedDatasetSet);
332 }
333 phSharedDatasetSet = nullptr;
334 CPLFree(ppDatasets);
335 ppDatasets = nullptr;
336 }
337 }
338 }
339
340 /* -------------------------------------------------------------------- */
341 /* Destroy the raster bands if they exist. */
342 /* -------------------------------------------------------------------- */
343 for( int i = 0; i < nBands && papoBands != nullptr; ++i )
344 {
345 if( papoBands[i] != nullptr )
346 delete papoBands[i];
347 papoBands[i] = nullptr;
348 }
349
350 CPLFree(papoBands);
351
352 if ( m_poStyleTable )
353 {
354 delete m_poStyleTable;
355 m_poStyleTable = nullptr;
356 }
357
358 if( m_poPrivate != nullptr )
359 {
360 if( m_poPrivate->hMutex != nullptr )
361 CPLDestroyMutex(m_poPrivate->hMutex);
362
363 CPLFree(m_poPrivate->m_pszWKTCached);
364 if( m_poPrivate->m_poSRSCached )
365 {
366 m_poPrivate->m_poSRSCached->Release();
367 }
368 CPLFree(m_poPrivate->m_pszWKTGCPCached);
369 if( m_poPrivate->m_poSRSGCPCached )
370 {
371 m_poPrivate->m_poSRSGCPCached->Release();
372 }
373 }
374
375 delete m_poPrivate;
376
377 CSLDestroy(papszOpenOptions);
378 }
379
380 /************************************************************************/
381 /* AddToDatasetOpenList() */
382 /************************************************************************/
383
AddToDatasetOpenList()384 void GDALDataset::AddToDatasetOpenList()
385 {
386 /* -------------------------------------------------------------------- */
387 /* Add this dataset to the open dataset list. */
388 /* -------------------------------------------------------------------- */
389 bIsInternal = false;
390
391 CPLMutexHolderD(&hDLMutex);
392
393 if (poAllDatasetMap == nullptr)
394 poAllDatasetMap = new std::map<GDALDataset *, GIntBig>;
395 (*poAllDatasetMap)[this] = -1;
396 }
397
398 /************************************************************************/
399 /* FlushCache() */
400 /************************************************************************/
401
402 /**
403 * \brief Flush all write cached data to disk.
404 *
405 * Any raster (or other GDAL) data written via GDAL calls, but buffered
406 * internally will be written to disk.
407 *
408 * The default implementation of this method just calls the FlushCache() method
409 * on each of the raster bands and the SyncToDisk() method
410 * on each of the layers. Conceptionally, calling FlushCache() on a dataset
411 * should include any work that might be accomplished by calling SyncToDisk()
412 * on layers in that dataset.
413 *
414 * Using this method does not prevent use from calling GDALClose()
415 * to properly close a dataset and ensure that important data not addressed
416 * by FlushCache() is written in the file.
417 *
418 * This method is the same as the C function GDALFlushCache().
419 */
420
FlushCache()421 void GDALDataset::FlushCache()
422
423 {
424 // This sometimes happens if a dataset is destroyed before completely
425 // built.
426
427 if( papoBands != nullptr )
428 {
429 for( int i = 0; i < nBands; ++i )
430 {
431 if( papoBands[i] != nullptr )
432 papoBands[i]->FlushCache();
433 }
434 }
435
436 const int nLayers = GetLayerCount();
437 // cppcheck-suppress knownConditionTrueFalse
438 if( nLayers > 0 )
439 {
440 CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
441 for( int i = 0; i < nLayers; ++i )
442 {
443 OGRLayer *poLayer = GetLayer(i);
444
445 if( poLayer )
446 {
447 poLayer->SyncToDisk();
448 }
449 }
450 }
451 }
452
453 /************************************************************************/
454 /* GDALFlushCache() */
455 /************************************************************************/
456
457 /**
458 * \brief Flush all write cached data to disk.
459 *
460 * @see GDALDataset::FlushCache().
461 */
462
GDALFlushCache(GDALDatasetH hDS)463 void CPL_STDCALL GDALFlushCache( GDALDatasetH hDS )
464
465 {
466 VALIDATE_POINTER0(hDS, "GDALFlushCache");
467
468 GDALDataset::FromHandle(hDS)->FlushCache();
469 }
470
471 /************************************************************************/
472 /* BlockBasedFlushCache() */
473 /* */
474 /* This helper method can be called by the */
475 /* GDALDataset::FlushCache() for particular drivers to ensure */
476 /* that buffers will be flushed in a manner suitable for pixel */
477 /* interleaved (by block) IO. That is, if all the bands have */
478 /* the same size blocks then a given block will be flushed for */
479 /* all bands before proceeding to the next block. */
480 /************************************************************************/
481
482 //! @cond Doxygen_Suppress
BlockBasedFlushCache()483 void GDALDataset::BlockBasedFlushCache()
484
485 {
486 GDALRasterBand *poBand1 = GetRasterBand(1);
487 if( poBand1 == nullptr )
488 {
489 GDALDataset::FlushCache();
490 return;
491 }
492
493 int nBlockXSize = 0;
494 int nBlockYSize = 0;
495 poBand1->GetBlockSize(&nBlockXSize, &nBlockYSize);
496
497 /* -------------------------------------------------------------------- */
498 /* Verify that all bands match. */
499 /* -------------------------------------------------------------------- */
500 for( int iBand = 1; iBand < nBands; ++iBand )
501 {
502 GDALRasterBand *poBand = GetRasterBand(iBand + 1);
503
504 int nThisBlockXSize, nThisBlockYSize;
505 poBand->GetBlockSize(&nThisBlockXSize, &nThisBlockYSize);
506 if( nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize )
507 {
508 GDALDataset::FlushCache();
509 return;
510 }
511 }
512
513 /* -------------------------------------------------------------------- */
514 /* Now flush writable data. */
515 /* -------------------------------------------------------------------- */
516 for( int iY = 0; iY < poBand1->nBlocksPerColumn; ++iY )
517 {
518 for( int iX = 0; iX < poBand1->nBlocksPerRow; ++iX )
519 {
520 for( int iBand = 0; iBand < nBands; ++iBand )
521 {
522 GDALRasterBand *poBand = GetRasterBand(iBand + 1);
523
524 const CPLErr eErr = poBand->FlushBlock(iX, iY);
525
526 if( eErr != CE_None )
527 return;
528 }
529 }
530 }
531 }
532
533 /************************************************************************/
534 /* RasterInitialize() */
535 /* */
536 /* Initialize raster size */
537 /************************************************************************/
538
RasterInitialize(int nXSize,int nYSize)539 void GDALDataset::RasterInitialize( int nXSize, int nYSize )
540
541 {
542 CPLAssert(nXSize > 0 && nYSize > 0);
543
544 nRasterXSize = nXSize;
545 nRasterYSize = nYSize;
546 }
547 //! @endcond
548
549 /************************************************************************/
550 /* AddBand() */
551 /************************************************************************/
552
553 /**
554 * \fn GDALDataset::AddBand(GDALDataType, char**)
555 * \brief Add a band to a dataset.
556 *
557 * This method will add a new band to the dataset if the underlying format
558 * supports this action. Most formats do not.
559 *
560 * Note that the new GDALRasterBand is not returned. It may be fetched
561 * after successful completion of the method by calling
562 * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest
563 * band will always be the last band.
564 *
565 * @param eType the data type of the pixels in the new band.
566 *
567 * @param papszOptions a list of NAME=VALUE option strings. The supported
568 * options are format specific. NULL may be passed by default.
569 *
570 * @return CE_None on success or CE_Failure on failure.
571 */
572
AddBand(CPL_UNUSED GDALDataType eType,CPL_UNUSED char ** papszOptions)573 CPLErr GDALDataset::AddBand( CPL_UNUSED GDALDataType eType,
574 CPL_UNUSED char **papszOptions )
575
576 {
577 ReportError(CE_Failure, CPLE_NotSupported,
578 "Dataset does not support the AddBand() method.");
579
580 return CE_Failure;
581 }
582
583 /************************************************************************/
584 /* GDALAddBand() */
585 /************************************************************************/
586
587 /**
588 * \brief Add a band to a dataset.
589 *
590 * @see GDALDataset::AddBand().
591 */
592
GDALAddBand(GDALDatasetH hDataset,GDALDataType eType,CSLConstList papszOptions)593 CPLErr CPL_STDCALL GDALAddBand( GDALDatasetH hDataset,
594 GDALDataType eType, CSLConstList papszOptions )
595
596 {
597 VALIDATE_POINTER1(hDataset, "GDALAddBand", CE_Failure);
598
599 return GDALDataset::FromHandle(hDataset)->AddBand(eType,
600 const_cast<char**>(papszOptions));
601 }
602
603 /************************************************************************/
604 /* SetBand() */
605 /************************************************************************/
606
607 //! @cond Doxygen_Suppress
608 /** Set a band in the band array, updating the band count, and array size
609 * appropriately.
610 *
611 * @param nNewBand new band number (indexing starts at 1)
612 * @param poBand band object.
613 */
614
SetBand(int nNewBand,GDALRasterBand * poBand)615 void GDALDataset::SetBand( int nNewBand, GDALRasterBand * poBand )
616
617 {
618 /* -------------------------------------------------------------------- */
619 /* Do we need to grow the bands list? */
620 /* -------------------------------------------------------------------- */
621 if( nBands < nNewBand || papoBands == nullptr )
622 {
623 GDALRasterBand **papoNewBands = nullptr;
624
625 if( papoBands == nullptr )
626 papoNewBands = static_cast<GDALRasterBand **>(VSICalloc(
627 sizeof(GDALRasterBand *), std::max(nNewBand, nBands)));
628 else
629 papoNewBands = static_cast<GDALRasterBand **>(
630 VSIRealloc(papoBands, sizeof(GDALRasterBand *) *
631 std::max(nNewBand, nBands)));
632 if (papoNewBands == nullptr)
633 {
634 ReportError(CE_Failure, CPLE_OutOfMemory,
635 "Cannot allocate band array");
636 return;
637 }
638
639 papoBands = papoNewBands;
640
641 for( int i = nBands; i < nNewBand; ++i )
642 papoBands[i] = nullptr;
643
644 nBands = std::max(nBands, nNewBand);
645 }
646
647 /* -------------------------------------------------------------------- */
648 /* Set the band. Resetting the band is currently not permitted. */
649 /* -------------------------------------------------------------------- */
650 if( papoBands[nNewBand - 1] != nullptr )
651 {
652 ReportError(CE_Failure, CPLE_NotSupported,
653 "Cannot set band %d as it is already set", nNewBand);
654 return;
655 }
656
657 papoBands[nNewBand - 1] = poBand;
658
659 /* -------------------------------------------------------------------- */
660 /* Set back reference information on the raster band. Note */
661 /* that the GDALDataset is a friend of the GDALRasterBand */
662 /* specifically to allow this. */
663 /* -------------------------------------------------------------------- */
664 poBand->nBand = nNewBand;
665 poBand->poDS = this;
666 poBand->nRasterXSize = nRasterXSize;
667 poBand->nRasterYSize = nRasterYSize;
668 poBand->eAccess = eAccess; // Default access to be same as dataset.
669 }
670 //! @endcond
671
672 /************************************************************************/
673 /* GetRasterXSize() */
674 /************************************************************************/
675
676 /**
677
678 \brief Fetch raster width in pixels.
679
680 Equivalent of the C function GDALGetRasterXSize().
681
682 @return the width in pixels of raster bands in this GDALDataset.
683
684 */
685
GetRasterXSize()686 int GDALDataset::GetRasterXSize() { return nRasterXSize; }
687
688 /************************************************************************/
689 /* GDALGetRasterXSize() */
690 /************************************************************************/
691
692 /**
693 * \brief Fetch raster width in pixels.
694 *
695 * @see GDALDataset::GetRasterXSize().
696 */
697
GDALGetRasterXSize(GDALDatasetH hDataset)698 int CPL_STDCALL GDALGetRasterXSize( GDALDatasetH hDataset )
699
700 {
701 VALIDATE_POINTER1(hDataset, "GDALGetRasterXSize", 0);
702
703 return GDALDataset::FromHandle(hDataset)->GetRasterXSize();
704 }
705
706 /************************************************************************/
707 /* GetRasterYSize() */
708 /************************************************************************/
709
710 /**
711
712 \brief Fetch raster height in pixels.
713
714 Equivalent of the C function GDALGetRasterYSize().
715
716 @return the height in pixels of raster bands in this GDALDataset.
717
718 */
719
GetRasterYSize()720 int GDALDataset::GetRasterYSize() { return nRasterYSize; }
721
722 /************************************************************************/
723 /* GDALGetRasterYSize() */
724 /************************************************************************/
725
726 /**
727 * \brief Fetch raster height in pixels.
728 *
729 * @see GDALDataset::GetRasterYSize().
730 */
731
GDALGetRasterYSize(GDALDatasetH hDataset)732 int CPL_STDCALL GDALGetRasterYSize( GDALDatasetH hDataset )
733
734 {
735 VALIDATE_POINTER1(hDataset, "GDALGetRasterYSize", 0);
736
737 return GDALDataset::FromHandle(hDataset)->GetRasterYSize();
738 }
739
740 /************************************************************************/
741 /* GetRasterBand() */
742 /************************************************************************/
743
744 /**
745
746 \brief Fetch a band object for a dataset.
747
748 See GetBands() for a C++ iterator version of this method.
749
750 Equivalent of the C function GDALGetRasterBand().
751
752 @param nBandId the index number of the band to fetch, from 1 to
753 GetRasterCount().
754
755 @return the nBandId th band object
756
757 */
758
GetRasterBand(int nBandId)759 GDALRasterBand * GDALDataset::GetRasterBand( int nBandId )
760
761 {
762 if ( papoBands )
763 {
764 if( nBandId < 1 || nBandId > nBands )
765 {
766 ReportError(CE_Failure, CPLE_IllegalArg,
767 "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
768 nBandId);
769 return nullptr;
770 }
771
772 return papoBands[nBandId - 1];
773 }
774 return nullptr;
775 }
776
777 /************************************************************************/
778 /* GDALGetRasterBand() */
779 /************************************************************************/
780
781 /**
782 * \brief Fetch a band object for a dataset.
783 * @see GDALDataset::GetRasterBand().
784 */
785
GDALGetRasterBand(GDALDatasetH hDS,int nBandId)786 GDALRasterBandH CPL_STDCALL GDALGetRasterBand( GDALDatasetH hDS, int nBandId )
787
788 {
789 VALIDATE_POINTER1(hDS, "GDALGetRasterBand", nullptr);
790
791 return GDALRasterBand::ToHandle(
792 GDALDataset::FromHandle(hDS)->GetRasterBand(nBandId));
793 }
794
795 /************************************************************************/
796 /* GetRasterCount() */
797 /************************************************************************/
798
799 /**
800 * \brief Fetch the number of raster bands on this dataset.
801 *
802 * Same as the C function GDALGetRasterCount().
803 *
804 * @return the number of raster bands.
805 */
806
GetRasterCount()807 int GDALDataset::GetRasterCount() { return papoBands ? nBands : 0; }
808
809 /************************************************************************/
810 /* GDALGetRasterCount() */
811 /************************************************************************/
812
813 /**
814 * \brief Fetch the number of raster bands on this dataset.
815 *
816 * @see GDALDataset::GetRasterCount().
817 */
818
GDALGetRasterCount(GDALDatasetH hDS)819 int CPL_STDCALL GDALGetRasterCount( GDALDatasetH hDS )
820
821 {
822 VALIDATE_POINTER1(hDS, "GDALGetRasterCount", 0);
823
824 return GDALDataset::FromHandle(hDS)->GetRasterCount();
825 }
826
827 /************************************************************************/
828 /* GetProjectionRef() */
829 /************************************************************************/
830
831 /**
832 * \brief Fetch the projection definition string for this dataset.
833 *
834 * Same as the C function GDALGetProjectionRef().
835 *
836 * The returned string defines the projection coordinate system of the
837 * image in OpenGIS WKT format. It should be suitable for use with the
838 * OGRSpatialReference class.
839 *
840 * When a projection definition is not available an empty (but not NULL)
841 * string is returned.
842 *
843 * \note Startig with GDAL 3.0, this is a compatibility layer around
844 * GetSpatialRef()
845 *
846 * @return a pointer to an internal projection reference string. It should
847 * not be altered, freed or expected to last for long.
848 *
849 * @see https://gdal.org/tutorials/osr_api_tut.html
850 */
851
GetProjectionRef() const852 const char *GDALDataset::GetProjectionRef() const
853 {
854 return GetProjectionRefFromSpatialRef(GetSpatialRef());
855
856 }
857
858 //! @cond Doxygen_Suppress
GetProjectionRefFromSpatialRef(const OGRSpatialReference * poSRS) const859 const char *GDALDataset::GetProjectionRefFromSpatialRef(const OGRSpatialReference* poSRS) const
860 {
861 if( !poSRS || !m_poPrivate )
862 {
863 return "";
864 }
865 char* pszWKT = nullptr;
866 poSRS->exportToWkt(&pszWKT);
867 if( !pszWKT )
868 {
869 return "";
870 }
871 if( m_poPrivate->m_pszWKTCached &&
872 strcmp(pszWKT, m_poPrivate->m_pszWKTCached) == 0 )
873 {
874 CPLFree(pszWKT);
875 return m_poPrivate->m_pszWKTCached;
876 }
877 CPLFree(m_poPrivate->m_pszWKTCached);
878 m_poPrivate->m_pszWKTCached = pszWKT;
879 return m_poPrivate->m_pszWKTCached;
880 }
881 //! @endcond
882
883 /************************************************************************/
884 /* _GetProjectionRef() */
885 /************************************************************************/
886
887 //! @cond Doxygen_Suppress
888 /** Pre GDAL-2.5 way */
_GetProjectionRef()889 const char *GDALDataset::_GetProjectionRef() { return (""); }
890 //! @endcond
891
892 /************************************************************************/
893 /* GetSpatialRef() */
894 /************************************************************************/
895
896 /**
897 * \brief Fetch the spatial reference for this dataset.
898 *
899 * Same as the C function GDALGetSpatialRef().
900 *
901 * When a projection definition is not available, null is returned. If used on
902 * a dataset where there are GCPs and not a geotransform, this method returns
903 * null. Use GetGCPSpatialRef() instead.
904 *
905 * @since GDAL 3.0
906 *
907 * @return a pointer to an internal object. It should not be altered or freed.
908 * Its lifetime will be the one of the dataset object, or until the next
909 * call to this method.
910 *
911 * @see https://gdal.org/tutorials/osr_api_tut.html
912 */
913
GetSpatialRef() const914 const OGRSpatialReference* GDALDataset::GetSpatialRef() const
915 {
916 return nullptr;
917 }
918
919 /************************************************************************/
920 /* GDALGetSpatialRef() */
921 /************************************************************************/
922
923 /**
924 * \brief Fetch the spatial reference for this dataset.
925 *
926 * @since GDAL 3.0
927 *
928 * @see GDALDataset::GetSpatialRef()
929 */
930
GDALGetSpatialRef(GDALDatasetH hDS)931 OGRSpatialReferenceH GDALGetSpatialRef( GDALDatasetH hDS )
932
933 {
934 VALIDATE_POINTER1(hDS, "GDALGetSpatialRef", nullptr);
935
936 return OGRSpatialReference::ToHandle(
937 const_cast<OGRSpatialReference*>(
938 GDALDataset::FromHandle(hDS)->GetSpatialRef()));
939 }
940
941 /************************************************************************/
942 /* GetSpatialRefFromOldGetProjectionRef() */
943 /************************************************************************/
944
945 //! @cond Doxygen_Suppress
GetSpatialRefFromOldGetProjectionRef() const946 const OGRSpatialReference* GDALDataset::GetSpatialRefFromOldGetProjectionRef() const
947 {
948 const char* pszWKT = const_cast<GDALDataset*>(this)->_GetProjectionRef();
949 if( !pszWKT || pszWKT[0] == '\0' || !m_poPrivate )
950 {
951 return nullptr;
952 }
953 if( !m_poPrivate->m_poSRSCached )
954 {
955 m_poPrivate->m_poSRSCached = new OGRSpatialReference();
956 m_poPrivate->m_poSRSCached->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
957 }
958 if( m_poPrivate->m_poSRSCached->importFromWkt(pszWKT) != OGRERR_NONE )
959 {
960 return nullptr;
961 }
962 return m_poPrivate->m_poSRSCached;
963 }
964 //! @endcond
965
966 /************************************************************************/
967 /* GDALGetProjectionRef() */
968 /************************************************************************/
969
970 /**
971 * \brief Fetch the projection definition string for this dataset.
972 *
973 * @see GDALDataset::GetProjectionRef()
974 */
975
GDALGetProjectionRef(GDALDatasetH hDS)976 const char * CPL_STDCALL GDALGetProjectionRef( GDALDatasetH hDS )
977
978 {
979 VALIDATE_POINTER1(hDS, "GDALGetProjectionRef", nullptr);
980
981 return GDALDataset::FromHandle(hDS)->GetProjectionRef();
982 }
983
984 /************************************************************************/
985 /* SetProjection() */
986 /************************************************************************/
987
988 /**
989 * \brief Set the projection reference string for this dataset.
990 *
991 * The string should be in OGC WKT or PROJ.4 format. An error may occur
992 * because of incorrectly specified projection strings, because the dataset
993 * is not writable, or because the dataset does not support the indicated
994 * projection. Many formats do not support writing projections.
995 *
996 * This method is the same as the C GDALSetProjection() function.
997 *
998 * \note Startig with GDAL 3.0, this is a compatibility layer around
999 * SetSpatialRef()
1000
1001 * @param pszProjection projection reference string.
1002 *
1003 * @return CE_Failure if an error occurs, otherwise CE_None.
1004 */
1005
SetProjection(const char * pszProjection)1006 CPLErr GDALDataset::SetProjection( const char *pszProjection )
1007 {
1008 if( pszProjection && pszProjection[0] != '\0' )
1009 {
1010 OGRSpatialReference oSRS;
1011 oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1012 if( oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE )
1013 {
1014 return CE_Failure;
1015 }
1016 return SetSpatialRef(&oSRS);
1017 }
1018 else
1019 {
1020 return SetSpatialRef(nullptr);
1021 }
1022 }
1023
1024 /************************************************************************/
1025 /* SetSpatialRef() */
1026 /************************************************************************/
1027
1028 /**
1029 * \brief Set the spatial reference system for this dataset.
1030 *
1031 * An error may occur because the dataset
1032 * is not writable, or because the dataset does not support the indicated
1033 * projection. Many formats do not support writing projections.
1034 *
1035 * This method is the same as the C GDALSetSpatialRef() function.
1036 *
1037 * @since GDAL 3.0
1038
1039 * @param poSRS spatial reference system object. nullptr can potentially be
1040 * passed for drivers that support unsetting the SRS.
1041 *
1042 * @return CE_Failure if an error occurs, otherwise CE_None.
1043 */
1044
SetSpatialRef(CPL_UNUSED const OGRSpatialReference * poSRS)1045 CPLErr GDALDataset::SetSpatialRef( CPL_UNUSED const OGRSpatialReference* poSRS )
1046 {
1047 if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1048 ReportError(CE_Failure, CPLE_NotSupported,
1049 "Dataset does not support the SetSpatialRef() method.");
1050 return CE_Failure;
1051 }
1052
1053 /************************************************************************/
1054 /* GDALSetSpatialRef() */
1055 /************************************************************************/
1056
1057 /**
1058 * \brief Set the spatial reference system for this dataset.
1059 *
1060 * @since GDAL 3.0
1061 *
1062 * @see GDALDataset::SetSpatialRef()
1063 */
1064
GDALSetSpatialRef(GDALDatasetH hDS,OGRSpatialReferenceH hSRS)1065 CPLErr GDALSetSpatialRef( GDALDatasetH hDS, OGRSpatialReferenceH hSRS )
1066
1067 {
1068 VALIDATE_POINTER1(hDS, "GDALSetSpatialRef", CE_Failure);
1069
1070 return GDALDataset::FromHandle(hDS)->SetSpatialRef(
1071 OGRSpatialReference::FromHandle(hSRS));
1072 }
1073
1074 /************************************************************************/
1075 /* _SetProjection() */
1076 /************************************************************************/
1077
1078 //! @cond Doxygen_Suppress
1079 /** Pre GDAL-2.5 way */
_SetProjection(const char *)1080 CPLErr GDALDataset::_SetProjection( const char * )
1081 {
1082 if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1083 ReportError(CE_Failure, CPLE_NotSupported,
1084 "Dataset does not support the SetProjection() method.");
1085 return CE_Failure;
1086 }
1087 //! @endcond
1088
1089 /************************************************************************/
1090 /* OldSetProjectionFromSetSpatialRef() */
1091 /************************************************************************/
1092
1093 //! @cond Doxygen_Suppress
OldSetProjectionFromSetSpatialRef(const OGRSpatialReference * poSRS)1094 CPLErr GDALDataset::OldSetProjectionFromSetSpatialRef(
1095 const OGRSpatialReference* poSRS)
1096 {
1097 if( !poSRS || poSRS->IsEmpty() )
1098 {
1099 return _SetProjection("");
1100 }
1101 char* pszWKT = nullptr;
1102 if( poSRS->exportToWkt(&pszWKT) != OGRERR_NONE )
1103 {
1104 CPLFree(pszWKT);
1105 return CE_Failure;
1106 }
1107 auto ret = _SetProjection(pszWKT);
1108 CPLFree(pszWKT);
1109 return ret;
1110 }
1111 //! @endcond
1112
1113 /************************************************************************/
1114 /* GDALSetProjection() */
1115 /************************************************************************/
1116
1117 /**
1118 * \brief Set the projection reference string for this dataset.
1119 *
1120 * @see GDALDataset::SetProjection()
1121 */
1122
GDALSetProjection(GDALDatasetH hDS,const char * pszProjection)1123 CPLErr CPL_STDCALL GDALSetProjection( GDALDatasetH hDS,
1124 const char * pszProjection )
1125
1126 {
1127 VALIDATE_POINTER1(hDS, "GDALSetProjection", CE_Failure);
1128
1129 return GDALDataset::FromHandle(hDS)->SetProjection(pszProjection);
1130 }
1131
1132 /************************************************************************/
1133 /* GetGeoTransform() */
1134 /************************************************************************/
1135
1136 /**
1137 * \brief Fetch the affine transformation coefficients.
1138 *
1139 * Fetches the coefficients for transforming between pixel/line (P,L) raster
1140 * space, and projection coordinates (Xp,Yp) space.
1141 *
1142 * \code
1143 * Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
1144 * Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
1145 * \endcode
1146 *
1147 * In a north up image, padfTransform[1] is the pixel width, and
1148 * padfTransform[5] is the pixel height. The upper left corner of the
1149 * upper left pixel is at position (padfTransform[0],padfTransform[3]).
1150 *
1151 * The default transform is (0,1,0,0,0,1) and should be returned even when
1152 * a CE_Failure error is returned, such as for formats that don't support
1153 * transformation to projection coordinates.
1154 *
1155 * This method does the same thing as the C GDALGetGeoTransform() function.
1156 *
1157 * @param padfTransform an existing six double buffer into which the
1158 * transformation will be placed.
1159 *
1160 * @return CE_None on success, or CE_Failure if no transform can be fetched.
1161 */
1162
GetGeoTransform(double * padfTransform)1163 CPLErr GDALDataset::GetGeoTransform( double * padfTransform )
1164
1165 {
1166 CPLAssert(padfTransform != nullptr);
1167
1168 padfTransform[0] = 0.0; // X Origin (top left corner)
1169 padfTransform[1] = 1.0; // X Pixel size */
1170 padfTransform[2] = 0.0;
1171
1172 padfTransform[3] = 0.0; // Y Origin (top left corner)
1173 padfTransform[4] = 0.0;
1174 padfTransform[5] = 1.0; // Y Pixel Size
1175
1176 return CE_Failure;
1177 }
1178
1179 /************************************************************************/
1180 /* GDALGetGeoTransform() */
1181 /************************************************************************/
1182
1183 /**
1184 * \brief Fetch the affine transformation coefficients.
1185 *
1186 * @see GDALDataset::GetGeoTransform()
1187 */
1188
GDALGetGeoTransform(GDALDatasetH hDS,double * padfTransform)1189 CPLErr CPL_STDCALL GDALGetGeoTransform( GDALDatasetH hDS,
1190 double * padfTransform )
1191
1192 {
1193 VALIDATE_POINTER1(hDS, "GDALGetGeoTransform", CE_Failure);
1194
1195 return GDALDataset::FromHandle(hDS)->GetGeoTransform(padfTransform);
1196 }
1197
1198 /************************************************************************/
1199 /* SetGeoTransform() */
1200 /************************************************************************/
1201
1202 /**
1203 * \fn GDALDataset::SetGeoTransform(double*)
1204 * \brief Set the affine transformation coefficients.
1205 *
1206 * See GetGeoTransform() for details on the meaning of the padfTransform
1207 * coefficients.
1208 *
1209 * This method does the same thing as the C GDALSetGeoTransform() function.
1210 *
1211 * @param padfTransform a six double buffer containing the transformation
1212 * coefficients to be written with the dataset.
1213 *
1214 * @return CE_None on success, or CE_Failure if this transform cannot be
1215 * written.
1216 */
1217
SetGeoTransform(CPL_UNUSED double * padfTransform)1218 CPLErr GDALDataset::SetGeoTransform( CPL_UNUSED double *padfTransform )
1219
1220 {
1221 if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1222 ReportError(CE_Failure, CPLE_NotSupported,
1223 "SetGeoTransform() not supported for this dataset.");
1224
1225 return CE_Failure;
1226 }
1227
1228 /************************************************************************/
1229 /* GDALSetGeoTransform() */
1230 /************************************************************************/
1231
1232 /**
1233 * \brief Set the affine transformation coefficients.
1234 *
1235 * @see GDALDataset::SetGeoTransform()
1236 */
1237
1238 CPLErr CPL_STDCALL
GDALSetGeoTransform(GDALDatasetH hDS,double * padfTransform)1239 GDALSetGeoTransform( GDALDatasetH hDS, double *padfTransform )
1240
1241 {
1242 VALIDATE_POINTER1(hDS, "GDALSetGeoTransform", CE_Failure);
1243
1244 return GDALDataset::FromHandle(hDS)->SetGeoTransform(padfTransform);
1245 }
1246
1247 /************************************************************************/
1248 /* GetInternalHandle() */
1249 /************************************************************************/
1250
1251 /**
1252 * \fn GDALDataset::GetInternalHandle(const char*)
1253 * \brief Fetch a format specific internally meaningful handle.
1254 *
1255 * This method is the same as the C GDALGetInternalHandle() method.
1256 *
1257 * @param pszHandleName the handle name desired. The meaningful names
1258 * will be specific to the file format.
1259 *
1260 * @return the desired handle value, or NULL if not recognized/supported.
1261 */
1262
GetInternalHandle(CPL_UNUSED const char * pszHandleName)1263 void *GDALDataset::GetInternalHandle( CPL_UNUSED const char *pszHandleName )
1264
1265 {
1266 return nullptr;
1267 }
1268
1269 /************************************************************************/
1270 /* GDALGetInternalHandle() */
1271 /************************************************************************/
1272
1273 /**
1274 * \brief Fetch a format specific internally meaningful handle.
1275 *
1276 * @see GDALDataset::GetInternalHandle()
1277 */
1278
1279 void * CPL_STDCALL
GDALGetInternalHandle(GDALDatasetH hDS,const char * pszRequest)1280 GDALGetInternalHandle( GDALDatasetH hDS, const char * pszRequest )
1281
1282 {
1283 VALIDATE_POINTER1(hDS, "GDALGetInternalHandle", nullptr);
1284
1285 return GDALDataset::FromHandle(hDS)->GetInternalHandle(pszRequest);
1286 }
1287
1288 /************************************************************************/
1289 /* GetDriver() */
1290 /************************************************************************/
1291
1292 /**
1293 * \brief Fetch the driver to which this dataset relates.
1294 *
1295 * This method is the same as the C GDALGetDatasetDriver() function.
1296 *
1297 * @return the driver on which the dataset was created with GDALOpen() or
1298 * GDALCreate().
1299 */
1300
GetDriver()1301 GDALDriver *GDALDataset::GetDriver() { return poDriver; }
1302
1303 /************************************************************************/
1304 /* GDALGetDatasetDriver() */
1305 /************************************************************************/
1306
1307 /**
1308 * \brief Fetch the driver to which this dataset relates.
1309 *
1310 * @see GDALDataset::GetDriver()
1311 */
1312
GDALGetDatasetDriver(GDALDatasetH hDataset)1313 GDALDriverH CPL_STDCALL GDALGetDatasetDriver( GDALDatasetH hDataset )
1314
1315 {
1316 VALIDATE_POINTER1(hDataset, "GDALGetDatasetDriver", nullptr);
1317
1318 return static_cast<GDALDriverH>(
1319 GDALDataset::FromHandle(hDataset)->GetDriver());
1320 }
1321
1322 /************************************************************************/
1323 /* Reference() */
1324 /************************************************************************/
1325
1326 /**
1327 * \brief Add one to dataset reference count.
1328 *
1329 * The reference is one after instantiation.
1330 *
1331 * This method is the same as the C GDALReferenceDataset() function.
1332 *
1333 * @return the post-increment reference count.
1334 */
1335
Reference()1336 int GDALDataset::Reference() { return ++nRefCount; }
1337
1338 /************************************************************************/
1339 /* GDALReferenceDataset() */
1340 /************************************************************************/
1341
1342 /**
1343 * \brief Add one to dataset reference count.
1344 *
1345 * @see GDALDataset::Reference()
1346 */
1347
GDALReferenceDataset(GDALDatasetH hDataset)1348 int CPL_STDCALL GDALReferenceDataset( GDALDatasetH hDataset )
1349
1350 {
1351 VALIDATE_POINTER1(hDataset, "GDALReferenceDataset", 0);
1352
1353 return GDALDataset::FromHandle(hDataset)->Reference();
1354 }
1355
1356 /************************************************************************/
1357 /* Dereference() */
1358 /************************************************************************/
1359
1360 /**
1361 * \brief Subtract one from dataset reference count.
1362 *
1363 * The reference is one after instantiation. Generally when the reference
1364 * count has dropped to zero the dataset may be safely deleted (closed).
1365 *
1366 * This method is the same as the C GDALDereferenceDataset() function.
1367 *
1368 * @return the post-decrement reference count.
1369 */
1370
Dereference()1371 int GDALDataset::Dereference() { return --nRefCount; }
1372
1373 /************************************************************************/
1374 /* GDALDereferenceDataset() */
1375 /************************************************************************/
1376
1377 /**
1378 * \brief Subtract one from dataset reference count.
1379 *
1380 * @see GDALDataset::Dereference()
1381 */
1382
GDALDereferenceDataset(GDALDatasetH hDataset)1383 int CPL_STDCALL GDALDereferenceDataset( GDALDatasetH hDataset )
1384
1385 {
1386 VALIDATE_POINTER1(hDataset, "GDALDereferenceDataset", 0);
1387
1388 return GDALDataset::FromHandle(hDataset)->Dereference();
1389 }
1390
1391
1392 /************************************************************************/
1393 /* ReleaseRef() */
1394 /************************************************************************/
1395
1396 /**
1397 * \brief Drop a reference to this object, and destroy if no longer referenced.
1398 * @return TRUE if the object has been destroyed.
1399 * @since GDAL 2.2
1400 */
1401
ReleaseRef()1402 int GDALDataset::ReleaseRef()
1403
1404 {
1405 if( Dereference() <= 0 )
1406 {
1407 nRefCount = 1;
1408 delete this;
1409 return TRUE;
1410 }
1411 return FALSE;
1412 }
1413
1414 /************************************************************************/
1415 /* GDALReleaseDataset() */
1416 /************************************************************************/
1417
1418 /**
1419 * \brief Drop a reference to this object, and destroy if no longer referenced.
1420 *
1421 * @see GDALDataset::ReleaseRef()
1422 * @since GDAL 2.2
1423 */
1424
GDALReleaseDataset(GDALDatasetH hDataset)1425 int CPL_STDCALL GDALReleaseDataset( GDALDatasetH hDataset )
1426
1427 {
1428 VALIDATE_POINTER1(hDataset, "GDALReleaseDataset", 0);
1429
1430 return GDALDataset::FromHandle(hDataset)->ReleaseRef();
1431 }
1432
1433 /************************************************************************/
1434 /* GetShared() */
1435 /************************************************************************/
1436
1437 /**
1438 * \brief Returns shared flag.
1439 *
1440 * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
1441 */
1442
GetShared() const1443 int GDALDataset::GetShared() const { return bShared; }
1444
1445 /************************************************************************/
1446 /* MarkAsShared() */
1447 /************************************************************************/
1448
1449 /**
1450 * \brief Mark this dataset as available for sharing.
1451 */
1452
MarkAsShared()1453 void GDALDataset::MarkAsShared()
1454
1455 {
1456 CPLAssert(!bShared);
1457
1458 bShared = true;
1459 if( bIsInternal )
1460 return;
1461
1462 GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
1463
1464 // Insert the dataset in the set of shared opened datasets.
1465 CPLMutexHolderD(&hDLMutex);
1466 if (phSharedDatasetSet == nullptr)
1467 phSharedDatasetSet =
1468 CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc,
1469 GDALSharedDatasetFreeFunc);
1470
1471 SharedDatasetCtxt *psStruct =
1472 static_cast<SharedDatasetCtxt *>(CPLMalloc(sizeof(SharedDatasetCtxt)));
1473 psStruct->poDS = this;
1474 psStruct->nPID = nPID;
1475 psStruct->eAccess = eAccess;
1476 psStruct->pszDescription = CPLStrdup(GetDescription());
1477 if(CPLHashSetLookup(phSharedDatasetSet, psStruct) != nullptr)
1478 {
1479 CPLFree(psStruct->pszDescription);
1480 CPLFree(psStruct);
1481 ReportError(CE_Failure, CPLE_AppDefined,
1482 "An existing shared dataset already has this description. "
1483 "This should not happen.");
1484 }
1485 else
1486 {
1487 CPLHashSetInsert(phSharedDatasetSet, psStruct);
1488
1489 (*poAllDatasetMap)[this] = nPID;
1490 }
1491 }
1492
1493 /************************************************************************/
1494 /* GetGCPCount() */
1495 /************************************************************************/
1496
1497 /**
1498 * \brief Get number of GCPs.
1499 *
1500 * This method is the same as the C function GDALGetGCPCount().
1501 *
1502 * @return number of GCPs for this dataset. Zero if there are none.
1503 */
1504
GetGCPCount()1505 int GDALDataset::GetGCPCount() { return 0; }
1506
1507 /************************************************************************/
1508 /* GDALGetGCPCount() */
1509 /************************************************************************/
1510
1511 /**
1512 * \brief Get number of GCPs.
1513 *
1514 * @see GDALDataset::GetGCPCount()
1515 */
1516
GDALGetGCPCount(GDALDatasetH hDS)1517 int CPL_STDCALL GDALGetGCPCount( GDALDatasetH hDS )
1518
1519 {
1520 VALIDATE_POINTER1(hDS, "GDALGetGCPCount", 0);
1521
1522 return GDALDataset::FromHandle(hDS)->GetGCPCount();
1523 }
1524
1525 /************************************************************************/
1526 /* GetGCPProjection() */
1527 /************************************************************************/
1528
1529 /**
1530 * \brief Get output projection for GCPs.
1531 *
1532 * This method is the same as the C function GDALGetGCPProjection().
1533 *
1534 * The projection string follows the normal rules from GetProjectionRef().
1535 *
1536 * \note Starting with GDAL 3.0, this is a compatibility layer around
1537 * GetGCPSpatialRef()
1538 *
1539 * @return internal projection string or "" if there are no GCPs.
1540 * It should not be altered, freed or expected to last for long.
1541 */
1542
GetGCPProjection()1543 const char *GDALDataset::GetGCPProjection()
1544 {
1545 return GetGCPProjectionFromSpatialRef(GetGCPSpatialRef());
1546 }
1547
1548 //! @cond Doxygen_Suppress
GetGCPProjectionFromSpatialRef(const OGRSpatialReference * poSRS) const1549 const char *GDALDataset::GetGCPProjectionFromSpatialRef(const OGRSpatialReference* poSRS) const
1550 {
1551 if( !poSRS || !m_poPrivate )
1552 {
1553 return "";
1554 }
1555 char* pszWKT = nullptr;
1556 poSRS->exportToWkt(&pszWKT);
1557 if( !pszWKT )
1558 {
1559 return "";
1560 }
1561 if( m_poPrivate->m_pszWKTGCPCached &&
1562 strcmp(pszWKT, m_poPrivate->m_pszWKTGCPCached) == 0 )
1563 {
1564 CPLFree(pszWKT);
1565 return m_poPrivate->m_pszWKTGCPCached;
1566 }
1567 CPLFree(m_poPrivate->m_pszWKTGCPCached);
1568 m_poPrivate->m_pszWKTGCPCached = pszWKT;
1569 return m_poPrivate->m_pszWKTGCPCached;
1570 }
1571 //! @endcond
1572
1573 /************************************************************************/
1574 /* _GetGCPProjection() */
1575 /************************************************************************/
1576
1577 //! @cond Doxygen_Suppress
1578 /** Pre GDAL-2.5 way */
_GetGCPProjection()1579 const char *GDALDataset::_GetGCPProjection() { return ""; }
1580 //! @endcond
1581
1582 /************************************************************************/
1583 /* GetGCPSpatialRef() */
1584 /************************************************************************/
1585
1586 /**
1587 * \brief Get output spatial reference system for GCPs.
1588 *
1589 * Same as the C function GDALGetGCPSpatialRef().
1590 *
1591 * When a SRS is not available, null is returned. If used on
1592 * a dataset where there is a geotransform, and not GCPs, this method returns
1593 * null. Use GetSpatialRef() instead.
1594 *
1595 * @since GDAL 3.0
1596 *
1597 * @return a pointer to an internal object. It should not be altered or freed.
1598 * Its lifetime will be the one of the dataset object, or until the next
1599 * call to this method.
1600 */
1601
GetGCPSpatialRef() const1602 const OGRSpatialReference* GDALDataset::GetGCPSpatialRef() const
1603 {
1604 return nullptr;
1605 }
1606
1607 /************************************************************************/
1608 /* GDALGetGCPSpatialRef() */
1609 /************************************************************************/
1610
1611 /**
1612 * \brief Get output spatial reference system for GCPs.
1613 *
1614 * @since GDAL 3.0
1615 *
1616 * @see GDALDataset::GetGCPSpatialRef()
1617 */
1618
GDALGetGCPSpatialRef(GDALDatasetH hDS)1619 OGRSpatialReferenceH GDALGetGCPSpatialRef( GDALDatasetH hDS )
1620
1621 {
1622 VALIDATE_POINTER1(hDS, "GDALGetGCPSpatialRef", nullptr);
1623
1624 return OGRSpatialReference::ToHandle(
1625 const_cast<OGRSpatialReference*>(
1626 GDALDataset::FromHandle(hDS)->GetGCPSpatialRef()));
1627 }
1628
1629 /************************************************************************/
1630 /* GetGCPSpatialRefFromOldGetGCPProjection() */
1631 /************************************************************************/
1632
1633 //! @cond Doxygen_Suppress
GetGCPSpatialRefFromOldGetGCPProjection() const1634 const OGRSpatialReference* GDALDataset::GetGCPSpatialRefFromOldGetGCPProjection() const
1635 {
1636 const char* pszWKT = const_cast<GDALDataset*>(this)->_GetGCPProjection();
1637 if( !pszWKT || pszWKT[0] == '\0' || !m_poPrivate )
1638 {
1639 return nullptr;
1640 }
1641 if( !m_poPrivate->m_poSRSGCPCached)
1642 {
1643 m_poPrivate->m_poSRSGCPCached = new OGRSpatialReference();
1644 m_poPrivate->m_poSRSGCPCached->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1645 }
1646 if( m_poPrivate->m_poSRSGCPCached->importFromWkt(pszWKT) != OGRERR_NONE )
1647 {
1648 return nullptr;
1649 }
1650 return m_poPrivate->m_poSRSGCPCached;
1651 }
1652 //! @endcond
1653
1654 /************************************************************************/
1655 /* GDALGetGCPProjection() */
1656 /************************************************************************/
1657
1658 /**
1659 * \brief Get output projection for GCPs.
1660 *
1661 * @see GDALDataset::GetGCPProjection()
1662 */
1663
GDALGetGCPProjection(GDALDatasetH hDS)1664 const char * CPL_STDCALL GDALGetGCPProjection( GDALDatasetH hDS )
1665
1666 {
1667 VALIDATE_POINTER1(hDS, "GDALGetGCPProjection", nullptr);
1668
1669 return GDALDataset::FromHandle(hDS)->GetGCPProjection();
1670 }
1671
1672 /************************************************************************/
1673 /* GetGCPs() */
1674 /************************************************************************/
1675
1676 /**
1677 * \brief Fetch GCPs.
1678 *
1679 * This method is the same as the C function GDALGetGCPs().
1680 *
1681 * @return pointer to internal GCP structure list. It should not be modified,
1682 * and may change on the next GDAL call.
1683 */
1684
GetGCPs()1685 const GDAL_GCP *GDALDataset::GetGCPs() { return nullptr; }
1686
1687 /************************************************************************/
1688 /* GDALGetGCPs() */
1689 /************************************************************************/
1690
1691 /**
1692 * \brief Fetch GCPs.
1693 *
1694 * @see GDALDataset::GetGCPs()
1695 */
1696
GDALGetGCPs(GDALDatasetH hDS)1697 const GDAL_GCP * CPL_STDCALL GDALGetGCPs( GDALDatasetH hDS )
1698
1699 {
1700 VALIDATE_POINTER1(hDS, "GDALGetGCPs", nullptr);
1701
1702 return GDALDataset::FromHandle(hDS)->GetGCPs();
1703 }
1704
1705 /************************************************************************/
1706 /* SetGCPs() */
1707 /************************************************************************/
1708
1709 /**
1710 * \brief Assign GCPs.
1711 *
1712 * This method is the same as the C function GDALSetGCPs().
1713 *
1714 * This method assigns the passed set of GCPs to this dataset, as well as
1715 * setting their coordinate system. Internally copies are made of the
1716 * coordinate system and list of points, so the caller remains responsible for
1717 * deallocating these arguments if appropriate.
1718 *
1719 * Most formats do not support setting of GCPs, even formats that can
1720 * handle GCPs. These formats will return CE_Failure.
1721 *
1722 * \note Startig with GDAL 3.0, this is a compatibility layer around
1723 * SetGCPs(int, const GDAL_GCP*, const char*)
1724 *
1725 * @param nGCPCount number of GCPs being assigned.
1726 *
1727 * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
1728 *
1729 * @param pszGCPProjection the new OGC WKT coordinate system to assign for the
1730 * GCP output coordinates. This parameter should be "" if no output coordinate
1731 * system is known.
1732 *
1733 * @return CE_None on success, CE_Failure on failure (including if action is
1734 * not supported for this format).
1735 */
1736
SetGCPs(int nGCPCount,const GDAL_GCP * pasGCPList,const char * pszGCPProjection)1737 CPLErr GDALDataset::SetGCPs( int nGCPCount,
1738 const GDAL_GCP *pasGCPList,
1739 const char *pszGCPProjection )
1740
1741 {
1742 if( pszGCPProjection && pszGCPProjection[0] != '\0' )
1743 {
1744 OGRSpatialReference oSRS;
1745 oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1746 if( oSRS.importFromWkt(pszGCPProjection) != OGRERR_NONE )
1747 {
1748 return CE_Failure;
1749 }
1750 return SetGCPs(nGCPCount, pasGCPList, &oSRS);
1751 }
1752 else
1753 {
1754 return SetGCPs(nGCPCount, pasGCPList,
1755 static_cast<const OGRSpatialReference*>(nullptr));
1756 }
1757 }
1758
1759 /************************************************************************/
1760 /* SetGCPs() */
1761 /************************************************************************/
1762
1763 /**
1764 * \brief Assign GCPs.
1765 *
1766 * This method is the same as the C function GDALSetGCPs().
1767 *
1768 * This method assigns the passed set of GCPs to this dataset, as well as
1769 * setting their coordinate system. Internally copies are made of the
1770 * coordinate system and list of points, so the caller remains responsible for
1771 * deallocating these arguments if appropriate.
1772 *
1773 * Most formats do not support setting of GCPs, even formats that can
1774 * handle GCPs. These formats will return CE_Failure.
1775 *
1776 * @since GDAL 3.0
1777 *
1778 * @param nGCPCount number of GCPs being assigned.
1779 *
1780 * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
1781 *
1782 * @param poGCP_SRS the new coordinate reference system to assign for the
1783 * GCP output coordinates. This parameter should be null if no output coordinate
1784 * system is known.
1785 *
1786 * @return CE_None on success, CE_Failure on failure (including if action is
1787 * not supported for this format).
1788 */
1789
SetGCPs(CPL_UNUSED int nGCPCount,CPL_UNUSED const GDAL_GCP * pasGCPList,CPL_UNUSED const OGRSpatialReference * poGCP_SRS)1790 CPLErr GDALDataset::SetGCPs( CPL_UNUSED int nGCPCount,
1791 CPL_UNUSED const GDAL_GCP *pasGCPList,
1792 CPL_UNUSED const OGRSpatialReference * poGCP_SRS )
1793
1794 {
1795 if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1796 ReportError(CE_Failure, CPLE_NotSupported,
1797 "Dataset does not support the SetGCPs() method.");
1798
1799 return CE_Failure;
1800 }
1801
1802 /************************************************************************/
1803 /* _SetGCPs() */
1804 /************************************************************************/
1805
1806 //! @cond Doxygen_Suppress
1807 /** Pre GDAL-2.5 way */
_SetGCPs(int,const GDAL_GCP *,const char *)1808 CPLErr GDALDataset::_SetGCPs( int,
1809 const GDAL_GCP*,
1810 const char * )
1811
1812 {
1813 if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1814 ReportError(CE_Failure, CPLE_NotSupported,
1815 "Dataset does not support the SetGCPs() method.");
1816
1817 return CE_Failure;
1818 }
1819 //! @endcond
1820
1821 /************************************************************************/
1822 /* OldSetGCPsFromNew() */
1823 /************************************************************************/
1824
1825 //! @cond Doxygen_Suppress
OldSetGCPsFromNew(int nGCPCount,const GDAL_GCP * pasGCPList,const OGRSpatialReference * poGCP_SRS)1826 CPLErr GDALDataset::OldSetGCPsFromNew(
1827 int nGCPCount, const GDAL_GCP *pasGCPList,
1828 const OGRSpatialReference * poGCP_SRS )
1829 {
1830 if( !poGCP_SRS || poGCP_SRS->IsEmpty() )
1831 {
1832 return _SetGCPs(nGCPCount, pasGCPList, "");
1833 }
1834 char* pszWKT = nullptr;
1835 if( poGCP_SRS->exportToWkt(&pszWKT) != OGRERR_NONE )
1836 {
1837 CPLFree(pszWKT);
1838 return CE_Failure;
1839 }
1840 auto ret = _SetGCPs(nGCPCount, pasGCPList, pszWKT);
1841 CPLFree(pszWKT);
1842 return ret;
1843 }
1844 //! @endcond
1845
1846 /************************************************************************/
1847 /* GDALSetGCPs() */
1848 /************************************************************************/
1849
1850 /**
1851 * \brief Assign GCPs.
1852 *
1853 * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const char*)
1854 */
1855
GDALSetGCPs(GDALDatasetH hDS,int nGCPCount,const GDAL_GCP * pasGCPList,const char * pszGCPProjection)1856 CPLErr CPL_STDCALL GDALSetGCPs( GDALDatasetH hDS, int nGCPCount,
1857 const GDAL_GCP *pasGCPList,
1858 const char *pszGCPProjection )
1859
1860 {
1861 VALIDATE_POINTER1(hDS, "GDALSetGCPs", CE_Failure);
1862
1863 return GDALDataset::FromHandle(hDS)
1864 ->SetGCPs(nGCPCount, pasGCPList, pszGCPProjection);
1865 }
1866
1867 /************************************************************************/
1868 /* GDALSetGCPs2() */
1869 /************************************************************************/
1870
1871 /**
1872 * \brief Assign GCPs.
1873 *
1874 * @since GDAL 3.0
1875 * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const OGRSpatialReference*)
1876 */
1877
GDALSetGCPs2(GDALDatasetH hDS,int nGCPCount,const GDAL_GCP * pasGCPList,OGRSpatialReferenceH hSRS)1878 CPLErr GDALSetGCPs2( GDALDatasetH hDS, int nGCPCount,
1879 const GDAL_GCP *pasGCPList,
1880 OGRSpatialReferenceH hSRS )
1881
1882 {
1883 VALIDATE_POINTER1(hDS, "GDALSetGCPs2", CE_Failure);
1884
1885 return GDALDataset::FromHandle(hDS)
1886 ->SetGCPs(nGCPCount, pasGCPList, OGRSpatialReference::FromHandle(hSRS));
1887 }
1888
1889 /************************************************************************/
1890 /* BuildOverviews() */
1891 /************************************************************************/
1892
1893 /**
1894 * \brief Build raster overview(s)
1895 *
1896 * If the operation is unsupported for the indicated dataset, then
1897 * CE_Failure is returned, and CPLGetLastErrorNo() will return
1898 * CPLE_NotSupported.
1899 *
1900 * Depending on the actual file format, all overviews level can be also
1901 * deleted by specifying nOverviews == 0. This works at least for external
1902 * overviews (.ovr), TIFF internal overviews, etc.
1903 *
1904 * Starting with GDAL 3.2, the GDAL_NUM_THREADS configuration option can be set
1905 * to "ALL_CPUS" or a integer value to specify the number of threads to use for
1906 * overview computation.
1907 *
1908 * This method is the same as the C function GDALBuildOverviews().
1909 *
1910 * @param pszResampling one of "AVERAGE", "AVERAGE_MAGPHASE", "RMS",
1911 * "BILINEAR", "CUBIC", "CUBICSPLINE", "GAUSS", "LANCZOS", "MODE", "NEAREST",
1912 * or "NONE" controlling the downsampling method applied.
1913 * @param nOverviews number of overviews to build, or 0 to clean overviews.
1914 * @param panOverviewList the list of overview decimation factors to build, or
1915 * NULL if nOverviews == 0.
1916 * @param nListBands number of bands to build overviews for in panBandList.
1917 * Build for all bands if this is 0.
1918 * @param panBandList list of band numbers.
1919 * @param pfnProgress a function to call to report progress, or NULL.
1920 * @param pProgressData application data to pass to the progress function.
1921 *
1922 * @return CE_None on success or CE_Failure if the operation doesn't work.
1923 *
1924 * For example, to build overview level 2, 4 and 8 on all bands the following
1925 * call could be made:
1926 * \code{.cpp}
1927 * int anOverviewList[3] = { 2, 4, 8 };
1928 *
1929 * poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, nullptr,
1930 * GDALDummyProgress, nullptr );
1931 * \endcode
1932 *
1933 * @see GDALRegenerateOverviews()
1934 */
1935
BuildOverviews(const char * pszResampling,int nOverviews,int * panOverviewList,int nListBands,int * panBandList,GDALProgressFunc pfnProgress,void * pProgressData)1936 CPLErr GDALDataset::BuildOverviews( const char *pszResampling,
1937 int nOverviews, int *panOverviewList,
1938 int nListBands, int *panBandList,
1939 GDALProgressFunc pfnProgress,
1940 void * pProgressData )
1941
1942 {
1943 int *panAllBandList = nullptr;
1944
1945 if( nListBands == 0 )
1946 {
1947 nListBands = GetRasterCount();
1948 panAllBandList =
1949 static_cast<int *>(CPLMalloc(sizeof(int) * nListBands));
1950 for( int i = 0; i < nListBands; ++i )
1951 panAllBandList[i] = i + 1;
1952
1953 panBandList = panAllBandList;
1954 }
1955
1956 if( pfnProgress == nullptr )
1957 pfnProgress = GDALDummyProgress;
1958
1959 const CPLErr eErr =
1960 IBuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,
1961 panBandList, pfnProgress, pProgressData);
1962
1963 if( panAllBandList != nullptr )
1964 CPLFree(panAllBandList);
1965
1966 return eErr;
1967 }
1968
1969 /************************************************************************/
1970 /* GDALBuildOverviews() */
1971 /************************************************************************/
1972
1973 /**
1974 * \brief Build raster overview(s)
1975 *
1976 * @see GDALDataset::BuildOverviews()
1977 */
1978
GDALBuildOverviews(GDALDatasetH hDataset,const char * pszResampling,int nOverviews,int * panOverviewList,int nListBands,int * panBandList,GDALProgressFunc pfnProgress,void * pProgressData)1979 CPLErr CPL_STDCALL GDALBuildOverviews( GDALDatasetH hDataset,
1980 const char *pszResampling,
1981 int nOverviews, int *panOverviewList,
1982 int nListBands, int *panBandList,
1983 GDALProgressFunc pfnProgress,
1984 void * pProgressData )
1985
1986 {
1987 VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
1988
1989 return GDALDataset::FromHandle(hDataset)
1990 ->BuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,
1991 panBandList, pfnProgress, pProgressData);
1992 }
1993
1994 /************************************************************************/
1995 /* IBuildOverviews() */
1996 /* */
1997 /* Default implementation. */
1998 /************************************************************************/
1999
2000 //! @cond Doxygen_Suppress
IBuildOverviews(const char * pszResampling,int nOverviews,int * panOverviewList,int nListBands,int * panBandList,GDALProgressFunc pfnProgress,void * pProgressData)2001 CPLErr GDALDataset::IBuildOverviews( const char *pszResampling,
2002 int nOverviews, int *panOverviewList,
2003 int nListBands, int *panBandList,
2004 GDALProgressFunc pfnProgress,
2005 void * pProgressData )
2006
2007 {
2008 if( oOvManager.IsInitialized() )
2009 return oOvManager.BuildOverviews(
2010 nullptr, pszResampling, nOverviews, panOverviewList, nListBands,
2011 panBandList, pfnProgress, pProgressData);
2012 else
2013 {
2014 ReportError(CE_Failure, CPLE_NotSupported,
2015 "BuildOverviews() not supported for this dataset.");
2016
2017 return CE_Failure;
2018 }
2019 }
2020 //! @endcond
2021
2022 /************************************************************************/
2023 /* IRasterIO() */
2024 /* */
2025 /* The default implementation of IRasterIO() is, in the general */
2026 /* case to pass the request off to each band objects rasterio */
2027 /* methods with appropriate arguments. In some cases, it might */
2028 /* choose instead the BlockBasedRasterIO() implementation. */
2029 /************************************************************************/
2030
2031 //! @cond Doxygen_Suppress
IRasterIO(GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,void * pData,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,GSpacing nPixelSpace,GSpacing nLineSpace,GSpacing nBandSpace,GDALRasterIOExtraArg * psExtraArg)2032 CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
2033 int nXOff, int nYOff, int nXSize, int nYSize,
2034 void * pData, int nBufXSize, int nBufYSize,
2035 GDALDataType eBufType,
2036 int nBandCount, int *panBandMap,
2037 GSpacing nPixelSpace, GSpacing nLineSpace,
2038 GSpacing nBandSpace,
2039 GDALRasterIOExtraArg* psExtraArg )
2040
2041 {
2042 const char *pszInterleave = nullptr;
2043
2044 CPLAssert(nullptr != pData);
2045
2046 const bool bHasSubpixelShift =
2047 psExtraArg->bFloatingPointWindowValidity &&
2048 psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
2049 (nXOff != psExtraArg->dfXOff || nYOff != psExtraArg->dfYOff);
2050
2051 if (!bHasSubpixelShift &&
2052 nXSize == nBufXSize && nYSize == nBufYSize && nBandCount > 1 &&
2053 (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) !=
2054 nullptr &&
2055 EQUAL(pszInterleave, "PIXEL"))
2056 {
2057 return BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2058 nBufXSize, nBufYSize, eBufType, nBandCount,
2059 panBandMap, nPixelSpace, nLineSpace,
2060 nBandSpace, psExtraArg);
2061 }
2062
2063 if( eRWFlag == GF_Read &&
2064 (psExtraArg->eResampleAlg == GRIORA_Cubic ||
2065 psExtraArg->eResampleAlg == GRIORA_CubicSpline ||
2066 psExtraArg->eResampleAlg == GRIORA_Bilinear ||
2067 psExtraArg->eResampleAlg == GRIORA_Lanczos) &&
2068 !(nXSize == nBufXSize && nYSize == nBufYSize) && nBandCount > 1 )
2069 {
2070 if( nBufXSize < nXSize && nBufYSize < nYSize && AreOverviewsEnabled() )
2071 {
2072 int bTried = FALSE;
2073 const CPLErr eErr =
2074 TryOverviewRasterIO( eRWFlag,
2075 nXOff, nYOff, nXSize, nYSize,
2076 pData, nBufXSize, nBufYSize,
2077 eBufType,
2078 nBandCount, panBandMap,
2079 nPixelSpace, nLineSpace,
2080 nBandSpace,
2081 psExtraArg,
2082 &bTried );
2083 if( bTried )
2084 return eErr;
2085 }
2086
2087 GDALDataType eFirstBandDT = GDT_Unknown;
2088 int nFirstMaskFlags = 0;
2089 GDALRasterBand *poFirstMaskBand = nullptr;
2090 int nOKBands = 0;
2091
2092 // Check if bands share the same mask band
2093 for( int i = 0; i < nBandCount; ++i )
2094 {
2095 GDALRasterBand *poBand = GetRasterBand(panBandMap[i]);
2096 if( (nBufXSize < nXSize || nBufYSize < nYSize) &&
2097 poBand->GetOverviewCount() )
2098 {
2099 // Could be improved to select the appropriate overview.
2100 break;
2101 }
2102 if( poBand->GetColorTable() != nullptr )
2103 {
2104 break;
2105 }
2106 const GDALDataType eDT = poBand->GetRasterDataType();
2107 if( GDALDataTypeIsComplex(eDT) )
2108 {
2109 break;
2110 }
2111 if( i == 0 )
2112 {
2113 eFirstBandDT = eDT;
2114 nFirstMaskFlags = poBand->GetMaskFlags();
2115 if( nFirstMaskFlags == GMF_NODATA)
2116 {
2117 // The dataset-level resampling code is not ready for nodata
2118 // Fallback to band-level resampling
2119 break;
2120 }
2121 poFirstMaskBand = poBand->GetMaskBand();
2122 }
2123 else
2124 {
2125 if( eDT != eFirstBandDT )
2126 {
2127 break;
2128 }
2129 int nMaskFlags = poBand->GetMaskFlags();
2130 if( nMaskFlags == GMF_NODATA)
2131 {
2132 // The dataset-level resampling code is not ready for nodata
2133 // Fallback to band-level resampling
2134 break;
2135 }
2136 GDALRasterBand *poMaskBand = poBand->GetMaskBand();
2137 if( nFirstMaskFlags == GMF_ALL_VALID &&
2138 nMaskFlags == GMF_ALL_VALID )
2139 {
2140 // Ok.
2141 }
2142 else if( poFirstMaskBand == poMaskBand )
2143 {
2144 // Ok.
2145 }
2146 else
2147 {
2148 break;
2149 }
2150 }
2151
2152 ++nOKBands;
2153 }
2154
2155 GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2156 void *pProgressDataGlobal = psExtraArg->pProgressData;
2157
2158 CPLErr eErr = CE_None;
2159 if( nOKBands > 0 )
2160 {
2161 if( nOKBands < nBandCount )
2162 {
2163 psExtraArg->pfnProgress = GDALScaledProgress;
2164 psExtraArg->pProgressData = GDALCreateScaledProgress(
2165 0.0, static_cast<double>(nOKBands) / nBandCount,
2166 pfnProgressGlobal,
2167 pProgressDataGlobal);
2168 if( psExtraArg->pProgressData == nullptr )
2169 psExtraArg->pfnProgress = nullptr;
2170 }
2171
2172 eErr = RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2173 pData, nBufXSize, nBufYSize, eBufType,
2174 nOKBands, panBandMap, nPixelSpace,
2175 nLineSpace, nBandSpace, psExtraArg);
2176
2177 if( nOKBands < nBandCount )
2178 {
2179 GDALDestroyScaledProgress(psExtraArg->pProgressData);
2180 }
2181 }
2182 if( eErr == CE_None && nOKBands < nBandCount )
2183 {
2184 if( nOKBands > 0 )
2185 {
2186 psExtraArg->pfnProgress = GDALScaledProgress;
2187 psExtraArg->pProgressData = GDALCreateScaledProgress(
2188 static_cast<double>(nOKBands) / nBandCount,
2189 1.0, pfnProgressGlobal,
2190 pProgressDataGlobal);
2191 if( psExtraArg->pProgressData == nullptr )
2192 psExtraArg->pfnProgress = nullptr;
2193 }
2194 eErr = BandBasedRasterIO(
2195 eRWFlag, nXOff, nYOff, nXSize, nYSize,
2196 static_cast<GByte *>(pData) + nBandSpace * nOKBands,
2197 nBufXSize, nBufYSize,
2198 eBufType, nBandCount - nOKBands, panBandMap + nOKBands,
2199 nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
2200 if( nOKBands > 0 )
2201 {
2202 GDALDestroyScaledProgress(psExtraArg->pProgressData);
2203 }
2204 }
2205
2206 psExtraArg->pfnProgress = pfnProgressGlobal;
2207 psExtraArg->pProgressData = pProgressDataGlobal;
2208
2209 return eErr;
2210 }
2211
2212 return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2213 nBufXSize, nBufYSize, eBufType, nBandCount,
2214 panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2215 psExtraArg);
2216 }
2217 //! @endcond
2218
2219 /************************************************************************/
2220 /* BandBasedRasterIO() */
2221 /* */
2222 /* Pass the request off to each band objects rasterio methods with */
2223 /* appropriate arguments. */
2224 /************************************************************************/
2225
2226 //! @cond Doxygen_Suppress
BandBasedRasterIO(GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,void * pData,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,GSpacing nPixelSpace,GSpacing nLineSpace,GSpacing nBandSpace,GDALRasterIOExtraArg * psExtraArg)2227 CPLErr GDALDataset::BandBasedRasterIO( GDALRWFlag eRWFlag,
2228 int nXOff, int nYOff, int nXSize, int nYSize,
2229 void * pData, int nBufXSize, int nBufYSize,
2230 GDALDataType eBufType,
2231 int nBandCount, int *panBandMap,
2232 GSpacing nPixelSpace, GSpacing nLineSpace,
2233 GSpacing nBandSpace,
2234 GDALRasterIOExtraArg* psExtraArg )
2235
2236 {
2237 int iBandIndex;
2238 CPLErr eErr = CE_None;
2239
2240 GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2241 void *pProgressDataGlobal = psExtraArg->pProgressData;
2242
2243 for( iBandIndex = 0;
2244 iBandIndex < nBandCount && eErr == CE_None;
2245 ++iBandIndex )
2246 {
2247 GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
2248
2249 if (poBand == nullptr)
2250 {
2251 eErr = CE_Failure;
2252 break;
2253 }
2254
2255 GByte *pabyBandData =
2256 static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
2257
2258 if( nBandCount > 1 )
2259 {
2260 psExtraArg->pfnProgress = GDALScaledProgress;
2261 psExtraArg->pProgressData = GDALCreateScaledProgress(
2262 1.0 * iBandIndex / nBandCount,
2263 1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,
2264 pProgressDataGlobal);
2265 if( psExtraArg->pProgressData == nullptr )
2266 psExtraArg->pfnProgress = nullptr;
2267 }
2268
2269 eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2270 pabyBandData, nBufXSize, nBufYSize,
2271 eBufType, nPixelSpace, nLineSpace, psExtraArg);
2272
2273 if( nBandCount > 1 )
2274 GDALDestroyScaledProgress(psExtraArg->pProgressData);
2275 }
2276
2277 psExtraArg->pfnProgress = pfnProgressGlobal;
2278 psExtraArg->pProgressData = pProgressDataGlobal;
2279
2280 return eErr;
2281 }
2282 //! @endcond
2283
2284 /************************************************************************/
2285 /* ValidateRasterIOOrAdviseReadParameters() */
2286 /************************************************************************/
2287
2288 //! @cond Doxygen_Suppress
ValidateRasterIOOrAdviseReadParameters(const char * pszCallingFunc,int * pbStopProcessingOnCENone,int nXOff,int nYOff,int nXSize,int nYSize,int nBufXSize,int nBufYSize,int nBandCount,int * panBandMap)2289 CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
2290 const char* pszCallingFunc,
2291 int* pbStopProcessingOnCENone,
2292 int nXOff, int nYOff, int nXSize, int nYSize,
2293 int nBufXSize, int nBufYSize,
2294 int nBandCount, int *panBandMap)
2295 {
2296
2297 /* -------------------------------------------------------------------- */
2298 /* Some size values are "noop". Lets just return to avoid */
2299 /* stressing lower level functions. */
2300 /* -------------------------------------------------------------------- */
2301 if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 )
2302 {
2303 CPLDebug("GDAL",
2304 "%s skipped for odd window or buffer size.\n"
2305 " Window = (%d,%d)x%dx%d\n"
2306 " Buffer = %dx%d",
2307 pszCallingFunc,
2308 nXOff, nYOff, nXSize, nYSize,
2309 nBufXSize, nBufYSize);
2310
2311 *pbStopProcessingOnCENone = TRUE;
2312 return CE_None;
2313 }
2314
2315 CPLErr eErr = CE_None;
2316 *pbStopProcessingOnCENone = FALSE;
2317
2318 if( nXOff < 0 || nXOff > INT_MAX - nXSize || nXOff + nXSize > nRasterXSize
2319 || nYOff < 0 || nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize )
2320 {
2321 ReportError(CE_Failure, CPLE_IllegalArg,
2322 "Access window out of range in %s. Requested "
2323 "(%d,%d) of size %dx%d on raster of %dx%d.",
2324 pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize,
2325 nRasterYSize);
2326 eErr = CE_Failure;
2327 }
2328
2329 if( panBandMap == nullptr && nBandCount > GetRasterCount() )
2330 {
2331 ReportError( CE_Failure, CPLE_IllegalArg,
2332 "%s: nBandCount cannot be greater than %d",
2333 pszCallingFunc, GetRasterCount() );
2334 eErr = CE_Failure;
2335 }
2336
2337 for( int i = 0; i < nBandCount && eErr == CE_None; ++i )
2338 {
2339 int iBand = (panBandMap != nullptr) ? panBandMap[i] : i + 1;
2340 if( iBand < 1 || iBand > GetRasterCount() )
2341 {
2342 ReportError(
2343 CE_Failure, CPLE_IllegalArg,
2344 "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
2345 pszCallingFunc, i, iBand);
2346 eErr = CE_Failure;
2347 }
2348
2349 if( eErr == CE_None && GetRasterBand( iBand ) == nullptr )
2350 {
2351 ReportError(
2352 CE_Failure, CPLE_IllegalArg,
2353 "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
2354 pszCallingFunc, i, iBand);
2355 eErr = CE_Failure;
2356 }
2357 }
2358
2359 return eErr;
2360 }
2361 //! @endcond
2362
2363 /************************************************************************/
2364 /* RasterIO() */
2365 /************************************************************************/
2366
2367 /**
2368 * \brief Read/write a region of image data from multiple bands.
2369 *
2370 * This method allows reading a region of one or more GDALRasterBands from
2371 * this dataset into a buffer, or writing data from a buffer into a region
2372 * of the GDALRasterBands. It automatically takes care of data type
2373 * translation if the data type (eBufType) of the buffer is different than
2374 * that of the GDALRasterBand.
2375 * The method also takes care of image decimation / replication if the
2376 * buffer size (nBufXSize x nBufYSize) is different than the size of the
2377 * region being accessed (nXSize x nYSize).
2378 *
2379 * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
2380 * writing from various organization of buffers.
2381 *
2382 * For highest performance full resolution data access, read and write
2383 * on "block boundaries" as returned by GetBlockSize(), or use the
2384 * ReadBlock() and WriteBlock() methods.
2385 *
2386 * This method is the same as the C GDALDatasetRasterIO() or
2387 * GDALDatasetRasterIOEx() functions.
2388 *
2389 * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
2390 * write a region of data.
2391 *
2392 * @param nXOff The pixel offset to the top left corner of the region
2393 * of the band to be accessed. This would be zero to start from the left side.
2394 *
2395 * @param nYOff The line offset to the top left corner of the region
2396 * of the band to be accessed. This would be zero to start from the top.
2397 *
2398 * @param nXSize The width of the region of the band to be accessed in pixels.
2399 *
2400 * @param nYSize The height of the region of the band to be accessed in lines.
2401 *
2402 * @param pData The buffer into which the data should be read, or from which
2403 * it should be written. This buffer must contain at least
2404 * nBufXSize * nBufYSize * nBandCount words of type eBufType. It is organized
2405 * in left to right,top to bottom pixel order. Spacing is controlled by the
2406 * nPixelSpace, and nLineSpace parameters.
2407 *
2408 * @param nBufXSize the width of the buffer image into which the desired region
2409 * is to be read, or from which it is to be written.
2410 *
2411 * @param nBufYSize the height of the buffer image into which the desired
2412 * region is to be read, or from which it is to be written.
2413 *
2414 * @param eBufType the type of the pixel values in the pData data buffer. The
2415 * pixel values will automatically be translated to/from the GDALRasterBand
2416 * data type as needed.
2417 *
2418 * @param nBandCount the number of bands being read or written.
2419 *
2420 * @param panBandMap the list of nBandCount band numbers being read/written.
2421 * Note band numbers are 1 based. This may be NULL to select the first
2422 * nBandCount bands.
2423 *
2424 * @param nPixelSpace The byte offset from the start of one pixel value in
2425 * pData to the start of the next pixel value within a scanline. If defaulted
2426 * (0) the size of the datatype eBufType is used.
2427 *
2428 * @param nLineSpace The byte offset from the start of one scanline in
2429 * pData to the start of the next. If defaulted (0) the size of the datatype
2430 * eBufType * nBufXSize is used.
2431 *
2432 * @param nBandSpace the byte offset from the start of one bands data to the
2433 * start of the next. If defaulted (0) the value will be
2434 * nLineSpace * nBufYSize implying band sequential organization
2435 * of the data buffer.
2436 *
2437 * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg
2438 * structure with additional arguments to specify resampling and progress
2439 * callback, or NULL for default behavior. The GDAL_RASTERIO_RESAMPLING
2440 * configuration option can also be defined to override the default resampling
2441 * to one of BILINEAR, CUBIC, CUBICSPLINE, LANCZOS, AVERAGE or MODE.
2442 *
2443 * @return CE_Failure if the access fails, otherwise CE_None.
2444 */
2445
RasterIO(GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,void * pData,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,GSpacing nPixelSpace,GSpacing nLineSpace,GSpacing nBandSpace,GDALRasterIOExtraArg * psExtraArg)2446 CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
2447 int nXOff, int nYOff, int nXSize, int nYSize,
2448 void * pData, int nBufXSize, int nBufYSize,
2449 GDALDataType eBufType,
2450 int nBandCount, int *panBandMap,
2451 GSpacing nPixelSpace, GSpacing nLineSpace,
2452 GSpacing nBandSpace,
2453 GDALRasterIOExtraArg* psExtraArg )
2454
2455 {
2456 GDALRasterIOExtraArg sExtraArg;
2457 if( psExtraArg == nullptr )
2458 {
2459 INIT_RASTERIO_EXTRA_ARG(sExtraArg);
2460 psExtraArg = &sExtraArg;
2461 }
2462 else if( psExtraArg->nVersion != RASTERIO_EXTRA_ARG_CURRENT_VERSION )
2463 {
2464 ReportError(CE_Failure, CPLE_AppDefined,
2465 "Unhandled version of GDALRasterIOExtraArg");
2466 return CE_Failure;
2467 }
2468
2469 GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize, nBufXSize,
2470 nBufYSize);
2471
2472 if( nullptr == pData )
2473 {
2474 ReportError(CE_Failure, CPLE_AppDefined,
2475 "The buffer into which the data should be read is null");
2476 return CE_Failure;
2477 }
2478
2479 /* -------------------------------------------------------------------- */
2480 /* Do some validation of parameters. */
2481 /* -------------------------------------------------------------------- */
2482
2483 if( eRWFlag != GF_Read && eRWFlag != GF_Write )
2484 {
2485 ReportError(
2486 CE_Failure, CPLE_IllegalArg,
2487 "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
2488 eRWFlag);
2489 return CE_Failure;
2490 }
2491
2492 if( eRWFlag == GF_Write )
2493 {
2494 if( eAccess != GA_Update )
2495 {
2496 ReportError( CE_Failure, CPLE_AppDefined,
2497 "Write operation not permitted on dataset opened "
2498 "in read-only mode" );
2499 return CE_Failure;
2500 }
2501 }
2502
2503 int bStopProcessing = FALSE;
2504 CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
2505 "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2506 nBufYSize, nBandCount, panBandMap);
2507 if( eErr != CE_None || bStopProcessing )
2508 return eErr;
2509
2510 /* -------------------------------------------------------------------- */
2511 /* If pixel and line spacing are defaulted assign reasonable */
2512 /* value assuming a packed buffer. */
2513 /* -------------------------------------------------------------------- */
2514 if( nPixelSpace == 0 )
2515 nPixelSpace = GDALGetDataTypeSizeBytes(eBufType);
2516
2517 if( nLineSpace == 0 )
2518 {
2519 nLineSpace = nPixelSpace * nBufXSize;
2520 }
2521
2522 if( nBandSpace == 0 && nBandCount > 1 )
2523 {
2524 nBandSpace = nLineSpace * nBufYSize;
2525 }
2526
2527 bool bNeedToFreeBandMap = false;
2528 int anBandMap[] = { 1, 2, 3, 4 };
2529 if( panBandMap == nullptr )
2530 {
2531 if( nBandCount > 4 )
2532 {
2533 panBandMap =
2534 static_cast<int *>(VSIMalloc2(sizeof(int), nBandCount));
2535 if (panBandMap == nullptr)
2536 {
2537 ReportError(CE_Failure, CPLE_OutOfMemory,
2538 "Out of memory while allocating band map array");
2539 return CE_Failure;
2540 }
2541
2542 for( int i = 0; i < nBandCount; ++i )
2543 panBandMap[i] = i + 1;
2544
2545 bNeedToFreeBandMap = true;
2546 }
2547 else
2548 {
2549 panBandMap = anBandMap;
2550 }
2551 }
2552
2553 int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
2554
2555 /* -------------------------------------------------------------------- */
2556 /* We are being forced to use cached IO instead of a driver */
2557 /* specific implementation. */
2558 /* -------------------------------------------------------------------- */
2559 if( bForceCachedIO )
2560 {
2561 eErr = BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2562 nBufXSize, nBufYSize, eBufType, nBandCount,
2563 panBandMap, nPixelSpace, nLineSpace,
2564 nBandSpace, psExtraArg);
2565 }
2566
2567 /* -------------------------------------------------------------------- */
2568 /* Call the format specific function. */
2569 /* -------------------------------------------------------------------- */
2570 else
2571 {
2572 eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2573 nBufXSize, nBufYSize, eBufType, nBandCount, panBandMap,
2574 nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
2575 }
2576
2577 if( bCallLeaveReadWrite ) LeaveReadWrite();
2578
2579 /* -------------------------------------------------------------------- */
2580 /* Cleanup */
2581 /* -------------------------------------------------------------------- */
2582 if( bNeedToFreeBandMap )
2583 CPLFree(panBandMap);
2584
2585 return eErr;
2586 }
2587
2588 /************************************************************************/
2589 /* GDALDatasetRasterIO() */
2590 /************************************************************************/
2591
2592 /**
2593 * \brief Read/write a region of image data from multiple bands.
2594 *
2595 * Use GDALDatasetRasterIOEx() if 64 bit spacings or extra arguments (resampling
2596 * resolution, progress callback, etc. are needed)
2597 *
2598 * @see GDALDataset::RasterIO()
2599 */
2600
2601 CPLErr CPL_STDCALL
GDALDatasetRasterIO(GDALDatasetH hDS,GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,void * pData,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,int nPixelSpace,int nLineSpace,int nBandSpace)2602 GDALDatasetRasterIO( GDALDatasetH hDS, GDALRWFlag eRWFlag,
2603 int nXOff, int nYOff, int nXSize, int nYSize,
2604 void * pData, int nBufXSize, int nBufYSize,
2605 GDALDataType eBufType,
2606 int nBandCount, int *panBandMap,
2607 int nPixelSpace, int nLineSpace, int nBandSpace )
2608
2609 {
2610 VALIDATE_POINTER1(hDS, "GDALDatasetRasterIO", CE_Failure);
2611
2612 GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2613
2614 return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2615 nBufXSize, nBufYSize, eBufType, nBandCount,
2616 panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2617 nullptr);
2618 }
2619
2620 /************************************************************************/
2621 /* GDALDatasetRasterIOEx() */
2622 /************************************************************************/
2623
2624 /**
2625 * \brief Read/write a region of image data from multiple bands.
2626 *
2627 * @see GDALDataset::RasterIO()
2628 * @since GDAL 2.0
2629 */
2630
GDALDatasetRasterIOEx(GDALDatasetH hDS,GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,void * pData,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,GSpacing nPixelSpace,GSpacing nLineSpace,GSpacing nBandSpace,GDALRasterIOExtraArg * psExtraArg)2631 CPLErr CPL_STDCALL GDALDatasetRasterIOEx(
2632 GDALDatasetH hDS, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,
2633 int nYSize, void *pData, int nBufXSize, int nBufYSize,
2634 GDALDataType eBufType, int nBandCount, int *panBandMap,
2635 GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
2636 GDALRasterIOExtraArg *psExtraArg )
2637
2638 {
2639 VALIDATE_POINTER1(hDS, "GDALDatasetRasterIOEx", CE_Failure);
2640
2641 GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2642
2643 return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2644 nBufXSize, nBufYSize, eBufType, nBandCount,
2645 panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2646 psExtraArg);
2647 }
2648 /************************************************************************/
2649 /* GetOpenDatasets() */
2650 /************************************************************************/
2651
2652 /**
2653 * \brief Fetch all open GDAL dataset handles.
2654 *
2655 * This method is the same as the C function GDALGetOpenDatasets().
2656 *
2657 * NOTE: This method is not thread safe. The returned list may change
2658 * at any time and it should not be freed.
2659 *
2660 * @param pnCount integer into which to place the count of dataset pointers
2661 * being returned.
2662 *
2663 * @return a pointer to an array of dataset handles.
2664 */
2665
GetOpenDatasets(int * pnCount)2666 GDALDataset **GDALDataset::GetOpenDatasets( int *pnCount )
2667
2668 {
2669 CPLMutexHolderD(&hDLMutex);
2670
2671 if (poAllDatasetMap == nullptr)
2672 {
2673 *pnCount = 0;
2674 return nullptr;
2675 }
2676
2677 *pnCount = static_cast<int>(poAllDatasetMap->size());
2678 ppDatasets = static_cast<GDALDataset **>(
2679 CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset *)));
2680 std::map<GDALDataset *, GIntBig>::iterator oIter =
2681 poAllDatasetMap->begin();
2682 for( int i = 0; oIter != poAllDatasetMap->end(); ++oIter, ++i )
2683 ppDatasets[i] = oIter->first;
2684 return ppDatasets;
2685 }
2686
2687 /************************************************************************/
2688 /* GDALGetOpenDatasets() */
2689 /************************************************************************/
2690
2691 /**
2692 * \brief Fetch all open GDAL dataset handles.
2693 *
2694 * @see GDALDataset::GetOpenDatasets()
2695 */
2696
GDALGetOpenDatasets(GDALDatasetH ** ppahDSList,int * pnCount)2697 void CPL_STDCALL GDALGetOpenDatasets( GDALDatasetH **ppahDSList, int *pnCount )
2698
2699 {
2700 VALIDATE_POINTER0(ppahDSList, "GDALGetOpenDatasets");
2701 VALIDATE_POINTER0(pnCount, "GDALGetOpenDatasets");
2702
2703 *ppahDSList = reinterpret_cast<GDALDatasetH *>(
2704 GDALDataset::GetOpenDatasets(pnCount));
2705 }
2706
2707 /************************************************************************/
2708 /* GDALCleanOpenDatasetsList() */
2709 /************************************************************************/
2710
2711 // Useful when called from the child of a fork(), to avoid closing
2712 // the datasets of the parent at the child termination.
GDALNullifyOpenDatasetsList()2713 void GDALNullifyOpenDatasetsList()
2714 {
2715 poAllDatasetMap = nullptr;
2716 phSharedDatasetSet = nullptr;
2717 ppDatasets = nullptr;
2718 hDLMutex = nullptr;
2719 }
2720
2721 /************************************************************************/
2722 /* GDALGetAccess() */
2723 /************************************************************************/
2724
2725 /**
2726 * \brief Return access flag
2727 *
2728 * @see GDALDataset::GetAccess()
2729 */
2730
GDALGetAccess(GDALDatasetH hDS)2731 int CPL_STDCALL GDALGetAccess( GDALDatasetH hDS )
2732 {
2733 VALIDATE_POINTER1(hDS, "GDALGetAccess", 0);
2734
2735 return GDALDataset::FromHandle(hDS)->GetAccess();
2736 }
2737
2738 /************************************************************************/
2739 /* AdviseRead() */
2740 /************************************************************************/
2741
2742 /**
2743 * \brief Advise driver of upcoming read requests.
2744 *
2745 * Some GDAL drivers operate more efficiently if they know in advance what
2746 * set of upcoming read requests will be made. The AdviseRead() method allows
2747 * an application to notify the driver of the region and bands of interest,
2748 * and at what resolution the region will be read.
2749 *
2750 * Many drivers just ignore the AdviseRead() call, but it can dramatically
2751 * accelerate access via some drivers.
2752 *
2753 * Depending on call paths, drivers might receive several calls to
2754 * AdviseRead() with the same parameters.
2755 *
2756 * @param nXOff The pixel offset to the top left corner of the region
2757 * of the band to be accessed. This would be zero to start from the left side.
2758 *
2759 * @param nYOff The line offset to the top left corner of the region
2760 * of the band to be accessed. This would be zero to start from the top.
2761 *
2762 * @param nXSize The width of the region of the band to be accessed in pixels.
2763 *
2764 * @param nYSize The height of the region of the band to be accessed in lines.
2765 *
2766 * @param nBufXSize the width of the buffer image into which the desired region
2767 * is to be read, or from which it is to be written.
2768 *
2769 * @param nBufYSize the height of the buffer image into which the desired
2770 * region is to be read, or from which it is to be written.
2771 *
2772 * @param eBufType the type of the pixel values in the pData data buffer. The
2773 * pixel values will automatically be translated to/from the GDALRasterBand
2774 * data type as needed.
2775 *
2776 * @param nBandCount the number of bands being read or written.
2777 *
2778 * @param panBandMap the list of nBandCount band numbers being read/written.
2779 * Note band numbers are 1 based. This may be NULL to select the first
2780 * nBandCount bands.
2781 *
2782 * @param papszOptions a list of name=value strings with special control
2783 * options. Normally this is NULL.
2784 *
2785 * @return CE_Failure if the request is invalid and CE_None if it works or
2786 * is ignored.
2787 */
2788
AdviseRead(int nXOff,int nYOff,int nXSize,int nYSize,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,char ** papszOptions)2789 CPLErr GDALDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
2790 int nBufXSize, int nBufYSize,
2791 GDALDataType eBufType,
2792 int nBandCount, int *panBandMap,
2793 char **papszOptions )
2794
2795 {
2796 /* -------------------------------------------------------------------- */
2797 /* Do some validation of parameters. */
2798 /* -------------------------------------------------------------------- */
2799 int bStopProcessing = FALSE;
2800 CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
2801 "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize,
2802 nBufXSize, nBufYSize, nBandCount, panBandMap);
2803 if( eErr != CE_None || bStopProcessing )
2804 return eErr;
2805
2806 for( int iBand = 0; iBand < nBandCount; ++iBand )
2807 {
2808 GDALRasterBand *poBand = nullptr;
2809
2810 if( panBandMap == nullptr )
2811 poBand = GetRasterBand(iBand + 1);
2812 else
2813 poBand = GetRasterBand(panBandMap[iBand]);
2814
2815 if ( poBand == nullptr )
2816 return CE_Failure;
2817
2818 eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize,
2819 nBufYSize, eBufType, papszOptions);
2820
2821 if( eErr != CE_None )
2822 return eErr;
2823 }
2824
2825 return CE_None;
2826 }
2827
2828 /************************************************************************/
2829 /* GDALDatasetAdviseRead() */
2830 /************************************************************************/
2831
2832 /**
2833 * \brief Advise driver of upcoming read requests.
2834 *
2835 * @see GDALDataset::AdviseRead()
2836 */
2837 CPLErr CPL_STDCALL
GDALDatasetAdviseRead(GDALDatasetH hDS,int nXOff,int nYOff,int nXSize,int nYSize,int nBufXSize,int nBufYSize,GDALDataType eDT,int nBandCount,int * panBandMap,CSLConstList papszOptions)2838 GDALDatasetAdviseRead( GDALDatasetH hDS,
2839 int nXOff, int nYOff, int nXSize, int nYSize,
2840 int nBufXSize, int nBufYSize, GDALDataType eDT,
2841 int nBandCount, int *panBandMap,
2842 CSLConstList papszOptions )
2843
2844 {
2845 VALIDATE_POINTER1(hDS, "GDALDatasetAdviseRead", CE_Failure);
2846
2847 return GDALDataset::FromHandle(hDS)
2848 ->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT,
2849 nBandCount, panBandMap, const_cast<char**>(papszOptions));
2850 }
2851
2852 /************************************************************************/
2853 /* AntiRecursionStruct */
2854 /************************************************************************/
2855
2856 namespace {
2857 // Prevent infinite recursion.
2858 struct AntiRecursionStruct
2859 {
2860 struct DatasetContext
2861 {
2862 std::string osFilename;
2863 int nOpenFlags;
2864 int nSizeAllowedDrivers;
2865
DatasetContext__anonc90914fe0111::AntiRecursionStruct::DatasetContext2866 DatasetContext(const std::string& osFilenameIn,
2867 int nOpenFlagsIn,
2868 int nSizeAllowedDriversIn) :
2869 osFilename(osFilenameIn),
2870 nOpenFlags(nOpenFlagsIn),
2871 nSizeAllowedDrivers(nSizeAllowedDriversIn) {}
2872 };
2873
2874 struct DatasetContextCompare {
operator ()__anonc90914fe0111::AntiRecursionStruct::DatasetContextCompare2875 bool operator() (const DatasetContext& lhs, const DatasetContext& rhs) const {
2876 return lhs.osFilename < rhs.osFilename ||
2877 (lhs.osFilename == rhs.osFilename &&
2878 (lhs.nOpenFlags < rhs.nOpenFlags ||
2879 (lhs.nOpenFlags == rhs.nOpenFlags &&
2880 lhs.nSizeAllowedDrivers < rhs.nSizeAllowedDrivers)));
2881 }
2882 };
2883
2884 std::set<DatasetContext, DatasetContextCompare> aosDatasetNamesWithFlags{};
2885 int nRecLevel = 0;
2886 };
2887 } // namespace
2888
2889 #ifdef WIN32
2890 // Currently thread_local and C++ objects don't work well with DLL on Windows
FreeAntiRecursion(void * pData)2891 static void FreeAntiRecursion( void* pData )
2892 {
2893 delete static_cast<AntiRecursionStruct*>(pData);
2894 }
2895
GetAntiRecursion()2896 static AntiRecursionStruct& GetAntiRecursion()
2897 {
2898 static AntiRecursionStruct dummy;
2899 int bMemoryErrorOccurred = false;
2900 void* pData = CPLGetTLSEx(CTLS_GDALOPEN_ANTIRECURSION, &bMemoryErrorOccurred);
2901 if( bMemoryErrorOccurred )
2902 {
2903 return dummy;
2904 }
2905 if( pData == nullptr)
2906 {
2907 auto pAntiRecursion = new AntiRecursionStruct();
2908 CPLSetTLSWithFreeFuncEx( CTLS_GDALOPEN_ANTIRECURSION,
2909 pAntiRecursion,
2910 FreeAntiRecursion, &bMemoryErrorOccurred );
2911 if( bMemoryErrorOccurred )
2912 {
2913 delete pAntiRecursion;
2914 return dummy;
2915 }
2916 return *pAntiRecursion;
2917 }
2918 return *static_cast<AntiRecursionStruct*>(pData);
2919 }
2920 #else
2921 static thread_local AntiRecursionStruct g_tls_antiRecursion;
GetAntiRecursion()2922 static AntiRecursionStruct& GetAntiRecursion()
2923 {
2924 return g_tls_antiRecursion;
2925 }
2926 #endif
2927
2928 /************************************************************************/
2929 /* GetFileList() */
2930 /************************************************************************/
2931
2932 /**
2933 * \brief Fetch files forming dataset.
2934 *
2935 * Returns a list of files believed to be part of this dataset. If it returns
2936 * an empty list of files it means there is believed to be no local file
2937 * system files associated with the dataset (for instance a virtual dataset).
2938 * The returned file list is owned by the caller and should be deallocated
2939 * with CSLDestroy().
2940 *
2941 * The returned filenames will normally be relative or absolute paths
2942 * depending on the path used to originally open the dataset. The strings
2943 * will be UTF-8 encoded.
2944 *
2945 * This method is the same as the C GDALGetFileList() function.
2946 *
2947 * @return NULL or a NULL terminated array of file names.
2948 */
2949
GetFileList()2950 char **GDALDataset::GetFileList()
2951
2952 {
2953 CPLString osMainFilename = GetDescription();
2954 VSIStatBufL sStat;
2955
2956 AntiRecursionStruct& sAntiRecursion = GetAntiRecursion();
2957 const AntiRecursionStruct::DatasetContext datasetCtxt(
2958 osMainFilename, 0, 0);
2959 auto& aosDatasetList = sAntiRecursion.aosDatasetNamesWithFlags;
2960 if( aosDatasetList.find(datasetCtxt) != aosDatasetList.end() )
2961 return nullptr;
2962
2963 /* -------------------------------------------------------------------- */
2964 /* Is the main filename even a real filesystem object? */
2965 /* -------------------------------------------------------------------- */
2966 int bMainFileReal =
2967 VSIStatExL(osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
2968
2969 /* -------------------------------------------------------------------- */
2970 /* Form new list. */
2971 /* -------------------------------------------------------------------- */
2972 char **papszList = nullptr;
2973
2974 if( bMainFileReal )
2975 papszList = CSLAddString(papszList, osMainFilename);
2976
2977 if( sAntiRecursion.nRecLevel == 100 )
2978 {
2979 CPLError(CE_Failure, CPLE_AppDefined,
2980 "GetFileList() called with too many recursion levels");
2981 return papszList;
2982 }
2983 ++sAntiRecursion.nRecLevel;
2984
2985 /* -------------------------------------------------------------------- */
2986 /* Do we have a known overview file? */
2987 /* -------------------------------------------------------------------- */
2988 if(oOvManager.IsInitialized() && oOvManager.poODS != nullptr)
2989 {
2990 auto iter = aosDatasetList.insert(datasetCtxt).first;
2991 char **papszOvrList = oOvManager.poODS->GetFileList();
2992 papszList = CSLInsertStrings(papszList, -1, papszOvrList);
2993 CSLDestroy(papszOvrList);
2994 aosDatasetList.erase(iter);
2995 }
2996
2997 /* -------------------------------------------------------------------- */
2998 /* Do we have a known mask file? */
2999 /* -------------------------------------------------------------------- */
3000 if( oOvManager.HaveMaskFile() )
3001 {
3002 auto iter = aosDatasetList.insert(datasetCtxt).first;
3003 char **papszMskList = oOvManager.poMaskDS->GetFileList();
3004 char **papszIter = papszMskList;
3005 while( papszIter && *papszIter )
3006 {
3007 if( CSLFindString( papszList, *papszIter ) < 0 )
3008 papszList = CSLAddString( papszList, *papszIter );
3009 ++papszIter;
3010 }
3011 CSLDestroy(papszMskList);
3012 aosDatasetList.erase(iter);
3013 }
3014
3015 --sAntiRecursion.nRecLevel;
3016
3017 return papszList;
3018 }
3019
3020 /************************************************************************/
3021 /* GDALGetFileList() */
3022 /************************************************************************/
3023
3024 /**
3025 * \brief Fetch files forming dataset.
3026 *
3027 * @see GDALDataset::GetFileList()
3028 */
3029
GDALGetFileList(GDALDatasetH hDS)3030 char ** CPL_STDCALL GDALGetFileList( GDALDatasetH hDS )
3031
3032 {
3033 VALIDATE_POINTER1(hDS, "GDALGetFileList", nullptr);
3034
3035 return GDALDataset::FromHandle(hDS)->GetFileList();
3036 }
3037
3038 /************************************************************************/
3039 /* CreateMaskBand() */
3040 /************************************************************************/
3041
3042 /**
3043 * \brief Adds a mask band to the dataset
3044 *
3045 * The default implementation of the CreateMaskBand() method is implemented
3046 * based on similar rules to the .ovr handling implemented using the
3047 * GDALDefaultOverviews object. A TIFF file with the extension .msk will
3048 * be created with the same basename as the original file, and it will have
3049 * one band.
3050 * The mask images will be deflate compressed tiled images with the same
3051 * block size as the original image if possible.
3052 * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
3053 * level, where xx matches the band number of a band of the main dataset. The
3054 * value of those items will be the one of the nFlagsIn parameter.
3055 *
3056 * Note that if you got a mask band with a previous call to GetMaskBand(), it
3057 * might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
3058 * again.
3059 *
3060 * @since GDAL 1.5.0
3061 *
3062 * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.
3063 * GMF_PER_DATASET will be always set, even if not explicitly
3064 * specified.
3065 * @return CE_None on success or CE_Failure on an error.
3066 *
3067 * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html
3068 * @see GDALRasterBand::CreateMaskBand()
3069 *
3070 */
CreateMaskBand(int nFlagsIn)3071 CPLErr GDALDataset::CreateMaskBand( int nFlagsIn )
3072
3073 {
3074 if( oOvManager.IsInitialized() )
3075 {
3076 CPLErr eErr = oOvManager.CreateMaskBand(nFlagsIn, -1);
3077 if (eErr != CE_None)
3078 return eErr;
3079
3080 // Invalidate existing raster band masks.
3081 for( int i = 0; i < nBands; ++i )
3082 {
3083 GDALRasterBand *poBand = papoBands[i];
3084 if (poBand->bOwnMask)
3085 delete poBand->poMask;
3086 poBand->bOwnMask = false;
3087 poBand->poMask = nullptr;
3088 }
3089
3090 return CE_None;
3091 }
3092
3093 ReportError(CE_Failure, CPLE_NotSupported,
3094 "CreateMaskBand() not supported for this dataset.");
3095
3096 return CE_Failure;
3097 }
3098
3099 /************************************************************************/
3100 /* GDALCreateDatasetMaskBand() */
3101 /************************************************************************/
3102
3103 /**
3104 * \brief Adds a mask band to the dataset
3105 * @see GDALDataset::CreateMaskBand()
3106 */
GDALCreateDatasetMaskBand(GDALDatasetH hDS,int nFlags)3107 CPLErr CPL_STDCALL GDALCreateDatasetMaskBand( GDALDatasetH hDS, int nFlags )
3108
3109 {
3110 VALIDATE_POINTER1(hDS, "GDALCreateDatasetMaskBand", CE_Failure);
3111
3112 return GDALDataset::FromHandle(hDS)->CreateMaskBand(nFlags);
3113 }
3114
3115 /************************************************************************/
3116 /* GDALOpen() */
3117 /************************************************************************/
3118
3119 /**
3120 * \brief Open a raster file as a GDALDataset.
3121 *
3122 * This function will try to open the passed file, or virtual dataset
3123 * name by invoking the Open method of each registered GDALDriver in turn.
3124 * The first successful open will result in a returned dataset. If all
3125 * drivers fail then NULL is returned and an error is issued.
3126 *
3127 * Several recommendations :
3128 * <ul>
3129 * <li>If you open a dataset object with GA_Update access, it is not recommended
3130 * to open a new dataset on the same underlying file.</li>
3131 * <li>The returned dataset should only be accessed by one thread at a time. If
3132 * you want to use it from different threads, you must add all necessary code
3133 * (mutexes, etc.) to avoid concurrent use of the object. (Some drivers, such
3134 * as GeoTIFF, maintain internal state variables that are updated each time a
3135 * new block is read, thus preventing concurrent use.) </li>
3136 * </ul>
3137 *
3138 * For drivers supporting the VSI virtual file API, it is possible to open a
3139 * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3140 * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3141 * server (see VSIInstallCurlFileHandler())
3142 *
3143 * \sa GDALOpenShared()
3144 * \sa GDALOpenEx()
3145 *
3146 * @param pszFilename the name of the file to access. In the case of
3147 * exotic drivers this may not refer to a physical file, but instead contain
3148 * information for the driver on how to access a dataset. It should be in UTF-8
3149 * encoding.
3150 *
3151 * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
3152 * drivers support only read only access.
3153 *
3154 * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3155 * this handle can be cast to a GDALDataset *.
3156 */
3157
3158 GDALDatasetH CPL_STDCALL
GDALOpen(const char * pszFilename,GDALAccess eAccess)3159 GDALOpen( const char * pszFilename, GDALAccess eAccess )
3160
3161 {
3162 const int nUpdateFlag = eAccess == GA_Update ? GDAL_OF_UPDATE : 0;
3163 const int nOpenFlags = GDAL_OF_RASTER | nUpdateFlag | GDAL_OF_VERBOSE_ERROR;
3164 GDALDatasetH hDataset =
3165 GDALOpenEx(pszFilename, nOpenFlags, nullptr, nullptr, nullptr);
3166 return hDataset;
3167 }
3168
3169 /************************************************************************/
3170 /* GDALOpenEx() */
3171 /************************************************************************/
3172
3173 /**
3174 * \brief Open a raster or vector file as a GDALDataset.
3175 *
3176 * This function will try to open the passed file, or virtual dataset
3177 * name by invoking the Open method of each registered GDALDriver in turn.
3178 * The first successful open will result in a returned dataset. If all
3179 * drivers fail then NULL is returned and an error is issued.
3180 *
3181 * Several recommendations :
3182 * <ul>
3183 * <li>If you open a dataset object with GDAL_OF_UPDATE access, it is not
3184 * recommended to open a new dataset on the same underlying file.</li>
3185 * <li>The returned dataset should only be accessed by one thread at a time. If
3186 * you want to use it from different threads, you must add all necessary code
3187 * (mutexes, etc.) to avoid concurrent use of the object. (Some drivers, such
3188 * as GeoTIFF, maintain internal state variables that are updated each time a
3189 * new block is read, thus preventing concurrent use.) </li>
3190 * </ul>
3191 *
3192 * For drivers supporting the VSI virtual file API, it is possible to open a
3193 * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3194 * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3195 * server (see VSIInstallCurlFileHandler())
3196 *
3197 * In order to reduce the need for searches through the operating system
3198 * file system machinery, it is possible to give an optional list of files with
3199 * the papszSiblingFiles parameter.
3200 * This is the list of all files at the same level in the file system as the
3201 * target file, including the target file. The filenames must not include any
3202 * path components, are essentially just the output of VSIReadDir() on the
3203 * parent directory. If the target object does not have filesystem semantics
3204 * then the file list should be NULL.
3205 *
3206 * @param pszFilename the name of the file to access. In the case of
3207 * exotic drivers this may not refer to a physical file, but instead contain
3208 * information for the driver on how to access a dataset. It should be in UTF-8
3209 * encoding.
3210 *
3211 * @param nOpenFlags a combination of GDAL_OF_ flags that may be combined
3212 * through logical or operator.
3213 * <ul>
3214 * <li>Driver kind: GDAL_OF_RASTER for raster drivers, GDAL_OF_VECTOR for vector
3215 * drivers, GDAL_OF_GNM for Geographic Network Model drivers.
3216 * If none of the value is specified, all kinds are implied.</li>
3217 * <li>Access mode: GDAL_OF_READONLY (exclusive)or GDAL_OF_UPDATE.</li>
3218 * <li>Shared mode: GDAL_OF_SHARED. If set, it allows the sharing of GDALDataset
3219 * handles for a dataset with other callers that have set GDAL_OF_SHARED.
3220 * In particular, GDALOpenEx() will first consult its list of currently
3221 * open and shared GDALDataset's, and if the GetDescription() name for one
3222 * exactly matches the pszFilename passed to GDALOpenEx() it will be
3223 * referenced and returned, if GDALOpenEx() is called from the same thread.</li>
3224 * <li>Verbose error: GDAL_OF_VERBOSE_ERROR. If set, a failed attempt to open
3225 * the file will lead to an error message to be reported.</li>
3226 * </ul>
3227 *
3228 * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
3229 * terminated list of strings with the driver short names that must be
3230 * considered.
3231 *
3232 * @param papszOpenOptions NULL, or a NULL terminated list of strings with open
3233 * options passed to candidate drivers. An option exists for all drivers,
3234 * OVERVIEW_LEVEL=level, to select a particular overview level of a dataset.
3235 * The level index starts at 0. The level number can be suffixed by "only" to
3236 * specify that only this overview level must be visible, and not sub-levels.
3237 * Open options are validated by default, and a warning is emitted in case the
3238 * option is not recognized. In some scenarios, it might be not desirable (e.g.
3239 * when not knowing which driver will open the file), so the special open option
3240 * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings. Alternatively,
3241 * since GDAL 2.1, an option name can be preceded by the @ character to indicate
3242 * that it may not cause a warning if the driver doesn't declare this option.
3243 * Starting with GDAL 3.3, OVERVIEW_LEVEL=NONE is supported to indicate that
3244 * no overviews should be exposed.
3245 *
3246 * @param papszSiblingFiles NULL, or a NULL terminated list of strings that are
3247 * filenames that are auxiliary to the main filename. If NULL is passed, a
3248 * probing of the file system will be done.
3249 *
3250 * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3251 * this handle can be cast to a GDALDataset *.
3252 *
3253 * @since GDAL 2.0
3254 */
3255
GDALOpenEx(const char * pszFilename,unsigned int nOpenFlags,const char * const * papszAllowedDrivers,const char * const * papszOpenOptions,const char * const * papszSiblingFiles)3256 GDALDatasetH CPL_STDCALL GDALOpenEx( const char *pszFilename,
3257 unsigned int nOpenFlags,
3258 const char *const *papszAllowedDrivers,
3259 const char *const *papszOpenOptions,
3260 const char *const *papszSiblingFiles )
3261 {
3262 VALIDATE_POINTER1(pszFilename, "GDALOpen", nullptr);
3263 /* -------------------------------------------------------------------- */
3264 /* In case of shared dataset, first scan the existing list to see */
3265 /* if it could already contain the requested dataset. */
3266 /* -------------------------------------------------------------------- */
3267 if( nOpenFlags & GDAL_OF_SHARED )
3268 {
3269 if( nOpenFlags & GDAL_OF_INTERNAL )
3270 {
3271 CPLError(CE_Failure, CPLE_IllegalArg,
3272 "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");
3273 return nullptr;
3274 }
3275
3276 CPLMutexHolderD(&hDLMutex);
3277
3278 if (phSharedDatasetSet != nullptr)
3279 {
3280 const GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
3281 SharedDatasetCtxt sStruct;
3282
3283 sStruct.nPID = nThisPID;
3284 sStruct.pszDescription = const_cast<char *>(pszFilename);
3285 sStruct.eAccess =
3286 (nOpenFlags & GDAL_OF_UPDATE) ? GA_Update : GA_ReadOnly;
3287 SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
3288 CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3289 if (psStruct == nullptr && (nOpenFlags & GDAL_OF_UPDATE) == 0)
3290 {
3291 sStruct.eAccess = GA_Update;
3292 psStruct = static_cast<SharedDatasetCtxt *>(
3293 CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3294 }
3295 if (psStruct)
3296 {
3297 psStruct->poDS->Reference();
3298 return psStruct->poDS;
3299 }
3300 }
3301 }
3302
3303 // If no driver kind is specified, assume all are to be probed.
3304 if( (nOpenFlags & GDAL_OF_KIND_MASK) == 0 )
3305 nOpenFlags |= GDAL_OF_KIND_MASK & ~GDAL_OF_MULTIDIM_RASTER;
3306
3307 GDALDriverManager *poDM = GetGDALDriverManager();
3308 // CPLLocaleC oLocaleForcer;
3309
3310 CPLErrorReset();
3311 VSIErrorReset();
3312 CPLAssert(nullptr != poDM);
3313
3314 // Build GDALOpenInfo just now to avoid useless file stat'ing if a
3315 // shared dataset was asked before.
3316 GDALOpenInfo oOpenInfo(pszFilename, nOpenFlags,
3317 const_cast<char **>(papszSiblingFiles));
3318 oOpenInfo.papszAllowedDrivers = papszAllowedDrivers;
3319
3320 AntiRecursionStruct& sAntiRecursion = GetAntiRecursion();
3321 if( sAntiRecursion.nRecLevel == 100 )
3322 {
3323 CPLError(CE_Failure, CPLE_AppDefined,
3324 "GDALOpen() called with too many recursion levels");
3325 return nullptr;
3326 }
3327
3328 auto dsCtxt = AntiRecursionStruct::DatasetContext(
3329 std::string(pszFilename), nOpenFlags, CSLCount(papszAllowedDrivers));
3330 if( sAntiRecursion.aosDatasetNamesWithFlags.find(dsCtxt) !=
3331 sAntiRecursion.aosDatasetNamesWithFlags.end() )
3332 {
3333 CPLError(CE_Failure, CPLE_AppDefined,
3334 "GDALOpen() called on %s recursively", pszFilename);
3335 return nullptr;
3336 }
3337
3338 // Remove leading @ if present.
3339 char **papszOpenOptionsCleaned =
3340 CSLDuplicate(const_cast<char **>(papszOpenOptions));
3341 for(char **papszIter = papszOpenOptionsCleaned; papszIter && *papszIter;
3342 ++papszIter)
3343 {
3344 char *pszOption = *papszIter;
3345 if( pszOption[0] == '@' )
3346 memmove(pszOption, pszOption + 1, strlen(pszOption + 1) + 1);
3347 }
3348
3349 oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3350
3351 #ifdef OGRAPISPY_ENABLED
3352 const bool bUpdate = (nOpenFlags & GDAL_OF_UPDATE) != 0;
3353 const int iSnapshot = (nOpenFlags & GDAL_OF_VECTOR) != 0 &&
3354 (nOpenFlags & GDAL_OF_RASTER) == 0 ?
3355 OGRAPISpyOpenTakeSnapshot(pszFilename, bUpdate) : INT_MIN;
3356 #endif
3357
3358 const int nDriverCount = poDM->GetDriverCount();
3359 for( int iDriver = 0; iDriver < nDriverCount; ++iDriver )
3360 {
3361 GDALDriver *poDriver = poDM->GetDriver(iDriver);
3362 if (papszAllowedDrivers != nullptr &&
3363 CSLFindString(papszAllowedDrivers,
3364 GDALGetDriverShortName(poDriver)) == -1)
3365 {
3366 continue;
3367 }
3368
3369 if( (nOpenFlags & GDAL_OF_RASTER) != 0 &&
3370 (nOpenFlags & GDAL_OF_VECTOR) == 0 &&
3371 poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr )
3372 continue;
3373 if( (nOpenFlags & GDAL_OF_VECTOR) != 0 &&
3374 (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3375 poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr )
3376 continue;
3377 if( (nOpenFlags & GDAL_OF_MULTIDIM_RASTER) != 0 &&
3378 (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3379 poDriver->GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) == nullptr )
3380 continue;
3381 if( poDriver->pfnOpen == nullptr &&
3382 poDriver->pfnOpenWithDriverArg == nullptr )
3383 {
3384 continue;
3385 }
3386
3387 // Remove general OVERVIEW_LEVEL open options from list before passing
3388 // it to the driver, if it isn't a driver specific option already.
3389 char **papszTmpOpenOptions = nullptr;
3390 char **papszTmpOpenOptionsToValidate = nullptr;
3391 char **papszOptionsToValidate = const_cast<char **>(papszOpenOptions);
3392 if( CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") !=
3393 nullptr &&
3394 (poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST) == nullptr ||
3395 CPLString(poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST))
3396 .ifind("OVERVIEW_LEVEL") == std::string::npos) )
3397 {
3398 papszTmpOpenOptions = CSLDuplicate(papszOpenOptionsCleaned);
3399 papszTmpOpenOptions =
3400 CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", nullptr);
3401 oOpenInfo.papszOpenOptions = papszTmpOpenOptions;
3402
3403 papszOptionsToValidate = CSLDuplicate(papszOptionsToValidate);
3404 papszOptionsToValidate =
3405 CSLSetNameValue(papszOptionsToValidate, "OVERVIEW_LEVEL", nullptr);
3406 papszTmpOpenOptionsToValidate = papszOptionsToValidate;
3407 }
3408
3409 const bool bIdentifyRes =
3410 poDriver->pfnIdentifyEx ?
3411 poDriver->pfnIdentifyEx(poDriver, &oOpenInfo) > 0:
3412 poDriver->pfnIdentify && poDriver->pfnIdentify(&oOpenInfo) > 0;
3413 if( bIdentifyRes )
3414 {
3415 GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3416 }
3417
3418 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3419 const bool bFpAvailableBefore = oOpenInfo.fpL != nullptr;
3420 CPLErrorReset();
3421 #endif
3422
3423 sAntiRecursion.nRecLevel ++;
3424 sAntiRecursion.aosDatasetNamesWithFlags.insert(dsCtxt);
3425
3426 GDALDataset *poDS = nullptr;
3427 if ( poDriver->pfnOpen != nullptr )
3428 {
3429 poDS = poDriver->pfnOpen(&oOpenInfo);
3430 // If we couldn't determine for sure with Identify() (it returned
3431 // -1), but Open() managed to open the file, post validate options.
3432 if( poDS != nullptr &&
3433 (poDriver->pfnIdentify || poDriver->pfnIdentifyEx) && !bIdentifyRes )
3434 {
3435 GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3436 }
3437 }
3438 else if( poDriver->pfnOpenWithDriverArg != nullptr )
3439 {
3440 poDS = poDriver->pfnOpenWithDriverArg(poDriver, &oOpenInfo);
3441 }
3442
3443 sAntiRecursion.nRecLevel --;
3444 sAntiRecursion.aosDatasetNamesWithFlags.erase(dsCtxt);
3445
3446 CSLDestroy(papszTmpOpenOptions);
3447 CSLDestroy(papszTmpOpenOptionsToValidate);
3448 oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3449
3450 if( poDS != nullptr )
3451 {
3452 poDS->nOpenFlags = nOpenFlags;
3453
3454 if( strlen(poDS->GetDescription()) == 0 )
3455 poDS->SetDescription(pszFilename);
3456
3457 if( poDS->poDriver == nullptr )
3458 poDS->poDriver = poDriver;
3459
3460 if( poDS->papszOpenOptions == nullptr )
3461 {
3462 poDS->papszOpenOptions = papszOpenOptionsCleaned;
3463 papszOpenOptionsCleaned = nullptr;
3464 }
3465
3466 if( !(nOpenFlags & GDAL_OF_INTERNAL) )
3467 {
3468 if( CPLGetPID() != GDALGetResponsiblePIDForCurrentThread() )
3469 CPLDebug("GDAL",
3470 "GDALOpen(%s, this=%p) succeeds as "
3471 "%s (pid=%d, responsiblePID=%d).",
3472 pszFilename, poDS, poDriver->GetDescription(),
3473 static_cast<int>(CPLGetPID()),
3474 static_cast<int>(
3475 GDALGetResponsiblePIDForCurrentThread()));
3476 else
3477 CPLDebug("GDAL", "GDALOpen(%s, this=%p) succeeds as %s.",
3478 pszFilename, poDS, poDriver->GetDescription());
3479
3480 poDS->AddToDatasetOpenList();
3481 }
3482
3483 if( nOpenFlags & GDAL_OF_SHARED )
3484 {
3485 if (strcmp(pszFilename, poDS->GetDescription()) != 0)
3486 {
3487 CPLError(CE_Warning, CPLE_NotSupported,
3488 "A dataset opened by GDALOpenShared should have "
3489 "the same filename (%s) "
3490 "and description (%s)",
3491 pszFilename, poDS->GetDescription());
3492 }
3493 else
3494 {
3495 poDS->MarkAsShared();
3496 }
3497 }
3498
3499 // Deal with generic OVERVIEW_LEVEL open option, unless it is
3500 // driver specific.
3501 if( CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") != nullptr &&
3502 (poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST) == nullptr ||
3503 CPLString(poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST))
3504 .ifind("OVERVIEW_LEVEL") == std::string::npos) )
3505 {
3506 CPLString osVal(
3507 CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL"));
3508 const int nOvrLevel = EQUAL(osVal, "NONE") ? -1 : atoi(osVal);
3509 const bool bThisLevelOnly =
3510 nOvrLevel == -1 || osVal.ifind("only") != std::string::npos;
3511 GDALDataset *poOvrDS = GDALCreateOverviewDataset(
3512 poDS, nOvrLevel, bThisLevelOnly);
3513 poDS->ReleaseRef();
3514 poDS = poOvrDS;
3515 if( poDS == nullptr )
3516 {
3517 if( nOpenFlags & GDAL_OF_VERBOSE_ERROR )
3518 {
3519 CPLError(CE_Failure, CPLE_OpenFailed,
3520 "Cannot open overview level %d of %s",
3521 nOvrLevel, pszFilename);
3522 }
3523 }
3524 }
3525 VSIErrorReset();
3526
3527 CSLDestroy(papszOpenOptionsCleaned);
3528
3529 #ifdef OGRAPISPY_ENABLED
3530 if( iSnapshot != INT_MIN )
3531 {
3532 GDALDatasetH hDS = GDALDataset::ToHandle(poDS);
3533 OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
3534 poDS = GDALDataset::FromHandle(hDS);
3535 }
3536 #endif
3537
3538 return poDS;
3539 }
3540
3541 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3542 if( bFpAvailableBefore && oOpenInfo.fpL == nullptr )
3543 {
3544 // In case the file descriptor was "consumed" by a driver
3545 // that ultimately failed, re-open it for next drivers.
3546 oOpenInfo.fpL = VSIFOpenL(
3547 pszFilename,
3548 (oOpenInfo.eAccess == GA_Update) ? "r+b" : "rb");
3549 }
3550 #else
3551 if( CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() > CE_Warning)
3552 {
3553 CSLDestroy(papszOpenOptionsCleaned);
3554
3555 #ifdef OGRAPISPY_ENABLED
3556 if( iSnapshot != INT_MIN )
3557 {
3558 GDALDatasetH hDS = nullptr;
3559 OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
3560 }
3561 #endif
3562 return nullptr;
3563 }
3564 #endif
3565 }
3566
3567 CSLDestroy(papszOpenOptionsCleaned);
3568
3569 #ifdef OGRAPISPY_ENABLED
3570 if( iSnapshot != INT_MIN )
3571 {
3572 GDALDatasetH hDS = nullptr;
3573 OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
3574 }
3575 #endif
3576
3577 if( nOpenFlags & GDAL_OF_VERBOSE_ERROR )
3578 {
3579 // Check to see if there was a filesystem error, and report it if so.
3580 // If not, return a more generic error.
3581 if(!VSIToCPLError(CE_Failure, CPLE_OpenFailed))
3582 {
3583 if( nDriverCount == 0 )
3584 {
3585 CPLError(CE_Failure, CPLE_OpenFailed,
3586 "No driver registered.");
3587 }
3588 else if( oOpenInfo.bStatOK )
3589 {
3590 CPLError(CE_Failure, CPLE_OpenFailed,
3591 "`%s' not recognized as a supported file format.",
3592 pszFilename);
3593 }
3594 else
3595 {
3596 // If Stat failed and no VSI error was set, assume it is because
3597 // the file did not exist on the filesystem.
3598 CPLError(CE_Failure, CPLE_OpenFailed,
3599 "`%s' does not exist in the file system, "
3600 "and is not recognized as a supported dataset name.",
3601 pszFilename);
3602 }
3603 }
3604 }
3605
3606 return nullptr;
3607 }
3608
3609 /************************************************************************/
3610 /* GDALOpenShared() */
3611 /************************************************************************/
3612
3613 /**
3614 * \brief Open a raster file as a GDALDataset.
3615 *
3616 * This function works the same as GDALOpen(), but allows the sharing of
3617 * GDALDataset handles for a dataset with other callers to GDALOpenShared().
3618 *
3619 * In particular, GDALOpenShared() will first consult its list of currently
3620 * open and shared GDALDataset's, and if the GetDescription() name for one
3621 * exactly matches the pszFilename passed to GDALOpenShared() it will be
3622 * referenced and returned.
3623 *
3624 * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same
3625 * pszFilename from two different threads, a different GDALDataset object will
3626 * be returned as it is not safe to use the same dataset from different threads,
3627 * unless the user does explicitly use mutexes in its code.
3628 *
3629 * For drivers supporting the VSI virtual file API, it is possible to open a
3630 * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3631 * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3632 * server (see VSIInstallCurlFileHandler())
3633 *
3634 * \sa GDALOpen()
3635 * \sa GDALOpenEx()
3636 *
3637 * @param pszFilename the name of the file to access. In the case of
3638 * exotic drivers this may not refer to a physical file, but instead contain
3639 * information for the driver on how to access a dataset. It should be in
3640 * UTF-8 encoding.
3641 *
3642 * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
3643 * drivers support only read only access.
3644 *
3645 * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3646 * this handle can be cast to a GDALDataset *.
3647 */
3648
3649 GDALDatasetH CPL_STDCALL
GDALOpenShared(const char * pszFilename,GDALAccess eAccess)3650 GDALOpenShared( const char *pszFilename, GDALAccess eAccess )
3651 {
3652 VALIDATE_POINTER1(pszFilename, "GDALOpenShared", nullptr);
3653 return GDALOpenEx(pszFilename,
3654 GDAL_OF_RASTER |
3655 (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
3656 GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR,
3657 nullptr, nullptr, nullptr);
3658 }
3659
3660 /************************************************************************/
3661 /* GDALClose() */
3662 /************************************************************************/
3663
3664 /**
3665 * \brief Close GDAL dataset.
3666 *
3667 * For non-shared datasets (opened with GDALOpen()) the dataset is closed
3668 * using the C++ "delete" operator, recovering all dataset related resources.
3669 * For shared datasets (opened with GDALOpenShared()) the dataset is
3670 * dereferenced, and closed only if the referenced count has dropped below 1.
3671 *
3672 * @param hDS The dataset to close. May be cast from a "GDALDataset *".
3673 */
3674
GDALClose(GDALDatasetH hDS)3675 void CPL_STDCALL GDALClose( GDALDatasetH hDS )
3676
3677 {
3678 if( hDS == nullptr )
3679 return;
3680
3681 #ifdef OGRAPISPY_ENABLED
3682 if( bOGRAPISpyEnabled )
3683 OGRAPISpyPreClose(hDS);
3684 #endif
3685
3686 GDALDataset *poDS = GDALDataset::FromHandle(hDS);
3687
3688 if (poDS->GetShared())
3689 {
3690 /* -------------------------------------------------------------------- */
3691 /* If this file is in the shared dataset list then dereference */
3692 /* it, and only delete/remote it if the reference count has */
3693 /* dropped to zero. */
3694 /* -------------------------------------------------------------------- */
3695 if( poDS->Dereference() > 0 )
3696 return;
3697
3698 delete poDS;
3699
3700 #ifdef OGRAPISPY_ENABLED
3701 if( bOGRAPISpyEnabled )
3702 OGRAPISpyPostClose();
3703 #endif
3704
3705 return;
3706 }
3707
3708 /* -------------------------------------------------------------------- */
3709 /* This is not shared dataset, so directly delete it. */
3710 /* -------------------------------------------------------------------- */
3711 delete poDS;
3712
3713 #ifdef OGRAPISPY_ENABLED
3714 if( bOGRAPISpyEnabled )
3715 OGRAPISpyPostClose();
3716 #endif
3717 }
3718
3719 /************************************************************************/
3720 /* GDALDumpOpenDataset() */
3721 /************************************************************************/
3722
GDALDumpOpenSharedDatasetsForeach(void * elt,void * user_data)3723 static int GDALDumpOpenSharedDatasetsForeach(void *elt, void *user_data)
3724 {
3725 SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
3726 FILE *fp = static_cast<FILE *>(user_data);
3727 GDALDataset *poDS = psStruct->poDS;
3728
3729 const char *pszDriverName = poDS->GetDriver() == nullptr
3730 ? "DriverIsNULL"
3731 : poDS->GetDriver()->GetDescription();
3732
3733 poDS->Reference();
3734 CPL_IGNORE_RET_VAL(
3735 VSIFPrintf(fp, " %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
3736 poDS->GetShared() ? 'S' : 'N', pszDriverName,
3737 static_cast<int>(psStruct->nPID), poDS->GetRasterXSize(),
3738 poDS->GetRasterYSize(), poDS->GetRasterCount(),
3739 poDS->GetDescription()));
3740
3741 return TRUE;
3742 }
3743
GDALDumpOpenDatasetsForeach(GDALDataset * poDS,FILE * fp)3744 static int GDALDumpOpenDatasetsForeach(GDALDataset *poDS, FILE *fp)
3745 {
3746
3747 // Don't list shared datasets. They have already been listed by
3748 // GDALDumpOpenSharedDatasetsForeach.
3749 if (poDS->GetShared())
3750 return TRUE;
3751
3752 const char *pszDriverName = poDS->GetDriver() == nullptr
3753 ? "DriverIsNULL"
3754 : poDS->GetDriver()->GetDescription();
3755
3756 poDS->Reference();
3757 CPL_IGNORE_RET_VAL(
3758 VSIFPrintf(fp, " %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
3759 poDS->GetShared() ? 'S' : 'N', pszDriverName, -1,
3760 poDS->GetRasterXSize(), poDS->GetRasterYSize(),
3761 poDS->GetRasterCount(), poDS->GetDescription()));
3762
3763 return TRUE;
3764 }
3765
3766 /**
3767 * \brief List open datasets.
3768 *
3769 * Dumps a list of all open datasets (shared or not) to the indicated
3770 * text file (may be stdout or stderr). This function is primarily intended
3771 * to assist in debugging "dataset leaks" and reference counting issues.
3772 * The information reported includes the dataset name, referenced count,
3773 * shared status, driver name, size, and band count.
3774 */
3775
GDALDumpOpenDatasets(FILE * fp)3776 int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp )
3777
3778 {
3779 VALIDATE_POINTER1(fp, "GDALDumpOpenDatasets", 0);
3780
3781 CPLMutexHolderD(&hDLMutex);
3782
3783 if (poAllDatasetMap == nullptr)
3784 return 0;
3785
3786 CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "Open GDAL Datasets:\n"));
3787
3788 for( auto oIter: *poAllDatasetMap )
3789 {
3790 GDALDumpOpenDatasetsForeach(oIter.first, fp);
3791 }
3792
3793 if (phSharedDatasetSet != nullptr)
3794 {
3795 CPLHashSetForeach(phSharedDatasetSet,
3796 GDALDumpOpenSharedDatasetsForeach, fp);
3797 }
3798 return static_cast<int>(poAllDatasetMap->size());
3799 }
3800
3801 /************************************************************************/
3802 /* BeginAsyncReader() */
3803 /************************************************************************/
3804
3805 /**
3806 * \brief Sets up an asynchronous data request
3807 *
3808 * This method establish an asynchronous raster read request for the
3809 * indicated window on the dataset into the indicated buffer. The parameters
3810 * for windowing, buffer size, buffer type and buffer organization are similar
3811 * to those for GDALDataset::RasterIO(); however, this call only launches
3812 * the request and filling the buffer is accomplished via calls to
3813 * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
3814 *
3815 * Once all processing for the created session is complete, or if no further
3816 * refinement of the request is required, the GDALAsyncReader object should
3817 * be destroyed with the GDALDataset::EndAsyncReader() method.
3818 *
3819 * Note that the data buffer (pData) will potentially continue to be
3820 * updated as long as the session lives, but it is not deallocated when
3821 * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
3822 * should be deallocated by the application at that point.
3823 *
3824 * Additional information on asynchronous IO in GDAL may be found at:
3825 * https://gdal.org/development/rfc/rfc24_progressive_data_support.html
3826 *
3827 * This method is the same as the C GDALBeginAsyncReader() function.
3828 *
3829 * @param nXOff The pixel offset to the top left corner of the region
3830 * of the band to be accessed. This would be zero to start from the left side.
3831 *
3832 * @param nYOff The line offset to the top left corner of the region
3833 * of the band to be accessed. This would be zero to start from the top.
3834 *
3835 * @param nXSize The width of the region of the band to be accessed in pixels.
3836 *
3837 * @param nYSize The height of the region of the band to be accessed in lines.
3838 *
3839 * @param pBuf The buffer into which the data should be read. This buffer must
3840 * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
3841 * It is organized in left to right,top to bottom pixel order. Spacing is
3842 * controlled by the nPixelSpace, and nLineSpace parameters.
3843 *
3844 * @param nBufXSize the width of the buffer image into which the desired region
3845 * is to be read, or from which it is to be written.
3846 *
3847 * @param nBufYSize the height of the buffer image into which the desired
3848 * region is to be read, or from which it is to be written.
3849 *
3850 * @param eBufType the type of the pixel values in the pData data buffer. The
3851 * pixel values will automatically be translated to/from the GDALRasterBand
3852 * data type as needed.
3853 *
3854 * @param nBandCount the number of bands being read or written.
3855 *
3856 * @param panBandMap the list of nBandCount band numbers being read/written.
3857 * Note band numbers are 1 based. This may be NULL to select the first
3858 * nBandCount bands.
3859 *
3860 * @param nPixelSpace The byte offset from the start of one pixel value in
3861 * pData to the start of the next pixel value within a scanline. If defaulted
3862 * (0) the size of the datatype eBufType is used.
3863 *
3864 * @param nLineSpace The byte offset from the start of one scanline in
3865 * pData to the start of the next. If defaulted the size of the datatype
3866 * eBufType * nBufXSize is used.
3867 *
3868 * @param nBandSpace the byte offset from the start of one bands data to the
3869 * start of the next. If defaulted (zero) the value will be
3870 * nLineSpace * nBufYSize implying band sequential organization
3871 * of the data buffer.
3872 *
3873 * @param papszOptions Driver specific control options in a string list or NULL.
3874 * Consult driver documentation for options supported.
3875 *
3876 * @return The GDALAsyncReader object representing the request.
3877 */
3878
BeginAsyncReader(int nXOff,int nYOff,int nXSize,int nYSize,void * pBuf,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,int nPixelSpace,int nLineSpace,int nBandSpace,char ** papszOptions)3879 GDALAsyncReader *GDALDataset::BeginAsyncReader(
3880 int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf, int nBufXSize,
3881 int nBufYSize, GDALDataType eBufType, int nBandCount, int *panBandMap,
3882 int nPixelSpace, int nLineSpace, int nBandSpace, char **papszOptions )
3883 {
3884 // See gdaldefaultasync.cpp
3885
3886 return GDALGetDefaultAsyncReader(this, nXOff, nYOff, nXSize, nYSize, pBuf,
3887 nBufXSize, nBufYSize, eBufType, nBandCount,
3888 panBandMap, nPixelSpace, nLineSpace,
3889 nBandSpace, papszOptions);
3890 }
3891
3892 /************************************************************************/
3893 /* GDALBeginAsyncReader() */
3894 /************************************************************************/
3895
3896 /**
3897 * \brief Sets up an asynchronous data request
3898 *
3899 * This method establish an asynchronous raster read request for the
3900 * indicated window on the dataset into the indicated buffer. The parameters
3901 * for windowing, buffer size, buffer type and buffer organization are similar
3902 * to those for GDALDataset::RasterIO(); however, this call only launches
3903 * the request and filling the buffer is accomplished via calls to
3904 * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
3905 *
3906 * Once all processing for the created session is complete, or if no further
3907 * refinement of the request is required, the GDALAsyncReader object should
3908 * be destroyed with the GDALDataset::EndAsyncReader() method.
3909 *
3910 * Note that the data buffer (pData) will potentially continue to be
3911 * updated as long as the session lives, but it is not deallocated when
3912 * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
3913 * should be deallocated by the application at that point.
3914 *
3915 * Additional information on asynchronous IO in GDAL may be found at:
3916 * https://gdal.org/development/rfc/rfc24_progressive_data_support.html
3917 *
3918 * This method is the same as the C++ GDALDataset::BeginAsyncReader() method.
3919 *
3920 * @param hDS handle to the dataset object.
3921 *
3922 * @param nXOff The pixel offset to the top left corner of the region
3923 * of the band to be accessed. This would be zero to start from the left side.
3924 *
3925 * @param nYOff The line offset to the top left corner of the region
3926 * of the band to be accessed. This would be zero to start from the top.
3927 *
3928 * @param nXSize The width of the region of the band to be accessed in pixels.
3929 *
3930 * @param nYSize The height of the region of the band to be accessed in lines.
3931 *
3932 * @param pBuf The buffer into which the data should be read. This buffer must
3933 * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
3934 * It is organized in left to right,top to bottom pixel order. Spacing is
3935 * controlled by the nPixelSpace, and nLineSpace parameters.
3936 *
3937 * @param nBufXSize the width of the buffer image into which the desired region
3938 * is to be read, or from which it is to be written.
3939 *
3940 * @param nBufYSize the height of the buffer image into which the desired
3941 * region is to be read, or from which it is to be written.
3942 *
3943 * @param eBufType the type of the pixel values in the pData data buffer. The
3944 * pixel values will automatically be translated to/from the GDALRasterBand
3945 * data type as needed.
3946 *
3947 * @param nBandCount the number of bands being read or written.
3948 *
3949 * @param panBandMap the list of nBandCount band numbers being read/written.
3950 * Note band numbers are 1 based. This may be NULL to select the first
3951 * nBandCount bands.
3952 *
3953 * @param nPixelSpace The byte offset from the start of one pixel value in
3954 * pData to the start of the next pixel value within a scanline. If defaulted
3955 * (0) the size of the datatype eBufType is used.
3956 *
3957 * @param nLineSpace The byte offset from the start of one scanline in
3958 * pData to the start of the next. If defaulted the size of the datatype
3959 * eBufType * nBufXSize is used.
3960 *
3961 * @param nBandSpace the byte offset from the start of one bands data to the
3962 * start of the next. If defaulted (zero) the value will be
3963 * nLineSpace * nBufYSize implying band sequential organization
3964 * of the data buffer.
3965 *
3966 * @param papszOptions Driver specific control options in a string list or NULL.
3967 * Consult driver documentation for options supported.
3968 *
3969 * @return handle representing the request.
3970 */
3971
3972 GDALAsyncReaderH CPL_STDCALL
GDALBeginAsyncReader(GDALDatasetH hDS,int nXOff,int nYOff,int nXSize,int nYSize,void * pBuf,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,int nPixelSpace,int nLineSpace,int nBandSpace,CSLConstList papszOptions)3973 GDALBeginAsyncReader( GDALDatasetH hDS, int nXOff, int nYOff,
3974 int nXSize, int nYSize,
3975 void *pBuf,
3976 int nBufXSize, int nBufYSize,
3977 GDALDataType eBufType,
3978 int nBandCount, int* panBandMap,
3979 int nPixelSpace, int nLineSpace,
3980 int nBandSpace,
3981 CSLConstList papszOptions )
3982
3983 {
3984 VALIDATE_POINTER1(hDS, "GDALDataset", nullptr);
3985 return static_cast<GDALAsyncReaderH>(
3986 GDALDataset::FromHandle(hDS)->BeginAsyncReader(
3987 nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize, nBufYSize, eBufType,
3988 nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
3989 const_cast<char**>(papszOptions)));
3990 }
3991
3992 /************************************************************************/
3993 /* EndAsyncReader() */
3994 /************************************************************************/
3995
3996 /**
3997 * End asynchronous request.
3998 *
3999 * This method destroys an asynchronous io request and recovers all
4000 * resources associated with it.
4001 *
4002 * This method is the same as the C function GDALEndAsyncReader().
4003 *
4004 * @param poARIO pointer to a GDALAsyncReader
4005 */
4006
EndAsyncReader(GDALAsyncReader * poARIO)4007 void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO) { delete poARIO; }
4008
4009 /************************************************************************/
4010 /* GDALEndAsyncReader() */
4011 /************************************************************************/
4012
4013 /**
4014 * End asynchronous request.
4015 *
4016 * This method destroys an asynchronous io request and recovers all
4017 * resources associated with it.
4018 *
4019 * This method is the same as the C++ method GDALDataset::EndAsyncReader().
4020 *
4021 * @param hDS handle to the dataset object.
4022 * @param hAsyncReaderH handle returned by GDALBeginAsyncReader()
4023 */
4024
GDALEndAsyncReader(GDALDatasetH hDS,GDALAsyncReaderH hAsyncReaderH)4025 void CPL_STDCALL GDALEndAsyncReader( GDALDatasetH hDS,
4026 GDALAsyncReaderH hAsyncReaderH )
4027 {
4028 VALIDATE_POINTER0(hDS, "GDALDataset");
4029 VALIDATE_POINTER0(hAsyncReaderH, "GDALAsyncReader");
4030 GDALDataset::FromHandle(hDS)
4031 ->EndAsyncReader(static_cast<GDALAsyncReader *>(hAsyncReaderH));
4032 }
4033
4034 /************************************************************************/
4035 /* CloseDependentDatasets() */
4036 /************************************************************************/
4037
4038 /**
4039 * Drop references to any other datasets referenced by this dataset.
4040 *
4041 * This method should release any reference to other datasets (e.g. a VRT
4042 * dataset to its sources), but not close the current dataset itself.
4043 *
4044 * If at least, one reference to a dependent dataset has been dropped,
4045 * this method should return TRUE. Otherwise it *should* return FALSE.
4046 * (Failure to return the proper value might result in infinite loop)
4047 *
4048 * This method can be called several times on a given dataset. After
4049 * the first time, it should not do anything and return FALSE.
4050 *
4051 * The driver implementation may choose to destroy its raster bands,
4052 * so be careful not to call any method on the raster bands afterwards.
4053 *
4054 * Basically the only safe action you can do after calling
4055 * CloseDependentDatasets() is to call the destructor.
4056 *
4057 * Note: the only legitimate caller of CloseDependentDatasets() is
4058 * GDALDriverManager::~GDALDriverManager()
4059 *
4060 * @return TRUE if at least one reference to another dataset has been dropped.
4061 */
CloseDependentDatasets()4062 int GDALDataset::CloseDependentDatasets()
4063 {
4064 return oOvManager.CloseDependentDatasets();
4065 }
4066
4067 /************************************************************************/
4068 /* ReportError() */
4069 /************************************************************************/
4070
4071 #ifndef DOXYGEN_XML
4072 /**
4073 * \brief Emits an error related to a dataset.
4074 *
4075 * This function is a wrapper for regular CPLError(). The only difference
4076 * with CPLError() is that it prepends the error message with the dataset
4077 * name.
4078 *
4079 * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4080 * @param err_no the error number (CPLE_*) from cpl_error.h.
4081 * @param fmt a printf() style format string. Any additional arguments
4082 * will be treated as arguments to fill in this format in a manner
4083 * similar to printf().
4084 *
4085 * @since GDAL 1.9.0
4086 */
4087
ReportError(CPLErr eErrClass,CPLErrorNum err_no,const char * fmt,...)4088 void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
4089 const char *fmt, ...)
4090 {
4091 va_list args;
4092 va_start(args, fmt);
4093 ReportErrorV(GetDescription(), eErrClass, err_no, fmt, args);
4094 va_end(args);
4095 }
4096
4097 /**
4098 * \brief Emits an error related to a dataset (static method)
4099 *
4100 * This function is a wrapper for regular CPLError(). The only difference
4101 * with CPLError() is that it prepends the error message with the dataset
4102 * name.
4103 *
4104 * @param pszDSName dataset name.
4105 * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4106 * @param err_no the error number (CPLE_*) from cpl_error.h.
4107 * @param fmt a printf() style format string. Any additional arguments
4108 * will be treated as arguments to fill in this format in a manner
4109 * similar to printf().
4110 *
4111 * @since GDAL 3.2.0
4112 */
4113
ReportError(const char * pszDSName,CPLErr eErrClass,CPLErrorNum err_no,const char * fmt,...)4114 void GDALDataset::ReportError(const char* pszDSName,
4115 CPLErr eErrClass, CPLErrorNum err_no,
4116 const char *fmt, ...)
4117 {
4118 va_list args;
4119 va_start(args, fmt);
4120 ReportErrorV(pszDSName, eErrClass, err_no, fmt, args);
4121 va_end(args);
4122 }
4123
ReportErrorV(const char * pszDSName,CPLErr eErrClass,CPLErrorNum err_no,const char * fmt,va_list args)4124 void GDALDataset::ReportErrorV(const char* pszDSName,
4125 CPLErr eErrClass, CPLErrorNum err_no,
4126 const char *fmt, va_list args)
4127 {
4128 char szNewFmt[256] = {};
4129 if (strlen(fmt) + strlen(pszDSName) + 3 >= sizeof(szNewFmt) - 1)
4130 pszDSName = CPLGetFilename(pszDSName);
4131 if (pszDSName[0] != '\0' && strchr(pszDSName, '%') == nullptr &&
4132 strlen(fmt) + strlen(pszDSName) + 3 < sizeof(szNewFmt) - 1)
4133 {
4134 snprintf(szNewFmt, sizeof(szNewFmt), "%s: %s", pszDSName, fmt);
4135 CPLErrorV(eErrClass, err_no, szNewFmt, args);
4136 }
4137 else
4138 {
4139 CPLErrorV(eErrClass, err_no, fmt, args);
4140 }
4141 }
4142 #endif
4143
4144 /************************************************************************/
4145 /* GetMetadata() */
4146 /************************************************************************/
GetMetadata(const char * pszDomain)4147 char **GDALDataset::GetMetadata(const char *pszDomain)
4148 {
4149 if( pszDomain != nullptr && EQUAL(pszDomain, "DERIVED_SUBDATASETS") )
4150 {
4151 oDerivedMetadataList.Clear();
4152
4153 // First condition: at least one raster band.
4154 if(GetRasterCount() > 0)
4155 {
4156 // Check if there is at least one complex band.
4157 bool hasAComplexBand = false;
4158
4159 for(int rasterId = 1; rasterId <= GetRasterCount(); ++rasterId)
4160 {
4161 if(GDALDataTypeIsComplex(
4162 GetRasterBand(rasterId)->GetRasterDataType()))
4163 {
4164 hasAComplexBand = true;
4165 break;
4166 }
4167 }
4168
4169 unsigned int nbSupportedDerivedDS = 0;
4170 const DerivedDatasetDescription *poDDSDesc =
4171 GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
4172
4173 int nNumDataset = 1;
4174 for(unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
4175 ++derivedId)
4176 {
4177 if(hasAComplexBand ||
4178 CPLString(poDDSDesc[derivedId].pszInputPixelType) !=
4179 "complex")
4180 {
4181 oDerivedMetadataList.SetNameValue(
4182 CPLSPrintf("DERIVED_SUBDATASET_%d_NAME", nNumDataset),
4183 CPLSPrintf("DERIVED_SUBDATASET:%s:%s",
4184 poDDSDesc[derivedId].pszDatasetName,
4185 GetDescription()));
4186
4187 CPLString osDesc(
4188 CPLSPrintf("%s from %s",
4189 poDDSDesc[derivedId].pszDatasetDescription,
4190 GetDescription()));
4191 oDerivedMetadataList.SetNameValue(
4192 CPLSPrintf("DERIVED_SUBDATASET_%d_DESC", nNumDataset),
4193 osDesc.c_str());
4194
4195 nNumDataset++;
4196 }
4197 }
4198 }
4199 return oDerivedMetadataList.List();
4200 }
4201
4202 return GDALMajorObject::GetMetadata(pszDomain);
4203 }
4204
4205 /**
4206 * \fn GDALDataset::SetMetadata( char ** papszMetadata, const char * pszDomain)
4207 * \brief Set metadata.
4208 *
4209 * CAUTION: depending on the format, older values of the updated information
4210 * might still be found in the file in a "ghost" state, even if no longer
4211 * accessible through the GDAL API. This is for example the case of the GTiff
4212 * format (this is not a exhaustive list)
4213 *
4214 * The C function GDALSetMetadata() does the same thing as this method.
4215 *
4216 * @param papszMetadata the metadata in name=value string list format to
4217 * apply.
4218 * @param pszDomain the domain of interest. Use "" or NULL for the default
4219 * domain.
4220 * @return CE_None on success, CE_Failure on failure and CE_Warning if the
4221 * metadata has been accepted, but is likely not maintained persistently
4222 * by the underlying object between sessions.
4223 */
4224
4225 /**
4226 * \fn GDALDataset::SetMetadataItem( const char * pszName, const char *
4227 * pszValue, const char * pszDomain)
4228 * \brief Set single metadata item.
4229 *
4230 * CAUTION: depending on the format, older values of the updated information
4231 * might still be found in the file in a "ghost" state, even if no longer
4232 * accessible through the GDAL API. This is for example the case of the GTiff
4233 * format (this is not a exhaustive list)
4234 *
4235 * The C function GDALSetMetadataItem() does the same thing as this method.
4236 *
4237 * @param pszName the key for the metadata item to fetch.
4238 * @param pszValue the value to assign to the key.
4239 * @param pszDomain the domain to set within, use NULL for the default domain.
4240 *
4241 * @return CE_None on success, or an error code on failure.
4242 */
4243
4244 /************************************************************************/
4245 /* GetMetadataDomainList() */
4246 /************************************************************************/
4247
GetMetadataDomainList()4248 char **GDALDataset::GetMetadataDomainList()
4249 {
4250 char **currentDomainList = CSLDuplicate(oMDMD.GetDomainList());
4251
4252 // Ensure that we do not duplicate DERIVED domain.
4253 if(GetRasterCount() > 0 &&
4254 CSLFindString(currentDomainList, "DERIVED_SUBDATASETS") == -1)
4255 {
4256 currentDomainList =
4257 CSLAddString(currentDomainList, "DERIVED_SUBDATASETS");
4258 }
4259 return currentDomainList;
4260 }
4261
4262 /************************************************************************/
4263 /* GetDriverName() */
4264 /************************************************************************/
4265
4266 /** Return driver name.
4267 * @return driver name.
4268 */
GetDriverName()4269 const char *GDALDataset::GetDriverName()
4270 {
4271 if( poDriver )
4272 return poDriver->GetDescription();
4273 return "";
4274 }
4275
4276 /************************************************************************/
4277 /* GDALDatasetReleaseResultSet() */
4278 /************************************************************************/
4279
4280 /**
4281 \brief Release results of ExecuteSQL().
4282
4283 This function should only be used to deallocate OGRLayers resulting from
4284 an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
4285 results set before destroying the GDALDataset may cause errors.
4286
4287 This function is the same as the C++ method GDALDataset::ReleaseResultSet()
4288
4289 @since GDAL 2.0
4290
4291 @param hDS the dataset handle.
4292 @param hLayer the result of a previous ExecuteSQL() call.
4293
4294 */
GDALDatasetReleaseResultSet(GDALDatasetH hDS,OGRLayerH hLayer)4295 void GDALDatasetReleaseResultSet( GDALDatasetH hDS, OGRLayerH hLayer )
4296
4297 {
4298 VALIDATE_POINTER0(hDS, "GDALDatasetReleaseResultSet");
4299
4300 #ifdef OGRAPISPY_ENABLED
4301 if( bOGRAPISpyEnabled )
4302 OGRAPISpy_DS_ReleaseResultSet(hDS, hLayer);
4303 #endif
4304
4305 GDALDataset::FromHandle(hDS)
4306 ->ReleaseResultSet(OGRLayer::FromHandle(hLayer));
4307 }
4308
4309 /************************************************************************/
4310 /* GDALDatasetGetLayerCount() */
4311 /************************************************************************/
4312
4313 /**
4314 \brief Get the number of layers in this dataset.
4315
4316 This function is the same as the C++ method GDALDataset::GetLayerCount()
4317
4318 @since GDAL 2.0
4319
4320 @param hDS the dataset handle.
4321 @return layer count.
4322 */
4323
GDALDatasetGetLayerCount(GDALDatasetH hDS)4324 int GDALDatasetGetLayerCount( GDALDatasetH hDS )
4325
4326 {
4327 VALIDATE_POINTER1(hDS, "GDALDatasetH", 0);
4328
4329 #ifdef OGRAPISPY_ENABLED
4330 if( bOGRAPISpyEnabled )
4331 OGRAPISpy_DS_GetLayerCount(reinterpret_cast<GDALDatasetH>(hDS));
4332 #endif
4333
4334 return GDALDataset::FromHandle(hDS)->GetLayerCount();
4335 }
4336
4337 /************************************************************************/
4338 /* GDALDatasetGetLayer() */
4339 /************************************************************************/
4340
4341 /**
4342 \brief Fetch a layer by index.
4343
4344 The returned layer remains owned by the
4345 GDALDataset and should not be deleted by the application.
4346
4347 This function is the same as the C++ method GDALDataset::GetLayer()
4348
4349 @since GDAL 2.0
4350
4351 @param hDS the dataset handle.
4352 @param iLayer a layer number between 0 and GetLayerCount()-1.
4353
4354 @return the layer, or NULL if iLayer is out of range or an error occurs.
4355 */
4356
GDALDatasetGetLayer(GDALDatasetH hDS,int iLayer)4357 OGRLayerH GDALDatasetGetLayer( GDALDatasetH hDS, int iLayer )
4358
4359 {
4360 VALIDATE_POINTER1(hDS, "GDALDatasetGetLayer", nullptr);
4361
4362 OGRLayerH hLayer = OGRLayer::ToHandle(
4363 GDALDataset::FromHandle(hDS)->GetLayer(iLayer));
4364
4365 #ifdef OGRAPISPY_ENABLED
4366 if( bOGRAPISpyEnabled )
4367 OGRAPISpy_DS_GetLayer(hDS, iLayer, hLayer);
4368 #endif
4369
4370 return hLayer;
4371 }
4372
4373 /************************************************************************/
4374 /* GDALDatasetGetLayerByName() */
4375 /************************************************************************/
4376
4377 /**
4378 \brief Fetch a layer by name.
4379
4380 The returned layer remains owned by the
4381 GDALDataset and should not be deleted by the application.
4382
4383 This function is the same as the C++ method GDALDataset::GetLayerByName()
4384
4385 @since GDAL 2.0
4386
4387 @param hDS the dataset handle.
4388 @param pszName the layer name of the layer to fetch.
4389
4390 @return the layer, or NULL if Layer is not found or an error occurs.
4391 */
4392
GDALDatasetGetLayerByName(GDALDatasetH hDS,const char * pszName)4393 OGRLayerH GDALDatasetGetLayerByName( GDALDatasetH hDS, const char *pszName )
4394
4395 {
4396 VALIDATE_POINTER1(hDS, "GDALDatasetGetLayerByName", nullptr);
4397
4398 OGRLayerH hLayer = OGRLayer::ToHandle(
4399 GDALDataset::FromHandle(hDS)->GetLayerByName(pszName));
4400
4401 #ifdef OGRAPISPY_ENABLED
4402 if( bOGRAPISpyEnabled )
4403 OGRAPISpy_DS_GetLayerByName(hDS, pszName, hLayer);
4404 #endif
4405
4406 return hLayer;
4407 }
4408
4409 /************************************************************************/
4410 /* GDALDatasetDeleteLayer() */
4411 /************************************************************************/
4412
4413 /**
4414 \brief Delete the indicated layer from the datasource.
4415
4416 If this function is supported
4417 the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
4418
4419 This method is the same as the C++ method GDALDataset::DeleteLayer().
4420
4421 @since GDAL 2.0
4422
4423 @param hDS the dataset handle.
4424 @param iLayer the index of the layer to delete.
4425
4426 @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
4427 layers is not supported for this datasource.
4428
4429 */
GDALDatasetDeleteLayer(GDALDatasetH hDS,int iLayer)4430 OGRErr GDALDatasetDeleteLayer( GDALDatasetH hDS, int iLayer )
4431
4432 {
4433 VALIDATE_POINTER1(hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE);
4434
4435 return GDALDataset::FromHandle(hDS)->DeleteLayer(iLayer);
4436 }
4437
4438 /************************************************************************/
4439 /* CreateLayer() */
4440 /************************************************************************/
4441
4442 /**
4443 \brief This method attempts to create a new layer on the dataset with the
4444 indicated name, coordinate system, geometry type.
4445
4446 The papszOptions argument
4447 can be used to control driver specific creation options. These options are
4448 normally documented in the format specific documentation.
4449
4450 In GDAL 2.0, drivers should extend the ICreateLayer() method and not
4451 CreateLayer(). CreateLayer() adds validation of layer creation options, before
4452 delegating the actual work to ICreateLayer().
4453
4454 This method is the same as the C function GDALDatasetCreateLayer() and the
4455 deprecated OGR_DS_CreateLayer().
4456
4457 In GDAL 1.X, this method used to be in the OGRDataSource class.
4458
4459 Example:
4460
4461 \code{.cpp}
4462 #include "gdal.h"
4463 #include "cpl_string.h"
4464
4465 ...
4466
4467 OGRLayer *poLayer;
4468 char **papszOptions;
4469
4470 if( !poDS->TestCapability( ODsCCreateLayer ) )
4471 {
4472 ...
4473 }
4474
4475 papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
4476 poLayer = poDS->CreateLayer( "NewLayer", nullptr, wkbUnknown,
4477 papszOptions );
4478 CSLDestroy( papszOptions );
4479
4480 if( poLayer == NULL )
4481 {
4482 ...
4483 }
4484 \endcode
4485
4486 @param pszName the name for the new layer. This should ideally not
4487 match any existing layer on the datasource.
4488 @param poSpatialRef the coordinate system to use for the new layer, or NULL if
4489 no coordinate system is available. The driver might only increase
4490 the reference counter of the object to take ownership, and not make a full copy,
4491 so do not use OSRDestroySpatialReference(), but OSRRelease() instead when you
4492 are done with the object.
4493 @param eGType the geometry type for the layer. Use wkbUnknown if there
4494 are no constraints on the types geometry to be written.
4495 @param papszOptions a StringList of name=value options. Options are driver
4496 specific.
4497
4498 @return NULL is returned on failure, or a new OGRLayer handle on success.
4499
4500 */
4501
CreateLayer(const char * pszName,OGRSpatialReference * poSpatialRef,OGRwkbGeometryType eGType,char ** papszOptions)4502 OGRLayer *GDALDataset::CreateLayer( const char * pszName,
4503 OGRSpatialReference * poSpatialRef,
4504 OGRwkbGeometryType eGType,
4505 char **papszOptions )
4506
4507 {
4508 ValidateLayerCreationOptions(papszOptions);
4509
4510 if( OGR_GT_IsNonLinear(eGType) && !TestCapability(ODsCCurveGeometries) )
4511 {
4512 eGType = OGR_GT_GetLinear(eGType);
4513 }
4514
4515 OGRLayer *poLayer =
4516 ICreateLayer(pszName, poSpatialRef, eGType, papszOptions);
4517 #ifdef DEBUG
4518 if( poLayer != nullptr && OGR_GT_IsNonLinear(poLayer->GetGeomType()) &&
4519 !poLayer->TestCapability(OLCCurveGeometries) )
4520 {
4521 CPLError(CE_Warning, CPLE_AppDefined,
4522 "Inconsistent driver: Layer geometry type is non-linear, but "
4523 "TestCapability(OLCCurveGeometries) returns FALSE.");
4524 }
4525 #endif
4526
4527 return poLayer;
4528 }
4529
4530 /************************************************************************/
4531 /* GDALDatasetCreateLayer() */
4532 /************************************************************************/
4533
4534 /**
4535 \brief This function attempts to create a new layer on the dataset with the
4536 indicated name, coordinate system, geometry type.
4537
4538 The papszOptions argument can be used to control driver specific creation
4539 options. These options are normally documented in the format specific
4540 documentation.
4541
4542 This method is the same as the C++ method GDALDataset::CreateLayer().
4543
4544 Example:
4545
4546 \code{.c}
4547 #include "gdal.h"
4548 #include "cpl_string.h"
4549
4550 ...
4551
4552 OGRLayerH hLayer;
4553 char **papszOptions;
4554
4555 if( !GDALDatasetTestCapability( hDS, ODsCCreateLayer ) )
4556 {
4557 ...
4558 }
4559
4560 papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
4561 hLayer = GDALDatasetCreateLayer( hDS, "NewLayer", NULL, wkbUnknown,
4562 papszOptions );
4563 CSLDestroy( papszOptions );
4564
4565 if( hLayer == NULL )
4566 {
4567 ...
4568 }
4569 \endcode
4570
4571 @since GDAL 2.0
4572
4573 @param hDS the dataset handle
4574 @param pszName the name for the new layer. This should ideally not
4575 match any existing layer on the datasource.
4576 @param hSpatialRef the coordinate system to use for the new layer, or NULL if
4577 no coordinate system is available. The driver might only increase
4578 the reference counter of the object to take ownership, and not make a full copy,
4579 so do not use OSRDestroySpatialReference(), but OSRRelease() instead when you
4580 are done with the object.
4581 @param eGType the geometry type for the layer. Use wkbUnknown if there
4582 are no constraints on the types geometry to be written.
4583 @param papszOptions a StringList of name=value options. Options are driver
4584 specific.
4585
4586 @return NULL is returned on failure, or a new OGRLayer handle on success.
4587
4588 */
4589
GDALDatasetCreateLayer(GDALDatasetH hDS,const char * pszName,OGRSpatialReferenceH hSpatialRef,OGRwkbGeometryType eGType,CSLConstList papszOptions)4590 OGRLayerH GDALDatasetCreateLayer( GDALDatasetH hDS,
4591 const char * pszName,
4592 OGRSpatialReferenceH hSpatialRef,
4593 OGRwkbGeometryType eGType,
4594 CSLConstList papszOptions )
4595
4596 {
4597 VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayer", nullptr);
4598
4599 if (pszName == nullptr)
4600 {
4601 CPLError(CE_Failure, CPLE_ObjectNull,
4602 "Name was NULL in GDALDatasetCreateLayer");
4603 return nullptr;
4604 }
4605
4606 OGRLayerH hLayer = OGRLayer::ToHandle(
4607 GDALDataset::FromHandle(hDS)->CreateLayer(
4608 pszName, OGRSpatialReference::FromHandle(hSpatialRef),
4609 eGType, const_cast<char**>(papszOptions)));
4610
4611 #ifdef OGRAPISPY_ENABLED
4612 if( bOGRAPISpyEnabled )
4613 OGRAPISpy_DS_CreateLayer(hDS, pszName, hSpatialRef, eGType, const_cast<char**>(papszOptions), hLayer);
4614 #endif
4615
4616 return hLayer;
4617 }
4618
4619 /************************************************************************/
4620 /* GDALDatasetCopyLayer() */
4621 /************************************************************************/
4622
4623 /**
4624 \brief Duplicate an existing layer.
4625
4626 This function creates a new layer, duplicate the field definitions of the
4627 source layer and then duplicate each features of the source layer.
4628 The papszOptions argument
4629 can be used to control driver specific creation options. These options are
4630 normally documented in the format specific documentation.
4631 The source layer may come from another dataset.
4632
4633 This method is the same as the C++ method GDALDataset::CopyLayer()
4634
4635 @since GDAL 2.0
4636
4637 @param hDS the dataset handle.
4638 @param hSrcLayer source layer.
4639 @param pszNewName the name of the layer to create.
4640 @param papszOptions a StringList of name=value options. Options are driver
4641 specific.
4642
4643 @return a handle to the layer, or NULL if an error occurs.
4644 */
GDALDatasetCopyLayer(GDALDatasetH hDS,OGRLayerH hSrcLayer,const char * pszNewName,CSLConstList papszOptions)4645 OGRLayerH GDALDatasetCopyLayer( GDALDatasetH hDS,
4646 OGRLayerH hSrcLayer, const char *pszNewName,
4647 CSLConstList papszOptions )
4648
4649 {
4650 VALIDATE_POINTER1(hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", nullptr);
4651 VALIDATE_POINTER1(hSrcLayer, "GDALDatasetCopyLayer", nullptr);
4652 VALIDATE_POINTER1(pszNewName, "GDALDatasetCopyLayer", nullptr);
4653
4654 return OGRLayer::ToHandle(
4655 GDALDataset::FromHandle(hDS)->CopyLayer(
4656 OGRLayer::FromHandle(hSrcLayer), pszNewName,
4657 const_cast<char**>(papszOptions)));
4658 }
4659
4660 /************************************************************************/
4661 /* GDALDatasetExecuteSQL() */
4662 /************************************************************************/
4663
4664 /**
4665 \brief Execute an SQL statement against the data store.
4666
4667 The result of an SQL query is either NULL for statements that are in error,
4668 or that have no results set, or an OGRLayer pointer representing a results
4669 set from the query. Note that this OGRLayer is in addition to the layers
4670 in the data store and must be destroyed with
4671 ReleaseResultSet() before the dataset is closed
4672 (destroyed).
4673
4674 This method is the same as the C++ method GDALDataset::ExecuteSQL()
4675
4676 For more information on the SQL dialect supported internally by OGR
4677 review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a> document. Some drivers (i.e.
4678 Oracle and PostGIS) pass the SQL directly through to the underlying RDBMS.
4679
4680 Starting with OGR 1.10, the <a href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a>
4681 can also be used.
4682
4683 @since GDAL 2.0
4684
4685 @param hDS the dataset handle.
4686 @param pszStatement the SQL statement to execute.
4687 @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.
4688
4689 @param pszDialect allows control of the statement dialect. If set to NULL, the
4690 OGR SQL engine will be used, except for RDBMS drivers that will use their
4691 dedicated SQL engine, unless OGRSQL is explicitly passed as the
4692 dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
4693
4694 @return an OGRLayer containing the results of the query. Deallocate with
4695 GDALDatasetReleaseResultSet().
4696
4697 */
4698
GDALDatasetExecuteSQL(GDALDatasetH hDS,const char * pszStatement,OGRGeometryH hSpatialFilter,const char * pszDialect)4699 OGRLayerH GDALDatasetExecuteSQL( GDALDatasetH hDS,
4700 const char *pszStatement,
4701 OGRGeometryH hSpatialFilter,
4702 const char *pszDialect )
4703
4704 {
4705 VALIDATE_POINTER1(hDS, "GDALDatasetExecuteSQL", nullptr);
4706
4707 OGRLayerH hLayer = OGRLayer::ToHandle(
4708 GDALDataset::FromHandle(hDS)->ExecuteSQL(
4709 pszStatement, OGRGeometry::FromHandle(hSpatialFilter),
4710 pszDialect));
4711
4712 #ifdef OGRAPISPY_ENABLED
4713 if( bOGRAPISpyEnabled )
4714 OGRAPISpy_DS_ExecuteSQL(hDS, pszStatement, hSpatialFilter, pszDialect, hLayer);
4715 #endif
4716
4717 return hLayer;
4718 }
4719
4720
4721 /************************************************************************/
4722 /* GDALDatasetAbortSQL() */
4723 /************************************************************************/
4724
4725 /**
4726 \brief Abort any SQL statement running in the data store.
4727
4728 This function can be safely called from any thread (pending that the dataset object is still alive). Driver implementations will make sure that it can be called in a thread-safe way.
4729
4730 This might not be implemented by all drivers. At time of writing, only SQLite, GPKG and PG drivers implement it
4731
4732 This method is the same as the C++ method GDALDataset::AbortSQL()
4733
4734 @since GDAL 3.2.0
4735
4736 @param hDS the dataset handle.
4737
4738 @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if AbortSQL
4739 is not supported for this datasource. .
4740
4741 */
4742
GDALDatasetAbortSQL(GDALDatasetH hDS)4743 OGRErr GDALDatasetAbortSQL( GDALDatasetH hDS )
4744
4745 {
4746 VALIDATE_POINTER1(hDS, "GDALDatasetAbortSQL", OGRERR_FAILURE );
4747 return GDALDataset::FromHandle(hDS)->AbortSQL();
4748 }
4749
4750
4751 /************************************************************************/
4752 /* GDALDatasetGetStyleTable() */
4753 /************************************************************************/
4754
4755 /**
4756 \brief Returns dataset style table.
4757
4758 This function is the same as the C++ method GDALDataset::GetStyleTable()
4759
4760 @since GDAL 2.0
4761
4762 @param hDS the dataset handle
4763 @return handle to a style table which should not be modified or freed by the
4764 caller.
4765 */
4766
GDALDatasetGetStyleTable(GDALDatasetH hDS)4767 OGRStyleTableH GDALDatasetGetStyleTable( GDALDatasetH hDS )
4768
4769 {
4770 VALIDATE_POINTER1(hDS, "OGR_DS_GetStyleTable", nullptr);
4771
4772 return reinterpret_cast<OGRStyleTableH>(
4773 GDALDataset::FromHandle(hDS)->GetStyleTable());
4774 }
4775
4776 /************************************************************************/
4777 /* GDALDatasetSetStyleTableDirectly() */
4778 /************************************************************************/
4779
4780 /**
4781 \brief Set dataset style table.
4782
4783 This function operate exactly as GDALDatasetSetStyleTable() except that it
4784 assumes ownership of the passed table.
4785
4786 This function is the same as the C++ method
4787 GDALDataset::SetStyleTableDirectly()
4788
4789 @since GDAL 2.0
4790
4791 @param hDS the dataset handle
4792 @param hStyleTable style table handle to set
4793
4794 */
4795
GDALDatasetSetStyleTableDirectly(GDALDatasetH hDS,OGRStyleTableH hStyleTable)4796 void GDALDatasetSetStyleTableDirectly( GDALDatasetH hDS,
4797 OGRStyleTableH hStyleTable )
4798
4799 {
4800 VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTableDirectly");
4801
4802 GDALDataset::FromHandle(hDS)
4803 ->SetStyleTableDirectly(reinterpret_cast<OGRStyleTable *>(hStyleTable));
4804 }
4805
4806 /************************************************************************/
4807 /* GDALDatasetSetStyleTable() */
4808 /************************************************************************/
4809
4810 /**
4811 \brief Set dataset style table.
4812
4813 This function operate exactly as GDALDatasetSetStyleTableDirectly() except that
4814 it assumes ownership of the passed table.
4815
4816 This function is the same as the C++ method GDALDataset::SetStyleTable()
4817
4818 @since GDAL 2.0
4819
4820 @param hDS the dataset handle
4821 @param hStyleTable style table handle to set
4822
4823 */
4824
GDALDatasetSetStyleTable(GDALDatasetH hDS,OGRStyleTableH hStyleTable)4825 void GDALDatasetSetStyleTable( GDALDatasetH hDS, OGRStyleTableH hStyleTable )
4826
4827 {
4828 VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTable");
4829 VALIDATE_POINTER0(hStyleTable, "OGR_DS_SetStyleTable");
4830
4831 GDALDataset::FromHandle(hDS)
4832 ->SetStyleTable(reinterpret_cast<OGRStyleTable *>(hStyleTable));
4833 }
4834
4835 /************************************************************************/
4836 /* ValidateLayerCreationOptions() */
4837 /************************************************************************/
4838
4839 //! @cond Doxygen_Suppress
ValidateLayerCreationOptions(const char * const * papszLCO)4840 int GDALDataset::ValidateLayerCreationOptions( const char* const* papszLCO )
4841 {
4842 const char *pszOptionList =
4843 GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
4844 if( pszOptionList == nullptr && poDriver != nullptr )
4845 {
4846 pszOptionList =
4847 poDriver->GetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST );
4848 }
4849 CPLString osDataset;
4850 osDataset.Printf("dataset %s", GetDescription());
4851 return GDALValidateOptions(pszOptionList, papszLCO,
4852 "layer creation option",
4853 osDataset);
4854 }
4855 //! @endcond
4856
4857 /************************************************************************/
4858 /* Release() */
4859 /************************************************************************/
4860
4861 /**
4862 \brief Drop a reference to this dataset, and if the reference count drops to one
4863 close (destroy) the dataset.
4864
4865 This method is the same as the C function OGRReleaseDataSource().
4866
4867 @deprecated. In GDAL 2, use GDALClose() instead
4868
4869 @return OGRERR_NONE on success or an error code.
4870 */
4871
Release()4872 OGRErr GDALDataset::Release()
4873
4874 {
4875 ReleaseRef();
4876 return OGRERR_NONE;
4877 }
4878
4879 /************************************************************************/
4880 /* GetRefCount() */
4881 /************************************************************************/
4882
4883 /**
4884 \brief Fetch reference count.
4885
4886 This method is the same as the C function OGR_DS_GetRefCount().
4887
4888 In GDAL 1.X, this method used to be in the OGRDataSource class.
4889
4890 @return the current reference count for the datasource object itself.
4891 */
4892
GetRefCount() const4893 int GDALDataset::GetRefCount() const { return nRefCount; }
4894
4895 /************************************************************************/
4896 /* GetSummaryRefCount() */
4897 /************************************************************************/
4898
4899 /**
4900 \brief Fetch reference count of datasource and all owned layers.
4901
4902 This method is the same as the C function OGR_DS_GetSummaryRefCount().
4903
4904 In GDAL 1.X, this method used to be in the OGRDataSource class.
4905
4906 @deprecated
4907
4908 @return the current summary reference count for the datasource and its layers.
4909 */
4910
GetSummaryRefCount() const4911 int GDALDataset::GetSummaryRefCount() const
4912
4913 {
4914 CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
4915 int nSummaryCount = nRefCount;
4916 GDALDataset *poUseThis = const_cast<GDALDataset *>(this);
4917
4918 for( int iLayer = 0; iLayer < poUseThis->GetLayerCount(); ++iLayer )
4919 nSummaryCount += poUseThis->GetLayer(iLayer)->GetRefCount();
4920
4921 return nSummaryCount;
4922 }
4923
4924 /************************************************************************/
4925 /* ICreateLayer() */
4926 /************************************************************************/
4927
4928 /**
4929 \brief This method attempts to create a new layer on the dataset with the
4930 indicated name, coordinate system, geometry type.
4931
4932 This method is reserved to implementation by drivers.
4933
4934 The papszOptions argument can be used to control driver specific creation
4935 options. These options are normally documented in the format specific
4936 documentation.
4937
4938 @param pszName the name for the new layer. This should ideally not
4939 match any existing layer on the datasource.
4940 @param poSpatialRef the coordinate system to use for the new layer, or NULL if
4941 no coordinate system is available.
4942 @param eGType the geometry type for the layer. Use wkbUnknown if there
4943 are no constraints on the types geometry to be written.
4944 @param papszOptions a StringList of name=value options. Options are driver
4945 specific.
4946
4947 @return NULL is returned on failure, or a new OGRLayer handle on success.
4948
4949 @since GDAL 2.0
4950 */
4951
ICreateLayer(CPL_UNUSED const char * pszName,CPL_UNUSED OGRSpatialReference * poSpatialRef,CPL_UNUSED OGRwkbGeometryType eGType,CPL_UNUSED char ** papszOptions)4952 OGRLayer *GDALDataset::ICreateLayer( CPL_UNUSED const char * pszName,
4953 CPL_UNUSED OGRSpatialReference * poSpatialRef,
4954 CPL_UNUSED OGRwkbGeometryType eGType,
4955 CPL_UNUSED char ** papszOptions )
4956
4957 {
4958 CPLError(CE_Failure, CPLE_NotSupported,
4959 "CreateLayer() not supported by this dataset.");
4960
4961 return nullptr;
4962 }
4963
4964 /************************************************************************/
4965 /* CopyLayer() */
4966 /************************************************************************/
4967
4968 /**
4969 \brief Duplicate an existing layer.
4970
4971 This method creates a new layer, duplicate the field definitions of the
4972 source layer and then duplicate each features of the source layer.
4973 The papszOptions argument
4974 can be used to control driver specific creation options. These options are
4975 normally documented in the format specific documentation.
4976 The source layer may come from another dataset.
4977
4978 This method is the same as the C function GDALDatasetCopyLayer() and the
4979 deprecated OGR_DS_CopyLayer().
4980
4981 In GDAL 1.X, this method used to be in the OGRDataSource class.
4982
4983 @param poSrcLayer source layer.
4984 @param pszNewName the name of the layer to create.
4985 @param papszOptions a StringList of name=value options. Options are driver
4986 specific. There is a common option to set output layer
4987 spatial reference: DST_SRSWKT. The option should be in
4988 WKT format.
4989
4990 @return a handle to the layer, or NULL if an error occurs.
4991 */
4992
CopyLayer(OGRLayer * poSrcLayer,const char * pszNewName,char ** papszOptions)4993 OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
4994 const char *pszNewName,
4995 char **papszOptions )
4996
4997 {
4998 /* -------------------------------------------------------------------- */
4999 /* Create the layer. */
5000 /* -------------------------------------------------------------------- */
5001 if( !TestCapability( ODsCCreateLayer ) )
5002 {
5003 CPLError(CE_Failure, CPLE_NotSupported,
5004 "This datasource does not support creation of layers.");
5005 return nullptr;
5006 }
5007
5008 const char *pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
5009 OGRSpatialReference oDstSpaRef(pszSRSWKT);
5010 oDstSpaRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
5011 OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
5012 OGRLayer *poDstLayer = nullptr;
5013
5014 CPLErrorReset();
5015 if( poSrcDefn->GetGeomFieldCount() > 1 &&
5016 TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
5017 {
5018 poDstLayer = ICreateLayer(pszNewName, nullptr, wkbNone, papszOptions);
5019 }
5020 else
5021 {
5022 if(nullptr == pszSRSWKT)
5023 {
5024 poDstLayer = ICreateLayer(pszNewName, poSrcLayer->GetSpatialRef(),
5025 poSrcDefn->GetGeomType(), papszOptions);
5026 }
5027 else
5028 {
5029 // Remove DST_WKT from option list to prevent warning from driver.
5030 const int nSRSPos = CSLFindName(papszOptions, "DST_SRSWKT");
5031 CPLStringList aosOptionsWithoutDstSRSWKT(
5032 CSLRemoveStrings(CSLDuplicate(papszOptions), nSRSPos, 1, nullptr));
5033 poDstLayer = ICreateLayer(pszNewName, &oDstSpaRef,
5034 poSrcDefn->GetGeomType(),
5035 aosOptionsWithoutDstSRSWKT.List());
5036 }
5037 }
5038
5039 if( poDstLayer == nullptr )
5040 return nullptr;
5041
5042 /* -------------------------------------------------------------------- */
5043 /* Add fields. Default to copy all fields, and make sure to */
5044 /* establish a mapping between indices, rather than names, in */
5045 /* case the target datasource has altered it (e.g. Shapefile */
5046 /* limited to 10 char field names). */
5047 /* -------------------------------------------------------------------- */
5048 const int nSrcFieldCount = poSrcDefn->GetFieldCount();
5049
5050 // Initialize the index-to-index map to -1's.
5051 int *panMap = static_cast<int *>(CPLMalloc(sizeof(int) * nSrcFieldCount));
5052 for( int iField = 0; iField < nSrcFieldCount; ++iField )
5053 panMap[iField] = -1;
5054
5055 // Caution: At the time of writing, the MapInfo driver
5056 // returns NULL until a field has been added.
5057 OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
5058 int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
5059 for( int iField = 0; iField < nSrcFieldCount; ++iField )
5060 {
5061 OGRFieldDefn *poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
5062 OGRFieldDefn oFieldDefn(poSrcFieldDefn);
5063
5064 // The field may have been already created at layer creation.
5065 int iDstField = -1;
5066 if (poDstFDefn)
5067 iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
5068 if (iDstField >= 0)
5069 {
5070 panMap[iField] = iDstField;
5071 }
5072 else if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
5073 {
5074 // Now that we've created a field, GetLayerDefn() won't return NULL.
5075 if (poDstFDefn == nullptr)
5076 poDstFDefn = poDstLayer->GetLayerDefn();
5077
5078 // Sanity check: if it fails, the driver is buggy.
5079 if (poDstFDefn != nullptr &&
5080 poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
5081 {
5082 CPLError(CE_Warning, CPLE_AppDefined,
5083 "The output driver has claimed to have added the %s "
5084 "field, but it did not!",
5085 oFieldDefn.GetNameRef());
5086 }
5087 else
5088 {
5089 panMap[iField] = nDstFieldCount;
5090 ++nDstFieldCount;
5091 }
5092 }
5093 }
5094
5095 /* -------------------------------------------------------------------- */
5096 OGRCoordinateTransformation *poCT = nullptr;
5097 OGRSpatialReference *sourceSRS = poSrcLayer->GetSpatialRef();
5098 if (sourceSRS != nullptr && pszSRSWKT != nullptr &&
5099 sourceSRS->IsSame(&oDstSpaRef) == FALSE)
5100 {
5101 poCT = OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef);
5102 if(nullptr == poCT)
5103 {
5104 CPLError(CE_Failure, CPLE_NotSupported,
5105 "This input/output spatial reference is not supported.");
5106 CPLFree(panMap);
5107 return nullptr;
5108 }
5109 }
5110 /* -------------------------------------------------------------------- */
5111 /* Create geometry fields. */
5112 /* -------------------------------------------------------------------- */
5113 const int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
5114 if( nSrcGeomFieldCount > 1 &&
5115 TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
5116 {
5117
5118 for( int iField = 0; iField < nSrcGeomFieldCount; ++iField )
5119 {
5120 if(nullptr == pszSRSWKT)
5121 {
5122 poDstLayer->CreateGeomField(
5123 poSrcDefn->GetGeomFieldDefn(iField));
5124 }
5125 else
5126 {
5127 OGRGeomFieldDefn *pDstGeomFieldDefn =
5128 poSrcDefn->GetGeomFieldDefn(iField);
5129 pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);
5130 poDstLayer->CreateGeomField(pDstGeomFieldDefn);
5131 }
5132 }
5133 }
5134
5135 /* -------------------------------------------------------------------- */
5136 /* Check if the destination layer supports transactions and set a */
5137 /* default number of features in a single transaction. */
5138 /* -------------------------------------------------------------------- */
5139 const int nGroupTransactions =
5140 poDstLayer->TestCapability(OLCTransactions) ? 128 : 0;
5141
5142 /* -------------------------------------------------------------------- */
5143 /* Transfer features. */
5144 /* -------------------------------------------------------------------- */
5145 OGRFeature *poFeature = nullptr;
5146
5147 poSrcLayer->ResetReading();
5148
5149 if( nGroupTransactions <= 0 )
5150 {
5151 while( true )
5152 {
5153 poFeature = poSrcLayer->GetNextFeature();
5154
5155 if( poFeature == nullptr )
5156 break;
5157
5158 CPLErrorReset();
5159 OGRFeature *poDstFeature =
5160 OGRFeature::CreateFeature(poDstLayer->GetLayerDefn());
5161
5162 if( poDstFeature->SetFrom( poFeature, panMap, TRUE ) !=
5163 OGRERR_NONE )
5164 {
5165 CPLError(CE_Failure, CPLE_AppDefined,
5166 "Unable to translate feature " CPL_FRMT_GIB
5167 " from layer %s.",
5168 poFeature->GetFID(), poSrcDefn->GetName());
5169 OGRFeature::DestroyFeature(poFeature);
5170 CPLFree(panMap);
5171 if(nullptr != poCT)
5172 OCTDestroyCoordinateTransformation(
5173 OGRCoordinateTransformation::ToHandle(poCT));
5174 return poDstLayer;
5175 }
5176
5177 if(nullptr != poCT)
5178 {
5179 for( int iField = 0; iField < nSrcGeomFieldCount; ++iField )
5180 {
5181 OGRGeometry *pGeom = poDstFeature->GetGeomFieldRef(iField);
5182 if(nullptr == pGeom)
5183 continue;
5184
5185 const OGRErr eErr = pGeom->transform(poCT);
5186 if(eErr == OGRERR_NONE)
5187 continue;
5188
5189 CPLError(
5190 CE_Failure, CPLE_AppDefined,
5191 "Unable to transform geometry " CPL_FRMT_GIB
5192 " from layer %s.",
5193 poFeature->GetFID(), poSrcDefn->GetName());
5194 OGRFeature::DestroyFeature(poFeature);
5195 CPLFree(panMap);
5196 OCTDestroyCoordinateTransformation(
5197 OGRCoordinateTransformation::ToHandle(poCT));
5198 return poDstLayer;
5199 }
5200 }
5201
5202 poDstFeature->SetFID(poFeature->GetFID());
5203
5204 OGRFeature::DestroyFeature(poFeature);
5205
5206 CPLErrorReset();
5207 if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE )
5208 {
5209 OGRFeature::DestroyFeature(poDstFeature);
5210 CPLFree(panMap);
5211 if(nullptr != poCT)
5212 OCTDestroyCoordinateTransformation(
5213 OGRCoordinateTransformation::ToHandle(poCT));
5214 return poDstLayer;
5215 }
5216
5217 OGRFeature::DestroyFeature(poDstFeature);
5218 }
5219 }
5220 else
5221 {
5222 OGRFeature **papoDstFeature = static_cast<OGRFeature **>(
5223 VSI_CALLOC_VERBOSE(sizeof(OGRFeature *), nGroupTransactions));
5224
5225 bool bStopTransfer = papoDstFeature == nullptr;
5226 while( !bStopTransfer )
5227 {
5228 /* -------------------------------------------------------------------- */
5229 /* Fill the array with features. */
5230 /* -------------------------------------------------------------------- */
5231 // Number of features in the temporary array.
5232 int nFeatCount = 0; // Used after for.
5233 for( nFeatCount = 0; nFeatCount < nGroupTransactions; ++nFeatCount )
5234 {
5235 poFeature = poSrcLayer->GetNextFeature();
5236
5237 if( poFeature == nullptr )
5238 {
5239 bStopTransfer = true;
5240 break;
5241 }
5242
5243 CPLErrorReset();
5244 papoDstFeature[nFeatCount] =
5245 OGRFeature::CreateFeature(poDstLayer->GetLayerDefn());
5246
5247 if( papoDstFeature[nFeatCount]->SetFrom(poFeature, panMap,
5248 TRUE) != OGRERR_NONE )
5249 {
5250 CPLError(CE_Failure, CPLE_AppDefined,
5251 "Unable to translate feature " CPL_FRMT_GIB
5252 " from layer %s.",
5253 poFeature->GetFID(), poSrcDefn->GetName());
5254 OGRFeature::DestroyFeature( poFeature );
5255 poFeature = nullptr;
5256 bStopTransfer = true;
5257 break;
5258 }
5259
5260 if(nullptr != poCT)
5261 {
5262 for( int iField = 0; iField < nSrcGeomFieldCount; ++iField )
5263 {
5264 OGRGeometry *pGeom =
5265 papoDstFeature[nFeatCount]->GetGeomFieldRef(iField);
5266 if(nullptr == pGeom)
5267 continue;
5268
5269 const OGRErr eErr = pGeom->transform(poCT);
5270 if(eErr == OGRERR_NONE)
5271 continue;
5272
5273 CPLError(
5274 CE_Failure, CPLE_AppDefined,
5275 "Unable to transform geometry " CPL_FRMT_GIB
5276 " from layer %s.",
5277 poFeature->GetFID(), poSrcDefn->GetName());
5278 OGRFeature::DestroyFeature(poFeature);
5279 bStopTransfer = true;
5280 poFeature = nullptr;
5281 break;
5282 }
5283 }
5284
5285 if (poFeature)
5286 {
5287 papoDstFeature[nFeatCount]->SetFID(poFeature->GetFID());
5288 OGRFeature::DestroyFeature(poFeature);
5289 poFeature = nullptr;
5290 }
5291 }
5292 int nFeaturesToAdd = nFeatCount;
5293
5294 CPLErrorReset();
5295 bool bStopTransaction = false;
5296 while( !bStopTransaction )
5297 {
5298 bStopTransaction = true;
5299 if( poDstLayer->StartTransaction() != OGRERR_NONE )
5300 break;
5301 for( int i = 0; i < nFeaturesToAdd; ++i )
5302 {
5303 if( poDstLayer->CreateFeature( papoDstFeature[i] ) !=
5304 OGRERR_NONE )
5305 {
5306 nFeaturesToAdd = i;
5307 bStopTransfer = true;
5308 bStopTransaction = false;
5309 }
5310 }
5311 if( bStopTransaction )
5312 {
5313 if( poDstLayer->CommitTransaction() != OGRERR_NONE )
5314 break;
5315 }
5316 else
5317 {
5318 poDstLayer->RollbackTransaction();
5319 }
5320 }
5321
5322 for( int i = 0; i < nFeatCount; ++i )
5323 OGRFeature::DestroyFeature(papoDstFeature[i]);
5324 }
5325 CPLFree(papoDstFeature);
5326 }
5327
5328 if(nullptr != poCT)
5329 OCTDestroyCoordinateTransformation(
5330 OGRCoordinateTransformation::ToHandle(poCT));
5331
5332 CPLFree(panMap);
5333
5334 return poDstLayer;
5335 }
5336
5337 /************************************************************************/
5338 /* DeleteLayer() */
5339 /************************************************************************/
5340
5341 /**
5342 \fn GDALDataset::DeleteLayer(int)
5343 \brief Delete the indicated layer from the datasource.
5344
5345 If this method is supported
5346 the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
5347
5348 This method is the same as the C function GDALDatasetDeleteLayer() and the
5349 deprecated OGR_DS_DeleteLayer().
5350
5351 In GDAL 1.X, this method used to be in the OGRDataSource class.
5352
5353 @param iLayer the index of the layer to delete.
5354
5355 @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
5356 layers is not supported for this datasource.
5357
5358 */
5359
DeleteLayer(CPL_UNUSED int iLayer)5360 OGRErr GDALDataset::DeleteLayer( CPL_UNUSED int iLayer )
5361
5362 {
5363 CPLError(CE_Failure, CPLE_NotSupported,
5364 "DeleteLayer() not supported by this dataset.");
5365
5366 return OGRERR_UNSUPPORTED_OPERATION;
5367 }
5368
5369 /************************************************************************/
5370 /* GetLayerByName() */
5371 /************************************************************************/
5372
5373 /**
5374 \brief Fetch a layer by name.
5375
5376 The returned layer remains owned by the
5377 GDALDataset and should not be deleted by the application.
5378
5379 This method is the same as the C function GDALDatasetGetLayerByName() and the
5380 deprecated OGR_DS_GetLayerByName().
5381
5382 In GDAL 1.X, this method used to be in the OGRDataSource class.
5383
5384 @param pszName the layer name of the layer to fetch.
5385
5386 @return the layer, or NULL if Layer is not found or an error occurs.
5387 */
5388
GetLayerByName(const char * pszName)5389 OGRLayer *GDALDataset::GetLayerByName( const char *pszName )
5390
5391 {
5392 CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
5393
5394 if ( ! pszName )
5395 return nullptr;
5396
5397 // First a case sensitive check.
5398 for( int i = 0; i < GetLayerCount(); ++i )
5399 {
5400 OGRLayer *poLayer = GetLayer(i);
5401
5402 if( strcmp( pszName, poLayer->GetName() ) == 0 )
5403 return poLayer;
5404 }
5405
5406 // Then case insensitive.
5407 for( int i = 0; i < GetLayerCount(); ++i )
5408 {
5409 OGRLayer *poLayer = GetLayer(i);
5410
5411 if( EQUAL( pszName, poLayer->GetName() ) )
5412 return poLayer;
5413 }
5414
5415 return nullptr;
5416 }
5417
5418 //! @cond Doxygen_Suppress
5419 /************************************************************************/
5420 /* ProcessSQLCreateIndex() */
5421 /* */
5422 /* The correct syntax for creating an index in our dialect of */
5423 /* SQL is: */
5424 /* */
5425 /* CREATE INDEX ON <layername> USING <columnname> */
5426 /************************************************************************/
5427
ProcessSQLCreateIndex(const char * pszSQLCommand)5428 OGRErr GDALDataset::ProcessSQLCreateIndex( const char *pszSQLCommand )
5429
5430 {
5431 char **papszTokens = CSLTokenizeString(pszSQLCommand);
5432
5433 /* -------------------------------------------------------------------- */
5434 /* Do some general syntax checking. */
5435 /* -------------------------------------------------------------------- */
5436 if( CSLCount(papszTokens) != 6
5437 || !EQUAL(papszTokens[0], "CREATE")
5438 || !EQUAL(papszTokens[1], "INDEX")
5439 || !EQUAL(papszTokens[2], "ON")
5440 || !EQUAL(papszTokens[4], "USING") )
5441 {
5442 CSLDestroy(papszTokens);
5443 CPLError(CE_Failure, CPLE_AppDefined,
5444 "Syntax error in CREATE INDEX command.\n"
5445 "Was '%s'\n"
5446 "Should be of form 'CREATE INDEX ON <table> USING <field>'",
5447 pszSQLCommand);
5448 return OGRERR_FAILURE;
5449 }
5450
5451 /* -------------------------------------------------------------------- */
5452 /* Find the named layer. */
5453 /* -------------------------------------------------------------------- */
5454 OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
5455 if( poLayer == nullptr )
5456 {
5457 CPLError(CE_Failure, CPLE_AppDefined,
5458 "CREATE INDEX ON failed, no such layer as `%s'.",
5459 papszTokens[3]);
5460 CSLDestroy(papszTokens);
5461 return OGRERR_FAILURE;
5462 }
5463
5464 /* -------------------------------------------------------------------- */
5465 /* Does this layer even support attribute indexes? */
5466 /* -------------------------------------------------------------------- */
5467 if( poLayer->GetIndex() == nullptr )
5468 {
5469 CPLError(CE_Failure, CPLE_AppDefined,
5470 "CREATE INDEX ON not supported by this driver.");
5471 CSLDestroy(papszTokens);
5472 return OGRERR_FAILURE;
5473 }
5474
5475 /* -------------------------------------------------------------------- */
5476 /* Find the named field. */
5477 /* -------------------------------------------------------------------- */
5478 int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
5479
5480 CSLDestroy(papszTokens);
5481
5482 if( i >= poLayer->GetLayerDefn()->GetFieldCount() )
5483 {
5484 CPLError(CE_Failure, CPLE_AppDefined,
5485 "`%s' failed, field not found.",
5486 pszSQLCommand);
5487 return OGRERR_FAILURE;
5488 }
5489
5490 /* -------------------------------------------------------------------- */
5491 /* Attempt to create the index. */
5492 /* -------------------------------------------------------------------- */
5493 OGRErr eErr = poLayer->GetIndex()->CreateIndex(i);
5494 if( eErr == OGRERR_NONE )
5495 {
5496 eErr = poLayer->GetIndex()->IndexAllFeatures(i);
5497 }
5498 else
5499 {
5500 if( strlen(CPLGetLastErrorMsg()) == 0 )
5501 CPLError(CE_Failure, CPLE_AppDefined, "Cannot '%s'", pszSQLCommand);
5502 }
5503
5504 return eErr;
5505 }
5506
5507 /************************************************************************/
5508 /* ProcessSQLDropIndex() */
5509 /* */
5510 /* The correct syntax for dropping one or more indexes in */
5511 /* the OGR SQL dialect is: */
5512 /* */
5513 /* DROP INDEX ON <layername> [USING <columnname>] */
5514 /************************************************************************/
5515
ProcessSQLDropIndex(const char * pszSQLCommand)5516 OGRErr GDALDataset::ProcessSQLDropIndex( const char *pszSQLCommand )
5517
5518 {
5519 char **papszTokens = CSLTokenizeString(pszSQLCommand);
5520
5521 /* -------------------------------------------------------------------- */
5522 /* Do some general syntax checking. */
5523 /* -------------------------------------------------------------------- */
5524 if( (CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6)
5525 || !EQUAL(papszTokens[0], "DROP")
5526 || !EQUAL(papszTokens[1], "INDEX")
5527 || !EQUAL(papszTokens[2], "ON")
5528 || (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4], "USING")) )
5529 {
5530 CSLDestroy(papszTokens);
5531 CPLError(CE_Failure, CPLE_AppDefined,
5532 "Syntax error in DROP INDEX command.\n"
5533 "Was '%s'\n"
5534 "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
5535 pszSQLCommand);
5536 return OGRERR_FAILURE;
5537 }
5538
5539 /* -------------------------------------------------------------------- */
5540 /* Find the named layer. */
5541 /* -------------------------------------------------------------------- */
5542 OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
5543 if( poLayer == nullptr )
5544 {
5545 CPLError(CE_Failure, CPLE_AppDefined,
5546 "DROP INDEX ON failed, no such layer as `%s'.",
5547 papszTokens[3]);
5548 CSLDestroy(papszTokens);
5549 return OGRERR_FAILURE;
5550 }
5551
5552 /* -------------------------------------------------------------------- */
5553 /* Does this layer even support attribute indexes? */
5554 /* -------------------------------------------------------------------- */
5555 if( poLayer->GetIndex() == nullptr )
5556 {
5557 CPLError(CE_Failure, CPLE_AppDefined,
5558 "Indexes not supported by this driver.");
5559 CSLDestroy(papszTokens);
5560 return OGRERR_FAILURE;
5561 }
5562
5563 /* -------------------------------------------------------------------- */
5564 /* If we were not given a field name, drop all indexes. */
5565 /* -------------------------------------------------------------------- */
5566 if( CSLCount(papszTokens) == 4 )
5567 {
5568 for( int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i )
5569 {
5570 OGRAttrIndex *poAttrIndex;
5571
5572 poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
5573 if( poAttrIndex != nullptr )
5574 {
5575 const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
5576 if(eErr != OGRERR_NONE)
5577 {
5578 CSLDestroy(papszTokens);
5579 return eErr;
5580 }
5581 }
5582 }
5583
5584 CSLDestroy(papszTokens);
5585 return OGRERR_NONE;
5586 }
5587
5588 /* -------------------------------------------------------------------- */
5589 /* Find the named field. */
5590 /* -------------------------------------------------------------------- */
5591 int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
5592 CSLDestroy(papszTokens);
5593
5594 if( i >= poLayer->GetLayerDefn()->GetFieldCount() )
5595 {
5596 CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
5597 pszSQLCommand);
5598 return OGRERR_FAILURE;
5599 }
5600
5601 /* -------------------------------------------------------------------- */
5602 /* Attempt to drop the index. */
5603 /* -------------------------------------------------------------------- */
5604 const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
5605
5606 return eErr;
5607 }
5608
5609 /************************************************************************/
5610 /* ProcessSQLDropTable() */
5611 /* */
5612 /* The correct syntax for dropping a table (layer) in the OGR SQL */
5613 /* dialect is: */
5614 /* */
5615 /* DROP TABLE <layername> */
5616 /************************************************************************/
5617
ProcessSQLDropTable(const char * pszSQLCommand)5618 OGRErr GDALDataset::ProcessSQLDropTable( const char *pszSQLCommand )
5619
5620 {
5621 char **papszTokens = CSLTokenizeString(pszSQLCommand);
5622
5623 /* -------------------------------------------------------------------- */
5624 /* Do some general syntax checking. */
5625 /* -------------------------------------------------------------------- */
5626 if( CSLCount(papszTokens) != 3
5627 || !EQUAL(papszTokens[0], "DROP")
5628 || !EQUAL(papszTokens[1], "TABLE") )
5629 {
5630 CSLDestroy(papszTokens);
5631 CPLError(CE_Failure, CPLE_AppDefined,
5632 "Syntax error in DROP TABLE command.\n"
5633 "Was '%s'\n"
5634 "Should be of form 'DROP TABLE <table>'",
5635 pszSQLCommand);
5636 return OGRERR_FAILURE;
5637 }
5638
5639 /* -------------------------------------------------------------------- */
5640 /* Find the named layer. */
5641 /* -------------------------------------------------------------------- */
5642 OGRLayer *poLayer = nullptr;
5643
5644 int i = 0; // Used after for.
5645 for( ; i < GetLayerCount(); ++i )
5646 {
5647 poLayer = GetLayer(i);
5648
5649 if( poLayer!= nullptr && EQUAL(poLayer->GetName(),papszTokens[2]) )
5650 break;
5651 poLayer = nullptr;
5652 }
5653
5654 if( poLayer == nullptr )
5655 {
5656 CPLError(CE_Failure, CPLE_AppDefined,
5657 "DROP TABLE failed, no such layer as `%s'.", papszTokens[2]);
5658 CSLDestroy(papszTokens);
5659 return OGRERR_FAILURE;
5660 }
5661
5662 CSLDestroy(papszTokens);
5663
5664 /* -------------------------------------------------------------------- */
5665 /* Delete it. */
5666 /* -------------------------------------------------------------------- */
5667
5668 return DeleteLayer(i);
5669 }
5670 //! @endcond
5671
5672 /************************************************************************/
5673 /* GDALDatasetParseSQLType() */
5674 /************************************************************************/
5675
5676 /* All arguments will be altered */
GDALDatasetParseSQLType(char * pszType,int & nWidth,int & nPrecision)5677 static OGRFieldType GDALDatasetParseSQLType(char *pszType, int &nWidth,
5678 int &nPrecision)
5679 {
5680 char *pszParenthesis = strchr(pszType, '(');
5681 if (pszParenthesis)
5682 {
5683 nWidth = atoi(pszParenthesis + 1);
5684 *pszParenthesis = '\0';
5685 char *pszComma = strchr(pszParenthesis + 1, ',');
5686 if (pszComma)
5687 nPrecision = atoi(pszComma + 1);
5688 }
5689
5690 OGRFieldType eType = OFTString;
5691 if (EQUAL(pszType, "INTEGER"))
5692 eType = OFTInteger;
5693 else if (EQUAL(pszType, "INTEGER[]"))
5694 eType = OFTIntegerList;
5695 else if (EQUAL(pszType, "FLOAT") ||
5696 EQUAL(pszType, "NUMERIC") ||
5697 EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
5698 EQUAL(pszType, "REAL") /* unofficial alias */)
5699 eType = OFTReal;
5700 else if (EQUAL(pszType, "FLOAT[]") ||
5701 EQUAL(pszType, "NUMERIC[]") ||
5702 EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||
5703 EQUAL(pszType, "REAL[]") /* unofficial alias */)
5704 eType = OFTRealList;
5705 else if (EQUAL(pszType, "CHARACTER") ||
5706 EQUAL(pszType, "TEXT") /* unofficial alias */ ||
5707 EQUAL(pszType, "STRING") /* unofficial alias */ ||
5708 EQUAL(pszType, "VARCHAR") /* unofficial alias */)
5709 eType = OFTString;
5710 else if (EQUAL(pszType, "TEXT[]") ||
5711 EQUAL(pszType, "STRING[]") /* unofficial alias */||
5712 EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)
5713 eType = OFTStringList;
5714 else if (EQUAL(pszType, "DATE"))
5715 eType = OFTDate;
5716 else if (EQUAL(pszType, "TIME"))
5717 eType = OFTTime;
5718 else if (EQUAL(pszType, "TIMESTAMP") ||
5719 EQUAL(pszType, "DATETIME") /* unofficial alias */ )
5720 eType = OFTDateTime;
5721 else
5722 CPLError(CE_Warning, CPLE_NotSupported,
5723 "Unsupported column type '%s'. Defaulting to VARCHAR",
5724 pszType);
5725
5726 return eType;
5727 }
5728
5729 /************************************************************************/
5730 /* ProcessSQLAlterTableAddColumn() */
5731 /* */
5732 /* The correct syntax for adding a column in the OGR SQL */
5733 /* dialect is: */
5734 /* */
5735 /* ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype> */
5736 /************************************************************************/
5737
5738 //! @cond Doxygen_Suppress
ProcessSQLAlterTableAddColumn(const char * pszSQLCommand)5739 OGRErr GDALDataset::ProcessSQLAlterTableAddColumn( const char *pszSQLCommand )
5740
5741 {
5742 char **papszTokens = CSLTokenizeString(pszSQLCommand);
5743
5744 /* -------------------------------------------------------------------- */
5745 /* Do some general syntax checking. */
5746 /* -------------------------------------------------------------------- */
5747 const char *pszLayerName = nullptr;
5748 const char *pszColumnName = nullptr;
5749 int iTypeIndex = 0;
5750 const int nTokens = CSLCount(papszTokens);
5751
5752 if( nTokens >= 7
5753 && EQUAL(papszTokens[0], "ALTER")
5754 && EQUAL(papszTokens[1], "TABLE")
5755 && EQUAL(papszTokens[3], "ADD")
5756 && EQUAL(papszTokens[4], "COLUMN"))
5757 {
5758 pszLayerName = papszTokens[2];
5759 pszColumnName = papszTokens[5];
5760 iTypeIndex = 6;
5761 }
5762 else if( nTokens >= 6
5763 && EQUAL(papszTokens[0], "ALTER")
5764 && EQUAL(papszTokens[1], "TABLE")
5765 && EQUAL(papszTokens[3], "ADD"))
5766 {
5767 pszLayerName = papszTokens[2];
5768 pszColumnName = papszTokens[4];
5769 iTypeIndex = 5;
5770 }
5771 else
5772 {
5773 CSLDestroy(papszTokens);
5774 CPLError(CE_Failure, CPLE_AppDefined,
5775 "Syntax error in ALTER TABLE ADD COLUMN command.\n"
5776 "Was '%s'\n"
5777 "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] "
5778 "<columnname> <columntype>'",
5779 pszSQLCommand);
5780 return OGRERR_FAILURE;
5781 }
5782
5783 /* -------------------------------------------------------------------- */
5784 /* Merge type components into a single string if there were split */
5785 /* with spaces */
5786 /* -------------------------------------------------------------------- */
5787 CPLString osType;
5788 for( int i = iTypeIndex; i < nTokens; ++i )
5789 {
5790 osType += papszTokens[i];
5791 CPLFree(papszTokens[i]);
5792 }
5793 char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
5794 papszTokens[iTypeIndex + 1] = nullptr;
5795
5796 /* -------------------------------------------------------------------- */
5797 /* Find the named layer. */
5798 /* -------------------------------------------------------------------- */
5799 OGRLayer *poLayer = GetLayerByName(pszLayerName);
5800 if( poLayer == nullptr )
5801 {
5802 CPLError(CE_Failure, CPLE_AppDefined,
5803 "%s failed, no such layer as `%s'.", pszSQLCommand,
5804 pszLayerName);
5805 CSLDestroy(papszTokens);
5806 return OGRERR_FAILURE;
5807 }
5808
5809 /* -------------------------------------------------------------------- */
5810 /* Add column. */
5811 /* -------------------------------------------------------------------- */
5812
5813 int nWidth = 0;
5814 int nPrecision = 0;
5815 OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
5816 OGRFieldDefn oFieldDefn(pszColumnName, eType);
5817 oFieldDefn.SetWidth(nWidth);
5818 oFieldDefn.SetPrecision(nPrecision);
5819
5820 CSLDestroy(papszTokens);
5821
5822 return poLayer->CreateField(&oFieldDefn);
5823 }
5824
5825 /************************************************************************/
5826 /* ProcessSQLAlterTableDropColumn() */
5827 /* */
5828 /* The correct syntax for dropping a column in the OGR SQL */
5829 /* dialect is: */
5830 /* */
5831 /* ALTER TABLE <layername> DROP [COLUMN] <columnname> */
5832 /************************************************************************/
5833
ProcessSQLAlterTableDropColumn(const char * pszSQLCommand)5834 OGRErr GDALDataset::ProcessSQLAlterTableDropColumn( const char *pszSQLCommand )
5835
5836 {
5837 char **papszTokens = CSLTokenizeString(pszSQLCommand);
5838
5839 /* -------------------------------------------------------------------- */
5840 /* Do some general syntax checking. */
5841 /* -------------------------------------------------------------------- */
5842 const char *pszLayerName = nullptr;
5843 const char *pszColumnName = nullptr;
5844 if( CSLCount(papszTokens) == 6
5845 && EQUAL(papszTokens[0], "ALTER")
5846 && EQUAL(papszTokens[1], "TABLE")
5847 && EQUAL(papszTokens[3], "DROP")
5848 && EQUAL(papszTokens[4], "COLUMN"))
5849 {
5850 pszLayerName = papszTokens[2];
5851 pszColumnName = papszTokens[5];
5852 }
5853 else if( CSLCount(papszTokens) == 5
5854 && EQUAL(papszTokens[0], "ALTER")
5855 && EQUAL(papszTokens[1], "TABLE")
5856 && EQUAL(papszTokens[3], "DROP"))
5857 {
5858 pszLayerName = papszTokens[2];
5859 pszColumnName = papszTokens[4];
5860 }
5861 else
5862 {
5863 CSLDestroy(papszTokens);
5864 CPLError(CE_Failure, CPLE_AppDefined,
5865 "Syntax error in ALTER TABLE DROP COLUMN command.\n"
5866 "Was '%s'\n"
5867 "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] "
5868 "<columnname>'",
5869 pszSQLCommand);
5870 return OGRERR_FAILURE;
5871 }
5872
5873 /* -------------------------------------------------------------------- */
5874 /* Find the named layer. */
5875 /* -------------------------------------------------------------------- */
5876 OGRLayer *poLayer = GetLayerByName(pszLayerName);
5877 if( poLayer == nullptr )
5878 {
5879 CPLError(CE_Failure, CPLE_AppDefined,
5880 "%s failed, no such layer as `%s'.", pszSQLCommand,
5881 pszLayerName);
5882 CSLDestroy(papszTokens);
5883 return OGRERR_FAILURE;
5884 }
5885
5886 /* -------------------------------------------------------------------- */
5887 /* Find the field. */
5888 /* -------------------------------------------------------------------- */
5889
5890 int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
5891 if( nFieldIndex < 0 )
5892 {
5893 CPLError(CE_Failure, CPLE_AppDefined,
5894 "%s failed, no such field as `%s'.", pszSQLCommand,
5895 pszColumnName);
5896 CSLDestroy(papszTokens);
5897 return OGRERR_FAILURE;
5898 }
5899
5900 /* -------------------------------------------------------------------- */
5901 /* Remove it. */
5902 /* -------------------------------------------------------------------- */
5903
5904 CSLDestroy(papszTokens);
5905
5906 return poLayer->DeleteField(nFieldIndex);
5907 }
5908
5909 /************************************************************************/
5910 /* ProcessSQLAlterTableRenameColumn() */
5911 /* */
5912 /* The correct syntax for renaming a column in the OGR SQL */
5913 /* dialect is: */
5914 /* */
5915 /* ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
5916 /************************************************************************/
5917
5918 OGRErr
ProcessSQLAlterTableRenameColumn(const char * pszSQLCommand)5919 GDALDataset::ProcessSQLAlterTableRenameColumn( const char *pszSQLCommand )
5920
5921 {
5922 char **papszTokens = CSLTokenizeString(pszSQLCommand);
5923
5924 /* -------------------------------------------------------------------- */
5925 /* Do some general syntax checking. */
5926 /* -------------------------------------------------------------------- */
5927 const char *pszLayerName = nullptr;
5928 const char *pszOldColName = nullptr;
5929 const char *pszNewColName = nullptr;
5930 if( CSLCount(papszTokens) == 8
5931 && EQUAL(papszTokens[0], "ALTER")
5932 && EQUAL(papszTokens[1], "TABLE")
5933 && EQUAL(papszTokens[3], "RENAME")
5934 && EQUAL(papszTokens[4], "COLUMN")
5935 && EQUAL(papszTokens[6], "TO"))
5936 {
5937 pszLayerName = papszTokens[2];
5938 pszOldColName = papszTokens[5];
5939 pszNewColName = papszTokens[7];
5940 }
5941 else if( CSLCount(papszTokens) == 7
5942 && EQUAL(papszTokens[0], "ALTER")
5943 && EQUAL(papszTokens[1], "TABLE")
5944 && EQUAL(papszTokens[3], "RENAME")
5945 && EQUAL(papszTokens[5], "TO"))
5946 {
5947 pszLayerName = papszTokens[2];
5948 pszOldColName = papszTokens[4];
5949 pszNewColName = papszTokens[6];
5950 }
5951 else
5952 {
5953 CSLDestroy(papszTokens);
5954 CPLError(CE_Failure, CPLE_AppDefined,
5955 "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
5956 "Was '%s'\n"
5957 "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] "
5958 "<columnname> TO <newname>'",
5959 pszSQLCommand);
5960 return OGRERR_FAILURE;
5961 }
5962
5963 /* -------------------------------------------------------------------- */
5964 /* Find the named layer. */
5965 /* -------------------------------------------------------------------- */
5966 OGRLayer *poLayer = GetLayerByName(pszLayerName);
5967 if( poLayer == nullptr )
5968 {
5969 CPLError(CE_Failure, CPLE_AppDefined,
5970 "%s failed, no such layer as `%s'.", pszSQLCommand,
5971 pszLayerName);
5972 CSLDestroy(papszTokens);
5973 return OGRERR_FAILURE;
5974 }
5975
5976 /* -------------------------------------------------------------------- */
5977 /* Find the field. */
5978 /* -------------------------------------------------------------------- */
5979
5980 const int nFieldIndex =
5981 poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
5982 if( nFieldIndex < 0 )
5983 {
5984 CPLError(CE_Failure, CPLE_AppDefined,
5985 "%s failed, no such field as `%s'.", pszSQLCommand,
5986 pszOldColName);
5987 CSLDestroy(papszTokens);
5988 return OGRERR_FAILURE;
5989 }
5990
5991 /* -------------------------------------------------------------------- */
5992 /* Rename column. */
5993 /* -------------------------------------------------------------------- */
5994 OGRFieldDefn *poOldFieldDefn =
5995 poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
5996 OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
5997 oNewFieldDefn.SetName(pszNewColName);
5998
5999 CSLDestroy(papszTokens);
6000
6001 return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn,
6002 ALTER_NAME_FLAG);
6003 }
6004
6005 /************************************************************************/
6006 /* ProcessSQLAlterTableAlterColumn() */
6007 /* */
6008 /* The correct syntax for altering the type of a column in the */
6009 /* OGR SQL dialect is: */
6010 /* */
6011 /* ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */
6012 /************************************************************************/
6013
ProcessSQLAlterTableAlterColumn(const char * pszSQLCommand)6014 OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand )
6015
6016 {
6017 char **papszTokens = CSLTokenizeString(pszSQLCommand);
6018
6019 /* -------------------------------------------------------------------- */
6020 /* Do some general syntax checking. */
6021 /* -------------------------------------------------------------------- */
6022 const char *pszLayerName = nullptr;
6023 const char *pszColumnName = nullptr;
6024 int iTypeIndex = 0;
6025 const int nTokens = CSLCount(papszTokens);
6026
6027 if( nTokens >= 8
6028 && EQUAL(papszTokens[0], "ALTER")
6029 && EQUAL(papszTokens[1], "TABLE")
6030 && EQUAL(papszTokens[3], "ALTER")
6031 && EQUAL(papszTokens[4], "COLUMN")
6032 && EQUAL(papszTokens[6], "TYPE"))
6033 {
6034 pszLayerName = papszTokens[2];
6035 pszColumnName = papszTokens[5];
6036 iTypeIndex = 7;
6037 }
6038 else if( nTokens >= 7
6039 && EQUAL(papszTokens[0], "ALTER")
6040 && EQUAL(papszTokens[1], "TABLE")
6041 && EQUAL(papszTokens[3], "ALTER")
6042 && EQUAL(papszTokens[5], "TYPE"))
6043 {
6044 pszLayerName = papszTokens[2];
6045 pszColumnName = papszTokens[4];
6046 iTypeIndex = 6;
6047 }
6048 else
6049 {
6050 CSLDestroy(papszTokens);
6051 CPLError(CE_Failure, CPLE_AppDefined,
6052 "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
6053 "Was '%s'\n"
6054 "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] "
6055 "<columnname> TYPE <columntype>'",
6056 pszSQLCommand);
6057 return OGRERR_FAILURE;
6058 }
6059
6060 /* -------------------------------------------------------------------- */
6061 /* Merge type components into a single string if there were split */
6062 /* with spaces */
6063 /* -------------------------------------------------------------------- */
6064 CPLString osType;
6065 for( int i = iTypeIndex; i < nTokens; ++i )
6066 {
6067 osType += papszTokens[i];
6068 CPLFree(papszTokens[i]);
6069 }
6070 char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6071 papszTokens[iTypeIndex + 1] = nullptr;
6072
6073 /* -------------------------------------------------------------------- */
6074 /* Find the named layer. */
6075 /* -------------------------------------------------------------------- */
6076 OGRLayer *poLayer = GetLayerByName(pszLayerName);
6077 if( poLayer == nullptr )
6078 {
6079 CPLError(CE_Failure, CPLE_AppDefined,
6080 "%s failed, no such layer as `%s'.", pszSQLCommand,
6081 pszLayerName);
6082 CSLDestroy(papszTokens);
6083 return OGRERR_FAILURE;
6084 }
6085
6086 /* -------------------------------------------------------------------- */
6087 /* Find the field. */
6088 /* -------------------------------------------------------------------- */
6089
6090 const int nFieldIndex =
6091 poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6092 if( nFieldIndex < 0 )
6093 {
6094 CPLError(CE_Failure, CPLE_AppDefined,
6095 "%s failed, no such field as `%s'.", pszSQLCommand,
6096 pszColumnName);
6097 CSLDestroy(papszTokens);
6098 return OGRERR_FAILURE;
6099 }
6100
6101 /* -------------------------------------------------------------------- */
6102 /* Alter column. */
6103 /* -------------------------------------------------------------------- */
6104
6105 OGRFieldDefn *poOldFieldDefn =
6106 poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6107 OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6108
6109 int nWidth = 0;
6110 int nPrecision = 0;
6111 OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6112 oNewFieldDefn.SetType(eType);
6113 oNewFieldDefn.SetWidth(nWidth);
6114 oNewFieldDefn.SetPrecision(nPrecision);
6115
6116 int l_nFlags = 0;
6117 if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
6118 l_nFlags |= ALTER_TYPE_FLAG;
6119 if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
6120 poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
6121 l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;
6122
6123 CSLDestroy(papszTokens);
6124
6125 if (l_nFlags == 0)
6126 return OGRERR_NONE;
6127
6128 return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn, l_nFlags);
6129 }
6130 //! @endcond
6131
6132 /************************************************************************/
6133 /* ExecuteSQL() */
6134 /************************************************************************/
6135
6136 /**
6137 \brief Execute an SQL statement against the data store.
6138
6139 The result of an SQL query is either NULL for statements that are in error,
6140 or that have no results set, or an OGRLayer pointer representing a results
6141 set from the query. Note that this OGRLayer is in addition to the layers
6142 in the data store and must be destroyed with
6143 ReleaseResultSet() before the dataset is closed
6144 (destroyed).
6145
6146 This method is the same as the C function GDALDatasetExecuteSQL() and the
6147 deprecated OGR_DS_ExecuteSQL().
6148
6149 For more information on the SQL dialect supported internally by OGR
6150 review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a> document. Some drivers (i.e.
6151 Oracle and PostGIS) pass the SQL directly through to the underlying RDBMS.
6152
6153 Starting with OGR 1.10, the <a href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a>
6154 can also be used.
6155
6156 In GDAL 1.X, this method used to be in the OGRDataSource class.
6157
6158 @param pszStatement the SQL statement to execute.
6159 @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.
6160 @param pszDialect allows control of the statement dialect. If set to NULL, the
6161 OGR SQL engine will be used, except for RDBMS drivers that will use their
6162 dedicated SQL engine, unless OGRSQL is explicitly passed as the
6163 dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
6164
6165 @return an OGRLayer containing the results of the query. Deallocate with
6166 ReleaseResultSet().
6167
6168 */
6169
ExecuteSQL(const char * pszStatement,OGRGeometry * poSpatialFilter,const char * pszDialect)6170 OGRLayer *GDALDataset::ExecuteSQL( const char *pszStatement,
6171 OGRGeometry *poSpatialFilter,
6172 const char *pszDialect )
6173
6174 {
6175 return ExecuteSQL(pszStatement, poSpatialFilter, pszDialect, nullptr);
6176 }
6177
6178 //! @cond Doxygen_Suppress
6179 OGRLayer *
ExecuteSQL(const char * pszStatement,OGRGeometry * poSpatialFilter,const char * pszDialect,swq_select_parse_options * poSelectParseOptions)6180 GDALDataset::ExecuteSQL( const char *pszStatement,
6181 OGRGeometry *poSpatialFilter,
6182 const char *pszDialect,
6183 swq_select_parse_options *poSelectParseOptions )
6184
6185 {
6186 if( pszDialect != nullptr && EQUAL(pszDialect, "SQLite") )
6187 {
6188 #ifdef SQLITE_ENABLED
6189 return OGRSQLiteExecuteSQL(this, pszStatement, poSpatialFilter,
6190 pszDialect);
6191 #else
6192 CPLError(CE_Failure, CPLE_NotSupported,
6193 "The SQLite driver needs to be compiled to support the "
6194 "SQLite SQL dialect");
6195 return nullptr;
6196 #endif
6197 }
6198
6199 /* -------------------------------------------------------------------- */
6200 /* Handle CREATE INDEX statements specially. */
6201 /* -------------------------------------------------------------------- */
6202 if( STARTS_WITH_CI(pszStatement, "CREATE INDEX") )
6203 {
6204 ProcessSQLCreateIndex(pszStatement);
6205 return nullptr;
6206 }
6207
6208 /* -------------------------------------------------------------------- */
6209 /* Handle DROP INDEX statements specially. */
6210 /* -------------------------------------------------------------------- */
6211 if( STARTS_WITH_CI(pszStatement, "DROP INDEX") )
6212 {
6213 ProcessSQLDropIndex(pszStatement);
6214 return nullptr;
6215 }
6216
6217 /* -------------------------------------------------------------------- */
6218 /* Handle DROP TABLE statements specially. */
6219 /* -------------------------------------------------------------------- */
6220 if( STARTS_WITH_CI(pszStatement, "DROP TABLE") )
6221 {
6222 ProcessSQLDropTable(pszStatement);
6223 return nullptr;
6224 }
6225
6226 /* -------------------------------------------------------------------- */
6227 /* Handle ALTER TABLE statements specially. */
6228 /* -------------------------------------------------------------------- */
6229 if( STARTS_WITH_CI(pszStatement, "ALTER TABLE") )
6230 {
6231 char **papszTokens = CSLTokenizeString(pszStatement);
6232 const int nTokens = CSLCount(papszTokens);
6233 if( nTokens >= 4 && EQUAL(papszTokens[3], "ADD") )
6234 {
6235 ProcessSQLAlterTableAddColumn(pszStatement);
6236 CSLDestroy(papszTokens);
6237 return nullptr;
6238 }
6239 else if( nTokens >= 4 && EQUAL(papszTokens[3], "DROP") )
6240 {
6241 ProcessSQLAlterTableDropColumn( pszStatement );
6242 CSLDestroy(papszTokens);
6243 return nullptr;
6244 }
6245 else if( nTokens >= 4 && EQUAL(papszTokens[3], "RENAME") )
6246 {
6247 ProcessSQLAlterTableRenameColumn(pszStatement);
6248 CSLDestroy(papszTokens);
6249 return nullptr;
6250 }
6251 else if( nTokens >= 4 && EQUAL(papszTokens[3], "ALTER") )
6252 {
6253 ProcessSQLAlterTableAlterColumn(pszStatement);
6254 CSLDestroy(papszTokens);
6255 return nullptr;
6256 }
6257 else
6258 {
6259 CPLError(CE_Failure, CPLE_AppDefined,
6260 "Unsupported ALTER TABLE command : %s", pszStatement);
6261 CSLDestroy(papszTokens);
6262 return nullptr;
6263 }
6264 }
6265
6266 /* -------------------------------------------------------------------- */
6267 /* Preparse the SQL statement. */
6268 /* -------------------------------------------------------------------- */
6269 swq_select *psSelectInfo = new swq_select();
6270 swq_custom_func_registrar *poCustomFuncRegistrar = nullptr;
6271 if( poSelectParseOptions != nullptr )
6272 poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;
6273 if( psSelectInfo->preparse( pszStatement,
6274 poCustomFuncRegistrar != nullptr ) != CE_None )
6275 {
6276 delete psSelectInfo;
6277 return nullptr;
6278 }
6279
6280 /* -------------------------------------------------------------------- */
6281 /* If there is no UNION ALL, build result layer. */
6282 /* -------------------------------------------------------------------- */
6283 if( psSelectInfo->poOtherSelect == nullptr )
6284 {
6285 return BuildLayerFromSelectInfo(psSelectInfo, poSpatialFilter,
6286 pszDialect, poSelectParseOptions);
6287 }
6288
6289 /* -------------------------------------------------------------------- */
6290 /* Build result union layer. */
6291 /* -------------------------------------------------------------------- */
6292 int nSrcLayers = 0;
6293 OGRLayer **papoSrcLayers = nullptr;
6294
6295 do
6296 {
6297 swq_select *psNextSelectInfo = psSelectInfo->poOtherSelect;
6298 psSelectInfo->poOtherSelect = nullptr;
6299
6300 OGRLayer *poLayer = BuildLayerFromSelectInfo(
6301 psSelectInfo, poSpatialFilter, pszDialect, poSelectParseOptions);
6302 if( poLayer == nullptr )
6303 {
6304 // Each source layer owns an independent select info.
6305 for( int i = 0; i < nSrcLayers; ++i )
6306 delete papoSrcLayers[i];
6307 CPLFree(papoSrcLayers);
6308
6309 // So we just have to destroy the remaining select info.
6310 delete psNextSelectInfo;
6311
6312 return nullptr;
6313 }
6314 else
6315 {
6316 papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(
6317 papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));
6318 papoSrcLayers[nSrcLayers] = poLayer;
6319 ++nSrcLayers;
6320
6321 psSelectInfo = psNextSelectInfo;
6322 }
6323 }
6324 while( psSelectInfo != nullptr );
6325
6326 return new OGRUnionLayer("SELECT", nSrcLayers, papoSrcLayers, TRUE);
6327 }
6328 //! @endcond
6329
6330
6331 /************************************************************************/
6332 /* AbortSQL() */
6333 /************************************************************************/
6334
6335 /**
6336 \brief Abort any SQL statement running in the data store.
6337
6338 This function can be safely called from any thread (pending that the dataset object is still alive). Driver implementations will make sure that it can be called in a thread-safe way.
6339
6340 This might not be implemented by all drivers. At time of writing, only SQLite, GPKG and PG drivers implement it
6341
6342 This method is the same as the C method GDALDatasetAbortSQL()
6343
6344 @since GDAL 3.2.0
6345
6346
6347 */
6348
AbortSQL()6349 OGRErr GDALDataset::AbortSQL( )
6350 {
6351 CPLError(CE_Failure, CPLE_NotSupported, "AbortSQL is not supported for this driver.");
6352 return OGRERR_UNSUPPORTED_OPERATION;
6353 }
6354
6355
6356 /************************************************************************/
6357 /* BuildLayerFromSelectInfo() */
6358 /************************************************************************/
6359
6360 struct GDALSQLParseInfo
6361 {
6362 swq_field_list sFieldList;
6363 int nExtraDSCount;
6364 GDALDataset **papoExtraDS;
6365 char *pszWHERE;
6366 };
6367
BuildLayerFromSelectInfo(swq_select * psSelectInfo,OGRGeometry * poSpatialFilter,const char * pszDialect,swq_select_parse_options * poSelectParseOptions)6368 OGRLayer *GDALDataset::BuildLayerFromSelectInfo(
6369 swq_select *psSelectInfo, OGRGeometry *poSpatialFilter,
6370 const char *pszDialect, swq_select_parse_options *poSelectParseOptions)
6371 {
6372 OGRGenSQLResultsLayer *poResults = nullptr;
6373 GDALSQLParseInfo *psParseInfo =
6374 BuildParseInfo(psSelectInfo, poSelectParseOptions);
6375
6376 if( psParseInfo )
6377 {
6378 poResults =
6379 new OGRGenSQLResultsLayer(this, psSelectInfo, poSpatialFilter,
6380 psParseInfo->pszWHERE, pszDialect);
6381 }
6382 else
6383 {
6384 delete psSelectInfo;
6385 }
6386 DestroyParseInfo(psParseInfo);
6387
6388 return poResults;
6389 }
6390
6391 /************************************************************************/
6392 /* DestroyParseInfo() */
6393 /************************************************************************/
6394
6395 //! @cond Doxygen_Suppress
DestroyParseInfo(GDALSQLParseInfo * psParseInfo)6396 void GDALDataset::DestroyParseInfo(GDALSQLParseInfo *psParseInfo)
6397 {
6398 if( psParseInfo == nullptr )
6399 return;
6400
6401 CPLFree(psParseInfo->sFieldList.names);
6402 CPLFree(psParseInfo->sFieldList.types);
6403 CPLFree(psParseInfo->sFieldList.table_ids);
6404 CPLFree(psParseInfo->sFieldList.ids);
6405
6406 // Release the datasets we have opened with OGROpenShared()
6407 // It is safe to do that as the 'new OGRGenSQLResultsLayer' itself
6408 // has taken a reference on them, which it will release in its
6409 // destructor.
6410 for( int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; ++iEDS )
6411 GDALClose(psParseInfo->papoExtraDS[iEDS]);
6412
6413 CPLFree(psParseInfo->papoExtraDS);
6414 CPLFree(psParseInfo->pszWHERE);
6415 CPLFree(psParseInfo);
6416 }
6417
6418 /************************************************************************/
6419 /* BuildParseInfo() */
6420 /************************************************************************/
6421
6422 GDALSQLParseInfo *
BuildParseInfo(swq_select * psSelectInfo,swq_select_parse_options * poSelectParseOptions)6423 GDALDataset::BuildParseInfo(swq_select *psSelectInfo,
6424 swq_select_parse_options *poSelectParseOptions)
6425 {
6426 int nFirstLayerFirstSpecialFieldIndex = 0;
6427
6428 GDALSQLParseInfo *psParseInfo =
6429 static_cast<GDALSQLParseInfo *>(CPLCalloc(1, sizeof(GDALSQLParseInfo)));
6430
6431 /* -------------------------------------------------------------------- */
6432 /* Validate that all the source tables are recognized, count */
6433 /* fields. */
6434 /* -------------------------------------------------------------------- */
6435 int nFieldCount = 0;
6436
6437 for( int iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
6438 {
6439 swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
6440 GDALDataset *poTableDS = this;
6441
6442 if( psTableDef->data_source != nullptr )
6443 {
6444 poTableDS = GDALDataset::FromHandle(
6445 OGROpenShared(psTableDef->data_source, FALSE, nullptr));
6446 if( poTableDS == nullptr )
6447 {
6448 if( strlen(CPLGetLastErrorMsg()) == 0 )
6449 CPLError(CE_Failure, CPLE_AppDefined,
6450 "Unable to open secondary datasource "
6451 "`%s' required by JOIN.",
6452 psTableDef->data_source);
6453
6454 DestroyParseInfo(psParseInfo);
6455 return nullptr;
6456 }
6457
6458 // Keep in an array to release at the end of this function.
6459 psParseInfo->papoExtraDS = static_cast<GDALDataset **>(CPLRealloc(
6460 psParseInfo->papoExtraDS,
6461 sizeof(GDALDataset *) * (psParseInfo->nExtraDSCount + 1)));
6462 psParseInfo->papoExtraDS[psParseInfo->nExtraDSCount++] = poTableDS;
6463 }
6464
6465 OGRLayer *poSrcLayer =
6466 poTableDS->GetLayerByName(psTableDef->table_name);
6467
6468 if( poSrcLayer == nullptr )
6469 {
6470 CPLError(CE_Failure, CPLE_AppDefined,
6471 "SELECT from table %s failed, no such table/featureclass.",
6472 psTableDef->table_name);
6473
6474 DestroyParseInfo(psParseInfo);
6475 return nullptr;
6476 }
6477
6478 nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
6479 if( iTable == 0 ||
6480 (poSelectParseOptions &&
6481 poSelectParseOptions->bAddSecondaryTablesGeometryFields) )
6482 nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
6483
6484 const char* pszFID = poSrcLayer->GetFIDColumn();
6485 if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
6486 poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
6487 nFieldCount++;
6488 }
6489
6490 /* -------------------------------------------------------------------- */
6491 /* Build the field list for all indicated tables. */
6492 /* -------------------------------------------------------------------- */
6493
6494 psParseInfo->sFieldList.table_count = psSelectInfo->table_count;
6495 psParseInfo->sFieldList.table_defs = psSelectInfo->table_defs;
6496
6497 psParseInfo->sFieldList.count = 0;
6498 psParseInfo->sFieldList.names = static_cast<char **>(
6499 CPLMalloc(sizeof(char *) * (nFieldCount + SPECIAL_FIELD_COUNT)));
6500 psParseInfo->sFieldList.types = static_cast<swq_field_type *>(CPLMalloc(
6501 sizeof(swq_field_type) * (nFieldCount + SPECIAL_FIELD_COUNT)));
6502 psParseInfo->sFieldList.table_ids = static_cast<int *>(
6503 CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
6504 psParseInfo->sFieldList.ids = static_cast<int *>(
6505 CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
6506
6507 bool bIsFID64 = false;
6508 for( int iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
6509 {
6510 swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
6511 GDALDataset *poTableDS = this;
6512
6513 if( psTableDef->data_source != nullptr )
6514 {
6515 poTableDS = GDALDataset::FromHandle(
6516 OGROpenShared(psTableDef->data_source, FALSE, nullptr));
6517 CPLAssert(poTableDS != nullptr);
6518 poTableDS->Dereference();
6519 }
6520
6521 OGRLayer *poSrcLayer =
6522 poTableDS->GetLayerByName(psTableDef->table_name);
6523
6524 for( int iField = 0;
6525 iField < poSrcLayer->GetLayerDefn()->GetFieldCount();
6526 iField++ )
6527 {
6528 OGRFieldDefn *poFDefn =
6529 poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
6530 const int iOutField = psParseInfo->sFieldList.count++;
6531 psParseInfo->sFieldList.names[iOutField] =
6532 const_cast<char *>(poFDefn->GetNameRef());
6533 if( poFDefn->GetType() == OFTInteger )
6534 {
6535 if( poFDefn->GetSubType() == OFSTBoolean )
6536 psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
6537 else
6538 psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
6539 }
6540 else if( poFDefn->GetType() == OFTInteger64 )
6541 {
6542 if( poFDefn->GetSubType() == OFSTBoolean )
6543 psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
6544 else
6545 psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
6546 }
6547 else if( poFDefn->GetType() == OFTReal )
6548 psParseInfo->sFieldList.types[iOutField] = SWQ_FLOAT;
6549 else if( poFDefn->GetType() == OFTString )
6550 psParseInfo->sFieldList.types[iOutField] = SWQ_STRING;
6551 else if( poFDefn->GetType() == OFTTime )
6552 psParseInfo->sFieldList.types[iOutField] = SWQ_TIME;
6553 else if( poFDefn->GetType() == OFTDate )
6554 psParseInfo->sFieldList.types[iOutField] = SWQ_DATE;
6555 else if( poFDefn->GetType() == OFTDateTime )
6556 psParseInfo->sFieldList.types[iOutField] = SWQ_TIMESTAMP;
6557 else
6558 psParseInfo->sFieldList.types[iOutField] = SWQ_OTHER;
6559
6560 psParseInfo->sFieldList.table_ids[iOutField] = iTable;
6561 psParseInfo->sFieldList.ids[iOutField] = iField;
6562 }
6563
6564 if( iTable == 0 )
6565 {
6566 nFirstLayerFirstSpecialFieldIndex = psParseInfo->sFieldList.count;
6567 }
6568
6569 if( iTable == 0 ||
6570 (poSelectParseOptions &&
6571 poSelectParseOptions->bAddSecondaryTablesGeometryFields) )
6572 {
6573
6574 for( int iField = 0;
6575 iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
6576 iField++ )
6577 {
6578 OGRGeomFieldDefn *poFDefn =
6579 poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
6580 const int iOutField = psParseInfo->sFieldList.count++;
6581 psParseInfo->sFieldList.names[iOutField] =
6582 const_cast<char *>(poFDefn->GetNameRef());
6583 if( *psParseInfo->sFieldList.names[iOutField] == '\0' )
6584 psParseInfo->sFieldList.names[iOutField] =
6585 const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
6586 psParseInfo->sFieldList.types[iOutField] = SWQ_GEOMETRY;
6587
6588 psParseInfo->sFieldList.table_ids[iOutField] = iTable;
6589 psParseInfo->sFieldList.ids[iOutField] =
6590 GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(
6591 poSrcLayer->GetLayerDefn(), iField);
6592 }
6593 }
6594
6595 if( iTable == 0 && poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
6596 EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES") )
6597 {
6598 bIsFID64 = true;
6599 }
6600 }
6601
6602 /* -------------------------------------------------------------------- */
6603 /* Expand '*' in 'SELECT *' now before we add the pseudo fields */
6604 /* -------------------------------------------------------------------- */
6605 const bool bAlwaysPrefixWithTableName =
6606 poSelectParseOptions &&
6607 poSelectParseOptions->bAlwaysPrefixWithTableName;
6608 if( psSelectInfo->expand_wildcard(&psParseInfo->sFieldList,
6609 bAlwaysPrefixWithTableName) != CE_None )
6610 {
6611 DestroyParseInfo(psParseInfo);
6612 return nullptr;
6613 }
6614
6615 for (int iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
6616 {
6617 psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] =
6618 const_cast<char *>(SpecialFieldNames[iField]);
6619 psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] =
6620 (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64
6621 : SpecialFieldTypes[iField];
6622 psParseInfo->sFieldList.table_ids[psParseInfo->sFieldList.count] = 0;
6623 psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] =
6624 nFirstLayerFirstSpecialFieldIndex + iField;
6625 psParseInfo->sFieldList.count++;
6626 }
6627
6628 /* In the case a layer has an explicit FID column name, then add it */
6629 /* so it can be selected */
6630 for( int iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
6631 {
6632 swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
6633 GDALDataset *poTableDS = this;
6634
6635 if( psTableDef->data_source != nullptr )
6636 {
6637 poTableDS = GDALDataset::FromHandle(
6638 OGROpenShared(psTableDef->data_source, FALSE, nullptr));
6639 CPLAssert(poTableDS != nullptr);
6640 poTableDS->Dereference();
6641 }
6642
6643 OGRLayer *poSrcLayer =
6644 poTableDS->GetLayerByName(psTableDef->table_name);
6645
6646 const char* pszFID = poSrcLayer->GetFIDColumn();
6647 if( pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
6648 poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0 )
6649 {
6650 const int iOutField = psParseInfo->sFieldList.count++;
6651 psParseInfo->sFieldList.names[iOutField] =
6652 const_cast<char*>(pszFID);
6653 if( poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
6654 EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES") )
6655 {
6656 psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
6657 }
6658 else
6659 {
6660 psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
6661 }
6662 psParseInfo->sFieldList.table_ids[iOutField] = iTable;
6663 psParseInfo->sFieldList.ids[iOutField] =
6664 poSrcLayer->GetLayerDefn()->GetFieldCount() + SPF_FID;
6665 }
6666 }
6667
6668 /* -------------------------------------------------------------------- */
6669 /* Finish the parse operation. */
6670 /* -------------------------------------------------------------------- */
6671 if( psSelectInfo->parse(&psParseInfo->sFieldList, poSelectParseOptions) !=
6672 CE_None )
6673 {
6674 DestroyParseInfo(psParseInfo);
6675 return nullptr;
6676 }
6677
6678 /* -------------------------------------------------------------------- */
6679 /* Extract the WHERE expression to use separately. */
6680 /* -------------------------------------------------------------------- */
6681 if( psSelectInfo->where_expr != nullptr )
6682 {
6683 psParseInfo->pszWHERE =
6684 psSelectInfo->where_expr->Unparse(&psParseInfo->sFieldList, '"');
6685 // CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
6686 }
6687
6688 return psParseInfo;
6689 }
6690 //! @endcond
6691
6692 /************************************************************************/
6693 /* ReleaseResultSet() */
6694 /************************************************************************/
6695
6696 /**
6697 \brief Release results of ExecuteSQL().
6698
6699 This method should only be used to deallocate OGRLayers resulting from
6700 an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
6701 results set before destroying the GDALDataset may cause errors.
6702
6703 This method is the same as the C function GDALDatasetReleaseResultSet() and the
6704 deprecated OGR_DS_ReleaseResultSet().
6705
6706 In GDAL 1.X, this method used to be in the OGRDataSource class.
6707
6708 @param poResultsSet the result of a previous ExecuteSQL() call.
6709 */
6710
ReleaseResultSet(OGRLayer * poResultsSet)6711 void GDALDataset::ReleaseResultSet( OGRLayer *poResultsSet )
6712
6713 {
6714 delete poResultsSet;
6715 }
6716
6717 /************************************************************************/
6718 /* GetStyleTable() */
6719 /************************************************************************/
6720
6721 /**
6722 \brief Returns dataset style table.
6723
6724 This method is the same as the C function GDALDatasetGetStyleTable() and the
6725 deprecated OGR_DS_GetStyleTable().
6726
6727 In GDAL 1.X, this method used to be in the OGRDataSource class.
6728
6729 @return pointer to a style table which should not be modified or freed by the
6730 caller.
6731 */
6732
GetStyleTable()6733 OGRStyleTable *GDALDataset::GetStyleTable() { return m_poStyleTable; }
6734
6735 /************************************************************************/
6736 /* SetStyleTableDirectly() */
6737 /************************************************************************/
6738
6739 /**
6740 \brief Set dataset style table.
6741
6742 This method operate exactly as SetStyleTable() except that it
6743 assumes ownership of the passed table.
6744
6745 This method is the same as the C function GDALDatasetSetStyleTableDirectly()
6746 and the deprecated OGR_DS_SetStyleTableDirectly().
6747
6748 In GDAL 1.X, this method used to be in the OGRDataSource class.
6749
6750 @param poStyleTable pointer to style table to set
6751
6752 */
SetStyleTableDirectly(OGRStyleTable * poStyleTable)6753 void GDALDataset::SetStyleTableDirectly( OGRStyleTable *poStyleTable )
6754 {
6755 if ( m_poStyleTable )
6756 delete m_poStyleTable;
6757 m_poStyleTable = poStyleTable;
6758 }
6759
6760 /************************************************************************/
6761 /* SetStyleTable() */
6762 /************************************************************************/
6763
6764 /**
6765 \brief Set dataset style table.
6766
6767 This method operate exactly as SetStyleTableDirectly() except
6768 that it does not assume ownership of the passed table.
6769
6770 This method is the same as the C function GDALDatasetSetStyleTable() and the
6771 deprecated OGR_DS_SetStyleTable().
6772
6773 In GDAL 1.X, this method used to be in the OGRDataSource class.
6774
6775 @param poStyleTable pointer to style table to set
6776
6777 */
6778
SetStyleTable(OGRStyleTable * poStyleTable)6779 void GDALDataset::SetStyleTable(OGRStyleTable *poStyleTable)
6780 {
6781 if ( m_poStyleTable )
6782 delete m_poStyleTable;
6783 if ( poStyleTable )
6784 m_poStyleTable = poStyleTable->Clone();
6785 }
6786
6787 /************************************************************************/
6788 /* IsGenericSQLDialect() */
6789 /************************************************************************/
6790
6791 //! @cond Doxygen_Suppress
IsGenericSQLDialect(const char * pszDialect)6792 int GDALDataset::IsGenericSQLDialect(const char *pszDialect)
6793 {
6794 return pszDialect != nullptr &&
6795 (EQUAL(pszDialect, "OGRSQL") || EQUAL(pszDialect, "SQLITE"));
6796 }
6797 //! @endcond
6798
6799 /************************************************************************/
6800 /* GetLayerCount() */
6801 /************************************************************************/
6802
6803 /**
6804 \brief Get the number of layers in this dataset.
6805
6806 This method is the same as the C function GDALDatasetGetLayerCount(),
6807 and the deprecated OGR_DS_GetLayerCount().
6808
6809 In GDAL 1.X, this method used to be in the OGRDataSource class.
6810
6811 @return layer count.
6812 */
6813
GetLayerCount()6814 int GDALDataset::GetLayerCount() { return 0; }
6815
6816 /************************************************************************/
6817 /* GetLayer() */
6818 /************************************************************************/
6819
6820 /**
6821 \fn GDALDataset::GetLayer(int)
6822 \brief Fetch a layer by index.
6823
6824 The returned layer remains owned by the
6825 GDALDataset and should not be deleted by the application.
6826
6827 See GetLayers() for a C++ iterator version of this method.
6828
6829 This method is the same as the C function GDALDatasetGetLayer() and the
6830 deprecated OGR_DS_GetLayer().
6831
6832 In GDAL 1.X, this method used to be in the OGRDataSource class.
6833
6834 @param iLayer a layer number between 0 and GetLayerCount()-1.
6835
6836 @return the layer, or NULL if iLayer is out of range or an error occurs.
6837
6838 @see GetLayers()
6839 */
6840
GetLayer(CPL_UNUSED int iLayer)6841 OGRLayer *GDALDataset::GetLayer(CPL_UNUSED int iLayer) { return nullptr; }
6842
6843 /************************************************************************/
6844 /* ResetReading() */
6845 /************************************************************************/
6846
6847 /**
6848 \brief Reset feature reading to start on the first feature.
6849
6850 This affects GetNextFeature().
6851
6852 Depending on drivers, this may also have the side effect of calling
6853 OGRLayer::ResetReading() on the layers of this dataset.
6854
6855 This method is the same as the C function GDALDatasetResetReading().
6856
6857 @since GDAL 2.2
6858 */
ResetReading()6859 void GDALDataset::ResetReading()
6860 {
6861 if( !m_poPrivate )
6862 return;
6863 m_poPrivate->nCurrentLayerIdx = 0;
6864 m_poPrivate->nLayerCount = -1;
6865 m_poPrivate->poCurrentLayer = nullptr;
6866 m_poPrivate->nFeatureReadInLayer = 0;
6867 m_poPrivate->nFeatureReadInDataset = 0;
6868 m_poPrivate->nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
6869 m_poPrivate->nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
6870 }
6871
6872 /************************************************************************/
6873 /* GDALDatasetResetReading() */
6874 /************************************************************************/
6875
6876 /**
6877 \brief Reset feature reading to start on the first feature.
6878
6879 This affects GDALDatasetGetNextFeature().
6880
6881 Depending on drivers, this may also have the side effect of calling
6882 OGR_L_ResetReading() on the layers of this dataset.
6883
6884 This method is the same as the C++ method GDALDataset::ResetReading()
6885
6886 @param hDS dataset handle
6887 @since GDAL 2.2
6888 */
GDALDatasetResetReading(GDALDatasetH hDS)6889 void CPL_DLL GDALDatasetResetReading( GDALDatasetH hDS )
6890 {
6891 VALIDATE_POINTER0(hDS, "GDALDatasetResetReading");
6892
6893 return GDALDataset::FromHandle(hDS)->ResetReading();
6894 }
6895
6896 /************************************************************************/
6897 /* GetNextFeature() */
6898 /************************************************************************/
6899
6900 /**
6901 \brief Fetch the next available feature from this dataset.
6902
6903 This method is intended for the few drivers where OGRLayer::GetNextFeature()
6904 is not efficient, but in general OGRLayer::GetNextFeature() is a more
6905 natural API.
6906
6907 See GetFeatures() for a C++ iterator version of this method.
6908
6909 The returned feature becomes the responsibility of the caller to
6910 delete with OGRFeature::DestroyFeature().
6911
6912 Depending on the driver, this method may return features from layers in a
6913 non sequential way. This is what may happen when the
6914 ODsCRandomLayerRead capability is declared (for example for the
6915 OSM and GMLAS drivers). When datasets declare this capability, it is strongly
6916 advised to use GDALDataset::GetNextFeature() instead of
6917 OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
6918 implementation.
6919
6920 The default implementation, used by most drivers, will
6921 however iterate over each layer, and then over each feature within this
6922 layer.
6923
6924 This method takes into account spatial and attribute filters set on layers that
6925 will be iterated upon.
6926
6927 The ResetReading() method can be used to start at the beginning again.
6928
6929 Depending on drivers, this may also have the side effect of calling
6930 OGRLayer::GetNextFeature() on the layers of this dataset.
6931
6932 This method is the same as the C function GDALDatasetGetNextFeature().
6933
6934 @param ppoBelongingLayer a pointer to a OGRLayer* variable to receive the
6935 layer to which the object belongs to, or NULL.
6936 It is possible that the output of *ppoBelongingLayer
6937 to be NULL despite the feature not being NULL.
6938 @param pdfProgressPct a pointer to a double variable to receive the
6939 percentage progress (in [0,1] range), or NULL.
6940 On return, the pointed value might be negative if
6941 determining the progress is not possible.
6942 @param pfnProgress a progress callback to report progress (for
6943 GetNextFeature() calls that might have a long
6944 duration) and offer cancellation possibility, or NULL.
6945 @param pProgressData user data provided to pfnProgress, or NULL
6946 @return a feature, or NULL if no more features are available.
6947 @since GDAL 2.2
6948 @see GetFeatures()
6949 */
6950
GetNextFeature(OGRLayer ** ppoBelongingLayer,double * pdfProgressPct,GDALProgressFunc pfnProgress,void * pProgressData)6951 OGRFeature *GDALDataset::GetNextFeature( OGRLayer **ppoBelongingLayer,
6952 double *pdfProgressPct,
6953 GDALProgressFunc pfnProgress,
6954 void *pProgressData )
6955 {
6956 if( !m_poPrivate || m_poPrivate->nCurrentLayerIdx < 0 )
6957 {
6958 if( ppoBelongingLayer != nullptr )
6959 *ppoBelongingLayer = nullptr;
6960 if( pdfProgressPct != nullptr )
6961 *pdfProgressPct = 1.0;
6962 if( pfnProgress != nullptr )
6963 pfnProgress(1.0, "", pProgressData);
6964 return nullptr;
6965 }
6966
6967 if ( m_poPrivate->poCurrentLayer == nullptr &&
6968 (pdfProgressPct != nullptr || pfnProgress != nullptr) )
6969 {
6970 if( m_poPrivate->nLayerCount < 0 )
6971 {
6972 m_poPrivate->nLayerCount = GetLayerCount();
6973 }
6974
6975 if( m_poPrivate->nTotalFeatures == TOTAL_FEATURES_NOT_INIT )
6976 {
6977 m_poPrivate->nTotalFeatures = 0;
6978 for(int i = 0; i < m_poPrivate->nLayerCount; i++)
6979 {
6980 OGRLayer *poLayer = GetLayer(i);
6981 if( poLayer == nullptr ||
6982 !poLayer->TestCapability(OLCFastFeatureCount) )
6983 {
6984 m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
6985 break;
6986 }
6987 GIntBig nCount = poLayer->GetFeatureCount(FALSE);
6988 if( nCount < 0 )
6989 {
6990 m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
6991 break;
6992 }
6993 m_poPrivate->nTotalFeatures += nCount;
6994 }
6995 }
6996 }
6997
6998 while( true )
6999 {
7000 if( m_poPrivate->poCurrentLayer == nullptr )
7001 {
7002 m_poPrivate->poCurrentLayer = GetLayer(m_poPrivate->nCurrentLayerIdx);
7003 if( m_poPrivate->poCurrentLayer == nullptr )
7004 {
7005 m_poPrivate->nCurrentLayerIdx = -1;
7006 if( ppoBelongingLayer != nullptr )
7007 *ppoBelongingLayer = nullptr;
7008 if( pdfProgressPct != nullptr )
7009 *pdfProgressPct = 1.0;
7010 return nullptr;
7011 }
7012 m_poPrivate->poCurrentLayer->ResetReading();
7013 m_poPrivate->nFeatureReadInLayer = 0;
7014 if( m_poPrivate->nTotalFeatures < 0 && pdfProgressPct != nullptr )
7015 {
7016 if( m_poPrivate->poCurrentLayer->TestCapability(
7017 OLCFastFeatureCount) )
7018 m_poPrivate->nTotalFeaturesInLayer =
7019 m_poPrivate->poCurrentLayer->GetFeatureCount(FALSE);
7020 else
7021 m_poPrivate->nTotalFeaturesInLayer = 0;
7022 }
7023 }
7024 OGRFeature *poFeature = m_poPrivate->poCurrentLayer->GetNextFeature();
7025 if( poFeature == nullptr )
7026 {
7027 m_poPrivate->nCurrentLayerIdx++;
7028 m_poPrivate->poCurrentLayer = nullptr;
7029 continue;
7030 }
7031
7032 m_poPrivate->nFeatureReadInLayer++;
7033 m_poPrivate->nFeatureReadInDataset++;
7034 if( pdfProgressPct != nullptr || pfnProgress != nullptr )
7035 {
7036 double dfPct = 0.0;
7037 if( m_poPrivate->nTotalFeatures > 0 )
7038 {
7039 dfPct = 1.0 * m_poPrivate->nFeatureReadInDataset /
7040 m_poPrivate->nTotalFeatures;
7041 }
7042 else
7043 {
7044 dfPct =
7045 1.0 * m_poPrivate->nCurrentLayerIdx / m_poPrivate->nLayerCount;
7046 if( m_poPrivate->nTotalFeaturesInLayer > 0 )
7047 {
7048 dfPct += 1.0 * m_poPrivate->nFeatureReadInLayer /
7049 m_poPrivate->nTotalFeaturesInLayer /
7050 m_poPrivate->nLayerCount;
7051 }
7052 }
7053 if( pdfProgressPct )
7054 *pdfProgressPct = dfPct;
7055 if( pfnProgress )
7056 pfnProgress(dfPct, "", nullptr);
7057 }
7058
7059 if( ppoBelongingLayer != nullptr )
7060 *ppoBelongingLayer = m_poPrivate->poCurrentLayer;
7061 return poFeature;
7062 }
7063 }
7064
7065 /************************************************************************/
7066 /* GDALDatasetGetNextFeature() */
7067 /************************************************************************/
7068 /**
7069 \brief Fetch the next available feature from this dataset.
7070
7071 This method is intended for the few drivers where OGR_L_GetNextFeature()
7072 is not efficient, but in general OGR_L_GetNextFeature() is a more
7073 natural API.
7074
7075 The returned feature becomes the responsibility of the caller to
7076 delete with OGRFeature::DestroyFeature().
7077
7078 Depending on the driver, this method may return features from layers in a
7079 non sequential way. This is what may happen when the
7080 ODsCRandomLayerRead capability is declared (for example for the
7081 OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7082 advised to use GDALDataset::GetNextFeature() instead of
7083 OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7084 implementation.
7085
7086 The default implementation, used by most drivers, will
7087 however iterate over each layer, and then over each feature within this
7088 layer.
7089
7090 This method takes into account spatial and attribute filters set on layers that
7091 will be iterated upon.
7092
7093 The ResetReading() method can be used to start at the beginning again.
7094
7095 Depending on drivers, this may also have the side effect of calling
7096 OGRLayer::GetNextFeature() on the layers of this dataset.
7097
7098 This method is the same as the C++ method GDALDataset::GetNextFeature()
7099
7100 @param hDS dataset handle.
7101 @param phBelongingLayer a pointer to a OGRLayer* variable to receive the
7102 layer to which the object belongs to, or NULL.
7103 It is possible that the output of *ppoBelongingLayer
7104 to be NULL despite the feature not being NULL.
7105 @param pdfProgressPct a pointer to a double variable to receive the
7106 percentage progress (in [0,1] range), or NULL.
7107 On return, the pointed value might be negative if
7108 determining the progress is not possible.
7109 @param pfnProgress a progress callback to report progress (for
7110 GetNextFeature() calls that might have a long
7111 duration) and offer cancellation possibility, or NULL
7112 @param pProgressData user data provided to pfnProgress, or NULL
7113 @return a feature, or NULL if no more features are available.
7114 @since GDAL 2.2
7115 */
GDALDatasetGetNextFeature(GDALDatasetH hDS,OGRLayerH * phBelongingLayer,double * pdfProgressPct,GDALProgressFunc pfnProgress,void * pProgressData)7116 OGRFeatureH CPL_DLL GDALDatasetGetNextFeature( GDALDatasetH hDS,
7117 OGRLayerH *phBelongingLayer,
7118 double *pdfProgressPct,
7119 GDALProgressFunc pfnProgress,
7120 void *pProgressData )
7121 {
7122 VALIDATE_POINTER1(hDS, "GDALDatasetGetNextFeature", nullptr);
7123
7124 return OGRFeature::ToHandle(
7125 GDALDataset::FromHandle(hDS)
7126 ->GetNextFeature(reinterpret_cast<OGRLayer **>(phBelongingLayer), pdfProgressPct,
7127 pfnProgress, pProgressData));
7128 }
7129
7130 /************************************************************************/
7131 /* TestCapability() */
7132 /************************************************************************/
7133
7134 /**
7135 \fn GDALDataset::TestCapability( const char * pszCap )
7136 \brief Test if capability is available.
7137
7138 One of the following dataset capability names can be passed into this
7139 method, and a TRUE or FALSE value will be returned indicating whether or not
7140 the capability is available for this object.
7141
7142 <ul>
7143 <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
7144 <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
7145 layers.<p>
7146 <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
7147 datasource support CreateGeomField() just after layer creation.<p>
7148 <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
7149 geometries.<p>
7150 <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
7151 transactions.<p>
7152 <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
7153 transactions through emulation.<p>
7154 <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
7155 GetNextFeature() implementation, potentially returning features from
7156 layers in a non sequential way.<p>
7157 <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
7158 CreateFeature() on layers in a non sequential way.<p>
7159 </ul>
7160
7161 The \#define macro forms of the capability names should be used in preference
7162 to the strings themselves to avoid misspelling.
7163
7164 This method is the same as the C function GDALDatasetTestCapability() and the
7165 deprecated OGR_DS_TestCapability().
7166
7167 In GDAL 1.X, this method used to be in the OGRDataSource class.
7168
7169 @param pszCap the capability to test.
7170
7171 @return TRUE if capability available otherwise FALSE.
7172 */
7173
TestCapability(CPL_UNUSED const char * pszCap)7174 int GDALDataset::TestCapability(CPL_UNUSED const char *pszCap) { return FALSE; }
7175
7176 /************************************************************************/
7177 /* GDALDatasetTestCapability() */
7178 /************************************************************************/
7179
7180 /**
7181 \brief Test if capability is available.
7182
7183 One of the following dataset capability names can be passed into this
7184 function, and a TRUE or FALSE value will be returned indicating whether or not
7185 the capability is available for this object.
7186
7187 <ul>
7188 <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
7189 <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
7190 layers.<p>
7191 <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
7192 datasource support CreateGeomField() just after layer creation.<p>
7193 <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
7194 geometries.<p>
7195 <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
7196 transactions.<p>
7197 <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
7198 transactions through emulation.<p>
7199 <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
7200 GetNextFeature() implementation, potentially returning features from
7201 layers in a non sequential way.<p>
7202 <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
7203 CreateFeature() on layers in a non sequential way.<p>
7204 </ul>
7205
7206 The \#define macro forms of the capability names should be used in preference
7207 to the strings themselves to avoid misspelling.
7208
7209 This function is the same as the C++ method GDALDataset::TestCapability()
7210
7211 @since GDAL 2.0
7212
7213 @param hDS the dataset handle.
7214 @param pszCap the capability to test.
7215
7216 @return TRUE if capability available otherwise FALSE.
7217 */
GDALDatasetTestCapability(GDALDatasetH hDS,const char * pszCap)7218 int GDALDatasetTestCapability( GDALDatasetH hDS, const char *pszCap )
7219
7220 {
7221 VALIDATE_POINTER1(hDS, "GDALDatasetTestCapability", 0);
7222 VALIDATE_POINTER1(pszCap, "GDALDatasetTestCapability", 0);
7223
7224 return GDALDataset::FromHandle(hDS)->TestCapability(pszCap);
7225 }
7226
7227 /************************************************************************/
7228 /* StartTransaction() */
7229 /************************************************************************/
7230
7231 /**
7232 \fn GDALDataset::StartTransaction(int)
7233 \brief For datasources which support transactions, StartTransaction creates a
7234 `transaction.
7235
7236 If starting the transaction fails, will return
7237 OGRERR_FAILURE. Datasources which do not support transactions will
7238 always return OGRERR_UNSUPPORTED_OPERATION.
7239
7240 Nested transactions are not supported.
7241
7242 All changes done after the start of the transaction are definitely applied in
7243 the datasource if CommitTransaction() is called. They may be canceled by
7244 calling RollbackTransaction() instead.
7245
7246 At the time of writing, transactions only apply on vector layers.
7247
7248 Datasets that support transactions will advertise the ODsCTransactions
7249 capability. Use of transactions at dataset level is generally preferred to
7250 transactions at layer level, whose scope is rarely limited to the layer from
7251 which it was started.
7252
7253 In case StartTransaction() fails, neither CommitTransaction() or
7254 RollbackTransaction() should be called.
7255
7256 If an error occurs after a successful StartTransaction(), the whole transaction
7257 may or may not be implicitly canceled, depending on drivers. (e.g. the PG
7258 driver will cancel it, SQLite/GPKG not). In any case, in the event of an error,
7259 an explicit call to RollbackTransaction() should be done to keep things
7260 balanced.
7261
7262 By default, when bForce is set to FALSE, only "efficient" transactions will be
7263 attempted. Some drivers may offer an emulation of transactions, but sometimes
7264 with significant overhead, in which case the user must explicitly allow for
7265 such an emulation by setting bForce to TRUE. Drivers that offer emulated
7266 transactions should advertise the ODsCEmulatedTransactions capability (and not
7267 ODsCTransactions).
7268
7269 This function is the same as the C function GDALDatasetStartTransaction().
7270
7271 @param bForce can be set to TRUE if an emulation, possibly slow, of a
7272 transaction
7273 mechanism is acceptable.
7274
7275 @return OGRERR_NONE on success.
7276 @since GDAL 2.0
7277 */
7278
StartTransaction(CPL_UNUSED int bForce)7279 OGRErr GDALDataset::StartTransaction( CPL_UNUSED int bForce )
7280 {
7281 return OGRERR_UNSUPPORTED_OPERATION;
7282 }
7283
7284 /************************************************************************/
7285 /* GDALDatasetStartTransaction() */
7286 /************************************************************************/
7287
7288 /**
7289 \brief For datasources which support transactions, StartTransaction creates a
7290 transaction.
7291
7292 If starting the transaction fails, will return
7293 OGRERR_FAILURE. Datasources which do not support transactions will
7294 always return OGRERR_UNSUPPORTED_OPERATION.
7295
7296 Nested transactions are not supported.
7297
7298 All changes done after the start of the transaction are definitely applied in
7299 the datasource if CommitTransaction() is called. They may be canceled by
7300 calling RollbackTransaction() instead.
7301
7302 At the time of writing, transactions only apply on vector layers.
7303
7304 Datasets that support transactions will advertise the ODsCTransactions
7305 capability.
7306 Use of transactions at dataset level is generally preferred to transactions at
7307 layer level, whose scope is rarely limited to the layer from which it was
7308 started.
7309
7310 In case StartTransaction() fails, neither CommitTransaction() or
7311 RollbackTransaction() should be called.
7312
7313 If an error occurs after a successful StartTransaction(), the whole
7314 transaction may or may not be implicitly canceled, depending on drivers. (e.g.
7315 the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
7316 error, an explicit call to RollbackTransaction() should be done to keep things
7317 balanced.
7318
7319 By default, when bForce is set to FALSE, only "efficient" transactions will be
7320 attempted. Some drivers may offer an emulation of transactions, but sometimes
7321 with significant overhead, in which case the user must explicitly allow for
7322 such an emulation by setting bForce to TRUE. Drivers that offer emulated
7323 transactions should advertise the ODsCEmulatedTransactions capability (and not
7324 ODsCTransactions).
7325
7326 This function is the same as the C++ method GDALDataset::StartTransaction()
7327
7328 @param hDS the dataset handle.
7329 @param bForce can be set to TRUE if an emulation, possibly slow, of a
7330 transaction
7331 mechanism is acceptable.
7332
7333 @return OGRERR_NONE on success.
7334 @since GDAL 2.0
7335 */
GDALDatasetStartTransaction(GDALDatasetH hDS,int bForce)7336 OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
7337 {
7338 VALIDATE_POINTER1(hDS, "GDALDatasetStartTransaction",
7339 OGRERR_INVALID_HANDLE);
7340
7341 #ifdef OGRAPISPY_ENABLED
7342 if( bOGRAPISpyEnabled )
7343 OGRAPISpy_Dataset_StartTransaction(hDS, bForce);
7344 #endif
7345
7346 return GDALDataset::FromHandle(hDS)->StartTransaction(bForce);
7347 }
7348
7349 /************************************************************************/
7350 /* CommitTransaction() */
7351 /************************************************************************/
7352
7353 /**
7354 \brief For datasources which support transactions, CommitTransaction commits a
7355 transaction.
7356
7357 If no transaction is active, or the commit fails, will return
7358 OGRERR_FAILURE. Datasources which do not support transactions will
7359 always return OGRERR_UNSUPPORTED_OPERATION.
7360
7361 Depending on drivers, this may or may not abort layer sequential readings that
7362 are active.
7363
7364 This function is the same as the C function GDALDatasetCommitTransaction().
7365
7366 @return OGRERR_NONE on success.
7367 @since GDAL 2.0
7368 */
CommitTransaction()7369 OGRErr GDALDataset::CommitTransaction() { return OGRERR_UNSUPPORTED_OPERATION; }
7370
7371 /************************************************************************/
7372 /* GDALDatasetCommitTransaction() */
7373 /************************************************************************/
7374
7375 /**
7376 \brief For datasources which support transactions, CommitTransaction commits a
7377 transaction.
7378
7379 If no transaction is active, or the commit fails, will return
7380 OGRERR_FAILURE. Datasources which do not support transactions will
7381 always return OGRERR_UNSUPPORTED_OPERATION.
7382
7383 Depending on drivers, this may or may not abort layer sequential readings that
7384 are active.
7385
7386 This function is the same as the C++ method GDALDataset::CommitTransaction()
7387
7388 @return OGRERR_NONE on success.
7389 @since GDAL 2.0
7390 */
GDALDatasetCommitTransaction(GDALDatasetH hDS)7391 OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
7392 {
7393 VALIDATE_POINTER1(hDS, "GDALDatasetCommitTransaction",
7394 OGRERR_INVALID_HANDLE);
7395
7396 #ifdef OGRAPISPY_ENABLED
7397 if( bOGRAPISpyEnabled )
7398 OGRAPISpy_Dataset_CommitTransaction(hDS);
7399 #endif
7400
7401 return GDALDataset::FromHandle(hDS)->CommitTransaction();
7402 }
7403
7404 /************************************************************************/
7405 /* RollbackTransaction() */
7406 /************************************************************************/
7407
7408 /**
7409 \brief For datasources which support transactions, RollbackTransaction will
7410 roll back a datasource to its state before the start of the current
7411 transaction.
7412 If no transaction is active, or the rollback fails, will return
7413 OGRERR_FAILURE. Datasources which do not support transactions will
7414 always return OGRERR_UNSUPPORTED_OPERATION.
7415
7416 This function is the same as the C function GDALDatasetRollbackTransaction().
7417
7418 @return OGRERR_NONE on success.
7419 @since GDAL 2.0
7420 */
RollbackTransaction()7421 OGRErr GDALDataset::RollbackTransaction()
7422 {
7423 return OGRERR_UNSUPPORTED_OPERATION;
7424 }
7425
7426 /************************************************************************/
7427 /* GDALDatasetRollbackTransaction() */
7428 /************************************************************************/
7429
7430 /**
7431 \brief For datasources which support transactions, RollbackTransaction will
7432 roll back a datasource to its state before the start of the current
7433 transaction.
7434 If no transaction is active, or the rollback fails, will return
7435 OGRERR_FAILURE. Datasources which do not support transactions will
7436 always return OGRERR_UNSUPPORTED_OPERATION.
7437
7438 This function is the same as the C++ method GDALDataset::RollbackTransaction().
7439
7440 @return OGRERR_NONE on success.
7441 @since GDAL 2.0
7442 */
GDALDatasetRollbackTransaction(GDALDatasetH hDS)7443 OGRErr GDALDatasetRollbackTransaction( GDALDatasetH hDS )
7444 {
7445 VALIDATE_POINTER1(hDS, "GDALDatasetRollbackTransaction",
7446 OGRERR_INVALID_HANDLE);
7447
7448 #ifdef OGRAPISPY_ENABLED
7449 if( bOGRAPISpyEnabled )
7450 OGRAPISpy_Dataset_RollbackTransaction(hDS);
7451 #endif
7452
7453 return GDALDataset::FromHandle(hDS)->RollbackTransaction();
7454 }
7455
7456
7457 //! @cond Doxygen_Suppress
7458
7459 /************************************************************************/
7460 /* ShareLockWithParentDataset() */
7461 /************************************************************************/
7462
7463 /* To be used typically by the GTiff driver to link overview datasets */
7464 /* with their main dataset, so that they share the same lock */
7465 /* Cf https://github.com/OSGeo/gdal/issues/1488 */
7466 /* The parent dataset should remain alive while the this dataset is alive */
7467
ShareLockWithParentDataset(GDALDataset * poParentDataset)7468 void GDALDataset::ShareLockWithParentDataset(GDALDataset* poParentDataset)
7469 {
7470 if( m_poPrivate != nullptr )
7471 {
7472 m_poPrivate->poParentDataset = poParentDataset;
7473 }
7474 }
7475
7476 /************************************************************************/
7477 /* EnterReadWrite() */
7478 /************************************************************************/
7479
EnterReadWrite(GDALRWFlag eRWFlag)7480 int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
7481 {
7482 if( m_poPrivate == nullptr )
7483 return FALSE;
7484
7485 if( m_poPrivate->poParentDataset )
7486 return m_poPrivate->poParentDataset->EnterReadWrite(eRWFlag);
7487
7488 if( eAccess == GA_Update )
7489 {
7490 if( m_poPrivate->eStateReadWriteMutex == GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN )
7491 {
7492 // In case dead-lock would occur, which is not impossible,
7493 // this can be used to prevent it, but at the risk of other
7494 // issues.
7495 if(CPLTestBool(
7496 CPLGetConfigOption("GDAL_ENABLE_READ_WRITE_MUTEX", "YES")))
7497 {
7498 m_poPrivate->eStateReadWriteMutex = GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED;
7499 }
7500 else
7501 {
7502 m_poPrivate->eStateReadWriteMutex = GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
7503 }
7504 }
7505 if( m_poPrivate->eStateReadWriteMutex == GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED )
7506 {
7507 // There should be no race related to creating this mutex since
7508 // it should be first created through IWriteBlock() / IRasterIO()
7509 // and then GDALRasterBlock might call it from another thread.
7510 #ifdef DEBUG_VERBOSE
7511 CPLDebug("GDAL",
7512 "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
7513 CPLGetPID(), GetDescription());
7514 #endif
7515 CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
7516
7517 const int nCountMutex = m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]++;
7518 if( nCountMutex == 0 && eRWFlag == GF_Read )
7519 {
7520 CPLReleaseMutex(m_poPrivate->hMutex);
7521 for( int i = 0; i < nBands; i++ )
7522 {
7523 auto blockCache = papoBands[i]->poBandBlockCache;
7524 if( blockCache )
7525 blockCache->WaitCompletionPendingTasks();
7526 }
7527 CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
7528 }
7529
7530 return TRUE;
7531 }
7532 }
7533 return FALSE;
7534 }
7535
7536 /************************************************************************/
7537 /* LeaveReadWrite() */
7538 /************************************************************************/
7539
LeaveReadWrite()7540 void GDALDataset::LeaveReadWrite()
7541 {
7542 if( m_poPrivate )
7543 {
7544 if( m_poPrivate->poParentDataset )
7545 {
7546 m_poPrivate->poParentDataset->LeaveReadWrite();
7547 return;
7548 }
7549
7550 m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]--;
7551 CPLReleaseMutex(m_poPrivate->hMutex);
7552 #ifdef DEBUG_VERBOSE
7553 CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s",
7554 CPLGetPID(), GetDescription());
7555 #endif
7556 }
7557 }
7558
7559 /************************************************************************/
7560 /* InitRWLock() */
7561 /************************************************************************/
7562
InitRWLock()7563 void GDALDataset::InitRWLock()
7564 {
7565 if( m_poPrivate )
7566 {
7567 if( m_poPrivate->poParentDataset )
7568 {
7569 m_poPrivate->poParentDataset->InitRWLock();
7570 return;
7571 }
7572
7573 if( m_poPrivate->eStateReadWriteMutex == GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN )
7574 {
7575 if( EnterReadWrite(GF_Write) )
7576 LeaveReadWrite();
7577 }
7578 }
7579 }
7580
7581 /************************************************************************/
7582 /* DisableReadWriteMutex() */
7583 /************************************************************************/
7584
7585 // The mutex logic is broken in multi-threaded situations, for example
7586 // with 2 WarpedVRT datasets being read at the same time. In that
7587 // particular case, the mutex is not needed, so allow the VRTWarpedDataset code
7588 // to disable it.
DisableReadWriteMutex()7589 void GDALDataset::DisableReadWriteMutex()
7590 {
7591 if( m_poPrivate )
7592 {
7593 if( m_poPrivate->poParentDataset )
7594 {
7595 m_poPrivate->poParentDataset->DisableReadWriteMutex();
7596 return;
7597 }
7598
7599 m_poPrivate->eStateReadWriteMutex = GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
7600 }
7601 }
7602
7603 /************************************************************************/
7604 /* TemporarilyDropReadWriteLock() */
7605 /************************************************************************/
7606
TemporarilyDropReadWriteLock()7607 void GDALDataset::TemporarilyDropReadWriteLock()
7608 {
7609 if( m_poPrivate == nullptr )
7610 return;
7611
7612 if( m_poPrivate->poParentDataset )
7613 {
7614 m_poPrivate->poParentDataset->TemporarilyDropReadWriteLock();
7615 return;
7616 }
7617
7618 if( m_poPrivate->hMutex )
7619 {
7620 #ifdef DEBUG_VERBOSE
7621 CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] "
7622 "Temporarily drop RW mutex for %s",
7623 CPLGetPID(), GetDescription());
7624 #endif
7625 CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
7626 const int nCount = m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
7627 #ifdef DEBUG_EXTRA
7628 m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()] = nCount;
7629 #endif
7630 for(int i = 0; i < nCount + 1; i++)
7631 {
7632 // The mutex is recursive
7633 // coverity[double_unlock]
7634 CPLReleaseMutex(m_poPrivate->hMutex);
7635 }
7636 }
7637 }
7638
7639 /************************************************************************/
7640 /* ReacquireReadWriteLock() */
7641 /************************************************************************/
7642
ReacquireReadWriteLock()7643 void GDALDataset::ReacquireReadWriteLock()
7644 {
7645 if( m_poPrivate == nullptr )
7646 return;
7647
7648 if( m_poPrivate->poParentDataset )
7649 {
7650 m_poPrivate->poParentDataset->ReacquireReadWriteLock();
7651 return;
7652 }
7653
7654 if( m_poPrivate->hMutex )
7655 {
7656 #ifdef DEBUG_VERBOSE
7657 CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] "
7658 "Reacquire temporarily dropped RW mutex for %s",
7659 CPLGetPID(), GetDescription());
7660 #endif
7661 CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
7662 const int nCount = m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
7663 #ifdef DEBUG_EXTRA
7664 CPLAssert(nCount ==
7665 m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()]);
7666 #endif
7667 if( nCount == 0 )
7668 CPLReleaseMutex(m_poPrivate->hMutex);
7669 for(int i = 0; i < nCount - 1; i++)
7670 {
7671 // The mutex is recursive
7672 // coverity[double_lock]
7673 CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
7674 }
7675 }
7676 }
7677
7678 /************************************************************************/
7679 /* AcquireMutex() */
7680 /************************************************************************/
7681
AcquireMutex()7682 int GDALDataset::AcquireMutex()
7683 {
7684 if( m_poPrivate == nullptr )
7685 return 0;
7686 if( m_poPrivate->poParentDataset )
7687 {
7688 return m_poPrivate->poParentDataset->AcquireMutex();
7689 }
7690
7691 return CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
7692 }
7693
7694 /************************************************************************/
7695 /* ReleaseMutex() */
7696 /************************************************************************/
7697
ReleaseMutex()7698 void GDALDataset::ReleaseMutex()
7699 {
7700 if( m_poPrivate )
7701 {
7702 if( m_poPrivate->poParentDataset )
7703 {
7704 m_poPrivate->poParentDataset->ReleaseMutex();
7705 return;
7706 }
7707
7708 CPLReleaseMutex(m_poPrivate->hMutex);
7709 }
7710 }
7711 //! @endcond
7712
7713
7714 /************************************************************************/
7715 /* GDALDataset::Features::Iterator::Private */
7716 /************************************************************************/
7717
7718 struct GDALDataset::Features::Iterator::Private
7719 {
7720 GDALDataset::FeatureLayerPair m_oPair{};
7721 GDALDataset* m_poDS = nullptr;
7722 bool m_bEOF = true;
7723 };
7724
Iterator(GDALDataset * poDS,bool bStart)7725 GDALDataset::Features::Iterator::Iterator(GDALDataset* poDS, bool bStart):
7726 m_poPrivate(new GDALDataset::Features::Iterator::Private())
7727 {
7728 m_poPrivate->m_poDS = poDS;
7729 if( bStart )
7730 {
7731 poDS->ResetReading();
7732 m_poPrivate->m_oPair.feature.reset(
7733 poDS->GetNextFeature(
7734 &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
7735 m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
7736 }
7737 }
7738
7739 GDALDataset::Features::Iterator::~Iterator() = default;
7740
7741 const GDALDataset::FeatureLayerPair&
operator *() const7742 GDALDataset::Features::Iterator::operator*() const
7743 {
7744 return m_poPrivate->m_oPair;
7745 }
7746
operator ++()7747 GDALDataset::Features::Iterator& GDALDataset::Features::Iterator::operator++()
7748 {
7749 m_poPrivate->m_oPair.feature.reset(
7750 m_poPrivate->m_poDS->GetNextFeature(
7751 &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
7752 m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
7753 return *this;
7754 }
7755
operator !=(const Iterator & it) const7756 bool GDALDataset::Features::Iterator::operator!= (const Iterator& it) const
7757 {
7758 return m_poPrivate->m_bEOF != it.m_poPrivate->m_bEOF;
7759 }
7760
7761 /************************************************************************/
7762 /* GetFeatures() */
7763 /************************************************************************/
7764
7765 /** Function that return an iterable object over features in the dataset
7766 * layer.
7767 *
7768 * This is a C++ iterator friendly version of GetNextFeature().
7769 *
7770 * Using this iterator for standard range-based loops is safe, but
7771 * due to implementation limitations, you shouldn't try to access
7772 * (dereference) more than one iterator step at a time, since the
7773 * FeatureLayerPair reference which is returned is reused.
7774 *
7775 * Typical use is:
7776 * \code{.cpp}
7777 * for( auto&& oFeatureLayerPair: poDS->GetFeatures() )
7778 * {
7779 * std::cout << "Feature of layer " <<
7780 * oFeatureLayerPair.layer->GetName() << std::endl;
7781 * oFeatureLayerPair.feature->DumpReadable();
7782 * }
7783 * \endcode
7784 *
7785 * @see GetNextFeature()
7786 *
7787 * @since GDAL 2.3
7788 */
GetFeatures()7789 GDALDataset::Features GDALDataset::GetFeatures()
7790 {
7791 return Features(this);
7792 }
7793
7794 /************************************************************************/
7795 /* begin() */
7796 /************************************************************************/
7797
7798 /**
7799 \brief Return beginning of feature iterator.
7800
7801 @since GDAL 2.3
7802 */
7803
begin() const7804 const GDALDataset::Features::Iterator GDALDataset::Features::begin() const
7805 {
7806 return {m_poSelf, true};
7807 }
7808
7809 /************************************************************************/
7810 /* end() */
7811 /************************************************************************/
7812
7813 /**
7814 \brief Return end of feature iterator.
7815
7816 @since GDAL 2.3
7817 */
7818
end() const7819 const GDALDataset::Features::Iterator GDALDataset::Features::end() const
7820 {
7821 return {m_poSelf, false};
7822 }
7823
7824 /************************************************************************/
7825 /* GDALDataset::Layers::Iterator::Private */
7826 /************************************************************************/
7827
7828 struct GDALDataset::Layers::Iterator::Private
7829 {
7830 OGRLayer* m_poLayer = nullptr;
7831 int m_iCurLayer = 0;
7832 int m_nLayerCount = 0;
7833 GDALDataset* m_poDS = nullptr;
7834 };
7835
Iterator()7836 GDALDataset::Layers::Iterator::Iterator():
7837 m_poPrivate(new Private())
7838 {}
7839
7840 // False positive of cppcheck 1.72
7841 // cppcheck-suppress uninitMemberVar
Iterator(const Iterator & oOther)7842 GDALDataset::Layers::Iterator::Iterator(const Iterator& oOther):
7843 m_poPrivate(new Private(*(oOther.m_poPrivate)))
7844 {
7845 }
7846
Iterator(Iterator && oOther)7847 GDALDataset::Layers::Iterator::Iterator(Iterator&& oOther) noexcept:
7848 m_poPrivate(std::move(oOther.m_poPrivate))
7849 {
7850 }
7851
Iterator(GDALDataset * poDS,bool bStart)7852 GDALDataset::Layers::Iterator::Iterator(GDALDataset* poDS, bool bStart):
7853 m_poPrivate(new Private())
7854 {
7855 m_poPrivate->m_poDS = poDS;
7856 m_poPrivate->m_nLayerCount = poDS->GetLayerCount();
7857 if( bStart )
7858 {
7859 if( m_poPrivate->m_nLayerCount )
7860 m_poPrivate->m_poLayer = poDS->GetLayer(0);
7861 }
7862 else
7863 {
7864 m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;
7865 }
7866 }
7867
7868 GDALDataset::Layers::Iterator::~Iterator() = default;
7869
7870 // False positive of cppcheck 1.72
7871 // cppcheck-suppress operatorEqVarError
operator =(const Iterator & oOther)7872 GDALDataset::Layers::Iterator& GDALDataset::Layers::Iterator::operator=(
7873 const Iterator& oOther)
7874 {
7875 *m_poPrivate = *oOther.m_poPrivate;
7876 return *this;
7877 }
7878
operator =(GDALDataset::Layers::Iterator && oOther)7879 GDALDataset::Layers::Iterator& GDALDataset::Layers::Iterator::operator=(
7880 GDALDataset::Layers::Iterator&& oOther) noexcept
7881 {
7882 m_poPrivate = std::move(oOther.m_poPrivate);
7883 return *this;
7884 }
7885
operator *() const7886 OGRLayer* GDALDataset::Layers::Iterator::operator*() const
7887 {
7888 return m_poPrivate->m_poLayer;
7889 }
7890
operator ++()7891 GDALDataset::Layers::Iterator& GDALDataset::Layers::Iterator::operator++()
7892 {
7893 m_poPrivate->m_iCurLayer ++;
7894 if( m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount )
7895 {
7896 m_poPrivate->m_poLayer =
7897 m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);
7898 }
7899 else
7900 {
7901 m_poPrivate->m_poLayer = nullptr;
7902 }
7903 return *this;
7904 }
7905
operator ++(int)7906 GDALDataset::Layers::Iterator GDALDataset::Layers::Iterator::operator++(int)
7907 {
7908 GDALDataset::Layers::Iterator temp = *this;
7909 ++(*this);
7910 return temp;
7911 }
7912
operator !=(const Iterator & it) const7913 bool GDALDataset::Layers::Iterator::operator!= (const Iterator& it) const
7914 {
7915 return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;
7916 }
7917
7918 /************************************************************************/
7919 /* GetLayers() */
7920 /************************************************************************/
7921
7922 /** Function that returns an iterable object over layers in the dataset.
7923 *
7924 * This is a C++ iterator friendly version of GetLayer().
7925 *
7926 * Typical use is:
7927 * \code{.cpp}
7928 * for( auto&& poLayer: poDS->GetLayers() )
7929 * {
7930 * std::cout << "Layer << poLayer->GetName() << std::endl;
7931 * }
7932 * \endcode
7933 *
7934 * @see GetLayer()
7935 *
7936 * @since GDAL 2.3
7937 */
GetLayers()7938 GDALDataset::Layers GDALDataset::GetLayers()
7939 {
7940 return Layers(this);
7941 }
7942
7943 /************************************************************************/
7944 /* begin() */
7945 /************************************************************************/
7946
7947 /**
7948 \brief Return beginning of layer iterator.
7949
7950 @since GDAL 2.3
7951 */
7952
begin() const7953 GDALDataset::Layers::Iterator GDALDataset::Layers::begin() const
7954 {
7955 return {m_poSelf, true};
7956 }
7957
7958 /************************************************************************/
7959 /* end() */
7960 /************************************************************************/
7961
7962 /**
7963 \brief Return end of layer iterator.
7964
7965 @since GDAL 2.3
7966 */
7967
end() const7968 GDALDataset::Layers::Iterator GDALDataset::Layers::end() const
7969 {
7970 return {m_poSelf, false};
7971 }
7972
7973 /************************************************************************/
7974 /* size() */
7975 /************************************************************************/
7976
7977 /**
7978 \brief Get the number of layers in this dataset.
7979
7980 @return layer count.
7981
7982 @since GDAL 2.3
7983 */
7984
size() const7985 size_t GDALDataset::Layers::size() const
7986 {
7987 return static_cast<size_t>(m_poSelf->GetLayerCount());
7988 }
7989
7990 /************************************************************************/
7991 /* operator[]() */
7992 /************************************************************************/
7993 /**
7994 \brief Fetch a layer by index.
7995
7996 The returned layer remains owned by the
7997 GDALDataset and should not be deleted by the application.
7998
7999 @param iLayer a layer number between 0 and size()-1.
8000
8001 @return the layer, or nullptr if iLayer is out of range or an error occurs.
8002
8003 @since GDAL 2.3
8004 */
8005
operator [](int iLayer)8006 OGRLayer* GDALDataset::Layers::operator[](int iLayer)
8007 {
8008 return m_poSelf->GetLayer(iLayer);
8009 }
8010
8011 /************************************************************************/
8012 /* operator[]() */
8013 /************************************************************************/
8014 /**
8015 \brief Fetch a layer by index.
8016
8017 The returned layer remains owned by the
8018 GDALDataset and should not be deleted by the application.
8019
8020 @param iLayer a layer number between 0 and size()-1.
8021
8022 @return the layer, or nullptr if iLayer is out of range or an error occurs.
8023
8024 @since GDAL 2.3
8025 */
8026
operator [](size_t iLayer)8027 OGRLayer* GDALDataset::Layers::operator[](size_t iLayer)
8028 {
8029 return m_poSelf->GetLayer(static_cast<int>(iLayer));
8030 }
8031
8032 /************************************************************************/
8033 /* operator[]() */
8034 /************************************************************************/
8035 /**
8036 \brief Fetch a layer by name.
8037
8038 The returned layer remains owned by the
8039 GDALDataset and should not be deleted by the application.
8040
8041 @param pszLayerName layer name
8042
8043 @return the layer, or nullptr if pszLayerName does not match with a layer
8044
8045 @since GDAL 2.3
8046 */
8047
operator [](const char * pszLayerName)8048 OGRLayer* GDALDataset::Layers::operator[](const char* pszLayerName)
8049 {
8050 return m_poSelf->GetLayerByName(pszLayerName);
8051 }
8052
8053 /************************************************************************/
8054 /* GDALDataset::Bands::Iterator::Private */
8055 /************************************************************************/
8056
8057 struct GDALDataset::Bands::Iterator::Private
8058 {
8059 GDALRasterBand* m_poBand = nullptr;
8060 int m_iCurBand = 0;
8061 int m_nBandCount = 0;
8062 GDALDataset* m_poDS = nullptr;
8063 };
8064
Iterator(GDALDataset * poDS,bool bStart)8065 GDALDataset::Bands::Iterator::Iterator(GDALDataset* poDS, bool bStart):
8066 m_poPrivate(new GDALDataset::Bands::Iterator::Private())
8067 {
8068 m_poPrivate->m_poDS = poDS;
8069 m_poPrivate->m_nBandCount = poDS->GetRasterCount();
8070 if( bStart )
8071 {
8072 if( m_poPrivate->m_nBandCount )
8073 m_poPrivate->m_poBand = poDS->GetRasterBand(1);
8074 }
8075 else
8076 {
8077 m_poPrivate->m_iCurBand = m_poPrivate->m_nBandCount;
8078 }
8079 }
8080
8081 GDALDataset::Bands::Iterator::~Iterator() = default;
8082
operator *()8083 GDALRasterBand* GDALDataset::Bands::Iterator::operator*()
8084 {
8085 return m_poPrivate->m_poBand;
8086 }
8087
operator ++()8088 GDALDataset::Bands::Iterator& GDALDataset::Bands::Iterator::operator++()
8089 {
8090 m_poPrivate->m_iCurBand ++;
8091 if( m_poPrivate->m_iCurBand < m_poPrivate->m_nBandCount )
8092 {
8093 m_poPrivate->m_poBand =
8094 m_poPrivate->m_poDS->GetRasterBand(1 + m_poPrivate->m_iCurBand);
8095 }
8096 else
8097 {
8098 m_poPrivate->m_poBand = nullptr;
8099 }
8100 return *this;
8101 }
8102
operator !=(const Iterator & it) const8103 bool GDALDataset::Bands::Iterator::operator!= (const Iterator& it) const
8104 {
8105 return m_poPrivate->m_iCurBand != it.m_poPrivate->m_iCurBand;
8106 }
8107
8108 /************************************************************************/
8109 /* GetBands() */
8110 /************************************************************************/
8111
8112 /** Function that returns an iterable object over GDALRasterBand in the dataset.
8113 *
8114 * This is a C++ iterator friendly version of GetRasterBand().
8115 *
8116 * Typical use is:
8117 * \code{.cpp}
8118 * for( auto&& poBand: poDS->GetBands() )
8119 * {
8120 * std::cout << "Band << poBand->GetDescription() << std::endl;
8121 * }
8122 * \endcode
8123 *
8124 * @see GetRasterBand()
8125 *
8126 * @since GDAL 2.3
8127 */
GetBands()8128 GDALDataset::Bands GDALDataset::GetBands()
8129 {
8130 return Bands(this);
8131 }
8132
8133 /************************************************************************/
8134 /* begin() */
8135 /************************************************************************/
8136
8137 /**
8138 \brief Return beginning of band iterator.
8139
8140 @since GDAL 2.3
8141 */
8142
begin() const8143 const GDALDataset::Bands::Iterator GDALDataset::Bands::begin() const
8144 {
8145 return {m_poSelf, true};
8146 }
8147
8148 /************************************************************************/
8149 /* end() */
8150 /************************************************************************/
8151
8152 /**
8153 \brief Return end of band iterator.
8154
8155 @since GDAL 2.3
8156 */
8157
end() const8158 const GDALDataset::Bands::Iterator GDALDataset::Bands::end() const
8159 {
8160 return {m_poSelf, false};
8161 }
8162
8163 /************************************************************************/
8164 /* size() */
8165 /************************************************************************/
8166
8167 /**
8168 \brief Get the number of raster bands in this dataset.
8169
8170 @return raster band count.
8171
8172 @since GDAL 2.3
8173 */
8174
size() const8175 size_t GDALDataset::Bands::size() const
8176 {
8177 return static_cast<size_t>(m_poSelf->GetRasterCount());
8178 }
8179
8180 /************************************************************************/
8181 /* operator[]() */
8182 /************************************************************************/
8183 /**
8184 \brief Fetch a raster band by index.
8185
8186 The returned band remains owned by the
8187 GDALDataset and should not be deleted by the application.
8188
8189 @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
8190 consistent with the conventions of C/C++, i.e. starting at 0.
8191
8192 @param iBand a band index between 0 and size()-1.
8193
8194 @return the band, or nullptr if iBand is out of range or an error occurs.
8195
8196 @since GDAL 2.3
8197 */
8198
operator [](int iBand)8199 GDALRasterBand* GDALDataset::Bands::operator[](int iBand)
8200 {
8201 return m_poSelf->GetRasterBand(1+iBand);
8202 }
8203
8204 /************************************************************************/
8205 /* operator[]() */
8206 /************************************************************************/
8207
8208 /**
8209 \brief Fetch a raster band by index.
8210
8211 The returned band remains owned by the
8212 GDALDataset and should not be deleted by the application.
8213
8214 @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
8215 consistent with the conventions of C/C++, i.e. starting at 0.
8216
8217 @param iBand a band index between 0 and size()-1.
8218
8219 @return the band, or nullptr if iBand is out of range or an error occurs.
8220
8221 @since GDAL 2.3
8222 */
8223
8224
operator [](size_t iBand)8225 GDALRasterBand* GDALDataset::Bands::operator[](size_t iBand)
8226 {
8227 return m_poSelf->GetRasterBand(1+static_cast<int>(iBand));
8228 }
8229
8230 /************************************************************************/
8231 /* GetRootGroup() */
8232 /************************************************************************/
8233
8234 /**
8235 \brief Return the root GDALGroup of this dataset.
8236
8237 Only valid for multidimensional datasets.
8238
8239 This is the same as the C function GDALDatasetGetRootGroup().
8240
8241 @since GDAL 3.1
8242 */
8243
GetRootGroup() const8244 std::shared_ptr<GDALGroup> GDALDataset::GetRootGroup() const
8245 {
8246 return nullptr;
8247 }
8248
8249
8250 /************************************************************************/
8251 /* GetRawBinaryLayout() */
8252 /************************************************************************/
8253
8254 //! @cond Doxygen_Suppress
8255 /**
8256 \brief Return the layout of a dataset that can be considered as a raw binary format.
8257
8258 @param sLayout Structure that will be set if the dataset is a raw binary one.
8259 @return true if the dataset is a raw binary one.
8260 @since GDAL 3.1
8261 */
8262
GetRawBinaryLayout(RawBinaryLayout & sLayout)8263 bool GDALDataset::GetRawBinaryLayout(RawBinaryLayout& sLayout)
8264 {
8265 CPL_IGNORE_RET_VAL(sLayout);
8266 return false;
8267 }
8268 //! @endcond
8269
8270
8271 /************************************************************************/
8272 /* ClearStatistics() */
8273 /************************************************************************/
8274
8275 /**
8276 \brief Clear statistics
8277
8278 Only implemented for now in PAM supported datasets
8279
8280 This is the same as the C function GDALDatasetClearStatistics().
8281
8282 @since GDAL 3.2
8283 */
8284
ClearStatistics()8285 void GDALDataset::ClearStatistics()
8286 {
8287 }
8288
8289 /************************************************************************/
8290 /* GDALDatasetClearStatistics() */
8291 /************************************************************************/
8292
8293 /**
8294 \brief Clear statistics
8295
8296 This is the same as the C++ method GDALDataset::ClearStatistics().
8297
8298 @since GDAL 3.2
8299 */
8300
GDALDatasetClearStatistics(GDALDatasetH hDS)8301 void GDALDatasetClearStatistics(GDALDatasetH hDS)
8302 {
8303 VALIDATE_POINTER0(hDS, __func__);
8304 GDALDataset::FromHandle(hDS)->ClearStatistics();
8305 }
8306
8307 /************************************************************************/
8308 /* GetFieldDomain() */
8309 /************************************************************************/
8310
8311 /** Get a field domain from its name.
8312 *
8313 * @return the field domain, or nullptr if not found.
8314 * @since GDAL 3.3
8315 */
GetFieldDomain(const std::string & name) const8316 const OGRFieldDomain* GDALDataset::GetFieldDomain(const std::string& name) const
8317 {
8318 const auto iter = m_oMapFieldDomains.find(name);
8319 if( iter == m_oMapFieldDomains.end() )
8320 return nullptr;
8321 return iter->second.get();
8322 }
8323
8324 /************************************************************************/
8325 /* GDALDatasetGetFieldDomain() */
8326 /************************************************************************/
8327
8328 /** Get a field domain from its name.
8329 *
8330 * This is the same as the C++ method GDALDataset::GetFieldDomain().
8331 *
8332 * @param hDS Dataset handle.
8333 * @param pszName Name of field domain.
8334 * @return the field domain (ownership remains to the dataset), or nullptr if not found.
8335 * @since GDAL 3.3
8336 */
GDALDatasetGetFieldDomain(GDALDatasetH hDS,const char * pszName)8337 OGRFieldDomainH GDALDatasetGetFieldDomain(GDALDatasetH hDS,
8338 const char* pszName)
8339 {
8340 VALIDATE_POINTER1(hDS, __func__, nullptr);
8341 VALIDATE_POINTER1(pszName, __func__, nullptr);
8342 return OGRFieldDomain::ToHandle(
8343 const_cast<OGRFieldDomain*>(
8344 GDALDataset::FromHandle(hDS)->GetFieldDomain(pszName)));
8345 }
8346
8347 /************************************************************************/
8348 /* AddFieldDomain() */
8349 /************************************************************************/
8350
8351 /** Add a field domain to the dataset.
8352 *
8353 * Only a few drivers will support this operation, and some of them might only
8354 * support it only for some types of field domains.
8355 * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
8356 * support this operation. A dataset having at least some support for this
8357 * operation should report the ODsCAddFieldDomain dataset capability.
8358 *
8359 * Anticipated failures will not be emitted through the CPLError()
8360 * infrastructure, but will be reported in the failureReason output parameter.
8361 *
8362 * @param domain The domain definition.
8363 * @param failureReason Output parameter. Will contain an error message if
8364 * an error occurs.
8365 * @return true in case of success.
8366 * @since GDAL 3.3
8367 */
AddFieldDomain(CPL_UNUSED std::unique_ptr<OGRFieldDomain> && domain,std::string & failureReason)8368 bool GDALDataset::AddFieldDomain(CPL_UNUSED std::unique_ptr<OGRFieldDomain>&& domain,
8369 std::string& failureReason)
8370 {
8371 failureReason = "AddFieldDomain not supported by this driver";
8372 return false;
8373 }
8374
8375 /************************************************************************/
8376 /* GDALDatasetAddFieldDomain() */
8377 /************************************************************************/
8378
8379 /** Add a field domain to the dataset.
8380 *
8381 * Only a few drivers will support this operation, and some of them might only
8382 * support it only for some types of field domains.
8383 * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
8384 * support this operation. A dataset having at least some support for this
8385 * operation should report the ODsCAddFieldDomain dataset capability.
8386 *
8387 * Anticipated failures will not be emitted through the CPLError()
8388 * infrastructure, but will be reported in the ppszFailureReason output parameter.
8389 *
8390 * @param hDS Dataset handle.
8391 * @param hFieldDomain The domain definition. Contrary to the C++ version,
8392 * the passed object is copied.
8393 * @param ppszFailureReason Output parameter. Will contain an error message if
8394 * an error occurs (*ppszFailureReason to be freed
8395 * with CPLFree). May be NULL.
8396 * @return true in case of success.
8397 * @since GDAL 3.3
8398 */
GDALDatasetAddFieldDomain(GDALDatasetH hDS,OGRFieldDomainH hFieldDomain,char ** ppszFailureReason)8399 bool GDALDatasetAddFieldDomain(GDALDatasetH hDS,
8400 OGRFieldDomainH hFieldDomain,
8401 char** ppszFailureReason)
8402 {
8403 VALIDATE_POINTER1(hDS, __func__, false);
8404 VALIDATE_POINTER1(hFieldDomain, __func__, false);
8405 auto poDomain = std::unique_ptr<OGRFieldDomain>(
8406 OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
8407 if( poDomain == nullptr )
8408 return false;
8409 std::string failureReason;
8410 const bool bRet =
8411 GDALDataset::FromHandle(hDS)->AddFieldDomain(
8412 std::move(poDomain), failureReason);
8413 if( ppszFailureReason )
8414 {
8415 *ppszFailureReason = failureReason.empty() ?
8416 nullptr : CPLStrdup(failureReason.c_str());
8417 }
8418 return bRet;
8419 }
8420
8421 //! @cond Doxygen_Suppress
8422
8423 /************************************************************************/
8424 /* SetEnableOverviews() */
8425 /************************************************************************/
8426
SetEnableOverviews(bool bEnable)8427 void GDALDataset::SetEnableOverviews(bool bEnable)
8428 {
8429 if( m_poPrivate )
8430 {
8431 m_poPrivate->m_bOverviewsEnabled = bEnable;
8432 }
8433 }
8434
8435 /************************************************************************/
8436 /* AreOverviewsEnabled() */
8437 /************************************************************************/
8438
AreOverviewsEnabled() const8439 bool GDALDataset::AreOverviewsEnabled() const
8440 {
8441 return m_poPrivate ? m_poPrivate->m_bOverviewsEnabled : true;
8442 }
8443
8444 //! @endcond
8445