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 <array>
19 : #include <climits>
20 : #include <cstdarg>
21 : #include <cstdio>
22 : #include <cstdlib>
23 : #include <cstring>
24 : #include <algorithm>
25 : #include <map>
26 : #include <mutex>
27 : #include <new>
28 : #include <set>
29 : #include <string>
30 : #include <utility>
31 :
32 : #include "cpl_conv.h"
33 : #include "cpl_error.h"
34 : #include "cpl_hash_set.h"
35 : #include "cpl_multiproc.h"
36 : #include "cpl_progress.h"
37 : #include "cpl_string.h"
38 : #include "cpl_vsi.h"
39 : #include "cpl_vsi_error.h"
40 : #include "gdal_alg.h"
41 : #include "ogr_api.h"
42 : #include "ogr_attrind.h"
43 : #include "ogr_core.h"
44 : #include "ogr_feature.h"
45 : #include "ogr_featurestyle.h"
46 : #include "ogr_gensql.h"
47 : #include "ogr_geometry.h"
48 : #include "ogr_p.h"
49 : #include "ogr_spatialref.h"
50 : #include "ogr_srs_api.h"
51 : #include "ograpispy.h"
52 : #include "ogrsf_frmts.h"
53 : #include "ogrunionlayer.h"
54 : #include "ogr_swq.h"
55 :
56 : #include "../frmts/derived/derivedlist.h"
57 :
58 : #ifdef SQLITE_ENABLED
59 : #include "../sqlite/ogrsqliteexecutesql.h"
60 : #endif
61 :
62 : extern const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT];
63 :
64 : CPL_C_START
65 : GDALAsyncReader *GDALGetDefaultAsyncReader(GDALDataset *poDS, int nXOff,
66 : int nYOff, int nXSize, int nYSize,
67 : void *pBuf, int nBufXSize,
68 : int nBufYSize, GDALDataType eBufType,
69 : int nBandCount, int *panBandMap,
70 : int nPixelSpace, int nLineSpace,
71 : int nBandSpace, char **papszOptions);
72 : CPL_C_END
73 :
74 : enum class GDALAllowReadWriteMutexState
75 : {
76 : RW_MUTEX_STATE_UNKNOWN,
77 : RW_MUTEX_STATE_ALLOWED,
78 : RW_MUTEX_STATE_DISABLED
79 : };
80 :
81 : const GIntBig TOTAL_FEATURES_NOT_INIT = -2;
82 : const GIntBig TOTAL_FEATURES_UNKNOWN = -1;
83 :
84 : class GDALDataset::Private
85 : {
86 : CPL_DISALLOW_COPY_ASSIGN(Private)
87 :
88 : public:
89 : CPLMutex *hMutex = nullptr;
90 : std::map<GIntBig, int> oMapThreadToMutexTakenCount{};
91 : #ifdef DEBUG_EXTRA
92 : std::map<GIntBig, int> oMapThreadToMutexTakenCountSaved{};
93 : #endif
94 : GDALAllowReadWriteMutexState eStateReadWriteMutex =
95 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN;
96 : int nCurrentLayerIdx = 0;
97 : int nLayerCount = -1;
98 : GIntBig nFeatureReadInLayer = 0;
99 : GIntBig nFeatureReadInDataset = 0;
100 : GIntBig nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
101 : GIntBig nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
102 : OGRLayer *poCurrentLayer = nullptr;
103 :
104 : std::mutex m_oMutexWKT{};
105 :
106 : char *m_pszWKTCached = nullptr;
107 : OGRSpatialReference *m_poSRSCached = nullptr;
108 : char *m_pszWKTGCPCached = nullptr;
109 : OGRSpatialReference *m_poSRSGCPCached = nullptr;
110 :
111 : GDALDataset *poParentDataset = nullptr;
112 :
113 : bool m_bOverviewsEnabled = true;
114 :
115 : std::vector<int>
116 : m_anBandMap{}; // used by RasterIO(). Values are 1, 2, etc.
117 :
118 147084 : Private() = default;
119 : };
120 :
121 : struct SharedDatasetCtxt
122 : {
123 : // PID of the thread that mark the dataset as shared
124 : // This may not be the actual PID, but the responsiblePID.
125 : GIntBig nPID;
126 : char *pszDescription;
127 : char *pszConcatenatedOpenOptions;
128 : int nOpenFlags;
129 :
130 : GDALDataset *poDS;
131 : };
132 :
133 : // Set of datasets opened as shared datasets (with GDALOpenShared)
134 : // The values in the set are of type SharedDatasetCtxt.
135 : static CPLHashSet *phSharedDatasetSet = nullptr;
136 :
137 : // Set of all datasets created in the constructor of GDALDataset.
138 : // In the case of a shared dataset, memorize the PID of the thread
139 : // that marked the dataset as shared, so that we can remove it from
140 : // the phSharedDatasetSet in the destructor of the dataset, even
141 : // if GDALClose is called from a different thread.
142 : static std::map<GDALDataset *, GIntBig> *poAllDatasetMap = nullptr;
143 :
144 : static CPLMutex *hDLMutex = nullptr;
145 :
146 : // Static array of all datasets. Used by GDALGetOpenDatasets.
147 : // Not thread-safe. See GDALGetOpenDatasets.
148 : static GDALDataset **ppDatasets = nullptr;
149 :
150 8339 : static unsigned long GDALSharedDatasetHashFunc(const void *elt)
151 : {
152 8339 : const SharedDatasetCtxt *psStruct =
153 : static_cast<const SharedDatasetCtxt *>(elt);
154 : return static_cast<unsigned long>(
155 8339 : CPLHashSetHashStr(psStruct->pszDescription) ^
156 8339 : CPLHashSetHashStr(psStruct->pszConcatenatedOpenOptions) ^
157 8339 : psStruct->nOpenFlags ^ psStruct->nPID);
158 : }
159 :
160 6944 : static int GDALSharedDatasetEqualFunc(const void *elt1, const void *elt2)
161 : {
162 6944 : const SharedDatasetCtxt *psStruct1 =
163 : static_cast<const SharedDatasetCtxt *>(elt1);
164 6944 : const SharedDatasetCtxt *psStruct2 =
165 : static_cast<const SharedDatasetCtxt *>(elt2);
166 13837 : return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
167 6893 : strcmp(psStruct1->pszConcatenatedOpenOptions,
168 6893 : psStruct2->pszConcatenatedOpenOptions) == 0 &&
169 20730 : psStruct1->nPID == psStruct2->nPID &&
170 13837 : psStruct1->nOpenFlags == psStruct2->nOpenFlags;
171 : }
172 :
173 394 : static void GDALSharedDatasetFreeFunc(void *elt)
174 : {
175 394 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
176 394 : CPLFree(psStruct->pszDescription);
177 394 : CPLFree(psStruct->pszConcatenatedOpenOptions);
178 394 : CPLFree(psStruct);
179 394 : }
180 :
181 : static std::string
182 7026 : GDALSharedDatasetConcatenateOpenOptions(CSLConstList papszOpenOptions)
183 : {
184 7026 : std::string osStr;
185 7039 : for (const char *pszOption : cpl::Iterate(papszOpenOptions))
186 13 : osStr += pszOption;
187 7026 : return osStr;
188 : }
189 :
190 : /************************************************************************/
191 : /* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
192 : /************************************************************************/
193 :
194 : // The open-shared mutex must be used by the ProxyPool too.
195 481560 : CPLMutex **GDALGetphDLMutex()
196 : {
197 481560 : return &hDLMutex;
198 : }
199 :
200 : // The current thread will act in the behalf of the thread of PID
201 : // responsiblePID.
202 471245 : void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
203 : {
204 : GIntBig *pResponsiblePID =
205 471245 : static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
206 471245 : if (pResponsiblePID == nullptr)
207 : {
208 207 : pResponsiblePID = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
209 207 : CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
210 : }
211 471245 : *pResponsiblePID = responsiblePID;
212 471245 : }
213 :
214 : // Get the PID of the thread that the current thread will act in the behalf of
215 : // By default : the current thread acts in the behalf of itself.
216 596009 : GIntBig GDALGetResponsiblePIDForCurrentThread()
217 : {
218 : GIntBig *pResponsiblePID =
219 596009 : static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
220 595873 : if (pResponsiblePID == nullptr)
221 43309 : return CPLGetPID();
222 552564 : return *pResponsiblePID;
223 : }
224 :
225 : /************************************************************************/
226 : /* ==================================================================== */
227 : /* GDALDataset */
228 : /* ==================================================================== */
229 : /************************************************************************/
230 :
231 : /**
232 : * \class GDALDataset "gdal_priv.h"
233 : *
234 : * A dataset encapsulating one or more raster bands. Details are further
235 : * discussed in the <a href="https://gdal.org/user/raster_data_model.html">GDAL
236 : * Raster Data Model</a>.
237 : *
238 : * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,
239 : * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new
240 : * dataset.
241 : */
242 :
243 : /************************************************************************/
244 : /* GDALDataset() */
245 : /************************************************************************/
246 :
247 : //! @cond Doxygen_Suppress
248 128092 : GDALDataset::GDALDataset()
249 128092 : : GDALDataset(CPLTestBool(CPLGetConfigOption("GDAL_FORCE_CACHING", "NO")))
250 : {
251 127958 : }
252 :
253 147180 : GDALDataset::GDALDataset(int bForceCachedIOIn)
254 147018 : : bForceCachedIO(CPL_TO_BOOL(bForceCachedIOIn)),
255 147180 : m_poPrivate(new(std::nothrow) GDALDataset::Private)
256 : {
257 147062 : }
258 :
259 : //! @endcond
260 :
261 : /************************************************************************/
262 : /* ~GDALDataset() */
263 : /************************************************************************/
264 :
265 : /**
266 : * \brief Destroy an open GDALDataset.
267 : *
268 : * This is the accepted method of closing a GDAL dataset and deallocating
269 : * all resources associated with it.
270 : *
271 : * Equivalent of the C callable GDALClose(). Except that GDALClose() first
272 : * decrements the reference count, and then closes only if it has dropped to
273 : * zero.
274 : *
275 : * For Windows users, it is not recommended to use the delete operator on the
276 : * dataset object because of known issues when allocating and freeing memory
277 : * across module boundaries. Calling GDALClose() is then a better option.
278 : */
279 :
280 147128 : GDALDataset::~GDALDataset()
281 :
282 : {
283 : // we don't want to report destruction of datasets that
284 : // were never really open or meant as internal
285 147119 : if (!bIsInternal && (nBands != 0 || !EQUAL(GetDescription(), "")))
286 : {
287 69521 : if (CPLGetPID() != GDALGetResponsiblePIDForCurrentThread())
288 209 : CPLDebug("GDAL",
289 : "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)",
290 209 : GetDescription(), this, static_cast<int>(CPLGetPID()),
291 209 : static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
292 : else
293 69351 : CPLDebug("GDAL", "GDALClose(%s, this=%p)", GetDescription(), this);
294 : }
295 :
296 147191 : if (IsMarkedSuppressOnClose())
297 : {
298 2318 : if (poDriver == nullptr ||
299 : // Someone issuing Create("foo.tif") on a
300 : // memory driver doesn't expect files with those names to be deleted
301 : // on a file system...
302 : // This is somewhat messy. Ideally there should be a way for the
303 : // driver to overload the default behavior
304 1154 : (!EQUAL(poDriver->GetDescription(), "MEM") &&
305 1115 : !EQUAL(poDriver->GetDescription(), "Memory")))
306 : {
307 1125 : VSIUnlink(GetDescription());
308 : }
309 : }
310 :
311 : /* -------------------------------------------------------------------- */
312 : /* Remove dataset from the "open" dataset list. */
313 : /* -------------------------------------------------------------------- */
314 147133 : if (!bIsInternal)
315 : {
316 140947 : CPLMutexHolderD(&hDLMutex);
317 70474 : if (poAllDatasetMap)
318 : {
319 : std::map<GDALDataset *, GIntBig>::iterator oIter =
320 70474 : poAllDatasetMap->find(this);
321 70474 : CPLAssert(oIter != poAllDatasetMap->end());
322 :
323 70474 : UnregisterFromSharedDataset();
324 :
325 70474 : poAllDatasetMap->erase(oIter);
326 :
327 70474 : if (poAllDatasetMap->empty())
328 : {
329 26502 : delete poAllDatasetMap;
330 26502 : poAllDatasetMap = nullptr;
331 26502 : if (phSharedDatasetSet)
332 : {
333 265 : CPLHashSetDestroy(phSharedDatasetSet);
334 : }
335 26502 : phSharedDatasetSet = nullptr;
336 26502 : CPLFree(ppDatasets);
337 26502 : ppDatasets = nullptr;
338 : }
339 : }
340 : }
341 :
342 : /* -------------------------------------------------------------------- */
343 : /* Destroy the raster bands if they exist. */
344 : /* -------------------------------------------------------------------- */
345 1673720 : for (int i = 0; i < nBands && papoBands != nullptr; ++i)
346 : {
347 1526590 : if (papoBands[i] != nullptr)
348 1526590 : delete papoBands[i];
349 1526590 : papoBands[i] = nullptr;
350 : }
351 :
352 147136 : CPLFree(papoBands);
353 :
354 147129 : if (m_poStyleTable)
355 : {
356 23 : delete m_poStyleTable;
357 23 : m_poStyleTable = nullptr;
358 : }
359 :
360 147129 : if (m_poPrivate != nullptr)
361 : {
362 147127 : if (m_poPrivate->hMutex != nullptr)
363 18470 : CPLDestroyMutex(m_poPrivate->hMutex);
364 :
365 : #if defined(__COVERITY__) || defined(DEBUG)
366 : // Not needed since at destruction there is no risk of concurrent use.
367 294256 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
368 : #endif
369 147132 : CPLFree(m_poPrivate->m_pszWKTCached);
370 147126 : if (m_poPrivate->m_poSRSCached)
371 : {
372 0 : m_poPrivate->m_poSRSCached->Release();
373 : }
374 147126 : CPLFree(m_poPrivate->m_pszWKTGCPCached);
375 147129 : if (m_poPrivate->m_poSRSGCPCached)
376 : {
377 0 : m_poPrivate->m_poSRSGCPCached->Release();
378 : }
379 : }
380 :
381 147132 : delete m_poPrivate;
382 :
383 147125 : CSLDestroy(papszOpenOptions);
384 147128 : }
385 :
386 : /************************************************************************/
387 : /* Close() */
388 : /************************************************************************/
389 :
390 : /** Do final cleanup before a dataset is destroyed.
391 : *
392 : * This method is typically called by GDALClose() or the destructor of a
393 : * GDALDataset subclass. It might also be called by C++ users before
394 : * destroying a dataset. It should not be called on a shared dataset whose
395 : * reference count is greater than one.
396 : *
397 : * It gives a last chance to the closing process to return an error code if
398 : * something goes wrong, in particular in creation / update scenarios where
399 : * file write or network communication might occur when finalizing the dataset.
400 : *
401 : * Implementations should be robust to this method to be called several times
402 : * (on subsequent calls, it should do nothing and return CE_None).
403 : * Once it has been called, no other method than Close() or the dataset
404 : * destructor should be called. RasterBand or OGRLayer owned by the dataset
405 : * should be assumed as no longer being valid.
406 : *
407 : * If a driver implements this method, it must also call it from its
408 : * dataset destructor.
409 : *
410 : * A typical implementation might look as the following
411 : * \code{.cpp}
412 : *
413 : * MyDataset::~MyDataset()
414 : * {
415 : * try
416 : * {
417 : * MyDataset::Close();
418 : * }
419 : * catch (const std::exception &exc)
420 : * {
421 : * // If Close() can throw exception
422 : * CPLError(CE_Failure, CPLE_AppDefined,
423 : * "Exception thrown in MyDataset::Close(): %s",
424 : * exc.what());
425 : * }
426 : * catch (...)
427 : * {
428 : * // If Close() can throw exception
429 : * CPLError(CE_Failure, CPLE_AppDefined,
430 : * "Exception thrown in MyDataset::Close()");
431 : * }
432 : * }
433 : *
434 : * CPLErr MyDataset::Close()
435 : * {
436 : * CPLErr eErr = CE_None;
437 : * if( nOpenFlags != OPEN_FLAGS_CLOSED )
438 : * {
439 : * if( MyDataset::FlushCache(true) != CE_None )
440 : * eErr = CE_Failure;
441 : *
442 : * // Do something driver specific
443 : * if (m_fpImage)
444 : * {
445 : * if( VSIFCloseL(m_fpImage) != 0 )
446 : * {
447 : * CPLError(CE_Failure, CPLE_FileIO, "VSIFCloseL() failed");
448 : * eErr = CE_Failure;
449 : * }
450 : * }
451 : *
452 : * // Call parent Close() implementation.
453 : * if( MyParentDatasetClass::Close() != CE_None )
454 : * eErr = CE_Failure;
455 : * }
456 : * return eErr;
457 : * }
458 : * \endcode
459 : *
460 : * @since GDAL 3.7
461 : */
462 86419 : CPLErr GDALDataset::Close()
463 : {
464 : // Call UnregisterFromSharedDataset() before altering nOpenFlags
465 86419 : UnregisterFromSharedDataset();
466 :
467 86415 : nOpenFlags = OPEN_FLAGS_CLOSED;
468 86415 : return CE_None;
469 : }
470 :
471 : /************************************************************************/
472 : /* UnregisterFromSharedDataset() */
473 : /************************************************************************/
474 :
475 156892 : void GDALDataset::UnregisterFromSharedDataset()
476 : {
477 156892 : if (!(!bIsInternal && bShared && poAllDatasetMap && phSharedDatasetSet))
478 156498 : return;
479 :
480 788 : CPLMutexHolderD(&hDLMutex);
481 :
482 : std::map<GDALDataset *, GIntBig>::iterator oIter =
483 394 : poAllDatasetMap->find(this);
484 394 : CPLAssert(oIter != poAllDatasetMap->end());
485 394 : const GIntBig nPIDCreatorForShared = oIter->second;
486 394 : bShared = false;
487 : SharedDatasetCtxt sStruct;
488 394 : sStruct.nPID = nPIDCreatorForShared;
489 394 : sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
490 394 : sStruct.pszDescription = const_cast<char *>(GetDescription());
491 : std::string osConcatenatedOpenOptions =
492 788 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
493 394 : sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
494 394 : sStruct.poDS = nullptr;
495 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
496 394 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
497 394 : if (psStruct && psStruct->poDS == this)
498 : {
499 393 : CPLHashSetRemove(phSharedDatasetSet, psStruct);
500 : }
501 : else
502 : {
503 1 : CPLDebug("GDAL",
504 : "Should not happen. Cannot find %s, "
505 : "this=%p in phSharedDatasetSet",
506 1 : GetDescription(), this);
507 : }
508 : }
509 :
510 : /************************************************************************/
511 : /* AddToDatasetOpenList() */
512 : /************************************************************************/
513 :
514 71798 : void GDALDataset::AddToDatasetOpenList()
515 : {
516 : /* -------------------------------------------------------------------- */
517 : /* Add this dataset to the open dataset list. */
518 : /* -------------------------------------------------------------------- */
519 71798 : bIsInternal = false;
520 :
521 71798 : CPLMutexHolderD(&hDLMutex);
522 :
523 71798 : if (poAllDatasetMap == nullptr)
524 26511 : poAllDatasetMap = new std::map<GDALDataset *, GIntBig>;
525 71798 : (*poAllDatasetMap)[this] = -1;
526 71798 : }
527 :
528 : /************************************************************************/
529 : /* FlushCache() */
530 : /************************************************************************/
531 :
532 : /**
533 : * \brief Flush all write cached data to disk.
534 : *
535 : * Any raster (or other GDAL) data written via GDAL calls, but buffered
536 : * internally will be written to disk.
537 : *
538 : * The default implementation of this method just calls the FlushCache() method
539 : * on each of the raster bands and the SyncToDisk() method
540 : * on each of the layers. Conceptually, calling FlushCache() on a dataset
541 : * should include any work that might be accomplished by calling SyncToDisk()
542 : * on layers in that dataset.
543 : *
544 : * Using this method does not prevent use from calling GDALClose()
545 : * to properly close a dataset and ensure that important data not addressed
546 : * by FlushCache() is written in the file.
547 : *
548 : * This method is the same as the C function GDALFlushCache().
549 : *
550 : * @param bAtClosing Whether this is called from a GDALDataset destructor
551 : * @return CE_None in case of success (note: return value added in GDAL 3.7)
552 : */
553 :
554 111838 : CPLErr GDALDataset::FlushCache(bool bAtClosing)
555 :
556 : {
557 111838 : CPLErr eErr = CE_None;
558 : // This sometimes happens if a dataset is destroyed before completely
559 : // built.
560 :
561 111838 : if (papoBands)
562 : {
563 1992220 : for (int i = 0; i < nBands; ++i)
564 : {
565 1889770 : if (papoBands[i])
566 : {
567 1889770 : if (papoBands[i]->FlushCache(bAtClosing) != CE_None)
568 7 : eErr = CE_Failure;
569 : }
570 : }
571 : }
572 :
573 111837 : const int nLayers = GetLayerCount();
574 : // cppcheck-suppress knownConditionTrueFalse
575 111836 : if (nLayers > 0)
576 : {
577 9784 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
578 14527 : for (int i = 0; i < nLayers; ++i)
579 : {
580 9635 : OGRLayer *poLayer = GetLayer(i);
581 :
582 9635 : if (poLayer)
583 : {
584 9635 : if (poLayer->SyncToDisk() != OGRERR_NONE)
585 0 : eErr = CE_Failure;
586 : }
587 : }
588 : }
589 :
590 111836 : return eErr;
591 : }
592 :
593 : /************************************************************************/
594 : /* GDALFlushCache() */
595 : /************************************************************************/
596 :
597 : /**
598 : * \brief Flush all write cached data to disk.
599 : *
600 : * @see GDALDataset::FlushCache().
601 : * @return CE_None in case of success (note: return value added in GDAL 3.7)
602 : */
603 :
604 4736 : CPLErr CPL_STDCALL GDALFlushCache(GDALDatasetH hDS)
605 :
606 : {
607 4736 : VALIDATE_POINTER1(hDS, "GDALFlushCache", CE_Failure);
608 :
609 4736 : return GDALDataset::FromHandle(hDS)->FlushCache(false);
610 : }
611 :
612 : /************************************************************************/
613 : /* DropCache() */
614 : /************************************************************************/
615 :
616 : /**
617 : * \brief Drop all write cached data
618 : *
619 : * This method is the same as the C function GDALDropCache().
620 : *
621 : * @return CE_None in case of success
622 : * @since 3.9
623 : */
624 :
625 1 : CPLErr GDALDataset::DropCache()
626 :
627 : {
628 1 : CPLErr eErr = CE_None;
629 :
630 1 : if (papoBands)
631 : {
632 2 : for (int i = 0; i < nBands; ++i)
633 : {
634 1 : if (papoBands[i])
635 : {
636 1 : if (papoBands[i]->DropCache() != CE_None)
637 0 : eErr = CE_Failure;
638 : }
639 : }
640 : }
641 :
642 1 : return eErr;
643 : }
644 :
645 : /************************************************************************/
646 : /* GDALDropCache() */
647 : /************************************************************************/
648 :
649 : /**
650 : * \brief Drop all write cached data
651 : *
652 : * @see GDALDataset::DropCache().
653 : * @return CE_None in case of success
654 : * @since 3.9
655 : */
656 :
657 0 : CPLErr CPL_STDCALL GDALDropCache(GDALDatasetH hDS)
658 :
659 : {
660 0 : VALIDATE_POINTER1(hDS, "GDALDropCache", CE_Failure);
661 :
662 0 : return GDALDataset::FromHandle(hDS)->DropCache();
663 : }
664 :
665 : /************************************************************************/
666 : /* GetEstimatedRAMUsage() */
667 : /************************************************************************/
668 :
669 : /**
670 : * \brief Return the intrinsic RAM usage of this dataset.
671 : *
672 : * The returned value should take into account caches in the underlying driver
673 : * and decoding library, but not the usage related to the GDAL block cache.
674 : *
675 : * At time of writing, this method is only implemented in the JP2OpenJPEG
676 : * driver. For single-tiled JPEG2000 images, the decoding of the image,
677 : * even partially, involves allocating at least
678 : * width * height * number_of_bands * sizeof(uint32_t) bytes inside the libopenjp2
679 : * library.
680 : *
681 : * This method is used by the GDALDatasetPool class, itself used by the GDAL VRT
682 : * driver, to determine how long a dataset in the pool must be kept open, given
683 : * the RAM usage of the dataset with respect to the usable total RAM.
684 : *
685 : * @since GDAL 3.7
686 : * @return RAM usage in bytes, or -1 if unknown (the default implementation
687 : * returns -1)
688 : */
689 :
690 3303 : GIntBig GDALDataset::GetEstimatedRAMUsage()
691 : {
692 3303 : return -1;
693 : }
694 :
695 : /************************************************************************/
696 : /* BlockBasedFlushCache() */
697 : /* */
698 : /* This helper method can be called by the */
699 : /* GDALDataset::FlushCache() for particular drivers to ensure */
700 : /* that buffers will be flushed in a manner suitable for pixel */
701 : /* interleaved (by block) IO. That is, if all the bands have */
702 : /* the same size blocks then a given block will be flushed for */
703 : /* all bands before proceeding to the next block. */
704 : /************************************************************************/
705 :
706 : //! @cond Doxygen_Suppress
707 350 : CPLErr GDALDataset::BlockBasedFlushCache(bool bAtClosing)
708 :
709 : {
710 350 : GDALRasterBand *poBand1 = GetRasterBand(1);
711 350 : if (poBand1 == nullptr || (IsMarkedSuppressOnClose() && bAtClosing))
712 : {
713 7 : return GDALDataset::FlushCache(bAtClosing);
714 : }
715 :
716 343 : int nBlockXSize = 0;
717 343 : int nBlockYSize = 0;
718 343 : poBand1->GetBlockSize(&nBlockXSize, &nBlockYSize);
719 :
720 : /* -------------------------------------------------------------------- */
721 : /* Verify that all bands match. */
722 : /* -------------------------------------------------------------------- */
723 1108 : for (int iBand = 1; iBand < nBands; ++iBand)
724 : {
725 765 : GDALRasterBand *poBand = GetRasterBand(iBand + 1);
726 :
727 : int nThisBlockXSize, nThisBlockYSize;
728 765 : poBand->GetBlockSize(&nThisBlockXSize, &nThisBlockYSize);
729 765 : if (nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize)
730 : {
731 0 : return GDALDataset::FlushCache(bAtClosing);
732 : }
733 : }
734 :
735 : /* -------------------------------------------------------------------- */
736 : /* Now flush writable data. */
737 : /* -------------------------------------------------------------------- */
738 794 : for (int iY = 0; iY < poBand1->nBlocksPerColumn; ++iY)
739 : {
740 991 : for (int iX = 0; iX < poBand1->nBlocksPerRow; ++iX)
741 : {
742 1690 : for (int iBand = 0; iBand < nBands; ++iBand)
743 : {
744 1150 : const CPLErr eErr = papoBands[iBand]->FlushBlock(iX, iY);
745 :
746 1150 : if (eErr != CE_None)
747 0 : return CE_Failure;
748 : }
749 : }
750 : }
751 343 : return CE_None;
752 : }
753 :
754 : /************************************************************************/
755 : /* RasterInitialize() */
756 : /* */
757 : /* Initialize raster size */
758 : /************************************************************************/
759 :
760 0 : void GDALDataset::RasterInitialize(int nXSize, int nYSize)
761 :
762 : {
763 0 : CPLAssert(nXSize > 0 && nYSize > 0);
764 :
765 0 : nRasterXSize = nXSize;
766 0 : nRasterYSize = nYSize;
767 0 : }
768 :
769 : //! @endcond
770 :
771 : /************************************************************************/
772 : /* AddBand() */
773 : /************************************************************************/
774 :
775 : /**
776 : * \fn GDALDataset::AddBand(GDALDataType, char**)
777 : * \brief Add a band to a dataset.
778 : *
779 : * This method will add a new band to the dataset if the underlying format
780 : * supports this action. Most formats do not.
781 : *
782 : * Note that the new GDALRasterBand is not returned. It may be fetched
783 : * after successful completion of the method by calling
784 : * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest
785 : * band will always be the last band.
786 : *
787 : * @param eType the data type of the pixels in the new band.
788 : *
789 : * @param papszOptions a list of NAME=VALUE option strings. The supported
790 : * options are format specific. NULL may be passed by default.
791 : *
792 : * @return CE_None on success or CE_Failure on failure.
793 : */
794 :
795 0 : CPLErr GDALDataset::AddBand(CPL_UNUSED GDALDataType eType,
796 : CPL_UNUSED char **papszOptions)
797 :
798 : {
799 0 : ReportError(CE_Failure, CPLE_NotSupported,
800 : "Dataset does not support the AddBand() method.");
801 :
802 0 : return CE_Failure;
803 : }
804 :
805 : /************************************************************************/
806 : /* GDALAddBand() */
807 : /************************************************************************/
808 :
809 : /**
810 : * \brief Add a band to a dataset.
811 : *
812 : * @see GDALDataset::AddBand().
813 : */
814 :
815 30 : CPLErr CPL_STDCALL GDALAddBand(GDALDatasetH hDataset, GDALDataType eType,
816 : CSLConstList papszOptions)
817 :
818 : {
819 30 : VALIDATE_POINTER1(hDataset, "GDALAddBand", CE_Failure);
820 :
821 60 : return GDALDataset::FromHandle(hDataset)->AddBand(
822 30 : eType, const_cast<char **>(papszOptions));
823 : }
824 :
825 : /************************************************************************/
826 : /* SetBand() */
827 : /************************************************************************/
828 :
829 : //! @cond Doxygen_Suppress
830 : /** Set a band in the band array, updating the band count, and array size
831 : * appropriately.
832 : *
833 : * @param nNewBand new band number (indexing starts at 1)
834 : * @param poBand band object.
835 : */
836 :
837 1742000 : void GDALDataset::SetBand(int nNewBand, GDALRasterBand *poBand)
838 :
839 : {
840 : /* -------------------------------------------------------------------- */
841 : /* Do we need to grow the bands list? */
842 : /* -------------------------------------------------------------------- */
843 1742000 : if (nBands < nNewBand || papoBands == nullptr)
844 : {
845 1008500 : GDALRasterBand **papoNewBands = nullptr;
846 :
847 1008500 : if (papoBands == nullptr)
848 93807 : papoNewBands = static_cast<GDALRasterBand **>(VSICalloc(
849 93788 : sizeof(GDALRasterBand *), std::max(nNewBand, nBands)));
850 : else
851 : papoNewBands = static_cast<GDALRasterBand **>(
852 914639 : VSIRealloc(papoBands, sizeof(GDALRasterBand *) *
853 914708 : std::max(nNewBand, nBands)));
854 1008450 : if (papoNewBands == nullptr)
855 : {
856 0 : ReportError(CE_Failure, CPLE_OutOfMemory,
857 : "Cannot allocate band array");
858 0 : return;
859 : }
860 :
861 1008450 : papoBands = papoNewBands;
862 :
863 1967380 : for (int i = nBands; i < nNewBand; ++i)
864 958931 : papoBands[i] = nullptr;
865 :
866 1008450 : nBands = std::max(nBands, nNewBand);
867 :
868 1008480 : if (m_poPrivate)
869 : {
870 1008960 : for (int i = static_cast<int>(m_poPrivate->m_anBandMap.size());
871 2750220 : i < nBands; ++i)
872 : {
873 1741640 : m_poPrivate->m_anBandMap.push_back(i + 1);
874 : }
875 : }
876 : }
877 :
878 : /* -------------------------------------------------------------------- */
879 : /* Set the band. Resetting the band is currently not permitted. */
880 : /* -------------------------------------------------------------------- */
881 1741600 : if (papoBands[nNewBand - 1] != nullptr)
882 : {
883 0 : ReportError(CE_Failure, CPLE_NotSupported,
884 : "Cannot set band %d as it is already set", nNewBand);
885 0 : return;
886 : }
887 :
888 1741600 : papoBands[nNewBand - 1] = poBand;
889 :
890 : /* -------------------------------------------------------------------- */
891 : /* Set back reference information on the raster band. Note */
892 : /* that the GDALDataset is a friend of the GDALRasterBand */
893 : /* specifically to allow this. */
894 : /* -------------------------------------------------------------------- */
895 1741600 : poBand->nBand = nNewBand;
896 1741600 : poBand->poDS = this;
897 1741600 : poBand->nRasterXSize = nRasterXSize;
898 1741600 : poBand->nRasterYSize = nRasterYSize;
899 1741600 : poBand->eAccess = eAccess; // Default access to be same as dataset.
900 : }
901 :
902 : //! @endcond
903 :
904 : /************************************************************************/
905 : /* SetBand() */
906 : /************************************************************************/
907 :
908 : //! @cond Doxygen_Suppress
909 : /** Set a band in the band array, updating the band count, and array size
910 : * appropriately.
911 : *
912 : * @param nNewBand new band number (indexing starts at 1)
913 : * @param poBand band object.
914 : */
915 :
916 76283 : void GDALDataset::SetBand(int nNewBand, std::unique_ptr<GDALRasterBand> poBand)
917 : {
918 76283 : SetBand(nNewBand, poBand.release());
919 76282 : }
920 :
921 : //! @endcond
922 :
923 : /************************************************************************/
924 : /* GetRasterXSize() */
925 : /************************************************************************/
926 :
927 : /**
928 :
929 : \brief Fetch raster width in pixels.
930 :
931 : Equivalent of the C function GDALGetRasterXSize().
932 :
933 : @return the width in pixels of raster bands in this GDALDataset.
934 :
935 : */
936 :
937 703372 : int GDALDataset::GetRasterXSize() const
938 : {
939 703372 : return nRasterXSize;
940 : }
941 :
942 : /************************************************************************/
943 : /* GDALGetRasterXSize() */
944 : /************************************************************************/
945 :
946 : /**
947 : * \brief Fetch raster width in pixels.
948 : *
949 : * @see GDALDataset::GetRasterXSize().
950 : */
951 :
952 36337 : int CPL_STDCALL GDALGetRasterXSize(GDALDatasetH hDataset)
953 :
954 : {
955 36337 : VALIDATE_POINTER1(hDataset, "GDALGetRasterXSize", 0);
956 :
957 36337 : return GDALDataset::FromHandle(hDataset)->GetRasterXSize();
958 : }
959 :
960 : /************************************************************************/
961 : /* GetRasterYSize() */
962 : /************************************************************************/
963 :
964 : /**
965 :
966 : \brief Fetch raster height in pixels.
967 :
968 : Equivalent of the C function GDALGetRasterYSize().
969 :
970 : @return the height in pixels of raster bands in this GDALDataset.
971 :
972 : */
973 :
974 584699 : int GDALDataset::GetRasterYSize() const
975 : {
976 584699 : return nRasterYSize;
977 : }
978 :
979 : /************************************************************************/
980 : /* GDALGetRasterYSize() */
981 : /************************************************************************/
982 :
983 : /**
984 : * \brief Fetch raster height in pixels.
985 : *
986 : * @see GDALDataset::GetRasterYSize().
987 : */
988 :
989 36001 : int CPL_STDCALL GDALGetRasterYSize(GDALDatasetH hDataset)
990 :
991 : {
992 36001 : VALIDATE_POINTER1(hDataset, "GDALGetRasterYSize", 0);
993 :
994 36001 : return GDALDataset::FromHandle(hDataset)->GetRasterYSize();
995 : }
996 :
997 : /************************************************************************/
998 : /* GetRasterBand() */
999 : /************************************************************************/
1000 :
1001 : /**
1002 :
1003 : \brief Fetch a band object for a dataset.
1004 :
1005 : See GetBands() for a C++ iterator version of this method.
1006 :
1007 : Equivalent of the C function GDALGetRasterBand().
1008 :
1009 : @param nBandId the index number of the band to fetch, from 1 to
1010 : GetRasterCount().
1011 :
1012 : @return the nBandId th band object
1013 :
1014 : */
1015 :
1016 12497100 : GDALRasterBand *GDALDataset::GetRasterBand(int nBandId)
1017 :
1018 : {
1019 12497100 : if (papoBands)
1020 : {
1021 12482200 : if (nBandId < 1 || nBandId > nBands)
1022 : {
1023 8545 : ReportError(CE_Failure, CPLE_IllegalArg,
1024 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1025 : nBandId);
1026 12 : return nullptr;
1027 : }
1028 :
1029 12473600 : return papoBands[nBandId - 1];
1030 : }
1031 14938 : return nullptr;
1032 : }
1033 :
1034 : /************************************************************************/
1035 : /* GetRasterBand() */
1036 : /************************************************************************/
1037 :
1038 : /**
1039 :
1040 : \brief Fetch a band object for a dataset.
1041 :
1042 : See GetBands() for a C++ iterator version of this method.
1043 :
1044 : Equivalent of the C function GDALGetRasterBand().
1045 :
1046 : @param nBandId the index number of the band to fetch, from 1 to
1047 : GetRasterCount().
1048 :
1049 : @return the nBandId th band object
1050 :
1051 : */
1052 :
1053 367 : const GDALRasterBand *GDALDataset::GetRasterBand(int nBandId) const
1054 :
1055 : {
1056 367 : if (papoBands)
1057 : {
1058 367 : if (nBandId < 1 || nBandId > nBands)
1059 : {
1060 0 : ReportError(CE_Failure, CPLE_IllegalArg,
1061 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1062 : nBandId);
1063 0 : return nullptr;
1064 : }
1065 :
1066 367 : return papoBands[nBandId - 1];
1067 : }
1068 0 : return nullptr;
1069 : }
1070 :
1071 : /************************************************************************/
1072 : /* GDALGetRasterBand() */
1073 : /************************************************************************/
1074 :
1075 : /**
1076 : * \brief Fetch a band object for a dataset.
1077 : * @see GDALDataset::GetRasterBand().
1078 : */
1079 :
1080 396739 : GDALRasterBandH CPL_STDCALL GDALGetRasterBand(GDALDatasetH hDS, int nBandId)
1081 :
1082 : {
1083 396739 : VALIDATE_POINTER1(hDS, "GDALGetRasterBand", nullptr);
1084 :
1085 396739 : return GDALRasterBand::ToHandle(
1086 396738 : GDALDataset::FromHandle(hDS)->GetRasterBand(nBandId));
1087 : }
1088 :
1089 : /************************************************************************/
1090 : /* GetRasterCount() */
1091 : /************************************************************************/
1092 :
1093 : /**
1094 : * \brief Fetch the number of raster bands on this dataset.
1095 : *
1096 : * Same as the C function GDALGetRasterCount().
1097 : *
1098 : * @return the number of raster bands.
1099 : */
1100 :
1101 6137510 : int GDALDataset::GetRasterCount() const
1102 : {
1103 6137510 : return papoBands ? nBands : 0;
1104 : }
1105 :
1106 : /************************************************************************/
1107 : /* GDALGetRasterCount() */
1108 : /************************************************************************/
1109 :
1110 : /**
1111 : * \brief Fetch the number of raster bands on this dataset.
1112 : *
1113 : * @see GDALDataset::GetRasterCount().
1114 : */
1115 :
1116 380804 : int CPL_STDCALL GDALGetRasterCount(GDALDatasetH hDS)
1117 :
1118 : {
1119 380804 : VALIDATE_POINTER1(hDS, "GDALGetRasterCount", 0);
1120 :
1121 380804 : return GDALDataset::FromHandle(hDS)->GetRasterCount();
1122 : }
1123 :
1124 : /************************************************************************/
1125 : /* GetProjectionRef() */
1126 : /************************************************************************/
1127 :
1128 : /**
1129 : * \brief Fetch the projection definition string for this dataset.
1130 : *
1131 : * Same as the C function GDALGetProjectionRef().
1132 : *
1133 : * The returned string defines the projection coordinate system of the
1134 : * image in OpenGIS WKT format. It should be suitable for use with the
1135 : * OGRSpatialReference class.
1136 : *
1137 : * When a projection definition is not available an empty (but not NULL)
1138 : * string is returned.
1139 : *
1140 : * \note Starting with GDAL 3.0, this is a compatibility layer around
1141 : * GetSpatialRef()
1142 : *
1143 : * @return a pointer to an internal projection reference string. It should
1144 : * not be altered, freed or expected to last for long.
1145 : *
1146 : * @see https://gdal.org/tutorials/osr_api_tut.html
1147 : */
1148 :
1149 5434 : const char *GDALDataset::GetProjectionRef() const
1150 : {
1151 5434 : const auto poSRS = GetSpatialRef();
1152 5434 : if (!poSRS || !m_poPrivate)
1153 : {
1154 2444 : return "";
1155 : }
1156 2990 : char *pszWKT = nullptr;
1157 2990 : poSRS->exportToWkt(&pszWKT);
1158 2990 : if (!pszWKT)
1159 : {
1160 0 : return "";
1161 : }
1162 :
1163 : // If called on a thread-safe dataset, we might be called by several
1164 : // threads, so make sure our accesses to m_pszWKTCached are protected
1165 : // by a mutex.
1166 5980 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1167 2990 : if (m_poPrivate->m_pszWKTCached &&
1168 822 : strcmp(pszWKT, m_poPrivate->m_pszWKTCached) == 0)
1169 : {
1170 821 : CPLFree(pszWKT);
1171 821 : return m_poPrivate->m_pszWKTCached;
1172 : }
1173 2169 : CPLFree(m_poPrivate->m_pszWKTCached);
1174 2169 : m_poPrivate->m_pszWKTCached = pszWKT;
1175 2169 : return m_poPrivate->m_pszWKTCached;
1176 : }
1177 :
1178 : /************************************************************************/
1179 : /* GetSpatialRef() */
1180 : /************************************************************************/
1181 :
1182 : /**
1183 : * \brief Fetch the spatial reference for this dataset.
1184 : *
1185 : * Same as the C function GDALGetSpatialRef().
1186 : *
1187 : * When a projection definition is not available, null is returned. If used on
1188 : * a dataset where there are GCPs and not a geotransform, this method returns
1189 : * null. Use GetGCPSpatialRef() instead.
1190 : *
1191 : * @since GDAL 3.0
1192 : *
1193 : * @return a pointer to an internal object. It should not be altered or freed.
1194 : * Its lifetime will be the one of the dataset object, or until the next
1195 : * call to this method.
1196 : *
1197 : * @see https://gdal.org/tutorials/osr_api_tut.html
1198 : */
1199 :
1200 16962 : const OGRSpatialReference *GDALDataset::GetSpatialRef() const
1201 : {
1202 16962 : return nullptr;
1203 : }
1204 :
1205 : /************************************************************************/
1206 : /* GDALGetSpatialRef() */
1207 : /************************************************************************/
1208 :
1209 : /**
1210 : * \brief Fetch the spatial reference for this dataset.
1211 : *
1212 : * @since GDAL 3.0
1213 : *
1214 : * @see GDALDataset::GetSpatialRef()
1215 : */
1216 :
1217 6503 : OGRSpatialReferenceH GDALGetSpatialRef(GDALDatasetH hDS)
1218 :
1219 : {
1220 6503 : VALIDATE_POINTER1(hDS, "GDALGetSpatialRef", nullptr);
1221 :
1222 6503 : return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1223 6503 : GDALDataset::FromHandle(hDS)->GetSpatialRef()));
1224 : }
1225 :
1226 : /************************************************************************/
1227 : /* GDALGetProjectionRef() */
1228 : /************************************************************************/
1229 :
1230 : /**
1231 : * \brief Fetch the projection definition string for this dataset.
1232 : *
1233 : * @see GDALDataset::GetProjectionRef()
1234 : */
1235 :
1236 1479 : const char *CPL_STDCALL GDALGetProjectionRef(GDALDatasetH hDS)
1237 :
1238 : {
1239 1479 : VALIDATE_POINTER1(hDS, "GDALGetProjectionRef", nullptr);
1240 :
1241 1479 : return GDALDataset::FromHandle(hDS)->GetProjectionRef();
1242 : }
1243 :
1244 : /************************************************************************/
1245 : /* SetProjection() */
1246 : /************************************************************************/
1247 :
1248 : /**
1249 : * \brief Set the projection reference string for this dataset.
1250 : *
1251 : * The string should be in OGC WKT or PROJ.4 format. An error may occur
1252 : * because of incorrectly specified projection strings, because the dataset
1253 : * is not writable, or because the dataset does not support the indicated
1254 : * projection. Many formats do not support writing projections.
1255 : *
1256 : * This method is the same as the C GDALSetProjection() function.
1257 : *
1258 : * \note Startig with GDAL 3.0, this is a compatibility layer around
1259 : * SetSpatialRef()
1260 :
1261 : * @param pszProjection projection reference string.
1262 : *
1263 : * @return CE_Failure if an error occurs, otherwise CE_None.
1264 : */
1265 :
1266 2385 : CPLErr GDALDataset::SetProjection(const char *pszProjection)
1267 : {
1268 2385 : if (pszProjection && pszProjection[0] != '\0')
1269 : {
1270 4404 : OGRSpatialReference oSRS;
1271 2202 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1272 2202 : if (oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE)
1273 : {
1274 2 : return CE_Failure;
1275 : }
1276 2200 : return SetSpatialRef(&oSRS);
1277 : }
1278 : else
1279 : {
1280 183 : return SetSpatialRef(nullptr);
1281 : }
1282 : }
1283 :
1284 : /************************************************************************/
1285 : /* SetSpatialRef() */
1286 : /************************************************************************/
1287 :
1288 : /**
1289 : * \brief Set the spatial reference system for this dataset.
1290 : *
1291 : * An error may occur because the dataset
1292 : * is not writable, or because the dataset does not support the indicated
1293 : * projection. Many formats do not support writing projections.
1294 : *
1295 : * This method is the same as the C GDALSetSpatialRef() function.
1296 : *
1297 : * @since GDAL 3.0
1298 :
1299 : * @param poSRS spatial reference system object. nullptr can potentially be
1300 : * passed for drivers that support unsetting the SRS.
1301 : *
1302 : * @return CE_Failure if an error occurs, otherwise CE_None.
1303 : */
1304 :
1305 0 : CPLErr GDALDataset::SetSpatialRef(CPL_UNUSED const OGRSpatialReference *poSRS)
1306 : {
1307 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1308 0 : ReportError(CE_Failure, CPLE_NotSupported,
1309 : "Dataset does not support the SetSpatialRef() method.");
1310 0 : return CE_Failure;
1311 : }
1312 :
1313 : /************************************************************************/
1314 : /* GDALSetSpatialRef() */
1315 : /************************************************************************/
1316 :
1317 : /**
1318 : * \brief Set the spatial reference system for this dataset.
1319 : *
1320 : * @since GDAL 3.0
1321 : *
1322 : * @see GDALDataset::SetSpatialRef()
1323 : */
1324 :
1325 1110 : CPLErr GDALSetSpatialRef(GDALDatasetH hDS, OGRSpatialReferenceH hSRS)
1326 :
1327 : {
1328 1110 : VALIDATE_POINTER1(hDS, "GDALSetSpatialRef", CE_Failure);
1329 :
1330 2220 : return GDALDataset::FromHandle(hDS)->SetSpatialRef(
1331 1110 : OGRSpatialReference::FromHandle(hSRS));
1332 : }
1333 :
1334 : /************************************************************************/
1335 : /* GDALSetProjection() */
1336 : /************************************************************************/
1337 :
1338 : /**
1339 : * \brief Set the projection reference string for this dataset.
1340 : *
1341 : * @see GDALDataset::SetProjection()
1342 : */
1343 :
1344 1778 : CPLErr CPL_STDCALL GDALSetProjection(GDALDatasetH hDS,
1345 : const char *pszProjection)
1346 :
1347 : {
1348 1778 : VALIDATE_POINTER1(hDS, "GDALSetProjection", CE_Failure);
1349 :
1350 1778 : return GDALDataset::FromHandle(hDS)->SetProjection(pszProjection);
1351 : }
1352 :
1353 : /************************************************************************/
1354 : /* GetGeoTransform() */
1355 : /************************************************************************/
1356 :
1357 : /**
1358 : * \brief Fetch the affine transformation coefficients.
1359 : *
1360 : * Fetches the coefficients for transforming between pixel/line (P,L) raster
1361 : * space, and projection coordinates (Xp,Yp) space.
1362 : *
1363 : * \code
1364 : * Xp = gt[0] + P*gt[1] + L*gt[2];
1365 : * Yp = gt[3] + P*padfTransform[4] + L*gt[5];
1366 : * \endcode
1367 : *
1368 : * In a north up image, gt[1] is the pixel width, and
1369 : * gt[5] is the pixel height. The upper left corner of the
1370 : * upper left pixel is at position (gt[0],gt[3]).
1371 : *
1372 : * The default transform is (0,1,0,0,0,1) and should be returned even when
1373 : * a CE_Failure error is returned, such as for formats that don't support
1374 : * transformation to projection coordinates.
1375 : *
1376 : * This method does the same thing as the C GDALGetGeoTransform() function.
1377 : *
1378 : * @param gt an existing six double buffer into which the
1379 : * transformation will be placed.
1380 : *
1381 : * @return CE_None on success, or CE_Failure if no transform can be fetched.
1382 : *
1383 : * @since 3.12
1384 : */
1385 :
1386 15457 : CPLErr GDALDataset::GetGeoTransform(GDALGeoTransform >) const
1387 :
1388 : {
1389 15457 : gt = GDALGeoTransform();
1390 :
1391 15457 : return CE_Failure;
1392 : }
1393 :
1394 : /************************************************************************/
1395 : /* GetGeoTransform() */
1396 : /************************************************************************/
1397 :
1398 : /**
1399 : * \brief Fetch the affine transformation coefficients.
1400 : *
1401 : * Fetches the coefficients for transforming between pixel/line (P,L) raster
1402 : * space, and projection coordinates (Xp,Yp) space.
1403 : *
1404 : * \code
1405 : * Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
1406 : * Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
1407 : * \endcode
1408 : *
1409 : * In a north up image, padfTransform[1] is the pixel width, and
1410 : * padfTransform[5] is the pixel height. The upper left corner of the
1411 : * upper left pixel is at position (padfTransform[0],padfTransform[3]).
1412 : *
1413 : * The default transform is (0,1,0,0,0,1) and should be returned even when
1414 : * a CE_Failure error is returned, such as for formats that don't support
1415 : * transformation to projection coordinates.
1416 : *
1417 : * This method does the same thing as the C GDALGetGeoTransform() function.
1418 : *
1419 : * @param padfTransform an existing six double buffer into which the
1420 : * transformation will be placed.
1421 : *
1422 : * @return CE_None on success, or CE_Failure if no transform can be fetched.
1423 : *
1424 : * @deprecated since 3.12. Use GetGeoTransform(GDALGeoTransform&) instead
1425 : */
1426 :
1427 2 : CPLErr GDALDataset::GetGeoTransform(double *padfTransform) const
1428 :
1429 : {
1430 2 : return GetGeoTransform(
1431 2 : *reinterpret_cast<GDALGeoTransform *>(padfTransform));
1432 : }
1433 :
1434 : /************************************************************************/
1435 : /* GDALGetGeoTransform() */
1436 : /************************************************************************/
1437 :
1438 : /**
1439 : * \brief Fetch the affine transformation coefficients.
1440 : *
1441 : * @see GDALDataset::GetGeoTransform()
1442 : */
1443 :
1444 8485 : CPLErr CPL_STDCALL GDALGetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1445 :
1446 : {
1447 8485 : VALIDATE_POINTER1(hDS, "GDALGetGeoTransform", CE_Failure);
1448 :
1449 16970 : return GDALDataset::FromHandle(hDS)->GetGeoTransform(
1450 8485 : *reinterpret_cast<GDALGeoTransform *>(padfTransform));
1451 : }
1452 :
1453 : /************************************************************************/
1454 : /* SetGeoTransform() */
1455 : /************************************************************************/
1456 :
1457 : /**
1458 : * \fn GDALDataset::SetGeoTransform(const GDALGeoTransform&)
1459 : * \brief Set the affine transformation coefficients.
1460 : *
1461 : * See GetGeoTransform() for details on the meaning of the padfTransform
1462 : * coefficients.
1463 : *
1464 : * This method does the same thing as the C GDALSetGeoTransform() function.
1465 : *
1466 : * @param gt the transformation coefficients to be written with the dataset.
1467 : *
1468 : * @return CE_None on success, or CE_Failure if this transform cannot be
1469 : * written.
1470 : *
1471 : * @since 3.12
1472 : */
1473 :
1474 0 : CPLErr GDALDataset::SetGeoTransform(CPL_UNUSED const GDALGeoTransform >)
1475 :
1476 : {
1477 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1478 0 : ReportError(CE_Failure, CPLE_NotSupported,
1479 : "SetGeoTransform() not supported for this dataset.");
1480 :
1481 0 : return CE_Failure;
1482 : }
1483 :
1484 : /************************************************************************/
1485 : /* SetGeoTransform() */
1486 : /************************************************************************/
1487 :
1488 : /**
1489 : * \brief Set the affine transformation coefficients.
1490 : *
1491 : * See GetGeoTransform() for details on the meaning of the padfTransform
1492 : * coefficients.
1493 : *
1494 : * This method does the same thing as the C GDALSetGeoTransform() function.
1495 : *
1496 : * @param padfTransform a six double buffer containing the transformation
1497 : * coefficients to be written with the dataset.
1498 : *
1499 : * @return CE_None on success, or CE_Failure if this transform cannot be
1500 : * written.
1501 : *
1502 : * @deprecated since 3.12. Use SetGeoTransform(const GDALGeoTransform&) instead
1503 : */
1504 30 : CPLErr GDALDataset::SetGeoTransform(const double *padfTransform)
1505 :
1506 : {
1507 30 : return SetGeoTransform(
1508 30 : *reinterpret_cast<const GDALGeoTransform *>(padfTransform));
1509 : }
1510 :
1511 : /************************************************************************/
1512 : /* GDALSetGeoTransform() */
1513 : /************************************************************************/
1514 :
1515 : /**
1516 : * \brief Set the affine transformation coefficients.
1517 : *
1518 : * @see GDALDataset::SetGeoTransform()
1519 : */
1520 :
1521 3853 : CPLErr CPL_STDCALL GDALSetGeoTransform(GDALDatasetH hDS,
1522 : const double *padfTransform)
1523 :
1524 : {
1525 3853 : VALIDATE_POINTER1(hDS, "GDALSetGeoTransform", CE_Failure);
1526 3853 : VALIDATE_POINTER1(padfTransform, "GDALSetGeoTransform", CE_Failure);
1527 :
1528 7706 : return GDALDataset::FromHandle(hDS)->SetGeoTransform(
1529 3853 : *reinterpret_cast<const GDALGeoTransform *>(padfTransform));
1530 : }
1531 :
1532 : /************************************************************************/
1533 : /* GetInternalHandle() */
1534 : /************************************************************************/
1535 :
1536 : /**
1537 : * \fn GDALDataset::GetInternalHandle(const char*)
1538 : * \brief Fetch a format specific internally meaningful handle.
1539 : *
1540 : * This method is the same as the C GDALGetInternalHandle() method.
1541 : *
1542 : * @param pszHandleName the handle name desired. The meaningful names
1543 : * will be specific to the file format.
1544 : *
1545 : * @return the desired handle value, or NULL if not recognized/supported.
1546 : */
1547 :
1548 184 : void *GDALDataset::GetInternalHandle(CPL_UNUSED const char *pszHandleName)
1549 :
1550 : {
1551 184 : return nullptr;
1552 : }
1553 :
1554 : /************************************************************************/
1555 : /* GDALGetInternalHandle() */
1556 : /************************************************************************/
1557 :
1558 : /**
1559 : * \brief Fetch a format specific internally meaningful handle.
1560 : *
1561 : * @see GDALDataset::GetInternalHandle()
1562 : */
1563 :
1564 60 : void *CPL_STDCALL GDALGetInternalHandle(GDALDatasetH hDS,
1565 : const char *pszRequest)
1566 :
1567 : {
1568 60 : VALIDATE_POINTER1(hDS, "GDALGetInternalHandle", nullptr);
1569 :
1570 60 : return GDALDataset::FromHandle(hDS)->GetInternalHandle(pszRequest);
1571 : }
1572 :
1573 : /************************************************************************/
1574 : /* GetDriver() */
1575 : /************************************************************************/
1576 :
1577 : /**
1578 : * \brief Fetch the driver to which this dataset relates.
1579 : *
1580 : * This method is the same as the C GDALGetDatasetDriver() function.
1581 : *
1582 : * @return the driver on which the dataset was created with GDALOpen() or
1583 : * GDALCreate().
1584 : */
1585 :
1586 30365 : GDALDriver *GDALDataset::GetDriver()
1587 : {
1588 30365 : return poDriver;
1589 : }
1590 :
1591 : /************************************************************************/
1592 : /* GDALGetDatasetDriver() */
1593 : /************************************************************************/
1594 :
1595 : /**
1596 : * \brief Fetch the driver to which this dataset relates.
1597 : *
1598 : * @see GDALDataset::GetDriver()
1599 : */
1600 :
1601 2680 : GDALDriverH CPL_STDCALL GDALGetDatasetDriver(GDALDatasetH hDataset)
1602 :
1603 : {
1604 2680 : VALIDATE_POINTER1(hDataset, "GDALGetDatasetDriver", nullptr);
1605 :
1606 : return static_cast<GDALDriverH>(
1607 2680 : GDALDataset::FromHandle(hDataset)->GetDriver());
1608 : }
1609 :
1610 : /************************************************************************/
1611 : /* Reference() */
1612 : /************************************************************************/
1613 :
1614 : /**
1615 : * \brief Add one to dataset reference count.
1616 : *
1617 : * The reference is one after instantiation.
1618 : *
1619 : * This method is the same as the C GDALReferenceDataset() function.
1620 : *
1621 : * @return the post-increment reference count.
1622 : */
1623 :
1624 254272 : int GDALDataset::Reference()
1625 : {
1626 254272 : return ++nRefCount;
1627 : }
1628 :
1629 : /************************************************************************/
1630 : /* GDALReferenceDataset() */
1631 : /************************************************************************/
1632 :
1633 : /**
1634 : * \brief Add one to dataset reference count.
1635 : *
1636 : * @see GDALDataset::Reference()
1637 : */
1638 :
1639 1220 : int CPL_STDCALL GDALReferenceDataset(GDALDatasetH hDataset)
1640 :
1641 : {
1642 1220 : VALIDATE_POINTER1(hDataset, "GDALReferenceDataset", 0);
1643 :
1644 1220 : return GDALDataset::FromHandle(hDataset)->Reference();
1645 : }
1646 :
1647 : /************************************************************************/
1648 : /* Dereference() */
1649 : /************************************************************************/
1650 :
1651 : /**
1652 : * \brief Subtract one from dataset reference count.
1653 : *
1654 : * The reference is one after instantiation. Generally when the reference
1655 : * count has dropped to zero the dataset may be safely deleted (closed).
1656 : *
1657 : * This method is the same as the C GDALDereferenceDataset() function.
1658 : *
1659 : * @return the post-decrement reference count.
1660 : */
1661 :
1662 311322 : int GDALDataset::Dereference()
1663 : {
1664 311322 : return --nRefCount;
1665 : }
1666 :
1667 : /************************************************************************/
1668 : /* GDALDereferenceDataset() */
1669 : /************************************************************************/
1670 :
1671 : /**
1672 : * \brief Subtract one from dataset reference count.
1673 : *
1674 : * @see GDALDataset::Dereference()
1675 : */
1676 :
1677 56141 : int CPL_STDCALL GDALDereferenceDataset(GDALDatasetH hDataset)
1678 :
1679 : {
1680 56141 : VALIDATE_POINTER1(hDataset, "GDALDereferenceDataset", 0);
1681 :
1682 56141 : return GDALDataset::FromHandle(hDataset)->Dereference();
1683 : }
1684 :
1685 : /************************************************************************/
1686 : /* ReleaseRef() */
1687 : /************************************************************************/
1688 :
1689 : /**
1690 : * \brief Drop a reference to this object, and destroy if no longer referenced.
1691 : * @return TRUE if the object has been destroyed.
1692 : * @since GDAL 2.2
1693 : */
1694 :
1695 250058 : int GDALDataset::ReleaseRef()
1696 :
1697 : {
1698 250058 : if (Dereference() <= 0)
1699 : {
1700 6977 : nRefCount = 1;
1701 6977 : delete this;
1702 6977 : return TRUE;
1703 : }
1704 243081 : return FALSE;
1705 : }
1706 :
1707 : /************************************************************************/
1708 : /* GDALReleaseDataset() */
1709 : /************************************************************************/
1710 :
1711 : /**
1712 : * \brief Drop a reference to this object, and destroy if no longer referenced.
1713 : *
1714 : * @see GDALDataset::ReleaseRef()
1715 : * @since GDAL 2.2
1716 : */
1717 :
1718 1458 : int CPL_STDCALL GDALReleaseDataset(GDALDatasetH hDataset)
1719 :
1720 : {
1721 1458 : VALIDATE_POINTER1(hDataset, "GDALReleaseDataset", 0);
1722 :
1723 1458 : return GDALDataset::FromHandle(hDataset)->ReleaseRef();
1724 : }
1725 :
1726 : /************************************************************************/
1727 : /* GetShared() */
1728 : /************************************************************************/
1729 :
1730 : /**
1731 : * \brief Returns shared flag.
1732 : *
1733 : * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
1734 : */
1735 :
1736 306227 : int GDALDataset::GetShared() const
1737 : {
1738 306227 : return bShared;
1739 : }
1740 :
1741 : /************************************************************************/
1742 : /* MarkAsShared() */
1743 : /************************************************************************/
1744 :
1745 : /**
1746 : * \brief Mark this dataset as available for sharing.
1747 : */
1748 :
1749 409 : void GDALDataset::MarkAsShared()
1750 :
1751 : {
1752 409 : CPLAssert(!bShared);
1753 :
1754 409 : bShared = true;
1755 409 : if (bIsInternal)
1756 14 : return;
1757 :
1758 395 : GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
1759 :
1760 : // Insert the dataset in the set of shared opened datasets.
1761 790 : CPLMutexHolderD(&hDLMutex);
1762 395 : if (phSharedDatasetSet == nullptr)
1763 267 : phSharedDatasetSet =
1764 267 : CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc,
1765 : GDALSharedDatasetFreeFunc);
1766 :
1767 : SharedDatasetCtxt *psStruct =
1768 395 : static_cast<SharedDatasetCtxt *>(CPLMalloc(sizeof(SharedDatasetCtxt)));
1769 395 : psStruct->poDS = this;
1770 395 : psStruct->nPID = nPID;
1771 395 : psStruct->nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
1772 395 : psStruct->pszDescription = CPLStrdup(GetDescription());
1773 : std::string osConcatenatedOpenOptions =
1774 790 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
1775 395 : psStruct->pszConcatenatedOpenOptions =
1776 395 : CPLStrdup(osConcatenatedOpenOptions.c_str());
1777 395 : if (CPLHashSetLookup(phSharedDatasetSet, psStruct) != nullptr)
1778 : {
1779 1 : GDALSharedDatasetFreeFunc(psStruct);
1780 1 : ReportError(CE_Failure, CPLE_AppDefined,
1781 : "An existing shared dataset already has this description. "
1782 : "This should not happen.");
1783 : }
1784 : else
1785 : {
1786 394 : CPLHashSetInsert(phSharedDatasetSet, psStruct);
1787 :
1788 394 : (*poAllDatasetMap)[this] = nPID;
1789 : }
1790 : }
1791 :
1792 : /************************************************************************/
1793 : /* MarkSuppressOnClose() */
1794 : /************************************************************************/
1795 :
1796 : /** Set that the dataset must be deleted on close. */
1797 1165 : void GDALDataset::MarkSuppressOnClose()
1798 : {
1799 1165 : bSuppressOnClose = true;
1800 1165 : }
1801 :
1802 : /************************************************************************/
1803 : /* UnMarkSuppressOnClose() */
1804 : /************************************************************************/
1805 :
1806 : /** Remove the flag requesting the dataset to be deleted on close. */
1807 1 : void GDALDataset::UnMarkSuppressOnClose()
1808 : {
1809 1 : bSuppressOnClose = false;
1810 1 : }
1811 :
1812 : /************************************************************************/
1813 : /* CleanupPostFileClosing() */
1814 : /************************************************************************/
1815 :
1816 : /** This method should be called by driver implementations in their destructor,
1817 : * after having closed all files, but before having freed resources that
1818 : * are needed for their GetFileList() implementation.
1819 : * This is used to implement MarkSuppressOnClose behavior.
1820 : */
1821 253 : void GDALDataset::CleanupPostFileClosing()
1822 : {
1823 253 : if (IsMarkedSuppressOnClose())
1824 : {
1825 1 : char **papszFileList = GetFileList();
1826 3 : for (int i = 0; papszFileList && papszFileList[i]; ++i)
1827 2 : VSIUnlink(papszFileList[i]);
1828 1 : CSLDestroy(papszFileList);
1829 : }
1830 253 : }
1831 :
1832 : /************************************************************************/
1833 : /* GetGCPCount() */
1834 : /************************************************************************/
1835 :
1836 : /**
1837 : * \brief Get number of GCPs.
1838 : *
1839 : * This method is the same as the C function GDALGetGCPCount().
1840 : *
1841 : * @return number of GCPs for this dataset. Zero if there are none.
1842 : */
1843 :
1844 15954 : int GDALDataset::GetGCPCount()
1845 : {
1846 15954 : return 0;
1847 : }
1848 :
1849 : /************************************************************************/
1850 : /* GDALGetGCPCount() */
1851 : /************************************************************************/
1852 :
1853 : /**
1854 : * \brief Get number of GCPs.
1855 : *
1856 : * @see GDALDataset::GetGCPCount()
1857 : */
1858 :
1859 1185 : int CPL_STDCALL GDALGetGCPCount(GDALDatasetH hDS)
1860 :
1861 : {
1862 1185 : VALIDATE_POINTER1(hDS, "GDALGetGCPCount", 0);
1863 :
1864 1185 : return GDALDataset::FromHandle(hDS)->GetGCPCount();
1865 : }
1866 :
1867 : /************************************************************************/
1868 : /* GetGCPProjection() */
1869 : /************************************************************************/
1870 :
1871 : /**
1872 : * \brief Get output projection for GCPs.
1873 : *
1874 : * This method is the same as the C function GDALGetGCPProjection().
1875 : *
1876 : * The projection string follows the normal rules from GetProjectionRef().
1877 : *
1878 : * \note Starting with GDAL 3.0, this is a compatibility layer around
1879 : * GetGCPSpatialRef()
1880 : *
1881 : * @return internal projection string or "" if there are no GCPs.
1882 : * It should not be altered, freed or expected to last for long.
1883 : */
1884 :
1885 874 : const char *GDALDataset::GetGCPProjection()
1886 : {
1887 874 : const auto poSRS = GetGCPSpatialRef();
1888 874 : if (!poSRS || !m_poPrivate)
1889 : {
1890 537 : return "";
1891 : }
1892 337 : char *pszWKT = nullptr;
1893 337 : poSRS->exportToWkt(&pszWKT);
1894 337 : if (!pszWKT)
1895 : {
1896 0 : return "";
1897 : }
1898 :
1899 : // If called on a thread-safe dataset, we might be called by several
1900 : // threads, so make sure our accesses to m_pszWKTCached are protected
1901 : // by a mutex.
1902 674 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1903 337 : if (m_poPrivate->m_pszWKTGCPCached &&
1904 256 : strcmp(pszWKT, m_poPrivate->m_pszWKTGCPCached) == 0)
1905 : {
1906 256 : CPLFree(pszWKT);
1907 256 : return m_poPrivate->m_pszWKTGCPCached;
1908 : }
1909 81 : CPLFree(m_poPrivate->m_pszWKTGCPCached);
1910 81 : m_poPrivate->m_pszWKTGCPCached = pszWKT;
1911 81 : return m_poPrivate->m_pszWKTGCPCached;
1912 : }
1913 :
1914 : /************************************************************************/
1915 : /* GetGCPSpatialRef() */
1916 : /************************************************************************/
1917 :
1918 : /**
1919 : * \brief Get output spatial reference system for GCPs.
1920 : *
1921 : * Same as the C function GDALGetGCPSpatialRef().
1922 : *
1923 : * When a SRS is not available, null is returned. If used on
1924 : * a dataset where there is a geotransform, and not GCPs, this method returns
1925 : * null. Use GetSpatialRef() instead.
1926 : *
1927 : * @since GDAL 3.0
1928 : *
1929 : * @return a pointer to an internal object. It should not be altered or freed.
1930 : * Its lifetime will be the one of the dataset object, or until the next
1931 : * call to this method.
1932 : */
1933 :
1934 39 : const OGRSpatialReference *GDALDataset::GetGCPSpatialRef() const
1935 : {
1936 39 : return nullptr;
1937 : }
1938 :
1939 : /************************************************************************/
1940 : /* GDALGetGCPSpatialRef() */
1941 : /************************************************************************/
1942 :
1943 : /**
1944 : * \brief Get output spatial reference system for GCPs.
1945 : *
1946 : * @since GDAL 3.0
1947 : *
1948 : * @see GDALDataset::GetGCPSpatialRef()
1949 : */
1950 :
1951 468 : OGRSpatialReferenceH GDALGetGCPSpatialRef(GDALDatasetH hDS)
1952 :
1953 : {
1954 468 : VALIDATE_POINTER1(hDS, "GDALGetGCPSpatialRef", nullptr);
1955 :
1956 468 : return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1957 468 : GDALDataset::FromHandle(hDS)->GetGCPSpatialRef()));
1958 : }
1959 :
1960 : /************************************************************************/
1961 : /* GDALGetGCPProjection() */
1962 : /************************************************************************/
1963 :
1964 : /**
1965 : * \brief Get output projection for GCPs.
1966 : *
1967 : * @see GDALDataset::GetGCPProjection()
1968 : */
1969 :
1970 803 : const char *CPL_STDCALL GDALGetGCPProjection(GDALDatasetH hDS)
1971 :
1972 : {
1973 803 : VALIDATE_POINTER1(hDS, "GDALGetGCPProjection", nullptr);
1974 :
1975 803 : return GDALDataset::FromHandle(hDS)->GetGCPProjection();
1976 : }
1977 :
1978 : /************************************************************************/
1979 : /* GetGCPs() */
1980 : /************************************************************************/
1981 :
1982 : /**
1983 : * \brief Fetch GCPs.
1984 : *
1985 : * This method is the same as the C function GDALGetGCPs().
1986 : *
1987 : * @return pointer to internal GCP structure list. It should not be modified,
1988 : * and may change on the next GDAL call.
1989 : */
1990 :
1991 10 : const GDAL_GCP *GDALDataset::GetGCPs()
1992 : {
1993 10 : return nullptr;
1994 : }
1995 :
1996 : /************************************************************************/
1997 : /* GDALGetGCPs() */
1998 : /************************************************************************/
1999 :
2000 : /**
2001 : * \brief Fetch GCPs.
2002 : *
2003 : * @see GDALDataset::GetGCPs()
2004 : */
2005 :
2006 580 : const GDAL_GCP *CPL_STDCALL GDALGetGCPs(GDALDatasetH hDS)
2007 :
2008 : {
2009 580 : VALIDATE_POINTER1(hDS, "GDALGetGCPs", nullptr);
2010 :
2011 580 : return GDALDataset::FromHandle(hDS)->GetGCPs();
2012 : }
2013 :
2014 : /************************************************************************/
2015 : /* SetGCPs() */
2016 : /************************************************************************/
2017 :
2018 : /**
2019 : * \brief Assign GCPs.
2020 : *
2021 : * This method is the same as the C function GDALSetGCPs().
2022 : *
2023 : * This method assigns the passed set of GCPs to this dataset, as well as
2024 : * setting their coordinate system. Internally copies are made of the
2025 : * coordinate system and list of points, so the caller remains responsible for
2026 : * deallocating these arguments if appropriate.
2027 : *
2028 : * Most formats do not support setting of GCPs, even formats that can
2029 : * handle GCPs. These formats will return CE_Failure.
2030 : *
2031 : * \note Startig with GDAL 3.0, this is a compatibility layer around
2032 : * SetGCPs(int, const GDAL_GCP*, const char*)
2033 : *
2034 : * @param nGCPCount number of GCPs being assigned.
2035 : *
2036 : * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
2037 : *
2038 : * @param pszGCPProjection the new OGC WKT coordinate system to assign for the
2039 : * GCP output coordinates. This parameter should be "" if no output coordinate
2040 : * system is known.
2041 : *
2042 : * @return CE_None on success, CE_Failure on failure (including if action is
2043 : * not supported for this format).
2044 : */
2045 :
2046 53 : CPLErr GDALDataset::SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList,
2047 : const char *pszGCPProjection)
2048 :
2049 : {
2050 53 : if (pszGCPProjection && pszGCPProjection[0] != '\0')
2051 : {
2052 68 : OGRSpatialReference oSRS;
2053 34 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
2054 34 : if (oSRS.importFromWkt(pszGCPProjection) != OGRERR_NONE)
2055 : {
2056 0 : return CE_Failure;
2057 : }
2058 34 : return SetGCPs(nGCPCount, pasGCPList, &oSRS);
2059 : }
2060 : else
2061 : {
2062 19 : return SetGCPs(nGCPCount, pasGCPList,
2063 19 : static_cast<const OGRSpatialReference *>(nullptr));
2064 : }
2065 : }
2066 :
2067 : /************************************************************************/
2068 : /* SetGCPs() */
2069 : /************************************************************************/
2070 :
2071 : /**
2072 : * \brief Assign GCPs.
2073 : *
2074 : * This method is the same as the C function GDALSetGCPs().
2075 : *
2076 : * This method assigns the passed set of GCPs to this dataset, as well as
2077 : * setting their coordinate system. Internally copies are made of the
2078 : * coordinate system and list of points, so the caller remains responsible for
2079 : * deallocating these arguments if appropriate.
2080 : *
2081 : * Most formats do not support setting of GCPs, even formats that can
2082 : * handle GCPs. These formats will return CE_Failure.
2083 : *
2084 : * @since GDAL 3.0
2085 : *
2086 : * @param nGCPCount number of GCPs being assigned.
2087 : *
2088 : * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
2089 : *
2090 : * @param poGCP_SRS the new coordinate reference system to assign for the
2091 : * GCP output coordinates. This parameter should be null if no output
2092 : * coordinate system is known.
2093 : *
2094 : * @return CE_None on success, CE_Failure on failure (including if action is
2095 : * not supported for this format).
2096 : */
2097 :
2098 1 : CPLErr GDALDataset::SetGCPs(CPL_UNUSED int nGCPCount,
2099 : CPL_UNUSED const GDAL_GCP *pasGCPList,
2100 : CPL_UNUSED const OGRSpatialReference *poGCP_SRS)
2101 :
2102 : {
2103 1 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
2104 1 : ReportError(CE_Failure, CPLE_NotSupported,
2105 : "Dataset does not support the SetGCPs() method.");
2106 :
2107 1 : return CE_Failure;
2108 : }
2109 :
2110 : /************************************************************************/
2111 : /* GDALSetGCPs() */
2112 : /************************************************************************/
2113 :
2114 : /**
2115 : * \brief Assign GCPs.
2116 : *
2117 : * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const char*)
2118 : */
2119 :
2120 30 : CPLErr CPL_STDCALL GDALSetGCPs(GDALDatasetH hDS, int nGCPCount,
2121 : const GDAL_GCP *pasGCPList,
2122 : const char *pszGCPProjection)
2123 :
2124 : {
2125 30 : VALIDATE_POINTER1(hDS, "GDALSetGCPs", CE_Failure);
2126 :
2127 30 : return GDALDataset::FromHandle(hDS)->SetGCPs(nGCPCount, pasGCPList,
2128 30 : pszGCPProjection);
2129 : }
2130 :
2131 : /************************************************************************/
2132 : /* GDALSetGCPs2() */
2133 : /************************************************************************/
2134 :
2135 : /**
2136 : * \brief Assign GCPs.
2137 : *
2138 : * @since GDAL 3.0
2139 : * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const OGRSpatialReference*)
2140 : */
2141 :
2142 9 : CPLErr GDALSetGCPs2(GDALDatasetH hDS, int nGCPCount, const GDAL_GCP *pasGCPList,
2143 : OGRSpatialReferenceH hSRS)
2144 :
2145 : {
2146 9 : VALIDATE_POINTER1(hDS, "GDALSetGCPs2", CE_Failure);
2147 :
2148 18 : return GDALDataset::FromHandle(hDS)->SetGCPs(
2149 9 : nGCPCount, pasGCPList, OGRSpatialReference::FromHandle(hSRS));
2150 : }
2151 :
2152 : /************************************************************************/
2153 : /* BuildOverviews() */
2154 : /************************************************************************/
2155 :
2156 : /**
2157 : * \brief Build raster overview(s)
2158 : *
2159 : * If the operation is not supported for the indicated dataset, then
2160 : * CE_Failure is returned, and CPLGetLastErrorNo() will return
2161 : * CPLE_NotSupported.
2162 : *
2163 : * Depending on the actual file format, all overviews level can be also
2164 : * deleted by specifying nOverviews == 0. This works at least for external
2165 : * overviews (.ovr), TIFF internal overviews, etc.
2166 : *
2167 : * Starting with GDAL 3.2, the GDAL_NUM_THREADS configuration option can be set
2168 : * to "ALL_CPUS" or a integer value to specify the number of threads to use for
2169 : * overview computation.
2170 : *
2171 : * This method is the same as the C function GDALBuildOverviewsEx().
2172 : *
2173 : * @param pszResampling one of "AVERAGE", "AVERAGE_MAGPHASE", "RMS",
2174 : * "BILINEAR", "CUBIC", "CUBICSPLINE", "GAUSS", "LANCZOS", "MODE", "NEAREST",
2175 : * or "NONE" controlling the downsampling method applied.
2176 : * @param nOverviews number of overviews to build, or 0 to clean overviews.
2177 : * @param panOverviewList the list of overview decimation factors (positive
2178 : * integers, normally larger or equal to 2) to build, or
2179 : * NULL if nOverviews == 0.
2180 : * @param nListBands number of bands to build overviews for in panBandList.
2181 : * Build for all bands if this is 0.
2182 : * @param panBandList list of band numbers.
2183 : * @param pfnProgress a function to call to report progress, or NULL.
2184 : * @param pProgressData application data to pass to the progress function.
2185 : * @param papszOptions (GDAL >= 3.6) NULL terminated list of options as
2186 : * key=value pairs, or NULL
2187 : *
2188 : * @return CE_None on success or CE_Failure if the operation doesn't work.
2189 : *
2190 : * For example, to build overview level 2, 4 and 8 on all bands the following
2191 : * call could be made:
2192 : * \code{.cpp}
2193 : * int anOverviewList[3] = { 2, 4, 8 };
2194 : *
2195 : * poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, nullptr,
2196 : * GDALDummyProgress, nullptr );
2197 : * \endcode
2198 : *
2199 : * @see GDALRegenerateOverviewsEx()
2200 : */
2201 :
2202 727 : CPLErr GDALDataset::BuildOverviews(const char *pszResampling, int nOverviews,
2203 : const int *panOverviewList, int nListBands,
2204 : const int *panBandList,
2205 : GDALProgressFunc pfnProgress,
2206 : void *pProgressData,
2207 : CSLConstList papszOptions)
2208 : {
2209 727 : int *panAllBandList = nullptr;
2210 :
2211 727 : if (nListBands == 0)
2212 : {
2213 716 : nListBands = GetRasterCount();
2214 : panAllBandList =
2215 716 : static_cast<int *>(CPLMalloc(sizeof(int) * nListBands));
2216 67427 : for (int i = 0; i < nListBands; ++i)
2217 66711 : panAllBandList[i] = i + 1;
2218 :
2219 716 : panBandList = panAllBandList;
2220 : }
2221 :
2222 727 : if (pfnProgress == nullptr)
2223 693 : pfnProgress = GDALDummyProgress;
2224 :
2225 1785 : for (int i = 0; i < nOverviews; ++i)
2226 : {
2227 1059 : if (panOverviewList[i] <= 0)
2228 : {
2229 1 : CPLError(CE_Failure, CPLE_IllegalArg,
2230 : "panOverviewList[%d] = %d is invalid. It must be a "
2231 : "positive value",
2232 1 : i, panOverviewList[i]);
2233 1 : CPLFree(panAllBandList);
2234 1 : return CE_Failure;
2235 : }
2236 : }
2237 :
2238 : // At time of writing, all overview generation options are actually
2239 : // expected to be passed as configuration options.
2240 726 : std::vector<std::unique_ptr<CPLConfigOptionSetter>> apoConfigOptionSetter;
2241 760 : for (const auto &[pszKey, pszValue] : cpl::IterateNameValue(papszOptions))
2242 : {
2243 : apoConfigOptionSetter.emplace_back(
2244 34 : std::make_unique<CPLConfigOptionSetter>(pszKey, pszValue, false));
2245 : }
2246 :
2247 : const CPLErr eErr =
2248 1452 : IBuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,
2249 726 : panBandList, pfnProgress, pProgressData, papszOptions);
2250 :
2251 726 : if (panAllBandList != nullptr)
2252 714 : CPLFree(panAllBandList);
2253 :
2254 726 : return eErr;
2255 : }
2256 :
2257 : /************************************************************************/
2258 : /* GDALBuildOverviews() */
2259 : /************************************************************************/
2260 :
2261 : /**
2262 : * \brief Build raster overview(s)
2263 : *
2264 : * @see GDALDataset::BuildOverviews() and GDALBuildOverviews()
2265 : */
2266 :
2267 35 : CPLErr CPL_STDCALL GDALBuildOverviews(GDALDatasetH hDataset,
2268 : const char *pszResampling, int nOverviews,
2269 : const int *panOverviewList,
2270 : int nListBands, const int *panBandList,
2271 : GDALProgressFunc pfnProgress,
2272 : void *pProgressData)
2273 :
2274 : {
2275 35 : VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2276 :
2277 35 : return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2278 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2279 35 : pfnProgress, pProgressData, nullptr);
2280 : }
2281 :
2282 : /************************************************************************/
2283 : /* GDALBuildOverviews() */
2284 : /************************************************************************/
2285 :
2286 : /**
2287 : * \brief Build raster overview(s)
2288 : *
2289 : * @see GDALDataset::BuildOverviews()
2290 : * @since GDAL 3.6
2291 : */
2292 :
2293 : CPLErr CPL_STDCALL
2294 672 : GDALBuildOverviewsEx(GDALDatasetH hDataset, const char *pszResampling,
2295 : int nOverviews, const int *panOverviewList, int nListBands,
2296 : const int *panBandList, GDALProgressFunc pfnProgress,
2297 : void *pProgressData, CSLConstList papszOptions)
2298 :
2299 : {
2300 672 : VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2301 :
2302 672 : return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2303 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2304 672 : pfnProgress, pProgressData, papszOptions);
2305 : }
2306 :
2307 : /************************************************************************/
2308 : /* IBuildOverviews() */
2309 : /* */
2310 : /* Default implementation. */
2311 : /************************************************************************/
2312 :
2313 : //! @cond Doxygen_Suppress
2314 195 : CPLErr GDALDataset::IBuildOverviews(const char *pszResampling, int nOverviews,
2315 : const int *panOverviewList, int nListBands,
2316 : const int *panBandList,
2317 : GDALProgressFunc pfnProgress,
2318 : void *pProgressData,
2319 : CSLConstList papszOptions)
2320 :
2321 : {
2322 195 : if (oOvManager.IsInitialized())
2323 194 : return oOvManager.BuildOverviews(
2324 : nullptr, pszResampling, nOverviews, panOverviewList, nListBands,
2325 194 : panBandList, pfnProgress, pProgressData, papszOptions);
2326 : else
2327 : {
2328 1 : ReportError(CE_Failure, CPLE_NotSupported,
2329 : "BuildOverviews() not supported for this dataset.");
2330 :
2331 1 : return CE_Failure;
2332 : }
2333 : }
2334 :
2335 : //! @endcond
2336 :
2337 : /************************************************************************/
2338 : /* AddOverviews() */
2339 : /* */
2340 : /* Default implementation. */
2341 : /************************************************************************/
2342 :
2343 : /**
2344 : * \brief Add overview from existing dataset(s)
2345 : *
2346 : * This function creates new overview levels or refresh existing one from
2347 : * the list of provided overview datasets.
2348 : * Source overviews may come from any GDAL supported format, provided they
2349 : * have the same number of bands and geospatial extent than the target
2350 : * dataset.
2351 : *
2352 : * If the operation is not supported for the indicated dataset, then
2353 : * CE_Failure is returned, and CPLGetLastErrorNo() will return
2354 : * CPLE_NotSupported.
2355 : *
2356 : * At time of writing, this method is only implemented for internal overviews
2357 : * of GeoTIFF datasets and external overviews in GeoTIFF format.
2358 : *
2359 : * @param apoSrcOvrDS Vector of source overviews.
2360 : * @param pfnProgress a function to call to report progress, or NULL.
2361 : * @param pProgressData application data to pass to the progress function.
2362 : * @param papszOptions NULL terminated list of options as
2363 : * key=value pairs, or NULL. None currently
2364 : *
2365 : * @return CE_None on success or CE_Failure if the operation doesn't work.
2366 : * @since 3.12
2367 : */
2368 5 : CPLErr GDALDataset::AddOverviews(const std::vector<GDALDataset *> &apoSrcOvrDS,
2369 : GDALProgressFunc pfnProgress,
2370 : void *pProgressData, CSLConstList papszOptions)
2371 : {
2372 5 : if (oOvManager.IsInitialized())
2373 : {
2374 4 : return oOvManager.AddOverviews(nullptr, apoSrcOvrDS, pfnProgress,
2375 4 : pProgressData, papszOptions);
2376 : }
2377 : else
2378 : {
2379 1 : ReportError(CE_Failure, CPLE_NotSupported,
2380 : "AddOverviews() not supported for this dataset.");
2381 1 : return CE_Failure;
2382 : }
2383 : }
2384 :
2385 : /************************************************************************/
2386 : /* IRasterIO() */
2387 : /* */
2388 : /* The default implementation of IRasterIO() is, in the general */
2389 : /* case to pass the request off to each band objects rasterio */
2390 : /* methods with appropriate arguments. In some cases, it might */
2391 : /* choose instead the BlockBasedRasterIO() implementation. */
2392 : /************************************************************************/
2393 :
2394 : //! @cond Doxygen_Suppress
2395 444249 : CPLErr GDALDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2396 : int nXSize, int nYSize, void *pData,
2397 : int nBufXSize, int nBufYSize,
2398 : GDALDataType eBufType, int nBandCount,
2399 : BANDMAP_TYPE panBandMap, GSpacing nPixelSpace,
2400 : GSpacing nLineSpace, GSpacing nBandSpace,
2401 : GDALRasterIOExtraArg *psExtraArg)
2402 :
2403 : {
2404 444249 : const char *pszInterleave = nullptr;
2405 :
2406 444249 : CPLAssert(nullptr != pData);
2407 :
2408 444249 : const bool bHasSubpixelShift =
2409 446332 : psExtraArg->bFloatingPointWindowValidity &&
2410 444950 : psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
2411 701 : (nXOff != psExtraArg->dfXOff || nYOff != psExtraArg->dfYOff);
2412 :
2413 444137 : if (!bHasSubpixelShift && nXSize == nBufXSize && nYSize == nBufYSize &&
2414 70111 : nBandCount > 1 &&
2415 70111 : (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) !=
2416 888386 : nullptr &&
2417 67042 : EQUAL(pszInterleave, "PIXEL"))
2418 : {
2419 63929 : return BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2420 : nBufXSize, nBufYSize, eBufType, nBandCount,
2421 : panBandMap, nPixelSpace, nLineSpace,
2422 63929 : nBandSpace, psExtraArg);
2423 : }
2424 :
2425 380320 : if (eRWFlag == GF_Read &&
2426 200900 : (psExtraArg->eResampleAlg == GRIORA_Cubic ||
2427 200202 : psExtraArg->eResampleAlg == GRIORA_CubicSpline ||
2428 200201 : psExtraArg->eResampleAlg == GRIORA_Bilinear ||
2429 200900 : psExtraArg->eResampleAlg == GRIORA_Lanczos) &&
2430 861 : !(nXSize == nBufXSize && nYSize == nBufYSize) && nBandCount > 1)
2431 : {
2432 839 : if (nBufXSize < nXSize && nBufYSize < nYSize && AreOverviewsEnabled())
2433 : {
2434 633 : int bTried = FALSE;
2435 633 : const CPLErr eErr = TryOverviewRasterIO(
2436 : eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
2437 : nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace,
2438 : nLineSpace, nBandSpace, psExtraArg, &bTried);
2439 633 : if (bTried)
2440 1 : return eErr;
2441 : }
2442 :
2443 838 : GDALDataType eFirstBandDT = GDT_Unknown;
2444 838 : int nFirstMaskFlags = 0;
2445 838 : GDALRasterBand *poFirstMaskBand = nullptr;
2446 838 : int nOKBands = 0;
2447 :
2448 : // Check if bands share the same mask band
2449 2569 : for (int i = 0; i < nBandCount; ++i)
2450 : {
2451 2301 : GDALRasterBand *poBand = GetRasterBand(panBandMap[i]);
2452 3934 : if ((nBufXSize < nXSize || nBufYSize < nYSize) &&
2453 1634 : poBand->GetOverviewCount())
2454 : {
2455 : // Could be improved to select the appropriate overview.
2456 3 : break;
2457 : }
2458 2297 : if (poBand->GetColorTable() != nullptr)
2459 : {
2460 0 : break;
2461 : }
2462 2297 : const GDALDataType eDT = poBand->GetRasterDataType();
2463 2297 : if (GDALDataTypeIsComplex(eDT))
2464 : {
2465 30 : break;
2466 : }
2467 2264 : if (i == 0)
2468 : {
2469 804 : eFirstBandDT = eDT;
2470 804 : nFirstMaskFlags = poBand->GetMaskFlags();
2471 806 : if (nFirstMaskFlags == GMF_NODATA)
2472 : {
2473 : // The dataset-level resampling code is not ready for nodata
2474 : // Fallback to band-level resampling
2475 10 : break;
2476 : }
2477 796 : poFirstMaskBand = poBand->GetMaskBand();
2478 : }
2479 : else
2480 : {
2481 1460 : if (eDT != eFirstBandDT)
2482 : {
2483 0 : break;
2484 : }
2485 1460 : int nMaskFlags = poBand->GetMaskFlags();
2486 1463 : if (nMaskFlags == GMF_NODATA)
2487 : {
2488 : // The dataset-level resampling code is not ready for nodata
2489 : // Fallback to band-level resampling
2490 0 : break;
2491 : }
2492 1463 : GDALRasterBand *poMaskBand = poBand->GetMaskBand();
2493 1465 : if (nFirstMaskFlags == GMF_ALL_VALID &&
2494 : nMaskFlags == GMF_ALL_VALID)
2495 : {
2496 : // Ok.
2497 : }
2498 819 : else if (poFirstMaskBand == poMaskBand)
2499 : {
2500 : // Ok.
2501 : }
2502 : else
2503 : {
2504 531 : break;
2505 : }
2506 : }
2507 :
2508 1731 : ++nOKBands;
2509 : }
2510 :
2511 842 : GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2512 842 : void *pProgressDataGlobal = psExtraArg->pProgressData;
2513 :
2514 842 : CPLErr eErr = CE_None;
2515 842 : if (nOKBands > 0)
2516 : {
2517 800 : if (nOKBands < nBandCount)
2518 : {
2519 531 : psExtraArg->pfnProgress = GDALScaledProgress;
2520 1062 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2521 531 : 0.0, static_cast<double>(nOKBands) / nBandCount,
2522 : pfnProgressGlobal, pProgressDataGlobal);
2523 531 : if (psExtraArg->pProgressData == nullptr)
2524 142 : psExtraArg->pfnProgress = nullptr;
2525 : }
2526 :
2527 800 : eErr = RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2528 : pData, nBufXSize, nBufYSize, eBufType,
2529 : nOKBands, panBandMap, nPixelSpace,
2530 : nLineSpace, nBandSpace, psExtraArg);
2531 :
2532 800 : if (nOKBands < nBandCount)
2533 : {
2534 531 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2535 : }
2536 : }
2537 842 : if (eErr == CE_None && nOKBands < nBandCount)
2538 : {
2539 571 : if (nOKBands > 0)
2540 : {
2541 528 : psExtraArg->pfnProgress = GDALScaledProgress;
2542 1056 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2543 528 : static_cast<double>(nOKBands) / nBandCount, 1.0,
2544 : pfnProgressGlobal, pProgressDataGlobal);
2545 528 : if (psExtraArg->pProgressData == nullptr)
2546 139 : psExtraArg->pfnProgress = nullptr;
2547 : }
2548 1142 : eErr = BandBasedRasterIO(
2549 : eRWFlag, nXOff, nYOff, nXSize, nYSize,
2550 571 : static_cast<GByte *>(pData) + nBandSpace * nOKBands, nBufXSize,
2551 : nBufYSize, eBufType, nBandCount - nOKBands,
2552 571 : panBandMap + nOKBands, nPixelSpace, nLineSpace, nBandSpace,
2553 : psExtraArg);
2554 571 : if (nOKBands > 0)
2555 : {
2556 528 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2557 : }
2558 : }
2559 :
2560 843 : psExtraArg->pfnProgress = pfnProgressGlobal;
2561 843 : psExtraArg->pProgressData = pProgressDataGlobal;
2562 :
2563 843 : return eErr;
2564 : }
2565 :
2566 379481 : return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2567 : nBufXSize, nBufYSize, eBufType, nBandCount,
2568 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2569 379481 : psExtraArg);
2570 : }
2571 :
2572 : //! @endcond
2573 :
2574 : /************************************************************************/
2575 : /* BandBasedRasterIO() */
2576 : /* */
2577 : /* Pass the request off to each band objects rasterio methods with */
2578 : /* appropriate arguments. */
2579 : /************************************************************************/
2580 :
2581 : //! @cond Doxygen_Suppress
2582 762887 : CPLErr GDALDataset::BandBasedRasterIO(
2583 : GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
2584 : void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
2585 : int nBandCount, const int *panBandMap, GSpacing nPixelSpace,
2586 : GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg *psExtraArg)
2587 :
2588 : {
2589 : int iBandIndex;
2590 762887 : CPLErr eErr = CE_None;
2591 :
2592 762887 : GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2593 762887 : void *pProgressDataGlobal = psExtraArg->pProgressData;
2594 :
2595 2059540 : for (iBandIndex = 0; iBandIndex < nBandCount && eErr == CE_None;
2596 : ++iBandIndex)
2597 : {
2598 1296640 : GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
2599 :
2600 1296640 : if (poBand == nullptr)
2601 : {
2602 0 : eErr = CE_Failure;
2603 0 : break;
2604 : }
2605 :
2606 1296640 : GByte *pabyBandData =
2607 1296640 : static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
2608 :
2609 1296640 : if (nBandCount > 1)
2610 : {
2611 786426 : psExtraArg->pfnProgress = GDALScaledProgress;
2612 1572860 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2613 : 1.0 * iBandIndex / nBandCount,
2614 786426 : 1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,
2615 : pProgressDataGlobal);
2616 786431 : if (psExtraArg->pProgressData == nullptr)
2617 783661 : psExtraArg->pfnProgress = nullptr;
2618 : }
2619 :
2620 2593300 : eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2621 : pabyBandData, nBufXSize, nBufYSize, eBufType,
2622 1296640 : nPixelSpace, nLineSpace, psExtraArg);
2623 :
2624 1296660 : if (nBandCount > 1)
2625 786447 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2626 : }
2627 :
2628 762899 : psExtraArg->pfnProgress = pfnProgressGlobal;
2629 762899 : psExtraArg->pProgressData = pProgressDataGlobal;
2630 :
2631 762899 : return eErr;
2632 : }
2633 :
2634 : //! @endcond
2635 :
2636 : /************************************************************************/
2637 : /* ValidateRasterIOOrAdviseReadParameters() */
2638 : /************************************************************************/
2639 :
2640 : //! @cond Doxygen_Suppress
2641 860459 : CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
2642 : const char *pszCallingFunc, int *pbStopProcessingOnCENone, int nXOff,
2643 : int nYOff, int nXSize, int nYSize, int nBufXSize, int nBufYSize,
2644 : int nBandCount, const int *panBandMap)
2645 : {
2646 :
2647 : /* -------------------------------------------------------------------- */
2648 : /* Some size values are "noop". Lets just return to avoid */
2649 : /* stressing lower level functions. */
2650 : /* -------------------------------------------------------------------- */
2651 860459 : if (nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1)
2652 : {
2653 32 : CPLDebug("GDAL",
2654 : "%s skipped for odd window or buffer size.\n"
2655 : " Window = (%d,%d)x%dx%d\n"
2656 : " Buffer = %dx%d",
2657 : pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2658 : nBufYSize);
2659 :
2660 24 : *pbStopProcessingOnCENone = TRUE;
2661 24 : return CE_None;
2662 : }
2663 :
2664 860427 : CPLErr eErr = CE_None;
2665 860427 : *pbStopProcessingOnCENone = FALSE;
2666 :
2667 860427 : if (nXOff < 0 || nXOff > INT_MAX - nXSize ||
2668 860430 : nXOff + nXSize > nRasterXSize || nYOff < 0 ||
2669 860430 : nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize)
2670 : {
2671 0 : ReportError(CE_Failure, CPLE_IllegalArg,
2672 : "Access window out of range in %s. Requested "
2673 : "(%d,%d) of size %dx%d on raster of %dx%d.",
2674 : pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize,
2675 : nRasterYSize);
2676 2 : eErr = CE_Failure;
2677 : }
2678 :
2679 860431 : if (panBandMap == nullptr && nBandCount > GetRasterCount())
2680 : {
2681 0 : ReportError(CE_Failure, CPLE_IllegalArg,
2682 : "%s: nBandCount cannot be greater than %d", pszCallingFunc,
2683 : GetRasterCount());
2684 0 : eErr = CE_Failure;
2685 : }
2686 :
2687 2616520 : for (int i = 0; i < nBandCount && eErr == CE_None; ++i)
2688 : {
2689 1756100 : int iBand = (panBandMap != nullptr) ? panBandMap[i] : i + 1;
2690 1756100 : if (iBand < 1 || iBand > GetRasterCount())
2691 : {
2692 3 : ReportError(
2693 : CE_Failure, CPLE_IllegalArg,
2694 : "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
2695 : pszCallingFunc, i, iBand);
2696 3 : eErr = CE_Failure;
2697 : }
2698 :
2699 1756090 : if (eErr == CE_None && GetRasterBand(iBand) == nullptr)
2700 : {
2701 0 : ReportError(
2702 : CE_Failure, CPLE_IllegalArg,
2703 : "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
2704 : pszCallingFunc, i, iBand);
2705 0 : eErr = CE_Failure;
2706 : }
2707 : }
2708 :
2709 860419 : return eErr;
2710 : }
2711 :
2712 : //! @endcond
2713 :
2714 : /************************************************************************/
2715 : /* RasterIO() */
2716 : /************************************************************************/
2717 :
2718 : /**
2719 : * \brief Read/write a region of image data from multiple bands.
2720 : *
2721 : * This method allows reading a region of one or more GDALRasterBands from
2722 : * this dataset into a buffer, or writing data from a buffer into a region
2723 : * of the GDALRasterBands. It automatically takes care of data type
2724 : * translation if the data type (eBufType) of the buffer is different than
2725 : * that of the GDALRasterBand.
2726 : * The method also takes care of image decimation / replication if the
2727 : * buffer size (nBufXSize x nBufYSize) is different than the size of the
2728 : * region being accessed (nXSize x nYSize).
2729 : *
2730 : * The window of interest expressed by (nXOff, nYOff, nXSize, nYSize) should be
2731 : * fully within the raster space, that is nXOff >= 0, nYOff >= 0,
2732 : * nXOff + nXSize <= GetRasterXSize() and nYOff + nYSize <= GetRasterYSize().
2733 : * If reads larger than the raster space are wished, GDALTranslate() might be used.
2734 : * Or use nLineSpace and a possibly shifted pData value.
2735 : *
2736 : * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
2737 : * writing from various organization of buffers.
2738 : *
2739 : * Some formats may efficiently implement decimation into a buffer by
2740 : * reading from lower resolution overview images. The logic of the default
2741 : * implementation in the base class GDALRasterBand is the following one. It
2742 : * computes a target_downscaling_factor from the window of interest and buffer
2743 : * size which is min(nXSize/nBufXSize, nYSize/nBufYSize).
2744 : * It then walks through overviews and will select the first one whose
2745 : * downscaling factor is greater than target_downscaling_factor / 1.2.
2746 : *
2747 : * Let's assume we have overviews at downscaling factors 2, 4 and 8.
2748 : * The relationship between target_downscaling_factor and the select overview
2749 : * level is the following one:
2750 : *
2751 : * target_downscaling_factor | selected_overview
2752 : * ------------------------- | -----------------
2753 : * ]0, 2 / 1.2] | full resolution band
2754 : * ]2 / 1.2, 4 / 1.2] | 2x downsampled band
2755 : * ]4 / 1.2, 8 / 1.2] | 4x downsampled band
2756 : * ]8 / 1.2, infinity[ | 8x downsampled band
2757 : *
2758 : * Note that starting with GDAL 3.9, this 1.2 oversampling factor can be
2759 : * modified by setting the GDAL_OVERVIEW_OVERSAMPLING_THRESHOLD configuration
2760 : * option. Also note that starting with GDAL 3.9, when the resampling algorithm
2761 : * specified in psExtraArg->eResampleAlg is different from GRIORA_NearestNeighbour,
2762 : * this oversampling threshold defaults to 1. Consequently if there are overviews
2763 : * of downscaling factor 2, 4 and 8, and the desired downscaling factor is
2764 : * 7.99, the overview of factor 4 will be selected for a non nearest resampling.
2765 : *
2766 : * For highest performance full resolution data access, read and write
2767 : * on "block boundaries" as returned by GetBlockSize(), or use the
2768 : * ReadBlock() and WriteBlock() methods.
2769 : *
2770 : * This method is the same as the C GDALDatasetRasterIO() or
2771 : * GDALDatasetRasterIOEx() functions.
2772 : *
2773 : * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
2774 : * write a region of data.
2775 : *
2776 : * @param nXOff The pixel offset to the top left corner of the region
2777 : * of the band to be accessed. This would be zero to start from the left side.
2778 : *
2779 : * @param nYOff The line offset to the top left corner of the region
2780 : * of the band to be accessed. This would be zero to start from the top.
2781 : *
2782 : * @param nXSize The width of the region of the band to be accessed in pixels.
2783 : *
2784 : * @param nYSize The height of the region of the band to be accessed in lines.
2785 : *
2786 : * @param pData The buffer into which the data should be read, or from which
2787 : * it should be written. This buffer must contain at least
2788 : * nBufXSize * nBufYSize * nBandCount words of type eBufType. It is organized
2789 : * in left to right,top to bottom pixel order. Spacing is controlled by the
2790 : * nPixelSpace, and nLineSpace parameters.
2791 : * Note that even with eRWFlag==GF_Write, the content of the buffer might be
2792 : * temporarily modified during the execution of this method (and eventually
2793 : * restored back to its original content), so it is not safe to use a buffer
2794 : * stored in a read-only section of the calling program.
2795 : *
2796 : * @param nBufXSize the width of the buffer image into which the desired region
2797 : * is to be read, or from which it is to be written.
2798 : *
2799 : * @param nBufYSize the height of the buffer image into which the desired
2800 : * region is to be read, or from which it is to be written.
2801 : *
2802 : * @param eBufType the type of the pixel values in the pData data buffer. The
2803 : * pixel values will automatically be translated to/from the GDALRasterBand
2804 : * data type as needed. Most driver implementations will use GDALCopyWords64()
2805 : * to perform data type translation.
2806 : *
2807 : * @param nBandCount the number of bands being read or written.
2808 : *
2809 : * @param panBandMap the list of nBandCount band numbers being read/written.
2810 : * Note band numbers are 1 based. This may be NULL to select the first
2811 : * nBandCount bands. (Note: before GDAL 3.10, argument type was "int*", and
2812 : * not "const int*")
2813 : *
2814 : * @param nPixelSpace The byte offset from the start of one pixel value in
2815 : * pData to the start of the next pixel value within a scanline. If defaulted
2816 : * (0) the size of the datatype eBufType is used.
2817 : *
2818 : * @param nLineSpace The byte offset from the start of one scanline in
2819 : * pData to the start of the next. If defaulted (0) the size of the datatype
2820 : * eBufType * nBufXSize is used.
2821 : *
2822 : * @param nBandSpace the byte offset from the start of one bands data to the
2823 : * start of the next. If defaulted (0) the value will be
2824 : * nLineSpace * nBufYSize implying band sequential organization
2825 : * of the data buffer.
2826 : *
2827 : * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg
2828 : * structure with additional arguments to specify resampling and progress
2829 : * callback, or NULL for default behavior. The GDAL_RASTERIO_RESAMPLING
2830 : * configuration option can also be defined to override the default resampling
2831 : * to one of BILINEAR, CUBIC, CUBICSPLINE, LANCZOS, AVERAGE or MODE.
2832 : *
2833 : * @return CE_Failure if the access fails, otherwise CE_None.
2834 : */
2835 :
2836 845461 : CPLErr GDALDataset::RasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2837 : int nXSize, int nYSize, void *pData, int nBufXSize,
2838 : int nBufYSize, GDALDataType eBufType,
2839 : int nBandCount, const int *panBandMap,
2840 : GSpacing nPixelSpace, GSpacing nLineSpace,
2841 : GSpacing nBandSpace,
2842 : GDALRasterIOExtraArg *psExtraArg)
2843 :
2844 : {
2845 : GDALRasterIOExtraArg sExtraArg;
2846 845461 : if (psExtraArg == nullptr)
2847 : {
2848 653331 : INIT_RASTERIO_EXTRA_ARG(sExtraArg);
2849 :
2850 : // 4 below inits are not strictly needed but make Coverity Scan
2851 : // happy
2852 653331 : sExtraArg.dfXOff = nXOff;
2853 653331 : sExtraArg.dfYOff = nYOff;
2854 653331 : sExtraArg.dfXSize = nXSize;
2855 653331 : sExtraArg.dfYSize = nYSize;
2856 :
2857 653331 : psExtraArg = &sExtraArg;
2858 : }
2859 192130 : else if (CPL_UNLIKELY(psExtraArg->nVersion >
2860 : RASTERIO_EXTRA_ARG_CURRENT_VERSION))
2861 : {
2862 0 : ReportError(CE_Failure, CPLE_AppDefined,
2863 : "Unhandled version of GDALRasterIOExtraArg");
2864 0 : return CE_Failure;
2865 : }
2866 :
2867 845461 : GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize, nBufXSize,
2868 : nBufYSize);
2869 :
2870 845457 : if (CPL_UNLIKELY(nullptr == pData))
2871 : {
2872 0 : ReportError(CE_Failure, CPLE_AppDefined,
2873 : "The buffer into which the data should be read is null");
2874 0 : return CE_Failure;
2875 : }
2876 :
2877 : /* -------------------------------------------------------------------- */
2878 : /* Do some validation of parameters. */
2879 : /* -------------------------------------------------------------------- */
2880 :
2881 845457 : if (CPL_UNLIKELY(eRWFlag != GF_Read && eRWFlag != GF_Write))
2882 : {
2883 0 : ReportError(
2884 : CE_Failure, CPLE_IllegalArg,
2885 : "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
2886 : eRWFlag);
2887 0 : return CE_Failure;
2888 : }
2889 :
2890 845457 : if (eRWFlag == GF_Write)
2891 : {
2892 215960 : if (CPL_UNLIKELY(eAccess != GA_Update))
2893 : {
2894 2 : ReportError(CE_Failure, CPLE_AppDefined,
2895 : "Write operation not permitted on dataset opened "
2896 : "in read-only mode");
2897 2 : return CE_Failure;
2898 : }
2899 : }
2900 :
2901 845455 : int bStopProcessing = FALSE;
2902 845455 : CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
2903 : "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2904 : nBufYSize, nBandCount, panBandMap);
2905 845456 : if (eErr != CE_None || bStopProcessing)
2906 14 : return eErr;
2907 845442 : if (CPL_UNLIKELY(eBufType == GDT_Unknown || eBufType == GDT_TypeCount))
2908 : {
2909 2 : ReportError(CE_Failure, CPLE_AppDefined,
2910 : "Illegal GDT_Unknown/GDT_TypeCount argument");
2911 2 : return CE_Failure;
2912 : }
2913 :
2914 : /* -------------------------------------------------------------------- */
2915 : /* If pixel and line spacing are defaulted assign reasonable */
2916 : /* value assuming a packed buffer. */
2917 : /* -------------------------------------------------------------------- */
2918 845440 : if (nPixelSpace == 0)
2919 422794 : nPixelSpace = GDALGetDataTypeSizeBytes(eBufType);
2920 :
2921 845444 : if (nLineSpace == 0)
2922 : {
2923 525879 : nLineSpace = nPixelSpace * nBufXSize;
2924 : }
2925 :
2926 845444 : if (nBandSpace == 0 && nBandCount > 1)
2927 : {
2928 66544 : nBandSpace = nLineSpace * nBufYSize;
2929 : }
2930 :
2931 845444 : if (panBandMap == nullptr)
2932 : {
2933 470972 : if (!m_poPrivate)
2934 0 : return CE_Failure;
2935 470972 : CPLAssert(static_cast<int>(m_poPrivate->m_anBandMap.size()) == nBands);
2936 470972 : panBandMap = m_poPrivate->m_anBandMap.data();
2937 : }
2938 :
2939 845445 : int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
2940 :
2941 : /* -------------------------------------------------------------------- */
2942 : /* We are being forced to use cached IO instead of a driver */
2943 : /* specific implementation. */
2944 : /* -------------------------------------------------------------------- */
2945 845444 : if (bForceCachedIO)
2946 : {
2947 18 : eErr = BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2948 : nBufXSize, nBufYSize, eBufType, nBandCount,
2949 : panBandMap, nPixelSpace, nLineSpace,
2950 18 : nBandSpace, psExtraArg);
2951 : }
2952 :
2953 : /* -------------------------------------------------------------------- */
2954 : /* Call the format specific function. */
2955 : /* -------------------------------------------------------------------- */
2956 : else
2957 : {
2958 845431 : eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2959 : nBufXSize, nBufYSize, eBufType, nBandCount,
2960 : // TODO: remove this const_cast once IRasterIO()
2961 : // takes a const int*
2962 : const_cast<int *>(panBandMap), nPixelSpace, nLineSpace,
2963 845426 : nBandSpace, psExtraArg);
2964 : }
2965 :
2966 845449 : if (bCallLeaveReadWrite)
2967 407455 : LeaveReadWrite();
2968 :
2969 845449 : return eErr;
2970 : }
2971 :
2972 : /************************************************************************/
2973 : /* GDALDatasetRasterIO() */
2974 : /************************************************************************/
2975 :
2976 : /**
2977 : * \brief Read/write a region of image data from multiple bands.
2978 : *
2979 : * Use GDALDatasetRasterIOEx() if 64 bit spacings or extra arguments (resampling
2980 : * resolution, progress callback, etc. are needed)
2981 : *
2982 : * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
2983 : *
2984 : * @see GDALDataset::RasterIO()
2985 : */
2986 :
2987 4762 : CPLErr CPL_STDCALL GDALDatasetRasterIO(GDALDatasetH hDS, GDALRWFlag eRWFlag,
2988 : int nXOff, int nYOff, int nXSize,
2989 : int nYSize, void *pData, int nBufXSize,
2990 : int nBufYSize, GDALDataType eBufType,
2991 : int nBandCount, const int *panBandMap,
2992 : int nPixelSpace, int nLineSpace,
2993 : int nBandSpace)
2994 :
2995 : {
2996 4762 : VALIDATE_POINTER1(hDS, "GDALDatasetRasterIO", CE_Failure);
2997 :
2998 4762 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2999 :
3000 4762 : return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
3001 : nBufXSize, nBufYSize, eBufType, nBandCount,
3002 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
3003 4762 : nullptr);
3004 : }
3005 :
3006 : /************************************************************************/
3007 : /* GDALDatasetRasterIOEx() */
3008 : /************************************************************************/
3009 :
3010 : /**
3011 : * \brief Read/write a region of image data from multiple bands.
3012 : *
3013 : * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
3014 : *
3015 : * @see GDALDataset::RasterIO()
3016 : * @since GDAL 2.0
3017 : */
3018 :
3019 352796 : CPLErr CPL_STDCALL GDALDatasetRasterIOEx(
3020 : GDALDatasetH hDS, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,
3021 : int nYSize, void *pData, int nBufXSize, int nBufYSize,
3022 : GDALDataType eBufType, int nBandCount, const int *panBandMap,
3023 : GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
3024 : GDALRasterIOExtraArg *psExtraArg)
3025 :
3026 : {
3027 352796 : VALIDATE_POINTER1(hDS, "GDALDatasetRasterIOEx", CE_Failure);
3028 :
3029 352796 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
3030 :
3031 352796 : return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
3032 : nBufXSize, nBufYSize, eBufType, nBandCount,
3033 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
3034 352796 : psExtraArg);
3035 : }
3036 :
3037 : /************************************************************************/
3038 : /* GetOpenDatasets() */
3039 : /************************************************************************/
3040 :
3041 : /**
3042 : * \brief Fetch all open GDAL dataset handles.
3043 : *
3044 : * This method is the same as the C function GDALGetOpenDatasets().
3045 : *
3046 : * NOTE: This method is not thread safe. The returned list may change
3047 : * at any time and it should not be freed.
3048 : *
3049 : * @param pnCount integer into which to place the count of dataset pointers
3050 : * being returned.
3051 : *
3052 : * @return a pointer to an array of dataset handles.
3053 : */
3054 :
3055 2258 : GDALDataset **GDALDataset::GetOpenDatasets(int *pnCount)
3056 :
3057 : {
3058 4516 : CPLMutexHolderD(&hDLMutex);
3059 :
3060 2258 : if (poAllDatasetMap == nullptr)
3061 : {
3062 2236 : *pnCount = 0;
3063 2236 : return nullptr;
3064 : }
3065 :
3066 22 : *pnCount = static_cast<int>(poAllDatasetMap->size());
3067 22 : ppDatasets = static_cast<GDALDataset **>(
3068 22 : CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset *)));
3069 22 : std::map<GDALDataset *, GIntBig>::iterator oIter = poAllDatasetMap->begin();
3070 606 : for (int i = 0; oIter != poAllDatasetMap->end(); ++oIter, ++i)
3071 584 : ppDatasets[i] = oIter->first;
3072 22 : return ppDatasets;
3073 : }
3074 :
3075 : /************************************************************************/
3076 : /* GDALGetOpenDatasets() */
3077 : /************************************************************************/
3078 :
3079 : /**
3080 : * \brief Fetch all open GDAL dataset handles.
3081 : *
3082 : * @see GDALDataset::GetOpenDatasets()
3083 : */
3084 :
3085 0 : void CPL_STDCALL GDALGetOpenDatasets(GDALDatasetH **ppahDSList, int *pnCount)
3086 :
3087 : {
3088 0 : VALIDATE_POINTER0(ppahDSList, "GDALGetOpenDatasets");
3089 0 : VALIDATE_POINTER0(pnCount, "GDALGetOpenDatasets");
3090 :
3091 0 : *ppahDSList =
3092 0 : reinterpret_cast<GDALDatasetH *>(GDALDataset::GetOpenDatasets(pnCount));
3093 : }
3094 :
3095 : /************************************************************************/
3096 : /* GDALCleanOpenDatasetsList() */
3097 : /************************************************************************/
3098 :
3099 : // Useful when called from the child of a fork(), to avoid closing
3100 : // the datasets of the parent at the child termination.
3101 0 : void GDALNullifyOpenDatasetsList()
3102 : {
3103 0 : poAllDatasetMap = nullptr;
3104 0 : phSharedDatasetSet = nullptr;
3105 0 : ppDatasets = nullptr;
3106 0 : hDLMutex = nullptr;
3107 0 : }
3108 :
3109 : /************************************************************************/
3110 : /* GDALGetAccess() */
3111 : /************************************************************************/
3112 :
3113 : /**
3114 : * \brief Return access flag
3115 : *
3116 : * @see GDALDataset::GetAccess()
3117 : */
3118 :
3119 0 : int CPL_STDCALL GDALGetAccess(GDALDatasetH hDS)
3120 : {
3121 0 : VALIDATE_POINTER1(hDS, "GDALGetAccess", 0);
3122 :
3123 0 : return GDALDataset::FromHandle(hDS)->GetAccess();
3124 : }
3125 :
3126 : /************************************************************************/
3127 : /* AdviseRead() */
3128 : /************************************************************************/
3129 :
3130 : /**
3131 : * \brief Advise driver of upcoming read requests.
3132 : *
3133 : * Some GDAL drivers operate more efficiently if they know in advance what
3134 : * set of upcoming read requests will be made. The AdviseRead() method allows
3135 : * an application to notify the driver of the region and bands of interest,
3136 : * and at what resolution the region will be read.
3137 : *
3138 : * Many drivers just ignore the AdviseRead() call, but it can dramatically
3139 : * accelerate access via some drivers.
3140 : *
3141 : * Depending on call paths, drivers might receive several calls to
3142 : * AdviseRead() with the same parameters.
3143 : *
3144 : * @param nXOff The pixel offset to the top left corner of the region
3145 : * of the band to be accessed. This would be zero to start from the left side.
3146 : *
3147 : * @param nYOff The line offset to the top left corner of the region
3148 : * of the band to be accessed. This would be zero to start from the top.
3149 : *
3150 : * @param nXSize The width of the region of the band to be accessed in pixels.
3151 : *
3152 : * @param nYSize The height of the region of the band to be accessed in lines.
3153 : *
3154 : * @param nBufXSize the width of the buffer image into which the desired region
3155 : * is to be read, or from which it is to be written.
3156 : *
3157 : * @param nBufYSize the height of the buffer image into which the desired
3158 : * region is to be read, or from which it is to be written.
3159 : *
3160 : * @param eBufType the type of the pixel values in the pData data buffer. The
3161 : * pixel values will automatically be translated to/from the GDALRasterBand
3162 : * data type as needed.
3163 : *
3164 : * @param nBandCount the number of bands being read or written.
3165 : *
3166 : * @param panBandMap the list of nBandCount band numbers being read/written.
3167 : * Note band numbers are 1 based. This may be NULL to select the first
3168 : * nBandCount bands.
3169 : *
3170 : * @param papszOptions a list of name=value strings with special control
3171 : * options. Normally this is NULL.
3172 : *
3173 : * @return CE_Failure if the request is invalid and CE_None if it works or
3174 : * is ignored.
3175 : */
3176 :
3177 14753 : CPLErr GDALDataset::AdviseRead(int nXOff, int nYOff, int nXSize, int nYSize,
3178 : int nBufXSize, int nBufYSize,
3179 : GDALDataType eBufType, int nBandCount,
3180 : int *panBandMap, char **papszOptions)
3181 :
3182 : {
3183 : /* -------------------------------------------------------------------- */
3184 : /* Do some validation of parameters. */
3185 : /* -------------------------------------------------------------------- */
3186 14753 : int bStopProcessing = FALSE;
3187 14753 : CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
3188 : "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize,
3189 : nBufXSize, nBufYSize, nBandCount, panBandMap);
3190 14753 : if (eErr != CE_None || bStopProcessing)
3191 20 : return eErr;
3192 :
3193 129042 : for (int iBand = 0; iBand < nBandCount; ++iBand)
3194 : {
3195 114309 : GDALRasterBand *poBand = nullptr;
3196 :
3197 114309 : if (panBandMap == nullptr)
3198 112988 : poBand = GetRasterBand(iBand + 1);
3199 : else
3200 1321 : poBand = GetRasterBand(panBandMap[iBand]);
3201 :
3202 114309 : if (poBand == nullptr)
3203 0 : return CE_Failure;
3204 :
3205 228618 : eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize,
3206 114309 : nBufYSize, eBufType, papszOptions);
3207 :
3208 114309 : if (eErr != CE_None)
3209 0 : return eErr;
3210 : }
3211 :
3212 14733 : return CE_None;
3213 : }
3214 :
3215 : /************************************************************************/
3216 : /* GDALDatasetAdviseRead() */
3217 : /************************************************************************/
3218 :
3219 : /**
3220 : * \brief Advise driver of upcoming read requests.
3221 : *
3222 : * @see GDALDataset::AdviseRead()
3223 : */
3224 1 : CPLErr CPL_STDCALL GDALDatasetAdviseRead(GDALDatasetH hDS, int nXOff, int nYOff,
3225 : int nXSize, int nYSize, int nBufXSize,
3226 : int nBufYSize, GDALDataType eDT,
3227 : int nBandCount, int *panBandMap,
3228 : CSLConstList papszOptions)
3229 :
3230 : {
3231 1 : VALIDATE_POINTER1(hDS, "GDALDatasetAdviseRead", CE_Failure);
3232 :
3233 2 : return GDALDataset::FromHandle(hDS)->AdviseRead(
3234 : nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, nBandCount,
3235 1 : panBandMap, const_cast<char **>(papszOptions));
3236 : }
3237 :
3238 : /************************************************************************/
3239 : /* GDALAntiRecursionStruct */
3240 : /************************************************************************/
3241 :
3242 : // Prevent infinite recursion.
3243 : struct GDALAntiRecursionStruct
3244 : {
3245 : struct DatasetContext
3246 : {
3247 : std::string osFilename;
3248 : int nOpenFlags;
3249 : std::string osAllowedDrivers;
3250 :
3251 79817 : DatasetContext(const std::string &osFilenameIn, int nOpenFlagsIn,
3252 : const std::string &osAllowedDriversIn)
3253 79817 : : osFilename(osFilenameIn), nOpenFlags(nOpenFlagsIn),
3254 79817 : osAllowedDrivers(osAllowedDriversIn)
3255 : {
3256 79815 : }
3257 : };
3258 :
3259 : struct DatasetContextCompare
3260 : {
3261 915340 : bool operator()(const DatasetContext &lhs,
3262 : const DatasetContext &rhs) const
3263 : {
3264 2672640 : return lhs.osFilename < rhs.osFilename ||
3265 885289 : (lhs.osFilename == rhs.osFilename &&
3266 872086 : (lhs.nOpenFlags < rhs.nOpenFlags ||
3267 1743570 : (lhs.nOpenFlags == rhs.nOpenFlags &&
3268 1787080 : lhs.osAllowedDrivers < rhs.osAllowedDrivers)));
3269 : }
3270 : };
3271 :
3272 : std::set<DatasetContext, DatasetContextCompare> aosDatasetNamesWithFlags{};
3273 : int nRecLevel = 0;
3274 : std::map<std::string, int> m_oMapDepth{};
3275 : };
3276 :
3277 : #ifdef _WIN32
3278 : // Currently thread_local and C++ objects don't work well with DLL on Windows
3279 : static void FreeAntiRecursionOpen(void *pData)
3280 : {
3281 : delete static_cast<GDALAntiRecursionStruct *>(pData);
3282 : }
3283 :
3284 : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3285 : {
3286 : static GDALAntiRecursionStruct dummy;
3287 : int bMemoryErrorOccurred = false;
3288 : void *pData =
3289 : CPLGetTLSEx(CTLS_GDALOPEN_ANTIRECURSION, &bMemoryErrorOccurred);
3290 : if (bMemoryErrorOccurred)
3291 : {
3292 : return dummy;
3293 : }
3294 : if (pData == nullptr)
3295 : {
3296 : auto pAntiRecursion = new GDALAntiRecursionStruct();
3297 : CPLSetTLSWithFreeFuncEx(CTLS_GDALOPEN_ANTIRECURSION, pAntiRecursion,
3298 : FreeAntiRecursionOpen, &bMemoryErrorOccurred);
3299 : if (bMemoryErrorOccurred)
3300 : {
3301 : delete pAntiRecursion;
3302 : return dummy;
3303 : }
3304 : return *pAntiRecursion;
3305 : }
3306 : return *static_cast<GDALAntiRecursionStruct *>(pData);
3307 : }
3308 : #else
3309 : static thread_local GDALAntiRecursionStruct g_tls_antiRecursion;
3310 :
3311 339642 : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3312 : {
3313 339642 : return g_tls_antiRecursion;
3314 : }
3315 : #endif
3316 :
3317 : //! @cond Doxygen_Suppress
3318 259821 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(const std::string &osIdentifier)
3319 259821 : : m_psAntiRecursionStruct(&GetAntiRecursionOpen()),
3320 : m_osIdentifier(osIdentifier),
3321 259821 : m_nDepth(++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3322 : {
3323 259821 : CPLAssert(!osIdentifier.empty());
3324 259821 : }
3325 :
3326 259821 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(
3327 259821 : const GDALAntiRecursionGuard &other, const std::string &osIdentifier)
3328 259821 : : m_psAntiRecursionStruct(other.m_psAntiRecursionStruct),
3329 259821 : m_osIdentifier(osIdentifier.empty()
3330 : ? osIdentifier
3331 26859 : : other.m_osIdentifier + osIdentifier),
3332 259821 : m_nDepth(m_osIdentifier.empty()
3333 259821 : ? 0
3334 286680 : : ++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3335 : {
3336 259821 : }
3337 :
3338 519642 : GDALAntiRecursionGuard::~GDALAntiRecursionGuard()
3339 : {
3340 519642 : if (!m_osIdentifier.empty())
3341 : {
3342 286680 : --m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier];
3343 : }
3344 519642 : }
3345 :
3346 : //! @endcond
3347 :
3348 : /************************************************************************/
3349 : /* GetFileList() */
3350 : /************************************************************************/
3351 :
3352 : /**
3353 : * \brief Fetch files forming dataset.
3354 : *
3355 : * Returns a list of files believed to be part of this dataset. If it returns
3356 : * an empty list of files it means there is believed to be no local file
3357 : * system files associated with the dataset (for instance a virtual dataset).
3358 : * The returned file list is owned by the caller and should be deallocated
3359 : * with CSLDestroy().
3360 : *
3361 : * The returned filenames will normally be relative or absolute paths
3362 : * depending on the path used to originally open the dataset. The strings
3363 : * will be UTF-8 encoded.
3364 : *
3365 : * This method is the same as the C GDALGetFileList() function.
3366 : *
3367 : * @return NULL or a NULL terminated array of file names.
3368 : */
3369 :
3370 4764 : char **GDALDataset::GetFileList()
3371 :
3372 : {
3373 9528 : CPLString osMainFilename = GetDescription();
3374 : VSIStatBufL sStat;
3375 :
3376 4764 : GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3377 : GDALAntiRecursionStruct::DatasetContext datasetCtxt(osMainFilename, 0,
3378 9528 : std::string());
3379 4764 : auto &aosDatasetList = sAntiRecursion.aosDatasetNamesWithFlags;
3380 4764 : if (cpl::contains(aosDatasetList, datasetCtxt))
3381 0 : return nullptr;
3382 :
3383 : /* -------------------------------------------------------------------- */
3384 : /* Is the main filename even a real filesystem object? */
3385 : /* -------------------------------------------------------------------- */
3386 : int bMainFileReal =
3387 4764 : VSIStatExL(osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
3388 :
3389 : /* -------------------------------------------------------------------- */
3390 : /* Form new list. */
3391 : /* -------------------------------------------------------------------- */
3392 4764 : char **papszList = nullptr;
3393 :
3394 4764 : if (bMainFileReal)
3395 4701 : papszList = CSLAddString(papszList, osMainFilename);
3396 :
3397 4764 : if (sAntiRecursion.nRecLevel == 100)
3398 : {
3399 0 : CPLError(CE_Failure, CPLE_AppDefined,
3400 : "GetFileList() called with too many recursion levels");
3401 0 : return papszList;
3402 : }
3403 4764 : ++sAntiRecursion.nRecLevel;
3404 :
3405 : /* -------------------------------------------------------------------- */
3406 : /* Do we have a known overview file? */
3407 : /* -------------------------------------------------------------------- */
3408 4764 : if (oOvManager.IsInitialized() && oOvManager.poODS != nullptr)
3409 : {
3410 61 : auto iter = aosDatasetList.insert(datasetCtxt).first;
3411 61 : char **papszOvrList = oOvManager.poODS->GetFileList();
3412 61 : papszList = CSLInsertStrings(papszList, -1, papszOvrList);
3413 61 : CSLDestroy(papszOvrList);
3414 61 : aosDatasetList.erase(iter);
3415 : }
3416 :
3417 : /* -------------------------------------------------------------------- */
3418 : /* Do we have a known mask file? */
3419 : /* -------------------------------------------------------------------- */
3420 4764 : if (oOvManager.HaveMaskFile())
3421 : {
3422 9 : auto iter = aosDatasetList.insert(std::move(datasetCtxt)).first;
3423 9 : for (const char *pszFile :
3424 18 : CPLStringList(oOvManager.poMaskDS->GetFileList()))
3425 : {
3426 9 : if (CSLFindString(papszList, pszFile) < 0)
3427 9 : papszList = CSLAddString(papszList, pszFile);
3428 : }
3429 9 : aosDatasetList.erase(iter);
3430 : }
3431 :
3432 4764 : --sAntiRecursion.nRecLevel;
3433 :
3434 4764 : return papszList;
3435 : }
3436 :
3437 : /************************************************************************/
3438 : /* GDALGetFileList() */
3439 : /************************************************************************/
3440 :
3441 : /**
3442 : * \brief Fetch files forming dataset.
3443 : *
3444 : * @see GDALDataset::GetFileList()
3445 : */
3446 :
3447 3974 : char **CPL_STDCALL GDALGetFileList(GDALDatasetH hDS)
3448 :
3449 : {
3450 3974 : VALIDATE_POINTER1(hDS, "GDALGetFileList", nullptr);
3451 :
3452 3974 : return GDALDataset::FromHandle(hDS)->GetFileList();
3453 : }
3454 :
3455 : /************************************************************************/
3456 : /* CreateMaskBand() */
3457 : /************************************************************************/
3458 :
3459 : /**
3460 : * \brief Adds a mask band to the dataset
3461 : *
3462 : * The default implementation of the CreateMaskBand() method is implemented
3463 : * based on similar rules to the .ovr handling implemented using the
3464 : * GDALDefaultOverviews object. A TIFF file with the extension .msk will
3465 : * be created with the same basename as the original file, and it will have
3466 : * one band.
3467 : * The mask images will be deflate compressed tiled images with the same
3468 : * block size as the original image if possible.
3469 : * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
3470 : * level, where xx matches the band number of a band of the main dataset. The
3471 : * value of those items will be the one of the nFlagsIn parameter.
3472 : *
3473 : * Note that if you got a mask band with a previous call to GetMaskBand(), it
3474 : * might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
3475 : * again.
3476 : *
3477 : * @since GDAL 1.5.0
3478 : *
3479 : * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.
3480 : * GMF_PER_DATASET will be always set, even if not explicitly
3481 : * specified.
3482 : * @return CE_None on success or CE_Failure on an error.
3483 : *
3484 : * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html
3485 : * @see GDALRasterBand::CreateMaskBand()
3486 : *
3487 : */
3488 17 : CPLErr GDALDataset::CreateMaskBand(int nFlagsIn)
3489 :
3490 : {
3491 17 : if (oOvManager.IsInitialized())
3492 : {
3493 17 : CPLErr eErr = oOvManager.CreateMaskBand(nFlagsIn, -1);
3494 17 : if (eErr != CE_None)
3495 0 : return eErr;
3496 :
3497 : // Invalidate existing raster band masks.
3498 45 : for (int i = 0; i < nBands; ++i)
3499 : {
3500 28 : GDALRasterBand *poBand = papoBands[i];
3501 28 : poBand->poMask.reset();
3502 : }
3503 :
3504 17 : return CE_None;
3505 : }
3506 :
3507 0 : ReportError(CE_Failure, CPLE_NotSupported,
3508 : "CreateMaskBand() not supported for this dataset.");
3509 :
3510 0 : return CE_Failure;
3511 : }
3512 :
3513 : /************************************************************************/
3514 : /* GDALCreateDatasetMaskBand() */
3515 : /************************************************************************/
3516 :
3517 : /**
3518 : * \brief Adds a mask band to the dataset
3519 : * @see GDALDataset::CreateMaskBand()
3520 : */
3521 89 : CPLErr CPL_STDCALL GDALCreateDatasetMaskBand(GDALDatasetH hDS, int nFlags)
3522 :
3523 : {
3524 89 : VALIDATE_POINTER1(hDS, "GDALCreateDatasetMaskBand", CE_Failure);
3525 :
3526 89 : return GDALDataset::FromHandle(hDS)->CreateMaskBand(nFlags);
3527 : }
3528 :
3529 : /************************************************************************/
3530 : /* GDALOpen() */
3531 : /************************************************************************/
3532 :
3533 : /**
3534 : * \brief Open a raster file as a GDALDataset.
3535 : *
3536 : * This function will try to open the passed file, or virtual dataset
3537 : * name by invoking the Open method of each registered GDALDriver in turn.
3538 : * The first successful open will result in a returned dataset. If all
3539 : * drivers fail then NULL is returned and an error is issued.
3540 : *
3541 : * Several recommendations :
3542 : * <ul>
3543 : * <li>If you open a dataset object with GA_Update access, it is not recommended
3544 : * to open a new dataset on the same underlying file.</li>
3545 : * <li>The returned dataset should only be accessed by one thread at a time. If
3546 : * you want to use it from different threads, you must add all necessary code
3547 : * (mutexes, etc.) to avoid concurrent use of the object. (Some drivers, such
3548 : * as GeoTIFF, maintain internal state variables that are updated each time a
3549 : * new block is read, thus preventing concurrent use.) </li>
3550 : * </ul>
3551 : *
3552 : * For drivers supporting the VSI virtual file API, it is possible to open a
3553 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3554 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3555 : * server (see VSIInstallCurlFileHandler())
3556 : *
3557 : * \sa GDALOpenShared()
3558 : * \sa GDALOpenEx()
3559 : *
3560 : * @param pszFilename the name of the file to access. In the case of
3561 : * exotic drivers this may not refer to a physical file, but instead contain
3562 : * information for the driver on how to access a dataset. It should be in UTF-8
3563 : * encoding.
3564 : *
3565 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
3566 : * drivers support only read only access.
3567 : *
3568 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3569 : * this handle can be cast to a GDALDataset *.
3570 : */
3571 :
3572 25237 : GDALDatasetH CPL_STDCALL GDALOpen(const char *pszFilename, GDALAccess eAccess)
3573 :
3574 : {
3575 25237 : const int nUpdateFlag = eAccess == GA_Update ? GDAL_OF_UPDATE : 0;
3576 25237 : const int nOpenFlags = GDAL_OF_RASTER | nUpdateFlag | GDAL_OF_VERBOSE_ERROR;
3577 : GDALDatasetH hDataset =
3578 25237 : GDALOpenEx(pszFilename, nOpenFlags, nullptr, nullptr, nullptr);
3579 25232 : return hDataset;
3580 : }
3581 :
3582 : /************************************************************************/
3583 : /* GetSharedDS() */
3584 : /************************************************************************/
3585 :
3586 6486 : static GDALDataset *GetSharedDS(const char *pszFilename,
3587 : unsigned int nOpenFlags,
3588 : const char *const *papszOpenOptions)
3589 : {
3590 12972 : CPLMutexHolderD(&hDLMutex);
3591 :
3592 6486 : if (phSharedDatasetSet != nullptr)
3593 : {
3594 6237 : const GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
3595 : SharedDatasetCtxt sStruct;
3596 :
3597 6237 : sStruct.nPID = nThisPID;
3598 6237 : sStruct.pszDescription = const_cast<char *>(pszFilename);
3599 6237 : sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
3600 : std::string osConcatenatedOpenOptions =
3601 6237 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
3602 6237 : sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
3603 6237 : sStruct.poDS = nullptr;
3604 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
3605 6237 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3606 6237 : if (psStruct == nullptr && (nOpenFlags & GDAL_OF_UPDATE) == 0)
3607 : {
3608 132 : sStruct.nOpenFlags |= GDAL_OF_UPDATE;
3609 : psStruct = static_cast<SharedDatasetCtxt *>(
3610 132 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3611 : }
3612 6237 : if (psStruct)
3613 : {
3614 6106 : return psStruct->poDS;
3615 : }
3616 : }
3617 380 : return nullptr;
3618 : }
3619 :
3620 : /************************************************************************/
3621 : /* GDALOpenEx() */
3622 : /************************************************************************/
3623 :
3624 : /**
3625 : * \brief Open a raster or vector file as a GDALDataset.
3626 : *
3627 : * This function will try to open the passed file, or virtual dataset
3628 : * name by invoking the Open method of each registered GDALDriver in turn.
3629 : * The first successful open will result in a returned dataset. If all
3630 : * drivers fail then NULL is returned and an error is issued.
3631 : *
3632 : * Several recommendations :
3633 : * <ul>
3634 : * <li>If you open a dataset object with GDAL_OF_UPDATE access, it is not
3635 : * recommended to open a new dataset on the same underlying file.</li>
3636 : * <li>The returned dataset should only be accessed by one thread at a time. If
3637 : * you want to use it from different threads, you must add all necessary code
3638 : * (mutexes, etc.) to avoid concurrent use of the object. (Some drivers, such
3639 : * as GeoTIFF, maintain internal state variables that are updated each time a
3640 : * new block is read, thus preventing concurrent use.) </li>
3641 : * </ul>
3642 : *
3643 : * For drivers supporting the VSI virtual file API, it is possible to open a
3644 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3645 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3646 : * server (see VSIInstallCurlFileHandler())
3647 : *
3648 : * In order to reduce the need for searches through the operating system
3649 : * file system machinery, it is possible to give an optional list of files with
3650 : * the papszSiblingFiles parameter.
3651 : * This is the list of all files at the same level in the file system as the
3652 : * target file, including the target file. The filenames must not include any
3653 : * path components, are essentially just the output of VSIReadDir() on the
3654 : * parent directory. If the target object does not have filesystem semantics
3655 : * then the file list should be NULL.
3656 : *
3657 : * @param pszFilename the name of the file to access. In the case of
3658 : * exotic drivers this may not refer to a physical file, but instead contain
3659 : * information for the driver on how to access a dataset. It should be in UTF-8
3660 : * encoding.
3661 : *
3662 : * @param nOpenFlags a combination of GDAL_OF_ flags that may be combined
3663 : * through logical or operator.
3664 : * <ul>
3665 : * <li>Driver kind:
3666 : * <ul>
3667 : * <li>GDAL_OF_RASTER for raster drivers,</li>
3668 : * <li>GDAL_OF_MULTIDIM_RASTER for multidimensional raster drivers,</li>
3669 : * <li>GDAL_OF_VECTOR for vector drivers,</li>
3670 : * <li>GDAL_OF_GNM for Geographic Network Model drivers.</li>
3671 : * </ul>
3672 : * GDAL_OF_RASTER and GDAL_OF_MULTIDIM_RASTER are generally mutually
3673 : * exclusive. If none of the value is specified, GDAL_OF_RASTER | GDAL_OF_VECTOR
3674 : * | GDAL_OF_GNM is implied.
3675 : * </li>
3676 : * <li>Access mode: GDAL_OF_READONLY (exclusive)or GDAL_OF_UPDATE.
3677 : * </li>
3678 : * <li>Shared mode: GDAL_OF_SHARED. If set,
3679 : * it allows the sharing of GDALDataset handles for a dataset with other callers
3680 : * that have set GDAL_OF_SHARED. In particular, GDALOpenEx() will first consult
3681 : * its list of currently open and shared GDALDataset's, and if the
3682 : * GetDescription() name for one exactly matches the pszFilename passed to
3683 : * GDALOpenEx() it will be referenced and returned, if GDALOpenEx() is called
3684 : * from the same thread.
3685 : * </li>
3686 : * <li>Thread safe mode: GDAL_OF_THREAD_SAFE (added in 3.10).
3687 : * This must be use in combination with GDAL_OF_RASTER, and is mutually
3688 : * exclusive with GDAL_OF_UPDATE, GDAL_OF_VECTOR, GDAL_OF_MULTIDIM_RASTER or
3689 : * GDAL_OF_GNM.
3690 : * </li>
3691 : * <li>Verbose error: GDAL_OF_VERBOSE_ERROR. If set,
3692 : * a failed attempt to open the file will lead to an error message to be
3693 : * reported.
3694 : * </li>
3695 : * </ul>
3696 : *
3697 : * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
3698 : * terminated list of strings with the driver short names that must be
3699 : * considered.
3700 : *
3701 : * @param papszOpenOptions NULL, or a NULL terminated list of strings with open
3702 : * options passed to candidate drivers. An option exists for all drivers,
3703 : * OVERVIEW_LEVEL=level, to select a particular overview level of a dataset.
3704 : * The level index starts at 0. The level number can be suffixed by "only" to
3705 : * specify that only this overview level must be visible, and not sub-levels.
3706 : * Open options are validated by default, and a warning is emitted in case the
3707 : * option is not recognized. In some scenarios, it might be not desirable (e.g.
3708 : * when not knowing which driver will open the file), so the special open option
3709 : * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings. Alternatively,
3710 : * since GDAL 2.1, an option name can be preceded by the @ character to indicate
3711 : * that it may not cause a warning if the driver doesn't declare this option.
3712 : * Starting with GDAL 3.3, OVERVIEW_LEVEL=NONE is supported to indicate that
3713 : * no overviews should be exposed.
3714 : *
3715 : * @param papszSiblingFiles NULL, or a NULL terminated list of strings that are
3716 : * filenames that are auxiliary to the main filename. If NULL is passed, a
3717 : * probing of the file system will be done.
3718 : *
3719 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3720 : * this handle can be cast to a GDALDataset *.
3721 : *
3722 : * @since GDAL 2.0
3723 : */
3724 :
3725 81167 : GDALDatasetH CPL_STDCALL GDALOpenEx(const char *pszFilename,
3726 : unsigned int nOpenFlags,
3727 : const char *const *papszAllowedDrivers,
3728 : const char *const *papszOpenOptions,
3729 : const char *const *papszSiblingFiles)
3730 : {
3731 81167 : VALIDATE_POINTER1(pszFilename, "GDALOpen", nullptr);
3732 :
3733 : // Hack for the ZARR driver. We translate the CACHE_KERCHUNK_JSON
3734 : // into VSIKERCHUNK_USE_CACHE config option
3735 81082 : std::unique_ptr<CPLConfigOptionSetter> poVSIKERCHUNK_USE_CACHESetter;
3736 81167 : if (CPLFetchBool(papszOpenOptions, "CACHE_KERCHUNK_JSON", false))
3737 : {
3738 13 : poVSIKERCHUNK_USE_CACHESetter = std::make_unique<CPLConfigOptionSetter>(
3739 26 : "VSIKERCHUNK_USE_CACHE", "YES", false);
3740 : }
3741 :
3742 : // Do some sanity checks on incompatible flags with thread-safe mode.
3743 81165 : if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
3744 : {
3745 : const struct
3746 : {
3747 : int nFlag;
3748 : const char *pszFlagName;
3749 128 : } asFlags[] = {
3750 : {GDAL_OF_UPDATE, "GDAL_OF_UPDATE"},
3751 : {GDAL_OF_VECTOR, "GDAL_OF_VECTOR"},
3752 : {GDAL_OF_MULTIDIM_RASTER, "GDAL_OF_MULTIDIM_RASTER"},
3753 : {GDAL_OF_GNM, "GDAL_OF_GNM"},
3754 : };
3755 :
3756 630 : for (const auto &asFlag : asFlags)
3757 : {
3758 506 : if ((nOpenFlags & asFlag.nFlag) != 0)
3759 : {
3760 4 : CPLError(CE_Failure, CPLE_IllegalArg,
3761 : "GDAL_OF_THREAD_SAFE and %s are mutually "
3762 : "exclusive",
3763 4 : asFlag.pszFlagName);
3764 4 : return nullptr;
3765 : }
3766 : }
3767 : }
3768 :
3769 : // If no driver kind is specified, assume all are to be probed.
3770 81161 : if ((nOpenFlags & GDAL_OF_KIND_MASK) == 0)
3771 7517 : nOpenFlags |= GDAL_OF_KIND_MASK & ~GDAL_OF_MULTIDIM_RASTER;
3772 :
3773 : /* -------------------------------------------------------------------- */
3774 : /* In case of shared dataset, first scan the existing list to see */
3775 : /* if it could already contain the requested dataset. */
3776 : /* -------------------------------------------------------------------- */
3777 81161 : if (nOpenFlags & GDAL_OF_SHARED)
3778 : {
3779 6486 : if (nOpenFlags & GDAL_OF_INTERNAL)
3780 : {
3781 0 : CPLError(CE_Failure, CPLE_IllegalArg,
3782 : "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");
3783 0 : return nullptr;
3784 : }
3785 :
3786 : auto poSharedDS =
3787 6486 : GetSharedDS(pszFilename, nOpenFlags, papszOpenOptions);
3788 6486 : if (poSharedDS)
3789 : {
3790 6106 : poSharedDS->Reference();
3791 6106 : return poSharedDS;
3792 : }
3793 : }
3794 :
3795 75055 : GDALDriverManager *poDM = GetGDALDriverManager();
3796 : // CPLLocaleC oLocaleForcer;
3797 :
3798 75055 : CPLErrorReset();
3799 75056 : VSIErrorReset();
3800 75054 : CPLAssert(nullptr != poDM);
3801 :
3802 : // Build GDALOpenInfo just now to avoid useless file stat'ing if a
3803 : // shared dataset was asked before.
3804 : GDALOpenInfo oOpenInfo(pszFilename, nOpenFlags,
3805 149954 : const_cast<char **>(papszSiblingFiles));
3806 75057 : oOpenInfo.papszAllowedDrivers = papszAllowedDrivers;
3807 :
3808 75057 : GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3809 75055 : if (sAntiRecursion.nRecLevel == 100)
3810 : {
3811 0 : CPLError(CE_Failure, CPLE_AppDefined,
3812 : "GDALOpen() called with too many recursion levels");
3813 0 : return nullptr;
3814 : }
3815 :
3816 149990 : std::string osAllowedDrivers;
3817 164773 : for (const char *pszDriverName : cpl::Iterate(papszAllowedDrivers))
3818 89718 : osAllowedDrivers += pszDriverName;
3819 : auto dsCtxt = GDALAntiRecursionStruct::DatasetContext(
3820 225120 : std::string(pszFilename), nOpenFlags, osAllowedDrivers);
3821 75051 : if (cpl::contains(sAntiRecursion.aosDatasetNamesWithFlags, dsCtxt))
3822 : {
3823 0 : CPLError(CE_Failure, CPLE_AppDefined,
3824 : "GDALOpen() called on %s recursively", pszFilename);
3825 0 : return nullptr;
3826 : }
3827 :
3828 : // Remove leading @ if present.
3829 : char **papszOpenOptionsCleaned =
3830 75034 : CSLDuplicate(const_cast<char **>(papszOpenOptions));
3831 80568 : for (char **papszIter = papszOpenOptionsCleaned; papszIter && *papszIter;
3832 : ++papszIter)
3833 : {
3834 5531 : char *pszOption = *papszIter;
3835 5531 : if (pszOption[0] == '@')
3836 203 : memmove(pszOption, pszOption + 1, strlen(pszOption + 1) + 1);
3837 : }
3838 :
3839 75037 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3840 75037 : oOpenInfo.nOpenFlags |= GDAL_OF_FROM_GDALOPEN;
3841 :
3842 : #ifdef OGRAPISPY_ENABLED
3843 75037 : const bool bUpdate = (nOpenFlags & GDAL_OF_UPDATE) != 0;
3844 : const int iSnapshot =
3845 18687 : (nOpenFlags & GDAL_OF_VECTOR) != 0 && (nOpenFlags & GDAL_OF_RASTER) == 0
3846 93724 : ? OGRAPISpyOpenTakeSnapshot(pszFilename, bUpdate)
3847 75037 : : INT_MIN;
3848 : #endif
3849 :
3850 75037 : const int nDriverCount = poDM->GetDriverCount(/*bIncludeHidden=*/true);
3851 75038 : GDALDriver *poMissingPluginDriver = nullptr;
3852 149957 : std::vector<GDALDriver *> apoSecondPassDrivers;
3853 :
3854 : // Lookup of matching driver for dataset can involve up to 2 passes:
3855 : // - in the first pass, all drivers that are compabile of the request mode
3856 : // (raster/vector/etc.) are probed using their Identify() method if it
3857 : // exists. If the Identify() method returns FALSE, the driver is skipped.
3858 : // If the Identify() methods returns GDAL_IDENTIFY_UNKNOWN and that the
3859 : // driver is a deferred-loading plugin, it is added to the
3860 : // apoSecondPassDrivers list for potential later probing, and execution
3861 : // continues to the next driver in the list.
3862 : // Otherwise if Identify() returns non-FALSE, the Open() method is used.
3863 : // If Open() returns a non-NULL dataset, the loop stops and it is
3864 : // returned. Otherwise looping over remaining drivers continues.
3865 : // - the second pass is optional, only if at least one driver was added
3866 : // into apoSecondPassDrivers during the first pass. It is similar
3867 : // to the first pass except it runs only on apoSecondPassDrivers drivers.
3868 : // And the Open() method of such drivers is used, causing them to be
3869 : // loaded for real.
3870 75031 : int iPass = 1;
3871 75044 : retry:
3872 7668120 : for (int iDriver = 0;
3873 7668160 : iDriver < (iPass == 1 ? nDriverCount
3874 34 : : static_cast<int>(apoSecondPassDrivers.size()));
3875 : ++iDriver)
3876 : {
3877 : GDALDriver *poDriver =
3878 7650740 : iPass == 1 ? poDM->GetDriver(iDriver, /*bIncludeHidden=*/true)
3879 793 : : apoSecondPassDrivers[iDriver];
3880 11172700 : if (papszAllowedDrivers != nullptr &&
3881 3519530 : CSLFindString(papszAllowedDrivers,
3882 : GDALGetDriverShortName(poDriver)) == -1)
3883 : {
3884 7214750 : continue;
3885 : }
3886 :
3887 4218430 : if (poDriver->GetMetadataItem(GDAL_DCAP_OPEN) == nullptr)
3888 39058 : continue;
3889 :
3890 11090000 : if ((nOpenFlags & GDAL_OF_RASTER) != 0 &&
3891 6048400 : (nOpenFlags & GDAL_OF_VECTOR) == 0 &&
3892 1879390 : poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr)
3893 451091 : continue;
3894 10892200 : if ((nOpenFlags & GDAL_OF_VECTOR) != 0 &&
3895 5449670 : (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3896 1731750 : poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
3897 1305520 : continue;
3898 5106740 : if ((nOpenFlags & GDAL_OF_MULTIDIM_RASTER) != 0 &&
3899 2556880 : (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3900 144473 : poDriver->GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) == nullptr)
3901 135882 : continue;
3902 :
3903 : // Remove general OVERVIEW_LEVEL open options from list before passing
3904 : // it to the driver, if it isn't a driver specific option already.
3905 2276520 : char **papszTmpOpenOptions = nullptr;
3906 2276520 : char **papszTmpOpenOptionsToValidate = nullptr;
3907 2276520 : char **papszOptionsToValidate = const_cast<char **>(papszOpenOptions);
3908 2276520 : if (CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") !=
3909 2278610 : nullptr &&
3910 183 : !poDriver->HasOpenOption("OVERVIEW_LEVEL"))
3911 : {
3912 183 : papszTmpOpenOptions = CSLDuplicate(papszOpenOptionsCleaned);
3913 : papszTmpOpenOptions =
3914 183 : CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", nullptr);
3915 183 : oOpenInfo.papszOpenOptions = papszTmpOpenOptions;
3916 :
3917 183 : papszOptionsToValidate = CSLDuplicate(papszOptionsToValidate);
3918 183 : papszOptionsToValidate = CSLSetNameValue(papszOptionsToValidate,
3919 : "OVERVIEW_LEVEL", nullptr);
3920 183 : papszTmpOpenOptionsToValidate = papszOptionsToValidate;
3921 : }
3922 :
3923 : const int nIdentifyRes =
3924 2278430 : poDriver->pfnIdentifyEx
3925 4559640 : ? poDriver->pfnIdentifyEx(poDriver, &oOpenInfo)
3926 2278420 : : poDriver->pfnIdentify ? poDriver->pfnIdentify(&oOpenInfo)
3927 2281220 : : GDAL_IDENTIFY_UNKNOWN;
3928 2281220 : if (nIdentifyRes == FALSE)
3929 : {
3930 1849020 : CSLDestroy(papszTmpOpenOptions);
3931 1846130 : CSLDestroy(papszTmpOpenOptionsToValidate);
3932 1848390 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3933 1848390 : continue;
3934 : }
3935 436093 : else if (iPass == 1 && nIdentifyRes < 0 &&
3936 868401 : poDriver->pfnOpen == nullptr &&
3937 109 : poDriver->GetMetadataItem("IS_NON_LOADED_PLUGIN"))
3938 : {
3939 : // Not loaded plugin
3940 106 : apoSecondPassDrivers.push_back(poDriver);
3941 106 : CSLDestroy(papszTmpOpenOptions);
3942 106 : CSLDestroy(papszTmpOpenOptionsToValidate);
3943 106 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3944 106 : continue;
3945 : }
3946 :
3947 432093 : const bool bIdentifyRes = nIdentifyRes == GDAL_IDENTIFY_TRUE;
3948 432093 : if (bIdentifyRes)
3949 : {
3950 55528 : GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3951 : }
3952 :
3953 : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3954 : const bool bFpAvailableBefore = oOpenInfo.fpL != nullptr;
3955 : CPLErrorReset();
3956 : #endif
3957 :
3958 432086 : sAntiRecursion.nRecLevel++;
3959 432086 : sAntiRecursion.aosDatasetNamesWithFlags.insert(dsCtxt);
3960 :
3961 435679 : GDALDataset *poDS = poDriver->Open(&oOpenInfo, false);
3962 :
3963 436107 : sAntiRecursion.nRecLevel--;
3964 436107 : sAntiRecursion.aosDatasetNamesWithFlags.erase(dsCtxt);
3965 :
3966 435673 : if (poDriver->pfnOpen != nullptr)
3967 : {
3968 : // If we couldn't determine for sure with Identify() (it returned
3969 : // -1), but Open() managed to open the file, post validate options.
3970 435729 : if (poDS != nullptr &&
3971 55360 : (poDriver->pfnIdentify || poDriver->pfnIdentifyEx) &&
3972 54826 : !bIdentifyRes)
3973 : {
3974 783 : GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3975 : }
3976 : }
3977 0 : else if (poDriver->pfnOpenWithDriverArg != nullptr)
3978 : {
3979 : // do nothing
3980 : }
3981 0 : else if (bIdentifyRes &&
3982 0 : poDriver->GetMetadataItem("MISSING_PLUGIN_FILENAME"))
3983 : {
3984 0 : if (!poMissingPluginDriver)
3985 : {
3986 0 : poMissingPluginDriver = poDriver;
3987 : }
3988 : }
3989 : else
3990 : {
3991 : // should not happen given the GDAL_DCAP_OPEN check
3992 0 : CSLDestroy(papszTmpOpenOptions);
3993 0 : CSLDestroy(papszTmpOpenOptionsToValidate);
3994 0 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3995 0 : continue;
3996 : }
3997 :
3998 435673 : CSLDestroy(papszTmpOpenOptions);
3999 435080 : CSLDestroy(papszTmpOpenOptionsToValidate);
4000 435081 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
4001 :
4002 435081 : if (poDS != nullptr)
4003 : {
4004 55268 : if (poDS->papszOpenOptions == nullptr)
4005 : {
4006 55013 : poDS->papszOpenOptions = papszOpenOptionsCleaned;
4007 55013 : papszOpenOptionsCleaned = nullptr;
4008 : }
4009 :
4010 : // Deal with generic OVERVIEW_LEVEL open option, unless it is
4011 : // driver specific.
4012 55268 : if (CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") !=
4013 55374 : nullptr &&
4014 39 : !poDriver->HasOpenOption("OVERVIEW_LEVEL"))
4015 : {
4016 : CPLString osVal(
4017 78 : CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL"));
4018 39 : const int nOvrLevel = EQUAL(osVal, "NONE") ? -1 : atoi(osVal);
4019 : const bool bThisLevelOnly =
4020 39 : nOvrLevel == -1 || osVal.ifind("only") != std::string::npos;
4021 : GDALDataset *poOvrDS =
4022 39 : GDALCreateOverviewDataset(poDS, nOvrLevel, bThisLevelOnly);
4023 39 : if (poOvrDS && (nOpenFlags & GDAL_OF_SHARED) != 0)
4024 : {
4025 4 : if (strcmp(pszFilename, poDS->GetDescription()) != 0)
4026 : {
4027 0 : CPLError(
4028 : CE_Warning, CPLE_NotSupported,
4029 : "A dataset opened by GDALOpenShared should have "
4030 : "the same filename (%s) "
4031 : "and description (%s)",
4032 0 : pszFilename, poDS->GetDescription());
4033 : }
4034 : else
4035 : {
4036 4 : CSLDestroy(poDS->papszOpenOptions);
4037 4 : poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
4038 4 : poDS->papszOpenOptions = CSLSetNameValue(
4039 : poDS->papszOpenOptions, "OVERVIEW_LEVEL", nullptr);
4040 : }
4041 : }
4042 39 : poDS->ReleaseRef();
4043 39 : poDS = poOvrDS;
4044 39 : if (poDS == nullptr)
4045 : {
4046 1 : if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
4047 : {
4048 1 : CPLError(CE_Failure, CPLE_OpenFailed,
4049 : "Cannot open overview level %d of %s",
4050 : nOvrLevel, pszFilename);
4051 : }
4052 : }
4053 : else
4054 : {
4055 : // For thread-safe opening, currently poDS is what will be
4056 : // the "master" dataset owned by the thread-safe dataset
4057 : // returned to the user, hence we do not register it as a
4058 : // visible one in the open dataset list, or mark it as shared.
4059 38 : if (!(nOpenFlags & GDAL_OF_INTERNAL) &&
4060 36 : !(nOpenFlags & GDAL_OF_THREAD_SAFE))
4061 : {
4062 35 : poDS->AddToDatasetOpenList();
4063 : }
4064 38 : if (nOpenFlags & GDAL_OF_SHARED)
4065 : {
4066 4 : CSLDestroy(poDS->papszOpenOptions);
4067 4 : poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
4068 4 : poDS->nOpenFlags = nOpenFlags;
4069 4 : if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
4070 4 : poDS->MarkAsShared();
4071 : }
4072 : }
4073 : }
4074 55296 : else if (nOpenFlags & GDAL_OF_SHARED)
4075 : {
4076 370 : if (strcmp(pszFilename, poDS->GetDescription()) != 0)
4077 : {
4078 2 : CPLError(CE_Warning, CPLE_NotSupported,
4079 : "A dataset opened by GDALOpenShared should have "
4080 : "the same filename (%s) "
4081 : "and description (%s)",
4082 2 : pszFilename, poDS->GetDescription());
4083 : }
4084 368 : else if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
4085 : {
4086 : // For thread-safe opening, currently poDS is what will be
4087 : // the "master" dataset owned by the thread-safe dataset
4088 : // returned to the user, hence we do not or mark it as shared.
4089 368 : poDS->MarkAsShared();
4090 : }
4091 : }
4092 :
4093 55335 : VSIErrorReset();
4094 :
4095 55249 : CSLDestroy(papszOpenOptionsCleaned);
4096 :
4097 : #ifdef OGRAPISPY_ENABLED
4098 55255 : if (iSnapshot != INT_MIN)
4099 : {
4100 11043 : GDALDatasetH hDS = GDALDataset::ToHandle(poDS);
4101 11043 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4102 11043 : poDS = GDALDataset::FromHandle(hDS);
4103 : }
4104 : #endif
4105 :
4106 55255 : if (poDS)
4107 : {
4108 55260 : poDS->m_bCanBeReopened = true;
4109 :
4110 55260 : if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
4111 : {
4112 : poDS =
4113 248 : GDALGetThreadSafeDataset(
4114 248 : std::unique_ptr<GDALDataset>(poDS), GDAL_OF_RASTER)
4115 124 : .release();
4116 124 : if (poDS)
4117 : {
4118 124 : poDS->m_bCanBeReopened = true;
4119 124 : poDS->poDriver = poDriver;
4120 124 : poDS->nOpenFlags = nOpenFlags;
4121 124 : if (!(nOpenFlags & GDAL_OF_INTERNAL))
4122 124 : poDS->AddToDatasetOpenList();
4123 124 : if (nOpenFlags & GDAL_OF_SHARED)
4124 0 : poDS->MarkAsShared();
4125 : }
4126 : }
4127 : }
4128 :
4129 56296 : return poDS;
4130 : }
4131 :
4132 : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
4133 : if (bFpAvailableBefore && oOpenInfo.fpL == nullptr)
4134 : {
4135 : // In case the file descriptor was "consumed" by a driver
4136 : // that ultimately failed, re-open it for next drivers.
4137 : oOpenInfo.fpL = VSIFOpenL(
4138 : pszFilename, (oOpenInfo.eAccess == GA_Update) ? "r+b" : "rb");
4139 : }
4140 : #else
4141 379813 : if (CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() > CE_Warning)
4142 : {
4143 1772 : CSLDestroy(papszOpenOptionsCleaned);
4144 :
4145 : #ifdef OGRAPISPY_ENABLED
4146 996 : if (iSnapshot != INT_MIN)
4147 : {
4148 187 : GDALDatasetH hDS = nullptr;
4149 187 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4150 : }
4151 : #endif
4152 996 : return nullptr;
4153 : }
4154 : #endif
4155 : }
4156 :
4157 : // cppcheck-suppress knownConditionTrueFalse
4158 17412 : if (iPass == 1 && !apoSecondPassDrivers.empty())
4159 : {
4160 14 : CPLDebugOnly("GDAL", "GDALOpen(): Second pass");
4161 13 : iPass = 2;
4162 13 : goto retry;
4163 : }
4164 :
4165 17398 : CSLDestroy(papszOpenOptionsCleaned);
4166 :
4167 : #ifdef OGRAPISPY_ENABLED
4168 18622 : if (iSnapshot != INT_MIN)
4169 : {
4170 645 : GDALDatasetH hDS = nullptr;
4171 645 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4172 : }
4173 : #endif
4174 :
4175 18622 : if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
4176 : {
4177 5584 : if (nDriverCount == 0)
4178 : {
4179 0 : CPLError(CE_Failure, CPLE_OpenFailed, "No driver registered.");
4180 : }
4181 5584 : else if (poMissingPluginDriver)
4182 : {
4183 0 : std::string osMsg("`");
4184 0 : osMsg += pszFilename;
4185 : osMsg += "' not recognized as being in a supported file format. "
4186 0 : "It could have been recognized by driver ";
4187 0 : osMsg += poMissingPluginDriver->GetDescription();
4188 0 : osMsg += ", but plugin ";
4189 : osMsg +=
4190 0 : GDALGetMessageAboutMissingPluginDriver(poMissingPluginDriver);
4191 :
4192 0 : CPLError(CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str());
4193 : }
4194 : // Check to see if there was a filesystem error, and report it if so.
4195 : // If not, return a more generic error.
4196 5584 : else if (!VSIToCPLError(CE_Failure, CPLE_OpenFailed))
4197 : {
4198 351 : if (oOpenInfo.bStatOK)
4199 : {
4200 348 : CPLError(CE_Failure, CPLE_OpenFailed,
4201 : "`%s' not recognized as being in a supported file "
4202 : "format.",
4203 : pszFilename);
4204 : }
4205 : else
4206 : {
4207 : // If Stat failed and no VSI error was set, assume it is because
4208 : // the file did not exist on the filesystem.
4209 3 : CPLError(CE_Failure, CPLE_OpenFailed,
4210 : "`%s' does not exist in the file system, "
4211 : "and is not recognized as a supported dataset name.",
4212 : pszFilename);
4213 : }
4214 : }
4215 : }
4216 :
4217 18623 : return nullptr;
4218 : }
4219 :
4220 : /************************************************************************/
4221 : /* GDALOpenShared() */
4222 : /************************************************************************/
4223 :
4224 : /**
4225 : * \brief Open a raster file as a GDALDataset.
4226 : *
4227 : * This function works the same as GDALOpen(), but allows the sharing of
4228 : * GDALDataset handles for a dataset with other callers to GDALOpenShared().
4229 : *
4230 : * In particular, GDALOpenShared() will first consult its list of currently
4231 : * open and shared GDALDataset's, and if the GetDescription() name for one
4232 : * exactly matches the pszFilename passed to GDALOpenShared() it will be
4233 : * referenced and returned.
4234 : *
4235 : * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same
4236 : * pszFilename from two different threads, a different GDALDataset object will
4237 : * be returned as it is not safe to use the same dataset from different threads,
4238 : * unless the user does explicitly use mutexes in its code.
4239 : *
4240 : * For drivers supporting the VSI virtual file API, it is possible to open a
4241 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
4242 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
4243 : * server (see VSIInstallCurlFileHandler())
4244 : *
4245 : * \sa GDALOpen()
4246 : * \sa GDALOpenEx()
4247 : *
4248 : * @param pszFilename the name of the file to access. In the case of
4249 : * exotic drivers this may not refer to a physical file, but instead contain
4250 : * information for the driver on how to access a dataset. It should be in
4251 : * UTF-8 encoding.
4252 : *
4253 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
4254 : * drivers support only read only access.
4255 : *
4256 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
4257 : * this handle can be cast to a GDALDataset *.
4258 : */
4259 :
4260 5224 : GDALDatasetH CPL_STDCALL GDALOpenShared(const char *pszFilename,
4261 : GDALAccess eAccess)
4262 : {
4263 5224 : VALIDATE_POINTER1(pszFilename, "GDALOpenShared", nullptr);
4264 5224 : return GDALOpenEx(pszFilename,
4265 : GDAL_OF_RASTER |
4266 : (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
4267 : GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR,
4268 5224 : nullptr, nullptr, nullptr);
4269 : }
4270 :
4271 : /************************************************************************/
4272 : /* GDALClose() */
4273 : /************************************************************************/
4274 :
4275 : /**
4276 : * \brief Close GDAL dataset.
4277 : *
4278 : * For non-shared datasets (opened with GDALOpen()) the dataset is closed
4279 : * using the C++ "delete" operator, recovering all dataset related resources.
4280 : * For shared datasets (opened with GDALOpenShared()) the dataset is
4281 : * dereferenced, and closed only if the referenced count has dropped below 1.
4282 : *
4283 : * @param hDS The dataset to close. May be cast from a "GDALDataset *".
4284 : * @return CE_None in case of success (return value since GDAL 3.7). On a
4285 : * shared dataset whose reference count is not dropped below 1, CE_None will
4286 : * be returned.
4287 : */
4288 :
4289 74553 : CPLErr CPL_STDCALL GDALClose(GDALDatasetH hDS)
4290 :
4291 : {
4292 74553 : if (!hDS)
4293 396 : return CE_None;
4294 :
4295 : #ifdef OGRAPISPY_ENABLED
4296 74157 : if (bOGRAPISpyEnabled)
4297 11 : OGRAPISpyPreClose(hDS);
4298 : #endif
4299 :
4300 74157 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
4301 :
4302 74157 : if (poDS->GetShared())
4303 : {
4304 : /* --------------------------------------------------------------------
4305 : */
4306 : /* If this file is in the shared dataset list then dereference */
4307 : /* it, and only delete/remote it if the reference count has */
4308 : /* dropped to zero. */
4309 : /* --------------------------------------------------------------------
4310 : */
4311 231 : if (poDS->Dereference() > 0)
4312 15 : return CE_None;
4313 :
4314 216 : CPLErr eErr = poDS->Close();
4315 216 : delete poDS;
4316 :
4317 : #ifdef OGRAPISPY_ENABLED
4318 216 : if (bOGRAPISpyEnabled)
4319 0 : OGRAPISpyPostClose();
4320 : #endif
4321 :
4322 216 : return eErr;
4323 : }
4324 :
4325 : /* -------------------------------------------------------------------- */
4326 : /* This is not shared dataset, so directly delete it. */
4327 : /* -------------------------------------------------------------------- */
4328 73926 : CPLErr eErr = poDS->Close();
4329 73925 : delete poDS;
4330 :
4331 : #ifdef OGRAPISPY_ENABLED
4332 73924 : if (bOGRAPISpyEnabled)
4333 11 : OGRAPISpyPostClose();
4334 : #endif
4335 73916 : return eErr;
4336 : }
4337 :
4338 : /************************************************************************/
4339 : /* GDALDumpOpenDataset() */
4340 : /************************************************************************/
4341 :
4342 0 : static int GDALDumpOpenSharedDatasetsForeach(void *elt, void *user_data)
4343 : {
4344 0 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
4345 0 : FILE *fp = static_cast<FILE *>(user_data);
4346 0 : GDALDataset *poDS = psStruct->poDS;
4347 :
4348 0 : const char *pszDriverName = poDS->GetDriver() == nullptr
4349 0 : ? "DriverIsNULL"
4350 0 : : poDS->GetDriver()->GetDescription();
4351 :
4352 0 : poDS->Reference();
4353 0 : CPL_IGNORE_RET_VAL(
4354 0 : VSIFPrintf(fp, " %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4355 0 : poDS->GetShared() ? 'S' : 'N', pszDriverName,
4356 0 : static_cast<int>(psStruct->nPID), poDS->GetRasterXSize(),
4357 : poDS->GetRasterYSize(), poDS->GetRasterCount(),
4358 0 : poDS->GetDescription()));
4359 :
4360 0 : return TRUE;
4361 : }
4362 :
4363 0 : static int GDALDumpOpenDatasetsForeach(GDALDataset *poDS, FILE *fp)
4364 : {
4365 :
4366 : // Don't list shared datasets. They have already been listed by
4367 : // GDALDumpOpenSharedDatasetsForeach.
4368 0 : if (poDS->GetShared())
4369 0 : return TRUE;
4370 :
4371 0 : const char *pszDriverName = poDS->GetDriver() == nullptr
4372 0 : ? "DriverIsNULL"
4373 0 : : poDS->GetDriver()->GetDescription();
4374 :
4375 0 : poDS->Reference();
4376 0 : CPL_IGNORE_RET_VAL(
4377 0 : VSIFPrintf(fp, " %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4378 0 : poDS->GetShared() ? 'S' : 'N', pszDriverName, -1,
4379 : poDS->GetRasterXSize(), poDS->GetRasterYSize(),
4380 0 : poDS->GetRasterCount(), poDS->GetDescription()));
4381 :
4382 0 : return TRUE;
4383 : }
4384 :
4385 : /**
4386 : * \brief List open datasets.
4387 : *
4388 : * Dumps a list of all open datasets (shared or not) to the indicated
4389 : * text file (may be stdout or stderr). This function is primarily intended
4390 : * to assist in debugging "dataset leaks" and reference counting issues.
4391 : * The information reported includes the dataset name, referenced count,
4392 : * shared status, driver name, size, and band count.
4393 : */
4394 :
4395 272 : int CPL_STDCALL GDALDumpOpenDatasets(FILE *fp)
4396 :
4397 : {
4398 272 : VALIDATE_POINTER1(fp, "GDALDumpOpenDatasets", 0);
4399 :
4400 544 : CPLMutexHolderD(&hDLMutex);
4401 :
4402 272 : if (poAllDatasetMap == nullptr)
4403 272 : return 0;
4404 :
4405 0 : CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "Open GDAL Datasets:\n"));
4406 :
4407 0 : for (const auto &oIter : *poAllDatasetMap)
4408 : {
4409 0 : GDALDumpOpenDatasetsForeach(oIter.first, fp);
4410 : }
4411 :
4412 0 : if (phSharedDatasetSet != nullptr)
4413 : {
4414 0 : CPLHashSetForeach(phSharedDatasetSet, GDALDumpOpenSharedDatasetsForeach,
4415 : fp);
4416 : }
4417 0 : return static_cast<int>(poAllDatasetMap->size());
4418 : }
4419 :
4420 : /************************************************************************/
4421 : /* BeginAsyncReader() */
4422 : /************************************************************************/
4423 :
4424 : /**
4425 : * \brief Sets up an asynchronous data request
4426 : *
4427 : * This method establish an asynchronous raster read request for the
4428 : * indicated window on the dataset into the indicated buffer. The parameters
4429 : * for windowing, buffer size, buffer type and buffer organization are similar
4430 : * to those for GDALDataset::RasterIO(); however, this call only launches
4431 : * the request and filling the buffer is accomplished via calls to
4432 : * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4433 : *
4434 : * Once all processing for the created session is complete, or if no further
4435 : * refinement of the request is required, the GDALAsyncReader object should
4436 : * be destroyed with the GDALDataset::EndAsyncReader() method.
4437 : *
4438 : * Note that the data buffer (pData) will potentially continue to be
4439 : * updated as long as the session lives, but it is not deallocated when
4440 : * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
4441 : * should be deallocated by the application at that point.
4442 : *
4443 : * Additional information on asynchronous IO in GDAL may be found at:
4444 : * https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4445 : *
4446 : * This method is the same as the C GDALBeginAsyncReader() function.
4447 : *
4448 : * @param nXOff The pixel offset to the top left corner of the region
4449 : * of the band to be accessed. This would be zero to start from the left side.
4450 : *
4451 : * @param nYOff The line offset to the top left corner of the region
4452 : * of the band to be accessed. This would be zero to start from the top.
4453 : *
4454 : * @param nXSize The width of the region of the band to be accessed in pixels.
4455 : *
4456 : * @param nYSize The height of the region of the band to be accessed in lines.
4457 : *
4458 : * @param pBuf The buffer into which the data should be read. This buffer must
4459 : * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4460 : * It is organized in left to right,top to bottom pixel order. Spacing is
4461 : * controlled by the nPixelSpace, and nLineSpace parameters.
4462 : *
4463 : * @param nBufXSize the width of the buffer image into which the desired region
4464 : * is to be read, or from which it is to be written.
4465 : *
4466 : * @param nBufYSize the height of the buffer image into which the desired
4467 : * region is to be read, or from which it is to be written.
4468 : *
4469 : * @param eBufType the type of the pixel values in the pData data buffer. The
4470 : * pixel values will automatically be translated to/from the GDALRasterBand
4471 : * data type as needed.
4472 : *
4473 : * @param nBandCount the number of bands being read or written.
4474 : *
4475 : * @param panBandMap the list of nBandCount band numbers being read/written.
4476 : * Note band numbers are 1 based. This may be NULL to select the first
4477 : * nBandCount bands.
4478 : *
4479 : * @param nPixelSpace The byte offset from the start of one pixel value in
4480 : * pData to the start of the next pixel value within a scanline. If defaulted
4481 : * (0) the size of the datatype eBufType is used.
4482 : *
4483 : * @param nLineSpace The byte offset from the start of one scanline in
4484 : * pData to the start of the next. If defaulted the size of the datatype
4485 : * eBufType * nBufXSize is used.
4486 : *
4487 : * @param nBandSpace the byte offset from the start of one bands data to the
4488 : * start of the next. If defaulted (zero) the value will be
4489 : * nLineSpace * nBufYSize implying band sequential organization
4490 : * of the data buffer.
4491 : *
4492 : * @param papszOptions Driver specific control options in a string list or NULL.
4493 : * Consult driver documentation for options supported.
4494 : *
4495 : * @return The GDALAsyncReader object representing the request.
4496 : */
4497 :
4498 1 : GDALAsyncReader *GDALDataset::BeginAsyncReader(
4499 : int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf, int nBufXSize,
4500 : int nBufYSize, GDALDataType eBufType, int nBandCount, int *panBandMap,
4501 : int nPixelSpace, int nLineSpace, int nBandSpace, char **papszOptions)
4502 : {
4503 : // See gdaldefaultasync.cpp
4504 :
4505 1 : return GDALGetDefaultAsyncReader(this, nXOff, nYOff, nXSize, nYSize, pBuf,
4506 : nBufXSize, nBufYSize, eBufType, nBandCount,
4507 : panBandMap, nPixelSpace, nLineSpace,
4508 1 : nBandSpace, papszOptions);
4509 : }
4510 :
4511 : /************************************************************************/
4512 : /* GDALBeginAsyncReader() */
4513 : /************************************************************************/
4514 :
4515 : /**
4516 : * \brief Sets up an asynchronous data request
4517 : *
4518 : * This method establish an asynchronous raster read request for the
4519 : * indicated window on the dataset into the indicated buffer. The parameters
4520 : * for windowing, buffer size, buffer type and buffer organization are similar
4521 : * to those for GDALDataset::RasterIO(); however, this call only launches
4522 : * the request and filling the buffer is accomplished via calls to
4523 : * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4524 : *
4525 : * Once all processing for the created session is complete, or if no further
4526 : * refinement of the request is required, the GDALAsyncReader object should
4527 : * be destroyed with the GDALDataset::EndAsyncReader() method.
4528 : *
4529 : * Note that the data buffer (pData) will potentially continue to be
4530 : * updated as long as the session lives, but it is not deallocated when
4531 : * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
4532 : * should be deallocated by the application at that point.
4533 : *
4534 : * Additional information on asynchronous IO in GDAL may be found at:
4535 : * https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4536 : *
4537 : * This method is the same as the C++ GDALDataset::BeginAsyncReader() method.
4538 : *
4539 : * @param hDS handle to the dataset object.
4540 : *
4541 : * @param nXOff The pixel offset to the top left corner of the region
4542 : * of the band to be accessed. This would be zero to start from the left side.
4543 : *
4544 : * @param nYOff The line offset to the top left corner of the region
4545 : * of the band to be accessed. This would be zero to start from the top.
4546 : *
4547 : * @param nXSize The width of the region of the band to be accessed in pixels.
4548 : *
4549 : * @param nYSize The height of the region of the band to be accessed in lines.
4550 : *
4551 : * @param pBuf The buffer into which the data should be read. This buffer must
4552 : * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4553 : * It is organized in left to right,top to bottom pixel order. Spacing is
4554 : * controlled by the nPixelSpace, and nLineSpace parameters.
4555 : *
4556 : * @param nBufXSize the width of the buffer image into which the desired region
4557 : * is to be read, or from which it is to be written.
4558 : *
4559 : * @param nBufYSize the height of the buffer image into which the desired
4560 : * region is to be read, or from which it is to be written.
4561 : *
4562 : * @param eBufType the type of the pixel values in the pData data buffer. The
4563 : * pixel values will automatically be translated to/from the GDALRasterBand
4564 : * data type as needed.
4565 : *
4566 : * @param nBandCount the number of bands being read or written.
4567 : *
4568 : * @param panBandMap the list of nBandCount band numbers being read/written.
4569 : * Note band numbers are 1 based. This may be NULL to select the first
4570 : * nBandCount bands.
4571 : *
4572 : * @param nPixelSpace The byte offset from the start of one pixel value in
4573 : * pData to the start of the next pixel value within a scanline. If defaulted
4574 : * (0) the size of the datatype eBufType is used.
4575 : *
4576 : * @param nLineSpace The byte offset from the start of one scanline in
4577 : * pData to the start of the next. If defaulted the size of the datatype
4578 : * eBufType * nBufXSize is used.
4579 : *
4580 : * @param nBandSpace the byte offset from the start of one bands data to the
4581 : * start of the next. If defaulted (zero) the value will be
4582 : * nLineSpace * nBufYSize implying band sequential organization
4583 : * of the data buffer.
4584 : *
4585 : * @param papszOptions Driver specific control options in a string list or NULL.
4586 : * Consult driver documentation for options supported.
4587 : *
4588 : * @return handle representing the request.
4589 : */
4590 :
4591 2 : GDALAsyncReaderH CPL_STDCALL GDALBeginAsyncReader(
4592 : GDALDatasetH hDS, int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf,
4593 : int nBufXSize, int nBufYSize, GDALDataType eBufType, int nBandCount,
4594 : int *panBandMap, int nPixelSpace, int nLineSpace, int nBandSpace,
4595 : CSLConstList papszOptions)
4596 :
4597 : {
4598 2 : VALIDATE_POINTER1(hDS, "GDALDataset", nullptr);
4599 : return static_cast<GDALAsyncReaderH>(
4600 2 : GDALDataset::FromHandle(hDS)->BeginAsyncReader(
4601 : nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize, nBufYSize, eBufType,
4602 : nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
4603 2 : const_cast<char **>(papszOptions)));
4604 : }
4605 :
4606 : /************************************************************************/
4607 : /* EndAsyncReader() */
4608 : /************************************************************************/
4609 :
4610 : /**
4611 : * End asynchronous request.
4612 : *
4613 : * This method destroys an asynchronous io request and recovers all
4614 : * resources associated with it.
4615 : *
4616 : * This method is the same as the C function GDALEndAsyncReader().
4617 : *
4618 : * @param poARIO pointer to a GDALAsyncReader
4619 : */
4620 :
4621 1 : void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO)
4622 : {
4623 1 : delete poARIO;
4624 1 : }
4625 :
4626 : /************************************************************************/
4627 : /* GDALEndAsyncReader() */
4628 : /************************************************************************/
4629 :
4630 : /**
4631 : * End asynchronous request.
4632 : *
4633 : * This method destroys an asynchronous io request and recovers all
4634 : * resources associated with it.
4635 : *
4636 : * This method is the same as the C++ method GDALDataset::EndAsyncReader().
4637 : *
4638 : * @param hDS handle to the dataset object.
4639 : * @param hAsyncReaderH handle returned by GDALBeginAsyncReader()
4640 : */
4641 :
4642 1 : void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS,
4643 : GDALAsyncReaderH hAsyncReaderH)
4644 : {
4645 1 : VALIDATE_POINTER0(hDS, "GDALDataset");
4646 1 : VALIDATE_POINTER0(hAsyncReaderH, "GDALAsyncReader");
4647 1 : GDALDataset::FromHandle(hDS)->EndAsyncReader(
4648 1 : static_cast<GDALAsyncReader *>(hAsyncReaderH));
4649 : }
4650 :
4651 : /************************************************************************/
4652 : /* CloseDependentDatasets() */
4653 : /************************************************************************/
4654 :
4655 : /**
4656 : * Drop references to any other datasets referenced by this dataset.
4657 : *
4658 : * This method should release any reference to other datasets (e.g. a VRT
4659 : * dataset to its sources), but not close the current dataset itself.
4660 : *
4661 : * If at least, one reference to a dependent dataset has been dropped,
4662 : * this method should return TRUE. Otherwise it *should* return FALSE.
4663 : * (Failure to return the proper value might result in infinite loop)
4664 : *
4665 : * This method can be called several times on a given dataset. After
4666 : * the first time, it should not do anything and return FALSE.
4667 : *
4668 : * The driver implementation may choose to destroy its raster bands,
4669 : * so be careful not to call any method on the raster bands afterwards.
4670 : *
4671 : * Basically the only safe action you can do after calling
4672 : * CloseDependentDatasets() is to call the destructor.
4673 : *
4674 : * Note: the only legitimate caller of CloseDependentDatasets() is
4675 : * GDALDriverManager::~GDALDriverManager()
4676 : *
4677 : * @return TRUE if at least one reference to another dataset has been dropped.
4678 : */
4679 18872 : int GDALDataset::CloseDependentDatasets()
4680 : {
4681 18872 : return oOvManager.CloseDependentDatasets();
4682 : }
4683 :
4684 : /************************************************************************/
4685 : /* ReportError() */
4686 : /************************************************************************/
4687 :
4688 : #ifndef DOXYGEN_XML
4689 : /**
4690 : * \brief Emits an error related to a dataset.
4691 : *
4692 : * This function is a wrapper for regular CPLError(). The only difference
4693 : * with CPLError() is that it prepends the error message with the dataset
4694 : * name.
4695 : *
4696 : * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4697 : * @param err_no the error number (CPLE_*) from cpl_error.h.
4698 : * @param fmt a printf() style format string. Any additional arguments
4699 : * will be treated as arguments to fill in this format in a manner
4700 : * similar to printf().
4701 : *
4702 : * @since GDAL 1.9.0
4703 : */
4704 :
4705 98 : void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
4706 : const char *fmt, ...) const
4707 : {
4708 : va_list args;
4709 98 : va_start(args, fmt);
4710 98 : ReportErrorV(GetDescription(), eErrClass, err_no, fmt, args);
4711 98 : va_end(args);
4712 98 : }
4713 :
4714 : /**
4715 : * \brief Emits an error related to a dataset (static method)
4716 : *
4717 : * This function is a wrapper for regular CPLError(). The only difference
4718 : * with CPLError() is that it prepends the error message with the dataset
4719 : * name.
4720 : *
4721 : * @param pszDSName dataset name.
4722 : * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4723 : * @param err_no the error number (CPLE_*) from cpl_error.h.
4724 : * @param fmt a printf() style format string. Any additional arguments
4725 : * will be treated as arguments to fill in this format in a manner
4726 : * similar to printf().
4727 : *
4728 : * @since GDAL 3.2.0
4729 : */
4730 :
4731 122 : void GDALDataset::ReportError(const char *pszDSName, CPLErr eErrClass,
4732 : CPLErrorNum err_no, const char *fmt, ...)
4733 : {
4734 : va_list args;
4735 122 : va_start(args, fmt);
4736 122 : ReportErrorV(pszDSName, eErrClass, err_no, fmt, args);
4737 122 : va_end(args);
4738 122 : }
4739 :
4740 220 : void GDALDataset::ReportErrorV(const char *pszDSName, CPLErr eErrClass,
4741 : CPLErrorNum err_no, const char *fmt,
4742 : va_list args)
4743 : {
4744 220 : pszDSName = CPLGetFilename(pszDSName);
4745 220 : if (pszDSName[0] != '\0')
4746 : {
4747 207 : CPLError(eErrClass, err_no, "%s",
4748 414 : std::string(pszDSName)
4749 207 : .append(": ")
4750 414 : .append(CPLString().vPrintf(fmt, args))
4751 : .c_str());
4752 : }
4753 : else
4754 : {
4755 13 : CPLErrorV(eErrClass, err_no, fmt, args);
4756 : }
4757 220 : }
4758 : #endif
4759 :
4760 : /************************************************************************/
4761 : /* GetMetadata() */
4762 : /************************************************************************/
4763 68517 : char **GDALDataset::GetMetadata(const char *pszDomain)
4764 : {
4765 : #ifndef WITHOUT_DERIVED
4766 68517 : if (pszDomain != nullptr && EQUAL(pszDomain, "DERIVED_SUBDATASETS"))
4767 : {
4768 10 : oDerivedMetadataList.Clear();
4769 :
4770 : // First condition: at least one raster band.
4771 10 : if (GetRasterCount() > 0)
4772 : {
4773 : // Check if there is at least one complex band.
4774 10 : bool hasAComplexBand = false;
4775 :
4776 19 : for (int rasterId = 1; rasterId <= GetRasterCount(); ++rasterId)
4777 : {
4778 11 : if (GDALDataTypeIsComplex(
4779 11 : GetRasterBand(rasterId)->GetRasterDataType()))
4780 : {
4781 2 : hasAComplexBand = true;
4782 2 : break;
4783 : }
4784 : }
4785 :
4786 10 : unsigned int nbSupportedDerivedDS = 0;
4787 : const DerivedDatasetDescription *poDDSDesc =
4788 10 : GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
4789 :
4790 10 : int nNumDataset = 1;
4791 80 : for (unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
4792 : ++derivedId)
4793 : {
4794 126 : if (hasAComplexBand ||
4795 126 : CPLString(poDDSDesc[derivedId].pszInputPixelType) !=
4796 : "complex")
4797 : {
4798 : oDerivedMetadataList.SetNameValue(
4799 : CPLSPrintf("DERIVED_SUBDATASET_%d_NAME", nNumDataset),
4800 : CPLSPrintf("DERIVED_SUBDATASET:%s:%s",
4801 22 : poDDSDesc[derivedId].pszDatasetName,
4802 22 : GetDescription()));
4803 :
4804 : CPLString osDesc(
4805 : CPLSPrintf("%s from %s",
4806 22 : poDDSDesc[derivedId].pszDatasetDescription,
4807 22 : GetDescription()));
4808 : oDerivedMetadataList.SetNameValue(
4809 : CPLSPrintf("DERIVED_SUBDATASET_%d_DESC", nNumDataset),
4810 22 : osDesc.c_str());
4811 :
4812 22 : nNumDataset++;
4813 : }
4814 : }
4815 : }
4816 10 : return oDerivedMetadataList.List();
4817 : }
4818 : #endif
4819 :
4820 68507 : return GDALMajorObject::GetMetadata(pszDomain);
4821 : }
4822 :
4823 : // clang-format off
4824 :
4825 : /**
4826 : * \fn GDALDataset::SetMetadata( char ** papszMetadata, const char * pszDomain)
4827 : * \brief Set metadata.
4828 : *
4829 : * CAUTION: depending on the format, older values of the updated information
4830 : * might still be found in the file in a "ghost" state, even if no longer
4831 : * accessible through the GDAL API. This is for example the case of the GTiff
4832 : * format (this is not a exhaustive list)
4833 : *
4834 : * The C function GDALSetMetadata() does the same thing as this method.
4835 : *
4836 : * @param papszMetadata the metadata in name=value string list format to
4837 : * apply.
4838 : * @param pszDomain the domain of interest. Use "" or NULL for the default
4839 : * domain.
4840 : * @return CE_None on success, CE_Failure on failure and CE_Warning if the
4841 : * metadata has been accepted, but is likely not maintained persistently
4842 : * by the underlying object between sessions.
4843 : */
4844 :
4845 : /**
4846 : * \fn GDALDataset::SetMetadataItem( const char * pszName, const char * pszValue, const char * pszDomain)
4847 : * \brief Set single metadata item.
4848 : *
4849 : * CAUTION: depending on the format, older values of the updated information
4850 : * might still be found in the file in a "ghost" state, even if no longer
4851 : * accessible through the GDAL API. This is for example the case of the GTiff
4852 : * format (this is not a exhaustive list)
4853 : *
4854 : * The C function GDALSetMetadataItem() does the same thing as this method.
4855 : *
4856 : * @param pszName the key for the metadata item to fetch.
4857 : * @param pszValue the value to assign to the key.
4858 : * @param pszDomain the domain to set within, use NULL for the default domain.
4859 : *
4860 : * @return CE_None on success, or an error code on failure.
4861 : */
4862 :
4863 : // clang-format on
4864 :
4865 : /************************************************************************/
4866 : /* GetMetadataDomainList() */
4867 : /************************************************************************/
4868 :
4869 936 : char **GDALDataset::GetMetadataDomainList()
4870 : {
4871 936 : char **currentDomainList = CSLDuplicate(oMDMD.GetDomainList());
4872 :
4873 : // Ensure that we do not duplicate DERIVED domain.
4874 1076 : if (GetRasterCount() > 0 &&
4875 140 : CSLFindString(currentDomainList, "DERIVED_SUBDATASETS") == -1)
4876 : {
4877 : currentDomainList =
4878 140 : CSLAddString(currentDomainList, "DERIVED_SUBDATASETS");
4879 : }
4880 936 : return currentDomainList;
4881 : }
4882 :
4883 : /************************************************************************/
4884 : /* GetDriverName() */
4885 : /************************************************************************/
4886 :
4887 : /** Return driver name.
4888 : * @return driver name.
4889 : */
4890 2056 : const char *GDALDataset::GetDriverName()
4891 : {
4892 2056 : if (poDriver)
4893 2044 : return poDriver->GetDescription();
4894 12 : return "";
4895 : }
4896 :
4897 : /************************************************************************/
4898 : /* GDALDatasetReleaseResultSet() */
4899 : /************************************************************************/
4900 :
4901 : /**
4902 : \brief Release results of ExecuteSQL().
4903 :
4904 : This function should only be used to deallocate OGRLayers resulting from
4905 : an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
4906 : results set before destroying the GDALDataset may cause errors.
4907 :
4908 : This function is the same as the C++ method GDALDataset::ReleaseResultSet()
4909 :
4910 : @since GDAL 2.0
4911 :
4912 : @param hDS the dataset handle.
4913 : @param hLayer the result of a previous ExecuteSQL() call.
4914 :
4915 : */
4916 3408 : void GDALDatasetReleaseResultSet(GDALDatasetH hDS, OGRLayerH hLayer)
4917 :
4918 : {
4919 3408 : VALIDATE_POINTER0(hDS, "GDALDatasetReleaseResultSet");
4920 :
4921 : #ifdef OGRAPISPY_ENABLED
4922 3408 : if (bOGRAPISpyEnabled)
4923 6 : OGRAPISpy_DS_ReleaseResultSet(hDS, hLayer);
4924 : #endif
4925 :
4926 6816 : GDALDataset::FromHandle(hDS)->ReleaseResultSet(
4927 3408 : OGRLayer::FromHandle(hLayer));
4928 : }
4929 :
4930 : /************************************************************************/
4931 : /* GDALDatasetGetLayerCount() */
4932 : /************************************************************************/
4933 :
4934 : /**
4935 : \brief Get the number of layers in this dataset.
4936 :
4937 : This function is the same as the C++ method GDALDataset::GetLayerCount()
4938 :
4939 : @since GDAL 2.0
4940 :
4941 : @param hDS the dataset handle.
4942 : @return layer count.
4943 : */
4944 :
4945 1454 : int GDALDatasetGetLayerCount(GDALDatasetH hDS)
4946 :
4947 : {
4948 1454 : VALIDATE_POINTER1(hDS, "GDALDatasetH", 0);
4949 :
4950 : #ifdef OGRAPISPY_ENABLED
4951 1454 : if (bOGRAPISpyEnabled)
4952 2 : OGRAPISpy_DS_GetLayerCount(reinterpret_cast<GDALDatasetH>(hDS));
4953 : #endif
4954 :
4955 1454 : return GDALDataset::FromHandle(hDS)->GetLayerCount();
4956 : }
4957 :
4958 : /************************************************************************/
4959 : /* GDALDatasetGetLayer() */
4960 : /************************************************************************/
4961 :
4962 : /**
4963 : \brief Fetch a layer by index.
4964 :
4965 : The returned layer remains owned by the
4966 : GDALDataset and should not be deleted by the application.
4967 :
4968 : This function is the same as the C++ method GDALDataset::GetLayer()
4969 :
4970 : @since GDAL 2.0
4971 :
4972 : @param hDS the dataset handle.
4973 : @param iLayer a layer number between 0 and GetLayerCount()-1.
4974 :
4975 : @return the layer, or NULL if iLayer is out of range or an error occurs.
4976 : */
4977 :
4978 9187 : OGRLayerH GDALDatasetGetLayer(GDALDatasetH hDS, int iLayer)
4979 :
4980 : {
4981 9187 : VALIDATE_POINTER1(hDS, "GDALDatasetGetLayer", nullptr);
4982 :
4983 : OGRLayerH hLayer =
4984 9187 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->GetLayer(iLayer));
4985 :
4986 : #ifdef OGRAPISPY_ENABLED
4987 9187 : if (bOGRAPISpyEnabled)
4988 3 : OGRAPISpy_DS_GetLayer(hDS, iLayer, hLayer);
4989 : #endif
4990 :
4991 9187 : return hLayer;
4992 : }
4993 :
4994 : /************************************************************************/
4995 : /* GDALDatasetGetLayerByName() */
4996 : /************************************************************************/
4997 :
4998 : /**
4999 : \brief Fetch a layer by name.
5000 :
5001 : The returned layer remains owned by the
5002 : GDALDataset and should not be deleted by the application.
5003 :
5004 : This function is the same as the C++ method GDALDataset::GetLayerByName()
5005 :
5006 : @since GDAL 2.0
5007 :
5008 : @param hDS the dataset handle.
5009 : @param pszName the layer name of the layer to fetch.
5010 :
5011 : @return the layer, or NULL if Layer is not found or an error occurs.
5012 : */
5013 :
5014 3379 : OGRLayerH GDALDatasetGetLayerByName(GDALDatasetH hDS, const char *pszName)
5015 :
5016 : {
5017 3379 : VALIDATE_POINTER1(hDS, "GDALDatasetGetLayerByName", nullptr);
5018 :
5019 3379 : OGRLayerH hLayer = OGRLayer::ToHandle(
5020 3379 : GDALDataset::FromHandle(hDS)->GetLayerByName(pszName));
5021 :
5022 : #ifdef OGRAPISPY_ENABLED
5023 3379 : if (bOGRAPISpyEnabled)
5024 4 : OGRAPISpy_DS_GetLayerByName(hDS, pszName, hLayer);
5025 : #endif
5026 :
5027 3379 : return hLayer;
5028 : }
5029 :
5030 : /************************************************************************/
5031 : /* GDALDatasetIsLayerPrivate() */
5032 : /************************************************************************/
5033 :
5034 : /**
5035 : \brief Returns true if the layer at the specified index is deemed a private or
5036 : system table, or an internal detail only.
5037 :
5038 : This function is the same as the C++ method GDALDataset::IsLayerPrivate()
5039 :
5040 : @since GDAL 3.4
5041 :
5042 : @param hDS the dataset handle.
5043 : @param iLayer a layer number between 0 and GetLayerCount()-1.
5044 :
5045 : @return true if the layer is a private or system table.
5046 : */
5047 :
5048 91 : int GDALDatasetIsLayerPrivate(GDALDatasetH hDS, int iLayer)
5049 :
5050 : {
5051 91 : VALIDATE_POINTER1(hDS, "GDALDatasetIsLayerPrivate", false);
5052 :
5053 91 : const bool res = GDALDataset::FromHandle(hDS)->IsLayerPrivate(iLayer);
5054 :
5055 91 : return res ? 1 : 0;
5056 : }
5057 :
5058 : /************************************************************************/
5059 : /* GetLayerIndex() */
5060 : /************************************************************************/
5061 :
5062 : /**
5063 : \brief Returns the index of the layer specified by name.
5064 :
5065 : @since GDAL 3.12
5066 :
5067 : @param pszName layer name (not NULL)
5068 :
5069 : @return an index >= 0, or -1 if not found.
5070 : */
5071 :
5072 3 : int GDALDataset::GetLayerIndex(const char *pszName)
5073 : {
5074 3 : const int nLayerCount = GetLayerCount();
5075 3 : int iMatch = -1;
5076 6 : for (int i = 0; i < nLayerCount; ++i)
5077 : {
5078 5 : if (const auto poLayer = GetLayer(i))
5079 : {
5080 5 : const char *pszLayerName = poLayer->GetDescription();
5081 5 : if (strcmp(pszName, pszLayerName) == 0)
5082 : {
5083 2 : iMatch = i;
5084 2 : break;
5085 : }
5086 3 : else if (EQUAL(pszName, pszLayerName))
5087 : {
5088 0 : iMatch = i;
5089 : }
5090 : }
5091 : }
5092 3 : return iMatch;
5093 : }
5094 :
5095 : /************************************************************************/
5096 : /* GDALDatasetDeleteLayer() */
5097 : /************************************************************************/
5098 :
5099 : /**
5100 : \brief Delete the indicated layer from the datasource.
5101 :
5102 : If this function is supported
5103 : the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
5104 :
5105 : This method is the same as the C++ method GDALDataset::DeleteLayer().
5106 :
5107 : @since GDAL 2.0
5108 :
5109 : @param hDS the dataset handle.
5110 : @param iLayer the index of the layer to delete.
5111 :
5112 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
5113 : layers is not supported for this datasource.
5114 :
5115 : */
5116 40 : OGRErr GDALDatasetDeleteLayer(GDALDatasetH hDS, int iLayer)
5117 :
5118 : {
5119 40 : VALIDATE_POINTER1(hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE);
5120 :
5121 : #ifdef OGRAPISPY_ENABLED
5122 40 : if (bOGRAPISpyEnabled)
5123 2 : OGRAPISpy_DS_DeleteLayer(hDS, iLayer);
5124 : #endif
5125 :
5126 40 : return GDALDataset::FromHandle(hDS)->DeleteLayer(iLayer);
5127 : }
5128 :
5129 : /************************************************************************/
5130 : /* CreateLayer() */
5131 : /************************************************************************/
5132 :
5133 : /**
5134 : \brief This method attempts to create a new layer on the dataset with the
5135 : indicated name, coordinate system, geometry type.
5136 :
5137 : The papszOptions argument
5138 : can be used to control driver specific creation options. These options are
5139 : normally documented in the format specific documentation.
5140 : That function will try to validate the creation option list passed to the
5141 : driver with the GDALValidateCreationOptions() method. This check can be
5142 : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5143 : to NO.
5144 :
5145 : Drivers should extend the ICreateLayer() method and not
5146 : CreateLayer(). CreateLayer() adds validation of layer creation options, before
5147 : delegating the actual work to ICreateLayer().
5148 :
5149 : This method is the same as the C function GDALDatasetCreateLayer() and the
5150 : deprecated OGR_DS_CreateLayer().
5151 :
5152 : Example:
5153 :
5154 : \code{.cpp}
5155 : #include "gdal.h"
5156 : #include "cpl_string.h"
5157 :
5158 : ...
5159 :
5160 : OGRLayer *poLayer;
5161 : char **papszOptions;
5162 :
5163 : if( !poDS->TestCapability( ODsCCreateLayer ) )
5164 : {
5165 : ...
5166 : }
5167 :
5168 : papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5169 : poLayer = poDS->CreateLayer( "NewLayer", nullptr, wkbUnknown,
5170 : papszOptions );
5171 : CSLDestroy( papszOptions );
5172 :
5173 : if( poLayer == NULL )
5174 : {
5175 : ...
5176 : }
5177 : \endcode
5178 :
5179 : @param pszName the name for the new layer. This should ideally not
5180 : match any existing layer on the datasource.
5181 : @param poSpatialRef the coordinate system to use for the new layer, or NULL if
5182 : no coordinate system is available.
5183 : @param eGType the geometry type for the layer. Use wkbUnknown if there
5184 : are no constraints on the types geometry to be written.
5185 : @param papszOptions a StringList of name=value options. Options are driver
5186 : specific.
5187 :
5188 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5189 :
5190 : */
5191 :
5192 7742 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5193 : const OGRSpatialReference *poSpatialRef,
5194 : OGRwkbGeometryType eGType,
5195 : CSLConstList papszOptions)
5196 :
5197 : {
5198 7742 : if (eGType == wkbNone)
5199 : {
5200 452 : return CreateLayer(pszName, nullptr, papszOptions);
5201 : }
5202 : else
5203 : {
5204 14580 : OGRGeomFieldDefn oGeomFieldDefn("", eGType);
5205 7290 : oGeomFieldDefn.SetSpatialRef(poSpatialRef);
5206 7290 : return CreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5207 : }
5208 : }
5209 :
5210 : /**
5211 : \brief This method attempts to create a new layer on the dataset with the
5212 : indicated name and geometry field definition.
5213 :
5214 : When poGeomFieldDefn is not null, most drivers should honor
5215 : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5216 : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5217 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5218 : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5219 : very few currently.
5220 :
5221 : Note that even if a geometry coordinate precision is set and a driver honors the
5222 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5223 : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5224 : with the coordinate precision. That is they are assumed to be valid once their
5225 : coordinates are rounded to it. If it might not be the case, the user may set
5226 : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5227 : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5228 : the passed geometries.
5229 :
5230 : The papszOptions argument
5231 : can be used to control driver specific creation options. These options are
5232 : normally documented in the format specific documentation.
5233 : This function will try to validate the creation option list passed to the
5234 : driver with the GDALValidateCreationOptions() method. This check can be
5235 : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5236 : to NO.
5237 :
5238 : Drivers should extend the ICreateLayer() method and not
5239 : CreateLayer(). CreateLayer() adds validation of layer creation options, before
5240 : delegating the actual work to ICreateLayer().
5241 :
5242 : This method is the same as the C function GDALDatasetCreateLayerFromGeomFieldDefn().
5243 :
5244 : @param pszName the name for the new layer. This should ideally not
5245 : match any existing layer on the datasource.
5246 : @param poGeomFieldDefn the geometry field definition to use for the new layer,
5247 : or NULL if there is no geometry field.
5248 : @param papszOptions a StringList of name=value options. Options are driver
5249 : specific.
5250 :
5251 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5252 : @since 3.9
5253 :
5254 : */
5255 :
5256 8795 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5257 : const OGRGeomFieldDefn *poGeomFieldDefn,
5258 : CSLConstList papszOptions)
5259 :
5260 : {
5261 8795 : if (CPLTestBool(
5262 : CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
5263 : {
5264 8795 : ValidateLayerCreationOptions(papszOptions);
5265 : }
5266 :
5267 : OGRLayer *poLayer;
5268 8795 : if (poGeomFieldDefn)
5269 : {
5270 8111 : OGRGeomFieldDefn oGeomFieldDefn(poGeomFieldDefn);
5271 8204 : if (OGR_GT_IsNonLinear(poGeomFieldDefn->GetType()) &&
5272 93 : !TestCapability(ODsCCurveGeometries))
5273 : {
5274 23 : oGeomFieldDefn.SetType(
5275 : OGR_GT_GetLinear(poGeomFieldDefn->GetType()));
5276 : }
5277 :
5278 8111 : poLayer = ICreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5279 : }
5280 : else
5281 : {
5282 684 : poLayer = ICreateLayer(pszName, nullptr, papszOptions);
5283 : }
5284 : #ifdef DEBUG
5285 8865 : if (poLayer != nullptr && OGR_GT_IsNonLinear(poLayer->GetGeomType()) &&
5286 70 : !poLayer->TestCapability(OLCCurveGeometries))
5287 : {
5288 0 : CPLError(CE_Warning, CPLE_AppDefined,
5289 : "Inconsistent driver: Layer geometry type is non-linear, but "
5290 : "TestCapability(OLCCurveGeometries) returns FALSE.");
5291 : }
5292 : #endif
5293 :
5294 8795 : return poLayer;
5295 : }
5296 :
5297 : //! @cond Doxygen_Suppress
5298 :
5299 : // Technical override to avoid ambiguous choice between the old and new
5300 : // new CreateLayer() signatures.
5301 11 : OGRLayer *GDALDataset::CreateLayer(const char *pszName)
5302 : {
5303 22 : OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5304 22 : return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5305 : }
5306 :
5307 : // Technical override to avoid ambiguous choice between the old and new
5308 : // new CreateLayer() signatures.
5309 1 : OGRLayer *GDALDataset::CreateLayer(const char *pszName, std::nullptr_t)
5310 : {
5311 2 : OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5312 2 : return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5313 : }
5314 :
5315 : //!@endcond
5316 :
5317 : /************************************************************************/
5318 : /* GDALDatasetCreateLayer() */
5319 : /************************************************************************/
5320 :
5321 : /**
5322 : \brief This function attempts to create a new layer on the dataset with the
5323 : indicated name, coordinate system, geometry type.
5324 :
5325 : The papszOptions argument can be used to control driver specific creation
5326 : options. These options are normally documented in the format specific
5327 : documentation.
5328 :
5329 : This method is the same as the C++ method GDALDataset::CreateLayer().
5330 :
5331 : Example:
5332 :
5333 : \code{.c}
5334 : #include "gdal.h"
5335 : #include "cpl_string.h"
5336 :
5337 : ...
5338 :
5339 : OGRLayerH hLayer;
5340 : char **papszOptions;
5341 :
5342 : if( !GDALDatasetTestCapability( hDS, ODsCCreateLayer ) )
5343 : {
5344 : ...
5345 : }
5346 :
5347 : papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5348 : hLayer = GDALDatasetCreateLayer( hDS, "NewLayer", NULL, wkbUnknown,
5349 : papszOptions );
5350 : CSLDestroy( papszOptions );
5351 :
5352 : if( hLayer == NULL )
5353 : {
5354 : ...
5355 : }
5356 : \endcode
5357 :
5358 : @since GDAL 2.0
5359 :
5360 : @param hDS the dataset handle
5361 : @param pszName the name for the new layer. This should ideally not
5362 : match any existing layer on the datasource.
5363 : @param hSpatialRef the coordinate system to use for the new layer, or NULL if
5364 : no coordinate system is available.
5365 : @param eGType the geometry type for the layer. Use wkbUnknown if there
5366 : are no constraints on the types geometry to be written.
5367 : @param papszOptions a StringList of name=value options. Options are driver
5368 : specific.
5369 :
5370 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5371 :
5372 : */
5373 :
5374 5908 : OGRLayerH GDALDatasetCreateLayer(GDALDatasetH hDS, const char *pszName,
5375 : OGRSpatialReferenceH hSpatialRef,
5376 : OGRwkbGeometryType eGType,
5377 : CSLConstList papszOptions)
5378 :
5379 : {
5380 5908 : VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayer", nullptr);
5381 :
5382 5908 : if (pszName == nullptr)
5383 : {
5384 0 : CPLError(CE_Failure, CPLE_ObjectNull,
5385 : "Name was NULL in GDALDatasetCreateLayer");
5386 0 : return nullptr;
5387 : }
5388 :
5389 : OGRLayerH hLayer =
5390 11816 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5391 5908 : pszName, OGRSpatialReference::FromHandle(hSpatialRef), eGType,
5392 : const_cast<char **>(papszOptions)));
5393 :
5394 : #ifdef OGRAPISPY_ENABLED
5395 5908 : if (bOGRAPISpyEnabled)
5396 8 : OGRAPISpy_DS_CreateLayer(hDS, pszName, hSpatialRef, eGType,
5397 : const_cast<char **>(papszOptions), hLayer);
5398 : #endif
5399 :
5400 5908 : return hLayer;
5401 : }
5402 :
5403 : /************************************************************************/
5404 : /* GDALDatasetCreateLayerFromGeomFieldDefn() */
5405 : /************************************************************************/
5406 :
5407 : /**
5408 : \brief This function attempts to create a new layer on the dataset with the
5409 : indicated name and geometry field.
5410 :
5411 : When poGeomFieldDefn is not null, most drivers should honor
5412 : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5413 : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5414 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5415 : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5416 : very few currently.
5417 :
5418 : Note that even if a geometry coordinate precision is set and a driver honors the
5419 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5420 : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5421 : with the coordinate precision. That is they are assumed to be valid once their
5422 : coordinates are rounded to it. If it might not be the case, the user may set
5423 : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5424 : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5425 : the passed geometries.
5426 :
5427 : The papszOptions argument can be used to control driver specific creation
5428 : options. These options are normally documented in the format specific
5429 : documentation.
5430 :
5431 : This method is the same as the C++ method GDALDataset::CreateLayer().
5432 :
5433 : @param hDS the dataset handle
5434 : @param pszName the name for the new layer. This should ideally not
5435 : match any existing layer on the datasource.
5436 : @param hGeomFieldDefn the geometry field definition. May be NULL to indicate
5437 : a non-spatial file (or if adding geometry fields later with OGR_L_CreateGeomField()
5438 : for drivers supporting that interface).
5439 : @param papszOptions a StringList of name=value options. Options are driver
5440 : specific.
5441 :
5442 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5443 :
5444 : @since GDAL 3.9
5445 :
5446 : */
5447 :
5448 : OGRLayerH
5449 14 : GDALDatasetCreateLayerFromGeomFieldDefn(GDALDatasetH hDS, const char *pszName,
5450 : OGRGeomFieldDefnH hGeomFieldDefn,
5451 : CSLConstList papszOptions)
5452 :
5453 : {
5454 14 : VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayerFromGeomFieldDefn", nullptr);
5455 :
5456 14 : if (!pszName)
5457 : {
5458 0 : CPLError(CE_Failure, CPLE_ObjectNull,
5459 : "Name was NULL in GDALDatasetCreateLayerFromGeomFieldDefn");
5460 0 : return nullptr;
5461 : }
5462 :
5463 : OGRLayerH hLayer =
5464 28 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5465 14 : pszName, OGRGeomFieldDefn::FromHandle(hGeomFieldDefn),
5466 : papszOptions));
5467 14 : return hLayer;
5468 : }
5469 :
5470 : /************************************************************************/
5471 : /* GDALDatasetCopyLayer() */
5472 : /************************************************************************/
5473 :
5474 : /**
5475 : \brief Duplicate an existing layer.
5476 :
5477 : This function creates a new layer, duplicate the field definitions of the
5478 : source layer and then duplicate each features of the source layer.
5479 : The papszOptions argument
5480 : can be used to control driver specific creation options. These options are
5481 : normally documented in the format specific documentation.
5482 : The source layer may come from another dataset.
5483 :
5484 : This method is the same as the C++ method GDALDataset::CopyLayer()
5485 :
5486 : @since GDAL 2.0
5487 :
5488 : @param hDS the dataset handle.
5489 : @param hSrcLayer source layer.
5490 : @param pszNewName the name of the layer to create.
5491 : @param papszOptions a StringList of name=value options. Options are driver
5492 : specific.
5493 :
5494 : @return a handle to the layer, or NULL if an error occurs.
5495 : */
5496 12 : OGRLayerH GDALDatasetCopyLayer(GDALDatasetH hDS, OGRLayerH hSrcLayer,
5497 : const char *pszNewName,
5498 : CSLConstList papszOptions)
5499 :
5500 : {
5501 12 : VALIDATE_POINTER1(hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", nullptr);
5502 12 : VALIDATE_POINTER1(hSrcLayer, "GDALDatasetCopyLayer", nullptr);
5503 12 : VALIDATE_POINTER1(pszNewName, "GDALDatasetCopyLayer", nullptr);
5504 :
5505 24 : return OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CopyLayer(
5506 : OGRLayer::FromHandle(hSrcLayer), pszNewName,
5507 24 : const_cast<char **>(papszOptions)));
5508 : }
5509 :
5510 : /************************************************************************/
5511 : /* GDALDatasetExecuteSQL() */
5512 : /************************************************************************/
5513 :
5514 : /**
5515 : \brief Execute an SQL statement against the data store.
5516 :
5517 : The result of an SQL query is either NULL for statements that are in error,
5518 : or that have no results set, or an OGRLayer pointer representing a results
5519 : set from the query. Note that this OGRLayer is in addition to the layers
5520 : in the data store and must be destroyed with
5521 : ReleaseResultSet() before the dataset is closed
5522 : (destroyed).
5523 :
5524 : This method is the same as the C++ method GDALDataset::ExecuteSQL()
5525 :
5526 : For more information on the SQL dialect supported internally by OGR
5527 : review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
5528 : document. Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
5529 : to the underlying RDBMS.
5530 :
5531 : Starting with OGR 1.10, the <a
5532 : href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
5533 : also be used.
5534 :
5535 : @since GDAL 2.0
5536 :
5537 : @param hDS the dataset handle.
5538 : @param pszStatement the SQL statement to execute.
5539 : @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.
5540 :
5541 : @param pszDialect allows control of the statement dialect. If set to NULL, the
5542 : OGR SQL engine will be used, except for RDBMS drivers that will use their
5543 : dedicated SQL engine, unless OGRSQL is explicitly passed as the
5544 : dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
5545 :
5546 : @return an OGRLayer containing the results of the query. Deallocate with
5547 : GDALDatasetReleaseResultSet().
5548 :
5549 : */
5550 :
5551 10449 : OGRLayerH GDALDatasetExecuteSQL(GDALDatasetH hDS, const char *pszStatement,
5552 : OGRGeometryH hSpatialFilter,
5553 : const char *pszDialect)
5554 :
5555 : {
5556 10449 : VALIDATE_POINTER1(hDS, "GDALDatasetExecuteSQL", nullptr);
5557 :
5558 : OGRLayerH hLayer =
5559 20898 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->ExecuteSQL(
5560 10449 : pszStatement, OGRGeometry::FromHandle(hSpatialFilter), pszDialect));
5561 :
5562 : #ifdef OGRAPISPY_ENABLED
5563 10449 : if (bOGRAPISpyEnabled)
5564 4 : OGRAPISpy_DS_ExecuteSQL(hDS, pszStatement, hSpatialFilter, pszDialect,
5565 : hLayer);
5566 : #endif
5567 :
5568 10449 : return hLayer;
5569 : }
5570 :
5571 : /************************************************************************/
5572 : /* GDALDatasetAbortSQL() */
5573 : /************************************************************************/
5574 :
5575 : /**
5576 : \brief Abort any SQL statement running in the data store.
5577 :
5578 : This function can be safely called from any thread (pending that the dataset
5579 : object is still alive). Driver implementations will make sure that it can be
5580 : called in a thread-safe way.
5581 :
5582 : This might not be implemented by all drivers. At time of writing, only SQLite,
5583 : GPKG and PG drivers implement it
5584 :
5585 : This method is the same as the C++ method GDALDataset::AbortSQL()
5586 :
5587 : @since GDAL 3.2.0
5588 :
5589 : @param hDS the dataset handle.
5590 :
5591 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if AbortSQL
5592 : is not supported for this datasource. .
5593 :
5594 : */
5595 :
5596 6 : OGRErr GDALDatasetAbortSQL(GDALDatasetH hDS)
5597 :
5598 : {
5599 6 : VALIDATE_POINTER1(hDS, "GDALDatasetAbortSQL", OGRERR_FAILURE);
5600 6 : return GDALDataset::FromHandle(hDS)->AbortSQL();
5601 : }
5602 :
5603 : /************************************************************************/
5604 : /* GDALDatasetGetStyleTable() */
5605 : /************************************************************************/
5606 :
5607 : /**
5608 : \brief Returns dataset style table.
5609 :
5610 : This function is the same as the C++ method GDALDataset::GetStyleTable()
5611 :
5612 : @since GDAL 2.0
5613 :
5614 : @param hDS the dataset handle
5615 : @return handle to a style table which should not be modified or freed by the
5616 : caller.
5617 : */
5618 :
5619 6 : OGRStyleTableH GDALDatasetGetStyleTable(GDALDatasetH hDS)
5620 :
5621 : {
5622 6 : VALIDATE_POINTER1(hDS, "OGR_DS_GetStyleTable", nullptr);
5623 :
5624 : return reinterpret_cast<OGRStyleTableH>(
5625 6 : GDALDataset::FromHandle(hDS)->GetStyleTable());
5626 : }
5627 :
5628 : /************************************************************************/
5629 : /* GDALDatasetSetStyleTableDirectly() */
5630 : /************************************************************************/
5631 :
5632 : /**
5633 : \brief Set dataset style table.
5634 :
5635 : This function operate exactly as GDALDatasetSetStyleTable() except that it
5636 : assumes ownership of the passed table.
5637 :
5638 : This function is the same as the C++ method
5639 : GDALDataset::SetStyleTableDirectly()
5640 :
5641 : @since GDAL 2.0
5642 :
5643 : @param hDS the dataset handle
5644 : @param hStyleTable style table handle to set
5645 :
5646 : */
5647 :
5648 0 : void GDALDatasetSetStyleTableDirectly(GDALDatasetH hDS,
5649 : OGRStyleTableH hStyleTable)
5650 :
5651 : {
5652 0 : VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTableDirectly");
5653 :
5654 0 : GDALDataset::FromHandle(hDS)->SetStyleTableDirectly(
5655 0 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
5656 : }
5657 :
5658 : /************************************************************************/
5659 : /* GDALDatasetSetStyleTable() */
5660 : /************************************************************************/
5661 :
5662 : /**
5663 : \brief Set dataset style table.
5664 :
5665 : This function operate exactly as GDALDatasetSetStyleTableDirectly() except that
5666 : it assumes ownership of the passed table.
5667 :
5668 : This function is the same as the C++ method GDALDataset::SetStyleTable()
5669 :
5670 : @since GDAL 2.0
5671 :
5672 : @param hDS the dataset handle
5673 : @param hStyleTable style table handle to set
5674 :
5675 : */
5676 :
5677 5 : void GDALDatasetSetStyleTable(GDALDatasetH hDS, OGRStyleTableH hStyleTable)
5678 :
5679 : {
5680 5 : VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTable");
5681 5 : VALIDATE_POINTER0(hStyleTable, "OGR_DS_SetStyleTable");
5682 :
5683 5 : GDALDataset::FromHandle(hDS)->SetStyleTable(
5684 5 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
5685 : }
5686 :
5687 : /************************************************************************/
5688 : /* ValidateLayerCreationOptions() */
5689 : /************************************************************************/
5690 :
5691 : //! @cond Doxygen_Suppress
5692 8795 : int GDALDataset::ValidateLayerCreationOptions(const char *const *papszLCO)
5693 : {
5694 : const char *pszOptionList =
5695 8795 : GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5696 8795 : if (pszOptionList == nullptr && poDriver != nullptr)
5697 : {
5698 : pszOptionList =
5699 8758 : poDriver->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5700 : }
5701 17590 : CPLString osDataset;
5702 8795 : osDataset.Printf("dataset %s", GetDescription());
5703 8795 : return GDALValidateOptions(pszOptionList, papszLCO, "layer creation option",
5704 17590 : osDataset);
5705 : }
5706 :
5707 : //! @endcond
5708 :
5709 : /************************************************************************/
5710 : /* Release() */
5711 : /************************************************************************/
5712 :
5713 : /**
5714 : \brief Drop a reference to this dataset, and if the reference count drops to one
5715 : close (destroy) the dataset.
5716 :
5717 : This method is the same as the C function OGRReleaseDataSource().
5718 :
5719 : @deprecated. In GDAL 2, use GDALClose() instead
5720 :
5721 : @return OGRERR_NONE on success or an error code.
5722 : */
5723 :
5724 3892 : OGRErr GDALDataset::Release()
5725 :
5726 : {
5727 3892 : ReleaseRef();
5728 3892 : return OGRERR_NONE;
5729 : }
5730 :
5731 : /************************************************************************/
5732 : /* GetRefCount() */
5733 : /************************************************************************/
5734 :
5735 : /**
5736 : \brief Fetch reference count.
5737 :
5738 : This method is the same as the C function OGR_DS_GetRefCount().
5739 :
5740 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5741 :
5742 : @return the current reference count for the datasource object itself.
5743 : */
5744 :
5745 918 : int GDALDataset::GetRefCount() const
5746 : {
5747 918 : return nRefCount;
5748 : }
5749 :
5750 : /************************************************************************/
5751 : /* GetSummaryRefCount() */
5752 : /************************************************************************/
5753 :
5754 : /**
5755 : \brief Fetch reference count of datasource and all owned layers.
5756 :
5757 : This method is the same as the C function OGR_DS_GetSummaryRefCount().
5758 :
5759 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5760 :
5761 : @deprecated
5762 :
5763 : @return the current summary reference count for the datasource and its layers.
5764 : */
5765 :
5766 0 : int GDALDataset::GetSummaryRefCount() const
5767 :
5768 : {
5769 0 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
5770 0 : int nSummaryCount = nRefCount;
5771 0 : GDALDataset *poUseThis = const_cast<GDALDataset *>(this);
5772 :
5773 0 : for (int iLayer = 0; iLayer < poUseThis->GetLayerCount(); ++iLayer)
5774 0 : nSummaryCount += poUseThis->GetLayer(iLayer)->GetRefCount();
5775 :
5776 0 : return nSummaryCount;
5777 : }
5778 :
5779 : /************************************************************************/
5780 : /* ICreateLayer() */
5781 : /************************************************************************/
5782 :
5783 : /**
5784 : \brief This method attempts to create a new layer on the dataset with the
5785 : indicated name, coordinate system, geometry type.
5786 :
5787 : This method is reserved to implementation by drivers.
5788 :
5789 : The papszOptions argument can be used to control driver specific creation
5790 : options. These options are normally documented in the format specific
5791 : documentation.
5792 :
5793 : @param pszName the name for the new layer. This should ideally not
5794 : match any existing layer on the datasource.
5795 : @param poGeomFieldDefn the geometry field definition to use for the new layer,
5796 : or NULL if there is no geometry field.
5797 : @param papszOptions a StringList of name=value options. Options are driver
5798 : specific.
5799 :
5800 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5801 :
5802 : @since GDAL 2.0 (prototype modified in 3.9)
5803 : */
5804 :
5805 : OGRLayer *
5806 16 : GDALDataset::ICreateLayer(CPL_UNUSED const char *pszName,
5807 : CPL_UNUSED const OGRGeomFieldDefn *poGeomFieldDefn,
5808 : CPL_UNUSED CSLConstList papszOptions)
5809 :
5810 : {
5811 16 : CPLError(CE_Failure, CPLE_NotSupported,
5812 : "CreateLayer() not supported by this dataset.");
5813 :
5814 16 : return nullptr;
5815 : }
5816 :
5817 : /************************************************************************/
5818 : /* CopyLayer() */
5819 : /************************************************************************/
5820 :
5821 : /**
5822 : \brief Duplicate an existing layer.
5823 :
5824 : This method creates a new layer, duplicate the field definitions of the
5825 : source layer and then duplicate each features of the source layer.
5826 : The papszOptions argument
5827 : can be used to control driver specific creation options. These options are
5828 : normally documented in the format specific documentation.
5829 : The source layer may come from another dataset.
5830 :
5831 : This method is the same as the C function GDALDatasetCopyLayer() and the
5832 : deprecated OGR_DS_CopyLayer().
5833 :
5834 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5835 :
5836 : @param poSrcLayer source layer.
5837 : @param pszNewName the name of the layer to create.
5838 : @param papszOptions a StringList of name=value options. Options are driver
5839 : specific. There is a common option to set output layer
5840 : spatial reference: DST_SRSWKT. The option should be in
5841 : WKT format. Starting with GDAL 3.7, the common option
5842 : COPY_MD can be set to NO to prevent the default copying
5843 : of the metadata from the source layer to the target layer.
5844 :
5845 : @return a handle to the layer, or NULL if an error occurs.
5846 : */
5847 :
5848 128 : OGRLayer *GDALDataset::CopyLayer(OGRLayer *poSrcLayer, const char *pszNewName,
5849 : char **papszOptions)
5850 :
5851 : {
5852 : /* -------------------------------------------------------------------- */
5853 : /* Create the layer. */
5854 : /* -------------------------------------------------------------------- */
5855 128 : if (!TestCapability(ODsCCreateLayer))
5856 : {
5857 0 : CPLError(CE_Failure, CPLE_NotSupported,
5858 : "This datasource does not support creation of layers.");
5859 0 : return nullptr;
5860 : }
5861 :
5862 128 : const char *pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
5863 256 : OGRSpatialReference oDstSpaRef(pszSRSWKT);
5864 128 : oDstSpaRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
5865 128 : OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
5866 128 : OGRLayer *poDstLayer = nullptr;
5867 :
5868 256 : CPLStringList aosCleanedUpOptions(CSLDuplicate(papszOptions));
5869 128 : aosCleanedUpOptions.SetNameValue("DST_SRSWKT", nullptr);
5870 128 : aosCleanedUpOptions.SetNameValue("COPY_MD", nullptr);
5871 :
5872 128 : CPLErrorReset();
5873 128 : const int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
5874 128 : if (nSrcGeomFieldCount == 1)
5875 : {
5876 76 : OGRGeomFieldDefn oGeomFieldDefn(poSrcDefn->GetGeomFieldDefn(0));
5877 76 : if (pszSRSWKT)
5878 5 : oGeomFieldDefn.SetSpatialRef(&oDstSpaRef);
5879 76 : poDstLayer = ICreateLayer(pszNewName, &oGeomFieldDefn,
5880 76 : aosCleanedUpOptions.List());
5881 : }
5882 : else
5883 : {
5884 : poDstLayer =
5885 52 : ICreateLayer(pszNewName, nullptr, aosCleanedUpOptions.List());
5886 : }
5887 :
5888 128 : if (poDstLayer == nullptr)
5889 0 : return nullptr;
5890 :
5891 128 : if (CPLTestBool(CSLFetchNameValueDef(papszOptions, "COPY_MD", "YES")))
5892 : {
5893 127 : char **papszMD = poSrcLayer->GetMetadata();
5894 127 : if (papszMD)
5895 7 : poDstLayer->SetMetadata(papszMD);
5896 : }
5897 :
5898 : /* -------------------------------------------------------------------- */
5899 : /* Add fields. Default to copy all fields, and make sure to */
5900 : /* establish a mapping between indices, rather than names, in */
5901 : /* case the target datasource has altered it (e.g. Shapefile */
5902 : /* limited to 10 char field names). */
5903 : /* -------------------------------------------------------------------- */
5904 128 : const int nSrcFieldCount = poSrcDefn->GetFieldCount();
5905 :
5906 : // Initialize the index-to-index map to -1's.
5907 256 : std::vector<int> anMap(nSrcFieldCount, -1);
5908 :
5909 : // Caution: At the time of writing, the MapInfo driver
5910 : // returns NULL until a field has been added.
5911 128 : OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
5912 128 : int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
5913 279 : for (int iField = 0; iField < nSrcFieldCount; ++iField)
5914 : {
5915 151 : OGRFieldDefn *poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
5916 302 : OGRFieldDefn oFieldDefn(poSrcFieldDefn);
5917 :
5918 : // The field may have been already created at layer creation.
5919 151 : int iDstField = -1;
5920 151 : if (poDstFDefn)
5921 151 : iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
5922 151 : if (iDstField >= 0)
5923 : {
5924 0 : anMap[iField] = iDstField;
5925 : }
5926 151 : else if (poDstLayer->CreateField(&oFieldDefn) == OGRERR_NONE)
5927 : {
5928 : // Now that we've created a field, GetLayerDefn() won't return NULL.
5929 151 : if (poDstFDefn == nullptr)
5930 0 : poDstFDefn = poDstLayer->GetLayerDefn();
5931 :
5932 : // Sanity check: if it fails, the driver is buggy.
5933 302 : if (poDstFDefn != nullptr &&
5934 151 : poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
5935 : {
5936 0 : CPLError(CE_Warning, CPLE_AppDefined,
5937 : "The output driver has claimed to have added the %s "
5938 : "field, but it did not!",
5939 : oFieldDefn.GetNameRef());
5940 : }
5941 : else
5942 : {
5943 151 : anMap[iField] = nDstFieldCount;
5944 151 : ++nDstFieldCount;
5945 : }
5946 : }
5947 : }
5948 :
5949 : /* -------------------------------------------------------------------- */
5950 128 : std::unique_ptr<OGRCoordinateTransformation> poCT;
5951 128 : OGRSpatialReference *sourceSRS = poSrcLayer->GetSpatialRef();
5952 128 : if (sourceSRS != nullptr && pszSRSWKT != nullptr && !oDstSpaRef.IsEmpty() &&
5953 0 : sourceSRS->IsSame(&oDstSpaRef) == FALSE)
5954 : {
5955 0 : poCT.reset(OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef));
5956 0 : if (nullptr == poCT)
5957 : {
5958 0 : CPLError(CE_Failure, CPLE_NotSupported,
5959 : "This input/output spatial reference is not supported.");
5960 0 : return nullptr;
5961 : }
5962 : }
5963 : /* -------------------------------------------------------------------- */
5964 : /* Create geometry fields. */
5965 : /* -------------------------------------------------------------------- */
5966 129 : if (nSrcGeomFieldCount > 1 &&
5967 1 : TestCapability(ODsCCreateGeomFieldAfterCreateLayer))
5968 : {
5969 :
5970 3 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5971 : {
5972 2 : if (nullptr == pszSRSWKT)
5973 : {
5974 2 : poDstLayer->CreateGeomField(
5975 2 : poSrcDefn->GetGeomFieldDefn(iField));
5976 : }
5977 : else
5978 : {
5979 : OGRGeomFieldDefn *pDstGeomFieldDefn =
5980 0 : poSrcDefn->GetGeomFieldDefn(iField);
5981 0 : pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);
5982 0 : poDstLayer->CreateGeomField(pDstGeomFieldDefn);
5983 : }
5984 : }
5985 : }
5986 :
5987 : /* -------------------------------------------------------------------- */
5988 : /* Check if the destination layer supports transactions and set a */
5989 : /* default number of features in a single transaction. */
5990 : /* -------------------------------------------------------------------- */
5991 : const int nGroupTransactions =
5992 128 : poDstLayer->TestCapability(OLCTransactions) ? 128 : 0;
5993 :
5994 : /* -------------------------------------------------------------------- */
5995 : /* Transfer features. */
5996 : /* -------------------------------------------------------------------- */
5997 128 : poSrcLayer->ResetReading();
5998 :
5999 128 : if (nGroupTransactions <= 0)
6000 : {
6001 : while (true)
6002 : {
6003 : auto poFeature =
6004 423 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
6005 :
6006 423 : if (poFeature == nullptr)
6007 125 : break;
6008 :
6009 298 : CPLErrorReset();
6010 : auto poDstFeature =
6011 298 : std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
6012 :
6013 298 : if (poDstFeature->SetFrom(poFeature.get(), anMap.data(), TRUE) !=
6014 : OGRERR_NONE)
6015 : {
6016 0 : CPLError(CE_Failure, CPLE_AppDefined,
6017 : "Unable to translate feature " CPL_FRMT_GIB
6018 : " from layer %s.",
6019 0 : poFeature->GetFID(), poSrcDefn->GetName());
6020 0 : return poDstLayer;
6021 : }
6022 :
6023 298 : if (nullptr != poCT)
6024 : {
6025 0 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
6026 : {
6027 0 : OGRGeometry *pGeom = poDstFeature->GetGeomFieldRef(iField);
6028 0 : if (nullptr == pGeom)
6029 0 : continue;
6030 :
6031 0 : const OGRErr eErr = pGeom->transform(poCT.get());
6032 0 : if (eErr == OGRERR_NONE)
6033 0 : continue;
6034 :
6035 0 : CPLError(CE_Failure, CPLE_AppDefined,
6036 : "Unable to transform geometry " CPL_FRMT_GIB
6037 : " from layer %s.",
6038 0 : poFeature->GetFID(), poSrcDefn->GetName());
6039 0 : return poDstLayer;
6040 : }
6041 : }
6042 :
6043 298 : poDstFeature->SetFID(poFeature->GetFID());
6044 :
6045 298 : CPLErrorReset();
6046 298 : if (poDstLayer->CreateFeature(poDstFeature.get()) != OGRERR_NONE)
6047 : {
6048 0 : return poDstLayer;
6049 : }
6050 298 : }
6051 : }
6052 : else
6053 : {
6054 3 : std::vector<std::unique_ptr<OGRFeature>> apoDstFeatures;
6055 : try
6056 : {
6057 3 : apoDstFeatures.resize(nGroupTransactions);
6058 : }
6059 0 : catch (const std::exception &e)
6060 : {
6061 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "%s", e.what());
6062 0 : return poDstLayer;
6063 : }
6064 3 : bool bStopTransfer = false;
6065 6 : while (!bStopTransfer)
6066 : {
6067 : /* --------------------------------------------------------------------
6068 : */
6069 : /* Fill the array with features. */
6070 : /* --------------------------------------------------------------------
6071 : */
6072 : // Number of features in the temporary array.
6073 3 : int nFeatCount = 0; // Used after for.
6074 33 : for (nFeatCount = 0; nFeatCount < nGroupTransactions; ++nFeatCount)
6075 : {
6076 : auto poFeature =
6077 33 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
6078 :
6079 33 : if (poFeature == nullptr)
6080 : {
6081 3 : bStopTransfer = true;
6082 3 : break;
6083 : }
6084 :
6085 30 : CPLErrorReset();
6086 30 : apoDstFeatures[nFeatCount] =
6087 60 : std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
6088 :
6089 60 : if (apoDstFeatures[nFeatCount]->SetFrom(
6090 60 : poFeature.get(), anMap.data(), TRUE) != OGRERR_NONE)
6091 : {
6092 0 : CPLError(CE_Failure, CPLE_AppDefined,
6093 : "Unable to translate feature " CPL_FRMT_GIB
6094 : " from layer %s.",
6095 0 : poFeature->GetFID(), poSrcDefn->GetName());
6096 0 : bStopTransfer = true;
6097 0 : poFeature.reset();
6098 0 : break;
6099 : }
6100 :
6101 30 : if (nullptr != poCT)
6102 : {
6103 0 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
6104 : {
6105 : OGRGeometry *pGeom =
6106 0 : apoDstFeatures[nFeatCount]->GetGeomFieldRef(iField);
6107 0 : if (nullptr == pGeom)
6108 0 : continue;
6109 :
6110 0 : const OGRErr eErr = pGeom->transform(poCT.get());
6111 0 : if (eErr == OGRERR_NONE)
6112 0 : continue;
6113 :
6114 0 : CPLError(CE_Failure, CPLE_AppDefined,
6115 : "Unable to transform geometry " CPL_FRMT_GIB
6116 : " from layer %s.",
6117 0 : poFeature->GetFID(), poSrcDefn->GetName());
6118 0 : bStopTransfer = true;
6119 0 : poFeature.reset();
6120 0 : break;
6121 : }
6122 : }
6123 :
6124 30 : if (poFeature)
6125 : {
6126 30 : apoDstFeatures[nFeatCount]->SetFID(poFeature->GetFID());
6127 : }
6128 : }
6129 :
6130 3 : CPLErrorReset();
6131 3 : bool bStopTransaction = false;
6132 6 : while (!bStopTransaction)
6133 : {
6134 3 : bStopTransaction = true;
6135 3 : if (poDstLayer->StartTransaction() != OGRERR_NONE)
6136 0 : break;
6137 33 : for (int i = 0; i < nFeatCount; ++i)
6138 : {
6139 30 : if (poDstLayer->CreateFeature(apoDstFeatures[i].get()) !=
6140 : OGRERR_NONE)
6141 : {
6142 0 : bStopTransfer = true;
6143 0 : bStopTransaction = false;
6144 0 : break;
6145 : }
6146 30 : apoDstFeatures[i].reset();
6147 : }
6148 3 : if (bStopTransaction)
6149 : {
6150 3 : if (poDstLayer->CommitTransaction() != OGRERR_NONE)
6151 0 : break;
6152 : }
6153 : else
6154 : {
6155 0 : poDstLayer->RollbackTransaction();
6156 : }
6157 : }
6158 : }
6159 : }
6160 :
6161 128 : return poDstLayer;
6162 : }
6163 :
6164 : /************************************************************************/
6165 : /* DeleteLayer() */
6166 : /************************************************************************/
6167 :
6168 : /**
6169 : \fn GDALDataset::DeleteLayer(int)
6170 : \brief Delete the indicated layer from the datasource.
6171 :
6172 : If this method is supported
6173 : the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
6174 :
6175 : This method is the same as the C function GDALDatasetDeleteLayer() and the
6176 : deprecated OGR_DS_DeleteLayer().
6177 :
6178 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6179 :
6180 : @param iLayer the index of the layer to delete.
6181 :
6182 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
6183 : layers is not supported for this datasource.
6184 :
6185 : */
6186 :
6187 389 : OGRErr GDALDataset::DeleteLayer(CPL_UNUSED int iLayer)
6188 :
6189 : {
6190 389 : CPLError(CE_Failure, CPLE_NotSupported,
6191 : "DeleteLayer() not supported by this dataset.");
6192 :
6193 389 : return OGRERR_UNSUPPORTED_OPERATION;
6194 : }
6195 :
6196 : /************************************************************************/
6197 : /* GetLayerByName() */
6198 : /************************************************************************/
6199 :
6200 : /**
6201 : \brief Fetch a layer by name.
6202 :
6203 : The returned layer remains owned by the
6204 : GDALDataset and should not be deleted by the application.
6205 :
6206 : This method is the same as the C function GDALDatasetGetLayerByName() and the
6207 : deprecated OGR_DS_GetLayerByName().
6208 :
6209 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6210 :
6211 : @param pszName the layer name of the layer to fetch.
6212 :
6213 : @return the layer, or NULL if Layer is not found or an error occurs.
6214 : */
6215 :
6216 29442 : OGRLayer *GDALDataset::GetLayerByName(const char *pszName)
6217 :
6218 : {
6219 58884 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
6220 :
6221 29442 : if (!pszName)
6222 0 : return nullptr;
6223 :
6224 : // First a case sensitive check.
6225 931862 : for (int i = 0; i < GetLayerCount(); ++i)
6226 : {
6227 913890 : OGRLayer *poLayer = GetLayer(i);
6228 :
6229 913890 : if (strcmp(pszName, poLayer->GetName()) == 0)
6230 11470 : return poLayer;
6231 : }
6232 :
6233 : // Then case insensitive.
6234 893536 : for (int i = 0; i < GetLayerCount(); ++i)
6235 : {
6236 875753 : OGRLayer *poLayer = GetLayer(i);
6237 :
6238 875753 : if (EQUAL(pszName, poLayer->GetName()))
6239 189 : return poLayer;
6240 : }
6241 :
6242 17783 : return nullptr;
6243 : }
6244 :
6245 : //! @cond Doxygen_Suppress
6246 : /************************************************************************/
6247 : /* ProcessSQLCreateIndex() */
6248 : /* */
6249 : /* The correct syntax for creating an index in our dialect of */
6250 : /* SQL is: */
6251 : /* */
6252 : /* CREATE INDEX ON <layername> USING <columnname> */
6253 : /************************************************************************/
6254 :
6255 28 : OGRErr GDALDataset::ProcessSQLCreateIndex(const char *pszSQLCommand)
6256 :
6257 : {
6258 28 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6259 :
6260 : /* -------------------------------------------------------------------- */
6261 : /* Do some general syntax checking. */
6262 : /* -------------------------------------------------------------------- */
6263 56 : if (CSLCount(papszTokens) != 6 || !EQUAL(papszTokens[0], "CREATE") ||
6264 84 : !EQUAL(papszTokens[1], "INDEX") || !EQUAL(papszTokens[2], "ON") ||
6265 28 : !EQUAL(papszTokens[4], "USING"))
6266 : {
6267 0 : CSLDestroy(papszTokens);
6268 0 : CPLError(CE_Failure, CPLE_AppDefined,
6269 : "Syntax error in CREATE INDEX command.\n"
6270 : "Was '%s'\n"
6271 : "Should be of form 'CREATE INDEX ON <table> USING <field>'",
6272 : pszSQLCommand);
6273 0 : return OGRERR_FAILURE;
6274 : }
6275 :
6276 : /* -------------------------------------------------------------------- */
6277 : /* Find the named layer. */
6278 : /* -------------------------------------------------------------------- */
6279 28 : OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6280 28 : if (poLayer == nullptr)
6281 : {
6282 0 : CPLError(CE_Failure, CPLE_AppDefined,
6283 : "CREATE INDEX ON failed, no such layer as `%s'.",
6284 0 : papszTokens[3]);
6285 0 : CSLDestroy(papszTokens);
6286 0 : return OGRERR_FAILURE;
6287 : }
6288 :
6289 : /* -------------------------------------------------------------------- */
6290 : /* Does this layer even support attribute indexes? */
6291 : /* -------------------------------------------------------------------- */
6292 28 : if (poLayer->GetIndex() == nullptr)
6293 : {
6294 0 : CPLError(CE_Failure, CPLE_AppDefined,
6295 : "CREATE INDEX ON not supported by this driver.");
6296 0 : CSLDestroy(papszTokens);
6297 0 : return OGRERR_FAILURE;
6298 : }
6299 :
6300 : /* -------------------------------------------------------------------- */
6301 : /* Find the named field. */
6302 : /* -------------------------------------------------------------------- */
6303 28 : int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6304 :
6305 28 : CSLDestroy(papszTokens);
6306 :
6307 28 : if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6308 : {
6309 0 : CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6310 : pszSQLCommand);
6311 0 : return OGRERR_FAILURE;
6312 : }
6313 :
6314 : /* -------------------------------------------------------------------- */
6315 : /* Attempt to create the index. */
6316 : /* -------------------------------------------------------------------- */
6317 28 : OGRErr eErr = poLayer->GetIndex()->CreateIndex(i);
6318 28 : if (eErr == OGRERR_NONE)
6319 : {
6320 28 : eErr = poLayer->GetIndex()->IndexAllFeatures(i);
6321 : }
6322 : else
6323 : {
6324 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
6325 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot '%s'", pszSQLCommand);
6326 : }
6327 :
6328 28 : return eErr;
6329 : }
6330 :
6331 : /************************************************************************/
6332 : /* ProcessSQLDropIndex() */
6333 : /* */
6334 : /* The correct syntax for dropping one or more indexes in */
6335 : /* the OGR SQL dialect is: */
6336 : /* */
6337 : /* DROP INDEX ON <layername> [USING <columnname>] */
6338 : /************************************************************************/
6339 :
6340 10 : OGRErr GDALDataset::ProcessSQLDropIndex(const char *pszSQLCommand)
6341 :
6342 : {
6343 10 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6344 :
6345 : /* -------------------------------------------------------------------- */
6346 : /* Do some general syntax checking. */
6347 : /* -------------------------------------------------------------------- */
6348 20 : if ((CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6) ||
6349 10 : !EQUAL(papszTokens[0], "DROP") || !EQUAL(papszTokens[1], "INDEX") ||
6350 30 : !EQUAL(papszTokens[2], "ON") ||
6351 10 : (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4], "USING")))
6352 : {
6353 0 : CSLDestroy(papszTokens);
6354 0 : CPLError(CE_Failure, CPLE_AppDefined,
6355 : "Syntax error in DROP INDEX command.\n"
6356 : "Was '%s'\n"
6357 : "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
6358 : pszSQLCommand);
6359 0 : return OGRERR_FAILURE;
6360 : }
6361 :
6362 : /* -------------------------------------------------------------------- */
6363 : /* Find the named layer. */
6364 : /* -------------------------------------------------------------------- */
6365 10 : OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6366 10 : if (poLayer == nullptr)
6367 : {
6368 0 : CPLError(CE_Failure, CPLE_AppDefined,
6369 : "DROP INDEX ON failed, no such layer as `%s'.",
6370 0 : papszTokens[3]);
6371 0 : CSLDestroy(papszTokens);
6372 0 : return OGRERR_FAILURE;
6373 : }
6374 :
6375 : /* -------------------------------------------------------------------- */
6376 : /* Does this layer even support attribute indexes? */
6377 : /* -------------------------------------------------------------------- */
6378 10 : if (poLayer->GetIndex() == nullptr)
6379 : {
6380 0 : CPLError(CE_Failure, CPLE_AppDefined,
6381 : "Indexes not supported by this driver.");
6382 0 : CSLDestroy(papszTokens);
6383 0 : return OGRERR_FAILURE;
6384 : }
6385 :
6386 : /* -------------------------------------------------------------------- */
6387 : /* If we were not given a field name, drop all indexes. */
6388 : /* -------------------------------------------------------------------- */
6389 10 : if (CSLCount(papszTokens) == 4)
6390 : {
6391 0 : for (int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i)
6392 : {
6393 : OGRAttrIndex *poAttrIndex;
6394 :
6395 0 : poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
6396 0 : if (poAttrIndex != nullptr)
6397 : {
6398 0 : const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6399 0 : if (eErr != OGRERR_NONE)
6400 : {
6401 0 : CSLDestroy(papszTokens);
6402 0 : return eErr;
6403 : }
6404 : }
6405 : }
6406 :
6407 0 : CSLDestroy(papszTokens);
6408 0 : return OGRERR_NONE;
6409 : }
6410 :
6411 : /* -------------------------------------------------------------------- */
6412 : /* Find the named field. */
6413 : /* -------------------------------------------------------------------- */
6414 10 : int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6415 10 : CSLDestroy(papszTokens);
6416 :
6417 10 : if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6418 : {
6419 0 : CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6420 : pszSQLCommand);
6421 0 : return OGRERR_FAILURE;
6422 : }
6423 :
6424 : /* -------------------------------------------------------------------- */
6425 : /* Attempt to drop the index. */
6426 : /* -------------------------------------------------------------------- */
6427 10 : const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6428 :
6429 10 : return eErr;
6430 : }
6431 :
6432 : /************************************************************************/
6433 : /* ProcessSQLDropTable() */
6434 : /* */
6435 : /* The correct syntax for dropping a table (layer) in the OGR SQL */
6436 : /* dialect is: */
6437 : /* */
6438 : /* DROP TABLE <layername> */
6439 : /************************************************************************/
6440 :
6441 500 : OGRErr GDALDataset::ProcessSQLDropTable(const char *pszSQLCommand)
6442 :
6443 : {
6444 500 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6445 :
6446 : /* -------------------------------------------------------------------- */
6447 : /* Do some general syntax checking. */
6448 : /* -------------------------------------------------------------------- */
6449 1000 : if (CSLCount(papszTokens) != 3 || !EQUAL(papszTokens[0], "DROP") ||
6450 500 : !EQUAL(papszTokens[1], "TABLE"))
6451 : {
6452 0 : CSLDestroy(papszTokens);
6453 0 : CPLError(CE_Failure, CPLE_AppDefined,
6454 : "Syntax error in DROP TABLE command.\n"
6455 : "Was '%s'\n"
6456 : "Should be of form 'DROP TABLE <table>'",
6457 : pszSQLCommand);
6458 0 : return OGRERR_FAILURE;
6459 : }
6460 :
6461 : /* -------------------------------------------------------------------- */
6462 : /* Find the named layer. */
6463 : /* -------------------------------------------------------------------- */
6464 500 : OGRLayer *poLayer = nullptr;
6465 :
6466 500 : int i = 0; // Used after for.
6467 40199 : for (; i < GetLayerCount(); ++i)
6468 : {
6469 40199 : poLayer = GetLayer(i);
6470 :
6471 40199 : if (poLayer != nullptr && EQUAL(poLayer->GetName(), papszTokens[2]))
6472 500 : break;
6473 39699 : poLayer = nullptr;
6474 : }
6475 :
6476 500 : if (poLayer == nullptr)
6477 : {
6478 0 : CPLError(CE_Failure, CPLE_AppDefined,
6479 0 : "DROP TABLE failed, no such layer as `%s'.", papszTokens[2]);
6480 0 : CSLDestroy(papszTokens);
6481 0 : return OGRERR_FAILURE;
6482 : }
6483 :
6484 500 : CSLDestroy(papszTokens);
6485 :
6486 : /* -------------------------------------------------------------------- */
6487 : /* Delete it. */
6488 : /* -------------------------------------------------------------------- */
6489 :
6490 500 : return DeleteLayer(i);
6491 : }
6492 :
6493 : //! @endcond
6494 :
6495 : /************************************************************************/
6496 : /* GDALDatasetParseSQLType() */
6497 : /************************************************************************/
6498 :
6499 : /* All arguments will be altered */
6500 6 : static OGRFieldType GDALDatasetParseSQLType(char *pszType, int &nWidth,
6501 : int &nPrecision)
6502 : {
6503 6 : char *pszParenthesis = strchr(pszType, '(');
6504 6 : if (pszParenthesis)
6505 : {
6506 4 : nWidth = atoi(pszParenthesis + 1);
6507 4 : *pszParenthesis = '\0';
6508 4 : char *pszComma = strchr(pszParenthesis + 1, ',');
6509 4 : if (pszComma)
6510 2 : nPrecision = atoi(pszComma + 1);
6511 : }
6512 :
6513 6 : OGRFieldType eType = OFTString;
6514 6 : if (EQUAL(pszType, "INTEGER"))
6515 0 : eType = OFTInteger;
6516 6 : else if (EQUAL(pszType, "INTEGER[]"))
6517 0 : eType = OFTIntegerList;
6518 6 : else if (EQUAL(pszType, "FLOAT") || EQUAL(pszType, "NUMERIC") ||
6519 4 : EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
6520 4 : EQUAL(pszType, "REAL") /* unofficial alias */)
6521 2 : eType = OFTReal;
6522 4 : else if (EQUAL(pszType, "FLOAT[]") || EQUAL(pszType, "NUMERIC[]") ||
6523 4 : EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||
6524 4 : EQUAL(pszType, "REAL[]") /* unofficial alias */)
6525 0 : eType = OFTRealList;
6526 4 : else if (EQUAL(pszType, "CHARACTER") ||
6527 0 : EQUAL(pszType, "TEXT") /* unofficial alias */ ||
6528 0 : EQUAL(pszType, "STRING") /* unofficial alias */ ||
6529 0 : EQUAL(pszType, "VARCHAR") /* unofficial alias */)
6530 4 : eType = OFTString;
6531 0 : else if (EQUAL(pszType, "TEXT[]") ||
6532 0 : EQUAL(pszType, "STRING[]") /* unofficial alias */ ||
6533 0 : EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)
6534 0 : eType = OFTStringList;
6535 0 : else if (EQUAL(pszType, "DATE"))
6536 0 : eType = OFTDate;
6537 0 : else if (EQUAL(pszType, "TIME"))
6538 0 : eType = OFTTime;
6539 0 : else if (EQUAL(pszType, "TIMESTAMP") ||
6540 0 : EQUAL(pszType, "DATETIME") /* unofficial alias */)
6541 0 : eType = OFTDateTime;
6542 : else
6543 0 : CPLError(CE_Warning, CPLE_NotSupported,
6544 : "Unsupported column type '%s'. Defaulting to VARCHAR",
6545 : pszType);
6546 :
6547 6 : return eType;
6548 : }
6549 :
6550 : /************************************************************************/
6551 : /* ProcessSQLAlterTableAddColumn() */
6552 : /* */
6553 : /* The correct syntax for adding a column in the OGR SQL */
6554 : /* dialect is: */
6555 : /* */
6556 : /* ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype> */
6557 : /************************************************************************/
6558 :
6559 : //! @cond Doxygen_Suppress
6560 2 : OGRErr GDALDataset::ProcessSQLAlterTableAddColumn(const char *pszSQLCommand)
6561 :
6562 : {
6563 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6564 :
6565 : /* -------------------------------------------------------------------- */
6566 : /* Do some general syntax checking. */
6567 : /* -------------------------------------------------------------------- */
6568 2 : const char *pszLayerName = nullptr;
6569 2 : const char *pszColumnName = nullptr;
6570 2 : int iTypeIndex = 0;
6571 2 : const int nTokens = CSLCount(papszTokens);
6572 :
6573 2 : if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6574 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD") &&
6575 2 : EQUAL(papszTokens[4], "COLUMN"))
6576 : {
6577 1 : pszLayerName = papszTokens[2];
6578 1 : pszColumnName = papszTokens[5];
6579 1 : iTypeIndex = 6;
6580 : }
6581 1 : else if (nTokens >= 6 && EQUAL(papszTokens[0], "ALTER") &&
6582 1 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD"))
6583 : {
6584 1 : pszLayerName = papszTokens[2];
6585 1 : pszColumnName = papszTokens[4];
6586 1 : iTypeIndex = 5;
6587 : }
6588 : else
6589 : {
6590 0 : CSLDestroy(papszTokens);
6591 0 : CPLError(CE_Failure, CPLE_AppDefined,
6592 : "Syntax error in ALTER TABLE ADD COLUMN command.\n"
6593 : "Was '%s'\n"
6594 : "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] "
6595 : "<columnname> <columntype>'",
6596 : pszSQLCommand);
6597 0 : return OGRERR_FAILURE;
6598 : }
6599 :
6600 : /* -------------------------------------------------------------------- */
6601 : /* Merge type components into a single string if there were split */
6602 : /* with spaces */
6603 : /* -------------------------------------------------------------------- */
6604 4 : CPLString osType;
6605 6 : for (int i = iTypeIndex; i < nTokens; ++i)
6606 : {
6607 4 : osType += papszTokens[i];
6608 4 : CPLFree(papszTokens[i]);
6609 : }
6610 2 : char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6611 2 : papszTokens[iTypeIndex + 1] = nullptr;
6612 :
6613 : /* -------------------------------------------------------------------- */
6614 : /* Find the named layer. */
6615 : /* -------------------------------------------------------------------- */
6616 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6617 2 : if (poLayer == nullptr)
6618 : {
6619 0 : CPLError(CE_Failure, CPLE_AppDefined,
6620 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6621 : pszLayerName);
6622 0 : CSLDestroy(papszTokens);
6623 0 : return OGRERR_FAILURE;
6624 : }
6625 :
6626 : /* -------------------------------------------------------------------- */
6627 : /* Add column. */
6628 : /* -------------------------------------------------------------------- */
6629 :
6630 2 : int nWidth = 0;
6631 2 : int nPrecision = 0;
6632 2 : OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6633 4 : OGRFieldDefn oFieldDefn(pszColumnName, eType);
6634 2 : oFieldDefn.SetWidth(nWidth);
6635 2 : oFieldDefn.SetPrecision(nPrecision);
6636 :
6637 2 : CSLDestroy(papszTokens);
6638 :
6639 2 : return poLayer->CreateField(&oFieldDefn);
6640 : }
6641 :
6642 : /************************************************************************/
6643 : /* ProcessSQLAlterTableDropColumn() */
6644 : /* */
6645 : /* The correct syntax for dropping a column in the OGR SQL */
6646 : /* dialect is: */
6647 : /* */
6648 : /* ALTER TABLE <layername> DROP [COLUMN] <columnname> */
6649 : /************************************************************************/
6650 :
6651 2 : OGRErr GDALDataset::ProcessSQLAlterTableDropColumn(const char *pszSQLCommand)
6652 :
6653 : {
6654 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6655 :
6656 : /* -------------------------------------------------------------------- */
6657 : /* Do some general syntax checking. */
6658 : /* -------------------------------------------------------------------- */
6659 2 : const char *pszLayerName = nullptr;
6660 2 : const char *pszColumnName = nullptr;
6661 3 : if (CSLCount(papszTokens) == 6 && EQUAL(papszTokens[0], "ALTER") &&
6662 4 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP") &&
6663 1 : EQUAL(papszTokens[4], "COLUMN"))
6664 : {
6665 1 : pszLayerName = papszTokens[2];
6666 1 : pszColumnName = papszTokens[5];
6667 : }
6668 2 : else if (CSLCount(papszTokens) == 5 && EQUAL(papszTokens[0], "ALTER") &&
6669 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP"))
6670 : {
6671 1 : pszLayerName = papszTokens[2];
6672 1 : pszColumnName = papszTokens[4];
6673 : }
6674 : else
6675 : {
6676 0 : CSLDestroy(papszTokens);
6677 0 : CPLError(CE_Failure, CPLE_AppDefined,
6678 : "Syntax error in ALTER TABLE DROP COLUMN command.\n"
6679 : "Was '%s'\n"
6680 : "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] "
6681 : "<columnname>'",
6682 : pszSQLCommand);
6683 0 : return OGRERR_FAILURE;
6684 : }
6685 :
6686 : /* -------------------------------------------------------------------- */
6687 : /* Find the named layer. */
6688 : /* -------------------------------------------------------------------- */
6689 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6690 2 : if (poLayer == nullptr)
6691 : {
6692 0 : CPLError(CE_Failure, CPLE_AppDefined,
6693 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6694 : pszLayerName);
6695 0 : CSLDestroy(papszTokens);
6696 0 : return OGRERR_FAILURE;
6697 : }
6698 :
6699 : /* -------------------------------------------------------------------- */
6700 : /* Find the field. */
6701 : /* -------------------------------------------------------------------- */
6702 :
6703 2 : int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6704 2 : if (nFieldIndex < 0)
6705 : {
6706 0 : CPLError(CE_Failure, CPLE_AppDefined,
6707 : "%s failed, no such field as `%s'.", pszSQLCommand,
6708 : pszColumnName);
6709 0 : CSLDestroy(papszTokens);
6710 0 : return OGRERR_FAILURE;
6711 : }
6712 :
6713 : /* -------------------------------------------------------------------- */
6714 : /* Remove it. */
6715 : /* -------------------------------------------------------------------- */
6716 :
6717 2 : CSLDestroy(papszTokens);
6718 :
6719 2 : return poLayer->DeleteField(nFieldIndex);
6720 : }
6721 :
6722 : /************************************************************************/
6723 : /* ProcessSQLAlterTableRenameColumn() */
6724 : /* */
6725 : /* The correct syntax for renaming a column in the OGR SQL */
6726 : /* dialect is: */
6727 : /* */
6728 : /* ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
6729 : /************************************************************************/
6730 :
6731 2 : OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn(const char *pszSQLCommand)
6732 :
6733 : {
6734 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6735 :
6736 : /* -------------------------------------------------------------------- */
6737 : /* Do some general syntax checking. */
6738 : /* -------------------------------------------------------------------- */
6739 2 : const char *pszLayerName = nullptr;
6740 2 : const char *pszOldColName = nullptr;
6741 2 : const char *pszNewColName = nullptr;
6742 3 : if (CSLCount(papszTokens) == 8 && EQUAL(papszTokens[0], "ALTER") &&
6743 1 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "RENAME") &&
6744 3 : EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TO"))
6745 : {
6746 1 : pszLayerName = papszTokens[2];
6747 1 : pszOldColName = papszTokens[5];
6748 1 : pszNewColName = papszTokens[7];
6749 : }
6750 2 : else if (CSLCount(papszTokens) == 7 && EQUAL(papszTokens[0], "ALTER") &&
6751 1 : EQUAL(papszTokens[1], "TABLE") &&
6752 2 : EQUAL(papszTokens[3], "RENAME") && EQUAL(papszTokens[5], "TO"))
6753 : {
6754 1 : pszLayerName = papszTokens[2];
6755 1 : pszOldColName = papszTokens[4];
6756 1 : pszNewColName = papszTokens[6];
6757 : }
6758 : else
6759 : {
6760 0 : CSLDestroy(papszTokens);
6761 0 : CPLError(CE_Failure, CPLE_AppDefined,
6762 : "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
6763 : "Was '%s'\n"
6764 : "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] "
6765 : "<columnname> TO <newname>'",
6766 : pszSQLCommand);
6767 0 : return OGRERR_FAILURE;
6768 : }
6769 :
6770 : /* -------------------------------------------------------------------- */
6771 : /* Find the named layer. */
6772 : /* -------------------------------------------------------------------- */
6773 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6774 2 : if (poLayer == nullptr)
6775 : {
6776 0 : CPLError(CE_Failure, CPLE_AppDefined,
6777 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6778 : pszLayerName);
6779 0 : CSLDestroy(papszTokens);
6780 0 : return OGRERR_FAILURE;
6781 : }
6782 :
6783 : /* -------------------------------------------------------------------- */
6784 : /* Find the field. */
6785 : /* -------------------------------------------------------------------- */
6786 :
6787 : const int nFieldIndex =
6788 2 : poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
6789 2 : if (nFieldIndex < 0)
6790 : {
6791 0 : CPLError(CE_Failure, CPLE_AppDefined,
6792 : "%s failed, no such field as `%s'.", pszSQLCommand,
6793 : pszOldColName);
6794 0 : CSLDestroy(papszTokens);
6795 0 : return OGRERR_FAILURE;
6796 : }
6797 :
6798 : /* -------------------------------------------------------------------- */
6799 : /* Rename column. */
6800 : /* -------------------------------------------------------------------- */
6801 : OGRFieldDefn *poOldFieldDefn =
6802 2 : poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6803 4 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6804 2 : oNewFieldDefn.SetName(pszNewColName);
6805 :
6806 2 : CSLDestroy(papszTokens);
6807 :
6808 2 : return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn,
6809 2 : ALTER_NAME_FLAG);
6810 : }
6811 :
6812 : /************************************************************************/
6813 : /* ProcessSQLAlterTableAlterColumn() */
6814 : /* */
6815 : /* The correct syntax for altering the type of a column in the */
6816 : /* OGR SQL dialect is: */
6817 : /* */
6818 : /* ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */
6819 : /************************************************************************/
6820 :
6821 4 : OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn(const char *pszSQLCommand)
6822 :
6823 : {
6824 4 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6825 :
6826 : /* -------------------------------------------------------------------- */
6827 : /* Do some general syntax checking. */
6828 : /* -------------------------------------------------------------------- */
6829 4 : const char *pszLayerName = nullptr;
6830 4 : const char *pszColumnName = nullptr;
6831 4 : int iTypeIndex = 0;
6832 4 : const int nTokens = CSLCount(papszTokens);
6833 :
6834 4 : if (nTokens >= 8 && EQUAL(papszTokens[0], "ALTER") &&
6835 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6836 2 : EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TYPE"))
6837 : {
6838 2 : pszLayerName = papszTokens[2];
6839 2 : pszColumnName = papszTokens[5];
6840 2 : iTypeIndex = 7;
6841 : }
6842 2 : else if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6843 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6844 2 : EQUAL(papszTokens[5], "TYPE"))
6845 : {
6846 2 : pszLayerName = papszTokens[2];
6847 2 : pszColumnName = papszTokens[4];
6848 2 : iTypeIndex = 6;
6849 : }
6850 : else
6851 : {
6852 0 : CSLDestroy(papszTokens);
6853 0 : CPLError(CE_Failure, CPLE_AppDefined,
6854 : "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
6855 : "Was '%s'\n"
6856 : "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] "
6857 : "<columnname> TYPE <columntype>'",
6858 : pszSQLCommand);
6859 0 : return OGRERR_FAILURE;
6860 : }
6861 :
6862 : /* -------------------------------------------------------------------- */
6863 : /* Merge type components into a single string if there were split */
6864 : /* with spaces */
6865 : /* -------------------------------------------------------------------- */
6866 8 : CPLString osType;
6867 8 : for (int i = iTypeIndex; i < nTokens; ++i)
6868 : {
6869 4 : osType += papszTokens[i];
6870 4 : CPLFree(papszTokens[i]);
6871 : }
6872 4 : char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6873 4 : papszTokens[iTypeIndex + 1] = nullptr;
6874 :
6875 : /* -------------------------------------------------------------------- */
6876 : /* Find the named layer. */
6877 : /* -------------------------------------------------------------------- */
6878 4 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6879 4 : if (poLayer == nullptr)
6880 : {
6881 0 : CPLError(CE_Failure, CPLE_AppDefined,
6882 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6883 : pszLayerName);
6884 0 : CSLDestroy(papszTokens);
6885 0 : return OGRERR_FAILURE;
6886 : }
6887 :
6888 : /* -------------------------------------------------------------------- */
6889 : /* Find the field. */
6890 : /* -------------------------------------------------------------------- */
6891 :
6892 : const int nFieldIndex =
6893 4 : poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6894 4 : if (nFieldIndex < 0)
6895 : {
6896 0 : CPLError(CE_Failure, CPLE_AppDefined,
6897 : "%s failed, no such field as `%s'.", pszSQLCommand,
6898 : pszColumnName);
6899 0 : CSLDestroy(papszTokens);
6900 0 : return OGRERR_FAILURE;
6901 : }
6902 :
6903 : /* -------------------------------------------------------------------- */
6904 : /* Alter column. */
6905 : /* -------------------------------------------------------------------- */
6906 :
6907 : OGRFieldDefn *poOldFieldDefn =
6908 4 : poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6909 8 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6910 :
6911 4 : int nWidth = 0;
6912 4 : int nPrecision = 0;
6913 4 : OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6914 4 : oNewFieldDefn.SetType(eType);
6915 4 : oNewFieldDefn.SetWidth(nWidth);
6916 4 : oNewFieldDefn.SetPrecision(nPrecision);
6917 :
6918 4 : int l_nFlags = 0;
6919 4 : if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
6920 2 : l_nFlags |= ALTER_TYPE_FLAG;
6921 4 : if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
6922 0 : poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
6923 4 : l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;
6924 :
6925 4 : CSLDestroy(papszTokens);
6926 :
6927 4 : if (l_nFlags == 0)
6928 0 : return OGRERR_NONE;
6929 :
6930 4 : return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn, l_nFlags);
6931 : }
6932 :
6933 : //! @endcond
6934 :
6935 : /************************************************************************/
6936 : /* ExecuteSQL() */
6937 : /************************************************************************/
6938 :
6939 : /**
6940 : \brief Execute an SQL statement against the data store.
6941 :
6942 : The result of an SQL query is either NULL for statements that are in error,
6943 : or that have no results set, or an OGRLayer pointer representing a results
6944 : set from the query. Note that this OGRLayer is in addition to the layers
6945 : in the data store and must be destroyed with
6946 : ReleaseResultSet() before the dataset is closed
6947 : (destroyed).
6948 :
6949 : This method is the same as the C function GDALDatasetExecuteSQL() and the
6950 : deprecated OGR_DS_ExecuteSQL().
6951 :
6952 : For more information on the SQL dialect supported internally by OGR
6953 : review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
6954 : document. Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
6955 : to the underlying RDBMS.
6956 :
6957 : Starting with OGR 1.10, the <a
6958 : href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
6959 : also be used.
6960 :
6961 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6962 :
6963 : @param pszStatement the SQL statement to execute.
6964 : @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.
6965 : @param pszDialect allows control of the statement dialect. If set to NULL, the
6966 : OGR SQL engine will be used, except for RDBMS drivers that will use their
6967 : dedicated SQL engine, unless OGRSQL is explicitly passed as the
6968 : dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
6969 :
6970 : @return an OGRLayer containing the results of the query. Deallocate with
6971 : ReleaseResultSet().
6972 :
6973 : */
6974 :
6975 3557 : OGRLayer *GDALDataset::ExecuteSQL(const char *pszStatement,
6976 : OGRGeometry *poSpatialFilter,
6977 : const char *pszDialect)
6978 :
6979 : {
6980 3557 : return ExecuteSQL(pszStatement, poSpatialFilter, pszDialect, nullptr);
6981 : }
6982 :
6983 : //! @cond Doxygen_Suppress
6984 : OGRLayer *
6985 3565 : GDALDataset::ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
6986 : const char *pszDialect,
6987 : swq_select_parse_options *poSelectParseOptions)
6988 :
6989 : {
6990 3565 : if (pszDialect != nullptr && EQUAL(pszDialect, "SQLite"))
6991 : {
6992 : #ifdef SQLITE_ENABLED
6993 650 : return OGRSQLiteExecuteSQL(this, pszStatement, poSpatialFilter,
6994 650 : pszDialect);
6995 : #else
6996 : CPLError(CE_Failure, CPLE_NotSupported,
6997 : "The SQLite driver needs to be compiled to support the "
6998 : "SQLite SQL dialect");
6999 : return nullptr;
7000 : #endif
7001 : }
7002 :
7003 2915 : if (pszDialect != nullptr && !EQUAL(pszDialect, "") &&
7004 14 : !EQUAL(pszDialect, "OGRSQL"))
7005 : {
7006 6 : std::string osDialectList = "'OGRSQL'";
7007 : #ifdef SQLITE_ENABLED
7008 3 : osDialectList += ", 'SQLITE'";
7009 : #endif
7010 : const char *pszDialects =
7011 3 : GetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS);
7012 3 : if (pszDialects)
7013 : {
7014 : const CPLStringList aosTokens(
7015 0 : CSLTokenizeString2(pszDialects, " ", 0));
7016 0 : for (int i = 0; i < aosTokens.size(); ++i)
7017 : {
7018 0 : if (!EQUAL(aosTokens[i], "OGRSQL") &&
7019 0 : !EQUAL(aosTokens[i], "SQLITE"))
7020 : {
7021 0 : osDialectList += ", '";
7022 0 : osDialectList += aosTokens[i];
7023 0 : osDialectList += "'";
7024 : }
7025 : }
7026 : }
7027 3 : CPLError(CE_Warning, CPLE_NotSupported,
7028 : "Dialect '%s' is unsupported. Only supported dialects are %s. "
7029 : "Defaulting to OGRSQL",
7030 : pszDialect, osDialectList.c_str());
7031 : }
7032 :
7033 : /* -------------------------------------------------------------------- */
7034 : /* Handle CREATE INDEX statements specially. */
7035 : /* -------------------------------------------------------------------- */
7036 2915 : if (STARTS_WITH_CI(pszStatement, "CREATE INDEX"))
7037 : {
7038 28 : ProcessSQLCreateIndex(pszStatement);
7039 28 : return nullptr;
7040 : }
7041 :
7042 : /* -------------------------------------------------------------------- */
7043 : /* Handle DROP INDEX statements specially. */
7044 : /* -------------------------------------------------------------------- */
7045 2887 : if (STARTS_WITH_CI(pszStatement, "DROP INDEX"))
7046 : {
7047 10 : ProcessSQLDropIndex(pszStatement);
7048 10 : return nullptr;
7049 : }
7050 :
7051 : /* -------------------------------------------------------------------- */
7052 : /* Handle DROP TABLE statements specially. */
7053 : /* -------------------------------------------------------------------- */
7054 2877 : if (STARTS_WITH_CI(pszStatement, "DROP TABLE"))
7055 : {
7056 500 : ProcessSQLDropTable(pszStatement);
7057 500 : return nullptr;
7058 : }
7059 :
7060 : /* -------------------------------------------------------------------- */
7061 : /* Handle ALTER TABLE statements specially. */
7062 : /* -------------------------------------------------------------------- */
7063 2377 : if (STARTS_WITH_CI(pszStatement, "ALTER TABLE"))
7064 : {
7065 11 : char **papszTokens = CSLTokenizeString(pszStatement);
7066 11 : const int nTokens = CSLCount(papszTokens);
7067 11 : if (nTokens >= 4 && EQUAL(papszTokens[3], "ADD"))
7068 : {
7069 2 : ProcessSQLAlterTableAddColumn(pszStatement);
7070 2 : CSLDestroy(papszTokens);
7071 2 : return nullptr;
7072 : }
7073 9 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "DROP"))
7074 : {
7075 2 : ProcessSQLAlterTableDropColumn(pszStatement);
7076 2 : CSLDestroy(papszTokens);
7077 2 : return nullptr;
7078 : }
7079 7 : else if (nTokens == 6 && EQUAL(papszTokens[3], "RENAME") &&
7080 1 : EQUAL(papszTokens[4], "TO"))
7081 : {
7082 1 : const char *pszSrcTableName = papszTokens[2];
7083 1 : const char *pszDstTableName = papszTokens[5];
7084 1 : auto poSrcLayer = GetLayerByName(pszSrcTableName);
7085 1 : if (poSrcLayer)
7086 : {
7087 1 : CPL_IGNORE_RET_VAL(poSrcLayer->Rename(pszDstTableName));
7088 : }
7089 : else
7090 : {
7091 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid layer name");
7092 : }
7093 1 : CSLDestroy(papszTokens);
7094 1 : return nullptr;
7095 : }
7096 6 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "RENAME"))
7097 : {
7098 2 : ProcessSQLAlterTableRenameColumn(pszStatement);
7099 2 : CSLDestroy(papszTokens);
7100 2 : return nullptr;
7101 : }
7102 4 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "ALTER"))
7103 : {
7104 4 : ProcessSQLAlterTableAlterColumn(pszStatement);
7105 4 : CSLDestroy(papszTokens);
7106 4 : return nullptr;
7107 : }
7108 : else
7109 : {
7110 0 : CPLError(CE_Failure, CPLE_AppDefined,
7111 : "Unsupported ALTER TABLE command : %s", pszStatement);
7112 0 : CSLDestroy(papszTokens);
7113 0 : return nullptr;
7114 : }
7115 : }
7116 :
7117 : /* -------------------------------------------------------------------- */
7118 : /* Preparse the SQL statement. */
7119 : /* -------------------------------------------------------------------- */
7120 2366 : swq_select *psSelectInfo = new swq_select();
7121 2366 : swq_custom_func_registrar *poCustomFuncRegistrar = nullptr;
7122 2366 : if (poSelectParseOptions != nullptr)
7123 8 : poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;
7124 2366 : if (psSelectInfo->preparse(pszStatement,
7125 2366 : poCustomFuncRegistrar != nullptr) != CE_None)
7126 : {
7127 141 : delete psSelectInfo;
7128 141 : return nullptr;
7129 : }
7130 :
7131 : /* -------------------------------------------------------------------- */
7132 : /* If there is no UNION ALL, build result layer. */
7133 : /* -------------------------------------------------------------------- */
7134 2225 : if (psSelectInfo->poOtherSelect == nullptr)
7135 : {
7136 2219 : return BuildLayerFromSelectInfo(psSelectInfo, poSpatialFilter,
7137 2219 : pszDialect, poSelectParseOptions);
7138 : }
7139 :
7140 : /* -------------------------------------------------------------------- */
7141 : /* Build result union layer. */
7142 : /* -------------------------------------------------------------------- */
7143 6 : int nSrcLayers = 0;
7144 6 : OGRLayer **papoSrcLayers = nullptr;
7145 :
7146 6 : do
7147 : {
7148 12 : swq_select *psNextSelectInfo = psSelectInfo->poOtherSelect;
7149 12 : psSelectInfo->poOtherSelect = nullptr;
7150 :
7151 12 : OGRLayer *poLayer = BuildLayerFromSelectInfo(
7152 : psSelectInfo, poSpatialFilter, pszDialect, poSelectParseOptions);
7153 12 : if (poLayer == nullptr)
7154 : {
7155 : // Each source layer owns an independent select info.
7156 0 : for (int i = 0; i < nSrcLayers; ++i)
7157 0 : delete papoSrcLayers[i];
7158 0 : CPLFree(papoSrcLayers);
7159 :
7160 : // So we just have to destroy the remaining select info.
7161 0 : delete psNextSelectInfo;
7162 :
7163 0 : return nullptr;
7164 : }
7165 : else
7166 : {
7167 24 : papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(
7168 12 : papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));
7169 12 : papoSrcLayers[nSrcLayers] = poLayer;
7170 12 : ++nSrcLayers;
7171 :
7172 12 : psSelectInfo = psNextSelectInfo;
7173 : }
7174 12 : } while (psSelectInfo != nullptr);
7175 :
7176 6 : return new OGRUnionLayer("SELECT", nSrcLayers, papoSrcLayers, TRUE);
7177 : }
7178 :
7179 : //! @endcond
7180 :
7181 : /************************************************************************/
7182 : /* AbortSQL() */
7183 : /************************************************************************/
7184 :
7185 : /**
7186 : \brief Abort any SQL statement running in the data store.
7187 :
7188 : This function can be safely called from any thread (pending that the dataset
7189 : object is still alive). Driver implementations will make sure that it can be
7190 : called in a thread-safe way.
7191 :
7192 : This might not be implemented by all drivers. At time of writing, only SQLite,
7193 : GPKG and PG drivers implement it
7194 :
7195 : This method is the same as the C method GDALDatasetAbortSQL()
7196 :
7197 : @since GDAL 3.2.0
7198 :
7199 :
7200 : */
7201 :
7202 0 : OGRErr GDALDataset::AbortSQL()
7203 : {
7204 0 : CPLError(CE_Failure, CPLE_NotSupported,
7205 : "AbortSQL is not supported for this driver.");
7206 0 : return OGRERR_UNSUPPORTED_OPERATION;
7207 : }
7208 :
7209 : /************************************************************************/
7210 : /* BuildLayerFromSelectInfo() */
7211 : /************************************************************************/
7212 :
7213 : struct GDALSQLParseInfo
7214 : {
7215 : swq_field_list sFieldList;
7216 : int nExtraDSCount;
7217 : GDALDataset **papoExtraDS;
7218 : char *pszWHERE;
7219 : };
7220 :
7221 2231 : OGRLayer *GDALDataset::BuildLayerFromSelectInfo(
7222 : swq_select *psSelectInfo, OGRGeometry *poSpatialFilter,
7223 : const char *pszDialect, swq_select_parse_options *poSelectParseOptions)
7224 : {
7225 4462 : std::unique_ptr<swq_select> psSelectInfoUnique(psSelectInfo);
7226 :
7227 2231 : std::unique_ptr<OGRGenSQLResultsLayer> poResults;
7228 : GDALSQLParseInfo *psParseInfo =
7229 2231 : BuildParseInfo(psSelectInfoUnique.get(), poSelectParseOptions);
7230 :
7231 2231 : if (psParseInfo)
7232 : {
7233 2196 : const auto nErrorCounter = CPLGetErrorCounter();
7234 4392 : poResults = std::make_unique<OGRGenSQLResultsLayer>(
7235 2196 : this, std::move(psSelectInfoUnique), poSpatialFilter,
7236 4392 : psParseInfo->pszWHERE, pszDialect);
7237 2273 : if (CPLGetErrorCounter() > nErrorCounter &&
7238 77 : CPLGetLastErrorType() != CE_None)
7239 77 : poResults.reset();
7240 : }
7241 :
7242 2231 : DestroyParseInfo(psParseInfo);
7243 :
7244 4462 : return poResults.release();
7245 : }
7246 :
7247 : /************************************************************************/
7248 : /* DestroyParseInfo() */
7249 : /************************************************************************/
7250 :
7251 : //! @cond Doxygen_Suppress
7252 2300 : void GDALDataset::DestroyParseInfo(GDALSQLParseInfo *psParseInfo)
7253 : {
7254 2300 : if (psParseInfo == nullptr)
7255 35 : return;
7256 :
7257 2265 : CPLFree(psParseInfo->sFieldList.names);
7258 2265 : CPLFree(psParseInfo->sFieldList.types);
7259 2265 : CPLFree(psParseInfo->sFieldList.table_ids);
7260 2265 : CPLFree(psParseInfo->sFieldList.ids);
7261 :
7262 : // Release the datasets we have opened with OGROpenShared()
7263 : // It is safe to do that as the 'new OGRGenSQLResultsLayer' itself
7264 : // has taken a reference on them, which it will release in its
7265 : // destructor.
7266 2272 : for (int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; ++iEDS)
7267 7 : GDALClose(psParseInfo->papoExtraDS[iEDS]);
7268 :
7269 2265 : CPLFree(psParseInfo->papoExtraDS);
7270 2265 : CPLFree(psParseInfo->pszWHERE);
7271 2265 : CPLFree(psParseInfo);
7272 : }
7273 :
7274 : /************************************************************************/
7275 : /* BuildParseInfo() */
7276 : /************************************************************************/
7277 :
7278 : GDALSQLParseInfo *
7279 2265 : GDALDataset::BuildParseInfo(swq_select *psSelectInfo,
7280 : swq_select_parse_options *poSelectParseOptions)
7281 : {
7282 2265 : int nFirstLayerFirstSpecialFieldIndex = 0;
7283 :
7284 : GDALSQLParseInfo *psParseInfo =
7285 2265 : static_cast<GDALSQLParseInfo *>(CPLCalloc(1, sizeof(GDALSQLParseInfo)));
7286 :
7287 : /* -------------------------------------------------------------------- */
7288 : /* Validate that all the source tables are recognized, count */
7289 : /* fields. */
7290 : /* -------------------------------------------------------------------- */
7291 2265 : int nFieldCount = 0;
7292 :
7293 4598 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7294 : {
7295 2336 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7296 2336 : GDALDataset *poTableDS = this;
7297 :
7298 2336 : if (psTableDef->data_source != nullptr)
7299 : {
7300 7 : poTableDS = GDALDataset::FromHandle(
7301 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7302 7 : if (poTableDS == nullptr)
7303 : {
7304 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
7305 0 : CPLError(CE_Failure, CPLE_AppDefined,
7306 : "Unable to open secondary datasource "
7307 : "`%s' required by JOIN.",
7308 : psTableDef->data_source);
7309 :
7310 0 : DestroyParseInfo(psParseInfo);
7311 0 : return nullptr;
7312 : }
7313 :
7314 : // Keep in an array to release at the end of this function.
7315 14 : psParseInfo->papoExtraDS = static_cast<GDALDataset **>(CPLRealloc(
7316 7 : psParseInfo->papoExtraDS,
7317 7 : sizeof(GDALDataset *) * (psParseInfo->nExtraDSCount + 1)));
7318 7 : psParseInfo->papoExtraDS[psParseInfo->nExtraDSCount++] = poTableDS;
7319 : }
7320 :
7321 : OGRLayer *poSrcLayer =
7322 2336 : poTableDS->GetLayerByName(psTableDef->table_name);
7323 :
7324 2336 : if (poSrcLayer == nullptr)
7325 : {
7326 3 : CPLError(CE_Failure, CPLE_AppDefined,
7327 : "SELECT from table %s failed, no such table/featureclass.",
7328 : psTableDef->table_name);
7329 :
7330 3 : DestroyParseInfo(psParseInfo);
7331 3 : return nullptr;
7332 : }
7333 :
7334 2333 : nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
7335 2333 : if (iTable == 0 ||
7336 34 : (poSelectParseOptions &&
7337 34 : poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7338 2296 : nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7339 :
7340 2333 : const char *pszFID = poSrcLayer->GetFIDColumn();
7341 2943 : if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7342 610 : poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7343 560 : nFieldCount++;
7344 : }
7345 :
7346 : /* -------------------------------------------------------------------- */
7347 : /* Build the field list for all indicated tables. */
7348 : /* -------------------------------------------------------------------- */
7349 :
7350 2262 : psParseInfo->sFieldList.table_count = psSelectInfo->table_count;
7351 2262 : psParseInfo->sFieldList.table_defs = psSelectInfo->table_defs;
7352 :
7353 2262 : psParseInfo->sFieldList.count = 0;
7354 2262 : psParseInfo->sFieldList.names = static_cast<char **>(
7355 2262 : CPLMalloc(sizeof(char *) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7356 4524 : psParseInfo->sFieldList.types = static_cast<swq_field_type *>(CPLMalloc(
7357 2262 : sizeof(swq_field_type) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7358 2262 : psParseInfo->sFieldList.table_ids = static_cast<int *>(
7359 2262 : CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7360 2262 : psParseInfo->sFieldList.ids = static_cast<int *>(
7361 2262 : CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7362 :
7363 2262 : bool bIsFID64 = false;
7364 4595 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7365 : {
7366 2333 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7367 2333 : GDALDataset *poTableDS = this;
7368 :
7369 2333 : if (psTableDef->data_source != nullptr)
7370 : {
7371 7 : poTableDS = GDALDataset::FromHandle(
7372 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7373 7 : CPLAssert(poTableDS != nullptr);
7374 7 : poTableDS->Dereference();
7375 : }
7376 :
7377 : OGRLayer *poSrcLayer =
7378 2333 : poTableDS->GetLayerByName(psTableDef->table_name);
7379 :
7380 2333 : for (int iField = 0;
7381 18501 : iField < poSrcLayer->GetLayerDefn()->GetFieldCount(); iField++)
7382 : {
7383 : OGRFieldDefn *poFDefn =
7384 16168 : poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
7385 16168 : const int iOutField = psParseInfo->sFieldList.count++;
7386 32336 : psParseInfo->sFieldList.names[iOutField] =
7387 16168 : const_cast<char *>(poFDefn->GetNameRef());
7388 16168 : if (poFDefn->GetType() == OFTInteger)
7389 : {
7390 4082 : if (poFDefn->GetSubType() == OFSTBoolean)
7391 160 : psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7392 : else
7393 3922 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7394 : }
7395 12086 : else if (poFDefn->GetType() == OFTInteger64)
7396 : {
7397 751 : if (poFDefn->GetSubType() == OFSTBoolean)
7398 0 : psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7399 : else
7400 751 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7401 : }
7402 11335 : else if (poFDefn->GetType() == OFTReal)
7403 2708 : psParseInfo->sFieldList.types[iOutField] = SWQ_FLOAT;
7404 8627 : else if (poFDefn->GetType() == OFTString)
7405 5573 : psParseInfo->sFieldList.types[iOutField] = SWQ_STRING;
7406 3054 : else if (poFDefn->GetType() == OFTTime)
7407 83 : psParseInfo->sFieldList.types[iOutField] = SWQ_TIME;
7408 2971 : else if (poFDefn->GetType() == OFTDate)
7409 143 : psParseInfo->sFieldList.types[iOutField] = SWQ_DATE;
7410 2828 : else if (poFDefn->GetType() == OFTDateTime)
7411 939 : psParseInfo->sFieldList.types[iOutField] = SWQ_TIMESTAMP;
7412 : else
7413 1889 : psParseInfo->sFieldList.types[iOutField] = SWQ_OTHER;
7414 :
7415 16168 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7416 16168 : psParseInfo->sFieldList.ids[iOutField] = iField;
7417 : }
7418 :
7419 2333 : if (iTable == 0)
7420 : {
7421 2262 : nFirstLayerFirstSpecialFieldIndex = psParseInfo->sFieldList.count;
7422 : }
7423 :
7424 2333 : if (iTable == 0 ||
7425 34 : (poSelectParseOptions &&
7426 34 : poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7427 : {
7428 :
7429 2296 : for (int iField = 0;
7430 4242 : iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7431 : iField++)
7432 : {
7433 : OGRGeomFieldDefn *poFDefn =
7434 1946 : poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
7435 1946 : const int iOutField = psParseInfo->sFieldList.count++;
7436 3892 : psParseInfo->sFieldList.names[iOutField] =
7437 1946 : const_cast<char *>(poFDefn->GetNameRef());
7438 1946 : if (*psParseInfo->sFieldList.names[iOutField] == '\0')
7439 1131 : psParseInfo->sFieldList.names[iOutField] =
7440 : const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
7441 1946 : psParseInfo->sFieldList.types[iOutField] = SWQ_GEOMETRY;
7442 :
7443 1946 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7444 1946 : psParseInfo->sFieldList.ids[iOutField] =
7445 1946 : GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(
7446 : poSrcLayer->GetLayerDefn(), iField);
7447 : }
7448 : }
7449 :
7450 2334 : if (iTable == 0 && poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7451 1 : EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7452 : {
7453 1 : bIsFID64 = true;
7454 : }
7455 : }
7456 :
7457 : /* -------------------------------------------------------------------- */
7458 : /* Expand '*' in 'SELECT *' now before we add the pseudo fields */
7459 : /* -------------------------------------------------------------------- */
7460 2262 : const bool bAlwaysPrefixWithTableName =
7461 2304 : poSelectParseOptions &&
7462 42 : poSelectParseOptions->bAlwaysPrefixWithTableName;
7463 2262 : if (psSelectInfo->expand_wildcard(&psParseInfo->sFieldList,
7464 2262 : bAlwaysPrefixWithTableName) != CE_None)
7465 : {
7466 2 : DestroyParseInfo(psParseInfo);
7467 2 : return nullptr;
7468 : }
7469 :
7470 13560 : for (int iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
7471 : {
7472 11300 : psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] =
7473 11300 : const_cast<char *>(SpecialFieldNames[iField]);
7474 11300 : psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] =
7475 11300 : (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64
7476 : : SpecialFieldTypes[iField];
7477 11300 : psParseInfo->sFieldList.table_ids[psParseInfo->sFieldList.count] = 0;
7478 11300 : psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] =
7479 11300 : nFirstLayerFirstSpecialFieldIndex + iField;
7480 11300 : psParseInfo->sFieldList.count++;
7481 : }
7482 :
7483 : /* In the case a layer has an explicit FID column name, then add it */
7484 : /* so it can be selected */
7485 4591 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7486 : {
7487 2331 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7488 2331 : GDALDataset *poTableDS = this;
7489 :
7490 2331 : if (psTableDef->data_source != nullptr)
7491 : {
7492 7 : poTableDS = GDALDataset::FromHandle(
7493 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7494 7 : CPLAssert(poTableDS != nullptr);
7495 7 : poTableDS->Dereference();
7496 : }
7497 :
7498 : OGRLayer *poSrcLayer =
7499 2331 : poTableDS->GetLayerByName(psTableDef->table_name);
7500 :
7501 2331 : const char *pszFID = poSrcLayer->GetFIDColumn();
7502 2941 : if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7503 610 : poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7504 : {
7505 560 : const int iOutField = psParseInfo->sFieldList.count++;
7506 560 : psParseInfo->sFieldList.names[iOutField] =
7507 : const_cast<char *>(pszFID);
7508 560 : if (poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7509 0 : EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7510 : {
7511 0 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7512 : }
7513 : else
7514 : {
7515 560 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7516 : }
7517 560 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7518 1120 : psParseInfo->sFieldList.ids[iOutField] =
7519 560 : poSrcLayer->GetLayerDefn()->GetFieldCount() + SPF_FID;
7520 : }
7521 : }
7522 :
7523 : /* -------------------------------------------------------------------- */
7524 : /* Finish the parse operation. */
7525 : /* -------------------------------------------------------------------- */
7526 2260 : if (psSelectInfo->parse(&psParseInfo->sFieldList, poSelectParseOptions) !=
7527 : CE_None)
7528 : {
7529 30 : DestroyParseInfo(psParseInfo);
7530 30 : return nullptr;
7531 : }
7532 :
7533 : /* -------------------------------------------------------------------- */
7534 : /* Extract the WHERE expression to use separately. */
7535 : /* -------------------------------------------------------------------- */
7536 2230 : if (psSelectInfo->where_expr != nullptr)
7537 : {
7538 956 : psParseInfo->pszWHERE =
7539 956 : psSelectInfo->where_expr->Unparse(&psParseInfo->sFieldList, '"');
7540 : // CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
7541 : }
7542 :
7543 2230 : return psParseInfo;
7544 : }
7545 :
7546 : //! @endcond
7547 :
7548 : /************************************************************************/
7549 : /* ReleaseResultSet() */
7550 : /************************************************************************/
7551 :
7552 : /**
7553 : \brief Release results of ExecuteSQL().
7554 :
7555 : This method should only be used to deallocate OGRLayers resulting from
7556 : an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
7557 : results set before destroying the GDALDataset may cause errors.
7558 :
7559 : This method is the same as the C function GDALDatasetReleaseResultSet() and the
7560 : deprecated OGR_DS_ReleaseResultSet().
7561 :
7562 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7563 :
7564 : @param poResultsSet the result of a previous ExecuteSQL() call.
7565 : */
7566 :
7567 2149 : void GDALDataset::ReleaseResultSet(OGRLayer *poResultsSet)
7568 :
7569 : {
7570 2149 : delete poResultsSet;
7571 2149 : }
7572 :
7573 : /************************************************************************/
7574 : /* GetStyleTable() */
7575 : /************************************************************************/
7576 :
7577 : /**
7578 : \brief Returns dataset style table.
7579 :
7580 : This method is the same as the C function GDALDatasetGetStyleTable() and the
7581 : deprecated OGR_DS_GetStyleTable().
7582 :
7583 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7584 :
7585 : @return pointer to a style table which should not be modified or freed by the
7586 : caller.
7587 : */
7588 :
7589 828 : OGRStyleTable *GDALDataset::GetStyleTable()
7590 : {
7591 828 : return m_poStyleTable;
7592 : }
7593 :
7594 : /************************************************************************/
7595 : /* SetStyleTableDirectly() */
7596 : /************************************************************************/
7597 :
7598 : /**
7599 : \brief Set dataset style table.
7600 :
7601 : This method operate exactly as SetStyleTable() except that it
7602 : assumes ownership of the passed table.
7603 :
7604 : This method is the same as the C function GDALDatasetSetStyleTableDirectly()
7605 : and the deprecated OGR_DS_SetStyleTableDirectly().
7606 :
7607 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7608 :
7609 : @param poStyleTable pointer to style table to set
7610 :
7611 : */
7612 0 : void GDALDataset::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
7613 : {
7614 0 : if (m_poStyleTable)
7615 0 : delete m_poStyleTable;
7616 0 : m_poStyleTable = poStyleTable;
7617 0 : }
7618 :
7619 : /************************************************************************/
7620 : /* SetStyleTable() */
7621 : /************************************************************************/
7622 :
7623 : /**
7624 : \brief Set dataset style table.
7625 :
7626 : This method operate exactly as SetStyleTableDirectly() except
7627 : that it does not assume ownership of the passed table.
7628 :
7629 : This method is the same as the C function GDALDatasetSetStyleTable() and the
7630 : deprecated OGR_DS_SetStyleTable().
7631 :
7632 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7633 :
7634 : @param poStyleTable pointer to style table to set
7635 :
7636 : */
7637 :
7638 824 : void GDALDataset::SetStyleTable(OGRStyleTable *poStyleTable)
7639 : {
7640 824 : if (m_poStyleTable)
7641 0 : delete m_poStyleTable;
7642 824 : if (poStyleTable)
7643 1 : m_poStyleTable = poStyleTable->Clone();
7644 824 : }
7645 :
7646 : /************************************************************************/
7647 : /* IsGenericSQLDialect() */
7648 : /************************************************************************/
7649 :
7650 : //! @cond Doxygen_Suppress
7651 1745 : int GDALDataset::IsGenericSQLDialect(const char *pszDialect)
7652 : {
7653 3182 : return pszDialect != nullptr &&
7654 3182 : (EQUAL(pszDialect, "OGRSQL") || EQUAL(pszDialect, "SQLITE"));
7655 : }
7656 :
7657 : //! @endcond
7658 :
7659 : /************************************************************************/
7660 : /* GetLayerCount() */
7661 : /************************************************************************/
7662 :
7663 : /**
7664 : \brief Get the number of layers in this dataset.
7665 :
7666 : This method is the same as the C function GDALDatasetGetLayerCount(),
7667 : and the deprecated OGR_DS_GetLayerCount().
7668 :
7669 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7670 :
7671 : @return layer count.
7672 : */
7673 :
7674 80897 : int GDALDataset::GetLayerCount()
7675 : {
7676 80897 : return 0;
7677 : }
7678 :
7679 : /************************************************************************/
7680 : /* GetLayer() */
7681 : /************************************************************************/
7682 :
7683 : /**
7684 : \fn GDALDataset::GetLayer(int)
7685 : \brief Fetch a layer by index.
7686 :
7687 : The returned layer remains owned by the
7688 : GDALDataset and should not be deleted by the application.
7689 :
7690 : See GetLayers() for a C++ iterator version of this method.
7691 :
7692 : This method is the same as the C function GDALDatasetGetLayer() and the
7693 : deprecated OGR_DS_GetLayer().
7694 :
7695 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7696 :
7697 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7698 :
7699 : @return the layer, or NULL if iLayer is out of range or an error occurs.
7700 :
7701 : @see GetLayers()
7702 : */
7703 :
7704 0 : OGRLayer *GDALDataset::GetLayer(CPL_UNUSED int iLayer)
7705 : {
7706 0 : return nullptr;
7707 : }
7708 :
7709 : /************************************************************************/
7710 : /* IsLayerPrivate() */
7711 : /************************************************************************/
7712 :
7713 : /**
7714 : \fn GDALDataset::IsLayerPrivate(int)
7715 : \brief Returns true if the layer at the specified index is deemed a private or
7716 : system table, or an internal detail only.
7717 :
7718 : This method is the same as the C function GDALDatasetIsLayerPrivate().
7719 :
7720 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7721 :
7722 : @return true if the layer is a private or system table.
7723 :
7724 : @since GDAL 3.4
7725 : */
7726 :
7727 843 : bool GDALDataset::IsLayerPrivate(CPL_UNUSED int iLayer) const
7728 : {
7729 843 : return false;
7730 : }
7731 :
7732 : /************************************************************************/
7733 : /* ResetReading() */
7734 : /************************************************************************/
7735 :
7736 : /**
7737 : \brief Reset feature reading to start on the first feature.
7738 :
7739 : This affects GetNextFeature().
7740 :
7741 : Depending on drivers, this may also have the side effect of calling
7742 : OGRLayer::ResetReading() on the layers of this dataset.
7743 :
7744 : This method is the same as the C function GDALDatasetResetReading().
7745 :
7746 : @since GDAL 2.2
7747 : */
7748 7 : void GDALDataset::ResetReading()
7749 : {
7750 7 : if (!m_poPrivate)
7751 0 : return;
7752 7 : m_poPrivate->nCurrentLayerIdx = 0;
7753 7 : m_poPrivate->nLayerCount = -1;
7754 7 : m_poPrivate->poCurrentLayer = nullptr;
7755 7 : m_poPrivate->nFeatureReadInLayer = 0;
7756 7 : m_poPrivate->nFeatureReadInDataset = 0;
7757 7 : m_poPrivate->nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
7758 7 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
7759 : }
7760 :
7761 : /************************************************************************/
7762 : /* GDALDatasetResetReading() */
7763 : /************************************************************************/
7764 :
7765 : /**
7766 : \brief Reset feature reading to start on the first feature.
7767 :
7768 : This affects GDALDatasetGetNextFeature().
7769 :
7770 : Depending on drivers, this may also have the side effect of calling
7771 : OGR_L_ResetReading() on the layers of this dataset.
7772 :
7773 : This method is the same as the C++ method GDALDataset::ResetReading()
7774 :
7775 : @param hDS dataset handle
7776 : @since GDAL 2.2
7777 : */
7778 14 : void CPL_DLL GDALDatasetResetReading(GDALDatasetH hDS)
7779 : {
7780 14 : VALIDATE_POINTER0(hDS, "GDALDatasetResetReading");
7781 :
7782 14 : return GDALDataset::FromHandle(hDS)->ResetReading();
7783 : }
7784 :
7785 : /************************************************************************/
7786 : /* GetNextFeature() */
7787 : /************************************************************************/
7788 :
7789 : /**
7790 : \brief Fetch the next available feature from this dataset.
7791 :
7792 : This method is intended for the few drivers where OGRLayer::GetNextFeature()
7793 : is not efficient, but in general OGRLayer::GetNextFeature() is a more
7794 : natural API.
7795 :
7796 : See GetFeatures() for a C++ iterator version of this method.
7797 :
7798 : The returned feature becomes the responsibility of the caller to
7799 : delete with OGRFeature::DestroyFeature().
7800 :
7801 : Depending on the driver, this method may return features from layers in a
7802 : non sequential way. This is what may happen when the
7803 : ODsCRandomLayerRead capability is declared (for example for the
7804 : OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7805 : advised to use GDALDataset::GetNextFeature() instead of
7806 : OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7807 : implementation.
7808 :
7809 : The default implementation, used by most drivers, will
7810 : however iterate over each layer, and then over each feature within this
7811 : layer.
7812 :
7813 : This method takes into account spatial and attribute filters set on layers that
7814 : will be iterated upon.
7815 :
7816 : The ResetReading() method can be used to start at the beginning again.
7817 :
7818 : Depending on drivers, this may also have the side effect of calling
7819 : OGRLayer::GetNextFeature() on the layers of this dataset.
7820 :
7821 : This method is the same as the C function GDALDatasetGetNextFeature().
7822 :
7823 : @param ppoBelongingLayer a pointer to a OGRLayer* variable to receive the
7824 : layer to which the object belongs to, or NULL.
7825 : It is possible that the output of *ppoBelongingLayer
7826 : to be NULL despite the feature not being NULL.
7827 : @param pdfProgressPct a pointer to a double variable to receive the
7828 : percentage progress (in [0,1] range), or NULL.
7829 : On return, the pointed value might be negative if
7830 : determining the progress is not possible.
7831 : @param pfnProgress a progress callback to report progress (for
7832 : GetNextFeature() calls that might have a long
7833 : duration) and offer cancellation possibility, or NULL.
7834 : @param pProgressData user data provided to pfnProgress, or NULL
7835 : @return a feature, or NULL if no more features are available.
7836 : @since GDAL 2.2
7837 : @see GetFeatures()
7838 : */
7839 :
7840 60 : OGRFeature *GDALDataset::GetNextFeature(OGRLayer **ppoBelongingLayer,
7841 : double *pdfProgressPct,
7842 : GDALProgressFunc pfnProgress,
7843 : void *pProgressData)
7844 : {
7845 60 : if (!m_poPrivate || m_poPrivate->nCurrentLayerIdx < 0)
7846 : {
7847 2 : if (ppoBelongingLayer != nullptr)
7848 2 : *ppoBelongingLayer = nullptr;
7849 2 : if (pdfProgressPct != nullptr)
7850 1 : *pdfProgressPct = 1.0;
7851 2 : if (pfnProgress != nullptr)
7852 0 : pfnProgress(1.0, "", pProgressData);
7853 2 : return nullptr;
7854 : }
7855 :
7856 58 : if (m_poPrivate->poCurrentLayer == nullptr &&
7857 8 : (pdfProgressPct != nullptr || pfnProgress != nullptr))
7858 : {
7859 1 : if (m_poPrivate->nLayerCount < 0)
7860 : {
7861 1 : m_poPrivate->nLayerCount = GetLayerCount();
7862 : }
7863 :
7864 1 : if (m_poPrivate->nTotalFeatures == TOTAL_FEATURES_NOT_INIT)
7865 : {
7866 1 : m_poPrivate->nTotalFeatures = 0;
7867 5 : for (int i = 0; i < m_poPrivate->nLayerCount; i++)
7868 : {
7869 4 : OGRLayer *poLayer = GetLayer(i);
7870 8 : if (poLayer == nullptr ||
7871 4 : !poLayer->TestCapability(OLCFastFeatureCount))
7872 : {
7873 0 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7874 0 : break;
7875 : }
7876 4 : GIntBig nCount = poLayer->GetFeatureCount(FALSE);
7877 4 : if (nCount < 0)
7878 : {
7879 0 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7880 0 : break;
7881 : }
7882 4 : m_poPrivate->nTotalFeatures += nCount;
7883 : }
7884 : }
7885 : }
7886 :
7887 : while (true)
7888 : {
7889 71 : if (m_poPrivate->poCurrentLayer == nullptr)
7890 : {
7891 44 : m_poPrivate->poCurrentLayer =
7892 22 : GetLayer(m_poPrivate->nCurrentLayerIdx);
7893 22 : if (m_poPrivate->poCurrentLayer == nullptr)
7894 : {
7895 7 : m_poPrivate->nCurrentLayerIdx = -1;
7896 7 : if (ppoBelongingLayer != nullptr)
7897 7 : *ppoBelongingLayer = nullptr;
7898 7 : if (pdfProgressPct != nullptr)
7899 1 : *pdfProgressPct = 1.0;
7900 7 : return nullptr;
7901 : }
7902 15 : m_poPrivate->poCurrentLayer->ResetReading();
7903 15 : m_poPrivate->nFeatureReadInLayer = 0;
7904 15 : if (m_poPrivate->nTotalFeatures < 0 && pdfProgressPct != nullptr)
7905 : {
7906 0 : if (m_poPrivate->poCurrentLayer->TestCapability(
7907 0 : OLCFastFeatureCount))
7908 0 : m_poPrivate->nTotalFeaturesInLayer =
7909 0 : m_poPrivate->poCurrentLayer->GetFeatureCount(FALSE);
7910 : else
7911 0 : m_poPrivate->nTotalFeaturesInLayer = 0;
7912 : }
7913 : }
7914 64 : OGRFeature *poFeature = m_poPrivate->poCurrentLayer->GetNextFeature();
7915 64 : if (poFeature == nullptr)
7916 : {
7917 13 : m_poPrivate->nCurrentLayerIdx++;
7918 13 : m_poPrivate->poCurrentLayer = nullptr;
7919 13 : continue;
7920 : }
7921 :
7922 51 : m_poPrivate->nFeatureReadInLayer++;
7923 51 : m_poPrivate->nFeatureReadInDataset++;
7924 51 : if (pdfProgressPct != nullptr || pfnProgress != nullptr)
7925 : {
7926 4 : double dfPct = 0.0;
7927 4 : if (m_poPrivate->nTotalFeatures > 0)
7928 : {
7929 4 : dfPct = 1.0 * m_poPrivate->nFeatureReadInDataset /
7930 4 : m_poPrivate->nTotalFeatures;
7931 : }
7932 : else
7933 : {
7934 0 : dfPct = 1.0 * m_poPrivate->nCurrentLayerIdx /
7935 0 : m_poPrivate->nLayerCount;
7936 0 : if (m_poPrivate->nTotalFeaturesInLayer > 0)
7937 : {
7938 0 : dfPct += 1.0 * m_poPrivate->nFeatureReadInLayer /
7939 0 : m_poPrivate->nTotalFeaturesInLayer /
7940 0 : m_poPrivate->nLayerCount;
7941 : }
7942 : }
7943 4 : if (pdfProgressPct)
7944 4 : *pdfProgressPct = dfPct;
7945 4 : if (pfnProgress)
7946 0 : pfnProgress(dfPct, "", nullptr);
7947 : }
7948 :
7949 51 : if (ppoBelongingLayer != nullptr)
7950 51 : *ppoBelongingLayer = m_poPrivate->poCurrentLayer;
7951 51 : return poFeature;
7952 13 : }
7953 : }
7954 :
7955 : /************************************************************************/
7956 : /* GDALDatasetGetNextFeature() */
7957 : /************************************************************************/
7958 : /**
7959 : \brief Fetch the next available feature from this dataset.
7960 :
7961 : This method is intended for the few drivers where OGR_L_GetNextFeature()
7962 : is not efficient, but in general OGR_L_GetNextFeature() is a more
7963 : natural API.
7964 :
7965 : The returned feature becomes the responsibility of the caller to
7966 : delete with OGRFeature::DestroyFeature().
7967 :
7968 : Depending on the driver, this method may return features from layers in a
7969 : non sequential way. This is what may happen when the
7970 : ODsCRandomLayerRead capability is declared (for example for the
7971 : OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7972 : advised to use GDALDataset::GetNextFeature() instead of
7973 : OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7974 : implementation.
7975 :
7976 : The default implementation, used by most drivers, will
7977 : however iterate over each layer, and then over each feature within this
7978 : layer.
7979 :
7980 : This method takes into account spatial and attribute filters set on layers that
7981 : will be iterated upon.
7982 :
7983 : The ResetReading() method can be used to start at the beginning again.
7984 :
7985 : Depending on drivers, this may also have the side effect of calling
7986 : OGRLayer::GetNextFeature() on the layers of this dataset.
7987 :
7988 : This method is the same as the C++ method GDALDataset::GetNextFeature()
7989 :
7990 : @param hDS dataset handle.
7991 : @param phBelongingLayer a pointer to a OGRLayer* variable to receive the
7992 : layer to which the object belongs to, or NULL.
7993 : It is possible that the output of *ppoBelongingLayer
7994 : to be NULL despite the feature not being NULL.
7995 : @param pdfProgressPct a pointer to a double variable to receive the
7996 : percentage progress (in [0,1] range), or NULL.
7997 : On return, the pointed value might be negative if
7998 : determining the progress is not possible.
7999 : @param pfnProgress a progress callback to report progress (for
8000 : GetNextFeature() calls that might have a long
8001 : duration) and offer cancellation possibility, or NULL
8002 : @param pProgressData user data provided to pfnProgress, or NULL
8003 : @return a feature, or NULL if no more features are available.
8004 : @since GDAL 2.2
8005 : */
8006 1917 : OGRFeatureH CPL_DLL GDALDatasetGetNextFeature(GDALDatasetH hDS,
8007 : OGRLayerH *phBelongingLayer,
8008 : double *pdfProgressPct,
8009 : GDALProgressFunc pfnProgress,
8010 : void *pProgressData)
8011 : {
8012 1917 : VALIDATE_POINTER1(hDS, "GDALDatasetGetNextFeature", nullptr);
8013 :
8014 3834 : return OGRFeature::ToHandle(GDALDataset::FromHandle(hDS)->GetNextFeature(
8015 : reinterpret_cast<OGRLayer **>(phBelongingLayer), pdfProgressPct,
8016 3834 : pfnProgress, pProgressData));
8017 : }
8018 :
8019 : /************************************************************************/
8020 : /* TestCapability() */
8021 : /************************************************************************/
8022 :
8023 : /**
8024 : \fn GDALDataset::TestCapability( const char * pszCap )
8025 : \brief Test if capability is available.
8026 :
8027 : One of the following dataset capability names can be passed into this
8028 : method, and a TRUE or FALSE value will be returned indicating whether or not
8029 : the capability is available for this object.
8030 :
8031 : <ul>
8032 : <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
8033 : <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
8034 : layers.<p>
8035 : <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
8036 : datasource support CreateGeomField() just after layer creation.<p>
8037 : <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
8038 : geometries.<p>
8039 : <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
8040 : transactions.<p>
8041 : <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
8042 : transactions through emulation.<p>
8043 : <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
8044 : GetNextFeature() implementation, potentially returning features from
8045 : layers in a non sequential way.<p>
8046 : <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
8047 : CreateFeature() on layers in a non sequential way.<p>
8048 : <li> <b>GDsCAddRelationship</b>: True if AddRelationship() is supported</li>
8049 : <li> <b>GDsCDeleteRelationship</b>: True if DeleteRelationship() is supported</li>
8050 : <li> <b>GDsCUpdateRelationship</b>: True if UpdateRelationship() is supported</li>
8051 : <li> <b>GDsCFastGetExtent</b>: True if GetExtent() is fast</li>
8052 : <li> <b>GDsCFastGetExtentWGS84LongLat</b>: True if GetExtentWGS84LongLat() is fast</li>
8053 : </ul>
8054 :
8055 : The \#define macro forms of the capability names should be used in preference
8056 : to the strings themselves to avoid misspelling.
8057 :
8058 : This method is the same as the C function GDALDatasetTestCapability() and the
8059 : deprecated OGR_DS_TestCapability().
8060 :
8061 : In GDAL 1.X, this method used to be in the OGRDataSource class.
8062 :
8063 : @param pszCap the capability to test.
8064 :
8065 : @return TRUE if capability available otherwise FALSE.
8066 : */
8067 :
8068 571 : int GDALDataset::TestCapability(const char *pszCap)
8069 : {
8070 571 : if (EQUAL(pszCap, GDsCFastGetExtent) ||
8071 569 : EQUAL(pszCap, GDsCFastGetExtentWGS84LongLat))
8072 : {
8073 4 : for (auto &&poLayer : GetLayers())
8074 : {
8075 2 : if (!poLayer->TestCapability(OLCFastGetExtent))
8076 2 : return FALSE;
8077 : }
8078 2 : return TRUE;
8079 : }
8080 567 : return FALSE;
8081 : }
8082 :
8083 : /************************************************************************/
8084 : /* GDALDatasetTestCapability() */
8085 : /************************************************************************/
8086 :
8087 : /**
8088 : \brief Test if capability is available.
8089 :
8090 : One of the following dataset capability names can be passed into this
8091 : function, and a TRUE or FALSE value will be returned indicating whether or not
8092 : the capability is available for this object.
8093 :
8094 : <ul>
8095 : <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
8096 : <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
8097 : layers.<p>
8098 : <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
8099 : datasource support CreateGeomField() just after layer creation.<p>
8100 : <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
8101 : geometries.<p>
8102 : <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
8103 : transactions.<p>
8104 : <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
8105 : transactions through emulation.<p>
8106 : <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
8107 : GetNextFeature() implementation, potentially returning features from
8108 : layers in a non sequential way.<p>
8109 : <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
8110 : CreateFeature() on layers in a non sequential way.<p>
8111 : <li> <b>GDsCAddRelationship</b>: True if AddRelationship() is supported</li>
8112 : <li> <b>GDsCDeleteRelationship</b>: True if DeleteRelationship() is supported</li>
8113 : <li> <b>GDsCUpdateRelationship</b>: True if UpdateRelationship() is supported</li>
8114 : <li> <b>GDsCFastGetExtent</b>: True if GetExtent() is fast</li>
8115 : <li> <b>GDsCFastGetExtentWGS84LongLat</b>: True if GetExtentWGS84LongLat() is fast</li>
8116 : </ul>
8117 :
8118 : The \#define macro forms of the capability names should be used in preference
8119 : to the strings themselves to avoid misspelling.
8120 :
8121 : This function is the same as the C++ method GDALDataset::TestCapability()
8122 :
8123 : @since GDAL 2.0
8124 :
8125 : @param hDS the dataset handle.
8126 : @param pszCap the capability to test.
8127 :
8128 : @return TRUE if capability available otherwise FALSE.
8129 : */
8130 122 : int GDALDatasetTestCapability(GDALDatasetH hDS, const char *pszCap)
8131 :
8132 : {
8133 122 : VALIDATE_POINTER1(hDS, "GDALDatasetTestCapability", 0);
8134 122 : VALIDATE_POINTER1(pszCap, "GDALDatasetTestCapability", 0);
8135 :
8136 122 : return GDALDataset::FromHandle(hDS)->TestCapability(pszCap);
8137 : }
8138 :
8139 : /************************************************************************/
8140 : /* StartTransaction() */
8141 : /************************************************************************/
8142 :
8143 : /**
8144 : \fn GDALDataset::StartTransaction(int)
8145 : \brief For datasources which support transactions, StartTransaction creates a
8146 : `transaction.
8147 :
8148 : If starting the transaction fails, will return
8149 : OGRERR_FAILURE. Datasources which do not support transactions will
8150 : always return OGRERR_UNSUPPORTED_OPERATION.
8151 :
8152 : Nested transactions are not supported.
8153 :
8154 : All changes done after the start of the transaction are definitely applied in
8155 : the datasource if CommitTransaction() is called. They may be canceled by
8156 : calling RollbackTransaction() instead.
8157 :
8158 : At the time of writing, transactions only apply on vector layers.
8159 :
8160 : Datasets that support transactions will advertise the ODsCTransactions
8161 : capability. Use of transactions at dataset level is generally preferred to
8162 : transactions at layer level, whose scope is rarely limited to the layer from
8163 : which it was started.
8164 :
8165 : In case StartTransaction() fails, neither CommitTransaction() or
8166 : RollbackTransaction() should be called.
8167 :
8168 : If an error occurs after a successful StartTransaction(), the whole transaction
8169 : may or may not be implicitly canceled, depending on drivers. (e.g. the PG
8170 : driver will cancel it, SQLite/GPKG not). In any case, in the event of an error,
8171 : an explicit call to RollbackTransaction() should be done to keep things
8172 : balanced.
8173 :
8174 : By default, when bForce is set to FALSE, only "efficient" transactions will be
8175 : attempted. Some drivers may offer an emulation of transactions, but sometimes
8176 : with significant overhead, in which case the user must explicitly allow for
8177 : such an emulation by setting bForce to TRUE. Drivers that offer emulated
8178 : transactions should advertise the ODsCEmulatedTransactions capability (and not
8179 : ODsCTransactions).
8180 :
8181 : This function is the same as the C function GDALDatasetStartTransaction().
8182 :
8183 : @param bForce can be set to TRUE if an emulation, possibly slow, of a
8184 : transaction
8185 : mechanism is acceptable.
8186 :
8187 : @return OGRERR_NONE on success.
8188 : @since GDAL 2.0
8189 : */
8190 :
8191 37 : OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
8192 : {
8193 37 : return OGRERR_UNSUPPORTED_OPERATION;
8194 : }
8195 :
8196 : /************************************************************************/
8197 : /* GDALDatasetStartTransaction() */
8198 : /************************************************************************/
8199 :
8200 : /**
8201 : \brief For datasources which support transactions, StartTransaction creates a
8202 : transaction.
8203 :
8204 : If starting the transaction fails, will return
8205 : OGRERR_FAILURE. Datasources which do not support transactions will
8206 : always return OGRERR_UNSUPPORTED_OPERATION.
8207 :
8208 : Nested transactions are not supported.
8209 :
8210 : All changes done after the start of the transaction are definitely applied in
8211 : the datasource if CommitTransaction() is called. They may be canceled by
8212 : calling RollbackTransaction() instead.
8213 :
8214 : At the time of writing, transactions only apply on vector layers.
8215 :
8216 : Datasets that support transactions will advertise the ODsCTransactions
8217 : capability.
8218 : Use of transactions at dataset level is generally preferred to transactions at
8219 : layer level, whose scope is rarely limited to the layer from which it was
8220 : started.
8221 :
8222 : In case StartTransaction() fails, neither CommitTransaction() or
8223 : RollbackTransaction() should be called.
8224 :
8225 : If an error occurs after a successful StartTransaction(), the whole
8226 : transaction may or may not be implicitly canceled, depending on drivers. (e.g.
8227 : the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
8228 : error, an explicit call to RollbackTransaction() should be done to keep things
8229 : balanced.
8230 :
8231 : By default, when bForce is set to FALSE, only "efficient" transactions will be
8232 : attempted. Some drivers may offer an emulation of transactions, but sometimes
8233 : with significant overhead, in which case the user must explicitly allow for
8234 : such an emulation by setting bForce to TRUE. Drivers that offer emulated
8235 : transactions should advertise the ODsCEmulatedTransactions capability (and not
8236 : ODsCTransactions).
8237 :
8238 : This function is the same as the C++ method GDALDataset::StartTransaction()
8239 :
8240 : @param hDS the dataset handle.
8241 : @param bForce can be set to TRUE if an emulation, possibly slow, of a
8242 : transaction
8243 : mechanism is acceptable.
8244 :
8245 : @return OGRERR_NONE on success.
8246 : @since GDAL 2.0
8247 : */
8248 105 : OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
8249 : {
8250 105 : VALIDATE_POINTER1(hDS, "GDALDatasetStartTransaction",
8251 : OGRERR_INVALID_HANDLE);
8252 :
8253 : #ifdef OGRAPISPY_ENABLED
8254 105 : if (bOGRAPISpyEnabled)
8255 2 : OGRAPISpy_Dataset_StartTransaction(hDS, bForce);
8256 : #endif
8257 :
8258 105 : return GDALDataset::FromHandle(hDS)->StartTransaction(bForce);
8259 : }
8260 :
8261 : /************************************************************************/
8262 : /* CommitTransaction() */
8263 : /************************************************************************/
8264 :
8265 : /**
8266 : \brief For datasources which support transactions, CommitTransaction commits a
8267 : transaction.
8268 :
8269 : If no transaction is active, or the commit fails, will return
8270 : OGRERR_FAILURE. Datasources which do not support transactions will
8271 : always return OGRERR_UNSUPPORTED_OPERATION.
8272 :
8273 : Depending on drivers, this may or may not abort layer sequential readings that
8274 : are active.
8275 :
8276 : This function is the same as the C function GDALDatasetCommitTransaction().
8277 :
8278 : @return OGRERR_NONE on success.
8279 : @since GDAL 2.0
8280 : */
8281 37 : OGRErr GDALDataset::CommitTransaction()
8282 : {
8283 37 : return OGRERR_UNSUPPORTED_OPERATION;
8284 : }
8285 :
8286 : /************************************************************************/
8287 : /* GDALDatasetCommitTransaction() */
8288 : /************************************************************************/
8289 :
8290 : /**
8291 : \brief For datasources which support transactions, CommitTransaction commits a
8292 : transaction.
8293 :
8294 : If no transaction is active, or the commit fails, will return
8295 : OGRERR_FAILURE. Datasources which do not support transactions will
8296 : always return OGRERR_UNSUPPORTED_OPERATION.
8297 :
8298 : Depending on drivers, this may or may not abort layer sequential readings that
8299 : are active.
8300 :
8301 : This function is the same as the C++ method GDALDataset::CommitTransaction()
8302 :
8303 : @return OGRERR_NONE on success.
8304 : @since GDAL 2.0
8305 : */
8306 76 : OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
8307 : {
8308 76 : VALIDATE_POINTER1(hDS, "GDALDatasetCommitTransaction",
8309 : OGRERR_INVALID_HANDLE);
8310 :
8311 : #ifdef OGRAPISPY_ENABLED
8312 76 : if (bOGRAPISpyEnabled)
8313 2 : OGRAPISpy_Dataset_CommitTransaction(hDS);
8314 : #endif
8315 :
8316 76 : return GDALDataset::FromHandle(hDS)->CommitTransaction();
8317 : }
8318 :
8319 : /************************************************************************/
8320 : /* RollbackTransaction() */
8321 : /************************************************************************/
8322 :
8323 : /**
8324 : \brief For datasources which support transactions, RollbackTransaction will
8325 : roll back a datasource to its state before the start of the current
8326 : transaction.
8327 : If no transaction is active, or the rollback fails, will return
8328 : OGRERR_FAILURE. Datasources which do not support transactions will
8329 : always return OGRERR_UNSUPPORTED_OPERATION.
8330 :
8331 : This function is the same as the C function GDALDatasetRollbackTransaction().
8332 :
8333 : @return OGRERR_NONE on success.
8334 : @since GDAL 2.0
8335 : */
8336 2 : OGRErr GDALDataset::RollbackTransaction()
8337 : {
8338 2 : return OGRERR_UNSUPPORTED_OPERATION;
8339 : }
8340 :
8341 : /************************************************************************/
8342 : /* GDALDatasetRollbackTransaction() */
8343 : /************************************************************************/
8344 :
8345 : /**
8346 : \brief For datasources which support transactions, RollbackTransaction will
8347 : roll back a datasource to its state before the start of the current
8348 : transaction.
8349 : If no transaction is active, or the rollback fails, will return
8350 : OGRERR_FAILURE. Datasources which do not support transactions will
8351 : always return OGRERR_UNSUPPORTED_OPERATION.
8352 :
8353 : This function is the same as the C++ method GDALDataset::RollbackTransaction().
8354 :
8355 : @return OGRERR_NONE on success.
8356 : @since GDAL 2.0
8357 : */
8358 44 : OGRErr GDALDatasetRollbackTransaction(GDALDatasetH hDS)
8359 : {
8360 44 : VALIDATE_POINTER1(hDS, "GDALDatasetRollbackTransaction",
8361 : OGRERR_INVALID_HANDLE);
8362 :
8363 : #ifdef OGRAPISPY_ENABLED
8364 44 : if (bOGRAPISpyEnabled)
8365 2 : OGRAPISpy_Dataset_RollbackTransaction(hDS);
8366 : #endif
8367 :
8368 44 : return GDALDataset::FromHandle(hDS)->RollbackTransaction();
8369 : }
8370 :
8371 : //! @cond Doxygen_Suppress
8372 :
8373 : /************************************************************************/
8374 : /* ShareLockWithParentDataset() */
8375 : /************************************************************************/
8376 :
8377 : /* To be used typically by the GTiff driver to link overview datasets */
8378 : /* with their main dataset, so that they share the same lock */
8379 : /* Cf https://github.com/OSGeo/gdal/issues/1488 */
8380 : /* The parent dataset should remain alive while the this dataset is alive */
8381 :
8382 2355 : void GDALDataset::ShareLockWithParentDataset(GDALDataset *poParentDataset)
8383 : {
8384 2355 : if (m_poPrivate != nullptr)
8385 : {
8386 2355 : m_poPrivate->poParentDataset = poParentDataset;
8387 : }
8388 2355 : }
8389 :
8390 : /************************************************************************/
8391 : /* SetQueryLoggerFunc() */
8392 : /************************************************************************/
8393 :
8394 0 : bool GDALDataset::SetQueryLoggerFunc(CPL_UNUSED GDALQueryLoggerFunc callback,
8395 : CPL_UNUSED void *context)
8396 : {
8397 0 : return false;
8398 : }
8399 :
8400 : /************************************************************************/
8401 : /* EnterReadWrite() */
8402 : /************************************************************************/
8403 :
8404 8113360 : int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
8405 : {
8406 16226600 : if (m_poPrivate == nullptr ||
8407 8113330 : IsThreadSafe(GDAL_OF_RASTER | (nOpenFlags & GDAL_OF_UPDATE)))
8408 11891 : return FALSE;
8409 :
8410 8101340 : if (m_poPrivate->poParentDataset)
8411 242561 : return m_poPrivate->poParentDataset->EnterReadWrite(eRWFlag);
8412 :
8413 7858780 : if (eAccess == GA_Update)
8414 : {
8415 2279150 : if (m_poPrivate->eStateReadWriteMutex ==
8416 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8417 : {
8418 : // In case dead-lock would occur, which is not impossible,
8419 : // this can be used to prevent it, but at the risk of other
8420 : // issues.
8421 10267 : if (CPLTestBool(
8422 : CPLGetConfigOption("GDAL_ENABLE_READ_WRITE_MUTEX", "YES")))
8423 : {
8424 10267 : m_poPrivate->eStateReadWriteMutex =
8425 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED;
8426 : }
8427 : else
8428 : {
8429 0 : m_poPrivate->eStateReadWriteMutex =
8430 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8431 : }
8432 : }
8433 2279150 : if (m_poPrivate->eStateReadWriteMutex ==
8434 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED)
8435 : {
8436 : // There should be no race related to creating this mutex since
8437 : // it should be first created through IWriteBlock() / IRasterIO()
8438 : // and then GDALRasterBlock might call it from another thread.
8439 : #ifdef DEBUG_VERBOSE
8440 : CPLDebug("GDAL",
8441 : "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
8442 : CPLGetPID(), GetDescription());
8443 : #endif
8444 1535350 : CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8445 :
8446 : const int nCountMutex =
8447 1535370 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]++;
8448 1535340 : if (nCountMutex == 0 && eRWFlag == GF_Read)
8449 : {
8450 520447 : CPLReleaseMutex(m_poPrivate->hMutex);
8451 1652060 : for (int i = 0; i < nBands; i++)
8452 : {
8453 1131610 : auto blockCache = papoBands[i]->poBandBlockCache;
8454 1131610 : if (blockCache)
8455 816878 : blockCache->WaitCompletionPendingTasks();
8456 : }
8457 520447 : CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8458 : }
8459 :
8460 1535340 : return TRUE;
8461 : }
8462 : }
8463 6323430 : return FALSE;
8464 : }
8465 :
8466 : /************************************************************************/
8467 : /* LeaveReadWrite() */
8468 : /************************************************************************/
8469 :
8470 1764320 : void GDALDataset::LeaveReadWrite()
8471 : {
8472 1764320 : if (m_poPrivate)
8473 : {
8474 1764320 : if (m_poPrivate->poParentDataset)
8475 : {
8476 228949 : m_poPrivate->poParentDataset->LeaveReadWrite();
8477 228949 : return;
8478 : }
8479 :
8480 1535370 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]--;
8481 1535320 : CPLReleaseMutex(m_poPrivate->hMutex);
8482 : #ifdef DEBUG_VERBOSE
8483 : CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s",
8484 : CPLGetPID(), GetDescription());
8485 : #endif
8486 : }
8487 : }
8488 :
8489 : /************************************************************************/
8490 : /* InitRWLock() */
8491 : /************************************************************************/
8492 :
8493 3963110 : void GDALDataset::InitRWLock()
8494 : {
8495 3963110 : if (m_poPrivate)
8496 : {
8497 3963110 : if (m_poPrivate->poParentDataset)
8498 : {
8499 8592 : m_poPrivate->poParentDataset->InitRWLock();
8500 8592 : return;
8501 : }
8502 :
8503 3954520 : if (m_poPrivate->eStateReadWriteMutex ==
8504 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8505 : {
8506 1 : if (EnterReadWrite(GF_Write))
8507 1 : LeaveReadWrite();
8508 : }
8509 : }
8510 : }
8511 :
8512 : /************************************************************************/
8513 : /* DisableReadWriteMutex() */
8514 : /************************************************************************/
8515 :
8516 : // The mutex logic is broken in multi-threaded situations, for example
8517 : // with 2 WarpedVRT datasets being read at the same time. In that
8518 : // particular case, the mutex is not needed, so allow the VRTWarpedDataset code
8519 : // to disable it.
8520 19406 : void GDALDataset::DisableReadWriteMutex()
8521 : {
8522 19406 : if (m_poPrivate)
8523 : {
8524 19404 : if (m_poPrivate->poParentDataset)
8525 : {
8526 0 : m_poPrivate->poParentDataset->DisableReadWriteMutex();
8527 0 : return;
8528 : }
8529 :
8530 19404 : m_poPrivate->eStateReadWriteMutex =
8531 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8532 : }
8533 : }
8534 :
8535 : /************************************************************************/
8536 : /* TemporarilyDropReadWriteLock() */
8537 : /************************************************************************/
8538 :
8539 3388690 : void GDALDataset::TemporarilyDropReadWriteLock()
8540 : {
8541 3388690 : if (m_poPrivate == nullptr)
8542 0 : return;
8543 :
8544 3388690 : if (m_poPrivate->poParentDataset)
8545 : {
8546 26294 : m_poPrivate->poParentDataset->TemporarilyDropReadWriteLock();
8547 26294 : return;
8548 : }
8549 :
8550 : #ifndef __COVERITY__
8551 3362400 : if (m_poPrivate->hMutex)
8552 : {
8553 : #ifdef DEBUG_VERBOSE
8554 : CPLDebug("GDAL",
8555 : "[Thread " CPL_FRMT_GIB "] "
8556 : "Temporarily drop RW mutex for %s",
8557 : CPLGetPID(), GetDescription());
8558 : #endif
8559 410671 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8560 : const int nCount =
8561 410671 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8562 : #ifdef DEBUG_EXTRA
8563 : m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()] = nCount;
8564 : #endif
8565 1246350 : for (int i = 0; i < nCount + 1; i++)
8566 : {
8567 : // The mutex is recursive
8568 835679 : CPLReleaseMutex(m_poPrivate->hMutex);
8569 : }
8570 : }
8571 : #endif
8572 : }
8573 :
8574 : /************************************************************************/
8575 : /* ReacquireReadWriteLock() */
8576 : /************************************************************************/
8577 :
8578 3388710 : void GDALDataset::ReacquireReadWriteLock()
8579 : {
8580 3388710 : if (m_poPrivate == nullptr)
8581 0 : return;
8582 :
8583 3388710 : if (m_poPrivate->poParentDataset)
8584 : {
8585 26294 : m_poPrivate->poParentDataset->ReacquireReadWriteLock();
8586 26294 : return;
8587 : }
8588 :
8589 : #ifndef __COVERITY__
8590 3362420 : if (m_poPrivate->hMutex)
8591 : {
8592 : #ifdef DEBUG_VERBOSE
8593 : CPLDebug("GDAL",
8594 : "[Thread " CPL_FRMT_GIB "] "
8595 : "Reacquire temporarily dropped RW mutex for %s",
8596 : CPLGetPID(), GetDescription());
8597 : #endif
8598 410673 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8599 : const int nCount =
8600 410673 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8601 : #ifdef DEBUG_EXTRA
8602 : CPLAssert(nCount ==
8603 : m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()]);
8604 : #endif
8605 410673 : if (nCount == 0)
8606 11350 : CPLReleaseMutex(m_poPrivate->hMutex);
8607 436358 : for (int i = 0; i < nCount - 1; i++)
8608 : {
8609 : // The mutex is recursive
8610 25685 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8611 : }
8612 : }
8613 : #endif
8614 : }
8615 :
8616 : /************************************************************************/
8617 : /* AcquireMutex() */
8618 : /************************************************************************/
8619 :
8620 196 : int GDALDataset::AcquireMutex()
8621 : {
8622 196 : if (m_poPrivate == nullptr)
8623 0 : return 0;
8624 196 : if (m_poPrivate->poParentDataset)
8625 : {
8626 0 : return m_poPrivate->poParentDataset->AcquireMutex();
8627 : }
8628 :
8629 196 : return CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8630 : }
8631 :
8632 : /************************************************************************/
8633 : /* ReleaseMutex() */
8634 : /************************************************************************/
8635 :
8636 196 : void GDALDataset::ReleaseMutex()
8637 : {
8638 196 : if (m_poPrivate)
8639 : {
8640 196 : if (m_poPrivate->poParentDataset)
8641 : {
8642 0 : m_poPrivate->poParentDataset->ReleaseMutex();
8643 0 : return;
8644 : }
8645 :
8646 196 : CPLReleaseMutex(m_poPrivate->hMutex);
8647 : }
8648 : }
8649 :
8650 : //! @endcond
8651 :
8652 : /************************************************************************/
8653 : /* GDALDataset::Features::Iterator::Private */
8654 : /************************************************************************/
8655 :
8656 : struct GDALDataset::Features::Iterator::Private
8657 : {
8658 : GDALDataset::FeatureLayerPair m_oPair{};
8659 : GDALDataset *m_poDS = nullptr;
8660 : bool m_bEOF = true;
8661 : };
8662 :
8663 4 : GDALDataset::Features::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8664 4 : : m_poPrivate(new GDALDataset::Features::Iterator::Private())
8665 : {
8666 4 : m_poPrivate->m_poDS = poDS;
8667 4 : if (bStart)
8668 : {
8669 2 : poDS->ResetReading();
8670 4 : m_poPrivate->m_oPair.feature.reset(poDS->GetNextFeature(
8671 2 : &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8672 2 : m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8673 : }
8674 4 : }
8675 :
8676 : GDALDataset::Features::Iterator::~Iterator() = default;
8677 :
8678 : const GDALDataset::FeatureLayerPair &
8679 20 : GDALDataset::Features::Iterator::operator*() const
8680 : {
8681 20 : return m_poPrivate->m_oPair;
8682 : }
8683 :
8684 20 : GDALDataset::Features::Iterator &GDALDataset::Features::Iterator::operator++()
8685 : {
8686 40 : m_poPrivate->m_oPair.feature.reset(m_poPrivate->m_poDS->GetNextFeature(
8687 20 : &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8688 20 : m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8689 20 : return *this;
8690 : }
8691 :
8692 22 : bool GDALDataset::Features::Iterator::operator!=(const Iterator &it) const
8693 : {
8694 22 : return m_poPrivate->m_bEOF != it.m_poPrivate->m_bEOF;
8695 : }
8696 :
8697 : /************************************************************************/
8698 : /* GetFeatures() */
8699 : /************************************************************************/
8700 :
8701 : /** Function that return an iterable object over features in the dataset
8702 : * layer.
8703 : *
8704 : * This is a C++ iterator friendly version of GetNextFeature().
8705 : *
8706 : * Using this iterator for standard range-based loops is safe, but
8707 : * due to implementation limitations, you shouldn't try to access
8708 : * (dereference) more than one iterator step at a time, since the
8709 : * FeatureLayerPair reference which is returned is reused.
8710 : *
8711 : * Typical use is:
8712 : * \code{.cpp}
8713 : * for( auto&& oFeatureLayerPair: poDS->GetFeatures() )
8714 : * {
8715 : * std::cout << "Feature of layer " <<
8716 : * oFeatureLayerPair.layer->GetName() << std::endl;
8717 : * oFeatureLayerPair.feature->DumpReadable();
8718 : * }
8719 : * \endcode
8720 : *
8721 : * @see GetNextFeature()
8722 : *
8723 : * @since GDAL 2.3
8724 : */
8725 2 : GDALDataset::Features GDALDataset::GetFeatures()
8726 : {
8727 2 : return Features(this);
8728 : }
8729 :
8730 : /************************************************************************/
8731 : /* begin() */
8732 : /************************************************************************/
8733 :
8734 : /**
8735 : \brief Return beginning of feature iterator.
8736 :
8737 : @since GDAL 2.3
8738 : */
8739 :
8740 2 : const GDALDataset::Features::Iterator GDALDataset::Features::begin() const
8741 : {
8742 2 : return {m_poSelf, true};
8743 : }
8744 :
8745 : /************************************************************************/
8746 : /* end() */
8747 : /************************************************************************/
8748 :
8749 : /**
8750 : \brief Return end of feature iterator.
8751 :
8752 : @since GDAL 2.3
8753 : */
8754 :
8755 2 : const GDALDataset::Features::Iterator GDALDataset::Features::end() const
8756 : {
8757 2 : return {m_poSelf, false};
8758 : }
8759 :
8760 : /************************************************************************/
8761 : /* GDALDataset::Layers::Iterator::Private */
8762 : /************************************************************************/
8763 :
8764 : struct GDALDataset::Layers::Iterator::Private
8765 : {
8766 : OGRLayer *m_poLayer = nullptr;
8767 : int m_iCurLayer = 0;
8768 : int m_nLayerCount = 0;
8769 : GDALDataset *m_poDS = nullptr;
8770 : };
8771 :
8772 2 : GDALDataset::Layers::Iterator::Iterator() : m_poPrivate(new Private())
8773 : {
8774 2 : }
8775 :
8776 : // False positive of cppcheck 1.72
8777 : // cppcheck-suppress uninitMemberVar
8778 9 : GDALDataset::Layers::Iterator::Iterator(const Iterator &oOther)
8779 9 : : m_poPrivate(new Private(*(oOther.m_poPrivate)))
8780 : {
8781 9 : }
8782 :
8783 5 : GDALDataset::Layers::Iterator::Iterator(Iterator &&oOther) noexcept
8784 5 : : m_poPrivate(std::move(oOther.m_poPrivate))
8785 : {
8786 5 : }
8787 :
8788 410 : GDALDataset::Layers::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8789 410 : : m_poPrivate(new Private())
8790 : {
8791 410 : m_poPrivate->m_poDS = poDS;
8792 410 : m_poPrivate->m_nLayerCount = poDS->GetLayerCount();
8793 410 : if (bStart)
8794 : {
8795 207 : if (m_poPrivate->m_nLayerCount)
8796 204 : m_poPrivate->m_poLayer = poDS->GetLayer(0);
8797 : }
8798 : else
8799 : {
8800 203 : m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;
8801 : }
8802 410 : }
8803 :
8804 : GDALDataset::Layers::Iterator::~Iterator() = default;
8805 :
8806 : // False positive of cppcheck 1.72
8807 : // cppcheck-suppress operatorEqVarError
8808 : GDALDataset::Layers::Iterator &
8809 1 : GDALDataset::Layers::Iterator::operator=(const Iterator &oOther)
8810 : {
8811 1 : *m_poPrivate = *oOther.m_poPrivate;
8812 1 : return *this;
8813 : }
8814 :
8815 3 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator=(
8816 : GDALDataset::Layers::Iterator &&oOther) noexcept
8817 : {
8818 3 : m_poPrivate = std::move(oOther.m_poPrivate);
8819 3 : return *this;
8820 : }
8821 :
8822 239 : OGRLayer *GDALDataset::Layers::Iterator::operator*() const
8823 : {
8824 239 : return m_poPrivate->m_poLayer;
8825 : }
8826 :
8827 230 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator++()
8828 : {
8829 230 : m_poPrivate->m_iCurLayer++;
8830 230 : if (m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount)
8831 : {
8832 41 : m_poPrivate->m_poLayer =
8833 41 : m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);
8834 : }
8835 : else
8836 : {
8837 189 : m_poPrivate->m_poLayer = nullptr;
8838 : }
8839 230 : return *this;
8840 : }
8841 :
8842 2 : GDALDataset::Layers::Iterator GDALDataset::Layers::Iterator::operator++(int)
8843 : {
8844 2 : GDALDataset::Layers::Iterator temp = *this;
8845 2 : ++(*this);
8846 2 : return temp;
8847 : }
8848 :
8849 427 : bool GDALDataset::Layers::Iterator::operator!=(const Iterator &it) const
8850 : {
8851 427 : return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;
8852 : }
8853 :
8854 : /************************************************************************/
8855 : /* GetLayers() */
8856 : /************************************************************************/
8857 :
8858 : /** Function that returns an iterable object over layers in the dataset.
8859 : *
8860 : * This is a C++ iterator friendly version of GetLayer().
8861 : *
8862 : * Typical use is:
8863 : * \code{.cpp}
8864 : * for( auto&& poLayer: poDS->GetLayers() )
8865 : * {
8866 : * std::cout << "Layer << poLayer->GetName() << std::endl;
8867 : * }
8868 : * \endcode
8869 : *
8870 : * @see GetLayer()
8871 : *
8872 : * @since GDAL 2.3
8873 : */
8874 208 : GDALDataset::Layers GDALDataset::GetLayers()
8875 : {
8876 208 : return Layers(this);
8877 : }
8878 :
8879 : /************************************************************************/
8880 : /* begin() */
8881 : /************************************************************************/
8882 :
8883 : /**
8884 : \brief Return beginning of layer iterator.
8885 :
8886 : @since GDAL 2.3
8887 : */
8888 :
8889 207 : GDALDataset::Layers::Iterator GDALDataset::Layers::begin() const
8890 : {
8891 207 : return {m_poSelf, true};
8892 : }
8893 :
8894 : /************************************************************************/
8895 : /* end() */
8896 : /************************************************************************/
8897 :
8898 : /**
8899 : \brief Return end of layer iterator.
8900 :
8901 : @since GDAL 2.3
8902 : */
8903 :
8904 203 : GDALDataset::Layers::Iterator GDALDataset::Layers::end() const
8905 : {
8906 203 : return {m_poSelf, false};
8907 : }
8908 :
8909 : /************************************************************************/
8910 : /* size() */
8911 : /************************************************************************/
8912 :
8913 : /**
8914 : \brief Get the number of layers in this dataset.
8915 :
8916 : @return layer count.
8917 :
8918 : @since GDAL 2.3
8919 : */
8920 :
8921 1 : size_t GDALDataset::Layers::size() const
8922 : {
8923 1 : return static_cast<size_t>(m_poSelf->GetLayerCount());
8924 : }
8925 :
8926 : /************************************************************************/
8927 : /* operator[]() */
8928 : /************************************************************************/
8929 : /**
8930 : \brief Fetch a layer by index.
8931 :
8932 : The returned layer remains owned by the
8933 : GDALDataset and should not be deleted by the application.
8934 :
8935 : @param iLayer a layer number between 0 and size()-1.
8936 :
8937 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
8938 :
8939 : @since GDAL 2.3
8940 : */
8941 :
8942 9 : OGRLayer *GDALDataset::Layers::operator[](int iLayer)
8943 : {
8944 9 : return m_poSelf->GetLayer(iLayer);
8945 : }
8946 :
8947 : /************************************************************************/
8948 : /* operator[]() */
8949 : /************************************************************************/
8950 : /**
8951 : \brief Fetch a layer by index.
8952 :
8953 : The returned layer remains owned by the
8954 : GDALDataset and should not be deleted by the application.
8955 :
8956 : @param iLayer a layer number between 0 and size()-1.
8957 :
8958 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
8959 :
8960 : @since GDAL 2.3
8961 : */
8962 :
8963 1 : OGRLayer *GDALDataset::Layers::operator[](size_t iLayer)
8964 : {
8965 1 : return m_poSelf->GetLayer(static_cast<int>(iLayer));
8966 : }
8967 :
8968 : /************************************************************************/
8969 : /* operator[]() */
8970 : /************************************************************************/
8971 : /**
8972 : \brief Fetch a layer by name.
8973 :
8974 : The returned layer remains owned by the
8975 : GDALDataset and should not be deleted by the application.
8976 :
8977 : @param pszLayerName layer name
8978 :
8979 : @return the layer, or nullptr if pszLayerName does not match with a layer
8980 :
8981 : @since GDAL 2.3
8982 : */
8983 :
8984 1 : OGRLayer *GDALDataset::Layers::operator[](const char *pszLayerName)
8985 : {
8986 1 : return m_poSelf->GetLayerByName(pszLayerName);
8987 : }
8988 :
8989 : /************************************************************************/
8990 : /* GDALDataset::Bands::Iterator::Private */
8991 : /************************************************************************/
8992 :
8993 : struct GDALDataset::Bands::Iterator::Private
8994 : {
8995 : GDALRasterBand *m_poBand = nullptr;
8996 : int m_iCurBand = 0;
8997 : int m_nBandCount = 0;
8998 : GDALDataset *m_poDS = nullptr;
8999 : };
9000 :
9001 6 : GDALDataset::Bands::Iterator::Iterator(GDALDataset *poDS, bool bStart)
9002 6 : : m_poPrivate(new GDALDataset::Bands::Iterator::Private())
9003 : {
9004 6 : m_poPrivate->m_poDS = poDS;
9005 6 : m_poPrivate->m_nBandCount = poDS->GetRasterCount();
9006 6 : if (bStart)
9007 : {
9008 3 : if (m_poPrivate->m_nBandCount)
9009 3 : m_poPrivate->m_poBand = poDS->GetRasterBand(1);
9010 : }
9011 : else
9012 : {
9013 3 : m_poPrivate->m_iCurBand = m_poPrivate->m_nBandCount;
9014 : }
9015 6 : }
9016 :
9017 : GDALDataset::Bands::Iterator::~Iterator() = default;
9018 :
9019 5 : GDALRasterBand *GDALDataset::Bands::Iterator::operator*()
9020 : {
9021 5 : return m_poPrivate->m_poBand;
9022 : }
9023 :
9024 3 : GDALDataset::Bands::Iterator &GDALDataset::Bands::Iterator::operator++()
9025 : {
9026 3 : m_poPrivate->m_iCurBand++;
9027 3 : if (m_poPrivate->m_iCurBand < m_poPrivate->m_nBandCount)
9028 : {
9029 2 : m_poPrivate->m_poBand =
9030 2 : m_poPrivate->m_poDS->GetRasterBand(1 + m_poPrivate->m_iCurBand);
9031 : }
9032 : else
9033 : {
9034 1 : m_poPrivate->m_poBand = nullptr;
9035 : }
9036 3 : return *this;
9037 : }
9038 :
9039 6 : bool GDALDataset::Bands::Iterator::operator!=(const Iterator &it) const
9040 : {
9041 6 : return m_poPrivate->m_iCurBand != it.m_poPrivate->m_iCurBand;
9042 : }
9043 :
9044 : /************************************************************************/
9045 : /* GetBands() */
9046 : /************************************************************************/
9047 :
9048 : /** Function that returns an iterable object over GDALRasterBand in the dataset.
9049 : *
9050 : * This is a C++ iterator friendly version of GetRasterBand().
9051 : *
9052 : * Typical use is:
9053 : * \code{.cpp}
9054 : * for( auto&& poBand: poDS->GetBands() )
9055 : * {
9056 : * std::cout << "Band << poBand->GetDescription() << std::endl;
9057 : * }
9058 : * \endcode
9059 : *
9060 : * @see GetRasterBand()
9061 : *
9062 : * @since GDAL 2.3
9063 : */
9064 7 : GDALDataset::Bands GDALDataset::GetBands()
9065 : {
9066 7 : return Bands(this);
9067 : }
9068 :
9069 : /************************************************************************/
9070 : /* begin() */
9071 : /************************************************************************/
9072 :
9073 : /**
9074 : \brief Return beginning of band iterator.
9075 :
9076 : @since GDAL 2.3
9077 : */
9078 :
9079 3 : const GDALDataset::Bands::Iterator GDALDataset::Bands::begin() const
9080 : {
9081 3 : return {m_poSelf, true};
9082 : }
9083 :
9084 : /************************************************************************/
9085 : /* end() */
9086 : /************************************************************************/
9087 :
9088 : /**
9089 : \brief Return end of band iterator.
9090 :
9091 : @since GDAL 2.3
9092 : */
9093 :
9094 3 : const GDALDataset::Bands::Iterator GDALDataset::Bands::end() const
9095 : {
9096 3 : return {m_poSelf, false};
9097 : }
9098 :
9099 : /************************************************************************/
9100 : /* size() */
9101 : /************************************************************************/
9102 :
9103 : /**
9104 : \brief Get the number of raster bands in this dataset.
9105 :
9106 : @return raster band count.
9107 :
9108 : @since GDAL 2.3
9109 : */
9110 :
9111 2 : size_t GDALDataset::Bands::size() const
9112 : {
9113 2 : return static_cast<size_t>(m_poSelf->GetRasterCount());
9114 : }
9115 :
9116 : /************************************************************************/
9117 : /* operator[]() */
9118 : /************************************************************************/
9119 : /**
9120 : \brief Fetch a raster band by index.
9121 :
9122 : The returned band remains owned by the
9123 : GDALDataset and should not be deleted by the application.
9124 :
9125 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9126 : consistent with the conventions of C/C++, i.e. starting at 0.
9127 :
9128 : @param iBand a band index between 0 and size()-1.
9129 :
9130 : @return the band, or nullptr if iBand is out of range or an error occurs.
9131 :
9132 : @since GDAL 2.3
9133 : */
9134 :
9135 1 : GDALRasterBand *GDALDataset::Bands::operator[](int iBand)
9136 : {
9137 1 : return m_poSelf->GetRasterBand(1 + iBand);
9138 : }
9139 :
9140 : /************************************************************************/
9141 : /* operator[]() */
9142 : /************************************************************************/
9143 :
9144 : /**
9145 : \brief Fetch a raster band by index.
9146 :
9147 : The returned band remains owned by the
9148 : GDALDataset and should not be deleted by the application.
9149 :
9150 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9151 : consistent with the conventions of C/C++, i.e. starting at 0.
9152 :
9153 : @param iBand a band index between 0 and size()-1.
9154 :
9155 : @return the band, or nullptr if iBand is out of range or an error occurs.
9156 :
9157 : @since GDAL 2.3
9158 : */
9159 :
9160 1 : GDALRasterBand *GDALDataset::Bands::operator[](size_t iBand)
9161 : {
9162 1 : return m_poSelf->GetRasterBand(1 + static_cast<int>(iBand));
9163 : }
9164 :
9165 : /************************************************************************/
9166 : /* GetRootGroup() */
9167 : /************************************************************************/
9168 :
9169 : /**
9170 : \brief Return the root GDALGroup of this dataset.
9171 :
9172 : Only valid for multidimensional datasets.
9173 :
9174 : This is the same as the C function GDALDatasetGetRootGroup().
9175 :
9176 : @since GDAL 3.1
9177 : */
9178 :
9179 2705 : std::shared_ptr<GDALGroup> GDALDataset::GetRootGroup() const
9180 : {
9181 2705 : return nullptr;
9182 : }
9183 :
9184 : /************************************************************************/
9185 : /* GetRawBinaryLayout() */
9186 : /************************************************************************/
9187 :
9188 : //! @cond Doxygen_Suppress
9189 : /**
9190 : \brief Return the layout of a dataset that can be considered as a raw binary
9191 : format.
9192 :
9193 : @param sLayout Structure that will be set if the dataset is a raw binary one.
9194 : @return true if the dataset is a raw binary one.
9195 : @since GDAL 3.1
9196 : */
9197 :
9198 0 : bool GDALDataset::GetRawBinaryLayout(RawBinaryLayout &sLayout)
9199 : {
9200 0 : CPL_IGNORE_RET_VAL(sLayout);
9201 0 : return false;
9202 : }
9203 :
9204 : //! @endcond
9205 :
9206 : /************************************************************************/
9207 : /* ClearStatistics() */
9208 : /************************************************************************/
9209 :
9210 : /**
9211 : \brief Clear statistics
9212 :
9213 : Only implemented for now in PAM supported datasets
9214 :
9215 : This is the same as the C function GDALDatasetClearStatistics().
9216 :
9217 : @since GDAL 3.2
9218 : */
9219 :
9220 11 : void GDALDataset::ClearStatistics()
9221 : {
9222 22 : auto poRootGroup = GetRootGroup();
9223 11 : if (poRootGroup)
9224 1 : poRootGroup->ClearStatistics();
9225 11 : }
9226 :
9227 : /************************************************************************/
9228 : /* GDALDatasetClearStatistics() */
9229 : /************************************************************************/
9230 :
9231 : /**
9232 : \brief Clear statistics
9233 :
9234 : This is the same as the C++ method GDALDataset::ClearStatistics().
9235 :
9236 : @since GDAL 3.2
9237 : */
9238 :
9239 2 : void GDALDatasetClearStatistics(GDALDatasetH hDS)
9240 : {
9241 2 : VALIDATE_POINTER0(hDS, __func__);
9242 2 : GDALDataset::FromHandle(hDS)->ClearStatistics();
9243 : }
9244 :
9245 : /************************************************************************/
9246 : /* GetFieldDomainNames() */
9247 : /************************************************************************/
9248 :
9249 : /** Returns a list of the names of all field domains stored in the dataset.
9250 : *
9251 : * @note The default implementation assumes that drivers fully populate
9252 : * m_oMapFieldDomains when opening a dataset. If this assumption is incorrect
9253 : * then a specialized implementation of GetFieldDomainNames() must be
9254 : * implemented.
9255 : *
9256 : * @param papszOptions Driver specific options determining how attributes
9257 : * should be retrieved. Pass nullptr for default behavior.
9258 : *
9259 : * @return list of field domain names
9260 : * @since GDAL 3.5
9261 : */
9262 : std::vector<std::string>
9263 41 : GDALDataset::GetFieldDomainNames(CPL_UNUSED CSLConstList papszOptions) const
9264 : {
9265 :
9266 41 : std::vector<std::string> names;
9267 41 : names.reserve(m_oMapFieldDomains.size());
9268 53 : for (const auto &it : m_oMapFieldDomains)
9269 : {
9270 12 : names.emplace_back(it.first);
9271 : }
9272 41 : return names;
9273 : }
9274 :
9275 : /************************************************************************/
9276 : /* GDALDatasetGetFieldDomainNames() */
9277 : /************************************************************************/
9278 :
9279 : /** Returns a list of the names of all field domains stored in the dataset.
9280 : *
9281 : * This is the same as the C++ method GDALDataset::GetFieldDomainNames().
9282 : *
9283 : * @param hDS Dataset handle.
9284 : * @param papszOptions Driver specific options determining how attributes
9285 : * should be retrieved. Pass nullptr for default behavior.
9286 : *
9287 : * @return list of field domain names, to be freed with CSLDestroy()
9288 : * @since GDAL 3.5
9289 : */
9290 32 : char **GDALDatasetGetFieldDomainNames(GDALDatasetH hDS,
9291 : CSLConstList papszOptions)
9292 : {
9293 32 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9294 : auto names =
9295 64 : GDALDataset::FromHandle(hDS)->GetFieldDomainNames(papszOptions);
9296 64 : CPLStringList res;
9297 137 : for (const auto &name : names)
9298 : {
9299 105 : res.AddString(name.c_str());
9300 : }
9301 32 : return res.StealList();
9302 : }
9303 :
9304 : /************************************************************************/
9305 : /* GetFieldDomain() */
9306 : /************************************************************************/
9307 :
9308 : /** Get a field domain from its name.
9309 : *
9310 : * @return the field domain, or nullptr if not found.
9311 : * @since GDAL 3.3
9312 : */
9313 270 : const OGRFieldDomain *GDALDataset::GetFieldDomain(const std::string &name) const
9314 : {
9315 270 : const auto iter = m_oMapFieldDomains.find(name);
9316 270 : if (iter == m_oMapFieldDomains.end())
9317 116 : return nullptr;
9318 154 : return iter->second.get();
9319 : }
9320 :
9321 : /************************************************************************/
9322 : /* GDALDatasetGetFieldDomain() */
9323 : /************************************************************************/
9324 :
9325 : /** Get a field domain from its name.
9326 : *
9327 : * This is the same as the C++ method GDALDataset::GetFieldDomain().
9328 : *
9329 : * @param hDS Dataset handle.
9330 : * @param pszName Name of field domain.
9331 : * @return the field domain (ownership remains to the dataset), or nullptr if
9332 : * not found.
9333 : * @since GDAL 3.3
9334 : */
9335 114 : OGRFieldDomainH GDALDatasetGetFieldDomain(GDALDatasetH hDS, const char *pszName)
9336 : {
9337 114 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9338 114 : VALIDATE_POINTER1(pszName, __func__, nullptr);
9339 114 : return OGRFieldDomain::ToHandle(const_cast<OGRFieldDomain *>(
9340 114 : GDALDataset::FromHandle(hDS)->GetFieldDomain(pszName)));
9341 : }
9342 :
9343 : /************************************************************************/
9344 : /* AddFieldDomain() */
9345 : /************************************************************************/
9346 :
9347 : /** Add a field domain to the dataset.
9348 : *
9349 : * Only a few drivers will support this operation, and some of them might only
9350 : * support it only for some types of field domains.
9351 : * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9352 : * support this operation. A dataset having at least some support for this
9353 : * operation should report the ODsCAddFieldDomain dataset capability.
9354 : *
9355 : * Anticipated failures will not be emitted through the CPLError()
9356 : * infrastructure, but will be reported in the failureReason output parameter.
9357 : *
9358 : * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9359 : * default implementation of GetFieldDomainNames() to work correctly, or
9360 : * alternatively a specialized implementation of GetFieldDomainNames() should be
9361 : * implemented.
9362 : *
9363 : * @param domain The domain definition.
9364 : * @param failureReason Output parameter. Will contain an error message if
9365 : * an error occurs.
9366 : * @return true in case of success.
9367 : * @since GDAL 3.3
9368 : */
9369 0 : bool GDALDataset::AddFieldDomain(
9370 : CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9371 : std::string &failureReason)
9372 : {
9373 0 : failureReason = "AddFieldDomain not supported by this driver";
9374 0 : return false;
9375 : }
9376 :
9377 : /************************************************************************/
9378 : /* GDALDatasetAddFieldDomain() */
9379 : /************************************************************************/
9380 :
9381 : /** Add a field domain to the dataset.
9382 : *
9383 : * Only a few drivers will support this operation, and some of them might only
9384 : * support it only for some types of field domains.
9385 : * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9386 : * support this operation. A dataset having at least some support for this
9387 : * operation should report the ODsCAddFieldDomain dataset capability.
9388 : *
9389 : * Anticipated failures will not be emitted through the CPLError()
9390 : * infrastructure, but will be reported in the ppszFailureReason output
9391 : * parameter.
9392 : *
9393 : * @param hDS Dataset handle.
9394 : * @param hFieldDomain The domain definition. Contrary to the C++ version,
9395 : * the passed object is copied.
9396 : * @param ppszFailureReason Output parameter. Will contain an error message if
9397 : * an error occurs (*ppszFailureReason to be freed
9398 : * with CPLFree). May be NULL.
9399 : * @return true in case of success.
9400 : * @since GDAL 3.3
9401 : */
9402 37 : bool GDALDatasetAddFieldDomain(GDALDatasetH hDS, OGRFieldDomainH hFieldDomain,
9403 : char **ppszFailureReason)
9404 : {
9405 37 : VALIDATE_POINTER1(hDS, __func__, false);
9406 37 : VALIDATE_POINTER1(hFieldDomain, __func__, false);
9407 : auto poDomain = std::unique_ptr<OGRFieldDomain>(
9408 74 : OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9409 37 : if (poDomain == nullptr)
9410 0 : return false;
9411 37 : std::string failureReason;
9412 74 : const bool bRet = GDALDataset::FromHandle(hDS)->AddFieldDomain(
9413 37 : std::move(poDomain), failureReason);
9414 37 : if (ppszFailureReason)
9415 : {
9416 37 : *ppszFailureReason =
9417 37 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9418 : }
9419 37 : return bRet;
9420 : }
9421 :
9422 : /************************************************************************/
9423 : /* DeleteFieldDomain() */
9424 : /************************************************************************/
9425 :
9426 : /** Removes a field domain from the dataset.
9427 : *
9428 : * Only a few drivers will support this operation.
9429 : *
9430 : * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9431 : * support this operation. A dataset having at least some support for this
9432 : * operation should report the ODsCDeleteFieldDomain dataset capability.
9433 : *
9434 : * Anticipated failures will not be emitted through the CPLError()
9435 : * infrastructure, but will be reported in the failureReason output parameter.
9436 : *
9437 : * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9438 : * default implementation of GetFieldDomainNames() to work correctly, or
9439 : * alternatively a specialized implementation of GetFieldDomainNames() should be
9440 : * implemented.
9441 : *
9442 : * @param name The domain name.
9443 : * @param failureReason Output parameter. Will contain an error message if
9444 : * an error occurs.
9445 : * @return true in case of success.
9446 : * @since GDAL 3.5
9447 : */
9448 0 : bool GDALDataset::DeleteFieldDomain(CPL_UNUSED const std::string &name,
9449 : std::string &failureReason)
9450 : {
9451 0 : failureReason = "DeleteFieldDomain not supported by this driver";
9452 0 : return false;
9453 : }
9454 :
9455 : /************************************************************************/
9456 : /* GDALDatasetDeleteFieldDomain() */
9457 : /************************************************************************/
9458 :
9459 : /** Removes a field domain from the dataset.
9460 : *
9461 : * Only a few drivers will support this operation.
9462 : *
9463 : * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9464 : * support this operation. A dataset having at least some support for this
9465 : * operation should report the ODsCDeleteFieldDomain dataset capability.
9466 : *
9467 : * Anticipated failures will not be emitted through the CPLError()
9468 : * infrastructure, but will be reported in the ppszFailureReason output
9469 : * parameter.
9470 : *
9471 : * @param hDS Dataset handle.
9472 : * @param pszName The domain name.
9473 : * @param ppszFailureReason Output parameter. Will contain an error message if
9474 : * an error occurs (*ppszFailureReason to be freed
9475 : * with CPLFree). May be NULL.
9476 : * @return true in case of success.
9477 : * @since GDAL 3.3
9478 : */
9479 8 : bool GDALDatasetDeleteFieldDomain(GDALDatasetH hDS, const char *pszName,
9480 : char **ppszFailureReason)
9481 : {
9482 8 : VALIDATE_POINTER1(hDS, __func__, false);
9483 8 : VALIDATE_POINTER1(pszName, __func__, false);
9484 8 : std::string failureReason;
9485 : const bool bRet =
9486 8 : GDALDataset::FromHandle(hDS)->DeleteFieldDomain(pszName, failureReason);
9487 8 : if (ppszFailureReason)
9488 : {
9489 0 : *ppszFailureReason =
9490 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9491 : }
9492 8 : return bRet;
9493 : }
9494 :
9495 : /************************************************************************/
9496 : /* UpdateFieldDomain() */
9497 : /************************************************************************/
9498 :
9499 : /** Updates an existing field domain by replacing its definition.
9500 : *
9501 : * The existing field domain with matching name will be replaced.
9502 : *
9503 : * Only a few drivers will support this operation, and some of them might only
9504 : * support it only for some types of field domains.
9505 : * At the time of writing (GDAL 3.5), only the Memory driver
9506 : * supports this operation. A dataset having at least some support for this
9507 : * operation should report the ODsCUpdateFieldDomain dataset capability.
9508 : *
9509 : * Anticipated failures will not be emitted through the CPLError()
9510 : * infrastructure, but will be reported in the failureReason output parameter.
9511 : *
9512 : * @param domain The domain definition.
9513 : * @param failureReason Output parameter. Will contain an error message if
9514 : * an error occurs.
9515 : * @return true in case of success.
9516 : * @since GDAL 3.5
9517 : */
9518 0 : bool GDALDataset::UpdateFieldDomain(
9519 : CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9520 : std::string &failureReason)
9521 : {
9522 0 : failureReason = "UpdateFieldDomain not supported by this driver";
9523 0 : return false;
9524 : }
9525 :
9526 : /************************************************************************/
9527 : /* GDALDatasetUpdateFieldDomain() */
9528 : /************************************************************************/
9529 :
9530 : /** Updates an existing field domain by replacing its definition.
9531 : *
9532 : * The existing field domain with matching name will be replaced.
9533 : *
9534 : * Only a few drivers will support this operation, and some of them might only
9535 : * support it only for some types of field domains.
9536 : * At the time of writing (GDAL 3.5), only the Memory driver
9537 : * supports this operation. A dataset having at least some support for this
9538 : * operation should report the ODsCUpdateFieldDomain dataset capability.
9539 : *
9540 : * Anticipated failures will not be emitted through the CPLError()
9541 : * infrastructure, but will be reported in the failureReason output parameter.
9542 : *
9543 : * @param hDS Dataset handle.
9544 : * @param hFieldDomain The domain definition. Contrary to the C++ version,
9545 : * the passed object is copied.
9546 : * @param ppszFailureReason Output parameter. Will contain an error message if
9547 : * an error occurs (*ppszFailureReason to be freed
9548 : * with CPLFree). May be NULL.
9549 : * @return true in case of success.
9550 : * @since GDAL 3.5
9551 : */
9552 4 : bool GDALDatasetUpdateFieldDomain(GDALDatasetH hDS,
9553 : OGRFieldDomainH hFieldDomain,
9554 : char **ppszFailureReason)
9555 : {
9556 4 : VALIDATE_POINTER1(hDS, __func__, false);
9557 4 : VALIDATE_POINTER1(hFieldDomain, __func__, false);
9558 : auto poDomain = std::unique_ptr<OGRFieldDomain>(
9559 8 : OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9560 4 : if (poDomain == nullptr)
9561 0 : return false;
9562 4 : std::string failureReason;
9563 8 : const bool bRet = GDALDataset::FromHandle(hDS)->UpdateFieldDomain(
9564 4 : std::move(poDomain), failureReason);
9565 4 : if (ppszFailureReason)
9566 : {
9567 0 : *ppszFailureReason =
9568 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9569 : }
9570 4 : return bRet;
9571 : }
9572 :
9573 : /************************************************************************/
9574 : /* GetRelationshipNames() */
9575 : /************************************************************************/
9576 :
9577 : /** Returns a list of the names of all relationships stored in the dataset.
9578 : *
9579 : * @param papszOptions Driver specific options determining how relationships
9580 : * should be retrieved. Pass nullptr for default behavior.
9581 : *
9582 : * @return list of relationship names
9583 : * @since GDAL 3.6
9584 : */
9585 : std::vector<std::string>
9586 157 : GDALDataset::GetRelationshipNames(CPL_UNUSED CSLConstList papszOptions) const
9587 : {
9588 157 : return {};
9589 : }
9590 :
9591 : /************************************************************************/
9592 : /* GDALDatasetGetRelationshipNames() */
9593 : /************************************************************************/
9594 :
9595 : /** Returns a list of the names of all relationships stored in the dataset.
9596 : *
9597 : * This is the same as the C++ method GDALDataset::GetRelationshipNames().
9598 : *
9599 : * @param hDS Dataset handle.
9600 : * @param papszOptions Driver specific options determining how relationships
9601 : * should be retrieved. Pass nullptr for default behavior.
9602 : *
9603 : * @return list of relationship names, to be freed with CSLDestroy()
9604 : * @since GDAL 3.6
9605 : */
9606 46 : char **GDALDatasetGetRelationshipNames(GDALDatasetH hDS,
9607 : CSLConstList papszOptions)
9608 : {
9609 46 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9610 : auto names =
9611 92 : GDALDataset::FromHandle(hDS)->GetRelationshipNames(papszOptions);
9612 92 : CPLStringList res;
9613 146 : for (const auto &name : names)
9614 : {
9615 100 : res.AddString(name.c_str());
9616 : }
9617 46 : return res.StealList();
9618 : }
9619 :
9620 : /************************************************************************/
9621 : /* GetRelationship() */
9622 : /************************************************************************/
9623 :
9624 : /** Get a relationship from its name.
9625 : *
9626 : * @return the relationship, or nullptr if not found.
9627 : * @since GDAL 3.6
9628 : */
9629 : const GDALRelationship *
9630 0 : GDALDataset::GetRelationship(CPL_UNUSED const std::string &name) const
9631 : {
9632 0 : return nullptr;
9633 : }
9634 :
9635 : /************************************************************************/
9636 : /* GDALDatasetGetRelationship() */
9637 : /************************************************************************/
9638 :
9639 : /** Get a relationship from its name.
9640 : *
9641 : * This is the same as the C++ method GDALDataset::GetRelationship().
9642 : *
9643 : * @param hDS Dataset handle.
9644 : * @param pszName Name of relationship.
9645 : * @return the relationship (ownership remains to the dataset), or nullptr if
9646 : * not found.
9647 : * @since GDAL 3.6
9648 : */
9649 52 : GDALRelationshipH GDALDatasetGetRelationship(GDALDatasetH hDS,
9650 : const char *pszName)
9651 : {
9652 52 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9653 52 : VALIDATE_POINTER1(pszName, __func__, nullptr);
9654 52 : return GDALRelationship::ToHandle(const_cast<GDALRelationship *>(
9655 52 : GDALDataset::FromHandle(hDS)->GetRelationship(pszName)));
9656 : }
9657 :
9658 : /************************************************************************/
9659 : /* AddRelationship() */
9660 : /************************************************************************/
9661 :
9662 : /** Add a relationship to the dataset.
9663 : *
9664 : * Only a few drivers will support this operation, and some of them might only
9665 : * support it only for some types of relationships.
9666 : *
9667 : * A dataset having at least some support for this
9668 : * operation should report the GDsCAddRelationship dataset capability.
9669 : *
9670 : * Anticipated failures will not be emitted through the CPLError()
9671 : * infrastructure, but will be reported in the failureReason output parameter.
9672 : *
9673 : * When adding a many-to-many relationship
9674 : * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9675 : * mapping table name (see GDALRelationship::GetMappingTableName) to instruct
9676 : * the driver to create an appropriately named and structured mapping table.
9677 : * Some dataset formats require particular naming conventions and field
9678 : * structures for the mapping table, and delegating the construction of the
9679 : * mapping table to the driver will avoid these pitfalls.
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::AddRelationship(
9688 : CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9689 : std::string &failureReason)
9690 : {
9691 0 : failureReason = "AddRelationship not supported by this driver";
9692 0 : return false;
9693 : }
9694 :
9695 : /************************************************************************/
9696 : /* GDALDatasetAddRelationship() */
9697 : /************************************************************************/
9698 :
9699 : /** Add a relationship to the dataset.
9700 : *
9701 : * Only a few drivers will support this operation, and some of them might only
9702 : * support it only for some types of relationships.
9703 : *
9704 : * A dataset having at least some support for this
9705 : * operation should report the GDsCAddRelationship dataset capability.
9706 : *
9707 : * Anticipated failures will not be emitted through the CPLError()
9708 : * infrastructure, but will be reported in the failureReason output parameter.
9709 : *
9710 : * When adding a many-to-many relationship
9711 : * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9712 : * mapping table name (see GDALRelationshipGetMappingTableName) to instruct the
9713 : * driver to create an appropriately named and structured mapping table. Some
9714 : * dataset formats require particular naming conventions and field structures
9715 : * for the mapping table, and delegating the construction of the mapping table
9716 : * to the driver will avoid these pitfalls.
9717 : *
9718 : * @param hDS Dataset handle.
9719 : * @param hRelationship The relationship definition. Contrary to the C++
9720 : * version, the passed object is copied.
9721 : * @param ppszFailureReason Output parameter. Will contain an error message if
9722 : * an error occurs (*ppszFailureReason to be freed
9723 : * with CPLFree). May be NULL.
9724 : * @return true in case of success.
9725 : * @since GDAL 3.6
9726 : */
9727 42 : bool GDALDatasetAddRelationship(GDALDatasetH hDS,
9728 : GDALRelationshipH hRelationship,
9729 : char **ppszFailureReason)
9730 : {
9731 42 : VALIDATE_POINTER1(hDS, __func__, false);
9732 42 : VALIDATE_POINTER1(hRelationship, __func__, false);
9733 : std::unique_ptr<GDALRelationship> poRelationship(
9734 84 : new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9735 42 : std::string failureReason;
9736 84 : const bool bRet = GDALDataset::FromHandle(hDS)->AddRelationship(
9737 42 : std::move(poRelationship), failureReason);
9738 42 : if (ppszFailureReason)
9739 : {
9740 0 : *ppszFailureReason =
9741 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9742 : }
9743 42 : return bRet;
9744 : }
9745 :
9746 : /************************************************************************/
9747 : /* DeleteRelationship() */
9748 : /************************************************************************/
9749 :
9750 : /** Removes a relationship from the dataset.
9751 : *
9752 : * Only a few drivers will support this operation.
9753 : *
9754 : * A dataset having at least some support for this
9755 : * operation should report the GDsCDeleteRelationship dataset capability.
9756 : *
9757 : * Anticipated failures will not be emitted through the CPLError()
9758 : * infrastructure, but will be reported in the failureReason output parameter.
9759 : *
9760 : * @param name The relationship name.
9761 : * @param failureReason Output parameter. Will contain an error message if
9762 : * an error occurs.
9763 : * @return true in case of success.
9764 : * @since GDAL 3.6
9765 : */
9766 0 : bool GDALDataset::DeleteRelationship(CPL_UNUSED const std::string &name,
9767 : std::string &failureReason)
9768 : {
9769 0 : failureReason = "DeleteRelationship not supported by this driver";
9770 0 : return false;
9771 : }
9772 :
9773 : /************************************************************************/
9774 : /* GDALDatasetDeleteRelationship() */
9775 : /************************************************************************/
9776 :
9777 : /** Removes a relationship from the dataset.
9778 : *
9779 : * Only a few drivers will support this operation.
9780 : *
9781 : * A dataset having at least some support for this
9782 : * operation should report the GDsCDeleteRelationship dataset capability.
9783 : *
9784 : * Anticipated failures will not be emitted through the CPLError()
9785 : * infrastructure, but will be reported in the ppszFailureReason output
9786 : * parameter.
9787 : *
9788 : * @param hDS Dataset handle.
9789 : * @param pszName The relationship name.
9790 : * @param ppszFailureReason Output parameter. Will contain an error message if
9791 : * an error occurs (*ppszFailureReason to be freed
9792 : * with CPLFree). May be NULL.
9793 : * @return true in case of success.
9794 : * @since GDAL 3.6
9795 : */
9796 6 : bool GDALDatasetDeleteRelationship(GDALDatasetH hDS, const char *pszName,
9797 : char **ppszFailureReason)
9798 : {
9799 6 : VALIDATE_POINTER1(hDS, __func__, false);
9800 6 : VALIDATE_POINTER1(pszName, __func__, false);
9801 6 : std::string failureReason;
9802 12 : const bool bRet = GDALDataset::FromHandle(hDS)->DeleteRelationship(
9803 6 : pszName, failureReason);
9804 6 : if (ppszFailureReason)
9805 : {
9806 0 : *ppszFailureReason =
9807 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9808 : }
9809 6 : return bRet;
9810 : }
9811 :
9812 : /************************************************************************/
9813 : /* UpdateRelationship() */
9814 : /************************************************************************/
9815 :
9816 : /** Updates an existing relationship by replacing its definition.
9817 : *
9818 : * The existing relationship with matching name will be replaced.
9819 : *
9820 : * Only a few drivers will support this operation, and some of them might only
9821 : * support it only for some types of relationships.
9822 : * A dataset having at least some support for this
9823 : * operation should report the GDsCUpdateRelationship dataset capability.
9824 : *
9825 : * Anticipated failures will not be emitted through the CPLError()
9826 : * infrastructure, but will be reported in the failureReason output parameter.
9827 : *
9828 : * @param relationship The relationship definition.
9829 : * @param failureReason Output parameter. Will contain an error message if
9830 : * an error occurs.
9831 : * @return true in case of success.
9832 : * @since GDAL 3.6
9833 : */
9834 0 : bool GDALDataset::UpdateRelationship(
9835 : CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9836 : std::string &failureReason)
9837 : {
9838 0 : failureReason = "UpdateRelationship not supported by this driver";
9839 0 : return false;
9840 : }
9841 :
9842 : /************************************************************************/
9843 : /* GDALDatasetUpdateRelationship() */
9844 : /************************************************************************/
9845 :
9846 : /** Updates an existing relationship by replacing its definition.
9847 : *
9848 : * The existing relationship with matching name will be replaced.
9849 : *
9850 : * Only a few drivers will support this operation, and some of them might only
9851 : * support it only for some types of relationships.
9852 : * A dataset having at least some support for this
9853 : * operation should report the GDsCUpdateRelationship dataset capability.
9854 : *
9855 : * Anticipated failures will not be emitted through the CPLError()
9856 : * infrastructure, but will be reported in the failureReason output parameter.
9857 : *
9858 : * @param hDS Dataset handle.
9859 : * @param hRelationship The relationship definition. Contrary to the C++
9860 : * version, the passed object is copied.
9861 : * @param ppszFailureReason Output parameter. Will contain an error message if
9862 : * an error occurs (*ppszFailureReason to be freed
9863 : * with CPLFree). May be NULL.
9864 : * @return true in case of success.
9865 : * @since GDAL 3.5
9866 : */
9867 9 : bool GDALDatasetUpdateRelationship(GDALDatasetH hDS,
9868 : GDALRelationshipH hRelationship,
9869 : char **ppszFailureReason)
9870 : {
9871 9 : VALIDATE_POINTER1(hDS, __func__, false);
9872 9 : VALIDATE_POINTER1(hRelationship, __func__, false);
9873 : std::unique_ptr<GDALRelationship> poRelationship(
9874 18 : new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9875 9 : std::string failureReason;
9876 18 : const bool bRet = GDALDataset::FromHandle(hDS)->UpdateRelationship(
9877 9 : std::move(poRelationship), failureReason);
9878 9 : if (ppszFailureReason)
9879 : {
9880 0 : *ppszFailureReason =
9881 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9882 : }
9883 9 : return bRet;
9884 : }
9885 :
9886 : /************************************************************************/
9887 : /* GDALDatasetSetQueryLoggerFunc() */
9888 : /************************************************************************/
9889 :
9890 : /**
9891 : * Sets the SQL query logger callback.
9892 : *
9893 : * When supported by the driver, the callback will be called with
9894 : * the executed SQL text, the error message, the execution time in milliseconds,
9895 : * the number of records fetched/affected and the client status data.
9896 : *
9897 : * A value of -1 in the execution time or in the number of records indicates
9898 : * that the values are unknown.
9899 : *
9900 : * @param hDS Dataset handle.
9901 : * @param pfnQueryLoggerFunc Callback function
9902 : * @param poQueryLoggerArg Opaque client status data
9903 : * @return true in case of success.
9904 : * @since GDAL 3.7
9905 : */
9906 1 : bool GDALDatasetSetQueryLoggerFunc(GDALDatasetH hDS,
9907 : GDALQueryLoggerFunc pfnQueryLoggerFunc,
9908 : void *poQueryLoggerArg)
9909 : {
9910 1 : VALIDATE_POINTER1(hDS, __func__, false);
9911 2 : return GDALDataset::FromHandle(hDS)->SetQueryLoggerFunc(pfnQueryLoggerFunc,
9912 1 : poQueryLoggerArg);
9913 : }
9914 :
9915 : //! @cond Doxygen_Suppress
9916 :
9917 : /************************************************************************/
9918 : /* SetEnableOverviews() */
9919 : /************************************************************************/
9920 :
9921 7491 : void GDALDataset::SetEnableOverviews(bool bEnable)
9922 : {
9923 7491 : if (m_poPrivate)
9924 : {
9925 7491 : m_poPrivate->m_bOverviewsEnabled = bEnable;
9926 : }
9927 7491 : }
9928 :
9929 : /************************************************************************/
9930 : /* AreOverviewsEnabled() */
9931 : /************************************************************************/
9932 :
9933 2005360 : bool GDALDataset::AreOverviewsEnabled() const
9934 : {
9935 2005360 : return m_poPrivate ? m_poPrivate->m_bOverviewsEnabled : true;
9936 : }
9937 :
9938 : /************************************************************************/
9939 : /* IsAllBands() */
9940 : /************************************************************************/
9941 :
9942 3487 : bool GDALDataset::IsAllBands(int nBandCount, const int *panBandList) const
9943 : {
9944 3487 : if (nBands != nBandCount)
9945 1 : return false;
9946 3486 : if (panBandList)
9947 : {
9948 12663 : for (int i = 0; i < nBandCount; ++i)
9949 : {
9950 9268 : if (panBandList[i] != i + 1)
9951 27 : return false;
9952 : }
9953 : }
9954 3459 : return true;
9955 : }
9956 :
9957 : //! @endcond
9958 :
9959 : /************************************************************************/
9960 : /* GetCompressionFormats() */
9961 : /************************************************************************/
9962 :
9963 : /** Return the compression formats that can be natively obtained for the
9964 : * window of interest and requested bands.
9965 : *
9966 : * For example, a tiled dataset may be able to return data in a compressed
9967 : * format if the window of interest matches exactly a tile. For some formats,
9968 : * drivers may also be able to merge several tiles together (not currently
9969 : * implemented though).
9970 : *
9971 : * Each format string is a pseudo MIME type, whose first part can be passed
9972 : * as the pszFormat argument of ReadCompressedData(), with additional
9973 : * parameters specified as key=value with a semi-colon separator.
9974 : *
9975 : * The amount and types of optional parameters passed after the MIME type is
9976 : * format dependent, and driver dependent (some drivers might not be able to
9977 : * return those extra information without doing a rather costly processing).
9978 : *
9979 : * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
9980 : * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
9981 : * consequently "JPEG" can be passed as the pszFormat argument of
9982 : * ReadCompressedData(). For JPEG, implementations can use the
9983 : * GDALGetCompressionFormatForJPEG() helper method to generate a string like
9984 : * above from a JPEG codestream.
9985 : *
9986 : * Several values might be returned. For example,
9987 : * the JPEGXL driver will return "JXL", but also potentially "JPEG"
9988 : * if the JPEGXL codestream includes a JPEG reconstruction box.
9989 : *
9990 : * In the general case this method will return an empty list.
9991 : *
9992 : * This is the same as C function GDALDatasetGetCompressionFormats().
9993 : *
9994 : * @param nXOff The pixel offset to the top left corner of the region
9995 : * of the band to be accessed. This would be zero to start from the left side.
9996 : *
9997 : * @param nYOff The line offset to the top left corner of the region
9998 : * of the band to be accessed. This would be zero to start from the top.
9999 : *
10000 : * @param nXSize The width of the region of the band to be accessed in pixels.
10001 : *
10002 : * @param nYSize The height of the region of the band to be accessed in lines.
10003 : *
10004 : * @param nBandCount the number of bands being requested.
10005 : *
10006 : * @param panBandList the list of nBandCount band numbers.
10007 : * Note band numbers are 1 based. This may be NULL to select the first
10008 : * nBandCount bands.
10009 : *
10010 : * @return a list of compatible formats (which may be empty)
10011 : *
10012 : * For example, to check if native compression format(s) are available on the
10013 : * whole image:
10014 : * \code{.cpp}
10015 : * const CPLStringList aosFormats =
10016 : * poDataset->GetCompressionFormats(0, 0,
10017 : * poDataset->GetRasterXSize(),
10018 : * poDataset->GetRasterYSize(),
10019 : * poDataset->GetRasterCount(),
10020 : * nullptr);
10021 : * for( const char* pszFormat: aosFormats )
10022 : * {
10023 : * // Remove optional parameters and just print out the MIME type.
10024 : * const CPLStringList aosTokens(CSLTokenizeString2(pszFormat, ";", 0));
10025 : * printf("Found format %s\n, aosTokens[0]);
10026 : * }
10027 : * \endcode
10028 : *
10029 : * @since GDAL 3.7
10030 : */
10031 : CPLStringList
10032 0 : GDALDataset::GetCompressionFormats(CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
10033 : CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
10034 : CPL_UNUSED int nBandCount,
10035 : CPL_UNUSED const int *panBandList)
10036 : {
10037 0 : return CPLStringList();
10038 : }
10039 :
10040 : /************************************************************************/
10041 : /* GDALDatasetGetCompressionFormats() */
10042 : /************************************************************************/
10043 :
10044 : /** Return the compression formats that can be natively obtained for the
10045 : * window of interest and requested bands.
10046 : *
10047 : * For example, a tiled dataset may be able to return data in a compressed
10048 : * format if the window of interest matches exactly a tile. For some formats,
10049 : * drivers may also be able to merge several tiles together (not currently
10050 : * implemented though).
10051 : *
10052 : * Each format string is a pseudo MIME type, whose first part can be passed
10053 : * as the pszFormat argument of ReadCompressedData(), with additional
10054 : * parameters specified as key=value with a semi-colon separator.
10055 : *
10056 : * The amount and types of optional parameters passed after the MIME type is
10057 : * format dependent, and driver dependent (some drivers might not be able to
10058 : * return those extra information without doing a rather costly processing).
10059 : *
10060 : * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
10061 : * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
10062 : * consequently "JPEG" can be passed as the pszFormat argument of
10063 : * ReadCompressedData(). For JPEG, implementations can use the
10064 : * GDALGetCompressionFormatForJPEG() helper method to generate a string like
10065 : * above from a JPEG codestream.
10066 : *
10067 : * Several values might be returned. For example,
10068 : * the JPEGXL driver will return "JXL", but also potentially "JPEG"
10069 : * if the JPEGXL codestream includes a JPEG reconstruction box.
10070 : *
10071 : * In the general case this method will return an empty list.
10072 : *
10073 : * This is the same as C++ method GDALDataset::GetCompressionFormats().
10074 : *
10075 : * @param hDS Dataset handle.
10076 : *
10077 : * @param nXOff The pixel offset to the top left corner of the region
10078 : * of the band to be accessed. This would be zero to start from the left side.
10079 : *
10080 : * @param nYOff The line offset to the top left corner of the region
10081 : * of the band to be accessed. This would be zero to start from the top.
10082 : *
10083 : * @param nXSize The width of the region of the band to be accessed in pixels.
10084 : *
10085 : * @param nYSize The height of the region of the band to be accessed in lines.
10086 : *
10087 : * @param nBandCount the number of bands being requested.
10088 : *
10089 : * @param panBandList the list of nBandCount band numbers.
10090 : * Note band numbers are 1 based. This may be NULL to select the first
10091 : * nBandCount bands.
10092 : *
10093 : * @return a list of compatible formats (which may be empty) that should be
10094 : * freed with CSLDestroy(), or nullptr.
10095 : *
10096 : * @since GDAL 3.7
10097 : */
10098 9 : char **GDALDatasetGetCompressionFormats(GDALDatasetH hDS, int nXOff, int nYOff,
10099 : int nXSize, int nYSize, int nBandCount,
10100 : const int *panBandList)
10101 : {
10102 9 : VALIDATE_POINTER1(hDS, __func__, nullptr);
10103 9 : return GDALDataset::FromHandle(hDS)
10104 9 : ->GetCompressionFormats(nXOff, nYOff, nXSize, nYSize, nBandCount,
10105 9 : panBandList)
10106 9 : .StealList();
10107 : }
10108 :
10109 : /************************************************************************/
10110 : /* ReadCompressedData() */
10111 : /************************************************************************/
10112 :
10113 : /** Return the compressed content that can be natively obtained for the
10114 : * window of interest and requested bands.
10115 : *
10116 : * For example, a tiled dataset may be able to return data in compressed format
10117 : * if the window of interest matches exactly a tile. For some formats, drivers
10118 : * may also be example to merge several tiles together (not currently
10119 : * implemented though).
10120 : *
10121 : * The implementation should make sure that the content returned forms a valid
10122 : * standalone file. For example, for the GeoTIFF implementation of this method,
10123 : * when extracting a JPEG tile, the method will automatically add the content
10124 : * of the JPEG Huffman and/or quantization tables that might be stored in the
10125 : * TIFF JpegTables tag, and not in tile data itself.
10126 : *
10127 : * In the general case this method will return CE_Failure.
10128 : *
10129 : * This is the same as C function GDALDatasetReadCompressedData().
10130 : *
10131 : * @param pszFormat Requested compression format (e.g. "JPEG",
10132 : * "WEBP", "JXL"). This is the MIME type of one of the values
10133 : * returned by GetCompressionFormats(). The format string is designed to
10134 : * potentially include at a later point key=value optional parameters separated
10135 : * by a semi-colon character. At time of writing, none are implemented.
10136 : * ReadCompressedData() implementations should verify optional parameters and
10137 : * return CE_Failure if they cannot support one of them.
10138 : *
10139 : * @param nXOff The pixel offset to the top left corner of the region
10140 : * of the band to be accessed. This would be zero to start from the left side.
10141 : *
10142 : * @param nYOff The line offset to the top left corner of the region
10143 : * of the band to be accessed. This would be zero to start from the top.
10144 : *
10145 : * @param nXSize The width of the region of the band to be accessed in pixels.
10146 : *
10147 : * @param nYSize The height of the region of the band to be accessed in lines.
10148 : *
10149 : * @param nBandCount the number of bands being requested.
10150 : *
10151 : * @param panBandList the list of nBandCount band numbers.
10152 : * Note band numbers are 1 based. This may be NULL to select the first
10153 : * nBandCount bands.
10154 : *
10155 : * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10156 : * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10157 : * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10158 : * buffer will be filled with the compressed data, provided that pnBufferSize
10159 : * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10160 : * of *ppBuffer, is sufficiently large to hold the data.
10161 : * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10162 : * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10163 : * free it with VSIFree().
10164 : * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10165 : * but *pnBufferSize will be updated with an upper bound of the size that would
10166 : * be necessary to hold it (if pnBufferSize != nullptr).
10167 : *
10168 : * @param pnBufferSize Output buffer size, or nullptr.
10169 : * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10170 : * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10171 : * method is successful, *pnBufferSize will be updated with the actual size
10172 : * used.
10173 : *
10174 : * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10175 : * If ppszDetailedFormat is not nullptr, then, on success, the method will
10176 : * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10177 : * *ppszDetailedFormat might contain strings like
10178 : * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10179 : * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10180 : * The string will contain at least as much information as what
10181 : * GetCompressionFormats() returns, and potentially more when
10182 : * ppBuffer != nullptr.
10183 : *
10184 : * @return CE_None in case of success, CE_Failure otherwise.
10185 : *
10186 : * For example, to request JPEG content on the whole image and let GDAL deal
10187 : * with the buffer allocation.
10188 : * \code{.cpp}
10189 : * void* pBuffer = nullptr;
10190 : * size_t nBufferSize = 0;
10191 : * CPLErr eErr =
10192 : * poDataset->ReadCompressedData("JPEG",
10193 : * 0, 0,
10194 : * poDataset->GetRasterXSize(),
10195 : * poDataset->GetRasterYSize(),
10196 : * poDataset->GetRasterCount(),
10197 : * nullptr, // panBandList
10198 : * &pBuffer,
10199 : * &nBufferSize,
10200 : * nullptr // ppszDetailedFormat
10201 : * );
10202 : * if (eErr == CE_None)
10203 : * {
10204 : * CPLAssert(pBuffer != nullptr);
10205 : * CPLAssert(nBufferSize > 0);
10206 : * VSILFILE* fp = VSIFOpenL("my.jpeg", "wb");
10207 : * if (fp)
10208 : * {
10209 : * VSIFWriteL(pBuffer, nBufferSize, 1, fp);
10210 : * VSIFCloseL(fp);
10211 : * }
10212 : * VSIFree(pBuffer);
10213 : * }
10214 : * \endcode
10215 : *
10216 : * Or to manage the buffer allocation on your side:
10217 : * \code{.cpp}
10218 : * size_t nUpperBoundBufferSize = 0;
10219 : * CPLErr eErr =
10220 : * poDataset->ReadCompressedData("JPEG",
10221 : * 0, 0,
10222 : * poDataset->GetRasterXSize(),
10223 : * poDataset->GetRasterYSize(),
10224 : * poDataset->GetRasterCount(),
10225 : * nullptr, // panBandList
10226 : * nullptr, // ppBuffer,
10227 : * &nUpperBoundBufferSize,
10228 : * nullptr // ppszDetailedFormat
10229 : * );
10230 : * if (eErr == CE_None)
10231 : * {
10232 : * std::vector<uint8_t> myBuffer;
10233 : * myBuffer.resize(nUpperBoundBufferSize);
10234 : * void* pBuffer = myBuffer.data();
10235 : * size_t nActualSize = nUpperBoundBufferSize;
10236 : * char* pszDetailedFormat = nullptr;
10237 : * // We also request detailed format, but we could have passed it to
10238 : * // nullptr as well.
10239 : * eErr =
10240 : * poDataset->ReadCompressedData("JPEG",
10241 : * 0, 0,
10242 : * poDataset->GetRasterXSize(),
10243 : * poDataset->GetRasterYSize(),
10244 : * poDataset->GetRasterCount(),
10245 : * nullptr, // panBandList
10246 : * &pBuffer,
10247 : * &nActualSize,
10248 : * &pszDetailedFormat);
10249 : * if (eErr == CE_None)
10250 : * {
10251 : * CPLAssert(pBuffer == myBuffer.data()); // pointed value not modified
10252 : * CPLAssert(nActualSize <= nUpperBoundBufferSize);
10253 : * myBuffer.resize(nActualSize);
10254 : * // do something useful
10255 : * VSIFree(pszDetailedFormat);
10256 : * }
10257 : * }
10258 : * \endcode
10259 : *
10260 : * @since GDAL 3.7
10261 : */
10262 462 : CPLErr GDALDataset::ReadCompressedData(
10263 : CPL_UNUSED const char *pszFormat, CPL_UNUSED int nXOff,
10264 : CPL_UNUSED int nYOff, CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
10265 : CPL_UNUSED int nBandCount, CPL_UNUSED const int *panBandList,
10266 : CPL_UNUSED void **ppBuffer, CPL_UNUSED size_t *pnBufferSize,
10267 : CPL_UNUSED char **ppszDetailedFormat)
10268 : {
10269 462 : return CE_Failure;
10270 : }
10271 :
10272 : /************************************************************************/
10273 : /* GDALDatasetReadCompressedData() */
10274 : /************************************************************************/
10275 :
10276 : /** Return the compressed content that can be natively obtained for the
10277 : * window of interest and requested bands.
10278 : *
10279 : * For example, a tiled dataset may be able to return data in compressed format
10280 : * if the window of interest matches exactly a tile. For some formats, drivers
10281 : * may also be example to merge several tiles together (not currently
10282 : * implemented though).
10283 : *
10284 : * The implementation should make sure that the content returned forms a valid
10285 : * standalone file. For example, for the GeoTIFF implementation of this method,
10286 : * when extracting a JPEG tile, the method will automatically adds the content
10287 : * of the JPEG Huffman and/or quantization tables that might be stored in the
10288 : * TIFF JpegTables tag, and not in tile data itself.
10289 : *
10290 : * In the general case this method will return CE_Failure.
10291 : *
10292 : * This is the same as C++ method GDALDataset:ReadCompressedData().
10293 : *
10294 : * @param hDS Dataset handle.
10295 : *
10296 : * @param pszFormat Requested compression format (e.g. "JPEG",
10297 : * "WEBP", "JXL"). This is the MIME type of one of the values
10298 : * returned by GetCompressionFormats(). The format string is designed to
10299 : * potentially include at a later point key=value optional parameters separated
10300 : * by a semi-colon character. At time of writing, none are implemented.
10301 : * ReadCompressedData() implementations should verify optional parameters and
10302 : * return CE_Failure if they cannot support one of them.
10303 : *
10304 : * @param nXOff The pixel offset to the top left corner of the region
10305 : * of the band to be accessed. This would be zero to start from the left side.
10306 : *
10307 : * @param nYOff The line offset to the top left corner of the region
10308 : * of the band to be accessed. This would be zero to start from the top.
10309 : *
10310 : * @param nXSize The width of the region of the band to be accessed in pixels.
10311 : *
10312 : * @param nYSize The height of the region of the band to be accessed in lines.
10313 : *
10314 : * @param nBandCount the number of bands being requested.
10315 : *
10316 : * @param panBandList the list of nBandCount band numbers.
10317 : * Note band numbers are 1 based. This may be NULL to select the first
10318 : * nBandCount bands.
10319 : *
10320 : * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10321 : * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10322 : * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10323 : * buffer will be filled with the compressed data, provided that pnBufferSize
10324 : * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10325 : * of *ppBuffer, is sufficiently large to hold the data.
10326 : * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10327 : * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10328 : * free it with VSIFree().
10329 : * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10330 : * but *pnBufferSize will be updated with an upper bound of the size that would
10331 : * be necessary to hold it (if pnBufferSize != nullptr).
10332 : *
10333 : * @param pnBufferSize Output buffer size, or nullptr.
10334 : * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10335 : * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10336 : * method is successful, *pnBufferSize will be updated with the actual size
10337 : * used.
10338 : *
10339 : * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10340 : * If ppszDetailedFormat is not nullptr, then, on success, the method will
10341 : * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10342 : * *ppszDetailedFormat might contain strings like
10343 : * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10344 : * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10345 : * The string will contain at least as much information as what
10346 : * GetCompressionFormats() returns, and potentially more when
10347 : * ppBuffer != nullptr.
10348 : *
10349 : * @return CE_None in case of success, CE_Failure otherwise.
10350 : *
10351 : * @since GDAL 3.7
10352 : */
10353 28 : CPLErr GDALDatasetReadCompressedData(GDALDatasetH hDS, const char *pszFormat,
10354 : int nXOff, int nYOff, int nXSize,
10355 : int nYSize, int nBandCount,
10356 : const int *panBandList, void **ppBuffer,
10357 : size_t *pnBufferSize,
10358 : char **ppszDetailedFormat)
10359 : {
10360 28 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10361 56 : return GDALDataset::FromHandle(hDS)->ReadCompressedData(
10362 : pszFormat, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandList,
10363 28 : ppBuffer, pnBufferSize, ppszDetailedFormat);
10364 : }
10365 :
10366 : /************************************************************************/
10367 : /* CanBeCloned() */
10368 : /************************************************************************/
10369 :
10370 : //! @cond Doxygen_Suppress
10371 :
10372 : /** This method is called by GDALThreadSafeDataset::Create() to determine if
10373 : * it is possible to create a thread-safe wrapper for a dataset, which involves
10374 : * the ability to Clone() it.
10375 : *
10376 : * Implementations of this method must be thread-safe.
10377 : *
10378 : * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10379 : * expressing the intended use for thread-safety.
10380 : * Currently, the only valid scope is in the base
10381 : * implementation is GDAL_OF_RASTER.
10382 : * @param bCanShareState Determines if cloned datasets are allowed to share
10383 : * state with the dataset they have been cloned from.
10384 : * If set to true, the dataset from which they have been
10385 : * cloned from must remain opened during the lifetime of
10386 : * its clones.
10387 : * @return true if the Clone() method is expected to succeed with the same values
10388 : * of nScopeFlags and bCanShareState.
10389 : */
10390 133 : bool GDALDataset::CanBeCloned(int nScopeFlags,
10391 : [[maybe_unused]] bool bCanShareState) const
10392 : {
10393 133 : return m_bCanBeReopened && nScopeFlags == GDAL_OF_RASTER;
10394 : }
10395 :
10396 : //! @endcond
10397 :
10398 : /************************************************************************/
10399 : /* Clone() */
10400 : /************************************************************************/
10401 :
10402 : //! @cond Doxygen_Suppress
10403 :
10404 : /** This method "clones" the current dataset, that is it returns a new instance
10405 : * that is opened on the same underlying "file".
10406 : *
10407 : * The base implementation uses GDALDataset::Open() to re-open the dataset.
10408 : * The MEM driver has a specialized implementation that returns a new instance,
10409 : * but which shares the same memory buffer as this.
10410 : *
10411 : * Implementations of this method must be thread-safe.
10412 : *
10413 : * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10414 : * expressing the intended use for thread-safety.
10415 : * Currently, the only valid scope is in the base
10416 : * implementation is GDAL_OF_RASTER.
10417 : * @param bCanShareState Determines if cloned datasets are allowed to share
10418 : * state with the dataset they have been cloned from.
10419 : * If set to true, the dataset from which they have been
10420 : * cloned from must remain opened during the lifetime of
10421 : * its clones.
10422 : * @return a new instance, or nullptr in case of error.
10423 : */
10424 : std::unique_ptr<GDALDataset>
10425 2035 : GDALDataset::Clone(int nScopeFlags, [[maybe_unused]] bool bCanShareState) const
10426 : {
10427 3872 : CPLStringList aosAllowedDrivers;
10428 2035 : if (poDriver)
10429 2035 : aosAllowedDrivers.AddString(poDriver->GetDescription());
10430 : return std::unique_ptr<GDALDataset>(GDALDataset::Open(
10431 2034 : GetDescription(),
10432 2034 : nScopeFlags | GDAL_OF_INTERNAL | GDAL_OF_VERBOSE_ERROR,
10433 3921 : aosAllowedDrivers.List(), papszOpenOptions));
10434 : }
10435 :
10436 : //! @endcond
10437 :
10438 : /************************************************************************/
10439 : /* GeolocationToPixelLine() */
10440 : /************************************************************************/
10441 :
10442 : /** Transform georeferenced coordinates to pixel/line coordinates.
10443 : *
10444 : * When poSRS is null, those georeferenced coordinates (dfGeolocX, dfGeolocY)
10445 : * must be in the "natural" SRS of the dataset, that is the one returned by
10446 : * GetSpatialRef() if there is a geotransform, GetGCPSpatialRef() if there are
10447 : * GCPs, WGS 84 if there are RPC coefficients, or the SRS of the geolocation
10448 : * array (generally WGS 84) if there is a geolocation array.
10449 : * If that natural SRS is a geographic one, dfGeolocX must be a longitude, and
10450 : * dfGeolocY a latitude. If that natural SRS is a projected one, dfGeolocX must
10451 : * be a easting, and dfGeolocY a northing.
10452 : *
10453 : * When poSRS is set to a non-null value, (dfGeolocX, dfGeolocY) must be
10454 : * expressed in that CRS, and that tuple must be conformant with the
10455 : * data-axis-to-crs-axis setting of poSRS, that is the one returned by
10456 : * the OGRSpatialReference::GetDataAxisToSRSAxisMapping(). If you want to be sure
10457 : * of the axis order, then make sure to call poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER)
10458 : * before calling this method, and in that case, dfGeolocX must be a longitude
10459 : * or an easting value, and dfGeolocX a latitude or a northing value.
10460 : *
10461 : * This method uses GDALCreateGenImgProjTransformer2() underneath.
10462 : *
10463 : * @param dfGeolocX X coordinate of the position (longitude or easting if poSRS
10464 : * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
10465 : * where interpolation should be done.
10466 : * @param dfGeolocY Y coordinate of the position (latitude or northing if poSRS
10467 : * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
10468 : * where interpolation should be done.
10469 : * @param poSRS If set, override the natural CRS in which dfGeolocX, dfGeolocY are expressed
10470 : * @param[out] pdfPixel Pointer to the variable where to the store the pixel/column coordinate.
10471 : * @param[out] pdfLine Pointer to the variable where to the store the line coordinate.
10472 : * @param papszTransformerOptions Options accepted by GDALCreateGenImgProjTransformer2(), or nullptr.
10473 : *
10474 : * @return CE_None on success, or an error code on failure.
10475 : * @since GDAL 3.11
10476 : */
10477 :
10478 : CPLErr
10479 15 : GDALDataset::GeolocationToPixelLine(double dfGeolocX, double dfGeolocY,
10480 : const OGRSpatialReference *poSRS,
10481 : double *pdfPixel, double *pdfLine,
10482 : CSLConstList papszTransformerOptions) const
10483 : {
10484 30 : CPLStringList aosTO(papszTransformerOptions);
10485 :
10486 15 : if (poSRS)
10487 : {
10488 4 : const char *const apszOptions[] = {"FORMAT=WKT2", nullptr};
10489 8 : const std::string osWKT = poSRS->exportToWkt(apszOptions);
10490 4 : aosTO.SetNameValue("DST_SRS", osWKT.c_str());
10491 4 : const auto eAxisMappingStrategy = poSRS->GetAxisMappingStrategy();
10492 4 : if (eAxisMappingStrategy == OAMS_TRADITIONAL_GIS_ORDER)
10493 : aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
10494 1 : "TRADITIONAL_GIS_ORDER");
10495 3 : else if (eAxisMappingStrategy == OAMS_AUTHORITY_COMPLIANT)
10496 : aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
10497 1 : "AUTHORITY_COMPLIANT");
10498 : else
10499 : {
10500 2 : const auto &anValues = poSRS->GetDataAxisToSRSAxisMapping();
10501 4 : std::string osVal;
10502 6 : for (int v : anValues)
10503 : {
10504 4 : if (!osVal.empty())
10505 2 : osVal += ',';
10506 4 : osVal += std::to_string(v);
10507 : }
10508 : aosTO.SetNameValue("DST_SRS_DATA_AXIS_TO_SRS_AXIS_MAPPING",
10509 2 : osVal.c_str());
10510 : }
10511 : }
10512 :
10513 15 : auto hTransformer = GDALCreateGenImgProjTransformer2(
10514 : GDALDataset::ToHandle(const_cast<GDALDataset *>(this)), nullptr,
10515 15 : aosTO.List());
10516 15 : if (hTransformer == nullptr)
10517 : {
10518 1 : return CE_Failure;
10519 : }
10520 :
10521 14 : double z = 0;
10522 14 : int bSuccess = 0;
10523 14 : GDALGenImgProjTransform(hTransformer, TRUE, 1, &dfGeolocX, &dfGeolocY, &z,
10524 : &bSuccess);
10525 14 : GDALDestroyTransformer(hTransformer);
10526 14 : if (bSuccess)
10527 : {
10528 14 : if (pdfPixel)
10529 14 : *pdfPixel = dfGeolocX;
10530 14 : if (pdfLine)
10531 14 : *pdfLine = dfGeolocY;
10532 14 : return CE_None;
10533 : }
10534 : else
10535 : {
10536 0 : return CE_Failure;
10537 : }
10538 : }
10539 :
10540 : /************************************************************************/
10541 : /* GDALDatasetGeolocationToPixelLine() */
10542 : /************************************************************************/
10543 :
10544 : /** Transform georeferenced coordinates to pixel/line coordinates.
10545 : *
10546 : * @see GDALDataset::GeolocationToPixelLine()
10547 : * @since GDAL 3.11
10548 : */
10549 :
10550 0 : CPLErr GDALDatasetGeolocationToPixelLine(GDALDatasetH hDS, double dfGeolocX,
10551 : double dfGeolocY,
10552 : OGRSpatialReferenceH hSRS,
10553 : double *pdfPixel, double *pdfLine,
10554 : CSLConstList papszTransformerOptions)
10555 : {
10556 0 : VALIDATE_POINTER1(hDS, "GDALDatasetGeolocationToPixelLine", CE_Failure);
10557 :
10558 0 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
10559 0 : return poDS->GeolocationToPixelLine(
10560 0 : dfGeolocX, dfGeolocY, OGRSpatialReference::FromHandle(hSRS), pdfPixel,
10561 0 : pdfLine, papszTransformerOptions);
10562 : }
10563 :
10564 : /************************************************************************/
10565 : /* GetExtent() */
10566 : /************************************************************************/
10567 :
10568 : /** Return extent of dataset in specified CRS.
10569 : *
10570 : * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
10571 : *
10572 : * For rasters, the base implementation of this method only succeeds if
10573 : * GetGeoTransform() and GetSpatialRef() succeed.
10574 : * For vectors, the base implementation of this method iterates over layers
10575 : * and call their OGRLayer::GetExtent() method.
10576 : *
10577 : * TestCapability(GDsCFastGetExtent) can be used to test if the execution
10578 : * time of this method is fast.
10579 : *
10580 : * This is the same as C function GDALGetExtent()
10581 : *
10582 : * @param[out] psExtent Pointer to output extent. Must NOT be null.
10583 : * @param poCRS CRS in which to express the extent. If not specified, this will
10584 : * be the raster CRS or the CRS of the first layer for a vector dataset.
10585 : * @return CE_None in case of success, CE_Failure otherwise
10586 : * @since GDAL 3.12
10587 : */
10588 :
10589 10 : CPLErr GDALDataset::GetExtent(OGREnvelope *psExtent,
10590 : const OGRSpatialReference *poCRS) const
10591 : {
10592 10 : auto poThisDS = const_cast<GDALDataset *>(this);
10593 10 : const OGRSpatialReference *poThisCRS = poThisDS->GetSpatialRef();
10594 10 : int nLayerCount = 0;
10595 10 : if (!poThisCRS)
10596 : {
10597 7 : nLayerCount = poThisDS->GetLayerCount();
10598 7 : if (nLayerCount >= 1)
10599 : {
10600 3 : if (auto poLayer = poThisDS->GetLayer(0))
10601 3 : poThisCRS = poLayer->GetSpatialRef();
10602 : }
10603 7 : if (!poThisCRS)
10604 4 : return CE_Failure;
10605 : }
10606 6 : if (!poCRS)
10607 2 : poCRS = poThisCRS;
10608 :
10609 6 : *psExtent = OGREnvelope();
10610 :
10611 6 : GDALGeoTransform gt;
10612 6 : const bool bHasGT = poThisDS->GetGeoTransform(gt) == CE_None;
10613 6 : if (bHasGT)
10614 : {
10615 : auto poCT = std::unique_ptr<OGRCoordinateTransformation>(
10616 6 : OGRCreateCoordinateTransformation(poThisCRS, poCRS));
10617 3 : if (poCT)
10618 : {
10619 3 : constexpr int DENSIFY_POINT_COUNT = 21;
10620 3 : OGREnvelope sEnvTmp;
10621 3 : double dfULX = gt[0];
10622 3 : double dfULY = gt[3];
10623 3 : double dfURX = 0, dfURY = 0;
10624 3 : gt.Apply(nRasterXSize, 0, &dfURX, &dfURY);
10625 3 : double dfLLX = 0, dfLLY = 0;
10626 3 : gt.Apply(0, nRasterYSize, &dfLLX, &dfLLY);
10627 3 : double dfLRX = 0, dfLRY = 0;
10628 3 : gt.Apply(nRasterXSize, nRasterYSize, &dfLRX, &dfLRY);
10629 : const double xmin =
10630 3 : std::min(std::min(dfULX, dfURX), std::min(dfLLX, dfLRX));
10631 : const double ymin =
10632 3 : std::min(std::min(dfULY, dfURY), std::min(dfLLY, dfLRY));
10633 : const double xmax =
10634 3 : std::max(std::max(dfULX, dfURX), std::max(dfLLX, dfLRX));
10635 : const double ymax =
10636 3 : std::max(std::max(dfULY, dfURY), std::max(dfLLY, dfLRY));
10637 3 : if (poCT->TransformBounds(xmin, ymin, xmax, ymax, &(sEnvTmp.MinX),
10638 : &(sEnvTmp.MinY), &(sEnvTmp.MaxX),
10639 3 : &(sEnvTmp.MaxY), DENSIFY_POINT_COUNT))
10640 : {
10641 3 : *psExtent = std::move(sEnvTmp);
10642 : }
10643 : }
10644 : }
10645 :
10646 6 : if (nLayerCount > 0)
10647 : {
10648 6 : for (auto &&poLayer : poThisDS->GetLayers())
10649 : {
10650 3 : auto poLayerCRS = poLayer->GetSpatialRef();
10651 3 : if (poLayerCRS)
10652 : {
10653 3 : OGREnvelope sLayerExtent;
10654 3 : if (poLayer->GetExtent(&sLayerExtent) == OGRERR_NONE)
10655 : {
10656 : auto poCT = std::unique_ptr<OGRCoordinateTransformation>(
10657 6 : OGRCreateCoordinateTransformation(poLayerCRS, poCRS));
10658 3 : if (poCT)
10659 : {
10660 3 : constexpr int DENSIFY_POINT_COUNT = 21;
10661 3 : OGREnvelope sEnvTmp;
10662 3 : if (poCT->TransformBounds(
10663 : sLayerExtent.MinX, sLayerExtent.MinY,
10664 : sLayerExtent.MaxX, sLayerExtent.MaxY,
10665 : &(sEnvTmp.MinX), &(sEnvTmp.MinY),
10666 : &(sEnvTmp.MaxX), &(sEnvTmp.MaxY),
10667 3 : DENSIFY_POINT_COUNT))
10668 : {
10669 3 : psExtent->Merge(sEnvTmp);
10670 : }
10671 : }
10672 : }
10673 : }
10674 : }
10675 : }
10676 :
10677 6 : return psExtent->IsInit() ? CE_None : CE_Failure;
10678 : }
10679 :
10680 : /************************************************************************/
10681 : /* GDALGetExtent() */
10682 : /************************************************************************/
10683 :
10684 : /** Return extent of dataset in specified CRS.
10685 : *
10686 : * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
10687 : *
10688 : * For rasters, the base implementation of this method only succeeds if
10689 : * GetGeoTransform() and GetSpatialRef() succeed.
10690 : * For vectors, the base implementation of this method iterates over layers
10691 : * and call their OGRLayer::GetExtent() method.
10692 : *
10693 : * TestCapability(GDsCFastGetExtent) can be used to test if the execution
10694 : * time of this method is fast.
10695 : *
10696 : * This is the same as C++ method GDALDataset::GetExtent()
10697 : *
10698 : * @param hDS Dataset handle. Must NOT be null.
10699 : * @param[out] psExtent Pointer to output extent. Must NOT be null.
10700 : * @param hCRS CRS in which to express the extent. If not specified, this will
10701 : * be the raster CRS or the CRS of the first layer for a vector dataset.
10702 : * @return extent in poCRS (valid only if IsInit() method returns true)
10703 : * @since GDAL 3.12
10704 : */
10705 :
10706 4 : CPLErr GDALGetExtent(GDALDatasetH hDS, OGREnvelope *psExtent,
10707 : OGRSpatialReferenceH hCRS)
10708 : {
10709 4 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10710 4 : VALIDATE_POINTER1(psExtent, __func__, CE_Failure);
10711 8 : return GDALDataset::FromHandle(hDS)->GetExtent(
10712 4 : psExtent, OGRSpatialReference::FromHandle(hCRS));
10713 : }
10714 :
10715 : /************************************************************************/
10716 : /* GetExtentWGS84LongLat() */
10717 : /************************************************************************/
10718 :
10719 : /** Return extent of dataset in WGS84 longitude/latitude
10720 : *
10721 : * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
10722 : *
10723 : * TestCapability(GDsCFastGetExtentWGS84LongLat) can be used to test if the execution
10724 : * time of this method is fast.
10725 : *
10726 : * This is the same as C function GDALGetExtentWGS84LongLat()
10727 : *
10728 : * @return extent (valid only if IsInit() method returns true)
10729 : * @since GDAL 3.12
10730 : */
10731 :
10732 6 : CPLErr GDALDataset::GetExtentWGS84LongLat(OGREnvelope *psExtent) const
10733 : {
10734 12 : OGRSpatialReference oSRS_WGS84;
10735 6 : oSRS_WGS84.SetFromUserInput("WGS84");
10736 6 : oSRS_WGS84.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
10737 12 : return GetExtent(psExtent, &oSRS_WGS84);
10738 : }
10739 :
10740 : /************************************************************************/
10741 : /* GDALGetExtentWGS84LongLat() */
10742 : /************************************************************************/
10743 :
10744 : /** Return extent of dataset in WGS84 longitude/latitude
10745 : *
10746 : * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
10747 : *
10748 : * TestCapability(GDsCFastGetExtentWGS84LongLat) can be used to test if the execution
10749 : * time of this method is fast.
10750 : *
10751 : * This is the same as C++ method GDALDataset::GetExtentWGS84LongLat()
10752 : *
10753 : * @param hDS Dataset handle. Must NOT be null.
10754 : * @param[out] psExtent Pointer to output extent. Must NOT be null.
10755 : * @return extent (valid only if IsInit() method returns true)
10756 : * @since GDAL 3.12
10757 : */
10758 :
10759 4 : CPLErr GDALGetExtentWGS84LongLat(GDALDatasetH hDS, OGREnvelope *psExtent)
10760 : {
10761 4 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10762 4 : VALIDATE_POINTER1(psExtent, __func__, CE_Failure);
10763 4 : return GDALDataset::FromHandle(hDS)->GetExtentWGS84LongLat(psExtent);
10764 : }
10765 :
10766 : /************************************************************************/
10767 : /* ReportUpdateNotSupportedByDriver() */
10768 : /************************************************************************/
10769 :
10770 : //! @cond Doxygen_Suppress
10771 :
10772 : /* static */
10773 1 : void GDALDataset::ReportUpdateNotSupportedByDriver(const char *pszDriverName)
10774 : {
10775 1 : CPLError(CE_Failure, CPLE_NotSupported,
10776 : "The %s driver does not support update access to existing "
10777 : "datasets.",
10778 : pszDriverName);
10779 1 : }
10780 :
10781 : //! @endcond
10782 :
10783 : /************************************************************************/
10784 : /* BuildFilename() */
10785 : /************************************************************************/
10786 :
10787 : /** Generates a filename, potentially relative to another one.
10788 : *
10789 : * Given the path to a reference directory, and a path to a file
10790 : * referenced from it, build a path to the file that the current application
10791 : * can use. If the file path is already absolute, rather than relative, or if
10792 : * bRelativeToReferencePath is false, then the filename of interest will be
10793 : * returned unaltered.
10794 : *
10795 : * This is enhanced version of CPLProjectRelativeFilenameSafe() that takes
10796 : * into account the subdataset syntax.
10797 : *
10798 : * Examples:
10799 : * \code{.cpp}
10800 : * BuildFilename("tmp/abc.gif", "abc/def", true) == "abc/def/tmp/abc.gif"
10801 : * BuildFilename("../abc.gif", "/abc/def") == "/abc/abc.gif"
10802 : * BuildFilename("abc.gif", "C:\WIN", true) == "C:\WIN\abc.gif"
10803 : * BuildFilename("abc.gif", "C:\WIN", false) == "abc.gif"
10804 : * BuildFilename("/home/even/foo.tif", "/home/even/workdir", true) == "/home/even/foo.tif"
10805 : * \endcode
10806 : *
10807 : * @param pszFilename Filename of interest.
10808 : * @param pszReferencePath Path to a reference directory.
10809 : * @param bRelativeToReferencePath Whether pszFilename, if a relative path, is
10810 : * relative to pszReferencePath
10811 : * @since 3.11
10812 : */
10813 :
10814 : /* static */
10815 104238 : std::string GDALDataset::BuildFilename(const char *pszFilename,
10816 : const char *pszReferencePath,
10817 : bool bRelativeToReferencePath)
10818 : {
10819 104238 : std::string osSrcDSName;
10820 104238 : if (pszReferencePath != nullptr && bRelativeToReferencePath)
10821 : {
10822 : // Try subdatasetinfo API first
10823 : // Note: this will become the only branch when subdatasetinfo will become
10824 : // available for NITF_IM, RASTERLITE and TILEDB
10825 2584 : const auto oSubDSInfo{GDALGetSubdatasetInfo(pszFilename)};
10826 2584 : if (oSubDSInfo && !oSubDSInfo->GetPathComponent().empty())
10827 : {
10828 8 : auto path{oSubDSInfo->GetPathComponent()};
10829 12 : osSrcDSName = oSubDSInfo->ModifyPathComponent(
10830 8 : CPLProjectRelativeFilenameSafe(pszReferencePath, path.c_str())
10831 4 : .c_str());
10832 4 : GDALDestroySubdatasetInfo(oSubDSInfo);
10833 : }
10834 : else
10835 : {
10836 2580 : bool bDone = false;
10837 15470 : for (const char *pszSyntax : apszSpecialSubDatasetSyntax)
10838 : {
10839 12892 : CPLString osPrefix(pszSyntax);
10840 12892 : osPrefix.resize(strchr(pszSyntax, ':') - pszSyntax + 1);
10841 12892 : if (pszSyntax[osPrefix.size()] == '"')
10842 2578 : osPrefix += '"';
10843 12892 : if (EQUALN(pszFilename, osPrefix, osPrefix.size()))
10844 : {
10845 2 : if (STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{ANY}"))
10846 : {
10847 2 : const char *pszLastPart = strrchr(pszFilename, ':') + 1;
10848 : // CSV:z:/foo.xyz
10849 2 : if ((pszLastPart[0] == '/' || pszLastPart[0] == '\\') &&
10850 0 : pszLastPart - pszFilename >= 3 &&
10851 0 : pszLastPart[-3] == ':')
10852 : {
10853 0 : pszLastPart -= 2;
10854 : }
10855 2 : CPLString osPrefixFilename = pszFilename;
10856 2 : osPrefixFilename.resize(pszLastPart - pszFilename);
10857 4 : osSrcDSName = osPrefixFilename +
10858 4 : CPLProjectRelativeFilenameSafe(
10859 2 : pszReferencePath, pszLastPart);
10860 2 : bDone = true;
10861 : }
10862 0 : else if (STARTS_WITH_CI(pszSyntax + osPrefix.size(),
10863 : "{FILENAME}"))
10864 : {
10865 0 : CPLString osFilename(pszFilename + osPrefix.size());
10866 0 : size_t nPos = 0;
10867 0 : if (osFilename.size() >= 3 && osFilename[1] == ':' &&
10868 0 : (osFilename[2] == '\\' || osFilename[2] == '/'))
10869 0 : nPos = 2;
10870 0 : nPos = osFilename.find(
10871 0 : pszSyntax[osPrefix.size() + strlen("{FILENAME}")],
10872 : nPos);
10873 0 : if (nPos != std::string::npos)
10874 : {
10875 0 : const CPLString osSuffix = osFilename.substr(nPos);
10876 0 : osFilename.resize(nPos);
10877 0 : osSrcDSName = osPrefix +
10878 0 : CPLProjectRelativeFilenameSafe(
10879 0 : pszReferencePath, osFilename) +
10880 0 : osSuffix;
10881 0 : bDone = true;
10882 : }
10883 : }
10884 2 : break;
10885 : }
10886 : }
10887 2580 : if (!bDone)
10888 : {
10889 2578 : std::string osReferencePath = pszReferencePath;
10890 2578 : if (!CPLIsFilenameRelative(pszReferencePath))
10891 : {
10892 : // Simplify path by replacing "foo/a/../b" with "foo/b"
10893 2287 : while (STARTS_WITH(pszFilename, "../"))
10894 : {
10895 : osReferencePath =
10896 5 : CPLGetPathSafe(osReferencePath.c_str());
10897 5 : pszFilename += strlen("../");
10898 : }
10899 : }
10900 :
10901 5156 : osSrcDSName = CPLProjectRelativeFilenameSafe(
10902 2578 : osReferencePath.c_str(), pszFilename);
10903 : }
10904 2584 : }
10905 : }
10906 : else
10907 : {
10908 101654 : osSrcDSName = pszFilename;
10909 : }
10910 104238 : return osSrcDSName;
10911 : }
|