Line data Source code
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 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "cpl_port.h"
15 : #include "gdal.h"
16 : #include "gdal_priv.h"
17 :
18 : #include <climits>
19 : #include <cstdarg>
20 : #include <cstdio>
21 : #include <cstdlib>
22 : #include <cstring>
23 : #include <algorithm>
24 : #include <map>
25 : #include <mutex>
26 : #include <new>
27 : #include <set>
28 : #include <string>
29 : #include <utility>
30 :
31 : #include "cpl_conv.h"
32 : #include "cpl_error.h"
33 : #include "cpl_hash_set.h"
34 : #include "cpl_multiproc.h"
35 : #include "cpl_progress.h"
36 : #include "cpl_string.h"
37 : #include "cpl_vsi.h"
38 : #include "cpl_vsi_error.h"
39 : #include "ogr_api.h"
40 : #include "ogr_attrind.h"
41 : #include "ogr_core.h"
42 : #include "ogr_feature.h"
43 : #include "ogr_featurestyle.h"
44 : #include "ogr_gensql.h"
45 : #include "ogr_geometry.h"
46 : #include "ogr_p.h"
47 : #include "ogr_spatialref.h"
48 : #include "ogr_srs_api.h"
49 : #include "ograpispy.h"
50 : #include "ogrsf_frmts.h"
51 : #include "ogrunionlayer.h"
52 : #include "ogr_swq.h"
53 :
54 : #include "../frmts/derived/derivedlist.h"
55 :
56 : #ifdef SQLITE_ENABLED
57 : #include "../sqlite/ogrsqliteexecutesql.h"
58 : #endif
59 :
60 : extern const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT];
61 :
62 : CPL_C_START
63 : GDALAsyncReader *GDALGetDefaultAsyncReader(GDALDataset *poDS, int nXOff,
64 : int nYOff, int nXSize, int nYSize,
65 : void *pBuf, int nBufXSize,
66 : int nBufYSize, GDALDataType eBufType,
67 : int nBandCount, int *panBandMap,
68 : int nPixelSpace, int nLineSpace,
69 : int nBandSpace, char **papszOptions);
70 : CPL_C_END
71 :
72 : enum class GDALAllowReadWriteMutexState
73 : {
74 : RW_MUTEX_STATE_UNKNOWN,
75 : RW_MUTEX_STATE_ALLOWED,
76 : RW_MUTEX_STATE_DISABLED
77 : };
78 :
79 : const GIntBig TOTAL_FEATURES_NOT_INIT = -2;
80 : const GIntBig TOTAL_FEATURES_UNKNOWN = -1;
81 :
82 : class GDALDataset::Private
83 : {
84 : CPL_DISALLOW_COPY_ASSIGN(Private)
85 :
86 : public:
87 : CPLMutex *hMutex = nullptr;
88 : std::map<GIntBig, int> oMapThreadToMutexTakenCount{};
89 : #ifdef DEBUG_EXTRA
90 : std::map<GIntBig, int> oMapThreadToMutexTakenCountSaved{};
91 : #endif
92 : GDALAllowReadWriteMutexState eStateReadWriteMutex =
93 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN;
94 : int nCurrentLayerIdx = 0;
95 : int nLayerCount = -1;
96 : GIntBig nFeatureReadInLayer = 0;
97 : GIntBig nFeatureReadInDataset = 0;
98 : GIntBig nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
99 : GIntBig nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
100 : OGRLayer *poCurrentLayer = nullptr;
101 :
102 : std::mutex m_oMutexWKT{};
103 :
104 : char *m_pszWKTCached = nullptr;
105 : OGRSpatialReference *m_poSRSCached = nullptr;
106 : char *m_pszWKTGCPCached = nullptr;
107 : OGRSpatialReference *m_poSRSGCPCached = nullptr;
108 :
109 : GDALDataset *poParentDataset = nullptr;
110 :
111 : bool m_bOverviewsEnabled = true;
112 :
113 : std::vector<int>
114 : m_anBandMap{}; // used by RasterIO(). Values are 1, 2, etc.
115 :
116 127103 : Private() = default;
117 : };
118 :
119 : struct SharedDatasetCtxt
120 : {
121 : // PID of the thread that mark the dataset as shared
122 : // This may not be the actual PID, but the responsiblePID.
123 : GIntBig nPID;
124 : char *pszDescription;
125 : char *pszConcatenatedOpenOptions;
126 : int nOpenFlags;
127 :
128 : GDALDataset *poDS;
129 : };
130 :
131 : // Set of datasets opened as shared datasets (with GDALOpenShared)
132 : // The values in the set are of type SharedDatasetCtxt.
133 : static CPLHashSet *phSharedDatasetSet = nullptr;
134 :
135 : // Set of all datasets created in the constructor of GDALDataset.
136 : // In the case of a shared dataset, memorize the PID of the thread
137 : // that marked the dataset as shared, so that we can remove it from
138 : // the phSharedDatasetSet in the destructor of the dataset, even
139 : // if GDALClose is called from a different thread.
140 : static std::map<GDALDataset *, GIntBig> *poAllDatasetMap = nullptr;
141 :
142 : static CPLMutex *hDLMutex = nullptr;
143 :
144 : // Static array of all datasets. Used by GDALGetOpenDatasets.
145 : // Not thread-safe. See GDALGetOpenDatasets.
146 : static GDALDataset **ppDatasets = nullptr;
147 :
148 8295 : static unsigned long GDALSharedDatasetHashFunc(const void *elt)
149 : {
150 8295 : const SharedDatasetCtxt *psStruct =
151 : static_cast<const SharedDatasetCtxt *>(elt);
152 : return static_cast<unsigned long>(
153 8295 : CPLHashSetHashStr(psStruct->pszDescription) ^
154 8295 : CPLHashSetHashStr(psStruct->pszConcatenatedOpenOptions) ^
155 8295 : psStruct->nOpenFlags ^ psStruct->nPID);
156 : }
157 :
158 6932 : static int GDALSharedDatasetEqualFunc(const void *elt1, const void *elt2)
159 : {
160 6932 : const SharedDatasetCtxt *psStruct1 =
161 : static_cast<const SharedDatasetCtxt *>(elt1);
162 6932 : const SharedDatasetCtxt *psStruct2 =
163 : static_cast<const SharedDatasetCtxt *>(elt2);
164 13817 : return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
165 6885 : strcmp(psStruct1->pszConcatenatedOpenOptions,
166 6885 : psStruct2->pszConcatenatedOpenOptions) == 0 &&
167 20702 : psStruct1->nPID == psStruct2->nPID &&
168 13817 : psStruct1->nOpenFlags == psStruct2->nOpenFlags;
169 : }
170 :
171 390 : static void GDALSharedDatasetFreeFunc(void *elt)
172 : {
173 390 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
174 390 : CPLFree(psStruct->pszDescription);
175 390 : CPLFree(psStruct->pszConcatenatedOpenOptions);
176 390 : CPLFree(psStruct);
177 390 : }
178 :
179 : static std::string
180 7006 : GDALSharedDatasetConcatenateOpenOptions(CSLConstList papszOpenOptions)
181 : {
182 7006 : std::string osStr;
183 7019 : for (const char *pszOption : cpl::Iterate(papszOpenOptions))
184 13 : osStr += pszOption;
185 7006 : return osStr;
186 : }
187 :
188 : /************************************************************************/
189 : /* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
190 : /************************************************************************/
191 :
192 : // The open-shared mutex must be used by the ProxyPool too.
193 60981 : CPLMutex **GDALGetphDLMutex()
194 : {
195 60981 : return &hDLMutex;
196 : }
197 :
198 : // The current thread will act in the behalf of the thread of PID
199 : // responsiblePID.
200 53728 : void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
201 : {
202 : GIntBig *pResponsiblePID =
203 53728 : static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
204 53728 : if (pResponsiblePID == nullptr)
205 : {
206 167 : pResponsiblePID = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
207 167 : CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
208 : }
209 53728 : *pResponsiblePID = responsiblePID;
210 53728 : }
211 :
212 : // Get the PID of the thread that the current thread will act in the behalf of
213 : // By default : the current thread acts in the behalf of itself.
214 162724 : GIntBig GDALGetResponsiblePIDForCurrentThread()
215 : {
216 : GIntBig *pResponsiblePID =
217 162724 : static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
218 162627 : if (pResponsiblePID == nullptr)
219 45323 : return CPLGetPID();
220 117304 : return *pResponsiblePID;
221 : }
222 :
223 : /************************************************************************/
224 : /* ==================================================================== */
225 : /* GDALDataset */
226 : /* ==================================================================== */
227 : /************************************************************************/
228 :
229 : /**
230 : * \class GDALDataset "gdal_priv.h"
231 : *
232 : * A dataset encapsulating one or more raster bands. Details are further
233 : * discussed in the <a href="https://gdal.org/user/raster_data_model.html">GDAL
234 : * Raster Data Model</a>.
235 : *
236 : * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,
237 : * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new
238 : * dataset.
239 : */
240 :
241 : /************************************************************************/
242 : /* GDALDataset() */
243 : /************************************************************************/
244 :
245 : //! @cond Doxygen_Suppress
246 111211 : GDALDataset::GDALDataset()
247 111211 : : GDALDataset(CPLTestBool(CPLGetConfigOption("GDAL_FORCE_CACHING", "NO")))
248 : {
249 111134 : }
250 :
251 127121 : GDALDataset::GDALDataset(int bForceCachedIOIn)
252 127021 : : bForceCachedIO(CPL_TO_BOOL(bForceCachedIOIn)),
253 127121 : m_poPrivate(new(std::nothrow) GDALDataset::Private)
254 : {
255 127070 : }
256 :
257 : //! @endcond
258 :
259 : /************************************************************************/
260 : /* ~GDALDataset() */
261 : /************************************************************************/
262 :
263 : /**
264 : * \brief Destroy an open GDALDataset.
265 : *
266 : * This is the accepted method of closing a GDAL dataset and deallocating
267 : * all resources associated with it.
268 : *
269 : * Equivalent of the C callable GDALClose(). Except that GDALClose() first
270 : * decrements the reference count, and then closes only if it has dropped to
271 : * zero.
272 : *
273 : * For Windows users, it is not recommended to use the delete operator on the
274 : * dataset object because of known issues when allocating and freeing memory
275 : * across module boundaries. Calling GDALClose() is then a better option.
276 : */
277 :
278 127118 : GDALDataset::~GDALDataset()
279 :
280 : {
281 : // we don't want to report destruction of datasets that
282 : // were never really open or meant as internal
283 127117 : if (!bIsInternal && (nBands != 0 || !EQUAL(GetDescription(), "")))
284 : {
285 59945 : if (CPLGetPID() != GDALGetResponsiblePIDForCurrentThread())
286 208 : CPLDebug("GDAL",
287 : "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)",
288 208 : GetDescription(), this, static_cast<int>(CPLGetPID()),
289 208 : static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
290 : else
291 59763 : CPLDebug("GDAL", "GDALClose(%s, this=%p)", GetDescription(), this);
292 : }
293 :
294 127164 : if (IsMarkedSuppressOnClose())
295 : {
296 2120 : if (poDriver == nullptr ||
297 : // Someone issuing Create("foo.tif") on a
298 : // memory driver doesn't expect files with those names to be deleted
299 : // on a file system...
300 : // This is somewhat messy. Ideally there should be a way for the
301 : // driver to overload the default behavior
302 1055 : (!EQUAL(poDriver->GetDescription(), "MEM") &&
303 1031 : !EQUAL(poDriver->GetDescription(), "Memory")))
304 : {
305 1041 : VSIUnlink(GetDescription());
306 : }
307 : }
308 :
309 : /* -------------------------------------------------------------------- */
310 : /* Remove dataset from the "open" dataset list. */
311 : /* -------------------------------------------------------------------- */
312 127129 : if (!bIsInternal)
313 : {
314 121276 : CPLMutexHolderD(&hDLMutex);
315 60638 : if (poAllDatasetMap)
316 : {
317 : std::map<GDALDataset *, GIntBig>::iterator oIter =
318 60638 : poAllDatasetMap->find(this);
319 60638 : CPLAssert(oIter != poAllDatasetMap->end());
320 :
321 60638 : UnregisterFromSharedDataset();
322 :
323 60638 : poAllDatasetMap->erase(oIter);
324 :
325 60638 : if (poAllDatasetMap->empty())
326 : {
327 24225 : delete poAllDatasetMap;
328 24225 : poAllDatasetMap = nullptr;
329 24225 : if (phSharedDatasetSet)
330 : {
331 270 : CPLHashSetDestroy(phSharedDatasetSet);
332 : }
333 24225 : phSharedDatasetSet = nullptr;
334 24225 : CPLFree(ppDatasets);
335 24225 : ppDatasets = nullptr;
336 : }
337 : }
338 : }
339 :
340 : /* -------------------------------------------------------------------- */
341 : /* Destroy the raster bands if they exist. */
342 : /* -------------------------------------------------------------------- */
343 941976 : for (int i = 0; i < nBands && papoBands != nullptr; ++i)
344 : {
345 814851 : if (papoBands[i] != nullptr)
346 814851 : delete papoBands[i];
347 814847 : papoBands[i] = nullptr;
348 : }
349 :
350 127125 : CPLFree(papoBands);
351 :
352 127120 : if (m_poStyleTable)
353 : {
354 23 : delete m_poStyleTable;
355 23 : m_poStyleTable = nullptr;
356 : }
357 :
358 127120 : if (m_poPrivate != nullptr)
359 : {
360 127121 : if (m_poPrivate->hMutex != nullptr)
361 14471 : CPLDestroyMutex(m_poPrivate->hMutex);
362 :
363 : // coverity[missing_lock]
364 127121 : CPLFree(m_poPrivate->m_pszWKTCached);
365 127114 : if (m_poPrivate->m_poSRSCached)
366 : {
367 0 : m_poPrivate->m_poSRSCached->Release();
368 : }
369 : // coverity[missing_lock]
370 127114 : CPLFree(m_poPrivate->m_pszWKTGCPCached);
371 127114 : if (m_poPrivate->m_poSRSGCPCached)
372 : {
373 0 : m_poPrivate->m_poSRSGCPCached->Release();
374 : }
375 : }
376 :
377 127113 : delete m_poPrivate;
378 :
379 127116 : CSLDestroy(papszOpenOptions);
380 127117 : }
381 :
382 : /************************************************************************/
383 : /* Close() */
384 : /************************************************************************/
385 :
386 : /** Do final cleanup before a dataset is destroyed.
387 : *
388 : * This method is typically called by GDALClose() or the destructor of a
389 : * GDALDataset subclass. It might also be called by C++ users before
390 : * destroying a dataset. It should not be called on a shared dataset whose
391 : * reference count is greater than one.
392 : *
393 : * It gives a last chance to the closing process to return an error code if
394 : * something goes wrong, in particular in creation / update scenarios where
395 : * file write or network communication might occur when finalizing the dataset.
396 : *
397 : * Implementations should be robust to this method to be called several times
398 : * (on subsequent calls, it should do nothing and return CE_None).
399 : * Once it has been called, no other method than Close() or the dataset
400 : * destructor should be called. RasterBand or OGRLayer owned by the dataset
401 : * should be assumed as no longer being valid.
402 : *
403 : * If a driver implements this method, it must also call it from its
404 : * dataset destructor.
405 : *
406 : * A typical implementation might look as the following
407 : * \code{.cpp}
408 : *
409 : * MyDataset::~MyDataset()
410 : * {
411 : * try
412 : * {
413 : * MyDataset::Close();
414 : * }
415 : * catch (const std::exception &exc)
416 : * {
417 : * // If Close() can throw exception
418 : * CPLError(CE_Failure, CPLE_AppDefined,
419 : * "Exception thrown in MyDataset::Close(): %s",
420 : * exc.what());
421 : * }
422 : * catch (...)
423 : * {
424 : * // If Close() can throw exception
425 : * CPLError(CE_Failure, CPLE_AppDefined,
426 : * "Exception thrown in MyDataset::Close()");
427 : * }
428 : * }
429 : *
430 : * CPLErr MyDataset::Close()
431 : * {
432 : * CPLErr eErr = CE_None;
433 : * if( nOpenFlags != OPEN_FLAGS_CLOSED )
434 : * {
435 : * if( MyDataset::FlushCache(true) != CE_None )
436 : * eErr = CE_Failure;
437 : *
438 : * // Do something driver specific
439 : * if (m_fpImage)
440 : * {
441 : * if( VSIFCloseL(m_fpImage) != 0 )
442 : * {
443 : * CPLError(CE_Failure, CPLE_FileIO, "VSIFCloseL() failed");
444 : * eErr = CE_Failure;
445 : * }
446 : * }
447 : *
448 : * // Call parent Close() implementation.
449 : * if( MyParentDatasetClass::Close() != CE_None )
450 : * eErr = CE_Failure;
451 : * }
452 : * return eErr;
453 : * }
454 : * \endcode
455 : *
456 : * @since GDAL 3.7
457 : */
458 75154 : CPLErr GDALDataset::Close()
459 : {
460 : // Call UnregisterFromSharedDataset() before altering nOpenFlags
461 75154 : UnregisterFromSharedDataset();
462 :
463 75152 : nOpenFlags = OPEN_FLAGS_CLOSED;
464 75152 : return CE_None;
465 : }
466 :
467 : /************************************************************************/
468 : /* UnregisterFromSharedDataset() */
469 : /************************************************************************/
470 :
471 135790 : void GDALDataset::UnregisterFromSharedDataset()
472 : {
473 135790 : if (!(!bIsInternal && bShared && poAllDatasetMap && phSharedDatasetSet))
474 135400 : return;
475 :
476 780 : CPLMutexHolderD(&hDLMutex);
477 :
478 : std::map<GDALDataset *, GIntBig>::iterator oIter =
479 390 : poAllDatasetMap->find(this);
480 390 : CPLAssert(oIter != poAllDatasetMap->end());
481 390 : const GIntBig nPIDCreatorForShared = oIter->second;
482 390 : bShared = false;
483 : SharedDatasetCtxt sStruct;
484 390 : sStruct.nPID = nPIDCreatorForShared;
485 390 : sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
486 390 : sStruct.pszDescription = const_cast<char *>(GetDescription());
487 : std::string osConcatenatedOpenOptions =
488 780 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
489 390 : sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
490 390 : sStruct.poDS = nullptr;
491 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
492 390 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
493 390 : if (psStruct && psStruct->poDS == this)
494 : {
495 389 : CPLHashSetRemove(phSharedDatasetSet, psStruct);
496 : }
497 : else
498 : {
499 1 : CPLDebug("GDAL",
500 : "Should not happen. Cannot find %s, "
501 : "this=%p in phSharedDatasetSet",
502 1 : GetDescription(), this);
503 : }
504 : }
505 :
506 : /************************************************************************/
507 : /* AddToDatasetOpenList() */
508 : /************************************************************************/
509 :
510 62022 : void GDALDataset::AddToDatasetOpenList()
511 : {
512 : /* -------------------------------------------------------------------- */
513 : /* Add this dataset to the open dataset list. */
514 : /* -------------------------------------------------------------------- */
515 62022 : bIsInternal = false;
516 :
517 62022 : CPLMutexHolderD(&hDLMutex);
518 :
519 62022 : if (poAllDatasetMap == nullptr)
520 24228 : poAllDatasetMap = new std::map<GDALDataset *, GIntBig>;
521 62022 : (*poAllDatasetMap)[this] = -1;
522 62021 : }
523 :
524 : /************************************************************************/
525 : /* FlushCache() */
526 : /************************************************************************/
527 :
528 : /**
529 : * \brief Flush all write cached data to disk.
530 : *
531 : * Any raster (or other GDAL) data written via GDAL calls, but buffered
532 : * internally will be written to disk.
533 : *
534 : * The default implementation of this method just calls the FlushCache() method
535 : * on each of the raster bands and the SyncToDisk() method
536 : * on each of the layers. Conceptually, calling FlushCache() on a dataset
537 : * should include any work that might be accomplished by calling SyncToDisk()
538 : * on layers in that dataset.
539 : *
540 : * Using this method does not prevent use from calling GDALClose()
541 : * to properly close a dataset and ensure that important data not addressed
542 : * by FlushCache() is written in the file.
543 : *
544 : * This method is the same as the C function GDALFlushCache().
545 : *
546 : * @param bAtClosing Whether this is called from a GDALDataset destructor
547 : * @return CE_None in case of success (note: return value added in GDAL 3.7)
548 : */
549 :
550 94721 : CPLErr GDALDataset::FlushCache(bool bAtClosing)
551 :
552 : {
553 94721 : CPLErr eErr = CE_None;
554 : // This sometimes happens if a dataset is destroyed before completely
555 : // built.
556 :
557 94721 : if (papoBands)
558 : {
559 1265690 : for (int i = 0; i < nBands; ++i)
560 : {
561 1178570 : if (papoBands[i])
562 : {
563 1178570 : if (papoBands[i]->FlushCache(bAtClosing) != CE_None)
564 7 : eErr = CE_Failure;
565 : }
566 : }
567 : }
568 :
569 94721 : const int nLayers = GetLayerCount();
570 : // cppcheck-suppress knownConditionTrueFalse
571 94721 : if (nLayers > 0)
572 : {
573 6890 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
574 11811 : for (int i = 0; i < nLayers; ++i)
575 : {
576 8366 : OGRLayer *poLayer = GetLayer(i);
577 :
578 8366 : if (poLayer)
579 : {
580 8366 : if (poLayer->SyncToDisk() != OGRERR_NONE)
581 0 : eErr = CE_Failure;
582 : }
583 : }
584 : }
585 :
586 94721 : return eErr;
587 : }
588 :
589 : /************************************************************************/
590 : /* GDALFlushCache() */
591 : /************************************************************************/
592 :
593 : /**
594 : * \brief Flush all write cached data to disk.
595 : *
596 : * @see GDALDataset::FlushCache().
597 : * @return CE_None in case of success (note: return value added in GDAL 3.7)
598 : */
599 :
600 4198 : CPLErr CPL_STDCALL GDALFlushCache(GDALDatasetH hDS)
601 :
602 : {
603 4198 : VALIDATE_POINTER1(hDS, "GDALFlushCache", CE_Failure);
604 :
605 4198 : return GDALDataset::FromHandle(hDS)->FlushCache(false);
606 : }
607 :
608 : /************************************************************************/
609 : /* DropCache() */
610 : /************************************************************************/
611 :
612 : /**
613 : * \brief Drop all write cached data
614 : *
615 : * This method is the same as the C function GDALDropCache().
616 : *
617 : * @return CE_None in case of success
618 : * @since 3.9
619 : */
620 :
621 1 : CPLErr GDALDataset::DropCache()
622 :
623 : {
624 1 : CPLErr eErr = CE_None;
625 :
626 1 : if (papoBands)
627 : {
628 2 : for (int i = 0; i < nBands; ++i)
629 : {
630 1 : if (papoBands[i])
631 : {
632 1 : if (papoBands[i]->DropCache() != CE_None)
633 0 : eErr = CE_Failure;
634 : }
635 : }
636 : }
637 :
638 1 : return eErr;
639 : }
640 :
641 : /************************************************************************/
642 : /* GDALDropCache() */
643 : /************************************************************************/
644 :
645 : /**
646 : * \brief Drop all write cached data
647 : *
648 : * @see GDALDataset::DropCache().
649 : * @return CE_None in case of success
650 : * @since 3.9
651 : */
652 :
653 0 : CPLErr CPL_STDCALL GDALDropCache(GDALDatasetH hDS)
654 :
655 : {
656 0 : VALIDATE_POINTER1(hDS, "GDALDropCache", CE_Failure);
657 :
658 0 : return GDALDataset::FromHandle(hDS)->DropCache();
659 : }
660 :
661 : /************************************************************************/
662 : /* GetEstimatedRAMUsage() */
663 : /************************************************************************/
664 :
665 : /**
666 : * \brief Return the intrinsic RAM usage of this dataset.
667 : *
668 : * The returned value should take into account caches in the underlying driver
669 : * and decoding library, but not the usage related to the GDAL block cache.
670 : *
671 : * At time of writing, this method is only implemented in the JP2OpenJPEG
672 : * driver. For single-tiled JPEG2000 images, the decoding of the image,
673 : * even partially, involves allocating at least
674 : * width * height * number_of_bands * sizeof(uint32_t) bytes inside the libopenjp2
675 : * library.
676 : *
677 : * This method is used by the GDALDatasetPool class, itself used by the GDAL VRT
678 : * driver, to determine how long a dataset in the pool must be kept open, given
679 : * the RAM usage of the dataset with respect to the usable total RAM.
680 : *
681 : * @since GDAL 3.7
682 : * @return RAM usage in bytes, or -1 if unknown (the default implementation
683 : * returns -1)
684 : */
685 :
686 1072 : GIntBig GDALDataset::GetEstimatedRAMUsage()
687 : {
688 1072 : return -1;
689 : }
690 :
691 : /************************************************************************/
692 : /* BlockBasedFlushCache() */
693 : /* */
694 : /* This helper method can be called by the */
695 : /* GDALDataset::FlushCache() for particular drivers to ensure */
696 : /* that buffers will be flushed in a manner suitable for pixel */
697 : /* interleaved (by block) IO. That is, if all the bands have */
698 : /* the same size blocks then a given block will be flushed for */
699 : /* all bands before proceeding to the next block. */
700 : /************************************************************************/
701 :
702 : //! @cond Doxygen_Suppress
703 346 : CPLErr GDALDataset::BlockBasedFlushCache(bool bAtClosing)
704 :
705 : {
706 346 : GDALRasterBand *poBand1 = GetRasterBand(1);
707 346 : if (poBand1 == nullptr || (IsMarkedSuppressOnClose() && bAtClosing))
708 : {
709 7 : return GDALDataset::FlushCache(bAtClosing);
710 : }
711 :
712 339 : int nBlockXSize = 0;
713 339 : int nBlockYSize = 0;
714 339 : poBand1->GetBlockSize(&nBlockXSize, &nBlockYSize);
715 :
716 : /* -------------------------------------------------------------------- */
717 : /* Verify that all bands match. */
718 : /* -------------------------------------------------------------------- */
719 1104 : for (int iBand = 1; iBand < nBands; ++iBand)
720 : {
721 765 : GDALRasterBand *poBand = GetRasterBand(iBand + 1);
722 :
723 : int nThisBlockXSize, nThisBlockYSize;
724 765 : poBand->GetBlockSize(&nThisBlockXSize, &nThisBlockYSize);
725 765 : if (nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize)
726 : {
727 0 : return GDALDataset::FlushCache(bAtClosing);
728 : }
729 : }
730 :
731 : /* -------------------------------------------------------------------- */
732 : /* Now flush writable data. */
733 : /* -------------------------------------------------------------------- */
734 790 : for (int iY = 0; iY < poBand1->nBlocksPerColumn; ++iY)
735 : {
736 991 : for (int iX = 0; iX < poBand1->nBlocksPerRow; ++iX)
737 : {
738 1690 : for (int iBand = 0; iBand < nBands; ++iBand)
739 : {
740 1150 : const CPLErr eErr = papoBands[iBand]->FlushBlock(iX, iY);
741 :
742 1150 : if (eErr != CE_None)
743 0 : return CE_Failure;
744 : }
745 : }
746 : }
747 339 : return CE_None;
748 : }
749 :
750 : /************************************************************************/
751 : /* RasterInitialize() */
752 : /* */
753 : /* Initialize raster size */
754 : /************************************************************************/
755 :
756 0 : void GDALDataset::RasterInitialize(int nXSize, int nYSize)
757 :
758 : {
759 0 : CPLAssert(nXSize > 0 && nYSize > 0);
760 :
761 0 : nRasterXSize = nXSize;
762 0 : nRasterYSize = nYSize;
763 0 : }
764 :
765 : //! @endcond
766 :
767 : /************************************************************************/
768 : /* AddBand() */
769 : /************************************************************************/
770 :
771 : /**
772 : * \fn GDALDataset::AddBand(GDALDataType, char**)
773 : * \brief Add a band to a dataset.
774 : *
775 : * This method will add a new band to the dataset if the underlying format
776 : * supports this action. Most formats do not.
777 : *
778 : * Note that the new GDALRasterBand is not returned. It may be fetched
779 : * after successful completion of the method by calling
780 : * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest
781 : * band will always be the last band.
782 : *
783 : * @param eType the data type of the pixels in the new band.
784 : *
785 : * @param papszOptions a list of NAME=VALUE option strings. The supported
786 : * options are format specific. NULL may be passed by default.
787 : *
788 : * @return CE_None on success or CE_Failure on failure.
789 : */
790 :
791 0 : CPLErr GDALDataset::AddBand(CPL_UNUSED GDALDataType eType,
792 : CPL_UNUSED char **papszOptions)
793 :
794 : {
795 0 : ReportError(CE_Failure, CPLE_NotSupported,
796 : "Dataset does not support the AddBand() method.");
797 :
798 0 : return CE_Failure;
799 : }
800 :
801 : /************************************************************************/
802 : /* GDALAddBand() */
803 : /************************************************************************/
804 :
805 : /**
806 : * \brief Add a band to a dataset.
807 : *
808 : * @see GDALDataset::AddBand().
809 : */
810 :
811 61 : CPLErr CPL_STDCALL GDALAddBand(GDALDatasetH hDataset, GDALDataType eType,
812 : CSLConstList papszOptions)
813 :
814 : {
815 61 : VALIDATE_POINTER1(hDataset, "GDALAddBand", CE_Failure);
816 :
817 122 : return GDALDataset::FromHandle(hDataset)->AddBand(
818 61 : eType, const_cast<char **>(papszOptions));
819 : }
820 :
821 : /************************************************************************/
822 : /* SetBand() */
823 : /************************************************************************/
824 :
825 : //! @cond Doxygen_Suppress
826 : /** Set a band in the band array, updating the band count, and array size
827 : * appropriately.
828 : *
829 : * @param nNewBand new band number (indexing starts at 1)
830 : * @param poBand band object.
831 : */
832 :
833 1029790 : void GDALDataset::SetBand(int nNewBand, GDALRasterBand *poBand)
834 :
835 : {
836 : /* -------------------------------------------------------------------- */
837 : /* Do we need to grow the bands list? */
838 : /* -------------------------------------------------------------------- */
839 1029790 : if (nBands < nNewBand || papoBands == nullptr)
840 : {
841 529182 : GDALRasterBand **papoNewBands = nullptr;
842 :
843 529182 : if (papoBands == nullptr)
844 77924 : papoNewBands = static_cast<GDALRasterBand **>(VSICalloc(
845 77890 : sizeof(GDALRasterBand *), std::max(nNewBand, nBands)));
846 : else
847 : papoNewBands = static_cast<GDALRasterBand **>(
848 451266 : VSIRealloc(papoBands, sizeof(GDALRasterBand *) *
849 451292 : std::max(nNewBand, nBands)));
850 529190 : if (papoNewBands == nullptr)
851 : {
852 0 : ReportError(CE_Failure, CPLE_OutOfMemory,
853 : "Cannot allocate band array");
854 0 : return;
855 : }
856 :
857 529190 : papoBands = papoNewBands;
858 :
859 1013710 : for (int i = nBands; i < nNewBand; ++i)
860 484518 : papoBands[i] = nullptr;
861 :
862 529190 : nBands = std::max(nBands, nNewBand);
863 :
864 529164 : if (m_poPrivate)
865 : {
866 529282 : for (int i = static_cast<int>(m_poPrivate->m_anBandMap.size());
867 1558900 : i < nBands; ++i)
868 : {
869 1029700 : m_poPrivate->m_anBandMap.push_back(i + 1);
870 : }
871 : }
872 : }
873 :
874 : /* -------------------------------------------------------------------- */
875 : /* Set the band. Resetting the band is currently not permitted. */
876 : /* -------------------------------------------------------------------- */
877 1029700 : if (papoBands[nNewBand - 1] != nullptr)
878 : {
879 0 : ReportError(CE_Failure, CPLE_NotSupported,
880 : "Cannot set band %d as it is already set", nNewBand);
881 0 : return;
882 : }
883 :
884 1029700 : papoBands[nNewBand - 1] = poBand;
885 :
886 : /* -------------------------------------------------------------------- */
887 : /* Set back reference information on the raster band. Note */
888 : /* that the GDALDataset is a friend of the GDALRasterBand */
889 : /* specifically to allow this. */
890 : /* -------------------------------------------------------------------- */
891 1029700 : poBand->nBand = nNewBand;
892 1029700 : poBand->poDS = this;
893 1029700 : poBand->nRasterXSize = nRasterXSize;
894 1029700 : poBand->nRasterYSize = nRasterYSize;
895 1029700 : poBand->eAccess = eAccess; // Default access to be same as dataset.
896 : }
897 :
898 : //! @endcond
899 :
900 : /************************************************************************/
901 : /* SetBand() */
902 : /************************************************************************/
903 :
904 : //! @cond Doxygen_Suppress
905 : /** Set a band in the band array, updating the band count, and array size
906 : * appropriately.
907 : *
908 : * @param nNewBand new band number (indexing starts at 1)
909 : * @param poBand band object.
910 : */
911 :
912 4672 : void GDALDataset::SetBand(int nNewBand, std::unique_ptr<GDALRasterBand> poBand)
913 : {
914 4672 : SetBand(nNewBand, poBand.release());
915 4672 : }
916 :
917 : //! @endcond
918 :
919 : /************************************************************************/
920 : /* GetRasterXSize() */
921 : /************************************************************************/
922 :
923 : /**
924 :
925 : \brief Fetch raster width in pixels.
926 :
927 : Equivalent of the C function GDALGetRasterXSize().
928 :
929 : @return the width in pixels of raster bands in this GDALDataset.
930 :
931 : */
932 :
933 378420 : int GDALDataset::GetRasterXSize() const
934 : {
935 378420 : return nRasterXSize;
936 : }
937 :
938 : /************************************************************************/
939 : /* GDALGetRasterXSize() */
940 : /************************************************************************/
941 :
942 : /**
943 : * \brief Fetch raster width in pixels.
944 : *
945 : * @see GDALDataset::GetRasterXSize().
946 : */
947 :
948 31814 : int CPL_STDCALL GDALGetRasterXSize(GDALDatasetH hDataset)
949 :
950 : {
951 31814 : VALIDATE_POINTER1(hDataset, "GDALGetRasterXSize", 0);
952 :
953 31814 : return GDALDataset::FromHandle(hDataset)->GetRasterXSize();
954 : }
955 :
956 : /************************************************************************/
957 : /* GetRasterYSize() */
958 : /************************************************************************/
959 :
960 : /**
961 :
962 : \brief Fetch raster height in pixels.
963 :
964 : Equivalent of the C function GDALGetRasterYSize().
965 :
966 : @return the height in pixels of raster bands in this GDALDataset.
967 :
968 : */
969 :
970 279398 : int GDALDataset::GetRasterYSize() const
971 : {
972 279398 : return nRasterYSize;
973 : }
974 :
975 : /************************************************************************/
976 : /* GDALGetRasterYSize() */
977 : /************************************************************************/
978 :
979 : /**
980 : * \brief Fetch raster height in pixels.
981 : *
982 : * @see GDALDataset::GetRasterYSize().
983 : */
984 :
985 31531 : int CPL_STDCALL GDALGetRasterYSize(GDALDatasetH hDataset)
986 :
987 : {
988 31531 : VALIDATE_POINTER1(hDataset, "GDALGetRasterYSize", 0);
989 :
990 31531 : return GDALDataset::FromHandle(hDataset)->GetRasterYSize();
991 : }
992 :
993 : /************************************************************************/
994 : /* GetRasterBand() */
995 : /************************************************************************/
996 :
997 : /**
998 :
999 : \brief Fetch a band object for a dataset.
1000 :
1001 : See GetBands() for a C++ iterator version of this method.
1002 :
1003 : Equivalent of the C function GDALGetRasterBand().
1004 :
1005 : @param nBandId the index number of the band to fetch, from 1 to
1006 : GetRasterCount().
1007 :
1008 : @return the nBandId th band object
1009 :
1010 : */
1011 :
1012 9124160 : GDALRasterBand *GDALDataset::GetRasterBand(int nBandId)
1013 :
1014 : {
1015 9124160 : if (papoBands)
1016 : {
1017 9119080 : if (nBandId < 1 || nBandId > nBands)
1018 : {
1019 6828 : ReportError(CE_Failure, CPLE_IllegalArg,
1020 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1021 : nBandId);
1022 13 : return nullptr;
1023 : }
1024 :
1025 9112260 : return papoBands[nBandId - 1];
1026 : }
1027 5073 : return nullptr;
1028 : }
1029 :
1030 : /************************************************************************/
1031 : /* GetRasterBand() */
1032 : /************************************************************************/
1033 :
1034 : /**
1035 :
1036 : \brief Fetch a band object for a dataset.
1037 :
1038 : See GetBands() for a C++ iterator version of this method.
1039 :
1040 : Equivalent of the C function GDALGetRasterBand().
1041 :
1042 : @param nBandId the index number of the band to fetch, from 1 to
1043 : GetRasterCount().
1044 :
1045 : @return the nBandId th band object
1046 :
1047 : */
1048 :
1049 0 : const GDALRasterBand *GDALDataset::GetRasterBand(int nBandId) const
1050 :
1051 : {
1052 0 : if (papoBands)
1053 : {
1054 0 : if (nBandId < 1 || nBandId > nBands)
1055 : {
1056 0 : ReportError(CE_Failure, CPLE_IllegalArg,
1057 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1058 : nBandId);
1059 0 : return nullptr;
1060 : }
1061 :
1062 0 : return papoBands[nBandId - 1];
1063 : }
1064 0 : return nullptr;
1065 : }
1066 :
1067 : /************************************************************************/
1068 : /* GDALGetRasterBand() */
1069 : /************************************************************************/
1070 :
1071 : /**
1072 : * \brief Fetch a band object for a dataset.
1073 : * @see GDALDataset::GetRasterBand().
1074 : */
1075 :
1076 282579 : GDALRasterBandH CPL_STDCALL GDALGetRasterBand(GDALDatasetH hDS, int nBandId)
1077 :
1078 : {
1079 282579 : VALIDATE_POINTER1(hDS, "GDALGetRasterBand", nullptr);
1080 :
1081 282579 : return GDALRasterBand::ToHandle(
1082 282580 : GDALDataset::FromHandle(hDS)->GetRasterBand(nBandId));
1083 : }
1084 :
1085 : /************************************************************************/
1086 : /* GetRasterCount() */
1087 : /************************************************************************/
1088 :
1089 : /**
1090 : * \brief Fetch the number of raster bands on this dataset.
1091 : *
1092 : * Same as the C function GDALGetRasterCount().
1093 : *
1094 : * @return the number of raster bands.
1095 : */
1096 :
1097 4139980 : int GDALDataset::GetRasterCount() const
1098 : {
1099 4139980 : return papoBands ? nBands : 0;
1100 : }
1101 :
1102 : /************************************************************************/
1103 : /* GDALGetRasterCount() */
1104 : /************************************************************************/
1105 :
1106 : /**
1107 : * \brief Fetch the number of raster bands on this dataset.
1108 : *
1109 : * @see GDALDataset::GetRasterCount().
1110 : */
1111 :
1112 373401 : int CPL_STDCALL GDALGetRasterCount(GDALDatasetH hDS)
1113 :
1114 : {
1115 373401 : VALIDATE_POINTER1(hDS, "GDALGetRasterCount", 0);
1116 :
1117 373401 : return GDALDataset::FromHandle(hDS)->GetRasterCount();
1118 : }
1119 :
1120 : /************************************************************************/
1121 : /* GetProjectionRef() */
1122 : /************************************************************************/
1123 :
1124 : /**
1125 : * \brief Fetch the projection definition string for this dataset.
1126 : *
1127 : * Same as the C function GDALGetProjectionRef().
1128 : *
1129 : * The returned string defines the projection coordinate system of the
1130 : * image in OpenGIS WKT format. It should be suitable for use with the
1131 : * OGRSpatialReference class.
1132 : *
1133 : * When a projection definition is not available an empty (but not NULL)
1134 : * string is returned.
1135 : *
1136 : * \note Starting with GDAL 3.0, this is a compatibility layer around
1137 : * GetSpatialRef()
1138 : *
1139 : * @return a pointer to an internal projection reference string. It should
1140 : * not be altered, freed or expected to last for long.
1141 : *
1142 : * @see https://gdal.org/tutorials/osr_api_tut.html
1143 : */
1144 :
1145 6037 : const char *GDALDataset::GetProjectionRef() const
1146 : {
1147 6037 : const auto poSRS = GetSpatialRef();
1148 6037 : if (!poSRS || !m_poPrivate)
1149 : {
1150 2551 : return "";
1151 : }
1152 3486 : char *pszWKT = nullptr;
1153 3486 : poSRS->exportToWkt(&pszWKT);
1154 3486 : if (!pszWKT)
1155 : {
1156 0 : return "";
1157 : }
1158 :
1159 : // If called on a thread-safe dataset, we might be called by several
1160 : // threads, so make sure our accesses to m_pszWKTCached are protected
1161 : // by a mutex.
1162 6972 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1163 3486 : if (m_poPrivate->m_pszWKTCached &&
1164 1292 : strcmp(pszWKT, m_poPrivate->m_pszWKTCached) == 0)
1165 : {
1166 1291 : CPLFree(pszWKT);
1167 1291 : return m_poPrivate->m_pszWKTCached;
1168 : }
1169 2195 : CPLFree(m_poPrivate->m_pszWKTCached);
1170 2195 : m_poPrivate->m_pszWKTCached = pszWKT;
1171 2195 : return m_poPrivate->m_pszWKTCached;
1172 : }
1173 :
1174 : /************************************************************************/
1175 : /* GetSpatialRef() */
1176 : /************************************************************************/
1177 :
1178 : /**
1179 : * \brief Fetch the spatial reference for this dataset.
1180 : *
1181 : * Same as the C function GDALGetSpatialRef().
1182 : *
1183 : * When a projection definition is not available, null is returned. If used on
1184 : * a dataset where there are GCPs and not a geotransform, this method returns
1185 : * null. Use GetGCPSpatialRef() instead.
1186 : *
1187 : * @since GDAL 3.0
1188 : *
1189 : * @return a pointer to an internal object. It should not be altered or freed.
1190 : * Its lifetime will be the one of the dataset object, or until the next
1191 : * call to this method.
1192 : *
1193 : * @see https://gdal.org/tutorials/osr_api_tut.html
1194 : */
1195 :
1196 13728 : const OGRSpatialReference *GDALDataset::GetSpatialRef() const
1197 : {
1198 13728 : return nullptr;
1199 : }
1200 :
1201 : /************************************************************************/
1202 : /* GDALGetSpatialRef() */
1203 : /************************************************************************/
1204 :
1205 : /**
1206 : * \brief Fetch the spatial reference for this dataset.
1207 : *
1208 : * @since GDAL 3.0
1209 : *
1210 : * @see GDALDataset::GetSpatialRef()
1211 : */
1212 :
1213 5727 : OGRSpatialReferenceH GDALGetSpatialRef(GDALDatasetH hDS)
1214 :
1215 : {
1216 5727 : VALIDATE_POINTER1(hDS, "GDALGetSpatialRef", nullptr);
1217 :
1218 5727 : return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1219 5727 : GDALDataset::FromHandle(hDS)->GetSpatialRef()));
1220 : }
1221 :
1222 : /************************************************************************/
1223 : /* GDALGetProjectionRef() */
1224 : /************************************************************************/
1225 :
1226 : /**
1227 : * \brief Fetch the projection definition string for this dataset.
1228 : *
1229 : * @see GDALDataset::GetProjectionRef()
1230 : */
1231 :
1232 1372 : const char *CPL_STDCALL GDALGetProjectionRef(GDALDatasetH hDS)
1233 :
1234 : {
1235 1372 : VALIDATE_POINTER1(hDS, "GDALGetProjectionRef", nullptr);
1236 :
1237 1372 : return GDALDataset::FromHandle(hDS)->GetProjectionRef();
1238 : }
1239 :
1240 : /************************************************************************/
1241 : /* SetProjection() */
1242 : /************************************************************************/
1243 :
1244 : /**
1245 : * \brief Set the projection reference string for this dataset.
1246 : *
1247 : * The string should be in OGC WKT or PROJ.4 format. An error may occur
1248 : * because of incorrectly specified projection strings, because the dataset
1249 : * is not writable, or because the dataset does not support the indicated
1250 : * projection. Many formats do not support writing projections.
1251 : *
1252 : * This method is the same as the C GDALSetProjection() function.
1253 : *
1254 : * \note Startig with GDAL 3.0, this is a compatibility layer around
1255 : * SetSpatialRef()
1256 :
1257 : * @param pszProjection projection reference string.
1258 : *
1259 : * @return CE_Failure if an error occurs, otherwise CE_None.
1260 : */
1261 :
1262 2432 : CPLErr GDALDataset::SetProjection(const char *pszProjection)
1263 : {
1264 2432 : if (pszProjection && pszProjection[0] != '\0')
1265 : {
1266 4574 : OGRSpatialReference oSRS;
1267 2287 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1268 2287 : if (oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE)
1269 : {
1270 2 : return CE_Failure;
1271 : }
1272 2285 : return SetSpatialRef(&oSRS);
1273 : }
1274 : else
1275 : {
1276 145 : return SetSpatialRef(nullptr);
1277 : }
1278 : }
1279 :
1280 : /************************************************************************/
1281 : /* SetSpatialRef() */
1282 : /************************************************************************/
1283 :
1284 : /**
1285 : * \brief Set the spatial reference system for this dataset.
1286 : *
1287 : * An error may occur because the dataset
1288 : * is not writable, or because the dataset does not support the indicated
1289 : * projection. Many formats do not support writing projections.
1290 : *
1291 : * This method is the same as the C GDALSetSpatialRef() function.
1292 : *
1293 : * @since GDAL 3.0
1294 :
1295 : * @param poSRS spatial reference system object. nullptr can potentially be
1296 : * passed for drivers that support unsetting the SRS.
1297 : *
1298 : * @return CE_Failure if an error occurs, otherwise CE_None.
1299 : */
1300 :
1301 0 : CPLErr GDALDataset::SetSpatialRef(CPL_UNUSED const OGRSpatialReference *poSRS)
1302 : {
1303 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1304 0 : ReportError(CE_Failure, CPLE_NotSupported,
1305 : "Dataset does not support the SetSpatialRef() method.");
1306 0 : return CE_Failure;
1307 : }
1308 :
1309 : /************************************************************************/
1310 : /* GDALSetSpatialRef() */
1311 : /************************************************************************/
1312 :
1313 : /**
1314 : * \brief Set the spatial reference system for this dataset.
1315 : *
1316 : * @since GDAL 3.0
1317 : *
1318 : * @see GDALDataset::SetSpatialRef()
1319 : */
1320 :
1321 967 : CPLErr GDALSetSpatialRef(GDALDatasetH hDS, OGRSpatialReferenceH hSRS)
1322 :
1323 : {
1324 967 : VALIDATE_POINTER1(hDS, "GDALSetSpatialRef", CE_Failure);
1325 :
1326 1934 : return GDALDataset::FromHandle(hDS)->SetSpatialRef(
1327 967 : OGRSpatialReference::FromHandle(hSRS));
1328 : }
1329 :
1330 : /************************************************************************/
1331 : /* GDALSetProjection() */
1332 : /************************************************************************/
1333 :
1334 : /**
1335 : * \brief Set the projection reference string for this dataset.
1336 : *
1337 : * @see GDALDataset::SetProjection()
1338 : */
1339 :
1340 1936 : CPLErr CPL_STDCALL GDALSetProjection(GDALDatasetH hDS,
1341 : const char *pszProjection)
1342 :
1343 : {
1344 1936 : VALIDATE_POINTER1(hDS, "GDALSetProjection", CE_Failure);
1345 :
1346 1936 : return GDALDataset::FromHandle(hDS)->SetProjection(pszProjection);
1347 : }
1348 :
1349 : /************************************************************************/
1350 : /* GetGeoTransform() */
1351 : /************************************************************************/
1352 :
1353 : /**
1354 : * \brief Fetch the affine transformation coefficients.
1355 : *
1356 : * Fetches the coefficients for transforming between pixel/line (P,L) raster
1357 : * space, and projection coordinates (Xp,Yp) space.
1358 : *
1359 : * \code
1360 : * Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
1361 : * Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
1362 : * \endcode
1363 : *
1364 : * In a north up image, padfTransform[1] is the pixel width, and
1365 : * padfTransform[5] is the pixel height. The upper left corner of the
1366 : * upper left pixel is at position (padfTransform[0],padfTransform[3]).
1367 : *
1368 : * The default transform is (0,1,0,0,0,1) and should be returned even when
1369 : * a CE_Failure error is returned, such as for formats that don't support
1370 : * transformation to projection coordinates.
1371 : *
1372 : * This method does the same thing as the C GDALGetGeoTransform() function.
1373 : *
1374 : * @param padfTransform an existing six double buffer into which the
1375 : * transformation will be placed.
1376 : *
1377 : * @return CE_None on success, or CE_Failure if no transform can be fetched.
1378 : */
1379 :
1380 12075 : CPLErr GDALDataset::GetGeoTransform(double *padfTransform)
1381 :
1382 : {
1383 12075 : CPLAssert(padfTransform != nullptr);
1384 :
1385 12075 : padfTransform[0] = 0.0; // X Origin (top left corner)
1386 12075 : padfTransform[1] = 1.0; // X Pixel size */
1387 12075 : padfTransform[2] = 0.0;
1388 :
1389 12075 : padfTransform[3] = 0.0; // Y Origin (top left corner)
1390 12075 : padfTransform[4] = 0.0;
1391 12075 : padfTransform[5] = 1.0; // Y Pixel Size
1392 :
1393 12075 : return CE_Failure;
1394 : }
1395 :
1396 : /************************************************************************/
1397 : /* GDALGetGeoTransform() */
1398 : /************************************************************************/
1399 :
1400 : /**
1401 : * \brief Fetch the affine transformation coefficients.
1402 : *
1403 : * @see GDALDataset::GetGeoTransform()
1404 : */
1405 :
1406 7674 : CPLErr CPL_STDCALL GDALGetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1407 :
1408 : {
1409 7674 : VALIDATE_POINTER1(hDS, "GDALGetGeoTransform", CE_Failure);
1410 :
1411 7674 : return GDALDataset::FromHandle(hDS)->GetGeoTransform(padfTransform);
1412 : }
1413 :
1414 : /************************************************************************/
1415 : /* SetGeoTransform() */
1416 : /************************************************************************/
1417 :
1418 : /**
1419 : * \fn GDALDataset::SetGeoTransform(double*)
1420 : * \brief Set the affine transformation coefficients.
1421 : *
1422 : * See GetGeoTransform() for details on the meaning of the padfTransform
1423 : * coefficients.
1424 : *
1425 : * This method does the same thing as the C GDALSetGeoTransform() function.
1426 : *
1427 : * @param padfTransform a six double buffer containing the transformation
1428 : * coefficients to be written with the dataset.
1429 : *
1430 : * @return CE_None on success, or CE_Failure if this transform cannot be
1431 : * written.
1432 : */
1433 :
1434 0 : CPLErr GDALDataset::SetGeoTransform(CPL_UNUSED double *padfTransform)
1435 :
1436 : {
1437 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1438 0 : ReportError(CE_Failure, CPLE_NotSupported,
1439 : "SetGeoTransform() not supported for this dataset.");
1440 :
1441 0 : return CE_Failure;
1442 : }
1443 :
1444 : /************************************************************************/
1445 : /* GDALSetGeoTransform() */
1446 : /************************************************************************/
1447 :
1448 : /**
1449 : * \brief Set the affine transformation coefficients.
1450 : *
1451 : * @see GDALDataset::SetGeoTransform()
1452 : */
1453 :
1454 3674 : CPLErr CPL_STDCALL GDALSetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1455 :
1456 : {
1457 3674 : VALIDATE_POINTER1(hDS, "GDALSetGeoTransform", CE_Failure);
1458 :
1459 3674 : return GDALDataset::FromHandle(hDS)->SetGeoTransform(padfTransform);
1460 : }
1461 :
1462 : /************************************************************************/
1463 : /* GetInternalHandle() */
1464 : /************************************************************************/
1465 :
1466 : /**
1467 : * \fn GDALDataset::GetInternalHandle(const char*)
1468 : * \brief Fetch a format specific internally meaningful handle.
1469 : *
1470 : * This method is the same as the C GDALGetInternalHandle() method.
1471 : *
1472 : * @param pszHandleName the handle name desired. The meaningful names
1473 : * will be specific to the file format.
1474 : *
1475 : * @return the desired handle value, or NULL if not recognized/supported.
1476 : */
1477 :
1478 0 : void *GDALDataset::GetInternalHandle(CPL_UNUSED const char *pszHandleName)
1479 :
1480 : {
1481 0 : return nullptr;
1482 : }
1483 :
1484 : /************************************************************************/
1485 : /* GDALGetInternalHandle() */
1486 : /************************************************************************/
1487 :
1488 : /**
1489 : * \brief Fetch a format specific internally meaningful handle.
1490 : *
1491 : * @see GDALDataset::GetInternalHandle()
1492 : */
1493 :
1494 58 : void *CPL_STDCALL GDALGetInternalHandle(GDALDatasetH hDS,
1495 : const char *pszRequest)
1496 :
1497 : {
1498 58 : VALIDATE_POINTER1(hDS, "GDALGetInternalHandle", nullptr);
1499 :
1500 58 : return GDALDataset::FromHandle(hDS)->GetInternalHandle(pszRequest);
1501 : }
1502 :
1503 : /************************************************************************/
1504 : /* GetDriver() */
1505 : /************************************************************************/
1506 :
1507 : /**
1508 : * \brief Fetch the driver to which this dataset relates.
1509 : *
1510 : * This method is the same as the C GDALGetDatasetDriver() function.
1511 : *
1512 : * @return the driver on which the dataset was created with GDALOpen() or
1513 : * GDALCreate().
1514 : */
1515 :
1516 26628 : GDALDriver *GDALDataset::GetDriver()
1517 : {
1518 26628 : return poDriver;
1519 : }
1520 :
1521 : /************************************************************************/
1522 : /* GDALGetDatasetDriver() */
1523 : /************************************************************************/
1524 :
1525 : /**
1526 : * \brief Fetch the driver to which this dataset relates.
1527 : *
1528 : * @see GDALDataset::GetDriver()
1529 : */
1530 :
1531 2659 : GDALDriverH CPL_STDCALL GDALGetDatasetDriver(GDALDatasetH hDataset)
1532 :
1533 : {
1534 2659 : VALIDATE_POINTER1(hDataset, "GDALGetDatasetDriver", nullptr);
1535 :
1536 : return static_cast<GDALDriverH>(
1537 2659 : GDALDataset::FromHandle(hDataset)->GetDriver());
1538 : }
1539 :
1540 : /************************************************************************/
1541 : /* Reference() */
1542 : /************************************************************************/
1543 :
1544 : /**
1545 : * \brief Add one to dataset reference count.
1546 : *
1547 : * The reference is one after instantiation.
1548 : *
1549 : * This method is the same as the C GDALReferenceDataset() function.
1550 : *
1551 : * @return the post-increment reference count.
1552 : */
1553 :
1554 18428 : int GDALDataset::Reference()
1555 : {
1556 18428 : return ++nRefCount;
1557 : }
1558 :
1559 : /************************************************************************/
1560 : /* GDALReferenceDataset() */
1561 : /************************************************************************/
1562 :
1563 : /**
1564 : * \brief Add one to dataset reference count.
1565 : *
1566 : * @see GDALDataset::Reference()
1567 : */
1568 :
1569 1065 : int CPL_STDCALL GDALReferenceDataset(GDALDatasetH hDataset)
1570 :
1571 : {
1572 1065 : VALIDATE_POINTER1(hDataset, "GDALReferenceDataset", 0);
1573 :
1574 1065 : return GDALDataset::FromHandle(hDataset)->Reference();
1575 : }
1576 :
1577 : /************************************************************************/
1578 : /* Dereference() */
1579 : /************************************************************************/
1580 :
1581 : /**
1582 : * \brief Subtract one from dataset reference count.
1583 : *
1584 : * The reference is one after instantiation. Generally when the reference
1585 : * count has dropped to zero the dataset may be safely deleted (closed).
1586 : *
1587 : * This method is the same as the C GDALDereferenceDataset() function.
1588 : *
1589 : * @return the post-decrement reference count.
1590 : */
1591 :
1592 66956 : int GDALDataset::Dereference()
1593 : {
1594 66956 : return --nRefCount;
1595 : }
1596 :
1597 : /************************************************************************/
1598 : /* GDALDereferenceDataset() */
1599 : /************************************************************************/
1600 :
1601 : /**
1602 : * \brief Subtract one from dataset reference count.
1603 : *
1604 : * @see GDALDataset::Dereference()
1605 : */
1606 :
1607 52386 : int CPL_STDCALL GDALDereferenceDataset(GDALDatasetH hDataset)
1608 :
1609 : {
1610 52386 : VALIDATE_POINTER1(hDataset, "GDALDereferenceDataset", 0);
1611 :
1612 52386 : return GDALDataset::FromHandle(hDataset)->Dereference();
1613 : }
1614 :
1615 : /************************************************************************/
1616 : /* ReleaseRef() */
1617 : /************************************************************************/
1618 :
1619 : /**
1620 : * \brief Drop a reference to this object, and destroy if no longer referenced.
1621 : * @return TRUE if the object has been destroyed.
1622 : * @since GDAL 2.2
1623 : */
1624 :
1625 13961 : int GDALDataset::ReleaseRef()
1626 :
1627 : {
1628 13961 : if (Dereference() <= 0)
1629 : {
1630 3281 : nRefCount = 1;
1631 3281 : delete this;
1632 3281 : return TRUE;
1633 : }
1634 10680 : return FALSE;
1635 : }
1636 :
1637 : /************************************************************************/
1638 : /* GDALReleaseDataset() */
1639 : /************************************************************************/
1640 :
1641 : /**
1642 : * \brief Drop a reference to this object, and destroy if no longer referenced.
1643 : *
1644 : * @see GDALDataset::ReleaseRef()
1645 : * @since GDAL 2.2
1646 : */
1647 :
1648 1293 : int CPL_STDCALL GDALReleaseDataset(GDALDatasetH hDataset)
1649 :
1650 : {
1651 1293 : VALIDATE_POINTER1(hDataset, "GDALReleaseDataset", 0);
1652 :
1653 1293 : return GDALDataset::FromHandle(hDataset)->ReleaseRef();
1654 : }
1655 :
1656 : /************************************************************************/
1657 : /* GetShared() */
1658 : /************************************************************************/
1659 :
1660 : /**
1661 : * \brief Returns shared flag.
1662 : *
1663 : * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
1664 : */
1665 :
1666 91186 : int GDALDataset::GetShared() const
1667 : {
1668 91186 : return bShared;
1669 : }
1670 :
1671 : /************************************************************************/
1672 : /* MarkAsShared() */
1673 : /************************************************************************/
1674 :
1675 : /**
1676 : * \brief Mark this dataset as available for sharing.
1677 : */
1678 :
1679 404 : void GDALDataset::MarkAsShared()
1680 :
1681 : {
1682 404 : CPLAssert(!bShared);
1683 :
1684 404 : bShared = true;
1685 404 : if (bIsInternal)
1686 13 : return;
1687 :
1688 391 : GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
1689 :
1690 : // Insert the dataset in the set of shared opened datasets.
1691 782 : CPLMutexHolderD(&hDLMutex);
1692 391 : if (phSharedDatasetSet == nullptr)
1693 271 : phSharedDatasetSet =
1694 271 : CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc,
1695 : GDALSharedDatasetFreeFunc);
1696 :
1697 : SharedDatasetCtxt *psStruct =
1698 391 : static_cast<SharedDatasetCtxt *>(CPLMalloc(sizeof(SharedDatasetCtxt)));
1699 391 : psStruct->poDS = this;
1700 391 : psStruct->nPID = nPID;
1701 391 : psStruct->nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
1702 391 : psStruct->pszDescription = CPLStrdup(GetDescription());
1703 : std::string osConcatenatedOpenOptions =
1704 782 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
1705 391 : psStruct->pszConcatenatedOpenOptions =
1706 391 : CPLStrdup(osConcatenatedOpenOptions.c_str());
1707 391 : if (CPLHashSetLookup(phSharedDatasetSet, psStruct) != nullptr)
1708 : {
1709 1 : GDALSharedDatasetFreeFunc(psStruct);
1710 1 : ReportError(CE_Failure, CPLE_AppDefined,
1711 : "An existing shared dataset already has this description. "
1712 : "This should not happen.");
1713 : }
1714 : else
1715 : {
1716 390 : CPLHashSetInsert(phSharedDatasetSet, psStruct);
1717 :
1718 390 : (*poAllDatasetMap)[this] = nPID;
1719 : }
1720 : }
1721 :
1722 : /************************************************************************/
1723 : /* MarkSuppressOnClose() */
1724 : /************************************************************************/
1725 :
1726 : /** Set that the dataset must be deleted on close. */
1727 1066 : void GDALDataset::MarkSuppressOnClose()
1728 : {
1729 1066 : bSuppressOnClose = true;
1730 1066 : }
1731 :
1732 : /************************************************************************/
1733 : /* UnMarkSuppressOnClose() */
1734 : /************************************************************************/
1735 :
1736 : /** Remove the flag requesting the dataset to be deleted on close. */
1737 1 : void GDALDataset::UnMarkSuppressOnClose()
1738 : {
1739 1 : bSuppressOnClose = false;
1740 1 : }
1741 :
1742 : /************************************************************************/
1743 : /* CleanupPostFileClosing() */
1744 : /************************************************************************/
1745 :
1746 : /** This method should be called by driver implementations in their destructor,
1747 : * after having closed all files, but before having freed resources that
1748 : * are needed for their GetFileList() implementation.
1749 : * This is used to implement MarkSuppressOnClose behavior.
1750 : */
1751 251 : void GDALDataset::CleanupPostFileClosing()
1752 : {
1753 251 : if (IsMarkedSuppressOnClose())
1754 : {
1755 1 : char **papszFileList = GetFileList();
1756 3 : for (int i = 0; papszFileList && papszFileList[i]; ++i)
1757 2 : VSIUnlink(papszFileList[i]);
1758 1 : CSLDestroy(papszFileList);
1759 : }
1760 251 : }
1761 :
1762 : /************************************************************************/
1763 : /* GetGCPCount() */
1764 : /************************************************************************/
1765 :
1766 : /**
1767 : * \brief Get number of GCPs.
1768 : *
1769 : * This method is the same as the C function GDALGetGCPCount().
1770 : *
1771 : * @return number of GCPs for this dataset. Zero if there are none.
1772 : */
1773 :
1774 12492 : int GDALDataset::GetGCPCount()
1775 : {
1776 12492 : return 0;
1777 : }
1778 :
1779 : /************************************************************************/
1780 : /* GDALGetGCPCount() */
1781 : /************************************************************************/
1782 :
1783 : /**
1784 : * \brief Get number of GCPs.
1785 : *
1786 : * @see GDALDataset::GetGCPCount()
1787 : */
1788 :
1789 1017 : int CPL_STDCALL GDALGetGCPCount(GDALDatasetH hDS)
1790 :
1791 : {
1792 1017 : VALIDATE_POINTER1(hDS, "GDALGetGCPCount", 0);
1793 :
1794 1017 : return GDALDataset::FromHandle(hDS)->GetGCPCount();
1795 : }
1796 :
1797 : /************************************************************************/
1798 : /* GetGCPProjection() */
1799 : /************************************************************************/
1800 :
1801 : /**
1802 : * \brief Get output projection for GCPs.
1803 : *
1804 : * This method is the same as the C function GDALGetGCPProjection().
1805 : *
1806 : * The projection string follows the normal rules from GetProjectionRef().
1807 : *
1808 : * \note Starting with GDAL 3.0, this is a compatibility layer around
1809 : * GetGCPSpatialRef()
1810 : *
1811 : * @return internal projection string or "" if there are no GCPs.
1812 : * It should not be altered, freed or expected to last for long.
1813 : */
1814 :
1815 786 : const char *GDALDataset::GetGCPProjection()
1816 : {
1817 786 : const auto poSRS = GetGCPSpatialRef();
1818 786 : if (!poSRS || !m_poPrivate)
1819 : {
1820 443 : return "";
1821 : }
1822 343 : char *pszWKT = nullptr;
1823 343 : poSRS->exportToWkt(&pszWKT);
1824 343 : if (!pszWKT)
1825 : {
1826 0 : return "";
1827 : }
1828 :
1829 : // If called on a thread-safe dataset, we might be called by several
1830 : // threads, so make sure our accesses to m_pszWKTCached are protected
1831 : // by a mutex.
1832 686 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1833 343 : if (m_poPrivate->m_pszWKTGCPCached &&
1834 256 : strcmp(pszWKT, m_poPrivate->m_pszWKTGCPCached) == 0)
1835 : {
1836 256 : CPLFree(pszWKT);
1837 256 : return m_poPrivate->m_pszWKTGCPCached;
1838 : }
1839 87 : CPLFree(m_poPrivate->m_pszWKTGCPCached);
1840 87 : m_poPrivate->m_pszWKTGCPCached = pszWKT;
1841 87 : return m_poPrivate->m_pszWKTGCPCached;
1842 : }
1843 :
1844 : /************************************************************************/
1845 : /* GetGCPSpatialRef() */
1846 : /************************************************************************/
1847 :
1848 : /**
1849 : * \brief Get output spatial reference system for GCPs.
1850 : *
1851 : * Same as the C function GDALGetGCPSpatialRef().
1852 : *
1853 : * When a SRS is not available, null is returned. If used on
1854 : * a dataset where there is a geotransform, and not GCPs, this method returns
1855 : * null. Use GetSpatialRef() instead.
1856 : *
1857 : * @since GDAL 3.0
1858 : *
1859 : * @return a pointer to an internal object. It should not be altered or freed.
1860 : * Its lifetime will be the one of the dataset object, or until the next
1861 : * call to this method.
1862 : */
1863 :
1864 39 : const OGRSpatialReference *GDALDataset::GetGCPSpatialRef() const
1865 : {
1866 39 : return nullptr;
1867 : }
1868 :
1869 : /************************************************************************/
1870 : /* GDALGetGCPSpatialRef() */
1871 : /************************************************************************/
1872 :
1873 : /**
1874 : * \brief Get output spatial reference system for GCPs.
1875 : *
1876 : * @since GDAL 3.0
1877 : *
1878 : * @see GDALDataset::GetGCPSpatialRef()
1879 : */
1880 :
1881 462 : OGRSpatialReferenceH GDALGetGCPSpatialRef(GDALDatasetH hDS)
1882 :
1883 : {
1884 462 : VALIDATE_POINTER1(hDS, "GDALGetGCPSpatialRef", nullptr);
1885 :
1886 462 : return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1887 462 : GDALDataset::FromHandle(hDS)->GetGCPSpatialRef()));
1888 : }
1889 :
1890 : /************************************************************************/
1891 : /* GDALGetGCPProjection() */
1892 : /************************************************************************/
1893 :
1894 : /**
1895 : * \brief Get output projection for GCPs.
1896 : *
1897 : * @see GDALDataset::GetGCPProjection()
1898 : */
1899 :
1900 711 : const char *CPL_STDCALL GDALGetGCPProjection(GDALDatasetH hDS)
1901 :
1902 : {
1903 711 : VALIDATE_POINTER1(hDS, "GDALGetGCPProjection", nullptr);
1904 :
1905 711 : return GDALDataset::FromHandle(hDS)->GetGCPProjection();
1906 : }
1907 :
1908 : /************************************************************************/
1909 : /* GetGCPs() */
1910 : /************************************************************************/
1911 :
1912 : /**
1913 : * \brief Fetch GCPs.
1914 : *
1915 : * This method is the same as the C function GDALGetGCPs().
1916 : *
1917 : * @return pointer to internal GCP structure list. It should not be modified,
1918 : * and may change on the next GDAL call.
1919 : */
1920 :
1921 10 : const GDAL_GCP *GDALDataset::GetGCPs()
1922 : {
1923 10 : return nullptr;
1924 : }
1925 :
1926 : /************************************************************************/
1927 : /* GDALGetGCPs() */
1928 : /************************************************************************/
1929 :
1930 : /**
1931 : * \brief Fetch GCPs.
1932 : *
1933 : * @see GDALDataset::GetGCPs()
1934 : */
1935 :
1936 559 : const GDAL_GCP *CPL_STDCALL GDALGetGCPs(GDALDatasetH hDS)
1937 :
1938 : {
1939 559 : VALIDATE_POINTER1(hDS, "GDALGetGCPs", nullptr);
1940 :
1941 559 : return GDALDataset::FromHandle(hDS)->GetGCPs();
1942 : }
1943 :
1944 : /************************************************************************/
1945 : /* SetGCPs() */
1946 : /************************************************************************/
1947 :
1948 : /**
1949 : * \brief Assign GCPs.
1950 : *
1951 : * This method is the same as the C function GDALSetGCPs().
1952 : *
1953 : * This method assigns the passed set of GCPs to this dataset, as well as
1954 : * setting their coordinate system. Internally copies are made of the
1955 : * coordinate system and list of points, so the caller remains responsible for
1956 : * deallocating these arguments if appropriate.
1957 : *
1958 : * Most formats do not support setting of GCPs, even formats that can
1959 : * handle GCPs. These formats will return CE_Failure.
1960 : *
1961 : * \note Startig with GDAL 3.0, this is a compatibility layer around
1962 : * SetGCPs(int, const GDAL_GCP*, const char*)
1963 : *
1964 : * @param nGCPCount number of GCPs being assigned.
1965 : *
1966 : * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
1967 : *
1968 : * @param pszGCPProjection the new OGC WKT coordinate system to assign for the
1969 : * GCP output coordinates. This parameter should be "" if no output coordinate
1970 : * system is known.
1971 : *
1972 : * @return CE_None on success, CE_Failure on failure (including if action is
1973 : * not supported for this format).
1974 : */
1975 :
1976 53 : CPLErr GDALDataset::SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList,
1977 : const char *pszGCPProjection)
1978 :
1979 : {
1980 53 : if (pszGCPProjection && pszGCPProjection[0] != '\0')
1981 : {
1982 70 : OGRSpatialReference oSRS;
1983 35 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1984 35 : if (oSRS.importFromWkt(pszGCPProjection) != OGRERR_NONE)
1985 : {
1986 0 : return CE_Failure;
1987 : }
1988 35 : return SetGCPs(nGCPCount, pasGCPList, &oSRS);
1989 : }
1990 : else
1991 : {
1992 18 : return SetGCPs(nGCPCount, pasGCPList,
1993 18 : static_cast<const OGRSpatialReference *>(nullptr));
1994 : }
1995 : }
1996 :
1997 : /************************************************************************/
1998 : /* SetGCPs() */
1999 : /************************************************************************/
2000 :
2001 : /**
2002 : * \brief Assign GCPs.
2003 : *
2004 : * This method is the same as the C function GDALSetGCPs().
2005 : *
2006 : * This method assigns the passed set of GCPs to this dataset, as well as
2007 : * setting their coordinate system. Internally copies are made of the
2008 : * coordinate system and list of points, so the caller remains responsible for
2009 : * deallocating these arguments if appropriate.
2010 : *
2011 : * Most formats do not support setting of GCPs, even formats that can
2012 : * handle GCPs. These formats will return CE_Failure.
2013 : *
2014 : * @since GDAL 3.0
2015 : *
2016 : * @param nGCPCount number of GCPs being assigned.
2017 : *
2018 : * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
2019 : *
2020 : * @param poGCP_SRS the new coordinate reference system to assign for the
2021 : * GCP output coordinates. This parameter should be null if no output
2022 : * coordinate system is known.
2023 : *
2024 : * @return CE_None on success, CE_Failure on failure (including if action is
2025 : * not supported for this format).
2026 : */
2027 :
2028 0 : CPLErr GDALDataset::SetGCPs(CPL_UNUSED int nGCPCount,
2029 : CPL_UNUSED const GDAL_GCP *pasGCPList,
2030 : CPL_UNUSED const OGRSpatialReference *poGCP_SRS)
2031 :
2032 : {
2033 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
2034 0 : ReportError(CE_Failure, CPLE_NotSupported,
2035 : "Dataset does not support the SetGCPs() method.");
2036 :
2037 0 : return CE_Failure;
2038 : }
2039 :
2040 : /************************************************************************/
2041 : /* GDALSetGCPs() */
2042 : /************************************************************************/
2043 :
2044 : /**
2045 : * \brief Assign GCPs.
2046 : *
2047 : * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const char*)
2048 : */
2049 :
2050 30 : CPLErr CPL_STDCALL GDALSetGCPs(GDALDatasetH hDS, int nGCPCount,
2051 : const GDAL_GCP *pasGCPList,
2052 : const char *pszGCPProjection)
2053 :
2054 : {
2055 30 : VALIDATE_POINTER1(hDS, "GDALSetGCPs", CE_Failure);
2056 :
2057 30 : return GDALDataset::FromHandle(hDS)->SetGCPs(nGCPCount, pasGCPList,
2058 30 : pszGCPProjection);
2059 : }
2060 :
2061 : /************************************************************************/
2062 : /* GDALSetGCPs2() */
2063 : /************************************************************************/
2064 :
2065 : /**
2066 : * \brief Assign GCPs.
2067 : *
2068 : * @since GDAL 3.0
2069 : * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const OGRSpatialReference*)
2070 : */
2071 :
2072 9 : CPLErr GDALSetGCPs2(GDALDatasetH hDS, int nGCPCount, const GDAL_GCP *pasGCPList,
2073 : OGRSpatialReferenceH hSRS)
2074 :
2075 : {
2076 9 : VALIDATE_POINTER1(hDS, "GDALSetGCPs2", CE_Failure);
2077 :
2078 18 : return GDALDataset::FromHandle(hDS)->SetGCPs(
2079 9 : nGCPCount, pasGCPList, OGRSpatialReference::FromHandle(hSRS));
2080 : }
2081 :
2082 : /************************************************************************/
2083 : /* BuildOverviews() */
2084 : /************************************************************************/
2085 :
2086 : /**
2087 : * \brief Build raster overview(s)
2088 : *
2089 : * If the operation is unsupported for the indicated dataset, then
2090 : * CE_Failure is returned, and CPLGetLastErrorNo() will return
2091 : * CPLE_NotSupported.
2092 : *
2093 : * Depending on the actual file format, all overviews level can be also
2094 : * deleted by specifying nOverviews == 0. This works at least for external
2095 : * overviews (.ovr), TIFF internal overviews, etc.
2096 : *
2097 : * Starting with GDAL 3.2, the GDAL_NUM_THREADS configuration option can be set
2098 : * to "ALL_CPUS" or a integer value to specify the number of threads to use for
2099 : * overview computation.
2100 : *
2101 : * This method is the same as the C function GDALBuildOverviewsEx().
2102 : *
2103 : * @param pszResampling one of "AVERAGE", "AVERAGE_MAGPHASE", "RMS",
2104 : * "BILINEAR", "CUBIC", "CUBICSPLINE", "GAUSS", "LANCZOS", "MODE", "NEAREST",
2105 : * or "NONE" controlling the downsampling method applied.
2106 : * @param nOverviews number of overviews to build, or 0 to clean overviews.
2107 : * @param panOverviewList the list of overview decimation factors to build, or
2108 : * NULL if nOverviews == 0.
2109 : * @param nListBands number of bands to build overviews for in panBandList.
2110 : * Build for all bands if this is 0.
2111 : * @param panBandList list of band numbers.
2112 : * @param pfnProgress a function to call to report progress, or NULL.
2113 : * @param pProgressData application data to pass to the progress function.
2114 : * @param papszOptions (GDAL >= 3.6) NULL terminated list of options as
2115 : * key=value pairs, or NULL
2116 : *
2117 : * @return CE_None on success or CE_Failure if the operation doesn't work.
2118 : *
2119 : * For example, to build overview level 2, 4 and 8 on all bands the following
2120 : * call could be made:
2121 : * \code{.cpp}
2122 : * int anOverviewList[3] = { 2, 4, 8 };
2123 : *
2124 : * poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, nullptr,
2125 : * GDALDummyProgress, nullptr );
2126 : * \endcode
2127 : *
2128 : * @see GDALRegenerateOverviewsEx()
2129 : */
2130 :
2131 654 : CPLErr GDALDataset::BuildOverviews(const char *pszResampling, int nOverviews,
2132 : const int *panOverviewList, int nListBands,
2133 : const int *panBandList,
2134 : GDALProgressFunc pfnProgress,
2135 : void *pProgressData,
2136 : CSLConstList papszOptions)
2137 : {
2138 654 : int *panAllBandList = nullptr;
2139 :
2140 654 : if (nListBands == 0)
2141 : {
2142 643 : nListBands = GetRasterCount();
2143 : panAllBandList =
2144 643 : static_cast<int *>(CPLMalloc(sizeof(int) * nListBands));
2145 1708 : for (int i = 0; i < nListBands; ++i)
2146 1065 : panAllBandList[i] = i + 1;
2147 :
2148 643 : panBandList = panAllBandList;
2149 : }
2150 :
2151 654 : if (pfnProgress == nullptr)
2152 623 : pfnProgress = GDALDummyProgress;
2153 :
2154 : // At time of writing, all overview generation options are actually
2155 : // expected to be passed as configuration options.
2156 654 : std::vector<std::unique_ptr<CPLConfigOptionSetter>> apoConfigOptionSetter;
2157 688 : for (const auto &[pszKey, pszValue] : cpl::IterateNameValue(papszOptions))
2158 : {
2159 : apoConfigOptionSetter.emplace_back(
2160 34 : std::make_unique<CPLConfigOptionSetter>(pszKey, pszValue, false));
2161 : }
2162 :
2163 : const CPLErr eErr =
2164 1308 : IBuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,
2165 654 : panBandList, pfnProgress, pProgressData, papszOptions);
2166 :
2167 654 : if (panAllBandList != nullptr)
2168 642 : CPLFree(panAllBandList);
2169 :
2170 1308 : return eErr;
2171 : }
2172 :
2173 : /************************************************************************/
2174 : /* GDALBuildOverviews() */
2175 : /************************************************************************/
2176 :
2177 : /**
2178 : * \brief Build raster overview(s)
2179 : *
2180 : * @see GDALDataset::BuildOverviews() and GDALBuildOverviews()
2181 : */
2182 :
2183 21 : CPLErr CPL_STDCALL GDALBuildOverviews(GDALDatasetH hDataset,
2184 : const char *pszResampling, int nOverviews,
2185 : const int *panOverviewList,
2186 : int nListBands, const int *panBandList,
2187 : GDALProgressFunc pfnProgress,
2188 : void *pProgressData)
2189 :
2190 : {
2191 21 : VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2192 :
2193 21 : return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2194 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2195 21 : pfnProgress, pProgressData, nullptr);
2196 : }
2197 :
2198 : /************************************************************************/
2199 : /* GDALBuildOverviews() */
2200 : /************************************************************************/
2201 :
2202 : /**
2203 : * \brief Build raster overview(s)
2204 : *
2205 : * @see GDALDataset::BuildOverviews()
2206 : * @since GDAL 3.6
2207 : */
2208 :
2209 : CPLErr CPL_STDCALL
2210 614 : GDALBuildOverviewsEx(GDALDatasetH hDataset, const char *pszResampling,
2211 : int nOverviews, const int *panOverviewList, int nListBands,
2212 : const int *panBandList, GDALProgressFunc pfnProgress,
2213 : void *pProgressData, CSLConstList papszOptions)
2214 :
2215 : {
2216 614 : VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2217 :
2218 614 : return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2219 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2220 614 : pfnProgress, pProgressData, papszOptions);
2221 : }
2222 :
2223 : /************************************************************************/
2224 : /* IBuildOverviews() */
2225 : /* */
2226 : /* Default implementation. */
2227 : /************************************************************************/
2228 :
2229 : //! @cond Doxygen_Suppress
2230 186 : CPLErr GDALDataset::IBuildOverviews(const char *pszResampling, int nOverviews,
2231 : const int *panOverviewList, int nListBands,
2232 : const int *panBandList,
2233 : GDALProgressFunc pfnProgress,
2234 : void *pProgressData,
2235 : CSLConstList papszOptions)
2236 :
2237 : {
2238 186 : if (oOvManager.IsInitialized())
2239 185 : return oOvManager.BuildOverviews(
2240 : nullptr, pszResampling, nOverviews, panOverviewList, nListBands,
2241 185 : panBandList, pfnProgress, pProgressData, papszOptions);
2242 : else
2243 : {
2244 1 : ReportError(CE_Failure, CPLE_NotSupported,
2245 : "BuildOverviews() not supported for this dataset.");
2246 :
2247 1 : return CE_Failure;
2248 : }
2249 : }
2250 :
2251 : //! @endcond
2252 :
2253 : /************************************************************************/
2254 : /* IRasterIO() */
2255 : /* */
2256 : /* The default implementation of IRasterIO() is, in the general */
2257 : /* case to pass the request off to each band objects rasterio */
2258 : /* methods with appropriate arguments. In some cases, it might */
2259 : /* choose instead the BlockBasedRasterIO() implementation. */
2260 : /************************************************************************/
2261 :
2262 : //! @cond Doxygen_Suppress
2263 438741 : CPLErr GDALDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2264 : int nXSize, int nYSize, void *pData,
2265 : int nBufXSize, int nBufYSize,
2266 : GDALDataType eBufType, int nBandCount,
2267 : BANDMAP_TYPE panBandMap, GSpacing nPixelSpace,
2268 : GSpacing nLineSpace, GSpacing nBandSpace,
2269 : GDALRasterIOExtraArg *psExtraArg)
2270 :
2271 : {
2272 438741 : const char *pszInterleave = nullptr;
2273 :
2274 438741 : CPLAssert(nullptr != pData);
2275 :
2276 438741 : const bool bHasSubpixelShift =
2277 439833 : psExtraArg->bFloatingPointWindowValidity &&
2278 438919 : psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
2279 178 : (nXOff != psExtraArg->dfXOff || nYOff != psExtraArg->dfYOff);
2280 :
2281 438644 : if (!bHasSubpixelShift && nXSize == nBufXSize && nYSize == nBufYSize &&
2282 69630 : nBandCount > 1 &&
2283 69631 : (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) !=
2284 877384 : nullptr &&
2285 65671 : EQUAL(pszInterleave, "PIXEL"))
2286 : {
2287 63502 : return BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2288 : nBufXSize, nBufYSize, eBufType, nBandCount,
2289 : panBandMap, nPixelSpace, nLineSpace,
2290 63501 : nBandSpace, psExtraArg);
2291 : }
2292 :
2293 375239 : if (eRWFlag == GF_Read &&
2294 199553 : (psExtraArg->eResampleAlg == GRIORA_Cubic ||
2295 199379 : psExtraArg->eResampleAlg == GRIORA_CubicSpline ||
2296 199378 : psExtraArg->eResampleAlg == GRIORA_Bilinear ||
2297 199553 : psExtraArg->eResampleAlg == GRIORA_Lanczos) &&
2298 331 : !(nXSize == nBufXSize && nYSize == nBufYSize) && nBandCount > 1)
2299 : {
2300 312 : if (nBufXSize < nXSize && nBufYSize < nYSize && AreOverviewsEnabled())
2301 : {
2302 153 : int bTried = FALSE;
2303 153 : const CPLErr eErr = TryOverviewRasterIO(
2304 : eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
2305 : nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace,
2306 : nLineSpace, nBandSpace, psExtraArg, &bTried);
2307 153 : if (bTried)
2308 1 : return eErr;
2309 : }
2310 :
2311 311 : GDALDataType eFirstBandDT = GDT_Unknown;
2312 311 : int nFirstMaskFlags = 0;
2313 311 : GDALRasterBand *poFirstMaskBand = nullptr;
2314 311 : int nOKBands = 0;
2315 :
2316 : // Check if bands share the same mask band
2317 1271 : for (int i = 0; i < nBandCount; ++i)
2318 : {
2319 1042 : GDALRasterBand *poBand = GetRasterBand(panBandMap[i]);
2320 1534 : if ((nBufXSize < nXSize || nBufYSize < nYSize) &&
2321 485 : poBand->GetOverviewCount())
2322 : {
2323 : // Could be improved to select the appropriate overview.
2324 3 : break;
2325 : }
2326 1046 : if (poBand->GetColorTable() != nullptr)
2327 : {
2328 0 : break;
2329 : }
2330 1048 : const GDALDataType eDT = poBand->GetRasterDataType();
2331 1045 : if (GDALDataTypeIsComplex(eDT))
2332 : {
2333 30 : break;
2334 : }
2335 1014 : if (i == 0)
2336 : {
2337 280 : eFirstBandDT = eDT;
2338 280 : nFirstMaskFlags = poBand->GetMaskFlags();
2339 283 : if (nFirstMaskFlags == GMF_NODATA)
2340 : {
2341 : // The dataset-level resampling code is not ready for nodata
2342 : // Fallback to band-level resampling
2343 6 : break;
2344 : }
2345 277 : poFirstMaskBand = poBand->GetMaskBand();
2346 : }
2347 : else
2348 : {
2349 734 : if (eDT != eFirstBandDT)
2350 : {
2351 0 : break;
2352 : }
2353 734 : int nMaskFlags = poBand->GetMaskFlags();
2354 734 : if (nMaskFlags == GMF_NODATA)
2355 : {
2356 : // The dataset-level resampling code is not ready for nodata
2357 : // Fallback to band-level resampling
2358 0 : break;
2359 : }
2360 734 : GDALRasterBand *poMaskBand = poBand->GetMaskBand();
2361 737 : if (nFirstMaskFlags == GMF_ALL_VALID &&
2362 : nMaskFlags == GMF_ALL_VALID)
2363 : {
2364 : // Ok.
2365 : }
2366 168 : else if (poFirstMaskBand == poMaskBand)
2367 : {
2368 : // Ok.
2369 : }
2370 : else
2371 : {
2372 55 : break;
2373 : }
2374 : }
2375 :
2376 960 : ++nOKBands;
2377 : }
2378 :
2379 323 : GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2380 323 : void *pProgressDataGlobal = psExtraArg->pProgressData;
2381 :
2382 323 : CPLErr eErr = CE_None;
2383 323 : if (nOKBands > 0)
2384 : {
2385 280 : if (nOKBands < nBandCount)
2386 : {
2387 55 : psExtraArg->pfnProgress = GDALScaledProgress;
2388 110 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2389 55 : 0.0, static_cast<double>(nOKBands) / nBandCount,
2390 : pfnProgressGlobal, pProgressDataGlobal);
2391 55 : if (psExtraArg->pProgressData == nullptr)
2392 53 : psExtraArg->pfnProgress = nullptr;
2393 : }
2394 :
2395 280 : eErr = RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2396 : pData, nBufXSize, nBufYSize, eBufType,
2397 : nOKBands, panBandMap, nPixelSpace,
2398 : nLineSpace, nBandSpace, psExtraArg);
2399 :
2400 280 : if (nOKBands < nBandCount)
2401 : {
2402 55 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2403 : }
2404 : }
2405 323 : if (eErr == CE_None && nOKBands < nBandCount)
2406 : {
2407 92 : if (nOKBands > 0)
2408 : {
2409 53 : psExtraArg->pfnProgress = GDALScaledProgress;
2410 106 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2411 53 : static_cast<double>(nOKBands) / nBandCount, 1.0,
2412 : pfnProgressGlobal, pProgressDataGlobal);
2413 53 : if (psExtraArg->pProgressData == nullptr)
2414 51 : psExtraArg->pfnProgress = nullptr;
2415 : }
2416 184 : eErr = BandBasedRasterIO(
2417 : eRWFlag, nXOff, nYOff, nXSize, nYSize,
2418 92 : static_cast<GByte *>(pData) + nBandSpace * nOKBands, nBufXSize,
2419 : nBufYSize, eBufType, nBandCount - nOKBands,
2420 92 : panBandMap + nOKBands, nPixelSpace, nLineSpace, nBandSpace,
2421 : psExtraArg);
2422 92 : if (nOKBands > 0)
2423 : {
2424 53 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2425 : }
2426 : }
2427 :
2428 319 : psExtraArg->pfnProgress = pfnProgressGlobal;
2429 319 : psExtraArg->pProgressData = pProgressDataGlobal;
2430 :
2431 319 : return eErr;
2432 : }
2433 :
2434 374927 : return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2435 : nBufXSize, nBufYSize, eBufType, nBandCount,
2436 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2437 374919 : psExtraArg);
2438 : }
2439 :
2440 : //! @endcond
2441 :
2442 : /************************************************************************/
2443 : /* BandBasedRasterIO() */
2444 : /* */
2445 : /* Pass the request off to each band objects rasterio methods with */
2446 : /* appropriate arguments. */
2447 : /************************************************************************/
2448 :
2449 : //! @cond Doxygen_Suppress
2450 637605 : CPLErr GDALDataset::BandBasedRasterIO(
2451 : GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
2452 : void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
2453 : int nBandCount, const int *panBandMap, GSpacing nPixelSpace,
2454 : GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg *psExtraArg)
2455 :
2456 : {
2457 : int iBandIndex;
2458 637605 : CPLErr eErr = CE_None;
2459 :
2460 637605 : GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2461 637605 : void *pProgressDataGlobal = psExtraArg->pProgressData;
2462 :
2463 1567450 : for (iBandIndex = 0; iBandIndex < nBandCount && eErr == CE_None;
2464 : ++iBandIndex)
2465 : {
2466 929821 : GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
2467 :
2468 929827 : if (poBand == nullptr)
2469 : {
2470 0 : eErr = CE_Failure;
2471 0 : break;
2472 : }
2473 :
2474 929827 : GByte *pabyBandData =
2475 929827 : static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
2476 :
2477 929827 : if (nBandCount > 1)
2478 : {
2479 428653 : psExtraArg->pfnProgress = GDALScaledProgress;
2480 857310 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2481 : 1.0 * iBandIndex / nBandCount,
2482 428653 : 1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,
2483 : pProgressDataGlobal);
2484 428657 : if (psExtraArg->pProgressData == nullptr)
2485 425086 : psExtraArg->pfnProgress = nullptr;
2486 : }
2487 :
2488 1859680 : eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2489 : pabyBandData, nBufXSize, nBufYSize, eBufType,
2490 929831 : nPixelSpace, nLineSpace, psExtraArg);
2491 :
2492 929852 : if (nBandCount > 1)
2493 428677 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2494 : }
2495 :
2496 637628 : psExtraArg->pfnProgress = pfnProgressGlobal;
2497 637628 : psExtraArg->pProgressData = pProgressDataGlobal;
2498 :
2499 637628 : return eErr;
2500 : }
2501 :
2502 : //! @endcond
2503 :
2504 : /************************************************************************/
2505 : /* ValidateRasterIOOrAdviseReadParameters() */
2506 : /************************************************************************/
2507 :
2508 : //! @cond Doxygen_Suppress
2509 726890 : CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
2510 : const char *pszCallingFunc, int *pbStopProcessingOnCENone, int nXOff,
2511 : int nYOff, int nXSize, int nYSize, int nBufXSize, int nBufYSize,
2512 : int nBandCount, const int *panBandMap)
2513 : {
2514 :
2515 : /* -------------------------------------------------------------------- */
2516 : /* Some size values are "noop". Lets just return to avoid */
2517 : /* stressing lower level functions. */
2518 : /* -------------------------------------------------------------------- */
2519 726890 : if (nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1)
2520 : {
2521 19 : CPLDebug("GDAL",
2522 : "%s skipped for odd window or buffer size.\n"
2523 : " Window = (%d,%d)x%dx%d\n"
2524 : " Buffer = %dx%d",
2525 : pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2526 : nBufYSize);
2527 :
2528 4 : *pbStopProcessingOnCENone = TRUE;
2529 4 : return CE_None;
2530 : }
2531 :
2532 726871 : CPLErr eErr = CE_None;
2533 726871 : *pbStopProcessingOnCENone = FALSE;
2534 :
2535 726871 : if (nXOff < 0 || nXOff > INT_MAX - nXSize ||
2536 726872 : nXOff + nXSize > nRasterXSize || nYOff < 0 ||
2537 726877 : nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize)
2538 : {
2539 0 : ReportError(CE_Failure, CPLE_IllegalArg,
2540 : "Access window out of range in %s. Requested "
2541 : "(%d,%d) of size %dx%d on raster of %dx%d.",
2542 : pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize,
2543 : nRasterYSize);
2544 2 : eErr = CE_Failure;
2545 : }
2546 :
2547 726873 : if (panBandMap == nullptr && nBandCount > GetRasterCount())
2548 : {
2549 0 : ReportError(CE_Failure, CPLE_IllegalArg,
2550 : "%s: nBandCount cannot be greater than %d", pszCallingFunc,
2551 : GetRasterCount());
2552 0 : eErr = CE_Failure;
2553 : }
2554 :
2555 1967380 : for (int i = 0; i < nBandCount && eErr == CE_None; ++i)
2556 : {
2557 1240510 : int iBand = (panBandMap != nullptr) ? panBandMap[i] : i + 1;
2558 1240510 : if (iBand < 1 || iBand > GetRasterCount())
2559 : {
2560 3 : ReportError(
2561 : CE_Failure, CPLE_IllegalArg,
2562 : "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
2563 : pszCallingFunc, i, iBand);
2564 3 : eErr = CE_Failure;
2565 : }
2566 :
2567 1240500 : if (eErr == CE_None && GetRasterBand(iBand) == nullptr)
2568 : {
2569 0 : ReportError(
2570 : CE_Failure, CPLE_IllegalArg,
2571 : "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
2572 : pszCallingFunc, i, iBand);
2573 0 : eErr = CE_Failure;
2574 : }
2575 : }
2576 :
2577 726864 : return eErr;
2578 : }
2579 :
2580 : //! @endcond
2581 :
2582 : /************************************************************************/
2583 : /* RasterIO() */
2584 : /************************************************************************/
2585 :
2586 : /**
2587 : * \brief Read/write a region of image data from multiple bands.
2588 : *
2589 : * This method allows reading a region of one or more GDALRasterBands from
2590 : * this dataset into a buffer, or writing data from a buffer into a region
2591 : * of the GDALRasterBands. It automatically takes care of data type
2592 : * translation if the data type (eBufType) of the buffer is different than
2593 : * that of the GDALRasterBand.
2594 : * The method also takes care of image decimation / replication if the
2595 : * buffer size (nBufXSize x nBufYSize) is different than the size of the
2596 : * region being accessed (nXSize x nYSize).
2597 : *
2598 : * The window of interest expressed by (nXOff, nYOff, nXSize, nYSize) should be
2599 : * fully within the raster space, that is nXOff >= 0, nYOff >= 0,
2600 : * nXOff + nXSize <= GetRasterXSize() and nYOff + nYSize <= GetRasterYSize().
2601 : * If reads larger than the raster space are wished, GDALTranslate() might be used.
2602 : * Or use nLineSpace and a possibly shifted pData value.
2603 : *
2604 : * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
2605 : * writing from various organization of buffers.
2606 : *
2607 : * Some formats may efficiently implement decimation into a buffer by
2608 : * reading from lower resolution overview images. The logic of the default
2609 : * implementation in the base class GDALRasterBand is the following one. It
2610 : * computes a target_downscaling_factor from the window of interest and buffer
2611 : * size which is min(nXSize/nBufXSize, nYSize/nBufYSize).
2612 : * It then walks through overviews and will select the first one whose
2613 : * downscaling factor is greater than target_downscaling_factor / 1.2.
2614 : *
2615 : * Let's assume we have overviews at downscaling factors 2, 4 and 8.
2616 : * The relationship between target_downscaling_factor and the select overview
2617 : * level is the following one:
2618 : *
2619 : * target_downscaling_factor | selected_overview
2620 : * ------------------------- | -----------------
2621 : * ]0, 2 / 1.2] | full resolution band
2622 : * ]2 / 1.2, 4 / 1.2] | 2x downsampled band
2623 : * ]4 / 1.2, 8 / 1.2] | 4x downsampled band
2624 : * ]8 / 1.2, infinity[ | 8x downsampled band
2625 : *
2626 : * Note that starting with GDAL 3.9, this 1.2 oversampling factor can be
2627 : * modified by setting the GDAL_OVERVIEW_OVERSAMPLING_THRESHOLD configuration
2628 : * option. Also note that starting with GDAL 3.9, when the resampling algorithm
2629 : * specified in psExtraArg->eResampleAlg is different from GRIORA_NearestNeighbour,
2630 : * this oversampling threshold defaults to 1. Consequently if there are overviews
2631 : * of downscaling factor 2, 4 and 8, and the desired downscaling factor is
2632 : * 7.99, the overview of factor 4 will be selected for a non nearest resampling.
2633 : *
2634 : * For highest performance full resolution data access, read and write
2635 : * on "block boundaries" as returned by GetBlockSize(), or use the
2636 : * ReadBlock() and WriteBlock() methods.
2637 : *
2638 : * This method is the same as the C GDALDatasetRasterIO() or
2639 : * GDALDatasetRasterIOEx() functions.
2640 : *
2641 : * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
2642 : * write a region of data.
2643 : *
2644 : * @param nXOff The pixel offset to the top left corner of the region
2645 : * of the band to be accessed. This would be zero to start from the left side.
2646 : *
2647 : * @param nYOff The line offset to the top left corner of the region
2648 : * of the band to be accessed. This would be zero to start from the top.
2649 : *
2650 : * @param nXSize The width of the region of the band to be accessed in pixels.
2651 : *
2652 : * @param nYSize The height of the region of the band to be accessed in lines.
2653 : *
2654 : * @param pData The buffer into which the data should be read, or from which
2655 : * it should be written. This buffer must contain at least
2656 : * nBufXSize * nBufYSize * nBandCount words of type eBufType. It is organized
2657 : * in left to right,top to bottom pixel order. Spacing is controlled by the
2658 : * nPixelSpace, and nLineSpace parameters.
2659 : * Note that even with eRWFlag==GF_Write, the content of the buffer might be
2660 : * temporarily modified during the execution of this method (and eventually
2661 : * restored back to its original content), so it is not safe to use a buffer
2662 : * stored in a read-only section of the calling program.
2663 : *
2664 : * @param nBufXSize the width of the buffer image into which the desired region
2665 : * is to be read, or from which it is to be written.
2666 : *
2667 : * @param nBufYSize the height of the buffer image into which the desired
2668 : * region is to be read, or from which it is to be written.
2669 : *
2670 : * @param eBufType the type of the pixel values in the pData data buffer. The
2671 : * pixel values will automatically be translated to/from the GDALRasterBand
2672 : * data type as needed. Most driver implementations will use GDALCopyWords64()
2673 : * to perform data type translation.
2674 : *
2675 : * @param nBandCount the number of bands being read or written.
2676 : *
2677 : * @param panBandMap the list of nBandCount band numbers being read/written.
2678 : * Note band numbers are 1 based. This may be NULL to select the first
2679 : * nBandCount bands. (Note: before GDAL 3.10, argument type was "int*", and
2680 : * not "const int*")
2681 : *
2682 : * @param nPixelSpace The byte offset from the start of one pixel value in
2683 : * pData to the start of the next pixel value within a scanline. If defaulted
2684 : * (0) the size of the datatype eBufType is used.
2685 : *
2686 : * @param nLineSpace The byte offset from the start of one scanline in
2687 : * pData to the start of the next. If defaulted (0) the size of the datatype
2688 : * eBufType * nBufXSize is used.
2689 : *
2690 : * @param nBandSpace the byte offset from the start of one bands data to the
2691 : * start of the next. If defaulted (0) the value will be
2692 : * nLineSpace * nBufYSize implying band sequential organization
2693 : * of the data buffer.
2694 : *
2695 : * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg
2696 : * structure with additional arguments to specify resampling and progress
2697 : * callback, or NULL for default behavior. The GDAL_RASTERIO_RESAMPLING
2698 : * configuration option can also be defined to override the default resampling
2699 : * to one of BILINEAR, CUBIC, CUBICSPLINE, LANCZOS, AVERAGE or MODE.
2700 : *
2701 : * @return CE_Failure if the access fails, otherwise CE_None.
2702 : */
2703 :
2704 714327 : CPLErr GDALDataset::RasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2705 : int nXSize, int nYSize, void *pData, int nBufXSize,
2706 : int nBufYSize, GDALDataType eBufType,
2707 : int nBandCount, const int *panBandMap,
2708 : GSpacing nPixelSpace, GSpacing nLineSpace,
2709 : GSpacing nBandSpace,
2710 : GDALRasterIOExtraArg *psExtraArg)
2711 :
2712 : {
2713 : GDALRasterIOExtraArg sExtraArg;
2714 714327 : if (psExtraArg == nullptr)
2715 : {
2716 530131 : INIT_RASTERIO_EXTRA_ARG(sExtraArg);
2717 :
2718 : // 4 below inits are not strictly needed but make Coverity Scan
2719 : // happy
2720 530131 : sExtraArg.dfXOff = nXOff;
2721 530131 : sExtraArg.dfYOff = nYOff;
2722 530131 : sExtraArg.dfXSize = nXSize;
2723 530131 : sExtraArg.dfYSize = nYSize;
2724 :
2725 530131 : psExtraArg = &sExtraArg;
2726 : }
2727 184196 : else if (CPL_UNLIKELY(psExtraArg->nVersion !=
2728 : RASTERIO_EXTRA_ARG_CURRENT_VERSION))
2729 : {
2730 0 : ReportError(CE_Failure, CPLE_AppDefined,
2731 : "Unhandled version of GDALRasterIOExtraArg");
2732 0 : return CE_Failure;
2733 : }
2734 :
2735 714327 : GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize, nBufXSize,
2736 : nBufYSize);
2737 :
2738 714309 : if (CPL_UNLIKELY(nullptr == pData))
2739 : {
2740 0 : ReportError(CE_Failure, CPLE_AppDefined,
2741 : "The buffer into which the data should be read is null");
2742 0 : return CE_Failure;
2743 : }
2744 :
2745 : /* -------------------------------------------------------------------- */
2746 : /* Do some validation of parameters. */
2747 : /* -------------------------------------------------------------------- */
2748 :
2749 714309 : if (CPL_UNLIKELY(eRWFlag != GF_Read && eRWFlag != GF_Write))
2750 : {
2751 0 : ReportError(
2752 : CE_Failure, CPLE_IllegalArg,
2753 : "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
2754 : eRWFlag);
2755 0 : return CE_Failure;
2756 : }
2757 :
2758 714309 : if (eRWFlag == GF_Write)
2759 : {
2760 212502 : if (CPL_UNLIKELY(eAccess != GA_Update))
2761 : {
2762 2 : ReportError(CE_Failure, CPLE_AppDefined,
2763 : "Write operation not permitted on dataset opened "
2764 : "in read-only mode");
2765 2 : return CE_Failure;
2766 : }
2767 : }
2768 :
2769 714307 : int bStopProcessing = FALSE;
2770 714307 : CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
2771 : "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2772 : nBufYSize, nBandCount, panBandMap);
2773 714327 : if (eErr != CE_None || bStopProcessing)
2774 20 : return eErr;
2775 714307 : if (CPL_UNLIKELY(eBufType == GDT_Unknown || eBufType == GDT_TypeCount))
2776 : {
2777 2 : ReportError(CE_Failure, CPLE_AppDefined,
2778 : "Illegal GDT_Unknown/GDT_TypeCount argument");
2779 2 : return CE_Failure;
2780 : }
2781 :
2782 : /* -------------------------------------------------------------------- */
2783 : /* If pixel and line spacing are defaulted assign reasonable */
2784 : /* value assuming a packed buffer. */
2785 : /* -------------------------------------------------------------------- */
2786 714305 : if (nPixelSpace == 0)
2787 415454 : nPixelSpace = GDALGetDataTypeSizeBytes(eBufType);
2788 :
2789 714297 : if (nLineSpace == 0)
2790 : {
2791 518620 : nLineSpace = nPixelSpace * nBufXSize;
2792 : }
2793 :
2794 714297 : if (nBandSpace == 0 && nBandCount > 1)
2795 : {
2796 67349 : nBandSpace = nLineSpace * nBufYSize;
2797 : }
2798 :
2799 714297 : if (panBandMap == nullptr)
2800 : {
2801 352163 : if (!m_poPrivate)
2802 0 : return CE_Failure;
2803 352163 : CPLAssert(static_cast<int>(m_poPrivate->m_anBandMap.size()) == nBands);
2804 352163 : panBandMap = m_poPrivate->m_anBandMap.data();
2805 : }
2806 :
2807 714296 : int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
2808 :
2809 : /* -------------------------------------------------------------------- */
2810 : /* We are being forced to use cached IO instead of a driver */
2811 : /* specific implementation. */
2812 : /* -------------------------------------------------------------------- */
2813 714313 : if (bForceCachedIO)
2814 : {
2815 7 : eErr = BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2816 : nBufXSize, nBufYSize, eBufType, nBandCount,
2817 : panBandMap, nPixelSpace, nLineSpace,
2818 7 : nBandSpace, psExtraArg);
2819 : }
2820 :
2821 : /* -------------------------------------------------------------------- */
2822 : /* Call the format specific function. */
2823 : /* -------------------------------------------------------------------- */
2824 : else
2825 : {
2826 714314 : eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2827 : nBufXSize, nBufYSize, eBufType, nBandCount,
2828 : // TODO: remove this const_cast once IRasterIO()
2829 : // takes a const int*
2830 : const_cast<int *>(panBandMap), nPixelSpace, nLineSpace,
2831 714306 : nBandSpace, psExtraArg);
2832 : }
2833 :
2834 714321 : if (bCallLeaveReadWrite)
2835 400467 : LeaveReadWrite();
2836 :
2837 714321 : return eErr;
2838 : }
2839 :
2840 : /************************************************************************/
2841 : /* GDALDatasetRasterIO() */
2842 : /************************************************************************/
2843 :
2844 : /**
2845 : * \brief Read/write a region of image data from multiple bands.
2846 : *
2847 : * Use GDALDatasetRasterIOEx() if 64 bit spacings or extra arguments (resampling
2848 : * resolution, progress callback, etc. are needed)
2849 : *
2850 : * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
2851 : *
2852 : * @see GDALDataset::RasterIO()
2853 : */
2854 :
2855 4395 : CPLErr CPL_STDCALL GDALDatasetRasterIO(GDALDatasetH hDS, GDALRWFlag eRWFlag,
2856 : int nXOff, int nYOff, int nXSize,
2857 : int nYSize, void *pData, int nBufXSize,
2858 : int nBufYSize, GDALDataType eBufType,
2859 : int nBandCount, const int *panBandMap,
2860 : int nPixelSpace, int nLineSpace,
2861 : int nBandSpace)
2862 :
2863 : {
2864 4395 : VALIDATE_POINTER1(hDS, "GDALDatasetRasterIO", CE_Failure);
2865 :
2866 4395 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2867 :
2868 4395 : return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2869 : nBufXSize, nBufYSize, eBufType, nBandCount,
2870 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2871 4395 : nullptr);
2872 : }
2873 :
2874 : /************************************************************************/
2875 : /* GDALDatasetRasterIOEx() */
2876 : /************************************************************************/
2877 :
2878 : /**
2879 : * \brief Read/write a region of image data from multiple bands.
2880 : *
2881 : * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
2882 : *
2883 : * @see GDALDataset::RasterIO()
2884 : * @since GDAL 2.0
2885 : */
2886 :
2887 350457 : CPLErr CPL_STDCALL GDALDatasetRasterIOEx(
2888 : GDALDatasetH hDS, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,
2889 : int nYSize, void *pData, int nBufXSize, int nBufYSize,
2890 : GDALDataType eBufType, int nBandCount, const int *panBandMap,
2891 : GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
2892 : GDALRasterIOExtraArg *psExtraArg)
2893 :
2894 : {
2895 350457 : VALIDATE_POINTER1(hDS, "GDALDatasetRasterIOEx", CE_Failure);
2896 :
2897 350457 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2898 :
2899 350457 : return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2900 : nBufXSize, nBufYSize, eBufType, nBandCount,
2901 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2902 350457 : psExtraArg);
2903 : }
2904 :
2905 : /************************************************************************/
2906 : /* GetOpenDatasets() */
2907 : /************************************************************************/
2908 :
2909 : /**
2910 : * \brief Fetch all open GDAL dataset handles.
2911 : *
2912 : * This method is the same as the C function GDALGetOpenDatasets().
2913 : *
2914 : * NOTE: This method is not thread safe. The returned list may change
2915 : * at any time and it should not be freed.
2916 : *
2917 : * @param pnCount integer into which to place the count of dataset pointers
2918 : * being returned.
2919 : *
2920 : * @return a pointer to an array of dataset handles.
2921 : */
2922 :
2923 1884 : GDALDataset **GDALDataset::GetOpenDatasets(int *pnCount)
2924 :
2925 : {
2926 3768 : CPLMutexHolderD(&hDLMutex);
2927 :
2928 1884 : if (poAllDatasetMap == nullptr)
2929 : {
2930 1858 : *pnCount = 0;
2931 1858 : return nullptr;
2932 : }
2933 :
2934 26 : *pnCount = static_cast<int>(poAllDatasetMap->size());
2935 26 : ppDatasets = static_cast<GDALDataset **>(
2936 26 : CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset *)));
2937 26 : std::map<GDALDataset *, GIntBig>::iterator oIter = poAllDatasetMap->begin();
2938 715 : for (int i = 0; oIter != poAllDatasetMap->end(); ++oIter, ++i)
2939 689 : ppDatasets[i] = oIter->first;
2940 26 : return ppDatasets;
2941 : }
2942 :
2943 : /************************************************************************/
2944 : /* GDALGetOpenDatasets() */
2945 : /************************************************************************/
2946 :
2947 : /**
2948 : * \brief Fetch all open GDAL dataset handles.
2949 : *
2950 : * @see GDALDataset::GetOpenDatasets()
2951 : */
2952 :
2953 0 : void CPL_STDCALL GDALGetOpenDatasets(GDALDatasetH **ppahDSList, int *pnCount)
2954 :
2955 : {
2956 0 : VALIDATE_POINTER0(ppahDSList, "GDALGetOpenDatasets");
2957 0 : VALIDATE_POINTER0(pnCount, "GDALGetOpenDatasets");
2958 :
2959 0 : *ppahDSList =
2960 0 : reinterpret_cast<GDALDatasetH *>(GDALDataset::GetOpenDatasets(pnCount));
2961 : }
2962 :
2963 : /************************************************************************/
2964 : /* GDALCleanOpenDatasetsList() */
2965 : /************************************************************************/
2966 :
2967 : // Useful when called from the child of a fork(), to avoid closing
2968 : // the datasets of the parent at the child termination.
2969 0 : void GDALNullifyOpenDatasetsList()
2970 : {
2971 0 : poAllDatasetMap = nullptr;
2972 0 : phSharedDatasetSet = nullptr;
2973 0 : ppDatasets = nullptr;
2974 0 : hDLMutex = nullptr;
2975 0 : }
2976 :
2977 : /************************************************************************/
2978 : /* GDALGetAccess() */
2979 : /************************************************************************/
2980 :
2981 : /**
2982 : * \brief Return access flag
2983 : *
2984 : * @see GDALDataset::GetAccess()
2985 : */
2986 :
2987 0 : int CPL_STDCALL GDALGetAccess(GDALDatasetH hDS)
2988 : {
2989 0 : VALIDATE_POINTER1(hDS, "GDALGetAccess", 0);
2990 :
2991 0 : return GDALDataset::FromHandle(hDS)->GetAccess();
2992 : }
2993 :
2994 : /************************************************************************/
2995 : /* AdviseRead() */
2996 : /************************************************************************/
2997 :
2998 : /**
2999 : * \brief Advise driver of upcoming read requests.
3000 : *
3001 : * Some GDAL drivers operate more efficiently if they know in advance what
3002 : * set of upcoming read requests will be made. The AdviseRead() method allows
3003 : * an application to notify the driver of the region and bands of interest,
3004 : * and at what resolution the region will be read.
3005 : *
3006 : * Many drivers just ignore the AdviseRead() call, but it can dramatically
3007 : * accelerate access via some drivers.
3008 : *
3009 : * Depending on call paths, drivers might receive several calls to
3010 : * AdviseRead() with the same parameters.
3011 : *
3012 : * @param nXOff The pixel offset to the top left corner of the region
3013 : * of the band to be accessed. This would be zero to start from the left side.
3014 : *
3015 : * @param nYOff The line offset to the top left corner of the region
3016 : * of the band to be accessed. This would be zero to start from the top.
3017 : *
3018 : * @param nXSize The width of the region of the band to be accessed in pixels.
3019 : *
3020 : * @param nYSize The height of the region of the band to be accessed in lines.
3021 : *
3022 : * @param nBufXSize the width of the buffer image into which the desired region
3023 : * is to be read, or from which it is to be written.
3024 : *
3025 : * @param nBufYSize the height of the buffer image into which the desired
3026 : * region is to be read, or from which it is to be written.
3027 : *
3028 : * @param eBufType the type of the pixel values in the pData data buffer. The
3029 : * pixel values will automatically be translated to/from the GDALRasterBand
3030 : * data type as needed.
3031 : *
3032 : * @param nBandCount the number of bands being read or written.
3033 : *
3034 : * @param panBandMap the list of nBandCount band numbers being read/written.
3035 : * Note band numbers are 1 based. This may be NULL to select the first
3036 : * nBandCount bands.
3037 : *
3038 : * @param papszOptions a list of name=value strings with special control
3039 : * options. Normally this is NULL.
3040 : *
3041 : * @return CE_Failure if the request is invalid and CE_None if it works or
3042 : * is ignored.
3043 : */
3044 :
3045 12313 : CPLErr GDALDataset::AdviseRead(int nXOff, int nYOff, int nXSize, int nYSize,
3046 : int nBufXSize, int nBufYSize,
3047 : GDALDataType eBufType, int nBandCount,
3048 : int *panBandMap, char **papszOptions)
3049 :
3050 : {
3051 : /* -------------------------------------------------------------------- */
3052 : /* Do some validation of parameters. */
3053 : /* -------------------------------------------------------------------- */
3054 12313 : int bStopProcessing = FALSE;
3055 12313 : CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
3056 : "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize,
3057 : nBufXSize, nBufYSize, nBandCount, panBandMap);
3058 12313 : if (eErr != CE_None || bStopProcessing)
3059 0 : return eErr;
3060 :
3061 54272 : for (int iBand = 0; iBand < nBandCount; ++iBand)
3062 : {
3063 41959 : GDALRasterBand *poBand = nullptr;
3064 :
3065 41959 : if (panBandMap == nullptr)
3066 40694 : poBand = GetRasterBand(iBand + 1);
3067 : else
3068 1265 : poBand = GetRasterBand(panBandMap[iBand]);
3069 :
3070 41959 : if (poBand == nullptr)
3071 0 : return CE_Failure;
3072 :
3073 83918 : eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize,
3074 41959 : nBufYSize, eBufType, papszOptions);
3075 :
3076 41959 : if (eErr != CE_None)
3077 0 : return eErr;
3078 : }
3079 :
3080 12313 : return CE_None;
3081 : }
3082 :
3083 : /************************************************************************/
3084 : /* GDALDatasetAdviseRead() */
3085 : /************************************************************************/
3086 :
3087 : /**
3088 : * \brief Advise driver of upcoming read requests.
3089 : *
3090 : * @see GDALDataset::AdviseRead()
3091 : */
3092 1 : CPLErr CPL_STDCALL GDALDatasetAdviseRead(GDALDatasetH hDS, int nXOff, int nYOff,
3093 : int nXSize, int nYSize, int nBufXSize,
3094 : int nBufYSize, GDALDataType eDT,
3095 : int nBandCount, int *panBandMap,
3096 : CSLConstList papszOptions)
3097 :
3098 : {
3099 1 : VALIDATE_POINTER1(hDS, "GDALDatasetAdviseRead", CE_Failure);
3100 :
3101 2 : return GDALDataset::FromHandle(hDS)->AdviseRead(
3102 : nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, nBandCount,
3103 1 : panBandMap, const_cast<char **>(papszOptions));
3104 : }
3105 :
3106 : /************************************************************************/
3107 : /* GDALAntiRecursionStruct */
3108 : /************************************************************************/
3109 :
3110 : // Prevent infinite recursion.
3111 : struct GDALAntiRecursionStruct
3112 : {
3113 : struct DatasetContext
3114 : {
3115 : std::string osFilename;
3116 : int nOpenFlags;
3117 : std::string osAllowedDrivers;
3118 :
3119 72075 : DatasetContext(const std::string &osFilenameIn, int nOpenFlagsIn,
3120 : const std::string &osAllowedDriversIn)
3121 72075 : : osFilename(osFilenameIn), nOpenFlags(nOpenFlagsIn),
3122 72075 : osAllowedDrivers(osAllowedDriversIn)
3123 : {
3124 72075 : }
3125 : };
3126 :
3127 : struct DatasetContextCompare
3128 : {
3129 1121580 : bool operator()(const DatasetContext &lhs,
3130 : const DatasetContext &rhs) const
3131 : {
3132 3278510 : return lhs.osFilename < rhs.osFilename ||
3133 1086050 : (lhs.osFilename == rhs.osFilename &&
3134 1071090 : (lhs.nOpenFlags < rhs.nOpenFlags ||
3135 2140580 : (lhs.nOpenFlags == rhs.nOpenFlags &&
3136 2191930 : lhs.osAllowedDrivers < rhs.osAllowedDrivers)));
3137 : }
3138 : };
3139 :
3140 : std::set<DatasetContext, DatasetContextCompare> aosDatasetNamesWithFlags{};
3141 : int nRecLevel = 0;
3142 : std::map<std::string, int> m_oMapDepth{};
3143 : };
3144 :
3145 : #ifdef _WIN32
3146 : // Currently thread_local and C++ objects don't work well with DLL on Windows
3147 : static void FreeAntiRecursionOpen(void *pData)
3148 : {
3149 : delete static_cast<GDALAntiRecursionStruct *>(pData);
3150 : }
3151 :
3152 : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3153 : {
3154 : static GDALAntiRecursionStruct dummy;
3155 : int bMemoryErrorOccurred = false;
3156 : void *pData =
3157 : CPLGetTLSEx(CTLS_GDALOPEN_ANTIRECURSION, &bMemoryErrorOccurred);
3158 : if (bMemoryErrorOccurred)
3159 : {
3160 : return dummy;
3161 : }
3162 : if (pData == nullptr)
3163 : {
3164 : auto pAntiRecursion = new GDALAntiRecursionStruct();
3165 : CPLSetTLSWithFreeFuncEx(CTLS_GDALOPEN_ANTIRECURSION, pAntiRecursion,
3166 : FreeAntiRecursionOpen, &bMemoryErrorOccurred);
3167 : if (bMemoryErrorOccurred)
3168 : {
3169 : delete pAntiRecursion;
3170 : return dummy;
3171 : }
3172 : return *pAntiRecursion;
3173 : }
3174 : return *static_cast<GDALAntiRecursionStruct *>(pData);
3175 : }
3176 : #else
3177 : static thread_local GDALAntiRecursionStruct g_tls_antiRecursion;
3178 :
3179 125993 : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3180 : {
3181 125993 : return g_tls_antiRecursion;
3182 : }
3183 : #endif
3184 :
3185 : //! @cond Doxygen_Suppress
3186 53917 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(const std::string &osIdentifier)
3187 53917 : : m_psAntiRecursionStruct(&GetAntiRecursionOpen()),
3188 : m_osIdentifier(osIdentifier),
3189 53917 : m_nDepth(++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3190 : {
3191 53917 : CPLAssert(!osIdentifier.empty());
3192 53917 : }
3193 :
3194 53917 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(
3195 53917 : const GDALAntiRecursionGuard &other, const std::string &osIdentifier)
3196 53917 : : m_psAntiRecursionStruct(other.m_psAntiRecursionStruct),
3197 53917 : m_osIdentifier(osIdentifier.empty()
3198 : ? osIdentifier
3199 26852 : : other.m_osIdentifier + osIdentifier),
3200 53917 : m_nDepth(m_osIdentifier.empty()
3201 53917 : ? 0
3202 80769 : : ++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3203 : {
3204 53917 : }
3205 :
3206 107834 : GDALAntiRecursionGuard::~GDALAntiRecursionGuard()
3207 : {
3208 107834 : if (!m_osIdentifier.empty())
3209 : {
3210 80769 : --m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier];
3211 : }
3212 107834 : }
3213 :
3214 : //! @endcond
3215 :
3216 : /************************************************************************/
3217 : /* GetFileList() */
3218 : /************************************************************************/
3219 :
3220 : /**
3221 : * \brief Fetch files forming dataset.
3222 : *
3223 : * Returns a list of files believed to be part of this dataset. If it returns
3224 : * an empty list of files it means there is believed to be no local file
3225 : * system files associated with the dataset (for instance a virtual dataset).
3226 : * The returned file list is owned by the caller and should be deallocated
3227 : * with CSLDestroy().
3228 : *
3229 : * The returned filenames will normally be relative or absolute paths
3230 : * depending on the path used to originally open the dataset. The strings
3231 : * will be UTF-8 encoded.
3232 : *
3233 : * This method is the same as the C GDALGetFileList() function.
3234 : *
3235 : * @return NULL or a NULL terminated array of file names.
3236 : */
3237 :
3238 4776 : char **GDALDataset::GetFileList()
3239 :
3240 : {
3241 9552 : CPLString osMainFilename = GetDescription();
3242 : VSIStatBufL sStat;
3243 :
3244 4776 : GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3245 : const GDALAntiRecursionStruct::DatasetContext datasetCtxt(osMainFilename, 0,
3246 9552 : std::string());
3247 4776 : auto &aosDatasetList = sAntiRecursion.aosDatasetNamesWithFlags;
3248 4776 : if (cpl::contains(aosDatasetList, datasetCtxt))
3249 0 : return nullptr;
3250 :
3251 : /* -------------------------------------------------------------------- */
3252 : /* Is the main filename even a real filesystem object? */
3253 : /* -------------------------------------------------------------------- */
3254 : int bMainFileReal =
3255 4776 : VSIStatExL(osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
3256 :
3257 : /* -------------------------------------------------------------------- */
3258 : /* Form new list. */
3259 : /* -------------------------------------------------------------------- */
3260 4776 : char **papszList = nullptr;
3261 :
3262 4776 : if (bMainFileReal)
3263 4721 : papszList = CSLAddString(papszList, osMainFilename);
3264 :
3265 4776 : if (sAntiRecursion.nRecLevel == 100)
3266 : {
3267 0 : CPLError(CE_Failure, CPLE_AppDefined,
3268 : "GetFileList() called with too many recursion levels");
3269 0 : return papszList;
3270 : }
3271 4776 : ++sAntiRecursion.nRecLevel;
3272 :
3273 : /* -------------------------------------------------------------------- */
3274 : /* Do we have a known overview file? */
3275 : /* -------------------------------------------------------------------- */
3276 4776 : if (oOvManager.IsInitialized() && oOvManager.poODS != nullptr)
3277 : {
3278 63 : auto iter = aosDatasetList.insert(datasetCtxt).first;
3279 63 : char **papszOvrList = oOvManager.poODS->GetFileList();
3280 63 : papszList = CSLInsertStrings(papszList, -1, papszOvrList);
3281 63 : CSLDestroy(papszOvrList);
3282 63 : aosDatasetList.erase(iter);
3283 : }
3284 :
3285 : /* -------------------------------------------------------------------- */
3286 : /* Do we have a known mask file? */
3287 : /* -------------------------------------------------------------------- */
3288 4776 : if (oOvManager.HaveMaskFile())
3289 : {
3290 11 : auto iter = aosDatasetList.insert(datasetCtxt).first;
3291 11 : for (const char *pszFile :
3292 22 : CPLStringList(oOvManager.poMaskDS->GetFileList()))
3293 : {
3294 11 : if (CSLFindString(papszList, pszFile) < 0)
3295 11 : papszList = CSLAddString(papszList, pszFile);
3296 : }
3297 11 : aosDatasetList.erase(iter);
3298 : }
3299 :
3300 4776 : --sAntiRecursion.nRecLevel;
3301 :
3302 4776 : return papszList;
3303 : }
3304 :
3305 : /************************************************************************/
3306 : /* GDALGetFileList() */
3307 : /************************************************************************/
3308 :
3309 : /**
3310 : * \brief Fetch files forming dataset.
3311 : *
3312 : * @see GDALDataset::GetFileList()
3313 : */
3314 :
3315 3982 : char **CPL_STDCALL GDALGetFileList(GDALDatasetH hDS)
3316 :
3317 : {
3318 3982 : VALIDATE_POINTER1(hDS, "GDALGetFileList", nullptr);
3319 :
3320 3982 : return GDALDataset::FromHandle(hDS)->GetFileList();
3321 : }
3322 :
3323 : /************************************************************************/
3324 : /* CreateMaskBand() */
3325 : /************************************************************************/
3326 :
3327 : /**
3328 : * \brief Adds a mask band to the dataset
3329 : *
3330 : * The default implementation of the CreateMaskBand() method is implemented
3331 : * based on similar rules to the .ovr handling implemented using the
3332 : * GDALDefaultOverviews object. A TIFF file with the extension .msk will
3333 : * be created with the same basename as the original file, and it will have
3334 : * one band.
3335 : * The mask images will be deflate compressed tiled images with the same
3336 : * block size as the original image if possible.
3337 : * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
3338 : * level, where xx matches the band number of a band of the main dataset. The
3339 : * value of those items will be the one of the nFlagsIn parameter.
3340 : *
3341 : * Note that if you got a mask band with a previous call to GetMaskBand(), it
3342 : * might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
3343 : * again.
3344 : *
3345 : * @since GDAL 1.5.0
3346 : *
3347 : * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.
3348 : * GMF_PER_DATASET will be always set, even if not explicitly
3349 : * specified.
3350 : * @return CE_None on success or CE_Failure on an error.
3351 : *
3352 : * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html
3353 : * @see GDALRasterBand::CreateMaskBand()
3354 : *
3355 : */
3356 17 : CPLErr GDALDataset::CreateMaskBand(int nFlagsIn)
3357 :
3358 : {
3359 17 : if (oOvManager.IsInitialized())
3360 : {
3361 17 : CPLErr eErr = oOvManager.CreateMaskBand(nFlagsIn, -1);
3362 17 : if (eErr != CE_None)
3363 0 : return eErr;
3364 :
3365 : // Invalidate existing raster band masks.
3366 45 : for (int i = 0; i < nBands; ++i)
3367 : {
3368 28 : GDALRasterBand *poBand = papoBands[i];
3369 28 : poBand->poMask.reset();
3370 : }
3371 :
3372 17 : return CE_None;
3373 : }
3374 :
3375 0 : ReportError(CE_Failure, CPLE_NotSupported,
3376 : "CreateMaskBand() not supported for this dataset.");
3377 :
3378 0 : return CE_Failure;
3379 : }
3380 :
3381 : /************************************************************************/
3382 : /* GDALCreateDatasetMaskBand() */
3383 : /************************************************************************/
3384 :
3385 : /**
3386 : * \brief Adds a mask band to the dataset
3387 : * @see GDALDataset::CreateMaskBand()
3388 : */
3389 84 : CPLErr CPL_STDCALL GDALCreateDatasetMaskBand(GDALDatasetH hDS, int nFlags)
3390 :
3391 : {
3392 84 : VALIDATE_POINTER1(hDS, "GDALCreateDatasetMaskBand", CE_Failure);
3393 :
3394 84 : return GDALDataset::FromHandle(hDS)->CreateMaskBand(nFlags);
3395 : }
3396 :
3397 : /************************************************************************/
3398 : /* GDALOpen() */
3399 : /************************************************************************/
3400 :
3401 : /**
3402 : * \brief Open a raster file as a GDALDataset.
3403 : *
3404 : * This function will try to open the passed file, or virtual dataset
3405 : * name by invoking the Open method of each registered GDALDriver in turn.
3406 : * The first successful open will result in a returned dataset. If all
3407 : * drivers fail then NULL is returned and an error is issued.
3408 : *
3409 : * Several recommendations :
3410 : * <ul>
3411 : * <li>If you open a dataset object with GA_Update access, it is not recommended
3412 : * to open a new dataset on the same underlying file.</li>
3413 : * <li>The returned dataset should only be accessed by one thread at a time. If
3414 : * you want to use it from different threads, you must add all necessary code
3415 : * (mutexes, etc.) to avoid concurrent use of the object. (Some drivers, such
3416 : * as GeoTIFF, maintain internal state variables that are updated each time a
3417 : * new block is read, thus preventing concurrent use.) </li>
3418 : * </ul>
3419 : *
3420 : * For drivers supporting the VSI virtual file API, it is possible to open a
3421 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3422 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3423 : * server (see VSIInstallCurlFileHandler())
3424 : *
3425 : * \sa GDALOpenShared()
3426 : * \sa GDALOpenEx()
3427 : *
3428 : * @param pszFilename the name of the file to access. In the case of
3429 : * exotic drivers this may not refer to a physical file, but instead contain
3430 : * information for the driver on how to access a dataset. It should be in UTF-8
3431 : * encoding.
3432 : *
3433 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
3434 : * drivers support only read only access.
3435 : *
3436 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3437 : * this handle can be cast to a GDALDataset *.
3438 : */
3439 :
3440 24259 : GDALDatasetH CPL_STDCALL GDALOpen(const char *pszFilename, GDALAccess eAccess)
3441 :
3442 : {
3443 24259 : const int nUpdateFlag = eAccess == GA_Update ? GDAL_OF_UPDATE : 0;
3444 24259 : const int nOpenFlags = GDAL_OF_RASTER | nUpdateFlag | GDAL_OF_VERBOSE_ERROR;
3445 : GDALDatasetH hDataset =
3446 24259 : GDALOpenEx(pszFilename, nOpenFlags, nullptr, nullptr, nullptr);
3447 24255 : return hDataset;
3448 : }
3449 :
3450 : /************************************************************************/
3451 : /* GetSharedDS() */
3452 : /************************************************************************/
3453 :
3454 6481 : static GDALDataset *GetSharedDS(const char *pszFilename,
3455 : unsigned int nOpenFlags,
3456 : const char *const *papszOpenOptions)
3457 : {
3458 12962 : CPLMutexHolderD(&hDLMutex);
3459 :
3460 6481 : if (phSharedDatasetSet != nullptr)
3461 : {
3462 6225 : const GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
3463 : SharedDatasetCtxt sStruct;
3464 :
3465 6225 : sStruct.nPID = nThisPID;
3466 6225 : sStruct.pszDescription = const_cast<char *>(pszFilename);
3467 6225 : sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
3468 : std::string osConcatenatedOpenOptions =
3469 6225 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
3470 6225 : sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
3471 6225 : sStruct.poDS = nullptr;
3472 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
3473 6225 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3474 6225 : if (psStruct == nullptr && (nOpenFlags & GDAL_OF_UPDATE) == 0)
3475 : {
3476 120 : sStruct.nOpenFlags |= GDAL_OF_UPDATE;
3477 : psStruct = static_cast<SharedDatasetCtxt *>(
3478 120 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3479 : }
3480 6225 : if (psStruct)
3481 : {
3482 6106 : return psStruct->poDS;
3483 : }
3484 : }
3485 375 : return nullptr;
3486 : }
3487 :
3488 : /************************************************************************/
3489 : /* GDALOpenEx() */
3490 : /************************************************************************/
3491 :
3492 : /**
3493 : * \brief Open a raster or vector file as a GDALDataset.
3494 : *
3495 : * This function will try to open the passed file, or virtual dataset
3496 : * name by invoking the Open method of each registered GDALDriver in turn.
3497 : * The first successful open will result in a returned dataset. If all
3498 : * drivers fail then NULL is returned and an error is issued.
3499 : *
3500 : * Several recommendations :
3501 : * <ul>
3502 : * <li>If you open a dataset object with GDAL_OF_UPDATE access, it is not
3503 : * recommended to open a new dataset on the same underlying file.</li>
3504 : * <li>The returned dataset should only be accessed by one thread at a time. If
3505 : * you want to use it from different threads, you must add all necessary code
3506 : * (mutexes, etc.) to avoid concurrent use of the object. (Some drivers, such
3507 : * as GeoTIFF, maintain internal state variables that are updated each time a
3508 : * new block is read, thus preventing concurrent use.) </li>
3509 : * </ul>
3510 : *
3511 : * For drivers supporting the VSI virtual file API, it is possible to open a
3512 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3513 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3514 : * server (see VSIInstallCurlFileHandler())
3515 : *
3516 : * In order to reduce the need for searches through the operating system
3517 : * file system machinery, it is possible to give an optional list of files with
3518 : * the papszSiblingFiles parameter.
3519 : * This is the list of all files at the same level in the file system as the
3520 : * target file, including the target file. The filenames must not include any
3521 : * path components, are essentially just the output of VSIReadDir() on the
3522 : * parent directory. If the target object does not have filesystem semantics
3523 : * then the file list should be NULL.
3524 : *
3525 : * @param pszFilename the name of the file to access. In the case of
3526 : * exotic drivers this may not refer to a physical file, but instead contain
3527 : * information for the driver on how to access a dataset. It should be in UTF-8
3528 : * encoding.
3529 : *
3530 : * @param nOpenFlags a combination of GDAL_OF_ flags that may be combined
3531 : * through logical or operator.
3532 : * <ul>
3533 : * <li>Driver kind:
3534 : * <ul>
3535 : * <li>GDAL_OF_RASTER for raster drivers,</li>
3536 : * <li>GDAL_OF_MULTIDIM_RASTER for multidimensional raster drivers,</li>
3537 : * <li>GDAL_OF_VECTOR for vector drivers,</li>
3538 : * <li>GDAL_OF_GNM for Geographic Network Model drivers.</li>
3539 : * </ul>
3540 : * GDAL_OF_RASTER and GDAL_OF_MULTIDIM_RASTER are generally mutually
3541 : * exclusive. If none of the value is specified, GDAL_OF_RASTER | GDAL_OF_VECTOR
3542 : * | GDAL_OF_GNM is implied.
3543 : * </li>
3544 : * <li>Access mode: GDAL_OF_READONLY (exclusive)or GDAL_OF_UPDATE.
3545 : * </li>
3546 : * <li>Shared mode: GDAL_OF_SHARED. If set,
3547 : * it allows the sharing of GDALDataset handles for a dataset with other callers
3548 : * that have set GDAL_OF_SHARED. In particular, GDALOpenEx() will first consult
3549 : * its list of currently open and shared GDALDataset's, and if the
3550 : * GetDescription() name for one exactly matches the pszFilename passed to
3551 : * GDALOpenEx() it will be referenced and returned, if GDALOpenEx() is called
3552 : * from the same thread.
3553 : * </li>
3554 : * <li>Thread safe mode: GDAL_OF_THREAD_SAFE (added in 3.10).
3555 : * This must be use in combination with GDAL_OF_RASTER, and is mutually
3556 : * exclusive with GDAL_OF_UPDATE, GDAL_OF_VECTOR, GDAL_OF_MULTIDIM_RASTER or
3557 : * GDAL_OF_GNM.
3558 : * </li>
3559 : * <li>Verbose error: GDAL_OF_VERBOSE_ERROR. If set,
3560 : * a failed attempt to open the file will lead to an error message to be
3561 : * reported.
3562 : * </li>
3563 : * </ul>
3564 : *
3565 : * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
3566 : * terminated list of strings with the driver short names that must be
3567 : * considered.
3568 : *
3569 : * @param papszOpenOptions NULL, or a NULL terminated list of strings with open
3570 : * options passed to candidate drivers. An option exists for all drivers,
3571 : * OVERVIEW_LEVEL=level, to select a particular overview level of a dataset.
3572 : * The level index starts at 0. The level number can be suffixed by "only" to
3573 : * specify that only this overview level must be visible, and not sub-levels.
3574 : * Open options are validated by default, and a warning is emitted in case the
3575 : * option is not recognized. In some scenarios, it might be not desirable (e.g.
3576 : * when not knowing which driver will open the file), so the special open option
3577 : * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings. Alternatively,
3578 : * since GDAL 2.1, an option name can be preceded by the @ character to indicate
3579 : * that it may not cause a warning if the driver doesn't declare this option.
3580 : * Starting with GDAL 3.3, OVERVIEW_LEVEL=NONE is supported to indicate that
3581 : * no overviews should be exposed.
3582 : *
3583 : * @param papszSiblingFiles NULL, or a NULL terminated list of strings that are
3584 : * filenames that are auxiliary to the main filename. If NULL is passed, a
3585 : * probing of the file system will be done.
3586 : *
3587 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3588 : * this handle can be cast to a GDALDataset *.
3589 : *
3590 : * @since GDAL 2.0
3591 : */
3592 :
3593 73410 : GDALDatasetH CPL_STDCALL GDALOpenEx(const char *pszFilename,
3594 : unsigned int nOpenFlags,
3595 : const char *const *papszAllowedDrivers,
3596 : const char *const *papszOpenOptions,
3597 : const char *const *papszSiblingFiles)
3598 : {
3599 73410 : VALIDATE_POINTER1(pszFilename, "GDALOpen", nullptr);
3600 :
3601 : // Do some sanity checks on incompatible flags with thread-safe mode.
3602 73410 : if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
3603 : {
3604 : const struct
3605 : {
3606 : int nFlag;
3607 : const char *pszFlagName;
3608 128 : } asFlags[] = {
3609 : {GDAL_OF_UPDATE, "GDAL_OF_UPDATE"},
3610 : {GDAL_OF_VECTOR, "GDAL_OF_VECTOR"},
3611 : {GDAL_OF_MULTIDIM_RASTER, "GDAL_OF_MULTIDIM_RASTER"},
3612 : {GDAL_OF_GNM, "GDAL_OF_GNM"},
3613 : };
3614 :
3615 630 : for (const auto &asFlag : asFlags)
3616 : {
3617 506 : if ((nOpenFlags & asFlag.nFlag) != 0)
3618 : {
3619 4 : CPLError(CE_Failure, CPLE_IllegalArg,
3620 : "GDAL_OF_THREAD_SAFE and %s are mutually "
3621 : "exclusive",
3622 4 : asFlag.pszFlagName);
3623 4 : return nullptr;
3624 : }
3625 : }
3626 : }
3627 :
3628 : // If no driver kind is specified, assume all are to be probed.
3629 73406 : if ((nOpenFlags & GDAL_OF_KIND_MASK) == 0)
3630 6032 : nOpenFlags |= GDAL_OF_KIND_MASK & ~GDAL_OF_MULTIDIM_RASTER;
3631 :
3632 : /* -------------------------------------------------------------------- */
3633 : /* In case of shared dataset, first scan the existing list to see */
3634 : /* if it could already contain the requested dataset. */
3635 : /* -------------------------------------------------------------------- */
3636 73406 : if (nOpenFlags & GDAL_OF_SHARED)
3637 : {
3638 6481 : if (nOpenFlags & GDAL_OF_INTERNAL)
3639 : {
3640 0 : CPLError(CE_Failure, CPLE_IllegalArg,
3641 : "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");
3642 0 : return nullptr;
3643 : }
3644 :
3645 : auto poSharedDS =
3646 6481 : GetSharedDS(pszFilename, nOpenFlags, papszOpenOptions);
3647 6481 : if (poSharedDS)
3648 : {
3649 6106 : poSharedDS->Reference();
3650 6106 : return poSharedDS;
3651 : }
3652 : }
3653 :
3654 67300 : GDALDriverManager *poDM = GetGDALDriverManager();
3655 : // CPLLocaleC oLocaleForcer;
3656 :
3657 67300 : CPLErrorReset();
3658 67300 : VSIErrorReset();
3659 67300 : CPLAssert(nullptr != poDM);
3660 :
3661 : // Build GDALOpenInfo just now to avoid useless file stat'ing if a
3662 : // shared dataset was asked before.
3663 : GDALOpenInfo oOpenInfo(pszFilename, nOpenFlags,
3664 134531 : const_cast<char **>(papszSiblingFiles));
3665 67298 : oOpenInfo.papszAllowedDrivers = papszAllowedDrivers;
3666 :
3667 67298 : GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3668 67299 : if (sAntiRecursion.nRecLevel == 100)
3669 : {
3670 0 : CPLError(CE_Failure, CPLE_AppDefined,
3671 : "GDALOpen() called with too many recursion levels");
3672 0 : return nullptr;
3673 : }
3674 :
3675 134530 : std::string osAllowedDrivers;
3676 160204 : for (const char *pszDriverName : cpl::Iterate(papszAllowedDrivers))
3677 92904 : osAllowedDrivers += pszDriverName;
3678 : auto dsCtxt = GDALAntiRecursionStruct::DatasetContext(
3679 201829 : std::string(pszFilename), nOpenFlags, osAllowedDrivers);
3680 67292 : if (cpl::contains(sAntiRecursion.aosDatasetNamesWithFlags, dsCtxt))
3681 : {
3682 0 : CPLError(CE_Failure, CPLE_AppDefined,
3683 : "GDALOpen() called on %s recursively", pszFilename);
3684 0 : return nullptr;
3685 : }
3686 :
3687 : // Remove leading @ if present.
3688 : char **papszOpenOptionsCleaned =
3689 67284 : CSLDuplicate(const_cast<char **>(papszOpenOptions));
3690 72581 : for (char **papszIter = papszOpenOptionsCleaned; papszIter && *papszIter;
3691 : ++papszIter)
3692 : {
3693 5295 : char *pszOption = *papszIter;
3694 5295 : if (pszOption[0] == '@')
3695 181 : memmove(pszOption, pszOption + 1, strlen(pszOption + 1) + 1);
3696 : }
3697 :
3698 67286 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3699 67286 : oOpenInfo.nOpenFlags |= GDAL_OF_FROM_GDALOPEN;
3700 :
3701 : #ifdef OGRAPISPY_ENABLED
3702 67286 : const bool bUpdate = (nOpenFlags & GDAL_OF_UPDATE) != 0;
3703 : const int iSnapshot =
3704 16914 : (nOpenFlags & GDAL_OF_VECTOR) != 0 && (nOpenFlags & GDAL_OF_RASTER) == 0
3705 84200 : ? OGRAPISpyOpenTakeSnapshot(pszFilename, bUpdate)
3706 67286 : : INT_MIN;
3707 : #endif
3708 :
3709 67286 : const int nDriverCount = poDM->GetDriverCount(/*bIncludeHidden=*/true);
3710 67296 : GDALDriver *poMissingPluginDriver = nullptr;
3711 134594 : std::vector<GDALDriver *> apoSecondPassDrivers;
3712 :
3713 : // Lookup of matching driver for dataset can involve up to 2 passes:
3714 : // - in the first pass, all drivers that are compabile of the request mode
3715 : // (raster/vector/etc.) are probed using their Identify() method if it
3716 : // exists. If the Identify() method returns FALSE, the driver is skipped.
3717 : // If the Identify() methods returns GDAL_IDENTIFY_UNKNOWN and that the
3718 : // driver is a deferred-loading plugin, it is added to the
3719 : // apoSecondPassDrivers list for potential later probing, and execution
3720 : // continues to the next driver in the list.
3721 : // Otherwise if Identify() returns non-FALSE, the Open() method is used.
3722 : // If Open() returns a non-NULL dataset, the loop stops and it is
3723 : // returned. Otherwise looping over remaining drivers continues.
3724 : // - the second pass is optional, only if at least one driver was added
3725 : // into apoSecondPassDrivers during the first pass. It is similar
3726 : // to the first pass except it runs only on apoSecondPassDrivers drivers.
3727 : // And the Open() method of such drivers is used, causing them to be
3728 : // loaded for real.
3729 67286 : int iPass = 1;
3730 67300 : retry:
3731 7896360 : for (int iDriver = 0;
3732 7896400 : iDriver < (iPass == 1 ? nDriverCount
3733 39 : : static_cast<int>(apoSecondPassDrivers.size()));
3734 : ++iDriver)
3735 : {
3736 : GDALDriver *poDriver =
3737 7868400 : iPass == 1 ? poDM->GetDriver(iDriver, /*bIncludeHidden=*/true)
3738 0 : : apoSecondPassDrivers[iDriver];
3739 11405100 : if (papszAllowedDrivers != nullptr &&
3740 3522630 : CSLFindString(papszAllowedDrivers,
3741 : GDALGetDriverShortName(poDriver)) == -1)
3742 : {
3743 7344360 : continue;
3744 : }
3745 :
3746 4447530 : if (poDriver->GetMetadataItem(GDAL_DCAP_OPEN) == nullptr)
3747 38752 : continue;
3748 :
3749 11841500 : if ((nOpenFlags & GDAL_OF_RASTER) != 0 &&
3750 6502870 : (nOpenFlags & GDAL_OF_VECTOR) == 0 &&
3751 2092340 : poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr)
3752 523988 : continue;
3753 11281500 : if ((nOpenFlags & GDAL_OF_VECTOR) != 0 &&
3754 5642690 : (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3755 1756150 : poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
3756 1347080 : continue;
3757 5357600 : if ((nOpenFlags & GDAL_OF_MULTIDIM_RASTER) != 0 &&
3758 2682550 : (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3759 143081 : poDriver->GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) == nullptr)
3760 135200 : continue;
3761 :
3762 : // Remove general OVERVIEW_LEVEL open options from list before passing
3763 : // it to the driver, if it isn't a driver specific option already.
3764 2404270 : char **papszTmpOpenOptions = nullptr;
3765 2404270 : char **papszTmpOpenOptionsToValidate = nullptr;
3766 2404270 : char **papszOptionsToValidate = const_cast<char **>(papszOpenOptions);
3767 7201400 : if (CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") !=
3768 2404450 : nullptr &&
3769 183 : (poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST) == nullptr ||
3770 2398630 : CPLString(poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST))
3771 111 : .ifind("OVERVIEW_LEVEL") == std::string::npos))
3772 : {
3773 183 : papszTmpOpenOptions = CSLDuplicate(papszOpenOptionsCleaned);
3774 : papszTmpOpenOptions =
3775 183 : CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", nullptr);
3776 183 : oOpenInfo.papszOpenOptions = papszTmpOpenOptions;
3777 :
3778 183 : papszOptionsToValidate = CSLDuplicate(papszOptionsToValidate);
3779 183 : papszOptionsToValidate = CSLSetNameValue(papszOptionsToValidate,
3780 : "OVERVIEW_LEVEL", nullptr);
3781 183 : papszTmpOpenOptionsToValidate = papszOptionsToValidate;
3782 : }
3783 :
3784 : const int nIdentifyRes =
3785 2398610 : poDriver->pfnIdentifyEx
3786 4799430 : ? poDriver->pfnIdentifyEx(poDriver, &oOpenInfo)
3787 2398600 : : poDriver->pfnIdentify ? poDriver->pfnIdentify(&oOpenInfo)
3788 2400820 : : GDAL_IDENTIFY_UNKNOWN;
3789 2400820 : if (nIdentifyRes == FALSE)
3790 : {
3791 1865430 : CSLDestroy(papszTmpOpenOptions);
3792 1864180 : CSLDestroy(papszTmpOpenOptionsToValidate);
3793 1864300 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3794 1864300 : continue;
3795 : }
3796 535784 : else if (iPass == 1 && nIdentifyRes < 0 &&
3797 1071300 : poDriver->pfnOpen == nullptr &&
3798 120 : poDriver->GetMetadataItem("IS_NON_LOADED_PLUGIN"))
3799 : {
3800 : // Not loaded plugin
3801 119 : apoSecondPassDrivers.push_back(poDriver);
3802 119 : CSLDestroy(papszTmpOpenOptions);
3803 119 : CSLDestroy(papszTmpOpenOptionsToValidate);
3804 119 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3805 119 : continue;
3806 : }
3807 :
3808 535273 : const bool bIdentifyRes = nIdentifyRes == GDAL_IDENTIFY_TRUE;
3809 535273 : if (bIdentifyRes)
3810 : {
3811 47420 : GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3812 : }
3813 :
3814 : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3815 : const bool bFpAvailableBefore = oOpenInfo.fpL != nullptr;
3816 : CPLErrorReset();
3817 : #endif
3818 :
3819 535264 : sAntiRecursion.nRecLevel++;
3820 535264 : sAntiRecursion.aosDatasetNamesWithFlags.insert(dsCtxt);
3821 :
3822 535358 : GDALDataset *poDS = poDriver->Open(&oOpenInfo, false);
3823 :
3824 534523 : sAntiRecursion.nRecLevel--;
3825 534523 : sAntiRecursion.aosDatasetNamesWithFlags.erase(dsCtxt);
3826 :
3827 535089 : if (poDriver->pfnOpen != nullptr)
3828 : {
3829 : // If we couldn't determine for sure with Identify() (it returned
3830 : // -1), but Open() managed to open the file, post validate options.
3831 534936 : if (poDS != nullptr &&
3832 48016 : (poDriver->pfnIdentify || poDriver->pfnIdentifyEx) &&
3833 47216 : !bIdentifyRes)
3834 : {
3835 818 : GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3836 : }
3837 : }
3838 153 : else if (poDriver->pfnOpenWithDriverArg != nullptr)
3839 : {
3840 : // do nothing
3841 : }
3842 0 : else if (bIdentifyRes &&
3843 0 : poDriver->GetMetadataItem("MISSING_PLUGIN_FILENAME"))
3844 : {
3845 0 : if (!poMissingPluginDriver)
3846 : {
3847 0 : poMissingPluginDriver = poDriver;
3848 : }
3849 : }
3850 : else
3851 : {
3852 : // should not happen given the GDAL_DCAP_OPEN check
3853 0 : CSLDestroy(papszTmpOpenOptions);
3854 0 : CSLDestroy(papszTmpOpenOptionsToValidate);
3855 0 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3856 0 : continue;
3857 : }
3858 :
3859 535089 : CSLDestroy(papszTmpOpenOptions);
3860 534645 : CSLDestroy(papszTmpOpenOptionsToValidate);
3861 534222 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3862 :
3863 534222 : if (poDS != nullptr)
3864 : {
3865 48020 : if (poDS->papszOpenOptions == nullptr)
3866 : {
3867 47764 : poDS->papszOpenOptions = papszOpenOptionsCleaned;
3868 47764 : papszOpenOptionsCleaned = nullptr;
3869 : }
3870 :
3871 : // Deal with generic OVERVIEW_LEVEL open option, unless it is
3872 : // driver specific.
3873 144057 : if (CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") !=
3874 48059 : nullptr &&
3875 39 : (poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST) ==
3876 78 : nullptr ||
3877 48058 : CPLString(poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST))
3878 39 : .ifind("OVERVIEW_LEVEL") == std::string::npos))
3879 : {
3880 : CPLString osVal(
3881 78 : CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL"));
3882 39 : const int nOvrLevel = EQUAL(osVal, "NONE") ? -1 : atoi(osVal);
3883 : const bool bThisLevelOnly =
3884 39 : nOvrLevel == -1 || osVal.ifind("only") != std::string::npos;
3885 : GDALDataset *poOvrDS =
3886 39 : GDALCreateOverviewDataset(poDS, nOvrLevel, bThisLevelOnly);
3887 39 : if (poOvrDS && (nOpenFlags & GDAL_OF_SHARED) != 0)
3888 : {
3889 4 : if (strcmp(pszFilename, poDS->GetDescription()) != 0)
3890 : {
3891 0 : CPLError(
3892 : CE_Warning, CPLE_NotSupported,
3893 : "A dataset opened by GDALOpenShared should have "
3894 : "the same filename (%s) "
3895 : "and description (%s)",
3896 0 : pszFilename, poDS->GetDescription());
3897 : }
3898 : else
3899 : {
3900 4 : CSLDestroy(poDS->papszOpenOptions);
3901 4 : poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
3902 4 : poDS->papszOpenOptions = CSLSetNameValue(
3903 : poDS->papszOpenOptions, "OVERVIEW_LEVEL", nullptr);
3904 : }
3905 : }
3906 39 : poDS->ReleaseRef();
3907 39 : poDS = poOvrDS;
3908 39 : if (poDS == nullptr)
3909 : {
3910 1 : if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
3911 : {
3912 1 : CPLError(CE_Failure, CPLE_OpenFailed,
3913 : "Cannot open overview level %d of %s",
3914 : nOvrLevel, pszFilename);
3915 : }
3916 : }
3917 : else
3918 : {
3919 : // For thread-safe opening, currently poDS is what will be
3920 : // the "master" dataset owned by the thread-safe dataset
3921 : // returned to the user, hence we do not register it as a
3922 : // visible one in the open dataset list, or mark it as shared.
3923 38 : if (!(nOpenFlags & GDAL_OF_INTERNAL) &&
3924 36 : !(nOpenFlags & GDAL_OF_THREAD_SAFE))
3925 : {
3926 35 : poDS->AddToDatasetOpenList();
3927 : }
3928 38 : if (nOpenFlags & GDAL_OF_SHARED)
3929 : {
3930 4 : CSLDestroy(poDS->papszOpenOptions);
3931 4 : poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
3932 4 : poDS->nOpenFlags = nOpenFlags;
3933 4 : if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
3934 4 : poDS->MarkAsShared();
3935 : }
3936 : }
3937 : }
3938 47979 : else if (nOpenFlags & GDAL_OF_SHARED)
3939 : {
3940 366 : if (strcmp(pszFilename, poDS->GetDescription()) != 0)
3941 : {
3942 2 : CPLError(CE_Warning, CPLE_NotSupported,
3943 : "A dataset opened by GDALOpenShared should have "
3944 : "the same filename (%s) "
3945 : "and description (%s)",
3946 2 : pszFilename, poDS->GetDescription());
3947 : }
3948 364 : else if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
3949 : {
3950 : // For thread-safe opening, currently poDS is what will be
3951 : // the "master" dataset owned by the thread-safe dataset
3952 : // returned to the user, hence we do not or mark it as shared.
3953 364 : poDS->MarkAsShared();
3954 : }
3955 : }
3956 :
3957 48018 : VSIErrorReset();
3958 :
3959 48020 : CSLDestroy(papszOpenOptionsCleaned);
3960 :
3961 : #ifdef OGRAPISPY_ENABLED
3962 48018 : if (iSnapshot != INT_MIN)
3963 : {
3964 10566 : GDALDatasetH hDS = GDALDataset::ToHandle(poDS);
3965 10566 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
3966 10566 : poDS = GDALDataset::FromHandle(hDS);
3967 : }
3968 : #endif
3969 :
3970 48018 : if (poDS)
3971 : {
3972 48017 : poDS->m_bCanBeReopened = true;
3973 :
3974 48017 : if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
3975 : {
3976 : poDS =
3977 248 : GDALGetThreadSafeDataset(
3978 248 : std::unique_ptr<GDALDataset>(poDS), GDAL_OF_RASTER)
3979 124 : .release();
3980 124 : if (poDS)
3981 : {
3982 124 : poDS->m_bCanBeReopened = true;
3983 124 : poDS->poDriver = poDriver;
3984 124 : poDS->nOpenFlags = nOpenFlags;
3985 124 : if (!(nOpenFlags & GDAL_OF_INTERNAL))
3986 124 : poDS->AddToDatasetOpenList();
3987 124 : if (nOpenFlags & GDAL_OF_SHARED)
3988 0 : poDS->MarkAsShared();
3989 : }
3990 : }
3991 : }
3992 :
3993 48868 : return poDS;
3994 : }
3995 :
3996 : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3997 : if (bFpAvailableBefore && oOpenInfo.fpL == nullptr)
3998 : {
3999 : // In case the file descriptor was "consumed" by a driver
4000 : // that ultimately failed, re-open it for next drivers.
4001 : oOpenInfo.fpL = VSIFOpenL(
4002 : pszFilename, (oOpenInfo.eAccess == GA_Update) ? "r+b" : "rb");
4003 : }
4004 : #else
4005 486202 : if (CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() > CE_Warning)
4006 : {
4007 1426 : CSLDestroy(papszOpenOptionsCleaned);
4008 :
4009 : #ifdef OGRAPISPY_ENABLED
4010 850 : if (iSnapshot != INT_MIN)
4011 : {
4012 140 : GDALDatasetH hDS = nullptr;
4013 140 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4014 : }
4015 : #endif
4016 850 : return nullptr;
4017 : }
4018 : #endif
4019 : }
4020 :
4021 : // cppcheck-suppress knownConditionTrueFalse
4022 27987 : if (iPass == 1 && !apoSecondPassDrivers.empty())
4023 : {
4024 16 : CPLDebugOnly("GDAL", "GDALOpen(): Second pass");
4025 14 : iPass = 2;
4026 14 : goto retry;
4027 : }
4028 :
4029 27949 : CSLDestroy(papszOpenOptionsCleaned);
4030 :
4031 : #ifdef OGRAPISPY_ENABLED
4032 18358 : if (iSnapshot != INT_MIN)
4033 : {
4034 936 : GDALDatasetH hDS = nullptr;
4035 936 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4036 : }
4037 : #endif
4038 :
4039 18358 : if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
4040 : {
4041 : // Check to see if there was a filesystem error, and report it if so.
4042 : // If not, return a more generic error.
4043 5666 : if (!VSIToCPLError(CE_Failure, CPLE_OpenFailed))
4044 : {
4045 152 : if (nDriverCount == 0)
4046 : {
4047 1 : CPLError(CE_Failure, CPLE_OpenFailed, "No driver registered.");
4048 : }
4049 151 : else if (oOpenInfo.bStatOK)
4050 : {
4051 148 : if (!poMissingPluginDriver)
4052 : {
4053 148 : CPLError(CE_Failure, CPLE_OpenFailed,
4054 : "`%s' not recognized as being in a supported file "
4055 : "format.",
4056 : pszFilename);
4057 : }
4058 : else
4059 : {
4060 0 : std::string osMsg("`");
4061 0 : osMsg += pszFilename;
4062 : osMsg +=
4063 : "' not recognized as being in a supported file format. "
4064 0 : "It could have been recognized by driver ";
4065 0 : osMsg += poMissingPluginDriver->GetDescription();
4066 0 : osMsg += ", but plugin ";
4067 : osMsg += poMissingPluginDriver->GetMetadataItem(
4068 0 : "MISSING_PLUGIN_FILENAME");
4069 : osMsg += " is not available in your "
4070 0 : "installation.";
4071 0 : if (const char *pszInstallationMsg =
4072 0 : poMissingPluginDriver->GetMetadataItem(
4073 0 : GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE))
4074 : {
4075 0 : osMsg += " ";
4076 0 : osMsg += pszInstallationMsg;
4077 : }
4078 :
4079 : VSIStatBuf sStat;
4080 0 : if (const char *pszGDALDriverPath =
4081 0 : CPLGetConfigOption("GDAL_DRIVER_PATH", nullptr))
4082 : {
4083 0 : if (VSIStat(pszGDALDriverPath, &sStat) != 0)
4084 : {
4085 0 : if (osMsg.back() != '.')
4086 0 : osMsg += ".";
4087 0 : osMsg += " Directory '";
4088 0 : osMsg += pszGDALDriverPath;
4089 : osMsg +=
4090 0 : "' pointed by GDAL_DRIVER_PATH does not exist.";
4091 : }
4092 : }
4093 : else
4094 : {
4095 0 : if (osMsg.back() != '.')
4096 0 : osMsg += ".";
4097 : #ifdef INSTALL_PLUGIN_FULL_DIR
4098 : if (VSIStat(INSTALL_PLUGIN_FULL_DIR, &sStat) != 0)
4099 : {
4100 : osMsg += " Directory '";
4101 : osMsg += INSTALL_PLUGIN_FULL_DIR;
4102 : osMsg += "' hardcoded in the GDAL library does not "
4103 : "exist and the GDAL_DRIVER_PATH "
4104 : "configuration option is not set.";
4105 : }
4106 : else
4107 : #endif
4108 : {
4109 : osMsg += " The GDAL_DRIVER_PATH configuration "
4110 0 : "option is not set.";
4111 : }
4112 : }
4113 :
4114 0 : CPLError(CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str());
4115 : }
4116 : }
4117 : else
4118 : {
4119 : // If Stat failed and no VSI error was set, assume it is because
4120 : // the file did not exist on the filesystem.
4121 3 : CPLError(CE_Failure, CPLE_OpenFailed,
4122 : "`%s' does not exist in the file system, "
4123 : "and is not recognized as a supported dataset name.",
4124 : pszFilename);
4125 : }
4126 : }
4127 : }
4128 :
4129 18430 : return nullptr;
4130 : }
4131 :
4132 : /************************************************************************/
4133 : /* GDALOpenShared() */
4134 : /************************************************************************/
4135 :
4136 : /**
4137 : * \brief Open a raster file as a GDALDataset.
4138 : *
4139 : * This function works the same as GDALOpen(), but allows the sharing of
4140 : * GDALDataset handles for a dataset with other callers to GDALOpenShared().
4141 : *
4142 : * In particular, GDALOpenShared() will first consult its list of currently
4143 : * open and shared GDALDataset's, and if the GetDescription() name for one
4144 : * exactly matches the pszFilename passed to GDALOpenShared() it will be
4145 : * referenced and returned.
4146 : *
4147 : * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same
4148 : * pszFilename from two different threads, a different GDALDataset object will
4149 : * be returned as it is not safe to use the same dataset from different threads,
4150 : * unless the user does explicitly use mutexes in its code.
4151 : *
4152 : * For drivers supporting the VSI virtual file API, it is possible to open a
4153 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
4154 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
4155 : * server (see VSIInstallCurlFileHandler())
4156 : *
4157 : * \sa GDALOpen()
4158 : * \sa GDALOpenEx()
4159 : *
4160 : * @param pszFilename the name of the file to access. In the case of
4161 : * exotic drivers this may not refer to a physical file, but instead contain
4162 : * information for the driver on how to access a dataset. It should be in
4163 : * UTF-8 encoding.
4164 : *
4165 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
4166 : * drivers support only read only access.
4167 : *
4168 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
4169 : * this handle can be cast to a GDALDataset *.
4170 : */
4171 :
4172 5221 : GDALDatasetH CPL_STDCALL GDALOpenShared(const char *pszFilename,
4173 : GDALAccess eAccess)
4174 : {
4175 5221 : VALIDATE_POINTER1(pszFilename, "GDALOpenShared", nullptr);
4176 5221 : return GDALOpenEx(pszFilename,
4177 : GDAL_OF_RASTER |
4178 : (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
4179 : GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR,
4180 5221 : nullptr, nullptr, nullptr);
4181 : }
4182 :
4183 : /************************************************************************/
4184 : /* GDALClose() */
4185 : /************************************************************************/
4186 :
4187 : /**
4188 : * \brief Close GDAL dataset.
4189 : *
4190 : * For non-shared datasets (opened with GDALOpen()) the dataset is closed
4191 : * using the C++ "delete" operator, recovering all dataset related resources.
4192 : * For shared datasets (opened with GDALOpenShared()) the dataset is
4193 : * dereferenced, and closed only if the referenced count has dropped below 1.
4194 : *
4195 : * @param hDS The dataset to close. May be cast from a "GDALDataset *".
4196 : * @return CE_None in case of success (return value since GDAL 3.7). On a
4197 : * shared dataset whose reference count is not dropped below 1, CE_None will
4198 : * be returned.
4199 : */
4200 :
4201 66026 : CPLErr CPL_STDCALL GDALClose(GDALDatasetH hDS)
4202 :
4203 : {
4204 66026 : if (!hDS)
4205 414 : return CE_None;
4206 :
4207 : #ifdef OGRAPISPY_ENABLED
4208 65612 : if (bOGRAPISpyEnabled)
4209 11 : OGRAPISpyPreClose(hDS);
4210 : #endif
4211 :
4212 65612 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
4213 :
4214 65612 : if (poDS->GetShared())
4215 : {
4216 : /* --------------------------------------------------------------------
4217 : */
4218 : /* If this file is in the shared dataset list then dereference */
4219 : /* it, and only delete/remote it if the reference count has */
4220 : /* dropped to zero. */
4221 : /* --------------------------------------------------------------------
4222 : */
4223 303 : if (poDS->Dereference() > 0)
4224 28 : return CE_None;
4225 :
4226 275 : CPLErr eErr = poDS->Close();
4227 275 : delete poDS;
4228 :
4229 : #ifdef OGRAPISPY_ENABLED
4230 275 : if (bOGRAPISpyEnabled)
4231 0 : OGRAPISpyPostClose();
4232 : #endif
4233 :
4234 275 : return eErr;
4235 : }
4236 :
4237 : /* -------------------------------------------------------------------- */
4238 : /* This is not shared dataset, so directly delete it. */
4239 : /* -------------------------------------------------------------------- */
4240 65309 : CPLErr eErr = poDS->Close();
4241 65308 : delete poDS;
4242 :
4243 : #ifdef OGRAPISPY_ENABLED
4244 65305 : if (bOGRAPISpyEnabled)
4245 11 : OGRAPISpyPostClose();
4246 : #endif
4247 65295 : return eErr;
4248 : }
4249 :
4250 : /************************************************************************/
4251 : /* GDALDumpOpenDataset() */
4252 : /************************************************************************/
4253 :
4254 0 : static int GDALDumpOpenSharedDatasetsForeach(void *elt, void *user_data)
4255 : {
4256 0 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
4257 0 : FILE *fp = static_cast<FILE *>(user_data);
4258 0 : GDALDataset *poDS = psStruct->poDS;
4259 :
4260 0 : const char *pszDriverName = poDS->GetDriver() == nullptr
4261 0 : ? "DriverIsNULL"
4262 0 : : poDS->GetDriver()->GetDescription();
4263 :
4264 0 : poDS->Reference();
4265 0 : CPL_IGNORE_RET_VAL(
4266 0 : VSIFPrintf(fp, " %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4267 0 : poDS->GetShared() ? 'S' : 'N', pszDriverName,
4268 0 : static_cast<int>(psStruct->nPID), poDS->GetRasterXSize(),
4269 : poDS->GetRasterYSize(), poDS->GetRasterCount(),
4270 0 : poDS->GetDescription()));
4271 :
4272 0 : return TRUE;
4273 : }
4274 :
4275 0 : static int GDALDumpOpenDatasetsForeach(GDALDataset *poDS, FILE *fp)
4276 : {
4277 :
4278 : // Don't list shared datasets. They have already been listed by
4279 : // GDALDumpOpenSharedDatasetsForeach.
4280 0 : if (poDS->GetShared())
4281 0 : return TRUE;
4282 :
4283 0 : const char *pszDriverName = poDS->GetDriver() == nullptr
4284 0 : ? "DriverIsNULL"
4285 0 : : poDS->GetDriver()->GetDescription();
4286 :
4287 0 : poDS->Reference();
4288 0 : CPL_IGNORE_RET_VAL(
4289 0 : VSIFPrintf(fp, " %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4290 0 : poDS->GetShared() ? 'S' : 'N', pszDriverName, -1,
4291 : poDS->GetRasterXSize(), poDS->GetRasterYSize(),
4292 0 : poDS->GetRasterCount(), poDS->GetDescription()));
4293 :
4294 0 : return TRUE;
4295 : }
4296 :
4297 : /**
4298 : * \brief List open datasets.
4299 : *
4300 : * Dumps a list of all open datasets (shared or not) to the indicated
4301 : * text file (may be stdout or stderr). This function is primarily intended
4302 : * to assist in debugging "dataset leaks" and reference counting issues.
4303 : * The information reported includes the dataset name, referenced count,
4304 : * shared status, driver name, size, and band count.
4305 : */
4306 :
4307 277 : int CPL_STDCALL GDALDumpOpenDatasets(FILE *fp)
4308 :
4309 : {
4310 277 : VALIDATE_POINTER1(fp, "GDALDumpOpenDatasets", 0);
4311 :
4312 554 : CPLMutexHolderD(&hDLMutex);
4313 :
4314 277 : if (poAllDatasetMap == nullptr)
4315 277 : return 0;
4316 :
4317 0 : CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "Open GDAL Datasets:\n"));
4318 :
4319 0 : for (const auto &oIter : *poAllDatasetMap)
4320 : {
4321 0 : GDALDumpOpenDatasetsForeach(oIter.first, fp);
4322 : }
4323 :
4324 0 : if (phSharedDatasetSet != nullptr)
4325 : {
4326 0 : CPLHashSetForeach(phSharedDatasetSet, GDALDumpOpenSharedDatasetsForeach,
4327 : fp);
4328 : }
4329 0 : return static_cast<int>(poAllDatasetMap->size());
4330 : }
4331 :
4332 : /************************************************************************/
4333 : /* BeginAsyncReader() */
4334 : /************************************************************************/
4335 :
4336 : /**
4337 : * \brief Sets up an asynchronous data request
4338 : *
4339 : * This method establish an asynchronous raster read request for the
4340 : * indicated window on the dataset into the indicated buffer. The parameters
4341 : * for windowing, buffer size, buffer type and buffer organization are similar
4342 : * to those for GDALDataset::RasterIO(); however, this call only launches
4343 : * the request and filling the buffer is accomplished via calls to
4344 : * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4345 : *
4346 : * Once all processing for the created session is complete, or if no further
4347 : * refinement of the request is required, the GDALAsyncReader object should
4348 : * be destroyed with the GDALDataset::EndAsyncReader() method.
4349 : *
4350 : * Note that the data buffer (pData) will potentially continue to be
4351 : * updated as long as the session lives, but it is not deallocated when
4352 : * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
4353 : * should be deallocated by the application at that point.
4354 : *
4355 : * Additional information on asynchronous IO in GDAL may be found at:
4356 : * https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4357 : *
4358 : * This method is the same as the C GDALBeginAsyncReader() function.
4359 : *
4360 : * @param nXOff The pixel offset to the top left corner of the region
4361 : * of the band to be accessed. This would be zero to start from the left side.
4362 : *
4363 : * @param nYOff The line offset to the top left corner of the region
4364 : * of the band to be accessed. This would be zero to start from the top.
4365 : *
4366 : * @param nXSize The width of the region of the band to be accessed in pixels.
4367 : *
4368 : * @param nYSize The height of the region of the band to be accessed in lines.
4369 : *
4370 : * @param pBuf The buffer into which the data should be read. This buffer must
4371 : * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4372 : * It is organized in left to right,top to bottom pixel order. Spacing is
4373 : * controlled by the nPixelSpace, and nLineSpace parameters.
4374 : *
4375 : * @param nBufXSize the width of the buffer image into which the desired region
4376 : * is to be read, or from which it is to be written.
4377 : *
4378 : * @param nBufYSize the height of the buffer image into which the desired
4379 : * region is to be read, or from which it is to be written.
4380 : *
4381 : * @param eBufType the type of the pixel values in the pData data buffer. The
4382 : * pixel values will automatically be translated to/from the GDALRasterBand
4383 : * data type as needed.
4384 : *
4385 : * @param nBandCount the number of bands being read or written.
4386 : *
4387 : * @param panBandMap the list of nBandCount band numbers being read/written.
4388 : * Note band numbers are 1 based. This may be NULL to select the first
4389 : * nBandCount bands.
4390 : *
4391 : * @param nPixelSpace The byte offset from the start of one pixel value in
4392 : * pData to the start of the next pixel value within a scanline. If defaulted
4393 : * (0) the size of the datatype eBufType is used.
4394 : *
4395 : * @param nLineSpace The byte offset from the start of one scanline in
4396 : * pData to the start of the next. If defaulted the size of the datatype
4397 : * eBufType * nBufXSize is used.
4398 : *
4399 : * @param nBandSpace the byte offset from the start of one bands data to the
4400 : * start of the next. If defaulted (zero) the value will be
4401 : * nLineSpace * nBufYSize implying band sequential organization
4402 : * of the data buffer.
4403 : *
4404 : * @param papszOptions Driver specific control options in a string list or NULL.
4405 : * Consult driver documentation for options supported.
4406 : *
4407 : * @return The GDALAsyncReader object representing the request.
4408 : */
4409 :
4410 1 : GDALAsyncReader *GDALDataset::BeginAsyncReader(
4411 : int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf, int nBufXSize,
4412 : int nBufYSize, GDALDataType eBufType, int nBandCount, int *panBandMap,
4413 : int nPixelSpace, int nLineSpace, int nBandSpace, char **papszOptions)
4414 : {
4415 : // See gdaldefaultasync.cpp
4416 :
4417 1 : return GDALGetDefaultAsyncReader(this, nXOff, nYOff, nXSize, nYSize, pBuf,
4418 : nBufXSize, nBufYSize, eBufType, nBandCount,
4419 : panBandMap, nPixelSpace, nLineSpace,
4420 1 : nBandSpace, papszOptions);
4421 : }
4422 :
4423 : /************************************************************************/
4424 : /* GDALBeginAsyncReader() */
4425 : /************************************************************************/
4426 :
4427 : /**
4428 : * \brief Sets up an asynchronous data request
4429 : *
4430 : * This method establish an asynchronous raster read request for the
4431 : * indicated window on the dataset into the indicated buffer. The parameters
4432 : * for windowing, buffer size, buffer type and buffer organization are similar
4433 : * to those for GDALDataset::RasterIO(); however, this call only launches
4434 : * the request and filling the buffer is accomplished via calls to
4435 : * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4436 : *
4437 : * Once all processing for the created session is complete, or if no further
4438 : * refinement of the request is required, the GDALAsyncReader object should
4439 : * be destroyed with the GDALDataset::EndAsyncReader() method.
4440 : *
4441 : * Note that the data buffer (pData) will potentially continue to be
4442 : * updated as long as the session lives, but it is not deallocated when
4443 : * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
4444 : * should be deallocated by the application at that point.
4445 : *
4446 : * Additional information on asynchronous IO in GDAL may be found at:
4447 : * https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4448 : *
4449 : * This method is the same as the C++ GDALDataset::BeginAsyncReader() method.
4450 : *
4451 : * @param hDS handle to the dataset object.
4452 : *
4453 : * @param nXOff The pixel offset to the top left corner of the region
4454 : * of the band to be accessed. This would be zero to start from the left side.
4455 : *
4456 : * @param nYOff The line offset to the top left corner of the region
4457 : * of the band to be accessed. This would be zero to start from the top.
4458 : *
4459 : * @param nXSize The width of the region of the band to be accessed in pixels.
4460 : *
4461 : * @param nYSize The height of the region of the band to be accessed in lines.
4462 : *
4463 : * @param pBuf The buffer into which the data should be read. This buffer must
4464 : * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4465 : * It is organized in left to right,top to bottom pixel order. Spacing is
4466 : * controlled by the nPixelSpace, and nLineSpace parameters.
4467 : *
4468 : * @param nBufXSize the width of the buffer image into which the desired region
4469 : * is to be read, or from which it is to be written.
4470 : *
4471 : * @param nBufYSize the height of the buffer image into which the desired
4472 : * region is to be read, or from which it is to be written.
4473 : *
4474 : * @param eBufType the type of the pixel values in the pData data buffer. The
4475 : * pixel values will automatically be translated to/from the GDALRasterBand
4476 : * data type as needed.
4477 : *
4478 : * @param nBandCount the number of bands being read or written.
4479 : *
4480 : * @param panBandMap the list of nBandCount band numbers being read/written.
4481 : * Note band numbers are 1 based. This may be NULL to select the first
4482 : * nBandCount bands.
4483 : *
4484 : * @param nPixelSpace The byte offset from the start of one pixel value in
4485 : * pData to the start of the next pixel value within a scanline. If defaulted
4486 : * (0) the size of the datatype eBufType is used.
4487 : *
4488 : * @param nLineSpace The byte offset from the start of one scanline in
4489 : * pData to the start of the next. If defaulted the size of the datatype
4490 : * eBufType * nBufXSize is used.
4491 : *
4492 : * @param nBandSpace the byte offset from the start of one bands data to the
4493 : * start of the next. If defaulted (zero) the value will be
4494 : * nLineSpace * nBufYSize implying band sequential organization
4495 : * of the data buffer.
4496 : *
4497 : * @param papszOptions Driver specific control options in a string list or NULL.
4498 : * Consult driver documentation for options supported.
4499 : *
4500 : * @return handle representing the request.
4501 : */
4502 :
4503 2 : GDALAsyncReaderH CPL_STDCALL GDALBeginAsyncReader(
4504 : GDALDatasetH hDS, int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf,
4505 : int nBufXSize, int nBufYSize, GDALDataType eBufType, int nBandCount,
4506 : int *panBandMap, int nPixelSpace, int nLineSpace, int nBandSpace,
4507 : CSLConstList papszOptions)
4508 :
4509 : {
4510 2 : VALIDATE_POINTER1(hDS, "GDALDataset", nullptr);
4511 : return static_cast<GDALAsyncReaderH>(
4512 2 : GDALDataset::FromHandle(hDS)->BeginAsyncReader(
4513 : nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize, nBufYSize, eBufType,
4514 : nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
4515 2 : const_cast<char **>(papszOptions)));
4516 : }
4517 :
4518 : /************************************************************************/
4519 : /* EndAsyncReader() */
4520 : /************************************************************************/
4521 :
4522 : /**
4523 : * End asynchronous request.
4524 : *
4525 : * This method destroys an asynchronous io request and recovers all
4526 : * resources associated with it.
4527 : *
4528 : * This method is the same as the C function GDALEndAsyncReader().
4529 : *
4530 : * @param poARIO pointer to a GDALAsyncReader
4531 : */
4532 :
4533 1 : void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO)
4534 : {
4535 1 : delete poARIO;
4536 1 : }
4537 :
4538 : /************************************************************************/
4539 : /* GDALEndAsyncReader() */
4540 : /************************************************************************/
4541 :
4542 : /**
4543 : * End asynchronous request.
4544 : *
4545 : * This method destroys an asynchronous io request and recovers all
4546 : * resources associated with it.
4547 : *
4548 : * This method is the same as the C++ method GDALDataset::EndAsyncReader().
4549 : *
4550 : * @param hDS handle to the dataset object.
4551 : * @param hAsyncReaderH handle returned by GDALBeginAsyncReader()
4552 : */
4553 :
4554 1 : void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS,
4555 : GDALAsyncReaderH hAsyncReaderH)
4556 : {
4557 1 : VALIDATE_POINTER0(hDS, "GDALDataset");
4558 1 : VALIDATE_POINTER0(hAsyncReaderH, "GDALAsyncReader");
4559 1 : GDALDataset::FromHandle(hDS)->EndAsyncReader(
4560 1 : static_cast<GDALAsyncReader *>(hAsyncReaderH));
4561 : }
4562 :
4563 : /************************************************************************/
4564 : /* CloseDependentDatasets() */
4565 : /************************************************************************/
4566 :
4567 : /**
4568 : * Drop references to any other datasets referenced by this dataset.
4569 : *
4570 : * This method should release any reference to other datasets (e.g. a VRT
4571 : * dataset to its sources), but not close the current dataset itself.
4572 : *
4573 : * If at least, one reference to a dependent dataset has been dropped,
4574 : * this method should return TRUE. Otherwise it *should* return FALSE.
4575 : * (Failure to return the proper value might result in infinite loop)
4576 : *
4577 : * This method can be called several times on a given dataset. After
4578 : * the first time, it should not do anything and return FALSE.
4579 : *
4580 : * The driver implementation may choose to destroy its raster bands,
4581 : * so be careful not to call any method on the raster bands afterwards.
4582 : *
4583 : * Basically the only safe action you can do after calling
4584 : * CloseDependentDatasets() is to call the destructor.
4585 : *
4586 : * Note: the only legitimate caller of CloseDependentDatasets() is
4587 : * GDALDriverManager::~GDALDriverManager()
4588 : *
4589 : * @return TRUE if at least one reference to another dataset has been dropped.
4590 : */
4591 18489 : int GDALDataset::CloseDependentDatasets()
4592 : {
4593 18489 : return oOvManager.CloseDependentDatasets();
4594 : }
4595 :
4596 : /************************************************************************/
4597 : /* ReportError() */
4598 : /************************************************************************/
4599 :
4600 : #ifndef DOXYGEN_XML
4601 : /**
4602 : * \brief Emits an error related to a dataset.
4603 : *
4604 : * This function is a wrapper for regular CPLError(). The only difference
4605 : * with CPLError() is that it prepends the error message with the dataset
4606 : * name.
4607 : *
4608 : * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4609 : * @param err_no the error number (CPLE_*) from cpl_error.h.
4610 : * @param fmt a printf() style format string. Any additional arguments
4611 : * will be treated as arguments to fill in this format in a manner
4612 : * similar to printf().
4613 : *
4614 : * @since GDAL 1.9.0
4615 : */
4616 :
4617 86 : void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
4618 : const char *fmt, ...) const
4619 : {
4620 : va_list args;
4621 86 : va_start(args, fmt);
4622 86 : ReportErrorV(GetDescription(), eErrClass, err_no, fmt, args);
4623 86 : va_end(args);
4624 86 : }
4625 :
4626 : /**
4627 : * \brief Emits an error related to a dataset (static method)
4628 : *
4629 : * This function is a wrapper for regular CPLError(). The only difference
4630 : * with CPLError() is that it prepends the error message with the dataset
4631 : * name.
4632 : *
4633 : * @param pszDSName dataset name.
4634 : * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4635 : * @param err_no the error number (CPLE_*) from cpl_error.h.
4636 : * @param fmt a printf() style format string. Any additional arguments
4637 : * will be treated as arguments to fill in this format in a manner
4638 : * similar to printf().
4639 : *
4640 : * @since GDAL 3.2.0
4641 : */
4642 :
4643 103 : void GDALDataset::ReportError(const char *pszDSName, CPLErr eErrClass,
4644 : CPLErrorNum err_no, const char *fmt, ...)
4645 : {
4646 : va_list args;
4647 103 : va_start(args, fmt);
4648 103 : ReportErrorV(pszDSName, eErrClass, err_no, fmt, args);
4649 103 : va_end(args);
4650 103 : }
4651 :
4652 189 : void GDALDataset::ReportErrorV(const char *pszDSName, CPLErr eErrClass,
4653 : CPLErrorNum err_no, const char *fmt,
4654 : va_list args)
4655 : {
4656 189 : pszDSName = CPLGetFilename(pszDSName);
4657 189 : if (pszDSName[0] != '\0')
4658 : {
4659 177 : CPLError(eErrClass, err_no, "%s",
4660 354 : std::string(pszDSName)
4661 177 : .append(": ")
4662 354 : .append(CPLString().vPrintf(fmt, args))
4663 : .c_str());
4664 : }
4665 : else
4666 : {
4667 12 : CPLErrorV(eErrClass, err_no, fmt, args);
4668 : }
4669 189 : }
4670 : #endif
4671 :
4672 : /************************************************************************/
4673 : /* GetMetadata() */
4674 : /************************************************************************/
4675 64983 : char **GDALDataset::GetMetadata(const char *pszDomain)
4676 : {
4677 : #ifndef WITHOUT_DERIVED
4678 64983 : if (pszDomain != nullptr && EQUAL(pszDomain, "DERIVED_SUBDATASETS"))
4679 : {
4680 8 : oDerivedMetadataList.Clear();
4681 :
4682 : // First condition: at least one raster band.
4683 8 : if (GetRasterCount() > 0)
4684 : {
4685 : // Check if there is at least one complex band.
4686 8 : bool hasAComplexBand = false;
4687 :
4688 14 : for (int rasterId = 1; rasterId <= GetRasterCount(); ++rasterId)
4689 : {
4690 8 : if (GDALDataTypeIsComplex(
4691 8 : GetRasterBand(rasterId)->GetRasterDataType()))
4692 : {
4693 2 : hasAComplexBand = true;
4694 2 : break;
4695 : }
4696 : }
4697 :
4698 8 : unsigned int nbSupportedDerivedDS = 0;
4699 : const DerivedDatasetDescription *poDDSDesc =
4700 8 : GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
4701 :
4702 8 : int nNumDataset = 1;
4703 64 : for (unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
4704 : ++derivedId)
4705 : {
4706 98 : if (hasAComplexBand ||
4707 98 : CPLString(poDDSDesc[derivedId].pszInputPixelType) !=
4708 : "complex")
4709 : {
4710 : oDerivedMetadataList.SetNameValue(
4711 : CPLSPrintf("DERIVED_SUBDATASET_%d_NAME", nNumDataset),
4712 : CPLSPrintf("DERIVED_SUBDATASET:%s:%s",
4713 20 : poDDSDesc[derivedId].pszDatasetName,
4714 20 : GetDescription()));
4715 :
4716 : CPLString osDesc(
4717 : CPLSPrintf("%s from %s",
4718 20 : poDDSDesc[derivedId].pszDatasetDescription,
4719 20 : GetDescription()));
4720 : oDerivedMetadataList.SetNameValue(
4721 : CPLSPrintf("DERIVED_SUBDATASET_%d_DESC", nNumDataset),
4722 20 : osDesc.c_str());
4723 :
4724 20 : nNumDataset++;
4725 : }
4726 : }
4727 : }
4728 8 : return oDerivedMetadataList.List();
4729 : }
4730 : #endif
4731 :
4732 64975 : return GDALMajorObject::GetMetadata(pszDomain);
4733 : }
4734 :
4735 : // clang-format off
4736 :
4737 : /**
4738 : * \fn GDALDataset::SetMetadata( char ** papszMetadata, const char * pszDomain)
4739 : * \brief Set metadata.
4740 : *
4741 : * CAUTION: depending on the format, older values of the updated information
4742 : * might still be found in the file in a "ghost" state, even if no longer
4743 : * accessible through the GDAL API. This is for example the case of the GTiff
4744 : * format (this is not a exhaustive list)
4745 : *
4746 : * The C function GDALSetMetadata() does the same thing as this method.
4747 : *
4748 : * @param papszMetadata the metadata in name=value string list format to
4749 : * apply.
4750 : * @param pszDomain the domain of interest. Use "" or NULL for the default
4751 : * domain.
4752 : * @return CE_None on success, CE_Failure on failure and CE_Warning if the
4753 : * metadata has been accepted, but is likely not maintained persistently
4754 : * by the underlying object between sessions.
4755 : */
4756 :
4757 : /**
4758 : * \fn GDALDataset::SetMetadataItem( const char * pszName, const char * pszValue, const char * pszDomain)
4759 : * \brief Set single metadata item.
4760 : *
4761 : * CAUTION: depending on the format, older values of the updated information
4762 : * might still be found in the file in a "ghost" state, even if no longer
4763 : * accessible through the GDAL API. This is for example the case of the GTiff
4764 : * format (this is not a exhaustive list)
4765 : *
4766 : * The C function GDALSetMetadataItem() does the same thing as this method.
4767 : *
4768 : * @param pszName the key for the metadata item to fetch.
4769 : * @param pszValue the value to assign to the key.
4770 : * @param pszDomain the domain to set within, use NULL for the default domain.
4771 : *
4772 : * @return CE_None on success, or an error code on failure.
4773 : */
4774 :
4775 : // clang-format on
4776 :
4777 : /************************************************************************/
4778 : /* GetMetadataDomainList() */
4779 : /************************************************************************/
4780 :
4781 786 : char **GDALDataset::GetMetadataDomainList()
4782 : {
4783 786 : char **currentDomainList = CSLDuplicate(oMDMD.GetDomainList());
4784 :
4785 : // Ensure that we do not duplicate DERIVED domain.
4786 923 : if (GetRasterCount() > 0 &&
4787 137 : CSLFindString(currentDomainList, "DERIVED_SUBDATASETS") == -1)
4788 : {
4789 : currentDomainList =
4790 137 : CSLAddString(currentDomainList, "DERIVED_SUBDATASETS");
4791 : }
4792 786 : return currentDomainList;
4793 : }
4794 :
4795 : /************************************************************************/
4796 : /* GetDriverName() */
4797 : /************************************************************************/
4798 :
4799 : /** Return driver name.
4800 : * @return driver name.
4801 : */
4802 2149 : const char *GDALDataset::GetDriverName()
4803 : {
4804 2149 : if (poDriver)
4805 2137 : return poDriver->GetDescription();
4806 12 : return "";
4807 : }
4808 :
4809 : /************************************************************************/
4810 : /* GDALDatasetReleaseResultSet() */
4811 : /************************************************************************/
4812 :
4813 : /**
4814 : \brief Release results of ExecuteSQL().
4815 :
4816 : This function should only be used to deallocate OGRLayers resulting from
4817 : an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
4818 : results set before destroying the GDALDataset may cause errors.
4819 :
4820 : This function is the same as the C++ method GDALDataset::ReleaseResultSet()
4821 :
4822 : @since GDAL 2.0
4823 :
4824 : @param hDS the dataset handle.
4825 : @param hLayer the result of a previous ExecuteSQL() call.
4826 :
4827 : */
4828 3568 : void GDALDatasetReleaseResultSet(GDALDatasetH hDS, OGRLayerH hLayer)
4829 :
4830 : {
4831 3568 : VALIDATE_POINTER0(hDS, "GDALDatasetReleaseResultSet");
4832 :
4833 : #ifdef OGRAPISPY_ENABLED
4834 3568 : if (bOGRAPISpyEnabled)
4835 6 : OGRAPISpy_DS_ReleaseResultSet(hDS, hLayer);
4836 : #endif
4837 :
4838 7136 : GDALDataset::FromHandle(hDS)->ReleaseResultSet(
4839 3568 : OGRLayer::FromHandle(hLayer));
4840 : }
4841 :
4842 : /************************************************************************/
4843 : /* GDALDatasetGetLayerCount() */
4844 : /************************************************************************/
4845 :
4846 : /**
4847 : \brief Get the number of layers in this dataset.
4848 :
4849 : This function is the same as the C++ method GDALDataset::GetLayerCount()
4850 :
4851 : @since GDAL 2.0
4852 :
4853 : @param hDS the dataset handle.
4854 : @return layer count.
4855 : */
4856 :
4857 1396 : int GDALDatasetGetLayerCount(GDALDatasetH hDS)
4858 :
4859 : {
4860 1396 : VALIDATE_POINTER1(hDS, "GDALDatasetH", 0);
4861 :
4862 : #ifdef OGRAPISPY_ENABLED
4863 1396 : if (bOGRAPISpyEnabled)
4864 2 : OGRAPISpy_DS_GetLayerCount(reinterpret_cast<GDALDatasetH>(hDS));
4865 : #endif
4866 :
4867 1396 : return GDALDataset::FromHandle(hDS)->GetLayerCount();
4868 : }
4869 :
4870 : /************************************************************************/
4871 : /* GDALDatasetGetLayer() */
4872 : /************************************************************************/
4873 :
4874 : /**
4875 : \brief Fetch a layer by index.
4876 :
4877 : The returned layer remains owned by the
4878 : GDALDataset and should not be deleted by the application.
4879 :
4880 : This function is the same as the C++ method GDALDataset::GetLayer()
4881 :
4882 : @since GDAL 2.0
4883 :
4884 : @param hDS the dataset handle.
4885 : @param iLayer a layer number between 0 and GetLayerCount()-1.
4886 :
4887 : @return the layer, or NULL if iLayer is out of range or an error occurs.
4888 : */
4889 :
4890 8994 : OGRLayerH GDALDatasetGetLayer(GDALDatasetH hDS, int iLayer)
4891 :
4892 : {
4893 8994 : VALIDATE_POINTER1(hDS, "GDALDatasetGetLayer", nullptr);
4894 :
4895 : OGRLayerH hLayer =
4896 8994 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->GetLayer(iLayer));
4897 :
4898 : #ifdef OGRAPISPY_ENABLED
4899 8994 : if (bOGRAPISpyEnabled)
4900 3 : OGRAPISpy_DS_GetLayer(hDS, iLayer, hLayer);
4901 : #endif
4902 :
4903 8994 : return hLayer;
4904 : }
4905 :
4906 : /************************************************************************/
4907 : /* GDALDatasetGetLayerByName() */
4908 : /************************************************************************/
4909 :
4910 : /**
4911 : \brief Fetch a layer by name.
4912 :
4913 : The returned layer remains owned by the
4914 : GDALDataset and should not be deleted by the application.
4915 :
4916 : This function is the same as the C++ method GDALDataset::GetLayerByName()
4917 :
4918 : @since GDAL 2.0
4919 :
4920 : @param hDS the dataset handle.
4921 : @param pszName the layer name of the layer to fetch.
4922 :
4923 : @return the layer, or NULL if Layer is not found or an error occurs.
4924 : */
4925 :
4926 3498 : OGRLayerH GDALDatasetGetLayerByName(GDALDatasetH hDS, const char *pszName)
4927 :
4928 : {
4929 3498 : VALIDATE_POINTER1(hDS, "GDALDatasetGetLayerByName", nullptr);
4930 :
4931 3498 : OGRLayerH hLayer = OGRLayer::ToHandle(
4932 3498 : GDALDataset::FromHandle(hDS)->GetLayerByName(pszName));
4933 :
4934 : #ifdef OGRAPISPY_ENABLED
4935 3498 : if (bOGRAPISpyEnabled)
4936 4 : OGRAPISpy_DS_GetLayerByName(hDS, pszName, hLayer);
4937 : #endif
4938 :
4939 3498 : return hLayer;
4940 : }
4941 :
4942 : /************************************************************************/
4943 : /* GDALDatasetIsLayerPrivate() */
4944 : /************************************************************************/
4945 :
4946 : /**
4947 : \brief Returns true if the layer at the specified index is deemed a private or
4948 : system table, or an internal detail only.
4949 :
4950 : This function is the same as the C++ method GDALDataset::IsLayerPrivate()
4951 :
4952 : @since GDAL 3.4
4953 :
4954 : @param hDS the dataset handle.
4955 : @param iLayer a layer number between 0 and GetLayerCount()-1.
4956 :
4957 : @return true if the layer is a private or system table.
4958 : */
4959 :
4960 91 : int GDALDatasetIsLayerPrivate(GDALDatasetH hDS, int iLayer)
4961 :
4962 : {
4963 91 : VALIDATE_POINTER1(hDS, "GDALDatasetIsLayerPrivate", false);
4964 :
4965 91 : const bool res = GDALDataset::FromHandle(hDS)->IsLayerPrivate(iLayer);
4966 :
4967 91 : return res ? 1 : 0;
4968 : }
4969 :
4970 : /************************************************************************/
4971 : /* GDALDatasetDeleteLayer() */
4972 : /************************************************************************/
4973 :
4974 : /**
4975 : \brief Delete the indicated layer from the datasource.
4976 :
4977 : If this function is supported
4978 : the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
4979 :
4980 : This method is the same as the C++ method GDALDataset::DeleteLayer().
4981 :
4982 : @since GDAL 2.0
4983 :
4984 : @param hDS the dataset handle.
4985 : @param iLayer the index of the layer to delete.
4986 :
4987 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
4988 : layers is not supported for this datasource.
4989 :
4990 : */
4991 42 : OGRErr GDALDatasetDeleteLayer(GDALDatasetH hDS, int iLayer)
4992 :
4993 : {
4994 42 : VALIDATE_POINTER1(hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE);
4995 :
4996 : #ifdef OGRAPISPY_ENABLED
4997 42 : if (bOGRAPISpyEnabled)
4998 2 : OGRAPISpy_DS_DeleteLayer(hDS, iLayer);
4999 : #endif
5000 :
5001 42 : return GDALDataset::FromHandle(hDS)->DeleteLayer(iLayer);
5002 : }
5003 :
5004 : /************************************************************************/
5005 : /* CreateLayer() */
5006 : /************************************************************************/
5007 :
5008 : /**
5009 : \brief This method attempts to create a new layer on the dataset with the
5010 : indicated name, coordinate system, geometry type.
5011 :
5012 : The papszOptions argument
5013 : can be used to control driver specific creation options. These options are
5014 : normally documented in the format specific documentation.
5015 : That function will try to validate the creation option list passed to the
5016 : driver with the GDALValidateCreationOptions() method. This check can be
5017 : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5018 : to NO.
5019 :
5020 : Drivers should extend the ICreateLayer() method and not
5021 : CreateLayer(). CreateLayer() adds validation of layer creation options, before
5022 : delegating the actual work to ICreateLayer().
5023 :
5024 : This method is the same as the C function GDALDatasetCreateLayer() and the
5025 : deprecated OGR_DS_CreateLayer().
5026 :
5027 : Example:
5028 :
5029 : \code{.cpp}
5030 : #include "gdal.h"
5031 : #include "cpl_string.h"
5032 :
5033 : ...
5034 :
5035 : OGRLayer *poLayer;
5036 : char **papszOptions;
5037 :
5038 : if( !poDS->TestCapability( ODsCCreateLayer ) )
5039 : {
5040 : ...
5041 : }
5042 :
5043 : papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5044 : poLayer = poDS->CreateLayer( "NewLayer", nullptr, wkbUnknown,
5045 : papszOptions );
5046 : CSLDestroy( papszOptions );
5047 :
5048 : if( poLayer == NULL )
5049 : {
5050 : ...
5051 : }
5052 : \endcode
5053 :
5054 : @param pszName the name for the new layer. This should ideally not
5055 : match any existing layer on the datasource.
5056 : @param poSpatialRef the coordinate system to use for the new layer, or NULL if
5057 : no coordinate system is available.
5058 : @param eGType the geometry type for the layer. Use wkbUnknown if there
5059 : are no constraints on the types geometry to be written.
5060 : @param papszOptions a StringList of name=value options. Options are driver
5061 : specific.
5062 :
5063 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5064 :
5065 : */
5066 :
5067 7365 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5068 : const OGRSpatialReference *poSpatialRef,
5069 : OGRwkbGeometryType eGType,
5070 : CSLConstList papszOptions)
5071 :
5072 : {
5073 7365 : if (eGType == wkbNone)
5074 : {
5075 446 : return CreateLayer(pszName, nullptr, papszOptions);
5076 : }
5077 : else
5078 : {
5079 13838 : OGRGeomFieldDefn oGeomFieldDefn("", eGType);
5080 6919 : oGeomFieldDefn.SetSpatialRef(poSpatialRef);
5081 6919 : return CreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5082 : }
5083 : }
5084 :
5085 : /**
5086 : \brief This method attempts to create a new layer on the dataset with the
5087 : indicated name and geometry field definition.
5088 :
5089 : When poGeomFieldDefn is not null, most drivers should honor
5090 : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5091 : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5092 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5093 : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5094 : very few currently.
5095 :
5096 : Note that even if a geometry coordinate precision is set and a driver honors the
5097 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5098 : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5099 : with the coordinate precision. That is they are assumed to be valid once their
5100 : coordinates are rounded to it. If it might not be the case, the user may set
5101 : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5102 : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5103 : the passed geometries.
5104 :
5105 : The papszOptions argument
5106 : can be used to control driver specific creation options. These options are
5107 : normally documented in the format specific documentation.
5108 : This function will try to validate the creation option list passed to the
5109 : driver with the GDALValidateCreationOptions() method. This check can be
5110 : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5111 : to NO.
5112 :
5113 : Drivers should extend the ICreateLayer() method and not
5114 : CreateLayer(). CreateLayer() adds validation of layer creation options, before
5115 : delegating the actual work to ICreateLayer().
5116 :
5117 : This method is the same as the C function GDALDatasetCreateLayerFromGeomFieldDefn().
5118 :
5119 : @param pszName the name for the new layer. This should ideally not
5120 : match any existing layer on the datasource.
5121 : @param poGeomFieldDefn the geometry field definition to use for the new layer,
5122 : or NULL if there is no geometry field.
5123 : @param papszOptions a StringList of name=value options. Options are driver
5124 : specific.
5125 :
5126 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5127 : @since 3.9
5128 :
5129 : */
5130 :
5131 8543 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5132 : const OGRGeomFieldDefn *poGeomFieldDefn,
5133 : CSLConstList papszOptions)
5134 :
5135 : {
5136 8543 : if (CPLTestBool(
5137 : CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
5138 : {
5139 8543 : ValidateLayerCreationOptions(papszOptions);
5140 : }
5141 :
5142 : OGRLayer *poLayer;
5143 8543 : if (poGeomFieldDefn)
5144 : {
5145 7869 : OGRGeomFieldDefn oGeomFieldDefn(poGeomFieldDefn);
5146 7963 : if (OGR_GT_IsNonLinear(poGeomFieldDefn->GetType()) &&
5147 94 : !TestCapability(ODsCCurveGeometries))
5148 : {
5149 23 : oGeomFieldDefn.SetType(
5150 : OGR_GT_GetLinear(poGeomFieldDefn->GetType()));
5151 : }
5152 :
5153 7869 : poLayer = ICreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5154 : }
5155 : else
5156 : {
5157 674 : poLayer = ICreateLayer(pszName, nullptr, papszOptions);
5158 : }
5159 : #ifdef DEBUG
5160 8614 : if (poLayer != nullptr && OGR_GT_IsNonLinear(poLayer->GetGeomType()) &&
5161 71 : !poLayer->TestCapability(OLCCurveGeometries))
5162 : {
5163 0 : CPLError(CE_Warning, CPLE_AppDefined,
5164 : "Inconsistent driver: Layer geometry type is non-linear, but "
5165 : "TestCapability(OLCCurveGeometries) returns FALSE.");
5166 : }
5167 : #endif
5168 :
5169 8543 : return poLayer;
5170 : }
5171 :
5172 : //! @cond Doxygen_Suppress
5173 :
5174 : // Technical override to avoid ambiguous choice between the old and new
5175 : // new CreateLayer() signatures.
5176 7 : OGRLayer *GDALDataset::CreateLayer(const char *pszName)
5177 : {
5178 14 : OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5179 14 : return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5180 : }
5181 :
5182 : // Technical override to avoid ambiguous choice between the old and new
5183 : // new CreateLayer() signatures.
5184 1 : OGRLayer *GDALDataset::CreateLayer(const char *pszName, std::nullptr_t)
5185 : {
5186 2 : OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5187 2 : return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5188 : }
5189 :
5190 : //!@endcond
5191 :
5192 : /************************************************************************/
5193 : /* GDALDatasetCreateLayer() */
5194 : /************************************************************************/
5195 :
5196 : /**
5197 : \brief This function attempts to create a new layer on the dataset with the
5198 : indicated name, coordinate system, geometry type.
5199 :
5200 : The papszOptions argument can be used to control driver specific creation
5201 : options. These options are normally documented in the format specific
5202 : documentation.
5203 :
5204 : This method is the same as the C++ method GDALDataset::CreateLayer().
5205 :
5206 : Example:
5207 :
5208 : \code{.c}
5209 : #include "gdal.h"
5210 : #include "cpl_string.h"
5211 :
5212 : ...
5213 :
5214 : OGRLayerH hLayer;
5215 : char **papszOptions;
5216 :
5217 : if( !GDALDatasetTestCapability( hDS, ODsCCreateLayer ) )
5218 : {
5219 : ...
5220 : }
5221 :
5222 : papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5223 : hLayer = GDALDatasetCreateLayer( hDS, "NewLayer", NULL, wkbUnknown,
5224 : papszOptions );
5225 : CSLDestroy( papszOptions );
5226 :
5227 : if( hLayer == NULL )
5228 : {
5229 : ...
5230 : }
5231 : \endcode
5232 :
5233 : @since GDAL 2.0
5234 :
5235 : @param hDS the dataset handle
5236 : @param pszName the name for the new layer. This should ideally not
5237 : match any existing layer on the datasource.
5238 : @param hSpatialRef the coordinate system to use for the new layer, or NULL if
5239 : no coordinate system is available.
5240 : @param eGType the geometry type for the layer. Use wkbUnknown if there
5241 : are no constraints on the types geometry to be written.
5242 : @param papszOptions a StringList of name=value options. Options are driver
5243 : specific.
5244 :
5245 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5246 :
5247 : */
5248 :
5249 5565 : OGRLayerH GDALDatasetCreateLayer(GDALDatasetH hDS, const char *pszName,
5250 : OGRSpatialReferenceH hSpatialRef,
5251 : OGRwkbGeometryType eGType,
5252 : CSLConstList papszOptions)
5253 :
5254 : {
5255 5565 : VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayer", nullptr);
5256 :
5257 5565 : if (pszName == nullptr)
5258 : {
5259 0 : CPLError(CE_Failure, CPLE_ObjectNull,
5260 : "Name was NULL in GDALDatasetCreateLayer");
5261 0 : return nullptr;
5262 : }
5263 :
5264 : OGRLayerH hLayer =
5265 11130 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5266 5565 : pszName, OGRSpatialReference::FromHandle(hSpatialRef), eGType,
5267 : const_cast<char **>(papszOptions)));
5268 :
5269 : #ifdef OGRAPISPY_ENABLED
5270 5565 : if (bOGRAPISpyEnabled)
5271 8 : OGRAPISpy_DS_CreateLayer(hDS, pszName, hSpatialRef, eGType,
5272 : const_cast<char **>(papszOptions), hLayer);
5273 : #endif
5274 :
5275 5565 : return hLayer;
5276 : }
5277 :
5278 : /************************************************************************/
5279 : /* GDALDatasetCreateLayerFromGeomFieldDefn() */
5280 : /************************************************************************/
5281 :
5282 : /**
5283 : \brief This function attempts to create a new layer on the dataset with the
5284 : indicated name and geometry field.
5285 :
5286 : When poGeomFieldDefn is not null, most drivers should honor
5287 : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5288 : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5289 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5290 : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5291 : very few currently.
5292 :
5293 : Note that even if a geometry coordinate precision is set and a driver honors the
5294 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5295 : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5296 : with the coordinate precision. That is they are assumed to be valid once their
5297 : coordinates are rounded to it. If it might not be the case, the user may set
5298 : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5299 : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5300 : the passed geometries.
5301 :
5302 : The papszOptions argument can be used to control driver specific creation
5303 : options. These options are normally documented in the format specific
5304 : documentation.
5305 :
5306 : This method is the same as the C++ method GDALDataset::CreateLayer().
5307 :
5308 : @param hDS the dataset handle
5309 : @param pszName the name for the new layer. This should ideally not
5310 : match any existing layer on the datasource.
5311 : @param hGeomFieldDefn the geometry field definition. May be NULL to indicate
5312 : a non-spatial file (or if adding geometry fields later with OGR_L_CreateGeomField()
5313 : for drivers supporting that interface).
5314 : @param papszOptions a StringList of name=value options. Options are driver
5315 : specific.
5316 :
5317 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5318 :
5319 : @since GDAL 3.9
5320 :
5321 : */
5322 :
5323 : OGRLayerH
5324 16 : GDALDatasetCreateLayerFromGeomFieldDefn(GDALDatasetH hDS, const char *pszName,
5325 : OGRGeomFieldDefnH hGeomFieldDefn,
5326 : CSLConstList papszOptions)
5327 :
5328 : {
5329 16 : VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayerFromGeomFieldDefn", nullptr);
5330 :
5331 16 : if (!pszName)
5332 : {
5333 0 : CPLError(CE_Failure, CPLE_ObjectNull,
5334 : "Name was NULL in GDALDatasetCreateLayerFromGeomFieldDefn");
5335 0 : return nullptr;
5336 : }
5337 :
5338 : OGRLayerH hLayer =
5339 32 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5340 16 : pszName, OGRGeomFieldDefn::FromHandle(hGeomFieldDefn),
5341 : papszOptions));
5342 16 : return hLayer;
5343 : }
5344 :
5345 : /************************************************************************/
5346 : /* GDALDatasetCopyLayer() */
5347 : /************************************************************************/
5348 :
5349 : /**
5350 : \brief Duplicate an existing layer.
5351 :
5352 : This function creates a new layer, duplicate the field definitions of the
5353 : source layer and then duplicate each features of the source layer.
5354 : The papszOptions argument
5355 : can be used to control driver specific creation options. These options are
5356 : normally documented in the format specific documentation.
5357 : The source layer may come from another dataset.
5358 :
5359 : This method is the same as the C++ method GDALDataset::CopyLayer()
5360 :
5361 : @since GDAL 2.0
5362 :
5363 : @param hDS the dataset handle.
5364 : @param hSrcLayer source layer.
5365 : @param pszNewName the name of the layer to create.
5366 : @param papszOptions a StringList of name=value options. Options are driver
5367 : specific.
5368 :
5369 : @return a handle to the layer, or NULL if an error occurs.
5370 : */
5371 10 : OGRLayerH GDALDatasetCopyLayer(GDALDatasetH hDS, OGRLayerH hSrcLayer,
5372 : const char *pszNewName,
5373 : CSLConstList papszOptions)
5374 :
5375 : {
5376 10 : VALIDATE_POINTER1(hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", nullptr);
5377 10 : VALIDATE_POINTER1(hSrcLayer, "GDALDatasetCopyLayer", nullptr);
5378 10 : VALIDATE_POINTER1(pszNewName, "GDALDatasetCopyLayer", nullptr);
5379 :
5380 20 : return OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CopyLayer(
5381 : OGRLayer::FromHandle(hSrcLayer), pszNewName,
5382 20 : const_cast<char **>(papszOptions)));
5383 : }
5384 :
5385 : /************************************************************************/
5386 : /* GDALDatasetExecuteSQL() */
5387 : /************************************************************************/
5388 :
5389 : /**
5390 : \brief Execute an SQL statement against the data store.
5391 :
5392 : The result of an SQL query is either NULL for statements that are in error,
5393 : or that have no results set, or an OGRLayer pointer representing a results
5394 : set from the query. Note that this OGRLayer is in addition to the layers
5395 : in the data store and must be destroyed with
5396 : ReleaseResultSet() before the dataset is closed
5397 : (destroyed).
5398 :
5399 : This method is the same as the C++ method GDALDataset::ExecuteSQL()
5400 :
5401 : For more information on the SQL dialect supported internally by OGR
5402 : review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
5403 : document. Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
5404 : to the underlying RDBMS.
5405 :
5406 : Starting with OGR 1.10, the <a
5407 : href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
5408 : also be used.
5409 :
5410 : @since GDAL 2.0
5411 :
5412 : @param hDS the dataset handle.
5413 : @param pszStatement the SQL statement to execute.
5414 : @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.
5415 :
5416 : @param pszDialect allows control of the statement dialect. If set to NULL, the
5417 : OGR SQL engine will be used, except for RDBMS drivers that will use their
5418 : dedicated SQL engine, unless OGRSQL is explicitly passed as the
5419 : dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
5420 :
5421 : @return an OGRLayer containing the results of the query. Deallocate with
5422 : GDALDatasetReleaseResultSet().
5423 :
5424 : */
5425 :
5426 10185 : OGRLayerH GDALDatasetExecuteSQL(GDALDatasetH hDS, const char *pszStatement,
5427 : OGRGeometryH hSpatialFilter,
5428 : const char *pszDialect)
5429 :
5430 : {
5431 10185 : VALIDATE_POINTER1(hDS, "GDALDatasetExecuteSQL", nullptr);
5432 :
5433 : OGRLayerH hLayer =
5434 20370 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->ExecuteSQL(
5435 10185 : pszStatement, OGRGeometry::FromHandle(hSpatialFilter), pszDialect));
5436 :
5437 : #ifdef OGRAPISPY_ENABLED
5438 10185 : if (bOGRAPISpyEnabled)
5439 4 : OGRAPISpy_DS_ExecuteSQL(hDS, pszStatement, hSpatialFilter, pszDialect,
5440 : hLayer);
5441 : #endif
5442 :
5443 10185 : return hLayer;
5444 : }
5445 :
5446 : /************************************************************************/
5447 : /* GDALDatasetAbortSQL() */
5448 : /************************************************************************/
5449 :
5450 : /**
5451 : \brief Abort any SQL statement running in the data store.
5452 :
5453 : This function can be safely called from any thread (pending that the dataset
5454 : object is still alive). Driver implementations will make sure that it can be
5455 : called in a thread-safe way.
5456 :
5457 : This might not be implemented by all drivers. At time of writing, only SQLite,
5458 : GPKG and PG drivers implement it
5459 :
5460 : This method is the same as the C++ method GDALDataset::AbortSQL()
5461 :
5462 : @since GDAL 3.2.0
5463 :
5464 : @param hDS the dataset handle.
5465 :
5466 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if AbortSQL
5467 : is not supported for this datasource. .
5468 :
5469 : */
5470 :
5471 6 : OGRErr GDALDatasetAbortSQL(GDALDatasetH hDS)
5472 :
5473 : {
5474 6 : VALIDATE_POINTER1(hDS, "GDALDatasetAbortSQL", OGRERR_FAILURE);
5475 6 : return GDALDataset::FromHandle(hDS)->AbortSQL();
5476 : }
5477 :
5478 : /************************************************************************/
5479 : /* GDALDatasetGetStyleTable() */
5480 : /************************************************************************/
5481 :
5482 : /**
5483 : \brief Returns dataset style table.
5484 :
5485 : This function is the same as the C++ method GDALDataset::GetStyleTable()
5486 :
5487 : @since GDAL 2.0
5488 :
5489 : @param hDS the dataset handle
5490 : @return handle to a style table which should not be modified or freed by the
5491 : caller.
5492 : */
5493 :
5494 6 : OGRStyleTableH GDALDatasetGetStyleTable(GDALDatasetH hDS)
5495 :
5496 : {
5497 6 : VALIDATE_POINTER1(hDS, "OGR_DS_GetStyleTable", nullptr);
5498 :
5499 : return reinterpret_cast<OGRStyleTableH>(
5500 6 : GDALDataset::FromHandle(hDS)->GetStyleTable());
5501 : }
5502 :
5503 : /************************************************************************/
5504 : /* GDALDatasetSetStyleTableDirectly() */
5505 : /************************************************************************/
5506 :
5507 : /**
5508 : \brief Set dataset style table.
5509 :
5510 : This function operate exactly as GDALDatasetSetStyleTable() except that it
5511 : assumes ownership of the passed table.
5512 :
5513 : This function is the same as the C++ method
5514 : GDALDataset::SetStyleTableDirectly()
5515 :
5516 : @since GDAL 2.0
5517 :
5518 : @param hDS the dataset handle
5519 : @param hStyleTable style table handle to set
5520 :
5521 : */
5522 :
5523 0 : void GDALDatasetSetStyleTableDirectly(GDALDatasetH hDS,
5524 : OGRStyleTableH hStyleTable)
5525 :
5526 : {
5527 0 : VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTableDirectly");
5528 :
5529 0 : GDALDataset::FromHandle(hDS)->SetStyleTableDirectly(
5530 0 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
5531 : }
5532 :
5533 : /************************************************************************/
5534 : /* GDALDatasetSetStyleTable() */
5535 : /************************************************************************/
5536 :
5537 : /**
5538 : \brief Set dataset style table.
5539 :
5540 : This function operate exactly as GDALDatasetSetStyleTableDirectly() except that
5541 : it assumes ownership of the passed table.
5542 :
5543 : This function is the same as the C++ method GDALDataset::SetStyleTable()
5544 :
5545 : @since GDAL 2.0
5546 :
5547 : @param hDS the dataset handle
5548 : @param hStyleTable style table handle to set
5549 :
5550 : */
5551 :
5552 5 : void GDALDatasetSetStyleTable(GDALDatasetH hDS, OGRStyleTableH hStyleTable)
5553 :
5554 : {
5555 5 : VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTable");
5556 5 : VALIDATE_POINTER0(hStyleTable, "OGR_DS_SetStyleTable");
5557 :
5558 5 : GDALDataset::FromHandle(hDS)->SetStyleTable(
5559 5 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
5560 : }
5561 :
5562 : /************************************************************************/
5563 : /* ValidateLayerCreationOptions() */
5564 : /************************************************************************/
5565 :
5566 : //! @cond Doxygen_Suppress
5567 8543 : int GDALDataset::ValidateLayerCreationOptions(const char *const *papszLCO)
5568 : {
5569 : const char *pszOptionList =
5570 8543 : GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5571 8543 : if (pszOptionList == nullptr && poDriver != nullptr)
5572 : {
5573 : pszOptionList =
5574 8543 : poDriver->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5575 : }
5576 17086 : CPLString osDataset;
5577 8543 : osDataset.Printf("dataset %s", GetDescription());
5578 8543 : return GDALValidateOptions(pszOptionList, papszLCO, "layer creation option",
5579 17086 : osDataset);
5580 : }
5581 :
5582 : //! @endcond
5583 :
5584 : /************************************************************************/
5585 : /* Release() */
5586 : /************************************************************************/
5587 :
5588 : /**
5589 : \brief Drop a reference to this dataset, and if the reference count drops to one
5590 : close (destroy) the dataset.
5591 :
5592 : This method is the same as the C function OGRReleaseDataSource().
5593 :
5594 : @deprecated. In GDAL 2, use GDALClose() instead
5595 :
5596 : @return OGRERR_NONE on success or an error code.
5597 : */
5598 :
5599 2145 : OGRErr GDALDataset::Release()
5600 :
5601 : {
5602 2145 : ReleaseRef();
5603 2145 : return OGRERR_NONE;
5604 : }
5605 :
5606 : /************************************************************************/
5607 : /* GetRefCount() */
5608 : /************************************************************************/
5609 :
5610 : /**
5611 : \brief Fetch reference count.
5612 :
5613 : This method is the same as the C function OGR_DS_GetRefCount().
5614 :
5615 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5616 :
5617 : @return the current reference count for the datasource object itself.
5618 : */
5619 :
5620 839 : int GDALDataset::GetRefCount() const
5621 : {
5622 839 : return nRefCount;
5623 : }
5624 :
5625 : /************************************************************************/
5626 : /* GetSummaryRefCount() */
5627 : /************************************************************************/
5628 :
5629 : /**
5630 : \brief Fetch reference count of datasource and all owned layers.
5631 :
5632 : This method is the same as the C function OGR_DS_GetSummaryRefCount().
5633 :
5634 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5635 :
5636 : @deprecated
5637 :
5638 : @return the current summary reference count for the datasource and its layers.
5639 : */
5640 :
5641 0 : int GDALDataset::GetSummaryRefCount() const
5642 :
5643 : {
5644 0 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
5645 0 : int nSummaryCount = nRefCount;
5646 0 : GDALDataset *poUseThis = const_cast<GDALDataset *>(this);
5647 :
5648 0 : for (int iLayer = 0; iLayer < poUseThis->GetLayerCount(); ++iLayer)
5649 0 : nSummaryCount += poUseThis->GetLayer(iLayer)->GetRefCount();
5650 :
5651 0 : return nSummaryCount;
5652 : }
5653 :
5654 : /************************************************************************/
5655 : /* ICreateLayer() */
5656 : /************************************************************************/
5657 :
5658 : /**
5659 : \brief This method attempts to create a new layer on the dataset with the
5660 : indicated name, coordinate system, geometry type.
5661 :
5662 : This method is reserved to implementation by drivers.
5663 :
5664 : The papszOptions argument can be used to control driver specific creation
5665 : options. These options are normally documented in the format specific
5666 : documentation.
5667 :
5668 : @param pszName the name for the new layer. This should ideally not
5669 : match any existing layer on the datasource.
5670 : @param poGeomFieldDefn the geometry field definition to use for the new layer,
5671 : or NULL if there is no geometry field.
5672 : @param papszOptions a StringList of name=value options. Options are driver
5673 : specific.
5674 :
5675 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5676 :
5677 : @since GDAL 2.0 (prototype modified in 3.9)
5678 : */
5679 :
5680 : OGRLayer *
5681 16 : GDALDataset::ICreateLayer(CPL_UNUSED const char *pszName,
5682 : CPL_UNUSED const OGRGeomFieldDefn *poGeomFieldDefn,
5683 : CPL_UNUSED CSLConstList papszOptions)
5684 :
5685 : {
5686 16 : CPLError(CE_Failure, CPLE_NotSupported,
5687 : "CreateLayer() not supported by this dataset.");
5688 :
5689 16 : return nullptr;
5690 : }
5691 :
5692 : /************************************************************************/
5693 : /* CopyLayer() */
5694 : /************************************************************************/
5695 :
5696 : /**
5697 : \brief Duplicate an existing layer.
5698 :
5699 : This method creates a new layer, duplicate the field definitions of the
5700 : source layer and then duplicate each features of the source layer.
5701 : The papszOptions argument
5702 : can be used to control driver specific creation options. These options are
5703 : normally documented in the format specific documentation.
5704 : The source layer may come from another dataset.
5705 :
5706 : This method is the same as the C function GDALDatasetCopyLayer() and the
5707 : deprecated OGR_DS_CopyLayer().
5708 :
5709 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5710 :
5711 : @param poSrcLayer source layer.
5712 : @param pszNewName the name of the layer to create.
5713 : @param papszOptions a StringList of name=value options. Options are driver
5714 : specific. There is a common option to set output layer
5715 : spatial reference: DST_SRSWKT. The option should be in
5716 : WKT format. Starting with GDAL 3.7, the common option
5717 : COPY_MD can be set to NO to prevent the default copying
5718 : of the metadata from the source layer to the target layer.
5719 :
5720 : @return a handle to the layer, or NULL if an error occurs.
5721 : */
5722 :
5723 125 : OGRLayer *GDALDataset::CopyLayer(OGRLayer *poSrcLayer, const char *pszNewName,
5724 : char **papszOptions)
5725 :
5726 : {
5727 : /* -------------------------------------------------------------------- */
5728 : /* Create the layer. */
5729 : /* -------------------------------------------------------------------- */
5730 125 : if (!TestCapability(ODsCCreateLayer))
5731 : {
5732 0 : CPLError(CE_Failure, CPLE_NotSupported,
5733 : "This datasource does not support creation of layers.");
5734 0 : return nullptr;
5735 : }
5736 :
5737 125 : const char *pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
5738 250 : OGRSpatialReference oDstSpaRef(pszSRSWKT);
5739 125 : oDstSpaRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
5740 125 : OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
5741 125 : OGRLayer *poDstLayer = nullptr;
5742 :
5743 250 : CPLStringList aosCleanedUpOptions(CSLDuplicate(papszOptions));
5744 125 : aosCleanedUpOptions.SetNameValue("DST_SRSWKT", nullptr);
5745 125 : aosCleanedUpOptions.SetNameValue("COPY_MD", nullptr);
5746 :
5747 125 : CPLErrorReset();
5748 125 : const int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
5749 125 : if (nSrcGeomFieldCount == 1)
5750 : {
5751 74 : OGRGeomFieldDefn oGeomFieldDefn(poSrcDefn->GetGeomFieldDefn(0));
5752 74 : if (pszSRSWKT)
5753 5 : oGeomFieldDefn.SetSpatialRef(&oDstSpaRef);
5754 74 : poDstLayer = ICreateLayer(pszNewName, &oGeomFieldDefn,
5755 74 : aosCleanedUpOptions.List());
5756 : }
5757 : else
5758 : {
5759 : poDstLayer =
5760 51 : ICreateLayer(pszNewName, nullptr, aosCleanedUpOptions.List());
5761 : }
5762 :
5763 125 : if (poDstLayer == nullptr)
5764 0 : return nullptr;
5765 :
5766 125 : if (CPLTestBool(CSLFetchNameValueDef(papszOptions, "COPY_MD", "YES")))
5767 : {
5768 124 : char **papszMD = poSrcLayer->GetMetadata();
5769 124 : if (papszMD)
5770 5 : poDstLayer->SetMetadata(papszMD);
5771 : }
5772 :
5773 : /* -------------------------------------------------------------------- */
5774 : /* Add fields. Default to copy all fields, and make sure to */
5775 : /* establish a mapping between indices, rather than names, in */
5776 : /* case the target datasource has altered it (e.g. Shapefile */
5777 : /* limited to 10 char field names). */
5778 : /* -------------------------------------------------------------------- */
5779 125 : const int nSrcFieldCount = poSrcDefn->GetFieldCount();
5780 :
5781 : // Initialize the index-to-index map to -1's.
5782 250 : std::vector<int> anMap(nSrcFieldCount, -1);
5783 :
5784 : // Caution: At the time of writing, the MapInfo driver
5785 : // returns NULL until a field has been added.
5786 125 : OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
5787 125 : int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
5788 269 : for (int iField = 0; iField < nSrcFieldCount; ++iField)
5789 : {
5790 144 : OGRFieldDefn *poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
5791 288 : OGRFieldDefn oFieldDefn(poSrcFieldDefn);
5792 :
5793 : // The field may have been already created at layer creation.
5794 144 : int iDstField = -1;
5795 144 : if (poDstFDefn)
5796 144 : iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
5797 144 : if (iDstField >= 0)
5798 : {
5799 0 : anMap[iField] = iDstField;
5800 : }
5801 144 : else if (poDstLayer->CreateField(&oFieldDefn) == OGRERR_NONE)
5802 : {
5803 : // Now that we've created a field, GetLayerDefn() won't return NULL.
5804 144 : if (poDstFDefn == nullptr)
5805 0 : poDstFDefn = poDstLayer->GetLayerDefn();
5806 :
5807 : // Sanity check: if it fails, the driver is buggy.
5808 288 : if (poDstFDefn != nullptr &&
5809 144 : poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
5810 : {
5811 0 : CPLError(CE_Warning, CPLE_AppDefined,
5812 : "The output driver has claimed to have added the %s "
5813 : "field, but it did not!",
5814 : oFieldDefn.GetNameRef());
5815 : }
5816 : else
5817 : {
5818 144 : anMap[iField] = nDstFieldCount;
5819 144 : ++nDstFieldCount;
5820 : }
5821 : }
5822 : }
5823 :
5824 : /* -------------------------------------------------------------------- */
5825 125 : std::unique_ptr<OGRCoordinateTransformation> poCT;
5826 125 : OGRSpatialReference *sourceSRS = poSrcLayer->GetSpatialRef();
5827 125 : if (sourceSRS != nullptr && pszSRSWKT != nullptr && !oDstSpaRef.IsEmpty() &&
5828 0 : sourceSRS->IsSame(&oDstSpaRef) == FALSE)
5829 : {
5830 0 : poCT.reset(OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef));
5831 0 : if (nullptr == poCT)
5832 : {
5833 0 : CPLError(CE_Failure, CPLE_NotSupported,
5834 : "This input/output spatial reference is not supported.");
5835 0 : return nullptr;
5836 : }
5837 : }
5838 : /* -------------------------------------------------------------------- */
5839 : /* Create geometry fields. */
5840 : /* -------------------------------------------------------------------- */
5841 126 : if (nSrcGeomFieldCount > 1 &&
5842 1 : TestCapability(ODsCCreateGeomFieldAfterCreateLayer))
5843 : {
5844 :
5845 3 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5846 : {
5847 2 : if (nullptr == pszSRSWKT)
5848 : {
5849 2 : poDstLayer->CreateGeomField(
5850 2 : poSrcDefn->GetGeomFieldDefn(iField));
5851 : }
5852 : else
5853 : {
5854 : OGRGeomFieldDefn *pDstGeomFieldDefn =
5855 0 : poSrcDefn->GetGeomFieldDefn(iField);
5856 0 : pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);
5857 0 : poDstLayer->CreateGeomField(pDstGeomFieldDefn);
5858 : }
5859 : }
5860 : }
5861 :
5862 : /* -------------------------------------------------------------------- */
5863 : /* Check if the destination layer supports transactions and set a */
5864 : /* default number of features in a single transaction. */
5865 : /* -------------------------------------------------------------------- */
5866 : const int nGroupTransactions =
5867 125 : poDstLayer->TestCapability(OLCTransactions) ? 128 : 0;
5868 :
5869 : /* -------------------------------------------------------------------- */
5870 : /* Transfer features. */
5871 : /* -------------------------------------------------------------------- */
5872 125 : poSrcLayer->ResetReading();
5873 :
5874 125 : if (nGroupTransactions <= 0)
5875 : {
5876 : while (true)
5877 : {
5878 : auto poFeature =
5879 399 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
5880 :
5881 399 : if (poFeature == nullptr)
5882 122 : break;
5883 :
5884 277 : CPLErrorReset();
5885 : auto poDstFeature =
5886 277 : std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
5887 :
5888 277 : if (poDstFeature->SetFrom(poFeature.get(), anMap.data(), TRUE) !=
5889 : OGRERR_NONE)
5890 : {
5891 0 : CPLError(CE_Failure, CPLE_AppDefined,
5892 : "Unable to translate feature " CPL_FRMT_GIB
5893 : " from layer %s.",
5894 0 : poFeature->GetFID(), poSrcDefn->GetName());
5895 0 : return poDstLayer;
5896 : }
5897 :
5898 277 : if (nullptr != poCT)
5899 : {
5900 0 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5901 : {
5902 0 : OGRGeometry *pGeom = poDstFeature->GetGeomFieldRef(iField);
5903 0 : if (nullptr == pGeom)
5904 0 : continue;
5905 :
5906 0 : const OGRErr eErr = pGeom->transform(poCT.get());
5907 0 : if (eErr == OGRERR_NONE)
5908 0 : continue;
5909 :
5910 0 : CPLError(CE_Failure, CPLE_AppDefined,
5911 : "Unable to transform geometry " CPL_FRMT_GIB
5912 : " from layer %s.",
5913 0 : poFeature->GetFID(), poSrcDefn->GetName());
5914 0 : return poDstLayer;
5915 : }
5916 : }
5917 :
5918 277 : poDstFeature->SetFID(poFeature->GetFID());
5919 :
5920 277 : CPLErrorReset();
5921 277 : if (poDstLayer->CreateFeature(poDstFeature.get()) != OGRERR_NONE)
5922 : {
5923 0 : return poDstLayer;
5924 : }
5925 277 : }
5926 : }
5927 : else
5928 : {
5929 3 : std::vector<std::unique_ptr<OGRFeature>> apoDstFeatures;
5930 : try
5931 : {
5932 3 : apoDstFeatures.resize(nGroupTransactions);
5933 : }
5934 0 : catch (const std::exception &e)
5935 : {
5936 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "%s", e.what());
5937 0 : return poDstLayer;
5938 : }
5939 3 : bool bStopTransfer = false;
5940 6 : while (!bStopTransfer)
5941 : {
5942 : /* --------------------------------------------------------------------
5943 : */
5944 : /* Fill the array with features. */
5945 : /* --------------------------------------------------------------------
5946 : */
5947 : // Number of features in the temporary array.
5948 3 : int nFeatCount = 0; // Used after for.
5949 33 : for (nFeatCount = 0; nFeatCount < nGroupTransactions; ++nFeatCount)
5950 : {
5951 : auto poFeature =
5952 33 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
5953 :
5954 33 : if (poFeature == nullptr)
5955 : {
5956 3 : bStopTransfer = true;
5957 3 : break;
5958 : }
5959 :
5960 30 : CPLErrorReset();
5961 30 : apoDstFeatures[nFeatCount] =
5962 60 : std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
5963 :
5964 60 : if (apoDstFeatures[nFeatCount]->SetFrom(
5965 60 : poFeature.get(), anMap.data(), TRUE) != OGRERR_NONE)
5966 : {
5967 0 : CPLError(CE_Failure, CPLE_AppDefined,
5968 : "Unable to translate feature " CPL_FRMT_GIB
5969 : " from layer %s.",
5970 0 : poFeature->GetFID(), poSrcDefn->GetName());
5971 0 : bStopTransfer = true;
5972 0 : poFeature.reset();
5973 0 : break;
5974 : }
5975 :
5976 30 : if (nullptr != poCT)
5977 : {
5978 0 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5979 : {
5980 : OGRGeometry *pGeom =
5981 0 : apoDstFeatures[nFeatCount]->GetGeomFieldRef(iField);
5982 0 : if (nullptr == pGeom)
5983 0 : continue;
5984 :
5985 0 : const OGRErr eErr = pGeom->transform(poCT.get());
5986 0 : if (eErr == OGRERR_NONE)
5987 0 : continue;
5988 :
5989 0 : CPLError(CE_Failure, CPLE_AppDefined,
5990 : "Unable to transform geometry " CPL_FRMT_GIB
5991 : " from layer %s.",
5992 0 : poFeature->GetFID(), poSrcDefn->GetName());
5993 0 : bStopTransfer = true;
5994 0 : poFeature.reset();
5995 0 : break;
5996 : }
5997 : }
5998 :
5999 30 : if (poFeature)
6000 : {
6001 30 : apoDstFeatures[nFeatCount]->SetFID(poFeature->GetFID());
6002 : }
6003 : }
6004 :
6005 3 : CPLErrorReset();
6006 3 : bool bStopTransaction = false;
6007 6 : while (!bStopTransaction)
6008 : {
6009 3 : bStopTransaction = true;
6010 3 : if (poDstLayer->StartTransaction() != OGRERR_NONE)
6011 0 : break;
6012 33 : for (int i = 0; i < nFeatCount; ++i)
6013 : {
6014 30 : if (poDstLayer->CreateFeature(apoDstFeatures[i].get()) !=
6015 : OGRERR_NONE)
6016 : {
6017 0 : bStopTransfer = true;
6018 0 : bStopTransaction = false;
6019 0 : break;
6020 : }
6021 30 : apoDstFeatures[i].reset();
6022 : }
6023 3 : if (bStopTransaction)
6024 : {
6025 3 : if (poDstLayer->CommitTransaction() != OGRERR_NONE)
6026 0 : break;
6027 : }
6028 : else
6029 : {
6030 0 : poDstLayer->RollbackTransaction();
6031 : }
6032 : }
6033 : }
6034 : }
6035 :
6036 125 : return poDstLayer;
6037 : }
6038 :
6039 : /************************************************************************/
6040 : /* DeleteLayer() */
6041 : /************************************************************************/
6042 :
6043 : /**
6044 : \fn GDALDataset::DeleteLayer(int)
6045 : \brief Delete the indicated layer from the datasource.
6046 :
6047 : If this method is supported
6048 : the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
6049 :
6050 : This method is the same as the C function GDALDatasetDeleteLayer() and the
6051 : deprecated OGR_DS_DeleteLayer().
6052 :
6053 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6054 :
6055 : @param iLayer the index of the layer to delete.
6056 :
6057 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
6058 : layers is not supported for this datasource.
6059 :
6060 : */
6061 :
6062 405 : OGRErr GDALDataset::DeleteLayer(CPL_UNUSED int iLayer)
6063 :
6064 : {
6065 405 : CPLError(CE_Failure, CPLE_NotSupported,
6066 : "DeleteLayer() not supported by this dataset.");
6067 :
6068 405 : return OGRERR_UNSUPPORTED_OPERATION;
6069 : }
6070 :
6071 : /************************************************************************/
6072 : /* GetLayerByName() */
6073 : /************************************************************************/
6074 :
6075 : /**
6076 : \brief Fetch a layer by name.
6077 :
6078 : The returned layer remains owned by the
6079 : GDALDataset and should not be deleted by the application.
6080 :
6081 : This method is the same as the C function GDALDatasetGetLayerByName() and the
6082 : deprecated OGR_DS_GetLayerByName().
6083 :
6084 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6085 :
6086 : @param pszName the layer name of the layer to fetch.
6087 :
6088 : @return the layer, or NULL if Layer is not found or an error occurs.
6089 : */
6090 :
6091 29425 : OGRLayer *GDALDataset::GetLayerByName(const char *pszName)
6092 :
6093 : {
6094 58850 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
6095 :
6096 29425 : if (!pszName)
6097 0 : return nullptr;
6098 :
6099 : // First a case sensitive check.
6100 934586 : for (int i = 0; i < GetLayerCount(); ++i)
6101 : {
6102 916338 : OGRLayer *poLayer = GetLayer(i);
6103 :
6104 916338 : if (strcmp(pszName, poLayer->GetName()) == 0)
6105 11177 : return poLayer;
6106 : }
6107 :
6108 : // Then case insensitive.
6109 895562 : for (int i = 0; i < GetLayerCount(); ++i)
6110 : {
6111 877464 : OGRLayer *poLayer = GetLayer(i);
6112 :
6113 877464 : if (EQUAL(pszName, poLayer->GetName()))
6114 150 : return poLayer;
6115 : }
6116 :
6117 18098 : return nullptr;
6118 : }
6119 :
6120 : //! @cond Doxygen_Suppress
6121 : /************************************************************************/
6122 : /* ProcessSQLCreateIndex() */
6123 : /* */
6124 : /* The correct syntax for creating an index in our dialect of */
6125 : /* SQL is: */
6126 : /* */
6127 : /* CREATE INDEX ON <layername> USING <columnname> */
6128 : /************************************************************************/
6129 :
6130 28 : OGRErr GDALDataset::ProcessSQLCreateIndex(const char *pszSQLCommand)
6131 :
6132 : {
6133 28 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6134 :
6135 : /* -------------------------------------------------------------------- */
6136 : /* Do some general syntax checking. */
6137 : /* -------------------------------------------------------------------- */
6138 56 : if (CSLCount(papszTokens) != 6 || !EQUAL(papszTokens[0], "CREATE") ||
6139 84 : !EQUAL(papszTokens[1], "INDEX") || !EQUAL(papszTokens[2], "ON") ||
6140 28 : !EQUAL(papszTokens[4], "USING"))
6141 : {
6142 0 : CSLDestroy(papszTokens);
6143 0 : CPLError(CE_Failure, CPLE_AppDefined,
6144 : "Syntax error in CREATE INDEX command.\n"
6145 : "Was '%s'\n"
6146 : "Should be of form 'CREATE INDEX ON <table> USING <field>'",
6147 : pszSQLCommand);
6148 0 : return OGRERR_FAILURE;
6149 : }
6150 :
6151 : /* -------------------------------------------------------------------- */
6152 : /* Find the named layer. */
6153 : /* -------------------------------------------------------------------- */
6154 28 : OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6155 28 : if (poLayer == nullptr)
6156 : {
6157 0 : CPLError(CE_Failure, CPLE_AppDefined,
6158 : "CREATE INDEX ON failed, no such layer as `%s'.",
6159 0 : papszTokens[3]);
6160 0 : CSLDestroy(papszTokens);
6161 0 : return OGRERR_FAILURE;
6162 : }
6163 :
6164 : /* -------------------------------------------------------------------- */
6165 : /* Does this layer even support attribute indexes? */
6166 : /* -------------------------------------------------------------------- */
6167 28 : if (poLayer->GetIndex() == nullptr)
6168 : {
6169 0 : CPLError(CE_Failure, CPLE_AppDefined,
6170 : "CREATE INDEX ON not supported by this driver.");
6171 0 : CSLDestroy(papszTokens);
6172 0 : return OGRERR_FAILURE;
6173 : }
6174 :
6175 : /* -------------------------------------------------------------------- */
6176 : /* Find the named field. */
6177 : /* -------------------------------------------------------------------- */
6178 28 : int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6179 :
6180 28 : CSLDestroy(papszTokens);
6181 :
6182 28 : if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6183 : {
6184 0 : CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6185 : pszSQLCommand);
6186 0 : return OGRERR_FAILURE;
6187 : }
6188 :
6189 : /* -------------------------------------------------------------------- */
6190 : /* Attempt to create the index. */
6191 : /* -------------------------------------------------------------------- */
6192 28 : OGRErr eErr = poLayer->GetIndex()->CreateIndex(i);
6193 28 : if (eErr == OGRERR_NONE)
6194 : {
6195 28 : eErr = poLayer->GetIndex()->IndexAllFeatures(i);
6196 : }
6197 : else
6198 : {
6199 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
6200 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot '%s'", pszSQLCommand);
6201 : }
6202 :
6203 28 : return eErr;
6204 : }
6205 :
6206 : /************************************************************************/
6207 : /* ProcessSQLDropIndex() */
6208 : /* */
6209 : /* The correct syntax for dropping one or more indexes in */
6210 : /* the OGR SQL dialect is: */
6211 : /* */
6212 : /* DROP INDEX ON <layername> [USING <columnname>] */
6213 : /************************************************************************/
6214 :
6215 10 : OGRErr GDALDataset::ProcessSQLDropIndex(const char *pszSQLCommand)
6216 :
6217 : {
6218 10 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6219 :
6220 : /* -------------------------------------------------------------------- */
6221 : /* Do some general syntax checking. */
6222 : /* -------------------------------------------------------------------- */
6223 20 : if ((CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6) ||
6224 10 : !EQUAL(papszTokens[0], "DROP") || !EQUAL(papszTokens[1], "INDEX") ||
6225 30 : !EQUAL(papszTokens[2], "ON") ||
6226 10 : (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4], "USING")))
6227 : {
6228 0 : CSLDestroy(papszTokens);
6229 0 : CPLError(CE_Failure, CPLE_AppDefined,
6230 : "Syntax error in DROP INDEX command.\n"
6231 : "Was '%s'\n"
6232 : "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
6233 : pszSQLCommand);
6234 0 : return OGRERR_FAILURE;
6235 : }
6236 :
6237 : /* -------------------------------------------------------------------- */
6238 : /* Find the named layer. */
6239 : /* -------------------------------------------------------------------- */
6240 10 : OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6241 10 : if (poLayer == nullptr)
6242 : {
6243 0 : CPLError(CE_Failure, CPLE_AppDefined,
6244 : "DROP INDEX ON failed, no such layer as `%s'.",
6245 0 : papszTokens[3]);
6246 0 : CSLDestroy(papszTokens);
6247 0 : return OGRERR_FAILURE;
6248 : }
6249 :
6250 : /* -------------------------------------------------------------------- */
6251 : /* Does this layer even support attribute indexes? */
6252 : /* -------------------------------------------------------------------- */
6253 10 : if (poLayer->GetIndex() == nullptr)
6254 : {
6255 0 : CPLError(CE_Failure, CPLE_AppDefined,
6256 : "Indexes not supported by this driver.");
6257 0 : CSLDestroy(papszTokens);
6258 0 : return OGRERR_FAILURE;
6259 : }
6260 :
6261 : /* -------------------------------------------------------------------- */
6262 : /* If we were not given a field name, drop all indexes. */
6263 : /* -------------------------------------------------------------------- */
6264 10 : if (CSLCount(papszTokens) == 4)
6265 : {
6266 0 : for (int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i)
6267 : {
6268 : OGRAttrIndex *poAttrIndex;
6269 :
6270 0 : poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
6271 0 : if (poAttrIndex != nullptr)
6272 : {
6273 0 : const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6274 0 : if (eErr != OGRERR_NONE)
6275 : {
6276 0 : CSLDestroy(papszTokens);
6277 0 : return eErr;
6278 : }
6279 : }
6280 : }
6281 :
6282 0 : CSLDestroy(papszTokens);
6283 0 : return OGRERR_NONE;
6284 : }
6285 :
6286 : /* -------------------------------------------------------------------- */
6287 : /* Find the named field. */
6288 : /* -------------------------------------------------------------------- */
6289 10 : int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6290 10 : CSLDestroy(papszTokens);
6291 :
6292 10 : if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6293 : {
6294 0 : CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6295 : pszSQLCommand);
6296 0 : return OGRERR_FAILURE;
6297 : }
6298 :
6299 : /* -------------------------------------------------------------------- */
6300 : /* Attempt to drop the index. */
6301 : /* -------------------------------------------------------------------- */
6302 10 : const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6303 :
6304 10 : return eErr;
6305 : }
6306 :
6307 : /************************************************************************/
6308 : /* ProcessSQLDropTable() */
6309 : /* */
6310 : /* The correct syntax for dropping a table (layer) in the OGR SQL */
6311 : /* dialect is: */
6312 : /* */
6313 : /* DROP TABLE <layername> */
6314 : /************************************************************************/
6315 :
6316 500 : OGRErr GDALDataset::ProcessSQLDropTable(const char *pszSQLCommand)
6317 :
6318 : {
6319 500 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6320 :
6321 : /* -------------------------------------------------------------------- */
6322 : /* Do some general syntax checking. */
6323 : /* -------------------------------------------------------------------- */
6324 1000 : if (CSLCount(papszTokens) != 3 || !EQUAL(papszTokens[0], "DROP") ||
6325 500 : !EQUAL(papszTokens[1], "TABLE"))
6326 : {
6327 0 : CSLDestroy(papszTokens);
6328 0 : CPLError(CE_Failure, CPLE_AppDefined,
6329 : "Syntax error in DROP TABLE command.\n"
6330 : "Was '%s'\n"
6331 : "Should be of form 'DROP TABLE <table>'",
6332 : pszSQLCommand);
6333 0 : return OGRERR_FAILURE;
6334 : }
6335 :
6336 : /* -------------------------------------------------------------------- */
6337 : /* Find the named layer. */
6338 : /* -------------------------------------------------------------------- */
6339 500 : OGRLayer *poLayer = nullptr;
6340 :
6341 500 : int i = 0; // Used after for.
6342 40199 : for (; i < GetLayerCount(); ++i)
6343 : {
6344 40199 : poLayer = GetLayer(i);
6345 :
6346 40199 : if (poLayer != nullptr && EQUAL(poLayer->GetName(), papszTokens[2]))
6347 500 : break;
6348 39699 : poLayer = nullptr;
6349 : }
6350 :
6351 500 : if (poLayer == nullptr)
6352 : {
6353 0 : CPLError(CE_Failure, CPLE_AppDefined,
6354 0 : "DROP TABLE failed, no such layer as `%s'.", papszTokens[2]);
6355 0 : CSLDestroy(papszTokens);
6356 0 : return OGRERR_FAILURE;
6357 : }
6358 :
6359 500 : CSLDestroy(papszTokens);
6360 :
6361 : /* -------------------------------------------------------------------- */
6362 : /* Delete it. */
6363 : /* -------------------------------------------------------------------- */
6364 :
6365 500 : return DeleteLayer(i);
6366 : }
6367 :
6368 : //! @endcond
6369 :
6370 : /************************************************************************/
6371 : /* GDALDatasetParseSQLType() */
6372 : /************************************************************************/
6373 :
6374 : /* All arguments will be altered */
6375 6 : static OGRFieldType GDALDatasetParseSQLType(char *pszType, int &nWidth,
6376 : int &nPrecision)
6377 : {
6378 6 : char *pszParenthesis = strchr(pszType, '(');
6379 6 : if (pszParenthesis)
6380 : {
6381 4 : nWidth = atoi(pszParenthesis + 1);
6382 4 : *pszParenthesis = '\0';
6383 4 : char *pszComma = strchr(pszParenthesis + 1, ',');
6384 4 : if (pszComma)
6385 2 : nPrecision = atoi(pszComma + 1);
6386 : }
6387 :
6388 6 : OGRFieldType eType = OFTString;
6389 6 : if (EQUAL(pszType, "INTEGER"))
6390 0 : eType = OFTInteger;
6391 6 : else if (EQUAL(pszType, "INTEGER[]"))
6392 0 : eType = OFTIntegerList;
6393 6 : else if (EQUAL(pszType, "FLOAT") || EQUAL(pszType, "NUMERIC") ||
6394 4 : EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
6395 4 : EQUAL(pszType, "REAL") /* unofficial alias */)
6396 2 : eType = OFTReal;
6397 4 : else if (EQUAL(pszType, "FLOAT[]") || EQUAL(pszType, "NUMERIC[]") ||
6398 4 : EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||
6399 4 : EQUAL(pszType, "REAL[]") /* unofficial alias */)
6400 0 : eType = OFTRealList;
6401 4 : else if (EQUAL(pszType, "CHARACTER") ||
6402 0 : EQUAL(pszType, "TEXT") /* unofficial alias */ ||
6403 0 : EQUAL(pszType, "STRING") /* unofficial alias */ ||
6404 0 : EQUAL(pszType, "VARCHAR") /* unofficial alias */)
6405 4 : eType = OFTString;
6406 0 : else if (EQUAL(pszType, "TEXT[]") ||
6407 0 : EQUAL(pszType, "STRING[]") /* unofficial alias */ ||
6408 0 : EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)
6409 0 : eType = OFTStringList;
6410 0 : else if (EQUAL(pszType, "DATE"))
6411 0 : eType = OFTDate;
6412 0 : else if (EQUAL(pszType, "TIME"))
6413 0 : eType = OFTTime;
6414 0 : else if (EQUAL(pszType, "TIMESTAMP") ||
6415 0 : EQUAL(pszType, "DATETIME") /* unofficial alias */)
6416 0 : eType = OFTDateTime;
6417 : else
6418 0 : CPLError(CE_Warning, CPLE_NotSupported,
6419 : "Unsupported column type '%s'. Defaulting to VARCHAR",
6420 : pszType);
6421 :
6422 6 : return eType;
6423 : }
6424 :
6425 : /************************************************************************/
6426 : /* ProcessSQLAlterTableAddColumn() */
6427 : /* */
6428 : /* The correct syntax for adding a column in the OGR SQL */
6429 : /* dialect is: */
6430 : /* */
6431 : /* ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype> */
6432 : /************************************************************************/
6433 :
6434 : //! @cond Doxygen_Suppress
6435 2 : OGRErr GDALDataset::ProcessSQLAlterTableAddColumn(const char *pszSQLCommand)
6436 :
6437 : {
6438 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6439 :
6440 : /* -------------------------------------------------------------------- */
6441 : /* Do some general syntax checking. */
6442 : /* -------------------------------------------------------------------- */
6443 2 : const char *pszLayerName = nullptr;
6444 2 : const char *pszColumnName = nullptr;
6445 2 : int iTypeIndex = 0;
6446 2 : const int nTokens = CSLCount(papszTokens);
6447 :
6448 2 : if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6449 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD") &&
6450 2 : EQUAL(papszTokens[4], "COLUMN"))
6451 : {
6452 1 : pszLayerName = papszTokens[2];
6453 1 : pszColumnName = papszTokens[5];
6454 1 : iTypeIndex = 6;
6455 : }
6456 1 : else if (nTokens >= 6 && EQUAL(papszTokens[0], "ALTER") &&
6457 1 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD"))
6458 : {
6459 1 : pszLayerName = papszTokens[2];
6460 1 : pszColumnName = papszTokens[4];
6461 1 : iTypeIndex = 5;
6462 : }
6463 : else
6464 : {
6465 0 : CSLDestroy(papszTokens);
6466 0 : CPLError(CE_Failure, CPLE_AppDefined,
6467 : "Syntax error in ALTER TABLE ADD COLUMN command.\n"
6468 : "Was '%s'\n"
6469 : "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] "
6470 : "<columnname> <columntype>'",
6471 : pszSQLCommand);
6472 0 : return OGRERR_FAILURE;
6473 : }
6474 :
6475 : /* -------------------------------------------------------------------- */
6476 : /* Merge type components into a single string if there were split */
6477 : /* with spaces */
6478 : /* -------------------------------------------------------------------- */
6479 4 : CPLString osType;
6480 6 : for (int i = iTypeIndex; i < nTokens; ++i)
6481 : {
6482 4 : osType += papszTokens[i];
6483 4 : CPLFree(papszTokens[i]);
6484 : }
6485 2 : char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6486 2 : papszTokens[iTypeIndex + 1] = nullptr;
6487 :
6488 : /* -------------------------------------------------------------------- */
6489 : /* Find the named layer. */
6490 : /* -------------------------------------------------------------------- */
6491 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6492 2 : if (poLayer == nullptr)
6493 : {
6494 0 : CPLError(CE_Failure, CPLE_AppDefined,
6495 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6496 : pszLayerName);
6497 0 : CSLDestroy(papszTokens);
6498 0 : return OGRERR_FAILURE;
6499 : }
6500 :
6501 : /* -------------------------------------------------------------------- */
6502 : /* Add column. */
6503 : /* -------------------------------------------------------------------- */
6504 :
6505 2 : int nWidth = 0;
6506 2 : int nPrecision = 0;
6507 2 : OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6508 4 : OGRFieldDefn oFieldDefn(pszColumnName, eType);
6509 2 : oFieldDefn.SetWidth(nWidth);
6510 2 : oFieldDefn.SetPrecision(nPrecision);
6511 :
6512 2 : CSLDestroy(papszTokens);
6513 :
6514 2 : return poLayer->CreateField(&oFieldDefn);
6515 : }
6516 :
6517 : /************************************************************************/
6518 : /* ProcessSQLAlterTableDropColumn() */
6519 : /* */
6520 : /* The correct syntax for dropping a column in the OGR SQL */
6521 : /* dialect is: */
6522 : /* */
6523 : /* ALTER TABLE <layername> DROP [COLUMN] <columnname> */
6524 : /************************************************************************/
6525 :
6526 2 : OGRErr GDALDataset::ProcessSQLAlterTableDropColumn(const char *pszSQLCommand)
6527 :
6528 : {
6529 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6530 :
6531 : /* -------------------------------------------------------------------- */
6532 : /* Do some general syntax checking. */
6533 : /* -------------------------------------------------------------------- */
6534 2 : const char *pszLayerName = nullptr;
6535 2 : const char *pszColumnName = nullptr;
6536 3 : if (CSLCount(papszTokens) == 6 && EQUAL(papszTokens[0], "ALTER") &&
6537 4 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP") &&
6538 1 : EQUAL(papszTokens[4], "COLUMN"))
6539 : {
6540 1 : pszLayerName = papszTokens[2];
6541 1 : pszColumnName = papszTokens[5];
6542 : }
6543 2 : else if (CSLCount(papszTokens) == 5 && EQUAL(papszTokens[0], "ALTER") &&
6544 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP"))
6545 : {
6546 1 : pszLayerName = papszTokens[2];
6547 1 : pszColumnName = papszTokens[4];
6548 : }
6549 : else
6550 : {
6551 0 : CSLDestroy(papszTokens);
6552 0 : CPLError(CE_Failure, CPLE_AppDefined,
6553 : "Syntax error in ALTER TABLE DROP COLUMN command.\n"
6554 : "Was '%s'\n"
6555 : "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] "
6556 : "<columnname>'",
6557 : pszSQLCommand);
6558 0 : return OGRERR_FAILURE;
6559 : }
6560 :
6561 : /* -------------------------------------------------------------------- */
6562 : /* Find the named layer. */
6563 : /* -------------------------------------------------------------------- */
6564 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6565 2 : if (poLayer == nullptr)
6566 : {
6567 0 : CPLError(CE_Failure, CPLE_AppDefined,
6568 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6569 : pszLayerName);
6570 0 : CSLDestroy(papszTokens);
6571 0 : return OGRERR_FAILURE;
6572 : }
6573 :
6574 : /* -------------------------------------------------------------------- */
6575 : /* Find the field. */
6576 : /* -------------------------------------------------------------------- */
6577 :
6578 2 : int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6579 2 : if (nFieldIndex < 0)
6580 : {
6581 0 : CPLError(CE_Failure, CPLE_AppDefined,
6582 : "%s failed, no such field as `%s'.", pszSQLCommand,
6583 : pszColumnName);
6584 0 : CSLDestroy(papszTokens);
6585 0 : return OGRERR_FAILURE;
6586 : }
6587 :
6588 : /* -------------------------------------------------------------------- */
6589 : /* Remove it. */
6590 : /* -------------------------------------------------------------------- */
6591 :
6592 2 : CSLDestroy(papszTokens);
6593 :
6594 2 : return poLayer->DeleteField(nFieldIndex);
6595 : }
6596 :
6597 : /************************************************************************/
6598 : /* ProcessSQLAlterTableRenameColumn() */
6599 : /* */
6600 : /* The correct syntax for renaming a column in the OGR SQL */
6601 : /* dialect is: */
6602 : /* */
6603 : /* ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
6604 : /************************************************************************/
6605 :
6606 2 : OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn(const char *pszSQLCommand)
6607 :
6608 : {
6609 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6610 :
6611 : /* -------------------------------------------------------------------- */
6612 : /* Do some general syntax checking. */
6613 : /* -------------------------------------------------------------------- */
6614 2 : const char *pszLayerName = nullptr;
6615 2 : const char *pszOldColName = nullptr;
6616 2 : const char *pszNewColName = nullptr;
6617 3 : if (CSLCount(papszTokens) == 8 && EQUAL(papszTokens[0], "ALTER") &&
6618 1 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "RENAME") &&
6619 3 : EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TO"))
6620 : {
6621 1 : pszLayerName = papszTokens[2];
6622 1 : pszOldColName = papszTokens[5];
6623 1 : pszNewColName = papszTokens[7];
6624 : }
6625 2 : else if (CSLCount(papszTokens) == 7 && EQUAL(papszTokens[0], "ALTER") &&
6626 1 : EQUAL(papszTokens[1], "TABLE") &&
6627 2 : EQUAL(papszTokens[3], "RENAME") && EQUAL(papszTokens[5], "TO"))
6628 : {
6629 1 : pszLayerName = papszTokens[2];
6630 1 : pszOldColName = papszTokens[4];
6631 1 : pszNewColName = papszTokens[6];
6632 : }
6633 : else
6634 : {
6635 0 : CSLDestroy(papszTokens);
6636 0 : CPLError(CE_Failure, CPLE_AppDefined,
6637 : "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
6638 : "Was '%s'\n"
6639 : "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] "
6640 : "<columnname> TO <newname>'",
6641 : pszSQLCommand);
6642 0 : return OGRERR_FAILURE;
6643 : }
6644 :
6645 : /* -------------------------------------------------------------------- */
6646 : /* Find the named layer. */
6647 : /* -------------------------------------------------------------------- */
6648 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6649 2 : if (poLayer == nullptr)
6650 : {
6651 0 : CPLError(CE_Failure, CPLE_AppDefined,
6652 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6653 : pszLayerName);
6654 0 : CSLDestroy(papszTokens);
6655 0 : return OGRERR_FAILURE;
6656 : }
6657 :
6658 : /* -------------------------------------------------------------------- */
6659 : /* Find the field. */
6660 : /* -------------------------------------------------------------------- */
6661 :
6662 : const int nFieldIndex =
6663 2 : poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
6664 2 : if (nFieldIndex < 0)
6665 : {
6666 0 : CPLError(CE_Failure, CPLE_AppDefined,
6667 : "%s failed, no such field as `%s'.", pszSQLCommand,
6668 : pszOldColName);
6669 0 : CSLDestroy(papszTokens);
6670 0 : return OGRERR_FAILURE;
6671 : }
6672 :
6673 : /* -------------------------------------------------------------------- */
6674 : /* Rename column. */
6675 : /* -------------------------------------------------------------------- */
6676 : OGRFieldDefn *poOldFieldDefn =
6677 2 : poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6678 4 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6679 2 : oNewFieldDefn.SetName(pszNewColName);
6680 :
6681 2 : CSLDestroy(papszTokens);
6682 :
6683 2 : return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn,
6684 2 : ALTER_NAME_FLAG);
6685 : }
6686 :
6687 : /************************************************************************/
6688 : /* ProcessSQLAlterTableAlterColumn() */
6689 : /* */
6690 : /* The correct syntax for altering the type of a column in the */
6691 : /* OGR SQL dialect is: */
6692 : /* */
6693 : /* ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */
6694 : /************************************************************************/
6695 :
6696 4 : OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn(const char *pszSQLCommand)
6697 :
6698 : {
6699 4 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6700 :
6701 : /* -------------------------------------------------------------------- */
6702 : /* Do some general syntax checking. */
6703 : /* -------------------------------------------------------------------- */
6704 4 : const char *pszLayerName = nullptr;
6705 4 : const char *pszColumnName = nullptr;
6706 4 : int iTypeIndex = 0;
6707 4 : const int nTokens = CSLCount(papszTokens);
6708 :
6709 4 : if (nTokens >= 8 && EQUAL(papszTokens[0], "ALTER") &&
6710 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6711 2 : EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TYPE"))
6712 : {
6713 2 : pszLayerName = papszTokens[2];
6714 2 : pszColumnName = papszTokens[5];
6715 2 : iTypeIndex = 7;
6716 : }
6717 2 : else if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6718 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6719 2 : EQUAL(papszTokens[5], "TYPE"))
6720 : {
6721 2 : pszLayerName = papszTokens[2];
6722 2 : pszColumnName = papszTokens[4];
6723 2 : iTypeIndex = 6;
6724 : }
6725 : else
6726 : {
6727 0 : CSLDestroy(papszTokens);
6728 0 : CPLError(CE_Failure, CPLE_AppDefined,
6729 : "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
6730 : "Was '%s'\n"
6731 : "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] "
6732 : "<columnname> TYPE <columntype>'",
6733 : pszSQLCommand);
6734 0 : return OGRERR_FAILURE;
6735 : }
6736 :
6737 : /* -------------------------------------------------------------------- */
6738 : /* Merge type components into a single string if there were split */
6739 : /* with spaces */
6740 : /* -------------------------------------------------------------------- */
6741 8 : CPLString osType;
6742 8 : for (int i = iTypeIndex; i < nTokens; ++i)
6743 : {
6744 4 : osType += papszTokens[i];
6745 4 : CPLFree(papszTokens[i]);
6746 : }
6747 4 : char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6748 4 : papszTokens[iTypeIndex + 1] = nullptr;
6749 :
6750 : /* -------------------------------------------------------------------- */
6751 : /* Find the named layer. */
6752 : /* -------------------------------------------------------------------- */
6753 4 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6754 4 : if (poLayer == nullptr)
6755 : {
6756 0 : CPLError(CE_Failure, CPLE_AppDefined,
6757 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6758 : pszLayerName);
6759 0 : CSLDestroy(papszTokens);
6760 0 : return OGRERR_FAILURE;
6761 : }
6762 :
6763 : /* -------------------------------------------------------------------- */
6764 : /* Find the field. */
6765 : /* -------------------------------------------------------------------- */
6766 :
6767 : const int nFieldIndex =
6768 4 : poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6769 4 : if (nFieldIndex < 0)
6770 : {
6771 0 : CPLError(CE_Failure, CPLE_AppDefined,
6772 : "%s failed, no such field as `%s'.", pszSQLCommand,
6773 : pszColumnName);
6774 0 : CSLDestroy(papszTokens);
6775 0 : return OGRERR_FAILURE;
6776 : }
6777 :
6778 : /* -------------------------------------------------------------------- */
6779 : /* Alter column. */
6780 : /* -------------------------------------------------------------------- */
6781 :
6782 : OGRFieldDefn *poOldFieldDefn =
6783 4 : poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6784 8 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6785 :
6786 4 : int nWidth = 0;
6787 4 : int nPrecision = 0;
6788 4 : OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6789 4 : oNewFieldDefn.SetType(eType);
6790 4 : oNewFieldDefn.SetWidth(nWidth);
6791 4 : oNewFieldDefn.SetPrecision(nPrecision);
6792 :
6793 4 : int l_nFlags = 0;
6794 4 : if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
6795 2 : l_nFlags |= ALTER_TYPE_FLAG;
6796 4 : if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
6797 0 : poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
6798 4 : l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;
6799 :
6800 4 : CSLDestroy(papszTokens);
6801 :
6802 4 : if (l_nFlags == 0)
6803 0 : return OGRERR_NONE;
6804 :
6805 4 : return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn, l_nFlags);
6806 : }
6807 :
6808 : //! @endcond
6809 :
6810 : /************************************************************************/
6811 : /* ExecuteSQL() */
6812 : /************************************************************************/
6813 :
6814 : /**
6815 : \brief Execute an SQL statement against the data store.
6816 :
6817 : The result of an SQL query is either NULL for statements that are in error,
6818 : or that have no results set, or an OGRLayer pointer representing a results
6819 : set from the query. Note that this OGRLayer is in addition to the layers
6820 : in the data store and must be destroyed with
6821 : ReleaseResultSet() before the dataset is closed
6822 : (destroyed).
6823 :
6824 : This method is the same as the C function GDALDatasetExecuteSQL() and the
6825 : deprecated OGR_DS_ExecuteSQL().
6826 :
6827 : For more information on the SQL dialect supported internally by OGR
6828 : review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
6829 : document. Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
6830 : to the underlying RDBMS.
6831 :
6832 : Starting with OGR 1.10, the <a
6833 : href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
6834 : also be used.
6835 :
6836 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6837 :
6838 : @param pszStatement the SQL statement to execute.
6839 : @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.
6840 : @param pszDialect allows control of the statement dialect. If set to NULL, the
6841 : OGR SQL engine will be used, except for RDBMS drivers that will use their
6842 : dedicated SQL engine, unless OGRSQL is explicitly passed as the
6843 : dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
6844 :
6845 : @return an OGRLayer containing the results of the query. Deallocate with
6846 : ReleaseResultSet().
6847 :
6848 : */
6849 :
6850 3474 : OGRLayer *GDALDataset::ExecuteSQL(const char *pszStatement,
6851 : OGRGeometry *poSpatialFilter,
6852 : const char *pszDialect)
6853 :
6854 : {
6855 3474 : return ExecuteSQL(pszStatement, poSpatialFilter, pszDialect, nullptr);
6856 : }
6857 :
6858 : //! @cond Doxygen_Suppress
6859 : OGRLayer *
6860 3482 : GDALDataset::ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
6861 : const char *pszDialect,
6862 : swq_select_parse_options *poSelectParseOptions)
6863 :
6864 : {
6865 3482 : if (pszDialect != nullptr && EQUAL(pszDialect, "SQLite"))
6866 : {
6867 : #ifdef SQLITE_ENABLED
6868 643 : return OGRSQLiteExecuteSQL(this, pszStatement, poSpatialFilter,
6869 643 : pszDialect);
6870 : #else
6871 : CPLError(CE_Failure, CPLE_NotSupported,
6872 : "The SQLite driver needs to be compiled to support the "
6873 : "SQLite SQL dialect");
6874 : return nullptr;
6875 : #endif
6876 : }
6877 :
6878 2839 : if (pszDialect != nullptr && !EQUAL(pszDialect, "") &&
6879 11 : !EQUAL(pszDialect, "OGRSQL"))
6880 : {
6881 2 : std::string osDialectList = "'OGRSQL'";
6882 : #ifdef SQLITE_ENABLED
6883 1 : osDialectList += ", 'SQLITE'";
6884 : #endif
6885 : const char *pszDialects =
6886 1 : GetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS);
6887 1 : if (pszDialects)
6888 : {
6889 : const CPLStringList aosTokens(
6890 0 : CSLTokenizeString2(pszDialects, " ", 0));
6891 0 : for (int i = 0; i < aosTokens.size(); ++i)
6892 : {
6893 0 : if (!EQUAL(aosTokens[i], "OGRSQL") &&
6894 0 : !EQUAL(aosTokens[i], "SQLITE"))
6895 : {
6896 0 : osDialectList += ", '";
6897 0 : osDialectList += aosTokens[i];
6898 0 : osDialectList += "'";
6899 : }
6900 : }
6901 : }
6902 1 : CPLError(CE_Warning, CPLE_NotSupported,
6903 : "Dialect '%s' is unsupported. Only supported dialects are %s. "
6904 : "Defaulting to OGRSQL",
6905 : pszDialect, osDialectList.c_str());
6906 : }
6907 :
6908 : /* -------------------------------------------------------------------- */
6909 : /* Handle CREATE INDEX statements specially. */
6910 : /* -------------------------------------------------------------------- */
6911 2839 : if (STARTS_WITH_CI(pszStatement, "CREATE INDEX"))
6912 : {
6913 28 : ProcessSQLCreateIndex(pszStatement);
6914 28 : return nullptr;
6915 : }
6916 :
6917 : /* -------------------------------------------------------------------- */
6918 : /* Handle DROP INDEX statements specially. */
6919 : /* -------------------------------------------------------------------- */
6920 2811 : if (STARTS_WITH_CI(pszStatement, "DROP INDEX"))
6921 : {
6922 10 : ProcessSQLDropIndex(pszStatement);
6923 10 : return nullptr;
6924 : }
6925 :
6926 : /* -------------------------------------------------------------------- */
6927 : /* Handle DROP TABLE statements specially. */
6928 : /* -------------------------------------------------------------------- */
6929 2801 : if (STARTS_WITH_CI(pszStatement, "DROP TABLE"))
6930 : {
6931 500 : ProcessSQLDropTable(pszStatement);
6932 500 : return nullptr;
6933 : }
6934 :
6935 : /* -------------------------------------------------------------------- */
6936 : /* Handle ALTER TABLE statements specially. */
6937 : /* -------------------------------------------------------------------- */
6938 2301 : if (STARTS_WITH_CI(pszStatement, "ALTER TABLE"))
6939 : {
6940 11 : char **papszTokens = CSLTokenizeString(pszStatement);
6941 11 : const int nTokens = CSLCount(papszTokens);
6942 11 : if (nTokens >= 4 && EQUAL(papszTokens[3], "ADD"))
6943 : {
6944 2 : ProcessSQLAlterTableAddColumn(pszStatement);
6945 2 : CSLDestroy(papszTokens);
6946 2 : return nullptr;
6947 : }
6948 9 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "DROP"))
6949 : {
6950 2 : ProcessSQLAlterTableDropColumn(pszStatement);
6951 2 : CSLDestroy(papszTokens);
6952 2 : return nullptr;
6953 : }
6954 7 : else if (nTokens == 6 && EQUAL(papszTokens[3], "RENAME") &&
6955 1 : EQUAL(papszTokens[4], "TO"))
6956 : {
6957 1 : const char *pszSrcTableName = papszTokens[2];
6958 1 : const char *pszDstTableName = papszTokens[5];
6959 1 : auto poSrcLayer = GetLayerByName(pszSrcTableName);
6960 1 : if (poSrcLayer)
6961 : {
6962 1 : CPL_IGNORE_RET_VAL(poSrcLayer->Rename(pszDstTableName));
6963 : }
6964 : else
6965 : {
6966 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid layer name");
6967 : }
6968 1 : CSLDestroy(papszTokens);
6969 1 : return nullptr;
6970 : }
6971 6 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "RENAME"))
6972 : {
6973 2 : ProcessSQLAlterTableRenameColumn(pszStatement);
6974 2 : CSLDestroy(papszTokens);
6975 2 : return nullptr;
6976 : }
6977 4 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "ALTER"))
6978 : {
6979 4 : ProcessSQLAlterTableAlterColumn(pszStatement);
6980 4 : CSLDestroy(papszTokens);
6981 4 : return nullptr;
6982 : }
6983 : else
6984 : {
6985 0 : CPLError(CE_Failure, CPLE_AppDefined,
6986 : "Unsupported ALTER TABLE command : %s", pszStatement);
6987 0 : CSLDestroy(papszTokens);
6988 0 : return nullptr;
6989 : }
6990 : }
6991 :
6992 : /* -------------------------------------------------------------------- */
6993 : /* Preparse the SQL statement. */
6994 : /* -------------------------------------------------------------------- */
6995 2290 : swq_select *psSelectInfo = new swq_select();
6996 2290 : swq_custom_func_registrar *poCustomFuncRegistrar = nullptr;
6997 2290 : if (poSelectParseOptions != nullptr)
6998 8 : poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;
6999 2290 : if (psSelectInfo->preparse(pszStatement,
7000 2290 : poCustomFuncRegistrar != nullptr) != CE_None)
7001 : {
7002 114 : delete psSelectInfo;
7003 114 : return nullptr;
7004 : }
7005 :
7006 : /* -------------------------------------------------------------------- */
7007 : /* If there is no UNION ALL, build result layer. */
7008 : /* -------------------------------------------------------------------- */
7009 2176 : if (psSelectInfo->poOtherSelect == nullptr)
7010 : {
7011 2171 : return BuildLayerFromSelectInfo(psSelectInfo, poSpatialFilter,
7012 2171 : pszDialect, poSelectParseOptions);
7013 : }
7014 :
7015 : /* -------------------------------------------------------------------- */
7016 : /* Build result union layer. */
7017 : /* -------------------------------------------------------------------- */
7018 5 : int nSrcLayers = 0;
7019 5 : OGRLayer **papoSrcLayers = nullptr;
7020 :
7021 5 : do
7022 : {
7023 10 : swq_select *psNextSelectInfo = psSelectInfo->poOtherSelect;
7024 10 : psSelectInfo->poOtherSelect = nullptr;
7025 :
7026 10 : OGRLayer *poLayer = BuildLayerFromSelectInfo(
7027 : psSelectInfo, poSpatialFilter, pszDialect, poSelectParseOptions);
7028 10 : if (poLayer == nullptr)
7029 : {
7030 : // Each source layer owns an independent select info.
7031 0 : for (int i = 0; i < nSrcLayers; ++i)
7032 0 : delete papoSrcLayers[i];
7033 0 : CPLFree(papoSrcLayers);
7034 :
7035 : // So we just have to destroy the remaining select info.
7036 0 : delete psNextSelectInfo;
7037 :
7038 0 : return nullptr;
7039 : }
7040 : else
7041 : {
7042 20 : papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(
7043 10 : papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));
7044 10 : papoSrcLayers[nSrcLayers] = poLayer;
7045 10 : ++nSrcLayers;
7046 :
7047 10 : psSelectInfo = psNextSelectInfo;
7048 : }
7049 10 : } while (psSelectInfo != nullptr);
7050 :
7051 5 : return new OGRUnionLayer("SELECT", nSrcLayers, papoSrcLayers, TRUE);
7052 : }
7053 :
7054 : //! @endcond
7055 :
7056 : /************************************************************************/
7057 : /* AbortSQL() */
7058 : /************************************************************************/
7059 :
7060 : /**
7061 : \brief Abort any SQL statement running in the data store.
7062 :
7063 : This function can be safely called from any thread (pending that the dataset
7064 : object is still alive). Driver implementations will make sure that it can be
7065 : called in a thread-safe way.
7066 :
7067 : This might not be implemented by all drivers. At time of writing, only SQLite,
7068 : GPKG and PG drivers implement it
7069 :
7070 : This method is the same as the C method GDALDatasetAbortSQL()
7071 :
7072 : @since GDAL 3.2.0
7073 :
7074 :
7075 : */
7076 :
7077 0 : OGRErr GDALDataset::AbortSQL()
7078 : {
7079 0 : CPLError(CE_Failure, CPLE_NotSupported,
7080 : "AbortSQL is not supported for this driver.");
7081 0 : return OGRERR_UNSUPPORTED_OPERATION;
7082 : }
7083 :
7084 : /************************************************************************/
7085 : /* BuildLayerFromSelectInfo() */
7086 : /************************************************************************/
7087 :
7088 : struct GDALSQLParseInfo
7089 : {
7090 : swq_field_list sFieldList;
7091 : int nExtraDSCount;
7092 : GDALDataset **papoExtraDS;
7093 : char *pszWHERE;
7094 : };
7095 :
7096 2181 : OGRLayer *GDALDataset::BuildLayerFromSelectInfo(
7097 : swq_select *psSelectInfo, OGRGeometry *poSpatialFilter,
7098 : const char *pszDialect, swq_select_parse_options *poSelectParseOptions)
7099 : {
7100 4362 : std::unique_ptr<swq_select> psSelectInfoUnique(psSelectInfo);
7101 :
7102 2181 : std::unique_ptr<OGRGenSQLResultsLayer> poResults;
7103 : GDALSQLParseInfo *psParseInfo =
7104 2181 : BuildParseInfo(psSelectInfoUnique.get(), poSelectParseOptions);
7105 :
7106 2181 : if (psParseInfo)
7107 : {
7108 2147 : const auto nErrorCounter = CPLGetErrorCounter();
7109 4294 : poResults = std::make_unique<OGRGenSQLResultsLayer>(
7110 2147 : this, std::move(psSelectInfoUnique), poSpatialFilter,
7111 4294 : psParseInfo->pszWHERE, pszDialect);
7112 2224 : if (CPLGetErrorCounter() > nErrorCounter &&
7113 77 : CPLGetLastErrorType() != CE_None)
7114 77 : poResults.reset();
7115 : }
7116 :
7117 2181 : DestroyParseInfo(psParseInfo);
7118 :
7119 4362 : return poResults.release();
7120 : }
7121 :
7122 : /************************************************************************/
7123 : /* DestroyParseInfo() */
7124 : /************************************************************************/
7125 :
7126 : //! @cond Doxygen_Suppress
7127 2249 : void GDALDataset::DestroyParseInfo(GDALSQLParseInfo *psParseInfo)
7128 : {
7129 2249 : if (psParseInfo == nullptr)
7130 34 : return;
7131 :
7132 2215 : CPLFree(psParseInfo->sFieldList.names);
7133 2215 : CPLFree(psParseInfo->sFieldList.types);
7134 2215 : CPLFree(psParseInfo->sFieldList.table_ids);
7135 2215 : CPLFree(psParseInfo->sFieldList.ids);
7136 :
7137 : // Release the datasets we have opened with OGROpenShared()
7138 : // It is safe to do that as the 'new OGRGenSQLResultsLayer' itself
7139 : // has taken a reference on them, which it will release in its
7140 : // destructor.
7141 2222 : for (int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; ++iEDS)
7142 7 : GDALClose(psParseInfo->papoExtraDS[iEDS]);
7143 :
7144 2215 : CPLFree(psParseInfo->papoExtraDS);
7145 2215 : CPLFree(psParseInfo->pszWHERE);
7146 2215 : CPLFree(psParseInfo);
7147 : }
7148 :
7149 : /************************************************************************/
7150 : /* BuildParseInfo() */
7151 : /************************************************************************/
7152 :
7153 : GDALSQLParseInfo *
7154 2215 : GDALDataset::BuildParseInfo(swq_select *psSelectInfo,
7155 : swq_select_parse_options *poSelectParseOptions)
7156 : {
7157 2215 : int nFirstLayerFirstSpecialFieldIndex = 0;
7158 :
7159 : GDALSQLParseInfo *psParseInfo =
7160 2215 : static_cast<GDALSQLParseInfo *>(CPLCalloc(1, sizeof(GDALSQLParseInfo)));
7161 :
7162 : /* -------------------------------------------------------------------- */
7163 : /* Validate that all the source tables are recognized, count */
7164 : /* fields. */
7165 : /* -------------------------------------------------------------------- */
7166 2215 : int nFieldCount = 0;
7167 :
7168 4499 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7169 : {
7170 2286 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7171 2286 : GDALDataset *poTableDS = this;
7172 :
7173 2286 : if (psTableDef->data_source != nullptr)
7174 : {
7175 7 : poTableDS = GDALDataset::FromHandle(
7176 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7177 7 : if (poTableDS == nullptr)
7178 : {
7179 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
7180 0 : CPLError(CE_Failure, CPLE_AppDefined,
7181 : "Unable to open secondary datasource "
7182 : "`%s' required by JOIN.",
7183 : psTableDef->data_source);
7184 :
7185 0 : DestroyParseInfo(psParseInfo);
7186 0 : return nullptr;
7187 : }
7188 :
7189 : // Keep in an array to release at the end of this function.
7190 14 : psParseInfo->papoExtraDS = static_cast<GDALDataset **>(CPLRealloc(
7191 7 : psParseInfo->papoExtraDS,
7192 7 : sizeof(GDALDataset *) * (psParseInfo->nExtraDSCount + 1)));
7193 7 : psParseInfo->papoExtraDS[psParseInfo->nExtraDSCount++] = poTableDS;
7194 : }
7195 :
7196 : OGRLayer *poSrcLayer =
7197 2286 : poTableDS->GetLayerByName(psTableDef->table_name);
7198 :
7199 2286 : if (poSrcLayer == nullptr)
7200 : {
7201 2 : CPLError(CE_Failure, CPLE_AppDefined,
7202 : "SELECT from table %s failed, no such table/featureclass.",
7203 : psTableDef->table_name);
7204 :
7205 2 : DestroyParseInfo(psParseInfo);
7206 2 : return nullptr;
7207 : }
7208 :
7209 2284 : nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
7210 2284 : if (iTable == 0 ||
7211 34 : (poSelectParseOptions &&
7212 34 : poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7213 2247 : nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7214 :
7215 2284 : const char *pszFID = poSrcLayer->GetFIDColumn();
7216 2894 : if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7217 610 : poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7218 560 : nFieldCount++;
7219 : }
7220 :
7221 : /* -------------------------------------------------------------------- */
7222 : /* Build the field list for all indicated tables. */
7223 : /* -------------------------------------------------------------------- */
7224 :
7225 2213 : psParseInfo->sFieldList.table_count = psSelectInfo->table_count;
7226 2213 : psParseInfo->sFieldList.table_defs = psSelectInfo->table_defs;
7227 :
7228 2213 : psParseInfo->sFieldList.count = 0;
7229 2213 : psParseInfo->sFieldList.names = static_cast<char **>(
7230 2213 : CPLMalloc(sizeof(char *) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7231 4426 : psParseInfo->sFieldList.types = static_cast<swq_field_type *>(CPLMalloc(
7232 2213 : sizeof(swq_field_type) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7233 2213 : psParseInfo->sFieldList.table_ids = static_cast<int *>(
7234 2213 : CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7235 2213 : psParseInfo->sFieldList.ids = static_cast<int *>(
7236 2213 : CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7237 :
7238 2213 : bool bIsFID64 = false;
7239 4497 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7240 : {
7241 2284 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7242 2284 : GDALDataset *poTableDS = this;
7243 :
7244 2284 : if (psTableDef->data_source != nullptr)
7245 : {
7246 7 : poTableDS = GDALDataset::FromHandle(
7247 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7248 7 : CPLAssert(poTableDS != nullptr);
7249 7 : poTableDS->Dereference();
7250 : }
7251 :
7252 : OGRLayer *poSrcLayer =
7253 2284 : poTableDS->GetLayerByName(psTableDef->table_name);
7254 :
7255 2284 : for (int iField = 0;
7256 18475 : iField < poSrcLayer->GetLayerDefn()->GetFieldCount(); iField++)
7257 : {
7258 : OGRFieldDefn *poFDefn =
7259 16191 : poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
7260 16191 : const int iOutField = psParseInfo->sFieldList.count++;
7261 32382 : psParseInfo->sFieldList.names[iOutField] =
7262 16191 : const_cast<char *>(poFDefn->GetNameRef());
7263 16191 : if (poFDefn->GetType() == OFTInteger)
7264 : {
7265 4195 : if (poFDefn->GetSubType() == OFSTBoolean)
7266 160 : psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7267 : else
7268 4035 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7269 : }
7270 11996 : else if (poFDefn->GetType() == OFTInteger64)
7271 : {
7272 707 : if (poFDefn->GetSubType() == OFSTBoolean)
7273 0 : psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7274 : else
7275 707 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7276 : }
7277 11289 : else if (poFDefn->GetType() == OFTReal)
7278 2655 : psParseInfo->sFieldList.types[iOutField] = SWQ_FLOAT;
7279 8634 : else if (poFDefn->GetType() == OFTString)
7280 5580 : psParseInfo->sFieldList.types[iOutField] = SWQ_STRING;
7281 3054 : else if (poFDefn->GetType() == OFTTime)
7282 83 : psParseInfo->sFieldList.types[iOutField] = SWQ_TIME;
7283 2971 : else if (poFDefn->GetType() == OFTDate)
7284 143 : psParseInfo->sFieldList.types[iOutField] = SWQ_DATE;
7285 2828 : else if (poFDefn->GetType() == OFTDateTime)
7286 939 : psParseInfo->sFieldList.types[iOutField] = SWQ_TIMESTAMP;
7287 : else
7288 1889 : psParseInfo->sFieldList.types[iOutField] = SWQ_OTHER;
7289 :
7290 16191 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7291 16191 : psParseInfo->sFieldList.ids[iOutField] = iField;
7292 : }
7293 :
7294 2284 : if (iTable == 0)
7295 : {
7296 2213 : nFirstLayerFirstSpecialFieldIndex = psParseInfo->sFieldList.count;
7297 : }
7298 :
7299 2284 : if (iTable == 0 ||
7300 34 : (poSelectParseOptions &&
7301 34 : poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7302 : {
7303 :
7304 2247 : for (int iField = 0;
7305 4144 : iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7306 : iField++)
7307 : {
7308 : OGRGeomFieldDefn *poFDefn =
7309 1897 : poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
7310 1897 : const int iOutField = psParseInfo->sFieldList.count++;
7311 3794 : psParseInfo->sFieldList.names[iOutField] =
7312 1897 : const_cast<char *>(poFDefn->GetNameRef());
7313 1897 : if (*psParseInfo->sFieldList.names[iOutField] == '\0')
7314 1084 : psParseInfo->sFieldList.names[iOutField] =
7315 : const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
7316 1897 : psParseInfo->sFieldList.types[iOutField] = SWQ_GEOMETRY;
7317 :
7318 1897 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7319 1897 : psParseInfo->sFieldList.ids[iOutField] =
7320 1897 : GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(
7321 : poSrcLayer->GetLayerDefn(), iField);
7322 : }
7323 : }
7324 :
7325 2285 : if (iTable == 0 && poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7326 1 : EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7327 : {
7328 1 : bIsFID64 = true;
7329 : }
7330 : }
7331 :
7332 : /* -------------------------------------------------------------------- */
7333 : /* Expand '*' in 'SELECT *' now before we add the pseudo fields */
7334 : /* -------------------------------------------------------------------- */
7335 2213 : const bool bAlwaysPrefixWithTableName =
7336 2255 : poSelectParseOptions &&
7337 42 : poSelectParseOptions->bAlwaysPrefixWithTableName;
7338 2213 : if (psSelectInfo->expand_wildcard(&psParseInfo->sFieldList,
7339 2213 : bAlwaysPrefixWithTableName) != CE_None)
7340 : {
7341 2 : DestroyParseInfo(psParseInfo);
7342 2 : return nullptr;
7343 : }
7344 :
7345 13266 : for (int iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
7346 : {
7347 11055 : psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] =
7348 11055 : const_cast<char *>(SpecialFieldNames[iField]);
7349 11055 : psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] =
7350 11055 : (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64
7351 : : SpecialFieldTypes[iField];
7352 11055 : psParseInfo->sFieldList.table_ids[psParseInfo->sFieldList.count] = 0;
7353 11055 : psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] =
7354 11055 : nFirstLayerFirstSpecialFieldIndex + iField;
7355 11055 : psParseInfo->sFieldList.count++;
7356 : }
7357 :
7358 : /* In the case a layer has an explicit FID column name, then add it */
7359 : /* so it can be selected */
7360 4493 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7361 : {
7362 2282 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7363 2282 : GDALDataset *poTableDS = this;
7364 :
7365 2282 : if (psTableDef->data_source != nullptr)
7366 : {
7367 7 : poTableDS = GDALDataset::FromHandle(
7368 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7369 7 : CPLAssert(poTableDS != nullptr);
7370 7 : poTableDS->Dereference();
7371 : }
7372 :
7373 : OGRLayer *poSrcLayer =
7374 2282 : poTableDS->GetLayerByName(psTableDef->table_name);
7375 :
7376 2282 : const char *pszFID = poSrcLayer->GetFIDColumn();
7377 2892 : if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7378 610 : poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7379 : {
7380 560 : const int iOutField = psParseInfo->sFieldList.count++;
7381 560 : psParseInfo->sFieldList.names[iOutField] =
7382 : const_cast<char *>(pszFID);
7383 560 : if (poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7384 0 : EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7385 : {
7386 0 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7387 : }
7388 : else
7389 : {
7390 560 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7391 : }
7392 560 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7393 1120 : psParseInfo->sFieldList.ids[iOutField] =
7394 560 : poSrcLayer->GetLayerDefn()->GetFieldCount() + SPF_FID;
7395 : }
7396 : }
7397 :
7398 : /* -------------------------------------------------------------------- */
7399 : /* Finish the parse operation. */
7400 : /* -------------------------------------------------------------------- */
7401 2211 : if (psSelectInfo->parse(&psParseInfo->sFieldList, poSelectParseOptions) !=
7402 : CE_None)
7403 : {
7404 30 : DestroyParseInfo(psParseInfo);
7405 30 : return nullptr;
7406 : }
7407 :
7408 : /* -------------------------------------------------------------------- */
7409 : /* Extract the WHERE expression to use separately. */
7410 : /* -------------------------------------------------------------------- */
7411 2181 : if (psSelectInfo->where_expr != nullptr)
7412 : {
7413 952 : psParseInfo->pszWHERE =
7414 952 : psSelectInfo->where_expr->Unparse(&psParseInfo->sFieldList, '"');
7415 : // CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
7416 : }
7417 :
7418 2181 : return psParseInfo;
7419 : }
7420 :
7421 : //! @endcond
7422 :
7423 : /************************************************************************/
7424 : /* ReleaseResultSet() */
7425 : /************************************************************************/
7426 :
7427 : /**
7428 : \brief Release results of ExecuteSQL().
7429 :
7430 : This method should only be used to deallocate OGRLayers resulting from
7431 : an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
7432 : results set before destroying the GDALDataset may cause errors.
7433 :
7434 : This method is the same as the C function GDALDatasetReleaseResultSet() and the
7435 : deprecated OGR_DS_ReleaseResultSet().
7436 :
7437 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7438 :
7439 : @param poResultsSet the result of a previous ExecuteSQL() call.
7440 : */
7441 :
7442 2094 : void GDALDataset::ReleaseResultSet(OGRLayer *poResultsSet)
7443 :
7444 : {
7445 2094 : delete poResultsSet;
7446 2094 : }
7447 :
7448 : /************************************************************************/
7449 : /* GetStyleTable() */
7450 : /************************************************************************/
7451 :
7452 : /**
7453 : \brief Returns dataset style table.
7454 :
7455 : This method is the same as the C function GDALDatasetGetStyleTable() and the
7456 : deprecated OGR_DS_GetStyleTable().
7457 :
7458 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7459 :
7460 : @return pointer to a style table which should not be modified or freed by the
7461 : caller.
7462 : */
7463 :
7464 682 : OGRStyleTable *GDALDataset::GetStyleTable()
7465 : {
7466 682 : return m_poStyleTable;
7467 : }
7468 :
7469 : /************************************************************************/
7470 : /* SetStyleTableDirectly() */
7471 : /************************************************************************/
7472 :
7473 : /**
7474 : \brief Set dataset style table.
7475 :
7476 : This method operate exactly as SetStyleTable() except that it
7477 : assumes ownership of the passed table.
7478 :
7479 : This method is the same as the C function GDALDatasetSetStyleTableDirectly()
7480 : and the deprecated OGR_DS_SetStyleTableDirectly().
7481 :
7482 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7483 :
7484 : @param poStyleTable pointer to style table to set
7485 :
7486 : */
7487 0 : void GDALDataset::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
7488 : {
7489 0 : if (m_poStyleTable)
7490 0 : delete m_poStyleTable;
7491 0 : m_poStyleTable = poStyleTable;
7492 0 : }
7493 :
7494 : /************************************************************************/
7495 : /* SetStyleTable() */
7496 : /************************************************************************/
7497 :
7498 : /**
7499 : \brief Set dataset style table.
7500 :
7501 : This method operate exactly as SetStyleTableDirectly() except
7502 : that it does not assume ownership of the passed table.
7503 :
7504 : This method is the same as the C function GDALDatasetSetStyleTable() and the
7505 : deprecated OGR_DS_SetStyleTable().
7506 :
7507 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7508 :
7509 : @param poStyleTable pointer to style table to set
7510 :
7511 : */
7512 :
7513 678 : void GDALDataset::SetStyleTable(OGRStyleTable *poStyleTable)
7514 : {
7515 678 : if (m_poStyleTable)
7516 0 : delete m_poStyleTable;
7517 678 : if (poStyleTable)
7518 1 : m_poStyleTable = poStyleTable->Clone();
7519 678 : }
7520 :
7521 : /************************************************************************/
7522 : /* IsGenericSQLDialect() */
7523 : /************************************************************************/
7524 :
7525 : //! @cond Doxygen_Suppress
7526 1737 : int GDALDataset::IsGenericSQLDialect(const char *pszDialect)
7527 : {
7528 3160 : return pszDialect != nullptr &&
7529 3160 : (EQUAL(pszDialect, "OGRSQL") || EQUAL(pszDialect, "SQLITE"));
7530 : }
7531 :
7532 : //! @endcond
7533 :
7534 : /************************************************************************/
7535 : /* GetLayerCount() */
7536 : /************************************************************************/
7537 :
7538 : /**
7539 : \brief Get the number of layers in this dataset.
7540 :
7541 : This method is the same as the C function GDALDatasetGetLayerCount(),
7542 : and the deprecated OGR_DS_GetLayerCount().
7543 :
7544 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7545 :
7546 : @return layer count.
7547 : */
7548 :
7549 85868 : int GDALDataset::GetLayerCount()
7550 : {
7551 85868 : return 0;
7552 : }
7553 :
7554 : /************************************************************************/
7555 : /* GetLayer() */
7556 : /************************************************************************/
7557 :
7558 : /**
7559 : \fn GDALDataset::GetLayer(int)
7560 : \brief Fetch a layer by index.
7561 :
7562 : The returned layer remains owned by the
7563 : GDALDataset and should not be deleted by the application.
7564 :
7565 : See GetLayers() for a C++ iterator version of this method.
7566 :
7567 : This method is the same as the C function GDALDatasetGetLayer() and the
7568 : deprecated OGR_DS_GetLayer().
7569 :
7570 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7571 :
7572 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7573 :
7574 : @return the layer, or NULL if iLayer is out of range or an error occurs.
7575 :
7576 : @see GetLayers()
7577 : */
7578 :
7579 0 : OGRLayer *GDALDataset::GetLayer(CPL_UNUSED int iLayer)
7580 : {
7581 0 : return nullptr;
7582 : }
7583 :
7584 : /************************************************************************/
7585 : /* IsLayerPrivate() */
7586 : /************************************************************************/
7587 :
7588 : /**
7589 : \fn GDALDataset::IsLayerPrivate(int)
7590 : \brief Returns true if the layer at the specified index is deemed a private or
7591 : system table, or an internal detail only.
7592 :
7593 : This method is the same as the C function GDALDatasetIsLayerPrivate().
7594 :
7595 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7596 :
7597 : @return true if the layer is a private or system table.
7598 :
7599 : @since GDAL 3.4
7600 : */
7601 :
7602 684 : bool GDALDataset::IsLayerPrivate(CPL_UNUSED int iLayer) const
7603 : {
7604 684 : return false;
7605 : }
7606 :
7607 : /************************************************************************/
7608 : /* ResetReading() */
7609 : /************************************************************************/
7610 :
7611 : /**
7612 : \brief Reset feature reading to start on the first feature.
7613 :
7614 : This affects GetNextFeature().
7615 :
7616 : Depending on drivers, this may also have the side effect of calling
7617 : OGRLayer::ResetReading() on the layers of this dataset.
7618 :
7619 : This method is the same as the C function GDALDatasetResetReading().
7620 :
7621 : @since GDAL 2.2
7622 : */
7623 5 : void GDALDataset::ResetReading()
7624 : {
7625 5 : if (!m_poPrivate)
7626 0 : return;
7627 5 : m_poPrivate->nCurrentLayerIdx = 0;
7628 5 : m_poPrivate->nLayerCount = -1;
7629 5 : m_poPrivate->poCurrentLayer = nullptr;
7630 5 : m_poPrivate->nFeatureReadInLayer = 0;
7631 5 : m_poPrivate->nFeatureReadInDataset = 0;
7632 5 : m_poPrivate->nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
7633 5 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
7634 : }
7635 :
7636 : /************************************************************************/
7637 : /* GDALDatasetResetReading() */
7638 : /************************************************************************/
7639 :
7640 : /**
7641 : \brief Reset feature reading to start on the first feature.
7642 :
7643 : This affects GDALDatasetGetNextFeature().
7644 :
7645 : Depending on drivers, this may also have the side effect of calling
7646 : OGR_L_ResetReading() on the layers of this dataset.
7647 :
7648 : This method is the same as the C++ method GDALDataset::ResetReading()
7649 :
7650 : @param hDS dataset handle
7651 : @since GDAL 2.2
7652 : */
7653 8 : void CPL_DLL GDALDatasetResetReading(GDALDatasetH hDS)
7654 : {
7655 8 : VALIDATE_POINTER0(hDS, "GDALDatasetResetReading");
7656 :
7657 8 : return GDALDataset::FromHandle(hDS)->ResetReading();
7658 : }
7659 :
7660 : /************************************************************************/
7661 : /* GetNextFeature() */
7662 : /************************************************************************/
7663 :
7664 : /**
7665 : \brief Fetch the next available feature from this dataset.
7666 :
7667 : This method is intended for the few drivers where OGRLayer::GetNextFeature()
7668 : is not efficient, but in general OGRLayer::GetNextFeature() is a more
7669 : natural API.
7670 :
7671 : See GetFeatures() for a C++ iterator version of this method.
7672 :
7673 : The returned feature becomes the responsibility of the caller to
7674 : delete with OGRFeature::DestroyFeature().
7675 :
7676 : Depending on the driver, this method may return features from layers in a
7677 : non sequential way. This is what may happen when the
7678 : ODsCRandomLayerRead capability is declared (for example for the
7679 : OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7680 : advised to use GDALDataset::GetNextFeature() instead of
7681 : OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7682 : implementation.
7683 :
7684 : The default implementation, used by most drivers, will
7685 : however iterate over each layer, and then over each feature within this
7686 : layer.
7687 :
7688 : This method takes into account spatial and attribute filters set on layers that
7689 : will be iterated upon.
7690 :
7691 : The ResetReading() method can be used to start at the beginning again.
7692 :
7693 : Depending on drivers, this may also have the side effect of calling
7694 : OGRLayer::GetNextFeature() on the layers of this dataset.
7695 :
7696 : This method is the same as the C function GDALDatasetGetNextFeature().
7697 :
7698 : @param ppoBelongingLayer a pointer to a OGRLayer* variable to receive the
7699 : layer to which the object belongs to, or NULL.
7700 : It is possible that the output of *ppoBelongingLayer
7701 : to be NULL despite the feature not being NULL.
7702 : @param pdfProgressPct a pointer to a double variable to receive the
7703 : percentage progress (in [0,1] range), or NULL.
7704 : On return, the pointed value might be negative if
7705 : determining the progress is not possible.
7706 : @param pfnProgress a progress callback to report progress (for
7707 : GetNextFeature() calls that might have a long
7708 : duration) and offer cancellation possibility, or NULL.
7709 : @param pProgressData user data provided to pfnProgress, or NULL
7710 : @return a feature, or NULL if no more features are available.
7711 : @since GDAL 2.2
7712 : @see GetFeatures()
7713 : */
7714 :
7715 47 : OGRFeature *GDALDataset::GetNextFeature(OGRLayer **ppoBelongingLayer,
7716 : double *pdfProgressPct,
7717 : GDALProgressFunc pfnProgress,
7718 : void *pProgressData)
7719 : {
7720 47 : if (!m_poPrivate || m_poPrivate->nCurrentLayerIdx < 0)
7721 : {
7722 2 : if (ppoBelongingLayer != nullptr)
7723 2 : *ppoBelongingLayer = nullptr;
7724 2 : if (pdfProgressPct != nullptr)
7725 1 : *pdfProgressPct = 1.0;
7726 2 : if (pfnProgress != nullptr)
7727 0 : pfnProgress(1.0, "", pProgressData);
7728 2 : return nullptr;
7729 : }
7730 :
7731 45 : if (m_poPrivate->poCurrentLayer == nullptr &&
7732 6 : (pdfProgressPct != nullptr || pfnProgress != nullptr))
7733 : {
7734 1 : if (m_poPrivate->nLayerCount < 0)
7735 : {
7736 1 : m_poPrivate->nLayerCount = GetLayerCount();
7737 : }
7738 :
7739 1 : if (m_poPrivate->nTotalFeatures == TOTAL_FEATURES_NOT_INIT)
7740 : {
7741 1 : m_poPrivate->nTotalFeatures = 0;
7742 5 : for (int i = 0; i < m_poPrivate->nLayerCount; i++)
7743 : {
7744 4 : OGRLayer *poLayer = GetLayer(i);
7745 8 : if (poLayer == nullptr ||
7746 4 : !poLayer->TestCapability(OLCFastFeatureCount))
7747 : {
7748 0 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7749 0 : break;
7750 : }
7751 4 : GIntBig nCount = poLayer->GetFeatureCount(FALSE);
7752 4 : if (nCount < 0)
7753 : {
7754 0 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7755 0 : break;
7756 : }
7757 4 : m_poPrivate->nTotalFeatures += nCount;
7758 : }
7759 : }
7760 : }
7761 :
7762 : while (true)
7763 : {
7764 56 : if (m_poPrivate->poCurrentLayer == nullptr)
7765 : {
7766 36 : m_poPrivate->poCurrentLayer =
7767 18 : GetLayer(m_poPrivate->nCurrentLayerIdx);
7768 18 : if (m_poPrivate->poCurrentLayer == nullptr)
7769 : {
7770 5 : m_poPrivate->nCurrentLayerIdx = -1;
7771 5 : if (ppoBelongingLayer != nullptr)
7772 5 : *ppoBelongingLayer = nullptr;
7773 5 : if (pdfProgressPct != nullptr)
7774 1 : *pdfProgressPct = 1.0;
7775 5 : return nullptr;
7776 : }
7777 13 : m_poPrivate->poCurrentLayer->ResetReading();
7778 13 : m_poPrivate->nFeatureReadInLayer = 0;
7779 13 : if (m_poPrivate->nTotalFeatures < 0 && pdfProgressPct != nullptr)
7780 : {
7781 0 : if (m_poPrivate->poCurrentLayer->TestCapability(
7782 0 : OLCFastFeatureCount))
7783 0 : m_poPrivate->nTotalFeaturesInLayer =
7784 0 : m_poPrivate->poCurrentLayer->GetFeatureCount(FALSE);
7785 : else
7786 0 : m_poPrivate->nTotalFeaturesInLayer = 0;
7787 : }
7788 : }
7789 51 : OGRFeature *poFeature = m_poPrivate->poCurrentLayer->GetNextFeature();
7790 51 : if (poFeature == nullptr)
7791 : {
7792 11 : m_poPrivate->nCurrentLayerIdx++;
7793 11 : m_poPrivate->poCurrentLayer = nullptr;
7794 11 : continue;
7795 : }
7796 :
7797 40 : m_poPrivate->nFeatureReadInLayer++;
7798 40 : m_poPrivate->nFeatureReadInDataset++;
7799 40 : if (pdfProgressPct != nullptr || pfnProgress != nullptr)
7800 : {
7801 4 : double dfPct = 0.0;
7802 4 : if (m_poPrivate->nTotalFeatures > 0)
7803 : {
7804 4 : dfPct = 1.0 * m_poPrivate->nFeatureReadInDataset /
7805 4 : m_poPrivate->nTotalFeatures;
7806 : }
7807 : else
7808 : {
7809 0 : dfPct = 1.0 * m_poPrivate->nCurrentLayerIdx /
7810 0 : m_poPrivate->nLayerCount;
7811 0 : if (m_poPrivate->nTotalFeaturesInLayer > 0)
7812 : {
7813 0 : dfPct += 1.0 * m_poPrivate->nFeatureReadInLayer /
7814 0 : m_poPrivate->nTotalFeaturesInLayer /
7815 0 : m_poPrivate->nLayerCount;
7816 : }
7817 : }
7818 4 : if (pdfProgressPct)
7819 4 : *pdfProgressPct = dfPct;
7820 4 : if (pfnProgress)
7821 0 : pfnProgress(dfPct, "", nullptr);
7822 : }
7823 :
7824 40 : if (ppoBelongingLayer != nullptr)
7825 40 : *ppoBelongingLayer = m_poPrivate->poCurrentLayer;
7826 40 : return poFeature;
7827 11 : }
7828 : }
7829 :
7830 : /************************************************************************/
7831 : /* GDALDatasetGetNextFeature() */
7832 : /************************************************************************/
7833 : /**
7834 : \brief Fetch the next available feature from this dataset.
7835 :
7836 : This method is intended for the few drivers where OGR_L_GetNextFeature()
7837 : is not efficient, but in general OGR_L_GetNextFeature() is a more
7838 : natural API.
7839 :
7840 : The returned feature becomes the responsibility of the caller to
7841 : delete with OGRFeature::DestroyFeature().
7842 :
7843 : Depending on the driver, this method may return features from layers in a
7844 : non sequential way. This is what may happen when the
7845 : ODsCRandomLayerRead capability is declared (for example for the
7846 : OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7847 : advised to use GDALDataset::GetNextFeature() instead of
7848 : OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7849 : implementation.
7850 :
7851 : The default implementation, used by most drivers, will
7852 : however iterate over each layer, and then over each feature within this
7853 : layer.
7854 :
7855 : This method takes into account spatial and attribute filters set on layers that
7856 : will be iterated upon.
7857 :
7858 : The ResetReading() method can be used to start at the beginning again.
7859 :
7860 : Depending on drivers, this may also have the side effect of calling
7861 : OGRLayer::GetNextFeature() on the layers of this dataset.
7862 :
7863 : This method is the same as the C++ method GDALDataset::GetNextFeature()
7864 :
7865 : @param hDS dataset handle.
7866 : @param phBelongingLayer a pointer to a OGRLayer* variable to receive the
7867 : layer to which the object belongs to, or NULL.
7868 : It is possible that the output of *ppoBelongingLayer
7869 : to be NULL despite the feature not being NULL.
7870 : @param pdfProgressPct a pointer to a double variable to receive the
7871 : percentage progress (in [0,1] range), or NULL.
7872 : On return, the pointed value might be negative if
7873 : determining the progress is not possible.
7874 : @param pfnProgress a progress callback to report progress (for
7875 : GetNextFeature() calls that might have a long
7876 : duration) and offer cancellation possibility, or NULL
7877 : @param pProgressData user data provided to pfnProgress, or NULL
7878 : @return a feature, or NULL if no more features are available.
7879 : @since GDAL 2.2
7880 : */
7881 1833 : OGRFeatureH CPL_DLL GDALDatasetGetNextFeature(GDALDatasetH hDS,
7882 : OGRLayerH *phBelongingLayer,
7883 : double *pdfProgressPct,
7884 : GDALProgressFunc pfnProgress,
7885 : void *pProgressData)
7886 : {
7887 1833 : VALIDATE_POINTER1(hDS, "GDALDatasetGetNextFeature", nullptr);
7888 :
7889 3666 : return OGRFeature::ToHandle(GDALDataset::FromHandle(hDS)->GetNextFeature(
7890 : reinterpret_cast<OGRLayer **>(phBelongingLayer), pdfProgressPct,
7891 3666 : pfnProgress, pProgressData));
7892 : }
7893 :
7894 : /************************************************************************/
7895 : /* TestCapability() */
7896 : /************************************************************************/
7897 :
7898 : /**
7899 : \fn GDALDataset::TestCapability( const char * pszCap )
7900 : \brief Test if capability is available.
7901 :
7902 : One of the following dataset capability names can be passed into this
7903 : method, and a TRUE or FALSE value will be returned indicating whether or not
7904 : the capability is available for this object.
7905 :
7906 : <ul>
7907 : <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
7908 : <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
7909 : layers.<p>
7910 : <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
7911 : datasource support CreateGeomField() just after layer creation.<p>
7912 : <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
7913 : geometries.<p>
7914 : <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
7915 : transactions.<p>
7916 : <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
7917 : transactions through emulation.<p>
7918 : <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
7919 : GetNextFeature() implementation, potentially returning features from
7920 : layers in a non sequential way.<p>
7921 : <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
7922 : CreateFeature() on layers in a non sequential way.<p>
7923 : </ul>
7924 :
7925 : The \#define macro forms of the capability names should be used in preference
7926 : to the strings themselves to avoid misspelling.
7927 :
7928 : This method is the same as the C function GDALDatasetTestCapability() and the
7929 : deprecated OGR_DS_TestCapability().
7930 :
7931 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7932 :
7933 : @param pszCap the capability to test.
7934 :
7935 : @return TRUE if capability available otherwise FALSE.
7936 : */
7937 :
7938 204 : int GDALDataset::TestCapability(CPL_UNUSED const char *pszCap)
7939 : {
7940 204 : return FALSE;
7941 : }
7942 :
7943 : /************************************************************************/
7944 : /* GDALDatasetTestCapability() */
7945 : /************************************************************************/
7946 :
7947 : /**
7948 : \brief Test if capability is available.
7949 :
7950 : One of the following dataset capability names can be passed into this
7951 : function, and a TRUE or FALSE value will be returned indicating whether or not
7952 : the capability is available for this object.
7953 :
7954 : <ul>
7955 : <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
7956 : <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
7957 : layers.<p>
7958 : <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
7959 : datasource support CreateGeomField() just after layer creation.<p>
7960 : <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
7961 : geometries.<p>
7962 : <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
7963 : transactions.<p>
7964 : <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
7965 : transactions through emulation.<p>
7966 : <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
7967 : GetNextFeature() implementation, potentially returning features from
7968 : layers in a non sequential way.<p>
7969 : <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
7970 : CreateFeature() on layers in a non sequential way.<p>
7971 : </ul>
7972 :
7973 : The \#define macro forms of the capability names should be used in preference
7974 : to the strings themselves to avoid misspelling.
7975 :
7976 : This function is the same as the C++ method GDALDataset::TestCapability()
7977 :
7978 : @since GDAL 2.0
7979 :
7980 : @param hDS the dataset handle.
7981 : @param pszCap the capability to test.
7982 :
7983 : @return TRUE if capability available otherwise FALSE.
7984 : */
7985 115 : int GDALDatasetTestCapability(GDALDatasetH hDS, const char *pszCap)
7986 :
7987 : {
7988 115 : VALIDATE_POINTER1(hDS, "GDALDatasetTestCapability", 0);
7989 115 : VALIDATE_POINTER1(pszCap, "GDALDatasetTestCapability", 0);
7990 :
7991 115 : return GDALDataset::FromHandle(hDS)->TestCapability(pszCap);
7992 : }
7993 :
7994 : /************************************************************************/
7995 : /* StartTransaction() */
7996 : /************************************************************************/
7997 :
7998 : /**
7999 : \fn GDALDataset::StartTransaction(int)
8000 : \brief For datasources which support transactions, StartTransaction creates a
8001 : `transaction.
8002 :
8003 : If starting the transaction fails, will return
8004 : OGRERR_FAILURE. Datasources which do not support transactions will
8005 : always return OGRERR_UNSUPPORTED_OPERATION.
8006 :
8007 : Nested transactions are not supported.
8008 :
8009 : All changes done after the start of the transaction are definitely applied in
8010 : the datasource if CommitTransaction() is called. They may be canceled by
8011 : calling RollbackTransaction() instead.
8012 :
8013 : At the time of writing, transactions only apply on vector layers.
8014 :
8015 : Datasets that support transactions will advertise the ODsCTransactions
8016 : capability. Use of transactions at dataset level is generally preferred to
8017 : transactions at layer level, whose scope is rarely limited to the layer from
8018 : which it was started.
8019 :
8020 : In case StartTransaction() fails, neither CommitTransaction() or
8021 : RollbackTransaction() should be called.
8022 :
8023 : If an error occurs after a successful StartTransaction(), the whole transaction
8024 : may or may not be implicitly canceled, depending on drivers. (e.g. the PG
8025 : driver will cancel it, SQLite/GPKG not). In any case, in the event of an error,
8026 : an explicit call to RollbackTransaction() should be done to keep things
8027 : balanced.
8028 :
8029 : By default, when bForce is set to FALSE, only "efficient" transactions will be
8030 : attempted. Some drivers may offer an emulation of transactions, but sometimes
8031 : with significant overhead, in which case the user must explicitly allow for
8032 : such an emulation by setting bForce to TRUE. Drivers that offer emulated
8033 : transactions should advertise the ODsCEmulatedTransactions capability (and not
8034 : ODsCTransactions).
8035 :
8036 : This function is the same as the C function GDALDatasetStartTransaction().
8037 :
8038 : @param bForce can be set to TRUE if an emulation, possibly slow, of a
8039 : transaction
8040 : mechanism is acceptable.
8041 :
8042 : @return OGRERR_NONE on success.
8043 : @since GDAL 2.0
8044 : */
8045 :
8046 37 : OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
8047 : {
8048 37 : return OGRERR_UNSUPPORTED_OPERATION;
8049 : }
8050 :
8051 : /************************************************************************/
8052 : /* GDALDatasetStartTransaction() */
8053 : /************************************************************************/
8054 :
8055 : /**
8056 : \brief For datasources which support transactions, StartTransaction creates a
8057 : transaction.
8058 :
8059 : If starting the transaction fails, will return
8060 : OGRERR_FAILURE. Datasources which do not support transactions will
8061 : always return OGRERR_UNSUPPORTED_OPERATION.
8062 :
8063 : Nested transactions are not supported.
8064 :
8065 : All changes done after the start of the transaction are definitely applied in
8066 : the datasource if CommitTransaction() is called. They may be canceled by
8067 : calling RollbackTransaction() instead.
8068 :
8069 : At the time of writing, transactions only apply on vector layers.
8070 :
8071 : Datasets that support transactions will advertise the ODsCTransactions
8072 : capability.
8073 : Use of transactions at dataset level is generally preferred to transactions at
8074 : layer level, whose scope is rarely limited to the layer from which it was
8075 : started.
8076 :
8077 : In case StartTransaction() fails, neither CommitTransaction() or
8078 : RollbackTransaction() should be called.
8079 :
8080 : If an error occurs after a successful StartTransaction(), the whole
8081 : transaction may or may not be implicitly canceled, depending on drivers. (e.g.
8082 : the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
8083 : error, an explicit call to RollbackTransaction() should be done to keep things
8084 : balanced.
8085 :
8086 : By default, when bForce is set to FALSE, only "efficient" transactions will be
8087 : attempted. Some drivers may offer an emulation of transactions, but sometimes
8088 : with significant overhead, in which case the user must explicitly allow for
8089 : such an emulation by setting bForce to TRUE. Drivers that offer emulated
8090 : transactions should advertise the ODsCEmulatedTransactions capability (and not
8091 : ODsCTransactions).
8092 :
8093 : This function is the same as the C++ method GDALDataset::StartTransaction()
8094 :
8095 : @param hDS the dataset handle.
8096 : @param bForce can be set to TRUE if an emulation, possibly slow, of a
8097 : transaction
8098 : mechanism is acceptable.
8099 :
8100 : @return OGRERR_NONE on success.
8101 : @since GDAL 2.0
8102 : */
8103 77 : OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
8104 : {
8105 77 : VALIDATE_POINTER1(hDS, "GDALDatasetStartTransaction",
8106 : OGRERR_INVALID_HANDLE);
8107 :
8108 : #ifdef OGRAPISPY_ENABLED
8109 77 : if (bOGRAPISpyEnabled)
8110 2 : OGRAPISpy_Dataset_StartTransaction(hDS, bForce);
8111 : #endif
8112 :
8113 77 : return GDALDataset::FromHandle(hDS)->StartTransaction(bForce);
8114 : }
8115 :
8116 : /************************************************************************/
8117 : /* CommitTransaction() */
8118 : /************************************************************************/
8119 :
8120 : /**
8121 : \brief For datasources which support transactions, CommitTransaction commits a
8122 : transaction.
8123 :
8124 : If no transaction is active, or the commit fails, will return
8125 : OGRERR_FAILURE. Datasources which do not support transactions will
8126 : always return OGRERR_UNSUPPORTED_OPERATION.
8127 :
8128 : Depending on drivers, this may or may not abort layer sequential readings that
8129 : are active.
8130 :
8131 : This function is the same as the C function GDALDatasetCommitTransaction().
8132 :
8133 : @return OGRERR_NONE on success.
8134 : @since GDAL 2.0
8135 : */
8136 37 : OGRErr GDALDataset::CommitTransaction()
8137 : {
8138 37 : return OGRERR_UNSUPPORTED_OPERATION;
8139 : }
8140 :
8141 : /************************************************************************/
8142 : /* GDALDatasetCommitTransaction() */
8143 : /************************************************************************/
8144 :
8145 : /**
8146 : \brief For datasources which support transactions, CommitTransaction commits a
8147 : transaction.
8148 :
8149 : If no transaction is active, or the commit fails, will return
8150 : OGRERR_FAILURE. Datasources which do not support transactions will
8151 : always return OGRERR_UNSUPPORTED_OPERATION.
8152 :
8153 : Depending on drivers, this may or may not abort layer sequential readings that
8154 : are active.
8155 :
8156 : This function is the same as the C++ method GDALDataset::CommitTransaction()
8157 :
8158 : @return OGRERR_NONE on success.
8159 : @since GDAL 2.0
8160 : */
8161 46 : OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
8162 : {
8163 46 : VALIDATE_POINTER1(hDS, "GDALDatasetCommitTransaction",
8164 : OGRERR_INVALID_HANDLE);
8165 :
8166 : #ifdef OGRAPISPY_ENABLED
8167 46 : if (bOGRAPISpyEnabled)
8168 2 : OGRAPISpy_Dataset_CommitTransaction(hDS);
8169 : #endif
8170 :
8171 46 : return GDALDataset::FromHandle(hDS)->CommitTransaction();
8172 : }
8173 :
8174 : /************************************************************************/
8175 : /* RollbackTransaction() */
8176 : /************************************************************************/
8177 :
8178 : /**
8179 : \brief For datasources which support transactions, RollbackTransaction will
8180 : roll back a datasource to its state before the start of the current
8181 : transaction.
8182 : If no transaction is active, or the rollback fails, will return
8183 : OGRERR_FAILURE. Datasources which do not support transactions will
8184 : always return OGRERR_UNSUPPORTED_OPERATION.
8185 :
8186 : This function is the same as the C function GDALDatasetRollbackTransaction().
8187 :
8188 : @return OGRERR_NONE on success.
8189 : @since GDAL 2.0
8190 : */
8191 2 : OGRErr GDALDataset::RollbackTransaction()
8192 : {
8193 2 : return OGRERR_UNSUPPORTED_OPERATION;
8194 : }
8195 :
8196 : /************************************************************************/
8197 : /* GDALDatasetRollbackTransaction() */
8198 : /************************************************************************/
8199 :
8200 : /**
8201 : \brief For datasources which support transactions, RollbackTransaction will
8202 : roll back a datasource to its state before the start of the current
8203 : transaction.
8204 : If no transaction is active, or the rollback fails, will return
8205 : OGRERR_FAILURE. Datasources which do not support transactions will
8206 : always return OGRERR_UNSUPPORTED_OPERATION.
8207 :
8208 : This function is the same as the C++ method GDALDataset::RollbackTransaction().
8209 :
8210 : @return OGRERR_NONE on success.
8211 : @since GDAL 2.0
8212 : */
8213 32 : OGRErr GDALDatasetRollbackTransaction(GDALDatasetH hDS)
8214 : {
8215 32 : VALIDATE_POINTER1(hDS, "GDALDatasetRollbackTransaction",
8216 : OGRERR_INVALID_HANDLE);
8217 :
8218 : #ifdef OGRAPISPY_ENABLED
8219 32 : if (bOGRAPISpyEnabled)
8220 2 : OGRAPISpy_Dataset_RollbackTransaction(hDS);
8221 : #endif
8222 :
8223 32 : return GDALDataset::FromHandle(hDS)->RollbackTransaction();
8224 : }
8225 :
8226 : //! @cond Doxygen_Suppress
8227 :
8228 : /************************************************************************/
8229 : /* ShareLockWithParentDataset() */
8230 : /************************************************************************/
8231 :
8232 : /* To be used typically by the GTiff driver to link overview datasets */
8233 : /* with their main dataset, so that they share the same lock */
8234 : /* Cf https://github.com/OSGeo/gdal/issues/1488 */
8235 : /* The parent dataset should remain alive while the this dataset is alive */
8236 :
8237 2120 : void GDALDataset::ShareLockWithParentDataset(GDALDataset *poParentDataset)
8238 : {
8239 2120 : if (m_poPrivate != nullptr)
8240 : {
8241 2120 : m_poPrivate->poParentDataset = poParentDataset;
8242 : }
8243 2120 : }
8244 :
8245 : /************************************************************************/
8246 : /* SetQueryLoggerFunc() */
8247 : /************************************************************************/
8248 :
8249 0 : bool GDALDataset::SetQueryLoggerFunc(CPL_UNUSED GDALQueryLoggerFunc callback,
8250 : CPL_UNUSED void *context)
8251 : {
8252 0 : return false;
8253 : }
8254 :
8255 : /************************************************************************/
8256 : /* EnterReadWrite() */
8257 : /************************************************************************/
8258 :
8259 6792050 : int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
8260 : {
8261 13584000 : if (m_poPrivate == nullptr ||
8262 6792040 : IsThreadSafe(GDAL_OF_RASTER | (nOpenFlags & GDAL_OF_UPDATE)))
8263 8666 : return FALSE;
8264 :
8265 6783300 : if (m_poPrivate->poParentDataset)
8266 38338 : return m_poPrivate->poParentDataset->EnterReadWrite(eRWFlag);
8267 :
8268 6744960 : if (eAccess == GA_Update)
8269 : {
8270 1601510 : if (m_poPrivate->eStateReadWriteMutex ==
8271 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8272 : {
8273 : // In case dead-lock would occur, which is not impossible,
8274 : // this can be used to prevent it, but at the risk of other
8275 : // issues.
8276 7533 : if (CPLTestBool(
8277 : CPLGetConfigOption("GDAL_ENABLE_READ_WRITE_MUTEX", "YES")))
8278 : {
8279 7533 : m_poPrivate->eStateReadWriteMutex =
8280 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED;
8281 : }
8282 : else
8283 : {
8284 0 : m_poPrivate->eStateReadWriteMutex =
8285 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8286 : }
8287 : }
8288 1601510 : if (m_poPrivate->eStateReadWriteMutex ==
8289 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED)
8290 : {
8291 : // There should be no race related to creating this mutex since
8292 : // it should be first created through IWriteBlock() / IRasterIO()
8293 : // and then GDALRasterBlock might call it from another thread.
8294 : #ifdef DEBUG_VERBOSE
8295 : CPLDebug("GDAL",
8296 : "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
8297 : CPLGetPID(), GetDescription());
8298 : #endif
8299 987749 : CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8300 :
8301 : const int nCountMutex =
8302 987759 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]++;
8303 987760 : if (nCountMutex == 0 && eRWFlag == GF_Read)
8304 : {
8305 335065 : CPLReleaseMutex(m_poPrivate->hMutex);
8306 865701 : for (int i = 0; i < nBands; i++)
8307 : {
8308 530636 : auto blockCache = papoBands[i]->poBandBlockCache;
8309 530636 : if (blockCache)
8310 489255 : blockCache->WaitCompletionPendingTasks();
8311 : }
8312 335065 : CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8313 : }
8314 :
8315 987760 : return TRUE;
8316 : }
8317 : }
8318 5757210 : return FALSE;
8319 : }
8320 :
8321 : /************************************************************************/
8322 : /* LeaveReadWrite() */
8323 : /************************************************************************/
8324 :
8325 1014640 : void GDALDataset::LeaveReadWrite()
8326 : {
8327 1014640 : if (m_poPrivate)
8328 : {
8329 1014640 : if (m_poPrivate->poParentDataset)
8330 : {
8331 26878 : m_poPrivate->poParentDataset->LeaveReadWrite();
8332 26878 : return;
8333 : }
8334 :
8335 987759 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]--;
8336 987754 : CPLReleaseMutex(m_poPrivate->hMutex);
8337 : #ifdef DEBUG_VERBOSE
8338 : CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s",
8339 : CPLGetPID(), GetDescription());
8340 : #endif
8341 : }
8342 : }
8343 :
8344 : /************************************************************************/
8345 : /* InitRWLock() */
8346 : /************************************************************************/
8347 :
8348 3639670 : void GDALDataset::InitRWLock()
8349 : {
8350 3639670 : if (m_poPrivate)
8351 : {
8352 3639670 : if (m_poPrivate->poParentDataset)
8353 : {
8354 7035 : m_poPrivate->poParentDataset->InitRWLock();
8355 7035 : return;
8356 : }
8357 :
8358 3632640 : if (m_poPrivate->eStateReadWriteMutex ==
8359 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8360 : {
8361 1 : if (EnterReadWrite(GF_Write))
8362 1 : LeaveReadWrite();
8363 : }
8364 : }
8365 : }
8366 :
8367 : /************************************************************************/
8368 : /* DisableReadWriteMutex() */
8369 : /************************************************************************/
8370 :
8371 : // The mutex logic is broken in multi-threaded situations, for example
8372 : // with 2 WarpedVRT datasets being read at the same time. In that
8373 : // particular case, the mutex is not needed, so allow the VRTWarpedDataset code
8374 : // to disable it.
8375 16238 : void GDALDataset::DisableReadWriteMutex()
8376 : {
8377 16238 : if (m_poPrivate)
8378 : {
8379 16239 : if (m_poPrivate->poParentDataset)
8380 : {
8381 0 : m_poPrivate->poParentDataset->DisableReadWriteMutex();
8382 0 : return;
8383 : }
8384 :
8385 16239 : m_poPrivate->eStateReadWriteMutex =
8386 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8387 : }
8388 : }
8389 :
8390 : /************************************************************************/
8391 : /* TemporarilyDropReadWriteLock() */
8392 : /************************************************************************/
8393 :
8394 3151360 : void GDALDataset::TemporarilyDropReadWriteLock()
8395 : {
8396 3151360 : if (m_poPrivate == nullptr)
8397 0 : return;
8398 :
8399 3151360 : if (m_poPrivate->poParentDataset)
8400 : {
8401 23045 : m_poPrivate->poParentDataset->TemporarilyDropReadWriteLock();
8402 23045 : return;
8403 : }
8404 :
8405 3128320 : if (m_poPrivate->hMutex)
8406 : {
8407 : #ifdef DEBUG_VERBOSE
8408 : CPLDebug("GDAL",
8409 : "[Thread " CPL_FRMT_GIB "] "
8410 : "Temporarily drop RW mutex for %s",
8411 : CPLGetPID(), GetDescription());
8412 : #endif
8413 291685 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8414 : const int nCount =
8415 291685 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8416 : #ifdef DEBUG_EXTRA
8417 : m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()] = nCount;
8418 : #endif
8419 887823 : for (int i = 0; i < nCount + 1; i++)
8420 : {
8421 : // The mutex is recursive
8422 : // coverity[double_unlock]
8423 596138 : CPLReleaseMutex(m_poPrivate->hMutex);
8424 : }
8425 : }
8426 : }
8427 :
8428 : /************************************************************************/
8429 : /* ReacquireReadWriteLock() */
8430 : /************************************************************************/
8431 :
8432 3151480 : void GDALDataset::ReacquireReadWriteLock()
8433 : {
8434 3151480 : if (m_poPrivate == nullptr)
8435 0 : return;
8436 :
8437 3151480 : if (m_poPrivate->poParentDataset)
8438 : {
8439 23045 : m_poPrivate->poParentDataset->ReacquireReadWriteLock();
8440 23045 : return;
8441 : }
8442 :
8443 3128430 : if (m_poPrivate->hMutex)
8444 : {
8445 : #ifdef DEBUG_VERBOSE
8446 : CPLDebug("GDAL",
8447 : "[Thread " CPL_FRMT_GIB "] "
8448 : "Reacquire temporarily dropped RW mutex for %s",
8449 : CPLGetPID(), GetDescription());
8450 : #endif
8451 291685 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8452 : const int nCount =
8453 291685 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8454 : #ifdef DEBUG_EXTRA
8455 : CPLAssert(nCount ==
8456 : m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()]);
8457 : #endif
8458 291685 : if (nCount == 0)
8459 11462 : CPLReleaseMutex(m_poPrivate->hMutex);
8460 315915 : for (int i = 0; i < nCount - 1; i++)
8461 : {
8462 : // The mutex is recursive
8463 : // coverity[double_lock]
8464 24230 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8465 : }
8466 : }
8467 : }
8468 :
8469 : /************************************************************************/
8470 : /* AcquireMutex() */
8471 : /************************************************************************/
8472 :
8473 196 : int GDALDataset::AcquireMutex()
8474 : {
8475 196 : if (m_poPrivate == nullptr)
8476 0 : return 0;
8477 196 : if (m_poPrivate->poParentDataset)
8478 : {
8479 0 : return m_poPrivate->poParentDataset->AcquireMutex();
8480 : }
8481 :
8482 196 : return CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8483 : }
8484 :
8485 : /************************************************************************/
8486 : /* ReleaseMutex() */
8487 : /************************************************************************/
8488 :
8489 196 : void GDALDataset::ReleaseMutex()
8490 : {
8491 196 : if (m_poPrivate)
8492 : {
8493 196 : if (m_poPrivate->poParentDataset)
8494 : {
8495 0 : m_poPrivate->poParentDataset->ReleaseMutex();
8496 0 : return;
8497 : }
8498 :
8499 196 : CPLReleaseMutex(m_poPrivate->hMutex);
8500 : }
8501 : }
8502 :
8503 : //! @endcond
8504 :
8505 : /************************************************************************/
8506 : /* GDALDataset::Features::Iterator::Private */
8507 : /************************************************************************/
8508 :
8509 : struct GDALDataset::Features::Iterator::Private
8510 : {
8511 : GDALDataset::FeatureLayerPair m_oPair{};
8512 : GDALDataset *m_poDS = nullptr;
8513 : bool m_bEOF = true;
8514 : };
8515 :
8516 4 : GDALDataset::Features::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8517 4 : : m_poPrivate(new GDALDataset::Features::Iterator::Private())
8518 : {
8519 4 : m_poPrivate->m_poDS = poDS;
8520 4 : if (bStart)
8521 : {
8522 2 : poDS->ResetReading();
8523 4 : m_poPrivate->m_oPair.feature.reset(poDS->GetNextFeature(
8524 2 : &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8525 2 : m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8526 : }
8527 4 : }
8528 :
8529 : GDALDataset::Features::Iterator::~Iterator() = default;
8530 :
8531 : const GDALDataset::FeatureLayerPair &
8532 20 : GDALDataset::Features::Iterator::operator*() const
8533 : {
8534 20 : return m_poPrivate->m_oPair;
8535 : }
8536 :
8537 20 : GDALDataset::Features::Iterator &GDALDataset::Features::Iterator::operator++()
8538 : {
8539 40 : m_poPrivate->m_oPair.feature.reset(m_poPrivate->m_poDS->GetNextFeature(
8540 20 : &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8541 20 : m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8542 20 : return *this;
8543 : }
8544 :
8545 22 : bool GDALDataset::Features::Iterator::operator!=(const Iterator &it) const
8546 : {
8547 22 : return m_poPrivate->m_bEOF != it.m_poPrivate->m_bEOF;
8548 : }
8549 :
8550 : /************************************************************************/
8551 : /* GetFeatures() */
8552 : /************************************************************************/
8553 :
8554 : /** Function that return an iterable object over features in the dataset
8555 : * layer.
8556 : *
8557 : * This is a C++ iterator friendly version of GetNextFeature().
8558 : *
8559 : * Using this iterator for standard range-based loops is safe, but
8560 : * due to implementation limitations, you shouldn't try to access
8561 : * (dereference) more than one iterator step at a time, since the
8562 : * FeatureLayerPair reference which is returned is reused.
8563 : *
8564 : * Typical use is:
8565 : * \code{.cpp}
8566 : * for( auto&& oFeatureLayerPair: poDS->GetFeatures() )
8567 : * {
8568 : * std::cout << "Feature of layer " <<
8569 : * oFeatureLayerPair.layer->GetName() << std::endl;
8570 : * oFeatureLayerPair.feature->DumpReadable();
8571 : * }
8572 : * \endcode
8573 : *
8574 : * @see GetNextFeature()
8575 : *
8576 : * @since GDAL 2.3
8577 : */
8578 2 : GDALDataset::Features GDALDataset::GetFeatures()
8579 : {
8580 2 : return Features(this);
8581 : }
8582 :
8583 : /************************************************************************/
8584 : /* begin() */
8585 : /************************************************************************/
8586 :
8587 : /**
8588 : \brief Return beginning of feature iterator.
8589 :
8590 : @since GDAL 2.3
8591 : */
8592 :
8593 2 : const GDALDataset::Features::Iterator GDALDataset::Features::begin() const
8594 : {
8595 2 : return {m_poSelf, true};
8596 : }
8597 :
8598 : /************************************************************************/
8599 : /* end() */
8600 : /************************************************************************/
8601 :
8602 : /**
8603 : \brief Return end of feature iterator.
8604 :
8605 : @since GDAL 2.3
8606 : */
8607 :
8608 2 : const GDALDataset::Features::Iterator GDALDataset::Features::end() const
8609 : {
8610 2 : return {m_poSelf, false};
8611 : }
8612 :
8613 : /************************************************************************/
8614 : /* GDALDataset::Layers::Iterator::Private */
8615 : /************************************************************************/
8616 :
8617 : struct GDALDataset::Layers::Iterator::Private
8618 : {
8619 : OGRLayer *m_poLayer = nullptr;
8620 : int m_iCurLayer = 0;
8621 : int m_nLayerCount = 0;
8622 : GDALDataset *m_poDS = nullptr;
8623 : };
8624 :
8625 2 : GDALDataset::Layers::Iterator::Iterator() : m_poPrivate(new Private())
8626 : {
8627 2 : }
8628 :
8629 : // False positive of cppcheck 1.72
8630 : // cppcheck-suppress uninitMemberVar
8631 9 : GDALDataset::Layers::Iterator::Iterator(const Iterator &oOther)
8632 9 : : m_poPrivate(new Private(*(oOther.m_poPrivate)))
8633 : {
8634 9 : }
8635 :
8636 5 : GDALDataset::Layers::Iterator::Iterator(Iterator &&oOther) noexcept
8637 5 : : m_poPrivate(std::move(oOther.m_poPrivate))
8638 : {
8639 5 : }
8640 :
8641 16 : GDALDataset::Layers::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8642 16 : : m_poPrivate(new Private())
8643 : {
8644 16 : m_poPrivate->m_poDS = poDS;
8645 16 : m_poPrivate->m_nLayerCount = poDS->GetLayerCount();
8646 16 : if (bStart)
8647 : {
8648 9 : if (m_poPrivate->m_nLayerCount)
8649 8 : m_poPrivate->m_poLayer = poDS->GetLayer(0);
8650 : }
8651 : else
8652 : {
8653 7 : m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;
8654 : }
8655 16 : }
8656 :
8657 : GDALDataset::Layers::Iterator::~Iterator() = default;
8658 :
8659 : // False positive of cppcheck 1.72
8660 : // cppcheck-suppress operatorEqVarError
8661 : GDALDataset::Layers::Iterator &
8662 1 : GDALDataset::Layers::Iterator::operator=(const Iterator &oOther)
8663 : {
8664 1 : *m_poPrivate = *oOther.m_poPrivate;
8665 1 : return *this;
8666 : }
8667 :
8668 1 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator=(
8669 : GDALDataset::Layers::Iterator &&oOther) noexcept
8670 : {
8671 1 : m_poPrivate = std::move(oOther.m_poPrivate);
8672 1 : return *this;
8673 : }
8674 :
8675 11 : OGRLayer *GDALDataset::Layers::Iterator::operator*() const
8676 : {
8677 11 : return m_poPrivate->m_poLayer;
8678 : }
8679 :
8680 11 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator++()
8681 : {
8682 11 : m_poPrivate->m_iCurLayer++;
8683 11 : if (m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount)
8684 : {
8685 7 : m_poPrivate->m_poLayer =
8686 7 : m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);
8687 : }
8688 : else
8689 : {
8690 4 : m_poPrivate->m_poLayer = nullptr;
8691 : }
8692 11 : return *this;
8693 : }
8694 :
8695 2 : GDALDataset::Layers::Iterator GDALDataset::Layers::Iterator::operator++(int)
8696 : {
8697 2 : GDALDataset::Layers::Iterator temp = *this;
8698 2 : ++(*this);
8699 2 : return temp;
8700 : }
8701 :
8702 12 : bool GDALDataset::Layers::Iterator::operator!=(const Iterator &it) const
8703 : {
8704 12 : return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;
8705 : }
8706 :
8707 : /************************************************************************/
8708 : /* GetLayers() */
8709 : /************************************************************************/
8710 :
8711 : /** Function that returns an iterable object over layers in the dataset.
8712 : *
8713 : * This is a C++ iterator friendly version of GetLayer().
8714 : *
8715 : * Typical use is:
8716 : * \code{.cpp}
8717 : * for( auto&& poLayer: poDS->GetLayers() )
8718 : * {
8719 : * std::cout << "Layer << poLayer->GetName() << std::endl;
8720 : * }
8721 : * \endcode
8722 : *
8723 : * @see GetLayer()
8724 : *
8725 : * @since GDAL 2.3
8726 : */
8727 12 : GDALDataset::Layers GDALDataset::GetLayers()
8728 : {
8729 12 : return Layers(this);
8730 : }
8731 :
8732 : /************************************************************************/
8733 : /* begin() */
8734 : /************************************************************************/
8735 :
8736 : /**
8737 : \brief Return beginning of layer iterator.
8738 :
8739 : @since GDAL 2.3
8740 : */
8741 :
8742 9 : GDALDataset::Layers::Iterator GDALDataset::Layers::begin() const
8743 : {
8744 9 : return {m_poSelf, true};
8745 : }
8746 :
8747 : /************************************************************************/
8748 : /* end() */
8749 : /************************************************************************/
8750 :
8751 : /**
8752 : \brief Return end of layer iterator.
8753 :
8754 : @since GDAL 2.3
8755 : */
8756 :
8757 7 : GDALDataset::Layers::Iterator GDALDataset::Layers::end() const
8758 : {
8759 7 : return {m_poSelf, false};
8760 : }
8761 :
8762 : /************************************************************************/
8763 : /* size() */
8764 : /************************************************************************/
8765 :
8766 : /**
8767 : \brief Get the number of layers in this dataset.
8768 :
8769 : @return layer count.
8770 :
8771 : @since GDAL 2.3
8772 : */
8773 :
8774 1 : size_t GDALDataset::Layers::size() const
8775 : {
8776 1 : return static_cast<size_t>(m_poSelf->GetLayerCount());
8777 : }
8778 :
8779 : /************************************************************************/
8780 : /* operator[]() */
8781 : /************************************************************************/
8782 : /**
8783 : \brief Fetch a layer by index.
8784 :
8785 : The returned layer remains owned by the
8786 : GDALDataset and should not be deleted by the application.
8787 :
8788 : @param iLayer a layer number between 0 and size()-1.
8789 :
8790 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
8791 :
8792 : @since GDAL 2.3
8793 : */
8794 :
8795 9 : OGRLayer *GDALDataset::Layers::operator[](int iLayer)
8796 : {
8797 9 : return m_poSelf->GetLayer(iLayer);
8798 : }
8799 :
8800 : /************************************************************************/
8801 : /* operator[]() */
8802 : /************************************************************************/
8803 : /**
8804 : \brief Fetch a layer by index.
8805 :
8806 : The returned layer remains owned by the
8807 : GDALDataset and should not be deleted by the application.
8808 :
8809 : @param iLayer a layer number between 0 and size()-1.
8810 :
8811 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
8812 :
8813 : @since GDAL 2.3
8814 : */
8815 :
8816 1 : OGRLayer *GDALDataset::Layers::operator[](size_t iLayer)
8817 : {
8818 1 : return m_poSelf->GetLayer(static_cast<int>(iLayer));
8819 : }
8820 :
8821 : /************************************************************************/
8822 : /* operator[]() */
8823 : /************************************************************************/
8824 : /**
8825 : \brief Fetch a layer by name.
8826 :
8827 : The returned layer remains owned by the
8828 : GDALDataset and should not be deleted by the application.
8829 :
8830 : @param pszLayerName layer name
8831 :
8832 : @return the layer, or nullptr if pszLayerName does not match with a layer
8833 :
8834 : @since GDAL 2.3
8835 : */
8836 :
8837 1 : OGRLayer *GDALDataset::Layers::operator[](const char *pszLayerName)
8838 : {
8839 1 : return m_poSelf->GetLayerByName(pszLayerName);
8840 : }
8841 :
8842 : /************************************************************************/
8843 : /* GDALDataset::Bands::Iterator::Private */
8844 : /************************************************************************/
8845 :
8846 : struct GDALDataset::Bands::Iterator::Private
8847 : {
8848 : GDALRasterBand *m_poBand = nullptr;
8849 : int m_iCurBand = 0;
8850 : int m_nBandCount = 0;
8851 : GDALDataset *m_poDS = nullptr;
8852 : };
8853 :
8854 6 : GDALDataset::Bands::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8855 6 : : m_poPrivate(new GDALDataset::Bands::Iterator::Private())
8856 : {
8857 6 : m_poPrivate->m_poDS = poDS;
8858 6 : m_poPrivate->m_nBandCount = poDS->GetRasterCount();
8859 6 : if (bStart)
8860 : {
8861 3 : if (m_poPrivate->m_nBandCount)
8862 3 : m_poPrivate->m_poBand = poDS->GetRasterBand(1);
8863 : }
8864 : else
8865 : {
8866 3 : m_poPrivate->m_iCurBand = m_poPrivate->m_nBandCount;
8867 : }
8868 6 : }
8869 :
8870 : GDALDataset::Bands::Iterator::~Iterator() = default;
8871 :
8872 5 : GDALRasterBand *GDALDataset::Bands::Iterator::operator*()
8873 : {
8874 5 : return m_poPrivate->m_poBand;
8875 : }
8876 :
8877 3 : GDALDataset::Bands::Iterator &GDALDataset::Bands::Iterator::operator++()
8878 : {
8879 3 : m_poPrivate->m_iCurBand++;
8880 3 : if (m_poPrivate->m_iCurBand < m_poPrivate->m_nBandCount)
8881 : {
8882 2 : m_poPrivate->m_poBand =
8883 2 : m_poPrivate->m_poDS->GetRasterBand(1 + m_poPrivate->m_iCurBand);
8884 : }
8885 : else
8886 : {
8887 1 : m_poPrivate->m_poBand = nullptr;
8888 : }
8889 3 : return *this;
8890 : }
8891 :
8892 6 : bool GDALDataset::Bands::Iterator::operator!=(const Iterator &it) const
8893 : {
8894 6 : return m_poPrivate->m_iCurBand != it.m_poPrivate->m_iCurBand;
8895 : }
8896 :
8897 : /************************************************************************/
8898 : /* GetBands() */
8899 : /************************************************************************/
8900 :
8901 : /** Function that returns an iterable object over GDALRasterBand in the dataset.
8902 : *
8903 : * This is a C++ iterator friendly version of GetRasterBand().
8904 : *
8905 : * Typical use is:
8906 : * \code{.cpp}
8907 : * for( auto&& poBand: poDS->GetBands() )
8908 : * {
8909 : * std::cout << "Band << poBand->GetDescription() << std::endl;
8910 : * }
8911 : * \endcode
8912 : *
8913 : * @see GetRasterBand()
8914 : *
8915 : * @since GDAL 2.3
8916 : */
8917 7 : GDALDataset::Bands GDALDataset::GetBands()
8918 : {
8919 7 : return Bands(this);
8920 : }
8921 :
8922 : /************************************************************************/
8923 : /* begin() */
8924 : /************************************************************************/
8925 :
8926 : /**
8927 : \brief Return beginning of band iterator.
8928 :
8929 : @since GDAL 2.3
8930 : */
8931 :
8932 3 : const GDALDataset::Bands::Iterator GDALDataset::Bands::begin() const
8933 : {
8934 3 : return {m_poSelf, true};
8935 : }
8936 :
8937 : /************************************************************************/
8938 : /* end() */
8939 : /************************************************************************/
8940 :
8941 : /**
8942 : \brief Return end of band iterator.
8943 :
8944 : @since GDAL 2.3
8945 : */
8946 :
8947 3 : const GDALDataset::Bands::Iterator GDALDataset::Bands::end() const
8948 : {
8949 3 : return {m_poSelf, false};
8950 : }
8951 :
8952 : /************************************************************************/
8953 : /* size() */
8954 : /************************************************************************/
8955 :
8956 : /**
8957 : \brief Get the number of raster bands in this dataset.
8958 :
8959 : @return raster band count.
8960 :
8961 : @since GDAL 2.3
8962 : */
8963 :
8964 2 : size_t GDALDataset::Bands::size() const
8965 : {
8966 2 : return static_cast<size_t>(m_poSelf->GetRasterCount());
8967 : }
8968 :
8969 : /************************************************************************/
8970 : /* operator[]() */
8971 : /************************************************************************/
8972 : /**
8973 : \brief Fetch a raster band by index.
8974 :
8975 : The returned band remains owned by the
8976 : GDALDataset and should not be deleted by the application.
8977 :
8978 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
8979 : consistent with the conventions of C/C++, i.e. starting at 0.
8980 :
8981 : @param iBand a band index between 0 and size()-1.
8982 :
8983 : @return the band, or nullptr if iBand is out of range or an error occurs.
8984 :
8985 : @since GDAL 2.3
8986 : */
8987 :
8988 1 : GDALRasterBand *GDALDataset::Bands::operator[](int iBand)
8989 : {
8990 1 : return m_poSelf->GetRasterBand(1 + iBand);
8991 : }
8992 :
8993 : /************************************************************************/
8994 : /* operator[]() */
8995 : /************************************************************************/
8996 :
8997 : /**
8998 : \brief Fetch a raster band by index.
8999 :
9000 : The returned band remains owned by the
9001 : GDALDataset and should not be deleted by the application.
9002 :
9003 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9004 : consistent with the conventions of C/C++, i.e. starting at 0.
9005 :
9006 : @param iBand a band index between 0 and size()-1.
9007 :
9008 : @return the band, or nullptr if iBand is out of range or an error occurs.
9009 :
9010 : @since GDAL 2.3
9011 : */
9012 :
9013 1 : GDALRasterBand *GDALDataset::Bands::operator[](size_t iBand)
9014 : {
9015 1 : return m_poSelf->GetRasterBand(1 + static_cast<int>(iBand));
9016 : }
9017 :
9018 : /************************************************************************/
9019 : /* GetRootGroup() */
9020 : /************************************************************************/
9021 :
9022 : /**
9023 : \brief Return the root GDALGroup of this dataset.
9024 :
9025 : Only valid for multidimensional datasets.
9026 :
9027 : This is the same as the C function GDALDatasetGetRootGroup().
9028 :
9029 : @since GDAL 3.1
9030 : */
9031 :
9032 2527 : std::shared_ptr<GDALGroup> GDALDataset::GetRootGroup() const
9033 : {
9034 2527 : return nullptr;
9035 : }
9036 :
9037 : /************************************************************************/
9038 : /* GetRawBinaryLayout() */
9039 : /************************************************************************/
9040 :
9041 : //! @cond Doxygen_Suppress
9042 : /**
9043 : \brief Return the layout of a dataset that can be considered as a raw binary
9044 : format.
9045 :
9046 : @param sLayout Structure that will be set if the dataset is a raw binary one.
9047 : @return true if the dataset is a raw binary one.
9048 : @since GDAL 3.1
9049 : */
9050 :
9051 0 : bool GDALDataset::GetRawBinaryLayout(RawBinaryLayout &sLayout)
9052 : {
9053 0 : CPL_IGNORE_RET_VAL(sLayout);
9054 0 : return false;
9055 : }
9056 :
9057 : //! @endcond
9058 :
9059 : /************************************************************************/
9060 : /* ClearStatistics() */
9061 : /************************************************************************/
9062 :
9063 : /**
9064 : \brief Clear statistics
9065 :
9066 : Only implemented for now in PAM supported datasets
9067 :
9068 : This is the same as the C function GDALDatasetClearStatistics().
9069 :
9070 : @since GDAL 3.2
9071 : */
9072 :
9073 4 : void GDALDataset::ClearStatistics()
9074 : {
9075 8 : auto poRootGroup = GetRootGroup();
9076 4 : if (poRootGroup)
9077 1 : poRootGroup->ClearStatistics();
9078 4 : }
9079 :
9080 : /************************************************************************/
9081 : /* GDALDatasetClearStatistics() */
9082 : /************************************************************************/
9083 :
9084 : /**
9085 : \brief Clear statistics
9086 :
9087 : This is the same as the C++ method GDALDataset::ClearStatistics().
9088 :
9089 : @since GDAL 3.2
9090 : */
9091 :
9092 2 : void GDALDatasetClearStatistics(GDALDatasetH hDS)
9093 : {
9094 2 : VALIDATE_POINTER0(hDS, __func__);
9095 2 : GDALDataset::FromHandle(hDS)->ClearStatistics();
9096 : }
9097 :
9098 : /************************************************************************/
9099 : /* GetFieldDomainNames() */
9100 : /************************************************************************/
9101 :
9102 : /** Returns a list of the names of all field domains stored in the dataset.
9103 : *
9104 : * @note The default implementation assumes that drivers fully populate
9105 : * m_oMapFieldDomains when opening a dataset. If this assumption is incorrect
9106 : * then a specialized implementation of GetFieldDomainNames() must be
9107 : * implemented.
9108 : *
9109 : * @param papszOptions Driver specific options determining how attributes
9110 : * should be retrieved. Pass nullptr for default behavior.
9111 : *
9112 : * @return list of field domain names
9113 : * @since GDAL 3.5
9114 : */
9115 : std::vector<std::string>
9116 32 : GDALDataset::GetFieldDomainNames(CPL_UNUSED CSLConstList papszOptions) const
9117 : {
9118 :
9119 32 : std::vector<std::string> names;
9120 32 : names.reserve(m_oMapFieldDomains.size());
9121 44 : for (const auto &it : m_oMapFieldDomains)
9122 : {
9123 12 : names.emplace_back(it.first);
9124 : }
9125 32 : return names;
9126 : }
9127 :
9128 : /************************************************************************/
9129 : /* GDALDatasetGetFieldDomainNames() */
9130 : /************************************************************************/
9131 :
9132 : /** Returns a list of the names of all field domains stored in the dataset.
9133 : *
9134 : * This is the same as the C++ method GDALDataset::GetFieldDomainNames().
9135 : *
9136 : * @param hDS Dataset handle.
9137 : * @param papszOptions Driver specific options determining how attributes
9138 : * should be retrieved. Pass nullptr for default behavior.
9139 : *
9140 : * @return list of field domain names, to be freed with CSLDestroy()
9141 : * @since GDAL 3.5
9142 : */
9143 33 : char **GDALDatasetGetFieldDomainNames(GDALDatasetH hDS,
9144 : CSLConstList papszOptions)
9145 : {
9146 33 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9147 : auto names =
9148 66 : GDALDataset::FromHandle(hDS)->GetFieldDomainNames(papszOptions);
9149 66 : CPLStringList res;
9150 141 : for (const auto &name : names)
9151 : {
9152 108 : res.AddString(name.c_str());
9153 : }
9154 33 : return res.StealList();
9155 : }
9156 :
9157 : /************************************************************************/
9158 : /* GetFieldDomain() */
9159 : /************************************************************************/
9160 :
9161 : /** Get a field domain from its name.
9162 : *
9163 : * @return the field domain, or nullptr if not found.
9164 : * @since GDAL 3.3
9165 : */
9166 291 : const OGRFieldDomain *GDALDataset::GetFieldDomain(const std::string &name) const
9167 : {
9168 291 : const auto iter = m_oMapFieldDomains.find(name);
9169 291 : if (iter == m_oMapFieldDomains.end())
9170 126 : return nullptr;
9171 165 : return iter->second.get();
9172 : }
9173 :
9174 : /************************************************************************/
9175 : /* GDALDatasetGetFieldDomain() */
9176 : /************************************************************************/
9177 :
9178 : /** Get a field domain from its name.
9179 : *
9180 : * This is the same as the C++ method GDALDataset::GetFieldDomain().
9181 : *
9182 : * @param hDS Dataset handle.
9183 : * @param pszName Name of field domain.
9184 : * @return the field domain (ownership remains to the dataset), or nullptr if
9185 : * not found.
9186 : * @since GDAL 3.3
9187 : */
9188 117 : OGRFieldDomainH GDALDatasetGetFieldDomain(GDALDatasetH hDS, const char *pszName)
9189 : {
9190 117 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9191 117 : VALIDATE_POINTER1(pszName, __func__, nullptr);
9192 117 : return OGRFieldDomain::ToHandle(const_cast<OGRFieldDomain *>(
9193 117 : GDALDataset::FromHandle(hDS)->GetFieldDomain(pszName)));
9194 : }
9195 :
9196 : /************************************************************************/
9197 : /* AddFieldDomain() */
9198 : /************************************************************************/
9199 :
9200 : /** Add a field domain to the dataset.
9201 : *
9202 : * Only a few drivers will support this operation, and some of them might only
9203 : * support it only for some types of field domains.
9204 : * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9205 : * support this operation. A dataset having at least some support for this
9206 : * operation should report the ODsCAddFieldDomain dataset capability.
9207 : *
9208 : * Anticipated failures will not be emitted through the CPLError()
9209 : * infrastructure, but will be reported in the failureReason output parameter.
9210 : *
9211 : * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9212 : * default implementation of GetFieldDomainNames() to work correctly, or
9213 : * alternatively a specialized implementation of GetFieldDomainNames() should be
9214 : * implemented.
9215 : *
9216 : * @param domain The domain definition.
9217 : * @param failureReason Output parameter. Will contain an error message if
9218 : * an error occurs.
9219 : * @return true in case of success.
9220 : * @since GDAL 3.3
9221 : */
9222 0 : bool GDALDataset::AddFieldDomain(
9223 : CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9224 : std::string &failureReason)
9225 : {
9226 0 : failureReason = "AddFieldDomain not supported by this driver";
9227 0 : return false;
9228 : }
9229 :
9230 : /************************************************************************/
9231 : /* GDALDatasetAddFieldDomain() */
9232 : /************************************************************************/
9233 :
9234 : /** Add a field domain to the dataset.
9235 : *
9236 : * Only a few drivers will support this operation, and some of them might only
9237 : * support it only for some types of field domains.
9238 : * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9239 : * support this operation. A dataset having at least some support for this
9240 : * operation should report the ODsCAddFieldDomain dataset capability.
9241 : *
9242 : * Anticipated failures will not be emitted through the CPLError()
9243 : * infrastructure, but will be reported in the ppszFailureReason output
9244 : * parameter.
9245 : *
9246 : * @param hDS Dataset handle.
9247 : * @param hFieldDomain The domain definition. Contrary to the C++ version,
9248 : * the passed object is copied.
9249 : * @param ppszFailureReason Output parameter. Will contain an error message if
9250 : * an error occurs (*ppszFailureReason to be freed
9251 : * with CPLFree). May be NULL.
9252 : * @return true in case of success.
9253 : * @since GDAL 3.3
9254 : */
9255 35 : bool GDALDatasetAddFieldDomain(GDALDatasetH hDS, OGRFieldDomainH hFieldDomain,
9256 : char **ppszFailureReason)
9257 : {
9258 35 : VALIDATE_POINTER1(hDS, __func__, false);
9259 35 : VALIDATE_POINTER1(hFieldDomain, __func__, false);
9260 : auto poDomain = std::unique_ptr<OGRFieldDomain>(
9261 70 : OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9262 35 : if (poDomain == nullptr)
9263 0 : return false;
9264 35 : std::string failureReason;
9265 70 : const bool bRet = GDALDataset::FromHandle(hDS)->AddFieldDomain(
9266 35 : std::move(poDomain), failureReason);
9267 35 : if (ppszFailureReason)
9268 : {
9269 0 : *ppszFailureReason =
9270 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9271 : }
9272 35 : return bRet;
9273 : }
9274 :
9275 : /************************************************************************/
9276 : /* DeleteFieldDomain() */
9277 : /************************************************************************/
9278 :
9279 : /** Removes a field domain from the dataset.
9280 : *
9281 : * Only a few drivers will support this operation.
9282 : *
9283 : * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9284 : * support this operation. A dataset having at least some support for this
9285 : * operation should report the ODsCDeleteFieldDomain dataset capability.
9286 : *
9287 : * Anticipated failures will not be emitted through the CPLError()
9288 : * infrastructure, but will be reported in the failureReason output parameter.
9289 : *
9290 : * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9291 : * default implementation of GetFieldDomainNames() to work correctly, or
9292 : * alternatively a specialized implementation of GetFieldDomainNames() should be
9293 : * implemented.
9294 : *
9295 : * @param name The domain name.
9296 : * @param failureReason Output parameter. Will contain an error message if
9297 : * an error occurs.
9298 : * @return true in case of success.
9299 : * @since GDAL 3.5
9300 : */
9301 0 : bool GDALDataset::DeleteFieldDomain(CPL_UNUSED const std::string &name,
9302 : std::string &failureReason)
9303 : {
9304 0 : failureReason = "DeleteFieldDomain not supported by this driver";
9305 0 : return false;
9306 : }
9307 :
9308 : /************************************************************************/
9309 : /* GDALDatasetDeleteFieldDomain() */
9310 : /************************************************************************/
9311 :
9312 : /** Removes a field domain from the dataset.
9313 : *
9314 : * Only a few drivers will support this operation.
9315 : *
9316 : * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9317 : * support this operation. A dataset having at least some support for this
9318 : * operation should report the ODsCDeleteFieldDomain dataset capability.
9319 : *
9320 : * Anticipated failures will not be emitted through the CPLError()
9321 : * infrastructure, but will be reported in the ppszFailureReason output
9322 : * parameter.
9323 : *
9324 : * @param hDS Dataset handle.
9325 : * @param pszName The domain name.
9326 : * @param ppszFailureReason Output parameter. Will contain an error message if
9327 : * an error occurs (*ppszFailureReason to be freed
9328 : * with CPLFree). May be NULL.
9329 : * @return true in case of success.
9330 : * @since GDAL 3.3
9331 : */
9332 10 : bool GDALDatasetDeleteFieldDomain(GDALDatasetH hDS, const char *pszName,
9333 : char **ppszFailureReason)
9334 : {
9335 10 : VALIDATE_POINTER1(hDS, __func__, false);
9336 10 : VALIDATE_POINTER1(pszName, __func__, false);
9337 10 : std::string failureReason;
9338 : const bool bRet =
9339 10 : GDALDataset::FromHandle(hDS)->DeleteFieldDomain(pszName, failureReason);
9340 10 : if (ppszFailureReason)
9341 : {
9342 0 : *ppszFailureReason =
9343 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9344 : }
9345 10 : return bRet;
9346 : }
9347 :
9348 : /************************************************************************/
9349 : /* UpdateFieldDomain() */
9350 : /************************************************************************/
9351 :
9352 : /** Updates an existing field domain by replacing its definition.
9353 : *
9354 : * The existing field domain with matching name will be replaced.
9355 : *
9356 : * Only a few drivers will support this operation, and some of them might only
9357 : * support it only for some types of field domains.
9358 : * At the time of writing (GDAL 3.5), only the Memory driver
9359 : * supports this operation. A dataset having at least some support for this
9360 : * operation should report the ODsCUpdateFieldDomain dataset capability.
9361 : *
9362 : * Anticipated failures will not be emitted through the CPLError()
9363 : * infrastructure, but will be reported in the failureReason output parameter.
9364 : *
9365 : * @param domain The domain definition.
9366 : * @param failureReason Output parameter. Will contain an error message if
9367 : * an error occurs.
9368 : * @return true in case of success.
9369 : * @since GDAL 3.5
9370 : */
9371 0 : bool GDALDataset::UpdateFieldDomain(
9372 : CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9373 : std::string &failureReason)
9374 : {
9375 0 : failureReason = "UpdateFieldDomain not supported by this driver";
9376 0 : return false;
9377 : }
9378 :
9379 : /************************************************************************/
9380 : /* GDALDatasetUpdateFieldDomain() */
9381 : /************************************************************************/
9382 :
9383 : /** Updates an existing field domain by replacing its definition.
9384 : *
9385 : * The existing field domain with matching name will be replaced.
9386 : *
9387 : * Only a few drivers will support this operation, and some of them might only
9388 : * support it only for some types of field domains.
9389 : * At the time of writing (GDAL 3.5), only the Memory driver
9390 : * supports this operation. A dataset having at least some support for this
9391 : * operation should report the ODsCUpdateFieldDomain dataset capability.
9392 : *
9393 : * Anticipated failures will not be emitted through the CPLError()
9394 : * infrastructure, but will be reported in the failureReason output parameter.
9395 : *
9396 : * @param hDS Dataset handle.
9397 : * @param hFieldDomain The domain definition. Contrary to the C++ version,
9398 : * the passed object is copied.
9399 : * @param ppszFailureReason Output parameter. Will contain an error message if
9400 : * an error occurs (*ppszFailureReason to be freed
9401 : * with CPLFree). May be NULL.
9402 : * @return true in case of success.
9403 : * @since GDAL 3.5
9404 : */
9405 5 : bool GDALDatasetUpdateFieldDomain(GDALDatasetH hDS,
9406 : OGRFieldDomainH hFieldDomain,
9407 : char **ppszFailureReason)
9408 : {
9409 5 : VALIDATE_POINTER1(hDS, __func__, false);
9410 5 : VALIDATE_POINTER1(hFieldDomain, __func__, false);
9411 : auto poDomain = std::unique_ptr<OGRFieldDomain>(
9412 10 : OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9413 5 : if (poDomain == nullptr)
9414 0 : return false;
9415 5 : std::string failureReason;
9416 10 : const bool bRet = GDALDataset::FromHandle(hDS)->UpdateFieldDomain(
9417 5 : std::move(poDomain), failureReason);
9418 5 : if (ppszFailureReason)
9419 : {
9420 0 : *ppszFailureReason =
9421 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9422 : }
9423 5 : return bRet;
9424 : }
9425 :
9426 : /************************************************************************/
9427 : /* GetRelationshipNames() */
9428 : /************************************************************************/
9429 :
9430 : /** Returns a list of the names of all relationships stored in the dataset.
9431 : *
9432 : * @param papszOptions Driver specific options determining how relationships
9433 : * should be retrieved. Pass nullptr for default behavior.
9434 : *
9435 : * @return list of relationship names
9436 : * @since GDAL 3.6
9437 : */
9438 : std::vector<std::string>
9439 46 : GDALDataset::GetRelationshipNames(CPL_UNUSED CSLConstList papszOptions) const
9440 : {
9441 46 : return {};
9442 : }
9443 :
9444 : /************************************************************************/
9445 : /* GDALDatasetGetRelationshipNames() */
9446 : /************************************************************************/
9447 :
9448 : /** Returns a list of the names of all relationships stored in the dataset.
9449 : *
9450 : * This is the same as the C++ method GDALDataset::GetRelationshipNames().
9451 : *
9452 : * @param hDS Dataset handle.
9453 : * @param papszOptions Driver specific options determining how relationships
9454 : * should be retrieved. Pass nullptr for default behavior.
9455 : *
9456 : * @return list of relationship names, to be freed with CSLDestroy()
9457 : * @since GDAL 3.6
9458 : */
9459 41 : char **GDALDatasetGetRelationshipNames(GDALDatasetH hDS,
9460 : CSLConstList papszOptions)
9461 : {
9462 41 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9463 : auto names =
9464 82 : GDALDataset::FromHandle(hDS)->GetRelationshipNames(papszOptions);
9465 82 : CPLStringList res;
9466 130 : for (const auto &name : names)
9467 : {
9468 89 : res.AddString(name.c_str());
9469 : }
9470 41 : return res.StealList();
9471 : }
9472 :
9473 : /************************************************************************/
9474 : /* GetRelationship() */
9475 : /************************************************************************/
9476 :
9477 : /** Get a relationship from its name.
9478 : *
9479 : * @return the relationship, or nullptr if not found.
9480 : * @since GDAL 3.6
9481 : */
9482 : const GDALRelationship *
9483 0 : GDALDataset::GetRelationship(CPL_UNUSED const std::string &name) const
9484 : {
9485 0 : return nullptr;
9486 : }
9487 :
9488 : /************************************************************************/
9489 : /* GDALDatasetGetRelationship() */
9490 : /************************************************************************/
9491 :
9492 : /** Get a relationship from its name.
9493 : *
9494 : * This is the same as the C++ method GDALDataset::GetRelationship().
9495 : *
9496 : * @param hDS Dataset handle.
9497 : * @param pszName Name of relationship.
9498 : * @return the relationship (ownership remains to the dataset), or nullptr if
9499 : * not found.
9500 : * @since GDAL 3.6
9501 : */
9502 50 : GDALRelationshipH GDALDatasetGetRelationship(GDALDatasetH hDS,
9503 : const char *pszName)
9504 : {
9505 50 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9506 50 : VALIDATE_POINTER1(pszName, __func__, nullptr);
9507 50 : return GDALRelationship::ToHandle(const_cast<GDALRelationship *>(
9508 50 : GDALDataset::FromHandle(hDS)->GetRelationship(pszName)));
9509 : }
9510 :
9511 : /************************************************************************/
9512 : /* AddRelationship() */
9513 : /************************************************************************/
9514 :
9515 : /** Add a relationship to the dataset.
9516 : *
9517 : * Only a few drivers will support this operation, and some of them might only
9518 : * support it only for some types of relationships.
9519 : *
9520 : * A dataset having at least some support for this
9521 : * operation should report the GDsCAddRelationship dataset capability.
9522 : *
9523 : * Anticipated failures will not be emitted through the CPLError()
9524 : * infrastructure, but will be reported in the failureReason output parameter.
9525 : *
9526 : * When adding a many-to-many relationship
9527 : * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9528 : * mapping table name (see GDALRelationship::GetMappingTableName) to instruct
9529 : * the driver to create an appropriately named and structured mapping table.
9530 : * Some dataset formats require particular naming conventions and field
9531 : * structures for the mapping table, and delegating the construction of the
9532 : * mapping table to the driver will avoid these pitfalls.
9533 : *
9534 : * @param relationship The relationship definition.
9535 : * @param failureReason Output parameter. Will contain an error message if
9536 : * an error occurs.
9537 : * @return true in case of success.
9538 : * @since GDAL 3.6
9539 : */
9540 0 : bool GDALDataset::AddRelationship(
9541 : CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9542 : std::string &failureReason)
9543 : {
9544 0 : failureReason = "AddRelationship not supported by this driver";
9545 0 : return false;
9546 : }
9547 :
9548 : /************************************************************************/
9549 : /* GDALDatasetAddRelationship() */
9550 : /************************************************************************/
9551 :
9552 : /** Add a relationship to the dataset.
9553 : *
9554 : * Only a few drivers will support this operation, and some of them might only
9555 : * support it only for some types of relationships.
9556 : *
9557 : * A dataset having at least some support for this
9558 : * operation should report the GDsCAddRelationship dataset capability.
9559 : *
9560 : * Anticipated failures will not be emitted through the CPLError()
9561 : * infrastructure, but will be reported in the failureReason output parameter.
9562 : *
9563 : * When adding a many-to-many relationship
9564 : * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9565 : * mapping table name (see GDALRelationshipGetMappingTableName) to instruct the
9566 : * driver to create an appropriately named and structured mapping table. Some
9567 : * dataset formats require particular naming conventions and field structures
9568 : * for the mapping table, and delegating the construction of the mapping table
9569 : * to the driver will avoid these pitfalls.
9570 : *
9571 : * @param hDS Dataset handle.
9572 : * @param hRelationship The relationship definition. Contrary to the C++
9573 : * version, the passed object is copied.
9574 : * @param ppszFailureReason Output parameter. Will contain an error message if
9575 : * an error occurs (*ppszFailureReason to be freed
9576 : * with CPLFree). May be NULL.
9577 : * @return true in case of success.
9578 : * @since GDAL 3.6
9579 : */
9580 42 : bool GDALDatasetAddRelationship(GDALDatasetH hDS,
9581 : GDALRelationshipH hRelationship,
9582 : char **ppszFailureReason)
9583 : {
9584 42 : VALIDATE_POINTER1(hDS, __func__, false);
9585 42 : VALIDATE_POINTER1(hRelationship, __func__, false);
9586 : std::unique_ptr<GDALRelationship> poRelationship(
9587 84 : new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9588 42 : std::string failureReason;
9589 84 : const bool bRet = GDALDataset::FromHandle(hDS)->AddRelationship(
9590 42 : std::move(poRelationship), failureReason);
9591 42 : if (ppszFailureReason)
9592 : {
9593 0 : *ppszFailureReason =
9594 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9595 : }
9596 42 : return bRet;
9597 : }
9598 :
9599 : /************************************************************************/
9600 : /* DeleteRelationship() */
9601 : /************************************************************************/
9602 :
9603 : /** Removes a relationship from the dataset.
9604 : *
9605 : * Only a few drivers will support this operation.
9606 : *
9607 : * A dataset having at least some support for this
9608 : * operation should report the GDsCDeleteRelationship dataset capability.
9609 : *
9610 : * Anticipated failures will not be emitted through the CPLError()
9611 : * infrastructure, but will be reported in the failureReason output parameter.
9612 : *
9613 : * @param name The relationship name.
9614 : * @param failureReason Output parameter. Will contain an error message if
9615 : * an error occurs.
9616 : * @return true in case of success.
9617 : * @since GDAL 3.6
9618 : */
9619 0 : bool GDALDataset::DeleteRelationship(CPL_UNUSED const std::string &name,
9620 : std::string &failureReason)
9621 : {
9622 0 : failureReason = "DeleteRelationship not supported by this driver";
9623 0 : return false;
9624 : }
9625 :
9626 : /************************************************************************/
9627 : /* GDALDatasetDeleteRelationship() */
9628 : /************************************************************************/
9629 :
9630 : /** Removes a relationship from the dataset.
9631 : *
9632 : * Only a few drivers will support this operation.
9633 : *
9634 : * A dataset having at least some support for this
9635 : * operation should report the GDsCDeleteRelationship dataset capability.
9636 : *
9637 : * Anticipated failures will not be emitted through the CPLError()
9638 : * infrastructure, but will be reported in the ppszFailureReason output
9639 : * parameter.
9640 : *
9641 : * @param hDS Dataset handle.
9642 : * @param pszName The relationship name.
9643 : * @param ppszFailureReason Output parameter. Will contain an error message if
9644 : * an error occurs (*ppszFailureReason to be freed
9645 : * with CPLFree). May be NULL.
9646 : * @return true in case of success.
9647 : * @since GDAL 3.6
9648 : */
9649 6 : bool GDALDatasetDeleteRelationship(GDALDatasetH hDS, const char *pszName,
9650 : char **ppszFailureReason)
9651 : {
9652 6 : VALIDATE_POINTER1(hDS, __func__, false);
9653 6 : VALIDATE_POINTER1(pszName, __func__, false);
9654 6 : std::string failureReason;
9655 12 : const bool bRet = GDALDataset::FromHandle(hDS)->DeleteRelationship(
9656 6 : pszName, failureReason);
9657 6 : if (ppszFailureReason)
9658 : {
9659 0 : *ppszFailureReason =
9660 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9661 : }
9662 6 : return bRet;
9663 : }
9664 :
9665 : /************************************************************************/
9666 : /* UpdateRelationship() */
9667 : /************************************************************************/
9668 :
9669 : /** Updates an existing relationship by replacing its definition.
9670 : *
9671 : * The existing relationship with matching name will be replaced.
9672 : *
9673 : * Only a few drivers will support this operation, and some of them might only
9674 : * support it only for some types of relationships.
9675 : * A dataset having at least some support for this
9676 : * operation should report the GDsCUpdateRelationship dataset capability.
9677 : *
9678 : * Anticipated failures will not be emitted through the CPLError()
9679 : * infrastructure, but will be reported in the failureReason output parameter.
9680 : *
9681 : * @param relationship The relationship definition.
9682 : * @param failureReason Output parameter. Will contain an error message if
9683 : * an error occurs.
9684 : * @return true in case of success.
9685 : * @since GDAL 3.6
9686 : */
9687 0 : bool GDALDataset::UpdateRelationship(
9688 : CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9689 : std::string &failureReason)
9690 : {
9691 0 : failureReason = "UpdateRelationship not supported by this driver";
9692 0 : return false;
9693 : }
9694 :
9695 : /************************************************************************/
9696 : /* GDALDatasetUpdateRelationship() */
9697 : /************************************************************************/
9698 :
9699 : /** Updates an existing relationship by replacing its definition.
9700 : *
9701 : * The existing relationship with matching name will be replaced.
9702 : *
9703 : * Only a few drivers will support this operation, and some of them might only
9704 : * support it only for some types of relationships.
9705 : * A dataset having at least some support for this
9706 : * operation should report the GDsCUpdateRelationship dataset capability.
9707 : *
9708 : * Anticipated failures will not be emitted through the CPLError()
9709 : * infrastructure, but will be reported in the failureReason output parameter.
9710 : *
9711 : * @param hDS Dataset handle.
9712 : * @param hRelationship The relationship definition. Contrary to the C++
9713 : * version, the passed object is copied.
9714 : * @param ppszFailureReason Output parameter. Will contain an error message if
9715 : * an error occurs (*ppszFailureReason to be freed
9716 : * with CPLFree). May be NULL.
9717 : * @return true in case of success.
9718 : * @since GDAL 3.5
9719 : */
9720 9 : bool GDALDatasetUpdateRelationship(GDALDatasetH hDS,
9721 : GDALRelationshipH hRelationship,
9722 : char **ppszFailureReason)
9723 : {
9724 9 : VALIDATE_POINTER1(hDS, __func__, false);
9725 9 : VALIDATE_POINTER1(hRelationship, __func__, false);
9726 : std::unique_ptr<GDALRelationship> poRelationship(
9727 18 : new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9728 9 : std::string failureReason;
9729 18 : const bool bRet = GDALDataset::FromHandle(hDS)->UpdateRelationship(
9730 9 : std::move(poRelationship), failureReason);
9731 9 : if (ppszFailureReason)
9732 : {
9733 0 : *ppszFailureReason =
9734 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9735 : }
9736 9 : return bRet;
9737 : }
9738 :
9739 : /************************************************************************/
9740 : /* GDALDatasetSetQueryLoggerFunc() */
9741 : /************************************************************************/
9742 :
9743 : /**
9744 : * Sets the SQL query logger callback.
9745 : *
9746 : * When supported by the driver, the callback will be called with
9747 : * the executed SQL text, the error message, the execution time in milliseconds,
9748 : * the number of records fetched/affected and the client status data.
9749 : *
9750 : * A value of -1 in the execution time or in the number of records indicates
9751 : * that the values are unknown.
9752 : *
9753 : * @param hDS Dataset handle.
9754 : * @param pfnQueryLoggerFunc Callback function
9755 : * @param poQueryLoggerArg Opaque client status data
9756 : * @return true in case of success.
9757 : * @since GDAL 3.7
9758 : */
9759 1 : bool GDALDatasetSetQueryLoggerFunc(GDALDatasetH hDS,
9760 : GDALQueryLoggerFunc pfnQueryLoggerFunc,
9761 : void *poQueryLoggerArg)
9762 : {
9763 1 : VALIDATE_POINTER1(hDS, __func__, false);
9764 2 : return GDALDataset::FromHandle(hDS)->SetQueryLoggerFunc(pfnQueryLoggerFunc,
9765 1 : poQueryLoggerArg);
9766 : }
9767 :
9768 : //! @cond Doxygen_Suppress
9769 :
9770 : /************************************************************************/
9771 : /* SetEnableOverviews() */
9772 : /************************************************************************/
9773 :
9774 7361 : void GDALDataset::SetEnableOverviews(bool bEnable)
9775 : {
9776 7361 : if (m_poPrivate)
9777 : {
9778 7361 : m_poPrivate->m_bOverviewsEnabled = bEnable;
9779 : }
9780 7361 : }
9781 :
9782 : /************************************************************************/
9783 : /* AreOverviewsEnabled() */
9784 : /************************************************************************/
9785 :
9786 1339160 : bool GDALDataset::AreOverviewsEnabled() const
9787 : {
9788 1339160 : return m_poPrivate ? m_poPrivate->m_bOverviewsEnabled : true;
9789 : }
9790 :
9791 : /************************************************************************/
9792 : /* IsAllBands() */
9793 : /************************************************************************/
9794 :
9795 67 : bool GDALDataset::IsAllBands(int nBandCount, const int *panBandList) const
9796 : {
9797 67 : if (nBands != nBandCount)
9798 1 : return false;
9799 66 : if (panBandList)
9800 : {
9801 3 : for (int i = 0; i < nBandCount; ++i)
9802 : {
9803 2 : if (panBandList[i] != i + 1)
9804 1 : return false;
9805 : }
9806 : }
9807 65 : return true;
9808 : }
9809 :
9810 : //! @endcond
9811 :
9812 : /************************************************************************/
9813 : /* GetCompressionFormats() */
9814 : /************************************************************************/
9815 :
9816 : /** Return the compression formats that can be natively obtained for the
9817 : * window of interest and requested bands.
9818 : *
9819 : * For example, a tiled dataset may be able to return data in a compressed
9820 : * format if the window of interest matches exactly a tile. For some formats,
9821 : * drivers may also be able to merge several tiles together (not currently
9822 : * implemented though).
9823 : *
9824 : * Each format string is a pseudo MIME type, whose first part can be passed
9825 : * as the pszFormat argument of ReadCompressedData(), with additional
9826 : * parameters specified as key=value with a semi-colon separator.
9827 : *
9828 : * The amount and types of optional parameters passed after the MIME type is
9829 : * format dependent, and driver dependent (some drivers might not be able to
9830 : * return those extra information without doing a rather costly processing).
9831 : *
9832 : * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
9833 : * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
9834 : * consequently "JPEG" can be passed as the pszFormat argument of
9835 : * ReadCompressedData(). For JPEG, implementations can use the
9836 : * GDALGetCompressionFormatForJPEG() helper method to generate a string like
9837 : * above from a JPEG codestream.
9838 : *
9839 : * Several values might be returned. For example,
9840 : * the JPEGXL driver will return "JXL", but also potentially "JPEG"
9841 : * if the JPEGXL codestream includes a JPEG reconstruction box.
9842 : *
9843 : * In the general case this method will return an empty list.
9844 : *
9845 : * This is the same as C function GDALDatasetGetCompressionFormats().
9846 : *
9847 : * @param nXOff The pixel offset to the top left corner of the region
9848 : * of the band to be accessed. This would be zero to start from the left side.
9849 : *
9850 : * @param nYOff The line offset to the top left corner of the region
9851 : * of the band to be accessed. This would be zero to start from the top.
9852 : *
9853 : * @param nXSize The width of the region of the band to be accessed in pixels.
9854 : *
9855 : * @param nYSize The height of the region of the band to be accessed in lines.
9856 : *
9857 : * @param nBandCount the number of bands being requested.
9858 : *
9859 : * @param panBandList the list of nBandCount band numbers.
9860 : * Note band numbers are 1 based. This may be NULL to select the first
9861 : * nBandCount bands.
9862 : *
9863 : * @return a list of compatible formats (which may be empty)
9864 : *
9865 : * For example, to check if native compression format(s) are available on the
9866 : * whole image:
9867 : * \code{.cpp}
9868 : * const CPLStringList aosFormats =
9869 : * poDataset->GetCompressionFormats(0, 0,
9870 : * poDataset->GetRasterXSize(),
9871 : * poDataset->GetRasterYSize(),
9872 : * poDataset->GetRasterCount(),
9873 : * nullptr);
9874 : * for( const char* pszFormat: aosFormats )
9875 : * {
9876 : * // Remove optional parameters and just print out the MIME type.
9877 : * const CPLStringList aosTokens(CSLTokenizeString2(pszFormat, ";", 0));
9878 : * printf("Found format %s\n, aosTokens[0]);
9879 : * }
9880 : * \endcode
9881 : *
9882 : * @since GDAL 3.7
9883 : */
9884 : CPLStringList
9885 0 : GDALDataset::GetCompressionFormats(CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
9886 : CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
9887 : CPL_UNUSED int nBandCount,
9888 : CPL_UNUSED const int *panBandList)
9889 : {
9890 0 : return CPLStringList();
9891 : }
9892 :
9893 : /************************************************************************/
9894 : /* GDALDatasetGetCompressionFormats() */
9895 : /************************************************************************/
9896 :
9897 : /** Return the compression formats that can be natively obtained for the
9898 : * window of interest and requested bands.
9899 : *
9900 : * For example, a tiled dataset may be able to return data in a compressed
9901 : * format if the window of interest matches exactly a tile. For some formats,
9902 : * drivers may also be able to merge several tiles together (not currently
9903 : * implemented though).
9904 : *
9905 : * Each format string is a pseudo MIME type, whose first part can be passed
9906 : * as the pszFormat argument of ReadCompressedData(), with additional
9907 : * parameters specified as key=value with a semi-colon separator.
9908 : *
9909 : * The amount and types of optional parameters passed after the MIME type is
9910 : * format dependent, and driver dependent (some drivers might not be able to
9911 : * return those extra information without doing a rather costly processing).
9912 : *
9913 : * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
9914 : * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
9915 : * consequently "JPEG" can be passed as the pszFormat argument of
9916 : * ReadCompressedData(). For JPEG, implementations can use the
9917 : * GDALGetCompressionFormatForJPEG() helper method to generate a string like
9918 : * above from a JPEG codestream.
9919 : *
9920 : * Several values might be returned. For example,
9921 : * the JPEGXL driver will return "JXL", but also potentially "JPEG"
9922 : * if the JPEGXL codestream includes a JPEG reconstruction box.
9923 : *
9924 : * In the general case this method will return an empty list.
9925 : *
9926 : * This is the same as C++ method GDALDataset::GetCompressionFormats().
9927 : *
9928 : * @param hDS Dataset handle.
9929 : *
9930 : * @param nXOff The pixel offset to the top left corner of the region
9931 : * of the band to be accessed. This would be zero to start from the left side.
9932 : *
9933 : * @param nYOff The line offset to the top left corner of the region
9934 : * of the band to be accessed. This would be zero to start from the top.
9935 : *
9936 : * @param nXSize The width of the region of the band to be accessed in pixels.
9937 : *
9938 : * @param nYSize The height of the region of the band to be accessed in lines.
9939 : *
9940 : * @param nBandCount the number of bands being requested.
9941 : *
9942 : * @param panBandList the list of nBandCount band numbers.
9943 : * Note band numbers are 1 based. This may be NULL to select the first
9944 : * nBandCount bands.
9945 : *
9946 : * @return a list of compatible formats (which may be empty) that should be
9947 : * freed with CSLDestroy(), or nullptr.
9948 : *
9949 : * @since GDAL 3.7
9950 : */
9951 9 : char **GDALDatasetGetCompressionFormats(GDALDatasetH hDS, int nXOff, int nYOff,
9952 : int nXSize, int nYSize, int nBandCount,
9953 : const int *panBandList)
9954 : {
9955 9 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9956 9 : return GDALDataset::FromHandle(hDS)
9957 9 : ->GetCompressionFormats(nXOff, nYOff, nXSize, nYSize, nBandCount,
9958 9 : panBandList)
9959 9 : .StealList();
9960 : }
9961 :
9962 : /************************************************************************/
9963 : /* ReadCompressedData() */
9964 : /************************************************************************/
9965 :
9966 : /** Return the compressed content that can be natively obtained for the
9967 : * window of interest and requested bands.
9968 : *
9969 : * For example, a tiled dataset may be able to return data in compressed format
9970 : * if the window of interest matches exactly a tile. For some formats, drivers
9971 : * may also be example to merge several tiles together (not currently
9972 : * implemented though).
9973 : *
9974 : * The implementation should make sure that the content returned forms a valid
9975 : * standalone file. For example, for the GeoTIFF implementation of this method,
9976 : * when extracting a JPEG tile, the method will automatically add the content
9977 : * of the JPEG Huffman and/or quantization tables that might be stored in the
9978 : * TIFF JpegTables tag, and not in tile data itself.
9979 : *
9980 : * In the general case this method will return CE_Failure.
9981 : *
9982 : * This is the same as C function GDALDatasetReadCompressedData().
9983 : *
9984 : * @param pszFormat Requested compression format (e.g. "JPEG",
9985 : * "WEBP", "JXL"). This is the MIME type of one of the values
9986 : * returned by GetCompressionFormats(). The format string is designed to
9987 : * potentially include at a later point key=value optional parameters separated
9988 : * by a semi-colon character. At time of writing, none are implemented.
9989 : * ReadCompressedData() implementations should verify optional parameters and
9990 : * return CE_Failure if they cannot support one of them.
9991 : *
9992 : * @param nXOff The pixel offset to the top left corner of the region
9993 : * of the band to be accessed. This would be zero to start from the left side.
9994 : *
9995 : * @param nYOff The line offset to the top left corner of the region
9996 : * of the band to be accessed. This would be zero to start from the top.
9997 : *
9998 : * @param nXSize The width of the region of the band to be accessed in pixels.
9999 : *
10000 : * @param nYSize The height of the region of the band to be accessed in lines.
10001 : *
10002 : * @param nBandCount the number of bands being requested.
10003 : *
10004 : * @param panBandList the list of nBandCount band numbers.
10005 : * Note band numbers are 1 based. This may be NULL to select the first
10006 : * nBandCount bands.
10007 : *
10008 : * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10009 : * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10010 : * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10011 : * buffer will be filled with the compressed data, provided that pnBufferSize
10012 : * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10013 : * of *ppBuffer, is sufficiently large to hold the data.
10014 : * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10015 : * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10016 : * free it with VSIFree().
10017 : * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10018 : * but *pnBufferSize will be updated with an upper bound of the size that would
10019 : * be necessary to hold it (if pnBufferSize != nullptr).
10020 : *
10021 : * @param pnBufferSize Output buffer size, or nullptr.
10022 : * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10023 : * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10024 : * method is successful, *pnBufferSize will be updated with the actual size
10025 : * used.
10026 : *
10027 : * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10028 : * If ppszDetailedFormat is not nullptr, then, on success, the method will
10029 : * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10030 : * *ppszDetailedFormat might contain strings like
10031 : * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10032 : * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10033 : * The string will contain at least as much information as what
10034 : * GetCompressionFormats() returns, and potentially more when
10035 : * ppBuffer != nullptr.
10036 : *
10037 : * @return CE_None in case of success, CE_Failure otherwise.
10038 : *
10039 : * For example, to request JPEG content on the whole image and let GDAL deal
10040 : * with the buffer allocation.
10041 : * \code{.cpp}
10042 : * void* pBuffer = nullptr;
10043 : * size_t nBufferSize = 0;
10044 : * CPLErr eErr =
10045 : * poDataset->ReadCompressedData("JPEG",
10046 : * 0, 0,
10047 : * poDataset->GetRasterXSize(),
10048 : * poDataset->GetRasterYSize(),
10049 : * poDataset->GetRasterCount(),
10050 : * nullptr, // panBandList
10051 : * &pBuffer,
10052 : * &nBufferSize,
10053 : * nullptr // ppszDetailedFormat
10054 : * );
10055 : * if (eErr == CE_None)
10056 : * {
10057 : * CPLAssert(pBuffer != nullptr);
10058 : * CPLAssert(nBufferSize > 0);
10059 : * VSILFILE* fp = VSIFOpenL("my.jpeg", "wb");
10060 : * if (fp)
10061 : * {
10062 : * VSIFWriteL(pBuffer, nBufferSize, 1, fp);
10063 : * VSIFCloseL(fp);
10064 : * }
10065 : * VSIFree(pBuffer);
10066 : * }
10067 : * \endcode
10068 : *
10069 : * Or to manage the buffer allocation on your side:
10070 : * \code{.cpp}
10071 : * size_t nUpperBoundBufferSize = 0;
10072 : * CPLErr eErr =
10073 : * poDataset->ReadCompressedData("JPEG",
10074 : * 0, 0,
10075 : * poDataset->GetRasterXSize(),
10076 : * poDataset->GetRasterYSize(),
10077 : * poDataset->GetRasterCount(),
10078 : * nullptr, // panBandList
10079 : * nullptr, // ppBuffer,
10080 : * &nUpperBoundBufferSize,
10081 : * nullptr // ppszDetailedFormat
10082 : * );
10083 : * if (eErr == CE_None)
10084 : * {
10085 : * std::vector<uint8_t> myBuffer;
10086 : * myBuffer.resize(nUpperBoundBufferSize);
10087 : * void* pBuffer = myBuffer.data();
10088 : * size_t nActualSize = nUpperBoundBufferSize;
10089 : * char* pszDetailedFormat = nullptr;
10090 : * // We also request detailed format, but we could have passed it to
10091 : * // nullptr as well.
10092 : * eErr =
10093 : * poDataset->ReadCompressedData("JPEG",
10094 : * 0, 0,
10095 : * poDataset->GetRasterXSize(),
10096 : * poDataset->GetRasterYSize(),
10097 : * poDataset->GetRasterCount(),
10098 : * nullptr, // panBandList
10099 : * &pBuffer,
10100 : * &nActualSize,
10101 : * &pszDetailedFormat);
10102 : * if (eErr == CE_None)
10103 : * {
10104 : * CPLAssert(pBuffer == myBuffer.data()); // pointed value not modified
10105 : * CPLAssert(nActualSize <= nUpperBoundBufferSize);
10106 : * myBuffer.resize(nActualSize);
10107 : * // do something useful
10108 : * VSIFree(pszDetailedFormat);
10109 : * }
10110 : * }
10111 : * \endcode
10112 : *
10113 : * @since GDAL 3.7
10114 : */
10115 418 : CPLErr GDALDataset::ReadCompressedData(
10116 : CPL_UNUSED const char *pszFormat, CPL_UNUSED int nXOff,
10117 : CPL_UNUSED int nYOff, CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
10118 : CPL_UNUSED int nBandCount, CPL_UNUSED const int *panBandList,
10119 : CPL_UNUSED void **ppBuffer, CPL_UNUSED size_t *pnBufferSize,
10120 : CPL_UNUSED char **ppszDetailedFormat)
10121 : {
10122 418 : return CE_Failure;
10123 : }
10124 :
10125 : /************************************************************************/
10126 : /* GDALDatasetReadCompressedData() */
10127 : /************************************************************************/
10128 :
10129 : /** Return the compressed content that can be natively obtained for the
10130 : * window of interest and requested bands.
10131 : *
10132 : * For example, a tiled dataset may be able to return data in compressed format
10133 : * if the window of interest matches exactly a tile. For some formats, drivers
10134 : * may also be example to merge several tiles together (not currently
10135 : * implemented though).
10136 : *
10137 : * The implementation should make sure that the content returned forms a valid
10138 : * standalone file. For example, for the GeoTIFF implementation of this method,
10139 : * when extracting a JPEG tile, the method will automatically adds the content
10140 : * of the JPEG Huffman and/or quantization tables that might be stored in the
10141 : * TIFF JpegTables tag, and not in tile data itself.
10142 : *
10143 : * In the general case this method will return CE_Failure.
10144 : *
10145 : * This is the same as C++ method GDALDataset:ReadCompressedData().
10146 : *
10147 : * @param hDS Dataset handle.
10148 : *
10149 : * @param pszFormat Requested compression format (e.g. "JPEG",
10150 : * "WEBP", "JXL"). This is the MIME type of one of the values
10151 : * returned by GetCompressionFormats(). The format string is designed to
10152 : * potentially include at a later point key=value optional parameters separated
10153 : * by a semi-colon character. At time of writing, none are implemented.
10154 : * ReadCompressedData() implementations should verify optional parameters and
10155 : * return CE_Failure if they cannot support one of them.
10156 : *
10157 : * @param nXOff The pixel offset to the top left corner of the region
10158 : * of the band to be accessed. This would be zero to start from the left side.
10159 : *
10160 : * @param nYOff The line offset to the top left corner of the region
10161 : * of the band to be accessed. This would be zero to start from the top.
10162 : *
10163 : * @param nXSize The width of the region of the band to be accessed in pixels.
10164 : *
10165 : * @param nYSize The height of the region of the band to be accessed in lines.
10166 : *
10167 : * @param nBandCount the number of bands being requested.
10168 : *
10169 : * @param panBandList the list of nBandCount band numbers.
10170 : * Note band numbers are 1 based. This may be NULL to select the first
10171 : * nBandCount bands.
10172 : *
10173 : * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10174 : * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10175 : * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10176 : * buffer will be filled with the compressed data, provided that pnBufferSize
10177 : * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10178 : * of *ppBuffer, is sufficiently large to hold the data.
10179 : * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10180 : * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10181 : * free it with VSIFree().
10182 : * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10183 : * but *pnBufferSize will be updated with an upper bound of the size that would
10184 : * be necessary to hold it (if pnBufferSize != nullptr).
10185 : *
10186 : * @param pnBufferSize Output buffer size, or nullptr.
10187 : * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10188 : * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10189 : * method is successful, *pnBufferSize will be updated with the actual size
10190 : * used.
10191 : *
10192 : * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10193 : * If ppszDetailedFormat is not nullptr, then, on success, the method will
10194 : * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10195 : * *ppszDetailedFormat might contain strings like
10196 : * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10197 : * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10198 : * The string will contain at least as much information as what
10199 : * GetCompressionFormats() returns, and potentially more when
10200 : * ppBuffer != nullptr.
10201 : *
10202 : * @return CE_None in case of success, CE_Failure otherwise.
10203 : *
10204 : * @since GDAL 3.7
10205 : */
10206 28 : CPLErr GDALDatasetReadCompressedData(GDALDatasetH hDS, const char *pszFormat,
10207 : int nXOff, int nYOff, int nXSize,
10208 : int nYSize, int nBandCount,
10209 : const int *panBandList, void **ppBuffer,
10210 : size_t *pnBufferSize,
10211 : char **ppszDetailedFormat)
10212 : {
10213 28 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10214 56 : return GDALDataset::FromHandle(hDS)->ReadCompressedData(
10215 : pszFormat, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandList,
10216 28 : ppBuffer, pnBufferSize, ppszDetailedFormat);
10217 : }
10218 :
10219 : /************************************************************************/
10220 : /* CanBeCloned() */
10221 : /************************************************************************/
10222 :
10223 : //! @cond Doxygen_Suppress
10224 :
10225 : /** This method is called by GDALThreadSafeDataset::Create() to determine if
10226 : * it is possible to create a thread-safe wrapper for a dataset, which involves
10227 : * the ability to Clone() it.
10228 : *
10229 : * Implementations of this method must be thread-safe.
10230 : *
10231 : * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10232 : * expressing the intended use for thread-safety.
10233 : * Currently, the only valid scope is in the base
10234 : * implementation is GDAL_OF_RASTER.
10235 : * @param bCanShareState Determines if cloned datasets are allowed to share
10236 : * state with the dataset they have been cloned from.
10237 : * If set to true, the dataset from which they have been
10238 : * cloned from must remain opened during the lifetime of
10239 : * its clones.
10240 : * @return true if the Clone() method is expected to succeed with the same values
10241 : * of nScopeFlags and bCanShareState.
10242 : */
10243 125 : bool GDALDataset::CanBeCloned(int nScopeFlags,
10244 : [[maybe_unused]] bool bCanShareState) const
10245 : {
10246 125 : return m_bCanBeReopened && nScopeFlags == GDAL_OF_RASTER;
10247 : }
10248 :
10249 : //! @endcond
10250 :
10251 : /************************************************************************/
10252 : /* Clone() */
10253 : /************************************************************************/
10254 :
10255 : //! @cond Doxygen_Suppress
10256 :
10257 : /** This method "clones" the current dataset, that is it returns a new instance
10258 : * that is opened on the same underlying "file".
10259 : *
10260 : * The base implementation uses GDALDataset::Open() to re-open the dataset.
10261 : * The MEM driver has a specialized implementation that returns a new instance,
10262 : * but which shares the same memory buffer as this.
10263 : *
10264 : * Implementations of this method must be thread-safe.
10265 : *
10266 : * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10267 : * expressing the intended use for thread-safety.
10268 : * Currently, the only valid scope is in the base
10269 : * implementation is GDAL_OF_RASTER.
10270 : * @param bCanShareState Determines if cloned datasets are allowed to share
10271 : * state with the dataset they have been cloned from.
10272 : * If set to true, the dataset from which they have been
10273 : * cloned from must remain opened during the lifetime of
10274 : * its clones.
10275 : * @return a new instance, or nullptr in case of error.
10276 : */
10277 : std::unique_ptr<GDALDataset>
10278 2027 : GDALDataset::Clone(int nScopeFlags, [[maybe_unused]] bool bCanShareState) const
10279 : {
10280 4054 : CPLStringList aosAllowedDrivers;
10281 2027 : if (poDriver)
10282 2027 : aosAllowedDrivers.AddString(poDriver->GetDescription());
10283 : return std::unique_ptr<GDALDataset>(GDALDataset::Open(
10284 2027 : GetDescription(),
10285 2027 : nScopeFlags | GDAL_OF_INTERNAL | GDAL_OF_VERBOSE_ERROR,
10286 4054 : aosAllowedDrivers.List(), papszOpenOptions));
10287 : }
10288 :
10289 : //! @endcond
|